#!/usr/bin/python
# -*- coding: utf-8 -*-
"""
2次元プロッタの CUI ファサードクラス
"""
import os
import sys
import thread
from math import pi, sqrt, cos
from numpy import array, arange,meshgrid, zeros, float64
from time import sleep
from vis.WxCom import *
from vis.UtilPlot import *
try:
    import Manyo as mm
    import Manyo.Utsusemi as mu
except:
    pass

"""
brief update history
[inamura 170126] changed to send "map-format" data to M2Plot (for VisualContQ)
[inamura 160627]  added setxlog and setylog
[inamura 160603-2] added to notify "updatedata".
"""

#######################################
#  D2EMatrix
####################################### 
class D2Matrix(object):
    """
    2次元データ用Matrix(粉末タイプ)読み込み
    """
    #########################################
    def ReadMatrix(self, matrix):
        """
        エレメントコンテナマトリックスの読み込み
        @param  matrix  エレメントコンテナマトリックス
        @retval 2次元プロッタの表示データ
        　　　　(datArray,  erArray, X, Y , 1: 斜交データ)
        """
        self.ei = 0.0
        self.runno = ""
        self.datArray = None
        self.erArray = None
        
        try:

            # マトリックスのヘッダーを取得
            mh = matrix.PutHeader()
            ## [inamura 100329]-->
            #self.ei = mh.PutDouble("Ei")
            #self.runno = mh.PutString("RUNNUMBER")
            #type = mh.PutString("SAMPLETYPE")
            ## <-- [inamura 100329]
        except:
            # ManyoLib データ読み出し時に例外発生(不当なデータ)
            raise PlotException('Common', 'C040', ())
            return
        ## [inamura 100329]-->
        # ヘッダーにパラメータがあれば取得
        ## [inamura 100708]-->
        #if (mh.CheckKey("Ei"))*(mh.CheckKey("RUNNUMBER"))*(mh.CheckKey("SAMPLETYPE"))==1:
        if mh.CheckKey("Ei"):
            self.ei = mh.PutDouble("Ei")
        else:
            self.ei = 0.0
        if mh.CheckKey("RUNNUMBER"):
            self.runno = mh.PutString("RUNNUMBER")
        else:
            self.runno = "Unknown"
        if mh.CheckKey("SAMPLETYPE"):
            type = mh.PutString("SAMPLETYPE")
        else:
            type = "Unknown"
        
        #else:
        #    raise PlotException('Common', 'C040', ())
        #    return
        ##<--[inamura 100708]
        ## <-- [inamura 100329]
        ## 試料タイプは粉末か
        #if type != "Powder":
        #    raise PlotException('Common', 'C041', ("Powder",))
        #    return
        try:
            # 2次元マップデータを作る
            ## [inamura 100708]-->
            if type == "Powder":
                X, Y = self._MakeMapData(matrix)
                i_type = 1 ##[inamura 130318]
            else:
                X, Y = self._MakeNormal2DMap(matrix)
                i_type = 0 ##[inamura 130318]
            ##<--[inamura 100708]
        except:
            raise
        else:
            # マップデータを返す
            #return (self.datArray, self.erArray, X, Y, 1) ##[inamura 130318]
            return (self.datArray, self.erArray, X, Y, i_type)

    #########################################
    def GetHeaderInfo(self):
        """
        エレメントコンテナマトリックスのヘッダー情報取得
        @param  無し
        @retval ラン番号と入射エネルギー
        """ 
        return self.runno, self.ei       

    #########################################
    def _MakeMapData(self, matrix):
        """
        エレメントコンテナマトリックスの読み込み
        @param  matrix  エレメントコンテナマトリックス
        @retval 2次元プロッタの表示データ
        　　　　(datArray,  erArray, X, Y , 1: 斜交データ)
        """
        ##[inamura 100708]-->
        #if type(matrix)==type(ElementContainerArray()):
        #if isinstance( matrix, mm.ElementContainerMatrix ): ##[inamura 130619]
        if isinstance( matrix, mm.ElementContainerArray ): ##[inamura 130619]
            eca = matrix
            matrix = mm.ElementContainerMatrix()
            matrix.Add(eca)
        ##<--[inamura 100708]
        # 全データ共通のはずなので、最初の1個から取得
        e0 = matrix(0,0)
        ebin = e0.PutXList()
            
        # アレイ の数を取得 (1?)
        numAr = matrix.PutSize()
        pols = []
        # アレイ 数だけ繰り返す
        for i in range(numAr):
            # マトリックスから 1アレイ分のデータ(エレメントアレイ)を読み出す
            ea = matrix.PutPointer(i)
            # エレメントコンテナ数を取り出す
            nEc = ea.PutSize()
            # エレメントアレイから、各 エレメントコンテナを取り出す
            for j in range(nEc):
                # エレメントコンテナのヘッダ取得
                ec = ea(j)
                ech = ec.PutHeader()
                ##[inamura 100122]->
                # MASKED=1かどうか
                if ((ech.CheckKey("MASKED")==1) and (ech.PutInt4("MASKED")==1)):
                    continue
                ##<-[inamura 100122]
                # 座標角(度)を取得
                pol = ech.PutDoubleVector("PixelPolarAngle")
                polr = pol[0]*pi/180.0

                # リストに追加
                pols.append(polr)

        if len(pols) < 2:
            raise PlotException('Common', 'C040', ())
            return
        
        pnum = len(pols)
        polr = pols[pnum-1]-pols[pnum-2]+pols[pnum-1]
        pols.append(polr)
        hfGap = (pols[1]-pols[0])/2.0
        # 最初のPSD
        theta = pols[0] - hfGap
        # 1本のPSD の角度より1.5倍以上あるとき、バンクギャップとみなす
        gapTh = hfGap*3.0
        
        thetas = [theta]
        gaps = []

        # PSD 両端部の散乱角を計算
        for i in range(pnum):
            # 確度の差分を求める
            gap = pols[i+1]-pols[i]
            # バンクギャップでなければ
            if gap < gapTh:
                hfGap = gap/2.0
                theta = pols[i] + hfGap
                thetas.append(theta)
                gaps.append(False)
            # バンクギャップ
            else:
                # 前の半値から
                theta = pols[i] + hfGap
                thetas.append(theta)
                gaps.append(False)
                theta = pols[i+1] - hfGap
                thetas.append(theta)
                gaps.append(True)
            ##[inamura 091219]->
            #角度差は常に一定ではないのでその都度ギャップ用閾値を作成する
            gapTh = hfGap*3.0
            ##<-[inamura 091219]
                
        enL = []
        datL = []
        erL = []
        # バンクギャップ用のマスク値作成
        mskYY = []
        mskEr = []
        for i in range(len(ebin)-1):
            mskYY.append(MASKVALUE)
            mskEr.append(0.0)
        
        k = 0
        # アレイ 数だけ繰り返す
        for i in range(numAr):
            # マトリックスから 1アレイ分のデータ(エレメントアレイ)を読み出す
            ea = matrix.PutPointer(i)
            ##[inamura 091219]->
            #ギャップの数に応じてデータを作成する
            for j in range(len(gaps)):
                #バンクギャップか
                if gaps[j]:
                    datL.append(mskYY)
                    erL.append(mskEr)
                else:
                    ec = ea.PutPointer(k)
                    yy = ec.PutYList()
                    er = ec.PutEList()

                    datL.append(yy)
                    erL.append(er)
                    k +=1
            """
            # エレメントコンテナ数を取り出す
            nEc = ea.PutSize()
            # エレメントアレイから、各 エレメントコンテナを取り出す
            for j in range(nEc):
                # バンクギャップか
                if gaps[k]:
                    # マスク値を入れる
                    datL.append(mskYY)
                    erL.append(mskEr)
                    k += 1
                
                # エレメントコンテナ読み出し
                ##[inamura 091210]-->
                #ec = ea.PutPointer(j)
                ec = HistogramBinToPoint(ea.PutPointer(j))
                ##<--[inamura 091210]
                yy = ec.PutYList()
                er = ec.PutEList()
                
                # リストに追加
                datL.append(yy)
                erL.append(er)
                k += 1
            """
            ##<-[inamura 091219]
        # 全点 0 のアレイを作成
        self.datArray =zeros((len(mskYY),len(datL)), float64)
        self.erArray =zeros((len(mskYY),len(datL)), float64)

        # 縦横を逆にして取り込む
        for i in range(len(mskYY)):
            for j in range(len(datL)):
                self.datArray[i][j] = datL[j][i]
                self.erArray[i][j] = erL[j][i]
                if erL[j][i]<0.0:                  #[inamura 170131]
                    self.datArray[i][j]=MASKVALUE

        # マップデータ用の X Y グリッドを作る
        return self._MakeXYGrid(ebin, thetas)

    #########################################    
    def _MakeXYGrid(self, ebin, thetas):
        """
        XグリッドとYグリッドを計算
        @param  ebin　エネルギーbin
        @param thetas 散乱角
        @retval XグリッドとYグリッド
        """ 

        x = arange(0.0,len(thetas) , 1.0)
        y = array(ebin)
        
        X,Y = meshgrid(x, y)

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

        for i in range(len(ebin)):

            hw = ebin[i]
            j = 0
            for theta in thetas:
                # 角度とエネルギーから散乱後の波数ベクトル計算
                kf = sqrt((self.ei-hw)/2.072)
                # Q を計算
                q =sqrt( ki2 + kf*kf - 2.0*ki*kf*cos(theta))
                X[i][j]= q
                j += 1
            
        return (X,Y)    

##[inamura 100708]-->
    #########################################
    def _MakeNormal2DMap(self,eca_in):
        """
        指定されたPSD のデータを返す
        @param  psd  psd No.
        @retval PSD のデータ
        """
        #if type(eca)!=type(ElementContainerArray()):
        ##[inamura 130619]-->
        #if not isinstance( eca, mm.ElementContainerArray ):
        #    raise
        if isinstance( eca_in, mm.ElementContainerArray ):
            eca = eca_in
        elif isinstance( eca_in, mm.ElementContainerMatrix ):
            eca = eca_in(0)
        else:
            msg = "M2Plot::_MakeNormal2DMap > argument is not ECA nor ECM"
            print( msg )
            raise UserWarning,msg
        ##<--[inamura 130619]
        numPixel = eca.PutTableSize()
        # 中心のエレメントコンテナのTOFを取得
        ec0 = eca(0) 
        tof = ec0.PutX()
        # リビニング後のY データの個数
        znum = len(tof)-1
       
        # リビニング後のカウント数アレイ用に全点 0 のアレイを作成
        self.datArray = zeros((znum, numPixel), float64)
        self.erArray  = zeros((znum, numPixel), float64)
        
        ## [inamura 150330]-->
        #hh_p = eca_in.PutHeaderPointer()
        #isHist = True
        #if (hh_p.CheckKey("isHistogram")==1) and (hh_p.PutInt4("isHistogram")==0): # isHistogram is existed and is 0 
        #    isHist = False
        #if (isHist):
        #    pass
        #else:
        #    hh_p = eca.PutHeaderPointer()
        #    if (hh_p.CheckKey("isHistogram")==1) and (hh_p.PutInt4("isHistogram")==1): # isHistogram is existed and is 1 
        #        isHist = True
        ## <--[inamura 150330]
        
        # 1検出器分の強度データを取り出す
        ## [inamura 100712]-->
        x_list = []
        for i in range(numPixel):
            # エレメントコンテナ取得
            ec = eca(i)
            hh = ec.PutHeader()
            if hh.CheckKey("XRANGE"):
                x_list.append( hh.PutDoubleVector("XRANGE")[0] )
            else:
                x_list.append(i)
            ##[inamura 150330]-->
            #if (isHist) or ( (hh.CheckKey("isHistogram")==1) and (hh.PutInt4("isHistgram")==1) ):
            #    print "@@@@ isHist is True" #[inamura 150515]
            #    ec = mu.HistogramBinToPoint( ec )
                
            yy = ec.PutYList()   
            ee = ec.PutEList()
            
            ##<--[inamura 150330]    
            # カウント数アレイとエラー値アレイへ格納 
            for j in range(len(yy)):
                self.datArray[j,i]=yy[j]
                self.erArray[j,i]=ee[j]
                if ee[j]<0.0:                  #[inamura 170131]
                    self.datArray[j,i]=MASKVALUE

        if hh.CheckKey("XRANGE"):
            x_list.append( hh.PutDoubleVector("XRANGE")[1] )
        else:
            x_list.append( numPixel )

        x = array( x_list )
        #x = arange(0, numPixel+1,1)
        ##<--[inamura 100712]
        return meshgrid(x, tof)
    
##<--[inamura 100708]

    
#######################################
#  M2Plot
####################################### 
class M2Plot(object) :
    """
    2次元プロッタのファサードクラス
    Python インタープリタ からプロッタを起動し
    制御するためのユーザインターフェイスを提供
    """
    # 2Dプロッタ通信クラスのインスタンスリスト
    plotList = []
    # plotList のロック用
    lck = thread.allocate_lock()
  
    #########################################
    def __init__(self, matrix=None, closeFlag = True):
        """
        コンストラクタ
        @param  matrix  2Dプロッタに表示するデータ、省略可
        　　　　　　　(エレメントコンテナマトリックス)
        @closeFlag   親プロセス終了時に、プロッタをクローズするか
        　　　　　　 否かのフラグ
        @retval 無し
        """
        self.plot = None
        # 入力チェッククラスのインスタンスを取得、メッセージ出力先は標準出力を指定
        self.val = Validator(None)
        # テンポラリファイルクラスのインスタンス取得
        self.tp = TempFile()
        # プロッタの作成
        self.NewPlot(matrix, closeFlag)
        
    ######################################### 
    def NewPlot(self, matrix, closeFlag = True): 
        """
        プロッタを追加し、カレントプロッタとする
        @param  data  プロッタに表示するデータ、省略可
        　　　　       ???
        @param closeFlag  親プロセス終了時に、子プロセスを終了させるかどうかのフラグ
        @retval 無し
        """    
        # プロッタNo.を取得
        pno = len(self.plotList) +1
        strPno = "%d" % pno
        self.pno = pno #[inamura 170126]
        
        if closeFlag == True:
            cflag = "True"
        else:
            cflag = "False"
        
        arg = ["D2Vis.py",strPno, cflag]

        # プロセスID とプロッタ番号からポート番号を生成
        pxx = (os.getpid() % 500)*20
        portno = 20000+ pxx + pno

        # GUI通信クラスのインスタンス取得
        p = CommWx()
        
        # プロセス生成と通信接続に成功したなら
        if p.NewComm(portno, arg):
            # 旧カレントプロッタのアイコン化要求
            self._IconizeCurrent()
            
            self.lck.acquire()
            # 追加したプロッタをリストへ追加
            self.plotList.append(p)
            # ロックの解放
            self.lck.release()
                
            # 追加したプロッタをカレントプロッタとする。   
            self.plot = p
            # データを設定       
            self.ChangeMap(matrix, True)
                
        else:
            print "\nError!!  Cannot create a new plotter!!."
    
    ######################################### 
    def ChangePlot(self, plot=None): 
        """
        カレントプロッタを変更する
        @param  plot  カレントにするプロッタ番号
        @retval 無し
        """
        # 引数が指定されていない場合
        if not self.val.ValidateObject(plot, "ChangePlot"):
            # エラー終了
            return   
        # 引数チェック
        if self.val.ValidateInteger(plot, "Argument", 1, len(self.plotList)):
            # 指定されたプロッタが閉じられていなければ
            if self.plotList[plot-1].IsAliveComm():
                # 旧カレントプロッタのアイコン化要求    
                self._IconizeCurrent()
                # カレントプロッタを変更
                self.plot = self.plotList[plot-1]
                # 新カレントプロッタの復元要求    
                self.plot.PutCommand("doiconize 0\n")
            # 既に閉じている場合は
            else:
                # エラーメッセージを表示
                print "\nThe 2D plotter(%d) has been already closed." % plot
     
    ######################################### 
    def _IconizeCurrent(self): 
        """
        カレントプロッタをアイコン化する
        @param  無し
        @retval 無し
        """             
        # 先にカレントプロッタがあれば
        if self.plot != None:
            # カレントプロッタが閉じられていなければ
            if self.plot.IsAliveComm():
                # 旧カレントプロッタのアイコン化要求
                self.plot.PutCommand("doiconize 1\n")

    #########################################         
    def ChangeMap(self, data=None, new = False):
        """
        プロッタのデータを変更
        @param  data  変更するデータ
        　　　　エレメントコンテナマトリックス
        @param  new  新規プロッタ
        @retval 無し
        """ 
        # 引数が指定されていない場合
        #if not self.val.ValidateObject(matrix, "ChangeData"):
            # エラー終了
        #    return   

        ##[inamrua 170126]-->
        isContainer = True
        if data==None:
            head = mm.HeaderBase()
            head.Add("RUNNUMBER","Dummy data")
            data = mm.ElementContainerMatrix(head)
            eca = mm.ElementContainerArray(head)
            a_ec = mm.ElementContainer()
            #a_ec.Add( "X", range(21) )
            a_ec.Add( "X", range(1,21) )
            a_ec.Add( "Y", range(20) )
            a_ec.Add( "E", range(20) )
            a_ec.SetKeys("X","Y","E")
            for i in range(10):
                rng = mm.MakeDoubleVector(2)
                rng[0] = 0.5 + float(i)*1.0
                rng[1] = 0.5 + float(i+1)*1.0
                hh = a_ec.PutHeaderPointer()
                if hh.CheckKey("XRANGE")==1:
                    hh.OverWrite("XRANGE",rng)
                else:
                    a_ec.AddToHeader("XRANGE",rng)
                eca.Add( mm.ElementContainer( a_ec ) )
            data.Add( eca )
            ecType = 0
        elif isinstance( data, mm.ElementContainerArray ):
            #print "Change Map: ElementContainerArray"
            # Matrix に変更
            ecType = 1
            # ヘッダーがあるか
            try:
                data.PutHeader()
            except:
                # ヘッダーを追加
                head=mm.HeaderBase()
                head.Add("RUNNUMBER","Unknown")
                data.SetHeader(head)

        elif isinstance(data,mm.ElementContainerMatrix):
            #print "Change Map: ElementContainerMatrix"
            ecType = 0
        elif type(data)==tuple:
            isContainer = False

        else:
            return
        
        if (isContainer):
            temppath = self.tp.GetTempName(".srlz")
            if temppath == None:
                # 異常終了
                print "\nError!! Cannot make a temporary file."   
                return
            # シリアライズ
            crw = mm.WriteSerializationFileBinary(temppath)
            crw.Save(data)
            del crw
            # コマンド作成(改行コード付)
            strCmd = "changedata %s %d\n" % (temppath, ecType)
            # コマンドの送信要求をカレントプロッタへ送る
            self.plot.PutCommand(strCmd)
            
        else:
            temppath = self.tp.GetTempName(".map")
            if temppath == None:
                # 異常終了
                print "\nError!! Cannot make a temporary file."   
                return
            
            ret = self.tp.MakeTempFile(data, temppath)
            # 正常終了か
            if ret == 0:
                # コマンド作成(改行コード付)
                strCmd = "changedata %s\n" % temppath
                # コマンドの送信要求をカレントプロッタへ送る
                self.plot.PutCommand(strCmd)
            else:
                # 異常終了
                print "\nError!! Cannot make a temporary file."
        """
        # テンポラリファイル名称を取得
        temppath = self.tp.GetTempName()
       
        if temppath == None:
            # 異常終了
            print "\nError!! Cannot make a temporary file."   
            return

        crw = mm.WriteSerializationFileBinary(temppath)
        
        ##[inamura 140821]-->
        if data==None:
            head = mm.HeaderBase()
            head.Add("RUNNUMBER","Dummy data")
            data = mm.ElementContainerMatrix(head)
            eca = mm.ElementContainerArray(head)
            a_ec = mm.ElementContainer()
            #a_ec.Add( "X", range(21) )
            a_ec.Add( "X", range(1,21) )
            a_ec.Add( "Y", range(20) )
            a_ec.Add( "E", range(20) )
            a_ec.SetKeys("X","Y","E")
            for i in range(10):
                rng = mm.MakeDoubleVector(2)
                rng[0] = 0.5 + float(i)*1.0
                rng[1] = 0.5 + float(i+1)*1.0
                hh = a_ec.PutHeaderPointer()
                if hh.CheckKey("XRANGE")==1:
                    hh.OverWrite("XRANGE",rng)
                else:
                    a_ec.AddToHeader("XRANGE",rng)
                eca.Add( mm.ElementContainer( a_ec ) )
            data.Add( eca )
        ##<--[inamura 140821]
        
        # Array データであれば
        if type(data)==type(mm.ElementContainerArray()):
            print "Change Map: ElementContainerArray"
            # Matrix に変更
            ecType = 1
            # ヘッダーがあるか
            try:
                data.PutHeader()
            except:
                # ヘッダーを追加
                head=mm.HeaderBase()
                head.Add("RUNNUMBER","Unknown")
                data.SetHeader(head)

        elif type(data)==type(mm.ElementContainerMatrix()):
            print "Change Map: ElementContainerMatrix"
            ecType = 0
            
        else:
            print "Error data!!"
            print "Accept only ElementContainerMatrix or ElementContainerArray only."
            return  
            
        # シリアライズ
        crw.Save(data)
        del crw    #[inamura 130617]
        # コマンド作成(改行コード付)
        strCmd = "changedata %s %d\n" % (temppath, ecType)
        # コマンドの送信要求をカレントプロッタへ送る
        self.plot.PutCommand(strCmd)
        
        # Manyo データからPython データタイプへ変換
        #d2 = D2Matrix()
        #try:
        #    mapXY = d2.ReadMatrix(matrix)
        #except PlotException, ex:
        #    PlotMessage(None, ex)
        #    return
        ## メインタイトルとサブタイトルを作る
        #
        #runno, ei = d2.GetHeaderInfo()
        #main = "Run no.: %s" % runno
        ###[inamura 100708]-->
        ##sub = "Ei (meV): %.2f" % ei
        #if ei != 0.0:
        #    sub = "Ei (meV): %.2f" % ei
        #else:
        #    if matrix.PutHeader().CheckKey("COMMENTS"):
        #        sub = matrix.PutHeader().PutString("COMMENTS")
        #    else:
        #        sub = ""
        #
        #if new:
        #    hh = matrix.PutHeader()
        #    xlabel = "Q(1/Angstrom)"
        #    ylabel = "Energy(meV)"
        #    zlabel = "Neutrons"
        #    if hh.CheckKey("XLABEL"):
        #        xlabel = hh.PutString("XLABEL")
        #    if hh.CheckKey("YLABEL"):
        #        ylabel = hh.PutString("YLABEL")
        #    if hh.CheckKey("ZLABEL"):
        #        zlabel = hh.PutString("ZLABEL")
        #    
        #    #object = [mapXY, main, sub, "Q(1/Angstrom)", "Energy(meV)","Neutrons"]
        #    object = [mapXY, main, sub, xlabel, ylabel, zlabel]
        ###<--[inamura 100708]
        #else:
        #    object = [mapXY, main, sub]
        #
        ## オブジェクトをシリアライズしてテンポラリファイルへ書き込む
        #ret = self.tp.MakeTempFile(object, temppath)
        ## 正常終了か
        #if ret == 0:
        #    # コマンド作成(改行コード付)
        #    strCmd = "changedata %s\n" % temppath
        #    # コマンドの送信要求をカレントプロッタへ送る
        #    self.plot.PutCommand(strCmd)
        #else:
        #    # 異常終了
        #    print "\nError!! Cannot make a temporary file." 
        """
        ##<--[inamrua 170126]

    #[inamrua 160603-2]-->
    #########################################         
    def UpdateMap(self, data=None, new = False):
        """
        プロッタのデータを変更
        @param  data  変更するデータ
        　　　　エレメントコンテナマトリックス
        @param  new  新規プロッタ
        @retval 無し
        """ 
        # テンポラリファイル名称を取得
        temppath = self.tp.GetTempName()
       
        if temppath == None:
            # 異常終了
            print "\nError!! Cannot make a temporary file."   
            return

        crw = mm.WriteSerializationFileBinary(temppath)
        
        ##[inamura 140821]-->
        if data==None:
            head = mm.HeaderBase()
            head.Add("RUNNUMBER","Dummy data")
            data = mm.ElementContainerMatrix(head)
            eca = mm.ElementContainerArray(head)
            a_ec = mm.ElementContainer()
            a_ec.Add( "X", range(21) )
            a_ec.Add( "Y", range(20) )
            a_ec.Add( "E", range(20) )
            a_ec.SetKeys("X","Y","E")
            for i in range(10):
                eca.Add( mm.ElementContainer( a_ec ) )
            data.Add( eca )
        ##<--[inamura 140821]
        
        # Array データであれば
        if type(data)==type(mm.ElementContainerArray()):
            print "Update Map: ElementContainerArray"
            # Matrix に変更
            ecType = 1
            # ヘッダーがあるか
            try:
                data.PutHeader()
            except:
                # ヘッダーを追加
                head=mm.HeaderBase()
                head.Add("RUNNUMBER","Unknown")
                data.SetHeader(head)

        elif type(data)==type(mm.ElementContainerMatrix()):
            print "Update Map: ElementContainerMatrix"
            ecType = 0
            
        else:
            print "Error data!!"
            print "Accept only ElementContainerMatrix or ElementContainerArray only."
            return  
            
        # シリアライズ
        crw.Save(data)
        del crw    #[inamura 130617]
        # コマンド作成(改行コード付)
        strCmd = "updatedata %s %d\n" % (temppath, ecType)
        # コマンドの送信要求をカレントプロッタへ送る
        self.plot.PutCommand(strCmd)
        
    #<--[inamrua 160603-2]

 
        
    #########################################         
    def SetLog(self, flag=True):
        """
        ログモード設定
        @param  flag  ログモード True or False
        @retval 無し
        """ 
        # 引数チェック
        if self.val.ValidateBoolean(flag, "Argument"):
            # コマンド作成
            strCmd = "setlog %d\n" % flag
            # コマンドの送信要求をカレントプロッタへ送る
            self.plot.PutCommand(strCmd)

    #[inamura 160627]-->
    #########################################         
    def SetXLog(self, flag=True):
        """
        ログモード設定
        @param  flag  ログモード True or False
        @retval 無し
        """ 
        # 引数チェック
        if self.val.ValidateBoolean(flag, "Argument"):
            # コマンド作成
            strCmd = "setxlog %d\n" % flag
            # コマンドの送信要求をカレントプロッタへ送る
            self.plot.PutCommand(strCmd)

    #########################################         
    def SetYLog(self, flag=True):
        """
        ログモード設定
        @param  flag  ログモード True or False
        @retval 無し
        """ 
        # 引数チェック
        if self.val.ValidateBoolean(flag, "Argument"):
            # コマンド作成
            strCmd = "setylog %d\n" % flag
            # コマンドの送信要求をカレントプロッタへ送る
            self.plot.PutCommand(strCmd)

    #<--[inamura 16027]
    #########################################         
    def SetWithPlot(self, flag=None, n=3):
        """
        プロッタ送信モード設定
        @param  flag  送信モード True or False
        @param   n  1: Xのみ  2: Yのみ 3: 両方
        @retval 無し
        """ 
        # 引数1チェック
        if not self.val.ValidateBoolean(flag, "Argument1"):
            return
        # 引数2 チェック
        if self.val.ValidateInteger(n, "Argument2", 1,3):
            # コマンド作成
            strCmd = "setwith %d %d\n" % (flag,n)
            # コマンドの送信要求をカレントプロッタへ送る
            self.plot.PutCommand(strCmd)
        
    #########################################         
    def SetZScale(self, z0=None, z1=None ):
        """
        自動スケールモード設定
        @param  z0 X軸始値
        @param  z1 X軸終値
        @retval 無し
        """ 
        # 引数無しか
        if z0==None and z1==None:
            # 自動モード(引数無し)コマンドの送信要求
            self.plot.PutCommand("setzscale\n")
            return
        
        if z1 == None:
            print "\nSetZScale takes none or 2 arguments." 
            return
        
        # 引数1チェック
        if not self.val.ValidateNumeric(z0, "Argument1",0.0):
            # エラー終了
            return 
        # 引数2チェック
        if not self.val.ValidateNumeric(z1, "Argument2" ,0.0):
            # エラー終了
            return 
        # 範囲チェック
        if z1 > z0:   
            # コマンド文字列作成
            strCmd = "setzscale %.3f %.3f\n" % (z0, z1)
            # コマンドの送信要求をカレントプロッタへ送る
            self.plot.PutCommand(strCmd)
        else:
            print "\nThe argument2 must be larger then the argument1."
                                        
    #########################################         
    def Close(self, plot=None):
        """
        プロッタ画面を閉じる
        @param  pno  プロッタ番号
        @retval 無し
        """ 
        # カレントプロッタのクローズ要求か
        if plot == None:
            self.plot.PutCommand("close\n" )
            
        # 入力チェックがOKか
        if self.val.ValidateInteger (plot, "Argument(Plotter Number)", 0, len(self.plotList)):
            # 全画面クローズ要求か
            if plot == 0:
                # 全プロッタに対し
                for pl in self.plotList:
                    # 生存していれば
                    if pl.IsAliveComm():
                        # クローズ要求を送信
                        pl.PutCommand("close\n" )
            else:
                pnum=int(plot)
                # 指定プロッタのインスタンス取得
                pl = self.plotList[pnum-1]
                # クローズ要求を送信
                pl.PutCommand("close\n" )


    #########################################         
    def SliceX(self, y=None, diff = 0.0, bin = 0.0):
        """
        Y値を指定してX方向にスライスする
        @param  y    Y値
        @param  diff 積算範囲　(Y±diff の範囲で積算)
        @param  bin  リビニング値　(0.0のときリビニングしない)
        @retval 無し
        """ 
        # 引数1チェック
        if y == None:
            print "\nSliceX needs at least one argument."
            return
        if not self.val.ValidateNumeric(y, "Argument1"):
            # エラー終了
            return 
        # 引数2チェック
        if not self.val.ValidateNumeric(diff, "Argument2" , 0.0):
            # エラー終了
            return 
        # 引数3チェック
        if self.val.ValidateNumeric(bin, "Argument3" , 0.0):
            strCmd = "slicex %.3f %.3f %.3f\n" % (y, diff, bin)
            ret = self.plot.PutCommand(strCmd)
    
    #########################################         
    def SliceY(self, x=None, diff = 0.0, bin = 0.0):
        """
        X値を指定してY方向にスライスする
        @param  x    X値
        @param  diff 積算範囲　(X±diff の範囲で積算)
        @param  bin  リビニング値　(0.0のときリビニングしない)
        @retval 無し        """ 
        # 引数1チェック
        if x == None:
            print "\nSliceY needs at least one argument."
            return
        if not self.val.ValidateNumeric(x, "Argument1"):
            # エラー終了
            return 
        # 引数2チェック
        if not self.val.ValidateNumeric(diff, "Argument2" , 0.0):
            # エラー終了
            return 
        # 引数3チェック
        if self.val.ValidateNumeric(bin, "Argument3" , 0.0, 1000.0):
            strCmd = "slicey %.3f %.3f %.3f\n" % (x, diff, bin)
            ret = self.plot.PutCommand(strCmd)
            
    #########################################         
    def SliceXRange(self, y0=None, y1=None, fract=1, bin = 0.0):
        """
        Xデータを切り取るYの範囲を指定        @param y0  X値の始値
        @param  y1  Y値の終値
        @param  fract  分割数
        @param  bin 　ビン値
        @retval 無し        """
        # 引数の有無をチェック
        if y0 == None or y1==None:
            print "\nSliceXRange needs at least two arguments."
            return
        
        # 引数1チェック
        if not self.val.ValidateNumeric(y0, "Argument 1"):
            # エラー終了
            return 
        # 引数2チェック
        if not self.val.ValidateNumeric(y1, "Argument 2" ):
            # エラー終了
            return 

        # 引数3チェック
        if not self.val.ValidateInteger(fract, "Argument 3" , 1,50):
            # エラー終了
            return 
        # 引数4チェック
        if self.val.ValidateNumeric(bin, "Argument 4" , 0.0, 1000.0):
            # 終値 >= 始値チェック
            if y1 > y0:
                strCmd = "slicexrange %.3f %.3f %d %.3f\n" % (y0, y1, fract, bin)
                ret = self.plot.PutCommand(strCmd)
            else:
                print "\nThe argument2 must be larger then the argument1." 
    
    #########################################         
    def SliceYRange(self, x0=None, x1=None, fract=1, bin = 0.0):
        """
        Y データを切り取るXの範囲を指定        @param  x0  X値の始値
        @param  x1  X値の終値
        @param  fract  分割数
        @param  bin 　ビン値
        @retval 無し        """
        # 引数の有無をチェック
        if x0 == None or x1==None:
            print "\nSliceYRange needs at least two arguments."
            return
        # 引数1チェック
        if not self.val.ValidateNumeric(x0, "Argument 1"):
            # エラー終了
            return 
        # 引数2チェック
        if not self.val.ValidateNumeric(x1, "Argument 2" ):
            # エラー終了
            return 

        # 引数3チェック
        if not self.val.ValidateInteger(fract, "Argument 3" , 1,50):
            # エラー終了
            return 
        # 引数4チェック
        if self.val.ValidateNumeric(bin, "Argument 4" , 0.0, 1000.0):
            # 終値 >= 始値チェック
            if x1 > x0:
                strCmd = "sliceyrange %.3f %.3f %d %.3f\n" % (x0, x1, fract, bin)
                ret = self.plot.PutCommand(strCmd)
            else:
                print "\nThe argument2 must be larger then the argument1."  

    #########################################         
    def AddToPlot(self, n=3):
        """
        表示中のデータをプロッタへ送信
        @param  n  1: Xのみ  2: Yのみ 3: 両方
        @retval 無し
        """
        # 引数チェック
        if self.val.ValidateInteger(n, "Argument", 1,3):
            strCmd = "add %d\n" % n
            # データ追加要求をカレントプロッタへ送る
            self.plot.PutCommand(strCmd) 
        
    #########################################         
    def ClearPlot(self, n=3):
        """
        プロッタをクリア
        @param  n  1: Xのみ  2: Yのみ 3: 両方
        @retval 無
        """
        # 引数チェック
        if self.val.ValidateInteger(n, "Argument", 1,3):
            strCmd = "clear %d\n" % n
            # データ追加要求をカレントプロッタへ送る
            self.plot.PutCommand(strCmd)
             
    #########################################         
    def SetXLabel(self, xlabel=""):
        """
        X軸のラベル設定
        @param  xlabel　横軸のラベル文字列
        @retval 無し
        """
        # 引数チェック
        if self.val.ValidateString(xlabel, "Argument", 0,50):
            # コマンド作成
            strCmd = "xlabel %s\n" % xlabel
            # 座標ラベル変更要求をカレントプロッタへ送る
            self.plot.PutCommand(strCmd)

    #########################################         
    def SetYLabel(self, ylabel=""):
        """
        Y軸のラベル設定
        @param  xlabel　横軸のラベル文字列
        @retval 無し
        """
        # 引数チェック
        if self.val.ValidateString(ylabel, "Argument", 0,50):
            # コマンド作成
            strCmd = "ylabel %s\n" % ylabel
            # 座標ラベル変更要求をカレントプロッタへ送る
            self.plot.PutCommand(strCmd)

    #########################################         
    def SetZLabel(self, zlabel=""):
        """
        Z軸のラベル設定
        @param  zlabel　横軸のラベル文字列
        @retval 無し
        """
        # 引数チェック
        if self.val.ValidateString(zlabel, "Argument", 0,50):
            # コマンド作成
            strCmd = "zlabel %s\n" % zlabel
            # 座標ラベル変更要求をカレントプロッタへ送る
            self.plot.PutCommand(strCmd)
            
    #########################################         
    def SetMainTitle(self, main=""):
        """
        メインタイトル設定
        @param  main　メインタイトル
        @retval 無し
        """
        # 引数チェック
        if self.val.ValidateString(main, "Argument", 0,50):
            # コマンド作成
            strCmd = "maintitle %s\n" % main
            # タイトル変更要求をカレントプロッタへ送る
            self.plot.PutCommand(strCmd) 
    
    #########################################         
    def SetSubTitle(self, sub=""):
        """
        サブタイトル設定
        @param  sub　サブタイトル
        @retval 無し
        """
        # 引数チェック
        if self.val.ValidateString(sub, "Argument", 0,50):
            # コマンド作成
            strCmd = "subtitle %s\n" % sub
            # タイトル変更要求をカレントプロッタへ送る
            self.plot.PutCommand(strCmd)               
                                     
    #########################################         
    def Print(self):
        """
        カレントプロッタを印刷する
        @param  無し
        @retval 無し
        """ 
        # 印刷要求をカレントプロッタへ送る
        answer = self.plot.PutCommand("print\n" ) 
        
    #########################################         
    def Save(self, fname=None):
        """
        画像ファイルの保存
        @param  ファイル名
        @retval 無し
        """
        # 引数が指定されていない場合
        if not self.val.ValidateObject(fname, "Save"):
            # エラー終了
            return   
        # 引数チェック
        if not self.val.ValidateString(fname, "Argument", 4,256):
            return
        
        # ファイル名取り出し
        filename = os.path.basename(fname)
        path, ext = os.path.splitext(filename)
        # 拡張子を除くファイル名の長さは1以上か
        if len(path) > 1:
            # サポートしている拡張子か
            if ext==".png" or ext==".ps" or ext==".eps" :
                strCmd = "save " + fname + '\n'
                # 画像保存要求をカレントプロッタへ送る
                self.plot.PutCommand(strCmd) 
            else:
                print "\nError!!  Extention must be png, ps, or eps."
        else:
            print "\nError!! Invalid file name."

#####################################################################
if __name__ == '__main__':
    """
    以下はテスト用のスクリプト

    """
    M2Plot(None,False)
    
    #import ECMSerialize as ECM
    #ecms = ECM.ECMSerialize()
    #DAT = ecms.Decode("/home/mlfdev/PowderData120207.dmp")
    #p = M2Plot(DAT, False)
#    import Read2D
#    # レガシィファイルを読み込んで、エレメントコンテナマトリックスを作成
#    dat = Read2D.Read2D("dummy.spe", "dummy.phx", 70.0)
#    mat = dat.GetMatrix()
#   
#    p=M2Plot(mat)
#    sleep(1)
#    p.SetLog(True)
#    p.Print()
#    p.Save("2dplot.ps")
#    p.NewPlot(mat)
#    p.NewPlot(mat)
#    p.Close(2)
#    p.SetMainTitle("Title set")
#    p.SetSubTitle("EI=70[meV]")
#    p.SliceXRange(-5,1,1)
#    p.SetWithPlot(True)
#    p.SliceYRange(3,5,4,0.1)
#    p.SetWithPlot(False)
#    sleep(2)
#    p.SetWithPlot(False, 2)
#    p.SliceX(0.5,2.0, 0.2)
#    p.AddToPlot(1)
#    p.SliceY(3.0,0.0,1)
#    p.SliceXRange
#    sleep(1)
#    p.AddToPlot(3) 
#    p.ClearPlot(3)
#    p.SetXLabel("X")
#    p.SetYLabel("yy Test")
#    p.SetZLabel("Z Axis")
#    sleep(2)
#    p.SetLog(False)
#    sleep(2)
#    p.SetZScale(0.0, 15.0)
#    sleep(2)
#    p.SetLog(True)
#    sleep(2)
#    p.SetZScale()
#    sleep(2)
#    p.Close(1)
#    sleep(2)
    
