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

"""
DetectorMap.py
検出器のマップ表示
"""
import sys
#sys.path.append("c:\\mlf\\1029")
#sys.path.append("c:\\source\\dataacq\\src") 
import wx
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
from matplotlib import cm
#import matplotlib.numerix.ma as ma
try:
    import numpy.ma as ma
except:
    import numpy.core.ma as ma
#import matplotlib.numerix as numpy
from numpy import arange, array, meshgrid,zeros, float64
import threading
import os, time, glob
import cStringIO, zlib
try:
    import scipy.weave as weave
    import platform
    wflag = True and (platform.system() != "Windows")
except:
    wflag = False
import vis.D2Vis as D2Vis
from exp.ChopConfiguration import *
from vis.UtilPlot import *
from vis.FastPlot import *

import math ##[inamura 120115]

import Manyo as mm
import Manyo.Utsusemi as mu

#######################################
#  DMatrixObj
#######################################  
class DMatrixObj(object):
    
    """
    エレメントコンテナマトリックスのハンドリングクラス
    """
        
    #########################################
    def __init__(self, parent, matrix, hTable):
        """
        コンストラクタ
        @param  parent    親クラスのインスタンス
        @param  matrix  　　 エレメントコンテナマトリックス
        @param  hTable　      PSD読み出し用のハッシュテーブル
        @retval 無し
        """ 
        self.matrix = matrix
        self.hTable = hTable
        self.numBank = parent.numBank
        self.numPSD = parent.numPSD
        self.numPixel = parent.numPixel
        self.frame = parent.frame
        
        # データ変換クラスのインスタンスを取得
        self.ce= ConvertEC()
        
        # 無効検出器ID 格納用のリストを準備
        self.masked = []

    #########################################
    def ReadMatrix(self, func):
        """
        エレメントコンテナマトリックスを読み込み、カウントマップを作成
        @param  func　     読み込み終了時のコールバック関数
        @retval 無し
        """
        self.progress = 0
        numRead = len(self.hTable)
        # プログレスバーダイアログ表示
        pdg = wx.ProgressDialog("Loading Matrix","Loading time:",numRead)
        # サブスレッドスタート(データ読み込み)
        th = threading.Thread(target=self._ReadData)
        th.setDaemon(True)
        th.start()
        
        # 進捗表示
        while self.progress < numRead:
            wx.Sleep(1)
            pdg.Update(self.progress)
        pdg.Destroy()
        
        # コールバック関数の実行(マップ表示)
        apply(func)

       
    #########################################
    def _ReadData(self):
        """
        エレメントコンテナマトリックスを読み出す
        @param   matrix  エレメントコンテナマトリックス
        @param  hTable　 PSD読み出し用のハッシュテーブル
        @retval 無し 
        """ 
        # データマップ格納用アレイを準備
        iPSD = self.numBank * (self.numPSD+2) - 2
        self.arData = zeros([self.numPixel, iPSD],float64)
        self.arErr = zeros([self.numPixel, iPSD],float64) ##[inamura 120115]
        # マスクデータを格納
        for i in range(self.numPixel):
            for j in range(iPSD):
                self.arData[i,j] = MASKVALUE
        self.matTOF = []
        self.matINT = []
        self.matERR = []   ##[inamura 120115]
        ##[inamura 100129]-->
        #Inamura 
        ##self.searchId = SearchHeaderChoppers()
        ##self.searchId.SetInputP(self.matrix)
        self.searchId = mm.SearchInHeader(self.matrix)
        # PixelInfoのデータリストを準備
        self.PixelInfo = []
        for i in range(self.numPixel):
            psd_list=[]
            for j in range(iPSD):
                psd_list.append((0.0,0.0,0.0))
            self.PixelInfo.append(psd_list)
             
        ##<--[inamura 100129]
        empty_flag = 0
        #make empty
        ec = self.matrix(1,0)
        xx = array(ec.PutXList())
        yy = ec.PutYList()
        for j in range(len(yy)):
            yy[j]=0
        yy = array(yy)

        emp_psdTOF = []
        emp_psdINT = []
        for i in range(self.numPixel):
            emp_psdTOF.append(xx)
            emp_psdINT.append(yy)
        #--Inamura
        
        # ハッシュテーブルの数だけ繰り返す
        #print "psdID=",
        for xi in range(len(self.hTable)):
            psdID = self.hTable[xi]
            
            #Inamura
            #print "Search id =",psdID
            if psdID >=0:
                #print psdID,
                self.searchId.SearchArray("PSDID",psdID)
                vect_index = self.searchId.PutResultIndex(0)
                retId = -1
                if vect_index.size()!=0:
                    retID = vect_index[0]
                if retID == -1:
                    self.masked.append(psdID)
                    # デテクタデータを書き込み
                    self.matTOF.append(emp_psdTOF) 
                    self.matINT.append(emp_psdINT)
                    self.matERR.append(emp_psdINT) ##[inamura 1201015]
                    #print "empty!!"
                else:
                    # エレメントアレイのポインタを取得
                    ea = self.matrix.PutPointer(retID)
                    # エレメントアレイのヘッダからマスク情報を取得
                    eah = ea.PutHeader()
                    if eah.PutInt4("MASKED"):
                        self.masked.append(psdID)
                        print "Masked = ",psdID

                    # データマップの横軸インデックスを求める
                    psdTOF = []
                    psdINT = []
                    psdERR = []  ##[inamura 120115]
                    # ピクセル数だけ読み出す
                    for i in range(self.numPixel):
                        if not psdID in self.masked:
                            ec = ea.PutPointer(i)
                            try:
                                 ech = ec.PutHeader()
                            except:
                                 print "Cannot load Header of ec(%d) in psdId(%d)" % (i,retID)
                                 raise
                                 
                            tc = ech.PutInt4("TotalCounts")
                            yi = self.numPixel - i - 1
                            self.arData[yi, xi]= tc
                            self.arErr[yi, xi] = math.sqrt(tc) ##[inamura 120115]
                            ##[inamura 100129]-->
                            angP = ech.PutDoubleVector("PixelPolarAngle")
                            angA = ech.PutDoubleVector("PixelAzimAngle")
                            posi = ech.PutDoubleVector("PixelPosition")
                            L2 = sqrt(posi[0]*posi[0]+posi[1]*posi[1]+posi[2]*posi[2])
                            self.PixelInfo[yi][xi] = ( angP[0], angA[0], L2 )
                        # ピクセルデータを取得
                        xx = array(ec.PutXList())
                        yy = array(ec.PutYList())
                        ee = array(ec.PutEList()) ##[inamura 120115]
                        psdTOF.append(xx)
                        psdINT.append(yy) 
                        psdERR.append(ee) ##[inamura 120115]
                     # デテクタデータを書き込み
                    self.matTOF.append(psdTOF) 
                    self.matINT.append(psdINT)
                    self.matERR.append(psdERR) ##[inamura 120115]

            self.progress += 1
            
        print "Masked:", self.masked
        
    #########################################    
    def GetMapData(self):
        """
        全検出単位のカウントマップを返す
        @param  無し        @retval カウントマップデータ(PSD×Pixecl の2次元配列)
        """
        ##[inamura 100621]-->
        #return  self.arData + 0.05
        return  self.arData
        ##<--[inamura 100621]

    #########################################    
    def RemakeMapData(self, tof1, tof2, hTable):
        """
        全検出単位のカウントマップを返す
        @param  tof1  　TOF 範囲始値
        @param  tof2　  TOF 範囲終値
        @param  hTable  PSD読み出し用のハッシュテーブル
        @retval カウントマップデータ(PSD×Pixecl の2次元配列)
        """ 
    
        code =\
         """
         double sum = 0.0;
         int i;

         for(int i=0; i < yy.ubound(0) ;i++) {
             if( tof(i) > tof2) {
                 break;    
                 }
             if( tof(i) >= tof1) {
                 sum += yy(i);
             }
         }
         return_val = sum; 

         """
        
        ##[inamura 120115]-->
        code_err =\
         """
         double sum = 0.0;
         int i;

         for(int i=0; i < ee.ubound(0) ;i++) {
             if( tof(i) > tof2) {
                 break;    
                 }
             if( tof(i) >= tof1) {
                 sum += ee(i)*ee(i);
             }
         }
         return_val = sum; 

         """ ##<--[inamura 120115]
        time0 = time.clock()

        # ハッシュテーブル内の数だけ繰り返す
        for xi in range(len(hTable)):
            psdID = hTable[xi]
            # 有効な検出器か
            if psdID >= 0:
                if self.IsValid(psdID):
                    # ピクセル数だけ読み出す
                    for j in range(self.numPixel):
                        """
                        tof= self.matTOF[psdID][j]
                        yy= self.matINT[psdID][j]
                        ee= self.matERR[psdID][j] ##[inamura 120115]
                        """
                        tof= self.matTOF[xi][j]
                        yy= self.matINT[xi][j]
                        ee= self.matERR[xi][j] ## [inamura 120125]
                        # weave がインポートされているか
                        if wflag:
                            # C言語で積算
                            sum = weave.inline(code, ['tof', 'yy','tof1', 'tof2'], type_converters = weave.converters.blitz)
                            sum_e2 = weave.inline(code_err, ['tof', 'ee','tof1', 'tof2'], type_converters = weave.converters.blitz)##[inamura 120115]
                        else:
                            # python で積算
                            sum = 0.0
                            sum_e2 = 0.0 ##[inamura 120115]
                            for i in range(len(yy)):
                                # 範囲の終わりか
                                if tof[i] > tof2:
                                    break
                                # 範囲内か
                                if tof[i] >= tof1:
                                    sum += yy[i]
                                    sum_e2 += ee[i]*ee[i] ##[inamura 120115]
                        # 新たな値に入れ替える            
                        #Inamura
                        #self.arData[j, xi] = sum
                        self.arData[(self.numPixel-j-1),xi]=sum
                        self.arErr[(self.numPixel-j-1),xi] = math.sqrt( sum_e2 ) ##[inamura 120115]
                        #--Inamura
                # Masked PSD
                else:
                    for j in range(self.numPixel):
                        self.arData[j,xi]= MASKVALUE
                         
            self.npsd = psdID
                
        tsec = time.clock() - time0
        print "Calc Time: %.1f sec" % tsec
        ##[inamura 100621]-->
        #return  self.arData + 0.05
        return  self.arData
        ##<--[inamura 100621]
    
    #########################################    
    def GetPSDArray(self, psd):
        """
        指定されたPSD のデータを返す
        @param  psd  psd No.
        @retval PSD のデータ
        """
        #Inamura
        self.searchId.SearchArray("PSDID",psd)
        vect_index = self.searchId.PutResultIndex(0)
        if vect_index.size()==0:
            return (None,None,None)
        psd = vect_index[0]
        #--Inamura
        # 中心のエレメントコンテナのTOFを取得
        ec0 = self.matrix(psd, self.numPixel/2) 
        tof = ec0.PutX()
        # リビニング後のY データの個数
        znum = len(tof)-1
       
        # リビニング後のカウント数アレイ用に全点 0 のアレイを作成        
        zz =zeros((znum, self.numPixel), float64)
        er =zeros((znum, self.numPixel), float64)
        
        # 1検出器分の強度データを取り出す
        for i in range(self.numPixel):
            # エレメントコンテナ取得
            ec = self.matrix(psd, i)
            # 中央のTOF 値でリビニング 
            ecx = ec.ReBin(tof)
            yy = ecx.PutYList()   
            ee = ecx.PutEList()
            # カウント数アレイとエラー値アレイへ格納 
            for j in range(len(yy)):
                zz[j,i]=yy[j]
                er[j,i]=ee[j]
        
        return (tof,zz, er)
    
   
    #########################################    
    def GetMax(self):
        """
        カウント数の最大値(マスク値を除く)
        @param  無し
        @retval 最大値
        """
        ##[inamura 100621]-->
        #max = 1.0
        max = -1.0E10
        ##<--[inamura 100621]
        for i in range(len(self.arData)):
            for j in range(len(self.arData[0])):
                if self.arData[i,j] < MASKVALUE: 
                    if self.arData[i,j] > max:
                        max = self.arData[i,j]
        return  max

    ##[inamura 100621]-->
    #########################################    
    def GetMin(self):
        """
        カウント数の最小値
        @param  無し
        @retval 最小値
        """ 
        min = 1.0E10
        for i in range(len(self.arData)):
            for j in range(len(self.arData[0])):
                 if self.arData[i,j] < min:
                      min = self.arData[i,j]
        return  min
    ##<--[inamura 100621]
    #########################################    
    def GetTitle(self):
        """
        マトリックスのヘッダーよりランNo.とサンプル名を取得
        @param  無し
        @retval Run No. (文字列)
        """
        runNo = "" 
        sample = ""
        try:
            # マトリックスのヘッダーを取得
            mth = self.matrix.PutHeader()
            # ヘッダーストリングを取得
            runNo = mth.PutString("RUNNUMBER")
        except:
            return  ""

        return  runNo

    #########################################
    def GetTOFRange(self):
        """
        データ読み出し時のTOF範囲を取得
        @param  無し
        @retval ヒストグラムデータ(X, Y, er, ヘッダー、xunit, yunit)
        """ 
        # 中心のエレメントコンテナのTOFを取得
        ec0 = self.matrix(0, self.numPixel/2) 
        tof = ec0.PutX()
        n = len(tof)-1
        return (tof[0], tof[n])
    
    #########################################
    def GetHistogram(self, psdID, pixel):
        """
        PSD-ID からヒストグラムを取得
        @param  psdID PSD No
        @param  pixel Pixel No
        @retval ヒストグラムデータ(X, Y, er, ヘッダー、xunit, yunit)
        """
        #Inamura
        self.searchId.SearchArray("PSDID",psdID)
        vect_index = self.searchId.PutResultIndex(0)
        if vect_index.size()==0:
            return None
        psdID = vect_index[0]
        #--Inamura
        
        # エレメントコンテナ取得
        ec = self.matrix(psdID, pixel)
        # Manyo データからプロッタ用データに変換
        pdat = self.ce.ConvertEC(ec)
        # トレースラベルを追加
        label = "%d-%d" % (psdID, pixel)
        pdat[3]["Label"] = label
        return pdat

    #########################################    
    def IntegrateHistogram(self, lstPSDid):
        """
        指定されたヒストグラムを積算して返す
        ヘッダーの PSD-ID には積算情報を書きこむ
        @param  lstPSDid (ブロックNo.、PSD No.、Pixel No. のタプル　のリスト)
        @retval ヒストグラムデータ()
        """     
        # 領域の中心のPSD と　Pixel を求める
        ps = []
        px = []
        for psdID in lstPSDid:
            if not psdID[0] in ps:
                ps.append(psdID[0])
            if not psdID[1] in px:
                px.append(psdID[1])
        pp = ps[len(ps)/2]
        xx = px[len(px)/2]

        #Inamura
        self.searchId.SearchArray("PSDID",pp)
        vect_index = self.searchId.PutResultIndex(0)
        if vect_index.size()==0:
            return (None,None,None)
        pp = vect_index[0]
        #--Inamura

        # 領域の中心のエレメントコンテナのTOFを取得
        ec0 = self.matrix(pp, xx) 
        tof = ec0.PutX()
        
        # 積算 PSD-ID の文字列を作る
        strSum = ""
        
        # リストに含まれるデータを積算
        n = 0.0

        for psdID in lstPSDid:
             
             #Inamura
            self.searchId.SearchArray("PSDID",psdID[0])
            vect_index = self.searchId.PutResultIndex(0)
            if vect_index.size()==0:
                return (None,None,None)
            psd = vect_index[0]
            # 強度とエラーを取得
#            ec = self.matrix(psdID[0], psdID[1])
            ec = self.matrix(psd,psdID[1])
            #--Inamura
            
            # 領域中心のTOFでリビニング
            ## [inamura 100414]-->
            ## At calulating TOF, Binning must be use!!
            #ecx = ec.ReBin(tof)
            ecx = ec.Binning(tof)
            ## <--[inamura 100414]
            yy = ecx.PutYList()   
            er = ecx.PutEList()
            yy = array(yy)
            er = array(er)
            
            # 最初か
            if strSum == "":
                sumyy = yy
                sumer = er*er
                hist = self.ce.ConvertEC(ec)
            # 2回目以降か
            else:
                # Y値リストとエラーを積算
                sumyy = sumyy + yy
                sumer = sumer + er*er
            
            # psdID の文字列を作成
            strDat = "%d-%d" % (psdID[0], psdID[1])
            # 積算文字列を作成
            if strSum == "":
                strSum = strSum + strDat
            else:
                strSum = strSum + "+" + strDat
            # 積算回数をカウント    
            n += 1.0
            
        # 積算回数で割る        
        sumyy = sumyy / n
#        sumer = sqrt(sumer/n)
        sumer = sqrt(sumer)/n    # 2009.06.15 Minakawa 修正
                    
        # ヘッダー内の Label を、積算文字列に変更
        hist[3]["Label"] = strSum
        hist[1] = sumyy
        hist[2] = sumer
        
        # 積算後のヒストグラムデータに変更   
        return hist        


    #########################################
    def IsValid(self, psd):
        """
        マスクされている検出器かどうかを調べる
        @param   psd  PSD ID   
        @retval True: 有効　or  False: 無効
        """ 
        # マスクPSD のリスト中にあるか
        if psd in self.masked:
            return False
        else:
            return True
    
    
    ##[inamura 120117]-->
    #########################################
    def GetLineFromIntensities(self, psdRange, pixelRange, xAxis ):
         """
         Get Intensity as plot along Pixel direction
         @param psdRange   tupple of minimum and maximum PSD
         @param pixelRange tupple of minimum and maximum PixelNo
         @param xAxis      "PSD" or "PIXEL" to be x-axis
         """
         if not xAxis in ["PSD","PIXEL"]:
             raise 
         
         min_psd = psdRange[0]
         max_psd = psdRange[1]
         min_pix = pixelRange[0]
         max_pix = pixelRange[1]
         
         xi_min = -1
         xi_max = -1
         for i in range(len(self.hTable)):
             if min_psd==self.hTable[i]:
                 xi_min = i
                 break
         for i in range(len(self.hTable)):
             if max_psd==self.hTable[i]:
                 xi_max = i
                 break
         
         if xi_min>xi_max:
             tmp = xi_min
             xi_min = xi_max
             xi_max = tmp
         
         yi_min = self.numPixel - max_pix -1
         yi_max = self.numPixel - min_pix -1

         psd_in = []
         for i in range( xi_min, (xi_max+1) ):
             if self.hTable[i]!=-1:
                 psd_in.append( i )
         
         pixel_in = range( yi_min, (yi_max+1) )
         
         xx = []
         yy = []
         ee = []
                  
         if xAxis=="PSD":
             for i in range( len(psd_in) ):
                 xx.append( self.hTable[ psd_in[i] ] )
                 yy.append(0.0)
                 ee.append(0.0)
             for pix in pixel_in:
                 for i in range(len(psd_in)):
                     yy[i] += self.arData[ pix, psd_in[i] ]
                     ee[i] += self.arErr[ pix, psd_in[i] ]*self.arErr[ pix, psd_in[i] ]
             for i in range( len(xx) ):
                 yy[i] = yy[i]/( double(len(pixel_in)) )
                 ee[i] = math.sqrt(ee[i])/( double(len(pixel_in)) )

         else:
             for i in range( len(pixel_in) ):
                 xx.append( self.numPixel-(pixel_in[i]+1) )
                 yy.append(0.0)
                 ee.append(0.0)
             for psd in psd_in:
                 for i in range( len(pixel_in) ):
                     yy[i] += self.arData[ pixel_in[i], psd ]
                     ee[i] += self.arErr[ pixel_in[i], psd ]*self.arErr[ pixel_in[i], psd ]
             for i in range( len(xx) ):
                 yy[i] = yy[i]/( double(len(psd_in)) )
                 ee[i] = math.sqrt(ee[i])/( double(len(psd_in)) )

         label = "%d-%d,%d-%d(along %s)" % (min_psd, min_pix, max_psd, max_pix, xAxis)
         print "label=",label
         header = {"Label":label }
         
         ret = []
         if xAxis=="PSD":
             ret = [xx,yy,ee,header,"PSDID","Counts"]
         else:
             ret = [xx,yy,ee,header,"PIXEL","Counts"]
             
         return ret

    ##<--[inamura 120117]
    
#######################################
#  DQuasiObj
#######################################  
class DQuasiObj(object):
    
    """
    擬似データのハンドリングクラス
    """
    # X値リスト(デバッグ用ダミーデータ)
    xx = [0, 3,   5,    6,   9,   11,  12,  13,  14,    16,  18, 21,  22,  23,  24, 38, 40]
    # Y値リスト(デバッグ用ダミーデータ)
    yy = [0.0,0.0, 1.0, 5.0, 0.0, 0.0, 100.0,  250.0,  180.0, 90.0, 0.0, 0.0 ,2.0, 14.0,0.0, 0.0] 
    # エラーリスト(デバッグ用ダミーデータ)
    er = er = [1, 1, 1, 2, 1, 1, 6, 7, 5, 4, 2, 0, 2, 3, 2, 1]
        
    #########################################
    def __init__(self, parent, fname, hTable):
        """
        擬似データファイル読み込み、カウントマップを作成
        @param  parent    親クラスのインスタンス
        @param  fname  　擬似データファイル名
        @param  hTable　 PSD読み出し用のハッシュテーブル
        @retval 無し
        """ 
        self.numBank = parent.numBank
        self.numPSD = parent.numPSD
        self.numPixel = parent.numPixel

        # 疑似データファイルを開く
        datFile = open(fname, 'r')

        dataList = []
        dummy = []
        # バンクギャップ用のダミーデータを準備
        for i in range(self.numPixel):
            dummy.append(MASKVALUE)
        
        i = 1
        psd = 0
        for line in datFile:
            try:
                # 1検出器分のデータを読み込んで、実数に変換
                data = map(float, line[:-1].split(','))
            except:
                i += 1
                if i > self.numBank:
                    break
                # バンクギャップ用のダミーデータを作成
                dataList.append(dummy)    
                dataList.append(dummy)
                psd += 2
            else:
                if hTable[psd] >=0:
                    # データを追加
                    data.reverse()
                    dataList.append(data)
                else:
                    dataList.append(dummy)
                psd += 1
                
        # データアレイを準備        
        self.arData =zeros((self.numPixel,(self.numPSD+2)*self.numBank - 2))
        
        # 縦横を入れ替え
        for i in range(self.numPixel):
            for j in range((self.numPSD+2)*self.numBank - 2):
                self.arData[i][j] = dataList[j][i]        
        # 疑似データファイルをクローズ
        datFile.close()               

    #########################################    
    def GetMapData(self):
        """
        全検出単位のカウントマップを返す
        @param  無し
        @retval カウントマップデータ(PSD×Pixecl の2次元配列)
        """ 
        return  self.arData + 0.05

    #########################################    
    def RemakeMapData(self, tof1, tof2, hTable):
        """
        全検出単位のカウントマップを返す
        @param  tof1  　TOF 範囲始値
        @param  tof2　  TOF 範囲終値
        @param  hTable  PSD読み出し用のハッシュテーブル
        @retval カウントマップデータ(PSD×Pixecl の2次元配列)
        """ 
        return  self.arData + 0.05
    
    #########################################    
    def GetPSDArray(self, psd):
        """
        指定されたPSD のデータを返す
        @param  psd  psd No.
        @retval PSD のデータ
        """ 

        # Y データの個数
        tof = arange(5000.0, 15100.0, 100.0)
        znum = len(tof)-1

        # 全点 0 のアレイを作成        
        zz =zeros((znum, self.numPixel), float64)
        er =zeros((znum, self.numPixel), float64)

        # 1検出器分の強度データを取り出す
        for i in range(self.numPixel):
            k = 100
            for j in range(znum):
                while True:
                    if k ==  len(self.arData[0]):
                         break
                    yy = self.arData[i,k]
                    if self.arData[i,k] < MASKVALUE: 
                        break
                    k += 1
                    
                zz[j,i]=yy
                if k ==  len(self.arData[0]):
                    break
                k += 1
        zz[10,10] = -1.5
        return (tof,zz, er)

   
    #########################################    
    def GetMax(self):
        """
        カウント数の最大値(マスク値を除く)
        @param  無し
        @retval 最大値
        """ 
        max = 1.0
        for i in range(len(self.arData)):
            for j in range(len(self.arData[0])):
                if self.arData[i,j] < MASKVALUE: 
                    if self.arData[i,j] > max:
                        max = self.arData[i,j]
        return  max
    
    #########################################    
    def GetTitle(self):
        """
        マトリックスのヘッダーよりランNo.とサンプル名を取得
        @param  無し
        @retval Run No. (文字列)
        """
        return  "AMT0002"

    #########################################
    def GetTOFRange(self):
        """
        データ読み出し時のTOF範囲を取得
        @param  無し
        @retval ヒストグラムデータ(X, Y, er, ヘッダー、xunit, yunit)
        """ 
        n = len(self.xx)-1
        return (self.xx[0], self.xx[n])
    
    #########################################
    def GetHistogram(self, psdID, pixel):
        """
        疑似ヒストグラムデータを返す
        @param  psdID PSD No
        @param  pixel Pixel No
        @retval x, y, er のアレイ、x軸単位、Y軸単位、ヘッダーディクショナリのタプル
        """ 
        # ヘッダーディクショナリ作成
        strPSD = "%d-%d" % (psdID, pixel)
        header = {"Label":strPSD, "RunNo":"AMT00001",}   
        
        return (self.xx,self.yy,self.er,header,"micro-sec","Newtrons")              
   
    #########################################    
    def IntegrateHistogram(self, lstPSDid):
        """
        指定されたヒストグラムを積算して返す
        ヘッダーの PSD-ID には積算情報を書きこむ
        @param  lstPSDid (ブロックNo.、PSD No.、Pixel No. のタプル　のリスト)
        @retval ヒストグラムデータ()
        """     

        # 積算 PSD-ID の文字列を作る
        strSum = ""
        
        # リストに含まれるデータを積算
        for psdID in lstPSDid:
            # psdID の文字列を作成
            strDat = "%d-%d" % (psdID[0], psdID[1])
            # 積算文字列を作成
            if strSum == "":
                strSum = strSum + strDat
            else:
                strSum = strSum + "+" + strDat
                
        header = {"Label":strSum, "RunNo":"AMT00001",}   
        return (self.xx,self.yy,self.er,header,"micro-sec","Newtrons")   


    #########################################
    def IsValid(self, psd):
        """
        マスクされている検出器かどうかを調べる
        @param   psd  PSD ID   
        @retval True: 有効　or  False: 無効
        """ 
        return True

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

    #########################################
    def __init__(self, parent, matrix):
        """
        検出器マップ表示処理のコンストラクタ
        @param  parent 親画面のインスタンス   
        @param  matrix エレメントアレイマトリックス   
        @retval 無し
        """ 
        # 初期化
        self.logFlag = False
        self.dragFlag = False
        self.d2 = None
        # プロッタ番号の初期化
        self.order = 0
        # プロッタリストの準備
        self.plots = []
        # カレントプロッタ
        self.plot = None

        # リソースからメイン画面を取得
        res = ResourceFile()
        self.frame = res.GetFrame(parent, "mapframe")
        # リソースからフレームが取得できなかった
        if self.frame == None:
            return
        # アイコンを設定
        self.frame.SetIcon(Images().GetMainIcon())
        # メニューバーを取得
        self.menuBar= res.GetMenuBar('MainMenuBar')
        self.frame.SetMenuBar(self.menuBar)
        # グラフ描画用のパネルを取得
        panel = res.GetCtrl(self.frame, 'mapPanel')

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

        # ツールバー作成
        self.toolbar = ChartToolBar(self,0)
        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()
        
        # コンフィギュレーションを取得
        try:
            """
            cnf = ChopConfiguration()
            # 分光器名を取得
            instrument = cnf.PutSpectrometerName()
            # 検出器情報を取得
            self.numBank, self.numPSD, self.numPixel = cnf.PutDetectInfo()
            # PSD 情報(ハッシュテーブル)を取得
            self.hTable = cnf.PutPSDInfo()
            """
            self.numBank = 1
            self.numPSD = matrix.PutSize()
            self.numPixel = matrix(0).PutSize()
            self.hTable = []
            for i in range(self.numPSD):
                 if matrix(i).PutHeaderPointer().PutInt4("MASKED")==1:
                      self.hTable.append(-1)
                 else:
                      self.hTable.append( matrix(i).PutHeaderPointer().PutInt4("PSDID") )
            print "hTable=",self.hTable
            instrument = matrix.PutHeaderPointer().PutString("INSTRUMENT")

        except PlotException, ex:
            PlotMessage(self.frame,ex)
            self.OnClose()
            return
        
        # フレームのタイトルに分光器名を付加
        strT1 = self.frame.GetTitle()
        strT2 = " for %s" % instrument
        self.frame.SetTitle(strT1+strT2)
        
        # イベントハンドラーの設定
        self._SetEventHandler(res)
        
        # メイン画面を表示
        self.frame.Show()
        
        time.sleep(0.1) ##[inamura 100726] for stability on command line
        
        # 引数が文字列であったなら
        if type(matrix) == type(""):
            # 疑似データファイル読み込み
            self.do = DQuasiObj(self, matrix, self.hTable)
            self._DispChart()
        else:
            # エレメントコンテナマトリックスをロード
            self.do = DMatrixObj(self, matrix, self.hTable)
            self.do.ReadMatrix(self._DispChart)

    #########################################
    def _DispChart(self):
        """
        検出器マップチャートを描画する
        @param   無し   
        @retval 無し
        """
        # マップデータの取得   
        self.Z = self.do.GetMapData()
        self.datMax = self.do.GetMax()
        self.zMax = self.datMax
        ##[inamura 100621]-->
        self.datMin = self.do.GetMin()
        if (self.logFlag) and (self.datMin <= 0.0):
             self.zMin = 1.0E-20
        else:
             self.zMin = self.datMin
        
        self.yminTx.SetValue( ("%g" % self.zMin) )
        self.ymaxTx.SetValue( ("%g" % self.zMax) )
        ##<--[inamura 100621]
        ##[inamura 100129]-->
        self.PixelInfo = self.do.PixelInfo
        ##<--[inamura 100129]

        # マップデータからマスクデータ作成
        self.Zm = ma.masked_where(self.Z >= MASKVALUE, self.Z)

        # TOF Range の初期値を設定
        tof1, tof2 = self.do.GetTOFRange()
        # 始値のテキストボックスに値を設定    
        strtof1 = "%d" % tof1
        strtof2 = "%d" % tof2
        self.tofTx1.SetValue(strtof1)
        self.tofTx2.SetValue(strtof2)

        # PSD の最大値を検索
        self.maxPSD = 0
        for pnum in self.hTable:
            if pnum > self.maxPSD:
                self.maxPSD = pnum

        # 検出器マップの描画
        self.PlotChart()
        


    #########################################
    def _SetEventHandler(self, res):
        """
        イベントハンドラーの登録
        @param  res リソースファイルのインスタンス   
        @retval 無し
        """ 
        # プリントボタンのリスナー登録
        IFEvtProp(0).AddListner('print',  self.OnPrint)
        # 保存ボタンのリスナー登録
        IFEvtProp(0).AddListner('save',  self.OnSave)
        
        #ボタンのイベントハンドラ登録
        self.frame.Bind(wx.EVT_BUTTON, self.OnBtRedraw, id=ResourceFile().GetId('btRedraw'))
        self.frame.Bind(wx.EVT_BUTTON, self.OnBt2dPlot, id=ResourceFile().GetId('bt2dPlot'))
        self.frame.Bind(wx.EVT_BUTTON, self.OnBtAppend, id=ResourceFile().GetId('btAppend'))
        self.frame.Bind(wx.EVT_BUTTON, self.OnBtSumm, id=ResourceFile().GetId('btSumm'))
        self.frame.Bind(wx.EVT_BUTTON, self.OnNewPlot, id=ResourceFile().GetId('btNewPlot'))
        ##[inamura 100621]-->
        self.frame.Bind(wx.EVT_BUTTON, self.OnBtRedrawInt, id=ResourceFile().GetId('btIntSet'))
        self.frame.Bind(wx.EVT_BUTTON, self.OnBtRedraw, id=ResourceFile().GetId('btIntClear'))
        ##<--[inamura 100621]
 
        #メニューのイベントハンドラ登録
        self.frame.Bind(wx.EVT_MENU, self.OnPrint, id=ResourceFile().GetId('menu_print'))
        self.frame.Bind(wx.EVT_MENU, self.OnClose, id=ResourceFile().GetId('menu_exit'))
        self.frame.Bind(wx.EVT_MENU, self.OnNewPlot, id=ResourceFile().GetId('menu_plot'))
        self.frame.Bind(wx.EVT_MENU, self.OnLog, id=ResourceFile().GetId('menu_log'))
        
        #クローズイベント登録
        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.OnBtDown)
        self.canvas.mpl_connect('button_release_event', self.OnBtUp)
        
        #テキストボックスのコントロール取得
        panel = ResourceFile().GetCtrl(self.frame, 'panel0')
        self.psdTx0 = ResourceFile().GetCtrl(panel, 'psd0')
        self.psdTx1 = ResourceFile().GetCtrl(panel, 'PSD1')
        self.pxTx1 = ResourceFile().GetCtrl(panel, 'pixel1')
        self.psdTx2 = ResourceFile().GetCtrl(panel, 'PSD2')
        self.pxTx2 = ResourceFile().GetCtrl(panel, 'pixel2')
        self.tofTx1 = ResourceFile().GetCtrl(panel, 'tof1')
        self.tofTx2 = ResourceFile().GetCtrl(panel, 'tof2')
        
        #リストのコントロール取得
        self.plist = ResourceFile().GetCtrl(panel, 'plotList')
        self.frame.Bind(wx.EVT_LISTBOX, self.OnListSelect, self.plist)
        
        # 検出器情報のコントロール取得
        pn = ResourceFile().GetCtrl(self.frame,'panel2')
        self.iftxt = ResourceFile().GetCtrl(pn,'infotxt')         
        
        #スライダーのイベントハンドラ登録
        panels = ResourceFile().GetCtrl(self.frame,'panel1')
        # リソースからスライダーのID を取得
        self.slider = ResourceFile().GetCtrl(panels,'slider')
        # スライダーのイベントハンドラーを設定
        self.slider.Bind(wx.EVT_SLIDER , self.OnSlider)

        #[inamura 100621]-->
        self.yminTx = ResourceFile().GetCtrl(pn,'ymin')
        self.ymaxTx = ResourceFile().GetCtrl(pn,'ymax')
        #<--[inamura 100621]
        self.cbXax = ResourceFile().GetCtrl(panel, 'cbXaxisOfPlot') # [inamura 120115]
        
    #########################################
    def PlotChart(self):
        """
        検出器マップチャートを描画する
        @param   無し   
        @retval 無し
        """ 
        # フィギュアをクリア 
        self.fig.clf()
        # タイトルを取得
        runNo = self.do.GetTitle()
        strRunNo = "Run No.: " + runNo

        # グラフのタイトルとして、ランNo.を表示
        self.fig.text(0.08, 0.94, strRunNo)
        ##[inamura 100622]-->
        x0 = float(self.tofTx1.GetValue())
        x1 = float(self.tofTx2.GetValue())
        y0 = float(self.yminTx.GetValue())
        y1 = float(self.ymaxTx.GetValue())
        strInfo1 = "X-axis Range\nIntensity Range"
        strInfo2 = ": %g - %g\n: %g - %g" % (x0,x1,y0,y1)
        self.fig.text(0.20, 0.905, strInfo1)
        self.fig.text(0.32, 0.905, strInfo2)
        ##<--[inamura 100622]

        x = arange(0, (self.numPSD+2)*self.numBank - 1, 1)
        y = arange(0, self.numPixel+1, 1)
        X, Y = meshgrid(x, y)

        # 検出器マップ用のサブプロットを準備
        self.ax = self.fig.add_subplot(111)
        self.ax.set_position([0.08, 0.15, 0.89 ,0.73])
        
        # カラーバー用の座標軸を準備
        axc = self.fig.add_axes([0.68, 0.93, 0.25 ,0.03])
        
        # カーソル表示用のサブプロットを準備(透過モード)
        self.cursol = self.fig.add_subplot(111,frameon=False)
        self.cursol.set_position([0.08, 0.15, 0.89 ,0.73])
        
        # マスクデータの色作成(白色)
        cmap = cm.jet
        cmap.set_bad('w', 1.0)
        
        # ログ表示か
        if self.logFlag:
            # カラーマップをログモードで表示
            pc = self.ax.pcolormesh(X, Y, self.Zm,  cmap=cmap,\
                                    norm=LogNorm(vmin=self.zMin, vmax=self.zMax)) ##[inamura 100621]
                                #norm=LogNorm(vmin=0.11, vmax=self.zMax))
        else:
            # カラーマップをリニアモードで表示
            pc = self.ax.pcolormesh(X, Y, self.Zm, cmap=cmap,\
                                    norm=Normalize(vmin=self.zMin, vmax=self.zMax)) ##[inamura 100621]
                                #norm=Normalize(vmin=0, vmax=self.zMax))
            
        # カラーマップと関連付けて、カラーバーを表示     
        self.fig.colorbar(pc, cax=axc, orientation='horizontal')
        # カラーバーの座標ラベルの文字を小さくする
        xlabels = getp(axc, 'xticklabels')
        setp(xlabels, size=7)
        
        # チャートを整える
        self.ArrangeChart()
        
        # グラフを再表示              
        self.canvas.draw()    
    
    #########################################
    def ArrangeChart(self):
        """
        検出器マップチャートを整える
        @param   無し   
        @retval 無し
        """ 
        # X軸範囲とY軸範囲をセット
        self.ax.set_xlim((0.0, (self.numPSD+2)*self.numBank - 2))
        self.ax.set_ylim((0.0, self.numPixel))
        self.cursol.set_xlim((0.0, (self.numPSD+2)*self.numBank - 2))
        self.cursol.set_ylim((0.0, self.numPixel))
        
        # 検出器マップの座標を消す
        self.ax.set_xticks([])
        self.ax.set_yticks([])

        # カーソル用サブプロットの座標を消す
        self.cursol.set_xticks([])
        self.cursol.set_yticks([])

        # ピクセル番号をグラフ左に表示
        ##[inamura 100622]-->
        #hf = self.numPixel / 2
        #strHf = "%d" % hf
        #strPx = "%d" % self.numPixel
        hf = self.numPixel / 2 -1
        strHf = "%d" % hf
        strPx = "%d" % (self.numPixel -1)
        # バンク番号をグラフ下に表示
        #self.ax.text(-3, self.numPixel-1, "1", horizontalalignment='right')
        self.ax.text(-3, self.numPixel-1, "0", horizontalalignment='right')
        self.ax.text(-3, hf, strHf, horizontalalignment='right')
        self.ax.text(-3, 0, strPx, horizontalalignment='right')
        ##<--[inamura 100622]
        self.fig.text(0.5, 0.07, "Bank", horizontalalignment='center')
        
        xx = 0.09
        xP = self.numPSD
        for i in range(self.numBank):
            # バンク No. 表示
            num = i+1.0
            strBk = "%d" % num
            bx = i*(self.numPSD+2) + self.numPSD / 2 + 1.0 
            self.ax.text(bx, -7, strBk, horizontalalignment='center')
            xx += 0.084
            # バンク境界表示
            if not num == self.numBank:
                #self.ax.axvspan(xP, xP+2, facecolor='0.4')
                self.ax.axvspan(xP-0.2, xP+2, facecolor='0.4') ## [inamura 100726] for matplotlib 0.98
                xP = xP + 2 + self.numPSD

    #########################################        
    def UpdateStatusBar(self, event):
        """
        マウス位置の検出器情報を表示
        @param   event イベント情報   
        @retval 無し
        """ 
        # マウス位置を取得
        x, y = int(event.xdata), int(event.ydata)
        # マウス位置の PSD-ID を取得
        #[inamura091012]--
        #pixel = self.numPixel - y
        pixel = self.numPixel - (y+1)
        #--[inamura091012]
        psd = self.hTable[x] 
        # マウス位置の カウント数を取得 
        counts = self.Z[y,x]
        # 検出器があるか
        if self.hTable[x] >= 0:
            strSTDID = "PSD ID: %03d -%03d \n" % (psd, pixel)
            # 有効な検出器か 
            if self.do.IsValid(psd):
                ##[inamura 100129]-->
                #strCounts = "     Counts: %d" % counts
                strCounts = "     2theta:%+08.3f  Azim:%+08.3f  L2:%08.2f\n" % self.PixelInfo[y][x]
                strCounts+= "     Counts: %d" % counts
                ##<--[inamura 100129]
            else:
                ##[inamura 100129]-->
                #strCounts = "     Counts: --"
                strCounts = "     2theta:xxxx.xxx  Azim:xxxx.xxx  L2:xxxxx.xx\n"
                strCounts+= "     Counts: xx\n"
                ##<--[inamura 100129]
        # 無効な検出器の場合は情報を表示しない
        else:
            ##[inamura 100129]-->
            #strSTDID = "        PSD ID: ---- "
            #strCounts = "     Counts: --"
            strSTDID = "PSD ID: xxx -xxx \n"
            strCounts = "     2theta:xxxx.xxx  Azim:xxxx.xxx  L2:xxxxx.xx\n"
            strCounts+= "     Counts: xx"
            ##<--[inamura 100129]
        # マップの下にマウス位置の情報を表示    
        self.iftxt.SetLabel(strSTDID +strCounts)

    #########################################
    def OnMouseMove(self, event):
        """
        マウス-ボタンクリックイベント処理
        @param   event イベント情報   
        @retval 無し
        """ 
        # マウス位置がグラフ内かどうかをチェック
        if not event.inaxes:
            return
        # グラフ内であっても、None が来ることがあるのでプロテクト
        if event.ydata == None or event.xdata == None:
            return
                
        # ドラッグ中であれば
        if self.dragFlag:
            # カーソル用サブプロットをクリア
            self.cursol.clear()
            ##[inamura 100726]-->
            ## if version of matplotlib > 0.98
            if matplotlib_verNo > 980:
                 self.cursol.autoscale(False)
            ##<--[inamura 100726]
            # 現在のY　レンジを取得
            y0, y1 = self.cursol.set_ylim()
            
            if event.ydata-y0 > self.ydata:
                yy0 = self.ydata
                yy1 = event.ydata
            else:
                yy0 = event.ydata
                yy1 = self.ydata
                
            if event.xdata-y0 > self.xdata:
                xx0 = self.xdata
                xx1 = event.xdata
            else:
                xx0 = event.xdata
                xx1 = self.xdata    
            # Y の比率を計算    
            ymin = (yy0-y0)/ (y1-y0)
            ymax = (yy1-y0)/ (y1-y0)

            self.cursol.axvspan(xx0, xx1, ymin=ymin, ymax=ymax, facecolor='w', alpha=0.4)
            # カーソル用サブプロットの座標を消す
            self.cursol.set_xticks([])
            self.cursol.set_yticks([])
            # グラフを再表示              
            self.canvas.draw()
            
        # ドラッグ中でなければ    
        else:
            # マウス位置の検出器ヘッダー情報を表示
            self.UpdateStatusBar(event)         
    
    #########################################
    def OnBtDown(self, event):
        """
        マウス-ボタンクリックイベント処理
        @param   event イベント情報   
        @retval 無し
        """ 
       
        # パン処理中またはズーム処理中であれば、以下の処理を実行しない
        if self.toolbar._active == 'PAN' or self.toolbar._active == 'ZOOM':
            return
        if event.inaxes:
            # ドラッグ開始フラグをセット
            self.dragFlag = True
            # ドラッグ時のカーソル表示用に、開始位置を保存
            self.xdata = event.xdata
            self.ydata = event.ydata
            # クリック位置のPSD-ID を保存
            self.x0, self.y0 = int(event.xdata), int(event.ydata)
        else:
            self.x0 = -1

                
    #########################################
    def OnBtUp(self, event):
        """
        マウス-ボタンアップイベント処理
        @param   event イベント情報   
        @retval 無し
        """ 
        
        # パン処理中またはズーム処理中であれば、以下の処理を実行しない
        if self.toolbar._active == 'PAN' or self.toolbar._active == 'ZOOM':
            return
        # ドラッグ開始時にグラフ外だったか
        if not event.inaxes or self.x0 < 0:
            return
        
        # ドラッグ中であれば
        if self.dragFlag:
            # ドラッグフラグを解除
            self.dragFlag = False
            # ドラッグカーソルを消す
            #self.cursol.clear()             ##[inamura 100726]
            # カーソル用サブプロットの座標を消す
            self.cursol.set_xticks([])
            self.cursol.set_yticks([])
            # グラフを再表示              
            self.canvas.draw()   

        # ボタンアップ時の位置を取得
        x2, y2 = int(event.xdata), int(event.ydata)
        # 始値より小さければ入れ替える
        if self.x0 > x2:
            x1 = x2
            x2 = self.x0
        else:
            x1 = self.x0
            
        if self.y0 < y2:
            y1 = y2
            y2 = self.y0
        else:
            y1 = self.y0    

        #Inamura
        #pixel1 = self.numPixel - y1
        #pixel2= self.numPixel - y2
        pixel1 = self.numPixel - y1 - 1
        pixel2= self.numPixel - y2 - 1
        #--Inamura  
        
        xx = x1
        psi1 = -1
        psi2 = -1
        
        while xx <= x2 :
            # 最も近い PSD 
            if self.hTable[xx] >= 0 and self.do.IsValid(self.hTable[xx]):
                if psi1 < 0:
                    psi1 = self.hTable[xx] 
                    psi2 = self.hTable[xx] 
                else:
                    psi2 = self.hTable[xx]
            xx += 1
        # データ無しか
        if psi1 < 0 :
            self.psdTx0.SetValue("")
            self.psdTx1.SetValue("")
            self.pxTx1.SetValue("")
            self.psdTx2.SetValue("")
            self.pxTx2.SetValue("")
            return

        # 始値のテキストボックスに値を設定    
        strpsd = "%d" % psi1
        strpx = "%d" % pixel1
        self.psdTx0.SetValue(strpsd)
        self.psdTx1.SetValue(strpsd)
        self.pxTx1.SetValue(strpx)
        # ボタン押下時と位置が同じであるなら、ドラッグではなくクリック
        if x1 == x2 and y1 == y2:
            # 終値のテキストボックスをクリア            
            self.psdTx2.SetValue("")
            self.pxTx2.SetValue("")
            ##[inamura 100726]-->
            self.cursol.clear()
            if matplotlib_verNo > 980:
                 self.cursol.autoscale(False)
            self.cursol.set_xticks([])
            self.cursol.set_yticks([])
            self.canvas.draw()
            ##<--[inamura 100726]
        else:
            # 終値のテキストボックスに値を設定
            strpsd = "%d" % psi2
            strpx = "%d" % pixel2
            self.psdTx2.SetValue(strpsd)
            self.pxTx2.SetValue(strpx)
        
    

    #########################################
    def OnBtAppend(self, event):
        """
        Appendボタン押下イベント処理
        @param   event イベント情報   
        @retval 無し
        """ 
        # 個別にデータをプロッタへ追加
        self.AddToPlot(False)

    #########################################
    def OnBtRedraw(self, event):
        """
        指定されたTOFレンジからカウント数を
        再計算し、マップを再表示
        @param   event イベント情報   
        @retval 無し
        """ 
        try:
            try:
                # TOF Range をテキストボックスから取得
                tof1 = float(self.tofTx1.GetValue())
                tof2 = float(self.tofTx2.GetValue())
            except:
                # エラーメッセージを表示   
                raise PlotException('Common','C027',("TOF Range",))
            if tof1 > tof2:
                  raise PlotException('Common','C010',("TOF Range End","TOF Range First"))
            ##[inamura 091114]->
            #if tof1 < 0.0:
            #      raise PlotException('Common','C009',("TOF Range First","0.0"))
            ##<-[inamura 091114]
        except PlotException, ex:
            PlotMessage(self.frame,ex)
            return
        # カーソルを砂時計に変更    
        self.frame.SetCursor(wx.StockCursor(wx.CURSOR_WAIT))    
        # マップデータを再作成    
        self.Z = self.do.RemakeMapData(tof1, tof2, self.hTable)
        # カーソルを戻す   
        self.frame.SetCursor(wx.StockCursor(wx.CURSOR_ARROW))
        
        self.datMax = self.do.GetMax()
        self.zMax = self.datMax
        ##[inamura 100621]-->
        self.datMin = self.do.GetMin()
        if (self.logFlag) and (self.datMin <= 0.0):
             self.zMin = 1.0E-20
        else:
             self.zMin = self.datMin
        
        self.yminTx.SetValue( ("%g" % self.zMin) )
        self.ymaxTx.SetValue( ("%g" % self.zMax) )
        ##<--[inamura 100621]
        
        # マップデータからマスクデータ作成
        self.Zm = ma.masked_where(self.Z >= MASKVALUE, self.Z)
        
        # マップを再描画
        self.PlotChart()    

    ##[inamura 100621]-->
    #########################################
    def OnBtRedrawInt(self, event):
        """
        指定されたIntensityレンジとTOFレンジからカウント数を
        再計算し、マップを再表示
        @param   event イベント情報   
        @retval 無し
        """ 
        try:
            try:
                # TOF Range をテキストボックスから取得
                tof1 = float(self.tofTx1.GetValue())
                tof2 = float(self.tofTx2.GetValue())
                int1 = float(self.yminTx.GetValue())
                int2 = float(self.ymaxTx.GetValue())
            except:
                # エラーメッセージを表示   
                raise PlotException('Common','C027',("TOF Range",))
            if tof1 > tof2:
                  raise PlotException('Common','C010',("TOF Range End","TOF Range First"))

        except PlotException, ex:
            PlotMessage(self.frame,ex)
            return
        # カーソルを砂時計に変更    
        self.frame.SetCursor(wx.StockCursor(wx.CURSOR_WAIT))    
        # マップデータを再作成    
        self.Z = self.do.RemakeMapData(tof1, tof2, self.hTable)
        # カーソルを戻す   
        self.frame.SetCursor(wx.StockCursor(wx.CURSOR_ARROW))

        self.zMin = int1
        self.zMax = int2
        
        # マップデータからマスクデータ作成
        self.Zm = ma.masked_where(self.Z >= MASKVALUE, self.Z)
        
        # マップを再描画
        self.PlotChart()    
    ##<--[inamura 100621]
    #########################################
    def OnBt2dPlot(self, event):
        """
        2次元プロッタボタン押下イベント処理
        @param   event イベント情報   
        @retval 無し
        """
        try:
            try:
                # PSD No. をテキストボックスから取得
                psd = int(self.psdTx0.GetValue())
            except:
                # エラーメッセージを表示   
                raise PlotException('Common','C026',("PSD No.",))
            # PSD No. の入力範囲チェック
            if psd < 0 or psd > self.maxPSD:
                strPSD = "%d" % self.maxPSD
                raise PlotException('Common','C008',("PSD","0",strPSD))  
            # 有効な検出器か
            if not self.do.IsValid(psd):
                # 無効な検出器
                raise PlotException('FastVis','F005',(self.psdTx0.GetValue(),))
            
        except PlotException, ex:
            PlotMessage(self.frame,ex)
            return
        # PSD のデータを取得
        tof, zz, er = self.do.GetPSDArray(psd)
        
        #Inamura
        if tof==None:
            return
        #--Inamrua
        
        # 2次元マップ用のデータ作成    
        x = arange(0, self.numPixel+1, 1)
        X, Y = meshgrid(x, tof)
        map = (zz, er, X, Y)

        # D2 プロッタが表示されているか
        if self.d2 == None:
            # 2Dプロッタフレームクローズイベントのリスナー登録
            IFEvtProp(100).AddListner('2dclosed',  self.OnNotify2DClose)
            self.d2 = D2Vis.MapD2Frame(self.frame , map, 100, "2D TOF Map") 
        else:
            # データ変更
            IFEvtProp(100).NotifyEvent(self, "changedata", map)        

        # タイトルを取得
        runNo = self.do.GetTitle()
        main = "Run No.: " + runNo
        sub = "PSD No.: %d" % psd
            
        # タイトル設定コマンド送信
        IFEvtProp(100).NotifyEvent(self, "title", (main, sub))
        # スケールラベル設定コマンド送信
        IFEvtProp(100).NotifyEvent(self, "scalelabel", ("Pixel No.", "TOF (micro sec)","Neutrons"))  

    #########################################
    def OnBtSumm(self, event):
        """
        Summボタン押下イベント処理
        @param   event イベント情報   
        @retval 無し
        """ 
        # 積算語にデータをプロッタへ追加
        self.AddToPlot(True)
        
    #########################################    
    def AddToPlot(self, sumFlag):
        """
        Append Sum データをプロッタへ追加
        @param   sumFlag True であれば、積算後に追加   
        @retval 無し
        """ 
        try:
            try:
                # 始点のPSD-ID をテキストボックスから取得
                psd1 = int(self.psdTx1.GetValue())
                px1 = int(self.pxTx1.GetValue())
                self.ppsd = psd1
            except:
                # エラーメッセージを表示   
                raise PlotException('Common','C026',("PSD No. and Pixel No."))
         
            try:
                # 終点のPSD-ID をテキストボックスから取得
                psd2 = int(self.psdTx2.GetValue())
                px2 = int(self.pxTx2.GetValue())
            except:
                # 終点が空白であれば、始点=終点とする
                psd2 = psd1
                px2 = px1
                # 終点テキストボックスをクリアする
                self.psdTx2.SetValue("")
                self.pxTx2.SetValue("")

            # PSD No. の入力範囲チェック
            if psd1 < 0 or psd1 > self.maxPSD or psd2 < 0 or psd2 > self.maxPSD:
                strPSD = "%d" % self.maxPSD
                raise PlotException('Common','C008',("PSD","0",strPSD))    
            # Pixel No. の入力範囲チェック
            if px1 < 0 or px1 >= self.numPixel or px2 < 0 or px2 >= self.numPixel:
                strPx = "%d" % (self.numPixel-1)
                raise PlotException('Common','C008',("Pixel","0",strPx)) 
                    
        except PlotException, ex:
            PlotMessage(self.frame,ex)
            return    

        # 逆転していたなら
        if psd1 > psd2:
            # 入れ替え
            tmp = psd1
            psd1 = psd2
            psd2 = tmp
        # 逆転していたなら
        if px1 > px2:
            # 入れ替え
            tmp = px1
            px1 = px2
            px2 = tmp
        
        # PSD-ID を格納するリストを準備(積算用)
        lstSum = []
        # ヒストグラム を格納するリストを準備
        datList = []
        
        ##[inamura 120115]-->
        Xaxis = self.cbXax.GetSelection() 
        print "Xaxis=",Xaxis
        if Xaxis==-1:
            Xaxis=0
        if Xaxis==0:
            # PSD No. の範囲を繰り返す
            while psd1 <= psd2:
                # 検出器は有効か
                if psd1 in self.hTable and self.do.IsValid(psd1):
                    px = px1
                    # ピクセル範囲を繰り返す
                    while px <= px2:
                        # 積算ならば 
                        if sumFlag:
                            # 積算用PSD-ID リストに追加
                            lstSum.append((psd1, px)) 
                        else:
                            # 個別であれば、ヒストグラムをデータリストに追加
                            dat = self.do.GetHistogram(psd1, px)
                            datList.append(dat) 
                            
                        px +=1
                psd1 +=1
            try:
                # 範囲内に有効なPSDがなければ
                if len(datList) == 0 and len(lstSum) == 0 :
                    raise PlotException('FastVis','F004',()) 
            except PlotException, ex:
                PlotMessage(self.frame,ex)
                return    
        
            # 積算ならば    
            if sumFlag:
                # PSD-ID のリストを渡して積算データを取得
                dat = self.do.IntegrateHistogram(lstSum)
                datList.append(dat)
                
        elif Xaxis==1: ## along PSD
            if sumFlag:
                psdRange=[ psd1,psd2 ]
                pixRange=[ px1, px2 ]
                datList.append( self.do.GetLineFromIntensities(psdRange,pixRange,"PSD") )
            else:
                for p in range(px1,(px2+1)):
                    psdRange = [psd1,psd2 ]
                    pixRange = [ p, p ]
                    datList.append( self.do.GetLineFromIntensities(psdRange,pixRange,"PSD") )

        elif Xaxis==2: ## along Pixel
            if sumFlag:
                psdRange=[ psd1,psd2 ]
                pixRange=[ px1, px2 ]
                datList.append( self.do.GetLineFromIntensities(psdRange,pixRange,"PIXEL") )
            else:
                for p in range(psd1,(psd2+1)):
                    psdRange = [ p, p ]
                    pixRange = [ px1,px2 ]
                    datList.append( self.do.GetLineFromIntensities(psdRange,pixRange,"PIXEL") )
        else:
            pass
        ##<--[inamura 120115]
        # 選択中のプロッタがあれば
        if not self.plot == None:
            # データ追加要求イベント発行
            IFEvtProp(self.plot[1]).NotifyEvent(self, "add", datList)
        else:
            self.psd1 = psd1
            # 選択中のプロッタが無い場合は、新規にプロッタを追加
            self.OnNewPlot(data = datList)
   

    ##############################################
    def OnNewPlot(self, evt=None, data = None):
        """
        新規プロッタの作成
        カレントプロッタの切替
        @param  evt 　イベント
        @param  data ヒストグラムデータ
        @retval 無し
        """     
        # 選択中のプロッタがあれば
        if not self.plot == None:
            # プロッタのアイコン化要求イベント発行
            IFEvtProp(self.plot[1]).NotifyEvent(self, "doiconize", True)

        # プロッタ番号をインクリメント
        self.order  += 1
        
        # プロッタフレームクローズイベントのリスナー登録
        IFEvtProp(self.order).AddListner('plotclose',  self.OnNotifyPlotClose)
        # プロッタフレームアイコン化イベントのリスナー登録
        IFEvtProp(self.order).AddListner('ploticonized',  self.OnNotifyPlotIconized)
        
        # 新しいプロッタウィンドウを開く
        pi = PlotFrame(self.frame, data, self.order)
        self.plot = [pi, self.order]

        # プロッタ一覧に加える文字列を作成
        strPlot = " Plotter(%d)" % self.order
        # プロッタリストに追加
        self.plots.append(self.plot)
        
        # タイトルを取得
        runNo = self.do.GetTitle()
        main = "Run No.: " + runNo
            
        # タイトル設定コマンド送信
        IFEvtProp(self.order).NotifyEvent(self, "title", (main,"*"))
        
        # 表示リストに追加
        self.plist.Append(strPlot)
        # 追加したプロッタを選択状態にする
        pno = len(self.plots)
        self.plist.SetSelection(pno-1) 

    ##############################################    
    def OnListSelect(self, evt):
        """
        リスト選択イベント処理関数
        カレントプロッタの切替
        @param  evt 　イベント
        @retval 無し
        """
        # 選択消失イベントか 2009.05.07 Minakawa Add
        if evt.GetSelection() < 0:
             return
        
        # 選択中のプロッタがあれば
        if not self.plot == None:
            # プロッタのアイコン化要求イベント発行
            IFEvtProp(self.plot[1]).NotifyEvent(self, "doiconize", True) 
               
        # 選択されたプロッタのインスタンスをカレントプロッタとする
        self.plot = self.plots[evt.GetSelection()]
        # プロッタ復元要求イベント発行
        IFEvtProp(self.plot[1]).NotifyEvent(self, "doiconize", False) 

    ##############################################
    def OnLog(self, evt):
        """
        ログメニューイベント処理関数
        ログとリニアのモード切替
        @param  evt 　イベント
        @retval 無し
        """     
        # メニューのチェックを取得し、ログフラグに設定
        self.logFlag = evt.IsChecked()
        ##[inamura 100621]-->
        if self.logFlag:
             if self.zMin <= 0.0:
                  self.zMin = 1.0E-20
        else:
             self.zMin = self.datMin

        self.yminTx.SetValue( ("%g" % self.zMin) )
        ##<--[inamura 100621]
        # マップの再描画
        self.PlotChart()

    ##############################################    
    def OnSlider(self, evt):
        """
        スライダーイベント処理関数
        Z 軸範囲を変更(拡大)
        @param  evt 　イベント
        @retval 無し
        """     
        # スライダーの最大値を取得
        max = self.slider.GetMax()
        # 現在値を取得し、割合に変換
        svalue = max - self.slider.GetValue() + 1
        
        # ログスケールか
        if self.logFlag:
#            self.zMax = self.datMax * log10(svalue) / max
            ##[inamura 100621]-->
            #self.zMax = self.datMax * svalue / max
            if self.datMin <= 0.0:
                 self.zMin = 1.0E-20
            self.zMax = (self.datMax - self.zMin) * svalue / max
            ##<--[inamura 100621]
        # リニアスケール
        else:
            ##[inamura 100621]-->
            #self.zMax = self.datMax * svalue / max
            self.zMax = (self.datMax - self.datMin) * svalue / max
        #if self.zMax < 10.0:
        #    self.zMax = 10.0
            ##<--[inamura 100621]
        # マップの再描画
        ##[inamura 100621]-->
        self.yminTx.SetValue( ("%d" % self.zMin) )
        self.ymaxTx.SetValue( ("%d" % self.zMax) )
        ##<--[inamura 100621]
        self.PlotChart()
        
    #####################################################
    def OnNotifyPlotClose(self, wid, evt, value=None):
        """
        プロッタクローズイベント対応処理
        @param  wid 　 イベント発生元のインスタンス
        @param  evt 　イベントの種類
        @param  value  無し   
        @retval 無し
        """ 
        i = 0
        # インスタンスリストから、クローズしたプロッタを検索
        for pl in self.plots:
            if pl[0] == wid:
               # I/F をクリア 
               IFEvtProp(i+1).InitIF() 
               # インスタンスリストから削除 
               del self.plots[i]
               # 表示リストから削除
               self.plist.Delete(i)
               # クローズしたプロッタがカレントだったなら
               if wid == self.plot[0]:
                   
                   # カレントプロッタを変更
                   pno = len(self.plots)
                   # 他に開いているプロッタがあれば
                   if pno > 0:
                       # リストの最後のプロッタをカレントプロッタとする
                       self.plot = self.plots[pno-1]
                       self.plist.SetSelection(pno-1)
                       # プロッタ復元要求イベント発行
                       IFEvtProp(self.plot[1]).NotifyEvent(self, "doiconize", False) 
                   # 全部のプロッタがクローズされたなら    
                   else:
                       # カレントプロッタ無しとする
                       self.plot = None
                   
               break     
            i +=1

    ###################################################            
    def OnNotifyPlotIconized(self, wid, evt, flag):
        """
        プロッタアイコン化イベント対応処理
        @param  wid 　 イベント発生元のインスタンス
        @param  evt 　イベントの種類
        @param  flag  アイコン化フラグ   
        @retval 無し
        """ 
        i = 0
        # インスタンスリストから、イベントの発生したプロッタを検索
        for pl in self.plots:
            # イベント発生元と同じインスタンスか
            if pl[0] == wid:
                strP = self.plist.GetString(i)
                # アイコン化されたのか
                if flag:
                    # 表示中のリストにアイコン化文字列を付加
                    self.plist.SetString(i, strP+" - Iconized")
                # 復元であれば
                else:
                    # アイコン化文字列を消す
                    self.plist.SetString(i, strP[:-11])
                break
            i +=1          

    ######################################################
    def OnPrint(self,*args):
        """
        Print メニューイベント処理
        print コマンド処理
        印刷ダイアログを表示
        @param  *args イベント情報
        @retval 無し
        """ 
        # プラットフォームを判定     
        if os.name == "posix" or os.name == "mac" :
            # Linux または Mac OS なら
            # 現在の時間よりテンポラリファイル名を作成
            tsec = int(time.time()*10.0)
            tmpf = "map%d.ps" % tsec

            try:
                try:
                    # ポストスクリプトファイルを作成
                    self.canvas.print_figure(tmpf, dpi=600, orientation="landscape")
                except:
                    raise PlotException('Common','C018',(tmpf,))
                # スプーラにファイルを送信
                strCmd = "lpr %s" % tmpf
                ret = os.system(strCmd)
                # エラーがあったなら

                if ret > 0:
                    # エラーメッセージを表示
                    raise PlotException('Common','C023',())
                
            except PlotException, ex:
                PlotMessage(self.frame,ex)
            
        # Linux または Mac OS 以外(Windowsを想定)
        else:
            # 現在の解像度を取得
            dpi = self.canvas.figure.dpi.get()
            # 印刷用に解像度を高くする
            self.canvas.figure.dpi.set(160)
            #用紙をA4に設定
            self.canvas.printerData.SetPaperId(wx.PAPER_A4)
            # 用紙を横方向に設定
            self.canvas.printerData.SetOrientation(wx.LANDSCAPE)
            # マージンを設定
            self.canvas.printer_margin = 1.0
            # 印刷ダイアログを表示

            self.canvas.Printer_Print()
            # 解像度を元に戻す
            self.canvas.figure.dpi.set(dpi)
            # 再描画
            self.canvas.draw()
            
    ######################################################
    def OnSave(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.parent.frame,ex)
    
    #########################################
    def OnNotify2DClose(self, *args):
        """
        2Dプロッタクローズイベント受信処理
        @param *args　　イベント
        @retval 無し
        """
        # I/F をクリア 
        IFEvtProp(100).InitIF()
        self.d2 = None
                        
    ##############################################        
    def OnClose(self, evt=None):
        """
        デテクタマップ画面クローズ
        @param  evt 　イベント
        @retval 無し
        """
        # 印刷に使用したテンポラリファイルのリストを取得
        tmpfiles = glob.glob("map*.ps")
        # テンポラリファイルを削除
        for tmpf in tmpfiles:
            try:
                # ファイルを削除
                os.remove(tmpf)
            except:
                # 削除 できなかったら(スプーラが使用中?)、次回に削除
                pass
        # メッセージの解放 
        MessageFile().CloseDoc()
        
        # ---> 2008/04/27 Minakawa add
        # 全 1D Plotter のI/F をクリア 
        for i in range(len(self.plots)):
            IFEvtProp(i+1).InitIF()
        # 2Dプロッタが開いているなら
        if self.d2 != None:
            # 2Dプロッタのクローズ要求を出す(孫画面のI/F をクリアさせるため)　
            IFEvtProp(100).NotifyEvent(self, "close")
        # 自分のI/F をクリア
        IFEvtProp(0).InitIF()
        # <--- 2008/04/27 Minakawa add
        
        # 検出器マップ画面のクローズ
        self.frame.Destroy() 
        
#######################################
#  DetectMap
#######################################  
class DetectMap(object):
    """
    Application Class 
    """
    #########################################
    def __init__(self, matrix=None):
        """
        アプリケーションスタート
        @param  matrix  エレメントコンテナマトリックス
        @retval 無し
        """ 
        app = wx.App()
        try:
            if matrix == None:
                raise PlotException('FastVis','F002',())

        except PlotException, ex:
            PlotMessage(None,ex)
        else:    
            
            fig = MapFrame(None, matrix)
            app.MainLoop()


###################################       
if __name__ == '__main__':
    pass
   


