# -*- coding: utf-8 -*-

#####################
## Command Sequence of Data Reduction
## 2010.11.10 ver 0.2 use GetHistogramOfEnergyTransfer
## 2010.05.18 ver 0.1
#####################

# special reserved word for commands history
from __future__ import print_function
HISTORY = None
# reserved words for return value in this.
DAT = None

import Manyo as mm
import Manyo.Utsusemi as mu
import utsusemi.ana.Reduction.BaseCommandsInEla as BaseCom
import utsusemi.DNA.ana.Reduction.BaseCommandsDNA as BaseComDNA
import re
import math
import datetime
import os
inst_code = mu.UtsusemiEnvGetInstCode()
if inst_code=="AMR":
    Def_NumOfPixel=120
    Def_L1=30.0
    Def_L2=4.0
    Def_dS=25.4*25.0
elif inst_code:
    Def_NumOfPixel=100
    Def_L1=18.03
    Def_L2=2.50
    Def_dS=25.4*19.0
elif inst_code:
    Def_NumOfPixel=100
    Def_L1=18.03
    Def_L2=2.50
    Def_dS=25.4*19.0
else:
    Def_NumOfPixel=100
    Def_L1=18.03
    Def_L2=2.50
    Def_dS=25.4*19.0
########################################
def CopyData(runno=10):
    """
    Copy EventData file from DAQ0 or DAQ1 into /data/SIK
    @param runno (int) First Run No of a measurement to be copied
    @retval None
    """
    BaseCom.CopyData(runno)

########################################
def GetDataOfWhite(runNo=197,startTOF=-1,endTOF=-1,binTOF=-1,MaskFile="mask.txt",NormFactor=1000000.0):
    """
    Load EventData and convert to histogram using corrections as below:
    - GetHistogram(runNo,startTOF=-1,endTOF=-1,binTOF=-1,startPSD=-1,endPSD=-1,pixelNo=100)
    - NormByBeamCurrent
    - DoMask
    - SolidAngleCorrection
    @param runNo      (int)    Run Number
    @param MaskFile   (string) file name for masking
    @param NormFactor (double) normalize factor data*factor/beamCurrent. if 0, do nothing.
    @retval DAT     (ElementContainerMatrix)
    """
    startPSD=-1
    endPSD=-1
    pixelNo=Def_NumOfPixel
    dat = BaseCom.GetHistogram(runNo,0,startTOF,endTOF,binTOF,startPSD,endPSD,pixelNo)
    if NormFactor!=0:
        BaseCom.NormByBeamCurrent(dat, NormFactor)
    BaseCom.DoMask(dat,MaskFile)
    BaseCom.SolidAngleCorrection(dat)

    return dat

#########################################
def GetDataOfMonochroEi(runNo=-1,Ei=0.0,Resolution=0.5,deltaE=0.0,L1=18.03,MaskFile="mask.txt",NormFactor=1000000.0):
    """
    Load EventData and convert to histogram using corrections as below:
    - GetHistogramBydE(runNo,Ei,Resolution=round(deltaE/Ei)/10,t0shift=0.0,L1,L2=2.5,NumOfPixel=100)
    - NormByBeamCurrent(DAT,NormFactor)
    - DoMask(DAT)
    - TofToEnergyTransfer(DAT,Ei,L1,t0shift=0.0,deltaE,EminRate=0.9,EmaxRate=0.9)
    - SolidAngleCorrection(DAT)
    - kikfCorrection(DAT)
    @param runNo    (int) Run Number
    @param Ei       (double) Incident Energy
    @param Resolution (double) Energy Resolution for tof binnings at Elastic Peak [%]
    @param deltaE   (double) Delta Energy Transfer [meV]
    @param L1       (double)  Distance between moderator to sample [m]
    @param MaskFile (string) file name for masking
    @param NormFactor (double) normalize factor data*factor/beamCurrent. if 0, do nothing.
    @retval DAT     ElementCotainerMatix as result
    """
    if (Ei<=0.0) or (deltaE<=0.0):
        raise UserWarning("ParameterError")
    
    #Resolution = round(deltaE/Ei)/10.0
    t0shift = 0.0
    L2 = Def_L2
    numOfPixel = Def_NumOfPixel
    EminRate = 0.9
    EmaxRate = 0.9
    
    dat = BaseCom.GetHistogramBydE(runNo,Ei,Resolution,t0shift,L1,L2,numOfPixel)
    if NormFactor!=0:
        BaseCom.NormByBeamCurrent(dat, NormFactor)
    BaseCom.DoMask(dat,MaskFile)
    BaseCom.SolidAngleCorrection(dat)
    BaseCom.TofToEnergyTransfer(dat,Ei,L1,t0shift,deltaE,EminRate,EmaxRate)
    BaseCom.KiKfCorrection(dat)

    return dat

#########################################
def GetDataOfMonochroEi2(runNo=-1,Ei=0.0,deltaE=0.0,Emin=0.0,Emax=0.0,MaskFile="mask.txt",NormFactor=1000000.0):
    """
    Load EventData and convert to histogram using corrections as below:
    - GetHistogramOfEnergyTransfer(runNo,Ei,dHW,hw_min,hw_max,startTime,endTime)
    - NormByBeamCurrent(DAT,NormFactor)
    - DoMask(DAT)
    - SolidAngleCorrection(DAT)
    - kikfCorrection(DAT)
    @param runNo    (int) Run Number
    @param Ei       (double) Incident Energy [meV]
    @param deltaE   (double) Delta Energy Transfer [meV]
    @param Emin     (double) minimum of Energy Transfer [meV]
    @param Emax     (double) maximum of Energy Transfer [meV]
    @param MaskFile (string) file name for masking
    @param NormFactor (double) normalize factor data*factor/beamCurrent. if 0, do nothing.
    @retval DAT     ElementCotainerMatix as result
    """
    if (Ei<=0.0) or (deltaE<=0.0):
        raise UserWarning("ParameterError")
        
    dat = BaseCom.GetHistogramOfEnergyTransfer(runNo,Ei,deltaE,Emin,Emax)
    if runNo!=0: ## [inamura 101115]
        if NormFactor!=0:
            BaseCom.NormByBeamCurrent(dat, NormFactor)
        BaseCom.DoMask(dat,MaskFile)
        BaseCom.SolidAngleCorrection(dat)
        BaseCom.KiKfCorrection(dat)

    return dat

##########################################
def ToPowder(dat=DAT,startQ=-1.0,endQ=-1.0,deltaQ=0.1):
    """
    Convert data from crystal to powder

    @param dat    (ElementContaienrMatrix)
    @param startQ (double) Q value of range; if minus, auto calculated
    @param endQ   (double) Q value of range; if minus, auto calculated
    @param deltaQ (double) binning of Q
    @retval ECM   (ElementContainerMatrix)
    """

    return BaseCom.ToPowder(dat,startQ,endQ,deltaQ)

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

def GetDataOfDNA(runNo=314,HwParam=" ",LambParam=" ",QParam=" ",TimeParam=" ",initFile="GetQEDataOfDNA.ini",outputData="QE",fileTag="_"):
    """
    Load EventData and convert to QE map
    - GetHistogramHW(runNo,dHW,hw_min,hw_max,tof_offset,startTime,endTime)
    - DoMask(DAT)
    - ILambdaCorrDNA(dat,ec)
    - SolidAngleCorrDNA(dat)
    - CreateQEMap(dat,startQ,endQ,deltaQ)

    @param runNo        (int) Run Number
    @param HwParam      (string)
    @param LambParam    (string)
    @param QParam       (string)
    @param TimeParam    (string)
    @param initFile     (string)
    @param fileTag      (string)   
    @retval ECM      (ElementContainerMatrix)
    """

    if outputData !="QE" and outputData !="HW" and outputData !="TOF" and outputData !="MON":
      print("outputData column : QE or HW or TOF or MON")
      return

    #search_dir="/home/dnaadmin/ana/setup"
    search_dir = os.path.join(mu.UtsusemiEnvGetUserDir(),"ana","setup") #[inamura 230330]
    filepath =os.path.join(search_dir,initFile) 

    useT0ModCorr      = SearchInitParamBool("useT0ModCorr",filepath)
    useMonEff         = SearchInitParamBool("useMonEff",filepath)
    useILambdaCorr    = SearchInitParamBool("useILambdaCorr",filepath)
    useMonNormalCorr  = SearchInitParamBool("useMonNormalCorr",filepath)
    useProtonNormCorr = SearchInitParamBool("useProtonNormCorr",filepath)
    useSolidAngleCorr = SearchInitParamBool("useSolidAngleCorr",filepath)
    useDetEff         = SearchInitParamBool("useDetEff",filepath)
    useAbsoCorr       = SearchInitParamBool("useAbsoCorr",filepath)
    useEffCorr        = SearchInitParamBool("useEffCorr",filepath)
    useFileOutput     = SearchInitParamBool("useFileOutput",filepath)
    filename          = SearchInitParamString("filename",filepath)
    laticetype        = SearchInitParamString("laticetype",filepath)
    sampletype        = SearchInitParamString("sampletype",filepath)
    sampleDataFile    = SearchInitParamString("sampleDataFile",filepath)
    factor            = float(SearchInitParamString("factor",filepath))
    t0_offset         = float(SearchInitParamString("t0_offset",filepath))
    background        = float(SearchInitParamString("background",filepath))
    useFileOutput     = SearchInitParamBool("useFileOutput",filepath)
    #T. Yamada Added [121123]
    UseFastChopper    = SearchInitParamBool("UseFastChopper",filepath)
    #T.Yamada End [121123]


    useEiConv = True

    QParamList = QParam.split(",")
    if len(QParamList)==3:
            startQ = float(QParamList[0])
            endQ = float(QParamList[1])
            deltaQ = float(QParamList[2])
    else:
            startQ = 0.0
            endQ = 3.0
            deltaQ = 0.05
    if outputData != "MON":
        if outputData == "TOF":
           #DAT = BaseComDNA.GetHistogram(runNo,0,-1,-1,-1,-1,-1,100) T. Yamada Comment out [121123]
           DAT = BaseComDNA.GetHistogram(runNo,0,-1,-1,-1,-1,-1,120) #T.Yamada Modified [121123]
           return DAT
        if laticetype == "111":
           #DAT = BaseComDNA.GetHistogramHW(runNo,HwParam,LambParam,t0_offset,useT0ModCorr,TimeParam,L1) T. Yamada Comment out[121123]
           DAT = BaseComDNA.GetHistogramHW(runNo,HwParam,LambParam,t0_offset,useT0ModCorr,TimeParam,UseFastChopper=UseFastChopper) # T. Yamada Modified[121123]
        elif laticetype == "333":
           #DAT = BaseComDNA.GetHistogramHW333(runNo,HwParam,LambParam,t0_offset,useT0ModCorr,TimeParam,L1) T. Yamada Comment out [121123]
            DAT = BaseComDNA.GetHistogramHW333(runNo,HwParam,LambParam,t0_offset,useT0ModCorr,TimeParam,UseFastChopper=UseFastChopper) # T. Yamada Modified[121123]
        else:
           return
        if outputData == "HW":
           print("ttt")
           return DAT
        BaseComDNA.DoMask(DAT, filename)
    #EC = BaseComDNA.GetMonHistogram(runNo,useEiConv,LambParam,t0_offset,background,useT0ModCorr,TimeParam) T. Yamada Comment out [121123]
    EC = BaseComDNA.GetMonHistogram(runNo,useEiConv,LambParam,t0_offset,background,useT0ModCorr,TimeParam,UseFastChopper) #T. Yamada Modified [121123]

    if outputData == "MON":
        return EC

    BaseComDNA.MutiplyConstant(EC,factor)

    if useMonNormalCorr:
        SumEC = sum(EC.PutY())
        BaseComDNA.MutiplyConstant(DAT,1/SumEC/factor)
        print("Monitor Normalize factor * factor = {}".format(SumEC*factor))

    if useProtonNormCorr:
        bc=BaseComDNA.GetRunInfoTime(runNo,TimeParam)
        BaseComDNA.MutiplyConstant(DAT,1/bc/factor)
        print("ProtonCurrent Normalize factor * factor = {}".format(bc*factor))

    if useILambdaCorr:
        ECM = BaseComDNA.ILambdaCorrDNA(DAT, EC, useMonEff)
    else:
        ECM = DAT

    if useSolidAngleCorr:
        ECM2 = BaseComDNA.SolidAngleCorrDNA(ECM, useDetEff, useAbsoCorr,useEffCorr,sampletype,sampleDataFile)
        BaseComDNA.MutiplyConstant(ECM2,1e-6) #T. Yamada Add [121123]
    else:
        ECM2 = ECM
    ECA = BaseComDNA.CreateQEMap(ECM2,startQ,endQ,deltaQ)

    if useFileOutput:
        if (fileTag=="_"):
            BaseComDNA.OutputECA(ECA, "_"+outputData)
            BaseComDNA.OutputECAText(ECA, "_"+outputData)
        else:
            BaseComDNA.OutputECA(ECA, "_"+outputData+"_"+fileTag)
            BaseComDNA.OutputECAText(ECA, "_"+outputData+"_"+fileTag)

    return ECA

#########################################
#T.Yamada [130122]
def GetDataOfDNAElasticScan(runNo=2175,FastChopperUse = True, Analyzer = 111, Time=" ",TempCh = "C2", Temperature=" ", QEReduction=True):
    """
    Get ElasticScan Data
    @param runNo        (int) Run Number
    @FastChopperUse     (bool) Use Fast Chopper
    @Analyzer           (int) Select Si Analyzer 111 or 333
    @Time               (string) time(start), time(end), time(delta)
    @TempCh             (string) temperature Channel A , B, C ,C2, D, or D2 in LS340
    @Temperature        (string) temperature(start), temperature(end), temperature(delta)
    @QEReduction        (bool) Data Reduction 
    @retval EC      (ElementContainerMatrix)
    """
    if Analyzer == 111:
        #---LambdaParam
        LambdaCenter = 6.321
        dLambda = 4.15 #3.0 T.Yamada [130516]
        #---QParam
        Qmin = 0.0
        Qmax = 2.0
        dQ = 0.1
        if FastChopperUse:
            #---HWParam
            Emin = -0.01
            Emax = 0.01
            dE = 0.005
            #---condition file
            #inifile = "GetQEDataOfDNAElasticScan.ini" #the path is "~/ana/setup
            inifile = "GetQEDataOfDNAElasticScanMulth.ini" #the path is "~/ana/setup
        else:
            #---HWParam
            Emin = -0.2
            Emax = 0.05
            dE = 0.05
            #---condition file
            inifile = "GetQEDataOfDNAElasticScanLowResoEMulth.ini" #the path is "~/ana/setup
    elif Analyzer == 333:
        #---LambdaParam
        LambdaCenter = 3.4 # 3 T.Yamada [130516]
        dLambda = 4.16 #3.0 T.Yamada[130516]
        #---QParam
        Qmin = 0.0
        Qmax = 6.0
        dQ = 0.15 #0.1 T.Yamada[130516]

        if FastChopperUse:
            #---HWParam
            Emin = -0.01
            Emax = 0.01
            dE = 0.005
            #---condition file
            inifile = "GetQEDataOfDNAElasticScan.ini" #the path is "~/ana/setup
        else:
            #---HWParam
            Emin = -0.2
            Emax = 0.05
            dE = 0.05
            #---condition file
            inifile = "GetQEDataOfDNAElasticScanLowResoE.ini" #the path is "~/ana/setup

        raise  UserWarning("condition has not been made yet.")
    else:
        raise  UserWarning("input 111 or 333")

    LambdaParam = "%.4f,%.4f" %(LambdaCenter,dLambda)
    HWParam ="%f,%f,%f" %(dE,Emin,Emax)
    HWParam2 ="%f,%f" %(Emin,Emax)
    QParam = "%.3f,%.3f,%.3f" %(Qmin,Qmax,dQ)
    print("HWParam:{} {}".format(HWParam, HWParam2))
    print("LambdaParam:{}".format(LambdaParam))
    print("QParam:{}".format(QParam))

    print("TimeParam: {}".format(Time))
    print("TempCh: {}".format(TempCh))
    print("TempParam: {}".format(Temperature))

#    dataPath = "/usr/local/mlf/DNA/tmp/" T. Yamada[130218]
#    dataPath = "/home/dnaadmin/DNA/tmp/" #T.Yamada[130218]
    dataPath = os.path.join(mu.UtsusemiEnvGetUserDir(),"DNA","tmp") #[inamura 230330]
    ECMbstName = "ECM_%d_ES.bst" %(runNo)
    ESName = "DRRun%dES.txt" % (runNo)
    TIName = "DRRun%dTI.txt" % (runNo)

    ECMbstCheck = os.path.exists(dataPath+ECMbstName)
    ECMbstCheck = os.path.exists(os.path.join(dataPath, ECMbstName))
    print("ECMCheck:{}".format(ECMbstCheck))

    import ElasticScan

    if QEReduction or ECMbstCheck == False :
        print("ECM make start")
        #ECM = ElasticScan.GetQETimeECM(runNo, HWParam, LambdaParam, QParam, Time, inifile) T.Yamada[130304]
        ECM = ElasticScan.GetQETimeECMMulth(runNo, HWParam, LambdaParam, QParam, Time, inifile)
        print("ECM make end")
    ECM = ElasticScan.ReadECM(ECMbstName)
    EC = ElasticScan.ElasticScanTotalIntensity(ECM, HWParam2, QParam, inifile)
    EC2 = ElasticScan.ElasticScanCheckTempNew(EC, TempCh)
    EC4 = ElasticScan.ElasticScanXAxisChangeToTemp(EC, EC2, Temperature)
    ElasticScan.OutputECText(EC, "Run"+str(runNo)+"TItime.txt")
    ElasticScan.OutputECText(EC2,"TItemp.txt")
    ElasticScan.OutputECText(EC4, TIName)
    ECA = ElasticScan.ElasticScanQ2LnI(ECM, HWParam2, QParam, inifile)
    EC1 = ElasticScan.ElasticScanFit(ECA, "p1")
    EC3 = ElasticScan.ElasticScanXAxisChangeToTemp(EC1, EC2, Temperature)
    ElasticScan.OutputECText(EC1, "u2time.txt")
    ElasticScan.OutputECText(EC3, ESName)

    return EC3


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

def SearchInitParamBool(paramstring,filepath):
    f=open(filepath)
    lines = f.readlines()
    f.close()

    for line in lines:
        flug1 = re.search(paramstring, line)
        if flug1:
            if re.search("#", line):
                line = line.split("#")[0]
            flug2 = re.search("True",line)
            if flug2:
                print(paramstring,"\t: True")
                return True
            else:
                print(paramstring,"\t: False")
                return False

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

def SearchInitParamString(paramstring,filepath):
    f=open(filepath)
    lines = f.readlines()
    f.close()
    result =""
    for line in lines:
        flug1 = re.search(paramstring, line)
        if flug1:
            if re.search("#", line):
                line = line.split("#")[0]
            if re.search("\n", line):
                line = line.split("\n")[0]
            flug2 = re.search(" ", line)
            if flug2:
                linelist =line.split(" ")
                for i in range(len(linelist)):
                    if linelist[i]!="" and linelist[i]!=paramstring:
                         result = linelist[i]
                         print(paramstring,"\t:",result)
    return result


# Dictionary for entry the name of functions
_functions = {
               "CopyData":CopyData,
               "GetDataOfWhite":GetDataOfWhite,
               "GetDataOfMonochroEi":GetDataOfMonochroEi,
               "GetDataOfMonochroEi2":GetDataOfMonochroEi2,
               "ToPowder":ToPowder,
               "GetDataOfDNA":GetDataOfDNA,
               "GetDataOfDNAElasticScan":GetDataOfDNAElasticScan
             }
         
