#!/usr/bin/python3
# -*- coding: utf-8 -*-
"""
可視化処理制御モジュール
[170117] Start Qt version
"""
from __future__ import print_function
import uGao.M2PlotPlus as D2Vis
import uGao.uGaoUtil as UtilPlot
import numpy as np
from utsusemi.vis.VisContQTab import VisContQTab
import Cmm

import time
import sys

import threading
import os
PYSIDEVER = 1
try:
    from PySide6 import QtCore, QtGui, QtWidgets
    from PySide6.QtGui import QAction
    PYSIDEVER = 6
except:
    try:
        from PySide2 import QtCore, QtGui, QtWidgets
        from PySide2.QtWidgets import QAction
        PYSIDEVER = 2
    except:
        from PySide import QtCore, QtGui
        import PySide.QtGui as QtWidgets
        from PySide.QtGui import QAction

if QtCore.__version__ < '5.0.0':
    from utsusemi.vis.ui_VisContQ import Ui_MainWindow, Ui_SettingDialog, Ui_DataOperationDialog
else:
    if PYSIDEVER == 2:
        from utsusemi.vis.ui2_VisContQ import Ui_MainWindow, Ui_SettingDialog, Ui_DataOperationDialog
    elif PYSIDEVER == 6:
        from utsusemi.vis.ui6_VisContQ import Ui_MainWindow, Ui_SettingDialog, Ui_DataOperationDialog


try:
    import Manyo as mm
    import Manyo.Utsusemi as mu  # [inamura 121228]
except:
    pass

if mu.UtsusemiEnvGetDebugMode():
    mu.UtsusemiMessage("DetectorMap PySide Ver={}".format(PYSIDEVER))

SpectTypeDic = {
    "SIK": "Direct",
    "DNA": "Inverted",
    "HRC": "Direct",
    "AMR": "Direct"
}  # [inamura 150903]

#######################################
#  Setting Dialog
#######################################


class SettingDialog(QtWidgets.QDialog):
    """
    Dialog class for Setting
    """
    #########################################################

    def __init__(self, parent):
        """
        """
        self.parent = parent
        # self.res = parent.res

        super(SettingDialog, self).__init__(parent)
        self.dialog = Ui_SettingDialog()
        if self.dialog is None:
            return
        self.dialog.setupUi(self)

        self.ckSliceAveMode = self.findChild(
            QtWidgets.QCheckBox, u'ckSliceAverageMode')
        self.ckSliceAveMode.stateChanged.connect(self.OnCheckSliceAveMode)

        if self.parent.isSliceAverageMode:
            self.ckSliceAveMode.setCheckState(QtCore.Qt.Checked)
        else:
            self.ckSliceAveMode.setCheckState(QtCore.Qt.Unchecked)

        # Show this dialog
        self.show()

    ##############################################

    def OnCheckSliceAveMode(self):
        """
        チェックボックスのイベントハンドラ
        @param  evt 　イベント
        @retval 無し
        """
        print("--OnCheckSliceAveMode")
        if self.ckSliceAveMode.checkState() == QtCore.Qt.Checked:
            self.parent.isSliceAverageMode = True
            print("---- isSliceAverageMode is True")
        else:
            self.parent.isSliceAverageMode = False
            print("---- isSliceAverageMode is False")

    ##########################################################
    def OnClose(self):
        """
        Function driven by Close event (just destroy)
        @param  evt  event info
        @retval None
        """
        self.close()


#######################################
#  DataOperatorDialog [inamura 120709]
#######################################
class DataOperatorDialog(QtWidgets.QDialog):
    """
    Dialog class for data operation
    """
    #########################################################

    def __init__(self, parent):
        """
        """

        self.parent = parent
        # self.res = parent.res
        # Get resource
        super(DataOperatorDialog, self).__init__(parent)
        self.dialog = Ui_DataOperationDialog()
        if self.dialog is None:
            return
        self.dialog.setupUi(self)

        # Get control
        # チェックボックスのイベントハンドラ登録
        self.ckPr = self.findChild(QtWidgets.QCheckBox, u'ckPr')
        self.ckPr.stateChanged.connect(self.OnCheck)

        # コンボボックスのイベントハンドラ登録
        self.cbOP = self.findChild(QtWidgets.QComboBox, u'cbOP')
        self.cbOP.activated.connect(self.OnComboOP)

        # Button's Event Handler
        self.btCalc = self.findChild(QtWidgets.QPushButton, u'btCalc')
        self.btCalc.clicked.connect(self.OnCalc)
        self.btClose = self.findChild(QtWidgets.QPushButton, u'btClose')
        self.btClose.clicked.connect(self.OnClose)

        # Text Handler
        self.asta1 = self.findChild(QtWidgets.QLabel, u'asta1')
        self.asta2 = self.findChild(QtWidgets.QLabel, u'asta2')
        self.m1 = self.findChild(QtWidgets.QLabel, u'm1')
        self.m2 = self.findChild(QtWidgets.QLabel, u'm2')

        # Show this dialog
        self.show()

    ##########################################################

    def OnClose(self):
        """
        Function driven by Close event (just destroy)
        @retval None
        """
        self.close()

    ##############################################
    def OnCheck(self):
        """
        チェックボックスのイベントハンドラ
        @param  evt 　イベント        @retval 無し        """
        # 演算式のコントロールを取得
        cb0 = self.findChild(QtWidgets.QComboBox, u'cb0')
        eq = self.findChild(QtWidgets.QLabel, u'stEQ')
        btCalc = self.findChild(QtWidgets.QPushButton, u'btCalc')

        if self.ckPr.checkState() == QtCore.Qt.Checked:
            cb0.setEnabled(False)
            eq.setEnabled(False)
            btCalc.setText("Show")
        else:
            cb0.setEnabled(False)
            eq.setEnabled(False)
            btCalc.setText("Calculate")

    ##############################################
    def OnComboOP(self):
        """
        演算子コンボボックスのイベントハンドラ
        @param  evt 　イベント
        @retval 無し
        """
        # 演算子無しか
        if self.cbOP.currentIndex() == 2:
            self.m2.setEnabled(False)
            self.asta2.setEnabled(False)
            self.cb2.setEnabled(False)
        else:        # 減算または加算
            self.m2.setEnabled(True)
            self.asta2.setEnabled(True)
            self.cb2.setEnabled(True)

    ##############################################
    def OnCalc(self, evt):
        """
        Calcurateボタンのイベントハンドラ
        @param  evt 　イベント
        @retval 無し
        """
        try:
            try:
                # 係数をテキストボックスから取得
                sm1 = str(self.m1.currentText())
                m1 = float(sm1)
                sm2 = str(self.m2.currentText())
                m2 = float(sm2)
            except:
                raise UtilPlot.PlotException(
                    'Common', 'C027', ("Coefficient",))
            # 各コンボボックスのコントロールを取得
            c0 = self.cb0.currentIndex()
            c1 = self.cb1.currentIndex()
            c2 = self.cb2.currentIndex()
            c3 = self.cbOP.currentIndex()

            # サンプルタイトル文字列を作る
            strSamp = self._MakeSampName(c1, c2, c3, sm1, sm2)
            # スライスデータ間の演算か
            if self.ckPr.checkState() == QtCore.Qt.Checked:
                self._OperateSlicedData(c1, c2, c3, m1, m2, strSamp)
            else:
                # 生データ間の演算(あれば射影後のデータも)
                self._OperateRawData(c0, c1, c2, c3, m1, m2, strSamp)

        except UtilPlot.PlotException as ex:
            UtilPlot.PlotMessage(self.dialog, ex)
            return

    #########################################
    def _MakeSampName(self, i1, i2, op, sm1, sm2):
        """
        スライスデータを演算し、2D マップ表示
        @param　 i1　タブ1 のインデックス
        @param　 i2　タブ2 のインデックス
        @param　 op　0: 減算、1: 加算
        @param　 sm1　タブ1 のデータに乗ずる係数(文字列)
        @param　 sm2　タブ2 のデータに乗ずる係数(文字列)
        @retval 無し
        """
        t1 = self.parent.tabs[i1]
        if t1.ECM is None:
            raise UtilPlot.PlotException(
                'VisCont', 'V006', (self.parent.tname[i1],))
        h1 = t1.ECM.PutHeaderPointer()
        if h1.CheckKey("SampleName") == 1:
            s1 = h1.PutString("SampleName")
            if '*' in s1:
                s1 = '( %s )' % s1
        else:
            s1 = self.parent.tname[i1]

        if op == 2:
            return "%s * %s" % (sm1, s1)

        t2 = self.parent.tabs[i2]
        if t2.ECM is None:
            raise UtilPlot.PlotException(
                'VisCont', 'V006', (self.parent.tname[i2],))
        h2 = t2.ECM.PutHeaderPointer()
        if h1.CheckKey("SampleName") == 1:
            s2 = h2.PutString("SampleName")
        else:
            s2 = self.parent.tname[i2]

        if h1.PutDouble("Ei") != h2.PutDouble("Ei"):
            raise UtilPlot.PlotException('VisCont', 'V007', ())

        if '*' in s2:
            s2 = "( %s )" % s2

        # 演算子を作る
        if op == 0:
            opc = '-'
        else:
            opc = '+'

        # 演算内容を示す文字列を作る
        return "%s * %s %s %s * %s" % (sm1, s1, opc, sm2, s2)

    #########################################
    def _OperateSlicedData(self, i1, i2, op, m1, m2, samp):
        """
        スライスデータを演算し、2D マップ表示
        @param　 i1　タブ1 のインデックス
        @param　 i2　タブ2 のインデックス
        @param　 op　0: 減算、1: 加算
        @param　 m1　タブ1 のデータに乗ずる係数
        @param　 m2　タブ2 のデータに乗ずる係数
        @param　 samp　演算過程を示すサンプル名
        @retval 無し
        """
        t1 = self.parent.tabs[i1]

        # タブ1にスライスデータがあるか
        if t1.map is None:
            raise UtilPlot.PlotException(
                'VisCont', 'V004', (self.parent.tname[i1],))

        # 演算するデータを取得
        mt1 = t1.map[0]
        et1 = t1.map[1]
        param1 = t1.GetTabParam()

        # タブ間の演算か
        if op != 2:
            t2 = self.parent.tabs[i2]
            # タブ2にスライスデータがあるか
            if t2.map is None:
                raise UtilPlot.PlotException(
                    'VisCont', 'V004', (self.parent.tname[i2],))

            # タブ間のパラメータを比較
            param2 = t2.GetTabParam()
            for i in range(len(param1)):
                # パラメータにアンマッチがあるか
                if param1[i] != param2[i]:
                    raise UtilPlot.PlotException(
                        'VisCont', 'V005', (self.parent.tname[i1], self.parent.tname[i2]))

            # 演算するデータを取得
            mt2 = t2.map[0]
            et2 = t2.map[1]

            # 縦・横のデータ数が等しいか
            if len(mt1) != len(mt2) or len(mt1[0]) != len(mt2[0]):
                raise UtilPlot.PlotException('VisCont', 'V009', ())

        # 減算か
        if op == 0:
            dd = m1 * mt1 - m2 * mt2
            ee = m1 * m1 * et1 * et1 + m2 * m2 * et2 * et2
        # 加算か
        elif op == 1:
            dd = m1 * mt1 + m2 * mt2
            ee = m1 * m1 * et1 * et1 + m2 * m2 * et2 * et2
        else:
            dd = m1 * mt1
            ee = m1 * m1 * et1 * et1

        ee = np.sqrt(ee)

        # マスク値処理
        for i in range(len(mt1)):
            for j in range(len(mt1[0])):
                if mt1[i, j] == UtilPlot.MASKVALUE:
                    dd[i, j] = UtilPlot.MASKVALUE
                    ee[i, j] = 0.0

        map = (dd, ee, t1.map[2], t1.map[3])

        if self.parent.pmap is None:
            self.parent.pmap = Plot2DMap(0, "0", self.parent.frame)
        # 2D マップ表示
        sd = t1.hist[t1.histI]
        self.parent.pmap.PlotMap(t1, map, sd._keys, sd._titles)

    #########################################
    def _OperateRawData(self, i0, i1, i2, op, m1, m2, samp):
        """
        スライスデータを演算し、2D マップ表示
        @param　 i0　演算結果を入れるタブ のインデックス
        @param　 i1　タブ1 のインデックス
        @param　 i2　タブ2 のインデックス
        @param　 op　0: 減算、1: 加算
        @param　 m1　タブ1 のデータに乗ずる係数
        @param　 m2　タブ2 のデータに乗ずる係数
        @param　 samp　演算過程を示すサンプル名
        @retval 無し
        """
        # タブのインスタンスを取得
        t0 = self.parent.tabs[i0]
        t1 = self.parent.tabs[i1]
        t2 = self.parent.tabs[i2]
        # タブ1のパラメータを取得
        param1 = t1.GetTabParam()
        # データを取得
        ecm1 = t1.ECM

        # タブ間の加減算であれば
        if op != 2:
            # タブ2のパラメータを取得
            param2 = t2.GetTabParam()
            # タブ間のサンプル情報を比較
            for i in range(13):
                # パラメータにアンマッチがあるか
                if param1[i] != param2[i]:
                    raise UtilPlot.PlotException(
                        'VisCont', 'V005', (self.parent.tname[i1], self.parent.tname[i2]))
            ecm2 = t2.ECM
            # データ数のチェック
            if ecm1.PutTableSize() != ecm2.PutTableSize():
                raise UtilPlot.PlotException('VisCont', 'V009', ())
            if ecm1(0).PutTableSize() != ecm1(0).PutTableSize():
                raise UtilPlot.PlotException('VisCont', 'V009', ())
            ec1 = ecm1(0, 0).PutX()
            ec2 = ecm2(0, 0).PutX()
            if ec1.size() != ec2.size():
                raise UtilPlot.PlotException('VisCont', 'V009', ())

        # データをロードするタブを選択状態とする
        self.parent.note.SetSelection(i0)

        # 減算か
        if op == 0:
            ecm3 = ecm1.Mul(m1) - ecm2.Mul(m2)

        # 加算か
        elif op == 1:
            ecm3 = ecm1.Mul(m1) + ecm2.Mul(m2)

        else:
            ecm3 = ecm1.Mul(m1)

        ecm3.InputHeader(ecm1.PutHeader())
        t0.SetDataToTab(ecm3)


#######################################
#  VisConMtFrame
#######################################
class VisContMFrame(QtWidgets.QMainWindow):
    """
    可視化制御画面クラス
    """
    # tabs = [None, None, None, None, None, None, None, None, None, None]
    tabs = []
    tname = ['A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J']
    tdict = {"A": 0, "B": 1, "C": 2, "D": 3, "E": 4,
             "F": 5, "G": 6, "H": 7, "I": 8, "J": 9}

    #########################################################
    def __init__(self, m0=None, m1=None, m2=None, m3=None, m4=None, m5=None, m6=None, m7=None, m8=None, m9=None):
        """
        コンストラクタ
        @param  m0～m4  ElementContainerMatrix
        @retval 無し
        """
        # print "VisualContM_2nd_version"
        super(VisContMFrame, self).__init__(None)
        self.frame = Ui_MainWindow()
        # リソースからフレームが取得できなかった
        if self.frame is None:
            return
        self.frame.setupUi(self)

        self.pmap = None

        # アイコンの設定
        # self.frame.SetIcon(UtilPlot.Images().GetMainIcon())
        # メニューバーを作る
        menu_loaddata = self.findChild(QAction, u"menu_load")
        menu_legacy = self.findChild(QAction, u"menu_legacy")
        menu_load_qxqyqz = self.findChild(QAction, u"menu_load_qxqyqz_text")
        menu_setting = self.findChild(QAction, u"menu_setting")
        menu_close = self.findChild(QAction, u"menu_exit")
        menu_loaddata.triggered.connect(self.OnLoadData)
        menu_legacy.triggered.connect(self.OnLoadLegacy)
        menu_load_qxqyqz.triggered.connect(self.OnLoadQxQyQzText)
        menu_setting.triggered.connect(self.OnSettings)
        menu_close.triggered.connect(self.OnClose)

        self.note = self.findChild(QtWidgets.QTabWidget, u"tabWidget")

        # ボタンのイベントハンドラ設定
        btn_apply = self.findChild(QtWidgets.QPushButton, u"btApply")
        btn_opper = self.findChild(QtWidgets.QPushButton, u"btOpperate")
        btn_apply.clicked.connect(self.OnApply)
        btn_opper.clicked.connect(self.OnOpperate)

        # logo panel
        logo_path = os.path.join(
            os.environ['UTSUSEMI_BASE_DIR'], 'vis', 'LOGO_utsusemi4_c_banner_vcm.png')
        if os.path.exists(logo_path):
            splash_panel = self.findChild(QtWidgets.QLabel, u'splash_label')
            splash_panel.setAlignment(QtCore.Qt.AlignCenter)
            splash_panel.setPixmap(QtGui.QPixmap(logo_path))
        """
        #logo_path = os.path.join( os.environ['UTSUSEMI_BASE_DIR'],'vis','LOGO_utsusemi3_s.png' )
        logo_path = os.path.join( os.environ['UTSUSEMI_BASE_DIR'],'vis','LOGO_utsusemi_3_c_long_small.png' )
        if os.path.exists( logo_path ):
            logo_panel = self.res.GetCtrl(self.frame, 'logoPanel' )
            logo_bmp = wx.Image(logo_path).ConvertToBitmap()
            #wx.StaticBitmap(logo_panel, -1, logo_bmp, (0,0),(200,40))
            wx.StaticBitmap(logo_panel, -1, logo_bmp, (5,0),(205,40))
        else:
            print "log path=", logo_path
        """
        # Title
        self.setWindowTitle("VisualContM")

        # クローズイベント登録
        # self.frame.Bind(wx.EVT_CLOSE, self.OnClose)

        # 画面を表示
        self.show()
        # 各タブのインスタンスを取得し保存、データをセット
        self.tabs = []
        dam = self.AddNewTab(m0, 0)

        # Slice Mode Setting [inamura 150602]
        self.isSliceAverageMode = True

    ##############################################
    def SetTab(self, mm, num):
        """
        タブインスタンスを生成し、データをセット
        @param  mm  エレメントコンテナマトリックス
        @param  num  データを追加するタブのNO.
        @retval 無し
        """
        self.AddNewTab(mm, num)

    ##############################################
    def AddNewTab(self, mm, num=-1):
        """
        """
        cur_num = len(self.tabs)
        # print("Num of tabs={}".format(cur_num))
        if num < 0:
            self.tabs.append(None)
            num = len(self.tabs) - 1
            self.AddNewTabWidget(num)
        elif num >= cur_num:
            for i in range(cur_num, (num + 1)):
                self.tabs.append(None)
                self.AddNewTabWidget(num)
        else:
            pass

        # タブインスタンスを生成
        if self.tabs[num] is None:
            self.tabs[num] = OperationTab(self, num)

        # データが指定されていれば
        if mm is not None:
            self.AddMatrix(mm, num)

        return num

    ##############################################
    def AddNewTabWidget(self, num):
        tabT = self.tname[num]
        tabw = self.findChild(QtWidgets.QTabWidget, u"tabWidget")
        tt = VisContQTab()
        new_tab = tt.CreateTab(tabw, tabT)
        tabw.addTab(new_tab, tabT)

    ##############################################
    def OnApply(self, evt=None):
        """
        開いているタブのパラメータを他のタブ画面にコピーする
        @param  evt 　イベント
        @retval 無し
        """
        # 開いているタブのパラメータを取得する
        num = self.note.currentIndex()
        # num = self.note.GetSelection()
        param = self.tabs[num].GetTabParam()

        # 他のタブにパラメータを設定する
        for i in range(len(self.tabs)):
            if i != num:
                self.tabs[i].SetTabParam(param)

    ##############################################
    def OnOpperate(self, evt=None):
        """
        ##[inamura 120709]
        """
        # show dialog
        dlg = DataOperatorDialog(self)

    ##############################################
    def AddMatrix(self, matrix, num=-1):
        """
        マトリックスデータの追加
        @param  matrix 　エレメントコンテナマトリックス
        @param  num  データを追加するタブのNO.  -1 は指定無し
        @retval 無し
        """
        if num < 0 or num >= len(self.tabs):
            num = self.AddNewTab(matrix, num)
            return
        # タブが指定されていなければ
        # if num < 0:
            # 空のタブをさがす、なければ置き換え
            # num = self.GetTabNum()
            # キャンセルか
            # if num is None:
            #    return

        # マトリックスクラスでデータ読み込み
        if isinstance(matrix, mm.ElementContainerMatrix):
            self.tabs[num].SetDataToTab(matrix)

    ##############################################

    def OnLoadData(self):
        """
        Load ElementContainerMatrix from binary file
        @param None
        @retval None
        """
        cpath = os.getcwd()
        filepath, filt = QtWidgets.QFileDialog.getOpenFileName(
            self, "ElementContainerMatrix data file open ...", cpath, filter='ManyoBinary,Dump,Serialized (*.mdb *.dmp *.srlz)')
        # Cancel ?
        if filepath == "":
            return

        file_name = os.path.basename(filepath)
        dir_name = os.path.dirname(filepath)
        base, extcode = os.path.splitext(file_name)
        ret_dat = None
        if extcode == ".mdb":
            ret_dat = Cmm.LoadDataFromManyoBinary(dir_name, file_name)
        elif extcode == ".dmp":
            ret_dat = Cmm.LoadDataFromDump(dir_name, file_name)
        elif extcode == ".srlz":
            ret_dat = Cmm.LoadDataFromSrlz(dir_name, file_name, "ECM")
        else:
            msg = "File extension is invalid."
            ret = QtWidgets.QMessageBox().information(
                None, u"Error", msg, QtWidgets.QMessageBox.Ok)
            return

        if not isinstance(ret_dat, mm.ElementContainerMatrix):
            msg = "This is not ElementContainerMatrix data."
            ret = QtWidgets.QMessageBox().information(
                None, u"Error", msg, QtWidgets.QMessageBox.Ok)
            return

        self.AddMatrix(ret_dat)

    ##############################################
    def OnLoadLegacy(self, *args):
        """
        デテクタマップ画面クローズ
        @param  evt 　イベント
        @retval 無し
        """
        """
        # 空のタブをさがす、なければ置き換え
        num = self.GetTabNum()
        # キャンセルか
        if num is None:
            return

        # データをロードするタブを選択状態とする
        self.note.SetSelection(num)

        # SPE ファイルオープンダイアログ
        dlg = wx.FileDialog(self.frame, 'SPE File Open ...', os.getcwd(), style=wx.OPEN, wildcard='SPE(*.SPE)|*.SPE')

        # キャンセルか
        if dlg.ShowModal() != wx.ID_OK:
            return

        spefile = dlg.GetPath()
        dir = os.path.dirname(spefile)

        # PHX ファイルオープンダイアログ
        dlg = wx.FileDialog(self.frame, 'PHX File Open ...', dir, style=wx.OPEN, wildcard='PHX(*.PHX)|*.PHX')

        # キャンセルか
        if dlg.ShowModal() != wx.ID_OK:
            return

        phxfile = dlg.GetPath()

        # Ei 指定、正常に入力されるまで繰り返す
        while True:
            dlg = wx.TextEntryDialog(self.frame, "Main Ei (mev):",
                                  "Input Ei", style=wx.OK|wx.CANCEL)
            # キャンセルか
            if dlg.ShowModal() != wx.ID_OK:
                return
            try:
                try:
                    ei = float(dlg.GetValue())
                except:
                    raise UtilPlot.PlotException('Common', 'C027', ("Ei",))
                else:
                    if ei > 0.0:
                        break
                    raise UtilPlot.PlotException('Common', 'C009', ("Ei","0.0"))
            except UtilPlot.PlotException, ex:
                UtilPlot.PlotMessage(self.frame, ex)

        # レガシィファイルの読み込みクラスのインスタンス取得
        spe = LegacyFile()
        # SPE ファイルの読み込み
        try:
            spe.ReadFiles(spefile, phxfile, ei)
        except UtilPlot.PlotException, ex:
                UtilPlot.PlotMessage(self.frame, ex)
        else:
            self.tabs[num].ECM = spe
        """
        print("---- OnLoadLegacy")
        return

    ##############################################
    def OnLoadQxQyQzText(self, evt=None):
        """
        ##[inamura 150601]
        """
        cpath = os.getcwd()
        filename, filt = QtWidgets.QFileDialog.getOpenFileName(
            self, "QxQyQz Text File Open ...", cpath, filter='Text Files (*.txt)')
        # dlg = wx.FileDialog(self.frame, 'QxQyQx Text File Open ...', os.getcwd(), style=wx.OPEN, wildcard='Text(*.txt)|*.txt')
        # Cancel ?
        if filename == "":
            return

        # filename = dlg.GetPath()
        fo = open(filename, "r")
        qx = mm.MakeDoubleVector()
        qy = mm.MakeDoubleVector()
        qz = mm.MakeDoubleVector()
        hw = mm.MakeDoubleVector()
        ii = mm.MakeDoubleVector()
        ee = mm.MakeDoubleVector()
        Ei = 0.0
        TAB = "A"
        while(True):
            a_line = fo.readline()
            if a_line == "":
                break
            if a_line.find('##Ei=') == 0:
                sep_line = a_line.split("=")
                ei_str = sep_line[1].split(" ")
                Ei = float(ei_str[0].strip())
            if a_line.find('##TAB=') == 0:
                sep_line = a_line.split("=")
                TAB = sep_line[1].strip()
            elif a_line.find("#") != 0:
                sep_line = a_line.split(" ")
                if len(sep_line) < 6:
                    fo.close()
                    msg = "QxQyQx file is invalid."
                    print(msg)
                    raise UserWarning(msg)
                else:
                    qx.append(float(sep_line[0].strip()))
                    qy.append(float(sep_line[1].strip()))
                    qz.append(float(sep_line[2].strip()))
                    hw.append(float(sep_line[3].strip()))
                    ii.append(float(sep_line[4].strip()))
                    ee.append(float(sep_line[5].strip()))
            else:
                pass

        ec = mm.ElementContainer()
        ec.Add("Qx", qx)
        ec.Add("Qy", qy)
        ec.Add("Qz", qz)
        ec.Add("hw", hw)
        ec.Add("Intensity", ii)
        ec.Add("Error", ee)
        ec.SetKeys("hw", "Intensity", "Error")
        hh_ec = ec.PutHeaderPointer()
        hh_ec.Add("MASKED", 0)

        eca = mm.ElementContainerArray()
        eca.Add(ec)
        hh_eca = eca.PutHeaderPointer()
        hh_eca.Add("MASKED", 0)
        del ec

        ecm = mm.ElementContainerMatrix()
        ecm.Add(eca)
        del eca

        hh_ecm = ecm.PutHeaderPointer()
        hh_ecm.Add("Ei", Ei)
        hh_ecm.Add("QxQyQzTextFile", str(filename))
        hh_ecm.Add("MASKED", 0)
        hh_ecm.Add("isHistogram", 0)

        self.AddNewTab(ecm, self.tdict[TAB])

    ##############################################
    def OnSettings(self, evt=None):
        """
        ##[inamura 150602]
        """
        dlg = SettingDialog(self)

    ##############################################
    # def GetTabNum(self):
        """
        データを読み込むタブを探す
        @param  無し
        @retval 空タブのインデックス
        """
        """
        num = None
        # 空のタブを探す
        for i in range(5):
            if self.tabs[i].smpDat is None:
                num = i
                break
        # 空のタブがあればタブNo.を返す
        if num is not None:
            return num

        # 空のタブが無い場合は置き換えるタブを指定
        while True:
            code,ok = QtWidgets.QInputDialog.getItem(self, u"Tab to Replace", u"Tab =", ["A","B","C","D","E","F","G"])
            if not ok:
                return None

            try:
                return tdict[code]
            except:
                raise UtilPlot.PlotException('Common', 'C013', ("A, B, C, D or E",))
        """

        """
            dlg = wx.TextEntryDialog(self.frame, "Tab to replace (A, B, C, D or E):",
                                  "Tab to Replace", style=wx.OK|wx.CANCEL)

            if dlg.ShowModal() != wx.ID_OK:
                return None
            try:
                #code = dlg.GetValue().strip()
                #code.capitalize()
                if code == 'A' or code == 'a':
                    return 0
                elif code == 'B' or code == 'b':
                    return 1
                elif code == 'C' or code == 'c':
                    return 2
                elif code == 'D' or code == 'd':
                    return 3
                elif code == 'E' or code == 'e':
                    return 4
                else:
                    raise UtilPlot.PlotException('Common', 'C013', ("A, B, C, D or E",))
            except UtilPlot.PlotException, ex:
                UtilPlot.PlotMessage(self.frame, ex)
        """
    ##############################################

    def closeEvent(self, evt):
        """
        Close Event (virtual)
        """
        self.OnClose()
        evt.accept()

    ##############################################
    def OnClose(self, *args):
        """
        デテクタマップ画面クローズ
        @param  evt 　イベント
        @retval 無し
        """
        # ---> 2008/04/27 Minakawa add
        # 2Dプロッタのクローズ要求を出す
        if self.pmap is not None:
            self.pmap.Request2DClose()
        # 全タブに2Dプロッタのクローズ要求を出す
        for tab in self.tabs:
            if tab.pmap is not None:
                tab.pmap.Request2DClose()
        # <--- 2008/04/27 Minakawa add

        for tab in self.tabs:
            # [inamura 120503]-->
            try:
                if tab.ECM is not None:
                    del tab.ECM
            except:
                print("#####*******  Tab has no ECM!!!")

            # if tab.ECM is not None:
            #    del tab.ECM
            # <--[inamura 120503]
            del tab
        self.tabs = []
        # 画面のクローズ
        # self.frame.Destroy()

#######################################
#  OperationTab
#######################################


class OperationTab(object):
    """
    可視化制御画面クラス
    """

    #########################################################
    def __init__(self, parent, num):
        """
        コンストラクタ
        @param  parent  親クラスのインスタンス
        @param  num  タブNo.
        @retval 無し
        """
        self.parent = parent
        self.note = parent.note
        self.frame = parent.frame
        self.num = num      # タブ No.
        tab_list = ["A", "B", "C", "D", "E", "F", "G", "H", "I", "J"]
        self.TABCODE = tab_list[num]

        # self.smpDat = None  # データクラス
        # self.smpInfo = None # サンプル情報クラス
        self.map = None     # スライス後の2次元マップデータ
        self.ECM = None

        # [inamura 150903]-->
        spect_type = "Direct"
        if "UTSUSEMI_INST_CODE" in os.environ:
            sys_name = os.environ["UTSUSEMI_INST_CODE"]
            if sys_name in SpectTypeDic:
                spect_type = SpectTypeDic[sys_name]
        self.VisualCalcSqe = mu.UtsusemiSqeCalc2(
            spect_type)  # [inamura 121228]
        # <--[inamura 150903]

        # タブオブジェクトを取得
        # self.tab = self.note.GetPage(num)
        self.tab = self.note

        self.frame = parent.frame
        # self.res = parent.res

        self.pmap = None
        # self.dat = OperateMatrix()

        # ハンドル取得とイベントハンドラの設定
        self.HandleTB()

        # スライス履歴リストを初期化
        self.hist = []
        self.histI = 0

        # ボタンを選択不可
        self.SetStatus(False)

    #########################################################
    def HandleTB(self):
        """
        テキストボックス読み込み用のハンドル取得
        @param  無し
        @retval 無し
        """

        btn_load_name = u'btLoad_%s' % (self.TABCODE)
        btn_save_name = u'btSave_%s' % (self.TABCODE)
        bt_load = self.tab.findChild(QtWidgets.QPushButton, btn_load_name)
        bt_save = self.tab.findChild(QtWidgets.QPushButton, btn_save_name)
        bt_load.clicked.connect(self.OnLoad)
        bt_save.clicked.connect(self.OnSave)

        """
        # プログレスバーのコントロール取得
        self.gauge = self.res.GetCtrl(self.tab, 'gauge')

        # プログレスバー表示用のタイマーを準備
        self.timer = wx.Timer(panel1)
        panel1.Bind(wx.EVT_TIMER, self.TimerHandler)
        """
        # サンプル情報テキストボックスのコントロールを取得
        self.sinfo = []
        self.sinfoEnabled = []
        for i in range(15):
            ii = i + 1
            txt = u"txt%d_p1_%1s" % (ii, self.TABCODE)
            self.sinfo.append(self.tab.findChild(QtWidgets.QLineEdit, txt))
            self.sinfoEnabled.append(True)

        ch_rotate_axis_tmp = u"chRotateAxis%3s_%1s"
        self.chrotax1 = self.tab.findChild(
            QtWidgets.QComboBox, ch_rotate_axis_tmp % ("1st", self.TABCODE))
        self.chrotax2 = self.tab.findChild(
            QtWidgets.QComboBox, ch_rotate_axis_tmp % ("2nd", self.TABCODE))
        self.chrotax3 = self.tab.findChild(
            QtWidgets.QComboBox, ch_rotate_axis_tmp % ("3rd", self.TABCODE))

        # UVベクトルテキストボックスのコントロールを取得
        self.uv = []
        for i in range(4):
            uv0 = []
            for j in range(5):
                ii = i * 5 + j + 1
                txt = u"txt%d_p2_%1s" % (ii, self.TABCODE)
                uv0.append(self.tab.findChild(QtWidgets.QLineEdit, txt))
            self.uv.append(uv0)

        # Projection Axes unit
        self.uv_unit = []
        for i in range(4):
            txt = u"txt%d_p2_%1s" % (21 + i, self.TABCODE)
            self.uv_unit.append(self.tab.findChild(QtWidgets.QLineEdit, txt))

        # スライス情報テキストボックスのコントロールを取得
        self.slice = []
        for i in range(12):
            ii = i + 1
            txt = u"txt%d_p3_%1s" % (ii, self.TABCODE)
            self.slice.append(self.tab.findChild(QtWidgets.QLineEdit, txt))

        # リソースよりコントロールを取得
        self.chv1 = self.tab.findChild(
            QtWidgets.QComboBox, u"v1ch_%s" % (self.TABCODE))
        self.chv2 = self.tab.findChild(
            QtWidgets.QComboBox, u"v2ch_%s" % (self.TABCODE))
        self.chv3 = self.tab.findChild(
            QtWidgets.QComboBox, u"v3ch_%s" % (self.TABCODE))
        self.chv4 = self.tab.findChild(
            QtWidgets.QComboBox, u"v4ch_%s" % (self.TABCODE))
        self.cbdiagfold = self.tab.findChild(
            QtWidgets.QComboBox, u"cbDiagFoldType_%s" % (self.TABCODE))

        self.FoldTxtList = []
        self.FoldTxtList.append(self.tab.findChild(
            QtWidgets.QLineEdit, u"txtFold1_%s" % (self.TABCODE)))
        self.FoldTxtList.append(self.tab.findChild(
            QtWidgets.QLineEdit, u"txtFold2_%s" % (self.TABCODE)))
        self.FoldTxtList.append(self.tab.findChild(
            QtWidgets.QLineEdit, u"txtFold3_%s" % (self.TABCODE)))
        self.FoldTxtList.append(self.tab.findChild(
            QtWidgets.QLineEdit, u"txtFold4_%s" % (self.TABCODE)))

        self.DiagFoldAxesList = []
        self.DiagFoldAxesList.append(self.tab.findChild(
            QtWidgets.QComboBox, u"cbDiagFoldAx1_%s" % (self.TABCODE)))
        self.DiagFoldAxesList.append(self.tab.findChild(
            QtWidgets.QComboBox, u"cbDiagFoldAx2_%s" % (self.TABCODE)))
        self.DiagFoldAxesList.append(self.tab.findChild(
            QtWidgets.QComboBox, u"cbDiagFoldAx3_%s" % (self.TABCODE)))
        #self.DiagFoldAxesList.append(self.tab.findChild(
        #    QtWidgets.QComboBox, u"cbDiagFoldAx4_%s" % (self.TABCODE)))

        btProj = self.tab.findChild(
            QtWidgets.QPushButton, u'btProj_%s' % (self.TABCODE))
        self.btAutoFill = self.tab.findChild(
            QtWidgets.QPushButton, u"btAutoFill_%s" % (self.TABCODE))

        self.btSlice = self.tab.findChild(
            QtWidgets.QPushButton, u"btSlice_%s" % self.TABCODE)
        self.btBack = self.tab.findChild(
            QtWidgets.QToolButton, u"btBack_%s" % self.TABCODE)
        self.btForward = self.tab.findChild(
            QtWidgets.QToolButton, u"btForward_%s" % self.TABCODE)

        self.btSliceOutTxt = self.tab.findChild(
            QtWidgets.QPushButton, u"btOutTxt_%s" % self.TABCODE)
        self.btSliceOutBin = self.tab.findChild(
            QtWidgets.QPushButton, u"btOutBin_%s" % self.TABCODE)

        self.btOutVbin = self.tab.findChild(
            QtWidgets.QPushButton, u"btOutVbin_%s" % self.TABCODE)

        self.btAutoFillBtnList = [None, None, None, None, None]
        self.btAutoFillBtnList[0] = self.tab.findChild(
            QtWidgets.QPushButton, u'btAutoFillAx1_%s' % (self.TABCODE))
        self.btAutoFillBtnList[1] = self.tab.findChild(
            QtWidgets.QPushButton, u'btAutoFillAx2_%s' % (self.TABCODE))
        self.btAutoFillBtnList[2] = self.tab.findChild(
            QtWidgets.QPushButton, u'btAutoFillAx3_%s' % (self.TABCODE))
        self.btAutoFillBtnList[3] = self.tab.findChild(
            QtWidgets.QPushButton, u'btAutoFillAx4_%s' % (self.TABCODE))
        self.btAutoFillBtnList[4] = self.btAutoFill

        # CHOICEイベントハンドラ登録
        self.chrotax1.activated.connect(
            lambda: self.OnChoiceRotateAxes(self.chrotax1))
        self.chrotax2.activated.connect(
            lambda: self.OnChoiceRotateAxes(self.chrotax2))
        self.chrotax3.activated.connect(
            lambda: self.OnChoiceRotateAxes(self.chrotax3))
        self.chRotationSteps = [self.chrotax1, self.chrotax2, self.chrotax3]
        self.chRotationStepsEnabled = [True, True, True]
        self.chv1.activated.connect(lambda: self.OnChoicePlotAxes(self.chv1))
        self.chv2.activated.connect(lambda: self.OnChoicePlotAxes(self.chv2))
        self.chv3.activated.connect(lambda: self.OnChoicePlotAxes(self.chv3))
        self.chv4.activated.connect(lambda: self.OnChoicePlotAxes(self.chv4))

        self.cbdiagfold.activated.connect(self.OnComboDiagFold)

        self.DiagFoldAxesList[0].activated.connect(
                lambda:self.OnComboDiagFoldAx(self.DiagFoldAxesList[0]))
        self.DiagFoldAxesList[1].activated.connect(
                lambda:self.OnComboDiagFoldAx(self.DiagFoldAxesList[1]))
        self.DiagFoldAxesList[2].activated.connect(
                lambda:self.OnComboDiagFoldAx(self.DiagFoldAxesList[2]))

        # ボタンのイベントハンドラ設定
        btProj.clicked.connect(self.OnProj)
        self.btSlice.clicked.connect(self.OnSlice)

        self.btBack.clicked.connect(self.OnBack)
        self.btForward.clicked.connect(self.OnForward)

        btClr = self.tab.findChild(
            QtWidgets.QPushButton, u'btClr_%s' % self.TABCODE)
        btClr.clicked.connect(self.OnProjClea)
        # self.btSliceOutTxt.clicked.connect( self.SliceOutTxt )
        # self.btSliceOutBin.clicked.connect( self.SliceOutBin )
        self.btAutoFill.clicked.connect(self.OnAutoFill)

        self.btAutoFillBtnList[0].clicked.connect(self.OnAutoFillAxis1)
        self.btAutoFillBtnList[1].clicked.connect(self.OnAutoFillAxis2)
        self.btAutoFillBtnList[2].clicked.connect(self.OnAutoFillAxis3)
        self.btAutoFillBtnList[3].clicked.connect(self.OnAutoFillAxis4)

        self.btSliceOutTxt.clicked.connect(self.OnSliceOutTxt)
        self.btSliceOutBin.clicked.connect(self.OnSliceOutBin)
        self.btOutVbin.clicked.connect(self.OnSliceOutBinOfD4Mat)

        # ボタンコントロールリスト
        # self.lstbt = [btProj, btSlice, self.btAutoFill,btSliceOutTxt,btSliceOutBin, self.btBack, self.btForward] ##[inamura 120216]
        # self.lstbtEnabled = [True,True,True,True,True,True,True]
        # self.lstbt = [btProj, btSlice, self.btAutoFill,self.btBack, self.btForward,self.btOutVbin,self.btSliceOutTxt,self.btSliceOutBin]
        self.lstbt = [btProj, self.btAutoFillBtnList, self.btBack,
                      self.btForward, self.btOutVbin, self.btSliceOutTxt, self.btSliceOutBin]
        self.lstbtEnabled = [True, True, True, True, True, True, True, True]

        self.Initialize()

    #############################################
    def Initialize(self):
        """
        """
        sinfo_val = [1.0, 1.0, 1.0, 90.0, 90.0, 90.0,
                     1.0, 0.0, 0.0, 0.0, 1.0, 0.0,
                     0.0, 0.0, 0.0]
        proj_val = [[1.0, 0.0, 0.0, 0.0],
                    [0.0, 1.0, 0.0, 0.0],
                    [0.0, 0.0, 1.0, 0.0],
                    [0.0, 0.0, 0.0, 1.0]]
        proj_label = ["Qa", "Qb", "Qc", "Energy"]
        proj_unit = ["rlu", "rlu", "rlu", "meV"]
        for i in range(len(sinfo_val)):
            self.sinfo[i].setText("%g" % (sinfo_val[i]))

        for i in range(len(self.chRotationSteps)):
            self.chRotationSteps[i].setEnabled(False)
            self.chRotationStepsEnabled[i] = False
        self.chRotationSteps[0].setEnabled(True)
        self.chRotationStepsEnabled[0] = True
        self.chRotationSteps[0].setCurrentIndex(0)
        for i in [12, 13, 14]:
            self.sinfo[i].setEnabled(False)
            self.sinfoEnabled[i] = False

        for i in range(len(proj_val)):
            v_val = proj_val[i]
            for j in range(len(v_val)):
                self.uv[i][j].setText("%g" % (proj_val[i][j]))
            self.uv[i][4].setText(proj_label[i])
            self.uv_unit[i].setText(proj_unit[i])

        for i in range(3):
            self.uv[i][3].setEnabled(False)
            self.uv[3][i].setEnabled(False)

        for i in range(12):
            self.slice[i].setText("0.0")

        for i in range(4):
            self.FoldTxtList[i].setText("-1")

        self.chv1.setCurrentIndex(2)  # set ComboBox Thickness
        self.chv2.setCurrentIndex(2)  # set Thickness
        self.chv3.setCurrentIndex(2)  # set Thickness
        self.chv4.setCurrentIndex(2)  # set Thickness
        for i in range(4):
            self.slice[i * 3 + 2].setEnabled(False)  # Step is disabled
            self.slice[i * 3 + 2].setText("0.05")  # Initial Step values 0.05

        self.cbdiagfold.setCurrentIndex(0)
        for a_chb in self.DiagFoldAxesList:
            a_chb.setCurrentIndex(0)
            a_chb.setEnabled(False)
        self.tab.findChild(QtWidgets.QComboBox, u"cbDiagFoldAx4_{:1s}".format(self.TABCODE)).setEnabled(False)

        self.btSlice.setEnabled(False)

    #############################################
    def TimerHandler(self, evt):
        """
        タイマー監視ルーチン
        プログレスバーの表示
        @param  evt イベント情報
        @retval 無し
        """
        # num, max = self.spe.GetProgress()
        num, max = (1, 1)
        # 読み込みが開始されたか
        if num > 0:
            # 読み込み中か
            if num < (max - 1):
                pb = num * 20 / max
                # self.gauge.SetValue(pb)
            # 読み込み終了
            else:
                # プログレスバーを消す
                # self.gauge.Hide()
                # タイマー停止
                self.timer.Stop()
                # タブにデータを表示
                # self._SetData()

    #########################################

    def SetDataToTab(self, ecm):
        """
        タブにデータを設定
        @param ecm ElementContainerMatrix
        @retval 無し
        """
        if self.ECM is not None:
            del self.ECM

        self.ECM = mm.ElementContainerMatrix(ecm)

        self._SetData()

    #########################################
    def _SetData(self):
        """
        タブにデータを設定
        @param  無し
        @retval 無し
        """
        # サンプル情報クラスの生成
        # self.smpInfo = SampleInfo(self.smpDat.sample)
        # self.smpInfo.SetInfoFromHeader(self.smpDat.ECMHeader) #[inamura 101001]
        # スライス履歴を初期化
        self._InitSlice()
        # サンプル名をタブに表示
        smp = self.tab.findChild(
            QtWidgets.QLabel, u'sample_%s' % (self.TABCODE))
        ecm_h = self.ECM.PutHeader()
        if (ecm_h.CheckKey("SampleName") == 1):
            smp.setText(ecm_h.PutString("SampleName"))

        # Ei値をタブに表示
        if mu.UtsusemiEnvGetInstCode() == "DNA":
            Ef = self.ECM(0, 0).PutHeaderPointer(
            ).PutDouble(mu.UTSUSEMI_KEY_HEAD_EF)
            strEi = "%.5f" % Ef
            label_Ei = self.tab.findChild(
                QtWidgets.QLabel, u'label2_%s' % (self.TABCODE))
            label_Ei.setText("Ef [meV] :")
        else:
            strEi = "%.2f" % ecm_h.PutDouble(mu.UTSUSEMI_KEY_HEAD_EI)
        stei = self.tab.findChild(
            QtWidgets.QLabel, u'stei_%s' % (self.TABCODE))
        stei.setText(strEi)
        # サンプル情報表示
        self._DispSampleInfo()

        # 射影ボタンを選択可、スライスボタンを選択不可とする
        self.SetStatus(False)  # [inamura 120214]
        self.SetStatus(True, 1)
        code = self.note.tabText(self.num)
        # タブにデータロード済みマークをつける
        self.note.setTabText(self.num, code + "*")

    #########################################################
    def _DispSampleInfo(self):
        """
        サンプル情報を表示
        @param  無し
        @retval 無し
        """

        ecm_h = self.ECM.PutHeader()
        if (ecm_h.CheckKey(mu.UTSUSEMI_KEY_HEAD_SAMPLE_LATTICECONSTS) == 1):
            lcs = ecm_h.PutDoubleVector(mu.UTSUSEMI_KEY_HEAD_SAMPLE_LATTICECONSTS)
            self.sinfo[0].setText("%.3f" % lcs[0])
            self.sinfo[1].setText("%.3f" % lcs[1])
            self.sinfo[2].setText("%.3f" % lcs[2])
            self.sinfo[3].setText("%.1f" % lcs[3])
            self.sinfo[4].setText("%.1f" % lcs[4])
            self.sinfo[5].setText("%.1f" % lcs[5])
        if (ecm_h.CheckKey(mu.UTSUSEMI_KEY_HEAD_SAMPLE_UVECT) == 1):
            suv = ecm_h.PutDoubleVector(mu.UTSUSEMI_KEY_HEAD_SAMPLE_UVECT)
            self.sinfo[6].setText("%.1f" % suv[0])
            self.sinfo[7].setText("%.1f" % suv[1])
            self.sinfo[8].setText("%.1f" % suv[2])
        if (ecm_h.CheckKey(mu.UTSUSEMI_KEY_HEAD_SAMPLE_VVECT) == 1):
            svv = ecm_h.PutDoubleVector(mu.UTSUSEMI_KEY_HEAD_SAMPLE_VVECT)
            self.sinfo[9].setText("%.1f" % svv[0])
            self.sinfo[10].setText("%.1f" % svv[1])
            self.sinfo[11].setText("%.1f" % svv[2])
        if (ecm_h.CheckKey("SampleRotatePhi") == 1):
            phi = ecm_h.PutDouble("SampleRotatePhi")
            self.sinfo[12].setText("%.1f" % phi)

    #########################################################

    def GetTabParam(self):
        """
        タブのもつパラメータ(テキストボックスの値他)を返す
        @param  無し
        @retval パラメータの一覧(リスト)
        """
        param = []
        # サンプル情報を取得
        for ss in self.sinfo:
            param.append(ss.text())

        # Rotation info
        for ii in self.chRotationSteps:
            param.append(ii.currentIndex())

        # 射影情報を取得
        # [inamura 100201]-->
        # for i in range(3):
        for i in range(4):  # <--[inamura 100201]
            for j in range(5):
                param.append(self.uv[i][j].text())
        # [inamura 100201]-->
        # 縮約軸の情報を取得
        # param.append(self.rbox.GetSelection())
        # <--[inamura100201]
        # スライス情報を取得
        for sl in self.slice:
            param.append(sl.text())
        # 軸情報を取得
        param.append(self.chv1.currentIndex())  # [inamura 150526]
        param.append(self.chv2.currentIndex())  # [inamura 150526]
        param.append(self.chv3.currentIndex())  # [inamura 150526]
        param.append(self.chv4.currentIndex())  # [inamura 150526]

        return param

    #########################################################
    def SetTabParam(self, param):
        """
        タブのもつパラメータ(テキストボックスの値他)に値を設定
        @param  param パラメータの一覧(リスト)
        @retval 無し
        """
        k = 0
        # サンプル情報を設定
        for ss in self.sinfo:
            ss.setText(param[k])
            k += 1

        # Rotation Info
        for ii in self.chRotationSteps:
            ii.setCurrentIndex(param[k])
            self.OnChoiceRotateAxes(ii)
            k += 1

        # 射影情報を設定
        # [inamura100201]-->
        for i in range(4):  # <--[inamura100201]
            for j in range(5):
                self.uv[i][j].setText(param[k])
                k += 1

        # [inamura100201]
        # 縮約軸の情報を設定
        # self.rbox.SetSelection(param[k])
        # k += 1
        # <--[inamura100201]

        # スライス情報を設定
        for sl in self.slice:
            sl.setText(param[k])
            k += 1

        # 軸情報を設定
        self.chv1.setCurrentIndex(param[k])
        self.chv2.setCurrentIndex(param[k + 1])
        self.chv3.setCurrentIndex(param[k + 2])
        self.chv4.setCurrentIndex(param[k + 3])  # [inamura 150526]
        # ステップテキストボックスの選択可/不可を設定
        self.SetStepEnable()

        # スライス履歴を初期化
        self._InitSlice()

    #########################################
    def OnRadioBox(self, evt):  # No Need
        """
        ラジオボタンボックスイベント処理
        @param evt　　イベント
        @retval 無し
        """
        ax = evt.GetSelection()
        # 表示を初期化
        # [inamura 100127]-->
        val = [["1", "0", "0", "0"], ["0", "1", "0", "0"],
               ["0", "0", "1", "0"], ["0", "0", "0", "1"]]
        for i in range(4):
            for j in range(4):
                self.uv[i][j].setText(val[i][j])

        self.uv[0][4].setText("Qa (rlu)")
        self.uv[1][4].setText("Qb (rlu)")
        self.uv[2][4].setText("Qc (rlu)")
        self.uv[3][4].setText("Energy (meV)")

        # <--[inamura 100127]
    #########################################
    def OnChoiceRotateAxes(self, sender=None):
        """
        CHOICE Event
        ##[inamura 150526]
        @param sender    QtObj
        @retval None
        """

        if sender == self.chrotax1:
            if self.chrotax1.currentIndex() == 0:
                self.sinfo[12].setEnabled(False)
                self.sinfoEnabled[12] = False
                self.chrotax2.setEnabled(False)
                self.sinfo[13].setEnabled(False)
                self.sinfoEnabled[13] = False
                self.chrotax3.setEnabled(False)
                self.sinfo[14].setEnabled(False)
                self.sinfoEnabled[14] = False
            else:
                self.sinfo[12].setEnabled(True)
                self.sinfoEnabled[12] = True
                self.chrotax2.setEnabled(True)
                if self.chrotax2.currentIndex() == 0:
                    self.sinfo[13].setEnabled(False)
                    self.sinfoEnabled[13] = False
                    self.chrotax3.setEnabled(False)
                    self.sinfo[14].setEnabled(False)
                    self.sinfoEnabled[14] = False
                else:
                    self.sinfo[13].setEnabled(True)
                    self.sinfoEnabled[13] = True
                    self.chrotax3.setEnabled(True)
                    if self.chrotax3.currentIndex() == 0:
                        self.sinfo[14].setEnabled(False)
                        self.sinfoEnabled[14] = False
                    else:
                        self.sinfo[14].setEnabled(True)
                        self.sinfoEnabled[14] = True

        elif sender == self.chrotax2:
            if self.chrotax1.currentIndex() == 0:
                self.sinfo[13].setEnabled(False)
                self.sinfoEnabled[13] = False
                self.chrotax3.setEnabled(True)
                self.sinfo[14].setEnabled(False)
                self.sinfoEnabled[14] = False
            else:
                if sender.currentIndex() == 0:
                    self.sinfo[13].setEnabled(False)
                    self.sinfoEnabled[13] = False
                    self.chrotax3.setEnabled(False)
                    self.sinfo[14].setEnabled(False)
                    self.sinfoEnabled[14] = False
                else:
                    self.chrotax3.setEnabled(True)
                    self.sinfo[13].setEnabled(True)
                    self.sinfoEnabled[13] = True
                    if self.chrotax3.currentIndex() == 0:
                        self.sinfo[14].setEnabled(False)
                        self.sinfoEnabled[14] = False
                    else:
                        self.sinfo[14].setEnabled(True)
                        self.sinfoEnabled[14] = True

        else:
            if (self.chrotax1.currentIndex() == 0) or (self.chrotax2.currentIndex() == 0) or (sender.currentIndex() == 0):
                self.sinfo[14].setEnabled(False)
                self.sinfoEnabled[14] = False
            else:
                self.sinfo[14].setEnabled(True)
                self.sinfoEnabled[14] = True

    #########################################
    def OnChoicePlotAxes(self, sender=None):
        """
        コンボボックスイベント処理
        @param evt　　イベント
        @retval 無し
        """
        # ステップテキストボックスを取得
        # [inamura 150526]-->
        if sender == self.chv1:
            step = self.slice[2]
        elif sender == self.chv2:
            step = self.slice[5]
        elif sender == self.chv3:
            step = self.slice[8]
        else:
            step = self.slice[11]
        # 暑さ指定ならステップは選択不可
        if sender.currentIndex() == 2:  # 0..X-Axis, 1..Y-Axis, 2..Thickness
            step.setEnabled(False)
        else:
            step.setEnabled(True)
        # <--[inamura 150526]
        self.CheckEnabledSlice()

    #########################################
    def CheckEnabledSlice(self):
        """Check Slice is enabled from ComboBox for slice axies
        """
        # Control "Slice" button by the values of Plot Axis combo boxes
        clist = [0, 0, 0, 0]
        clist[0] = self.chv1.currentIndex()
        clist[1] = self.chv2.currentIndex()
        clist[2] = self.chv3.currentIndex()
        clist[3] = self.chv4.currentIndex()
        xaxis = 0
        yaxis = 0
        for a_c in clist:
            if a_c == 0:
                xaxis += 1
            elif a_c == 1:
                yaxis += 1
        # AutoFill button is enabled
        if xaxis == 1 and yaxis == 1 and self.lstbtEnabled[1]:
            self.btSlice.setEnabled(True)
        else:
            self.btSlice.setEnabled(False)

    # [inamura 1307xx]->
    def OnComboDiagFold(self, evt=None):
        """
        """
        index = 0
        if isinstance(evt, int):
            index = evt
        else:
            index = self.cbdiagfold.currentIndex()

        if index == 0:
            for obj in self.DiagFoldAxesList:
                obj.setCurrentIndex(0)
                obj.setEnabled(False)
        else:
            for obj in self.DiagFoldAxesList:
                obj.setEnabled(True)
    def OnComboDiagFoldAx(self, sender=None):
        """
        """
        c_id = sender.currentIndex()
        if c_id == 0:
            return
        for a_cb in self.DiagFoldAxesList:
            if a_cb != sender:
                if a_cb.currentIndex() == c_id:
                    a_cb.setCurrentIndex(0)


    #########################################
    def OnProj(self, *args):
        """
        Exec Projection ボタン押下イベント処理
        射影処理を実行
        @param evt　　イベント
        @retval 無し
        """
        # サンプル情報テキストボックスの値を取得
        sample = []
        try:
            # サンプル情報をテキストボックスから取得
            for cont in self.sinfo:
                anum = cont.text().strip()
                try:
                    num = float(anum)
                except:
                    raise UtilPlot.PlotException(
                        'Common', 'C027', ("Sample Info",))
                sample.append(num)

            # [inamura 150526]-->
            if not self.sinfoEnabled[12]:
                sample[12] = 0.0
            if not self.sinfoEnabled[13]:
                sample[13] = 0.0
            if not self.sinfoEnabled[14]:
                sample[14] = 0.0
            # <--[inamura 150526]

            # サンプル情報クラスに詰め替え
            ecm_h = self.ECM.PutHeaderPointer()

            lcv = mm.MakeDoubleVector()
            for i in range(6):
                lcv.append(sample[i])
            if ecm_h.CheckKey(mu.UTSUSEMI_KEY_HEAD_SAMPLE_LATTICECONSTS) == 1:
                ecm_h.OverWrite(mu.UTSUSEMI_KEY_HEAD_SAMPLE_LATTICECONSTS, lcv)
            else:
                ecm_h.Add(mu.UTSUSEMI_KEY_HEAD_SAMPLE_LATTICECONSTS, lcv)

            uv = mm.MakeDoubleVector()
            vv = mm.MakeDoubleVector()
            for i in range(3):
                uv.append(sample[6 + i])
                vv.append(sample[9 + i])
            if ecm_h.CheckKey(mu.UTSUSEMI_KEY_HEAD_SAMPLE_UVECT) == 1:
                ecm_h.OverWrite(mu.UTSUSEMI_KEY_HEAD_SAMPLE_UVECT, uv)
            else:
                ecm_h.Add(mu.UTSUSEMI_KEY_HEAD_SAMPLE_UVECT, uv)
            if ecm_h.CheckKey(mu.UTSUSEMI_KEY_HEAD_SAMPLE_VVECT) == 1:
                ecm_h.OverWrite(mu.UTSUSEMI_KEY_HEAD_SAMPLE_VVECT, vv)
            else:
                ecm_h.Add(mu.UTSUSEMI_KEY_HEAD_SAMPLE_VVECT, vv)

            if ecm_h.CheckKey("SampleRotatePhi") == 1:
                ecm_h.OverWrite("SampleRotatePhi", float(sample[12]))
            else:
                ecm_h.Add("SampleRotatePhi", float(sample[12]))

            # [inamura 150526]-->
            rotSteps = mm.MakeDoubleVector()
            # self.chRotationSteps is [self.chrotax1,self.chrotax2,self.chrotax3]
            for i in range(3):
                if self.sinfoEnabled[12 + i]:
                    axis_num = -1.0
                    if self.chRotationSteps[i].currentIndex() == 1:   # if Y-axis
                        axis_num = 1.0                             # 1 means Y-axis in VisualCalcSqe
                    elif self.chRotationSteps[i].currentIndex() == 2:  # if Z-axis
                        axis_num = 2.0                             # 2 means Z-axis in VisualCalcSqe
                    elif self.chRotationSteps[i].currentIndex() == 3:  # if X-axis
                        axis_num = 0.0                             # 0 means X-axis in VisualCalcSqe
                    else:
                        break
                    if axis_num > -1.0:
                        rotSteps.append(axis_num)                # axis number
                        rotSteps.append(float(sample[12 + i]))   # angle
                else:
                    break

            if ecm_h.CheckKey(mu.UTSUSEMI_KEY_HEAD_SAMPLE_ROTATESTEPS) == 1:
                ecm_h.OverWrite(mu.UTSUSEMI_KEY_HEAD_SAMPLE_ROTATESTEPS, rotSteps)
            else:
                ecm_h.Add(mu.UTSUSEMI_KEY_HEAD_SAMPLE_ROTATESTEPS, rotSteps)
            # <--[inamura 150526]

            # U1, U2, U3 ベクトルをテキストボックスから取得
            viewAxis = np.zeros([4, 4], np.float64)
            for i in range(4):
                # <-- [inamura 100127]
                for j in range(4):
                    anum = self.uv[i][j].text()
                    try:
                        num = float(anum)
                    except:
                        raise UtilPlot.PlotException(
                            'Common', 'C027', ("U Vector",))

                    viewAxis[i][j] = num
                # U1, U2, U3, ベクトルが直交しているかどうかを確認
                # sp0 = dot(viewAxis[0], viewAxis[1])
                # sp1 = dot(viewAxis[1], viewAxis[2])
                # sp2 = dot(viewAxis[0], viewAxis[2])

                # 内積誤差の範囲で0でなかったら
                # if abs(sp0) > 0.01 or abs(sp1) > 0.01 or abs(sp2) > 0.01:
                #    raise UtilPlot.PlotException('VisCont', 'V000', ())
            # U1, U2, U3, ベクトルが１次独立しているかどうかを確認
            try:
                v = mm.MakeDoubleVector(9)
                v[0] = float(self.uv[0][0].text())
                v[1] = float(self.uv[0][1].text())
                v[2] = float(self.uv[0][2].text())
                v[3] = float(self.uv[1][0].text())
                v[4] = float(self.uv[1][1].text())
                v[5] = float(self.uv[1][2].text())
                v[6] = float(self.uv[2][0].text())
                v[7] = float(self.uv[3][1].text())
                v[8] = float(self.uv[2][2].text())
                p = mu.UtsusemiSqeCalc2()
                r = p.InverseMatrix(v)
                if r.empty():
                    raise UserWarning(
                        "Given Vectors for Projection are not linearly independent")
            except:
                pass
        except UtilPlot.PlotException as ex:
            UtilPlot.PlotMessage(self.frame, ex)
            return

        # 射影処理を実行
        self.SetStatus(False)
        self.VisualCalcSqe.SetTarget(self.ECM)
        viewAxis_in = mm.MakeDoubleVector()
        for i in range(4):
            for j in range(4):
                viewAxis_in.append(viewAxis[i][j])
        # [inamura 150601]-->
        # all_u = self.VisualCalcSqe.Projection(viewAxis_in)
        hh_ECM = self.ECM.PutHeaderPointer()
        if hh_ECM.CheckKey("QxQyQzTextFile") == 1:
            all_u = self.VisualCalcSqe.Projection_QxQyQz(viewAxis_in)
        else:
            all_u = self.VisualCalcSqe.Projection(viewAxis_in)
        # <--[inamura 150601]

        # スライスボタンを選択可とする
        # self.SetStatus(True,  4)
        # self.SetStatus(True,  5) ##[inamura 120216]
        self.SetStatus(True)  # [inamura 181214]

        code = self.note.tabText(self.num)
        # タブに射影済みマークをつける
        self.note.setTabText(self.num, code[0] + "**")

        # スライス履歴を初期化
        self._InitSlice()

        # Auto filling
        # self.OnAutoFill()
        hw_v = self.ECM(0, 0).PutX()
        dhw = hw_v[1] - hw_v[0]
        self.slice[11].setText("{0:g}".format(dhw))
        self.CheckEnabledSlice()
        # [inamura 100615]-->
        # print "On Proj, min and max Vx=",self.dat.Vx.min(),self.dat.Vx.max()
        # print "On Proj, min and max Vy=",self.dat.Vy.min(),self.dat.Vy.max()
        # print "On Proj, min and max Vz=",self.dat.Vz.min(),self.dat.Vz.max()
        # print "On Proj, min and max Vw=",self.dat.Vw.min(),self.dat.Vw.max()
        # [inamura 100930]
        # self.slice[0].SetValue( "%g" % round( (self.dat.Vx.min()-0.1),1) )
        # self.slice[1].SetValue( "%g" % round( (self.dat.Vx.max()+0.1),1) )
        # self.slice[3].SetValue( "%g" % round( (self.dat.Vy.min()-0.1),1) )
        # self.slice[4].SetValue( "%g" % round( (self.dat.Vy.max()+0.1),1) )
        # self.slice[6].SetValue( "%g" % round( (self.dat.Vz.min()-0.1),1) )
        # self.slice[7].SetValue( "%g" % round( (self.dat.Vz.max()+0.1),1) )
        # self.slice[9].SetValue( "%g" % round( (self.dat.Vw.min()-0.1),1) )
        # self.slice[10].SetValue( "%g" % round( (self.dat.Vw.max()+0.1),1) )
        # <--[inamura 100930]<--[inamura 100616]

    # [inamura 100130]-->
    #########################################
    def OnProjClea(self, *args):
        # 表示を初期化
        val = [["1", "0", "0", "0"], ["0", "1", "0", "0"],
               ["0", "0", "1", "0"], ["0", "0", "0", "1"]]
        for i in range(4):
            for j in range(4):
                self.uv[i][j].setText(val[i][j])

        self.uv[0][4].setText("Qa")
        self.uv[1][4].setText("Qb")
        self.uv[2][4].setText("Qc")
        self.uv[3][4].setText("Energy")
        self.uv_unit[0].setText("rlu")
        self.uv_unit[1].setText("rlu")
        self.uv_unit[2].setText("rlu")
        self.uv_unit[3].setText("meV")

        # スライスボタンを選択不可とする
        if self.lstbtEnabled[0]:
            self.SetStatus(False)
            self.SetStatus(True, 1)
        else:
            self.SetStatus(False)
        self.btSlice.setEnabled(False)

    # <--[inamura 100130]
    # [inamura 100930]-->
    #########################################
    def OnAutoFill(self, *args):
        try:
            qrv = self.VisualCalcSqe.PutQRange()
            self.slice[0].setText("%g" % round((qrv[0] - 0.1), 1))
            self.slice[1].setText("%g" % round((qrv[1] + 0.1), 1))
            self.slice[3].setText("%g" % round((qrv[2] - 0.1), 1))
            self.slice[4].setText("%g" % round((qrv[3] + 0.1), 1))
            self.slice[6].setText("%g" % round((qrv[4] - 0.1), 1))
            self.slice[7].setText("%g" % round((qrv[5] + 0.1), 1))
            self.slice[9].setText("%g" % round((qrv[6] - 0.1), 1))
            self.slice[10].setText("%g" % round((qrv[7] + 0.1), 1))
        except:
            print("Do the projection first.")

    # <--[inamura 100930]
    # [inamura 150316]-->
    #########################################
    def OnAutoFillAxis1(self):
        """
        """
        qrv = self.VisualCalcSqe.PutQRange()
        self.slice[0].setText("%g" % round((qrv[0] - 0.1), 1))
        self.slice[1].setText("%g" % round((qrv[1] + 0.1), 1))
    #########################################

    def OnAutoFillAxis2(self):
        """
        """
        qrv = self.VisualCalcSqe.PutQRange()
        self.slice[3].setText("%g" % round((qrv[2] - 0.1), 1))
        self.slice[4].setText("%g" % round((qrv[3] + 0.1), 1))
    #########################################

    def OnAutoFillAxis3(self):
        """
        """
        qrv = self.VisualCalcSqe.PutQRange()
        self.slice[6].setText("%g" % round((qrv[4] - 0.1), 1))
        self.slice[7].setText("%g" % round((qrv[5] + 0.1), 1))
    #########################################

    def OnAutoFillAxis4(self):
        """
        """
        qrv = self.VisualCalcSqe.PutQRange()
        self.slice[9].setText("%g" % round((qrv[6] - 0.1), 1))
        self.slice[10].setText("%g" % round((qrv[7] + 0.1), 1))

    #########################################
    def OnAutoFillAxes(self, *args):
        try:
            btn_name = self.tab.sender()
            qrv = self.VisualCalcSqe.PutQRange()
            if btn_name == self.btAutoFillBtnList[0]:
                self.slice[0].setText("%g" % round((qrv[0] - 0.1), 1))
                self.slice[1].setText("%g" % round((qrv[1] + 0.1), 1))
            elif btn_name == self.btAutoFillBtnList[1]:
                self.slice[3].setText("%g" % round((qrv[2] - 0.1), 1))
                self.slice[4].setText("%g" % round((qrv[3] + 0.1), 1))
            elif btn_name == self.btAutoFillBtnList[2]:
                self.slice[6].setText("%g" % round((qrv[4] - 0.1), 1))
                self.slice[7].setText("%g" % round((qrv[5] + 0.1), 1))
            elif btn_name == self.btAutoFillBtnList[3]:
                self.slice[9].setText("%g" % round((qrv[6] - 0.1), 1))
                self.slice[10].setText("%g" % round((qrv[7] + 0.1), 1))
            else:
                pass
        except:
            print("Do the projection first")

    # <--[inamura 150316]
    #########################################
    def _InitSlice(self):
        """
        スライス履歴を初期化
        @param  無し
        @retval 無し
        """
        # スライス履歴リストを初期化
        self.hist = []
        self.histI = 0
        self.btBack.setEnabled(False)
        self.btForward.setEnabled(False)

    #########################################
    def _Slice(self):
        """
        Data Slice
        @param None
        @return tupple of result data, xkey, ykey, xtitle and ytitle
        """
        avs = []
        avs.append(self.chv1.currentIndex())
        avs.append(self.chv2.currentIndex())
        avs.append(self.chv3.currentIndex())
        avs.append(self.chv4.currentIndex())
        AxType = mm.MakeStringVector()

        n1 = []
        n2 = []
        n3 = []
        for i in range(4):
            if avs[i] == 0:
                n1.append(i)
                AxType.append("X")
            elif avs[i] == 1:
                n2.append(i)
                AxType.append("Y")
            else:
                n3.append(i)
                AxType.append("T")
                if len(n3) > 1:
                    avs[i] = 3

        if len(n1) != 1 or len(n2) != 1 or len(n3) != 2:
            raise UtilPlot.PlotException('VisCont', 'V001', ())

        # [inamura 1307xx]-->
        foldings = mm.MakeDoubleVector()
        for i in range(7):
            foldings.append(-1.0)

        for i in range(len(self.FoldTxtList)):
            tmp_f = float(self.FoldTxtList[i].text())
            if tmp_f < 0.0:
                tmp_f = -1.0
            foldings[i] = tmp_f

        DiagCond = self.cbdiagfold.currentIndex()
        # print "### DiagCond = ",DiagCond
        if (DiagCond == 1) or (DiagCond == 2) or (DiagCond == 3):
            foldings[4] = float(DiagCond)
            ax_fold = [-1, -1]
            for i, a_cb in enumerate(self.DiagFoldAxesList):
                c_id = a_cb.currentIndex()
                if c_id == 1: # X' is selected
                    ax_fold[0] = i
                elif c_id == 2: # Y' is selected
                    ax_fold[1] = i
            if -1 in ax_fold:
                print("Diagonal Folding failed. (X' or Y' is not found.)")
            else:
                foldings[5] = float(ax_fold[0])
                foldings[6] = float(ax_fold[1])
        else:
            foldings[4] = -1.0
            foldings[5] = 0.0
            foldings[6] = 0.0
        # if self.ckbf1.GetValue(): # diagonal line Y=X
        #    foldings[4] = 1.0
        # if self.ckbf2.GetValue(): # diagonal line Y=-X
        #    foldings[5] = 1.0
        # print "Foldings=",foldings[0],foldings[1],foldings[2],foldings[3],foldings[4],foldings[5],foldings[6]
        # <--[inamura 1307xx]

        A1range = mm.MakeDoubleVector()
        A2range = mm.MakeDoubleVector()
        A3range = mm.MakeDoubleVector()
        A4range = mm.MakeDoubleVector()

        for i in range(3):
            A1range.append(float(self.slice[0 + i].text()))
            A2range.append(float(self.slice[3 + i].text()))
            A3range.append(float(self.slice[6 + i].text()))
            A4range.append(float(self.slice[9 + i].text()))

        # ret = self.VisualCalcSqe.Slice( A1range,A2range,A3range,A4range,AxType,foldings )
        ret = self.VisualCalcSqe.Slice(A1range, A2range, A3range, A4range,
                                       AxType, foldings, self.parent.isSliceAverageMode)  # [inamura 150602]

        """
        xv = self.VisualCalcSqe.PutXArray()
        yv = self.VisualCalcSqe.PutYArray()
        II = self.VisualCalcSqe.PutDArray()
        EE = self.VisualCalcSqe.PutEArray()
        #print "size=",xv.size(),yv.size(),II.size(),EE.size()

        h = []
        v = []
        for i in range(xv.size()):
            h.append(xv[i])
        for i in range(yv.size()):
            v.append(yv[i])

        h = array(h)
        v = array(v)

        H, V = meshgrid(h, v)

        numx = xv.size()-1
        numy = yv.size()-1
        #print "numx,numy=",numx,numy

        data =np.zeros((numy,numx), np.float64)
        err =np.zeros((numy,numx), np.float64)

        for j in range(numx):
            for k in range(numy):
                data[k,j] = II[ j*numy + k ]
                err[k,j] = EE[ j*numy + k ]

        #self.map = ( data, err, H, V, 1 )
        self.map = ( data, err, H, V, 0 ) ##[inamura 130624]
        """
        if self.map is not None:
            del self.map
        self.map = mm.ElementContainerArray()
        xtitle = ""
        ytitle = ""
        xunit = ""
        yunit = ""
        for i in range(4):
            if AxType[i] == "X":
                xtitle = self.uv[i][4].text()
                xunit = self.uv_unit[i].text()
            elif AxType[i] == "Y":
                ytitle = self.uv[i][4].text()
                yunit = self.uv_unit[i].text()
        xkey = xtitle.replace(" ", "")
        ykey = ytitle.replace(" ", "")
        xkey = xkey.replace(",", "")
        ykey = ykey.replace(",", "")
        if not self.VisualCalcSqe.SetSlicedElementContainerArray(self.map, str(ykey), str(xkey), str(yunit), str(xunit)):
            del self.map
            self.map = None
            return (False, "", "")

        # self.SetStatus(True, 4)
        # self.SetStatus(True, 5) ##[inamura 120216]
        # self.SetStatus(True) ##[inamura 181214]

        return (True, xkey, ykey, xtitle, ytitle)

    #########################################
    def OnSlice(self, *args):
        """
        Slice ボタン押下イベント処理
        2D マップにスライス結果を表示
        @param evt　　イベント
        @retval 無し
        """
        flag, xkey, ykey, xtitle, ytitle = self._Slice()
        if not flag:
            return

        # タブラベルを取得
        code = self.note.tabText(self.num)

        if self.pmap is None:
            # self.pmap = Plot2DMap(self.num, code[0], self.frame)
            self.pmap = Plot2DMap(self.num, code[0], self.parent)
        # 2D マップ表示
        self.pmap.PlotMap(self, self.map, (str(xkey), str(ykey)),
                          (str(xtitle), str(ytitle)))

        # 履歴を記録
        self.PutHistory((str(xkey), str(ykey)), (str(xtitle), str(ytitle)))
        # タブラベルにスライスデータ有りのマークをつける
        self.note.setTabText(self.num, code[0] + "***")

    #########################################
    def OnSliceOutTxt(self, *args):
        """
        """
        flag, xkey, ykey, xtitle, ytitle = self._Slice()
        if not flag:
            return

        print("#[inamura 181214] Under construction")

    #########################################
    def OnSliceOutBin(self, *args):
        """
        """
        flag, xkey, ykey, xtitle, ytitle = self._Slice()
        if not flag:
            return

        print("#[inamura 181214] OutBin")
        filepath, filt = QtWidgets.QFileDialog.getSaveFileName(
            self.parent, u"Save Sliced data to Bin File ...", os.getcwd(), filter=u"(*.mdb *.dmp)")
        filepath = str(filepath)
        if filepath == "":
            return

        file_name = os.path.basename(filepath)
        dir_name = os.path.dirname(filepath)
        base, extcode = os.path.splitext(file_name)

        if extcode not in [".mdb", ".dmp"]:
            msg = "File extension is invalid. [.mdb or .dmp]"
            ret = QtWidgets.QMessageBox().information(
                None, u"Error", msg, QtWidgets.QMessageBox.Ok)
            return
        if extcode == ".mdb":
            Cmm.SaveDataToManyoBinary(self.map, dir_name, file_name)
        else:
            Cmm.SaveDataToDump(self.map, dir_name, file_name)
        return

    # [inamura 110206]-->
    #########################################
    def _devideBinAsZeroCenter(self, r_min, r_step):
        """
        calculate min of binning to satisfy that zero becomes center of a bin
        @param r_min (float) min value
        @param r_step (float) step value
        @return r_min (float) calculated min value
        """

        if r_min < 0.0:
            p = -r_step / 2.0
            while(p > r_min):
                p -= r_step
            r_min = p
        else:
            p = r_step / 2.0
            while(p < r_min):
                p += r_step
            r_min = p - r_step

        return r_min
    # <--[inamura 110206]

    #########################################
    def PutHistory(self, keys, labels):
        """
        スライス履歴を保存
        @param labels (tupple) X and Y labels
        @retval 無し
        """
        xkey, ykey = keys
        xlabel, ylabel = labels
        sd = SlicedData(ver=2)  # [inamura 100930]

        # 軸条件を取得
        # [inamura 100127]-->
        # sd.axis = (self.chv1.GetSelection(),self.chv2.GetSelection(), self.chv3.GetSelection())  ##[inamura 150526]
        #
        # スライス条件テキストボックスの文字列を保存
        # for i in range(9):

        sd.axis = (self.chv1.currentIndex(), self.chv2.currentIndex(
        ), self.chv3.currentIndex(), self.chv4.currentIndex())  # [inamura 150526]
        for i in range(12):
            # <--[inamura 100127]
            sd.txts[i] = self.slice[i].text()

        sd._keys = (xkey, ykey)
        sd._titles = (xlabel, ylabel)
        sd.map = self.map
        # 履歴を保存
        self.hist.append(sd)
        self.histI = len(self.hist) - 1
        # 前にデータがあれば
        if self.histI > 0:
            # バックボタンを選択可とする
            self.btBack.setEnabled(True)

    #########################################
    def OnBack(self, *args):
        """
        バック ボタン押下イベント処理
        前のパラメータを表示し、2Dマップ画像を戻す
        @param evt  イベント
        @retval 無し
        """

        self.histI = self.histI - 1
        # 履歴データを表示
        self.DispHistory()
        # フォワードボタンを選択可とする
        self.btForward.setEnabled(True)
        # 前にデータが無ければ
        if self.histI == 0:
            # バックボタンを選択不可とする
            self.btBack.setEnabled(False)

    #########################################
    def OnForward(self, *args):
        """
        前へ ボタン押下イベント処理
        元のパラメータを表示し、2Dマップ画像を戻す
        @param evt  イベント
        @retval 無し
        """
        self.histI += 1
        # 履歴データを表示
        self.DispHistory()
        # バックボタンを選択可とする
        self.btBack.setEnabled(True)
        # 後にデータが無ければ
        if self.histI == len(self.hist) - 1:
            # バックボタンを選択不可とする
            self.btForward.setEnabled(False)

    #########################################
    def DispHistory(self):
        """
        スライス履歴表示、パラメータを設定し
        マップを表示
        @param 無し
        @retval 無し
        """
        sd = self.hist[self.histI]
        # 軸条件を設定
        self.chv1.setCurrentIndex(sd.axis[0])
        self.chv2.setCurrentIndex(sd.axis[1])
        self.chv3.setCurrentIndex(sd.axis[2])
        self.chv4.setCurrentIndex(sd.axis[3])
        # スライス条件テキストボックスに保存文字列を設定
        # [inamura 100127]-->
        # for i in range(9):
        for i in range(12):
            # <--[inamura 100127]
            self.slice[i].setText(sd.txts[i])

        self.SetStepEnable()
        # 2次元マップを表示
        self.pmap.PlotMap(self, sd.map, sd._keys, sd._titles)

    #########################################
    def SetStepEnable(self):
        """
        ステップテキストボックスの選択可・不可を設定
        @param 無し
        @retval 無し
        """
        if self.chv1.currentIndex() == 2:
            self.slice[2].setEnabled(False)
        else:
            self.slice[2].setEnabled(True)

        if self.chv2.currentIndex() == 2:
            self.slice[5].setEnabled(False)
        else:
            self.slice[5].setEnabled(True)

        if self.chv3.currentIndex() == 2:
            self.slice[8].setEnabled(False)
        else:
            self.slice[8].setEnabled(True)

        # [inamura 101020]-->
        if self.chv4.currentIndex() == 2:
            self.slice[11].setEnabled(False)
        else:
            self.slice[11].setEnabled(True)
        # <--[inamura 101020]

    #########################################
    # [inamura 100615]-->
    # def SetStatus(self, flag, num = 4):
    # def SetStatus(self, flag, num = 5): # <--[inamura 100615]
    # def SetStatus(self, flag, num = 6): # <--[inamura 110223]
    # def SetStatus(self, flag, num = 7): # <--[inamura 120215]
    def SetStatus(self, flag, num=7):
        """
        状態表示とボタン制御
        @param flag   ボタンの選択可・不可フラグ
        @param num　　　ボタンの数
        @retval 無し
        """
        # ボタンの選択可・不可
        for i in range(num):
            if type(self.lstbt[i]) == list:
                for a_btn in self.lstbt[i]:
                    a_btn.setEnabled(flag)
            else:
                self.lstbt[i].setEnabled(flag)
            self.lstbtEnabled[i] = flag

    # [inamura 110419]-->
    #########################################
    def _SliceForOutputD4Mat(self, isText=True):
        """
        """
        if isText:
            filename, filt = QtWidgets.QFileDialog.getSaveFileName(
                self.parent, u"Save Output Text File ...", os.getcwd(), filter=u'Text File (*.txt)')
        else:
            filename, filt = QtWidgets.QFileDialog.getSaveFileName(
                self.parent, u"Save Output Bin File ...", os.getcwd(), filter=u"vbin File (*.vbin)")

        # Cancel?
        if filename == "":
            return

        try:

            # Get Slicing parameter from text box on the panel
            param = np.zeros([12], np.float64)

            # get type of axis X, Y or T
            avs = []
            avs.append(self.chv1.currentIndex())
            avs.append(self.chv2.currentIndex())
            avs.append(self.chv3.currentIndex())
            avs.append(self.chv4.currentIndex())

            # Set axis range using type of axis
            for i in range(4):
                r_min = float(self.slice[i * 3].text())
                r_max = float(self.slice[i * 3 + 1].text())
                # if X or Y
                if avs[i] < 2:
                    r_step = float(self.slice[i * 3 + 2].text())
                    r_min = self._devideBinAsZeroCenter(r_min, r_step)
                # if T
                else:
                    r_step = r_max - r_min

                param[i * 3] = r_min
                param[i * 3 + 1] = r_max
                param[i * 3 + 2] = r_step

            print(param)
            ax1 = mm.MakeDoubleVector()
            ax2 = mm.MakeDoubleVector()
            ax3 = mm.MakeDoubleVector()
            ax4 = mm.MakeDoubleVector()

            for i in range(3):
                ax1.append(param[0 + i])
                ax2.append(param[3 + i])
                ax3.append(param[6 + i])
                ax4.append(param[9 + i])

            # Get folding flag
            # [inamura 130617]-->
            # fld = mm.MakeInt4Vector()
            # for i in range(4):
            #    fld.append(0)
            #
            # if self.cks1.GetValue():
            #    fld[0]=1
            # if self.cks2.GetValue():
            #    fld[1]=1
            # if self.cks3.GetValue():
            #    fld[2]=1
            # if self.cks4.GetValue():
            #    fld[3]=1
            fld = mm.MakeDoubleVector()
            for i in range(4):
                fld.append(0)
            for i in range(len(self.FoldTxtList)):
                tmp = float(self.FoldTxtList[i].text())
                if tmp < 0.0:
                    fld[i] = 0.0
                else:
                    fld[i] = 1.0
            # <--[inamura 130617]
            print("Foldings={}, {}, {}, {}".format(
                fld[0], fld[1], fld[2], fld[3]))
            self.SetStatus(False)

            # Execute slicing for output
            savefile = filename
            # convD4Mat = Manyo.ConvertEcmToD4Matrix()
            # convD4Mat.SetTarget( self.ECM )
            """
            if not self.ckbSaveMem.GetValue():
                print "Mapping with much memory."
                convD4Mat.Mapping(ax1,ax2,ax3,ax4,fld)
            else:
                print "Mapping with low memory"
                ff = os.path.join(os.getcwd(),"temp_execslice.bin")
                convD4Mat.MakeTempMapFile( ff, ax1, ax2, ax3, ax4, fld )
                print "Finished make map file"
                convD4Mat.TempMapping()

            ret = convD4Mat.SaveSlicedDataToFile( str(savefile) )
            """
            # convD4Mat.SaveSimpleSlicedDataToFile( str(savefile) )
            # convD4Mat.PartialMapping( str(savefile),ax1,ax2,ax3,ax4,fld )
            # self.VisualCalcSqe.ConvertToD4Mat( str(savefile),ax1,ax2,ax3,ax4,fld )
            self.VisualCalcSqe.ConvertToD4Mat(str(
                savefile), ax1, ax2, ax3, ax4, fld, self.parent.isSliceAverageMode)  # [inamura 150602]
            # self.SetStatus(True, 4)
            # self.SetStatus(True, 5) ##[inamura 120216]
            self.SetStatus(True)  # [inamura 181214]

        except UtilPlot.PlotException as ex:
            UtilPlot.PlotMessage(self.frame, ex)
            return

    #########################################
    def OnSliceOutTxtOfD4Mat(self, evt=None):
        """
        """
        print("On Slice OutTxt")

        self._SliceForOutputD4Mat(isText=True)

    #########################################

    def OnSliceOutBinOfD4Mat(self, evt=None):
        """
        """
        print("On Slice Out bin file")

        self._SliceForOutputD4Mat(isText=False)

    # <--[inamura 110419]
    # [inamrua 110206]-->
    #########################################
    def OnLoad(self, evt=None):
        """
        Load parameters of VisualCont control from xml file
        @param evt
        @return None
        """

        # open dialog
        filename, filt = QtWidgets.QFileDialog.getOpenFileName(
            self.note, "Open Parameter File for VisualCont2 ...", os.getcwd(), filter='xml Files (*.xml)')

        # is Cancel?
        if filename == "":
            return

        # get file path
        xml_file = filename

        # make instance and load file and analysis XML parameter
        vcp = mu.UtsusemiSqeCalcXtalParams(str(xml_file))
        lc = vcp.PutLatticeConsts()
        uv = vcp.PutUVector()
        vv = vcp.PutVVector()
        rv = vcp.PutRotateSteps()
        ro_list = []
        if rv.size() != 0:
            for i in range(int(rv.size() / 2)):
                ax_dic = {0: "X", 1: "Y", 2: "Z"}
                ax_id = int(rv[2 * i])   # axis 0="X", 1="Y", 2="Y"
                ax_val = rv[2 * i + 1]
                ro_list.append((ax_dic[ax_id], ax_val))

        # Set text box on the panel from obtained parameters
        # sample info, U-vector, V-vector and fai
        self.sinfo[0].setText("%6.4f" % float(lc[0]))
        self.sinfo[1].setText("%6.4f" % float(lc[1]))
        self.sinfo[2].setText("%6.4f" % float(lc[2]))
        self.sinfo[3].setText("%6.4f" % float(lc[3]))
        self.sinfo[4].setText("%6.4f" % float(lc[4]))
        self.sinfo[5].setText("%6.4f" % float(lc[5]))
        self.sinfo[6].setText("%6.4f" % float(uv[0]))
        self.sinfo[7].setText("%6.4f" % float(uv[1]))
        self.sinfo[8].setText("%6.4f" % float(uv[2]))
        self.sinfo[9].setText("%6.4f" % float(vv[0]))
        self.sinfo[10].setText("%6.4f" % float(vv[1]))
        self.sinfo[11].setText("%6.4f" % float(vv[2]))

        ro_axis_dic = {"Y": 1, "Z": 2, "X": 3}
        for i, a_rot in enumerate(ro_list):
            ax_num = 0
            try:
                ax_num = ro_axis_dic[a_rot[0]]
            except:
                pass
            self.chRotationSteps[i].setEnabled(True)
            self.chRotationStepsEnabled[i] = True
            self.chRotationSteps[i].setCurrentIndex(ax_num)
            self.sinfo[12 + i].setText("%6.4f" % float(a_rot[1]))
            self.sinfo[12 + i].setEnabled(True)
            self.sinfoEnabled[12 + i] = True
            if (i + 1) < len(self.chRotationSteps):
                self.chRotationSteps[i + 1].setEnabled(True)
                self.chRotationStepsEnabled[i + 1] = True

        # Projection infor
        proj_axes = vcp.PutViewAxes()
        proj_labels = vcp.PutViewAxesLabels()
        proj_units = vcp.PutViewAxesUnits()
        for id in range(4):
            for col in range(4):
                self.uv[id][col].setText("%g" % (proj_axes[4 * id + col]))
            self.uv[id][4].setText(proj_labels[id])
            self.uv_unit[id].setText(proj_units[id])

        # Slicing ranges and steps
        ax_types = vcp.PutAxType()
        for id in range(4):
            type = ax_types[id]
            if type in ["x", "y", "p", "t"]:
                range_axis = vcp.PutAxRange(id, False)
                self.slice[3 * id + 0].setText("%g" % (range_axis[0]))
                self.slice[3 * id + 1].setText("%g" % (range_axis[1]))
                self.slice[3 * id + 2].setText("%g" % (range_axis[2]))
            else:
                print("type in xml file is invalid!!")
                raise
        # axis type for slicing
        dic = {"x": 0, "y": 1, "p": 2, "t": 2}
        self.chv1.setCurrentIndex(dic[ax_types[0]])
        self.chv2.setCurrentIndex(dic[ax_types[1]])
        self.chv3.setCurrentIndex(dic[ax_types[2]])
        self.chv4.setCurrentIndex(dic[ax_types[3]])  # [inamura 150527]

        # folding
        foldings = vcp.PutFolding()
        for i in range(4):
            self.FoldTxtList[i].setText("%g" % (foldings[i]))

        diag_folding = vcp.PutDiagFolding()
        if diag_folding.size() == 0:
            diag_folding.append(0)
        if diag_folding[0] in [0, 1, 2, 3]:
            self.cbdiagfold.setCurrentIndex(diag_folding[0])
            self.OnComboDiagFold(diag_folding[0])
            #if diag_folding[0] == 0:
            #    self.OnComboDiagFold(0)
            #else:
            #    self.OnComboDiagFold(1)
            if diag_folding[0] != 0:
                for obj in self.DiagFoldAxesList:
                    obj.setCurrentIndex(0)
                if diag_folding[1] != 0:
                    self.DiagFoldAxesList[diag_folding[1] - 1].setCurrentIndex(1)
                if diag_folding[2] != 0:
                    self.DiagFoldAxesList[diag_folding[2] - 1].setCurrentIndex(2)

        # Update panel display
        self.SetStepEnable()
        del vcp

    #########################################
    def OnSave(self, evt=None):
        """
        Save parameters to xml file from information on the panel
        @param evt
        @return None
        """
        sample = []
        for i in range(len(self.sinfo)):  # [inamura 161104]
            anum = self.sinfo[i].text().strip()
            try:
                num = float(anum)
            except:
                raise UtilPlot.PlotException(
                    'Common', 'C027', ("Sample Info",))
            sample.append(num)

        # make instance
        vcp = mu.UtsusemiSqeCalcXtalParams()
        vcp.SetLatticeConstants(sample[:6])
        vcp.SetUVvector(sample[6:9], sample[9:12])

        rotationSteps = []
        for i, rax, rflag in zip([0, 1, 2], self.chRotationSteps, self.chRotationStepsEnabled):
            if rflag:
                ax_num = rax.currentIndex()
                if ax_num == 1:
                    rotationSteps.append(["Y", sample[12 + i]])
                elif ax_num == 2:
                    rotationSteps.append(["Z", sample[12 + i]])
                elif ax_num == 3:
                    rotationSteps.append(["X", sample[12 + i]])
                else:
                    break

        for a_step in rotationSteps:
            vcp.AddRotationStep(a_step[0], float(a_step[1]))

        # Make parameters to give to VisContParams
        # axisInfo
        axisInfo = []
        for id in range(4):
            a_list = []
            for col in range(4):
                a_list.append(float(self.uv[id][col].text()))
            a_list.append(self.uv[id][4].text())
            a_list.append(self.uv_unit[id].text())
            axisInfo.append(a_list)
        vcp.SetProjectionAxes(
            axisInfo[0], axisInfo[1], axisInfo[2], axisInfo[3])

        # sliceInfo
        dic = {0: "x", 1: "y", 2: "t"}
        type_list = []
        type_list.append(dic[self.chv1.currentIndex()])
        type_list.append(dic[self.chv2.currentIndex()])
        type_list.append(dic[self.chv3.currentIndex()])
        type_list.append(dic[self.chv4.currentIndex()])  # [inamura 150527]

        fold_list = []
        for i in range(4):
            fold_list.append(float(self.FoldTxtList[i].text()))

        sliceInfo = []
        for id in range(4):
            a_list = [type_list[id]]
            for i in range(3):
                a_list.append(float(self.slice[3 * id + i].text()))
            a_list.append(fold_list[id])
            sliceInfo.append(a_list)

        for i in range(4):
            vcp.SetSliceAxis("%1d" % (
                i), type_list[i], sliceInfo[i][1], sliceInfo[i][2], sliceInfo[i][3], fold_list[i])

        diagFoldInfo = [self.cbdiagfold.currentIndex(), -1, -1]
        for i, obj in enumerate(self.DiagFoldAxesList):
            print("[inamura 251001] OnSave : DiagFoldAxesList[{}].currentIndex() = {}".format(i, obj.currentIndex()))
            if obj.currentIndex() == 1:
                diagFoldInfo[1] = i + 1
            elif obj.currentIndex() == 2:
                diagFoldInfo[2] = i + 1
        if diagFoldInfo[1] == -1 or diagFoldInfo[2] == -1:
            # raise UserWarning("DiagFoldInfo is invalid.")
            print("DiagFoldInfo is invalid.")
            diagFoldInfo[1] = 0
            diagFoldInfo[2] = 0
        """
        for id in range(len(self.DiagFoldAxesList)):
            if self.DiagFoldAxesList[id].checkState() == QtCore.Qt.Checked:
                diagFoldInfo.append(id + 1)
        if len(diagFoldInfo) == 1:
            diagFoldInfo.append(0)
            diagFoldInfo.append(0)
        if len(diagFoldInfo) == 2:
            raise UserWarning("DiagFoldInfo is invalid.")
        if len(diagFoldInfo) > 3:
            diagFoldInfo = diagFoldInfo[:3]
        """
        ret = vcp.SetDiagFolding(
            "%d" % (diagFoldInfo[0]), diagFoldInfo[1], diagFoldInfo[2])
        if not ret:
            print("ERROR SetDiagFoling")
        #vcp.SetDiagFolding([diagFoldInfo[0], diagFoldInfo[1], diagFoldInfo[2]])

        # open dialog
        filename, filt = QtWidgets.QFileDialog.getSaveFileName(
            self.note, "Save Parameter File ...", os.getcwd(), filter='XML (*.xml)')

        # if cancel?
        if filename == "":
            return

        # get file path
        savefile = str(filename)

        # Check extension
        if savefile[-4:] != ".xml":
            savefile = savefile + ".xml"

        # save to XML file
        vcp.SaveFile(savefile)

        del vcp

    # <--[inamrua 110206]
# -----------------------------------[ work book mark 2017.01.23]
#######################################
#  Plot2DMap
#######################################


class Plot2DMap(object):
    """
    2次元マップ表示クラス
    """
    #########################################################

    def __init__(self, num, code, frame):
        """
        コンストラクタ
        @param  num  タブ No.
        @param  code  マップ画面タイトルに付する記号
        @param  frame  親フレーム
        @retval 無し
        """
        self.frame = frame
        self.code = code
        self.d2 = None
        if num == 0:
            self.ifi = UtilPlot.IFEvtProp(0)
            self.pno = 0
        else:
            self.pno = (num + 1) * 10
            self.ifi = UtilPlot.IFEvtProp(self.pno)

    #########################################
    def PlotMap(self, tab, map_obj, _keys, _titles=None):
        """
        2D マップ表示
        @param tab タブのインスタンス
        @param map 2D データ
        @param _keys key for uGao plotting
        @param _titles labels for uGao plotting
        @retval 無し
        """
        # D2 プロッタが表示されているか
        if self.d2 is None:
            self.ifi.AddListner('u2dclosed', self.OnNotify2DClose)
            self.d2 = D2Vis.M2PlotPlus(self.frame, None, self.pno)

        self.ifi.NotifyEvent(self, "changedata", map_obj)
        self.ifi.NotifyEvent(self, "turnmodeplotonly", True)
        self.ifi.NotifyEvent(self, 'setwindowtitle', ["VisualContM_Slice"])

        while(True):
            time.sleep(0.1)
            if self.ifi.GetProperty("isready"):
                break
        xkey, ykey = _keys
        xtitle = xkey
        ytitle = ykey
        if _titles is not None:
            xtitle, ytitle = _titles
        if xkey == "":
            xkey = "-"
            xtitle = "-"
        if ykey == "":
            xkey = "-"
            ytitle = "-"
        self.ifi.NotifyEvent(self, "showdata", (xkey, ykey, "-", 0.0, 0.0))
        self.ifi.NotifyEvent(self, "setlabels", (xtitle, ytitle))
        labels = ["", "", ""]
        labels[tab.chv1.currentIndex()] = tab.uv[0][4].text()
        labels[tab.chv2.currentIndex()] = tab.uv[1][4].text()
        labels[tab.chv3.currentIndex()] = tab.uv[2][4].text()
        # [inamura 150527]
        labels[tab.chv4.currentIndex()] = tab.uv[3][4].text()

        # メインタイトル作成
        # di = tab.smpDat
        ecm_h = tab.ECM.PutHeader()
        if ecm_h.CheckKey("SampleName") == 1:
            # sample = ecm_h.PutString("SampleName")
            sample = "Sample: %s " % ecm_h.PutString("SampleName")
        else:
            sample = ""
            if ecm_h.CheckKey("INSTRUMENT") == 1:
                sample += "%s" % ecm_h.PutString("INSTRUMENT")
            if ecm_h.CheckKey("RUNNUMBER") == 1:
                # sample += "%06d" % ( int( ecm_h.PutString("RUNNUMBER") ) ) ##[inamura 161121]
                sample += "%s" % (ecm_h.PutString("RUNNUMBER"))
            else:
                sample = "---"
        Ei = 0.0
        Ef = 0.0
        if ecm_h.CheckKey(mu.UTSUSEMI_KEY_HEAD_EI) == 1:
            Ei = ecm_h.PutDouble(mu.UTSUSEMI_KEY_HEAD_EI)
        elif tab.ECM(0, 0).PutHeader().CheckKey(mu.UTSUSEMI_KEY_HEAD_EF) == 1:
            Ef = tab.ECM(0, 0).PutHeader().PutDouble(mu.UTSUSEMI_KEY_HEAD_EF)

        # main = "Sample: %s  ( Ei = %.1f (meV) )" % ( sample , Ei )
        if Ei > 0.0:
            main = "%s ( Ei= %.1f (meV) )" % (sample, Ei)
        elif Ef > 0.0:
            main = "%s ( Ef= %.1f (meV) )" % (sample, Ef)
        else:
            main = "%s " % (sample)
        # サブタイトル作成
        # str0 = "Ei (meV): %.1f\n" % di.ei
        str1 = "U=[%s, %s, %s]\n" % (
            tab.sinfo[6].text(), tab.sinfo[7].text(), tab.sinfo[8].text())
        str2 = "V=[%s, %s, %s]\n" % (
            tab.sinfo[9].text(), tab.sinfo[10].text(), tab.sinfo[11].text())
        # str3 = "Psi=%s\n" % tab.sinfo[12].text()
        str3 = "Rot=["
        ro_axes_list = ["", "Y", "Z", "X"]
        for i in range(3):
            if tab.chRotationSteps[i].isEnabled():
                st_axis = ro_axes_list[tab.chRotationSteps[i].currentIndex()]
                if st_axis != "":
                    angle = float(tab.sinfo[12 + i].text())
                    str3 += "{}:{},".format(st_axis, angle)
        str3 = str3[:-1] + "]\n"

        str4 = "ax1=[%s, %s, %s,%s]\n" % (tab.uv[0][0].text(
        ), tab.uv[0][1].text(), tab.uv[0][2].text(), tab.uv[0][3].text())
        str5 = "ax2=[%s, %s, %s,%s]\n" % (tab.uv[1][0].text(
        ), tab.uv[1][1].text(), tab.uv[1][2].text(), tab.uv[1][3].text())
        str6 = "ax3=[%s, %s, %s,%s]\n" % (tab.uv[2][0].text(
        ), tab.uv[2][1].text(), tab.uv[2][2].text(), tab.uv[2][3].text())
        str7 = "ax4=[%s, %s, %s,%s]\n" % (tab.uv[3][0].text(
        ), tab.uv[3][1].text(), tab.uv[3][2].text(), tab.uv[3][3].text())

        ii = []
        nn = []
        if tab.chv1.currentIndex() == 2:
            ii.append(0)
            nn.append("ax1")
        if tab.chv2.currentIndex() == 2:
            ii.append(1)
            nn.append("ax2")
        if tab.chv3.currentIndex() == 2:
            ii.append(2)
            nn.append("ax3")
        if tab.chv4.currentIndex() == 2:
            ii.append(3)
            nn.append("ax4")

        # Thickness 取得
        th11 = tab.slice[ii[0] * 3].text()
        th12 = tab.slice[ii[0] * 3 + 1].text()
        th21 = tab.slice[ii[1] * 3].text()
        th22 = tab.slice[ii[1] * 3 + 1].text()
        str8 = "Thick=[%s:%s - %s]\nThick=[%s:%s - %s]" % (
            nn[0], th11, th12, nn[1], th21, th22)

        # sub = str1+str2+str3+str4+str5+str6+str7+str8 ##[inamura 120211]
        sub = str1 + str2 + str3 + ";" + str4 + str5 + str6 + str7 + ";" + str8

        # タイトル設定コマンド送信
        self.ifi.NotifyEvent(self, "settitles", (main, sub))
        # self.ifi.NotifyEvent(self, "title", (main, sub))
        # self.d2.SetMainTitle( main )
        # self.d2.SetSubTitle( sub )

        # スケールラベル設定コマンド送信
        # self.ifi.NotifyEvent(self, "scalelabel", (labels[0], labels[1],"Neutrons"))
        # self.d2.SetXLabel( labels[0] )
        # self.d2.SetYLabel( labels[1] )
        # self.d2.SetZLabel( "Neutrons" )

        # 表示中のデータを保存
        self.plotNow = (map_obj, labels[0], labels[1])

    #########################################

    def OnNotify2DClose(self, *args):
        """
        2Dプロッタクローズイベント受信処理
        @param evt　　イベント
        @retval 無し
        """
        # print "OnNotify2DClose"
        self.plotNow = None
        if self.d2 is not None:
            del self.d2
            self.d2 = None
        self.ifi.InitIF()

    #########################################
    def Request2DClose(self):
        """
        2Dプロッタクローズ要求処理
        @param  無し
        @retval 無し
        """
        # 2Dプロッタが開いているなら
        if self.d2 is not None:
            # 2Dプロッタのクローズ要求を出す　
            self.ifi.NotifyEvent(self, "plotclose")
            """
            if self.d2.plot.plot.poll() is None: ## if M2Plot is not closed.
                self.d2.Close(0)
            del self.d2
            self.d2=None
            """

#######################################
#  VisCont
#######################################


class VisCont(object):
    """
    Application Class
    """
    #########################################

    def __init__(self, m0=None, m1=None, m2=None, m3=None, m4=None, m5=None, m6=None, m7=None, m8=None, m9=None):
        """
        アプリケーションスタート
        @param  m0,m1,m2,m3,m4  エレメントコンテナマトリックス
        @retval 無し
        """
        # Hi-resolution Display for windows
        if PYSIDEVER != 6:
            if hasattr(QtCore.Qt, 'AA_EnableHighDpiScaling'):
                QtWidgets.QApplication.setAttribute(
                    QtCore.Qt.AA_EnableHighDpiScaling, True)
        # app = QtWidgets.QApplication(sys.argv)
        app = QtWidgets.QApplication.instance()
        if not app:
            app = QtWidgets.QApplication(sys.argv)
        # Set Default Font Size to (default 14)
        deffont = app.font()
        if "UTSUSEMI_DEFAULT_FONTSIZE" in os.environ:
            deffontsize = int(os.environ["UTSUSEMI_DEFAULT_FONTSIZE"])
            deffont.setPointSize(deffontsize)
        else:
            deffont.setPointSize(10)
        app.setFont(deffont)
        VisContMFrame(m0, m1, m2, m3, m4, m5, m6, m7, m8, m9)
        if PYSIDEVER == 6:
            app.exec()
        else:
            app.exec_()
        # sys.exit(0)


#######################################
#  SlicedData
#######################################
class SlicedData(object):
    """
     スライスデータクラス
     [inamura 100930]
    """
    #########################################

    def __init__(self, ver=1):
        """
        コンストラクタ
        @param  ver (int) indicates VisualCont or VisualCont2
        @retval 無し
        """
        if ver == 1:
            # 選択されている軸
            self.axes = (0, 1, 2)
            # テキストボックスの設定値
            self.txts = ["1", "2", "3", "4", "5", "6", "7", "8", "9"]

        elif ver == 2:
            self.axes = (0, 1, 2, 2)
            self.txts = ["1", "2", "3", "4", "5",
                         "6", "7", "8", "9", "10", "11", "12"]

        # マップデータ
        self.map = None
        self._keys = ("", "")
        self._titles = ("", "")


if __name__ == '__main__':

    vc = VisCont()
