# -*- coding: utf-8 -*-
from __future__ import print_function
import sys
#from pyqtgraph.Qt import QtCore, QtGui, uic
#from PySide import QtCore
try:
    import PySide6
    from PySide6 import QtCore, QtGui, QtWidgets
except:
    import PySide2
    from PySide2 import QtCore, QtGui, QtWidgets
#from pyqtgraph.Qt import QtCore,QtGui,QtWidgets
import pyqtgraph as pg
import pyqtgraph.opengl as gl
import numpy as np
from OpenGL.GL import *
import SliceData
import FreeSliceData
import ViewSubData

import Manyo
#import Manyo.Utsusemi
import PlaneSlicer
import uGao.M2PlotPlusCui as mp
import threading
import math
import time
import os
import subprocess

class ViewMainData(QtCore.QObject):
    SLICE_XY = 0
    SLICE_YZ = 1
    SLICE_ZX = 2

    PROCESS_MAIN       = 0
    PROCESS_M2PLOT     = 1
    PROCESS_OUT_IMAGE  = 2
    PROCESS_OUT_BINARY = 3

    DATA_ORI_XYZ = 0
    DATA_ORI_XZY = 1
    DATA_ORI_YXZ = 2
    DATA_ORI_YZX = 3
    DATA_ORI_ZXY = 4
    DATA_ORI_ZYX = 5

    HEADKEY_SLICE3DKEYS = "SLICE3DKEYS"
    HEADKEY_SLICE3DBINS = "SLICE3DBINS"

    update_scrollbar_signal   = QtCore.Signal()
    update_scrollbar_signal   = QtCore.Signal()
    update_scrollbar_range_signal = QtCore.Signal()
    update_data_info_signal   = QtCore.Signal()
    update_basic_slice_signal = QtCore.Signal()
    update_axis_grid_signal   = QtCore.Signal()
    status_bar_signal         = QtCore.Signal(str)
    create_slice_signal       = QtCore.Signal(tuple)
    create_free_slice_signal  = QtCore.Signal(tuple)
    update_slice_view_signal  = QtCore.Signal()
    update_glview_signal      = QtCore.Signal()
    save_glview_signal        = QtCore.Signal(str)
    update_autoscale_signal   = QtCore.Signal()

    update_grid_size_signal   = QtCore.Signal()
    update_grid_signal        = QtCore.Signal()
    def __init__(self,ecm_in=None):
        super(ViewMainData, self).__init__()
        self.filePath = ""
        self.stop_event = threading.Event()
        self.data_xy = np.zeros((1, 1))
        self.data_xy_pos = 0.0
        self.data_xy_range = [0.0, 1.0, 0.0, 1.0]
        self.data_yz = np.zeros((1, 1))
        self.data_yz_pos = 0.0
        self.data_yz_range = [0.0, 1.0, 0.0, 1.0]
        self.data_zx = np.zeros((1, 1))
        self.data_zx_pos = 0.0
        self.data_zx_range = [0.0, 1.0, 0.0, 1.0]
        self.data_ax1bin = 1.0
        self.data_ax2bin = 1.0
        self.data_ax3bin = 1.0
        self.data_free = np.zeros((1, 1))

        self.intensityMin = 9999.0
        self.intensityMax = -9999.0
        self.imageID = 0

        self.basicSliceAx1From = 0.0
        self.basicSliceAx1To   = 0.0
        self.basicSliceAx2From = 0.0
        self.basicSliceAx2To   = 0.0
        self.basicSliceAx3From = 0.0
        self.basicSliceAx3To   = 0.0

        # 3面スライス用共通データ
        self.basicSliceAx1bin = 0.01
        self.basicSliceAx2bin = 0.01
        self.basicSliceAx3bin = 0.01

        self.basicSliceAx1Scale = 1.0
        self.basicSliceAx2Scale = 1.0
        self.basicSliceAx3Scale = 1.0

        # 3面スライス用データ(各軸)
        self.ax1Slice = SliceData.SliceData()
        self.ax1Slice.axisTitle = "ax1"
        self.ax2Slice = SliceData.SliceData()
        self.ax2Slice.axisTitle = "ax2"
        self.ax3Slice = SliceData.SliceData()
        self.ax3Slice.axisTitle = "ax3"

        self.slicePlane = ViewMainData.SLICE_XY


        self.freeSlice = FreeSliceData.FreeSliceData()

        self.ax1Key = "Xval"
        self.ax2Key = "Yval"
        self.ax3Key = "Zval"

        #---------
        self.update_slice_view_flag = False
        # signals

        # [tito 20220519] comment out
        """
        self.update_scrollbar_signal   = QtCore.SIGNAL("update_scrollbar_signal")
        self.update_scrollbar_range_signal = QtCore.SIGNAL("update_scrollbar_range_signal")
        self.update_data_info_signal   = QtCore.SIGNAL("update_data_information_signal")
        self.update_basic_slice_signal = QtCore.SIGNAL("update_basic_slice_signal")
        self.update_axis_grid_signal   = QtCore.SIGNAL("update_axis_grid_signal")
        self.status_bar_signal         = QtCore.SIGNAL("status_bar_signal")
        self.create_slice_signal       = QtCore.SIGNAL("create_slice_signal")
        self.create_free_slice_signal  = QtCore.SIGNAL("create_free_slice_signal")
        self.update_slice_view_signal  = QtCore.SIGNAL("update_slice_view_signal")
        self.update_glview_signal      = QtCore.SIGNAL("update_glview_signal")
        self.save_glview_signal        = QtCore.SIGNAL("save_glview_signal")
        self.update_autoscale_signal   = QtCore.SIGNAL("update_autoscale_signal")

        self.update_grid_size_signal   = QtCore.SIGNAL("update_grid_size_signal")
        self.update_grid_signal        = QtCore.SIGNAL("update_grid_signal")
        """

        #[inamura 170227]-->
        self.data_ecm = None
        if (ecm_in!=None):
            self.SetData( ecm_in )
        #<--[inamura 170227]

    #[inamura 170227]-->
    #[inamura 180422]
    def SetData(self, ecm_in, xkey="-", ykey="-", zkey="-", isFromFile=False, xbin="-", ybin="-", zbin="-"):
        if self.data_ecm!=None:
            del self.data_ecm

        self.data_ecm = ecm_in

        if not isFromFile:
            self.filePath="Direct"

        ecm_hh = self.data_ecm.PutHeaderPointer()
        if ( xkey=="-" and ykey=="-" and zkey=="-" ):
            if ecm_hh.CheckKey(ViewMainData.HEADKEY_SLICE3DKEYS)==1:
                key_vect = ecm_hh.PutStringVector(ViewMainData.HEADKEY_SLICE3DKEYS)
                self.ax1Key = key_vect[0]
                self.ax2Key = key_vect[1]
                self.ax3Key = key_vect[2]
            else:
                self.data_ecm = None
                return
        else:
            self.ax1Key = xkey
            self.ax2Key = ykey
            self.ax3Key = zkey


        #self.rangex = [-0.5, 3.0]
        #self.rangey = [-1.0, 1.5]
        #self.rangez = [0.1, 30.1]

        #self.getDataInformation()
        self.getDataInformation2(xbin,ybin,zbin) #[inamura 180422]
        self.getDataKeys()

        # set view scale
        lenX = float(self.rangex[1] - self.rangex[0])
        lenY = float(self.rangey[1] - self.rangey[0])
        lenZ = float(self.rangez[1] - self.rangez[0])

        scaleExp = 3
        if lenX < lenY and lenX < lenZ:
           self.basicSliceAx1Scale = 1.0
           self.basicSliceAx2Scale = lenX/lenY
           self.basicSliceAx3Scale = lenX/lenZ
        elif lenY < lenZ:
           self.basicSliceAx1Scale = lenY/lenX
           self.basicSliceAx2Scale = 1.0
           self.basicSliceAx3Scale = lenY/lenZ
        else:
           self.basicSliceAx1Scale = lenZ/lenX
           self.basicSliceAx2Scale = lenZ/lenY
           self.basicSliceAx3Scale = 1.0

        self.basicSliceAx1Scale = round(self.basicSliceAx1Scale, scaleExp)
        self.basicSliceAx2Scale = round(self.basicSliceAx2Scale, scaleExp)
        self.basicSliceAx3Scale = round(self.basicSliceAx3Scale, scaleExp)

        self.basicSliceAx1From = self.rangex[0]
        self.basicSliceAx1To   = self.rangex[1]
        self.basicSliceAx2From = self.rangey[0]
        self.basicSliceAx2To   = self.rangey[1]
        self.basicSliceAx3From = self.rangez[0]
        self.basicSliceAx3To   = self.rangez[1]

        self.ax1Slice.thickness = self.basicSliceAx1bin * 1.0
        self.ax2Slice.thickness = self.basicSliceAx2bin * 1.0
        self.ax3Slice.thickness = self.basicSliceAx3bin * 1.0


        lenX = self.rangex[1] - self.rangex[0]
        lenY = self.rangey[1] - self.rangey[0]
        lenZ = self.rangez[1] - self.rangez[0]

        self.UpdatePlotter() #[inamura 180422]

    #[inamura 180422]-->
    def UpdatePlotter(self):
        self.update_data_info_signal.emit()
        self.update_basic_slice_signal.emit()
        self.update_axis_grid_signal.emit()
        self.update_scrollbar_range_signal.emit()
        QtWidgets.QApplication.restoreOverrideCursor()
    #<--[inamura 180422]

    def ReadSerializationFileBinary(self, filePath):
        QtWidgets.QApplication.setOverrideCursor(QtGui.QCursor(QtCore.Qt.WaitCursor))
        self.filePath = filePath
        data_ecm = None
        root, ext = os.path.splitext(str(filePath))
        if ext == ".txt":
            #data_ecm = Manyo.ElementContainerMatrix()
            #tt = Manyo.Utsusemi.UtsusemiContainerTextConverter()
            #tt.Load( str(filePath), data_ecm )
            #del tt
            (ECM, bins, mins, maxs) = self.ReadFromTextFile(str(filePath))
            self.SetData(ecm_in=ECM, xkey="-", ykey="-", zkey="-", isFromFile=True, xbin=str(bins[0]), ybin=str(bins[1]), zbin=str(bins[2]))
            return
        elif ext == ".srlz":
            data_ecm = Manyo.ElementContainerMatrix()
            file = Manyo.ReadSerializationFileBinary(str(filePath))
            file.Load(data_ecm)
            del file
        elif ext == ".mdb":
            ff = Manyo.ManyoDataIO()
            data_ecm = ff.ReadElementContainerMatrix(str(filePath))
            del ff

        if data_ecm.PutHeaderPointer().CheckKey(ViewMainData.HEADKEY_SLICE3DBINS) == 1:
            bins = data_ecm.PutHeaderPointer().PutDoubleVector(ViewMainData.HEADKEY_SLICE3DBINS)
            self.SetData(ecm_in=data_ecm, xkey="-", ykey="-", zkey="-", isFromFile=True, xbin=str(bins[0]), ybin=str(bins[1]), zbin=str(bins[2]))
            return
        self.SetData(data_ecm)
    #<--[inamura 170227]

    def ReadFromTextFile(self, filepath):
        bins = [0.0, 0.0, 0.0]
        mins = [1e10, 1e10, 1e10, 1e10]
        maxs = [-1e10, -1e10, -1e10, -1e10]
        fo = open(filepath, "r")
        vx = []
        vy = []
        vz = []
        ii = []
        ee = []
        if fo is None:
            print("Failed open given file : {}".format(filepath))
        # Read Text file
        while(True):
            aline = fo.readline()
            if aline == "":
                break
            # If comment out line or header info
            if aline.find("# ") == 0:
                if aline.find("BINS") != 0:
                    v0 = aline.split("=")
                    if len(v0) == 2:
                        v = v0[1].split(",")
                        if len(v) == 3:
                            bins[0] = float(v[0])
                            bins[1] = float(v[1])
                            bins[2] = float(v[2])
                        else:
                            print("Header BINS format is not valid (BINS = <x_bin>, <y_bin>, <z_bin>)")
            else:
                aline = aline.strip()
                v = aline.split(",")
                if len(v) != 5:
                    print("Invalid format = {}".format(aline))
                    continue
                vv = []
                try:
                    for av in v:
                        vv.append(float(av))
                except:
                    print("Infalid format for float conversions")
                    continue

                for i in range(4):
                    if vv[i] < mins[i]:
                        mins[i] = vv[i]
                    if vv[i] > maxs[i]:
                        maxs[i] = mins[i]

                vx.append(vv[0])
                vy.append(vv[1])
                vz.append(vv[2])
                ii.append(vv[3])
                ee.append(vv[4])
        fo.close()
        EC = Manyo.ElementContainer()
        vx_key = "Vx"
        vy_key = "Vy"
        vz_key = "Vz"
        ii_key = "Intensity"
        ee_key = "Error"
        EC.Add(vx_key, vx)
        EC.Add(vy_key, vy)
        EC.Add(vz_key, vz)
        EC.Add(ii_key, ii)
        EC.Add(ee_key, ee)
        EC.SetKeys(vz_key, ii_key, ee_key)
        ECA = Manyo.ElementContainerArray()
        ECA.Add(EC)
        hh = Manyo.HeaderBase()
        vst = Manyo.MakeStringVector()
        vst.push_back(vx_key)
        vst.push_back(vy_key)
        vst.push_back(vz_key)
        hh.Add(ViewMainData.HEADKEY_SLICE3DKEYS, vst)
        ECM = Manyo.ElementContainerMatrix(hh)
        ECM.Add(ECA)
        return (ECM, bins, mins, maxs)

    def getDataInformation(self):
        if not hasattr(self, 'data_ecm'):
            return

        ecaNum = self.data_ecm.PutSize()
        eca0 = self.data_ecm.Put(0)
        ecNum = eca0.PutSize()

        ec0  = eca0.Put(0)

        xmin = ec0.Min(str(self.ax1Key))
        xmax = ec0.Max(str(self.ax1Key))
        ymin = ec0.Min(str(self.ax2Key))
        ymax = ec0.Max(str(self.ax2Key))
        zmin = ec0.Min(str(self.ax3Key))
        zmax = ec0.Max(str(self.ax3Key))

        ec1 = eca0.Put(1)

        if xmin != xmax:
            xlist = ec0.PutList(str(self.ax1Key))
            xmin1 = ec1.Min(str(self.ax2Key))
            if xmin != xmin1:
               data_orientation = ViewMainData.DATA_ORI_XYZ
               ylist = [0] * ecNum
               zlist = [0] * ecaNum
            else:
               data_orientation = ViewMainData.DATA_ORI_XZY
               ylist = [0] * ecaNum
               zlist = [0] * ecNum
        elif ymin != ymax:
            ylist = ec0.PutList(str(self.ax2Key))
            xmin1 = ec1.Min(str(self.ax1Key))
            if xmin != xmin1:
               data_orientation = ViewMainData.DATA_ORI_YXZ
               xlist = [0] * ecNum
               zlist = [0] * ecaNum
            else:
               data_orientation = ViewMainData.DATA_ORI_YZX
               xlist = [0] * ecaNum
               zlist = [0] * ecNum
        elif zmin != zmax:
            zlist = ec0.PutList(str(self.ax3Key))
            xmin1 = ec1.Min(str(self.ax1Key))
            if xmin != xmin1:
               data_orientation = ViewMainData.DATA_ORI_ZXY
               xlist = [0] * ecNum
               ylist = [0] * ecaNum
            else:
               data_orientation = ViewMainData.DATA_ORI_ZYX
               xlist = [0] * ecaNum
               ylist = [0] * ecNum

        for id in range(ecNum):
            if data_orientation == ViewMainData.DATA_ORI_ZXY or \
               data_orientation == ViewMainData.DATA_ORI_YXZ:
                xlist[id] = eca0(id).Min(str(self.ax1Key))
            elif data_orientation == ViewMainData.DATA_ORI_XYZ or \
                 data_orientation == ViewMainData.DATA_ORI_ZYX:
                ylist[id] = eca0(id).Min(str(self.ax2Key))
            elif data_orientation == ViewMainData.DATA_ORI_XZY or \
                 data_orientation == ViewMainData.DATA_ORI_YZX:
                zlist[id] = eca0(id).Min(str(self.ax3Key))

        for id in range(ecaNum):
            if data_orientation == ViewMainData.DATA_ORI_ZYX or \
               data_orientation == ViewMainData.DATA_ORI_YZX:
                xlist[id] = self.data_ecm(id, 0).Min(str(self.ax1Key))
            elif data_orientation == ViewMainData.DATA_ORI_XZY or \
                 data_orientation == ViewMainData.DATA_ORI_ZXY:
                ylist[id] = self.data_ecm(id, 0).Min(str(self.ax2Key))
            elif data_orientation == ViewMainData.DATA_ORI_XYZ or \
                 data_orientation == ViewMainData.DATA_ORI_YXZ:
                zlist[id] = self.data_ecm(id, 0).Min(str(self.ax3Key))



        # get minimum bin size
        size = len(xlist)
        xlist.sort() #[inamura 180422]
        tmp1 = np.array(xlist[0:size-1])
        tmp2 = np.array(xlist[1:size])
        tmp3 = tmp2 - tmp1
        self.basicSliceAx1bin = min(tmp3)

        size = len(ylist)
        ylist.sort() #[inamura 180422]
        tmp1 = np.array(ylist[0:size-1])
        tmp2 = np.array(ylist[1:size])
        tmp3 = tmp2 - tmp1
        self.basicSliceAx2bin = min(tmp3)

        size = len(zlist)
        zlist.sort() #[inamura 180422]
        tmp1 = np.array(zlist[0:size-1])
        tmp2 = np.array(zlist[1:size])
        tmp3 = tmp2 - tmp1
        self.basicSliceAx3bin = min(tmp3)
        del tmp1, tmp2, tmp3

        # get xrange, yrange, zrange
        self.rangex = [min(xlist), max(xlist)]
        self.rangey = [min(ylist), max(ylist)]
        self.rangez = [min(zlist), max(zlist)]
        #print "len(xlist), len(ylist), len(zlist)=",len(xlist), len(ylist), len(zlist)
        del xlist, ylist, zlist

    def getDataInformationIntensity(self):
        if not hasattr(self, 'data_ecm'):
            return
        eca   = self.data_ecm.Put(0)
        ecaNum = self.data_ecm.PutSize()
        ecNum = eca.PutSize()
        minIntensity = np.zeros((ecaNum, ecNum))
        maxIntensity = np.zeros((ecaNum, ecNum))
        for id in range(ecaNum):
            eca = self.data_ecm(id)
            if eca.PutHeaderPointer().CheckKey("MASKED") == 1:
                if eca.PutHeaderPointer().PutInt4("MASKED") == 1:
                    continue
            ecNum = eca.PutSize()
            for i in range(ecNum):
                """
                ec = eca(i)
                intensity = ec.PutList("Intensity")
                #intensity = ec.PutYList()
                error     = ec.PutList("Error")
                tmp  = np.array(intensity)
                maxIntensity[id, i] = tmp.max()
                tmp2 = tmp[np.where(tmp < 1.0)]
                if tmp2.size > 0:
                    minIntensity[id, i] = tmp2.min()
                    #maxIntensity[id, i] = tmp.max()
                """
                if eca(i).PutHeaderPointer().CheckKey("MASKED") == 1:
                    if eca(i).PutHeaderPointer().PutInt4("MASKED") == 1:
                        continue
                minIntensity[id, i] = eca(i).Min("Intensity")
                maxIntensity[id, i] = eca(i).Max("Intensity")

        self.intensityMin = minIntensity.min()
        self.viewSubData.scalarRangeMin = self.intensityMin
        self.intensityMax = maxIntensity.max()
        self.viewSubData.scalarRangeMax = self.intensityMax

    #[inamura 180422]-->
    def getDataInformation2(self,in_xbin,in_ybin,in_zbin):
        if in_xbin=="-":
            self.getDataInformation()
        else:
            xbin = -1.0
            ybin = -1.0
            zbin = -1.0
            if in_xbin!="-":
                xbin = float(in_xbin)
            if in_ybin!="-":
                ybin = float(in_ybin)
            if in_zbin!="-":
                zbin = float(in_zbin)
            if (xbin>0.) and (ybin<0.0):
                ybin = xbin
            if (xbin>0.) and (zbin<0.0):
                zbin = xbin

            self.basicSliceAx1bin = xbin
            self.basicSliceAx2bin = ybin
            self.basicSliceAx3bin = zbin

        try:
            import Manyo.MLF as mm
            p = mm.MlfMatrixSlicer(self.data_ecm)
            p.SetAxes(str(self.ax1Key), str(self.ax2Key), str(self.ax3Key) )
            v = p.PutAllAxesRanges()
            del p
            xMin = v[0]
            xMax = v[1]
            yMin = v[2]
            yMax = v[3]
            zMin = v[4]
            zMax = v[5]
            if in_xbin!="-":
                xMin = math.floor(xMin/xbin)*xbin
                xMax = math.floor(xMax/xbin)*xbin
                yMin = math.floor(yMin/ybin)*ybin
                yMax = math.floor(yMax/ybin)*ybin
                zMin = math.floor(zMin/zbin)*zbin
                zMax = math.floor(zMax/zbin)*zbin
            self.rangex = [ xMin, xMax ]
            self.rangey = [ yMin, yMax ]
            self.rangez = [ zMin, zMax ]
        except:
            pass
        #<--[inamura 180422]

        self. getDataInformationIntensity()

    def getDataKeys(self):
        #self.ax1Key = "Xval"
        #self.ax2Key = "Yval"
        #self.ax3Key = "Zval"

        self.ax1Slice.axisTitle = self.ax1Key
        self.ax2Slice.axisTitle = self.ax2Key
        self.ax3Slice.axisTitle = self.ax3Key

    def isThreadRunning(self):
        running = False
        if hasattr(self, "sliceThread"):
           if self.sliceThread.is_alive():
               running = True

        return running

        #tlist = threading.enumerate()
        #if 1 < len(tlist):
        #     return True
        #else:
        #     return False
        #for t in tlist:
        #        print t.name

    def getThreadName(self, process, planeID):
        procName = ""
        if process == ViewMainData.PROCESS_MAIN:
           procName = "main"
        elif process == ViewMainData.PROCESS_M2PLOT:
           procName = "m2plot"
        elif process == ViewMainData.PROCESS_OUT_IMAGE:
           procName = "image"
        elif process == ViewMainData.PROCESS_OUT_BINARY:
           procName = "binary"

        procName += "-%d" % planeID
        return procName

    def doFreeSliceView(self, process, outputPath):
        if self.isThreadRunning():
            #QtGui.QMessageBox.warning(self, 'Error', 'Other thread is running. Please wait.')
            return False

        if process == ViewMainData.PROCESS_M2PLOT:
            self.showFreeSliceView(process, outputPath)
        else:
            self.sliceThread = threading.Thread(target = self.showFreeSliceView, \
                                                args=(process, outputPath))
            self.sliceThread.start()
        return True

    def showFreeSliceView(self, process, outputPath):
        QtWidgets.QApplication.setOverrideCursor(QtGui.QCursor(QtCore.Qt.WaitCursor))
        self.stop_event.clear()
        ps = PlaneSlicer.PlaneSlicer(self.data_ecm)

        org = self.freeSlice.org
        x   = self.freeSlice.x
        y   = self.freeSlice.y
        xbin   = self.freeSlice.xbin
        ybin   = self.freeSlice.ybin
        rngx  = self.freeSlice.rangex
        rngy  = self.freeSlice.rangey
        thick = self.freeSlice.thickness

        ps.SetAxes(str(self.ax1Key), str(self.ax2Key), str(self.ax3Key) ) #[inamura 180422]
        ps.SetPlaneKeys(str(self.ax1Key), str(self.ax2Key) ) #[inamura 180422]

        eca  = ps.GetPlane(org, x, y, xbin, ybin, rngx, rngy, thick)

        root, ext = os.path.splitext(str(outputPath))

        current = 0
        if process == ViewMainData.PROCESS_M2PLOT:
            p    = mp.M2PlotPlusCui(eca)
#            subprocess.call("mp.M2PLot(eca)")
        elif process == ViewMainData.PROCESS_OUT_BINARY:
            path = root + "-f%03d.eca" % (current -1)
            eca.SaveToBinFile("Intensity", path)
            #filePath = "‾/test.srlz"
            #write_binary = Manyo.WriteSerializationFileBinary(str(filePath))
            #write_binary.Save(eca)
        elif process == ViewMainData.PROCESS_MAIN:
            self.extractIntensityForFreeSlice(eca)
            self.create_free_slice_signal.emit((0,))
            self.update_glview_signal.emit()
#             if self.update_slice_view_flag:
#                 self.emit(self.update_slice_view_signal, (planeID, ))
#             time.sleep(1)
        elif process == ViewMainData.PROCESS_OUT_IMAGE:
            self.extractIntensityForFreeSlice(eca)
            self.create_free_slice_signal.emit((0,))
            self.update_glview_signal.emit()

#             if self.update_slice_view_flag:
#                 self.emit(self.update_slice_view_signal, (planeID, ))
# #            path = root + "%03d.png" % (current -1)
#             path = root + "%03d.png" % self.imageID
#             self.emit(self.save_glview_signal, path)
#             time.sleep(1)

#        message = "%d/%d done  @ %s = %g" % (current, totalNum, posStr, pos)
#        self.emit(self.status_bar_signal, message)

#        self.emit(self.update_scrollbar_signal)

        QtWidgets.QApplication.restoreOverrideCursor()


    def doBasicSliceView(self, process, planeID, outputPath, ax1Changed = False, ax2Changed = False, ax3Changed = False):
        if self.isThreadRunning():
            #QtGui.QMessageBox.warning(self, 'Error', 'Other thread is running. Please wait.')
            return False

        #threadName = self.getThreadName(process, planeID)
        #self.sliceThread = threading.Thread(target = self.showBasicSliceViewThread,
        #                   args=(process, planeID, outputPath), name=threadName)
        #self.sliceThread.start()
        if process == ViewMainData.PROCESS_M2PLOT:
            self.showBasicSliceView(process, planeID, outputPath)
        else:
            threadName = self.getThreadName(process, planeID)
            self.sliceThread = threading.Thread(target = self.showBasicSliceViewThread, \
                                                args=(process, planeID, outputPath, ax1Changed, ax2Changed, ax3Changed), name=threadName)
            self.sliceThread.start()
        return True

    def showBasicSliceViewThread(self, process, planeID, outputPath, ax1Changed, ax2Changed, ax3Changed):
        self.imageID = 0
#        if process == ViewMainData.PROCESS_MAIN:
        if process == ViewMainData.PROCESS_MAIN or \
           process == ViewMainData.PROCESS_OUT_IMAGE:
            if ax3Changed:
                planeID = ViewMainData.SLICE_XY
                self.showBasicSliceView(process, planeID, outputPath)
            if ax1Changed:
                planeID = ViewMainData.SLICE_YZ
                self.showBasicSliceView(process, planeID, outputPath)
            if ax2Changed:
                planeID = ViewMainData.SLICE_ZX
                self.showBasicSliceView(process, planeID, outputPath)
        else:
            self.showBasicSliceView(process, planeID, outputPath)


    def showBasicSliceView(self, process, planeID, outputPath):
        QtWidgets.QApplication.setOverrideCursor(QtGui.QCursor(QtCore.Qt.WaitCursor))
        self.stop_event.clear()
        ps = PlaneSlicer.PlaneSlicer(self.data_ecm)

        pos = 0.0
        org = []
        x   = []
        y   = []
        xbin = 0.01
        ybin = 0.01
        rngx = []
        rngy = []
        thick = 1.0

        pos_str = ""
        pos_min  = 0.0
        pos_max  = 0.0
        pos_step = 0.0

        self.data_ax1bin = self.basicSliceAx1bin
        self.data_ax2bin = self.basicSliceAx2bin
        self.data_ax3bin = self.basicSliceAx3bin

        ps.SetAxes(str(self.ax1Key), str(self.ax2Key), str(self.ax3Key) ) #[inamura 180422]
        if planeID == ViewMainData.SLICE_XY:
            #ps.SetAxes(self.ax1Key, self.ax2Key, self.ax3Key)
            ps.SetPlaneKeys(str(self.ax1Key), str(self.ax2Key)) #[inamura 180422]
            pos_str = self.ax3Slice.position
            xbin = self.basicSliceAx1bin
            ybin = self.basicSliceAx2bin
            rngx = self.rangex
            rngy = self.rangey
            #rngx = [self.basicSliceAx1From, self.basicSliceAx1To]
            #rngy = [self.basicSliceAx2From, self.basicSliceAx2To]
            thick = self.ax3Slice.thickness
        elif planeID == ViewMainData.SLICE_YZ:
            #ps.SetAxes(self.ax2Key, self.ax3Key, self.ax1Key)
            ps.SetPlaneKeys(str(self.ax2Key), str(self.ax3Key)) #[inamura 180422]
            pos_str = self.ax1Slice.position
            xbin = self.basicSliceAx2bin
            ybin = self.basicSliceAx3bin
            rngx = self.rangey
            rngy = self.rangez
            thick = self.ax1Slice.thickness
        elif planeID == ViewMainData.SLICE_ZX:
            #ps.SetAxes(self.ax3Key, self.ax1Key, self.ax2Key)
            ps.SetPlaneKeys(str(self.ax1Key), str(self.ax3Key)) #[inamura 180422]
            pos_str = self.ax2Slice.position
            xbin = self.basicSliceAx1bin
            ybin = self.basicSliceAx3bin
            rngx = self.rangex
            rngy = self.rangez
            thick = self.ax2Slice.thickness

        pos_list = pos_str.split(":")
        if len(pos_list) == 3:
            pos_min = float(pos_list[0])
            pos_max = float(pos_list[1])
            pos_step = abs(float(pos_list[2]))
        else:
            pos_min = pos_max = float(pos_list[0])
            pos_step = 1.0


        pos_list = []
        if pos_min<pos_max:
            tmppos = pos_min
            while tmppos <= pos_max:
                pos_list.append( tmppos )
                tmppos += pos_step
        elif pos_min>pos_max:
            tmppos = pos_min
            while tmppos >= pos_max:
                pos_list.append( tmppos )
                tmppos -= pos_step
        elif pos_min==pos_max:
            pos_list.append( pos_min )

        totalNum = len(pos_list)

        root, ext = os.path.splitext(str(outputPath))
        current = 1
        posStr = ""
        x0 = rngx[0]-xbin/2.0 #[inamura 170227]
        y0 = rngy[0]-ybin/2.0 #[inamura 170227]
        for pos in pos_list:
            if self.stop_event.is_set():
                self.stop_event.clear()
                break

            if planeID == ViewMainData.SLICE_XY:
#                org = [0.0, 0.0, pos]
#                x   = [1.0, 0.0, pos]
#                y   = [0.0, 1.0, pos]

                org = [x0,     y0, pos]
                x   = [x0+1.0, y0, pos]
                y   = [x0, y0+1.0, pos]
                posStr = "z"
            elif planeID == ViewMainData.SLICE_YZ:
#                org = [pos, 0.0, 0.0]
#                x   = [pos, 1.0, 0.0]
#                y   = [pos, 0.0, 1.0]
                org = [pos, x0,     y0]
                x   = [pos, x0+1.0, y0]
                y   = [pos, x0, y0+1.0]
                posStr = "x"
            elif planeID == ViewMainData.SLICE_ZX:
#                org = [0.0, pos, 0.0]
#                x   = [1.0, pos, 0.0]
#                y   = [0.0, pos, 1.0]
                org = [x0,     pos, y0]
                x   = [x0+1.0, pos, y0]
                y   = [x0,     pos, y0+1.0]
                posStr = "y"

            eca  = ps.GetPlane(org, x, y, xbin, ybin, rngx, rngy, thick)
            #print "org = ", org
            #print "x = ", x
            #print "y = ", y
            #print "xbin, ybin = ", xbin, ybin
            #print "rngx = ", rngx
            #print "rngy = ", rngy
            #print "thick = ", thick

            if process == ViewMainData.PROCESS_M2PLOT:
                p    = mp.M2PlotPlusCui(eca)
#                subprocess.call("mp.M2PLot(eca)")
            elif process == ViewMainData.PROCESS_OUT_BINARY:
                path = root + "%03d.eca" % (current -1)
                eca.SaveToBinFile("Intensity", path)
                #filePath = "‾/test.srlz"
                #write_binary = Manyo.WriteSerializationFileBinary(str(filePath))
                #write_binary.Save(eca)
            elif process == ViewMainData.PROCESS_MAIN:
                self.extractIntensity(eca, pos, planeID)
#                self.emit(self.create_slice_signal, (planeID, pos))
                self.create_slice_signal.emit((planeID,))
                self.update_grid_size_signal.emit()
                self.update_grid_signal.emit()
                self.update_glview_signal.emit()
                if self.update_slice_view_flag:
                    self.update_slice_view_signal.emit((planeID, ))
                time.sleep(1)
            elif process == ViewMainData.PROCESS_OUT_IMAGE:
                self.extractIntensity(eca, pos, planeID)
                self.create_slice_signal.emit((planeID,))
                self.update_glview_signal.emit()
                if self.update_slice_view_flag:
                    self.update_slice_view_signal.emit((planeID, ))
#                path = root + "%03d.png" % (current -1)
                path = root + "%03d.png" % self.imageID
                self.save_glview_signal.emit(path)
                time.sleep(1)

            message = "%d/%d done  @ %s = %g" % (current, totalNum, posStr, pos)
            self.status_bar_signal.emit(message)
            current += 1
            self.imageID += 1

        self.update_scrollbar_signal.emit()
        QtWidgets.QApplication.restoreOverrideCursor()

    def extractIntensityForFreeSlice(self, eca):
        ecNum = eca.PutSize()
        x = np.array([0])
        #print ecNum

        ec = eca.Put(0)
        y  = ec.PutXList()
        ylen = len(y)

        xval = eca.PutHeader().PutDoubleVector(self.ax1Key)
        xval_list = Manyo.DoubleVectorToList(xval)

        x = xval_list
        xlen = len(x)

        # print len(x)
        # print x
        # print len(y)
        # print y

        self.data_free = np.zeros((xlen, ylen))

        tmpMin = 9999.0
        tmpMax = -9999.0
        #self.intensityMin = tmpMin
        #self.intensityMax = tmpMax

        for xid in range(xlen):
           ec = eca.Put(xid)
           intensity = ec.PutYList()
           #tmpMin = min(intensity)
           #tmpMax = max(intensity)

           for yid in range(len(intensity)):
              val = intensity[yid]
              if val > 1.0: # 1e+100 ... Invalid Value ???
                  val = 1e-16

              if val < tmpMin:
                  tmpMin = val
              elif tmpMax < val:
                  if val <= 1.0:
                      tmpMax = val
              self.data_free[xid,yid] = val

#           if tmpMin < self.intensityMin:
#               self.intensityMin = tmpMin
#           if self.intensityMax < tmpMax:
#               self.intensityMax = tmpMax





    def extractIntensity(self, eca, pos, planeID):
        ecNum = eca.PutSize()

        x = np.array([0])
        xvalKey = ""
        if planeID == ViewMainData.SLICE_XY:
            minx = min(self.rangex)
            maxx = max(self.rangex)
            minx -= self.basicSliceAx1bin
            maxx += self.basicSliceAx1bin
            x  = np.arange(minx, maxx, self.basicSliceAx1bin)
            xvalKey = self.ax1Key
        elif planeID == ViewMainData.SLICE_YZ:
            minx = min(self.rangey)
            maxx = max(self.rangey)
            minx -= self.basicSliceAx2bin
            maxx += self.basicSliceAx2bin
            x  = np.arange(minx, maxx, self.basicSliceAx2bin)
            xvalKey = self.ax2Key
        elif planeID == ViewMainData.SLICE_ZX:
            minx = min(self.rangex)
            maxx = max(self.rangex)
            minx -= self.basicSliceAx1bin
            maxx += self.basicSliceAx1bin
            x  = np.arange(minx, maxx, self.basicSliceAx1bin)
            xvalKey = self.ax1Key

        if ecNum < len(x):
           x = x[0:ecNum]  # OLD...

        xlen = len(x)
        ec = eca.Put(0)
        y  = ec.PutXList()
        ylen = len(y)

        xval = eca.PutHeader().PutDoubleVector(str(xvalKey)) #[inamura 180422]
        xval_list = Manyo.DoubleVectorToList(xval)

        x = xval_list
#        print(xval_list)
#        print eca.PutHeader().Dump()
#        print ec.PutHeader().Dump()

        if planeID == ViewMainData.SLICE_XY:
            self.data_xy = np.zeros((xlen, ylen))
            self.data_xy_range = [min(x), max(x), min(y), max(y)]
            self.data_xy_pos = pos
        elif planeID == ViewMainData.SLICE_YZ:
            self.data_yz = np.zeros((xlen, ylen))
            self.data_yz_range = [min(x), max(x), min(y), max(y)]
            self.data_yz_pos = pos
        elif planeID == ViewMainData.SLICE_ZX:
#           self.data_zx = np.zeros((xlen, ylen))
#           variable x means z, variable y means x.
#           data_zx[X][Y]: [X] have to be x and [y] have to be z:
            self.data_zx = np.zeros((xlen, ylen))
            self.data_zx_range = [min(x), max(x), min(y), max(y)]
            self.data_zx_pos = pos

        tmpMin = 9999.0
        tmpMax = -9999.0
        self.intensityMin = tmpMin
        self.intensityMax = tmpMax

        for xid in range(xlen):
           ec = eca.Put(xid)
           intensity = ec.PutYList()
           #tmpMin = min(intensity)
           #tmpMax = max(intensity)

           for yid in range(len(intensity)):
              val = intensity[yid]
              #if val > 1.0: # 1e+100 ... Invalid Value ???
              if val > 1.0e+30:
                  val = 1e-16

              if val < tmpMin:
                  tmpMin = val
              elif tmpMax < val:
                  if val <= 1.0:
                      tmpMax = val
              if planeID == ViewMainData.SLICE_XY:
                  self.data_xy[xid,yid] = val
              elif planeID == ViewMainData.SLICE_YZ:
                  self.data_yz[xid,yid] = val
              elif planeID == ViewMainData.SLICE_ZX:
#                  self.data_zx[xid,yid] = val
                  self.data_zx[xid,yid] = val

           if tmpMin < self.intensityMin:
               self.intensityMin = tmpMin
           if self.intensityMax < tmpMax:
               self.intensityMax = tmpMax

        if self.viewSubData.autoScale == True:
            self.viewSubData.scalarRangeMin = self.intensityMin
            self.viewSubData.scalarRangeMax = self.intensityMax
            self.update_autoscale_signal.emit()

