from __future__ import print_function

import Manyo
import Manyo.MLF as mm
import Manyo.Utsusemi as mu
import Manyo.SAS as ms
import utsusemi.ana.Reduction.BaseCommands as BC
import utsusemi.SAS.ana.Reduction.CorrBaseCommands as CBC
from utsusemi.SAS.ana.Reduction.SASUtils import SASBankDic

import os
import glob

"""
Base Functions for SAS
Hist.py
- GetHistogramSAS
- GetMonHistSAS
- GetPulseHeightSAS
- GetMonHistByPhSAS
- MergeSMSC4DetMap

"""
########################################
def CheckT0bUpdate(runNo):
    """
    """
    # <-- TI [20140403]
    sys_name = mu.UtsusemiEnvGetInstCode()
    edb_base_dirs = []
    path_tmpl = os.path.join(mu.UtsusemiEnvGetInstDataDir(), sys_name+"%0d")
    for i in range(0,100):
        if os.path.exists( path_tmpl%(i) ):
            edb_base_dirs.append( path_tmpl%(i) )
    #edb_base_dirs = [os.path.join(os.environ['UTSUSEMI_DATA_DIR'], sys_name),
    #                 os.path.join(os.environ['UTSUSEMI_DATA_DIR'], sys_name+"00")]
    t0b_dir = os.path.join(mu.UtsusemiEnvGetUserDir(), 'ana', 'tmp')
    t0b_template = '%s%06d_??_???_???.t0b'%(sys_name, runNo)
    t0b_list = glob.glob(os.path.join(t0b_dir, t0b_template))
    for edb_base_dir in edb_base_dirs:
        edb_dir_candidates = glob.glob(os.path.join(edb_base_dir, '%s%06d_????????'%(sys_name, runNo)))
        if len(edb_dir_candidates) == 0:
            #raise UserWarning, "edb not fount"  ## [20150311]YI -->
            pass
        else:
            edb_dir_candidates.sort()
            edb_dir = edb_dir_candidates[-1]
            for t0b in t0b_list:
                edb_template = os.path.join(edb_dir, '%s_???.edb'%(os.path.basename(t0b)[:-8]))
                edb_list = glob.glob(edb_template)
                if len(edb_list)==0:
                    continue
                edb_list.sort()
                edb = edb_list[-1]
                t0b_stat = os.stat(t0b)
                edb_stat = os.stat(edb)
                if t0b_stat.st_mtime <= edb_stat.st_mtime:
                    os.system("rm %s"%t0b)
    ## <-- [20150311]YI
    # --> TI [20140403]

########################################
def GetHistogramBaseSAS( runNo="0", Xrange="0.7 7.6 0.1 dL", Bank="SM", TimeSlice="-1 -1", frameBoundary="0.0", isTimeFoc=False, SolAngCor=True, paramFiles="- -", isPH=False, PHrange="0 4096" ):
    """
    Base Function to Load EventData to produce histogram for SAS
    GetHistogramBaseSAS( runNo=0, Xrange="0.7 7.6 0.1 dL", Bank="SM", TimeSlice="-1 -1", frameBoundary="0.0", isTimeFoc=False, SolAngCor=True, paramFiles="- -", isPH=False, PHrange="0 4096" )

    @param runNo     (string)     Run Number
    @param Xrange    (string)  "startX endX widthX type" separated with space (not comma) : type=[dL, dL/L, tof, d, rd, ene]
    @param Bank      (string)  "SM"...  Monitors by "MON1" or "MON2"
    @param TimeSlice (string)  "startTime endTime" separated with space: "-1 -1" means no-setting.
    @param frameBoundary (string) "frameBoundary" or "frameBoundary TofMask_min TofMask_max"
    @param isTimeFoc (bool)    True or False
    @param SolAngCor  (bool)    True or False for Solid Angle Correction
    @param paramFiles (string) "WiringInfo DetectorInfo"
    @param isPH (bool)
    @param PHrange (string)
    @retval DAT (ElementContainerMatrix)
    """

    ## Check Bank
    detType=""
    mode_no=0 #"PSD"
    #RPMT_PARAM=[128, 1024, 128, 1024, 32] #[<LLD_X>,<HLD_X>,<LLD_Y>,<HLD_Y>,<LmtCoi>]
    RPMT_LLDHLD = [0, 0, 0, 0] #[<LLD_X>,<HLD_X>,<LLD_Y>,<HLD_Y>]
    RPMT_COI = 32 #<LmtCoi>
    if Bank == "RPMTo":
        detType="RPMTo"
        mode_no=3
    elif Bank == "MON1":
        detType="N2MON1"
        mode_no=1
    elif Bank == "MON2":
        detType="N2MON2"
        mode_no=2
    elif Bank == "MON3":
        detType="N2MON3"
        mode_no=4
    elif Bank.find("RPMT")==0: #RPMT,<LLD_X>,<HLD_X>,<LLD_Y>,<HLD_Y>,<LmtCoi>
        detType="PSD"
        mode_no=5
        rpmt_params=Bank.split(",")
        if len(rpmt_params)>1:
            RPMT_LLDHLD[0] = int(rpmt_params[1])
        if len(rpmt_params)>2:
            RPMT_LLDHLD[1] = int(rpmt_params[2])
        if len(rpmt_params)>3:
            RPMT_LLDHLD[2] = int(rpmt_params[3])
        if len(rpmt_params)>4:
            RPMT_LLDHLD[3] = int(rpmt_params[4])
        if len(rpmt_params)>5:
            RPMT_LLDHLD[4] = int(rpmt_params[5])
        if len(rpmt_params)>6:
            RPMT_COI = int(rpmt_params[6])
    elif Bank in list(SASBankDic.keys()):
        detType="PSD"
        mode_no=0
    elif Bank.upper().strip()=="ALL":
        detType="PSD"
        mode_no=0
    else:
        banks = Bank.split(" ")
        tmpBank = ""
        for a_bank in banks:
            if a_bank!="" or a_bank!=" ":
                num_of_pixels = ""
                ind_deli = a_bank.find(":")
                if ind_deli>0:
                    num_of_pixels = a_bank[ind_deli:]
                    a_bank=a_bank[:ind_deli]
                if a_bank=="SM":
                    tmpBank += "SMBL14"+num_of_pixels+","+"SMBL16"+num_of_pixels+","
                elif a_bank in SASBankDic:
                    tmpBank += (a_bank+num_of_pixels+",")
                else:
                    pass
        if tmpBank!="":
            Bank = tmpBank[:-1]
            detType="PSD"
            mode_no=0
        else:
            raise UserWarning("Bank info is invalid. ["+Bank+"]")

    if isPH:
        if PHrange!="":
            ph_range_list = PHrange.split(" ")
            detType+="-PH[%d:%d]"%(int(ph_range_list[0]),int(ph_range_list[1]))
        else:
            detType+="-PH"

    if Bank=="":
        raise UserWarning("Bank is invalid.")
    else:
        print("========[ Bank = %s ]"%(Bank))
    ## If paramFiles is given.(Not Work, under construction)
    wfile_found_path=""
    dfile_found_path=""
    cfile_found_path=""
    if paramFiles!="- -":
        param_files_list = paramFiles.split(" ")
        if len(param_files_list)>=2:
            if param_files_list[0]!="-":
                wfile_found_path = mu.FindParamFilePath( param_files_list[0] )
                if wfile_found_path=="":
                    raise UserWarning("Given WiringInfo is not found.(%s)"%(param_files_list[0]))
            if param_files_list[1]!="-":
                dfile_found_path = mu.FindParamFilePath( param_files_list[1] )
                if dfile_found_path=="":
                    raise UserWarning("Given DetectorInfo is not found.(%s)"%(param_files_list[1]))
        if len(param_files_list)>=3:
            cfile_found_path = mu.FindParamFilePath( param_files_list[2] )
            if cfile_found_path=="":
                raise UserWarning("Given CaseInfo is not found.(%s)"%(param_files_list[2]))

    ## Check Time Slice
    TimeSliceList=TimeSlice.split(" ")
    time_range=[]
    for ts in TimeSliceList:
        if ts!="":
            time_range.append( float(ts) )

    ## Check Frame Boundary
    frame_bound_list = frameBoundary.split(" ")
    if (len(frame_bound_list)!=1) and (len(frame_bound_list)!=3):
        raise UserWarning("Frame Boundary argument is invalid.")
    frameBoundary_val = ""
    if (frame_bound_list[0]!="0.0"):
        ind = frame_bound_list[0].find(":")
        if (ind<0):
            frameBoundary_val = "2,%s"%frame_bound_list[0] # TOF boundary
        else:
            frameBoundary_val = frame_bound_list[0]        # Lambda or Energy boundary

    #if (frameBoundary_val!=0.0):
    #    mpf.EDW.set_FrameInfo(frameNo=2, boundary=frameBoundary_val )

    ## set tof mask region
    mask_region = ""
    if (len(frame_bound_list)==3):
        mask_region = "%f-%f"%(float(frame_bound_list[1]),float(frame_bound_list[2]))

    ## Make RunNo List
    if type(runNo)==str:
        runNo_list = runNo.split(" ")
        if len(runNo_list)==0:
            raise UserWarning("runNos are invalid")
    elif type(runNo)==int:
        runNo_list = [ str(runNo) ]

    ## Check T0b
    runNo = ""
    for a_runNo in runNo_list:
        CheckT0bUpdate(int(a_runNo))
        runNo += a_runNo+","
        if mode_no==5:
            DaqId = 13 #Default
            ind = Bank.find(":")
            if ind>0:
                DaqId=int(Bank[ind+1:])
            #ConvertFromRPMTK2Psd( int(a_runNo), DaqId, 0, "SAS03")
            ConvertFromRPMTK2Psd(int(a_runNo), DaqId, 0, "SAS03", mode_no, RPMT_LLDHLD, RPMT_COI, dfile_found_path)
    runNo = runNo[:-1]

    ## Make Parameter File to Create Histogram
    GNH = mu.UtsusemiGetNeunetHistogram()

    if GNH.SetRunNo( runNo, wfile_found_path, dfile_found_path, str(mode_no) ):
        pass
    else:
        raise UserWarning("")

    if cfile_found_path!="":
        if GNH.SetCaseInfo(cfile_found_path):
            pass
        else:
            raise UserWarning("CaseInfo is not invalid.")

    conv_params=""
    p_list=Xrange.split(" ")
    if len(p_list)!=4:
        raise UserWarning("param error")
    AxType=p_list[3].lower()
    if AxType=="dl":
        conv_params="lambda,%g,%g,%g"%(float(p_list[0]),float(p_list[1]),float(p_list[2]))
    elif AxType=="dl/l":
        conv_params="rlambda,%g,%g,%g"%(float(p_list[0]),float(p_list[1]),float(p_list[2]))
    elif AxType=="tof":
        conv_params="tof,%g,%g,%g"%(float(p_list[0]),float(p_list[1]),float(p_list[2]))
    elif AxType=="d":
        conv_params="d,%g,%g,%g"%(float(p_list[0]),float(p_list[1]),float(p_list[2]))
    elif AxType == "rd":
        conv_params="rd,%g,%g,%g"%(float(p_list[0]),float(p_list[1]),float(p_list[2]))
    elif AxType=="ene":
        conv_params="energy,%g,%g,%g"%(float(p_list[0]),float(p_list[1]),float(p_list[2]))
    else:
        raise UserWarning("param error about conv type ({})".format(AxType))

    #print( "Conv Params="+conv_params )
    #print( "DetType="+detType )
    #print( "Bank="+Bank )

    if not GNH.SetConversionParameter( conv_params ):
        raise UserWarning("Conv_params is invalid."+conv_params)

    if not GNH.SetDetParam( detType ):
        if detType!="RPMTo":
            raise UserWarning("DetType is invalid."+detType)

    if mode_no==0:
        GNH.SetDetRange( Bank )

    ## Because T0-ID of NEUNNET is different with monitor(GateNET) or RPMT.
    if mode_no==0:
        GNH.SetFlagOfPulseIdCheck(True)
    else:
        GNH.SetFlagOfPulseIdCheck(False)

    GNH.SetFlagToAddTofBin(True)
    #if frameBoundary_val!=0.0:
    #    GNH.SetFrameInfo( "2,%g"%(frameBoundary_val) )
    if frameBoundary_val!="":
        GNH.SetFrameInfo( frameBoundary_val )
        print("python >> ------------ NEW SetFrameInfo")

    if mask_region!="":
        GNH.SetMaskInfo("NoFile,"+mask_region)

    ## Create Histograms
    data_base_dir = mu.UtsusemiEnvGetDataDir()
    if detType!="RPMTo": ## Neunet series
        print("---- Histogram Create ----")
        dat_list = []
        if len(time_range)==2:
            GNH.SetTimeRange("%g,%g"%(time_range[0],time_range[1]))

        #the path of converted data for RPMT is different from that of original data,
        if mode_no==5:
            mu.UtsusemiClearRunDataPathDict()
        if not GNH.LoadEventDataFiles( data_base_dir, "" ):
            msg = " LoadEventDataFiles failed."
            raise UserWarning(msg)
        v_cases = GNH.PutListOfCases()
        # print("#[inamura 220310] cases.size()={}".format(v_cases.size()))
        caselist = []
        if v_cases.size()==0:
            caselist = [1]
        else:
            for i in range(v_cases.size()):
                caselist.append( v_cases[i] )
        for caseId in caselist:
            dat = Manyo.ElementContainerMatrix()
            if not GNH.SetElementContainerMatrix( dat, caseId ):
                msg = " SetElementContainerMatrix failed."
                raise UserWarning(msg)
            if mode_no == 5:
                # add periods infor of multi-runNos
                periods = Manyo.MakeDoubleVector()
                for a_runNo in runNo_list:
                    v_runno = mu.FindRunDataFolders(int(a_runNo))
                    target = "SAS{:06d}_10_254_000.edb".format(int(a_runNo))
                    for k in range(v_runno.size()):
                        fname = os.path.join(v_runno[k], target)
                        print("#[inamura 230531] fname={}".format(fname))
                        if os.path.exists(fname):
                            TT = mu.T0TreatToolsNeunet()
                            TT.readOrgEvent(fname)
                            a_period = TT.putMeasPeriodFromT0()
                            del TT
                            for l in range(a_period.size()):
                                periods.append(a_period[l])
                dat.PutHeaderPointer().OverWrite(mu.UTSUSEMI_KEY_HEAD_MEASPERIOD, periods)
            dat_list.append(dat)
    else:
        pfiles=GNH.MakeTempInfoFiles()
        dat = GetHistogramRPMT( runNo, pfiles[0], pfiles[1], time_range )
        dat_list.append(dat)
    del GNH

    ## Create Lambda Vector for each EC
    for dat in dat_list:
        tt1 = ms.CreateLambVector( dat )
        tt1.Execute()
        del tt1

    ## Convertion from histogram to per_unit
    for dat in dat_list:
        tt2 = ms.ConvertToPoint(dat)
        tt2.Execute()
        del tt2

    ## Solid angle correction
    if (SolAngCor):
        for dat in dat_list:
            for i in range(dat.PutSize()):
                if (dat(i).PutHeaderPointer().PutString("TYPE")=="PSD"):
                    for j in range( dat(i).PutSize() ):
                        ec = dat(i,j)
                        sa = ec.PutHeaderPointer().PutDouble("PixelSolidAngle")
                        if sa==0.0:
                            raise UserWarning("Solid angle = 0 at %d,%d"%(i,j))
                        else:
                            ec.MulMySelf(1.0/sa)

            p_chk = mu.UtsusemiCheckDataProcess()
            p_chk.AddProcess( dat, "SolidAngleCorrection" )
            del p_chk

    if len(dat_list)==1:
        return dat_list[0]
    return dat_list

########################################
def GetHistogramRPMT( runNo, wfile, dfile, timeslice=[] ):
    """
    Load EventData to produce histogram
    GetHistogramSAS( runNo=0, AxType="lambda", Xrange="0.7 7.7 0.05", Bank="SM", TimeSlice="-1 -1", frameBoundary=0.0, isTimeFoc=False )

    @param runNo     (int)     Run Number
    @retval DAT (ElementContainerMatrix)
    """

    dataPath = mu.UtsusemiEnvGetDataDir()
    t0Path = ""

    if type(runNo)==int:
        runNo_list = [ str(runNo) ]
    elif type(runNo)==str:
        runNo_list = runNo.split(" ")
        if len(runNo_list)==0:
            raise UserWarning("RunNo is invalid")
    else:
        raise UserWarning("RunNo is invalid")

    v_runNo = Manyo.MakeUInt4Vector()
    for a_runNo in runNo_list:
        v_runNo.append( int(a_runNo) )

    tt=mu.UtsusemiEventDataConverterRPMT()
    tt.LoadParamFiles( wfile, dfile )
    tt.SetHistAllocation()

    dat=Manyo.ElementContainerMatrix()
    tt.SetElementContainerMatrix( dat, v_runNo, dataPath, t0Path )

    Phi=mu.PhiCalculation(dat,0.2,0.2,0.2)
    Phi.CalcPhi()
    del Phi

    dat2 = Manyo.ElementContainerMatrix(dat.PutHeader())
    hh_dat2 = dat2.PutHeaderPointer()

    vid = Manyo.MakeInt4Vector()
    vid.push_back(SASBankDic["RPMT"])
    vnm = Manyo.MakeStringVector()
    vnm.push_back("RPMT")
    vbs = Manyo.MakeInt4Vector()
    vbs.push_back(820)

    hh_dat2.Add("BANKIDLIST", vid )
    hh_dat2.Add("BANKNAMELIST", vnm )
    hh_dat2.Add("BANKSIZELIST", vbs )

    num_of_eca = dat.PutSize()
    for i in range(num_of_eca):
        eca = dat(num_of_eca-1-i)

        hh = eca.PutHeader()
        #DETID=hh.PutInt4("DETID")
        #hh.OverWrite("DETID", num_of_eca-1-DETID)
        hh.Add("BANKID",SASBankDic["RPMT"])
        hh.Add("INDEXINBANK", i )
        eca2 = Manyo.ElementContainerArray(hh)
        num_of_ec = eca.PutSize()
        for j in range(num_of_ec):
            eca2.Add( eca(num_of_ec-1-j) )
        dat2.Add(eca2)
        """
        hh = eca.PutHeaderPointer()
        hh.Add("BANKID",SASBankDic["RPMT"])
        hh.Add("INDEXINBANK", i )
        dat2.Add(eca)
        """
    for i in range(520):
        eca2 = Manyo.ElementContainerArray()
        eca2.AddToHeader("DETID", i+520 )
        eca2.AddToHeader("MASKED",1 )
        dat2.Add(eca2)
    return dat2

########################################
def GetHistogramSAS( runNo=0, Xrange="0.7 7.6 0.1 dL", Bank="SM", TimeSlice="-1 -1", frameBoundary="0.0", isTimeFoc=False, SolAngCor=True, paramFiles="- -" ):
    """
    Load EventData to produce histogram
    GetHistogramSAS( runNo=0, AxType="lambda", Xrange="0.7 7.7 0.05", Bank="SM", TimeSlice="-1 -1", frameBoundary=0.0, isTimeFoc=False )

    @param runNo     (int)     Run Number
    @param Xrange    (string)  "startX endX widthX type" separated with space (not comma) : type=[dL, dL/L, tof]
    @param Bank      (string)  "SM"...  Monitors by "MON1" or "MON2"
    @param TimeSlice (string)  "startTime endTime" separated with space: "-1 -1" means no-setting.
    @param frameBoundary (string) "frameBoundary" or "frameBoundary TofMask_min TofMask_max"
    @param isTimeFoc (bool)    True or False
    @param SolAngCor  (bool)    True or False for Solid Angle Correction
    @param paramFiles (string) "WiringInfo DetectorInfo"
    @retval DAT (ElementContainerMatrix)
    """
    return GetHistogramBaseSAS( runNo, Xrange, Bank, TimeSlice, frameBoundary, isTimeFoc, SolAngCor, paramFiles, isPH=False, PHrange="" )

########################################
def GetMonHistSAS( runNo="0", MonNo=1, AxType="lambda", Xrange="0.7 7.6 0.1", MonIndex=0, TimeSlice="-1 -1", frameBoundary="0.0", CalibEffi=True, RPMTarea="150 150 152 152", RPMTeffiParam="0.10516 0.04838", paramFiles="- -" ):
    """
    Load EventData to produce histogram of monitors
    GetMonHistSAS( runNo="0", MonNo=1, AxType="lambda", Xrange="0.7 7.7 0.05", MonIndex=0, TimeSlice="-1 -1", frameBoundary="0.0", CalibEffi=True, RPMTarea="150 150 152 152", RPMTeffiParam="0.10516 0.04838" )

    @param runNo     (string)     Run Number
    @param MonNo     (int)     Monitor Number 1 (up-stream), 2 (down-stream), 3 or 10
    @param AxType    (string)  Type must be "tof', "lambda", "lamda2", "d" or "rd"
    @param Xrange    (string)  "startX endX widthX" separated with space (not comma)
    @param MonIndex  (int)
    @param TimeSlice (string)  "startTime endTime" separated with space: "-1 -1" means no-setting.
    @param frameBoundary (string) "frameBoundary" or "frameBoundary TofMask_min TofMask_max"
    @param CalibEffi (bool)    Monitor-detector efficiency calibration
    @param RPMTarea  (string)  Summation area of RPMT
    @param RPMTeffiParam (string) Efficiency parameters alpha and beta for RPMT
    @param paramFiles (stirng) "<wiringinfo> <detectroinfo>[ <caseinfo>]"
    @retval EC (ElementContainer)
    """

    Bank=""
    if MonNo==1:
        Bank="MON1"
    elif MonNo==2:
        Bank="MON2"
    elif MonNo==3:
        Bank="MON3"
    elif MonNo==10:
        Bank="RPMT"
    else:
        raise UserWarning("MonNo is invalid")

    ax_axis=AxType.lower()
    if ax_axis=="tof":
        Xrange += " tof"
    elif ax_axis=="lambda":
        Xrange += " dl"
    elif ax_axis=="lambda2":
        Xrange += " dl/l"
    elif ax_axis=="d":
        Xrange += " d"
    elif ax_axis=="rd":
        Xrange += " rd"
    else:
        raise UserWarning("AxType is invalid %s"%(AxType))

    dat_list = GetHistogramBaseSAS( runNo, Xrange, Bank, TimeSlice, frameBoundary, isTimeFoc=False, SolAngCor=False, paramFiles=paramFiles, isPH=False, PHrange="" )

    if type(dat_list)!=list:
        dat_list = [dat_list]
    ec_list = []
    for dat in dat_list:
        if Bank=="RPMT":
            eff_ab = RPMTeffiParam.split(" ")
            try:
                alpha = float(eff_ab[0])
                beta = float(eff_ab[1])
            except:
                raise UserWarning("RPMTeffiParam is invalid (%s)"%(eff_ab))
            if (CalibEffi):
                CBC.CorrectDetEffiRPMT( dat, alpha, beta )
            #return GetSumPixelArea( dat, RPMTarea )
            ec_list.append(GetSumPixelArea( dat, RPMTarea ))

        else:
            ec = Manyo.ElementContainer( dat.Put(MonIndex).Put(0) )
            #key_kc = "KICKERCOUNT"
            #kick_count = dat.PutHeader().PutInt4(key_kc)
            #ec.AddToHeader(key_kc,kick_count)
            ec.InputHeader( dat.PutHeader() )

            # Monitor Detector Efficienty Calibration
            if (CalibEffi):
                p_N2 = 0.465  #[atm]
                t_Mon = 12   # thickness of monitor [mm]
                t_Al  = 0.5  # thickness of Al window [mm]

                dec = ms.DetectorEffiCorrection()
                dec.N2MonEffiCorrection( ec, p_N2, t_Mon, t_Al )
                del dec
            #del dat
            #return ec
            ec_list.append(ec)
    if len(ec_list)==1:
        return ec_list[0]
    else:
        return ec_list

########################################
def GetPulseHeightSAS( runNo="0", Xrange="0 10000 10", Bank="SM", TimeSlice="-1 -1", frameBoundary="0.0", paramFiles="- -",PHbin=5 ):
    """
    Make Pulse Height data of EventData
    GetPulseHeightSAS( runNo=0, Xrange="0 10000 10", Bank="SM", TimeSlice="-1 -1", paramFiles="- -" ):

    @param runNo     (string)     Run Number
    @param Xrange    (string)  "startX endX widthX type" separated with space (not comma) : type=[dL, dL/L, tof]
    @param Bank      (string)  "SM"...  Monitors by "MON1" or "MON2"
    @param TimeSlice (string)  "startTime endTime" separated with space: "-1 -1" means no-setting.
    @param frameBoundary (string) "frameBoundary" or "frameBoundary TofMask_min TofMask_max"
    @param paramFiles (string) "WiringInfo DetectorInfo"
    @param PHbin      (int)    Pulse Height bin
    @retval ECA (ElementContainerArray)
    """
    ss = Xrange.split(" ")
    if len(ss)==3:
        Xrange = Xrange+" tof"

    isTimeFoc=False
    SolAngCor=False
    isPH=True
    PHrange=""
    dat = GetHistogramBaseSAS( runNo, Xrange, Bank, TimeSlice, frameBoundary, isTimeFoc, SolAngCor, paramFiles, isPH, PHrange )

    ret = BC.GetPH( dat, PHbin )
    pId_list = []
    for i in range( ret.PutSize() ):
        hh = ret(i).PutHeaderPointer()
        pId_list.append( hh.PutInt4("DetId") )
    pId_list.sort()

    eca = Manyo.ElementContainerArray(dat.PutHeader())
    SIH = Manyo.SearchInHeader()
    SIH.SetTarget( ret )
    for pId in pId_list:
        #print "pid=",pId
        if (SIH.Search( "DetId", pId )):
            rslt_v0 = SIH.PutResultIndex(0)
            tmp_ec = ret(rslt_v0[0])
            tmp_hh = tmp_ec.PutHeaderPointer()
            x_range = Manyo.MakeDoubleVector()
            x_range.push_back( float( pId-0.5 ) )
            x_range.push_back( float( pId+0.5 ) )
            tmp_hh.Add( "XRANGE", x_range )
            tmp_hh.Add( "isHistogram", 0 ) ##[inamura 150515]
            eca.Add( tmp_ec )
        else:
            print("serching failed at pId=",pId)
    del SIH
    del dat

    return eca


########################################
def GetMonHistByPhSAS( runNo="0", MonNo=1, Xrange="0.0 40000.0 10.0 tof", phRange="0 10000", MonIndex=0, TimeSlice="-1 -1", frameBoundary=0.0, CalibEffi=True ):
    """
    Load EventData to produce histogram of monitors limited by pulse height
    GetMonHistByPhSAS( runNo="0", MonNo=1, Xrange="0.0 40000.0 10.0 tof", phRange="0 10000", MonIndex=0, TimeSlice="-1 -1", frameBoundary=0.0, CalibEffi=True )

    @param runNo     (int)     Run Number
    @param MonNo     (int)     Monitor Number 1 (up-stream) or 2 (down-stream)
    @param Xrange    (string)  "startX endX widthX type" separated with space (not comma) : type=[dL, dL/L, tof]
    @param phRange   (string)  "lld hld"
    @param MonIndex  (int)     0.. digital  1.. analog
    @param TimeSlice (string)  "startTime endTime" separated with space: "-1 -1" means no-setting.
    @param frameBoundary (float)
    @param CalibEffi (bool)    Monitor-detector efficiency calibration
    @retval EC (ElementContainer)
    """
    Bank=""
    if MonNo==1:
        Bank="MON1"
    elif MonNo==2:
        Bank="MON2"
    elif MonNo==3:
        Bank="MON3"
    else:
        raise UserWarning("MonNo is invalid")

    dat = GetHistogramBaseSAS( runNo, Xrange, Bank, TimeSlice, str(frameBoundary), isTimeFoc=False, SolAngCor=False, paramFiles="- -", isPH=True, PHrange=phRange )

    ec = dat.Put(MonIndex).Put(0)
    key_kc = "KICKERCOUNT"
    kick_count = dat.PutHeader().PutInt4(key_kc)
    ec.AddToHeader(key_kc,kick_count)

    # Monitor Detector Efficienty Calibration
    if (CalibEffi):
        p_N2 = 0.465  #[atm]
        t_Mon = 12   # thickness of monitor [mm]
        t_Al  = 0.5  # thickness of Al window [mm]

        dec = ms.DetectorEffiCorrection()
        dec.N2MonEffiCorrection( ec, p_N2, t_Mon, t_Al )
        del dec



    return ec

#########################################
def MergeSMSC4DetMap(dat):
    """
    Merge Data SM and SC bank into one ElementContainerMatrix
    to plot using DetectMap
    @param dat  (ElementContainerMatrix)
    @retval ElementContainerMatrix
    """
    SIH = Manyo.SearchInHeader( dat )
    matrix = []
    for i in range(25):
        a_line=[]
        for j in range(125):
            a_line.append(None)
        matrix.append(a_line)

    ##SC_Lower
    pixel_no=66
    for det_id in range( 872, 928 ):
        if SIH.SearchArray("DETID", det_id ):
            vv = SIH.PutResultIndex(0)
            if vv.size()!=0:
                for i in range(25):
                    matrix[24-i][pixel_no] = (vv[0],i)
            pixel_no+=1

    ##SC_Upper
    pixel_no = 2
    for det_id in range( 816, 872 ):
        if SIH.SearchArray("DETID", det_id ):
            vv = SIH.PutResultIndex(0)
            if vv.size()!=0:
                for i in range(25):
                    matrix[24-i][pixel_no] =(vv[0],i)
            pixel_no+=1

    ##SC_Left
    det_no = 7
    for det_id in range( 928, 936 ):
        if SIH.SearchArray("DETID", det_id ):
            vv = SIH.PutResultIndex(0)
            if vv.size()!=0:
                for i in range(8):
                    #matrix[det_no][63-i] =(vv[0],i+8)
                    #matrix[det_no][65-i] =(vv[0],i+8)
                    matrix[det_no][65-i] =(vv[0],15-i)
            det_no=det_no-1

    ##SC_rigth
    det_no = 24
    for det_id in range( 936, 944 ):
        if SIH.SearchArray("DETID", det_id ):
            vv = SIH.PutResultIndex(0)
            if vv.size()!=0:
                for i in range(8):
                    #matrix[det_no][63-i] = (vv[0],i+8)
                    #matrix[det_no][65-i] = (vv[0],i+8)
                    matrix[det_no][65-i] =(vv[0],15-i)
            det_no=det_no-1


    ec_tmp = dat(0,0)
    xx=ec_tmp.PutXList()
    yy=ec_tmp.PutYList()
    ee=ec_tmp.PutEList()
    xkey=ec_tmp.PutXKey()
    ykey=ec_tmp.PutYKey()
    ekey=ec_tmp.PutEKey()
    yy_zero = [0]*len(yy)
    ee_zero = [0]*len(yy)
    hh_ec = Manyo.HeaderBase()
    hh_ec.Add("MASKED",1)
    ec_empty = Manyo.ElementContainer(hh_ec)
    ec_empty.Add(xkey,xx)
    ec_empty.Add(ykey,yy_zero)
    ec_empty.Add(ekey,ee_zero)
    ec_empty.SetKeys(xkey,ykey,ekey)

    hh=dat.PutHeader()
    hh.Erase("BANKIDLIST")
    hh.Erase("BANKSIZELIST")
    hh.Erase("BANKNAMELIST")
    """
    v_id=Manyo.MakeInt4Vector(3)
    v_id[0]=0
    v_id[1]=1
    v_id[2]=2
    v_size=Manyo.MakeInt4Vector(3)
    v_size[0]=112
    v_size[1]=25
    v_size[2]=144
    v_name=Manyo.MakeStringVector(3)
    v_name[0]="SM16"
    v_name[1]="SC"
    v_name[2]="SM14"
    """
    v_id=Manyo.MakeInt4Vector(1)
    v_id[0]=0
    v_size=Manyo.MakeInt4Vector(1)
    v_size[0]=112+25+144
    v_name=Manyo.MakeStringVector(1)
    v_name[0]="SM+SC"

    hh.Add("BANKIDLIST",v_id)
    hh.Add("BANKSIZELIST",v_size)
    hh.Add("BANKNAMELIST",v_name)

    ecm = Manyo.ElementContainerMatrix( hh )


    # SM16
    for psd_no in range(112):
        psd_id = 280 + psd_no
        if SIH.SearchArray("DETID", psd_id ):
            vv = SIH.PutResultIndex(0)
            if len(vv)!=0:
                eca = dat.Put(vv[0])
                hh = eca.PutHeaderPointer()
                hh.Erase("BANKID")
                hh.Erase("INDEXINBANK")
                hh.Add("BANKID",0)
                hh.Add("INDEXINBANK", psd_no)

                ecm.Add( eca )
                del eca
            else:
                eca = Manyo.ElementContainerArray()
                hh=eca.PutHeaderPointer()
                hh.Add("DETID", psd_id)
                hh.Add("MASKED", 1 )
                hh.Add("BANKID", 0 )
                hh.Add("INDEXINBANK", psd_no )
                ecm.Add(eca)
                del eca

    # SC
    det_no = 112
    for a_psd in matrix:
        det_id = 2000 + det_no
        eca = Manyo.ElementContainerArray()
        hh=eca.PutHeaderPointer()
        hh.Add("DETID", det_id)
        hh.Add("BANKID", 0 )
        hh.Add("INDEXINBANK", det_no )
        isAllNone = True
        pixelNo=0
        for a_pixel in a_psd:

            if a_pixel==None:
                eca.Add( ec_empty )
            else:
                #print "det_id,pixelNo=",det_no,pixelNo
                eca.Add( dat(a_pixel[0],a_pixel[1]) )
                #hh_ec=dat(a_pixel[0]).PutHeaderPointer()
                #print "DetId,pixelNo=",hh_ec.PutInt4("DETID")
                isAllNone = False
            pixelNo+=1
        if isAllNone:
            hh.Add("MASKED", 1 )
        else:
            hh.Add("MASKED", 0 )
        ecm.Add(eca)
        det_no +=1

    # SM14
    for psd_no in range(144):
        psd_id = 392 + psd_no
        if SIH.SearchArray("DETID", psd_id ):
            vv = SIH.PutResultIndex(0)
            if len(vv)!=0:
                eca = dat.Put(vv[0])
                hh = eca.PutHeaderPointer()
                hh.Erase("BANKID")
                hh.Erase("INDEXINBANK")
                hh.Add("BANKID",0)
                hh.Add("INDEXINBANK", 112+25+psd_no)
                ecm.Add( eca )
                del eca
            else:
                eca = Manyo.ElementContainerArray()
                hh=eca.PutHeaderPointer()
                hh.Add("DETID", psd_no+112+25)
                hh.Add("MASKED", 1 )
                hh.Add("BANKID", 0 )
                hh.Add("INDEXINBANK", 112+25+psd_no)
                ecm.Add(eca)
                del eca

    del SIH
    return ecm

def RPMTRemoveCenterLine( dat, PsdRange="200 201", PixelRange="198 199" ):
    """
    Merge Data SM and SC bank into one ElementContainerMatrix
    to plot using DetectMap
    @param dat  [Def:DAT] (ElementContainerMatrix)
    @param PsdRange
    @param PixelRange
    @retval None
    """
    import Manyo

    psd_range_list=PsdRange.split(" ")
    if len(psd_range_list)!=2:
        raise UserWarning("PsdRange is invalid #1")
    psd1 = int(psd_range_list[0])
    psd2 = int(psd_range_list[1])

    pixel_range_list=PixelRange.split(" ")
    if len(pixel_range_list)!=2:
        raise UserWarning("PixelRange is invalid")
    pixel1 = int(pixel_range_list[0])
    pixel2 = int(pixel_range_list[1])

    SIH = Manyo.SearchInHeader()
    SIH.SetTarget( dat )
    eca1 = None
    eca2 = None
    if (SIH.SearchArray( "DETID", psd1 )):
        rslt = SIH.PutResultIndex(0)
        if rslt.size()!=0:
            eca1 = dat.PutPointer(rslt[0])
    if (SIH.SearchArray( "DETID", psd2 )):
        rslt = SIH.PutResultIndex(0)
        if rslt.size()!=0:
            eca2 = dat.PutPointer(rslt[0])

    if eca1==None or eca2==None:
        raise UserWarning("PsdRange is invalid #2")

    import math
    for i in range( eca1.PutSize() ):
        ec1 = eca1(i)
        ec2 = eca2(i)
        keyX = ec1.PutXKey()
        keyY = ec1.PutYKey()
        keyE = ec1.PutEKey()

        yy1 = ec1.PutY()
        yy2 = ec2.PutY()
        ee1 = ec1.PutE()
        ee2 = ec2.PutE()
        yy_ave = Manyo.MakeDoubleVector()
        ee_ave = Manyo.MakeDoubleVector()
        for j in range(yy1.size()):
            yy_ave.push_back( (yy1[j]+yy2[j])/2.0 )
            ee_ave.push_back( math.sqrt( (ee1[j]*ee1[j])+(ee2[j]*ee2[j]) ) )
        ec1.Replace( keyY, yy_ave )
        ec1.Replace( keyE, ee_ave )
        ec2.Replace( keyY, yy_ave )
        ec2.Replace( keyE, ee_ave )

        ec1.SetKeys( keyX, keyY, keyE )
        ec2.SetKeys( keyX, keyY, keyE )

    #del SIH

    for i in range( dat.PutSize() ):
        if dat(i).PutSize()==0:
            continue
        ec1 = dat(i,pixel1)
        ec2 = dat(i,pixel2)
        """
        ec1 = None
        ec2 = None
        for j in range(dat(i).PutSize()):
            ypos = dat(i,j).PutHeaderPointer().PutInt4("YPOS")
            if ypos==pixel1:
                ec1 = dat(i,j)
            elif ypos==pixel2:
                ec2 = dat(i,j)
        if ec1==None or ec2==None:
            raise
        """
        keyX = ec1.PutXKey()
        keyY = ec1.PutYKey()
        keyE = ec1.PutEKey()

        yy1 = ec1.PutY()
        yy2 = ec2.PutY()
        ee1 = ec1.PutE()
        ee2 = ec2.PutE()
        yy_ave = Manyo.MakeDoubleVector()
        ee_ave = Manyo.MakeDoubleVector()
        for j in range(yy1.size()):
            yy_ave.push_back( (yy1[j]+yy2[j])/2.0 )
            ee_ave.push_back( math.sqrt( (ee1[j]*ee1[j])+(ee2[j]*ee2[j]) ) )
        ec1.Replace( keyY, yy_ave )
        ec1.Replace( keyE, ee_ave )
        ec2.Replace( keyY, yy_ave )
        ec2.Replace( keyE, ee_ave )

        ec1.SetKeys( keyX, keyY, keyE )
        ec2.SetKeys( keyX, keyY, keyE )

    del SIH


def ConvertFromRPMTK2Psd(runNo, daqId, modNo=0, dataPath=None, modeNo=5, rpmtPrm=[128,1024,128,1024], lmtCoi=32, dfile=""):
    """
    Convert event data for RPMT of KEK to ones for PSD

    @param runNo (int) runNo
    @param daqId (int) Daq Id for RPMT of KEK
    @param dataPath (string) Data path
    @param modNo (int) Module No. for RPMT of KEK
    @param rpmtPrm (list)
    @param lmtCoi (int)
    @param dfile (string) DetectorInfo file
    @retval None
    """
    print( ".... Start Conversion event data from RPMT-KEK to PSD .... " )
    print("ConvertFromRPMTK2Psd >>> LLD_X={:d}, HLD_X={:d}, LmtCoi={:d}".format(rpmtPrm[0], rpmtPrm[1], lmtCoi))
    print("ConvertFromRPMTK2Psd >>> LLD_Y={:d}, HLD_Y={:d}, LmtCoi={:d}".format(rpmtPrm[2], rpmtPrm[3], lmtCoi))
    root_data = mu.FindRootDataFolder()
    inst_code = mu.UtsusemiEnvGetInstCode()
    run_folders_v = mu.FindRunDataFolders( runNo )
    target_dir_list = None
    for i in range(run_folders_v.size()):
        # print(" run_folders_v = ", run_folders_v[i])
        run_folder = run_folders_v[i]
        target_dir = os.path.join(run_folder, "%3s%06d_%02d_%03d_???.edb"%(inst_code, runNo,daqId, modNo))
        target_dir_list = glob.glob(target_dir)
        if len(target_dir_list) != 0:
            break
        else:
            target_dir_list = None
    if target_dir_list is None:
        raise UserWarning( "ConvertFromRPMTK2Psd >> Not found RunNo in %s"%(target_dir) )
    target_dir_list.sort()
    Output_dir = os.path.dirname( target_dir_list[0] )
    RPMT_data_files = Manyo.MakeStringVector()
    for a_file in target_dir_list:
        RPMT_data_files.append( str( a_file ) )


    if dataPath!=None:
        Output_dir = os.path.join( root_data, dataPath, os.path.basename( Output_dir ) )
        if not os.access( Output_dir, os.F_OK ):
            try:
                os.system( "mkdir -p %s"%(Output_dir) )
            except:
                raise UserWarning( "ConvertFromRPMTK2Psd >> Cannot make directory as %s"%(Output_dir) )
        else:
            try:
                if mu.UtsusemiEnvGetDebugMode():
                    print( "ConvertFromRPMTK2Psd >>> Try to Delete Old Data" )
                os.system( "rm -rf %s/*"%(Output_dir) )
                if mu.UtsusemiEnvGetDebugMode():
                    print( "Delete OK." )
            except:
                raise UserWarning( "ConvertFromRPMTK2Psd >> Cannot delete old files in %s"%(Output_dir) )

    if not os.access( Output_dir, os.W_OK):
        raise UserWarning( "ConvertFromRPMTK2Psd >> Cannot write converted data in %s"%(Output_dir) )

    tt=ms.RPMTDataConverter()
    tt.SetDaqId(daqId)
    if tt.SetParamsFromAnaEnv(runNo, modeNo, "", dfile):
        tt.Execute(RPMT_data_files, Output_dir, runNo, rpmtPrm[0], rpmtPrm[1], rpmtPrm[2], rpmtPrm[3], lmtCoi)
    else:
        print("ConvertFromRPMTK2Psd >>> RPMTDataConverter::SetParamFromAnaEnv false")
    del tt

#########################################
def GetPulseHeightFromRPMTK( runNo, daqId, modNo=0, dataPath=None, width_bin=2, max_bin=4048, LmtCoin=32):
    """
    Get PulseHeight data from raw data from RPMT of KEK

    @param runNo (int) runNo
    @param daqId (int) Daq Id for RPMT of KEK
    @param modNo (int) Module No. for RPMT of KEK
    @param dataPath (string)
    @param width_bin (int) bin width of Pulse Height channels
    @param max_bin (int) maximum bin of Pulse Height channels
    @param LmtCoin (int) Upper limit of Coincidence clock
    @retval ECA ElementContainerArray of pulse height histograms for X, Y, X+Y
    """
    print( ".... Create Pulse Height data from event data from RPMT-KEK .... " )
    root_data = mu.FindRootDataFolder()
    inst_code = mu.UtsusemiEnvGetInstCode()
    run_folders_v = mu.FindRunDataFolders( runNo )
    run_folder = run_folders_v[0]
    target_dir = os.path.join( run_folder, "%3s%06d_%02d_%03d_???.edb"%(inst_code,runNo,daqId, modNo) )
    target_dir_list = glob.glob( target_dir )
    if len(target_dir_list)==0:
        raise UserWarning( "ConvertFromRPMTK2Psd >> Not found RunNo in %s"%(target_dir) )
    target_dir_list.sort()
    Output_dir = os.path.dirname( target_dir_list[0] )
    RPMT_data_files = Manyo.MakeStringVector()
    for a_file in target_dir_list:
        RPMT_data_files.append( str( a_file ) )

    tt=ms.RPMTDataConverter()
    tt.SetDaqId(daqId)
    HH=Manyo.HeaderBase()
    HH.Add(mu.UTSUSEMI_KEY_HEAD_RUNNUMBER, "%3s%06d"%(inst_code,runNo))
    HH.Add(mu.UTSUSEMI_KEY_HEAD_INSTRUMENT, inst_code)
    ecX=Manyo.ElementContainer(HH)
    ecY=Manyo.ElementContainer(HH)
    tt.PutPulseHeight(ecX, ecY, RPMT_data_files, width_bin, max_bin, LmtCoin)
    ec = ecX+ecY
    ECA=Manyo.ElementContainerArray(HH)
    ECA.Add(ecX)
    ECA.Add(ecY)
    ECA.Add(ec)

    del tt
    return ECA
#########################################
def RPMTGetBeamCenterDropPosi(DAT=None, lamStep="1.0,2.0,3.0,4.0,5.0,6.0,7.0", deltaLam=0.5, init_par="1.0e14, 5.0, 5.0, 150.0, 150.0", factor=1e-10, withPlot=False):
    """
    Get beam center positions at each lambda range
    RPMTGetBeamCenterDropPosi(DAT=None, lamStep="1.0,2.0,3.0,4.0,5.0,6.0,7.0", deltaLam=0.5, init_par="1.0e14, 5.0, 5.0, 150.0, 150.0", factor=1e-10, withPlot=False)

    @param DAT (ElementContainerMatrix)
    @param lamStep (string) list of the center lambda
    @param deltaLam (float) width of lambra range for each the center lambda
    @param init_par (string) Initial values for fitting "<A>, <w_X>, <w_Y>, <c_X>, <c_Y>"
    @param factor (float) Intensity = factor*Intensity
    @param withPlot (bool) Plot results or not
    @retval EC ElementContainer for X-Y positions of beam center
    """
    DATs = DAT.Mul(factor)
    lamStep = lamStep.strip()
    num_space = len(lamStep.split(" "))
    num_comma = len(lamStep.split(","))
    lam_step = []
    if num_space > num_comma:
        for l in lamStep.split(" "):
            lam_step.append(float(l))
    elif num_comma >= num_space:
        LamRnage = lamStep.replace(" ","")
        for l in lamStep.split(","):
            lam_step.append(float(l))
    else:
        raise UserWarning("RPMTGetBeamCenterDropPosi>> invalid Lambda range parameter")

    init_par=init_par.strip()
    num_space = len(init_par.split(" "))
    num_comma = len(init_par.split(","))
    init_param = []
    if num_comma == 5:
        for l in init_par.split(","):
            init_param.append(float(l))
    elif num_space == 5:
        for l in init_par.split(" "):
            init_param.append(float(l))
    else:
        raise UserWarning("RPMTGetBeamCenterDropPosi>> invalid Lambda range parameter")

    param_initial = tuple(init_param)
    print("param_initial = ",param_initial)

    import numpy as np
    import math
    from scipy.optimize import curve_fit
    def gauss_2d(X, A, sigma_x, sigma_y, mu_x, mu_y):
        x, y = X
        z = A * np.exp(-((x-mu_x)**2)/(2.0 * sigma_x**2)) * np.exp(-((y-mu_y)**2)/(2.0 * sigma_y**2))
        return z.ravel()
    def line_1d(X, A, B):
        return A + (X * B)
    def drop_lambda(X, A, B):
        return A - (B * X * X)

    # Data
    num_x = DATs.PutSize()
    num_y = DATs(0).PutSize()
    xx = np.arange(num_x)
    yy = np.arange(num_y)

    x_data, y_data = np.meshgrid(xx, yy)
    z_data = np.zeros((num_y, num_x), np.float64)

    mu_x_list = []
    mu_y_list = []
    mu_e_list = []
    for lr in lam_step:
        # Make data
        for i in range(num_x):
            for j in range(num_y):
                EC = DATs(i, j)
                p = EC.Sum((lr - deltaLam), (lr + deltaLam))
                z_data[j, i] = p.first

        # Fitting
        #param_initial = ( 1000, 5.0, 5.0, 150.0, 150.0 )
        X = np.array([x_data, y_data])
        popt, pcov = curve_fit(gauss_2d, X, z_data.ravel(), p0=param_initial)
        perr = np.sqrt(np.diag(pcov))

        # Results
        A, sigma_x, sigma_y, mu_x, mu_y = popt
        print("perr= {}".format(perr))
        print(" A = {}\n sigma_x = {}\n sigma_y={}\n mu_x={}\n mu_y={}".format(A, sigma_x, sigma_y, mu_x, mu_y))
        DI=ms.SASDetectorInfoEditorRPMT()
        mu_x_list.append(float(mu_x) * DI.PutPixelSizeX())
        mu_y_list.append(float(mu_y) * DI.PutPixelSizeY())
        #mu_x_list.append(float(mu_x))
        #mu_y_list.append(float(mu_y))
        mu_e_list.append(1.0)

    print("mu_x_list = ",mu_x_list)
    print("mu_y_list = ",mu_y_list)

    EC = Manyo.ElementContainer()
    EC.Add("Xch", mu_x_list, "mm")
    EC.Add("Ych", mu_y_list, "mm")
    EC.Add("Error", mu_e_list, "mm")
    EC.SetKeys("Xch", "Ych", "Error")

    # line fit
    popt, pcov = curve_fit(line_1d, mu_x_list, mu_y_list)
    perr = np.sqrt(np.diag(pcov))
    A, B = popt
    print(type(A),type(B))
    A=float(A)
    B=float(B)

    print("Line Fitting: A={}, B={}".format(A, B))
    #rotAng = math.atan(1.0 / (float(B) * 0.207 / 0.205)) / math.pi * 180.0
    rotAng = math.atan(1.0 / B) / math.pi * 180.0
    print("Rotate Angle = {}".format(rotAng))

    x_fit = []
    y_fit = []
    e_fit = []
    for x in range(100):
        #xx = 150.5 + (0.01 * float(x))
        xx = 30.75 + (0.01 * float(x))
        x_fit.append(xx)
        y_fit.append(A + (B * xx))
        e_fit.append(1.0)

    # print(x_fit)
    # print(y_fit)
    EC2 = Manyo.ElementContainer()
    EC2.Add("Xch", x_fit, "mm")
    EC2.Add("Ych", y_fit, "mm")
    EC2.Add("Error", e_fit, "mm")
    EC2.SetKeys("Xch", "Ych", "Error")

    x_p = []
    y_p = []
    e_p = []
    print("Line Fitting: A={}, B={}".format(A, B))
    for x1, y1 in zip(mu_x_list, mu_y_list):
        x0 = (x1 + (B * y1) - (A * B)) / ((B * B) + 1)
        y0 = A + (x0 * B)
        x_p.append(x0)
        y_p.append(y0)
        e_p.append(0.10)
        # print("x1 {} -> {}".format(x1, x0))
        # print("y1 {} -> {}".format(y1, y_p[-1]))
    EC3 = Manyo.ElementContainer()
    EC3.Add("Xch", x_p, "mml")
    EC3.Add("Ych", y_p, "mm")
    EC3.Add("Error", e_p, "mm")
    EC3.SetKeys("Xch", "Ych", "Error")

    # Dropping distance
    drop_dist = []
    drop_err = []
    for xp, yp in zip(x_p, y_p):
        dist = -1.0 *  math.sqrt(((xp - x_p[0]) * (xp - x_p[0])) + ((yp - y_p[0]) * (yp - y_p[0])))
        drop_dist.append(dist)
        drop_err.append(0.1)

    popt, pcov = curve_fit(drop_lambda, lam_step, drop_dist)
    perr = np.sqrt(np.diag(pcov))
    A, B = popt

    A = float(A)
    B = float(B)
    print( "Drop fitting A = {}, B= {}".format(A, B))
    drop_lam_fit = []
    drop_dist_fit = []
    drop_err_fit = []
    for i in range(160):
        drop_lam_fit.append(float(i)/10.0)
        drop_dist_fit.append(-1.0 * (B * float(i) * float(i) / 100.0)) # Distance=0 at lambda -> 0.
        drop_err_fit.append(0.1)

    EC4 = Manyo.ElementContainer()
    EC4.Add("Lambda", lam_step, "Ang")
    EC4.Add("Distance", drop_dist, "mm")
    EC4.Add("Error", drop_err, "mm")
    EC4.SetKeys("Lambda", "Distance", "Error")
    EC5 = Manyo.ElementContainer()
    EC5.Add("Lambda", drop_lam_fit, "Ang")
    EC5.Add("Distance", drop_dist_fit, "mm")
    EC5.Add("Error", drop_err_fit, "mm")
    EC5.SetKeys("Lambda", "Distance", "Error")

    drop_origin_dx = x_p[-1] - x_p[0]
    drop_origin_dy = y_p[-1] - y_p[0]
    drop_origin_dl = math.sqrt((drop_origin_dx * drop_origin_dx) + (drop_origin_dy * drop_origin_dy))
    drop_origin_dx /= drop_origin_dl
    drop_origin_dy /= drop_origin_dl
    drop_origin_x = drop_origin_dx * math.fabs(A) + x_p[0]
    drop_origin_y = drop_origin_dy * math.fabs(A) + y_p[0]

    drop_origin_px = drop_origin_x / 0.205
    drop_origin_py = drop_origin_y / 0.207

    print("True Beam Center x = {}, y = {} [mm]".format(drop_origin_x, drop_origin_y))
    print("True Beam Center x = {}, y = {} [pixel]".format(drop_origin_px, drop_origin_py))

    # Save results into xml file
    # under construction

    if withPlot:
        import VisualModule as VB
        p1 = VB.MPlot([EC, EC2, EC3])
        p1 = VB.MPlot([EC4, EC5])
        # VB.M2PlotPlus(DAT)

    '''
    ec_lam = []
    ec_drop = []
    ec_e = []
    for i in range(len(mu_x_list)-1):
        inext = i + 1
        ec_lam.append((lam_step[i] + lam_step[inext]) / 2.0)
        mx = (mu_x_list[inext] - mu_x_list[i]) * 0.205
        my = (mu_y_list[inext] - mu_y_list[i]) * 0.207
        ec_drop.append(math.sqrt(mx * mx + my * my))
        ec_e.append(1.0)

    EC2 = Manyo.ElementContainer()
    EC2.Add("Lambda", ec_lam, "Ang")
    EC2.Add("Distance", ec_drop, "mm")
    EC2.Add("Error", ec_e, "mm")
    EC2.SetKeys("Lambda", "Distance", "Error")

    if withPlot:
        import VisualModule as VB
        p1 = VB.MPlot(EC)
        p2 = VB.MPlot(EC2)
        VB.M2PlotPlus(DAT)
    '''
    return EC

#########################################
def CreateRPMTDetectorInfoFromData(runNo=206316, lamStep="1.0,2.0,3.0,4.0,5.0,6.0,7.0", deltaLam=0.5, factor=1e-10, withPlot=False):
    """
    Create new detector info for RPMT from beam center positions drifted by a gravity
    CreateRPMTDetectorInfoFromData(runNo="206316", lamStep="1.0,2.0,3.0,4.0,5.0,6.0,7.0", deltaLam=0.5, factor=1e-10, withPlot=False)

    @param runNo (int)
    @param lamStep (string) list of the center lambda
    @param deltaLam (float) width of lambra range for each the center lambda
    @param factor (float) Intensity = factor*Intensity
    @param withPlot (bool) Plot results or not
    @retval None
    """

    dfile_org = os.path.join( mu.UtsusemiEnvGetBaseDir(), mu.UtsusemiEnvGetInstCode(), "ana", "Reduction", "DetectorInfo_newRPMT_origin.xml")
    DAT0=GetHistogramSAS( runNo=str(runNo), Xrange="0.7 15.5 0.1 dL", Bank="RPMT", TimeSlice="-1 -1", frameBoundary="0.0", isTimeFoc=False, SolAngCor=True, paramFiles="- " + dfile_org )
    DAT0.MulMySelf(factor)

    lamStep = lamStep.strip()
    num_space = len(lamStep.split(" "))
    num_comma = len(lamStep.split(","))
    lam_step = []
    if num_space > num_comma:
        for l in lamStep.split(" "):
            lam_step.append(float(l))
    elif num_comma >= num_space:
        LamRnage = lamStep.replace(" ","")
        for l in lamStep.split(","):
            lam_step.append(float(l))
    else:
        raise UserWarning("CreateRPMTDetectorInfoFromData >>> invalid Lambda range parameter")

    import numpy as np
    import math
    from scipy.optimize import curve_fit
    def gauss_2d(X, A, sigma_x, sigma_y, mu_x, mu_y):
        x, y = X
        z = A * np.exp(-((x-mu_x)**2)/(2.0 * sigma_x**2)) * np.exp(-((y-mu_y)**2)/(2.0 * sigma_y**2))
        return z.ravel()
    def line_1d(X, A, B):
        return A + (X * B)
    def drop_lambda(X, A, B):
        return A - (B * X * X)

    # Find Beam Center to fix XchShift and YchShift
    DI=ms.SASDetectorInfoEditorRPMT()
    if DI.Read(dfile_org):
        pass
    else:
        print("Failed to Read {}".format(dfile_org))
        return False

    # Data
    def GetBeamCenter(DAT, lam_step, deltaLam):
        num_x = DAT.PutSize()
        num_y = DAT(0).PutSize()
        xx = np.arange(num_x)
        yy = np.arange(num_y)

        x_data, y_data = np.meshgrid(xx, yy)
        z_data = np.zeros((num_y, num_x), np.float64)

        mu_x_list = []
        mu_y_list = []
        mu_e_list = []
        for lr in lam_step:
            # Make data
            for i in range(num_x):
                for j in range(num_y):
                    EC = DAT(i, j)
                    p = EC.Sum((lr - deltaLam), (lr + deltaLam))
                    z_data[j, i] = p.first

            # max-value position
            iy_max, ix_max = np.unravel_index(np.argmax(z_data), z_data.shape)

            # Fitting
            #param_initial = ( 1000, 5.0, 5.0, 150.0, 150.0 )
            param_initial = ( 1000.0, 5.0, 5.0, ix_max, iy_max )
            X = np.array([x_data, y_data])
            popt, pcov = curve_fit(gauss_2d, X, z_data.ravel(), p0=param_initial)
            perr = np.sqrt(np.diag(pcov))

            # Results
            A, sigma_x, sigma_y, mu_x, mu_y = popt
            mu_x_list.append(float(mu_x) * DI.PutPixelSizeX())
            mu_y_list.append(float(mu_y) * DI.PutPixelSizeY())
            mu_e_list.append(1.0)

            # If Debug Mode
            if mu.UtsusemiEnvGetDebugMode():
                print("Fitting ix_max, iy_max = {}, {}".format(ix_max, iy_max))
                print("perr= {}".format(perr))
                print(" A = {}\n sigma_x = {}\n sigma_y={}\n mu_x={}\n mu_y={}".format(A, sigma_x, sigma_y, mu_x, mu_y))
        return (mu_x_list, mu_y_list, mu_e_list)

    mu_x_list, mu_y_list, mu_e_list = GetBeamCenter(DAT0, [1.5], 1.0)
    if mu.UtsusemiEnvGetDebugMode():
        print(mu_x_list[0]/DI.PutPixelSizeX(), mu_y_list[0]/DI.PutPixelSizeY())
        print("DI.PutSizeXch()={}".format(DI.PutSizeXch()))
        print("DI.PutSizeXch()/2.0 = {}".format(DI.PutSizeXch()/2.0))
    # _XchOffset = (UInt4)(_numOfLines/_binWidth/2 - (Int4)(_size_Xch/2) + _XchShift);
    # _YchOffset = (UInt4)(_numOfLines/_binWidth/2 - (Int4)(_size_Ych/2) + _YchShift);
    # PutNumOfLines();    UInt4 PutBinWidth();    UInt4 PutSizeXch();    UInt4 PutSizeYch();

    xchshift = int((DI.PutSizeXch()/2.0) -1.0 - mu_x_list[0]/DI.PutPixelSizeX()) # [pixel]
    ychshift = int((DI.PutSizeYch()/2.0) -1.0 - mu_y_list[0]/DI.PutPixelSizeY())
    if mu.UtsusemiEnvGetDebugMode():
        print("CreateRPMTDetectorInfoFromData >>> XchShift, YchShift = {}, {}".format(xchshift, ychshift))
    DI.SetChannelShift(xchshift, ychshift)
    tmp_dfile = os.path.join(os.getcwd(), "tmp_DetectorInfo_newRPMT.xml")
    if DI.Write(tmp_dfile):
        print("CreateRPMTDetectorInfoFromData >>> Temporal file = {}".format(tmp_dfile))
    else:
        raise

    # Find lambda dependency of Beam Center
    DAT1=GetHistogramSAS( runNo=runNo, Xrange="0.7 15.5 0.1 dL", Bank="RPMT", TimeSlice="-1 -1", frameBoundary="0.0", isTimeFoc=False, SolAngCor=True, paramFiles="- " + tmp_dfile )
    DAT1.MulMySelf(factor)
    mu_x_list, mu_y_list, mu_e_list = GetBeamCenter(DAT1, lam_step, deltaLam)
    if mu.UtsusemiEnvGetDebugMode():
        print("mu_x_list = ",mu_x_list)
        print("mu_y_list = ",mu_y_list)

    hh_ec = Manyo.HeaderBase()
    hh_ec.Add(mu.UTSUSEMI_KEY_HEAD_RUNNUMBER, "SAS{:06d}".format(runNo))
    hh_ec.Add(mu.UTSUSEMI_KEY_HEAD_LABEL, "Measured")
    EC = Manyo.ElementContainer(hh_ec)
    EC.Add("Xch", mu_x_list, "mm")
    EC.Add("Ych", mu_y_list, "mm")
    EC.Add("Error", mu_e_list, "mm")
    EC.SetKeys("Xch", "Ych", "Error")

    # line fit
    popt, pcov = curve_fit(line_1d, mu_x_list, mu_y_list)
    perr = np.sqrt(np.diag(pcov))
    A, B = popt

    A=float(A)
    B=float(B)

    if mu.UtsusemiEnvGetDebugMode():
        print("Line Fitting: A={}, B={}".format(A, B))

    rotAng = math.atan(1.0 / B) / math.pi * 180.0
    print("CreateRPMTDetectorInfoFromData >>> Rotate Angle = {}".format(rotAng))

    x_fit = []
    y_fit = []
    e_fit = []
    for x in range(100):
        #xx = 150.5 + (0.01 * float(x))
        xx = 30.75 + (0.01 * float(x))
        x_fit.append(xx)
        y_fit.append(A + (B * xx))
        e_fit.append(1.0)

    hh_ec.OverWrite(mu.UTSUSEMI_KEY_HEAD_LABEL, "Fitting")
    EC2 = Manyo.ElementContainer(hh_ec)
    EC2.Add("Xch", x_fit, "mm")
    EC2.Add("Ych", y_fit, "mm")
    EC2.Add("Error", e_fit, "mm")
    EC2.SetKeys("Xch", "Ych", "Error")

    x_p = []
    y_p = []
    e_p = []
    if mu.UtsusemiEnvGetDebugMode():
        print("Line Fitting: A={}, B={}".format(A, B))
    for x1, y1 in zip(mu_x_list, mu_y_list):
        x0 = (x1 + (B * y1) - (A * B)) / ((B * B) + 1)
        y0 = A + (x0 * B)
        x_p.append(x0)
        y_p.append(y0)
        e_p.append(0.10)

    hh_ec.OverWrite(mu.UTSUSEMI_KEY_HEAD_LABEL, "Positions")
    EC3 = Manyo.ElementContainer(hh_ec)
    EC3.Add("Xch", x_p, "mml")
    EC3.Add("Ych", y_p, "mm")
    EC3.Add("Error", e_p, "mm")
    EC3.SetKeys("Xch", "Ych", "Error")

    # Dropping distance
    drop_dist = []
    drop_err = []
    for xp, yp in zip(x_p, y_p):
        dist = -1.0 *  math.sqrt(((xp - x_p[0]) * (xp - x_p[0])) + ((yp - y_p[0]) * (yp - y_p[0])))
        drop_dist.append(dist)
        drop_err.append(0.1)

    popt, pcov = curve_fit(drop_lambda, lam_step, drop_dist)
    perr = np.sqrt(np.diag(pcov))
    A, B = popt

    A = float(A)
    B = float(B)
    print( "CreateRPMTDetectorInfoFromData >>> Drop fitting A = {}, B= {}".format(A, B))

    # Fitted line
    drop_lam_fit = []
    drop_dist_fit = []
    drop_err_fit = []
    for i in range(160):
        drop_lam_fit.append(float(i)/10.0)
        drop_dist_fit.append(-1.0 * (B * float(i) * float(i) / 100.0)) # Distance=0 at lambda -> 0.
        drop_err_fit.append(0.1)

    hh_ec.OverWrite(mu.UTSUSEMI_KEY_HEAD_LABEL, "Measured")
    EC4 = Manyo.ElementContainer(hh_ec)
    EC4.Add("Lambda", lam_step, "Ang")
    EC4.Add("Distance", drop_dist, "mm")
    EC4.Add("Error", drop_err, "mm")
    EC4.SetKeys("Lambda", "Distance", "Error")
    hh_ec.OverWrite(mu.UTSUSEMI_KEY_HEAD_LABEL, "Fitting")
    EC5 = Manyo.ElementContainer(hh_ec)
    EC5.Add("Lambda", drop_lam_fit, "Ang")
    EC5.Add("Distance", drop_dist_fit, "mm")
    EC5.Add("Error", drop_err_fit, "mm")
    EC5.SetKeys("Lambda", "Distance", "Error")

    drop_origin_dx = x_p[-1] - x_p[0]
    drop_origin_dy = y_p[-1] - y_p[0]
    drop_origin_dl = math.sqrt((drop_origin_dx * drop_origin_dx) + (drop_origin_dy * drop_origin_dy))
    drop_origin_dx /= drop_origin_dl
    drop_origin_dy /= drop_origin_dl
    drop_origin_x = drop_origin_dx * math.fabs(A) + x_p[0]
    drop_origin_y = drop_origin_dy * math.fabs(A) + y_p[0]

    drop_origin_px = drop_origin_x / 0.205
    drop_origin_py = drop_origin_y / 0.207

    print("CreateRPMTDetectorInfoFromData >> True Beam Center x = {}, y = {} [mm]".format(drop_origin_x, drop_origin_y))
    print("CreateRPMTDetectorInfoFromData >> True Beam Center x = {}, y = {} [pixel]".format(drop_origin_px, drop_origin_py))

    # Save results into xml file
    out_file = None
    if DI.Read(dfile_org):
        if DI.SetChannelShift(xchshift, ychshift):
            if DI.SetBeamCenterPixel(drop_origin_px, drop_origin_py):
                if DI.SetRotateAngle(-1.0*rotAng):
                    if DI.SetIncidentGravityParam( B ):
                        out_file = os.path.join(os.getcwd(), "new_"+os.path.basename(dfile_org))
                        if DI.Write(out_file):
                            print("CreateRPMTDetectorInfoFromData >>> Output File = {}".format(out_file))
                            # DI.Dump()
                        else:
                            print("Failed to save as {}".format(out_file))
                            return False
                else:
                    print("Failed to SetRotateAngle with {} [deg]".format(rotAng))
                    return False
            else:
                print("Failed to SetBeamCenterPixel with {}, {} [pixel]".format(drop_origin_px, drop_origin_py))
                return False
        else:
            return False
    else:
        print("Failed to Read {}".format(dfile_org))
        return False

    # Data with final detector info
    DAT_res = GetHistogramSAS( runNo=runNo, Xrange="0.7 15.5 0.1 dL", Bank="RPMT", TimeSlice="-1 -1", frameBoundary="0.0", isTimeFoc=False, SolAngCor=True, paramFiles="- " + out_file )
    DAT_res.MulMySelf(factor)

    if withPlot:
        import VisualModule as VB
        p1 = VB.MPlot([EC, EC2, EC3])
        p1.SetXScale(27.0, 35.0)
        p1.SetYScale(24.0, 32.0)
        p1.SetPlotParam(1, ls="", mk="o", eb=False)
        p1.SetPlotParam(2, ls="-", mk="", eb=False)
        p1.SetPlotParam(3, ls="", mk="s", eb=False)
        p2 = VB.MPlot([EC4, EC5])
        p2.SetYScale(-6.5, 0.5)
        p2.SetPlotParam(1, ls="", mk="o", eb=False)
        p2.SetPlotParam(2, ls="-", mk="", eb=False)
        p2.SetXLabel("Lambda")
        p2.SetYLabel("Drop distance")
        VB.M2PlotPlus(DAT_res)

    return DAT_res

#########################################
def GetSumPixelArea( dat, PixelRange ):
    p_list_s = PixelRange.split(" ")
    p_list = []
    for a_posi in p_list_s:
        if a_posi!="":
            p_list.append( int(a_posi) )
    if len(p_list)!=4:
        raise UserWarning("PixelRange is invalid.( must be 4 values )")
    x0 = p_list[0]
    y0 = p_list[1]
    x1 = p_list[2]
    y1 = p_list[3]
    if x0>=(dat.PutSize()) or x1>=(dat.PutSize()) or y0>=(dat(0).PutSize()) or y1>=(dat(0).PutSize()) or x0<0 or y0<0 or x1<0 or y1<0:
        raise UserWarning("PixelRange is invalid. (%d,%d,%d,%d)"%(tuple(p_list)))

    det_v = Manyo.MakeUInt4Vector()
    pix_v = Manyo.MakeUInt4Vector()
    for px in range( x0, x1+1 ):
        for py in range( y0, y1+1 ):
            det_v.append(px)
            pix_v.append(py)

    import Manyo.Utsusemi as mu
    tt=mm.AverageElementContainerMatrix(dat)
    tt.SetPoints( det_v, pix_v )
    EC = tt.GetSum()
    del tt

    EC.InputHeader(dat.PutHeader())
    lamb_vect = dat(x0,y0).Put("Lamb")
    EC.Add("Lamb",lamb_vect)
    return EC

#########################################
def GetHistInelaSAS( runNo="0", Bank="SM", Ei=10.0, Erange="-5 5", dHW=0.1):
    """
    Histogram Creation for inelastic scattering on SAS

    @param runNo     (string)  Run Number "10,11,12"
    @param Bank      (string)  "SM"...  Monitors by "MON1" or "MON2"
    @param Ei        (float)   Incident energy
    @param Erange    (string)  <hw_min>, <hw_max>
    @param dHW       (float)   bin width of hw
    @retval DAT (ElementContainerMatrix)
    """
    UGH = mu.UtsusemiGetNeunetHistogram()
    if not UGH.SetRunNo( runNo ):
        raise UserWarning( "RunNo is invalid." )

    if len(Erange.split(" "))>=len(Erange.split(",")):
        hw_range_st = Erange.split(" ")
    else:
        hw_range_st = Erange.split(",")
    if len(hw_range_st)>=2:
        hw_min = float(hw_range_st[0])
        hw_max = float(hw_range_st[1])
        if hw_max >= Ei:
            raise UserWarning( "Erange hw_max is too large (<Ei)." )
    else:
        raise UserWarning( "Erange is invalid." )

    UUC = mu.UtsusemiUnitConverter()
    print("Incident Lambda = {}".format( UUC.EtoLambda(Ei) ))
    print("Lambda (Ei - hw_max) = {}".format( UUC.EtoLambda(Ei-hw_max) ))
    print("Lambda (Ei - hw_min) = {}".format( UUC.EtoLambda(Ei-hw_min) ))
    params = "hw,{},{},{},{}".format( Ei, hw_min, hw_max, dHW )
    if not UGH.SetConversionParameter( params ):
        raise UserWarning( "Params is invalid.({})".format(params) )

    if not UGH.SetDetParam("psd"):
        raise UserWarning( "Det Type is invalid.({})".format("psd") )


    if len(Bank.split(","))>=len(Bank.split(" ")):
        bank_list = Bank.split(",")
    else:
        bank_list = Bank.split(" ")
    Bank_fixed = ""
    for a_bank in bank_list:
        if a_bank=="SM":
            Bank_fixed += "SMBL14,SMBL16,"
        else:
            Bank_fixed += (a_bank+",")
    Bank_fixed = Bank_fixed[:-1]
    print("Bank_fixed = ",Bank_fixed)
    if not UGH.SetDetRange( Bank_fixed ):
        raise UserWarning( "Bank is invalid.({})".format(Bank))

    UGH.SetFlagToAddTofBin(True)
    wfile = UGH.MakeTempWiringInfo()
    dfile = UGH.MakeTempDetectorInfo()
    #del UGH
    runNos = runNo.split(",")
    runNov = Manyo.MakeUInt4Vector()
    for a_run in runNos:
        runNov.push_back( int(a_run) )
    DAT = Manyo.ElementContainerMatrix()
    UGH.SetElementContainerMatrix(DAT,runNov,wfile,dfile,False,"/data","")
    del UGH


    """
    tt=mu.UtsusemiEventDataConverterNeunet()
    tt.LoadParamFiles( wfile, dfile )
    tt.SetHistAllocation()
    DAT = Manyo.ElementContainerMatrix()
    tt.SetElementContainerMatrix( DAT, runNo, "/data","" )
    del tt
    """

    pp=mu.UtsusemiReductionInEla(DAT)
    pp.CalcPhi()
    pp.KiKfCorrect()
    pp.dHWCorrect()
    #pp.NormBySolidAngle()
    del pp

    return DAT

#########################################
