#!/usr/bin/python
# -*- coding: utf-8 -*-
"""
D2Vis.py
2次元プロッタ処理
"""
import wx
import os
import time
import tempfile
import matplotlib
# 先に指定されていなかったら、バックエンドを指定
if not matplotlib.get_backend() == 'WXAgg':
    matplotlib.use('WXAgg')
## [inamura 100726] for checking version of  matplotlib
vers = matplotlib.__version__.split('.')
matplotlib_verNo = int(vers[0])*1000 + int(vers[1])*10 + int(vers[0])
## <--[inamura 100726]
from matplotlib.backends.backend_wxagg import FigureCanvasWxAgg as FigCanvas
from pylab import *
from matplotlib.colors import LogNorm
from matplotlib.figure import Figure
#import matplotlib.numerix as numpy
from numpy import *
import cStringIO, zlib
import sys
#import matplotlib.numerix.ma as ma
try:
    import numpy.ma as ma
except:
    import numpy.core.ma as ma
from matplotlib import cm
from vis.UtilPlot import *
from vis.ChartToolBar import ChartToolBar
from vis.FastPlot import *

## [KCS 130520]-->
try:
    import Manyo as mm
    from vis.M2Plot import D2Matrix 
    import vis.M2Clip as mc
    import Manyo.Utsusemi as mu
except:
    pass
import  wx.grid as gridlib
## <-- [KCS 130520]

##[inamura 101022]-->
#print "This is smooth version" 
try:
    from scipy import signal
    import scipy
except:
    pass
##<--[inamura 101022]
if sys.platform=='darwin':
    D2VISXRC = "D2Vis_macosx"
else:
    D2VISXRC = "D2Vis"
"""
brief update history
[inamura 
[inamura 171124] - fix change of smoothing window value does not applied to plotter correctly
[inamura 171106] - rewrite comparison between self.Z and None to use isinstance(self.Z, ndarray)
[inamura 170726] - improved LoadDataFromText to enable to read non-linear axes
[inamura 170306] - fixed the issue that smoothing does not work on update data
                 - fixed the incorrect plotting and axes on loading data from text
[inamura 170302] - added haxby color map, replaced color map combobox to choice
[inamura 170126] - changed to send "map-format" data to M2Plot (for VisualContQ)
[inamura 170118] - improved SaveAsText format : added X,Y Label
[inamura 170111] - added functions to change Bad and Background Color
[inamura 160823] - bugfix of drawing at UpdataData event
[inamura 160803] - bugfix of Legacy2DFile
                 - bugfix of error in MakeMeshList
[inamura 160726] - added Tick Setting
                 - improved FreeSlicer xscale
[inamura 160721] added FreeSlicer
[inamura 160627]  added setxlog and setylog
[inamura 160603-2] added to notify "updatedata".
[inamura 160603] improved SaveAsText to save data points out of Q range at elastic
[inamura 160401] improved GUI for MacOS by using D2Vis_macosx.xrc
[inamura 160229] Bugfix the freeze at ModalDialog.Destroy() on cocoa wx
[inamura 160218] added SaveAsText dialog
2014.09.01 Bugfix and improved MapObj::_ReBinEC 
2014.08.21 Add function to load text data file
2014.06.05 Bugfix of wrong setting of slicing parameters
2013.06.28 KCS bugfix
2013.06.25 KCS bugfix
2013.06.24 Improve SaveAsText on type=0 ( not powder mode )
2013.06.17-20 Merge latest Inamura version and KCS parts
2013.05.20 Add Overplot and Clip Redgion functions
2012.11.04 Update SaveAsText
2012.10.29 Debug around font control in SetXyRange2D and add listners for dialog
2012.07.11 Enable to change font size and font name on labels or titles
2012.07.10 Add Clickable area to show dialogs
2012.04.17 Add Quiet mode and CUI for Save figure
2012.02.11 Add Single plotter mode and Quiet mode
2011.01.25 Revise befavior to plot with smoothing (can replot with Apply button)
2011.01.25 Add new color map as default
2011.01.06 Add cursol on/off button, revise behavior of checkbox for smoothing
2010.12.14 Add function to output TEXT data
2010.10.22 Add smoothing function
2010.07.26 matplotlib 1.0.0 version
2010.06.22 Revise style to show Z-value (log scale
2009.09.24 Add color map dialog and x-y scale dialog

"""


#######################################
#  HistObj
#######################################  
class HistObj(object):
    
    """
    ヒストグラムデータクラス
    """
    #########################################
    def __init__(self, bins, counts, errs, fp=0.0, mp=0.0, ep=0.0):
        """
        コンストラクタ
        @param  bins  ヒストグラムのビン(array型) 
        @param  counts  強度値(array型) 
        @param  errs  エラー値(array型)
        @param  fp    始値
        @param  mp    中央値
        @param  ep    終値
        @retval 無し
        """ 
        # ヒストグラムビン
        self.bins = bins
        # Y データ
        self.counts = counts
        # エラー値
        self.errs = errs
        # 積算カウンター　2009.12.25 Minakawa 追加
        self.numInteg = zeros(len(counts),int) 
        for i in range(len(counts)):
            if counts[i] < MASKVALUE:
                self.numInteg[i] = 1 
        # 始値
        self.fp = fp
        # 中央値
        self.mp = mp
        # 終値
        self.ep = ep 
               
       
    #########################################
    def AddData(self, data) :
        """
        ヒストグラムデータを加算　2009.12.25 Minakawa 全面変更
        @param   data  加算対象のデータインスタンス
        @retval 無し
        """ 
        for i in range(len(self.counts)):
            # どちらもマスク値でなければ
            if data.counts[i] < MASKVALUE and self.counts[i] < MASKVALUE:
                # データを加算
                self.counts[i] += data.counts[i]
                # 積算回数を加算
                ##[inamura 100617]-->
                if self.numInteg[i]==1:
                    self.errs[i] = self.errs[i]*self.errs[i]      
                #self.numInteg[i] += 1
                
                #self.errs[i] = self.errs[i]*self.errs[i] + data.errs[i]*data.errs[i]
                self.errs[i] += data.errs[i]*data.errs[i]
                self.numInteg[i] += 1
                ##<--[inamura 100617]
                
            # 加算対象がマスク値であるなら
            elif self.counts[i] >= MASKVALUE:
                # データを置き換える
                self.counts[i] = data.counts[i]
                # 積算回数を加算
                self.numInteg[i] = 1
                #self.errs[i] = data.errs[i]*data.errs[i]
                self.errs[i] = data.errs[i]

        
    #########################################
    def DevidData(self, num) :
        """
        ヒストグラムデータを除算
        @param   num  除数
        @retval 無し
        """ 
        #self.counts = self.counts / num
        #self.errs = sqrt(self.errs) / num  
        for i in range(len(self.counts)):
            if self.numInteg[i] > 1:
                self.errs[i] = sqrt(self.errs[i])
            
            self.counts[i] = self.counts[i] / num
            self.errs[i] = self.errs[i] / num
        
    #########################################
    def DevidInteg(self) :
        """
        ヒストグラムデータを除算
        @param  無し
        @retval 無し
        """ 
        for i in range(len(self.counts)):
            # 積算回数があれば
            if self.numInteg[i] > 1:
                # 積算回数で除する
                self.counts[i] = self.counts[i] / self.numInteg[i]
                self.errs[i] = sqrt(self.errs[i]) / self.numInteg[i]          
        
  

    #########################################
    def ClearInteg(self) :
        """
        積算カウンターをクリア
        @param  無し
        @retval 無し
        """ 
        
    #########################################
    def ReBin(self, bins1) :
        """
        リビニング実行
        対象となる bin 値列と同じになるようにリビニングを実行
        2009.12.22 全面改訂
        (個数ヒストグラムから密度ヒストグラムに変更)
        @param  bins1  リビニング後のビン配列
        @retval 無し
        """ 
        bnum = len(bins1)-1
        
        # 積算用に全点 0 のアレイを作成        
        z1 =zeros(bnum, float64)   # データ用
        e1 =zeros(bnum, float64)   # エラー用
        k1 =zeros(bnum, float64)   # データの重み用
        
        # リビニング後のビン値の最初のカウンターを求める
        j=0
        while bins1[j+1] < self.bins[0]:
            j += 1
        # リビニング前のビン値の最初のカウンターを求める
        i=0
        while self.bins[i] < bins1[0]:
            i += 1

        # リビニング前の全データについて繰り返す
        while i < len(self.counts):
            # リビニング後の最後のデータまで終わったか    
            if j >= bnum:
                break
            # リビニング後のビン幅 
            bin = bins1[j+1]-bins1[j]
            # マスク値でなければ
            if self.counts[i] < MASKVALUE:
                 # 対象ビンの値を取り出す
                zint = self.counts[i]
                err = self.errs[i]

                # リビニング前のビンがリビニング後のビンより大きければ
                if self.bins[i+1] > bins1[j+1]:
                    kk = bins1[j+1]-self.bins[i]
                    ##[inamura 100619]-->
                    z1[j] += zint*kk
                    e1[j] += kk*kk*err*err
                    #z1[j] += zint*(kk/bin)/err/err
                    #e1[j] += (kk/bin)/err/err
                    ##<--[inamura 100619]
                    k1[j] += kk
                    # リビニング後のビンが前のビンに到達するまで
                    while True:
                        j += 1
                        # リビニング後の最後のビンなら
                        if j >= bnum:
                            break
                        bin = bins1[j+1]-bins1[j]
                        # 前のビンに未達か
                        if bins1[j+1] < self.bins[i+1]:
                            kk = bins1[j+1]-bins1[j]
                            ##[inamura 100619]-->
                            z1[j] += zint*kk
                            e1[j] += kk*kk*err*err
                            #z1[j] += zint*(kk/bin)/err/err
                            #e1[j] += (kk/bin)/err/err
                            ##<--[inamura 100210]
                            k1[j] += kk
                        else:
                            kk = self.bins[i+1]-bins1[j]
                            break

                # リビニング後の対象ビンにリビニング前の値を加算
                elif(self.bins[i] < bins1[j]):
                    # 比例配分した値を加算
                    kk = self.bins[i+1] - bins1[j]
                else:
                    # リビニング前のビン幅が領域値
                    kk = self.bins[i+1] - self.bins[i]
                if j >= bnum:
                    break
                ##[inamura 100619]-->
                z1[j] += zint*kk
                e1[j] += kk*kk*err*err
                #z1[j] += zint*(kk/bin)/err/err
                #e1[j] += (kk/bin)/err/err
                ##<--[inamura 100210]
                k1[j] += kk
            i += 1
            if self.bins[i] > bins1[j+1]:
                j+= 1

        # 加算した値をリビニング後のビン幅で除算
        for i in range(bnum):
            # 加算された値があるか
            if k1[i] > 0.0:
                ##[inamura 100619]-->
                z1[i] = z1[i]/k1[i]
                e1[i] = sqrt(e1[i])/k1[i]
                #z1[i] = z1[i]/e1[i]
                #e1[i] = 1.0/sqrt(e1[i])                
                ##<--[inamura 100619]
                
            # 何も値が無ければマスク値とする
            else:
                z1[i] = MASKVALUE 
                e1[i] = 0.0

        # リビニング後のデータに入れ替え
        #print "-----------------"
        #print self.bins[59],self.bins[60],self.bins[61],self.bins[62],self.bins[63]
        #print bins1[59], bins1[60], bins1[61], bins1[62], bins1[63]
        #print self.counts[59],self.counts[60],self.counts[61],self.counts[62]
        #print z1[59],z1[60],z1[61],z1[62]
        #print k1[59],k1[60],k1[61],k1[62]
        self.bins = bins1
        self.counts = z1
        self.errs = e1
        ##[inamura 100726]-->
        self.numInteg = zeros(len(self.counts),int) 
        for i in range(len(self.counts)):
            if self.counts[i] < MASKVALUE:
                self.numInteg[i] = 1
        ##<--[inamura 100726]

#######################################
#  MapObje
#######################################  
class MapObj(object):
    
    """
    データハンドリングクラス
    """

    #########################################
    def __init__(self, data, order):
        """
        データを読み込み、カラーコンツァーマップを作成
        @param  data  データオブジェクト
        @param  order  イベントディスパッチャのID
        @retval 無し
        """ 
        # 初期化
        self.X = self.Y = None
        self.qArray = None
        self.arData = None
        self.erData = None
        self.mclip = None  # ElementContainerMatrixArray ## [KCS 130520]
        self.zRange = (0.0, 1.0, 0.005)
        self.type = 0   #  0: 直交 1: 斜交
        self.xylabels = ["*","*"] ##[inamura 170118]
        
        # プロパティ管理クラスのインスタンスを取得
        self.ifi = IFEvtProp(order)
        
        # 公開プロパティを登録
        self.ifi.AddProperty('grid',       lambda : (self.X, self.Y))
        self.ifi.AddProperty('mapdata',    lambda : self.arData)
        self.ifi.AddProperty('erdata',    lambda : self.erData)
        self.ifi.AddProperty('zrange',     lambda : self.zRange)
        self.ifi.AddProperty('qlist',     lambda : self.qList)
        self.ifi.AddProperty('mclip',     lambda : self.mclip) ## [KCS 130520]
        # データが指定されていれば
        if data != None:
            # データを読み込み
            self.ChangeData(data)

    ## [KCS 130520]-->
    ###################################################             
    def GetZValue(self, xdata, ydata):
        """
        マウス位置の強度取得
        @param  xdata (float) マウス位置の x値
        @param  ydata (float) マウス位置の y値
        @retval 無し
        """ 
        xnum = len(self.X[0])
        ynum = len(self.Y)
        
        # データの無い領域であれば
        if ydata < self.Y.min() or ydata > self.Y.max():
            return None
        
        # yインデックス取得
        for yy in range(ynum):
            if ydata < self.Y[yy,0]:
                break
        yy = yy-1
        
        # データの無い領域であれば
        if xdata < self.X[yy,0] or xdata > self.X[yy,xnum-1]:
            return None
        
        # xインデックス取得
        for xx in range(xnum):
            if xdata < self.X[yy,xx]:
                break
        zint = self.arData[yy,xx-1]
        
        # マスクデータか
        if zint >= MASKVALUE-1.0:
            return None
        
        return zint
    ##<-- [KCS 130520]
    
    ###################################################             
    def ChangeData(self, data):
        """
        データ変更イベント処理
        @param  data データオブジェクト
        @retval 無し
        """
        ## [inamura 150515]-->
        KEY_ISHIST = "isHistogram"
        if isinstance( data, mm.ElementContainerMatrix ):
            isHist = True
            hh_data=  data.PutHeaderPointer()
            if (hh_data.CheckKey(KEY_ISHIST)==1) and (hh_data.PutInt4(KEY_ISHIST)==0): # isHistogram is existed and is 0
                isHist=False
            
            for i in range( data.PutSize() ):
                eca = data(i)
                hh_eca = eca.PutHeaderPointer()
                if (hh_eca.CheckKey(KEY_ISHIST)==1) and (hh_eca.PutInt4(KEY_ISHIST)==0):
                    isHist = False
                
                for j in range( eca.PutSize() ):
                    ec = eca(j)
                    hh_ec = ec.PutHeaderPointer()
                    if (hh_ec.CheckKey(KEY_ISHIST)==1) and (hh_ec.PutInt4(KEY_ISHIST)==0):
                        continue
                    elif not isHist:
                        continue
                    elif (hh_ec.CheckKey(KEY_ISHIST)==0) or ( (hh_ec.CheckKey(KEY_ISHIST)==1) and (hh_ec.PutInt4(KEY_ISHIST)==1) ):
                        tt = mu.HistogramBinToPoint(ec)
                        xkey=ec.PutXKey()
                        ykey=ec.PutYKey()
                        ekey=ec.PutEKey()
                        ec.Replace( ykey, tt.PutY() )
                        ec.Replace( ekey, tt.PutE() )
                        ec.SetKeys( xkey, ykey, ekey )
                        if (hh_ec.CheckKey(KEY_ISHIST)==1):
                            hh_ec.OverWrite( KEY_ISHIST, 0 )
                        else:
                            hh_ec.Add( KEY_ISHIST, 0 )
                        del tt
        elif isinstance( data, mm.ElementContainerArray ):
            isHist = True
            hh_data=  data.PutHeaderPointer()
            if (hh_data.CheckKey(KEY_ISHIST)==1) and (hh_data.PutInt4(KEY_ISHIST)==0): # isHistogram is existed and is 0
                isHist=False
            
            for i in range( data.PutSize() ):
                ec = data(i)
                hh_ec = ec.PutHeaderPointer()
                if (hh_ec.CheckKey(KEY_ISHIST)==1) and (hh_ec.PutInt4(KEY_ISHIST)==0):
                    continue
                elif not isHist:
                    continue
                elif (hh_ec.CheckKey(KEY_ISHIST)==0) or ( (hh_ec.CheckKey(KEY_ISHIST)==1) and (hh_ec.PutInt4(KEY_ISHIST)==1) ):
                    tt = mu.HistogramBinToPoint(ec)
                    xkey=ec.PutXKey()
                    ykey=ec.PutYKey()
                    ekey=ec.PutEKey()
                    ec.Replace( ykey, tt.PutY() )
                    ec.Replace( ekey, tt.PutE() )
                    ec.SetKeys( xkey, ykey, ekey )
                    if (hh_ec.CheckKey(KEY_ISHIST)==1):
                        hh_ec.OverWrite( KEY_ISHIST, 0 )
                    else:
                        hh_ec.Add( KEY_ISHIST, 0 )
                    del tt
        ##<-- [inamura 150515]
        
        ## [KCS 130520]-->
        self.mclip = None
        if type(data)==type(mm.ElementContainerMatrix()):
            # Matrix であれば、最初のArray を取得
            self.mclip =  mc.M2Clip(data)
            ec = data(0,0)
        elif type(data)==type(mm.ElementContainerArray()):
            self.mclip =  mc.M2Clip(data)
            ec = data(0)
        # Map データでなければ
        if self.mclip != None:
            # 正しいデータか
            if self.mclip.IsInvalid():
                self.mclip = None
                return 
            # Map データに変換
            dm = D2Matrix()
            data = dm.ReadMatrix(data)
        ## <--[KCS 130520]
        
        # データを格納
        self.arData = data[0]
        self.erData = data[1]
        self.X = data[2]
        self.Y = data[3]
        try:
            self.type = data[4]
        except:
            # タイプの指定が無ければ直交データ
            self.type = 0
        
        # マスク値を除く最大値を検索
        self.maxCount = 0.0
        for i in range(len(self.arData)):
            for j in range(len(self.arData[0])):
                if self.arData[i][j] < MASKVALUE-1.0:
                    if self.arData[i][j] > self.maxCount :
                        self.maxCount = self.arData[i][j]
        self.numBins = len(self.X)       
        
        # データの属性を取得
        self.GetZRange()
        # Q代表値値のリストを作成
        qnum = len(self.X[0])-1
        self.qArray = zeros(qnum, float64)
        qg = (self.X.max()-self.X.min()) / qnum
        qvalue = self.X.min() + qg/2.0
        
        for i in range(qnum):
            self.qArray[i] = qvalue
            qvalue += qg

    #########################################    
    def GetZRange(self):
        """
        データの最小値と最大値、オフセット値を返す
        (ログモードでは、0ゃ負値を扱えないため)
        @param  無し
        @retval 最小値、最大値、オフセット値のタプル
        """ 
        # オフセットは、最大値の1/1000
        offset = self.maxCount / 1000.0
        # オフセットは、0.05 より大きくしない
        if offset > 0.05:
            offset = 0.05

        offset = 1.0E-25 #[inamura 100618]
        self.zRange =  (self.arData.min(), self.maxCount,offset)
        

    #########################################
    def GetHistX(self, eslice):
        """
        指定されたY値におけるヒストグラムを取得
        @param  eslice ( Y中央値、Y始値、Y終値) のタプル 
        @retval ヒストグラムオブジェクト
        """
        # 始値 <= 中央値 <= 終値 であること
        if eslice[1] > eslice[0] or eslice[0] > eslice[2]:
            #raise PlotException('Common', 'C001', ("GetHistX", "Index"))
            return
        # ebin の数
        nY = len(self.Y)-1
        # 範囲チェック
        if eslice[1] > self.Y[nY,0] or eslice[2] < self.Y[0,0]:
            #raise PlotException('Common', 'C001', ("GetHistX", "Index"))
            return
        ## [KCS 130520]-->
        # ElementContainerMatrixArrayがあれば
        if self.mclip != None:  
            self.mclip.ClearClipRegion()
            # 水平方向に積算
            self.mclip.SetAxis(1)
            #self.mclip.SetClipRegion(self.X.min(), eslice[0], self.X.max(),eslice[2])
            self.mclip.SetClipRegion(self.X.min(), eslice[1], self.X.max(),eslice[2]) ##[inamura 140605]
            # 積算実行
            self.mclip.ExecClip()
            ec = self.mclip.GetEC(0)
            
            # リビニング用のビン値が指定されているか
            if eslice[3] > 0.0:
                ec = self._ReBinEC(eslice[3],ec)
            #<-- 2013.06.25 Bug Fix KCS    
            #return HistObj(ec.PutXList(), array(ec.PutYList()), ec.PutEList(),eslice[0],eslice[1],eslice[2])
            return HistObj(ec.PutXList(), array(ec.PutYList()), ec.PutEList(),eslice[1],eslice[0],eslice[2])
            #--> 2013.06.25 Bug Fix KCS  
            ##<-- [KCS 130520]
        
        m0 =  mp = -1
        
        # 始値、中央値、終値に相当するデータを探索
        for i in range(nY):
            # 始値を超えたか
            if self.Y[i,0] > eslice[1]:
                # 最初か
                if m0 < 0:
                    # 四捨五入により、近い方のインデックスを始値として保存
                    if i> 0 and (self.Y[i,0]-eslice[1]) > (eslice[1]- self.Y[i-1,0]):
                        m0 = i-1
                    else:
                        m0 = i
            # 中央値を超えたか        
            if self.Y[i,0] > eslice[0]:
                # 最初か
                if mp < 0:
                    # 四捨五入により、近い方のインデックスを中央値として保存
                    if i> 0 and (self.Y[i,0]-eslice[0]) > (eslice[0]- self.Y[i-1,0]):
                        mp = i-1
                    else:
                        mp = i                    
            # 終値を超えたか
            if self.Y[i,0] > eslice[2]:
                break
        # 四捨五入により、近い方のインデックスを終値として保存
        if i> 0 and (self.Y[i,0]-eslice[2]) > (eslice[2]- self.Y[i-1,0]):
            m1 = i-1
        else:
            m1 = i

        if m0 < 0:
            m0 = m1
        if mp < 0:
            mp = m1
            
        # 中央値のビン値列を取得
        ebin =  self.X[mp,:] 
        zp = self.arData[mp,:].copy()
        ep = self.erData[mp,:].copy()
        # ヒストグラムインスタンスを作る
        ecenter = HistObj(ebin, zp, ep,self.Y[m0,0],self.Y[mp,0],self.Y[m1,0] )
        
        # リビニングのビン値が指定されているか
        if eslice[3] > 0.0:
            # リビニングする
            self.InciceDat(eslice[3], ecenter)
            
        # 始値= 終値 なら積算無し 
        if m0 == m1:
            return ecenter
        
        # マスク場所特定用にカウント値を保存
        #counts = ecenter.counts[:] 2009.12.25 Minakawa 削除
        
        # 始値から終値まで、再構成しながらZ値を平均
        mi = m0
        while mi <= m1:
            # 中央値でなければ
            if mi != mp:
                # ヒストグラムのカウント数を取得
                z0 = self.arData[mi,:].copy()
                er0 = self.erData[mi,:].copy()
                # ビン値配列取得
                ebin0 = self.X[mi,:]
                # ヒストグラム作成　
                edat = HistObj(ebin0, z0, er0)
                # リビニングのビン値が指定されているか
                if eslice[3] > 0.0:
                    # 指定されたビン値でリビニング
                    self.InciceDat(eslice[3], edat)
                # 斜方形であれば 
                
                if self.type == 1:
                    # 中央値のビンに合わせてリビニング
                    edat.ReBin(ecenter.bins)

                # 加算
                ecenter.AddData(edat)

            mi += 1
            
        # 積算回数で割る
        #ecenter.DevidData(m1-m0+1)
        ecenter.DevidInteg()
        
        # 中央値のMASKVALUEと同じ位置にMASKVALUE を入れる　2009.12.25 Minakawa 削除
        #for i in range(len(counts)):
        #    if counts[i] >= MASKVALUE-1.0:
        #        ecenter.counts[i]= MASKVALUE
        #        ecenter.errs[i]= 0.0
        return ecenter     

    #########################################
    def _ReBinEC(self, bin0,ec) :
        """
        ElementContainerのリビニングを行う
        @param  bin0    刻み
        @param  ec (ElementContainer)   ヒストグラムデータクラスのインスタンス
        @retval (ElementContainer) リビニング後のデータ
        """ 
        xx = ec.PutXList()
        min0 = xx[0]
        max0 = xx[len(xx)-1]
        # リビニング後のビン配列を作る
        r_min = bin0/2.0
        if r_min<=min0:  ##[inamura 140901] fixed min->min0
            while( (r_min+bin0)<min0 ):
                r_min += bin0
        else:
            while( r_min>min0 ): ##[inamura 140901] fixed min->min0
                r_min -= bin0
        
        bins1 = arange( r_min, max0+bin0, bin0 )
        # ベクターに変換
        vecBin = mm.ListToDoubleVector(bins1)
        # リビニング
        #return  ec.ReBin(vecBin)
        return  ec.Averaging(vecBin) ##[inamura 140901]
    
    #########################################
    def InciceDat(self, bin,data) :
        """
        刻み直し
        @param  bin    刻み
        @param  data   ヒストグラムデータクラスのインスタンス
        @retval 無し
        """
        min = data.bins[0]
        max = data.bins[len(data.bins)-1]

        # リビニング後のビン配列を作る
        ##[inamura 100619]-->
        r_min = bin/2.0
        if r_min<=min:
            while( (r_min+bin)<min ):
                r_min += bin
        else:
            while( r_min>min ):
                r_min -= bin
        
        bins1 = arange( r_min, max+bin, bin )
        #bins1 = arange(min, max+bin, bin)
        ##<--[inamura 100619]
        # リビニング
        data.ReBin(bins1)

    
    #########################################
    def GetHistY(self, qslice):
        """
        指定されたX値におけるヒストグラムを取得
        @param  qslice  X中央値、X始値、X終値のタプル 
        @retval ヒストグラムオブジェクト
        """ 
        
        # 始値 <= 中央値 <= 終値 であること
        if qslice[1] > qslice[0] or qslice[0] > qslice[2]:
            #raise PlotException('Common', 'C001', ("GetHistY", "Index"))
            return
        # qbin の数
        nX = len(self.qArray)
        # 範囲チェック
        if qslice[1] < self.X.min() or qslice[2] > self.X.max():
            #raise PlotException('Common', 'C001', ("GetHistY", "Index"))
            return
        ## [KCS 130520]-->
        # ElementContainerMatrixArrayがあれば
        if self.mclip != None:  
            self.mclip.ClearClipRegion()
            
            # TOFまたはEnergyをX軸としてに積算
            self.mclip.SetAxis(0)
            #self.mclip.SetClipRegion(qslice[0], self.Y.min(), qslice[2], self.Y.max())
            self.mclip.SetClipRegion(qslice[1], self.Y.min(), qslice[2], self.Y.max()) ##[inamura 140605]
            # 積算実行
            self.mclip.ExecClip()
            ec = self.mclip.GetEC(0)
            
            # リビニング用のビン値が指定されているか
            if qslice[3] > 0.0:
                ec = self._ReBinEC(qslice[3],ec)
            #<-- 2013.06.25 Bug Fix KCS
            #return HistObj(ec.PutXList(), array(ec.PutYList()), ec.PutEList(),qslice[0],qslice[1],qslice[2])    
            return HistObj(ec.PutXList(), array(ec.PutYList()), ec.PutEList(),qslice[1],qslice[0],qslice[2])
            #--> 2013.06.25 Bug Fix KCS
            ##<-- [KCS 130520]
        m0 = mp = -1
        
        # 始値、中央値、終値に相当するインデックスを探索
        for i in range(nX):

            # 始値を超えたか
            if self.qArray[i] > qslice[1]:
                # 最初か
                if m0 < 0 :
                    # 四捨五入により、近い方のインデックスを始値として保存
                    m0 = self._hAdjast(i, qslice[1])
            # 中央値を超えたか        
            if self.qArray[i] > qslice[0]:
                # 最初か
                if mp < 0:
                    # 四捨五入により、近い方のインデックスを 中央値として保存
                    mp = self._hAdjast(i, qslice[0])
                    
            # 終値を超えたか
            if self.qArray[i] > qslice[2]:
                break
        # 四捨五入により、近い方のインデックスを終値として保存
        m1 = self._hAdjast(i, qslice[2])
            
        if m0 < 0:
            m0 = m1
        if mp < 0:
            mp = m1
        # 中央値のQビン値列とカウント数列を取得
        qcenter = self._GetQSlice(mp)
        qcenter.fp = self.qArray[m0]
        qcenter.mp = self.qArray[mp]
        qcenter.ep = self.qArray[m1]

        # ビン値が指定されているか
        if qslice[3] > 0.0:
            # リビニングする
            self.InciceDat(qslice[3], qcenter)
            
        # 始値= 終値 なら積算無し 
        if m0 == m1:
            return qcenter 
        
        # マスク場所特定用にカウント値を保存
        # リビニングアルゴリズムの変更に伴い削除　2009.11.25 Minakawa
        # counts = qcenter.counts[:]
        
        # 始値から終値まで、再構成しながらZ値を平均
        mi = m0
        while mi <= m1:
            # 中央値でなければ
            if mi != mp:
                # ヒストグラム取得
                qdat = self._GetQSlice(mi)

                # リビニング用のビン値が指定されているか
                if qslice[3] > 0.0:
                    # 指定されたビン値でリビニング
                    self.InciceDat(qslice[3], qdat)
                # 斜方形であれば    
                if self.type == 1:
                    # 中央値のビンに合わせてリビニング
                    qdat.ReBin(qcenter.bins)
                # 加算
                qcenter.AddData(qdat)
            mi += 1
                
        # 積算回数で割る
        qcenter.DevidInteg()
        
        # 中央値のMASKVALUEと同じ位置にMASKVALUE を入れる
        # リビニングアルゴリズムの変更に伴い削除　2009.11.25 Minakawa
        #for i in range(len(counts)):
        #    if counts[i] >= MASKVALUE-1.0:
        #        qcenter.counts[i]= MASKVALUE
        #        qcenter.errs[i]= 0.0
        
        #print "GetYHist: qcenter.bins=",qcenter.bins ##[inamura 100726]
        return qcenter     
    
    #########################################
    def _hAdjast(self, qi, qvalue):
        """
        四捨五入して、近いほうのインデックスを返す
        @param  qi       Q値インデックス
        @param  qvalue   比較対照のQ値
        @retval Q値インデックス
        """ 
        # 初期値であれば
        if qi == 0:
            return qi
        # どちらが近いか
        if (self.qArray[qi]-qvalue) > (qvalue- self.qArray[qi-1]):
            return qi-1
        else:
            return qi
            
    #########################################
    def _GetQSlice(self, qindex):
        """
        Q値の等しい点におけるヒストグラムを取得
        @param  qindex   Q値のインデックス
        @retval ヒストグラムインスタンス
        """ 
        # 直交データか
        if self.type == 0:
            # ビン値列を取得
            qbin =  self.Y[:,qindex] 
            zp = self.arData[:, qindex].copy()
            erp = self.erData[:,qindex].copy()
            # ヒストグラムインスタンスを作る
            return HistObj(qbin, zp, erp)
        
        zz = []
        qq = []
        er = []

        # 探索終了点

        endJ = len(self.qArray)

        j = 0
        ii = 0
        bj = 0
        qvalue = self.qArray[qindex]
        
        # エネルギー列毎に求める    
        for i in range(len(self.Y)):
            # データの無い領域か
            if self.X[i,0] > qvalue:
                zz.append(MASKVALUE)
                er.append(0)
                qq.append(self.Y[i,j])
                
            else:
                # Q値を超える点を探索
                while j <= endJ:
                    if self.X[i,j] > qvalue:
                        ii = i
                        # 最初のデータを除き
                        if i == 0:
                            bj = j
                        # 前のデータとインデックスが変わっていたなら、Qラインと交わっている
                        elif not bj == j:
                             # 前のデータを、カウント数を面積比で重み付き平均した値と入れ替える
                             zz[i-1],er[i-1]  = self._WeightingAverage(qvalue, i-1, j, bj)
                             #変わったインデックスを保存         
                             bj = j
                        j = j-1  
                        # 最後のデータか
                        if i == self.numBins-1:
                             break
                        # データ追加
                        else:
                            zz.append(self.arData[i,j])
                            er.append(self.erData[i,j])
                            qq.append(self.Y[i,j])
                            j = j -1
                        break
                    j +=1
                if j > endJ:
                    j = 0
                    zz.append(MASKVALUE)
                    er.append(0)
                    qq.append(self.Y[i,j])
                if j < 0:
                    j = 0    
        # 最後のbin値を追加
        ##[inamura 100712]-->
        if ii < i:
            #qq.append(self.Y[ii+1,j-1])
            c_i = i
            while(True):
                if zz[c_i]==MASKVALUE:
                    zz = zz[:-1]
                    er = er[:-1]
                    qq = qq[:-1]
                    c_i -= 1
                else:
                    qq.append(self.Y[c_i+1,j-1])
                    break
        else:    
            #qq.append(self.Y[ii,j-1])
            qq.append(self.Y[i,j-1])
        
        #qq.append(self.Y[i-1,j-1])
        #print " GetQSlice: ii,i = ",ii,i
        #print " GetQSlice: len(self.Y),len(self.arData),len(self.Y[0]),len(self.arData[0])=",len(self.Y),len(self.arData),len(self.Y[0]),len(self.arData[0])
        #print " GetQSlice: len(qq),len(zz),=",len(qq),len(zz)
        #print "_GetQSlice: qq=",qq,zz
        ##<--[inamura 100712]
        return HistObj(array(qq),array(zz), array(er))

    #########################################
    def _WeightingAverage(self, qx, ii,jj, bjj):
        """
        2個のカウント数が同一Q値上にあるとき、カウント数を面積比で比例配分
        隣接する四角形の面積はほぼ等しいことから、
        面積比を三角形の底辺の長さ比で代替
        @param  qx       Q値
        @param  ii      エネルギー配列のインデックス
        @param  jj      Q値配列のインデックス
        @param  bjj     1個前のQ値配列のインデックス
        @retval 比例配分後のカウント数
        """ 
        if bjj == 0:
            c1 = MASKVALUE
            er1 = 0
        else:
            c1 = self.arData[ii,bjj-1]
            er1 = self.erData[ii,bjj-1]
        c2 = self.arData[ii,jj-1]
        er2 = self.erData[ii,jj-1]
        
        # どちらもマスク値なら
        if c1 >= MASKVALUE-1.0 and c2 >= MASKVALUE-1.0:
            # 入れ替え無し
            return (c1, er1)

        if bjj < jj:
            # 指定されたQ値と交差するグリッド直線の座標を取得
            x0 = self.X[ii, bjj]
            x1 = self.X[ii+1, bjj]
            # X 値が同じであれば
            if x1 == qx :
                # 入れ替え無し
                return (c1, er1)
        else:
            # 指定されたQ値と交差するグリッド直線の座標を取得
            x0 = self.X[ii, jj]
            x1 = self.X[ii+1, jj]
            # X 値が同じであれば
            if x1 == qx :
                # 入れ替え
                return (c2, er2)
        # グリッド直線と x = qx の直線との交点の長さ
        xp1 = (qx - x0)/(x1-x0)
        xp2 = (x1 - qx)/(x1-x0)
        # 前の値がマスク値であれば
        if c1 >= MASKVALUE-1.0:
            counts = c2
            k = 1.0/xp2
            err = er2*er2*k*k
        elif c2 >= MASKVALUE-1.0:
            counts = c1
            k = 1.0/xp1
            err = er1*er1*k*k
        else:    
            # 2個のカウント数を三角形の底辺の長さ比で重み付き平均する
            counts = c1*xp1 + c2*xp2
            err = er1*er1*xp1*xp1+er2*er2*xp2*xp2
        return (counts, sqrt(err))

    ##[inamura 101214]-->
    #########################################
    def MakeMeshList(self,dQ=0.0):
        """
        Make Mesh data using GetHistX
        @param dQ (double) bin width of Q
        @return None
        """
        elastic = self.GetHistX( (0.0,0.0,0.0,dQ) )
        num_Xbin = len(elastic.bins)-1
        delta_Xbin = (elastic.bins[num_Xbin]-elastic.bins[0])/num_Xbin

        #print elastic.bins
        #print "deltaXbin=",delta_Xbin
        
        Ybin = []
        num_Ybin = len(self.Y)-1
        for i in range(num_Ybin):
            Ybin.append( (self.Y[i,0]+self.Y[i+1,0])/2.0 )

        ##[inamura 160603]-->
        ybin_min = min(Ybin)
        ybin_max = max(Ybin)
        xhist_ymin = self.GetHistX( (ybin_min,ybin_min,ybin_min,dQ) )
        xhist_ymax = self.GetHistX( (ybin_max,ybin_max,ybin_max,dQ) )
        edge_list = []
        edge_list.append( min(xhist_ymin.bins) )
        edge_list.append( max(xhist_ymin.bins) )
        edge_list.append( min(xhist_ymax.bins) )
        edge_list.append( max(xhist_ymax.bins) )
        edge_list.append( min(elastic.bins) )
        edge_list.append( max(elastic.bins) )
        xbin_min = min( edge_list )
        xbin_max = max( edge_list )
        
        mesh_xbins = elastic.bins[:]
        if (xbin_min<mesh_xbins[0]):
            dbin=mesh_xbins[1]-mesh_xbins[0]
            new_bins=[]
            val = mesh_xbins[0]-dbin
            while(val>xbin_min):
                new_bins.append( val )
                val -= dbin
            new_bins.reverse()
            new_bins.extend( mesh_xbins )
            mesh_xbins = new_bins[:]
        if (xbin_max>mesh_xbins[-1]):
            dbin=mesh_xbins[-1]-mesh_xbins[-2]
            new_bins=[]
            val = mesh_xbins[-1]+dbin
            while(val<xbin_max):
                new_bins.append( val )
                val += dbin
            #[inamura 160803]-->
            #mesh_xbins.extend( new_bins )
            if isinstance( mesh_xbins, list ):
                mesh_xbins.extend( new_bins )
            else:
                tmp = mesh_xbins.tolist()
                tmp.extend( new_bins )
                mesh_xbins = array(tmp)
            #<--[inamura 160803]
        
        XX = []
        YY = []
        II = []
        EE = []
        #print "new_bins=",mesh_xbins
        for y in Ybin:
            sl = self.GetHistX( (y,y,y,0.0) )
            #print "y=",y
            #print sl.bins
            sl.ReBin( mesh_xbins )
            for i in range( len(mesh_xbins)-1 ):
                XX.append( (mesh_xbins[i]+mesh_xbins[i+1])/2.0 )
                YY.append( y )
                II.append( sl.counts[i] )
                EE.append( sl.errs[i] )

        """
        XX = []
        YY = []
        II = []
        EE = []
        for y in Ybin:
            sl = self.GetHistX( (y,y,y,0.0) )
            sl.ReBin( elastic.bins )
            for i in range( len(elastic.bins)-1 ):
                XX.append( (elastic.bins[i]+elastic.bins[i+1])/2.0 )
                YY.append( y )
                II.append( sl.counts[i] )
                EE.append( sl.errs[i] )
        """
        ##<--[inamura 160603]
        return (XX,YY,II,EE)
        
    #########################################
    def SaveAsText(self,filename,dQ=0.0):
        """
        Make mesh data and save data as text file
        @param filename (string) File name
        @param dQ (double) bin width of Q
        @return None
        """
        try:
            fd = open( filename,'w' )
        except:
            raise

        ##[inamura 121104]->
        fd.write("## X,Y,Intensity,Error \n")
        ##[inamura 140821]->
        xmin=(self.X[0][0]+self.X[0][1])/2.0
        xmax=(self.X[0][-2]+self.X[0][-1])/2.0
        xbin=self.X[0][1]-self.X[0][0]
        ymin=(self.Y[0][0]+self.Y[1][0])/2.0
        ymax=(self.Y[-2][0]+self.Y[-1][0])/2.0
        ybin=self.Y[1][0]-self.Y[0][0]
        xrange_text="## XRANGE=%f,%f,%f \n"%(xmin,xmax,xbin)
        yrange_text="## YRANGE=%f,%f,%f \n"%(ymin,ymax,ybin)
        fd.write(xrange_text)
        fd.write(yrange_text)
        ##<--[inamura 140821]
        if self.type==0:
            for i in range( len(self.arData) ):
                for j in range( len(self.arData[i]) ):
                    ##[inamura 130624]-->
                    XX=(self.X[i+1][j+1]+self.X[i][j])/2.0
                    YY=(self.Y[i+1][j+1]+self.Y[i][j])/2.0
                    II=0.0
                    EE=0.0
                    if self.arData[i][j] < MASKVALUE-1.0:
                        II=self.arData[i][j]
                        EE=self.erData[i][j]
                    fd.write( "%f, %f, %f, %f\n" % (XX,YY,II,EE) )
                    #if self.arData[i][j] < MASKVALUE-1.0:
                    #    tmp = (self.X[i][j],self.Y[i][j],self.arData[i][j],self.erData[i][j] )
                    #else:
                    #    tmp = (self.X[i][j],self.Y[i][j],0.0,0.0)
                    #
                    #fd.write( "%f, %f, %f, %f\n" % (tmp) )
                    ##<--[inamura 130624]
        else:
            (XX,YY,II,EE) = self.MakeMeshList( dQ )
            
            for (xx,yy,ii,ee) in zip(XX,YY,II,EE):
                if ii<MASKVALUE:
                    fd.write( "%f, %f, %f, %f\n" % (xx,yy,ii,ee) )
        ##<--[inamura 121104]
        
        fd.close()
        
    ##<--[inamura 101214]
    ##[inamura 160218]-->
    #########################################
    def SaveAsText2(self,filename,dQ=0.0,isIgnoreMask=True,maskinfo=[False,0.0]):
        """
        Make mesh data and save data as text file
        @param filename (string) File name
        @param dQ (double) bin width of Q
        @param isIgnoreMask (bool) True: ignore data with MASKVALUE
        @param maskinfo (list) [bool,double]=[ use given mask value or not, mask value ]
        @return None
        """
        try:
            fd = open( filename,'w' )
        except:
            raise

        fd.write("## X,Y,Intensity,Error \n")
        if self.type==0:
            xmin=(self.X[0][0]+self.X[0][1])/2.0
            xmax=(self.X[0][-2]+self.X[0][-1])/2.0
            xbin=self.X[0][1]-self.X[0][0]
            ymin=(self.Y[0][0]+self.Y[1][0])/2.0
            ymax=(self.Y[-2][0]+self.Y[-1][0])/2.0
            ybin=self.Y[1][0]-self.Y[0][0]
            xrange_text="## XRANGE=%f,%f,%f \n"%(xmin,xmax,xbin)
            yrange_text="## YRANGE=%f,%f,%f \n"%(ymin,ymax,ybin)

            fd.write(xrange_text)
            fd.write(yrange_text)
            ##[inamura 170118]-->
            xlabel_text="## XLABEL=%s\n"%(self.ifi.GetProperty('xlabel'))
            ylabel_text="## YLABEL=%s\n"%(self.ifi.GetProperty('ylabel'))
            fd.write(xlabel_text)
            fd.write(ylabel_text)
            ##<--[inamura 170118]
            for i in range( len(self.arData) ):
                for j in range( len(self.arData[i]) ):
                    XX=(self.X[i+1][j+1]+self.X[i][j])/2.0
                    YY=(self.Y[i+1][j+1]+self.Y[i][j])/2.0
                    II=0.0
                    EE=0.0
                    if self.arData[i][j] < MASKVALUE-1.0:
                        II=self.arData[i][j]
                        EE=self.erData[i][j]
                        fd.write( "%g, %g, %g, %g\n" % (XX,YY,II,EE) )
                    elif isIgnoreMask:
                        continue
                    else:
                        if maskinfo[0]:
                            II=maskinfo[1]
                            EE=0.0
                        else:
                            II=self.arData[i][j]
                            EE=self.erData[i][j]
                        fd.write( "%g, %g, %g, %g\n" % (XX,YY,II,EE) )
                    
        else:
            (XX,YY,II,EE) = self.MakeMeshList( dQ )
            
            ind=0
            ybin=0.0
            while(True):
                if YY[ind]!=YY[ind+1]:
                    ybin=YY[ind+1]-YY[ind]
                    break
                else:
                    ind+=1
                    if ind==(len(YY)-1):
                        return
            
            xrange_text="## XRANGE=%g,%g,%g \n"%(min(XX),max(XX),dQ)
            yrange_text="## YRANGE=%g,%g,%g \n"%(min(YY),max(YY),ybin)
            fd.write(xrange_text)
            fd.write(yrange_text)
            
            for (xx,yy,ii,ee) in zip(XX,YY,II,EE):
                if ii<MASKVALUE:
                    fd.write( "%g, %g, %g, %g\n" % (xx,yy,ii,ee) )
                elif isIgnoreMask:
                    continue
                else:
                    if maskinfo[0]:
                        fd.write( "%g, %g, %g, %g\n" % (xx,yy,maskinfo[1],0.0) )
                    else:
                        fd.write( "%g, %g, %g, %g\n" % (xx,yy,ii,ee) )
        
        fd.close()
        
    ##<--[inamura 160218]
    ##[inamura 140821]-->
    #########################################
    def LoadDataFromText(self,filename):
        """
        Load mesh data from text file
        @param filename (string) File name
        @return None
        """
        try:
            fd = open( filename,'r' )
        except:
            raise
        
        x_range_list = []
        y_range_list = []
        XX=[]
        YY=[]
        II=[]
        EE=[]
        while(True):
            tmp = fd.readline()
            if tmp=="":
                break
            if tmp.find("##")!=-1:
                if tmp.find("XRANGE")!=-1:
                    tmp2=tmp.split("=")
                    x_range_list_s = tmp2[1].split(",")
                    if len(x_range_list_s)!=3:
                        raise
                    x_range_list = []
                    for a_val in x_range_list_s:
                        x_range_list.append( float(a_val) )
                        
                if tmp.find("YRANGE")!=-1:
                    tmp2=tmp.split("=")
                    y_range_list_s = tmp2[1].split(",")
                    if len(y_range_list_s)!=3:
                        raise
                    y_range_list = []
                    for a_val in y_range_list_s:
                        y_range_list.append( float(a_val) )
                ##[inamura 170118]-->
                if tmp.find("XLABEL")!=-1:
                    try:
                        tmp2 = tmp.split("=")
                        self.xylabels[0] = tmp2[1]
                    except:
                        print "XLABEL is invalid"
                if tmp.find("YLABEL")!=-1:
                    try:
                        tmp2 = tmp.split("=")
                        self.xylabels[1] = tmp2[1]
                    except:
                        print "YLABEL is invalid"
                ##<--[inamura 170118]
            else:
               # tmp = tmp[:-1]
                tmp = tmp.strip()
                if tmp!="":
                    val_list_s = tmp.split(",")
                    if len(val_list_s)!=4:
                        print "Read Error : line=",tmp
                    else:
                        XX.append( float( val_list_s[0] ) )
                        YY.append( float( val_list_s[1] ) )
                        II.append( float( val_list_s[2] ) )
                        EE.append( float( val_list_s[3] ) )
        
        fd.close()

        ##[inamura 170726]-->
        #if x_range_list==[] or y_range_list==[]:
        #    raise

        #print "x_range_list = %f, %f, %f"%(x_range_list[0],x_range_list[1],x_range_list[2])
        #print "y_range_list = %f, %f, %f"%(y_range_list[0],y_range_list[1],y_range_list[2])
        #XX_list = arange( x_range_list[0]-(x_range_list[2]/2.0), x_range_list[1]+x_range_list[2], x_range_list[2] )
        #YY_list = arange( y_range_list[0]-(y_range_list[2]/2.0), y_range_list[1]+y_range_list[2], y_range_list[2] )
        XX_list = []
        YY_list = []
        if x_range_list==[]:
            XX_list = self._MakeAxisFromData(XX)
        else:
            XX_list = arange( x_range_list[0]-(x_range_list[2]/2.0), x_range_list[1]+x_range_list[2], x_range_list[2] )
        if y_range_list==[]:
            YY_list = self._MakeAxisFromData(YY)
        else:
            YY_list = arange( y_range_list[0]-(y_range_list[2]/2.0), y_range_list[1]+y_range_list[2], y_range_list[2] )
        ##<--[inamura 170726]
        arData = zeros([len(YY_list)-1,len(XX_list)-1],float64)
        erData = zeros([len(YY_list)-1,len(XX_list)-1],float64)
        
        for i in range( len(YY_list)-1 ):
            for j in range( len(XX_list)-1 ):
                arData[i,j] = MASKVALUE
        
        for a_x, a_y, a_i, a_e in zip( XX,YY,II,EE ):
            ##[inamura 170726]-->
            if len(x_range_list)==0:
                i_x = -1
                if a_x>XX_list[-1]:
                    continue
                for i,xx in enumerate(XX_list):
                    if a_x<=xx:
                        i_x = i-1
                        break
            else:
                i_x = int( (a_x-x_range_list[0]+(x_range_list[2]/2.0))/x_range_list[2] )
                
            if len(y_range_list)==0:
                i_y = -1
                if a_y>YY_list[-1]:
                    continue
                for i,yy in enumerate(YY_list):
                    if a_y<=yy:
                        i_y = i-1
                        break
            else:
                i_y = int( (a_y-y_range_list[0]+(y_range_list[2]/2.0))/y_range_list[2] )
            ##<--[inamura 170726]
            arData[i_y,i_x] = a_i
            erData[i_y,i_x] = a_e
        
        X, Y = meshgrid( XX_list, YY_list )
        
        #self.ChangeData((arData,erData,X,Y,0)) ##[inamura 170306]
        return (arData,erData,X,Y,0)
    ##<--[inamura 140821]
    ##[inamura 170726]-->
    #########################################
    def _MakeAxisFromData(self,orgList):
        """
        """
        VV = orgList[:]
        VV.sort()
        vv1_list = [VV[0]]
        pre_vv = VV[0]
        for vv in VV:
            if vv!=pre_vv:
                pre_vv = vv
                vv1_list.append(vv)
        vv2_list = []
        for i in range( len(vv1_list)-1 ):
            vv2_list.append( (vv1_list[i]+vv1_list[i+1])/2.0 )

        ret_list = []
        ret_list.append( vv1_list[0] - (vv2_list[0]-vv1_list[0]) )
        ret_list.extend( vv2_list )
        ret_list.append( vv1_list[-1] + (vv1_list[-1]-vv2_list[-1]) )
        
        del VV

        return ret_list
    ##<--[inamura 170726]
## [KCS 130330]-->

#############################################
# PlotTrace:
#############################################
class PlotTrace(object):
    """
    オーバープロットデータ
    """
    ####################################################
    def __init__(self, xdata, ydata, xlabel = "", ylabel = "", color = "#ffffff", draw = True, linewidth=1.0):
        """
        ##[inamura 160728]
        コンストラクタ
        @param  (array) xdata 
        @param  (array) ydata 
        @param  (string) xlabel xデータのラベル 
        @param  (string) ylabel yデータのラベル
        @param  (string) color カラーコード
        @param  (bool) draw 描画フラグ
        @retval 無し
        """
        self.xdata = xdata
        self.ydata = ydata
        self.xlabel = xlabel
        self.ylabel = ylabel
        self.color = color
        self.draw = draw
        self.linewidth = linewidth ##[inamura 160728]
  
    ####################################################
    def SetColorCode(self, color):
        """
        カラーコード設定
        @param  (string) color カラーコード
        @retval 無し
        """
        self.color = color
  
    ####################################################
    def SetDrawFlag(self, draw):
        """
        描画フラグ設定
        @param  (bool) draw 描画フラグ
        @retval 無し
        """
        self.draw = draw

    ##[inamura 160728]-->
    ####################################################
    def SetLineWidth(self, lw=1.0):
        """
        描画フラグ設定
        @param  (bool) draw 描画フラグ
        @retval 無し
        """
        self.linewidth = lw
    ##<--[inamura 160728]

#############################################
# GridOverPlot:
#############################################
class GridOverPlot(gridlib.Grid):
    """
    オーバープロットのグリッド
    """
    ####################################################
    def __init__(self, panel, funcColor, funcFlag, funcLW):
        """
        ##[inamura 160728] add funcLW
        コンストラクタ
        @param  (cont) panel グリッドを作るパネル
        @param  (func) funcColor 色変更時の再描画関数
        @param  (func) funcFlag フラグ変更時の再描画関数
        @param  (func) funcLW
        @retval 無し
        """
        self.panel = panel
        self.funcColor = funcColor
        self.funcFlag = funcFlag
        self.funcLW = funcLW ##[inamura 160728]
        
        # 空のグリッド作成
        gridlib.Grid.__init__(self, panel, -1, pos=(0, 0), size=(panel.Size))
        self.CreateGrid(0, 7) ##[inamura 160728]
        # 0列に、チェックボックス属性を設定
        attrCheck = gridlib.GridCellAttr()
        attrCheck.SetEditor(gridlib.GridCellBoolEditor())
        attrCheck.SetRenderer(gridlib.GridCellBoolRenderer())
        attrCheck.SetReadOnly(True)  #[inamura 130627]
        self.SetColAttr(0, attrCheck)
        # 行ラベル
        self.SetRowLabelSize(30)
        # 列ラベルとサイズの設定
        self.SetColLabelValue(0, 'Disp')
        self.SetColSize(0, 35)
        self.SetColLabelValue(1, 'File Name')
        self.SetColSize(1, 200)
        self.SetColLabelValue(2, 'Color')
        self.SetColSize(2, 75)
        self.SetColLabelValue(3, 'R')
        self.SetColSize(3, 30)
        self.SetColLabelValue(4, 'B')
        self.SetColSize(4, 30)
        self.SetColLabelValue(5, 'G')
        self.SetColSize(5, 30)
        self.SetColLabelValue(6, 'LW') ##[inamura 160728]
        self.SetColSize(6, 30)         ##[inamura 160728]
        
        # 色選択コンボボックスを追加
        attrChoice = gridlib.GridCellAttr()
        self.colors = ['white','black', 'blue', 'yellow', 'red', 'green','magenta' ,'cyan']
        self.colorCodes = ['ffffff', '000000','0000ff','ffff00','ff0000',
                            '008000', 'ff00ff', '00ffff']
        attrChoice.SetEditor(gridlib.GridCellChoiceEditor(choices=self.colors))
        attrChoice.SetRenderer(gridlib.GridCellEnumRenderer())
        self.SetColAttr(2, attrChoice)
        
        # ファイル名はリードオンリー
        attrReadOnly = gridlib.GridCellAttr()
        attrReadOnly.SetReadOnly(True)
        self.SetColAttr(1, attrReadOnly)
        # クリックイベントのハンドラ設定
        self.Bind(gridlib.EVT_GRID_CELL_LEFT_CLICK, self.OnClick)
        # セル変更イベントのハンドラ設定
        self.Bind(gridlib.EVT_GRID_CELL_CHANGE, self.OnChange)

        self.Bind(gridlib.EVT_GRID_EDITOR_CREATED,
              self.OnGridEditorCreated)

    ##########################################################    
    def OnGridEditorCreated(self, event):
        
        #生成されたコンボボックスにイベントハンドラを設定
        comboBox = event.GetControl() 
        comboBox.Bind(wx.EVT_COMBOBOX, self.OnComboBox)
        event.Skip() 
    
    ##########################################################    
    def OnComboBox(self, event): 
        # コンボボックスの変更を確定するために、フォーカスを移す
        self.SetGridCursor(0, 0) 
        event.Skip()   

    ####################################################
    def OnChange(self, evt):
        """
        変更のイベントハンドラ
        @param  evt イベント
        @retval 無し
        """
        # Changed LineWidth ? ##[inamura 160728]-->
        if evt.Col == 6:
            lw = float(self.GetCellValue(evt.Row, 6))
            apply(self.funcLW, (evt.Row, lw ))
            return
        ##<--[inamura 160728]
        # カラーコンボボックスの変更か
        if evt.Col == 2:
            color = self.GetCellValue(evt.Row, 2)
            # 変わった色のコードを求める
            for i in range(len(self.colors)):
                if color == self.colors[i]:
                    code = self.colorCodes[i]
                    # コードを表示
                    self.SetCellValue(evt.Row, 3, code[:2])
                    self.SetCellValue(evt.Row, 4, code[2:4])
                    self.SetCellValue(evt.Row, 5, code[4:])
        # カラーコードの変更か
        elif evt.Col>=3 and evt.Col <=5:
            hexCode = self.GetCellValue(evt.Row, evt.Col)
            try:
                try:
                    int(hexCode, 16)
                except:
                    raise PlotException('Common', 'C008', ("RBG Code","00","ff"))
            except PlotException, ex:
                PlotMessage(self.panel, ex)
                return
        code = "#"
        code += self.GetCellValue(evt.Row, 3)
        code += self.GetCellValue(evt.Row, 4)
        code += self.GetCellValue(evt.Row, 5)
        # 再描画
        apply(self.funcColor, (evt.Row, code)) 
        
    ####################################################
    def OnClick(self, evt):
        """
        １クリックでチェックボックスをOn/Off する
        @param  evt イベント
        @retval 無し
        """
        # 最初の列がクリックされたか
        if evt.Col == 0:
            # チェックボックスの状態を反転
            if self.GetCellValue(evt.Row, 0) == '1':
                self.SetCellValue(evt.Row, 0, '0')
                flag = False
            else:
                self.SetCellValue(evt.Row, 0, '1')
                flag = True
            # 再描画
            apply(self.funcFlag, (evt.Row, flag))
        evt.Skip()

    ####################################################
    def AppendFile(self, fname):
        """
        グリッドの最後に行を追加し、データを表示
        @param  (string) fname テキストファイル名
        @retval 無し
        """
        # 1行追加
        self.AppendRows(1)
        # 行数取得
        num = self.NumberRows - 1
        # １行分のデータを追加
        self.SetCellValue(num, 0, '1')
        self.SetCellValue(num, 1, fname)
        self.SetCellValue(num, 2, 'white')
        self.SetCellValue(num, 3, 'ff')
        self.SetCellValue(num, 4, 'ff')
        self.SetCellValue(num, 5, 'ff')
        self.SetCellValue(num, 6, '1.0') ##[inamura 160728]

    ####################################################
    def Remove(self):
        """
        選択行の削除
        @param  無し
        @retval [int] 削除した行のインデックスリスト
        """
        # 選択行取得
        rows = self.GetSelectedRows()
        rows.sort()
        rows.reverse()
        # 下から順番に削除
        for rowNo in rows:
            self.DeleteRows(rowNo,1,True)
    
        return rows

#########################################
#       OverPlotDialog Deffinition
#########################################  
FILE_HEADER = "**  MPLOT FILE **"
XLABEL = "X label"
YLABEL = "Y label"
    
#########################################
#       OverPlotDialog
#########################################        
class OverPlotDialog(wx.Dialog):
    """
    オーバープロットダイアログクラス
    """
    
    ##########################################################
    def __init__(self, parent, order, res):
        """
        コンストラクタ
        @param  parent   親ウィンドウのID
        @param  order    プロッタの起動順序
        @param  res  リソース
        @retval 無し
        """ 
        self.openFlag = True
        self.traces = []   # 描画データ
        self.path = os.getenv("UTSUSEMI_USR_PRIV_HOME")
        # インターフェイスクラスのインスタンスを取得
        self.ifi = IFEvtProp(order)
        # リソースよりダイアログボックスを取得して作成
        self.res = res
        self.dg = self.res.GetDialog(parent, 'DgOverPlot')
        # アイコンを設定
        self.dg.SetIcon(Images().GetMainIcon())
        
        #クローズイベント登録
        self.dg.Bind(wx.EVT_CLOSE, self.OnClose)
        #ボタンイベント登録
        self.dg.Bind(wx.EVT_BUTTON, self.OnClose, id=self.res.GetId('btClose'))
        self.dg.Bind(wx.EVT_BUTTON, self.OnAddFiles, id=self.res.GetId('btAdd'))
        self.dg.Bind(wx.EVT_BUTTON, self.OnRemove, id=self.res.GetId('btRemove'))
        
        # 空のグリッド作成
        panel = self.res.GetCtrl(self.dg, 'pnGrid')
        self.grd = GridOverPlot(panel, self.ChangeColor, self.ChangeFlag, self.ChangeLineWidth) ##[inamura 160728]
       
        self.dg.Show(True)
    
    ##########################################################
    def ChangeColor(self, raw, code):
        """
        色の変更
        @param  raw (int) 行インデックス
        @param  code (string) カラーコード
        @retval 無し
        """ 
        self.traces[raw].SetColorCode(code)
        self.ifi.NotifyEvent(self.dg,'overplot', self.traces )
        
    ##########################################################
    def ChangeFlag(self, raw, flag):
        """
        描画フラグの変更
        @param  raw (int) 行インデックス
        @param  code (string) カラーコード
        @retval 無し
        """     
        self.traces[raw].SetDrawFlag(flag)
        self.ifi.NotifyEvent(self.dg,'overplot', self.traces )
        
    #[inamura 160728]-->
    ##########################################################
    def ChangeLineWidth(self, raw, lw):
        """
        描画フラグの変更
        @param  raw (int) 行インデックス
        @param  code (string) カラーコード
        @retval 無し
        """     
        self.traces[raw].SetLineWidth(lw)
        self.ifi.NotifyEvent(self.dg,'overplot', self.traces )
    #<--[inamura 160728]
    ##########################################################
    def OnClose(self, evt):
        """
        Cancel ボタンイベント処理
        @param  evt イベント情報
        @retval 無し
        """ 
        self.dg.Hide() 
        self.openFlag = False
    
    ##########################################################
    def OnAddFiles(self, evt):
        """
        Add ボタンイベント処理
        ファイルを読み込み、グリッドに追加
        @param  evt イベント情報
        @retval 無し
        """ 
        
        # ファイルオープンダイアログ(複数ファイル選択可)
        dlg = wx.FileDialog(self.dg, 'Text File Open ...', self.path,
                            style=wx.OPEN|wx.MULTIPLE,  wildcard='Text File(*.txt)|*.txt')

        # キャンセルか
        if dlg.ShowModal() != wx.ID_OK:
            return 
        # 次回のためにディレクトリを保存
        self.path = dlg.GetDirectory()
        # ファイル複数可を取得
        paths = dlg.GetPaths()
        dlg.Destroy()
        
        # 選択されたファイルについて
        for path in paths:
            # トレースデータの読み込み
            trace = self._ReadTxtFile(path)
            # よみこめたなら
            if trace != None:
                self.traces.append(trace)
                # グリッドにファイル名を表示
                fname = os.path.basename(path)
                self.grd.AppendFile(fname)
        # データがあれば
        if len(self.traces) > 0:
            # トレース再描画
            self.ifi.NotifyEvent(self.dg,'overplot', self.traces )
    
    ##########################################################
    def _ReadTxtFile(self, path):
        """
        テキストファイル読み込み
        @param  paths (string) フルパス
        @retval ([xVzlues],[yValues])
        """  
        try:
            # 指定されたファイルを開く
            try:
                fp = codecs.open(path, 'r', "utf-8")
            except:
                raise PlotException('Common', 'C006', (path,))
            # タイトル行を読み込む
            line = fp.readline().strip()
            xlabel = ""
            ylabel = ""
            # 正しいタイトル行か
            if line != FILE_HEADER:
                try:
                    x,y = self._ReadOtherFile(fp, line)
                    plotDat = PlotTrace(x,y)
                except:
                    raise PlotException('Common', 'C015', (path,))
            else:
                # データ読み込み
                x,y, xlabel, ylabel = self._ReadMPlotFile(fp)
                plotDat = PlotTrace(x,y, xlabel, ylabel)
                if len(x) < 2:
                    raise PlotException('Common', 'C040', ())    
        except PlotException, ex:
            PlotMessage(self.dg, ex)
            return None
        
        xvalues = array(x, dtype=float)
        yvalues = array(y, dtype=float)
        numDat = len(yvalues)
        # X点とY点の数が等しいか
        if len(xvalues) == numDat:    
            return plotDat
        # ヒストグラムであれば、X点の中心値を求める
        xnew = zeros(numDat, float64)
        for i in range(len(yvalues)):
            xnew[i] = xvalues[i]+(xvalues[i+1]-xvalues[i])/2.0
        plotDat.xdata = xnew
        return plotDat
            
    ######################################################
    def _ReadMPlotFile(self, fp):
        """
        MPlot 形式のテキストファイルにデータを出力(1トレース)
        @param  fp ファイルポインタ
        @retval data (x, y, er, header, xunit, yunit)
        """ 
        x = []
        y = []
        xlabel = ""
        ylabel = ""
        stat = 0
        comment = False  ## コメント読み飛ばし
        
        # データの終了まで
        while 1:
            # 読み込み終了
            if stat == 5:
                break
            line = fp.readline()
            if line == "":
                break
            line = line.strip()
            if '"""' in line:
                if comment:
                    comment = False
                else:
                    comment = True
                continue
            elif comment:
                continue

            if "--------" in line:
                stat += 1
            elif stat == 3:
                # 単位読み込み
                words = line.split(':')
                if len(words) == 2 and XLABEL in line:
                    xlabel = words[1]
                if len(words) == 2 and YLABEL in line:
                    ylabel = words[1]
            elif stat == 4:
                # データ読み込み
                nums = line.split()
                if len(nums) == 3:
                    try:
                        xx = (float(nums[0]))
                        yy = (float(nums[1]))
                    except:
                        pass
                    else:
                        x.append(xx)
                        y.append(yy)
                # 最後のXデータか
                # ヒストグラムデータの場合、Xデータの個数が1個多い       
                elif len(nums) == 1:
                    try:
                        xx = (float(nums[0]))
                    except:
                        pass
                    else:
                        x.append(xx)
        fp.close 
        
        return (x,y, xlabel, ylabel)
        
    ######################################################
    def _ReadOtherFile(self, fp, line):
        """
        テキストファイルにデータを出力(1トレース)
        FastPlot で出力したデータではないファイルの読み込み
        @param  fp ファイルポインタ
        @param  line 最初に読み込んだ行
        @retval data (x, y, er)
        """ 
        x = []
        y = []

        comment = False  
        
        # データの終了まで
        while True:
            if '"""' in line:
                if comment:
                    comment = False
                else:
                    comment = True
                line = fp.readline().strip()
                continue
            elif comment:
                line = fp.readline().strip()
                continue

            if line.find(",")>0:
                nums = line.split(",")
            else:
                nums = line.split()
            if len(nums) >= 2:
                try:
                    xx = (float(nums[0]))
                    yy = (float(nums[1]))
                except:
                    fp.close()
                    raise
                x.append(xx)
                y.append(yy)

            # データ読み込み
            line = fp.readline().strip()
            if line == "":
                break 
        fp.close
        return (x,y)                     
    
    ##########################################################
    def OnRemove(self, evt):
        """
        Remove ボタンイベント処理
        ファイルをグリッドから削除
        @param  evt イベント情報
        @retval 無し
        """     
        rows = self.grd.Remove()
        # トレースリストを削除
        for row in rows:
            self.traces.pop(row)
        # トレース再描画
        self.ifi.NotifyEvent(self.dg,'overplot', self.traces )        
        
        
    ##########################################################
    def ShowDg(self):
        """
        Cancel ボタンイベント処理
        @param  evt イベント情報
        @retval 無し
        """ 
        if not self.openFlag:    
            self.dg.Show(True)
            self.openFlag = True


#############################################
# Region:
#############################################
class Region(object):
    """
    領域データ
    """
    ####################################################
    def __init__(self, x0,y0,x1,y1, clip=True, horizontal = True ):
        """
        コンストラクタ
        @param  (float) x0 
        @param  (float) y0
        @param  (float) x1 
        @param  (float) y1
        @param  (bool) clip  True: Clip, False:Exclude
        @param  (bool) Horizontal True: Horizontal, False: Vertical
        @retval 無し
        """
        self.x0 = x0
        self.y0 = y0
        self.x1 = x1
        self.y1 = y1
        self.clip = clip
        self.horizontal = horizontal
  
     
#############################################
# GridRegions:
#############################################
class GridRegions(gridlib.Grid):
    """
    領域表示グリッド
    """
    ####################################################
    def __init__(self, panel, funcChange):
        """
        コンストラクタ
        @param  (cont) panel グリッドを作るパネル
        @retval 無し
        """
        # 空のグリッド作成
        gridlib.Grid.__init__(self, panel, -1, pos=(0, 0), size=(panel.Size))
        self.CreateGrid(0, 6)
        self.panel = panel
        self.funcChange = funcChange       
        # 行ラベルを表示
        self.SetRowLabelSize(30)
        # 列ラベルとサイズの設定
        self.SetColLabelValue(0, 'x0')
        self.SetColSize(0, 60)
        self.SetColLabelValue(1, 'y0')
        self.SetColSize(1, 60)
        self.SetColLabelValue(2, 'x1')
        self.SetColSize(2, 60)
        self.SetColLabelValue(3, 'y1')
        self.SetColSize(3, 60)
        
        self.SetColLabelValue(4, 'Type')
        self.SetColSize(4, 80)
        self.SetColLabelValue(5, 'Direction')
        self.SetColSize(5, 90)
                
        # タイプ選択コンボボックスを追加
        attrChoice1 = gridlib.GridCellAttr()
        types = ['Clip','Mask' ]
        attrChoice1.SetEditor(gridlib.GridCellChoiceEditor(choices=types))
        attrChoice1.SetRenderer(gridlib.GridCellEnumRenderer())
        self.SetColAttr(4, attrChoice1)
        
        # 方向選択コンボボックスを追加
        attrChoice2 = gridlib.GridCellAttr()
        directions = ['Horizontal','Vartical','' ]
        attrChoice2.SetEditor(gridlib.GridCellChoiceEditor(choices=directions))
        attrChoice2.SetRenderer(gridlib.GridCellEnumRenderer())
        self.SetColAttr(5, attrChoice2)
        
        self.Bind(gridlib.EVT_GRID_CELL_CHANGE, self.OnChange)
        
        self.Bind(gridlib.EVT_GRID_EDITOR_CREATED,
              self.OnGridEditorCreated)
        
    ##########################################################    
    def OnGridEditorCreated(self, event):
        
        #生成されたコンボボックスにイベントハンドラを設定
        comboBox = event.GetControl() 
        comboBox.Bind(wx.EVT_COMBOBOX, self.OnComboBox)
        event.Skip() 
    
    ##########################################################    
    def OnComboBox(self, event): 
        # コンボボックスの変更を確定するために、フォーカスを移す
        self.SetGridCursor(0, 0) 
        event.Skip()   

    ####################################################
    def OnChange(self, evt):
        """
        変更のイベントハンドラ
        @param  evt イベント
        @retval 無し
        """
        # 方向が変更されたのであれば何もしない
        if evt.Col == 5:
            return
        try:
            try:
                x0 = float(self.GetCellValue(evt.Row, 0))
            except:
                raise PlotException('Common', 'C027', ("x0",))
            try:
                y0 = float(self.GetCellValue(evt.Row, 1))
            except:
                raise PlotException('Common', 'C027', ("y0",))
            try:
                x1 = float(self.GetCellValue(evt.Row, 2))
            except:
                raise PlotException('Common', 'C027', ("x1",))
            try:
                y1 = float(self.GetCellValue(evt.Row, 3))
            except:
                raise PlotException('Common', 'C027', ("y1",))
            
            if x0 >= x1:
                raise PlotException('Common', 'C009', ("x1","x0"))
            if y0 >= y1:
                raise PlotException('Common', 'C009', ("y1","y0"))
        except PlotException, ex:
            PlotMessage(self.panel, ex)
            return
        apply(self.funcChange, ())
       
    ####################################################
    def AppendRegion(self, x0,y0, x1,y1):
        """
        グリッドの最後に行を追加し、データを表示
        @param  (string) fname テキストファイル名
        @retval 無し
        """
        # 1行追加
        self.AppendRows(1)
        # 行数取得
        num = self.NumberRows - 1
        
        stx0 = "%.3f" % x0
        sty0 = "%.3f" % y0
        stx1 = "%.3f" % x1
        sty1 = "%.3f" % y1
        # １行分のデータを追加
        self.SetCellValue(num, 0, stx0)
        self.SetCellValue(num, 1, sty0)
        self.SetCellValue(num, 2, stx1)
        self.SetCellValue(num, 3, sty1)
        #--> 2013.0628 KCS 
        #self.SetCellValue(num, 4, 'Clip')
        self.SetCellValue(num, 4, 'Mask')
        #<-- 2013.0628 KCS 
        self.SetCellValue(num, 5, 'Horizontal')
        
    ####################################################
    def Remove(self):
        """
        選択行の削除
        @param  無し
        @retval 無し
        """
        # 選択行取得
        rows = self.GetSelectedRows()
        rows.sort()
        rows.reverse()
        # 下から順番に削除
        for rowNo in rows:
            self.DeleteRows(rowNo,1,True)
    
    ####################################################
    def RemoveAll(self):
        """
        全行を削除
        @param  無し
        @retval 無し
        """
        self.DeleteRows(0,self.NumberRows,True)

    ####################################################
    def GetAllRows(self):
        """
        全データを取得
        @param  無し
        @retval ([Region]) 全行のリスト
        """
        self.SetFocus()
        regions = []
        for i in range(self.NumberRows):
           
            clip = False
            horizontal = False
            
            if self.GetCellValue(i, 4) == "Clip":
                clip = True
            if self.GetCellValue(i, 5) == "Horizontal":
                horizontal = True
            x0 = float(self.GetCellValue(i, 0))
            y0 = float(self.GetCellValue(i, 1))
            x1 = float(self.GetCellValue(i, 2))
            y1 = float(self.GetCellValue(i, 3))
            region = Region(x0,y0,x1,y1, clip, horizontal)
            regions.append(region)   
        return regions
    
    ####################################################
    def _CheckRegion(self, index):
        """
        指定行のデータをチェック
        @param  (int) index  行インデックス
        @retval Region or None
        """
        x0=y0=x1=y1=0.0
               
        try:
            try:
                x0 = float(self.GetCellValue(index, 0))
            except:
                self.SetGridCursor(index, 0)
                raise PlotException('Common', 'C027', ("x0",))
            try:
                y0 = float(self.GetCellValue(index, 1))
            except:
                self.SetGridCursor(index, 1)
                raise PlotException('Common', 'C027', ("y0",))
            try:
                x1 = float(self.GetCellValue(index, 2))
            except:
                self.SetGridCursor(index, 2)
                raise PlotException('Common', 'C027', ("x1",))
            try:
                y1 = float(self.GetCellValue(index, 3))
            except:
                self.SetGridCursor(index, 3)
                raise PlotException('Common', 'C027', ("y1",))
            
            if x0 >= x1:
                self.SetGridCursor(index, 1)
                raise PlotException('Common', 'C009', ("x1","x0"))
            if y0 >= y1:
                self.SetGridCursor(index, 3)
                raise PlotException('Common', 'C009', ("y1","y0"))
        except PlotException, ex:
            PlotMessage(self.panel, ex)
            return None
            
        return (x0,y0,x1,y1)  
    
#########################################
#       ClipDialog
#########################################        
class ClipDialog(wx.Dialog):
    """
    領域指定ダイアログクラス
    """
    
    ##########################################################
    def __init__(self, parent, order, res):
        """
        コンストラクタ
        @param  parent   親ウィンドウのID
        @param  order    プロッタの起動順序
        @param  res  リソース
        @retval 無し
        """ 
        self.openFlag = True
        self.regions = []
        # インターフェイスクラスのインスタンスを取得
        self.ifi = IFEvtProp(order)
        self.order = order
        self.plot0 = None
        self.plot1 = None
        
        # 公開プロパティを登録
        self.ifi.AddProperty('clipdg', lambda : (self.openFlag))
        self.ifi.AddProperty('clipregions', lambda : (self.regions))
        
        # リソースよりダイアログボックスを取得して作成
        self.res = res
        self.dg = self.res.GetDialog(parent, 'DgClip')
        # アイコンを設定
        self.dg.SetIcon(Images().GetMainIcon())
        
        # 領域設定イベントのリスナー登録
        self.ifi.AddListner('addRegion',  self.OnNotifyAddRegion)
        # データ変更のリスナー登録
        self.ifi.AddListner('changedata', self.OnNotifyChangeData)
        
        #クローズイベント登録
        self.dg.Bind(wx.EVT_CLOSE, self.OnClose)
        #ボタンイベント登録
        self.dg.Bind(wx.EVT_BUTTON, self.OnClose, id=self.res.GetId('btClose'))
        self.dg.Bind(wx.EVT_BUTTON, self.OnDisp, id=self.res.GetId('btDisp'))
        self.dg.Bind(wx.EVT_BUTTON, self.OnRemove, id=self.res.GetId('btRemove'))
        
        # 1次元プロッタへのデータ追加イベントのリスナー登録
        IFEvtProp(order*10).AddListner("plotclose",  self.OnNotify0Close)
        IFEvtProp(order*10+1).AddListner("plotclose",  self.OnNotify1Close)
        
        # 空のグリッド作成
        panel = self.res.GetCtrl(self.dg, 'pnGrid')
        self.grd = GridRegions(panel, self.ReDrawRequest)
        self.dg.Show(True)
    
    
        
    ##########################################################
    def OnClose(self, evt):
        """
        Cancel ボタンイベント処理
        @param  evt イベント情報
        @retval 無し
        """ 
        self.dg.Hide() 
        #<-- 2013.06.28 KCS
        # 領域を消す
        #self.regions = []
        # グラフに領域の再描画を通知
        #self.ifi.NotifyEvent(None,'drawRegions')
        #<-- 2013.0628 KCS 
        self.openFlag = False
        # 1D プロッタをクローズ
        self._ClosePlots()
        
    ##########################################################
    def _ClosePlots(self):
        """
        1D プロッタをクローズ
        @param  無し
        @retval 無し
        """   
        # プロッタ0(水平方向用)が表示されていれば
        if self.plot0 != None:
            # プロッタにクローズを通知
            IFEvtProp(self.plot0).NotifyEvent(None,'close') 
            self.plot0 = None
        # プロッタ1(垂直方向用)が表示されていれば
        if self.plot1 != None:
            # プロッタにクローズを通知
            IFEvtProp(self.plot1).NotifyEvent(None,'close') 
            self.plot1 = None
        
    ###################################################                        
    def OnNotify0Close(self, wid, evtType, value):
        """
        1Dプロッタ0クローズイベント処理
        @param  wid イベント発生元のインスタンス
        @param  evtType イベントタイプ
        @param  value 　Log モードフラグ
        @retval 無し
        """  
        print "Plot0 Close" 
        self.plot0 = None
    
    ###################################################                        
    def OnNotify1Close(self, wid, evtType, value):
        """
        1Dプロッタ1クローズイベント処理
        @param  wid イベント発生元のインスタンス
        @param  evtType イベントタイプ
        @param  value 　Log モードフラグ
        @retval 無し
        """   
        print "Plot1 Close" 
        self.plot1 = None
    
        
    ##########################################################
    def ShowDg(self):
        """
        ダイアログボックス表示
        @param  無し
        @retval 無し
        """ 
        if not self.openFlag:    
            self.dg.Show(True)
            self.openFlag = True   
            # 領域の再表示要求
            self.ReDrawRequest()
            
    ###################################################        
    def OnNotifyAddRegion(self, wid, evtType, region):
        """
        領域設定イベント処理
        @param  wid イベント発生元のインスタンス
        @param  evtType イベントタイプ
        @param  traces トレースオブジェクト
        @retval 無し
        """ 
        if self.openFlag:
            x0,y0,x1,y1 = region
            # 1行を追加
            self.grd.AppendRegion(x0,y0,x1,y1)
            self.ReDrawRequest()

    ##########################################################
    def OnRemove(self, evt):
        """
        Remove ボタンイベント処理
        領域をグリッドから削除
        @param  evt イベント情報
        @retval 無し
        """     
        # 1行削除
        self.grd.Remove()
        self.ReDrawRequest()

    ##########################################################
    def OnDisp(self, evt):
        """
        Disp ボタンイベント処理
        領域を切り取り、プロッタに表示
        @param  evt イベント情報
        @retval 無し
        """  
        # 先にプロッタが開いていればクローズ
        self._ClosePlots()
        # クリッパークラスのインスタンス取得
        mclip = self.ifi.GetProperty('mclip')
        try:
            if mclip == None:
                raise PlotException('Common','C040',())
        except PlotException, ex:
            PlotMessage(self.dg,ex)
            return
        # グリッド中の全データを取得
        regions = self.grd.GetAllRows()
        
        #--> 2013.06.28 KCS Delete
        # マスク領域の設定
        #mclip.ClearMask()
        #for region in regions:
            # マスク指定か
        #    if not region.clip:
        #        mclip.SetMask(region.x0, region.y0, region.x1, region.y1)
        #<-- 2013.06.28 KCS Delete
        
        # 水平方向に積算
        mclip.SetAxis(1)
        hLabels = []
        mclip.ClearClipRegion()
        for region in regions:
            # クリップ指定かつ水平方向積算指定か
            if region.clip and region.horizontal:
                
                hLabel = "%.4f,%.4f - %.4f,%.4f" % (region.x0, region.y0, region.x1, region.y1)
                hLabels.append(hLabel)
                mclip.SetClipRegion(region.x0, region.y0, region.x1, region.y1)
        # データがあれば
        if len(hLabels) > 0:
            # 積算実行
            mclip.ExecClip()
            ecarray = mclip.GetECArray()
            # プロッタに出力
            self._PlotOut(ecarray, hLabels, True)
        
        # 垂直方向に積算
        mclip.SetAxis(0)
        vLabels = []
        mclip.ClearClipRegion()
        for region in regions:
            # クリップ指定かつ垂直方向積算指定か
            if region.clip and not region.horizontal:
                vLabel = "%.4f,%.4f - %.4f,%.4f" % (region.y0, region.x0, region.y1, region.x1)
                vLabels.append(vLabel)
                mclip.SetClipRegion(region.x0, region.y0, region.x1, region.y1)
        # データがあれば
        if len(vLabels) > 0:
            # 積算実行
            mclip.ExecClip()
            ecarray = mclip.GetECArray()
            # プロッタに出力
            self._PlotOut(ecarray,vLabels, False)

    ##########################################################
    def _PlotOut(self, ecarray, labels, horizontal):
        """
        ElementContainer(複数個) を1D プロッタに表示
        @param  ecarray ElementContainerArray
        @param  labels ([string]) トレースラベルのリスト
        @param  horizantal (Bool) 水平方向フラグ
        @retval 無し
        """  
        data = []
        for i in range(ecarray.PutSize()):
            ec = ecarray(i)
            dicLabel = {'label':labels[i]}
            datum = [ec.PutXList(),ec.PutYList(), ec.PutEList(), dicLabel]
            data.append(datum)
            
        # メインタイトル取得
        title = self.ifi.GetProperty('title1')
        ylabel = self.ifi.GetProperty('zlabel')
        
        # 水平方向へのクリップか
        if horizontal:
            xlabel = self.ifi.GetProperty('xlabel')
            
            self.plot0 = self.order*10
            plotNo = self.plot0
            # 1Dプロッタを開く
            PlotFrame(self.dg, data, self.plot0, "Horizontal Clipping")
        else:
            xlabel = self.ifi.GetProperty('ylabel')
            self.plot1 = self.order*10+1
            plotNo = self.plot1
            # 1Dプロッタを開く
            PlotFrame(self.dg, data, self.plot1, "Vertical Clipping")
        # タイトル表示
        IFEvtProp(plotNo).NotifyEvent(None, 'title', (title, ""))
        # ラベル表示
        IFEvtProp(plotNo).NotifyEvent(None, 'scalelabel', (xlabel, ylabel))
        
    ##########################################################
    def ReDrawRequest(self):
        """
        再表示要求
        @param  無し
        @retval 無し
        """ 
        # 全データを取得
        #self.regions = self.grd.GetAllRows()
        self.regions = self.grd.GetAllRows()
        
        #-->- 2013.06.28 KCS Add
        # クリッパークラスのインスタンス取得
        mclip = self.ifi.GetProperty('mclip')
        # マスク領域の設定
        mclip.ClearMask()
        for region in self.regions:
            # マスク指定か
            if not region.clip:
                mclip.SetMask(region.x0, region.y0, region.x1, region.y1)
        #<-- 2013.06.28 KCS Add
        
        # グラフに領域の再描画を通知
        self.ifi.NotifyEvent(None,'drawRegions')
        
    ###################################################        
    def OnNotifyChangeData(self, wid, evtType, graphid):
        """
        データ変更イベント処理
        @param  wid イベント発生元のインスタンス
        @param  evtType イベントタイプ
        @param graphid グラフID
        @retval 無し
        """ 
        # グリッドのデータを削除
        self.grd.RemoveAll()
        # 1Dプロッタが開いていれば閉じる
        self._ClosePlots()
##<-- [KCS 1300520]    

##[inamura 160721]-->
#######################################
# Free Slicer
#######################################
class FreeSlicerFrame(wx.Frame):
    """
    Free Slicer on plotted data
    """
        ##########################################################
    def __init__(self, parent, order, postfix, dobj):
        """
        コンストラクタ
        @param  parent   親ウィンドウのID
        @param  order  プロッタの起動順序
        @param  postfix 画面タイトルに付ける親の識別子    
        @retval 無し
        """ 
        
        self.order = order
        self.pno = order*10+11
        self.parent = parent
        self.dmap = dobj
        # リソース取得      
        res = ResourceFile(D2VISXRC)
        self.frame = res.GetFrame(parent, 'FreeSliceFrame')
        # アイコンを設定
        self.frame.SetIcon(Images().GetMainIcon())
        
        if order > 0:
            # タイトル文字列を取得
            strT = self.frame.GetTitle()
            # 順番を付してタイトル文字列を作成
            self.frame.SetTitle(strT + postfix)
            
        panel = res.GetCtrl(self.frame, 'panel')
        # テキストボックス
        self.tx0 = res.GetCtrl(panel, 'txX1')
        self.ty0 = res.GetCtrl(panel, 'txY1')
        self.tx1 = res.GetCtrl(panel, 'txX2')
        self.ty1 = res.GetCtrl(panel, 'txY2')
        self.txw = res.GetCtrl(panel, 'txWidth')
        self.txn = res.GetCtrl(panel, 'txBinWidth')
        self.ts0 = res.GetCtrl(panel, 'txNewX0' ) #[inamura 160726]
        self.ts1 = res.GetCtrl(panel, 'txNewX1' ) #[inamura 160726]
        
        # ボタンのイベントハンドラ登録
        self.frame.Bind(wx.EVT_BUTTON, self.OnSlice, id=res.GetId('btSlice'))
        self.frame.Bind(wx.EVT_BUTTON, self.OnClose, id=res.GetId('btClose'))
        
        #[inamura 160726]-->
        # チェックボックス
        self.ckUseNewScale = res.GetCtrl(panel, 'ckUseNewScale')
        # チェックボックスのイベントハンドラ登録
        self.ckUseNewScale.Bind(wx.EVT_CHECKBOX, self.OnUseNewScale, self.ckUseNewScale)
        #<--[inamura 160726]
        
        #[X]ボタン押下時のイベントハンドラ登録
        self.frame.Bind(wx.EVT_CLOSE, self.OnClose)
        
        # ダイアログ表示
        self.frame.Show()
        
        # to avoid parts in frame are shrinked
        if sys.platform =="darwin":
            self.frame.SetSize( (300,300) )
        if sys.platform =="win32":
            self.frame.SetSize( (300,300) )
            
        self.Slicer = None
        self.plotter = None
        self.eca = None
        self.ifi_master = IFEvtProp(self.order)
        self.ifi_master.AddListner("changedata", self.OnNotifyChangeData)
        self.ifi_master.AddListner("updatedata", self.OnNotifyChangeData)
        self.ifi_plot = IFEvtProp(self.pno)
        if self.dmap!=None and self.dmap.mclip==None:
            self.Slicer = mu.UtsusemiPlaneSlicer()
            self.ImportData()
        

    ##########################################################
    def ImportData(self):
        """
        Data import from plotted data
        @param evt
        @retval None
        """
        # Get data from plotter
        X, Y = self.ifi_master.GetProperty('grid')
        ardata = self.ifi_master.GetProperty('mapdata')
        erdata = self.ifi_master.GetProperty('erdata')
        
        numX = len(ardata)
        numPixel = len(ardata[0])
        if self.eca!=None:
            del self.eca
        self.eca = mm.ElementContainerArray()
        xKey = "X"
        yKey = "Y"

        xvec = mm.MakeDoubleVector()
        for i in range(numPixel):
            xvec.push_back( float(X[0][i] ) )
        
        hh = self.eca.PutHeaderPointer()
        hh.Add("xvec",xvec)
        
        yvec = []        
        for i in range(numX):
            yvec.append( float(Y[i][0]) )
        yvec.append( float( Y[i][-1] + (Y[i][-1]-Y[i][-2])/2.0 ) )

        
        for p in range(numPixel):
            intensity = []
            error = []
            for i in range(numX):
                intensity.append( float(ardata[i][p]) )
                error.append( float(erdata[i][p]) )
            
            ec = mm.ElementContainer()            
            ec.Add("y",yvec)
            ec.Add("Intensity",intensity)
            ec.Add("Error",error)
            ec.SetKeys("y","Intensity","Error")
            self.eca.Add(ec)
            
        self.Slicer.SetPlane( self.eca )
        
    ##########################################################
    def Show(self):
        """
        Shows the FreeSlicer frame
        @param None
        @retval None
        """
        self.frame.Show()

    #########################################################
    def OnNotifyChangeData(self, wid, evtType, data):
        """
        データ変更イベント処理
        @param  wid イベント発生元のインスタンス
        @param  evt イベントタイプ
        @param  data データオブジェクト
        　　　　　　　文字列の場合は、ダミーデータファイル名とみなす
        @retval 無し
        """
        #print "-----[FreeSlicer]::OnNotifyChangeData"
        if self.dmap!=None and self.dmap.mclip==None:
            self.ImportData()
        
    #########################################################
    def OnNotifyPlotClose(self,wid, evtType, value):
        """
        Plotter Closed Event
        @param wid
        @param evtType
        @param value
        """
        self.plotter = None
        
    #[inamura 160726]-->
    ##########################################################
    def OnUseNewScale(self, evt=None):
        """
        """
        flag = self.ckUseNewScale.GetValue()
        self.ts0.Enable( flag )
        self.ts1.Enable( flag )
    #<--[inamura 160726]
    ##########################################################
    def OnClose(self, evt=None):
        """
        Closeボタンイベント処理
        @param  evt イベント情報
        @retval 無し
        """ 
        if self.plotter!=None:
            self.ifi_plot.NotifyEvent(None,'close')
        self.frame.Hide()
    ##########################################################
    def OnSlice(self, evt=None):
        """
        Sliceボタンイベント処理
        @param  evt イベント情報
        @retval 無し
        """
        if self.Slicer==None:
            self.OnSlice2()
            return
        
        #self.ImportData()

        sv = mm.MakeDoubleVector(2)
        sv[0] = float( self.tx0.GetValue() )
        sv[1] = float( self.ty0.GetValue() )
        
        ev = mm.MakeDoubleVector(2)
        ev[0] = float( self.tx1.GetValue() )
        ev[1] = float( self.ty1.GetValue() )
        
        width = float( self.txw.GetValue() )
        binw = float( self.txn.GetValue() )
        #[inamura 160726]-->
        ratio = 1.0
        if self.ckUseNewScale.GetValue():
            X0 = float( self.ts0.GetValue() )
            X1 = float( self.ts1.GetValue() )
            if X0==X1:
                msg = "New Scale Values are invalid."
                dial = wx.MessageDialog(None, msg, "ERROR", wx.OK | wx.ICON_EXCLAMATION )
                dial.ShowModal()
                return
            ratio = (X1-X0)/math.sqrt( (ev[0]-sv[0])**2 + (ev[1]-sv[1])**2 )
            DX = float( self.txn.GetValue() )
            binw = DX/ratio
        
        if binw==0.0:
            msg = "Bin Width is invalid."
            dial = wx.MessageDialog(None, msg, "ERROR", wx.OK | wx.ICON_EXCLAMATION )
            dial.ShowModal()
            return
        #<--[inamura 160726]
        
        ec = self.Slicer.GetLine( sv, ev, binw, width )
        
        #[inamura 160726]-->
        if self.ckUseNewScale.GetValue():
            new_xx = []
            for x in ec.PutXList():
                new_xx.append( X0+x*ratio )
            
            xkey = ec.PutXKey()
            ykey = ec.PutYKey()
            ekey = ec.PutEKey()
            ec.Replace( xkey, new_xx )
            ec.SetKeys( xkey, ykey, ekey )
        #<--[inamura 160726]

        ce = ConvertEC()
        data = ce.ConvertEC( ec )
        if self.plotter==None:
            self.plotter = PlotFrame(self.frame, data, self.pno, "FreeSlice")
            self.ifi_plot.AddListner("plotclose", self.OnNotifyPlotClose)
        else:
            self.ifi_plot.NotifyEvent(None, "add", [data])

##<--[inamura 160721]
    ##########################################################
    def OnSlice2(self):
        """
        Sliceボタンイベント処理
        @param  evt イベント情報
        @retval 無し
        """
        sx = float( self.tx0.GetValue() )
        sy = float( self.ty0.GetValue() )
        ex = float( self.tx1.GetValue() )
        ey = float( self.ty1.GetValue() )
        
        width = float( self.txw.GetValue() )
        binw = float( self.txn.GetValue() )

        ratio = 1.0
        if self.ckUseNewScale.GetValue():
            X0 = float( self.ts0.GetValue() )
            X1 = float( self.ts1.GetValue() )
            if X0==X1:
                msg = "New Scale Values are invalid."
                dial = wx.MessageDialog(None, msg, "ERROR", wx.OK | wx.ICON_EXCLAMATION )
                dial.ShowModal()
                return
            ratio = (X1-X0)/math.sqrt( (ev[0]-sv[0])**2 + (ev[1]-sv[1])**2 )
            DX = float( self.txn.GetValue() )
            binw = DX/ratio
        
        if binw==0.0:
            msg = "Bin Width is invalid."
            dial = wx.MessageDialog(None, msg, "ERROR", wx.OK | wx.ICON_EXCLAMATION )
            dial.ShowModal()
            return
        
        self.dmap.mclip.ClearClipRegion()
        self.dmap.mclip.SetClipRegion( sx, sy, ex, ey )
        self.dmap.mclip.SetAxis(2,width,binw)
        self.dmap.mclip.ExecClip()
        ec = self.dmap.mclip.GetEC(0)
        
        if self.ckUseNewScale.GetValue():
            new_xx = []
            for x in ec.PutXList():
                new_xx.append( X0+x*ratio )
            
            xkey = ec.PutXKey()
            ykey = ec.PutYKey()
            ekey = ec.PutEKey()
            ec.Replace( xkey, new_xx )
            ec.SetKeys( xkey, ykey, ekey )

        ce = ConvertEC()
        data = ce.ConvertEC( ec )
        if self.plotter==None:
            self.plotter = PlotFrame(self.frame, data, self.pno, "FreeSlice")
            self.ifi_plot.AddListner("plotclose", self.OnNotifyPlotClose)
        else:
            self.ifi_plot.NotifyEvent(None, "add", [data])

#######################################
#  Legacy2DFile
####################################### 
class Legacy2DFile(object):
    """
    以前のファイル形式クラス
    """
    ###################################################             
    def ReadData(self, fname1, fname2, ei):
        """
        データ変更イベント処理
        @param  fname1  SPE ファイル名
        @param fname2   PHX ファイル名
        @param ei       入射エネルギー
        @retval 無し
        """ 
        
        # 疑似データファイル読み込み
        try:
            self._ReadSPEFile(fname1)
            self._ReadPHXFile(fname2)
        except:
            raise
            return None
        else:
            # グリッドを作成
            X, Y = self._MakeXYGrid(ei)
            return (self.arData, self.erData, X, Y,1)

    #########################################
    def _ReadSPEFile(self, fname):
        """
        ダミーデータを読み込み、カラーコンツァーマップを作成
        @param  fname  ダミーデータファイル
        @retval 無し
        """ 
        try:
            datFile = open(fname, 'r')
        except:
            raise PlotException('Common', 'C006', (fname,))
            return
                
        # エネルギービン格納リストを準備 
        self.ebins = []
        # データ格納リストを準備 
        self.dataList = []
        self.errList = []
        
        self.numPsd = 0
        self.numBins = 0
        self.maxCount = 0.0

        # データファイルから、検出器数とビンの数-1を取得
        line = datFile.readline()
        self.numPsd, self.numBins = map(int, line.split())
        if self.numPsd > 3000:
            datFile.close()
            raise PlotException('VisCont', 'V011', ("SPE",))
        # 
        self.numBins +=1
        
        # エネルギービンのデータまで読み飛ばし
        while True:
            line = datFile.readline()
            if "Energy" in line:
                break
        
        # エネルギービンのデータ読み込み
        while True:
            line = datFile.readline()
            if "S(Phi,w)" in line:
                break
            dat = self._ChangeNums(line)

            # 1行分のデータ(8個)をリストに追加
            self.ebins.extend(dat)
           
        # 検出器数分のデータ読み込み    
        for i in range(self.numPsd):
            # 1検出器のデータ読み込み
            hist = []
            errs = []
            while True:
                line = datFile.readline()
                if "###" in line:
                    break
                dat = self._ChangeNums(line)
                # 1行分のデータ(8個)をリストに追加
                hist.extend(dat)
                 
            # エラーデータ読み込み
            while True:
                line = datFile.readline()
                try:
                    line.split()
                except:
                    # ファイルの終了、クローズ
                    datFile.close()
                    break
                if len(line)==0:
                    # ファイルの終了、クローズ
                    datFile.close()
                    break
                    
                if "###" in line:
                    break
                dat = self._ChangeNums(line)
                # 1行分のエラー(8個)をリストに追加
                errs.extend(dat)

            # 1検出器分のヒストグラムとエラーをデータリストに追加
            self.dataList.append(hist)
            self.errList.append(errs)

    #########################################
    def _ReadPHXFile(self, fname):
        """
        角度ファイル読み込み
        @param  fname  ダミーデータファイル
        @retval 無し
        """ 
        # 角度ファイルを開く
        try:
            fra = open(fname, 'r')
        except:
            raise PlotException('Common', 'C006', (fname,))
            return
                
        # 散乱角データ格納用リストを準備
        self.faiPols = []
        # 検出器の個数読み込み
        line = fra.readline().split()
         
        # 検出器ギャップ用のリストを準備
        self.gap =[]
        bFai = 0.0
        # 検出器数分の角度データ読み込み  
        isForceRead = False  #[inamura 160803]
        for i in range(self.numPsd):
            try:
                line = fra.readline().split()
            except:
                break
            fai = float(line[2])/180.0*pi
            dfai = float(line[4])/180.0*pi
            #[inamura 160803]-->
            #if float(line[3]) > 0.0:
            if (not isForceRead) and float(line[3])>0.0:
                msg = "Given SPE and PHX files is not regular 2D data. Force to read ?"
                dial = wx.MessageDialog(None, msg, "WARNING", wx.YES_NO | wx.NO_DEFAULT | wx.ICON_QUESTION )
                res=dial.ShowModal()
                if res==wx.ID_YES:
                    isForceRead=True
                else:
                    # 角度ファイルをクローズ
                    fra.close()
                    raise PlotException('VisCont', 'V011', ("PHX",))
                    return
                #<--[inamura 160803]
                
            self.faiPols.append((fai,dfai))

            if fai - bFai > dfai:  #[inamura 160803]
                self.gap.append(i-1)
            bFai = fai
        # 角度ファイルをクローズ
        fra.close()

        #[inamura 160803]-->
        #self.gap.pop(0)
        if len(self.gap)!=0:
            self.gap.pop(0)
        #<--[inamura 160803]
        # ギャップ数を格納
        self.numGap = len(self.gap)
        
        # 全点 0 のアレイを作成        
        self.arData =zeros((self.numBins-1,self.numPsd+self.numGap), float64)
        self.erData =zeros((self.numBins-1,self.numPsd+self.numGap), float64)

        # 縦横を逆にして取り込む
        for i in range(self.numBins-1):
            ng = 0
            for j in range(self.numPsd):
                self.arData[i][j+ng] = self.dataList[j][i]
                self.erData[i][j+ng] = self.errList[j][i]
                if ng < self.numGap:
                    if j == self.gap[ng]:
                        self.arData[i][j+ng+1] = MASKVALUE
                        self.erData[i][j+ng+1] = 0.0
                        ng +=1

    #########################################    
    def _ChangeNums(self,strLine ):
        """
        全検出単位のマップデータを返す
        @param  strLine 数値文字列
        @retval 実数に変換後のリスト
        """ 

        numList = []
        
        lnum = len(strLine)
        i = 0
        j = 10
        # 10 文字の数値を切り出す
        while j < lnum:
            num = float(strLine[i:j])
            numList.append(num)
            i += 10
            j += 10
        return numList

    #########################################    
    def _MakeXYGrid(self, ei):
        """
        XグリッドとYグリッドを計算
        @param  ei  入射エネルギー
        @retval XグリッドとYグリッド
        """ 
        nGap = len(self.gap)
        x = arange(0.0,self.numPsd+nGap+1 , 1.0)
        y = array(self.ebins)
        
        X,Y = meshgrid(x, y)

        ki = sqrt(ei/2.072)
        ki2 = ki*ki

        for i in range(self.numBins):

            hw = self.ebins[i]
            ng = 0
            for j in range(self.numPsd):
                # 角度読み込み
                faix, deltaFai = self.faiPols[j]
                fai = faix - deltaFai/2.0
                kf = sqrt((ei-hw)/2.072) #[inamura 160803]

                # Q を計算
                q =sqrt( ki2 + kf*kf - 2.0*ki*kf*cos(fai))
               
                X[i][j+ng]= q
                
                if ng < nGap:
                    if j == self.gap[ng]:
                        fai = faix + deltaFai/2.0
                        q =sqrt( ki2 + kf*kf - 2.0*ki*kf*cos(fai))
                        X[i][j+ng+1]= q
                        ng +=1
                        
            fai = faix + deltaFai/2.0
            q =sqrt( ki2 + kf*kf - 2.0*ki*kf*cos(fai))            
            X[i][j+ng+1]= q
            
        return (X,Y)    

class LoadSnsSqeFile(object):
    """
    """
    ###################################################             
    def ReadData(self, fname1):
        """
        データ変更イベント処理
        @param  fname1  SPE ファイル名
        @retval 無し
        """ 
        
        # 疑似データファイル読み込み
        try:
            return self._ReadSQEFile(fname1)
        except:
            raise
            return None

    #########################################
    def _ReadSQEFile(self, fname):
        """
        ダミーデータを読み込み、カラーコンツァーマップを作成
        @param  fname  ダミーデータファイル
        @retval 無し
        """ 
        try:
            datFile = open(fname, 'r')
        except:
            raise PlotException('Common', 'C006', (fname,))
            return
                
        # エネルギービン格納リストを準備 
        self.ebins = []
        self.qbins = []
        # データ格納リストを準備 
        self.dataList = []
        self.errList = []
        
        self.numQbins = 0
        self.numEbins = 0
        
        # データファイルから、検出器数とビンの数-1を取得
        line = datFile.readline()
        self.numQbins, self.numEbins = map(int, line.split())

        qbin_num_lines = int(self.numQbins/8)
        if (self.numQbins % 8)>0:
            qbin_num_lines +=1
        ebin_num_lines = int(self.numEbins/8)
        if (self.numEbins % 8)>0:
            ebin_num_lines +=1

        counts = 0
        while(True):
            line = datFile.readline()
            if line=="" or line==None:
                break
            
            if line.find("###")==0:
                counts += 1
            if counts==1: ## |Q|
                for i in range(qbin_num_lines):
                    line = datFile.readline()
                    dat = self._ChangeNums(line)
                    self.qbins.extend(dat)
            elif counts==2: ## Energy
                for i in range(ebin_num_lines):
                    line = datFile.readline()
                    dat = self._ChangeNums(line)
                    self.ebins.extend(dat)
            elif (counts % 2)==1: ## Intensity
                int_list = []
                for i in range(ebin_num_lines):
                    line = datFile.readline()
                    dat = self._ChangeNums(line)
                    int_list.extend(dat)
                self.dataList.append( int_list )
            elif (counts % 2)==0: ## Error
                err_list = []
                for i in range(ebin_num_lines):
                    line = datFile.readline()
                    dat = self._ChangeNums(line)
                    err_list.extend(dat)
                self.errList.append( err_list )

        X, Y = meshgrid( array(self.qbins[:-1]),array(self.ebins[:-1]) )
        
        # 全点 0 のアレイを作成        
        self.arData =zeros((self.numEbins-1,self.numQbins-1), float64)
        self.erData =zeros((self.numEbins-1,self.numQbins-1), float64)

        # 縦横を逆にして取り込む
        for i in range(self.numQbins-1):
            for j in range(self.numEbins-1):
                self.arData[j][i] = self.dataList[i][j]
                self.erData[j][i] = self.errList[i][j]

        return (self.arData, self.erData, X, Y, 0) ## chokko data
        
    #########################################    
    def _ChangeNums(self,strLine ):
        """
        return data from text line
        @param  strLine 数値文字列
        @retval 実数に変換後のリスト
        """ 

        numList = []
        
        lnum = len(strLine)
        i = 0
        j = 10
        # 10 文字の数値を切り出す
        while j < lnum:
            num = float(strLine[i:j])
            if num<-1.0e+19:
                num = MASKVALUE
            numList.append(num)
            i += 10
            j += 10
        return numList

##[inamura 090924]->
#########################################
#       SetColorMapDialog
#########################################
class SetColorMap2DDialog(wx.Dialog):
    """
    ColorMap 設定ダイアログクラス
    """
    ##########################################################
    def __init__(self, parent, order, postfix):
        """
        コンストラクタ
        @param  parent   親ウィンドウのID
        @param  order  プロッタの起動順序
        @param  postfix 画面タイトルに付ける親の識別子    
        @retval 無し
        """ 
        
        self.ifi = IFEvtProp(order)
        
        # リソース取得      
        res = ResourceFile(D2VISXRC)
        #res = ResourceFile('D2Vis') #[inamura 160401]
        self.dialog = res.GetDialog(parent, 'Dg2DColorMap')
        # アイコンを設定
        self.dialog.SetIcon(Images().GetMainIcon())
        
        if order > 0:
            # タイトル文字列を取得
            strT = self.dialog.GetTitle()
            # 順番を付してタイトル文字列を作成
            self.dialog.SetTitle(strT + postfix)
            
        # コンボボックス
        self.cbCS = res.GetCtrl(self.dialog, 'ColorMap')
        # コンボボックスのイベントハンドラ登録
        self.cbCS.Bind(wx.EVT_CHOICE, self.OnComboCS, self.cbCS) ##[inamura 170302]
        # コンボボックスの初期値設定
        self.orgCS=self.ifi.GetProperty("colormap")
        self.cbCS.SetLabel(self.orgCS)#[inamura 170302]
        
        # ボタンのイベントハンドラ登録
        self.dialog.Bind(wx.EVT_BUTTON, self.OnCancel, id=res.GetId('btCancel'))
        self.dialog.Bind(wx.EVT_BUTTON, self.OnClose, id=res.GetId('btClose'))
        #[X]ボタン押下時のイベントハンドラ登録
        self.dialog.Bind(wx.EVT_CLOSE, self.OnClose)
        
        self.ifi.NotifyEvent(self, "setcolormap2ddg", False) ##[inamura 121029]
        
        # ダイアログ表示
        self.dialog.ShowModal()
        
    ##########################################################
    def OnComboCS(self, evt):
        """
        Color Map 変更イベント処理
        @param  evt イベント情報
        @retval 無し
        """ 
        # ColorMapの名前を取得
        value=self.cbCS.GetString(self.cbCS.GetSelection())#[inamura 170302]
        print "Apply value=",value

        # トレース属性変更要求をだす
        self.ifi.NotifyEvent(self, "colormap", value )

    ##########################################################
    def OnClose(self, evt):
        """
        Closeボタンイベント処理
        @param  evt イベント情報
        @retval 無し
        """ 
        self.ifi.NotifyEvent(self, "setcolormap2ddg", True) ##[inamura 121029]
        self.dialog.EndModal(self.dialog.GetReturnCode()) #[inamura 160229]
        self.dialog.Destroy()

    ##########################################################
    def OnCancel(self, evt):
        """
        Cancelボタンイベント処理
        @param  evt イベント情報
        @retval 無し
        """ 

        self.ifi.NotifyEvent(self, "colormap", self.orgCS )
        self.ifi.NotifyEvent(self, "setcolormap2ddg", True) ##[inamura 121029]
        self.dialog.EndModal(self.dialog.GetReturnCode()) #[inamura 160229]
        self.dialog.Destroy()



#########################################
#       Set XY range Dialog
#########################################        
class SetXYRange2DDialog(wx.Dialog):
    """
    X,Y Range パラメータ設定ダイアログクラス
    """
    
    ##########################################################
    def __init__(self, parent, order, postfix):
        """
        コンストラクタ
        @param  parent   親ウィンドウのID
        @param  order  プロッタの起動順序
        @param  postfix 画面タイトルに付ける親の識別子    
        @retval 無し
        """ 
        # インターフェイスクラスのインスタンスを取得
        self.ifi = IFEvtProp(order)
        
        # リソースを取得
        res = ResourceFile(D2VISXRC)
        #res = ResourceFile('D2Vis') #[inamura 160401]
        self.dg = res.GetDialog(parent, 'Dg2DSetting')
        # アイコンを設定
        self.dg.SetIcon(Images().GetMainIcon())
        # アイコンを設定
        #self.dg.SetIcon(Images().GetMainIcon())
        # タイトル文字列を取得
        strT = self.dg.GetTitle()
        # 順番を付してタイトル文字列を作成
        self.dg.SetTitle(strT + postfix)
        # ボタンのイベントハンドラを登録
        self.dg.Bind(wx.EVT_BUTTON, self.OnClose, id=res.GetId('btClose'))
        self.dg.Bind(wx.EVT_BUTTON, self.OnApplyX, id=res.GetId('btXApply'))
        self.dg.Bind(wx.EVT_BUTTON, self.OnApplyY, id=res.GetId('btYApply'))
        
        # リソースよりコントロールを取得
        panel1 = res.GetCtrl(self.dg, 'xyrangepanel')
        
        # チェックボックス
        self.ckXAuto = res.GetCtrl(panel1, 'ckXAuto')
        self.ckYAuto = res.GetCtrl(panel1, 'ckYAuto')
 
        # テキストボックス
        self.tx0 = res.GetCtrl(panel1, 'x0')
        self.tx1 = res.GetCtrl(panel1, 'x1')
        self.ty0 = res.GetCtrl(panel1, 'y0')
        self.ty1 = res.GetCtrl(panel1, 'y1')
        # プッシュボタン
        self.applyX = res.GetCtrl(self.dg, 'btXApply')
        self.applyY = res.GetCtrl(self.dg, 'btYApply')
        
        ##[inamura 120711]-->
        ifdrawdic = self.ifi.GetProperty('drawdic')
        self.isOnly = self.ifi.GetProperty('only2d')
        self.init_drawdic = None
        if self.isOnly:
            self.init_drawdic = ifdrawdic["SingleMode"].copy()
        else:
            self.init_drawdic = ifdrawdic["MultiMode"].copy()

        self.spinFS = res.GetCtrl(self.dg,'spFS')
        self.spinFS.Bind(wx.EVT_SPINCTRL, self.OnSetFont, self.spinFS)
        self.chFontName = res.GetCtrl(self.dg, 'chFontName')
        self.chFontName.Bind(wx.EVT_CHOICE, self.OnSetFont, self.chFontName)
        ##<--[inamura 120711]
        
        #[X]ボタン押下時のイベントハンドラ登録
        self.dg.Bind(wx.EVT_CLOSE, self.OnClose)
        # チェックボックスのイベントハンドラ登録
        self.ckXAuto.Bind(wx.EVT_CHECKBOX, self.OnAutoX, self.ckXAuto)
        self.ckYAuto.Bind(wx.EVT_CHECKBOX, self.OnAutoY, self.ckYAuto)
        
        # 各部品に値を設定
        self._SetValues()
        
        # ダイアログオープンイベント発行
        self.ifi.NotifyEvent(self, "setxyrange2ddg", False) ##[inamura 121029]
        
        # ダイアログ表示
        self.dg.Show()
        
    ##########################################################
    def _SetValues(self):
        """
        現在のパラメータを取得して画面に設定
        @param  無し
        @retval 無し
        """ 
       
        # 現在のスケールX範囲をテキストボックスにセット
        self.ckXAuto.SetValue(self.ifi.GetProperty('autox2d'))
        self._SetEnableXRange()

        # 現在のスケールY範囲をテキストボックスにセット
        self.ckYAuto.SetValue(self.ifi.GetProperty('autoy2d'))
        self._SetEnableYRange()
        
        ##[inamura 120711]-->
        self.spinFS.SetValue( self.init_drawdic["TickLabelSize"] )
        fdic = self.ifi.GetProperty('drawdic')
        fnl = fdic["FontList"]
        for it_fnl in fnl:
            self.chFontName.Append(it_fnl)
        self.chFontName.SetStringSelection( self.init_drawdic["ScaleFont"] )
        ##<--[inamura 120711]
        
    ##########################################################
    def OnClose(self, evt):
        """
        ダイアログクローズイベント処理
        @param  evt イベント情報
        @retval 無し
        """ 
        ##[inamura 120711]-->
        params = []
        #params.append( ['TickLabelSize', self.init_drawdic["TickLabelSize"] ] )
        #params.append( ['ScaleFont',self.init_drawdic["ScaleFont"] ] )
        #self.ifi.NotifyEvent(self, 'setdrawinfo', params )
        ##<--[inamura 120711]

        # パラメータ設定ダイアログクローズイベントを発行
        self.ifi.NotifyEvent(self, "setxyrange2ddg", True) ##[inamura 121029]
        
        self.dg.Destroy() 

    ##########################################################        
    def OnAutoX(self, evt=None):
        """
        AutoXチェックボックスイベント処理
        @param  evt イベント情報
        @retval 無し
        """ 
        self._SetEnableXRange()
        # スケール変更通知をリスナーへ送信
        self.ifi.NotifyEvent(self, "xscale2d", (True, None, None))

    ##########################################################        
    def _SetEnableXRange(self):
        """
        X Range の選択可/不可を設定
        @param  evt イベント情報
        @retval 無し
        """ 
  
        # 自動モードであれば
        if self.ckXAuto.GetValue():
            # テキストボックスを選択不可とする
            self.tx0.Enable(False)    
            self.tx1.Enable(False)
            self.applyX.Enable(False)
            
        # マニュアルモードなら
        else:
            # 範囲プロパティを取得し文字列に変換
            strx0 = "%.5f" % (self.ifi.GetProperty('xrange2d'))[0]
            strx1 = "%.5f" % (self.ifi.GetProperty('xrange2d'))[1]
            # テキストボックスに値を設定    
            self.tx0.SetValue(strx0)
            self.tx1.SetValue(strx1)
            # スケール入力テキストボックスを選択可とする
            self.tx0.Enable(True)
            self.tx1.Enable(True)
            # Apply ボタンを選択可とする
            self.applyX.Enable(True)

            
    ##########################################################        
    def OnAutoY(self, evt=None):
        """
        AutoYチェックボックスイベント処理
        @param  evt イベント情報
        @retval 無し
        """ 
        self._SetEnableYRange()
        # スケール変更通知をリスナーへ送信
        self.ifi.NotifyEvent(self, "yscale2d", (True, None, None))
        
    ##########################################################        
    def _SetEnableYRange(self):
        """
        X Range の選択可/不可を設定
        @param  evt イベント情報
        @retval 無し
        """     
        # 自動モードであれば
        if self.ckYAuto.GetValue():
            # テキストボックスを選択不可とする
            self.ty0.Enable(False)    
            self.ty1.Enable(False)
            self.applyY.Enable(False)
        # マニュアルモードなら
        else:
            # 範囲プロパティを取得し文字列に変換
            stry0 = "%.5f" % (self.ifi.GetProperty('yrange2d'))[0]
            stry1 = "%.5f" % (self.ifi.GetProperty('yrange2d'))[1]
            # テキストボックスに値を設定    
            self.ty0.SetValue(stry0)
            self.ty1.SetValue(stry1) 
            # スケール入力テキストボックスを選択可とする
            self.ty0.Enable(True)    
            self.ty1.Enable(True)
            # Apply ボタンを選択可とする
            self.applyY.Enable(True)

    ##########################################################    
    def OnApplyX(self, evt):
        """
        Applyボタンイベント処理
        @param  evt イベント情報
        @retval 無し
        """ 
        # テキストボックスより値を取得
        # 数値か
        try:
            x0 = float(self.tx0.GetValue())
        except:
            x0 = 0.0 
        try:
            x1 = float(self.tx1.GetValue())
        except:
            x1 = 1.0
        # 同値か
        if x0 == x1:
            x1 = x0+1.0
        # 逆転していたら
        if x0 > x1 :
            # 入れ替える
            tmp = x0
            x0 = x1
            x1 = tmp
        
        # 数値を再表示  
        strX0 = "%.5f" % x0   
        strX1 = "%.5f" % x1
        self.tx0.SetValue(strX0)
        self.tx1.SetValue(strX1)
         
        # スケール変更通知をリスナーへ送信
        self.ifi.NotifyEvent(self, "xscale2d", (False, x0, x1))
        
    ##########################################################    
    def OnApplyY(self, evt):
        """
        Applyボタンイベント処理
        @param  evt イベント情報
        @retval 無し
        """ 
        # テキストボックスより値を取得
        # 数値か
        try:
            y0 = float(self.ty0.GetValue())
        except:
            y0 = 0.0 
        try:
            y1 = float(self.ty1.GetValue())
        except:
            y1 = 1.0
        # 同値か
        if y0 == y1:
            y1 = y0+1.0
        # 逆転していたら
        if y0 > y1 :
            # 入れ替える
            tmp = y0
            y0 = y1
            y1 = tmp
        
        # 数値を再表示  
        strY0 = "%.5f" % y0   
        strY1 = "%.5f" % y1
        self.ty0.SetValue(strY0)
        self.ty1.SetValue(strY1)
        # スケール変更通知をリスナーへ送信
        self.ifi.NotifyEvent(self, "yscale2d", (False, y0, y1))
    ##[inamura 120711]-->
    ##########################################################
    def OnSetFont(self, evt):
        """
        """
        params = []
        params.append(['TickLabelSize', self.spinFS.GetValue()])
        params.append(['ScaleFont',self.chFontName.GetStringSelection()])
                       
        self.ifi.NotifyEvent(self, 'setdrawinfo', params )
    ##<--[inamura 120711]

##<-[inamura 090924]
##[inamura 110106]-->
#######################################
#  ChartToolBarD2Vis
#######################################         
class ChartToolBarD2Vis(ChartToolBar):
    """
    D2Vis用ツールバーの拡張クラス
    Cursor表示処理用のアイコン追加
    """
    def __init__(self, parent, order):
        """
        コンストラクタ
        @param order  イベントディスパッチャのID
        @param parent  親クラスのインスタンス
        @param order   イベントディスパッチャのID
        @retval 無
        """
        self.parent = parent
        # イベント管理クラスのインスタンスを取得
        self.ifi = IFEvtProp(order)
        #先にスーパークラスのコンストラクタを実行させる
        ChartToolBar.__init__(self, parent, order)

    ##################################    
    def _init_toolbar(self):
        """
        ツールバーを作成
        @param 無し
        @retval 無し
        """
        #先にスーパークラスのツールバーを作る
        ChartToolBar._init_toolbar(self)
        
        self._parent = self.parent.canvas.GetParent()
        # アイコンのIDを生成
        self._CURSOR = wx.NewId()
        self._SINGLM = wx.NewId() ##[inamura 120211]
        self._GRIDON = wx.NewId() ##[inamura 160124]
        
        # アイコンのサイズ指定
        self.SetToolBitmapSize(wx.Size(24, 24))
        
        # セパレータを入れる
        self.AddSeparator()
        #アイコンをツールバーに追加
        self.AddCheckTool(self._CURSOR, self.GetCursorIconData(), shortHelp='Cursor On/Off')
        self.AddCheckTool(self._SINGLM, self.GetSingleModeIconData(), shortHelp='SingleMode On/Off')##[inamura 120211]
        self.AddCheckTool(self._GRIDON, self.GetAxisGridIconData(), shortHelp='Axis Grid On/Off')##[inamura 160124]
        
        #　各アイコン押下時のイベントハンドラ作成 
        if wx.VERSION_STRING >= '2.5':
            self.Bind(wx.EVT_TOOL, self.OnCursor, id=self._CURSOR)
            self.Bind(wx.EVT_TOOL, self.OnSingleMode, id=self._SINGLM) ##[inamura 120211]
            self.Bind(wx.EVT_TOOL, self.OnAxisGrid, id=self._GRIDON) ##[inamura 160124]
        else:
            wx.EVT_TOOL(self, self._CURSOR, self.OnCursor)
            wx.EVT_TOOL(self, self._SINGLM, self.OnIngleMode) ##[inamura 120211]
            wx.EVT_TOOL(self, self._GRIDON, self.OnAxisGrid) ##[inamura 160124]
            
        # turn off Cursor
        self.SetCursorBtn(False)
        
        # ツールバーの再表示
        self.Realize()

    ##################################    
    def OnCursor(self, *args):
        """
        Cursorモード変更
        @param  *args    イベント情報
        @retval 無し
        """
        # Cursorラベルモードの設定または解除 
        self.SetCursorBtn(self.GetToolState(self._CURSOR))

        # update D2Chart
        self.parent.d2.UpdateCursol(3)
 
    ##################################    
    def SetCursorBtn(self, flag): 
        """
        CURSOR ボタンオン/オフ処理
        @param  flag  True: On  False: Off
        @retval 無し
        """ 
        self.cursorMode = flag 
        # Turn on/off Cursor button
        self.ToggleTool(self._CURSOR, flag)

    ###################################################
    def GetCursorIconData(self):
        """
        Return Icom picture data as Bitmap
        Image text data is XPM format.
        @param None
        @retval wx.Bitmap
        """
        xpm_icon_data = [
            "24 24 4 1",
            " 	c None",
            ".	c #BACDF3",
            "+	c #000000",
            "@	c #8896B2",
            "                        ",
            " ...................... ",
            " ..........++.......... ",
            " ..........++.@@....... ",
            " ..........++.@@....... ",
            " ..........++.@@....... ",
            " ..........++.@@....... ",
            " ..........++.@@....... ",
            " ..........++.@@....... ",
            " ..........++.@@....... ",
            " ..........++.@@....... ",
            " .++++++++++++++++++++. ",
            " .++++++++++++++++++++. ",
            " ..........++.@@....... ",
            " ..@@@@@@@@++@@@@@@@@@@ ",
            " ..@@@@@@@@++@@@@@@@@@@ ",
            " ..........++.@@....... ",
            " ..........++.@@....... ",
            " ..........++.@@....... ",
            " ..........++.@@....... ",
            " ..........++.@@....... ",
            " ..........++.@@....... ",
            " .............@@....... ",
            "                        "]
        
        return wx.BitmapFromXPMData(xpm_icon_data)
    
##<--[inamura 110106]
##[inamura 120211]-->
    ##################################    
    def OnSingleMode(self, *args):
        """
        Cursorモード変更
        @param  *args    イベント情報
        @retval 無し
        """
        # Cursorラベルモードの設定または解除 
        ret = self.SetSingleModeBtn(self.GetToolState(self._SINGLM))

        # update D2Chart
        self.parent.d2.OnNotifyShowOnly2d(None,None,ret) ##[inamura 120710]
        #self.parent.d2.isOnly = ret
        #self.parent.d2.PlotD2Chart()
        #self.parent.d2.UpdateCursol(3)
        #self.parent.d2.canvas.draw()
 
    ##################################    
    def SetSingleModeBtn(self, flag): 
        """
        CURSOR ボタンオン/オフ処理
        @param  flag  True: On  False: Off
        @retval 無し
        """ 
        self.SingleMode = flag 
        # Turn on/off Cursor button
        self.ToggleTool(self._SINGLM, flag)
        return flag

    ###################################################
    def GetSingleModeIconData(self):
        """
        Return Icom picture data as Bitmap
        Image text data is XPM format.
        @param None
        @retval wx.Bitmap
        """
        xpm_icon_data = [
            "22 21 69 2",
            "AA c #FFFFFFFFFFFF",
            "BA c #FFFFCCCCCCCC",
            "CA c #FFFFCCCC9999",
            "DA c #FFFF99999999",
            "EA c #CCCCFFFFFFFF",
            "FA c #CCCCFFFFCCCC",
            "GA c #CCCCCCCCFFFF",
            "HA c #CCCCCCCCCCCC",
            "IA c #CCCCCCCC9999",
            "JA c #CCCC99999999",
            "KA c #CCCC66666666",
            "LA c #CCCC33336666",
            "MA c #9999FFFFCCCC",
            "NA c #9999FFFF9999",
            "OA c #9999CCCCFFFF",
            "PA c #9999CCCCCCCC",
            "AB c #9999CCCC9999",
            "BB c #99999999FFFF",
            "CB c #99999999CCCC",
            "DB c #999999999999",
            "EB c #999999996666",
            "FB c #999966669999",
            "GB c #999966666666",
            "HB c #999966663333",
            "IB c #999933330000",
            "JB c #6666CCCCFFFF",
            "KB c #6666CCCCCCCC",
            "LB c #66669999FFFF",
            "MB c #66669999CCCC",
            "NB c #666699999999",
            "OB c #66666666CCCC",
            "PB c #666666669999",
            "AC c #666666666666",
            "BC c #666666663333",
            "CC c #666633333333",
            "DC c #666633330000",
            "EC c #33339999CCCC",
            "FC c #33336666CCCC",
            "GC c #333366669999",
            "HC c #33333333CCCC",
            "IC c #333333339999",
            "JC c #333333336666",
            "KC c #333300006666",
            "LC c #333300000000",
            "MC c #00006666CCCC",
            "NC c #000066669999",
            "OC c #00003333CCCC",
            "PC c #000033339999",
            "AD c #000033336666",
            "BD c #000033333333",
            "CD c #000000006666",
            "DD c #000000003333",
            "ED c #777700000000",
            "FD c #555500000000",
            "GD c #444400000000",
            "HD c #00000000BBBB",
            "ID c #000000008888",
            "JD c #000000007777",
            "KD c #000000005555",
            "LD c #000000004444",
            "MD c #EEEEEEEEEEEE",
            "ND c #DDDDDDDDDDDD",
            "OD c #BBBBBBBBBBBB",
            "PD c #AAAAAAAAAAAA",
            "AE c #888888888888",
            "BE c #777777777777",
            "CE c #555555555555",
            "DE c #222222222222",
            "EE c #000000000000",
            "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEE",
            "AAAAMDAAAAAAAAAAMDMDMDAAAAAAMDAAAAAAAAAAAACE",
            "AAMDAAAAMDAAAADBAEFBDBMDAAMDAAAAMDAAMDAAAACE",
            "AAAAAAAAAAAAODLDLDDDDDNBAAAAAAAAAAAAAAMDAACE",
            "AAMDAAAAAAAAICKDBDJCADJDCBAAAAAAAAAAAAHAJACE",
            "AAAAAAAAAAPDIDJCLDBDICMCPCGAAAAAAAAAAAJALACE",
            "AAAAAAAAMDPBADADBDKDADICCDPBMDAAAAAAAABAKACE",
            "AAMDAAAAHAIDOCJCADADPCMCJCLDODAAAAAAAAJADACE",
            "AAAAAAAAPDIDFCADCDADMCHCPCKDGCAAAAAAAABAIACE",
            "AAAAAAMDGCPCICPCBDKCPCMCICADIDGAAAAAAAFACACE",
            "AAMDAANDADOCMCADLDADGCOCMCICIDMBAAAAAANDNACE",
            "AAAAAAPDJDICOCPCDEADOCGCOCADPCPCMDAAAAFAABCE",
            "AAAAAABEPCMCFCECLDGCECOCFCADICMCCBAAAAPAMACE",
            "AAAAMDJCMCFCECECCDNCLBMCFCNCICOCMBAAAAEAKBCE",
            "AAAANDPCPCFCECFCICPCECECNCHCOCNCMCGAAAPAOBCE",
            "AAAAPDOCPCECECOCMCHDGCJBOCMCMCOCOCPAAABBMBCE",
            "AAAACBGCFCKBPAMCFCFCECPAECNBPBFCECCBAAODOBCE",
            "AAMDAECCACGBEBBEGBBEEBGBGBCEHBBEBEBEMDPDJCCE",
            "AAMDFDGDIBBEHBGBBEHBACHBBCEDLCFDHBDCJANDABCE",
            "AANDPDJAMAHAOAMAHAPAGAMANDODDBJAHAFAHAAAAACE",
            "EECECECECECECECECECECECECECECECECECECECECECE"]
        
        return wx.BitmapFromXPMData(xpm_icon_data)

##<--[inamura 120211]
    ##[inamura 160124]-->
    ##################################    
    def OnAxisGrid(self, *args):
        """
        AxisGridモード変更
        @param  *args    イベント情報
        @retval 無し
        """
        # AxisGridモードの設定または解除 
        ret = self.SetAxisGridBtn(self.GetToolState(self._GRIDON))
        
        ddic = self.ifi.GetProperty('gridstyledic')
        ddic["Show"]=ret
        # update D2Chart
        self.parent.d2.OnNotifyShowOnly2d(None,None,None)
        
    ##################################    
    def SetAxisGridBtn(self, flag): 
        """
        CURSOR ボタンオン/オフ処理
        @param  flag  True: On  False: Off
        @retval 無し
        """ 
        self.AxisGrid = flag 
        # Turn on/off Cursor button
        self.ToggleTool(self._GRIDON, flag)
        return flag

    ###################################################
    def GetAxisGridIconData(self):
        """
        Return Icom picture data as Bitmap
        Image text data is XPM format.
        @param None
        @retval wx.Bitmap
        """
        xpm_icon_data = [
            "24 24 4 1",
            " 	c None",
            ".	c #BACDF3",
            "+	c #000000",
            "@	c #8896B2",
            "                        ",
            " ...................... ",
            " ....+.....+.....+..... ",
            " ....+@....+@....+@.... ",
            " ....+@....+@....+@.... ",
            " ....+@....+@....+@.... ",
            " +++++++++++++++++++++. ",
            " .@@@+@@@@@+@@@@@+@@@@@ ",
            " ....+@....+@....+@.... ",
            " ....+@....+@....+@.... ",
            " ....+@....+@....+@.... ",
            " ....+@....+@....+@.... ",
            " .++++++++++++++++++++. ",
            " ..@@+@@@@@+@@@@+@@@@@@ ",
            " ....+@....+@....+@.... ",
            " ....+@....+@....+@.... ",
            " ....+@....+@....+@.... ",
            " ....+@....+@....+@.... ",
            " +++++++++++++++++++++. ",
            " .@@@+@@@@@+@@@@@+@@@@@ ",
            " ....+@....+@....+@.... ",
            " ....+@....+@....+@.... ",
            " .....@.....@.....@.... ",
            "                        "]
        
        return wx.BitmapFromXPMData(xpm_icon_data)
        ##<--[inamura 160124]


##[inamura 160124]-->
#########################################
#       SetAxisGridStyleDialog
#########################################
class SetAxisGridStyleDialog(wx.Dialog):
    """
    AxisGridStyle 設定ダイアログクラス
    """
    ##########################################################
    def __init__(self, parent, order, postfix):
        """
        コンストラクタ
        @param  parent   親ウィンドウのID
        @param  order  プロッタの起動順序
        @param  postfix 画面タイトルに付ける親の識別子    
        @retval 無し
        """ 
        
        self.ifi = IFEvtProp(order)
        self.parent = parent
        
        # リソース取得      
        self.res = ResourceFile(D2VISXRC)
        #self.res = ResourceFile('D2Vis') #[inamura 160401]
        self.dialog = self.res.GetDialog(parent, 'Dg2DGridSetting')
        # アイコンを設定
        self.dialog.SetIcon(Images().GetMainIcon())
        
        # ボタンのイベントハンドラを登録
        self.dialog.Bind(wx.EVT_BUTTON, self.OnClose, id=self.res.GetId('btClose'))
        
        # リソースよりコントロールを取得
        # コンボボックス
        self.cbXLC = self.res.GetCtrl(self.dialog, 'XlineColor')
        self.cbXLS = self.res.GetCtrl(self.dialog, 'XlineStyle')
        self.cbYLC = self.res.GetCtrl(self.dialog, 'YlineColor')
        self.cbYLS = self.res.GetCtrl(self.dialog, 'YlineStyle')
        
        # コンボボックスのイベントハンドラ登録
        self.cbXLC.Bind(wx.EVT_COMBOBOX, self.OnComboXLC, self.cbXLC)
        self.cbXLS.Bind(wx.EVT_COMBOBOX, self.OnComboXLS, self.cbXLS)
        self.cbYLC.Bind(wx.EVT_COMBOBOX, self.OnComboYLC, self.cbYLC)
        self.cbYLS.Bind(wx.EVT_COMBOBOX, self.OnComboYLS, self.cbYLS)

        # スピンボタン
        self.spinXLW = self.res.GetCtrl(self.dialog, 'XlineWidth')
        self.spinYLW = self.res.GetCtrl(self.dialog, 'YlineWidth')
        
        # スピンボタンのイベントハンドラ登録
        self.spinXLW.Bind(wx.EVT_SPINCTRL, self.OnSpinXLW, self.spinXLW)
        self.spinYLW.Bind(wx.EVT_SPINCTRL, self.OnSpinYLW, self.spinYLW)
        
        #[X]ボタン押下時のイベントハンドラ登録
        self.dialog.Bind(wx.EVT_CLOSE, self.OnClose)
        
        # ダイアログオープンイベント発行
        self.ifi.NotifyEvent(self, "setaxisgridstyle2ddg", False)
        
        # Set Values
        self.initialize()
        
        # ダイアログ表示
        self.dialog.Show()
        
    ##########################################################
    def initialize(self):
        """
        """
        ddic = self.ifi.GetProperty('gridstyledic')
        self.cbXLC.SetSelection( self._GetAttrNum( ddic["XlineColor"], TraceAtt.color )-1 )
        self.cbYLC.SetSelection( self._GetAttrNum( ddic["YlineColor"], TraceAtt.color )-1 )
        self.cbXLS.SetSelection( self._GetAttrNum( ddic["XlineStyle"], TraceAtt.linestyle ) )
        self.cbYLS.SetSelection( self._GetAttrNum( ddic["YlineStyle"], TraceAtt.linestyle ) )
        self.spinXLW.SetValue( self._GetAttrNum( ddic["XlineWidth"], TraceAtt.linewidth ) )
        self.spinYLW.SetValue( self._GetAttrNum( ddic["YlineWidth"], TraceAtt.linewidth ) )
        
    ##########################################################
    def _GetAttrNum(self, value, lst):
        """
        指定された値を検索しリストのインデックスに変換
        @param  value 値
        @param  lst 値
        @retval インデックス
        """ 
        # リストから指定された値を検索
        i = 0
        for item in lst:
            # 値と等しいか
            if item == value:
                # インデックスを返す
                return i
            i += 1
        # 検索できなかった場合
        return 0
    ##########################################################    
    def OnComboXLC(self, evt):
        """
        ラインColor変更イベント処理
        @param  evt イベント情報
        @retval 無し
        """
        lc = TraceAtt.color[self.cbXLC.GetSelection()+1]
        ddic = self.ifi.GetProperty('gridstyledic')
        ddic['XlineColor'] = lc
        self.ifi.NotifyEvent(self,'showonly2d', None)
    ##########################################################    
    def OnComboXLS(self, evt):
        """
        ラインスタイル変更イベント処理
        @param  evt イベント情報
        @retval 無し
        """
        ls = TraceAtt.linestyle[self.cbXLS.GetSelection()]
        ddic = self.ifi.GetProperty('gridstyledic')
        ddic['XlineStyle'] = ls
        self.ifi.NotifyEvent(self,'showonly2d', None)
    ##########################################################
    def OnSpinXLW(self, evt):
        """
        """
        lw = TraceAtt.linewidth[int(self.spinXLW.GetValue())]
        ddic = self.ifi.GetProperty('gridstyledic')
        ddic['XlineWidth'] = lw
        self.ifi.NotifyEvent(self,'showonly2d', None)
        
    ##########################################################    
    def OnComboYLC(self, evt):
        """
        ラインスタイル変更イベント処理
        @param  evt イベント情報
        @retval 無し
        """
        lc = TraceAtt.color[self.cbYLC.GetSelection()+1]
        ddic = self.ifi.GetProperty('gridstyledic')
        ddic['YlineColor'] = lc
        self.ifi.NotifyEvent(self,'showonly2d', None)
        
    ##########################################################    
    def OnComboYLS(self, evt):
        """
        ラインスタイル変更イベント処理
        @param  evt イベント情報
        @retval 無し
        """
        ls = TraceAtt.linestyle[self.cbYLS.GetSelection()]
        ddic = self.ifi.GetProperty('gridstyledic')
        ddic['YlineStyle'] = ls
        self.ifi.NotifyEvent(self,'showonly2d', None)
        
    ##########################################################
    def OnSpinYLW(self, evt):
        """
        """
        lw = TraceAtt.linewidth[int(self.spinYLW.GetValue())]
        ddic = self.ifi.GetProperty('gridstyledic')
        ddic['YlineWidth'] = lw
        self.ifi.NotifyEvent(self,'showonly2d', None)
        
    ##########################################################
    def OnClose(self, evt):
        """
        Closeボタンイベント処理
        @param  evt イベント情報
        @retval 無し
        """ 
        self.ifi.NotifyEvent(self, "setaxisgridstyle2ddg", True) 
        self.dialog.Destroy()

        
##<--[inamura 160124]
##[inamura 160726]-->
#########################################
#       SetAxisTickStyleDialog
#########################################
class SetAxisTickStyleDialog(wx.Dialog):
    """
    AxisTickStyle 設定ダイアログクラス
    """
    ##########################################################
    def __init__(self, parent, order, postfix):
        """
        コンストラクタ
        @param  parent   親ウィンドウのID
        @param  order  プロッタの起動順序
        @param  postfix 画面タイトルに付ける親の識別子    
        @retval 無し
        """ 
        
        self.ifi = IFEvtProp(order)
        self.parent = parent
        
        # リソース取得      
        self.res = ResourceFile(D2VISXRC)
        self.dialog = self.res.GetDialog(parent, 'Dg2TickStyleSetting')
        # アイコンを設定
        self.dialog.SetIcon(Images().GetMainIcon())
        
        # ボタンのイベントハンドラを登録
        self.dialog.Bind(wx.EVT_BUTTON, self.OnApply, id=self.res.GetId('btApply'))
        self.dialog.Bind(wx.EVT_BUTTON, self.OnRevert, id=self.res.GetId('btRevert'))
        self.dialog.Bind(wx.EVT_BUTTON, self.OnClose, id=self.res.GetId('btClose'))
        self.dialog.Bind(wx.EVT_BUTTON, self.OnApplyLW, id=self.res.GetId('btApplyFrameLW')) ##[inamura 160728]
        
        # リソースよりコントロールを取得
        # テキストボックスのコントローラ取得        
        self.txMajorLength = self.res.GetCtrl(self.dialog, 'txMajorLength')
        self.txMajorWidth = self.res.GetCtrl(self.dialog, 'txMajorWidth')
        self.txMinorLength = self.res.GetCtrl(self.dialog, 'txMinorLength')
        self.txMinorWidth = self.res.GetCtrl(self.dialog, 'txMinorWidth')
        self.txFrameLineWidth = self.res.GetCtrl(self.dialog, 'txFrameLineWidth') ##[inamura 160728]
        
        # チェックボックス
        self.ckUseMinorTick = self.res.GetCtrl(self.dialog, 'ckUseMinorTick')
        self.ckRightSideOn = self.res.GetCtrl(self.dialog, 'ckRightSideOn')
        self.ckTopSideOn = self.res.GetCtrl(self.dialog, 'ckTopSideOn')
        
        # チェックボックスのイベントハンドラ登録
        self.ckUseMinorTick.Bind(wx.EVT_CHECKBOX, self.OnUseMinorTick, self.ckUseMinorTick)
        self.ckRightSideOn.Bind(wx.EVT_CHECKBOX, self.OnRightSide, self.ckRightSideOn)
        self.ckTopSideOn.Bind(wx.EVT_CHECKBOX, self.OnTopSide, self.ckTopSideOn)

        ##[inamura 160728]-->
        self.chTickColor = self.res.GetCtrl(self.dialog, 'chTickColor')
        self.chTickColor.Bind(wx.EVT_CHOICE, self.OnTickColor, self.chTickColor)
        ##<--[inamura 160728]
        ##[inamura 170111]-->
        self.chBadColor = self.res.GetCtrl(self.dialog, 'chBadColor' )
        self.chBadColor.Bind(wx.EVT_CHOICE, self.OnBadColor, self.chBadColor)
        self.chBGColor = self.res.GetCtrl(self.dialog, 'chBGColor' )
        self.chBGColor.Bind(wx.EVT_CHOICE, self.OnBGColor, self.chBGColor)
        ##<--[inamura 170111]
        
        #[X]ボタン押下時のイベントハンドラ登録
        self.dialog.Bind(wx.EVT_CLOSE, self.OnClose)
        
        # ダイアログオープンイベント発行
        self.ifi.NotifyEvent(self, "setaxistickstyle2ddg", False)
        
        # Set Values
        self.initialize()
        
        pdict = self.ifi.GetProperty("tickstyledic")
        self.orgDict = pdict.copy()
        
        # ダイアログ表示
        self.dialog.Show()
        
        # to avoid parts in frame are shrinked
        if sys.platform =="darwin":
            self.dialog.SetSize( (310,440) )
        if sys.platform =="win32":
            self.dialog.SetSize( (320,450) )
        
    ##########################################################
    def initialize(self, evt=None):
        """
        """
        pdict = self.ifi.GetProperty("tickstyledic")
        self.txMajorLength.SetValue( str(pdict["MajorLength"]) )
        self.txMajorWidth.SetValue( str(pdict["MajorWidth"]) )
        self.txMinorLength.SetValue( str(pdict["MinorLength"]) )
        self.txMinorWidth.SetValue( str(pdict["MinorWidth"]) )
        self.txFrameLineWidth.SetValue( str(pdict["FrameLineWidth"]) ) ##[inamura 160728]
        flag = pdict["Minor"]
        self.ckUseMinorTick.SetValue( flag )
        self.txMinorLength.Enable(flag)
        self.txMinorWidth.Enable(flag)
        if pdict["TopSide"]=="on":
            self.ckTopSideOn.SetValue(True)
        else:
            self.ckTopSideOn.SetValue(False)
        if pdict["RightSide"]=="on":
            self.ckRightSideOn.SetValue(True)
        else:
            self.ckRightSideOn.SetValue(False)
        self.chTickColor.SetStringSelection( pdict["TickColor"] ) ##[inamura 160728]
        
    ##########################################################
    def OnUseMinorTick(self, evt=None):
        """
        UseMinorTick Check Boxイベント処理
        @param  evt イベント情報
        @retval 無し
        """
        pdict = self.ifi.GetProperty("tickstyledic")
        flag = self.ckUseMinorTick.GetValue()
        pdict["Minor"] = flag
        self.txMinorLength.Enable(flag)
        self.txMinorWidth.Enable(flag)
        self.ifi.NotifyEvent(self,'showonly2d', None)

    ##########################################################
    def OnTopSide(self, evt=None):
        """
        TopSideOn Check Boxイベント処理
        @param  evt イベント情報
        @retval 無し
        """
        pdict = self.ifi.GetProperty("tickstyledic")
        if self.ckTopSideOn.GetValue():
            pdict["TopSide"] = "on"
        else:
            pdict["TopSide"] = "off"
        self.ifi.NotifyEvent(self,'showonly2d', None)
        
    ##########################################################
    def OnRightSide(self, evt=None):
        """
        RightSideOn Check Boxイベント処理
        @param  evt イベント情報
        @retval 無し
        """
        pdict = self.ifi.GetProperty("tickstyledic")
        if self.ckRightSideOn.GetValue():
            pdict["RightSide"] = "on"
        else:
            pdict["RightSide"] = "off"
        self.ifi.NotifyEvent(self,'showonly2d', None)

    ##[inamura 160728]-->
    ##########################################################
    def OnTickColor(self, evt=None):
        """
        Tick color changeイベント処理
        @param  evt イベント情報
        @retval 無し
        """
        pdict = self.ifi.GetProperty("tickstyledic")
        pdict["TickColor"] = self.chTickColor.GetStringSelection()
        self.ifi.NotifyEvent(self,'showonly2d', None)


    ##########################################################
    def OnApplyLW(self, evt=None):
        """
        Apply Frame Line Widthボタンイベント処理
        @param  evt イベント情報
        @retval 無し
        """ 
        pdict = self.ifi.GetProperty("tickstyledic")
        pdict["FrameLineWidth"]  = float( self.txFrameLineWidth.GetValue() )
        self.ifi.NotifyEvent(self,'showonly2d', None)
        
    ##<--[inamura 160728]
    ##########################################################
    def OnApply(self, evt=None):
        """
        Applyボタンイベント処理
        @param  evt イベント情報
        @retval 無し
        """ 
        pdict = self.ifi.GetProperty("tickstyledic")
        pdict["MajorLength"] = float( self.txMajorLength.GetValue() )
        pdict["MajorWidth"]  = float( self.txMajorWidth.GetValue() )
        pdict["MinorLength"] = float( self.txMinorLength.GetValue() )
        pdict["MinorWidth"]  = float( self.txMinorWidth.GetValue() )
        self.ifi.NotifyEvent(self,'showonly2d', None)

    ##########################################################
    def OnRevert(self, evt=None):
        """
        Revertボタンイベント処理
        @param  evt イベント情報
        @retval 無し
        """ 
        pdict = self.ifi.GetProperty("tickstyledic")
        for a_key in pdict.keys():
            pdict[a_key] = self.orgDict[a_key]
        self.initialize()
        
        self.ifi.NotifyEvent(self,'showonly2d', None)
        
    ##########################################################
    def OnClose(self, evt=None):
        """
        Closeボタンイベント処理
        @param  evt イベント情報
        @retval 無し
        """ 
        self.ifi.NotifyEvent(self, "setaxistickstyle2ddg", True) 
        self.dialog.Destroy()

    ##[inamura 170111]-->
    ##########################################################
    def OnBadColor(self, evt=None):
        """
        Bad color changeイベント処理
        @param  evt イベント情報
        @retval 無し
        """
        pdict = self.ifi.GetProperty("tickstyledic")
        pdict["BadColor"] = self.chBadColor.GetStringSelection()
        self.ifi.NotifyEvent(self,'showonly2d', None)
    ##########################################################
    def OnBGColor(self, evt=None):
        """
        Background color changeイベント処理
        @param  evt イベント情報
        @retval 無し
        """
        pdict = self.ifi.GetProperty("tickstyledic")
        pdict["BGColor"] = self.chBGColor.GetStringSelection()
        self.ifi.NotifyEvent(self,'showonly2d', None)
    ##<--[inamura 170111]
    
##<--[inamura 160726]
##[inamura 160218]-->
#########################################
#       SetSaveAsTextDialog
#########################################
class SetSaveAsTextDialog(wx.Dialog):
    """
    SaveAsText 設定ダイアログクラス
    """
    ##########################################################
    def __init__(self, parent, order, postfix, dataobj=None):
        """
        コンストラクタ
        @param  parent   親ウィンドウのID
        @param  order  プロッタの起動順序
        @param  postfix 画面タイトルに付ける親の識別子    
        @param  dataobj
        @retval 無し
        """ 
        
        self.ifi = IFEvtProp(order)
        self.parent = parent
        self.dmap = dataobj
        
        # リソース取得      
        #self.res = ResourceFile('D2Vis')
        self.res = ResourceFile(D2VISXRC) #[inamura 160401]
                
        self.dialog = self.res.GetDialog(parent, 'Dg2DSaveAsText')
        # アイコンを設定
        self.dialog.SetIcon(Images().GetMainIcon())
        
        # チェックボックス
        self.ckIgnoreMask = self.res.GetCtrl(self.dialog, 'ckIgnoreMask')
        
        # チェックボックスのイベントハンドラ登録
        self.ckIgnoreMask.Bind(wx.EVT_CHECKBOX, self.OnIgnoreMask, self.ckIgnoreMask)
        
        # コンボボックス
        self.chMaskVal = self.res.GetCtrl(self.dialog, 'chMaskValue')
        
        # コンボボックスのイベントハンドラ登録
        self.chMaskVal.Bind(wx.EVT_CHOICE, self.OnMaskVal, self.chMaskVal)
        
        # テキストボックスのコントローラ取得        
        self.txMaskVal = self.res.GetCtrl(self.dialog, 'txMaskValue')
        self.txQbin = self.res.GetCtrl(self.dialog, 'txQbin' )
        self.stQbin = self.res.GetCtrl(self.dialog, 'stQbin' )
        
        # ボタンのイベントハンドラを登録
        self.btnSave = self.res.GetCtrl( self.dialog, 'btSave' )
        self.btnCancel = self.res.GetCtrl( self.dialog, 'btCancel' )
        self.btnSave.Bind(wx.EVT_BUTTON, self.OnSave, self.btnSave )
        self.btnCancel.Bind(wx.EVT_BUTTON, self.OnCancel, self.btnCancel )
        #self.dialog.Bind(wx.EVT_BUTTON, self.OnSave, id=self.res.GetId('btSave'))
        #self.dialog.Bind(wx.EVT_BUTTON, self.OnCancel, id=self.res.GetId('btCancel'))
        
        #[X]ボタン押下時のイベントハンドラ登録
        self.dialog.Bind(wx.EVT_CLOSE, self.OnCancel)
        
        # Set Values
        self.initialize()
        
        # ダイアログ表示
        self.dialog.Show()
        
    ##########################################################
    def initialize(self):
        """
        """
        self.isIgnoreMask = True
        self.useGivenMaskVal = True
        self.ckIgnoreMask.SetValue(True)
        self.chMaskVal.Enable(False)
        self.txMaskVal.Enable(False)
        if self.dmap.type==0:
            self.txQbin.Enable(False)
            self.stQbin.Enable(False)
        else:
            self.txQbin.Enable(True)
            self.stQbin.Enable(True)
        return
        
    ##########################################################
    def OnIgnoreMask(self, event=None):
        """
        IgnoreMask チェックボックスイベント処理
        @param   event イベント情報   
        @retval 無し
        """ 
        # チェックされたのか
        self.isIgnoreMask = self.ckIgnoreMask.GetValue()
        if self.isIgnoreMask:
            # MaskValue テキストボックスを選択不可
            self.chMaskVal.Enable(False)
            self.txMaskVal.Enable(False)
        else:  
            self.chMaskVal.Enable(True)
            self.txMaskVal.Enable(False)
            index = self.chMaskVal.GetSelection()
            if index==0:
                self.txMaskVal.Enable(True)
                
    ##########################################################
    def OnMaskVal(self, event=None):
        """
        
        """
        self._CtrlParts(True)
        
    ##########################################################
    def OnSave(self, event=None):
        """
        """
        self._CtrlParts(False)
        maskval = 0.0
        if (not self.isIgnoreMask) and self.useGivenMaskVal:
            try:
                maskval = float( self.txMaskVal.GetValue() )
            except:
                msg = "Given Mask Value is invalid (%s)"%(self.txMaskVal.GetValue())
                dial = wx.MessageDialog(None, msg, "Warning", wx.OK | wx.ICON_EXCLAMATION )
                dial.ShowModal()
                self._CtrlParts(True)
                return
        dQ=0.0
        if self.dmap.type!=0:
            try:
                dQ = float( self.txQbin.GetValue() )
            except:
                msg = "Given Q-bin Value is invalid (%s)"%(self.txQbin.GetValue())
                dial = wx.MessageDialog(None, msg, "Warning", wx.OK | wx.ICON_EXCLAMATION )
                dial.ShowModal()
                self._CtrlParts(True)
                return
        
        maskinfo=[self.useGivenMaskVal, maskval ]
        dlg =wx.FileDialog(self.parent, "Save data as text files", style=wx.SAVE, wildcard='Text(*.txt)|*.txt')
        if dlg.ShowModal() == wx.ID_OK:
            self.dmap.SaveAsText2(dlg.GetPath(),dQ,self.isIgnoreMask,maskinfo)
            self.OnCancel()
            
        self._CtrlParts(True)

    ##########################################################
    def _CtrlParts(self, isEnable=True):
        """
        """
        if not isEnable in [True,False]:
            return
            
        if isEnable:
            self.btnSave.Enable(True)
            self.btnCancel.Enable(True)
            self.ckIgnoreMask.Enable(True)
            if self.isIgnoreMask:
                self.chMaskVal.Enable(False)
                self.txMaskVal.Enable(False)
            else:
                self.chMaskVal.Enable(True)
                self.txMaskVal.Enable(False)
                index = self.chMaskVal.GetSelection()
                self.useGivenMaskVal = True
                if index==0:
                    self.txMaskVal.Enable(True)
                    pass
                elif index==1:
                    self.txMaskVal.SetValue( str(0.0) )
                elif index==2:
                    self.txMaskVal.SetValue( str(-1.0) )
                else:
                    self.useGivenMaskVal = False
                    self.txMaskVal.SetValue( "" )
        else:
            self.ckIgnoreMask.Enable(False)
            self.chMaskVal.Enable(False)
            self.txMaskVal.Enable(False)
            self.btnSave.Enable(False)
            self.btnCancel.Enable(False)
            
            
    ##########################################################
    def OnCancel(self, evt=None):
        """
        Cancel ボタンイベント処理
        @param  evt イベント情報
        @retval 無し
        """ 
        
        self.dialog.Destroy()        
        
##<-[inamura 160218]

#########################################
#       Title2DDialog
#########################################
class Title2DDialog(wx.Dialog):
    """
    タイトル設定ダイアログクラス
    """
    ##########################################################
    def __init__(self, parent, order, postfix):
        """
        コンストラクタ
        @param  parent   親ウィンドウのID
        @param  order  プロッタの起動順序
        @param  postfix 画面タイトルに付ける親の識別子    
        @retval 無し
        """ 

        self.ifi = IFEvtProp(order)
        
        # リソース取得      
        res = ResourceFile(D2VISXRC)
        #res = ResourceFile('D2Vis') #[inamura 160401]
        self.dialog = res.GetDialog(parent, 'Dg2DTitle')
        
        if order > 0:
            # タイトル文字列を取得
            strT = self.dialog.GetTitle()
            # 順番を付してタイトル文字列を作成
            self.dialog.SetTitle(strT + postfix)
        
        # テキストボックスのコントローラ取得        
        self.text1 = res.GetCtrl(self.dialog, 'tx1')
        self.text2 = res.GetCtrl(self.dialog, 'tx2')
        
        self.text1.SetValue(self.ifi.GetProperty("title1"))
        self.text2.SetValue(self.ifi.GetProperty("title2"))
        # ボタンのイベントハンドラ登録
        self.dialog.Bind(wx.EVT_BUTTON, self.OnOk, id=res.GetId('btOk'))
        self.dialog.Bind(wx.EVT_BUTTON, self.OnCancel, id=res.GetId('btCancel'))
        #[X]ボタン押下時のイベントハンドラ登録
        self.dialog.Bind(wx.EVT_CLOSE, self.OnCancel)
        # ダイアログオープンイベント発行
        self.ifi.NotifyEvent(self, "title2ddg", False) ##[inamura 121029]
        
        ##[inamura 120711]-->
        # Font Info
        ifdrawdic = self.ifi.GetProperty('drawdic')
        self.isOnly = self.ifi.GetProperty('only2d')
        self.init_drawdic = None
        if self.isOnly:
            self.init_drawdic = ifdrawdic["SingleMode"].copy()
        else:
            self.init_drawdic = ifdrawdic["MultiMode"].copy()

        self.spinFS = res.GetCtrl(self.dialog,'spFS')
        self.spinFS.Bind(wx.EVT_SPINCTRL, self.OnSetFont, self.spinFS)
        self.spinFS.SetValue( self.init_drawdic["TitleSize"] )
        
        self.chFontName = res.GetCtrl(self.dialog, 'chFontName')
        self.chFontName.Bind(wx.EVT_CHOICE, self.OnSetFont, self.chFontName)
        fdic = self.ifi.GetProperty('drawdic')
        fnl = fdic["FontList"]
        for it_fnl in fnl:
            self.chFontName.Append(it_fnl)
        self.chFontName.SetStringSelection( self.init_drawdic["TitleFont"] )
        ##<--[inamura 120711]
                
        # ダイアログ表示
        self.dialog.ShowModal()

    ##########################################################
    def OnOk(self, evt):
        """
        OK ボタンイベント処理
        @param  evt イベント情報
        @retval 無し
        """ 
        # テキストボックスから値を取得
        main = self.text1.GetValue()
        sub = self.text2.GetValue()
        try:
            # 日本語文字列が含まれているかどうかをチェック
            try:
                str(main)
            except:
                raise PlotException('Common', 'C025', ("Main Title",))
            try:
                str(sub)
            except:
                raise PlotException('Common', 'C025', ("Sub Title",))
        except PlotException, ex:
            PlotMessage(self.dialog, ex)
        
        else:    
            # 前と変わらなかったら
            if self.ifi.GetProperty("title1") == main:
                # 変更無記号を送信(自動更新を解除しないため)
                # 注: 一度メインタイトル変更すると、自動更新モードを解除する
                # サブタイトルは、自動更新モードに影響しない
                main = '*'
            # タイトル変更要求送信    
            self.ifi.NotifyEvent(self, "title", (main, sub))
            
            self.ifi.NotifyEvent(self, "title2ddg", True) ##[inamura 121029]
            
            self.dialog.EndModal(self.dialog.GetReturnCode()) #[inamura 160229]
            self.dialog.Destroy()
          
    ##########################################################
    def OnCancel(self, evt):
        """
        Cancel ボタンイベント処理
        @param  evt イベント情報
        @retval 無し
        """ 
        ##[inamura 120711]-->
        params = []
        params.append(['TitleSize', self.init_drawdic["TitleSize"]])
        params.append(['TitleFont', self.init_drawdic["TitleFont"]])
        self.ifi.NotifyEvent(self, 'setdrawinfo', params )
        ##<--[inamrua 120711]
        
        self.ifi.NotifyEvent(self, "title2ddg", True) ##[inamura 121029]
        
        self.dialog.EndModal(self.dialog.GetReturnCode()) #[inamura 160229]
        self.dialog.Destroy()        
        
    ##[inamura 120711]-->
    ##########################################################
    def OnSetFont(self, evt):
        """
        """
        params = []
        params.append(['TitleSize', self.spinFS.GetValue()])
        params.append(['TitleFont',self.chFontName.GetStringSelection()])
                       
        self.ifi.NotifyEvent(self, 'setdrawinfo', params )
    ##<--[inamura 120711]



#########################################
#       ScaleLabel3Dialog
#########################################
class ScaleLabel3Dialog(wx.Dialog):
    """
    スケールラベル設定ダイアログクラス
    """
    ##########################################################
    def __init__(self,parent, order, postfix):
        """
        コンストラクタ
        @param  parent   親ウィンドウのID
        @param  order  プロッタの起動順序
        @param  postfix
        @retval 無し
        """ 

        self.ifi = IFEvtProp(order)
        
        # リソース取得      
        res = ResourceFile(D2VISXRC)
        self.dialog = res.GetDialog(parent, 'Dg2ScaleLabel')
        
        # タイトル文字列を取得
        strT = self.dialog.GetTitle()
        # 順番を付してタイトル文字列を作成
        self.dialog.SetTitle(strT + postfix)
 
        # テキストボックスのコントローラ取得        
        self.xlabel = res.GetCtrl(self.dialog, 'xlabel')
        self.ylabel = res.GetCtrl(self.dialog, 'ylabel')
        self.zlabel = res.GetCtrl(self.dialog, 'zlabel')
        # プロパティを取得
        xl= self.ifi.GetProperty("xlabel")
        yl= self.ifi.GetProperty("ylabel")
        zl= self.ifi.GetProperty("zlabel")
        
        # プロパティが取得できたら、テキストボックスに設定
        self.xlabel.SetValue(xl)
        self.ylabel.SetValue(yl)
        self.zlabel.SetValue(zl)
            
        # ボタンのイベントハンドラ登録
        self.dialog.Bind(wx.EVT_BUTTON, self.OnOk, id=res.GetId('btOk'))
        self.dialog.Bind(wx.EVT_BUTTON, self.OnCancel, id=res.GetId('btCancel'))
        #[X]ボタン押下時のイベントハンドラ登録
        self.dialog.Bind(wx.EVT_CLOSE, self.OnCancel)
        
        ##[inamura 120711]-->
        # Font Info
        ifdrawdic = self.ifi.GetProperty('drawdic')
        self.isOnly = self.ifi.GetProperty('only2d')
        self.init_drawdic = None
        if self.isOnly:
            self.init_drawdic = ifdrawdic["SingleMode"].copy()
        else:
            self.init_drawdic = ifdrawdic["MultiMode"].copy()

        self.spinFS = res.GetCtrl(self.dialog,'spFS')
        self.spinFS.Bind(wx.EVT_SPINCTRL, self.OnSetFont, self.spinFS)
        self.spinFS.SetValue( self.init_drawdic["LabelSize"] )
        
        self.chFontName = res.GetCtrl(self.dialog, 'chFontName')
        self.chFontName.Bind(wx.EVT_CHOICE, self.OnSetFont, self.chFontName)
        fdic = self.ifi.GetProperty('drawdic')
        fnl = fdic["FontList"]
        for it_fnl in fnl:
            self.chFontName.Append(it_fnl)
        self.chFontName.SetStringSelection( self.init_drawdic["LabelFont"] )
        ##<--[inamura 120711]

        # ダイアログオープンイベント発行
        self.ifi.NotifyEvent(self, "scalelabel3dg", False) ##[inamura 121029]
        
        # ダイアログ表示
        self.dialog.ShowModal()
        

    ##########################################################
    def OnOk(self,evt):
        """
        OK ボタンイベント処理
        @param  evt イベント情報
        @retval 無し
        """ 
        # テキストボックスから値を取得
        xlabel = self.xlabel.GetValue()
        ylabel = self.ylabel.GetValue()
        zlabel = self.zlabel.GetValue()
        try:        # エレメントコンテナ変換クラスのインスタンス取得?
#        self.ce = ConvertEC()
            # 日本語文字列が含まれているかどうかをチェック
            try:
                str(xlabel)
            except:
                raise PlotException('Common','C025',("X Label",))
            try:
                str(ylabel)
            except:
                raise PlotException('Common','C025',("Y Label",))
            try:
                str(zlabel)
            except:
                raise PlotException('Common','C025',("Z Label",))
                        
        except PlotException, ex:
            PlotMessage(self.dialog,ex)
        else:    
            self.ifi.NotifyEvent(self, "scalelabel", (xlabel,ylabel,zlabel))
            self.ifi.NotifyEvent(self, "scalelabel3dg", True) ##[inamura 121029]
            self.dialog.EndModal(self.dialog.GetReturnCode()) #[inamura 160229]
            self.dialog.Destroy()
          
    ##########################################################
    def OnCancel(self,evt):
        """
        Cancel ボタンイベント処理
        @param  evt イベント情報
        @retval 無し
        """ 
        ##[inamura 120711]-->
        params = []
        params.append(['LabelSize', self.init_drawdic["LabelSize"]])
        params.append(['LabelFont', self.init_drawdic["LabelFont"]])
        self.ifi.NotifyEvent(self, 'setdrawinfo', params )
        ##<--[inamrua 120711]
        
        self.ifi.NotifyEvent(self, "scalelabel3dg", True) ##[inamura 121029]
        
        self.dialog.EndModal(self.dialog.GetReturnCode()) #[inamura 160229]
        self.dialog.Destroy()        
        
    ##[inamura 120711]-->
    ##########################################################
    def OnSetFont(self, evt):
        """
        """
        params = []
        params.append(['LabelSize', self.spinFS.GetValue()])
        params.append(['LabelFont',self.chFontName.GetStringSelection()])
                       
        self.ifi.NotifyEvent(self, 'setdrawinfo', params )
    ##<--[inamura 120711]

#######################################
#  SlicingPanel
#######################################  
class SlicingPanel(object):
    
    """
    スライス条件パネル
    """

    #########################################
    def __init__(self, frame, panel, id, order):
        """
        スライス条件パネルの初期化、コントロールを取得、
        イベントハンドラ登録等を実行
        @param  frame  フレームID
        @param  panel  XパネルまたはYパネルのID
        @param  id     X=1, Y=2
        @param  order  イベントディスパッチャのID
        @retval 無し
        """ 
        # 入力チェッククラスのインスタンスを取得、親ウィンドウは、MapD2Frame
        self.val = Validator(frame)

        self.id = id
        # プロッタのインターフェイスを取得
        self.ifi = IFEvtProp(order)
        #res = ResourceFile('D2Vis')
        res = ResourceFile(D2VISXRC) #[inamura 160401]
        # コントロールを取得
        self.txV = res.GetCtrl(panel, 'value')
        self.txdiff = res.GetCtrl(panel, 'dif')
        self.txr0 = res.GetCtrl(panel, 'tx0')
        self.txr1 = res.GetCtrl(panel, 'tx1')
        self.rdCenter = res.GetCtrl(panel, 'rdcenter')
        self.rdRange = res.GetCtrl(panel, 'rdrange')
        ## [KCS 130520]-->
        #self.frac = res.GetCtrl(panel, 'spfrac')
        self.ckAuto = res.GetCtrl(panel, 'ckAuto')
        self.txDelta = res.GetCtrl(panel, 'txDelta')
        ## <--[KCS 130520]
        self.ckrbin = res.GetCtrl(panel, 'ckrb')
        self.txbin = res.GetCtrl(panel, 'bin')
        self.ckwith = res.GetCtrl(panel, 'ckwith')

        # ラジオボタンのイベントハンドラ登録
        self.rdCenter.Bind(wx.EVT_RADIOBUTTON, self.OnCenter, self.rdCenter)
        self.rdRange.Bind(wx.EVT_RADIOBUTTON, self.OnRange, self.rdRange) 
        
        # チェックボックスのイベントハンドラ登録
        self.ckrbin.Bind(wx.EVT_CHECKBOX, self.OnRebin, self.ckrbin)
        self.ckAuto.Bind(wx.EVT_CHECKBOX, self.OnAutoSlice, self.ckAuto)

        #ボタンのイベントハンドラ登録
        panel.Bind(wx.EVT_BUTTON, self.OnBtShow, id=res.GetId('btshow'))
        panel.Bind(wx.EVT_BUTTON, self.OnBtAppend, id=res.GetId('btappend'))
        panel.Bind(wx.EVT_BUTTON, self.OnBtClear, id=res.GetId('btclear'))
        
        # プロッタを初期化
        self.plot = None
        self.sliceParams = (0.0, 0.0, 1.0, 0.0, False)
        
        # スライス条件変更のリスナー登録
        self.ifi.AddListner('slicex',  self.OnNotifySlice)
        self.ifi.AddListner('slicey',  self.OnNotifySlice)
        self.ifi.AddListner('slicexrange',  self.OnNotifySliceRange)
        self.ifi.AddListner('sliceyrange',  self.OnNotifySliceRange)
        # スライス条件取得要求のリスナ登録
        self.ifi.AddListner('pickparams',  self.OnNotifyPickParams)
        # プロッタ送信モード変更得要求のリスナ登録
        self.ifi.AddListner('setwith',  self.OnNotifySetWith)

        # 公開プロパティを登録
        if id ==1:
            self.ifi.AddProperty('xparam',  lambda : self.sliceParams)
        else:
            self.ifi.AddProperty('yparam',  lambda : self.sliceParams)

    #########################################    
    def OnNotifyPickParams(self, wid, evt, value=None):
        """
        パネルからスライス条件を取得
        @param  wid イベント発生元のインスタンス
        @param  evt イベントタイプ
        @param  value 
        @retval　無し
        """ 
        # 中心値指定か
        if self.rdCenter.GetValue():
            try:
                # 中心値を取得
                pos = float(self.txV.GetValue())
            except:
                pos = 0.0
                self.txV.SetValue("0.000")
            try:  
                #　加減算値を取得  
                diff= float(self.txdiff.GetValue())
            except:
                diff = 0.0
                self.txdiff.SetValue("0.000")
            if diff < 0.0:
                diff = 0.0
                self.txdiff.SetValue("0.000")        
            r0 = pos - diff
            r1 = pos + diff
            # 中心値指定の場合は、切片数は常に1
            frac = 1
        # レンジ指定
        else:
            try:
                # 始値を取得
                r0 = float(self.txr0.GetValue())
            except:
                r0 = 0.0
            try: 
                # 終値を取得   
                r1 = float(self.txr1.GetValue())
            except:
                r1 = r0 + 1.0
            ## [KCS 130520]-->            
            # 分割数を取得
            #try:
            #    frac = int(self.frac.GetValue())
            #except:
            #    frac = 1
            #if r0 > r1:
            #    r1 = r0
            #    frac = 1
            #strR0 = "%.3f" % r0
            #self.txr0.SetValue(strR0)
            #strR1 = "%.3f" % r1 
            #self.txr1.SetValue(strR1)   
            #self.frac.SetValue(frac)

            # 自動スライスが指定されているか
            if self.ckAuto.GetValue():
                try:
                    # 分割時のデルタ値を取得
                    try:
                        delta = float(self.txDelta.GetValue())
                    except:
                        raise PlotException('Common', 'C027', ("Delta", ))
                    if delta <= 0.0:
                        raise PlotException('Common', 'C009', ("Delta", "0.0"))
                except PlotException, ex:
                    PlotMessage(self.self.panel,ex)
                    return
                
                # 中心値 0.0 を始点に範囲を求める
                r00 = 0.0-delta/2.0
                if r0 >= 0.0:
                    while True:
                        if r00 >= r0:
                            r0 = r00
                            break
                        r00 += delta
                else:
                    while True:
                        if r00 <= r0:
                            r0 = r00
                            break
                        r00 -= delta
                r00 = r0
                while True:
                    if r00 > r1:
                        r1 = r00 - delta
                        break
                    r00 += delta
                frac = int((r1-r0)/delta+ 0.1)
                print "frac: ", frac
                self.txDelta.SetValue("%.3f" % delta)
                self.txr0.SetValue("%.3f" % r0)
                self.txr1.SetValue("%.3f" % r1)
            else:
                frac = 1
            ##<-- [KCS 130520]
            
        # リビニングが指定されているか
        if self.ckrbin.GetValue():
            try:
                binI = float(self.txbin.GetValue())
                # 負値だったら
                if binI < 0.0:
                    self.txbin.SetValue("0.000")
                    binI = 0.0
            except:
                # 文字列等は空白とみなす
                self.txbin.SetValue("0.000")
                binI = 0.0 
        else:
            binI = 0.0
    
        self.sliceParams = (r0, r1, frac, binI, self.ckwith.GetValue()) 

    ######################################################
    def OnNotifySlice(self, wid, evt, params):
        """
        スライス条件指定イベント処理
        @param  wid イベント発生元のインスタンス
        @param  evt イベントタイプ
        @param  params スライス条件のタプル
        @retval 無し
        """ 

        # X パネルか
        if evt=="slicex" and self.id == 1 :
            self.SetCenterValue(params[0], params[1], params[2])
        elif evt=="slicey" and self.id == 2:
            self.SetCenterValue(params[0], params[1], params[2])
        
    ######################################################
    def OnNotifySliceRange(self, wid, evt, params):
        """
        スライスレンジ条件指定イベント処理
        @param  wid イベント発生元のインスタンス
        @param  evt イベントタイプ
        @param  params スライス条件のタプル
        @retval 無し
        """ 
        # X パネルか
        if evt=="slicexrange" and self.id == 1 :
            self.SetRangeValues(params[0], params[1], params[2], params[3])
        elif evt=="sliceyrange" and self.id == 2:
            self.SetRangeValues(params[0], params[1], params[2], params[3])
    
    #########################################    
    def SetCenterValue(self, pos, diff = None, bin = None):
        """
        中心位置と範囲をテキストボックスに反映
        @param   pos   中心位置   
        @param   diff  範囲 
        @param   bin   ビン値  
        @retval　無し
        """ 
        # テキストボックスへの設定文字列作成
        strV = "%.3f" % pos
        # 中心値に設定
        self.txV.SetValue(strV)
        # 範囲が指定されているか
        if not diff == None:
            # 範囲をテキストボックスへ設定
            strDiff = "%.3f" % diff
            self.txdiff.SetValue(strDiff)
        # リビニング値が指定されているか
        if not bin == None:
            # ビン値をテキストボックスへ設定
            strBin = "%.3f" % bin
            self.txbin.SetValue(strBin)
            if bin > 0.0:
                binflag = True
            else:
                binflag = False
            # ビンモードを変更
            self.ckrbin.SetValue(binflag)
            self.OnRebin()
        # ラジオボタンを On にセット
        self.rdCenter.SetValue(True)
        self.OnCenter()

    #########################################
    def SetRangeValues(self, pos0, pos1, delta=0.0, bin = None):
        """
        積算範囲をテキストボックスに反映
        @param   pos0  レンジ始値  
        @param   pos1  レンジ終値 
        @param   delta 分割数 
        @param   bin   ビン値   
        @retval　無し
        """ 
        # テキストボックスへの設定文字列作成
        strR0 = "%.3f" % pos0
        strR1 = "%.3f" % pos1
        
        # レンジテキストボックスに設定
        self.txr0.SetValue(strR0)
        self.txr1.SetValue(strR1)
        # ラジオボタンを On にセット
        self.rdRange.SetValue(True)

        ## [KCS 130520]-->
        # 分割数が指定されていたなら
        if delta > 0.0:
            # テキストボックスに値を設定
            self.txDelta.SetValue("%.3f" % delta)
        else:
            self.txDelta.SetValue("")
        #if not fract == None:
            # スピンボックスに値を設定
        #    self.frac.SetValue(fract)
        ##<-- [KCS 130520]
        
        # リビニング値が指定されているか
        if not bin == None:
            # ビン値をテキストボックスへ設定
            strBin = "%.3f" % bin
            self.txbin.SetValue(strBin)
            if bin > 0.0:
                binflag = True
            else:
                binflag = False
            # ビンモードを変更
            self.ckrbin.SetValue(binflag)
            self.OnRebin()
            
        self.OnRange()

    ######################################################
    def OnNotifySetWith(self, wid, evt, params):
        """
        プロッタ送信モード変更イベント処理
        @param  wid イベント発生元のインスタンス
        @param  evt イベントタイプ
        @param  params プロッタ送信モード条件のタプル
        @retval 無し
        """ 
        # X パネルに対する要求か
        if params[1]==1 or params[1]==3 :
            if self.id == 1:
                self.ckwith.SetValue(params[0])
        # Y パネルに対する要求か        
        if params[1]==2 or params[1]==3 :
            if self.id == 2:
                self.ckwith.SetValue(params[0])

    ##<--[KCS: 130520]
    #########################################    
    def OnAutoSlice(self, event=None):
        """
        Rebinning チェックボックスイベント処理
        @param   event イベント情報   
        @retval 無し
        """ 
        # チェックされたのか
        if self.ckAuto.GetValue():
            # Delat テキストボックスを選択不可
            self.txDelta.Enable(True) 
        else:  
            self.txDelta.Enable(False)
    ##--> [KCS: 130520]
    
    #########################################    
    def OnCenter(self, event=None):
        """
        Centerラジオボタン押下イベント処理
        @param   event イベント情報   
        @retval 無し
        """ 
        # チェックされたのか
        if self.rdCenter.GetValue():
            # Value と diff テキストボックスを選択可
            self.txV.Enable(True)   
            self.txdiff.Enable(True)
            # Range テキストボックスを選択不可
            self.txr0.Enable(False)   
            self.txr1.Enable(False)
            ## [KCS 130520]-->
            self.ckAuto.SetValue(False)
            self.ckAuto.Enable(False)
            self.txDelta.Enable(False)
            # Fracturing スピンボタンを選択不可
            #self.frac.Enable(False)
            ##<-- [KCS 130520]
            # Range ラジオボタンのチェックを外す
            self.rdRange.SetValue(False)

    #########################################    
    def OnRange(self, event=None):
        """
        Rangeラジオボタン押下イベント処理
        @param   event イベント情報   
        @retval 無し
        """ 
        # チェックされたのか
        if self.rdRange.GetValue():
            # Value と diff テキストボックスを選択不可
            self.txV.Enable(False)   
            self.txdiff.Enable(False)
            # Range テキストボックスを選択可
            self.txr0.Enable(True)   
            self.txr1.Enable(True)
            ## [KCS 130520]-->
            self.ckAuto.Enable(True)
            # Fracturing スピンボタンを選択不可
            #self.frac.Enable(True)
            # Range ラジオボタンのチェックを外す
            ##<-- [KCS 130520]
            self.rdCenter.SetValue(False) 
    
    #########################################    
    def OnRebin(self, event=None):
        """
        Rebinning チェックボックスイベント処理
        @param   event イベント情報   
        @retval 無し
        """ 
        # チェックされたのか
        if self.ckrbin.GetValue():
            # bin テキストボックスを選択不可
            self.txbin.Enable(True) 
        else:  
            self.txbin.Enable(False)

    #########################################    
    def OnBtShow(self, event):
        """
        Showボタン押下イベント処理
        @param   event イベント情報   
        @retval 無し
        """ 
        self.ifi.NotifyEvent(self, "show", self.id)
        
    #########################################    
    def OnBtAppend(self, event):
        """
        Appendボタン押下イベント処理
        @param   event イベント情報   
        @retval 無し
        """ 
        self.ifi.NotifyEvent(self, "add", self.id)    
    
    #########################################    
    def OnBtClear(self, event):
        """
        Peplace(X)ボタン押下イベント処理
        @param   event イベント情報   
        @retval 無し
        """ 
        # データクリア要求発行
        self.ifi.NotifyEvent(self, "clear", self.id)  

#######################################
#  ZScalePanel
#######################################  
class ZScalePanel(object):
    """
    Z　スケールパネルクラス
    """

    #########################################
    def __init__(self, panel, order):
        """
        Zスケールパネルのコントロールクラス
        @param  panel  ZパネルのID
        @param  order イベントディスパッチャのID
        @retval 無し
        """ 
        #res = ResourceFile('D2Vis')
        res = ResourceFile(D2VISXRC) #[inamura 160401]
        # ボタンのイベントハンドラ登録
        panel.Bind(wx.EVT_BUTTON, self.OnBtzApply, id=res.GetId('btzapply'))
        # コントロールの取得
        self.ckauto = res.GetCtrl(panel, 'ckauto')
        self.cklog = res.GetCtrl(panel, 'cklog')
        self.txz0 = res.GetCtrl(panel, 'z0')
        self.txz1 = res.GetCtrl(panel, 'z1')
        self.btzApply = res.GetCtrl(panel, 'btzapply')
        ##[inamura 101022]-->
        self.cksmooth = res.GetCtrl(panel, 'cksmooth')
        self.txsmooth = res.GetCtrl(panel, 'window')
        ##<--[inamura 101022]
        ##[inamura 160627]-->
        self.ckXlog = res.GetCtrl(panel, 'ckXlog')
        self.ckYlog = res.GetCtrl(panel, 'ckYlog')
        self.ckXlog.Bind(wx.EVT_CHECKBOX, self.OnLogX, self.ckXlog) 
        self.ckYlog.Bind(wx.EVT_CHECKBOX, self.OnLogY, self.ckYlog) 
        ##<--[inamura 160627]
        # チェックボックスのイベントハンドラ登録
        self.ckauto.Bind(wx.EVT_CHECKBOX, self.OnZAuto, self.ckauto)
        self.cklog.Bind(wx.EVT_CHECKBOX, self.OnLog, self.cklog) 
        self.cksmooth.Bind(wx.EVT_CHECKBOX, self.OnSmooth, self.cksmooth) ##[inamura 101022]
        
        self.ifi = IFEvtProp(order)
        # Zスケール変更のリスナー登録
        self.ifi.AddListner('setzscale', self.OnNotifySetZScale)
        # ログモード設定のリスナー登録
        self.ifi.AddListner('setlog', self.OnNotifySetLog)

        ##[inamura 160627]-->
        self.ifi.AddListner('setxlog', self.OnNotifySetXLog)
        self.ifi.AddListner('setylog', self.OnNotifySetYLog)
        ##<--[inamura 160627]
        # keeping smoothing window
        self.smoothwindow = 1      ##[inamura 110124]
        self.ifi.AddProperty('smoothwindow', lambda : self.smoothwindow) ##[inamura 170306]

    ##############################################
    def OnNotifySetZScale(self, wid, evtType, zscale):
        """
        Z軸設定イベント処理
        @param  wid イベント発生元のインスタンス
        @param  evtType イベントタイプ
        @param  zscale 　スケール範囲タプル
        @retval 無し
        """ 
        # マニュアルモードであれば
        if not zscale[0]:
            # テキストボックスへ値を設定
            ##[inamura 100622]-->
            #strZ0 = "%.3f" % zscale[1]
            #strZ1 = "%.3f" % zscale[2]
            strZ0 = "%g" % zscale[1]
            strZ1 = "%g" % zscale[2]
            ##<--[inamura 100622]
            self.txz0.SetValue(strZ0)
            self.txz1.SetValue(strZ1)
        # 自動モードチェックボックスへ値を設定
        self.ckauto.SetValue(zscale[0])
        # Zスケール変更処理
        self.OnZAuto()
        
    ##############################################
    def OnNotifySetLog(self, wid, evtType, logFlag):
        """
        Zログモード設定イベント処理関数
        @param  wid イベント発生元のインスタンス
        @param  evtType イベントタイプ
        @param  logFlag　ログフラグ
        @retval 無し
        """ 
        # チェックボックスにログフラグを設定
        self.cklog.SetValue(logFlag)
        # Zスケール変更イベント発行
        self.ifi.NotifyEvent(self, "log", logFlag)     

    ##############################################
    def ChangeAutoRange(self, z0, z1):
        """
        データ変更時のZ軸設定処理(自動モード時)
        @param  z0 Z軸始値
        @param  z1 Z軸終値
        @retval 無し
        """ 
        # 自動モードであれば
        if self.ckauto.GetValue():
            # テキストボックスへ値を設定
            self.SetRange(z0, z1)
        
    ##############################################
    def SetRange(self, z0,z1):
        """
        Z軸設定処理
        @param  z0 Z軸始値
        @param  z1 Z軸終値
        @retval 無し
        """ 
        # テキストボックスへ値を設定
        ##[inamura 100622]-->
        #strZ0 = "%.3f" % z0
        #strZ1 = "%.3f" % z1
        strZ0 = "%g" % z0
        strZ1 = "%g" % z1
        ##<--[inamura 100622]
        self.txz0.SetValue(strZ0)
        self.txz1.SetValue(strZ1)
        
    ##############################################
    def OnLog(self, evt):
        """
        ログメニューイベント処理関数
        ログとリニアのモード切替
        @param  evt 　イベント
        @retval 無し
        """
        print "OnLog"
        # チェックボックスの値を取得し、ログフラグに設定
        logFlag = self.cklog.GetValue()
        # ログモードであれば
        if logFlag:
           z0 = float(self.txz0.GetValue())
           # 負値は不可   
           if z0 < 0.0:
               ##[inamura 100622]-->
               #self.txz0.SetValue("0.000")
               self.txz0.SetValue("1.0e-25")
               ##<--[inamura 100622]
        # ログモード変更イベント発行
        self.ifi.NotifyEvent(self, "log", logFlag) 

    ##[inamura 160627]-->
    ##############################################
    def OnLogX(self, evt):
        """
        ログメニューイベント処理関数
        ログとリニアのモード切替
        @param  evt 　イベント
        @retval 無し
        """
        print "OnLogX"
        logXFlag = self.ckXlog.GetValue()
        self.ifi.NotifyEvent(self, "logx", logXFlag )
            
    ##############################################
    def OnLogY(self, evt):
        """
        ログメニューイベント処理関数
        ログとリニアのモード切替
        @param  evt 　イベント
        @retval 無し
        """
        print "OnLogY"
        logYFlag = self.ckYlog.GetValue()
        self.ifi.NotifyEvent(self, "logy", logYFlag )
    
    ##############################################
    def OnNotifySetXLog(self, wid, evtType, logFlag):
        """
        Zログモード設定イベント処理関数
        @param  wid イベント発生元のインスタンス
        @param  evtType イベントタイプ
        @param  logFlag　ログフラグ
        @retval 無し
        """ 
        self.ckXlog.SetValue(logFlag)
        self.ifi.NotifyEvent(self, "logx", logFlag)
    ##############################################
    def OnNotifySetYLog(self, wid, evtType, logFlag):
        """
        Zログモード設定イベント処理関数
        @param  wid イベント発生元のインスタンス
        @param  evtType イベントタイプ
        @param  logFlag　ログフラグ
        @retval 無し
        """ 
        self.ckYlog.SetValue(logFlag)
        self.ifi.NotifyEvent(self, "logy", logFlag)
    ##<--[inamura 160627]

    ##############################################    
    def OnZAuto(self, evt=None):
        """
        Z軸範囲自動チェックボックスイベント処理
        @param  evt 　イベント
        @retval 無し
        """     
        # 自動モードであれば
        if self.ckauto.GetValue():
            # テキストボックスとボタンを選択不可
            self.txz0.Enable(False)    
            self.txz1.Enable(False)
            self.btzApply.Enable(False)
            # Zスケール変更イベント発行
            self.ifi.NotifyEvent(self, "zscale", (True,0.0,0.0))
        else:
            # テキストボックスとボタンを選択可に
            self.txz0.Enable(True)    
            self.txz1.Enable(True)
            self.btzApply.Enable(True)
            # 現在のテキストボックスの値を取得し送信
            self.OnBtzApply()
            
    #####################################################
    def OnBtzApply(self, ezt=None):
        """
        Zパネルアプライボタンイベント処理
        @param  evt 　イベントの種類
        @retval 無し
        """
        ##[inamura 110124]-->
        ## smoothing 
        if self.cksmooth.GetValue():
            window = float( self.txsmooth.GetValue() )
            if self.smoothwindow!=window:
                self.smoothwindow = window #[inamura 171124]
                self.ifi.NotifyEvent(self, "smooth", (True,window) )
        ##<--[inamura 110124]
        # テキストボックスの値を取得
        try:
            z0 = float(self.txz0.GetValue())
        except:
            z0 = 0.0
        # ログモードであれば    
        if self.cklog.GetValue() :
            # 負値は不可   
            if z0 < 0.0:
                ##[inamura 100622]-->
                #z0 = 0.0
                z0 = 1.0E-25
                ##<--[inamura 100622]
        try:
            z1 = float(self.txz1.GetValue())
        except:
            z1 = z0+1.0
        # 1.0 以下は不可
        ##[inamura 091210]-->
        ##if z1 < z0+1.0:
        ##    z1 = z0+1.0
        ##<--[inamura 091210]
        # 再表示
        ##[inamura 100622]-->
        #strZ0 = "%.3f" % z0
        strZ0 = "%g" % z0
        self.txz0.SetValue(strZ0)
        #strZ1 = "%.3f" % z1
        strZ1 = "%g" % z1
        self.txz1.SetValue(strZ1)
        
        # Zスケール変更イベント発行
        self.ifi.NotifyEvent(self, "zscale", (False,z0,z1)) 
              
    ##[inamura 101022]-->
    #####################################################
    def OnSmooth(self, evt):
        """
        checkbox event for smoothing
        @param evt type of event
        @retval None
        """
        # チェックボックスの値を取得
        smtFlag = self.cksmooth.GetValue()
        window = float( self.txsmooth.GetValue() )
        self.smoothwindow = window
        print "OnSmooth::",smtFlag,window
        self.ifi.NotifyEvent(self, "smooth", (smtFlag,window) )

    ##<--[inamura 101022]
    ##[inamura 110106]-->
    #####################################################
    def DisableSmooth(self):
        """
        Turn off smoothing mode
        @retval None
        """
        smtFlag = False
        self.cksmooth.SetValue(smtFlag)
        window = float( self.txsmooth.GetValue() )
        self.smoothwindow = window
        #print "DisableSmooth::",smtFlag,window
        self.ifi.NotifyEvent(self, "smooth", (smtFlag,window) )
    ##<--[inamura 110106]

#######################################
#  MapD2Frame
#######################################  
class MapD2Frame(object):
    """
    検出器マップ表示画面クラス
    """

    #########################################
    def __init__(self, parent=None, data=None, pno=1, fTitle = None, isQuiet=False):
        """
        2次元マップ表示処理のコンストラクタ
        @param  parent 親画面のインスタンス   
        @param  data  データオブジェクト 
        @param  pno   プロッタ番号
        @param  fTitle   画面タイトルの後に表示する文字列
                         (VisualCont から起動したときに起動元識別用に付与)
        @retval 無し
        """ 

        # 初期化処理
        self.plot = [None, None]
        self.dragFlag = False
        self.dowmP = (0, 0, 0, 0)
        self.pno = pno
        self.dmap = None
        self.opdg = None    #[KCS: 130520]
        self.clipdg = None  #[KCS: 130520]
        
        # リソースからメイン画面を取得
        ##<--[KCS: 130520]
        #res = ResourceFile()
        #self.frame = res.GetFrame(parent, "sqeMapframe")
        #self.res = ResourceFile('D2Vis')
        self.res = ResourceFile(D2VISXRC) #[inamura 160401]
        self.frame = self.res.GetFrame(parent, "sqeMapframe")
        ##<--[KCS: 130520]
        
        # リソースからフレームが取得できなかった
        if self.frame == None:
            return
        # フレームのタイトルに番号を付ける
        strT = self.frame.GetTitle()
        if fTitle:
            self.post = " (%s)" % fTitle
        else:
            self.post = " (%d)" % pno
            
        self.frame.SetTitle(strT + self.post)
        
        # アイコンを設定
        self.frame.SetIcon(Images().GetMainIcon())
        # メニューバーを取得
        self.menuBar= self.res.GetMenuBar('sqeMenuBar')
        self.frame.SetMenuBar(self.menuBar)

        # グラフ描画用のパネルを取得
        panel = self.res.GetCtrl(self.frame, 'mappanel')

        # グラフ描画用のフィギュアとキャンバスを作成
        self.fig   = Figure((6.0,6.4), 100)
        self.canvas= FigCanvas(panel, -1, self.fig)
        sizer = wx.BoxSizer(wx.VERTICAL)

        # ツールバー作成
        #self.toolbar = ChartToolBar(self,pno)
        self.toolbar = ChartToolBarD2Vis(self,pno) ## [inamura 110106]
        sizer.Add(self.toolbar, 0, wx.LEFT|wx.TOP|wx.GROW)
        self.toolbar.Show()
        sizer.Add(self.canvas, 1, wx.LEFT | wx.EXPAND)
        # サイザーに入れる
        panel.SetSizer(sizer)
        panel.Fit()
        # イベントハンドラーの設定
        self._SetEventHandler(self.res)
        
        # 文字列ならファイル名
        try:
            if type(data) == type(""):
                self.lf = Legacy2DFile()
                # ファイルを読み込み、マップデータ(非直方形)を作る
                try:
                    mapXY = self.lf.ReadData(data[0],data[1])
                except:
                    raise
                if mapXY == None:
                    pass
                else:
                    # マップデータをセットし、データクラスのインスタンスを取得
                    self.dmap = MapObj(mapXY, pno)
            else:
                # データクラスのインスタンス取得
                self.dmap = MapObj(data, pno)  
        except:
            # データクラスのインスタンス取得
            self.dmap = MapObj(data, pno)

        # Z スケールレンジに初期値(データの最小値と最大値)を設定
        minI, maxI, self.offset = self.ifi.GetProperty("zrange")
        # ログモードであれば
        if minI > 0:
            minI = 0.0
        # Zパネルに値を設定    
        self.zp.SetRange(minI, maxI)

        # メイン画面を表示
        if not isQuiet:
            self.frame.Show() ##[inamura 120211]
        
        # 検出器マップの描画
        self.d2 = D2Chart(self, panel,pno )

        ## [KCS: 130520]-->
        # ElementContainerArray が設定されていなければ
        if self.dmap == None or self.dmap.mclip == None:
            # クリップメニューを選択不可とする
            self.menuBar.Enable(self.res.GetId('menu_Clip'), False)
        else:
            D2CuiIF(pno).SetHeaderAndLabels(data)
        ##<-- [KCS: 130520]
        self.freeslicer=None #[inamura 160721]


    #########################################
    def _SetEventHandler(self, res):
        """
        イベントハンドラーの登録
        @param  res リソースファイルのインスタンス   
        @retval 無し
        """ 
        # リソース取得
        
        # プロパティ管理クラスのインスタンスを取得
        self.ifi = IFEvtProp(self.pno)

        #メニューのイベントハンドラ登録
        self.frame.Bind(wx.EVT_MENU, self.OnLegacy, id=res.GetId('menu_legacy'))
        self.frame.Bind(wx.EVT_MENU, self.OnPrint, id=res.GetId('menu_print'))
        self.frame.Bind(wx.EVT_MENU, self.OnClose, id=res.GetId('menu_exit'))
        self.frame.Bind(wx.EVT_MENU, self.OnLabel, id=res.GetId('menu_label'))
        self.frame.Bind(wx.EVT_MENU, self.OnTitle, id=res.GetId('menu_title'))
        self.frame.Bind(wx.EVT_MENU, self.OnSNS_SQEFile, id=res.GetId('menu_SNS_sqe'))
        ##[inamura 090924]->
        self.frame.Bind(wx.EVT_MENU, self.OnColorMap, id=res.GetId('menu_colormap'))
        self.frame.Bind(wx.EVT_MENU, self.OnSetXYRange, id=res.GetId('menu_xyrange'))
        ##<-[inamura 090924]

        self.frame.Bind(wx.EVT_MENU, self.OnSaveAsText, id=res.GetId('menu_saveas')) ##[inamura 101214]
        self.frame.Bind(wx.EVT_MENU, self.OnLoadDataFromText, id=res.GetId('menu_loadtext')) ##[inamura 140821]
        self.frame.Bind(wx.EVT_MENU, self.OnAxisGridStyle, id=res.GetId('menu_grid')) ##[inamura 160124]
        self.frame.Bind(wx.EVT_MENU, self.OnAxisTickStyle, id=res.GetId('menu_ticks')) ##[inamura 160726]
        ## [KCS: 130520]-->
        self.frame.Bind(wx.EVT_MENU, self.OnOverPlot, id=res.GetId('menu_Overplot'))
        self.frame.Bind(wx.EVT_MENU, self.OnClip, id=res.GetId('menu_Clip'))
        ##-->[KCS: 13052]
        self.frame.Bind(wx.EVT_MENU, self.OnFreeSlice, id=res.GetId('menu_freeslice')) #[inamura 160721]
        
        #クローズイベント登録
        self.frame.Bind(wx.EVT_CLOSE, self.OnClose)
 
        #マウスイベントのリスナ登録
        self.canvas.mpl_connect('motion_notify_event', self.OnMouseMove)
        self.canvas.mpl_connect('button_press_event', self.OnMouseDown)
        self.canvas.mpl_connect('button_release_event', self.OnMouseUp)
        
        # Xパネルのコントロール取得
        xp = res.GetCtrl(self.frame, 'xpanel')
        self.xp = SlicingPanel(self.frame, xp, 1, self.pno)
         
        # Yパネルのコントロール取得
        yp = res.GetCtrl(self.frame, 'ypanel')
        self.yp = SlicingPanel(self.frame, yp, 2, self.pno)
        
        # Zパネルのコントロール取得
        zp = res.GetCtrl(self.frame, 'zpanel')
        self.zp = ZScalePanel(zp, self.pno)

        # 1次元プロッタへのデータ追加イベントのリスナー登録
        self.ifi.AddListner('add',  self.OnNotifyAppend)
        # 1次元プロッタのクリアイベントのリスナー登録
        self.ifi.AddListner('clear',  self.OnNotifyClear)
        # 印刷イベントのリスナー登録
        self.ifi.AddListner('print',  self.OnPrint)
        # 画像保存要求のリスナー登録
        self.ifi.AddListner('save',  self.OnNotifySave)
        # 2Dプロッタクローズ要求のリスナー登録
        self.ifi.AddListner('close',  self.OnClose)
        # アイコン化処理のリスナー登録
        self.ifi.AddListner('doiconize', self.OnNotifyDoIconize)
        # 2次元プロッタデータ変更のリスナー登録
        self.ifi.AddListner('changedata', self.OnNotifyChangeData)
        # Add Listner for open/close of dialogs [inamura 121029]-->
        self.ifi.AddListner('scalelabel3dg', self.OnNotifyChildDg)
        self.ifi.AddListner('title2ddg', self.OnNotifyChildDg)
        self.ifi.AddListner('setxyrange2ddg', self.OnNotifyChildDg)
        self.ifi.AddListner('setcolormap2ddg', self.OnNotifyChildDg)
        ##<--[inamura 121029]
        self.ifi.AddListner('setaxisgridstyle2ddg', self.OnNotifyChildDg) ##[inamura 160224]
        self.ifi.AddListner('setaxistickstyle2ddg', self.OnNotifyChildDg) ##[inamura 160726]
        
        self.ifi.AddListner('updatedata', self.OnNotifyUpdateData) ##[inamura 160603-2]
        # データ情報表示用に文字列のコントロール取得
        panely = res.GetCtrl(self.frame, 'panel2')
        self.infotxt = res.GetCtrl(panely, 'infotxt')
        
        # Double Click state
        self.doubleClick_state1 = [ 0, 0.0] ##[inamura 120710]
        self.doubleClick_interval = 0.6     ##[inamura 120710]
            
    ######################################################
    def OnNotifySave(self, wid, evt, fname):
        """
        画像保存処理
        @param  wid イベント発生元のインスタンス
        @param  evt イベントタイプ
        @param  fname ファイル名
        @retval 無し
        """ 
        try:
            try:
                self.canvas.print_figure(fname,dpi=300)
            except:
                raise PlotException('Common','C018',(fname,))
        except PlotException, ex:
                PlotMessage(self.frame,ex)

    #########################################    
    def OnNotifyAppend(self, wid, evt, pID):
        """
        Appendボタン押下イベント処理
        @param  wid イベント発生元のインスタンス
        @param  evt イベントタイプ
        @param  pID 　プロッタID
        @retval 無し
        """
        # ヘッダー作成
        header = {}
        if pID == 1 or pID == 3:
            # Qヒストグラム取得
            hist = self.ifi.GetProperty("qdata")
            strLabel = self.ifi.GetProperty("strenergy")
            header["Label"] = strLabel
            # データ追加
            self.AddToPlot((hist.bins, hist.counts, hist.errs, header), 1)
        if pID == 2 or pID == 3:
            # エネルギーヒストグラム取得
            hist = self.ifi.GetProperty("edata")
            strLabel = self.ifi.GetProperty("strq")
            header["Label"] = strLabel
            # データ追加
            self.AddToPlot((hist.bins, hist.counts, hist.errs, header), 2)

        
    #########################################    
    def OnNotifyClear(self, wid, evt, pID):
        """
        Peplace(X)ボタン押下イベント処理
        @param  wid イベント発生元のインスタンス
        @param  evt イベントタイプ
        @param  pID 　プロッタID
        @retval 無し
        """ 
        print pID
        if pID == 1 or pID == 3:
            # データクリア要求発行
            IFEvtProp(self.pno+1).NotifyEvent(self, "remove", 0) 
        if pID == 2 or pID == 3:
            # データクリア要求発行
            IFEvtProp(self.pno+2).NotifyEvent(self, "remove", 0)     

    ##############################################        
    def OnLegacy(self, *args):
        """
        レガシィファイル読み込み
        @param  *args 　イベント
        @retval 無し
        """

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

        # キャンセルか
        if dlg.ShowModal() != wx.ID_OK:
            return
        
        spefile = dlg.GetPath()
        fspe = dlg.GetFilename()
        dir = os.path.dirname(spefile)
        
        # PHX ファイルオープンダイアログ
        dlg = wx.FileDialog(self.frame, 'PHX File Open ...', dir, style=wx.OPEN, wildcard='PHX(*.PHX,*.phx)|*.PHX;*.phx') #[inamura 160803]

        # キャンセルか
        if dlg.ShowModal() != wx.ID_OK:
            return
        
        phxfile = dlg.GetPath()
        fphx = dlg.GetFilename()
        # タイトルをファイル名から作る
        strMain = fspe + ', ' + fphx
        
        # 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 PlotException('Common', 'C027', ("Ei",))
                else:
                    if ei > 0.0:
                        break
                    raise PlotException('Common', 'C027', ("Ei","0.0"))
            except PlotException, ex:
                PlotMessage(self.frame, ex)

        # レガシィファイルの読み込みクラスのインスタンス取得
        spe = Legacy2DFile()
        # SPE ファイルの読み込み
        try:
            # ファイルを読み込み、マップデータ(非直交)を作る
            mapXY = spe.ReadData(spefile, phxfile, ei)
        except PlotException, ex:
                PlotMessage(self.frame, ex)
        else:
            ifi = IFEvtProp(self.pno)
            # データ変更
            ifi.NotifyEvent(self, "changedata", mapXY)
            # サブタイトル作成
            strSub = "Ei (meV): %.1f\n" % ei  
            # タイトル設定コマンド送信
            ifi.NotifyEvent(None, "title", (strMain, strSub))
            # スケールラベル設定コマンド送信
            ifi.NotifyEvent(None, "scalelabel", ("Q (1/Angstrom)", "Energy (meV)","Neutrons"))
            # クリップメニューを選択不可とする
            self.menuBar.Enable(self.res.GetId('menu_Clip'), False)  

    ##############################################        
    def OnSNS_SQEFile(self, *args):
        """
        ファイル読み込み
        @param  *args 　イベント
        @retval 無し
        """
        # SPE ファイルオープンダイアログ
        dlg = wx.FileDialog(self.frame, 'SPE File Open ...', os.getcwd(), style=wx.OPEN, wildcard='SPE(*.SPE,*.spe)|*.SPE;*.spe') #[inamura 160803]

        # キャンセルか
        if dlg.ShowModal() != wx.ID_OK:
            return
        
        spefile = dlg.GetPath()
        fspe = dlg.GetFilename()
        dir = os.path.dirname(spefile)

        # タイトルをファイル名から作る
        strMain = fspe

        # レガシィファイルの読み込みクラスのインスタンス取得
        spe = LoadSnsSqeFile()
        # SPE ファイルの読み込み
        try:
            # ファイルを読み込み、マップデータ(非直交)を作る
            mapXY = spe.ReadData(spefile)
        except PlotException, ex:
                PlotMessage(self.frame, ex)
        else:
            ifi = IFEvtProp(self.pno)
            # データ変更
            ifi.NotifyEvent(self, "changedata", mapXY)
            # サブタイトル作成
            strSub = ""
            # タイトル設定コマンド送信
            ifi.NotifyEvent(None, "title", (strMain, strSub))
            # スケールラベル設定コマンド送信
            ifi.NotifyEvent(None, "scalelabel", ("Q (1/Angstrom)", "Energy (meV)","Neutrons"))
            # クリップメニューを選択不可とする
            self.menuBar.Enable(self.res.GetId('menu_Clip'), False)

        
    #########################################    
    def AddToPlot(self, data, pID):
        """
        データをプロッタへ追加
        @param  data   追加データ
        @param  pID 　プロッタID
        @retval 無し
        """ 
        ifi = IFEvtProp(pID+self.pno)
        
        pt = " - %d" % pID
        # プロッタが起動されていなければ
        if self.plot[pID-1] == None:
            # プロッタフレームクローズイベントのリスナー登録
            ifi.AddListner('plotclose',  self.OnNotifyPlotClose)
            # Q ヒストグラム用のプロッタウィンドウを開く
            self.plot[pID-1] = PlotFrame(self.frame, data, pID+self.pno, self.post+pt)
            # タイトル取得
            main = IFEvtProp(self.pno).GetProperty("title1")
            subs = IFEvtProp(self.pno).GetProperty("title2").split('\n')
            sub = ""
            for line in subs:
                sub = sub + line.strip() + ', '
            sub = sub[:-2]    

            # タイトル設定コマンド送信
            ifi.NotifyEvent(self, "title", (main, sub)) 
            # 軸ラベル取得
            xlb = IFEvtProp(self.pno).GetProperty("xlabel")
            ylb = IFEvtProp(self.pno).GetProperty("ylabel")
            zlb = IFEvtProp(self.pno).GetProperty("zlabel") 
            
#            zlb = "Newtrons"
            # 軸ラベル設定コマンド送信 
            if pID == 1:
                ifi.NotifyEvent(self, "scalelabel", (xlb, zlb)) 
            else:
                ifi.NotifyEvent(self, "scalelabel", (ylb, zlb))
             
        else:
            # データ追加要求イベント発行
            ifi.NotifyEvent(self, "add", [data])
            
  
            
    #####################################################
    def OnNotifyPlotClose(self, wid, evt, value=None):
        """
        プロッタクローズイベント対応処理
        @param  wid 　 イベント発生元のインスタンス
        @param  evt 　イベントの種類
        @param  value  無し   
        @retval 無し
        """ 
        # プロッタ(1)がクローズされたのか
        if self.plot[0] == wid:
            IFEvtProp(self.pno+1).InitIF()
            self.plot[0] = None
        # プロッタ(2)がクローズされたのか    
        elif self.plot[1] == wid:
            IFEvtProp(self.pno+2).InitIF()
            self.plot[1] = None 
    
    ###################################################
    def OnNotifyDoIconize(self, wid, evtType, flag):
        """
        ウィンドウアイコン化または復元要求受信処理
        @param wid
        @param evtType
        @param  flag    True: アイコン化　False: 元に戻す  
        @retval 無し
        """ 
        # アイコン化する、または元に戻す
        self.frame.Iconize(flag)        

    ###################################################             
    def OnNotifyChangeData(self, wid, evtType, data):
        """
        データ変更イベント処理
        @param  wid イベント発生元のインスタンス
        @param  evt イベントタイプ
        @param  data データオブジェクト
        　　　　　　　文字列の場合は、ダミーデータファイル名とみなす
        @retval 無し
        """
        self.dmap.ChangeData(data)

        ## [KCS: 130520]-->
        # ElementContainerArray が設定されていれば
        if self.dmap != None and self.dmap.mclip != None:
            # クリップメニューを選択可とする
            self.menuBar.Enable(self.res.GetId('menu_Clip'), True)
        ##<-- [KCS: 130520]
        
        # Zデータの範囲を取得
        min, max, offset = self.ifi.GetProperty("zrange")
        if min >= 0.0:
            min = 0.0
        else:
            if self.ifi.GetProperty("logflag"):
                min = 0.0
            
        self.zp.ChangeAutoRange(min, max)
        self.zp.DisableSmooth() ##[inamura 110106]
        self.d2.PlotD2Chart()
         
    ##[inamura 160603-2]-->
    ###################################################             
    def OnNotifyUpdateData(self, wid, evtType, data):
        """
        Update Map Data Event
        made from OnNotifyChangeData
        @param  wid イベント発生元のインスタンス
        @param  evt イベントタイプ
        @param  data データオブジェクト
        　　　　　　　文字列の場合は、ダミーデータファイル名とみなす
        @retval 無し
        """
        self.dmap.ChangeData(data)

        # ElementContainerArray が設定されていれば
        if self.dmap != None and self.dmap.mclip != None:
            # クリップメニューを選択可とする
            self.menuBar.Enable(self.res.GetId('menu_Clip'), True)
        
        # Zデータの範囲を取得
        min, max, offset = self.ifi.GetProperty("zrange")
        if min >= 0.0:
            min = 0.0
        else:
            if self.ifi.GetProperty("logflag"):
                min = 0.0
            
        #self.zp.ChangeAutoRange(min, max) #[inamura 160823]
        #self.zp.DisableSmooth()           #[inamura 160823]
        #self.d2.PlotD2Chart() ##[inamura 170306]
    ##<--[inamura 160603-2]

    #########################################
    def OnMouseMove(self, event):
        """
        マウス-ポインタ移動イベント処理
        @param   event イベント情報   
        @retval 無し
        """ 
        # データ無しなら
        if self.ifi.GetProperty("mapdata") is None:
            return
          
        # マウス位置がグラフ内かどうかをチェック
        if not event.inaxes:
            self.infotxt.SetLabel("")
            return
        
        # グラフ内であっても、None が来ることがあるのでプロテクト
        if event.ydata == None or event.xdata == None:
            self.infotxt.SetLabel("")
            return

        # Qヒストグラム内か
        if event.y > self.ifi.GetProperty("y1dpi"):
            strTx = "X=%.3f    Z= %.3f" % (event.xdata, event.ydata)
            self.infotxt.SetLabel(strTx)
            return
        # エネルギーヒストグラム内か
        elif event.x > self.ifi.GetProperty("x1dpi"):
            strTx = "Y=%.3f    Z= %.3f" % (event.ydata, event.xdata)
            self.infotxt.SetLabel(strTx)
            return
        # カラーマップ外か
        if event.y < self.ifi.GetProperty("y0dpi") or event.y > self.ifi.GetProperty("y1dpi"):
            return
        elif event.x > self.ifi.GetProperty("x1dpi"):
            return
        else:
            # マウスのY位置におけるヒストグラムを取得
#            try:
#                hist = self.dmap.GetHistX((event.ydata,event.ydata,event.ydata, 0.0))
#            except:
#                self.infotxt.SetLabel("")
#                return
            # Z データの無い領域か
#            if hist.bins[0] > event.xdata or hist.bins[len(hist.bins)-1] < event.xdata:
#                # マウス位置の情報を表示、Z データ無し
#                strTx = "X=%.3f    Y=%.3f    Z= --" % (event.xdata, event.ydata)
#            # カラーコンツァー表示領域
#            else:
#                for i in range(len(hist.bins)):
#                    if hist.bins[i]> event.xdata:
#                        break
#                    # マスク値であれば
#                    if hist.counts[i] >= MASKVALUE-1.0:
#                        # Z データは無し 
#                        strTx = "X=%.3f    Y=%.3f    Z= --" % (event.xdata, event.ydata)
#                    else:
#                        strTx = "X=%.3f    Y=%.3f    Z= %.3f" % (event.xdata, event.ydata, hist.counts[i])

            # マウス位置における強度を取得
            zz = self.dmap.GetZValue(event.xdata, event.ydata)
            # データが取得できなければ(マップ外)
            if zz == None:
                # マウス位置の情報を表示、Z データ無し
                strTx = "X=%.3f    Y=%.3f    Z= --" % (event.xdata, event.ydata)
            else:
                strTx = "X=%.3f    Y=%.3f    Z= %.3f" % (event.xdata, event.ydata, zz)
                
           # ドラッグ中か
            if self.dragFlag:
                # ドラッグ範囲を、半透明の領域で表示
                self.d2.DrawRectCursol(event, self.downP)   
        # マウス位置情報表示
        self.infotxt.SetLabel(strTx)

    #########################################
    def OnMouseDown(self, event):
        """
        マウス-ボタンクリックイベント処理
        @param   event イベント情報   
        @retval 無し
        """ 

        # パン処理中またはズーム処理中であれば、以下の処理を実行しない
        if self.toolbar._active == 'PAN' or self.toolbar._active == 'ZOOM':
            return

        # グラフ範囲外か
        if not event.inaxes:
            ##[inamura 120710]-->
            # if click in title area
            if event.y > self.ifi.GetProperty("y1dpi"):
                self.doubleClick_state1[0] = 3
            elif event.x < (self.ifi.GetProperty("x0dpi")*0.4) or event.y < (self.ifi.GetProperty("y0dpi")*0.7):
                self.doubleClick_state1[0] = 2
            elif event.x < self.ifi.GetProperty("x0dpi") or event.y < self.ifi.GetProperty("y0dpi"):
                self.doubleClick_state1[0] = 1
            else:
                self.doubleClick_state1[0] = 0
            ##<--[inamura 120710]

            return
        # カラーマップグラフ内か
        if event.y <= self.ifi.GetProperty("y1dpi") and event.x <= self.ifi.GetProperty("x1dpi"):
            # マウスクリック点のデータを保存
            self.downP = (event.x, event.y, event.xdata, event.ydata)
            # ドラッグ開始
            self.dragFlag = True 
        
            self.doubleClick_state1[0] = 0 ##[inamura 120710]
        

    #########################################
    def OnMouseUp(self, event):
        """
        マウス-ボタンアップイベント処理
        @param   event イベント情報   
        @retval 無し
        """
        ##[inamura 120710]-->
        if (self.doubleClick_state1[1]!=0.0) and (self.doubleClick_state1[1]+self.doubleClick_interval)>time.time():
            if self.doubleClick_state1[0]==1:
                self.OnSetXYRange(None)
            if self.doubleClick_state1[0]==2:
                self.OnLabel(None)
            if self.doubleClick_state1[0]==3:
                self.OnTitle(None)
            self.doubleClick_state1[1] = 0.0
        else:
            self.doubleClick_state1[1] = time.time()            
        ##<--[inamura 120710]

        # ドラッグ中(マップ内でボタン押下された)か
        if self.dragFlag:
            # ドラッグ終了
            self.dragFlag = False
        else:
            return
        # データ無しなら
        if self.ifi.GetProperty("mapdata") is None:
            return
        
        # パン処理中またはズーム処理中であれば、以下の処理を実行しない
        if self.toolbar._active == 'PAN' or self.toolbar._active == 'ZOOM':
            return

        # グラフ範囲外か
        if not event.inaxes:
            return
        # カラーマップグラフ外であれば何もしない
        if event.y > self.ifi.GetProperty("y1dpi") or event.x > self.ifi.GetProperty("x1dpi"):
            return

        # 開始点と終了点との差が、1 pixel 以下であればクリックとみなす
        if abs(self.downP[0] - event.x) < 2.0 and abs(self.downP[1] - event.y) < 2.0 :
            # 中心値のテキストボックスに値を設定
            self.ifi.NotifyEvent(self, "slicex", (event.ydata, None, None)) 
            self.ifi.NotifyEvent(self, "slicey", (event.xdata, None, None)) 

        # ドラッグならば
        else:
            #--> [KCS: 130520]
            # クリップダイアログ表示中か
            if self.clipdg == None:
                clipFlg = False
            else:
                clipFlg = self.ifi.GetProperty('clipdg') 
            #<-- [KCS: 130520]
            # X方向のドラッグ開始点と終了点の大小比較
            if event.xdata > self.downP[2]:
                x0 = self.downP[2]
                x1 = event.xdata
            else:
                x0 = event.xdata
                x1 = self.downP[2]

            if not clipFlg:    # [KCS: 130520]
                # Y Slice パネルの　Range へ　値を設定
                self.ifi.NotifyEvent(self, "sliceyrange", (x0,x1, 1, None)) 

            # Y方向のドラッグ開始点と終了点の大小比較
            if event.ydata > self.downP[3]:
                y0 = self.downP[3]
                y1 = event.ydata
            else:
                y0 = event.ydata
                y1 = self.downP[3]

            #--> # [KCS: 130520]
            # クリップダイアログが表示されていれば
            if clipFlg:
                # ダイアログに、領域を追加
                self.ifi.NotifyEvent(None,'addRegion',(x0,y0,x1,y1))
                # グラフに領域の再描画を通知
                #self.ifi.NotifyEvent(None,'drawRegions')
                return
            else:
            #<-- # [KCS: 130520]
            
                # X Slice パネルの　Range へ　値を設定
                self.ifi.NotifyEvent(self, "slicexrange", (y0,y1, 1, None)) 
        
        # カーソルとグラフを表示
        self.ifi.NotifyEvent(self, "show", 3)       

    ######################################################
    def OnTitle(self,event):
        """
        Set Graph Title メニューイベント処理
        スケール設定ダイアログを表示
        @param  event イベント情報
        @retval 無し
        """ 
        # タイトル設定ダイアログを開く 
        Title2DDialog(self.frame, self.pno, self.post)
 

    ######################################################
    def OnLabel(self,event):
        """
        Set Scale Label メニューイベント処理
        スケール設定ダイアログを表示
        @param  event イベント情報
        @retval 無し
        """ 
        ScaleLabel3Dialog(self.frame, self.pno, self.post)

    ##[inamura 090924]->
    ######################################################
    def OnColorMap(self,event):
        """
        Set ColorMap メニューイベント処理
        スケール設定ダイアログを表示
        @param  event イベント情報
        @retval 無し
        """ 
        
        dlg = SetColorMap2DDialog(self.frame, self.pno, self.post)

    ######################################################
    def OnSetXYRange(self,event):
        """
        Set Graph Parameter メニューイベント処理
        スケール設定ダイアログを表示
        @param  event イベント情報
        @retval 無し
        """ 
        
        dlg = SetXYRange2DDialog(self.frame, self.pno, self.post)
        
    ##<-[inamura 090924]

    ##<--[KCS: 130520]
    ##############################################        
    def OnOverPlot(self, *args):
        """
        オーバプロット画面表示
        @param  *args 　イベント情報
        @retval 無し
        """ 
        if self.opdg == None:
            self.opdg = OverPlotDialog(self.frame, self.pno, self.res)
        else:
            self.opdg.ShowDg()
            
    ##############################################        
    def OnClip(self, *args):
        """
        クリップ画面表示
        @param  *args 　イベント情報
        @retval 無し
        """ 
        if self.clipdg == None:
            self.clipdg = ClipDialog(self.frame, self.pno, self.res)
        else:
            # 画面を再表示
            self.clipdg.ShowDg() 
            
    ##<--[KCS: 130520]

    ##[inamura 160721]-->
    ##############################################
    def OnFreeSlice(self, *arg):
        """
        Free Slice 
        @param *args Event Info
        @retval None
        """
        if self.freeslicer == None:
            self.freeslicer = FreeSlicerFrame(self.frame,self.pno,self.post,self.dmap)
        else:
            self.freeslicer.Show()
    ##<--[inamura 160721]
    ##############################################        
    def OnPrint(self, *args):
        """
        デテクタマップ印刷
        @param  *args 　イベント情報
        @retval 無し
        """ 
       
        # プラットフォームを判定     
        if os.name == "posix" or os.name == "mac" :
            # 領域を破線で表示し直す
            xc,yc = self.ifi.GetProperty("cursol")
            self.d2.DrawCursols(xc, yc, False)
            fname = "_d2plot.ps" 
            # テンポラリファイルの絶対パスを作成(指定されたテンポラリディレクトリの下)
            tmpf = os.path.join(tempfile.gettempdir(), fname)
            # Linux または Mac OS なら
            try:
                try:
                    # ポストスクリプトファイルを作成
                    self.canvas.print_figure(tmpf, dpi=600)
                except:
                    raise PlotException('Common','C018',(tmpf,))
                # スプーラにファイルを送信
                ret = os.system("lpr "+tmpf)
                # エラーがあったなら
                if ret > 0:
                    # エラーメッセージを表示
                    raise PlotException('Common','C023',())
                
            except PlotException, ex:
                PlotMessage(self.frame,ex)
            time.sleep(2.0)
            # カーソルを元に戻す
            self.d2.DrawCursols(xc, yc, True)  
        # Linux または Mac OS 以外(Windowsを想定)
        else:
            #用紙をA4に設定
            self.canvas.printerData.SetPaperId(wx.PAPER_A4)
            # 印刷画像の幅を設定 
            self.canvas.printer_width = 7.0
            # マージンを設定
            self.canvas.printer_margin = 1.0
            #プリントダイアログを表示        
            self.canvas.Printer_Print() 

    ##############################################        
    def OnClose(self, *args):
        """
        デテクタマップ画面クローズ
        @param  evt 　イベント
        @retval 無し
        """
        # インターフェイスのクリア
        IFEvtProp(self.pno+1).InitIF()
        IFEvtProp(self.pno+2).InitIF()

        # 2次元プロッタフレームクローズイベント発行
        self.ifi.NotifyEvent(self, "2dclosed")
        
        IFEvtProp(self.pno).InitIF()
        
        # 検出器マップ画面のクローズ       
        self.frame.Destroy() 

    ##[inamura 101214]-->
    ##############################################
    def OnSaveAsText(self, *args):
        """
        """
        
        ##[inamura 160218]-->
        dlg = SetSaveAsTextDialog(self.frame, self.pno, self.post, self.dmap)
        """
        dlg =wx.FileDialog(self.frame, "Save data as text files", style=wx.SAVE, wildcard='Text(*.*)|*.*')
        if dlg.ShowModal() == wx.ID_OK:
            try:
                self.dmap.SaveAsText(dlg.GetPath())
            except:
                raise
           
        """
        ##<--[inamura 160218]
    ##<--[inamura 101214]
    ##[inamura 140821]-->
    ##############################################
    def OnLoadDataFromText(self, *args):
        """
        """
        print "OnLoadDataFromText"
        dlg =wx.FileDialog(self.frame, "Load data from text", style=wx.OPEN, wildcard='Text(*.*)|*.*')
        if dlg.ShowModal() == wx.ID_OK:
            try:
                mapXY=self.dmap.LoadDataFromText(dlg.GetPath()) ##[inamura 170306]
                #self.ifi.NotifyEvent(self, "changedata", mapXY) ##[inamura 170306]
                self.ifi.NotifyEvent(self, "updatedata", mapXY) ##[inamura 170306]
                ##[inamura 170726]-->
                xlabel = self.dmap.xylabels[0]
                ylabel = self.dmap.xylabels[1]
                zlabel = "Intensity"
                self.ifi.NotifyEvent(self, "scalelabel", (xlabel,ylabel,zlabel))
                ##<--[inamura 170726]
            except:
                raise
        """
        # Zデータの範囲を取得
        min, max, offset = self.ifi.GetProperty("zrange")
        if min >= 0.0:
            min = 0.0
        else:
            if self.ifi.GetProperty("logflag"):
                min = 0.0
            
        self.zp.ChangeAutoRange(min, max)
        self.zp.DisableSmooth() ##[inamura 110106]
        self.d2._DispInitialMap()
        self.d2.OnNotifyLabel(None,None,(self.dmap.xylabels[0], self.dmap.xylabels[1],"*"))##[inamura 170118]
        self.d2.PlotD2Chart()
        self.d2.UpdateCursol(3)
        self.d2.canvas.draw() ##[inamura 160123]
        """
    ##<--[inamura 140821]

    ##[inamura 121029]-->
    ###############################################
    def OnNotifyChildDg(self, wid, evt, flag):
        """
        """
        if evt == "scalelabel3dg":
            self.menuBar.Enable(self.res.GetId('menu_label'), flag)
        elif evt == "title2ddg":
            self.menuBar.Enable(self.res.GetId('menu_title'), flag)
        elif evt == "setxyrange2ddg":
            self.menuBar.Enable(self.res.GetId('menu_xyrange'), flag)
        elif evt == "setcolormap2ddg":
            self.menuBar.Enable(self.res.GetId('menu_colormap'), flag)
        elif evt == "setaxisgridstyle2ddg": ##[inamura 160224]
            self.menuBar.Enable(self.res.GetId('menu_grid'), flag)
    ##<--[inamura 121029]

    ##[inamura 160124]-->
    ##############################################
    def OnAxisGridStyle(self, *args):
        """
        """
        #print "OnAxisGridStyle"
        dlg = SetAxisGridStyleDialog(self.frame, self.pno, self.post)
        
    ##<--[inamura 160124]
    ##[inamura 160726]-->
    ##############################################
    def OnAxisTickStyle(self, *args):
        """
        """
        dlg = SetAxisTickStyleDialog(self.frame, self.pno, self.post)
        
#######################################
#  D2Chart
#######################################  
class D2Chart(object):
    """
    グラフ描画 Class 
    """
    #########################################
    def __init__(self, parent, panel, order):
        """
        コンストラクタ
        @param  parent  起動クラスインスタンス
        @param  panel   描画用パネル
        @param  order　　イベントディスパッチャのID
        @retval 無し
        """
        self.fig = parent.fig
        self.canvas = parent.canvas
        self.dmap = parent.dmap
        self.frame = parent.frame
        self.xcyc = [None, None]
        self.toolbar = parent.toolbar ##[inamura 110106]
        self.isOnly = False ##[inamura 120111]
        self.traces = None  ##[KCS 130520]
        self.parent = parent ##[KCS 130520]
        
        ##[inamura 120711]-->
        # Draw managements
        sModeDic = {}
        mModeDic = {}
        sModeDic["MainPosi"] = [0.13, 0.105, 0.75, 0.75]
        mModeDic["MainPosi"] = [0.1, 0.095, 0.63, 0.62]
        sModeDic["ColorBarPosi"] = [0.90, 0.15, 0.05 ,0.62]
        mModeDic["ColorBarPosi"] = [0.02, 0.04, 0.28 ,0.02]
        sModeDic["ColorBarOri"] = 'vertical'
        mModeDic["ColorBarOri"] = 'horizontal'
        sModeDic["TickLabelSize"] = 10
        mModeDic["TickLabelSize"] = 8
        sModeDic["LabelSize"] = 12
        mModeDic["LabelSize"] = 8
        sModeDic["TitleSize"] = 12
        mModeDic["TitleSize"] = 12
        sModeDic["LabelFont"] = 'serif'
        mModeDic["LabelFont"] = 'serif'
        sModeDic["TitleFont"] = 'serif'
        mModeDic["TitleFont"] = 'serif'
        sModeDic["ScaleFont"] = 'serif'
        mModeDic["ScaleFont"] = 'serif'
        fDic = ["serif","sans-serif","monospace"]
        self.DrawDic = {"SingleMode":sModeDic,"MultiMode":mModeDic,"FontList":fDic}
        ##<--[inamura120711]
        ##[inamura 160124]-->
        self.GridStyleDic = { "Show":False,
                              "XlineWidth":0.5,
                              "XlineColor":"b",
                              "XlineStyle":"-",
                              "YlineWidth":0.5,
                              "YlineColor":"b",
                              "YlineStyle":"-" }
        ##<--[inamura 160124]
        ##[inamura 160726]-->
        self.TickStyleDic = { "Minor":False,
                              "MinorLength":2,  # default=2
                              "MinorWidth":0.5, # default=0.5
                              "MajorLength":5,  # default=5
                              "MajorWidth":0.5, # default=0.5
                              "TopSide":"off",
                              "RightSide":"off",
                              "BadColor":"white",  #[inamura 170111]
                              "BGColor":"white",   #[inamura 170111]
                              "TickColor":"black",    ##[inamura 160728]
                              "FrameLineWidth": 1.0 } ##[inamura 160728]
        ##<--[inamura 160726]

        # 初期化
        self.logFlag = False
 
        # プロパティ管理クラスのインスタンスを取得
        self.ifi = IFEvtProp(order) 
        # データ変更のリスナー登録
        self.ifi.AddListner('changedata', self.OnNotifyChangeData)
        # グラフ表示イベントのリスナー登録
        self.ifi.AddListner('show',  self.OnNotifyShow)
        # ログモード変更イベントのリスナー登録
        self.ifi.AddListner('log',  self.OnNotifyLog)
        # XYスケール範囲変更イベントのリスナー登録
        self.ifi.AddListner('changexy',  self.OnChangeXY)
        # Homeボタン押下イベントのリスナー登録
        self.ifi.AddListner('home',  self.OnHome)
        # タイトル変更のリスナー登録
        self.ifi.AddListner('title', self.OnNotifyTitle)
        # ラベル変更のリスナー登録
        self.ifi.AddListner('scalelabel', self.OnNotifyLabel)
        # Zスケール変更のリスナー登録
        self.ifi.AddListner('zscale', self.OnNotifyZScale)
        ##[inamura 090924]->
        # Color Scale変更のリスナー登録
        self.ifi.AddListner('colormap', self.OnNotifyColorMap)
        # X,Y Range変更のリスナー登録
        self.ifi.AddListner('xscale2d', self.OnNotifyXScale2D)
        self.ifi.AddListner('yscale2d', self.OnNotifyYScale2D)
        ##<-[inamura 090924]
        ##[inamura 101022]-->
        self.smoothFlag = False
        self.ifi.AddListner('smooth', self.OnNotifySmooth)
        ##<--[inamura 101022]
        self.ifi.AddListner('showonly2d', self.OnNotifyShowOnly2d) ##[inamura 120417]
        ##--> [KCS 130520]
        # オーバラップトレース表示
        self.ifi.AddListner('overplot', self.OnNotifyOverPlot) 
        # クリップ領域表示
        self.ifi.AddListner('drawRegions', self.OnNotifyClipRegions) 
        ##<--[KCS 130520]
        
        self.ifi.AddListner('setdrawinfo', self.OnNotifySetDrawInfo) ##[inamura 120711]
        self.ifi.AddListner('updatedata', self.OnNotifyUpdateData) ##[inamura 160603-2]
        ##[inamura 160627]-->
        self.ifi.AddListner('logx', self.OnNotifySetXLog )
        self.ifi.AddListner('logy', self.OnNotifySetYLog )
        self.isLogX = False
        self.isLogY = False
        ##<--[inamura 160627]
        # 2D画面描画準備
        self._DispInitialMap()
        # 描画
        self.PlotD2Chart()
        
        # Mapパネルのサイズ取得
        xsize,ysize = panel.GetSize()
        self.panel = panel ##[inamura 120710]
        
        #  グラフ境界のピクセル値を求める
#        pos = self.ax.get_position()   matplotlib 0.98.5 対応
        pos = VerHandlePlotLib().GetSubPlotPos(self.ax)
        
        self.x1dpi = (pos[0]+pos[2])*xsize
        self.y1dpi = (pos[1]+pos[3])*(ysize-20)
        self.y0dpi = pos[1]*(ysize-20)
        self.x0dpi = pos[0]*xsize   ##[inamura 120710]
        
        # 公開プロパティを登録
        self.ifi.AddProperty('logflag',    lambda : self.logFlag)
        self.ifi.AddProperty('title1',     lambda : self.title1)
        self.ifi.AddProperty('title2',     lambda : self.title2)
        self.ifi.AddProperty('xlabel',     lambda : self.xlabel)
        self.ifi.AddProperty('ylabel',     lambda : self.ylabel)
        self.ifi.AddProperty('zlabel',     lambda : self.zlabel)
        self.ifi.AddProperty('x0dpi',      lambda : self.x0dpi) ##[inamura 120710]
        self.ifi.AddProperty('x1dpi',      lambda : self.x1dpi)
        self.ifi.AddProperty('y0dpi',      lambda : self.y0dpi)
        self.ifi.AddProperty('y1dpi',      lambda : self.y1dpi)
        self.ifi.AddProperty('qdata',      lambda : self.qdata)
        self.ifi.AddProperty('edata',      lambda : self.edata)
        self.ifi.AddProperty('strenergy',  lambda : self.strEnergy)
        self.ifi.AddProperty('strq',       lambda : self.strQ)
        self.ifi.AddProperty('cursol',     lambda : self.xcyc)
        ##[inamura 090924]->
        self.ifi.AddProperty('colormap',   lambda : self.colormap)
        self.ifi.AddProperty('autox2d',    lambda : self.autox2DFlag)
        self.ifi.AddProperty('autoy2d',    lambda : self.autoy2DFlag)
        self.ifi.AddProperty('xrange2d',   lambda : self.xrange)
        self.ifi.AddProperty('yrange2d',   lambda : self.yrange)
        ##<-[inamura 090924]
        self.ifi.AddProperty('only2d',   lambda : self.isOnly) ##[inamura 120417]
        self.ifi.AddProperty('drawdic',  lambda : self.DrawDic)##[inamura 120711]
        self.ifi.AddProperty('gridstyledic', lambda : self.GridStyleDic) ##[ianmrua 160124]
        self.ifi.AddProperty('tickstyledic', lambda : self.TickStyleDic) ##[inamura 160726]
        
        # データ無しか
        #if self.Z is None: #[inamura 171106]
        if not isinstance(self.Z, ndarray):
            return
                
        # カーソル位置の初期値をテキストボックスに設定
        cx = self.xrange[0]+ (self.xrange[1] - self.xrange[0] ) / 2.0
        # スライス条件指定イベント発行
        self.ifi.NotifyEvent(self, "slicey", (cx, 0.0, 0.0)) 
        cy = self.yrange[0]+ (self.yrange[1] - self.yrange[0] ) / 2.0
        # スライス条件指定イベント発行
        self.ifi.NotifyEvent(self, "slicex", (cy, 0.0, 0.0))
        # カーソルとグラフを表示
        self.UpdateCursol(3) 
    
    #########################################
    def _DispInitialMap(self):
        """
        データの準備
        @param  無し   
        @retval 無し
        """ 
        self.title1 = ""
        self.title2 = ""
        # 各軸のラベル文字列を作成
        self.xlabel = "X"
        self.ylabel = "Y"
        self.zlabel = "Z" 

        ##[inamura 090924]->
        # Color Scale 0: gray scale, 1: jet
        self.colormap = "default"
        self.autox2DFlag = True
        self.autoy2DFlag = True
        ##<-[inamura 090924]
        ##[inamura 110125]-->
        # Original ColorMap
        cdict = {'blue': ((0.0, 0.0, 0.0),
                          (0.16, 1, 1),
                          (0.377, 1, 1),
                          (0.67, 0, 0),
                          (1, 0,0)),
                 'green': ((0.0, 0, 0),
                           (0.174, 0, 0),
                           (0.410, 1, 1),
                           (0.66, 1, 1),
                           (0.915, 0, 0),
                           (1, 0, 0)),
                 'red': ((0.0, 0, 0),
                         (0.387, 0, 0),
                         (0.680, 1, 1),
                         (0.896, 1, 1),
                         (1, 0.5, 0.5))
                 }
        
        self.colormap_default = matplotlib.colors.LinearSegmentedColormap('default_utsusemi',cdict,256)
        ##<--[inamura 110125]
        ##[inamura 170302]-->
        _GMT_haxby_data =  {'blue': [(0.0, 0.474509805441, 0.474509805441), (0.0322580635548, 0.588235318661, 0.588235318661), (0.0645161271095, 0.686274528503, 0.686274528503), (0.0967741906643, 0.784313738346, 0.784313738346), (0.129032254219, 0.831372559071, 0.831372559071), (0.161290317774, 0.878431379795, 0.878431379795), (0.193548381329, 0.941176474094, 0.941176474094), (0.225806444883, 0.972549021244, 0.972549021244), (0.258064508438, 1.0, 1.0), (0.290322571993, 1.0, 1.0), (0.322580635548, 1.0, 1.0), (0.354838699102, 0.941176474094, 0.941176474094), (0.387096762657, 0.882352948189, 0.882352948189), (0.419354826212, 0.784313738346, 0.784313738346), (0.451612889767, 0.68235296011, 0.68235296011), (0.483870953321, 0.658823549747, 0.658823549747), (0.516129016876, 0.635294139385, 0.635294139385), (0.548387110233, 0.552941203117, 0.552941203117), (0.580645143986, 0.474509805441, 0.474509805441), (0.612903237343, 0.407843142748, 0.407843142748), (0.645161271095, 0.341176480055, 0.341176480055), (0.677419364452, 0.270588248968, 0.270588248968), (0.709677398205, 0.29411765933, 0.29411765933), (0.741935491562, 0.305882364511, 0.305882364511), (0.774193525314, 0.352941185236, 0.352941185236), (0.806451618671, 0.486274510622, 0.486274510622), (0.838709652424, 0.61960786581, 0.61960786581), (0.870967745781, 0.68235296011, 0.68235296011), (0.903225779533, 0.768627464771, 0.768627464771), (0.93548387289, 0.843137264252, 0.843137264252), (0.967741906643, 0.921568632126, 0.921568632126), (1.0, 1.0, 1.0)], 'green': [(0.0, 0.0, 0.0), (0.0322580635548, 0.0, 0.0), (0.0645161271095, 0.0196078438312, 0.0196078438312), (0.0967741906643, 0.0392156876624, 0.0392156876624), (0.129032254219, 0.0980392172933, 0.0980392172933), (0.161290317774, 0.156862750649, 0.156862750649), (0.193548381329, 0.40000000596, 0.40000000596), (0.225806444883, 0.505882382393, 0.505882382393), (0.258064508438, 0.686274528503, 0.686274528503), (0.290322571993, 0.745098054409, 0.745098054409), (0.322580635548, 0.792156875134, 0.792156875134), (0.354838699102, 0.882352948189, 0.882352948189), (0.387096762657, 0.921568632126, 0.921568632126), (0.419354826212, 0.921568632126, 0.921568632126), (0.451612889767, 0.92549020052, 0.92549020052), (0.483870953321, 0.960784316063, 0.960784316063), (0.516129016876, 1.0, 1.0), (0.548387110233, 0.960784316063, 0.960784316063), (0.580645143986, 0.92549020052, 0.92549020052), (0.612903237343, 0.843137264252, 0.843137264252), (0.645161271095, 0.741176486015, 0.741176486015), (0.677419364452, 0.627451002598, 0.627451002598), (0.709677398205, 0.458823531866, 0.458823531866), (0.741935491562, 0.313725501299, 0.313725501299), (0.774193525314, 0.352941185236, 0.352941185236), (0.806451618671, 0.486274510622, 0.486274510622), (0.838709652424, 0.61960786581, 0.61960786581), (0.870967745781, 0.701960802078, 0.701960802078), (0.903225779533, 0.768627464771, 0.768627464771), (0.93548387289, 0.843137264252, 0.843137264252), (0.967741906643, 0.921568632126, 0.921568632126), (1.0, 1.0, 1.0)], 'red': [(0.0, 0.0392156876624, 0.0392156876624), (0.0322580635548, 0.156862750649, 0.156862750649), (0.0645161271095, 0.0784313753247, 0.0784313753247), (0.0967741906643, 0.0, 0.0), (0.129032254219, 0.0, 0.0), (0.161290317774, 0.0, 0.0), (0.193548381329, 0.101960785687, 0.101960785687), (0.225806444883, 0.0509803928435, 0.0509803928435), (0.258064508438, 0.0980392172933, 0.0980392172933), (0.290322571993, 0.196078434587, 0.196078434587), (0.322580635548, 0.266666680574, 0.266666680574), (0.354838699102, 0.380392163992, 0.380392163992), (0.387096762657, 0.415686279535, 0.415686279535), (0.419354826212, 0.486274510622, 0.486274510622), (0.451612889767, 0.541176497936, 0.541176497936), (0.483870953321, 0.674509823322, 0.674509823322), (0.516129016876, 0.803921580315, 0.803921580315), (0.548387110233, 0.874509811401, 0.874509811401), (0.580645143986, 0.941176474094, 0.941176474094), (0.612903237343, 0.96862745285, 0.96862745285), (0.645161271095, 1.0, 1.0), (0.677419364452, 1.0, 1.0), (0.709677398205, 0.956862747669, 0.956862747669), (0.741935491562, 0.933333337307, 0.933333337307), (0.774193525314, 1.0, 1.0), (0.806451618671, 1.0, 1.0), (0.838709652424, 1.0, 1.0), (0.870967745781, 0.960784316063, 0.960784316063), (0.903225779533, 1.0, 1.0), (0.93548387289, 1.0, 1.0), (0.967741906643, 1.0, 1.0), (1.0, 1.0, 1.0)]}
        self.colormap_haxby = matplotlib.colors.LinearSegmentedColormap('GMT_haxby',_GMT_haxby_data,256)
        ##<--[inamura 170302]
        # マップデータ取得
        self.Z = self.ifi.GetProperty("mapdata")
        # データ無しなら
        #if self.Z is None: #[inamura 171106]
        if not isinstance(self.Z, ndarray):
            return

        # Zデータの範囲を取得
        min, max, self.offset = self.ifi.GetProperty("zrange")
        if min >= 0.0:
            min = 0.0
        else:
#            if self.ifi.GetProperty("logflag"):  # 2008/04/28 Minakawa modify
           if self.logFlag:
                min = 0.0
            
        # 描画範囲を作る
        self.zMin = self.datMin = min
        self.zMax = self.datMax = max
        # グリッドデータ作成
        self.X,self.Y = self.ifi.GetProperty("grid")
        # マップデータからマスクデータ作成
        self.Zm = ma.masked_where(self.Z >= MASKVALUE-1.0, self.Z)
        
        # 描画範囲の初期設定設定
        self.xrange = (self.X.min(), self.X.max())
        self.yrange = (self.Y.min(), self.Y.max())
        
       
    #########################################        
    def _ConvertCenterValue(self, bins):
        """
        bin値の中央値に変換する
        @param   bins  bin値をいれた配列
        @retval 中央値に変換後の配列
        """ 
        # データ(bin の境界値)数 - 1 の array を作る
        xx = zeros(len(bins)-1, float64)
        # 各bin の中央値を作る
        for i in range(len(bins)-1):
            xx[i]= (bins[i]+bins[i+1])/2.0
            
        return xx    

    #########################################        
    def GetMax(self, data, rng ):
        """
        指定範囲内で、マスク値を除く最大値を取得
        @param   data データ
        @param   rng 　探索範囲始値と終値のタプル
        @retval 最小値と最大値のタプル
        """ 
        minV = 100000000000000.0
        maxV = -10000000000000.0
        # データ配列を探索
        for i in range(len(data.counts)):
            # 指定された範囲内か
            if data.bins[i+1] >= rng[0] and data.bins[i+1] <= rng[1]:
                # 最小値サーチ
                if data.counts[i] < minV:
                    minV = data.counts[i]
                # マスク値でなければ
                if data.counts[i] < MASKVALUE-1.0:
                    # 最大値サーチ
                    if data.counts[i] > maxV:
                        maxV = data.counts[i]
        if minV > 0.0:
            minV = 0.0     
        return (minV, maxV*1.05)                         
  
    #########################################        
    def UpdateQbinGraph(self, eslice):
        """
        指定された E値におけるQ bin グラフの表示
        @param   eslice  E中央値、E始値、E終値のタプル 
        @retval 無し
        """ 
        # エネルギー値の等しい点におけるヒストグラムを取得
        try:
            self.qdata = self.dmap.GetHistX(eslice)
        except PlotException, ex:
            PlotMessage(self.frame, ex)
        if self.qdata == None:
            print "UpdateQbinGraph Er"
            return
        # Xデータ(bin の境界値)の中央値に変換
        self.qxx = self._ConvertCenterValue(self.qdata.bins)
        # 指定範囲における、マスク値を除いた最大値を求める
        qzmin, qzmax = self.GetMax(self.qdata, self.ax.get_xlim())

        # マスクデータに変換        
        self.qzm = ma.masked_where(self.qdata.counts >= MASKVALUE, self.qdata.counts)
        
        # グラフ上に表示する値を保存

        if self.qdata.fp-self.qdata.ep == 0.0:
            self.strEnergy = "%.3f" % self.qdata.mp
        else:
            self.strEnergy = "%.3f (%.3f - %.3f)" % (self.qdata.mp,self.qdata.fp,self.qdata.ep) 

        # グラフの描画
        self.DrawQbinGraph(self.ax.get_xlim(), (qzmin, qzmax))

    #########################################        
    def DrawQbinGraph(self, xlim, ylim):
        """
        指定された E値におけるQ bin グラフの表示
        @param   xlim  X軸範囲のタプル
        @param   ylim  Y軸範囲のタプル
        @retval 無し
        """ 
        if self.isOnly:
            return ##[inamura 120211]
        # Q bin グラフをクリア
        self.axq.clear() 

        # 指定された E値におけるQ bin グラフ表示
        self.axq.plot(self.qxx,self.qzm, linewidth=0.6)
        #[inamura 160627]-->
        if self.isLogX:
            if self.qxx.min()!=MASKVALUE:
                self.axq.set_xscale('log')
        else:
            self.axq.set_xscale('linear')
        #<--[inamura 160627]
        # 座標ラベルの文字を小さくする
        xcl = getp(self.axq, 'xticklabels')
        setp(xcl, size=7)
        ycl = getp(self.axq, 'yticklabels')
        setp(ycl, size=7)     

        # 表示範囲を設定

        self.axq.set_xlim(xlim)
        self.axq.set_ylim(ylim)
        # グラフタイトルを表示
        strGtitle = "Y = %s" % self.strEnergy
        yy = (ylim[1]-ylim[0])*0.05+ylim[1]
        ##[inamura 120711]-->
        target = self.DrawDic["MultiMode"]
        #self.axq.text(xlim[0], yy, strGtitle, fontsize = 8)
        self.axq.text(xlim[0], yy, strGtitle, fontname=target["TitleFont"],fontsize = 8)
        # Y軸のラベルを表示
        #self.axq.set_ylabel(self.zlabel, fontsize = 9)
        self.axq.set_ylabel(self.zlabel, fontname=target["TitleFont"],fontsize = 9)
        ##<--[inamura 120711]
    #########################################        
    def UpdateEbinGraph(self, qslice):
        """
        指定された Q値におけるE bin グラフの表示
        @param   qslice  Q中央値、Q始値、Q終値のタプル 
        @retval 無し
        """ 
        # 指定されたQ値におけるヒストグラムを取得
        try:
            self.edata = self.dmap.GetHistY(qslice)
        except PlotException, ex:
            PlotMessage(self.frame, ex)
        if self.edata == None:
            #print "UpdateEbinGraph Er" #[inamura 160803]
            return
        # Xデータ(bin の境界値)の中央値に変換
        yy = self._ConvertCenterValue(self.edata.bins)
        # 指定範囲における、マスク値を除いた最大値を求める
        ezmin, ezmax = self.GetMax(self.edata, self.ax.get_ylim())

        # 縦グラフ用にマスクデータを変換
        for i in range(len(yy)):
            if self.edata.counts[i] >= MASKVALUE-1.0:
                # マスクデータセット
                yy[i] = MASKVALUE
        # 表示用のマスクデータを作成
        self.ym = ma.masked_where(yy >= MASKVALUE, yy)

        # Q値のテキストを保存
        if self.edata.fp-self.edata.ep == 0.0:
            self.strQ = "%.3f" % self.edata.mp
        else:
            self.strQ = "%.3f (%.3f - %.3f)" % (self.edata.mp,self.edata.fp,self.edata.ep) 
            
        # グラフの描画
        self.DrawEbinGraph((ezmin, ezmax), self.ax.get_ylim(),)

    #########################################        
    def DrawEbinGraph(self, xlim, ylim):
        """
        指定された E値におけるQ bin グラフの表示
        @param   xlim  X軸範囲のタプル
        @param   ylim  Y軸範囲のタプル
        @retval 無し
        """         
        if self.isOnly:
            return ##[inamura 120211]
        # E bin グラフをクリア
        self.axe.clear()
        # E bin グラフ表示
        self.axe.plot(self.edata.counts, self.ym, linewidth=0.6)
        #[inamura 160627]-->
        if self.isLogY:
            if self.edata.counts.min()!=MASKVALUE:
                self.axe.set_yscale('log')
        else:
            self.axe.set_yscale('linear')
        #<--[inamura 160627]
        # 座標ラベルの文字を小さくする

        xcl = getp(self.axe, 'xticklabels')
        setp(xcl, size=7)
        ycl = getp(self.axe, 'yticklabels')
        setp(ycl, size=7)   
        # Q値のタイトル文字列を作る
        strGtitle = "X = %s" % self.strQ
        # スケール範囲を設定
        self.axe.set_xlim(xlim)
        self.axe.set_ylim(ylim)

        yy = (ylim[1]-ylim[0])*0.015+ylim[1] 
        # タイトル文字列表示
        ##[inamura 120711]-->
        target = self.DrawDic["MultiMode"]
        #self.axe.text(xlim[0], yy, strGtitle, fontsize = 8)
        self.axe.text(xlim[0], yy, strGtitle, fontname=target["LabelFont"],fontsize = 8)
        # X軸のラベルを表示
        #self.axe.set_xlabel(self.zlabel, fontsize = 9)
        self.axe.set_xlabel(self.zlabel, fontname=target["LabelFont"],fontsize = 9)
        ##<--[inamura 120711]

    #########################################        
    def UpdateCursol(self, graphid):
        """
        十字カーソルとカーソル位置のグラフを表示
        @param   graphid 
                 1: Q bin graph のみ
                 2: Energy bin graph のみ
                 3: 両方のグラフ
        @retval 無し
        """ 
        # パラメータの取得要求
        self.ifi.NotifyEvent(self, "pickparams") 

        # パネルからX 軸スライス条件を取得
        x0, x1, frcX, xbin, xflag = self.ifi.GetProperty("xparam")
        if graphid == 2:
            xc = self.xcyc[0]
            frcX = 0

        # パネルからY 軸スライス条件を取得
        y0, y1, frcY, ybin, yflag = self.ifi.GetProperty("yparam")
        if graphid == 1:
            frcY = 0
            yc = self.xcyc[1]
        
        # Q bin と E bin 両方のグラフの描画が終了するまで繰り返す
        while True:
            # Q bin グラフの描画は必要か?
            if frcX > 0:
                xr = (x1-x0)/frcX
                xx = x0+xr/2.0
                xc = [xx, x0, x0+xr, xbin, xflag]
            # E bin グラフの描画は必要か?    
            if frcY > 0:
                yr = (y1-y0)/frcY
                yy = y0+yr/2.0
                yc = [yy, y0, y0+yr, ybin, yflag]

                
            # Q bin　と E bin の両方のグラフ描画か     
            if graphid == 3:
                # Q bin グラフの描画は終了しているか

                if frcX <= 0:
                    # E bin グラフのみの描画指定   
                    graphid = 2
                # E bin グラフの描画は終了しているか   
                elif frcY <= 0:
                    # Q bin グラフのみの描画指定  
                    graphid = 1
                    
            # カーソルとグラフ表示
            self.UpdateGraphs(xc,yc,graphid)

            if frcX:
                x0 = x0+xr
                frcX = frcX - 1
            if frcY:
                y0 = y0+yr
                frcY = frcY - 1
            # 描画終了か
            if frcX <= 0 and frcY <= 0:
                break
            else:
                # 次のグラフを描画する場合、すぐに消えないようにする
                time.sleep(1) 
        
        #--> [KCS: 130520]
        # オーバプロット表示
        #self.DrawOverPlot()
        # クリップ領域表示
        #self.DrawClipRegion()
        #self.canvas.draw()
        #<-- [KCS: 130520]

    #########################################        
    def DrawCursols(self, xc, yc, spanflag):
        """
        十字カーソルとカーソル位置のグラフを表示
        @param   xc　　Q bin グラフ表示条件
        @param   yc　　E bin グラフ表示条件  
        @param   spanflag    
                 True: 領域を半透明の帯で表示
                 False: 領域を破線で表示
        @retval 無し
        """ 
        if xc == None:
            return
        # カーソルをクリア
        self.cursol.clear()
        
        #--> 2013.06.25 KCS Bug Fix
        # オーバプロット表示
        self.DrawOverPlot()
        # クリップ領域表示
        self.DrawClipRegion()
        #<-- 2013.06.25 KCS Bug Fix        
        
        ##[inamura 110106]-->
        # If Cursor Off mode
        if not self.toolbar.cursorMode:
            self.cursol.set_xlim(self.ax.get_xlim()) 
            self.cursol.set_ylim(self.ax.get_ylim())
            self.cursol.set_xticks([])
            self.cursol.set_yticks([])
            return
        ##<--[inamura 110106]
        # 半透明の帯で表示か
        if spanflag:
            # X軸のスライス範囲を半透明な領域で表示
            self.cursol.axhspan(xc[1], xc[2],facecolor='w', alpha=0.4) 
            # Y軸のスライス範囲を半透明な領域で表示
            self.cursol.axvspan(yc[1], yc[2],facecolor='w', alpha=0.4) 
        else:
            # X軸のスライス範囲を点線で表示
            self.cursol.axhline(y=xc[1], linestyle='--', color='k', linewidth=0.6)
            self.cursol.axhline(y=xc[2], linestyle='--', color='k', linewidth=0.6)
            # Y軸のスライス範囲を点線で表示
            self.cursol.axvline(x=yc[1], linestyle='--', color='k', linewidth=0.6)
            self.cursol.axvline(x=yc[2], linestyle='--', color='k', linewidth=0.6)
            
        # 中心値に十字カーソルを表示
        self.cursol.axhline(y=xc[0], color='k', linewidth=0.6)
        self.cursol.axvline(x=yc[0], color='k', linewidth=0.6)
        
        # カーソルのスケールをカラーマップのスケールに合わせる
        self.cursol.set_xlim(self.ax.get_xlim()) 
        self.cursol.set_ylim(self.ax.get_ylim())
        
        # カーソルのスケール文字を消す
        self.cursol.set_xticks([])
        self.cursol.set_yticks([])

    #########################################        
    def UpdateGraphs(self, xc, yc, graphid, pflag = True):
        """
        十字カーソルとカーソル位置のグラフを表示
        @param   xc　　Q bin グラフ表示条件
        @param   yc　　E bin グラフ表示条件  
        @param   grahid    
                 1: Q bin graph のみ
                 2: Energy bin graph のみ
                 3: 両方のグラフ
        @param   pflag プロッタ送信フラグ
        　　　　　True: プロッタ送信が指定されていれば送信
        　　　　　False: プロッタ送信が指定されていても送信しない
                        (タイトル、ラベル変更時等に使用)          
        @retval 無し
        """ 
        # データ無しか
        if xc == None:
            self.canvas.draw()
            return
        # Q bin graph　表示か
        if graphid == 1 or graphid == 3:
            # Q bin グラフを描画
            self.UpdateQbinGraph(xc)
            if self.qdata == None:
                return
            xc[0] = self.qdata.mp
            xc[1] = self.qdata.fp
            xc[2] = self.qdata.ep
        # E bin グラフ　表示か
        if graphid == 2 or graphid == 3:
            #  E bin グラフを描画
            self.UpdateEbinGraph(yc)
            if self.edata == None:
                return
            yc[0] = self.edata.mp
            yc[1] = self.edata.fp
            yc[2] = self.edata.ep
        # カーソルを再表示
        self.DrawCursols(xc, yc, True) 
        
        #<-- 2013.06.25 KCS Bug Fix
        # オーバプロット表示
        #self.DrawOverPlot()
        # クリップ領域表示
        #self.DrawClipRegion()
        #-->2013.06.25 KCS Bug Fix       
       
        self.canvas.draw()
        self.frame.Update()
        
        # Q bin graph　表示か
        if graphid == 1 or graphid == 3:
            # with Plotter Sending が指定されていたなら
            if xc[4] and pflag:
                # プロッタ(1) にデータ追加指定
                self.ifi.NotifyEvent(self, "add", 1) 
        # E bin グラフ　表示か
        if graphid == 2 or graphid == 3:
            # with Plotter Sending が指定されていたなら
            if yc[4] and pflag:
                # プロッタ(2) にデータ追加指定
                self.ifi.NotifyEvent(self, "add", 2) 
                
        # 印刷用に、現在の領域を保存
        self.xcyc = (xc,yc)

    #########################################
    def PlotD2Chart(self):
        """
        2Dチャートを描画する
        @param   無し   
        @retval 無し
        """ 
        ##[inamura 120711]-->
        if self.isOnly:
            target = self.DrawDic["SingleMode"]
        else:
            target = self.DrawDic["MultiMode"]
        ##<--[inamura 120711]

        # 全グラフクリア
        self.fig.clf()
        # グラフのメインタイトルを表示
        #self.fig.text(0.1, 0.97, self.title1, fontsize = 10)
        self.fig.text(0.1, 0.97, self.title1, fontname=target["TitleFont"], fontsize=target["TitleSize"]) ##[inamura 120711]
        # グラフのサブタイトルを表示
        ##[inamura 120211]-->
        if self.isOnly:
            colms = self.title2.split(';')
            colm_offset = float( int(800/len(colms)) )/1000.0
            xxt = 0.15
            #xxt = 0.6
            for colm in colms:
                #yyt = 0.945
                #yyt = 0.97
                yyt = 0.940
                lines = colm.split('\n')
                for line in lines:
                    #self.fig.text( xxt, yyt, line, fontsize=9 )
                    self.fig.text( xxt, yyt, line, fontname=target["TitleFont"], fontsize=target["TitleSize"]) ##[inamura 120711]
                    yyt = yyt-0.025
                xxt = xxt + colm_offset
        else:
            title2 = self.title2.replace(';','')
            lines = title2.split('\n')
            yyt = 0.945
            for line in lines:
                #self.fig.text(0.76, yyt, line, fontsize = 9)
                self.fig.text(0.76, yyt, line, fontname=target["TitleFont"], fontsize=target["TitleSize"]) ##[inamura 120711]
                yyt = yyt - 0.025
        ##<--[inamura 120211]
        
        # SQEマップ用のサブプロットを準備
        self.ax = self.fig.add_subplot(111)
        #self.ax.set_position([0.1, 0.095, 0.63 ,0.62])
        self.ax.set_position(target["MainPosi"]) ##[inamura 120211]
        
        if not self.isOnly:
            # Q bin ヒストグラム用の座標を用意
            self.axq = self.fig.add_axes([0.1, 0.74, 0.63 ,0.19])
            
            # Energy bin ヒストグラム用の座標を用意
            self.axe = self.fig.add_axes([0.790, 0.095, 0.18 ,0.62])
        
        #--> {KCS: 140430]     
        # オーバプロット用のサブプロットを準備(透過モード)
        self.ovplot = self.fig.add_subplot(111,frameon=False)
        self.ovplot.set_position(target["MainPosi"])
        #<-- {KCS: 140430]

        
        # データがあれば
        #if self.Z is not None: #[inamura 171106]
        if isinstance(self.Z, ndarray):
            # カラーバー用の座標軸を準備
            #axc = self.fig.add_axes([0.02, 0.04, 0.28 ,0.02])
            axc = self.fig.add_axes(target["ColorBarPosi"]) ##[inamura 120211]
            # カーソル表示用のサブプロットを準備(透過モード)
            self.cursol = self.fig.add_subplot(111,frameon=False)
            #self.cursol.set_position([0.1, 0.095, 0.63 ,0.62])
            self.cursol.set_position(target["MainPosi"])    ##[inamura 120211]
            
            
            # マスクデータの色作成(白色)
            ##[inamura 090924]->
            #print "PlotD2Chart >> self.colormap=",self.colormap
            ##[inamura 110125]-->
            if self.colormap=="default":
                cmap=self.colormap_default
            elif self.colormap=="haxby":  #[inamura 170302]
                cmap=self.colormap_haxby
            else:
                cmap=get_cmap(self.colormap)
            ##<--[inamura 110125]
            #cmap = cm.jet
            ##<-[inamura 090924]
            ##[inamura 170111]-->
            #cmap.set_bad('w', 1.0)
            #self.ax.set_axis_bgcolor('k')
            cmap.set_bad(self.TickStyleDic["BadColor"], 1.0)
            if matplotlib_verNo<2000:
                self.ax.set_axis_bgcolor(self.TickStyleDic["BGColor"])
            else:
                self.ax.set_facecolor(self.TickStyleDic["BGColor"])
            ##<--[inamura 170111]

            # ログモードか
            if self.logFlag:
                logZm = self.Zm + self.offset
                zmin = self.zMin
                # 表示データの最小値以下か
                #[inamura 100618]-->
                #if zmin < 0.05:
                #    zmin = 0.05
                if zmin < 1.0E-25:
                    zmin = 1.0E-25
                pc = self.ax.pcolormesh(self.X, self.Y, logZm,  cmap=cmap, \
                                    norm=LogNorm(vmin=zmin, vmax=self.zMax))
            # リニアモード
            else:
                pc = self.ax.pcolormesh(self.X, self.Y, self.Zm, cmap=cmap, \
                                        norm=Normalize(vmin=self.zMin, vmax=self.zMax))
                              

            #[inamura 160627]-->
            if self.isLogX:
                self.ax.set_xscale("log")
            else:
                self.ax.set_xscale("linear")
            if self.isLogY:
                self.ax.set_yscale("log")
            else:
                self.ax.set_yscale("linear")
            #<--[inamura 160627]
            # カラーマップと関連付けて、カラーバーを表示
            #self.fig.colorbar(pc, cax=axc, orientation='horizontal')
            self.fig.colorbar(pc, cax=axc, orientation=target["ColorBarOri"]) ##[inamura 120211]
            axc.yaxis.set_tick_params( which='major', left=True) ##[inamura 160728]
            #axc.xaxis.set_tick_params( which='major', top=True) ##[inamura 160728]

            # 座標範囲を設定
            self.ax.set_xlim(self.xrange[0], self.xrange[1])
            self.ax.set_ylim(self.yrange[0], self.yrange[1])
            self.cursol.set_xlim(self.xrange[0], self.xrange[1])
            self.cursol.set_ylim(self.yrange[0], self.yrange[1])
            self.ovplot.set_xlim(self.xrange[0], self.xrange[1])
            self.ovplot.set_ylim(self.yrange[0], self.yrange[1])
            # カラーバーの座標ラベルの文字を小さくする
            xlabels = getp(axc, 'xticklabels')
            setp(xlabels, size=6)
            ylabels = getp(axc, 'yticklabels') ##[inamura 120211]
            setp(ylabels, size=6)
        
        else:
            if not self.isOnly:
                setp( self.axq.get_xticklabels(), visible=False)
                setp( self.axq.get_yticklabels(), visible=False)
                setp( self.axe.get_xticklabels(), visible=False)
                setp( self.axe.get_yticklabels(), visible=False)
            #setp( self.axq.get_xticklabels(), visible=False)
            #setp( self.axq.get_yticklabels(), visible=False)
            #setp( self.axe.get_xticklabels(), visible=False)
            #setp( self.axe.get_yticklabels(), visible=False)
        
        # カラーマップの座標ラベルの文字を小さくする
        #setp(self.ax.get_xticklabels(), size=8)
        #setp(self.ax.get_yticklabels(), size=8)     
        setp(self.ax.get_xticklabels(), size=target["TickLabelSize"])
        setp(self.ax.get_yticklabels(), size=target["TickLabelSize"]) ##[inamura 120211]
        setp(self.ax.get_xticklabels(), fontname=target["ScaleFont"]) ##[inamura 120711]
        setp(self.ax.get_yticklabels(), fontname=target["ScaleFont"]) ##[inamura 120711]
        
        # X軸のラベルを表示
        #self.ax.set_xlabel(self.xlabel, fontsize = 9)
        self.ax.set_xlabel(self.xlabel, fontname=target["LabelFont"], fontsize=target["LabelSize"]) ##[inamura 120711]
        # Y軸のラベルを表示
        self.ax.yaxis.tick_left()
        #self.ax.set_ylabel(self.ylabel, fontsize = 9)
        self.ax.set_ylabel(self.ylabel, fontname=target["LabelFont"], fontsize=target["LabelSize"]) ##[inamura 120711]
        
        ##[inamura 160124]-->
        if (self.GridStyleDic["Show"]):
            # X-axis grid style
            self.ax.xaxis.grid(True, color=self.GridStyleDic["XlineColor"],
                               linestyle=self.GridStyleDic["XlineStyle"],
                               linewidth=self.GridStyleDic["XlineWidth"])
            # Y-axis grid style
            self.ax.yaxis.grid(True, color=self.GridStyleDic["YlineColor"],
                               linestyle=self.GridStyleDic["YlineStyle"],
                               linewidth=self.GridStyleDic["YlineWidth"])
        else:
            self.ax.xaxis.grid(False)
            self.ax.yaxis.grid(False)
        ##<--[inamura 160124]
        ##[inamura 160726]-->
        tcolor = self.TickStyleDic["TickColor"] ##[inamura 160728]
        self.ax.xaxis.set_tick_params( which='major', length=self.TickStyleDic["MajorLength"], width=self.TickStyleDic["MajorWidth"], top=self.TickStyleDic["TopSide"],color=tcolor )
        self.ax.yaxis.set_tick_params( which='major', length=self.TickStyleDic["MajorLength"], width=self.TickStyleDic["MajorWidth"], right=self.TickStyleDic["RightSide"],color=tcolor )
        if (self.TickStyleDic["Minor"]):
            from matplotlib.ticker import AutoMinorLocator
            self.ax.xaxis.set_minor_locator(AutoMinorLocator(5))
            self.ax.yaxis.set_minor_locator(AutoMinorLocator(5))
            self.ax.xaxis.set_tick_params( which='minor', length=self.TickStyleDic["MinorLength"], width=self.TickStyleDic["MinorWidth"], top=self.TickStyleDic["TopSide"],color=tcolor )
            self.ax.yaxis.set_tick_params( which='minor', length=self.TickStyleDic["MinorLength"], width=self.TickStyleDic["MinorWidth"], right=self.TickStyleDic["RightSide"],color=tcolor )
        ##<--[inamura 160726]
        ##[inamura 160728]-->
        lw=self.TickStyleDic["FrameLineWidth"]
        self.ax.spines["top"].set_linewidth(lw)
        self.ax.spines["right"].set_linewidth(lw)
        self.ax.spines["bottom"].set_linewidth(lw)
        self.ax.spines["left"].set_linewidth(lw)
        ##<--[inamura 160728]


    #########################################
    def DrawRectCursol(self, event, downP):
        """
        ドラッグ範囲を半透明のカーソルにて表示
        @param   event マウス移動時のイベント情報 
        @param   downP マウスボタン押下時の位置情報  
        @retval 無し
        """
        #--> [KCS: 130520]
        # クリップダイアログ表示中か
        if self.parent.clipdg == None:
            clipFlg = False
        else:
            clipFlg = self.ifi.GetProperty('clipdg') 
        #<-- [KCS: 130520]
        
        # カーソルをクリア
        self.cursol.clear()
        self.cursol.set_xlim(self.xrange[0], self.xrange[1])
        self.cursol.set_ylim(self.yrange[0], self.yrange[1])
        ##[inamura 100726]-->
        ## if version of matplotlib > 0.98
        if matplotlib_verNo > 980:
            #self.cursol.autoscale(False)
            self.cursol.set_autoscale_on(False) #[inamura 110129]
        ##<--[inamura 100726]
        # ドラッグ開始点と現在のX位置の大小比較
        if event.xdata > downP[2]:
            x0 = downP[2]
            x1 = event.xdata
        else:
            x0 = event.xdata
            x1 = downP[2]
        
        if not clipFlg:  # [KCS: 130520]
            # X軸のマウス移動範囲を半透明な領域で表示
            self.cursol.axvspan(x0, x1,facecolor='w', alpha=0.4) 
        
        # ドラッグ開始点と現在のY位置の大小比較
        if event.ydata > downP[3]:
            y0 = downP[3]
            y1 = event.ydata
        else:
            y0 = event.ydata
            y1 = downP[3]
        # クリップダイアログ表示中であれば
        if clipFlg:
            # 半透明の矩形を表示
            rect = Rectangle((x0, y0), (x1-x0), (y1-y0), ec = 'none', fc='w', alpha=0.4)
            self.cursol.add_patch(rect)
        else:
            # Y軸のマウス移動範囲を半透明な領域で表示
            self.cursol.axhspan(y0, y1,facecolor='w', alpha=0.4)
        
        # カーソルのスケール文字を消す
        self.cursol.set_xticks([])
        self.cursol.set_yticks([])
        
        # グラフを再表示              
        self.canvas.draw()
              
        #--> {KCS: 140430]
    
    ###################################################        
    def OnNotifyOverPlot(self, wid, evtType, traces):
        """
        オーバープロットデータ変更イベント処理
        @param  wid イベント発生元のインスタンス
        @param  evtType イベントタイプ
        @param  traces トレースオブジェクト
        @retval 無し
        """ 
        # トレースデータ表示
        self.traces = traces
        #--> 2013.0625 KCS Bug Fix
        #self.DrawOverPlot()
        xc,yc = self.ifi.GetProperty("cursol")
        self.DrawCursols(xc,yc,True)
        #<-- 2013.0625 KCS Bug Fix
        # グラフを再表示              
        self.canvas.draw()
        
    #########################################
    def DrawOverPlot(self):
        """
        オーバプロットトレースの描画
        @param  無し
        @retval 無し
        """ 
        if self.traces == None:
            return
        # 先の描画をクリア
        #self.ovplot.clear()
        
        for trace in self.traces:
            if trace.draw:
                if trace.xlabel == self.ylabel:
                    self.ovplot.plot(trace.ydata, trace.xdata, linewidth=trace.linewidth,  ##[inamura 160728]
                                     color=trace.color)
                    # 描画範囲を合わせる
                    self.ovplot.set_ylim(self.ax.get_ylim()) 
                    if trace.ylabel != self.zlabel:
                        self.ovplot.set_xlim(self.ax.get_xlim()) 
                else:
                    self.ovplot.plot(trace.xdata, trace.ydata, linewidth=trace.linewidth, ##[inamura 160728]
                                     color=trace.color)
                    # 描画範囲を合わせる
                    self.ovplot.set_xlim(self.ax.get_xlim()) 
                    if trace.ylabel != self.zlabel:
                        self.ovplot.set_ylim(self.ax.get_ylim()) 
        # スケール文字を消す
        self.ovplot.set_xticks([])
        self.ovplot.set_yticks([]) 

    ###################################################        
    def OnNotifyClipRegions(self, wid, evtType, value):
        """
        オーバープロットデータ変更イベント処理
        @param  wid イベント発生元のインスタンス
        @param  evtType イベントタイプ
        @param  rigions 領域オブジェクト
        @retval 無し
        """ 
        # トレースデータ表示
        #--> 2013.0625 KCS Bug Fix
        #self.DrawClipRegion()
        xc,yc = self.ifi.GetProperty("cursol")
        self.DrawCursols(xc,yc,True)
        #<-- 2013.0625 KCS Bug Fix
        # グラフを再表示              
        self.canvas.draw()

    #########################################
    def DrawClipRegion(self):
        """
        クリップ領域の描画
        @param  無し
        @retval 無し
        """ 
        if self.parent.clipdg == None:
            return
        if not self.ifi.GetProperty('clipdg'):
            return
        regions = self.ifi.GetProperty('clipregions')
        
        
        # 先の描画をクリア
        #self.cursol.clear()
        for rg in regions:
            # 半透明の矩形を表示
            if rg.clip:
                color = 'w'
            else:
                color = 'r'
            rect = Rectangle((rg.x0, rg.y0), (rg.x1-rg.x0), (rg.y1-rg.y0),
                              ec = 'none', fc=color, alpha=0.4)
            self.cursol.add_patch(rect)
        
        # カーソルのスケール文字を消す
        self.cursol.set_xticks([])
        self.cursol.set_yticks([])
        
    #<-- {KCS: 140430]
    
        
    ###################################################        
    def OnHome(self, wid, evt, value):
        """
        Home ボタン押下イベント処理関数
        @param  wid イベント発生元のインスタンス
        @param  evt イベントタイプ
        @retval 無し
        """ 
        # カラーマップのX軸に合わせて、Q bin グラフを描画
        qzmin, qzmax = self.GetMax(self.qdata, self.ax.get_xlim())

        self.DrawQbinGraph(self.ax.get_xlim(), (qzmin, qzmax))
        # カラーマップのY軸に合わせて、E bin グラフを描画
        ezmin, ezmax = self.GetMax(self.edata, self.ax.get_ylim())

        self.DrawEbinGraph((ezmin,ezmax), self.ax.get_ylim())
        # グラフを再表示              
        self.canvas.draw()

    ###################################################        
    def OnNotifyChangeData(self, wid, evtType, graphid):
        """
        データ変更イベント処理
        @param  wid イベント発生元のインスタンス
        @param  evtType イベントタイプ
        @param graphid グラフID
        @retval 無し
        """ 
        # データ表示
        self._DispInitialMap()
        self.PlotD2Chart()
       
        # カーソル位置の初期値をテキストボックスに設定
        cx = self.xrange[0]+ (self.xrange[1] - self.xrange[0] ) / 2.0
        # スライス条件指定イベント発行
        self.ifi.NotifyEvent(self, "slicey", (cx, 0.0, 0.0)) 
        cy = self.yrange[0]+ (self.yrange[1] - self.yrange[0] ) / 2.0
        # スライス条件指定イベント発行
        self.ifi.NotifyEvent(self, "slicex", (cy, 0.0, 0.0))
        # カーソルとグラフを表示
        self.UpdateCursol(3)  

    ##[inamura 160603-2]-->
    ###################################################        
    def OnNotifyUpdateData(self, wid, evtType, graphid):
        """
        Update Map Data Event
        made from OnNotifyChangeData
        @param  wid イベント発生元のインスタンス
        @param  evtType イベントタイプ
        @param graphid グラフID
        @retval 無し
        """ 
        # データ表示
        #self._DispInitialMap()
        # マップデータ取得
        self.Z = self.ifi.GetProperty("mapdata")
        #[inamura 160823]-->
        #if self.Z==None: #[inamura 171106]
        if not isinstance(self.Z, ndarray):
            #while(self.Z==None): #[inamura 171106]
            while(not isinstance(self.Z, ndarray)):
                import time
                time.sleep(0.2)
                self.Z = self.ifi.GetProperty("mapdata")
        self.X,self.Y = self.ifi.GetProperty("grid")
        # マップデータからマスクデータ作成
        self.Zm = ma.masked_where(self.Z >= MASKVALUE-1.0, self.Z)
        
        self.DoSmooth() ##[inamura 170306]
        
        # 描画範囲の初期設定設定
        self.xrange = (self.X.min(), self.X.max())
        self.yrange = (self.Y.min(), self.Y.max())
        #<--[inamura 160823]
        try:
            self.PlotD2Chart()
        except:
            self._DispInitialMap()
            self.PlotD2Chart()
       
        ##[inamura 160823]-->
        # パラメータの取得要求
        self.ifi.NotifyEvent(self, "pickparams")
        x0, x1, frcX, xbin, xflag = self.ifi.GetProperty("xparam")
        y0, y1, frcY, ybin, yflag = self.ifi.GetProperty("yparam")
        isXsliceRange= not self.parent.xp.rdCenter.GetValue()
        if x0<self.Y.min() or x1>self.Y.max():
            isXsliceRange=False
            x0 = self.yrange[0]+ (self.yrange[1] - self.yrange[0] ) / 2.0
            x1=x0
           
        isYsliceRange= not self.parent.yp.rdCenter.GetValue()
        if y0<self.X.min() or y1>self.X.max():
            isYsliceRange=False
            y0 = self.xrange[0]+ (self.xrange[1] - self.xrange[0] ) / 2.0
            y1=y0

        if isXsliceRange:
            self.ifi.NotifyEvent(self, "slicexrange", (x0,x1,None,xbin) )
        else:
            self.ifi.NotifyEvent(self, "slicex", ((x0+x1)/2.0, (x1-x0)/2.0, xbin))
        
        if isYsliceRange:
            self.ifi.NotifyEvent(self, "sliceyrange", (y0,y1,None,ybin) )
        else:
            self.ifi.NotifyEvent(self, "slicey", ((y0+y1)/2.0, (y1-y0)/2.0, ybin))
            
        ##<--[inamura 160823]
        # カーソル位置の初期値をテキストボックスに設定
        #cx = self.xrange[0]+ (self.xrange[1] - self.xrange[0] ) / 2.0
        # スライス条件指定イベント発行
        #self.ifi.NotifyEvent(self, "slicey", (cx, 0.0, 0.0)) 
        #cy = self.yrange[0]+ (self.yrange[1] - self.yrange[0] ) / 2.0
        # スライス条件指定イベント発行
        #self.ifi.NotifyEvent(self, "slicex", (cy, 0.0, 0.0))
        # カーソルとグラフを表示
        self.UpdateCursol(3)  
    ##<--[inamura 160603-2]

    ###################################################        
    def OnNotifyShow(self, wid, evtType, graphid):
        """
        グラフ表示要求イベント処理
        @param  wid       イベント発生元のインスタンス
        @param  evtType       イベントタイプ
        @param  graphid 　1: Energy bin graph
　                         2: Q bin graph
        @retval 無し
        """  
    
        self.UpdateCursol(graphid)       

    ###################################################        
    def OnNotifyZScale(self, wid, evtType, zscale):
        """
        Z軸変更イベント処理
        @param  wid イベント発生元のインスタンス
        @param  evtType イベントタイプ
        @param  zscale 　スケール範囲タプル
        @retval 無し
        """ 
        # 自動モードであれば
        if zscale[0]:
            # データの最小値と最大値を設定
            self.zMax = self.datMax
            self.zMin = self.datMin

        # マニュアルモードであれば
        else:
            # データの最小値より小さい値は不可
            if zscale[1] < self.datMin - self.offset:
                self.datMin = self.offset
            # 設定値にオフセットを付加
            self.zMin = zscale[1] + self.offset
            self.zMax = zscale[2] + self.offset

        # マップの再描画
        self.PlotD2Chart()    
        # カーソルを表示
        self.UpdateGraphs(self.xcyc[0], self.xcyc[1], 3, False)         

    ###################################################             
    def OnNotifyTitle(self, wid, evtType, titles):
        """
        グラフタイトル変更イベント処理
        Set Plotting Param ボタンを選択可とする
        @param  wid イベント発生元のインスタンス
        @param  evtType イベントタイプ
        @param  titles 1行目と2行目の文字列タプル
        @retval 無し
        """ 
        # グラフタイトルを取得
        title1, title2 = titles

        # メインタイトルが変更されたか
        if not title1 == '*':
            self.title1 = title1
        # サブタイトルが変更されたか    
        if not title2 == '*':
            self.title2 = title2
        # グラフを再描画
        self.PlotD2Chart()
        # カーソルを表示
        self.UpdateGraphs(self.xcyc[0], self.xcyc[1], 3, False) 

    ###################################################        
    def OnNotifyLabel(self, wid, evtType,labels):
        """
        スケールラベル変更イベント処理
        Set Plotting Param ボタンを選択可とする
        @param  wid イベント発生元のインスタンス
        @param  evtType イベントタイプ
        @param  labels X軸ラベル、Y軸ラベル、Z軸ラベル文字列タプル
        @retval 無し
        """ 
        # 縦軸、横軸のラベルを取得
        xlabel, ylabel, zlabel = labels
        # Xラベルが変更されたか
        if xlabel != '*':
            self.xlabel = xlabel
        # Yラベルが変更されたか   
        if ylabel != '*':
            self.ylabel = ylabel    
        # Zラベルが変更されたか   
        if zlabel != '*':
            self.zlabel = zlabel    
        # グラフを再描画
        self.PlotD2Chart()
        # カーソルを表示
        self.UpdateGraphs(self.xcyc[0], self.xcyc[1], 3, False)  
             

    ###################################################                        
    def OnNotifyLog(self, wid, evtType, value):
        """
        Log モード変更イベント処理
        @param  wid イベント発生元のインスタンス
        @param  evtType イベントタイプ
        @param  value 　Log モードフラグ
        @retval 無し
        """ 
        # ログモード変更
        self.logFlag = value
        # ログモードでは負値は不可
        if value and self.zMin < self.offset:
            self.zMin = self.offset
            
        # マップの再描画
        self.PlotD2Chart()
        # カーソルを表示
        self.UpdateGraphs(self.xcyc[0], self.xcyc[1], 3, False)            

    ###################################################        
    def OnChangeXY(self, wid, evt, mouseEvent):
        """
        ズーム・パン　イベント処理関数
        @param  wid イベント発生元のインスタンス
        @param  evt イベントタイプ
        @param  mouseEvent  マウスボタンダウン時とアップ時のイベントのタプル
        @retval 無し
        """ 
        # ズームまたはパン時のドラッグ開始点のイベント取得
        event = mouseEvent[0]
        # Q bin グラフ内か
        if event.y > self.y1dpi:
            # Q bin グラフを描画
            #self.DrawQbinGraph(self.axq.get_xlim(), self.axq.get_ylim())
            if not self.isOnly:
                self.DrawQbinGraph(self.axq.get_xlim(), self.axq.get_ylim()) ##[inamura 120211]
        # E bin グラフ内か
        elif event.x > self.x1dpi:
            # E bin グラフを描画
            #self.DrawEbinGraph(self.axe.get_xlim(), self.axe.get_ylim())
            if not self.isOnly:
                self.DrawEbinGraph(self.axe.get_xlim(), self.axe.get_ylim()) ##[inamura 120211]
        
        # カラーマップ内か
        else:
            # カラーマップのX軸に合わせて、Q bin グラフを描画
            qzmin, qzmax = self.GetMax(self.qdata, self.ax.get_xlim())
            self.DrawQbinGraph(self.ax.get_xlim(), (qzmin, qzmax))
            # カラーマップのY軸に合わせて、E bin グラフを描画
            ezmin, ezmax = self.GetMax(self.edata, self.ax.get_ylim())
            
            self.DrawEbinGraph((ezmin,ezmax), self.ax.get_ylim())
            
        # グラフを再表示              
        self.canvas.draw()

    ##[inamura 090924]->
    ###################################################                        
    def OnNotifyColorMap(self, wid, evtType, value):
        """
        ColorScale変更イベント処理
        @param  wid イベント発生元のインスタンス
        @param  evtType イベントタイプ
        @param  value 　Name of Colormap
        @retval 無し
        """
        print "OnNotifyColorMap value=",value
        # ColorScale変更
        self.colormap = value
            
        # マップの再描画
        self.PlotD2Chart()
        # カーソルを表示
        self.UpdateGraphs(self.xcyc[0], self.xcyc[1], 3, False)

    ###################################################        
    def OnNotifyXScale2D(self, wid, evtType, xscale):
        """
        プロットデータ変更イベント処理
        @param  wid イベント発生元のインスタンス
        @param  evt イベントタイプ
        @param  scale 　スケール範囲タプル
        @retval 無し
        """ 
        
        # 自動モードか
        if xscale[0]:
            self.autoXFlag = True
        else:
            # 範囲が指定されていたらマニュアル指定
            self.autoXFlag = False
            self.xrange = ( xscale[1], xscale[2] )
            
        # マップの再描画
        self.PlotD2Chart()
        # カーソルを表示
        self.UpdateGraphs(self.xcyc[0], self.xcyc[1], 3, False)
       
    ###################################################        
    def OnNotifyYScale2D(self, wid, evtType, yscale):
        """
        プロットデータ変更イベント処理
        @param  wid イベント発生元のインスタンス
        @param  evt イベントタイプ
        @param  scale 　スケール範囲タプル
        @retval 無し
        """ 
        
        # 自動モードか
        if yscale[0]:
            self.autoYFlag = True
        else:
            # 範囲が指定されていたらマニュアル指定
            self.autoYFlag = False
            self.yrange = ( yscale[1], yscale[2] )

        # マップの再描画
        self.PlotD2Chart()
        # カーソルを表示
        self.UpdateGraphs(self.xcyc[0], self.xcyc[1], 3, False)

    ##<-[inamura 090924]
    ##[inamura 101022]-->
    ###################################################                        
    def OnNotifySmooth(self, wid, evtType, value):
        """
        Smoothing モード変更イベント処理
        @param  wid イベント発生元のインスタンス
        @param  evtType イベントタイプ
        @param  value 　smoothing モードフラグ
        @retval 無し
        """
        #print "OnNotifySmooth"
        # smoothモード変更
        self.smoothFlag = value[0]
        
        self.DoSmooth() ##[inamura 170306]
        
    ###################################################
    def DoSmooth(self):
        """
        Smoothing ##[inamura 170306]
        @param  None
        @retval 無し
        """
        #if self.smoothFlag and self.Z!=None:
        if self.smoothFlag and isinstance(self.Z, ndarray):
            ##[inamura 170306]-->
            smooth_window=self.ifi.GetProperty("smoothwindow")
            sw=int( abs( smooth_window ) ) 
            """
            Zm = self.Z.copy()
            for i in range(int(Zm.size/Zm[0].size)):
                for j in range(int(Zm[0].size-sw*6)):
                    if self.Z[i][sw*3+j]>=MASKVALUE-1.0:
                        ssum=0.0
                        isum=0
                        for k in range(sw*6):
                            if self.Z[i][j+k]< MASKVALUE:
                                isum+=1
                                ssum+=self.Z[i][j+k]
                        if isum!=0:
                            Zm[i][sw*3+j]=ssum/float(isum)
                            
            g = self.gauss_kern( sw, None)
            tmpZm = signal.convolve( Zm, g, mode='valid')
            
            print "Zm.size/Zm[0].size=",Zm.size/Zm[0].size
            print "Zm[0].size = ",Zm[0].size
            print "tmpZm.size/tmpZm[0].size=",tmpZm.size/tmpZm[0].size
            print "tmpZm[0].size = ",tmpZm[0].size
            for i in range( int(tmpZm.size/tmpZm[0].size)):
                for j in range( int(tmpZm[0].size) ):
                    #Zm[i][j]=tmpZm[i+sw][j+sw]
                    Zm[sw+i][sw+j]=tmpZm[i][j]
            self.Zm = ma.masked_where(self.Z >= MASKVALUE-1.0, Zm)
            """
            sw_org = int(abs( smooth_window ) )
            ##<--[inamura 170306]
            sw = int(sw_org*2)
            numZx=int(self.Z.size/self.Z[0].size)
            numZy=int(self.Z[0].size)
            Zm = zeros( (int(numZx+sw*2),int(numZy+sw*2)),float )

            for i in range(numZx):
                for j in range(numZy):
                    Zm[sw+i][sw+j]=self.Z[i][j]
            
            mX,mY = where(self.Z>=(MASKVALUE-1.0))
            for (i,j) in zip( mX, mY ):
                st_k = i-sw
                en_k = i+sw
                st_l = j-sw
                en_l = j+sw
                if st_k<0: st_k=0
                if en_k>=numZx: en_k=numZx-1
                if st_l<0: st_l=0
                if en_l>=numZy: en_l=numZy-1

                ssum = 0.0
                isum = 0
                for k in range(st_k,en_k+1):
                    for l in range(st_l,en_l+1):
                        if self.Z[k][l]< MASKVALUE:
                            isum+=1
                            ssum+=self.Z[k][l]

                if isum!=0:
                    Zm[sw+i][sw+j]=ssum/float(isum)

            
            for i in range(numZx):
                for j in range(sw):
                    Zm[sw+i][j]       = (Zm[sw+i][sw]+Zm[sw+i][sw+1])/2.0
                    Zm[sw+i][j+numZy] = (Zm[sw+i][sw+numZy-2]+Zm[sw+i][sw+numZy-1])/2.0
            
            for i in range(sw):
                for j in range(numZy+sw*2):
                    Zm[i][j]       = (Zm[sw][j]+Zm[sw+1][j])/2.0
                    Zm[numZx+i][j] = (Zm[numZx-2][j]+Zm[numZx-1][j])/2.0

            g = self.gauss_kern( sw_org, None)
            if scipy.__version__ > '0.19.0':
                tmpZm = signal.convolve( Zm, g, mode='valid', method='direct')
            else:
                tmpZm = signal.convolve( Zm, g, mode='valid')
            outZm = zeros( (numZx,numZy),float )
            for i in range(numZx):
                for j in range(numZy):
                    outZm[i][j]=tmpZm[sw_org+i][sw_org+j]
                    
            #print "Zm.size/Zm[0].size=",Zm.size/Zm[0].size
            #print "Zm[0].size = ",Zm[0].size
            #print "tmpZm.size/tmpZm[0].size=",tmpZm.size/tmpZm[0].size
            #print "tmpZm[0].size = ",tmpZm[0].size

            
            if outZm.size==self.Z.size:
                self.Zm = ma.masked_where(self.Z >= MASKVALUE-1.0, outZm)
            else:
                print "self.Z.size/self.Z[0].size=",numZx
                print "self.Z[0].size = ",numZy
                self.Zm = ma.masked_where(self.Z >= MASKVALUE-1.0, self.Z)
            
        else:
            self.Zm = ma.masked_where(self.Z >= MASKVALUE-1.0, self.Z)
            
        # マップの再描画
        self.PlotD2Chart()
        # カーソルを表示
        self.UpdateGraphs(self.xcyc[0], self.xcyc[1], 3, False)

    ###################################################                        
    def gauss_kern(self, size, sizey=None):
        size = int(size)
        if not sizey:
            sizey = size
        else:
            sizey = int(sizey)
        x, y = mgrid[-size:size+1, -sizey:sizey+1]
        g = exp(-(x**2/float(size) + y**2/float(sizey) ) )
        return g / g.sum()
    
    ##<--[inamura 101022]
    ##[inamura 120417]-->
    ###################################################
    def OnNotifyShowOnly2d(self, wid, evtType, value):
        """
        """
        if value in [True,False,None]: ##[inamura 160124]
            if (value!=None):
                self.isOnly=value
            self.PlotD2Chart()
            self.UpdateCursol(3)
            self.canvas.draw()
            ##[inamura 120710]-->
            xsize,ysize = self.panel.GetSize()
            pos = VerHandlePlotLib().GetSubPlotPos(self.ax)
            self.x1dpi = (pos[0]+pos[2])*xsize
            self.y1dpi = (pos[1]+pos[3])*(ysize-20)
            self.y0dpi = pos[1]*(ysize-20)
            self.x0dpi = pos[0]*xsize
            ##<--[inamura 120710]
    ##<--[inamura 120417]
    ##[inamura 120711]-->
    ###################################################
    def OnNotifySetDrawInfo(self, wid, evtType, params):
        """
        """
        for param in params:
            if self.isOnly:
                self.DrawDic["SingleMode"][param[0]]=param[1]
            else:
                self.DrawDic["MultiMode"][param[0]]=param[1]
        
        self.PlotD2Chart()
        self.UpdateCursol(3)
        self.canvas.draw()
    ##<--[inamura 120711]
    ##[inamura 160627]-->
    ###################################################
    def OnNotifySetXLog(self, wid, evtType, flag):
        """
        """
        self.isLogX = flag
        if flag:
            if self.X.min()<=0.0:
                self.ifi.NotifyEvent(self, "setxlog", False)
                self.isLogX = False
                return
        self.PlotD2Chart()
        self.UpdateGraphs(self.xcyc[0], self.xcyc[1], 3, False)            
    ###################################################
    def OnNotifySetYLog(self, wid, evtType, flag):
        """
        """
        self.isLogY = flag
        if flag:
            if self.Y.min()<=0.0:
                self.ifi.NotifyEvent(self, "setylog", False)
                self.isLogY = False
                return
        self.PlotD2Chart()
        self.UpdateGraphs(self.xcyc[0], self.xcyc[1], 3, False)            

    ##<--[inamura 160627]

#######################################
#  CuiIF
####################################### 
class D2CuiIF(object):
    """
    CUI からのコマンドを解析し、プロッタに対し
    イベントを発行する
    """
    ##########################################################
    def __init__(self, order=None):
        """
        コンストラクタ
        @param  order    プロッタの起動順序
        @retval 無し
        """ 
        if order != None:
            self.ifi = IFEvtProp(order)
            
    ###################################################    
    def StartPlot(self, plotNum, func,isQuiet=False): ##[inamura 120417]
        """
        コンストラクタ
        @param  plotNum  プロットナンバー
        @param  func   起動した画面のクローズイベント発生時に実行する関数
        @retval 無し
        """  
        self.func = func
        # テンポラリファイルクラスのインスタンス取得
        self.tp = TempFile()
        
        # 2次元プロッタ画面の起動
        self.plot = MapD2Frame(None, None, plotNum,"",isQuiet) ##[inamura 120417]
 
        # プロッタが公開しているインターフェイスクラスのインスタンスを取得
        self.ifi = IFEvtProp(plotNum)
        
        # プロッタフレームクローズイベントのリスナー登録
        self.ifi.AddListner('plotclose', self.OnNotifyClose)
        
        # コマンドとその実行関数登録
        self.functions = {"changedata"  :self.ChangeData, 
                          "add"         : self.ExecInt, 
                          "clear"       : self.ExecInt, 
                          "setlog"      : self.ChangeMode, 
                          "setwith"     : self.SetWithPlot, 
                          "setzscale"   : self.SetScale,  
                          "save"        : self.SaveFile,
                          "slicex"      : self.Slice,
                          "slicey"      : self.Slice, 
                          "slicexrange" : self.SliceRange,
                          "sliceyrange" : self.SliceRange, 
                          "xlabel"      : self.SetXLabel, 
                          "ylabel"      : self.SetYLabel,
                          "zlabel"      : self.SetZLabel, 
                          "maintitle"   : self.SetMain, 
                          "subtitle"    : self.SetSub,
                          "doiconize"   : self.ChangeMode,  
                          "print"       : self.Exec, 
                          "close"       : self.Exec,
                          "showonly2d"  : self.ShowOnly2d,
                          "updatedata"  : self.UpdateData,  ##[inamura 160603-2]
                          "setxlog"     : self.ChangeMode,
                          "setylog"     : self.ChangeMode } ##[inamura 160627]
                          
        
    #####################################################
    def OnNotifyClose(self, *arg):
        """
        プロッタクローズイベント対応処理
        @param  wid 　 イベント発生元のインスタンス
        @param  evt 　イベントの種類
        @param  value  無し   
        @retval 無し
        """
        # メッセージの解放 
        MessageFile().CloseDoc()
        # 通信クラスの終了処理コールバック関数を実行
        apply(self.func, ())     
        
    ###################################################    
    def TakeCommand(self, strCmd):
        """
        コマンドを解析し、プロッタ画面にイベントを発行
        @param  strCmd コマンド文字列
        @retval コマンドに対する応答
        """  
        # 文字列を空白区切りで分解
        args = strCmd.split()
        # コマンド実行関数を取得
        try:
            function = self.functions[args[0]]
        except:
            print "Command error!!", args
            return
        # 関数の実行
        return function(args)
        
    ###################################################    
    def ChangeData(self, args):
        """
        データ変更イベント発行
        @param  args コマンドと引数のタプル
        @retval 無し
        """
        ##[inamura 170126]-->
        if args[1][-4:]==".map":
            data = self.tp.ReadTempFile(args[1])
            if data == None:
                # 否定応答を返信
                return "NACK\n"
            # データ変更イベント発行
            self.ifi.NotifyEvent(self, args[0], data)

        else:
            # デシリアライズ
            crr = mm.ReadSerializationFileBinary(args[1])
            # 元データがArrayであれば
            if int(args[2]) == 1:
                mat = mm.ElementContainerArray()
                crr.Load(mat)
                del crr
            else:
                mat = ElementContainerMatrix()
                crr.Load(mat)
                del crr
            # デシリアライズ失敗?
            if mat == None:
                # 否定応答を返信
                return "NACK\n"
            # データ変更イベント発行
            self.ifi.NotifyEvent(self, args[0], mat)
            # タイトルとラベル設定イベント発行
            self.SetHeaderAndLabels(mat)
        ##<--[inamura 170126]
        
        ## [KCS 130330]-->
        
        # テンポラリファイルを読んでデシリアライズ
        #data = self.tp.ReadTempFile(args[1])
        #crr = mm.ReadSerializationFileBinary(args[1])
        #if data == None:
            # 否定応答を返信
        #    return "NACK\n"
        # データ変更イベント発行
        #self.ifi.NotifyEvent(self, args[0], data[0])
        
        # タイトル設定イベント発行
        #self.ifi.NotifyEvent(self, "title", (data[1], data[2]))
        # ラベル指定ありか
        #if len(data) == 6:
        #    # ラベル設定イベント発行
        #    self.ifi.NotifyEvent(self, "scalelabel", (data[3], data[4],data[5]))   
        ##[inamura 170126]-->
        """
        # デシリアライズ
        crr = mm.ReadSerializationFileBinary(args[1])
        # 元データがArrayであれば
        if int(args[2]) == 1:
            ##[inamura 130617]-->
            #mat= crr.LoadElementContainerArray()
            mat = mm.ElementContainerArray()
            crr.Load(mat)
            del crr
            ##<--[inamura 130617]
        else:
            ##[inamura 130617]-->
            #mat= crr.LoadElementContainerMatrix()
            mat = ElementContainerMatrix()
            crr.Load(mat)
            del crr
            ##<--[inamura 130617]
        
        # デシリアライズ失敗?
        if mat == None:
            # 否定応答を返信
            return "NACK\n"
        # データ変更イベント発行
        self.ifi.NotifyEvent(self, args[0], mat)
        # タイトルとラベル設定イベント発行
        self.SetHeaderAndLabels(mat)
        """
        ##<--[inamura 170126]
    ##[inamura 160603-2]-->
    ###################################################    
    def UpdateData(self, args):
        """
        データ変更イベント発行
        @param  args コマンドと引数のタプル
        @retval 無し
        """
        # デシリアライズ
        crr = mm.ReadSerializationFileBinary(args[1])
        # 元データがArrayであれば
        if int(args[2]) == 1:
            mat = mm.ElementContainerArray()
            crr.Load(mat)
            del crr
        else:
            mat = ElementContainerMatrix()
            crr.Load(mat)
            del crr
        
        # デシリアライズ失敗?
        if mat == None:
            # 否定応答を返信
            return "NACK\n"
        # データ変更イベント発行
        self.ifi.NotifyEvent(self, args[0], mat)
        #self.ifi.NotifyEvent(self, "changedata", mat)
        
    ##<--[inamura 160603-2]

    ###################################################    
    def SetHeaderAndLabels(self, data):
        """
        引数が整数1個のコマンドイベント発行
        @param  data ElementContainerArray or ElementContainerMatrix
        @retval 無し
        """
        # マトリックスのヘッダーを取得
        mh = data.PutHeader()
        
        # ラン番号よりメインタイトル作成
        if mh.CheckKey("RUNNUMBER"):
            main = "Run no.: " + mh.PutString("RUNNUMBER")
        else:
            main = "Run no.: Unknown"
            
        sub = ""
        if mh.CheckKey("Ei"):
            sub = "Ei (meV): %.2f" % mh.PutDouble("Ei")
        if mh.CheckKey("COMMENTS"):
            sub += mh.PutString("COMMENTS")
        
        if type(data)==type(mm.ElementContainerMatrix()):
            ec = data(0,0)
        else:
            ec = data(0)
        # ElementContainerのヘッダーを取得
        
        if ec.PutXKey() == "Energy":
            xlabel = "Q (1/Angstrom)"
            ylabel = "Energy (meV)"
        else:
            xlabel = "Index"
            ylabel = "TOF (us)"
        zlabel = "Neutrons"
        
        if mh.CheckKey("XLABEL"):
            xlabel = mh.PutString("XLABEL")
        if mh.CheckKey("YLABEL"):
            ylabel = mh.PutString("YLABEL")
        if mh.CheckKey("ZLABEL"):
            zlabel = mh.PutString("ZLABEL")
        
        # タイトル設定イベント発行
        self.ifi.NotifyEvent(self, "title", (main, sub))
        # ラベル設定イベント発行
        self.ifi.NotifyEvent(self, "scalelabel", (xlabel, ylabel,zlabel))
                
    ##<-- [KCS 130330]
                
    ###################################################    
    def ExecInt(self, args):
        """
        引数が整数1個のコマンドイベント発行
        @param  args コマンドと引数のタプル
        @retval 無し
        """
        # プロッタ追加またはプロッタクリアイベント発行
        self.ifi.NotifyEvent(self, args[0], int(args[1]))
        
                
    ###################################################    
    def SetScale(self, args):
        """
        モード変更イベント発行
        @param  args コマンドと引数のタプル
        @retval 無し
        """          
        # 引数無しであれば自動
        if len(args) == 1:
            # スケール変更(自動)イベント発行
            self.ifi.NotifyEvent(self, args[0], (True,))
        else:
            # マニュアルスケール Z軸範囲指定
            self.ifi.NotifyEvent(self, args[0], (False, float(args[1]), float(args[2])))         

    #########################################         
    def SetWithPlot(self, args):
        """
        プロッタ送信モード設定
        @param  args コマンドと引数のタプル
        @retval 無し
        """ 
        # 変更フラグはFalse か    
        if args[1]== "0":
            # モードイベント発行
            self.ifi.NotifyEvent(self, args[0], (False, int(args[2])))
        else:
            self.ifi.NotifyEvent(self, args[0], (True, int(args[2])))
 
    ###################################################    
    def ChangeMode(self, args):
        """
        モード変更イベント発行(Boolean 型引数)
        ログモード変更、オーバレイモード変更、アイコン化
        @param  args コマンドと引数のタプル
        @retval 無し
        """ 
        # 変更フラグはFalse か    
        if args[1]== "0":
            # モードイベント発行
            self.ifi.NotifyEvent(self, args[0], False)
        else:
            self.ifi.NotifyEvent(self, args[0], True)

    ###################################################    
    def Slice(self, args):
        """
        スライス条件指定イベント発行
        @param  args コマンドと引数のタプル
        @retval 無し
        """ 
        # スライス条件指定イベント発行(パネルの書き換え)
        self.ifi.NotifyEvent(self, args[0], (float(args[1]), float(args[2]), float(args[3]))) 
        # グラフ描画要求
        if args[0] == "slicex":
            self.ifi.NotifyEvent(self, "show", 1)
        else:
            self.ifi.NotifyEvent(self, "show", 2)
            
    ###################################################    
    def SliceRange(self, args):
        """
        スライス範囲条件指定イベント発行
        @param  args コマンドと引数のタプル
        @retval 無し
        """ 
        # スライス条件指定イベント発行(パネルの書き換え)
        self.ifi.NotifyEvent(self, args[0], (float(args[1]), float(args[2]),int(args[3]), float(args[4])))
        # グラフ描画要求
        if args[0] == "slicexrange":
            self.ifi.NotifyEvent(self, "show", 1)
        else:
            self.ifi.NotifyEvent(self, "show", 2)
                
    ###################################################    
    def SaveFile(self, args):
        """
        画像保存コマンドを送信
        @param  args コマンドと引数のタプル
        @retval 無し
        """ 
        strArg = self._Rebuild(args)         
        # 画像保存イベント発行
        self.ifi.NotifyEvent(self, args[0], strArg) 
        
    ###################################################    
    def _Rebuild(self, args):
        """
        文字列引数を復元(文字列に空白が含まれている場合)
        @param  args コマンドと引数のタプル
        @retval 復元後の文字列
        """ 
        strArg = ""
        # 引数文字列を連結
        for i in range(len(args)-1):
            strArg = strArg + " " + args[i+1]
        # 頭の余分な空白を消す    
        ret = strArg[1:]      
        # 復元後の文字列を返す
        return ret     
        
    ###################################################    
    def SetXLabel(self, args):
        """
        X軸ラベルコマンドを送信
        @param  args コマンドと引数のタプル
        @retval 無し
        """  
        strArg = self._Rebuild(args) 
        # スケールラベル設定コマンド送信
        self.ifi.NotifyEvent(self, "scalelabel", (strArg, "*", "*"))   
        
    ###################################################    
    def SetYLabel(self, args):
        """
        Y軸ラベルコマンドを送信
        @param  args コマンドと引数のタプル
        @retval 無し
        """  
        strArg = self._Rebuild(args) 
        # スケールラベル設定コマンド送信
        self.ifi.NotifyEvent(self, "scalelabel", ("*", strArg,"*"))    
        
    ###################################################    
    def SetZLabel(self, args):
        """
        Z軸ラベルコマンドを送信
        @param  args コマンドと引数のタプル
        @retval 無し
        """  
        strArg = self._Rebuild(args) 
        # スケールラベル設定コマンド送信
        self.ifi.NotifyEvent(self, "scalelabel", ("*", "*", strArg))             
        
    ###################################################    
    def SetMain(self, args):
        """
        メインタイトルを送信
        @param  args コマンドと引数のタプル
        @retval 無し
        """  
        strArg = self._Rebuild(args) 
                
        # タイトル設定コマンド送信
        self.ifi.NotifyEvent(self, "title", (strArg, "*"))   
        
    ###################################################    
    def SetSub(self, args):
        """
        サブタイトルを送信
        @param  args コマンドと引数のタプル
        @retval 無し
        """  
        strArg = self._Rebuild(args) 
                
        # タイトル設定コマンド送信
        self.ifi.NotifyEvent(self, "title", ("*", strArg))              
          
    ###################################################    
    def Exec(self, args):
        """
        コマンド実行イベント発行(引数無)
        Close 
        @param  args コマンドと引数のタプル
        @retval 無し
        """          
        # コマンド実行要求イベント発行
        self.ifi.NotifyEvent(self, args[0])   
       
    ###################################################    
    def GetAttr(self, args):
        """
        属性の取得
        @param  args コマンドと引数のタプル
        @retval 無し
        """          
        # 属性取得
        attr = self.ifi.GetProperty(args[1])
     
        # 属性が文字列か
        if args[2]=="0":
            return attr+'\n' 
        # 整数か
        elif args[2]=="1":
            return "%d\n" % attr  
        # 実数か
        elif args[2]=="2":
            return "%.5f\n" % attr
        # ブーリアンか
        elif args[2]=="3":
            if attr== True:
                return "True\n"
            else:
                return "False\n"
        # オブジェクトか
        elif args[2]=="4":
            # 現在の絶対時間(0.01秒単位)と、プロッタ番号よりテンポラリファイル名を作成
            tsec = int(time.time()*100.0)
            tmpf = "attrs%d" % tsec
            # テンポラリファイルの絶対パスを作成(指定されたテンポラリディレクトリの下)
            tmppath = os.path.join(tempfile.gettempdir(), tmpf)
            try:
                # テンポラリファイルを開く
                fw = file(tmppath, "wb")
                # オブジェクトをバイナリモードでシリアライズ
                pickle.dump(attr, fw, True)
            except:
                print "\nError!! Cant create a temp file."
            else:
                # テンポラリファイルをクローズ
                fw.close()
                # テンポラリファイル名を返信
                return tmppath + '\n'  

    ##[inamura 120417]-->
    ###################################################
    def ShowOnly2d(self,args):
        """
        """
        if args[1]=="True":
            isOnly=True
        else:
            isOnly=False
        print "ShowOnly2d=",isOnly
        self.ifi.NotifyEvent(self,'showonly2d', isOnly)
        
    ##<--[inamura 120417]

    
if __name__ == '__main__':
    """
    CUI-GUI コミュニケータから、プロセスとして起動されるときに
    実行する処理
    """
        # socket 経由で他のプロセスから起動
    if len(sys.argv) > 1:
        import vis.WxCom as WxCom
        # CUI-GUI コミュニケータのサーバアプリ(wxPython) 起動
        app = WxCom.WxApp() 
        # 2次元プロッタ(D2Plot)の CUI IF のインスタンス取得 
        cuif = D2CuiIF()
        # 起動時引数より、通信ポート番号を取得
        portno = int(sys.argv[1])
        # 起動時引数より、プロッタ番号を取得
        pno = int(sys.argv[3])
        # プロッタ終了フラグが指定されているか
        if len(sys.argv) >= 5: 
            if sys.argv[4] == "True":
                closeFlag = True
            else:
                closeFlag = False
        else:
            # 指定無しの場合は、True とする。
            closeFlag = True
        
        ##[inamrua 120417]-->
        # If Quiet Flag is set.
        isQuiet=False
        if len(sys.argv) >=6:
            if sys.argv[5]=="True":
                isQuiet=True
        # プロッタを起動
        cuif.StartPlot(pno, app.OnGUIClose,isQuiet) 
        ##<--[inamura 120417]
        # CUI との通信スタート(ポート番号と、コマンド処理関数を引数として渡す)
        app.OnStart(portno, closeFlag, cuif.TakeCommand)
        # wxPython のメインループ開始
        app.MainLoop()
    # 以下はデバッグ用スクリプト
    else:
        # 以下は、デバッグ用スクリプト
        app = wx.App()
        import ECMSerialize as ECM
        ecms = ECM.ECMSerialize()
        DAT = ecms.Decode("/home/mlfdev/PowderData120207.dmp")
        MapD2Frame(None, DAT)
        
        app.MainLoop()
        
            
        
        h = arange(1.0,10.0 , 1.0)
        v = arange(-1.0,0.1 , 0.1)
        
        numh = len(h)-1
        numv = len(v)-1
        # 斜方グリッド作成
        H, V = meshgrid(h, v)

        aa = 1.0
        for i in range(11):
            for j in range(9):
                H[i,j]= H[i,j]*aa
            aa = aa + 0.1
#            aa = aa - 0.1
        data =ones((numv,numh), float64)

        data[0,3] = 2.0
        data[0,4] = 5.0
        data[0,5] = 3.0
        data[1,1] = 8.0
        data[1,3] = 4.0
        data[1,4] = 10.0
        data[1,5] = 6.0
        data[1,7] = 7.0
        data[2,4] = 1.5
        data[3,3] = 4.0
        data[3,4] = 2.5
        data[3,5] = 3.5
        data[4,5] = 0.0
        data[6,0] = 0.5
        data[7,6] = 9.0
        data[0,2] = MASKVALUE
        data[1,2] = MASKVALUE
        data[2,2] = MASKVALUE
        data[3,2] = MASKVALUE
        data[4,2] = MASKVALUE
        data[5,2] = MASKVALUE
        data[6,2] = MASKVALUE
        data[7,2] = MASKVALUE
        data[8,3] = MASKVALUE
        data[9,4] = MASKVALUE
        """
        h = arange(5.69,5.85 , 0.04)
        v = arange(-10.0,-9.0 , 0.2)
        
        numh = len(h)-1
        numv = len(v)-1
        # 斜方グリッド作成
        H, V = meshgrid(h, v)
        data =zeros((numv,numh), float64)
        
        data[0,0]=0.761
        data[0,1]=0.897
        data[1,0]=1.136
        data[1,1]=1.121
        data[2,0]=0.938
        data[2,1]=1.129
        
        aa = 0.0
        for i in range(5):
            for j in range(4):
                H[i,j]= H[i,j]-aa
                
            aa += 0.005
        """
        #err = sqrt(data)
        #mapXY = (data, err, H,V, 1)
        #MapD2Frame(None, mapXY,1)

        #IFEvtProp(1).NotifyEvent(None, "title", ("Test patern", "Ei(meV)=20"))
        # スケールラベル設定コマンド送信
        #IFEvtProp(1).NotifyEvent(None, "scalelabel", ("Q(1/Angstrom)", "Energy(meV)","Neutrons"))  
        #app.MainLoop()
