#!/usr/bin/env python
# -*- coding: utf-8 -*-

"""
uGao pacakge
DetectorViewer
"""

__author__ = "ITO, Takayoshi (CROSS)"
__version__ = "23.08.00"
__date__ = "9th Aug. 2023"
import os
import os.path
import sys
import time
import glob
import shutil
import math
import numpy as np
import multiprocessing
import six

PYSIDEVER = 1
if '--pyside1' in sys.argv:
    from PySide import QtCore
    import PySide.QtGui as QtWidgets
else:
    try:
        from PySide6 import QtCore, QtGui, QtWidgets
        PYSIDEVER = 6
    except:
        try:
            from PySide2 import QtCore, QtGui, QtWidgets
            PYSIDEVER = 2
        except:
            from PySide import QtCore
            import PySide.QtGui as QtWidgets
# Python3のみなら次の部分でのimportで大丈夫なようだが、
# Python2では問題が生じるので呼び出し直前でimportしている
#import uGao.DetectorViewerIF as DetView
from uGao.Calculator import PutTwoTheta, RotateWXYZ, PutResultOfUserDefinedFormula, PutGauss
if QtCore.__version__<'5.0.0':
    from uGao.ui_DetectorViewer import Ui_MainWindow, Ui_Dialog
else:
    from uGao.ui2_DetectorViewer import Ui_MainWindow, Ui_Dialog
import uGao.MPlot as mp
import uGao.M2PlotPlusCui as m2cui

import Manyo
try:
    import Manyo.Utsusemi as mu
    HAS_UTSUSEMI = True
except ImportError:
    HAS_UTSUSEMI = False

########################################
# PixelInfoDialog
########################################
class PixelInfoDialog(QtWidgets.QDialog, Ui_Dialog):
    """
    ピクセル情報表示用ダイアログ
    """

    #########################################################
    def __init__(self, parent):
        """
        コンストラクタ
        """
        super(PixelInfoDialog, self).__init__(parent)
        self.setupUi(self)

########################################
# MyMainApp
########################################
class DetectorViewer(QtWidgets.QMainWindow, Ui_MainWindow):
    #########################################################
    def __init__(self, parent, screen):
        """コンストラクタ

        Parameters:
            screen (QScreen) スクリーン情報取得用オブジェクト
        """
        super(DetectorViewer, self).__init__(parent)
        self.setupUi(self)
        self._loaded_ecm = None
        self._loaded_filepath = None
        self.det_view = None
        self.mplot = None
        self.picked_pixel = [None, None, None] # [bankId, psdId(detId), pixel_position]

        self.pixel_info = PixelInfoDialog(None)

        # ラン番号からのDetecotrInfo, WiringInfo指定用の設定
        self._xml_path = None
        self._environ_path = None
        if "UTSUSEMI_BASE_DIR" in os.environ:
            self._xml_path = os.path.join(os.environ["UTSUSEMI_BASE_DIR"], os.environ["UTSUSEMI_INST_CODE"], "ana", "xml")
            _tmp_environ_path = os.path.join(self._xml_path, "environ_ana.xml")
            if os.path.exists(_tmp_environ_path):
                self._environ_path = _tmp_environ_path

        self._screen = screen
        rect_d = self._screen.availableGeometry() # デスクトップの有効範囲矩形
        center_d = rect_d.center()

        rect = self.rect()
        rect.moveTopLeft(rect_d.topLeft())
        self.setGeometry(rect)

        rect_pixel_info = self.pixel_info.rect()
        rect_pixel_info.moveLeft(rect_d.x())
        rect_pixel_info.moveTop(rect.y() + rect.height() + 60)
        self.pixel_info.setGeometry(rect_pixel_info)
        self.pixel_info.show()

        self.SetEventHandler()

    ########################################
    def SetEventHandler(self):
        """イベントハンドラ登録
        """
        if (self._environ_path is not None) and HAS_UTSUSEMI:
            self.btn_open.pressed.connect(self.OnViewFrameByRunNumber)
        else:
            self.btn_open.pressed.connect(self.OnViewFrame)
        self.btn_x_apply.pressed.connect(self.OnApplyXRange)
        if self._loaded_ecm is None:
            self.btn_x_apply.setEnabled(False)
        self.btn_cb_apply.pressed.connect(self.OnColorbarRange)
        if self.det_view is None:
            self.btn_cb_apply.setEnabled(False)
        self.actionOpen.triggered.connect(self.OnViewFrame)
        self.actionExit.triggered.connect(self.close)
        self.actionLoad_data.triggered.connect(self.OnLoadData)
        self.actionTwo_theta.triggered.connect(self.OnSetTwoTheta)
        self.actionFormula.triggered.connect(self.OnSetUserDefinedFormula)
        self.actionPicker_tolerance.triggered.connect(self.OnSetPickerTolerance)
        self.actionPixel_information.triggered.connect(self.OnPixelInfo)
        self.actionCreate_dummy_data.triggered.connect(self.OnCreateDummyData)
        self.actionAbout.triggered.connect(self.OnAbout)

        self.pixel_info.btn_new_plot.pressed.connect(self.OnPixelPlotNew)
        self.pixel_info.btn_append_plot.pressed.connect(self.OnPixelPlotAppend)
        self.pixel_info.btn_2d_plot.pressed.connect(self.On2dPlot)

    #########################################
    def OnAbout(self):
        """Aboutダイアログの表示
        """
        msgBox = QtWidgets.QMessageBox()
        url = "https://knowledge.mlf.plus/open.knowledge/view/71"
        message ="{0}\nVersion: {1}\nAuthor: {2}\nDate: {3}\nManual: {4}".format(__doc__, __version__, __author__, __date__, url)
        msgBox.about(self, "About uGao DetectorViewer", message)
    """
    ########################################
    def init_frame(self):
        #self.frm = self.res.LoadFrame(None, 'main_frame')
        #icon = wx.Icon(os.path.join(os.path.dirname(os.path.abspath(__file__)), "emaki_icon.png"), wx.BITMAP_TYPE_PNG)
        #self.frm.SetIcon(icon)
        self.frm.CreateStatusBar()
        self.frm.SetStatusText("")

    ########################################
    def init_pixel_frm(self):
        icon = wx.Icon(os.path.join(os.path.dirname(os.path.abspath(__file__)), "emaki_icon.png"), wx.BITMAP_TYPE_PNG)
        self.pxl_info_frm.SetIcon(icon)
    """

    ########################################
    def OnViewFrameByRunNumber(self, event=None):
        _run_number, _isOk = QtWidgets.QInputDialog.getInt(self, "Enter the run number",
                                                          "Run number:", 0)
        if _isOk:
            UAR = mu.UtsusemiAnaEnvironReader(self._environ_path)
            pfiles = UAR.PutParamFiles(_run_number)
            wiringInfoPath = pfiles[0]
            detInfoPath = pfiles[1]
            print(detInfoPath, wiringInfoPath)
            wiringInfoPath = os.path.join(self._xml_path, wiringInfoPath)
            detInfoPath = os.path.join(self._xml_path, detInfoPath)
            import uGao.DetectorViewerIF as DetView
            self.det_view = DetView.DetectorViewInterface(str(detInfoPath), str(wiringInfoPath))
            self.det_view_win = QtWidgets.QMainWindow(parent=self)
            self.control = self.det_view.edit_traits(parent=self, kind='subpanel').control
            self.det_view_win.setCentralWidget(self.control)
            self.det_view_win.setStatusBar(QtWidgets.QStatusBar())
            self.det_view_statusbar = self.det_view_win.statusBar()
            self.det_view_toolbar = self.det_view_win.findChildren(QtWidgets.QToolBar)[0]
            for a in self.det_view_toolbar.actions():
                if "Toggle axes indicator" in a.toolTip():
                    a.toggle()
                    break
            #self.view_frm.SetIcon(icon)
            #self.view_frm.CreateStatusBar()
            rect = self.rect()
            rect_pixel_info = self.pixel_info.rect()
            rect_d = self._screen.availableGeometry() # デスクトップの有効範囲矩形
            rect_view = self.det_view_win.rect()
            rect_view.setWidth(rect_d.width()/2)
            rect_view.setHeight(rect_d.height()/2)
            rect_view.moveLeft(rect_pixel_info.x() + rect_pixel_info.width() + 2)
            rect_view.moveTop(rect.y() + rect.height() + 60)
            self.det_view_win.setGeometry(rect_view)
            self.det_view_win.show()
            self.det_view.SetPickerCallback(self.PickerCallback)
            self.btn_open.setEnabled(False)
            self.actionOpen.setEnabled(False)

    ########################################
    def OnViewFrame(self):
        wildcard = "DetectorInfo files (*.xml)"
        # DetectorInfo選択ダイアログ表示
        dlg = QtWidgets.QFileDialog(self, "Open a DetectorInfo file", os.path.expanduser("."), wildcard)
        dlg.setFileMode(QtWidgets.QFileDialog.ExistingFile)
        # パスを取得。
        if dlg.exec_():
            filenames = dlg.selectedFiles()
            detInfoPath= str(filenames[-1])
            data_type, data_format, wildcard = dlg.selectedNameFilter().split()
            msg = "Data loading : {}".format( os.path.basename(detInfoPath) )
        else:
            return False
        del dlg
        wildcard = "WiringInfo files (*.xml)"
        # WiringInfo選択ダイアログを表示
        dlg = QtWidgets.QFileDialog(self, "Open a WiringInfo file", os.path.expanduser("."), wildcard)
        dlg.setFileMode(QtWidgets.QFileDialog.ExistingFile)
        # パスを取得。
        if dlg.exec_():
            filenames = dlg.selectedFiles()
            wiringInfoPath= str(filenames[-1])
            data_type, data_format, wildcard = dlg.selectedNameFilter().split()
        else:
            return False
        del dlg
        import uGao.DetectorViewerIF as DetView
        self.det_view = DetView.DetectorViewInterface(str(detInfoPath), str(wiringInfoPath))
        self.det_view_win = QtWidgets.QMainWindow(parent=self)
        self.control = self.det_view.edit_traits(parent=self, kind='subpanel').control
        self.det_view_win.setCentralWidget(self.control)
        self.det_view_win.setStatusBar(QtWidgets.QStatusBar())
        self.det_view_statusbar = self.det_view_win.statusBar()
        self.det_view_toolbar = self.det_view_win.findChildren(QtWidgets.QToolBar)[0]
        for a in self.det_view_toolbar.actions():
            if "Toggle axes indicator" in a.toolTip():
                a.toggle()
                break
        #self.view_frm.SetIcon(icon)
        #self.view_frm.CreateStatusBar()
        rect = self.rect()
        rect_pixel_info = self.pixel_info.rect()
        rect_d = self._screen.availableGeometry() # デスクトップの有効範囲矩形
        rect_view = self.det_view_win.rect()
        desktop_width = rect_d.width()
        desktop_height = rect_d.height()
        if desktop_width < 1280:
            desktop_width = 1280
        if desktop_height < 1280:
            desktop_height = 1280
        rect_view.setWidth(desktop_width//2)
        rect_view.setHeight(desktop_height//2)
        rect_view.moveLeft(rect_pixel_info.x() + rect_pixel_info.width() + 2)
        rect_view.moveTop(rect.y() + rect.height() + 60)
        self.det_view_win.setGeometry(rect_view)
        self.det_view_win.show()
        self.det_view.SetPickerCallback(self.PickerCallback)
        self.btn_open.setEnabled(False)
        self.actionOpen.setEnabled(False)

    ########################################
    def OnPixelInfo(self, event=None):
        self.pixel_info.show()

    ########################################
    def OnLoadData(self, event=None):
        """ヒストグラムデータ選択、読込
        """
        #wildcard = "Serialized ECM files (*.srlz)"
        #dlg = QtWidgets.QFileDialog(self, "Open a serialized ECM file", os.path.expanduser("."), wildcard)
        #dlg.setFileMode(QtWidgets.QFileDialog.ExistingFile)
        ## パスを取得。
        #if dlg.exec_():
        #    filenames = dlg.selectedFiles()
        #    self._loaded_filepath = str(filenames[-1])
        #else:
        #    return False
        filepath, filt = QtWidgets.QFileDialog.getOpenFileName(
            self, "Open Data file ...", os.getcwd(), filter='Serialized ECM, ManyoDataBinary (*.srlz *.mdb)')
        if filepath == "":
            return False
        if filepath[-5:] == ".srlz":
            print("Loading data: {0}".format(filepath))
            read = Manyo.ReadSerializationFileBinary(filepath)
            del self._loaded_ecm
            self._loaded_ecm = Manyo.ElementContainerMatrix()
            read.Load(self._loaded_ecm)
            del read
        elif filepath[-4:] == ".mdb":
            print("Loading data: {0}".format(filepath))
            read = Manyo.ManyoDataIO()
            del self._loaded_ecm
            self._loaded_ecm = Manyo.ElementContainerMatrix()
            read.Read(self._loaded_ecm, filepath)
            del read
        else:
            print("Given file format is invalid.")
            return
        self._loaded_filepath = filepath
        self.btn_x_apply.setEnabled(True)
        self.statusbar.showMessage("Data: {0}".format(self._loaded_filepath))

    ########################################
    def OnApplyXRange(self, event=None):
        """X範囲を適用し強度を描画
        """
        hh = self._loaded_ecm.PutHeader()
        bank_id_list = list(hh.PutInt4Vector("BANKIDLIST"))
        bank_size_list = list(hh.PutInt4Vector("BANKSIZELIST"))
        start = float(self.txt_x_start.text())
        end = float(self.txt_x_end.text())
        view_mask = self.actionMask_view.isChecked()
        for info, config in zip(self.det_view.bank_info, self.det_view.bank_configurations):
            data = []
            SS = Manyo.SearchInHeader()
            SS.SetTarget(self._loaded_ecm)
            for det_id in config["det_id_list"]:
                SS.SearchArray("DETID", det_id)
                rslt_vector = SS.PutResultIndex(0)
                if rslt_vector.size() != 0:
                    eca_index = rslt_vector[0]
                    for pixel_num in range(self._loaded_ecm(eca_index).PutSize()):
                        if not view_mask:
                            sum_ye = self._loaded_ecm(eca_index, pixel_num).Sum(start, end)
                            data.append(sum_ye[0])
                        else:
                            if self._loaded_ecm(eca_index).PutHeader().PutInt4("MASKED"):
                                data.append(0.0)
                            elif self._loaded_ecm(eca_index, pixel_num).PutHeader().PutInt4("MASKED"):
                                data.append(0.0)
                            elif self.HasMask(self._loaded_ecm(eca_index, pixel_num), start, end):
                                data.append(0.0)
                            else:
                                sum_ye = self._loaded_ecm(eca_index, pixel_num).Sum(start, end)
                                data.append(sum_ye[0])
                else:
                    print("Not found in a data container: Det. ID:", det_id, ". Intensity is filled by 0.")
                    for i in range(config["n_pxl_per_det"]):
                        data.append( 0.0 ) ##[inamura 161111]
            del SS
            self.det_view.SetScalarsToBankByBankId( info[1], data)
        self.btn_cb_apply.setEnabled(True)

    ########################################
    def HasMask(self, ec, start, end):
        """
        Is this EC has any error flag in this range?
        """
        x_list = ec.PutXList()
        e_list = ec.PutEList()
        if x_list[0] >= end or x_list[-1] <= start:
            return False
        for xx, e in zip( zip(x_list[:-1], x_list[1:]), e_list):
            if (start <= xx[0] and xx[1] <= end) and e < 0.:
                return True
            if xx[0] >= end:
                return False
        else:
            return False

    ########################################
    def OnSetTwoTheta(self, event=None):
        """Two thetaを強度として描画
        """
        #print(sys._getframe().f_code.co_name)
        pool = multiprocessing.Pool()
        for bankIndex, bank_config in enumerate(self.det_view.bank_configurations):
            try:
                coordinates = bank_config["coordinates"].T # これでcoordinatesは(n, 3)
                args = list(coordinates)
                data = np.array( pool.map(PutTwoTheta, args) )
                self.det_view.SetScalarsToBank( bankIndex, data)
            except:
                print("Unexpected error:", sys.exc_info()[0])
        self.btn_cb_apply.setEnabled(True)
        self.statusbar.showMessage("Plot two-theta as intensity")

    ########################################
    def PickerCallback(self, picker_obj):
        """ピクセル選択時用コールバック関数
        """
        #print picker_obj.selection_point # 画面上の位置
        #print picker_obj.pick_position # 空間上の位置
        #print picker_obj.mapper_position # mapper内での位置
        picked = picker_obj.actors
        if len(picked) == 0:
            self.det_view_statusbar.showMessage( "No object is picked.")
            return
        elif len(picked) > 1:
            self.det_view_statusbar.showMessage( "Pass due to multi picking.")
            return
        else:
            self.det_view_statusbar.clearMessage()
        for i, bank_module in enumerate(self.det_view.bank_modules):
            if bank_module.actor.actor._vtk_obj in [ o._vtk_obj for o in picked]:
                glyph_points = bank_module.glyph.glyph_source.glyph_source.output.points.to_array()
                point_id = picker_obj.point_id//glyph_points.shape[0]
                if point_id != -1:
                    intensity = bank_module.mlab_source.scalars[point_id]
                    x_rel = bank_module.mlab_source.x[point_id]
                    y_rel = bank_module.mlab_source.y[point_id]
                    z_rel = bank_module.mlab_source.z[point_id]
                    x_abs, y_abs, z_abs = picker_obj.picked_positions[0]
                    tth = PutTwoTheta( np.array([x_abs, y_abs, z_abs]) )
                    azm = np.degrees(np.arctan2(y_abs, x_abs))
                    self.det_view_statusbar.showMessage('Picked.')
                    self.pixel_info.txt_intensity_val.setText('{0:.4e}'.format(intensity))
                    self.pixel_info.txt_x_val.setText('{0:.1f}'.format(x_abs))
                    self.pixel_info.txt_y_val.setText('{0:.1f}'.format(y_abs))
                    self.pixel_info.txt_z_val.setText('{0:.1f}'.format(z_abs))
                    self.pixel_info.txt_tth_val.setText('{0:.2f}'.format(tth))
                    self.pixel_info.txt_azimuth_val.setText('{0:.2f}'.format(azm))
                    self.pixel_info.txt_rel_x_val.setText('{0:.1f}'.format(x_rel))
                    self.pixel_info.txt_rel_y_val.setText('{0:.1f}'.format(y_rel))
                    self.pixel_info.txt_rel_z_val.setText('{0:.1f}'.format(z_rel))
                    self.pixel_info.txt_bank_val.setText('{0}, {1}'.format(self.det_view.bank_info[i][0], self.det_view.bank_info[i][1]))
                    self.picked_pixel[0] = self.det_view.bank_info[i][1]
                    bank_config = self.det_view.bank_configurations[i]
                    n_pxl_per_det = bank_config["n_pxl_per_det"]
                    det_id = bank_config["det_id_list"][point_id//n_pxl_per_det]
                    self.picked_pixel[1] = det_id
                    pixel_position = point_id%n_pxl_per_det
                    self.picked_pixel[2] = pixel_position
                    self.pixel_info.txt_det_id_val.setText('{0}'.format(det_id))
                    self.pixel_info.txt_position_val.setText('{0}'.format(pixel_position))
                    self.pixel_info.txt_point_val.setText('{0}'.format(point_id))
                    break

    ########################################
    def PutElementContainerToPixelPlot(self):
        """選択ピクセルのECを返す
        """
        SS = Manyo.SearchInHeader()
        SS.SetTarget(self._loaded_ecm)
        SS.SearchArray("DETID", self.picked_pixel[1])
        rslt_vector = SS.PutResultIndex(0)
        if rslt_vector.size() != 0:
            eca_index = rslt_vector[0]
        else:
            print('[!] No mathcing DETID %d'%self.picked_pixel[1])
            return None
        del SS
        return self._loaded_ecm(eca_index).Put(self.picked_pixel[2])

    ########################################
    def PutElementContainerArrayTo2dPlot(self):
        """選択ピクセルを含むECAを返す
        """
        SS = Manyo.SearchInHeader()
        SS.SetTarget(self._loaded_ecm)
        SS.SearchArray("DETID", self.picked_pixel[1])
        rslt_vector = SS.PutResultIndex(0)
        if rslt_vector.size() != 0:
            eca_index = rslt_vector[0]
        else:
            print('[!] No mathcing DETID %d'%self.picked_pixel[1])
            return None
        del SS
        return self._loaded_ecm.Put(eca_index)

    ########################################
    def OnPixelPlotNew(self):
        """選択ピクセルを新規MPlotで表示
        """
        ec = self.PutElementContainerToPixelPlot()
        if ec is None:
            raise UserWarning
            return
        if self.mplot is None:
            self.mplot = mp.MPlot(ec)
        else:
            self.mplot.NewPlot(ec)

    ########################################
    def OnPixelPlotAppend(self):
        """選択ピクセルを既存MPlotに追加表示
        """
        if self.mplot is None:
            raise UserWarning('[!] No plotter exists.')
            return
        _plot_number, _isOk = QtWidgets.QInputDialog.getInt(self, "Enter a plotter number",
                                                       "Plotter number", 1)
        if _isOk:
            try:
                self.mplot.ChangePlot(_plot_number)
                ec = self.PutElementContainerToPixelPlot()
                if ec is None:
                    raise UserWarning
                    return
                self.mplot.AddData(ec)
            except:
                print("Unexpected error:", sys.exc_info()[0])

    ########################################
    def On2dPlot(self):
        """選択ピクセルを含むECAをM2PlotPlusで表示
        """
        eca = self.PutElementContainerArrayTo2dPlot()
        if eca is None:
            raise UserWarning
            return
        p = m2cui.M2PlotPlusCui()
        p.ChangeData(eca)

    ########################################
    def OnColorbarRange(self):
        """Colorbar範囲を変更
        """
        min_str = float(self.txt_cb_min.text())
        max_str = float(self.txt_cb_max.text())
        for mod in self.det_view.bank_modules:
            mod.actor.mapper.scalar_range = [float(min_str), float(max_str) ]
        return

    ########################################
    def OnCreateDummyData(self, event=None):
        """ピクセル座標からダミーデータを作成し保存
        """
        wildcard = "Serialized file (*.srlz)"
        dlg = QtWidgets.QFileDialog(self, "Save a dummy data",
                                os.path.expanduser("."), wildcard)
        dlg.setFileMode(QtWidgets.QFileDialog.AnyFile)
        # パスを取得。
        if dlg.exec_():
            filenames = dlg.selectedFiles()
            filename = str(filenames[-1])
        else:
            return False
        del dlg

        def gauss(A, c, w, x_data):
            template = "np.exp(-(x_data - c*%d)**2/(2.0*w**2))+"
            s = 'A*('
            for i in range(1,37):
                s += template%(i)
            else:
                s = s.rstrip('+')
            s += ')'
            return eval(s)

        def calc_tof(d, L, tth):
            return d*(252.777*L*2*math.sin(math.radians(tth)/2))

        inst_code = self.det_view.PutInstCode()
        ecm = Manyo.ElementContainerMatrix()
        for bankIndex, bank_config in enumerate(self.det_view.bank_configurations):
            print("Dummy data creation: {0} / {1}".format( bankIndex, len(self.det_view.bank_configurations)))
            coordinates = bank_config["coordinates"].T
            X = np.array([i*40.0 for i in range(1,1001)])
            X_mid = np.array([i*40.0+20.0 for i in range(1,1000)])
            ecm.AddToHeader("INSTRUMENT", inst_code)
            det_id_list = bank_config["det_id_list"]
            n_det = bank_config["n_det"]
            n_pxl_per_det = bank_config["n_pxl_per_det"]
            for i, det_id in enumerate(det_id_list):
                print(i, bankIndex)
                eca = Manyo.ElementContainerArray()
                eca.AddToHeader("DETID", det_id)
                for j in range(n_pxl_per_det):
                    x, y, z = coordinates[i*n_pxl_per_det+j].tolist()
                    tth = PutTwoTheta(coordinates[i*n_pxl_per_det+j])
                    L2 = math.sqrt(x**2+y**2+z**2)*0.001
                    L = L2 + 14.5
                    c = calc_tof(1.0, L, tth)
                    Y = gauss(1000.0, c, 40.0, X_mid)
                    E = np.sqrt(Y)
                    lmbd_bins = [tof/252.777/L for tof in X.tolist()]
                    qx_bins = [2*math.pi*x*0.001/L2/lmbd for lmbd in lmbd_bins]
                    qy_bins = [2*math.pi*y*0.001/L2/lmbd for lmbd in lmbd_bins]
                    qz_bins = [2*math.pi*(1.0-z*0.001/L2)/lmbd for lmbd in lmbd_bins]
                    qx_center = []
                    qy_center = []
                    qz_center = []
                    for k in range(len(lmbd_bins) -1):
                        qx_center.append( (qx_bins[k]+qx_bins[k+1])*0.5 )
                        qy_center.append( (qy_bins[k]+qy_bins[k+1])*0.5 )
                        qz_center.append( (qz_bins[k]+qz_bins[k+1])*0.5 )
                    ec = Manyo.ElementContainer()
                    ec.AddToHeader("DETID", det_id)
                    ec.AddToHeader("PixelPosition", Manyo.ListToDoubleVector([x, y, z]))
                    ec.Add('TOF', X.tolist())
                    ec.Add('Count', Y.tolist())
                    ec.Add('Error', E.tolist())
                    ec.Add('qx', qx_center)
                    ec.Add('qy', qy_center)
                    ec.Add('qz', qz_center)
                    ec.SetKeys('TOF', 'Count', 'Error')
                    eca.Add(ec)
                ecm.Add(eca)
        boostWrite = Manyo.WriteSerializationFileBinary(filename)
        boostWrite.Save(ecm)
        del boostWrite
        del ecm
        print("Dummy data creation: End")

    ########################################
    def OnSetUserDefinedFormula(self, event=None):
        """ピクセル座標を使い任意の関数による強度を描画
        """
        _formula, _isOk = QtWidgets.QInputDialog.getText(self, "Enter your formula",
                                              "Formula", text = "sqrt(x**2 + y**2 + z**2)")
        if _isOk:
            pool = multiprocessing.Pool()
            for bankIndex, bank_config in enumerate(self.det_view.bank_configurations):
                coordinates = bank_config["coordinates"].T
                args = list(coordinates)
                args = [[l, _formula] for l in args]
                data = np.array( pool.map(PutResultOfUserDefinedFormula, args) )
                self.det_view.SetScalarsToBank(bankIndex, data)
            self.btn_cb_apply.setEnabled(True)
            self.statusbar.showMessage("Formula: {0}".format(_formula))

    ########################################
    def OnSetPickerTolerance(self):
        """ピクセル選択のトレランスを変更
        """
        try:
            tolerance = self.det_view.PutPickerTolerance()
        except:
            return
        _tolerance_new, _isOk = QtWidgets.QInputDialog.getDouble(self, "Enter a new tolerance",
                                                   "Tolerance:", tolerance,
                                                   0.0, 1.0, 5)
        if _isOk:
            self.det_view.SetPickerTolerance(_tolerance_new)

    ##########################################################
    def closeEvent(self,event=None):
        self.pixel_info.close()
        if event is not None:
            event.accept()
        else:
            self.close()

if __name__ == '__main__':
    # ここのPy2/Py3, PySide1/PySide2の関係は要確認
    """
    if six.PY2:
        app = QtWidgets.QApplication(sys.argv)
    else:
        app = QtWidgets.QApplication.instance()
    """
    print("================================")
    print("Python")
    print(sys.version)
    print("Qt")
    print(QtCore.__version__)
    print("uGao.DetectorViewer")
    print("{0}, {1}".format(__version__, __date__))
    print("================================")
    # Hi-resolution Display for windows for PySide2
    if PYSIDEVER != 6:
        if hasattr(QtCore.Qt, 'AA_EnableHighDpiScaling'):
            QtWidgets.QApplication.setAttribute(
                QtCore.Qt.AA_EnableHighDpiScaling, True)
    app = QtWidgets.QApplication(sys.argv)
    if six.PY2:
        screen = app.desktop()
    else:
        screen = app.screens()[0]
    main_window = DetectorViewer(None, screen)
    main_window.show()
    """
    if six.PY2:
        sys.exit(app.exec_())
    else:
        app.exec_()
    """
    sys.exit(app.exec_())
