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

from __future__ import print_function
import time
import os
import Manyo
import Manyo.MLF as mm
import Manyo.Utsusemi as mu
import math
import numpy as np
from utsusemi.ana.Reduction.BaseCommands import *
from scipy.optimize import curve_fit

#########################################
# BaseCommands for Inelastic
#########################################

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


def PeakPosFit(ec, initial, ProfType):
    """
    Get peak position by Gaussian fit  (R.Kajimoto)
    @param ec       (ElementContainer)
    @param initial  (double) initial guess
    @param ProfType (int) profile type. 1: Gaussian, 2: split pseudo Voigt
    """
    def gauss(x, height, center, fwhm, BG):
        return height * np.exp(-1. * np.log(2.) * (x - center)**2 / (fwhm / 2.)**2) + BG

    def split_pseudo_voigt(x, height, center, fwhm, BG, eta_h, eta_l, A):
        eta_h = abs(eta_h)
        eta_l = abs(eta_l)
        A = abs(A)

        def func_l(x, center, fwhm, eta_h, eta_l, A):
            SqrtPiLn2 = np.sqrt(np.pi * np.log(2.))
            C = (1 + A) * (eta_h + SqrtPiLn2 * (1 - eta_h)) / (eta_l + SqrtPiLn2 * (1 - eta_l) + A * (eta_h + SqrtPiLn2 * (1 - eta_h)))
            LorentzPart = eta_l * 2. / (np.pi * fwhm) / (1. + ((1 + A) / A)**2 * ((x - center) / fwhm)**2)
            GaussPart = (1 - eta_l) * 2. * np.sqrt(np.log(2.)) / (np.sqrt(np.pi) * fwhm) * np.exp(-1. * np.log(2.) * ((1 + A) / A)**2 * ((x - center) / fwhm)**2)
            return C * (LorentzPart + GaussPart)

        ret = np.where((x - center) < 0,
                       height * func_l(x, center, fwhm, eta_h, eta_l, A) + BG,
                       height * func_l(x, center, fwhm, eta_l, eta_h, (1. / A)) + BG)

        return ret

    xx = ec.PutX()  # x-values are histogram bin boundaries
    xlist = []
    for i in range(xx.size() - 1):  # change x-values to bin centers
        xlist.append((xx[i] + xx[i + 1]) / 2.0)
    xarray = np.array(xlist)
    yarray = np.array(ec.PutYList())

    # initial guess of the fitting parameters
    height0 = np.max(yarray)
    BG0 = np.min(yarray)
    for i in range(xarray.size):
        if (yarray[i] > (height0 / 2.0)):
            half_maximum0 = xarray[i]
            break
    for i in reversed(range(xarray.size)):
        if (yarray[i] > (height0 / 2.0)):
            half_maximum1 = xarray[i]
            break
    fwhm0 = half_maximum1 - half_maximum0

    xfit = np.linspace(np.min(xarray), np.max(xarray), 500, endpoint=False)

    # curve fit
    if (ProfType == 1):  # Gaussian
        init_param = np.array([height0, initial, fwhm0, BG0])
        popt, pcov = curve_fit(gauss, xarray, yarray, p0=init_param)
        stdE = np.sqrt(np.diag(pcov))  # errors
        height_fit, center_fit, fwhm_fit, BG_fit = popt
        height_error, center_error, fwhm_error, BG_error = stdE
#        yfit = gauss(xarray, *popt)
        yfit = gauss(xfit, *popt)
    if (ProfType == 2):  # split pseudo Voigt
        eta_h0 = 0.1
        eta_l0 = 0.1
        A0 = 1.0
        height0 = height0 / (2. * np.sqrt(np.log(2.)) / (np.sqrt(np.pi) * fwhm0))
        init_param2 = np.array(
            [height0, initial, fwhm0, BG0, eta_h0, eta_l0, A0])

        popt, pcov = curve_fit(
            split_pseudo_voigt, xarray, yarray, p0=init_param2)
        stdE = np.sqrt(np.diag(pcov))  # errors
        height_fit, center_fit, fwhm_fit, BG_fit, eta_h_fit, eta_l_fit, A_fit = popt
        height_error, center_error, fwhm_error, BG_error, eta_h_error, eta_l_error, A_error = stdE
#        yfit = split_pseudo_voigt(xarray, *popt)
        yfit = split_pseudo_voigt(xfit, *popt)

    # print(popt)
    # print(stdE)
    # print(pcov)

    # import matplotlib.pyplot as plt
    # plt.plot(xarray, yarray)
    # plt.plot(xarray, yfit)
    # plt.show()

    ec_fit = Manyo.ElementContainer()
#    ec_fit.Add( "x", xx )
    ec_fit.Add("x", xfit.tolist())
    ec_fit.Add("y", yfit.tolist())
    ec_fit.Add("e", (yfit * 0).tolist())
    ec_fit.SetKeys("x", "y", "e")
    ec_fit.AddToHeader("Label", "Fit")
    # ec_fit.Dump()

    return center_fit, center_error, ec_fit

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


def GetMultiEi2(runNo="0", expEi="0.0", PSD="96,159", Pixel="30,70", Range=5.0, deltaE=0.1, PlotFlag=1, ProfType=2):
    """
    Get Incident Energy from raw event data after converting it to energy histogram (R.Kajimoto)
    @param runNo (string) run number
    @param expEi (string) initial Ei or multi Ei with comma as separater
    @param PSD   (string) range of PSDs to be used for fitting
    @param Pixel (string) range of Pixels to be used for fitting
    @param Range (double) range [%] relative to Ei used for fitting
    @param deltaE (double) Energy bin [%] relative to Ei
    @param PlotFlag (int) if 1, plot graph
    @param ProfType (int) profile type. 1: Gaussian, 2: Toraya's split pseudo Voigt function
    @retval None
    """
    if runNo == 0:
        raise UserWarning("No set runNo.")
    Ei_list_str = expEi.split(',')
    if len(Ei_list_str) <= 0:
        raise UserWarning("expEi is empty.")

    Ei_list = []
    for item in Ei_list_str:
        Ei = float(item)
        if Ei > 0.0:
            Ei_list.append(float(item))
    print("Ei = {}".format(Ei_list))

    PSD_list_str = PSD.split(',')
    if (len(PSD_list_str) == 1):
        minPsd = maxPsd = int(PSD_list_str[0])
    elif len(PSD_list_str) == 2:
        minPsd = int(PSD_list_str[0])
        maxPsd = int(PSD_list_str[1])
    else:
        raise UserWarning("Too many parameters in PSD argument")

    Pixel_list_str = Pixel.split(',')
    if len(Pixel_list_str) == 1:
        minPixel = maxPixel = int(Pixel_list_str[0])
    elif len(Pixel_list_str) == 2:
        minPixel = int(Pixel_list_str[0])
        maxPixel = int(Pixel_list_str[1])
    else:
        raise UserWarning("Too many parameters in Pixel argument")

    if maxPsd < 0:
        maxPsd = minPsd

    if PlotFlag == 1:
        try:
            import uGao.MPlot as mp
        except:
            import vis.MPlot as mp
        pp = mp.MPlot()
        pp.SetXLabel("Energy")
        pp.SetYLabel("Intensity")
        color_list = ["b", "g", "r", "c", "m", "y", "k"]

    EminRate = Range / 100.0
    EmaxRate = Range / 100.0

    FixedEi_list = []
    FixedEiError_list = []
    for num_of_Ei, Ei in enumerate(Ei_list):
        first_energy = Ei - (Ei * EminRate)
        last_energy = Ei + (Ei * EmaxRate)
        if first_energy < 0:
            first_energy = 0.0

        bin_energy = Ei * deltaE / 100.0

        print("Ei={:.3f}, dE=+-{:.3f}, Ebin={:.3f} ".format(Ei,
                                                            (Ei * EminRate), bin_energy))

        runNo = str(runNo)
        HistParam = "energy,{:f},{:f},{:f}".format(
            first_energy, last_energy, bin_energy)
        DetRange = "{:d}-{:d}".format(minPsd, maxPsd)
        DAT = GetNeunetHist(runNo=runNo, HistParam=HistParam,
                            DetParam="psd", DetRange=DetRange)
        EC = SumOfPixel(Target=DAT, PSD_min=minPsd, PSD_max=maxPsd,
                        Pixel_min=minPixel, Pixel_max=maxPixel)
        EC.AddToHeader("RUNNUMBER", runNo)
        # EC.Dump()

        FixedEi = 0.0
        error = 0.0
        FixedEi, error, EC_fit = PeakPosFit(EC, Ei, ProfType)
        try:
            FixedEi, error, EC_fit = PeakPosFit(EC, Ei, ProfType)
        except:
            print("Fit Faled")
            try:
                import uGao.MPlot as mp
            except:
                import vis.MPlot as mp
            p = mp.MPlot(EC)

        if PlotFlag == 1:
            plot_color = color_list[num_of_Ei % 7]
            pp.AddData([EC, EC_fit])
            pp.SetPlotParam((num_of_Ei * 2) + 1, lc=plot_color)
            pp.SetPlotParam((num_of_Ei + 1) * 2, ls="-",
                            lc=plot_color, mk="", eb=False)

        FixedEi_list.append("{:.3f}+-{:.3f}".format(FixedEi, error))

    print("=======================================")
    for (iEi, fEi) in zip(Ei_list, FixedEi_list):
        print("Input Incident Energy, Calculated Incident Energy = {:.3f}, {}".format(
            iEi, fEi))
    print("=======================================")

    if PlotFlag == 1:
        subtitle = "Ei [meV] = " + ', '.join(FixedEi_list)
        pp.SetSubTitle(subtitle)

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


def GetEiFromEvent(runNo=0, expEi="0.0", PSD="-1", PIXEL="-1", NumOfPixel=100, Resolution=0.5, PlotFlag=0):
    """
    Get Incident Energy from raw event data
    @param runNo (int) run number
    @param expEi (string) Initial Ei or multi Ei with comma as separater
    @param PSD   (string) range of PSDs to be used for fitting
    @param PIXEL (string) range of Pixels to be used for fitting
    @param NumOfPixel (int) the number of pixels in one PSD
    @param Resolution (double) resolution [%] for tof binning
    @param PlotFlag (int) if 1, plot graph
    @retval None
    """
    if runNo == 0:
        raise UserWarning("No set runNo.")
    Ei_list_str = expEi.split(',')
    if len(Ei_list_str) <= 0:
        raise UserWarning("expEi is empty.")

    Ei_list = []
    for item in Ei_list_str:
        Ei = float(item)
        if Ei > 0.0:
            Ei_list.append(float(item))
    print("Ei = {}".format(Ei_list))

    PSD_list_str = PSD.split(',')
    if (len(PSD_list_str) == 1):
        minPsd = maxPsd = int(PSD_list_str[0])
    elif len(PSD_list_str) == 2:
        minPsd = int(PSD_list_str[0])
        maxPsd = int(PSD_list_str[1])
    else:
        raise UserWarning("Too many parameters in PSD argument")

    PIXEL_list_str = PIXEL.split(',')
    if len(PIXEL_list_str) == 1:
        minPixel = maxPixel = int(PIXEL_list_str[0])
    elif len(PIXEL_list_str) == 2:
        minPixel = int(PIXEL_list_str[0])
        maxPixel = int(PIXEL_list_str[1])
    else:
        raise UserWarning("Too many parameters in Pixel argument")

    if maxPsd < 0:
        maxPsd = minPsd

    if PlotFlag == 1:
        import uGao.MPlot as mp
        pp = mp.MPlot()
    # import utsusemi.ana.Reduction.Histogram as HH ##[inamura 150917]
    import utsusemi.ana.Reduction.MonitorAnalysis as MON
    from math import sqrt
    paraFlag = 0
    # L1=Def_L1
    # L2=Def_L2
    GNH = mu.UtsusemiGetNeunetHistogram()
    GNH.SetRunNo(runNo)
    L1 = GNH.PutL1() / 1000.0
    L2 = GNH.PutTypicalL2() / 1000.0

    EminRate = 0.2
    EmaxRate = 0.2
    t0shift = 0.0

    uc = mu.UtsusemiUnitConverter()

    FixedEi_list = []
    for Ei in Ei_list:
        first_tof = uc.LEtoT(L1, Ei) + uc.LEtoT(L2,
                                                (Ei + (Ei * EminRate))) + t0shift
        last_tof = uc.LEtoT(L1, Ei) + uc.LEtoT(L2,
                                               (Ei - (Ei * EmaxRate))) + t0shift
        if first_tof < 0:
            first_tof = 0.0

        t_Ei = uc.LEtoT((L1 + L2), Ei)
        t_dE = uc.LEtoT(L1, Ei) + uc.LEtoT(L2, (Ei - (Ei * float(Resolution) / 100.0)))

        binTOF = int(abs(t_dE - t_Ei))
        if binTOF < 1:
            binTOF = 1

        print("Ei=%f, dE=%f, binTOF=%f " % (Ei, (Ei * Resolution / 100.0), binTOF))

        # DAT = HH.GetHistDTconst(runNo,first_tof,last_tof,binTOF,minPsd,maxPsd,NumOfPixel)
        # [inamura 151029]-->
        """
        DAT = HH.GetHistogramOfConv( runNo=runNo,
                                     ConvType=2,
                                     Params=[first_tof,last_tof,binTOF],
                                     detectorRange=[minPsd,maxPsd],
                                     numOfPixel=NumOfPixel,
                                     DetType="PSD"
                                     )
        """
        runNo = str(runNo)
        HistParam = "tof,%f,%f,%f" % (first_tof, last_tof, binTOF)
        DetParam = "psd"
        range_psd_min = int(minPsd / 8.) * 8
        range_psd_max = (int(maxPsd / 8.) + 1) * 8 - 1
        DetRange = "%d-%d:%d" % (range_psd_min, range_psd_max, NumOfPixel)
        DAT = GetNeunetHist(runNo=runNo,
                            HistParam=HistParam,
                            DetParam=DetParam,
                            DetRange=DetRange)
        # <--[inamura 151029]

        psd_v = Manyo.MakeUInt4Vector()
        pix_v = Manyo.MakeUInt4Vector()
        sum_Lp = 0.0
        num_of_sum = 0
        # print "Psd region = %d,%d" % (minPsd,maxPsd)
        # print "Pixel region = %d,%d" % (minPixel,maxPixel)
        search = Manyo.SearchInHeader(DAT)

        for ipsd in range(maxPsd - minPsd + 1):
            search.SearchArray("PSDID", (minPsd + ipsd))
            vect_index = search.PutResultIndex(0)
            if vect_index.size() == 0:
                print("Failed to find PSDID=%d" % (minPsd + ipsd))
                continue
            retID = vect_index[0]
            for ipixel in range(minPixel, (maxPixel + 1)):
                hh_mon = DAT(retID, ipixel).PutHeaderPointer()
                psd_v.append(retID)
                pix_v.append(ipixel)
                p_vec = hh_mon.PutDoubleVector("PixelPosition")
                sum_Lp += L1 * 1000.0 + sqrt(p_vec[0] * p_vec[0] + p_vec[1] * p_vec[1] + p_vec[2] * p_vec[2])
                num_of_sum += 1

        del search  # [inamura 120630]

        ave_Lp = sum_Lp / float(num_of_sum)

        avv = mm.AverageElementContainerMatrix(DAT, psd_v, pix_v)
        ec = Manyo.ElementContainer()
        if avv.GetAverage(ec):
            pass
        else:
            raise UserWarning("GetEiFromEvent > Failed GetAverage")
        if PlotFlag == 1:
            pp.AddData(ec)

        # detector as monitor at 18030.0+2500.0[mm] from moderator
        LenMon = [ave_Lp]

        header_arr = Manyo.HeaderBase()
        header_arr.Add("MASKED", 0)
        header_arr.Add("TYPE", "MONITOR")
        maskedEC = Manyo.MakeInt4Vector()
        maskedEC.append(-1)
        header_arr.Add("MASKEDElementContainer", maskedEC)
        header_arr.Add("SETEI", Ei)

        MonitorArr = Manyo.ElementContainerArray(header_arr)

        ret_list = []
        for i in range(len(LenMon)):
            header_mon = Manyo.HeaderBase()
            # header_mon.Add( "PIXELID", 99999999)
            header_mon.Add("MonitorId", i)
            header_mon.Add("LM", LenMon[i])
            header_mon.Add("Label", "M" + str(i))
            pVect = Manyo.MakeDoubleVector(3)
            pVect[0], pVect[1], pVect[2] = 0.0, 0.0, LenMon[i]
            header_mon.Add("PixelPosition", pVect)

            ec_mon = Manyo.ElementContainer(header_mon)
            ec_mon.Add("TOF", ec.PutX(), "microsecond")
            ec_mon.Add("Intensity", ec.PutY(), "neutrons")
            ec_mon.Add("Error", ec.PutE(), "neutrons")
            ec_mon.SetKeys("TOF", "Intensity", "Error")

            MonitorArr.Add(ec_mon)

        DAT.Add(MonitorArr)

        EI = 0.0
        mon = MON.MonitorAnalysis(DAT, Ei, t0shift, 0)
        try:
            mon.SearchPeakPosition(0)
            EI, unit = mon.PutIncidentEnergy()
        except:
            print("Fales")
            import uGao.MPlot as mp
            p = mp.MPlot(ec)

        FixedEi_list.append(EI)

    for (iEi, fEi) in zip(Ei_list, FixedEi_list):
        print("Input Incident Energy, Calclated Incident Energy )=( {}, {} )".format(
            iEi, fEi))

    del uc  # [inamura 120630]

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


def GetEi(dat, expEi=50.0, MonPsd=0, MonPixel=0, L1=18.03, T0shift=0.0, FittingType=0, Debug=0):
    """
    Get Incident Energy from Monitor Counter data
    @param  dat          (ElementContainerMatrix)
    @param  expEi        (Double)  expected incident energy
    @param  MonPsd       (int) PSD ID to be used as monitor
    @param  MonPixel     (int) Pixel No to be used as monitor
    @param  L1           (double) Distance between moderator to sample [m]
    @param  T0shift      (double) T0 offset [micro-sec]
    @param  FittingType  (UInt4)  Gaussian:0
    @param  Debug        (UInt4)  OFF:0, ON:1
    """
    print("---------")
    print("Monitor analysis ")
    print("------")

    SIH = Manyo.SearchInHeader(dat)
    SIH.SearchArray("PSDID", MonPsd)
    PSD_list = SIH.PutResultIndex(0)
    del SIH

    if PSD_list.size() != 0:
        print("Monitor Pixel = {}, {}".format(PSD_list[0], MonPixel))
        MonData = dat.Put(PSD_list[0]).Put(MonPixel)
        hh_mon = MonData.PutHeader()
        p_vec = hh_mon.PutDoubleVector("PixelPosition")
        from math import sqrt, exp
        l_p = L1 * 1000.0 + sqrt(p_vec[0] * p_vec[0] + p_vec[1] * p_vec[1] + p_vec[2] * p_vec[2])
        # detector as monitor at 18030.0+2500.0[mm] from moderator
        LenMon = [l_p]

        header_arr = Manyo.HeaderBase()
        header_arr.Add("MASKED", 0)
        header_arr.Add("TYPE", "MONITOR")
        maskedEC = Manyo.MakeInt4Vector()
        maskedEC.append(-1)
        header_arr.Add("MASKEDElementContainer", maskedEC)
        header_arr.Add("SETEI", expEi)

        MonitorArr = Manyo.ElementContainerArray(header_arr)

        ret_list = []
        for i in range(len(LenMon)):
            header_mon = Manyo.HeaderBase()
            # header_mon.Add( "PIXELID", 99999999)
            header_mon.Add("MonitorId", i)
            header_mon.Add("LM", LenMon[i])
            header_mon.Add("Label", "M" + str(i))
            pVect = Manyo.MakeDoubleVector(3)
            pVect[0], pVect[1], pVect[2] = 0.0, 0.0, LenMon[i]
            header_mon.Add("PixelPosition", pVect)

            ec_mon = Manyo.ElementContainer(header_mon)
            ec_mon.Add("TOF", MonData.PutX(), "microsecond")
            ec_mon.Add("Intensity", MonData.PutY(), "neutrons")
            ec_mon.Add("Error", MonData.PutE(), "neutrons")
            ec_mon.SetKeys("TOF", "Intensity", "Error")

            MonitorArr.Add(ec_mon)

        dat.Add(MonitorArr)
    else:
        hh = dat.PutHeaderPointer()
        if hh.CheckKey("Ei") == 1:
            hh.OverWrite("Ei", extEi)
        else:
            hh.Add("Ei", extEi)
        msg = "Cannot find PixelID=(%s)" % (MonPixel)
        print(msg)
        raise UserWarning(msg)

    import utsusemi.ana.Reduction.MonitorAnalysis as MON

    mon = MON.MonitorAnalysis(dat, expEi, T0shift, Debug)
    mon.SearchPeakPosition(0)
    EI, unit = mon.PutIncidentEnergy()
    print("( Incident energy, unit )= ( {}, {} )".format(EI, unit))

    hh = dat.PutHeaderPointer()
    if hh.CheckKey("Ei") == 1:
        hh.OverWrite("Ei", EI)
    else:
        hh.Add("Ei", EI)
    if hh.CheckKey("L1") == 1:
        hh.OverWrite("L1", L1)
    else:
        hh.Add("L1", L1)
    if hh.CheckKey("T0shift") == 1:
        hh.OverWrite("T0shift", T0shift)
    else:
        hh.Add("T0shift", T0shift)

    # [microsec] : peak position at Monitor 1 in TOF
    dat.PeakPosi_m1 = mon.PutPeakPosi(0)
    # [microsec] : peak width at Monitor 1 in TOF
    dat.PeakWidth_m1 = mon.PutPeakWidth(0)
    print("PeakPosi,PeakWidth= {}, {}".format(
        mon.PutPeakPosi(0), mon.PutPeakWidth(0)))

    del mon

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


def BoseFactorCorrection(dat, T=300.0):
    """
    Functon to do correction of Bose Factor

    @param dat (ElementContainerMatrix)
    @param T   (double)  [K]
    """
    # PROCESS = "BoseFactorCorrection"
    # ret = CheckDataProcess(dat,PROCESS)

    # bfc = mu.BoseFactorChoppers( dat, T )
    # bfc.DoCorrection()
    URI = mu.UtsusemiReductionInEla(dat)
    if URI.BoseFactorCorrect(T):
        pass
    else:
        raise UserWarning("Failed BoseFactorCorrection.")


##########################################
def BoseFactCorrEC(dat, T=300.0):
    """
    Functon to do Bose Factor correction on ElementContainer

    @param dat (ElementContaienr)
    @param T   (double) [K]

    """
    # PROCESS = "BoseFactCorr"
    # ret = BC.CheckDataProcess(dat,PROCESS)

    # import BoseFactor as BF
    # bf = BF.BoseCorrect(dat,T)

    # Add Header Info
    # SS = PROCESS+"(dat,T=%f)" % (T)
    # hh = dat.PutHeaderPointer()
    # process_vect = hh.PutStringVector("DATAPROCESSED")
    # process_vect.append(SS)
    # hh.OverWrite("DATAPROCESSED",process_vect)
    URI = mu.UtsusemiReductionInEla()
    if isinstance(dat, Manyo.ElementContainer):
        if URI.BoseFactorCorrectEC(dat, T):
            return
        else:
            raise UserWarning("Failed BoseFactorCorrection.")
    else:
        raise UserWarning(
            "Failed BoseFactorCorrection. Data must be ElementContainer")

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


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

    @param dat    (ElementContaienrMatrix)
    @param startQ (double) Q value of range;if -1, auto calculated
    @param endQ   (double) Q value of range;if -1, auto calculated
    @param deltaQ (double) binning of Q
    @retval ECM   (ElementContainerMatrix)
    """
    PROCESS = "ToPowder"
    # ret = CheckDataProcess(dat,PROCESS)
    # if mu.CheckDataProcessed(dat,PROCESS):
    #    return dat
    if not CheckDataProcess(dat, "TOF TO ENERGY TRANSFER"):
        msg = "ToPowder >> This data is invarid for ToPowder"
        print(msg)
        raise UserWarning(msg)
    # import utsusemi.ana.Reduction.ToPowder as TP
    # ecm = TP.ToPowder(dat,startQ,endQ,deltaQ)

    # TPC = mu.ToPowderChoppers( dat )
    # ecm = TPC.Execute( startQ, endQ, deltaQ )
    # del TPC ##[inamura 120630]
    URI = mu.UtsusemiReductionInEla(dat)
    ecm = Manyo.ElementContainerMatrix()
    URI.ToPowder(ecm, deltaQ, startQ, endQ)
    del URI
    # Add Header Info
    SS = PROCESS + "(dat,startQ=%f,endQ=%f,deltaQ=%f)" % (startQ, endQ, deltaQ)
    hh = ecm.PutHeaderPointer()
    process_vect = hh.PutStringVector("DATAPROCESSED")
    process_vect.append(SS)
    hh.OverWrite("DATAPROCESSED", process_vect)

    return ecm


##########################################
def PowderSQE(runNo="0", Ei=0.0, deltaE=0.0, Erange="0.0 0.0", deltaQ=0.1, Qrange="-1.0 -1.0", TimeSlice="-1.0 -1.0", MaskFile="default", NormFactor=1000000.0, TimeDepBack="TOF:None", Vpath="/home/sikuser/user/template/vanadium_correction/", Vfile="None", VintegRange="All", VpixelRange="2:97", DetEffi="None"):
    """
    Load EventData and convert to powder-averaged S(Q,E) with the vanadium correction. This includes:
    - GetDataOfMonoChroEi3(): convert to histogram
    - LadDataFromDump(): load vanadium data
    - RadialCollimatorCorrectSIK(): correct intensity unevenness due to the radial collimator
    - ToPowder(): powder average
    @param runNo    (string) Run Number(s) "<run1>[,<run2>,...]"(delimitor is comma or space)
    @param Ei       (double) Incident Energy [meV]
    @param deltaE   (double) Delta Energy Transfer [meV]
    @param Erange   (string) min and max of Energy Transfer [meV] "<min>,<max>"(delimitor is comma or space)
    @param deltaQ   (double) binning of Q
    @param Qrange   (string) min and max of Q "<min>,<max>"(delimitor is comma ro space)
    @param TimeSlice(string) start time and end time [seconds] "<min>,<max>"(delimitor is comma or space)
    @param MaskFile (string) file name for masking
    @param NormFactor (double) normalize factor data*factor/beamCurrent. if 0, do nothing.
    @param TimeDepBack (string) Subtruct time-independent-background "TOF:34000-36000" or "DARK:20717"
    @param Vpath    (string) path containing the vanaidum Manyo Binay (mdb) file
    @param Vfile    (string) name of vanadium Manyo Binay (mdb) file. If None, the vanadium correction is skipped
    @param VintegRange (string) Integrate range "All" or "<start>:<end>"
    @param VpixelRange (string) Pixel range to be used "All" or "<start>:<end>"
    @param DetEffi (string) File name of the detector efficiency correction data. "None" : do not correction
    @retval ECM     (ElementCotainerMatix)
    """

    from utsusemi.ana.Reduction.BaseCommands import SplitStringParameters
    QrangeList = SplitStringParameters(Qrange, 2, "float")
    if QrangeList == -1 or QrangeList == -2:
        raise userWarning("Q range is invalid.")

    ret = GetDataOfMonochroEi3(runNo, Ei, deltaE, Erange, TimeSlice, MaskFile, NormFactor, isCT8n=True, TimeDepBack=TimeDepBack, DetEffi=DetEffi)
    if Vfile != "None":
        VDAT = LoadDataFromManyoBinary(Vpath, Vfile)
        RadialCollimatorCorrectSIK(ret, VDAT, VintegRange, VpixelRange)
        mu.UtsusemiMessage('PowderSPE >> RadialCollimatorCorrect done', True)
    return ToPowder(ret, QrangeList[0], QrangeList[1], deltaQ)


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


def SaveDataToSPE(dat, path="./", filename="Sample.spe", phxfile="default", parfile="default"):
    """
    Save ElementContainerMatrix to SPE and phx file.
    @param  dat      (ElementContainerMatrix)
    @param  path     (String) path to data file
    @param  filename (String) SPE data file name
    @param  phxfile  (String) PHX file name ("None": not output, "default" means using same name of SPE file)
    @param  parfile  (String) PAR file name ("None": not output, "default" means using same name of SPE file)
    @retval None
    """
    import utsusemi.ana.Reduction.TreatSPE as TSPE
    tspe = TSPE.TreatSPE()
    fullpath = os.path.join(path, filename)
    if phxfile.upper() in ["DEFAULT", "NONE"]:
        phx_fullpath = phxfile
    else:
        phx_fullpath = os.path.join(path, phxfile)
    if parfile.upper() in ["DEFAULT", "NONE"]:
        par_fullpath = parfile
    else:
        par_fullpath = os.path.join(path, parfile)
    # tspe.MakeSPE(dat,fullpath,Def_Pixel_Size) ##[inamura 120806]
    tspe.MakeSPE(dat, fullpath, [], phx_fullpath, par_fullpath)

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


def LoadDataFromSPE(path="./", spefile="Sample.spe", Ei=100.0, num_of_pixels=100, runNo="XXX000001", phxfile="default", parfile="default"):
    """
    Make ElementContainerMatrix from SPE and phx file.
    @param  path     (String) path to folder including spefile
    @param  spefile  (String) SPE file name (extention is .spe or .SPE)
    @param  Ei       (Float) Incident Energy
    @param  num_of_pixels (Int) the number of pixels in a detector
    @param  runNo    (String) Run Number with instrument codes
    @param  phxfile  (String) PHX file (extention is .phx) or "default"
    @param  parfile  (String) PAR file (extention is .par) or "default"
    @retval ElementContainerMatrix
    """
    import utsusemi.ana.Reduction.TreatSPE as TSPE
    tspe = TSPE.TreatSPE()
    fullpath = os.path.join(path, spefile)
    if parfile.upper() == "DEFAULT":
        par_fullpath = parfile
    else:
        par_fullpath = os.path.join(path, parfile)
    if phxfile.upper() == "DEFAULT":
        phx_fullpath = phxfile
    else:
        phx_fullpath = os.path.join(path, phxfile)
    dat = tspe.LoadSPE(fullpath, Ei, num_of_pixels,
                       runNo, phx_fullpath, par_fullpath)
    SS = "TOF TO ENERGY TRANSFER"
    hh = dat.PutHeaderPointer()
    process_vect = Manyo.MakeStringVector()
    process_vect.append(SS)
    hh.Add("DATAPROCESSED", process_vect)
    return dat

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


def SavePowderDataToText(dat, deltaQ=0.0, path="./", filename="Sample.txt", isIgnoreMask=False, maskInfo=[False, 0.0]):
    """
    Save ElementContainerMatrix of powder to text file.
    @param  dat      (ElementContainerMatrix)
    @param  deltaQ   (double) bin width of Q
    @param  path     (String) path to data file
    @param  filename (String) text file name
    @param  isIgnoreMask (bool) ignore points having mask value or not
    @apram  maskInfo (list) [<flag>,<value>] flag means whether replacing mask value with <value> or not
    @retval None
    """
#    if type(dat)!=type(Manyo.ElementContainerMatrix()):
    if not isinstance(dat, Manyo.ElementContainerMatrix):
        raise UserWarning(
            "argument of dat is invalid.(must be ElementContainerMatrix)")

    PROCESS = "ToPowder"
    if not CheckDataProcess(dat, PROCESS):
        raise UserWarning("This data is not Powder data.")

    # from utsusemi.vis.M2Plot import D2Matrix
    # from utsusemi.vis.CuiD2Chart import D2Matrix
    # dd = D2Matrix()
    # (dat,err,X,Y,type)=dd.ReadMatrix( dat )
    #
    # print("Slice and output text...")
    # from utsusemi.vis.D2Vis import MapObj
    # dmap = MapObj( (dat,err,X,Y,type),1 )
    # dmap = MapObj( dd.ReadMatrix( dat ),1 )
    # dmap.SaveAsText( os.path.join(path,filename),deltaQ )

    try:
        fd = open(os.path.join(path, filename), 'w')
    except:
        raise UserWarning("Failed to open %s." %
                          (os.path.join(path, filename)))

    ebin = dat(0, 0).PutXList()
    MAS = mm.MlfArraySlicer(dat)
    MAS.SetQbin(deltaQ, -1, -1)
    ec = MAS.CutAlongX(ebin[0], ebin[1], True)
    qbin = ec.PutXList()

    fd.write("## X,Y,Intensity,Error \n")
    xrange_text = "## XRANGE=%g,%g,%g \n" % (qbin[0], qbin[-1], deltaQ)
    yrange_text = "## YRANGE=%g,%g,%g \n" % (
        ebin[0], ebin[-1], (ebin[1] - ebin[0]))
    fd.write(xrange_text)
    fd.write(yrange_text)
    for i in range(len(ebin) - 1):
        hw = (ebin[i] + ebin[i + 1]) / 2.0
        EC = MAS.CutAlongX(hw, hw, True)
        qq = EC.PutXList()
        ii = EC.PutYList()
        ee = EC.PutEList()
        for j in range(len(qq) - 1):
            q = (qq[j] + qq[j + 1]) / 2.0
            intensity = ii[j]
            error = ee[j]
            if intensity < (mm.MLF_MASKVALUE - 1):
                pass
            elif isIgnoreMask:
                continue
            else:
                if maskInfo[0]:
                    intensity = maskInfo[1]
                    error = 0.0
            fd.write("%g, %g, %g, %g\n" % (hw, q, intensity, error))
    fd.close()
    del MAS

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


def SaveDataToNxspe(dat, path="./", filename="Sample", params="PSI:0.0,TEMP:300.0,USER:mlfuser", isReduct=False):
    """
    Save ElementContainerMatrix to NXSPE file.
    @param  dat      (ElementContainerMatrix)
    @param  path     (String) path to data file
    @param  filename (String) data file name without extension of .nxspe
    @param  params   (string) Other information : psi [deg], temperature[K] and user name
    @param  isReduct (bool)   Reduce the precision of the intensity and error from 64bit to 32bit to reduce the Nxspe file size
    @retval None
    """
    p_dic = {"PSI": 0.0, "TEMP": 300.0, "USER": "mlfuser"}
    p_list = params.split(",")
    for ap in p_list:
        aps = ap.split(":")
        if len(aps) == 2:
            if aps[0] in p_dic:
                if type(p_dic[aps[0]]) == str:
                    p_dic[aps[0]] = aps[1]
                else:
                    p_dic[aps[0]] = float(aps[1])

    pp = filename.rfind(".")
    if pp == -1:
        filename = filename + ".nxspe"
    elif filename[pp:] != ".nxspe":
        filename = filename[:pp] + ".nxspe"

    fullpath = os.path.join(path, filename)
    NX = mu.NxspeFileIO(isReduct)
    if NX.SetData(dat, p_dic["PSI"], p_dic["TEMP"]):
        NX.Save(fullpath, p_dic["USER"])

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


def LoadDataFromNxspe(path="./", filename="Sample.nxspe", num_of_pixels=100):
    """
    Make ElementContainerMatrix from nxspe.
    @param  path     (String) path to folder including spefile
    @param  spefile  (String) SPE file name (extention is .spe or .SPE)
    @param  num_of_pixels (Int) the number of pixels in a detector
    @retval ElementContainerMatrix
    """
    fullpath = os.path.join(path, filename)
    if not os.path.exists(fullpath):
        raise UserWarning("Not found file = {}".format(fullpath))

    dat = Manyo.ElementContainerMatrix()
    NPI = mu.NxspeFileIO()
    if NPI.Read(dat, fullpath):
        return dat
    else:
        raise UserWarning("Failed to read file = {}".format(fullpath))

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


def KiKfCorrection(dat):
    """
    Ki/Kf correction for the inelastic scattering
    @param dat (ElementContainerMatrix)
    """
    # PROCESS = "Ki/kf"
    # ret = BC.CheckDataProcess(dat,PROCESS)

    # KK=mu.KiKfCorrection()
    # KK.SetTarget(dat)
    # KK.KiKfCorrect()
    # dat = KK.Put() ##[inamura 100924]
    # del KK ##[inamura 120630]
    UR = mu.UtsusemiReductionInEla()
    UR.KiKfCorrect(dat)
    del UR

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


def dHWCorrection(dat):
    """
    1/(delta-hw) correction for the inelastic scattering
    @param dat (ElementContainerMatrix)
    """
    UR = mu.UtsusemiReductionInEla()
    UR.dHWCorrect(dat)
    del UR

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


def MakeWhiteVanCorr(dat, Emin=20.0, Emax=40.0):
    """
    Make data of White Vanadium correction

    @param dat (ElementContainerMatrix) target data
    @retval None
    """
    print("Making data of WhiteVanCorr >>> executing...")

    VTC = mu.VanadiumToolsChoppers()
    van_ec = VTC.MakeWhiteVanData(dat, Emin, Emax)

    runno = int(dat.PutHeader().PutString("RUNNUMBER"))
    spectname = os.environ["UTSUSEMI_INST_CODE"]
    runno_str = spectname + ("%06d" % runno)
    FileName = "WVdata_" + runno_str + ".dmp"

    if "UTSUSEMI_USR_DIR" in os.environ:
        FilePath = os.path.join(os.environ["UTSUSEMI_USR_DIR"], "ana", "tmp")
    elif "HOME" in os.environ:
        FilePath = os.path.join(os.environ["HOME"], "ana", "tmp")
    else:
        FilePath = "./"
    SaveDataToDump(van_ec, path=FilePath, filename=FileName)


#########################################
def WhiteVanCorr(dat, runno=0, new=0):
    """
    White Vanadium correction

    @param dat (ElementContainerMatrix) target data
    @param runno (int) RunNo for white vanadium
    @param new   (int) If users require vanadium calculation again, new=1.
    @retval None
    """
    print("WhiteVanCorr >>> executing...")

    spectname = os.environ["UTSUSEMI_INST_CODE"]
    runno_str = spectname + ("%06d" % runno)
    FileName = "WVdata_" + runno_str + ".dmp"

    if "UTSUSEMI_USR_DIR" in os.environ:
        FilePath = os.path.join(os.environ["UTSUSEMI_USR_DIR"], "ana", "tmp")
    elif "HOME" in os.environ:
        FilePath = os.path.join(os.environ["HOME"], "ana", "tmp")
    else:
        FilePath = "./"
    if not os.path.exists(os.path.join(FilePath, FileName)):
        messages = "cannot find such white vanadium data of this runno,", runno, "."
        raise UserWarning(messages)

    van_ec = LoadDataFromDump(FilePath, FileName)
    VTC = mu.VanadiumToolsChoppers()
    VTC.CorrectWhiteVan(dat, van_ec)

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


def VisContMOutputFileByPhi(dat, param_file="param.xml", phi=0.0, output_file="./"):
    """
    Output figure file of sliced data using VisualContM function
    [inamura 110425]
    @param dat (ElementContainerMatrix)
    @param param_file (string) Parameter XML file for VisualCont
    @param phi (float) angle phi
    @param output_file (string) Path to output file. The extension must be only .txt or .vbin
    @return None
    """
    VisContQOutputFileByPhi(dat, param_file, phi, output_file)

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


def VisContMSliceToECA(dat, param_file="param.xml", phi=0.0):
    """
    Output figure file of sliced data using VisualContM function
    [inamura 170317]
    @param dat (ElementContainerArray)
    @param param_file (string) Parameter XML file for VisualCont
    @param phi (float) angle phi
    @return ElementContainerArray
    """
    return VisContQSliceToECA(dat, param_file, phi)

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


def VisContQOutputFileByPhi(dat, param_file="param.xml", phi=0.0, output_file="./"):
    """
    Output figure file of sliced data using VisualContM function
    [inamura 110425]
    @param dat (ElementContainerMatrix)
    @param param_file (string) Parameter XML file for VisualCont
    @param phi (float) angle phi
    @param output_file (string) Path to output file. The extension must be only .txt or .vbin
    @return None
    """
    # if type(dat)!=type(Manyo.ElementContainerMatrix()):
    if not isinstance(dat, Manyo.ElementContainerMatrix):
        messages = "Not ElementContainerMatrix"
        raise UserWarning(messages)
    if not os.path.exists(param_file):
        messages = "There is no such file ({}).".format(param_file)
        raise UserWarning(messages)
    if (output_file[-4:] != ".txt") and (output_file[-5:] != ".vbin"):
        messages = "Output file name must include .txt or .vbin as extension."
        raise UserWarning(messages)

    sqe = mu.UtsusemiSqeCalc2()
    sqe.SetTarget(dat)
    sqe.LoadXtalParam(param_file)
    sqe.SetRotationSteps("Y:%g" % (phi))
    sqe.Projection()
    sqe.ConvertToD4Mat(output_file)

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


def VisContQSliceToECA(dat, param_file="param.xml", phi=0.0):
    """
    Output figure file of sliced data using VisualContM function
    [inamura 170317]
    @param dat (ElementContainerArray)
    @param param_file (string) Parameter XML file for VisualCont
    @param phi (float) angle phi
    @return ElementContainerArray
    """
    # if type(dat)!=type(Manyo.ElementContainerMatrix()):

    if not isinstance(dat, Manyo.ElementContainerMatrix):
        messages = "Not ElementContainerMatrix"
        raise UserWarning(messages)
    if not os.path.exists(param_file):
        messages = "There is no such file ({}).".format(param_file)
        raise UserWarning(messages)

    sqe = mu.UtsusemiSqeCalc2()
    sqe.SetTarget(dat)
    sqe.LoadXtalParam(param_file)
    sqe.SetRotationSteps("Y:%g" % (phi))
    sqe.Projection()
    sqe.Slice()
    eca = Manyo.ElementContainerArray()
    sqe.SetSlicedElementContainerArray(eca)
    return eca

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


def VisContMOutputFigure(dat, param_file="param.xml", output_file="./", zmin=-1.0, zmax=-1.0):
    """
    Output data to a file using VisualContCommon function
    [inamura 120417]
    @param dat (ElementContainerMatrix)
    @param param_file (string) Parameter XML file for VisualCont
    @param output_file (string) Path to output file name of figure.
    @param zmin (float) min value of plotting Z-range
    @param zmax (float) max value of plotting Z-range
    @return None
    """
    VisContQOutputFigure(dat, param_file, output_file, zmin, zmax)

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


def VisContQOutputFigure(dat, param_file="param.xml", output_file="./", zmin=-1.0, zmax=-1.0):
    """
    Output data to a file using VisualContCommon function
    [inamura 120417]
    @param dat (ElementContainerMatrix)
    @param param_file (string) Parameter XML file for VisualCont
    @param output_file (string) Path to output file name of figure.
    @param zmin (float) min value of plotting Z-range
    @param zmax (float) max value of plotting Z-range
    @return None
    """
    # if type(dat)!=type(Manyo.ElementContainerMatrix()):
    if not isinstance(dat, Manyo.ElementContainerMatrix):
        messages = "Not ElementContainerMatrix"
        raise UserWarning(messages)
    if not os.path.exists(param_file):
        messages = "There is no such file." + param_file
        raise UserWarning(messages)
    if (output_file[-4:] != ".png"):
        messages = "Output file name must include .png as extension."
        raise UserWarning(messages)

    phi = 0.0
    eca = VisContQSliceToECA(dat, param_file, phi)
    # Plot in the dark to save figure.
    xtal = mu.UtsusemiSqeCalcXtalParams(param_file)
    titles = xtal.PutAxLabels()
    import uGao.U2IFInDark as UID
    p = UID.U2IFInDark(eca, 1)
    p.SetKeys(None, None, eca(0).PutYKey())
    # p.SetTitles( "U2IFInDark Test","YAHOOO!" )
    p.SetLabels(titles[0], titles[1])
    p.SetColorMap("Default")
    if (zmin != -1) and (zmax != -1):
        p.SetRange(False, zmin, zmax)
    p.SetFigureSize(10.0, 10.0)
    p.SaveFile(output_file)

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


def MakeRunList(start_run=-1, end_run=-1, output="~/run_list.txt", flag_proton=1, offset_sec=0.0, isCT8n=True, devTemp="LS340", devGonio="Gonio"):
    """
    Make run list
    @param start_run (int) start run number to be listed.
    @param end_run (int) start run number to be listed.
    @param output (string) output file name
    @param flag_proton (int) 0: no protons, 1:protons only, 2:kickers only, 3:both, 4:all
    @param offset_sec (float) offset second for Measurement Period to get protons
    @param isCT8n (bool) use CT8Neutron ( corrected by muon target effect ) or not
    @param devTemp (string) The instance name of temperature Control device like "LS340", "7Tmagnet", "LS336", "He3TL"@BL14, "Cry3He"@SE
    @param devGonio (string) The instance name of Gonio Control device like "Gonio", "7Tmagnet-EA"(encoder's angle), "7Tmagnet-SA"(set angle), "He3TL"@BL14
    @return None
    """
    data_folder = os.environ["UTSUSEMI_DATA_DIR"]
    sys_name = os.environ["UTSUSEMI_INST_CODE"]
    run_number_wild = "%s%06d_*" % (
        os.environ["UTSUSEMI_INST_CODE"], start_run)
    import glob
    print("--- Searching run number like %s" % (run_number_wild))
    run_folder_list = glob.glob(os.path.join(data_folder, sys_name + "*"))
    run_folder_list.sort()
    run_folder = ""
    for a_run_folder in run_folder_list:
        run_number_list = glob.glob(
            os.path.join(a_run_folder, run_number_wild))
        if len(run_number_list) != 0:
            run_folder = a_run_folder
            break
    if run_folder == "":
        raise UserWarning("Run folder not found :")
    print("--- fin")
    run_number_list.sort()
    isIROHA2Used = False
    if len(run_number_list) != 0:
        fullpath = os.path.join(
            run_folder, run_number_list[-1], "params", ("run%06d.xml" % (start_run)))
        if os.path.exists(fullpath):
            isIROHA2Used = True

    if (isIROHA2Used):
        import utsusemi.ana.Reduction.MakeRunListFromParamsIROHA2 as MR
    else:
        import utsusemi.ana.Reduction.MakeRunListFromParams as MR

    args = ["dummy"]
    if start_run <= 0:
        message = "start_run must be set."
        raise UserWarning(message)
    args.append("%d" % start_run)

    if end_run > 0:
        args.append("%d" % end_run)

    if output[:2] == "~/":
        output = os.path.join(os.getenv("UTSUSEMI_USR_DIR"), output[2:])
    args.append("-f")
    args.append(output)

    if flag_proton == 0:
        args.append("-np")
    elif flag_proton == 1:
        args.append("-p")
    elif flag_proton == 2:
        args.append("-k")
    elif flag_proton == 3:
        args.append("-pk")
    elif flag_proton == 4:
        args.append("-a")
        # if not isCT8n:
        #    isCT8n = True

    if isIROHA2Used:
        args.append("-r")
        args.append(data_folder)
        args.append("-T")
        args.append(devTemp)
        args.append("-G")
        args.append(devGonio)

    args.append("-os")  # set offset_sec
    args.append(offset_sec)

    if isCT8n:
        args.append("-CT8n")

    print(args)

    MR.MakeRunList(args)

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


def LoadRunListToExtract(filename, paramDic=None, mergeAngles=False, isD4Mat2=False):
    """
    Load run list file produced by MakeRunList() to convert tupple format used in Extract

    @params filename (str) File name of Run List file
    @params paramDic (dic) parameters
    @params mergeAngles (bool) merge same angle data
    @params isD4Mat2 (bool) Which is this function used D4Mat or D4Mat2
    @return list of tupple ( runNo, angle, norm )
    """
    from utsusemi.ana.Reduction.MakeRunListFromParamsIROHA2 import MAKERUNLIST_KEY_KICKERS, MAKERUNLIST_KEY_PROTONS, MAKERUNLIST_KEY_GONIO
    try:
        gonioValueAtZero = paramDic["gonio"]
        normFactor = paramDic["normFactor"]
    except:
        raise UserWarning("paramDic is invalid")

    conds = []

    fo = open(filename, "r")
    # read first line ( Header line )
    ss = fo.readline()
    head_list = ss.split()
    index_head_proton = 0
    index_head_kicker = 0
    index_head_gonio = 0
    for i, a_head in enumerate(head_list):
        if a_head.find(MAKERUNLIST_KEY_PROTONS) != -1:
            index_head_proton = 2 + i
        if a_head.find(MAKERUNLIST_KEY_KICKERS) != -1:
            index_head_kicker = 2 + i
        if a_head.find(MAKERUNLIST_KEY_GONIO) != -1:
            index_head_gonio = 2 + i

    if index_head_proton == 0:
        if index_head_kicker != 0:
            index_head_proton = index_head_kicker
        elif normFactor == 0:
            pass
        else:
            raise UserWarning(
                "Failed to find the header of both proton and kicker")

    if index_head_gonio == 0:
        raise UserWarning("Failed to find the header of gonio")

    while(True):
        ss = fo.readline()
        if ss == "":
            break
        if ss[0] == "#":
            print("Skip::", ss)
            continue
        ss_s = ss.split()
        runNo = int(ss_s[0])
        norm = None
        angle = None

        if normFactor == 0:
            norm = 0.0
        else:
            try:
                norm_val = float(ss_s[index_head_proton])
            except:
                raise UserWarning("Not found proton or kicker in RunList")
            norm = float(norm_val) / float(normFactor * (-1.0))

        try:
            if isD4Mat2:
                angle = float(ss_s[index_head_gonio]) + gonioValueAtZero
            else:
                angle = float(ss_s[index_head_gonio]) - gonioValueAtZero
        except:
            raise UserWarning("Not found gonio in RunList ")

        conds.append((runNo, angle, norm))
    fo.close()

    if mergeAngles:
        AngleList = []
        condsDict = {}
        for runNo, angle, norm in conds:
            angle_key = "%07.3f" % (angle)  # "123.450"
            if angle_key in AngleList:
                angle_info = condsDict[angle_key]
                angle_info[0] = angle_info[0] + ",%d" % (runNo)
                angle_info[1] = angle_info[1] + norm
                condsDict[angle_key] = angle_info
            else:
                AngleList.append(angle_key)
                condsDict[angle_key] = ["%d" % (runNo), norm]
        return (AngleList, condsDict)
    else:
        return conds

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


def TofToEnergyTransfer(dat, Ei=-1.0, L1=18.03, t0shift=0.0, deltaE=0.0, EminRate=0.9, EmaxRate=0.9):
    """
    Function to convert Time-of-Flight to Energy Transfer

    @param dat      (ElementContainerMatrix)
    @param Ei       (double) Incident Energy [meV]
    @param L1       (double) Distance between moderator to sample [m]
    @param t0shift  (double) T0 shift [micro-sec]
    @param deltaE   (double) Delta Energy Transfer [meV]
    @param EminRate (double) range for minus E
    @param EmaxRate (double) range for plus E [<1.0]
    """
    PROCESS = "TofToEnergyTransfer"
    ret = CheckDataProcess(dat, "TofToEnergy")

    # from utsusemi.ana.Reduction.DataReduct_SJY import Tof2Energy
    import math
    L1 *= 1000.0  # unit of L1 is [mm]
    hd = dat.PutHeaderPointer()
    if Ei > 0:
        if hd.CheckKey("Ei") == 1:
            hd.OverWrite("Ei", Ei)
        else:
            hd.Add("Ei", Ei)
    else:
        if hd.CheckKey("Ei") == 1:
            Ei = hd.PutDouble("Ei")
        else:
            msg = "Ei must be positive. Or Ei is not included in data"
            print(msg)
            raise UserWarning(msg)

    if L1 > 0:
        if hd.CheckKey("L1") == 1:
            hd.OverWrite("L1", L1)  # unit of L1 is [mm]
        else:
            hd.Add("L1", L1)  # unit of L1 is [mm]
    else:
        if hd.CheckKey("L1") == 1:
            L1 = hd.PutDouble("L1")
        else:
            L1 = 18.03 * 1.0E3

    if (hd.CheckKey("T0shift") == 1) and (t0shift == 0.0):
        t0shift = hd.PutDouble("T0shift")

    ED = mu.TofToEnergyTransfer()
    ED.SetTarget(dat)

    print(" ----start tof to energy---")
    if deltaE != 0.0:
        energy_vec = Manyo.MakeDoubleVector()
        Emin = -1.0 * Ei * EminRate
        Emax = Ei * EmaxRate

        energy_gain = -deltaE / 2.0
        energy_loss = deltaE / 2.0
        energy_gain_list = [energy_gain]
        energy_loss_list = [energy_loss]

        while(True):
            energy_gain = energy_gain - deltaE
            if energy_gain > Emin:
                energy_gain_list.append(energy_gain)
            energy_loss = energy_loss + deltaE
            if energy_loss < Emax:
                energy_loss_list.append(energy_loss)
            if (energy_gain < Emin) and (energy_loss > Emax):
                break
        energy_gain_num = len(energy_gain_list)
        for i in range(energy_gain_num):
            energy_vec.append(energy_gain_list[energy_gain_num - 1 - i])
        for i in range(len(energy_loss_list)):
            energy_vec.append(energy_loss_list[i])

        # numP=int(round( (Emax-Emin)/deltaE ))
        # for i in range(numP):
        #    energy_vec.append( Emin+i*deltaE )
        print("L1={}".format(L1))
        ED.Tof2EnergyTransfer(L1, t0shift, energy_vec)
        # print "python code finished"
        """
        for psd in range(dat.PutTableSize()):
            a_psd = dat(psd)
            for pixel in range(a_psd.PutTableSize()):
                a_pixel = dat(psd,pixel)
                xname = a_pixel.PutXKey()
                yname = a_pixel.PutYKey()
                ename = a_pixel.PutEKey()
                new_pixel = a_pixel.ReBin(energy_vec)
                a_pixel.Replace(xname,new_pixel.PutX())
                a_pixel.Replace(yname,new_pixel.PutY())
                a_pixel.Replace(ename,new_pixel.PutE())
                a_pixel.SetKeys(xname,yname,ename)
        """
    else:
        ED.Tof2EnergyTransfer(L1, t0shift)

    dat = ED.Put()  # [inamura 100924]
    del ED  # [inamura 120630]
    # Add Header Info
    SS = PROCESS + "(dat,Ei=%f,L1=%f,t0shift=%f,deltaE=%f,EminRate=%f,EmaxRate=%f)" % (Ei, L1 / 1000.0, t0shift, deltaE, EminRate, EmaxRate)
    hh = dat.PutHeaderPointer()
    process_vect = hh.PutStringVector("DATAPROCESSED")
    process_vect.append(SS)
    hh.OverWrite("DATAPROCESSED", process_vect)

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


def TofToEnergyTransferStrict(dat, Ei=-1.0, L1=18.03, t0shift=0.0, Emin=-10.0, Emax=10.0, deltaE=0.0):
    """
    Function to convert Time-of-Flight to Energy Transfer

    @param dat      (ElementContainerMatrix)
    @param Ei       (double) Incident Energy [meV]
    @param L1       (double) Distance between moderator to sample [m]
    @param t0shift  (double) T0 shift [micro-sec]
    @param Emin (double) minimum of E range
    @param Emax (double) maximum of E range
    @param deltaE   (double) Delta Energy Transfer [meV]
    """
    PROCESS = "TofToEnergyTransferStrict"
    ret = CheckDataProcess(dat, "TofToEnergy")

    # from utsusemi.ana.Reduction.DataReduct_SJY import Tof2Energy
    import math
    L1 *= 1000.0  # unit of L1 is [mm]
    hd = dat.PutHeaderPointer()
    if Ei > 0:
        if hd.CheckKey("Ei") == 1:
            hd.OverWrite("Ei", Ei)
        else:
            hd.Add("Ei", Ei)
    else:
        if hd.CheckKey("Ei") == 1:
            Ei = hd.PutDouble("Ei")
        else:
            msg = "Ei must be positive. Or Ei is not included in data"
            print(msg)
            raise UserWarning(msg)

    if L1 > 0:
        if hd.CheckKey("L1") == 1:
            hd.OverWrite("L1", L1)  # unit of L1 is [mm]
        else:
            hd.Add("L1", L1)  # unit of L1 is [mm]
    else:
        if hd.CheckKey("L1") == 1:
            L1 = hd.PutDouble("L1")
        else:
            L1 = 18.03 * 1.0E3

    if (hd.CheckKey("T0shift") == 1) and (t0shift == 0.0):
        t0shift = hd.PutDouble("T0shift")

    ED = mu.TofToEnergyTransfer()
    ED.SetTarget(dat)

    if deltaE != 0.0:
        energy_vec = Manyo.MakeDoubleVector()

        energy_gain = -deltaE / 2.0
        energy_loss = deltaE / 2.0
        energy_gain_list = [energy_gain]
        energy_loss_list = [energy_loss]

        while(True):
            energy_gain = energy_gain - deltaE
            if energy_gain > Emin:
                energy_gain_list.append(energy_gain)
            energy_loss = energy_loss + deltaE
            if energy_loss < Emax:
                energy_loss_list.append(energy_loss)
            if (energy_gain <= Emin) and (energy_loss >= Emax):
                energy_gain_list.append(energy_gain_list[-1] - deltaE)
                energy_loss_list.append(energy_loss_list[-1] + deltaE)
                break
        energy_gain_num = len(energy_gain_list)
        for i in range(energy_gain_num):
            energy_vec.append(energy_gain_list[energy_gain_num - 1 - i])
        for i in range(len(energy_loss_list)):
            energy_vec.append(energy_loss_list[i])

        ED.Tof2EnergyTransfer(L1, t0shift, energy_vec)

    else:
        ED.Tof2EnergyTransfer(L1, t0shift)

    dat = ED.Put()  # [inamura 100924]

    del ED
    # Add Header Info
    SS = PROCESS + "(dat,Ei=%f,L1=%f,t0shift=%f,deltaE=%f,Emin=%f,Emax=%f)" % (Ei, L1 / 1000.0, t0shift, deltaE, Emin, Emax)
    hh = dat.PutHeaderPointer()
    process_vect = hh.PutStringVector("DATAPROCESSED")
    process_vect.append(SS)
    hh.OverWrite("DATAPROCESSED", process_vect)

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


def DymPDF(DAT, hwSlice="0.2,1.0,12.5", rRange="0.1,40.0", magFFa="0.4220,17.684", magFFb="0.5948,6.005", magFFc="0.0043,-0.609", magFFd="-0.0219", CF=74.84, isXaxisR=True):
    """Calculate Dynamical PDF with magnetic form factor

    @param DAT      (ElementContainerMatrix)
    @param hwSlice  (string) hw Slicing infor "<bin width>,<min hw>,<max hw>"
    @param rRange   (string) output r range "<r bin width>,<max r>"
    @param magFFa   (string) magnetic form factor "<A1>,<a2>"
    @param magFFb   (string) magnetic form factor "<B1>,<b2>"
    @param magFFc   (string) magnetic form factor "<C1>,<c2>"
    @param magFFd   (string) magnetic form factor "<D>"
    @param CF       (float)  Correction factor
    @param isXaxisR (bool) X-axis of output 2d data, True:R, False:hw
    @retval ECA (ElementContainerArray)
    """
    hw_range_s = hwSlice.split(",")
    if len(hw_range_s) != 3:
        raise UserWarning("Invalid hwSlice argument")
    r_range_s = rRange.split(",")
    if len(r_range_s) != 2:
        raise UserWarning("Invalid rRange argument")
    mag_ffa_s = magFFa.split(",")
    if len(mag_ffa_s) != 2:
        raise UserWarning("Invalid magFFa arguments")
    mag_ffb_s = magFFb.split(",")
    if len(mag_ffb_s) != 2:
        raise UserWarning("Invalid magFFb arguments")
    mag_ffc_s = magFFc.split(",")
    if len(mag_ffc_s) != 2:
        raise UserWarning("Invalid magFFc arguments")

    hw_range = [float(x) for x in hw_range_s]
    r_range = [float(x) for x in r_range_s]
    mag_ff_s = mag_ffa_s[:]
    mag_ff_s.extend(mag_ffb_s)
    mag_ff_s.extend(mag_ffc_s)
    mag_ff_s.append(float(magFFd))
    magFF = [float(x) for x in mag_ff_s]

    DPDF = mu.ShamotoDymPDF()
    DPDF.SetData(DAT)
    DPDF.SetSliceWidth(hw_range[0], hw_range[1], hw_range[2])
    DPDF.SetCf(CF)
    print(magFF[0], magFF[1], magFF[2], magFF[3], magFF[4], magFF[5], magFF[6])
    DPDF.SetMagFormFact(magFF[0], magFF[1], magFF[2],
                        magFF[3], magFF[4], magFF[5], magFF[6])
    DPDF.SetRRange(r_range[0], r_range[1])
    DPDF.Execute()

    ECA = Manyo.ElementContainerArray()
    DPDF.PutResult(ECA, isXaxisR)
    return ECA

#########################################
def WideDymPDF(DAT, hwSlice="0.2,1.0,12.5", rRange="0.1,40.0", magFFa="0.4220,17.684", magFFb="0.5948,6.005", magFFc="0.0043,-0.609", magFFd="-0.0219", CF=74.84, qParam="6.0,5.0", isXaxisR=True):
    """Wide-Q dynamic magnetic pair density funcation analysis (wideDymPDF)

    @param DAT      (ElementContainerMatrix)
    @param hwSlice  (string) hw Slicing infor "<bin width>,<min hw>,<max hw>"
    @param rRange   (string) output r range "<r bin width>,<max r>"
    @param magFFa   (string) magnetic form factor "<A1>,<a2>"
    @param magFFb   (string) magnetic form factor "<B1>,<b2>"
    @param magFFc   (string) magnetic form factor "<C1>,<c2>"
    @param magFFd   (string) magnetic form factor "<D>"
    @param CF       (float)  Correction factor
    @param qParam   (string) "Qmin,Qmax2", Qmin for phonon background fitting, Qmax2 for dynamic magnetic PDF analysis
    @param isXaxisR (bool) X-axis of output 2d data, True:R, False:hw
    @retval ECA (ElementContainerArray)
    """
    hw_range_s = hwSlice.split(",")
    if len(hw_range_s) != 3:
        raise UserWarning("Invalid hwSlice argument")
    r_range_s = rRange.split(",")
    if len(r_range_s) != 2:
        raise UserWarning("Invalid rRange argument")
    mag_ffa_s = magFFa.split(",")
    if len(mag_ffa_s) != 2:
        raise UserWarning("Invalid magFFa arguments")
    mag_ffb_s = magFFb.split(",")
    if len(mag_ffb_s) != 2:
        raise UserWarning("Invalid magFFb arguments")
    mag_ffc_s = magFFc.split(",")
    if len(mag_ffc_s) != 2:
        raise UserWarning("Invalid magFFc arguments")
    q_param_s = qParam.split(",")
    if len(q_param_s) != 2:
        raise UserWarning("Invalid qRange arguments")

    hw_range = [float(x) for x in hw_range_s]
    r_range = [float(x) for x in r_range_s]
    mag_ff_s = mag_ffa_s[:]
    mag_ff_s.extend(mag_ffb_s)
    mag_ff_s.extend(mag_ffc_s)
    mag_ff_s.append(float(magFFd))
    magFF = [float(x) for x in mag_ff_s]
    Qmin_phononBG = float(q_param_s[0])
    Qmax_DymPDF = float(q_param_s[1])

    DPDF = mu.ShamotoDymPDF()
    DPDF.SetData(DAT)
    DPDF.SetSliceWidth(hw_range[0], hw_range[1], hw_range[2])
    DPDF.SetCf(CF)
    print(magFF[0], magFF[1], magFF[2], magFF[3], magFF[4], magFF[5], magFF[6])
    DPDF.SetMagFormFact(magFF[0], magFF[1], magFF[2],
                        magFF[3], magFF[4], magFF[5], magFF[6])
    DPDF.SetRRange(r_range[0], r_range[1])
    DPDF.ExecuteWideDymPDF(Qmin_phononBG, Qmax_DymPDF)

    ECA = Manyo.ElementContainerArray()
    DPDF.PutResult(ECA, isXaxisR)
    return ECA

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


def DyPDF(DAT, hwSlice="0.2,1.0,12.5", rRange="0.1,40.0", nav=5, CF=1.0, isXaxisR=True):
    """Calculate Dynamical PDF

    @param DAT      (ElementContainerMatrix)
    @param hwSlice  (string) hw Slicing infor "<bin width>,<min hw>,<max hw>"
    @param rRange   (string) output r range "<r bin width>,<max r>"
    @param nav      (int) the number of bins for averaging
    @param CF       (float)  Correction factor
    @param isXaxisR (bool) X-axis of output 2d data, True:R, False:hw
    @retval ECA (ElementContainerArray)
    """
    hw_range_s = hwSlice.split(",")
    if len(hw_range_s) != 3:
        raise UserWarning("Invalid hwSlice argument")
    r_range_s = rRange.split(",")
    if len(r_range_s) != 2:
        raise UserWarning("Invalid rRange argument")
    hw_range = [float(x) for x in hw_range_s]
    r_range = [float(x) for x in r_range_s]

    DPDF = mu.ShamotoDymPDF()
    DPDF.SetModeToDyPDF()
    DPDF.SetData(DAT)
    DPDF.SetSliceWidth(hw_range[0], hw_range[1], hw_range[2])
    DPDF.SetNav(nav)
    DPDF.SetCf(CF)
    DPDF.SetRRange(r_range[0], r_range[1])
    DPDF.Execute()

    ECA = Manyo.ElementContainerArray()
    DPDF.PutResult(ECA, isXaxisR)
    return ECA

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


def DymPDFFromSpinWText(filename, hwSlice="0.2,1.0,12.5", rRange="0.1,40.0", magFFa="0.4220,17.684", magFFb="0.5948,6.005", magFFc="0.0043,-0.609", magFFd="-0.0219", CF=74.84, isXaxisR=True):
    """Calculate Dynamical PDF with magnetic form factor using output file from SpinW

    @param filename (string) path and file name of the output file from SpinW
    @param hwSlice  (string) hw Slicing infor "<bin width>,<min hw>,<max hw>"
    @param rRange   (string) output r range "<r bin width>,<max r>"
    @param magFFa   (string) magnetic form factor "<A1>,<a2>"
    @param magFFb   (string) magnetic form factor "<B1>,<b2>"
    @param magFFc   (string) magnetic form factor "<C1>,<c2>"
    @param magFFd   (string) magnetic form factor "<D>"
    @param CF       (float)  Correction factor
    @param isXaxisR (bool) X-axis of output 2d data, True:R, False:hw
    @retval ECA (ElementContainerArray)
    """
    filepath = mu.FindParamFilePath(filename)
    if filepath == "":
        raise UserWarning("Invalid filename")
    DAT = None
    # If text data from SpinW is directly used as sliced data (Q-Intensity 1D) in ShamotoPDF
    if hwSlice.strip() == "-":
        # Make the sliced data from text
        with open(filepath, "r") as fi:
            DAT = Manyo.ElementContainerArray()
            qlist = []
            ilist = []
            elist = []
            a_line = fi.readline()
            pre_q = -1.0e30
            pre_hw = 0.0
            while (a_line != ""):
                vs = a_line.strip().split(",")
                if len(vs) <= 1:
                    vs = a_line.strip().split(" ")
                v = []
                for v0 in vs:
                    if v0 != "":
                        v.append(v0)
                if len(v) == 4:
                    if len(qlist) != 0 and float(v[0]) < pre_q:
                        ec = Manyo.ElementContainer()
                        ec.AddToHeader(mu.UTSUSEMI_KEY_HW, pre_hw)
                        ec.Add("Q", qlist, "1/A")
                        ec.Add("Intensity", ilist, "counts")
                        ec.Add("Error", elist, "counts")
                        ec.SetKeys("Q", "Intensity", "Error")
                        DAT.Add(ec)
                        qlist = []
                        ilist = []
                        elist = []
                    qlist.append(float(v[0]))
                    pre_q = float(v[0])
                    pre_hw = float(v[1])
                    ilist.append(float(v[2]))
                    elist.append(float(v[3]))
                else:
                    print("Read Error : {}".format(a_line))
                a_line = fi.readline()
    else:
        # Make EleemntContainerArray from S(Q,hw) as defalt format (Energy-Intensity 1D)
        keys = []
        eneDic = {}
        intDic = {}
        errDic = {}
        with open(filepath, "r") as fi:
            a_line = fi.readline()
            while (a_line != ""):
                vs = a_line.strip().split(",")
                if len(vs) <= 1:
                    vs = a_line.strip().split(" ")
                v = []
                for v0 in vs:
                    if v0 != "":
                        v.append(v0)
                if len(v) == 4:
                    if not (v[0] in keys):
                        keys.append(v[0])
                    if not (v[0] in eneDic.keys()):
                        eneDic[v[0]] = [float(v[1])]
                        intDic[v[0]] = [float(v[2])]
                        errDic[v[0]] = [float(v[3])]
                    else:
                        eneDic[v[0]].append(float(v[1]))
                        intDic[v[0]].append(float(v[2]))
                        errDic[v[0]].append(float(v[3]))
                a_line = fi.readline()

        DAT = Manyo.ElementContainerArray()
        d_x2 = (float(keys[1]) - float(keys[0])) / 2.0
        for akey in keys:
            EC = Manyo.ElementContainer()
            EC.Add("Energy", eneDic[akey], "meV")
            EC.Add("Intensity", intDic[akey], "counts")
            EC.Add("Error", errDic[akey], "counts")
            EC.SetKeys("Energy", "Intensity", "Error")
            EC.AddToHeader("Xaxis", float(akey))
            q_range = Manyo.MakeDoubleVector()
            q_range.push_back(float(akey) - d_x2)
            q_range.push_back(float(akey) + d_x2)
            EC.AddToHeader("XRANGE", q_range)
            DAT.Add(EC)

    #return DAT
    #return eneDic, intDic, errDic

    doSlice = True
    if hwSlice.strip() == "-":
        hwSlice = "0,0,0"
        doSlice = False

    hw_range_s = hwSlice.split(",")
    if len(hw_range_s) != 3:
        raise UserWarning("Invalid hwSlice argument")
    r_range_s = rRange.split(",")
    if len(r_range_s) != 2:
        raise UserWarning("Invalid rRange argument")
    mag_ffa_s = magFFa.split(",")
    if len(mag_ffa_s) != 2:
        raise UserWarning("Invalid magFFa arguments")
    mag_ffb_s = magFFb.split(",")
    if len(mag_ffb_s) != 2:
        raise UserWarning("Invalid magFFb arguments")
    mag_ffc_s = magFFc.split(",")
    if len(mag_ffc_s) != 2:
        raise UserWarning("Invalid magFFc arguments")

    hw_range = [float(x) for x in hw_range_s]
    r_range = [float(x) for x in r_range_s]
    mag_ff_s = mag_ffa_s[:]
    mag_ff_s.extend(mag_ffb_s)
    mag_ff_s.extend(mag_ffc_s)
    mag_ff_s.append(float(magFFd))
    magFF = [float(x) for x in mag_ff_s]

    DPDF = mu.ShamotoDymPDF()
    if doSlice:
        DPDF.SetData(DAT)
    else:
        DPDF.SetSlicedData(DAT)
    DPDF.SetSliceWidth(hw_range[0], hw_range[1], hw_range[2])
    DPDF.SetCf(CF)
    print(magFF[0], magFF[1], magFF[2], magFF[3], magFF[4], magFF[5], magFF[6])
    DPDF.SetMagFormFact(magFF[0], magFF[1], magFF[2],
                        magFF[3], magFF[4], magFF[5], magFF[6])
    DPDF.SetRRange(r_range[0], r_range[1])
    DPDF.Execute(doSlice)

    ECA = Manyo.ElementContainerArray()
    DPDF.PutResult(ECA, isXaxisR)
    return ECA

#################################
# facad DR series
#################################


def GetDataOfWhite(runNo=197, startTOF=0, endTOF=40000, binTOF=100, MaskFile="mask.txt", NormFactor=1000000.0, isCT8n=True):
    """
    Load EventData and convert to histogram using corrections as below:
    - GetNeunetHist( ... )
    - 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)
    """
    HistParam = "tof,%f,%f,%f" % (startTOF, endTOF, binTOF)
    DetParam = "psd"
    DetRange = "All"
    TimeRange = "All"
    FrameInfo = "None"
    MaskInfo = MaskFile
    CaseInfo = "None"
    TofShift = "None"

    dat = GetNeunetHist(runNo=str(runNo),
                        HistParam=HistParam,
                        DetParam=DetParam,
                        DetRange=DetRange,
                        TimeRange=TimeRange,
                        FrameInfo=FrameInfo,
                        MaskInfo=MaskInfo,
                        CaseInfo=CaseInfo,
                        TofShift=TofShift)
    if NormFactor != 0:
        NormByBeamCurrent(dat, NormFactor, 0, isCT8n)

    # BC.DoMask(dat,MaskFile)
    SolidAngleCorrection(dat)

    return dat

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


def GetDataOfMonochroEi(runNo=0, Ei=0.0, Resolution=0.3, deltaE=0.0, L1=30.0, MaskFile="mask.txt", NormFactor=1000.0):
    """
    This Function is obsolete. Please forget me ...

    @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     ElementContainerMatrix as result
    """
    raise UserWarning("This Function is obsolete. Please forget me...")
    return None

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


def GetDataOfMonochroEi2(runNo=0, Ei=0.0, deltaE=0.0, Emin=0.0, Emax=0.0, MaskFile="mask.txt", NormFactor=1000000.0, offset_sec=0.0, isCT8n=False, DetEffi="None"):
    """
    Load EventData and convert to histogram using corrections as below:
    - GetNeunetHist( ... ) including MaskInfo
    - NormByBeamCurrent(DAT,NormFactor)
    - SolidAngleCorrection(DAT)
    - kikfCorrection(DAT)
    - dHWCorrection(DAT)
    - DetectorEffi(DAT, DetEffi) # if DetEffi!="None"
    @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: Intensity/beamCurrent*factor. If 0, do nothing. If minus, Intensity/abs(factor)
    @param offset_sec (float) offset second for Measurement Period to get protons
    @param isCT8n (bool) use CT8Neutron ( corrected by muon target effect ) or not
    @param DetEffi (string) File name of the detector efficiency correction data. "None" : do not correction
    @retval DAT     ElementContainerMatrix as result
    """

    HistParam = "hw,%f,%f,%f,%f," % (Ei, Emin, Emax, deltaE)
    DetParam = "psd"
    DetRange = "All"
    TimeRange = "All"
    FrameInfo = "None"
    MaskInfo = "%s" % (MaskFile.strip())
    CaseInfo = "None"
    TofShift = "None"

    uc = mu.UtsusemiUnitConverter()
    # tof_ela = uc.LEtoT(Def_L1,Ei)
    # last_tof  = tof_ela + uc.LEtoT(Def_L2,(Ei-Emax) )
    GNH = mu.UtsusemiGetNeunetHistogram()
    GNH.SetRunNo(runNo)
    L1 = GNH.PutL1() / 1000.0
    L2 = GNH.PutTypicalL2() / 1000.0
    tof_ela = uc.LEtoT(L1, Ei)
    last_tof = tof_ela + uc.LEtoT(L2, (Ei - Emax))
    fInfo = [0, 0.0]

    if tof_ela <= 40000.0:
        if last_tof <= 40000.0:
            pass
        else:
            fInfo[0] = 2
            fInfo[1] = tof_ela
    elif 40000.0 < tof_ela and tof_ela <= 80000.0:
        fInfo[0] = 3
        fInfo[1] = tof_ela - 40000.0
    else:
        msg = "Ei is too small. Over second frame."
        raise UserWarning(msg)
    """
    if last_tof<=40000.0:
        pass
    elif last_tof<=80000.0:
        fInfo[0]=2
        if tof_ela<40000.0:
            fInfo[1]=tof_ela
        elif tof_ela<80000.0:
            fInfo[1]=40000.0
    elif last_tof<=120000.0:
        fInfo[0]=3
        if tof_ela<80000.0:
            fInfo[1]=tof_ela
        elif tof_ela<120000.0:
            fInfo[1]=40000.0
    else:
        raise UserWarning("Invalid energy range..")
    """
    del uc
    if fInfo[0] != 0:
        FrameInfo = "%d,%f" % (fInfo[0], fInfo[1])

    dat = GetNeunetHist(runNo=str(runNo),
                        HistParam=HistParam,
                        DetParam=DetParam,
                        DetRange=DetRange,
                        TimeRange=TimeRange,
                        FrameInfo=FrameInfo,
                        MaskInfo=MaskInfo,
                        CaseInfo=CaseInfo,
                        TofShift=TofShift)

    if runNo != 0:
        if NormFactor != 0:
            NormByBeamCurrent(dat, NormFactor, offset_sec,
                              isCT8n, isTagCorrect=True)
        SolidAngleCorrection(dat)
        KiKfCorrection(dat)
        dHWCorrection(dat)
        if DetEffi.upper() != "NONE":
            DetectorEffi(dat, DetEffi)

    return dat

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


def GetDataOfMonochroEi3(runNo="0", Ei=0.0, deltaE=0.0, Erange="0.0 0.0", TimeSlice="-1.0 -1.0", MaskFile="mask.txt", NormFactor=1000000.0, offset_sec=0.0, isCT8n=False, PulseHeight="-", TimeDepBack="DARK:None", DetEffi="None"):
    """
    Load EventData and convert to histogram using corrections as below:
    - GetNeunetHist( ... ) including MaskInfo
    - NormByBeamCurrent(DAT,NormFactor)
    - SolidAngleCorrection(DAT)
    - kikfCorrection(DAT)
    - dHWCorrection(DAT)
    - DetectorEffi(DAT, DetEffi) # if DetEffi!="None"
    @param runNo    (string) Run Number(s) "<run1>[,<run2>,...]"(delimitor is comma or space)
    @param Ei       (double) Incident Energy [meV]
    @param deltaE   (double) Delta Energy Transfer [meV]
    @param Erange   (string) min and max of Energy Transfer [meV] "<min>,<max>"(delimitor is comma or space)
    @param TimeSlice(string) start time and end time [seconds] "<min>,<max>"(delimitor is comma or space)
    @param MaskFile (string) file name for masking
    @param NormFactor (double) normalize factor: Intensity/beamCurrent*factor. If 0, do nothing. If minus, Intensity/abs(factor)
    @param offset_sec (float) offset second for Measurement Period to get protons
    @param isCT8n (bool) use CT8Neutron ( corrected by muon target effect ) or not
    @param PulseHeigh (string) PulseHeight range "min" or "min:max", if not use "-"
    @param TimeDepBack (string) Subtruct time-independent-background "TOF:34000-36000" or "DARK:20717"
    @param DetEffi (string) File name of the detector efficiency correction data. "None" : do not correction
    @retval DAT     ElementCotainerMatix as result
    """
    # runNo_list_st=runNo.split(" ")
    # runNoList = BC.SplitStringParameters( runNo, len(runNo_list_st), "int" )
    # if runNo==-1 or runNo==-2:
    #    raise UserWarning,"Run Numbers are invalid."

    ErangeList = SplitStringParameters(Erange, 2, "float")
    if ErangeList == -1 or ErangeList == -2:
        raise UserWarning("E range is invalid.")

    TimeList = SplitStringParameters(TimeSlice, 2, "float")
    if TimeList == -1 or TimeList == -2:
        raise UserWarning("Time Slice range is invalid.")

    RunNos = ""
    if len(runNo.split(",")) < len(runNo.split(" ")):
        for a_runNo in runNo.split(" "):
            if a_runNo != "":
                RunNos += "{},".format(a_runNo)
        RunNos = RunNos[:-1]
    else:
        RunNos = runNo
    # for a_runNo in runNoList:
    #    RunNos += "%d,"%(a_runNo)
    # RunNos = RunNos[:-1]

    # Puslse Height range
    PH_range = None
    if PulseHeight.strip() != "-":
        PHv = PulseHeight.split(":")
        if len(PHv) == 1:
            PHv.append("4096")
        if len(PHv) != 2:
            PHv2 = PulseHeight.split("-")
            if len(PHv2) == 1:
                PHV2.append("4096")
            if len(PHv2) != 2:
                raise UserWarning("PulseHeight range is invalid")
            PHv = PHv2
        PH_range = [int(PHv[0]), int(PHv[1])]
        if PH_range[0] <= 0 or PH_range[1] <= 0 or PH_range[0] > PH_range[1]:
            raise UserWarning("PulseHeight range is invalid")
    # TimeDepBack
    TimeDepBack_sp = TimeDepBack.split(",")
    TimeDepBackTofRange = ""
    TimeDepBackDarkRun = 0
    for a_TypeBack in TimeDepBack_sp:
        TDB = a_TypeBack.split(":")
        if len(TDB) != 2:
            raise UserWarning("Time-depend-background is invalid")
        if TDB[0].strip().upper() == "TOF" or TDB[0].strip().upper() == "TIMEDEP" or TDB[0].strip().upper() == "TIMEINDEP":
            if TDB[1].strip().upper() != "NONE":
                TimeDepBackTofRange = TDB[1].strip()
        elif TDB[0].strip().upper() == "DARK":
            if TDB[1].strip().upper() != "NONE":
                try:
                    TimeDepBackDarkRun = int(TDB[1].strip())
                except:
                    raise UserWarning("Dark Background is invalid")

    # RunNos=runNo
    HistParam = "hw,%f,%f,%f,%f," % (Ei, ErangeList[0], ErangeList[1], deltaE)
    if PH_range is None:
        DetParam = "psd"
    else:
        DetParam = "psd[%d:%d]" % (PH_range[0], PH_range[1])
    DetRange = "All"
    TimeRange = "%d,%d" % (TimeList[0], TimeList[1])
    FrameInfo = "None"
    # MaskInfo = "NoFile"
    MaskInfo = "%s" % (MaskFile.strip())
    CaseInfo = "None"
    TofShift = "None"
    if TimeDepBackTofRange == "":
        TimeDepBackTofRange = "TIMEDEP:None"
    else:
        TimeDepBackTofRange = "TIMEDEP:" + TimeDepBackTofRange

    uc = mu.UtsusemiUnitConverter()
    # tof_ela = uc.LEtoT(Def_L1,Ei)
    # last_tof  = tof_ela + uc.LEtoT(Def_L2,(Ei-ErangeList[1]) )
    runNo_tmp1 = RunNos.split(",")
    runNo_tmp2 = runNo_tmp1[0].split("-")
    runNo_int = int(runNo_tmp2[0])
    GNH = mu.UtsusemiGetNeunetHistogram()
    GNH.SetRunNo(runNo_int)
    L1 = GNH.PutL1() / 1000.0
    L2 = GNH.PutTypicalL2() / 1000.0
    tof_ela = uc.LEtoT(L1, Ei)
    last_tof = tof_ela + uc.LEtoT(L2, (Ei - ErangeList[1]))
    fInfo = [0, 0.0]

    if tof_ela <= 40000.0:
        if last_tof <= 40000.0:
            pass
        else:
            fInfo[0] = 2
            fInfo[1] = tof_ela
    elif 40000.0 < tof_ela and tof_ela <= 80000.0:
        fInfo[0] = 3
        fInfo[1] = tof_ela - 40000.0
    else:
        msg = "Ei is too small. Over second frame."
        raise UserWarning(msg)
    """
    if last_tof<=40000.0:
        pass
    elif last_tof<=80000.0:
        fInfo[0]=2
        if tof_ela<40000.0:
            fInfo[1]=tof_ela
        elif tof_ela<80000.0:
            fInfo[1]=40000.0
    elif last_tof<=120000.0:
        fInfo[0]=3
        if tof_ela<80000.0:
            fInfo[1]=tof_ela
        elif tof_ela<120000.0:
            fInfo[1]=40000.0
    else:
        raise UserWarning("Invalid energy range..")
    """
    del uc
    if fInfo[0] != 0:
        FrameInfo = "%d,%f" % (fInfo[0], fInfo[1])

    dat = GetNeunetHist(runNo=RunNos,
                        HistParam=HistParam,
                        DetParam=DetParam,
                        DetRange=DetRange,
                        TimeRange=TimeRange,
                        FrameInfo=FrameInfo,
                        MaskInfo=MaskInfo,
                        CaseInfo=CaseInfo,
                        BGInfo=TimeDepBackTofRange,
                        TofShift=TofShift)

    if TimeDepBackDarkRun != 0:
        dat_dark = GetNeunetHist(runNo=str(TimeDepBackDarkRun),
                                 HistParam=HistParam,
                                 DetParam=DetParam,
                                 DetRange=DetRange,
                                 TimeRange=TimeRange,
                                 FrameInfo=FrameInfo,
                                 MaskInfo=MaskInfo,
                                 CaseInfo=CaseInfo,
                                 BGInfo=TimeDepBackTofRange,
                                 TofShift=TofShift)
        SubDark = mu.UtsusemiSubtractDarkBackground()
        if SubDark.Execute(dat, dat_dark):
            pass
        else:
            raise UserWarning("Failed to subtract dark background.")

    # if runNoList[0]==0:
    if RunNos.strip() == "0":
        return dat

    NormByBeamCurrent(dat, NormFactor, offset_sec, isCT8n, isTagCorrect=True)
    """
    if NormFactor!=0:
        if len(runNoList)>1:
            bc = BC.GetBeamCurrentFromECM(dat)
            for i in range(len(runNoList)-1):
                dat_tmp = BC.GetHistogramOfEnergyTransfer(runNoList[i+1],Ei,deltaE,ErangeList[0],ErangeList[1],TimeList[0],TimeList[1])
                bc += BC.GetBeamCurrentFromECM(dat_tmp)
                dat_tmp2 = Manyo.ElementContainerMatrix( dat+dat_tmp )
                del dat_tmp,dat

                dat = dat_tmp2
            if NormFactor>0:
                dat.MulMySelf( float(NormFactor)/float(bc) )
            else:
                dat.MulMySelf( 1.0/float(NormFactor) )
        else:
            BC.NormByBeamCurrent(dat, NormFactor)
    """
    SolidAngleCorrection(dat)
    KiKfCorrection(dat)
    dHWCorrection(dat)
    if DetEffi.upper() != "NONE":
        DetectorEffi(dat, DetEffi)

    return dat

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


def SaveDataToDAVEgrp(dat, path="./", filename="Sample.grp", startQ=1.0, endQ=1.0, frcQ=1, binE=0.0):
    """
    Save grouped text (DAVE format) files of Q-sliced powder data
    @param  dat      (ElementContainerMatrix)
    @param  path     (String) path to data file
    @param  filename (String) data file name
    @param  startQ   (double) minimum limit of Q-range
    @param  endQ     (double) maximum limit of Q-range
    @param  frcQ     (int) number of division
    @param  binE      (double) rebinning width of energy
    @retval None
    """
    import codecs
    if not CheckDataProcess(dat, "ToPowder"):
        print("Data must be powder data.")
        raise UserWarning("Data must be powder data.")

    if not isinstance(dat, Manyo.ElementContainerMatrix):
        raise UserWarning("Not ElementContainerMatrix")

    if endQ < startQ or frcQ < 1:
        raise UserWarning("Parameter Error")

    if frcQ > 100:
        raise UserWarning("please input frcQ <= 100")

    Xinfo = "#Number of x-values\r"  # Energy Transfer
    Yinfo = "#Number of y-values\r"  # Qvalue
    Yinfo += str(int(frcQ)) + "\r"
    Yvalues = "# yvalues:\r"
    Xvalues = "# xvalues:\r"
    Ivalues = ""

    eca = dat(0)
    ec = eca.Put(0)
    if binE > 0.0:
        xx_org = ec.PutXList()
        v = mm.CalcRangeAsBinCenterZero(xx_org[0], xx_org[-1], binE)
        if v[2] > 1:
            xx_new = np.arange(v[0], v[1], binE)
            xx_new_v = Manyo.ListToDoubleVector(xx_new.tolist())
            print(xx_new)
            ec = ec.Averaging(xx_new_v)

    EnergyBin_org = ec.PutX()
    EnergyBin_org_size = len(EnergyBin_org)

    EnergyBin = []

    Xinfo += str(int(EnergyBin_org_size - 1)) + "\r"
    for j in range(EnergyBin_org_size - 1):
        ee_center = (EnergyBin_org[j] + EnergyBin_org[j + 1]) / 2

        if abs(ee_center) < 0.00000001:
            ee = 0.0
        else:
            ee = ee_center

        EnergyBin.append(ee)

        Xvalues += "%.6f\r" % (ee)

    print("Slice and output text...")
    MA = mm.MlfArraySlicer(dat)

    datalst = []

    ql = startQ
    qd = (endQ - startQ) / frcQ

    def _formatting(val):
        if val >= (mu.UTSUSEMIMASKVALUE64 / 10.0):
            val = 0.0
        p = str(val)
        if p.find("e") > 0:
            p2 = p.split("e")
            keta = len(p2[0])
            shisu = int(p2[1])
            if shisu < 0:
                f = "%" + "%d.%d" % (keta + abs(shisu), keta + abs(shisu) - 2) + "f"
            else:
                f = "%" + "%d.%d" % (keta + abs(shisu), 1) + "f"
            return f % float(val)
        else:
            return p

    for ii in range(frcQ):
        qc = ql + qd / 2.0
        qr = ql + qd

        Yvalues += "%.6f\r" % (qc)

        # obj = dmap.GetHistY([qc,ql,qr,binE])
        # ec = MA.CutAlongY(ql, qr)
        ec = Manyo.ElementContainer()
        MA.CutAlongY(ec, ql, qr)

        if binE > 0.0:
            xx_org = ec.PutXList()
            v = mm.CalcRangeAsBinCenterZero(xx_org[0], xx_org[-1], binE)
            if v[2] > 1:
                xx_new = np.arange(v[0], v[1], binE)
                xx_new_v = Manyo.ListToDoubleVector(xx_new.tolist())
                ec = ec.Averaging(xx_new_v)

        XX = ec.PutXList()
        YY = ec.PutYList()
        EE = ec.PutEList()

        if ii == 0:
            Ivalues += "#Group: %d" % (ii)
        else:
            Ivalues += "\r#Group: %d" % (ii)

        leftX = XX[0]

        cnt_leftX = 0
        for jj in range(len(EnergyBin)):
            if EnergyBin[jj] > leftX:
                break

            # Ivalues+="\rnan nan"
            Ivalues += "\r0 0"
            cnt_leftX += 1

        for kk in range(len(YY)):
            y_form = _formatting(YY[kk])
            e_form = _formatting(EE[kk])
            if float(y_form) == 0.0 and float(e_form) == 0.0:
                Ivalues += "\r0 0"
            else:
                Ivalues += "\r%s %s" % (y_form, e_form)

        for jj in range(cnt_leftX + len(YY), len(EnergyBin)):
            # Ivalues+="\rnan nan"
            Ivalues += "\r0 0"

        ql = qr

    try:
        fp = codecs.open(os.path.join(path, filename), 'w', "utf-8")
    except:
        raise UserWarning("File open Error")
    else:
        fp.write(Xinfo)
        fp.write(Yinfo)
        fp.write(Xvalues)
        fp.write(Yvalues)
        fp.write(Ivalues)
        fp.close()

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


def GetOrigPixelFromQXtalParam(XtalParam="XtalParam.xml", Q="1.0,1.0,1.0", Ei=45.56, hw=0.0, runNo=999999, pixNum=100):
    """
    Gets origina pixel position from Q position on caclucated S(Q,E) using XtalParam.xml
    @param XtalParam (string) path to XtalParam.xml
    @param Q         (string) "<Qa>, <Qb>, <Qc>"
    @param Ei        (float)  Incident Energy
    @param hw        (float)  Energy Transfer
    @param runNo     (int)    Run Number used to select suitable DetecterInfo.xml
    @param pixNum    (int)    The number of pixels on one PSD
    @retval tupple of detId and pixelNo of Detector
    """
    if not os.path.exists(XtalParam):
        raise UserWarning("XtalParam is not found")

    CC = Manyo.CppToPython()
    XP = mu.UtsusemiSqeCalcXtalParams(XtalParam)
    LC = CC.VectorDoubleToList(XP.PutLatticeConsts())
    Uv = CC.VectorDoubleToList(XP.PutUVector())
    Vv = CC.VectorDoubleToList(XP.PutVVector())
    RS = XP.PutRotateSteps()
    RotStep = ""
    if RS.size() == 0:
        RotStep = "None"
    else:
        for i in range(int(RS.size() / 2)):
            if int(RS[2 * i]) == 0:
                AX = "X"
            elif int(RS[2 * i]) == 1:
                AX = "Y"
            elif int(RS[2 * i]) == 2:
                AX = "Z"
            else:
                pass
            if RotStep == "":
                RotStep = "{}:{}".format(AX, float(RS[2 * i + 1]))
            else:
                RotStep = ",{}:{}".format(AX, float(RS[2 * i + 1]))
    VA = XP.PutViewAxes()
    VA1 = [VA[0], VA[1], VA[2]]
    VA2 = [VA[4], VA[5], VA[6]]
    VA3 = [VA[8], VA[9], VA[10]]

    if type(Q) is list:
        Qlist = Q[:]
    else:
        Qs = Q.split(",")
        Qlist = [float(Qs[i]) for i in range(len(Qs))]

    return GetOrigPixelFromQ(LC, Uv, Vv, RotStep, VA1, VA2, VA3, Qlist, Ei, hw, runNo, pixNum)

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


def GetOrigPixelFromQString(LatticeConst="4.8,8.4,2.9", LatticeAngles="90.0,90.0,90.0", Uvect="0.0,1.0,0.0", Vvect="0.0,0.0,1.0", RotAngle="None", ViewAxis1="1,0,0", ViewAxis2="0,1,0", ViewAxis3="0,0,1", Q="1.0,1.0,1.0", Ei=45.56, hw=0.0, runNo=999999, pixNum=100):
    """
    Gets origina pixel position from Q position on caclucated S(Q,E) using lattice constants, U and V vectores etc.
    @param LatticeConst (string) "<a>,<b>,<c>"
    @param LatticeAngle (string) "<alpha>,<beta>,<gamma>"
    @param Uvect        (string) "<Ua>, <Ub>, <Uc>"
    @param Vvect        (string) "<Va>, <Vb>, <Vc>"
    @param RotAngle     (string) "None" or "<AX>:<deg>[,<AX>:<deg>,..]" <AX>="X","Y","Z"
    @param ViewAxis1    (string) "<Ax1_a*>,<Ax1_b*>,<Ax1_c*>"
    @param ViewAxis2    (string) "<Ax2_a*>,<Ax2_b*>,<Ax2_c*>"
    @param ViewAxis3    (string) "<Ax3_a*>,<Ax3_b*>,<Ax3_c*>"
    @param Q            (string) "<Q1>,<Q2>,<Q3>"
    @param Ei           (float)  Incident Energy [meV]
    @param hw           (float)  Energy Transfer [meV]
    @param runNo        (int)    Run Number used to select suitable DetecterInfo.xml
    @param pixNum       (int)    The number of pixels on one PSD
    @retval tupple of detId and pixelNo of Detector
    """
    def Conv(II):
        IIV = II.split(",")
        ret = []
        for ii in IIV:
            ret.append(float(ii))
        return ret

    LC = Conv(LatticeConst + "," + LatticeAngles)
    UV = Conv(Uvect)
    VV = Conv(Vvect)
    AX1 = Conv(ViewAxis1)
    AX2 = Conv(ViewAxis2)
    AX3 = Conv(ViewAxis3)
    AX4 = [0.0, 0.0, 0.0, 1.0]

    Qlist = Conv(Q)

    return GetOrigPixelFromQ(LC, UV, VV, RotAngle, AX1, AX2, AX3, Qlist, Ei, hw, runNo, pixNum)

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


def GetOrigPixelFromQ(LatticeConst=[4.8, 8.4, 2.9, 90, 90, 90], Uvect=[0.0, 1.0, 0.0], Vvect=[0.0, 0.0, 1.0], RotAngle="None", ViewAxis1=[1, 0, 0], ViewAxis2=[0, 1, 0], ViewAxis3=[0, 0, 1], Q=[1.0, 1.0, 1.0], Ei=50.0, hw=0.0, runNo=999999, pixNum=100):
    """
    Gets origina pixel position from Q position on caclucated S(Q,E) using lattice constants, U and V vectores etc.
    @param LatticeConst (list)   [<a>,<b>,<c>]
    @param LatticeAngle (list)   [<alpha>,<beta>,<gamma>]
    @param Uvect        (list)   [<Ua>, <Ub>, <Uc>]
    @param Vvect        (list)   [<Va>, <Vb>, <Vc>]
    @param RotAngle      (string) "None" or "<AX>:<deg>[,<AX>:<deg>,..]" <AX>="X","Y","Z"
    @param ViewAxis1    (list)   [<Ax1_a*>,<Ax1_b*>,<Ax1_c*>]
    @param ViewAxis2    (list)   [<Ax2_a*>,<Ax2_b*>,<Ax2_c*>]
    @param ViewAxis3    (list)   [<Ax3_a*>,<Ax3_b*>,<Ax3_c*>]
    @param Q            (list)   [<Q1>,<Q2>,<Q3>]
    @param Ei           (float)  Incident Energy [meV]
    @param hw           (float)  Energy Transfer [meV]
    @param runNo        (int)    Run Number used to select suitable DetecterInfo.xml
    @param pixNum       (int)    The number of pixels on one PSD
    @retval tupple of detId and pixelNo of Detector
    """

    XP = mu.UtsusemiSqeCalcXtalParams()

    XP.SetLatticeConstants(LatticeConst)
    XP.SetUVvector(Uvect, Vvect)
    if RotAngle != "None":
        XP.SetRotationSteps(RotAngle)
    ViewAxis1.extend([0.0, 'Qa'])
    ViewAxis2.extend([0.0, 'Qb'])
    ViewAxis3.extend([0.0, 'Qb'])
    ViewAxis4 = [0.0, 0.0, 0.0, 1.0, 'Energy']
    XP.SetProjectionAxes(ViewAxis1, ViewAxis2, ViewAxis3, ViewAxis4)

    AE = mu.UtsusemiAnaEnvironReader("environ_ana.xml")
    if not AE._Status:
        raise UserWarning("environ_ana.xml is not found.")

    pfiles = AE.PutParamFiles(runNo, 0, True)

    UC = mu.UtsusemiUnitConverter()
    ki = math.sqrt(UC.EtoK2(Ei))
    kf = math.sqrt(UC.EtoK2(Ei - hw))

    # Make Projection Matrix
    SC = mu.UtsusemiSqeCalc2()
    A = SC.MakeProjectionMatrix(XP.PutLatticeConsts(), XP.PutUVector(
    ), XP.PutVVector(), XP.PutRotateSteps(), XP.PutViewAxes())

    # Reduce matrix size 4x4 to 3x3
    B = Manyo.MakeDoubleVector(9)
    B[0] = A[0]
    B[1] = A[1]
    B[2] = A[2]
    B[3] = A[4]
    B[4] = A[5]
    B[5] = A[6]
    B[6] = A[8]
    B[7] = A[9]
    B[8] = A[10]
    C = SC.InverseMatrix(B)

    # Conversion coordinate system from Q(Reciprocal Lattice) to q(Experimental)
    qx = C[0] * Q[0] + C[1] * Q[1] + C[2] * Q[2]
    qy = C[3] * Q[0] + C[4] * Q[1] + C[5] * Q[2]
    qz = C[6] * Q[0] + C[7] * Q[1] + C[8] * Q[2]

    # print("qx,qy,qz={},{},{}".format(qx,qy,qz))

    # Calculate Polar and Azimuth angles
    px = -qx / kf
    py = -qy / kf
    pz = (ki - qz) / kf
    # print("########## New Version")
    if mu.UtsusemiEnvGetDebugMode():
        print("q=({},{},{})".format(qx, qy, qz))
        print("P=({},{},{})".format(px, py, pz))
        # print("ki,kf={},{}".format(ki,kf))
    detId, pixel = GetDetectorPixelFromOrientation(px, py, pz, runNo, pixNum)
    mu.UtsusemiMessage("DetId={}, Pixel={}".format(int(detId), int(pixel)))
    return (int(detId), int(pixel))

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


def GetDetectorPixelFromOrientation(px, py, pz, runNo=999999, pixNum=100):
    AE = mu.UtsusemiAnaEnvironReader("environ_ana.xml")
    if not AE._Status:
        raise UserWarning("environ_ana.xml is not found.")
    pfiles = AE.PutParamFiles(runNo, 0, True)

    try:
        L = math.sqrt(px * px + py * py + pz * pz)
        px = px / L
        py = py / L
        pz = pz / L
    except:
        raise UserWarning(
            "GetDetectorPixelFromOrientation >> Invalid first argument (the orientation )")

    # Take PSD position and pixel data
    PosInfos = []
    DE = mu.DetectorInfoEditorNeunet(pfiles[1])
    WE = mu.WiringInfoEditorNeunet(pfiles[0])
    daqId_v = WE.PutDaqList()
    for i in range(daqId_v.size()):
        mod_v = WE.PutModuleList(daqId_v[i])
        for j in range(mod_v.size()):
            detId_v = WE.PutDetectorList(daqId_v[i], mod_v[j])
            for k in range(detId_v.size()):
                pp_v = DE.PutPositionInfoParams(detId_v[k])
                tmp = [detId_v[k]]
                for li in range(pp_v.size()):
                    tmp.append(float(pp_v[li]))
                PosInfos.append(tmp[:])

    # search minimum distance between PSD direction line and scattering orientation line
    # to find pixel which detects neutrons
    d_info = None
    d_min = 1000000.0
    for ppv in PosInfos:
        lx = ppv[4]
        ly = ppv[5]
        lz = ppv[6]
        lox = ppv[1]
        loy = ppv[2]
        loz = ppv[3]
        l0 = ppv[7]
        dd = ppv[8]

        L = math.sqrt((lx * lx) + (ly * ly) + (lz * lz))
        if L == 0.0:
            continue
        ux = lx / L
        uy = ly / L
        uz = lz / L

        ox = lox - (1.0 * l0 * ux)
        oy = loy - (1.0 * l0 * uy)
        oz = loz - (1.0 * l0 * uz)

        OP = (ox * px) + (oy * py) + (oz * pz)
        OU = (ox * ux) + (oy * uy) + (oz * uz)
        UP = (ux * px) + (uy * py) + (uz * pz)

        t = (OP - (OU * UP)) / (1 - (UP * UP))
        if t < 0.0:
            continue
        s = ((OP * UP) - OU) / (1 - (UP * UP))

        Pd_x = t * px
        Pd_y = t * py
        Pd_z = t * pz

        Ld_x = ox + s * ux
        Ld_y = oy + s * uy
        Ld_z = oz + s * uz

        d = math.sqrt((Pd_x - Ld_x) * (Pd_x - Ld_x) + (Pd_y - Ld_y) * (Pd_y - Ld_y) + (Pd_z - Ld_z) * (Pd_z - Ld_z))

        if d < d_min:
            d_min = d
            d_info = (d, ppv, s)

    if d_info is None:
        # raise UserWarning( "Failed." )
        return None

    mdist, ppv_m, s_m = d_info
    L = math.sqrt(ppv_m[4] * ppv_m[4] + ppv_m[5] * ppv_m[5] + ppv_m[6] * ppv_m[6])

    dx = L / float(pixNum)
    pix = int(s_m / dx)

    if mdist < (dd * 2.0):
        mu.UtsusemiMessage("DetId={}, Pixel={}, minimum d={}".format(
            int(ppv_m[0]), int(pix), mdist))
        return (int(ppv_m[0]), int(pix))
    else:
        mu.UtsusemiMessage("out of range")
        return None

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


def CalcYRotAngleFromQ(LatticeConst=[4.8, 8.4, 2.9, 90, 90, 90], Uvect=[0.0, 1.0, 0.0], Vvect=[0.0, 0.0, 1.0], RotAngle="None", ViewAxis1=[1, 0, 0], ViewAxis2=[0, 1, 0], ViewAxis3=[0, 0, 1], Q=[1.0, 1.0, 1.0], Ei=50.0, hw=0.0, runNo=999999, pixNum=100):
    """
    Calc angle around Y-axis to measure given Q-hw position on caclucated S(Q,E) using lattice constants, U and V vectores etc.
    @param LatticeConst (list)   [<a>,<b>,<c>]
    @param LatticeAngle (list)   [<alpha>,<beta>,<gamma>]
    @param Uvect        (list)   [<Ua>, <Ub>, <Uc>]
    @param Vvect        (list)   [<Va>, <Vb>, <Vc>]
    @param RotAngle     (string) "None" or "<AX>:<deg>[,<AX>:<deg>,..]" <AX>="X","Y","Z"
    @param ViewAxis1    (list)   [<Ax1_a*>,<Ax1_b*>,<Ax1_c*>]
    @param ViewAxis2    (list)   [<Ax2_a*>,<Ax2_b*>,<Ax2_c*>]
    @param ViewAxis3    (list)   [<Ax3_a*>,<Ax3_b*>,<Ax3_c*>]
    @param Q            (list)   [<Q1>,<Q2>,<Q3>]
    @param Ei           (float)  Incident Energy [meV]
    @param hw           (float)  Energy Transfer [meV]
    @param runNo        (int)    Run Number used to select suitable DetecterInfo.xml
    @param pixNum       (int)    The number of pixels on one PSD
    @retval None
    """
    def CalcTwoSpharePlane(OA=[0.0, 0.0, 0.0], OB=[0.0, 0.0, 0.0], Ra=0.0, Rb=0.0):
        A = OA[0] - OB[0]
        B = OA[1] - OB[1]
        C = OA[2] - OB[2]
        DA = OA[0] * OA[0] + OA[0] * OA[0] + OA[0] * OA[0]
        DB = OB[0] * OB[0] + OB[1] * OB[1] + OB[2] * OB[2]
        D = ((Ra * Ra - DA) - (Rb * Rb - DB)) / 2.0
        return (A, B, C, D)

    def CalcPosiOnSphare2D(LineP=[0.0, 0.0, 0.0], r=0.0, SCenter=[0.0, 0.0]):
        '''
        Line : ax+by+cz+d=0
        '''
        a = LineP[0]
        b = LineP[1]
        c = LineP[2]

        D = abs(a * SCenter[0] + b * SCenter[1] + c)
        P1 = (a * a + b * b) * r * r - D * D
        P2 = (a * a + b * b)
        Ax = (a * D - b * (math.sqrt(P1))) / P2 + SCenter[0]
        Ay = (b * D + a * (math.sqrt(P1))) / P2 + SCenter[1]

        Bx = (a * D + b * (math.sqrt(P1))) / P2 + SCenter[0]
        By = (b * D - a * (math.sqrt(P1))) / P2 + SCenter[1]

        return (Ax, Ay, Bx, By)

    XP = mu.UtsusemiSqeCalcXtalParams()

    XP.SetLatticeConstants(LatticeConst)
    XP.SetUVvector(Uvect, Vvect)
    if RotAngle != "None":
        XP.SetRotationSteps(RotAngle)
    VA1 = ViewAxis1[:]
    VA2 = ViewAxis2[:]
    VA3 = ViewAxis3[:]
    VA1.extend([0.0, 'Qa'])
    VA2.extend([0.0, 'Qb'])
    VA3.extend([0.0, 'Qb'])
    VA4 = [0.0, 0.0, 0.0, 1.0, 'Energy']
    XP.SetProjectionAxes(VA1, VA2, VA3, VA4)

    SC = mu.UtsusemiSqeCalc2()
    A = SC.MakeProjectionMatrix(XP.PutLatticeConsts(), XP.PutUVector(
    ), XP.PutVVector(), XP.PutRotateSteps(), XP.PutViewAxes())
    B = Manyo.MakeDoubleVector(9)
    B[0] = A[0]
    B[1] = A[1]
    B[2] = A[2]
    B[3] = A[4]
    B[4] = A[5]
    B[5] = A[6]
    B[6] = A[8]
    B[7] = A[9]
    B[8] = A[10]
    C = SC.InverseMatrix(B)

    UC = mu.UtsusemiUnitConverter()
    ki = math.sqrt(UC.EtoK2(Ei))
    kf = math.sqrt(UC.EtoK2(Ei - hw))
    if mu.UtsusemiEnvGetDebugMode():
        print("ki_q={}".format(ki))

    qx = C[0] * Q[0] + C[1] * Q[1] + C[2] * Q[2]
    qy = C[3] * Q[0] + C[4] * Q[1] + C[5] * Q[2]
    qz = C[6] * Q[0] + C[7] * Q[1] + C[8] * Q[2]
    if mu.UtsusemiEnvGetDebugMode():
        print("Qh,Qk,Ql={},{},{}".format(Q[0], Q[1], Q[2]))
        print("qx,qy,qz={},{},{}".format(qx, qy, qz))

    OA = [0, 0, 0]
    OB = [qx, qy, qz]

    Sa, Sb, Sc, Sd = CalcTwoSpharePlane(OA, OB, Ra=kf, Rb=ki)  # Q-plane
    if mu.UtsusemiEnvGetDebugMode():
        print("{}*x + {}*y + {}*z + {} =0".format(Sa, Sb, Sc, Sd))

    # On X-Z plane (Y=qy)
    # Sa*x + Sb*qx + Sc*z + Sd = 0
    # -> Sa*x + Sc*z + (Sb*qx + Sd) = 0
    # r = ki
    # center is qx,qz (ki)
    Ax, Az, Bx, Bz = CalcPosiOnSphare2D(
        LineP=[Sa, Sc, (Sd + Sb * qy)], r=ki, SCenter=[qx, qz])

    if mu.UtsusemiEnvGetDebugMode():
        print("A = {},{}".format(Ax, Az))
        print("B = {},{}".format(Bx, Bz))

        print("")
        print("Sa*Ax+Sc*Az+(Sd+Sb*qy)= {}".format(Sa * Ax + Sc * Az + Sd + Sb * qy))
        print("Sa*Bx+Sc*Bz+(Sd+Sb*qy)= {}".format(Sa * Bx + Sc * Bz + Sd + Sb * qy))
        print("")

    # angle between ki(0,0,ki) and AQ(qx-Ax, qy-qy, qz-Az)
    angA = math.acos((0 * (Ax - qx) + 0 * (qy - qy) + (ki) * (qz - Az)) / ki / ki) / math.pi * 180.0
    angB = math.acos((0 * (Bx - qx) + 0 * (qy - qy) + (ki) * (qz - Bz)) / ki / ki) / math.pi * 180.0

    if mu.UtsusemiEnvGetDebugMode():
        print("angA={}".format(angA))
        print("angB={}".format(angB))

    lastAngA = angA
    lastAngB = angB
    if (Ax - qx) < 0.0:
        lastAngA = -1.0 * angA
    if (Bx - qx) < 0.0:
        lastAngB = -1.0 * angB

    if mu.UtsusemiEnvGetDebugMode():
        revQh = B[0] * qx + B[1] * qy + B[2] * qz
        revQk = B[3] * qx + B[4] * qy + B[5] * qz
        revQl = B[6] * qx + B[7] * qy + B[8] * qz
        print("")
        print("Qh,Qk,Ql= {}, {}, {}".format(revQh, revQk, revQl))

    # return lastAng

    # Calc kf orientation
    XP.SetRotationSteps("Y:{}".format(-lastAngA))
    SC2 = mu.UtsusemiSqeCalc2()
    A2 = SC2.MakeProjectionMatrix(XP.PutLatticeConsts(), XP.PutUVector(
    ), XP.PutVVector(), XP.PutRotateSteps(), XP.PutViewAxes())
    R2 = SC2.PutInnerMatrix("R")
    kf_x = 0 - Ax
    kf_z = 0 - Az
    kf_y = 0 - qy
    px = R2[0] * kf_x + R2[1] * kf_y + R2[2] * kf_z
    py = R2[3] * kf_x + R2[4] * kf_y + R2[5] * kf_z
    pz = R2[6] * kf_x + R2[7] * kf_y + R2[8] * kf_z

    print("Y Rotation Angle= {}".format(lastAngA))
    if mu.UtsusemiEnvGetDebugMode():
        print("q=({},{},{})".format(Ax, qy, Az))
        print("P=({},{},{})".format(px, py, pz))
        # print("ki,kf={},{}".format(ki,kf))
    pix_info = GetDetectorPixelFromOrientation(px, py, pz, runNo, pixNum)
    if pix_info is not None:
        (detId_A, pixel_A) = pix_info
        print("   detId, pixel = {}, {}".format(detId_A, pixel_A))
    else:
        print(" Out of range ")

    XP.SetRotationSteps("Y:{}".format(-lastAngB))
    A2 = SC2.MakeProjectionMatrix(XP.PutLatticeConsts(), XP.PutUVector(), XP.PutVVector(), XP.PutRotateSteps(), XP.PutViewAxes())
    R2 = SC2.PutInnerMatrix("R")
    kf_x = 0 - Bx
    kf_z = 0 - Bz
    kf_y = 0 - qy
    px = R2[0] * kf_x + R2[1] * kf_y + R2[2] * kf_z
    py = R2[3] * kf_x + R2[4] * kf_y + R2[5] * kf_z
    pz = R2[6] * kf_x + R2[7] * kf_y + R2[8] * kf_z

    print("Y Rotation Angle= {}".format(lastAngB))
    if mu.UtsusemiEnvGetDebugMode():
        print("q=({},{},{})".format(Ax, qy, Az))
        print("P=({},{},{})".format(px, py, pz))
        # print("ki,kf={},{}".format(ki,kf))
    pix_info = GetDetectorPixelFromOrientation(px, py, pz, runNo, pixNum)
    if pix_info is not None:
        detId_B, pixel_B = pix_info
        print("   detId, pixel = {}, {}".format(detId_B, pixel_B))
    else:
        print(" Out of range ")

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


def CalcYRotAngleFromQXtalParam(XtalParam="XtalParam.xml", Q="1.0,1.0,1.0", Ei=45.56, hw=0.0, runNo=999999, pixNum=100):
    """
    Calc angle around Y-axis to measure given Q-hw position on caclucated S(Q,E) using XtalParam file
    @param XtalParam (string) path to XtalParam.xml
    @param Q         (string) "<Qa>, <Qb>, <Qc>"
    @param Ei        (float)  Incident Energy
    @param hw        (float)  Energy Transfer
    @param runNo     (int)    Run Number used to select suitable DetecterInfo.xml
    @param pixNum    (int)    The number of pixels on one PSD
    @retval None
    """
    if not os.path.exists(XtalParam):
        raise UserWarning("XtalParam is not found")

    CC = Manyo.CppToPython()
    XP = mu.UtsusemiSqeCalcXtalParams(XtalParam)
    LC = CC.VectorDoubleToList(XP.PutLatticeConsts())
    Uv = CC.VectorDoubleToList(XP.PutUVector())
    Vv = CC.VectorDoubleToList(XP.PutVVector())
    RS = XP.PutRotateSteps()
    RotStep = ""
    if RS.size() == 0:
        RotStep = "None"
    else:
        for i in range(int(RS.size() / 2)):
            if int(RS[2 * i]) == 0:
                AX = "X"
            elif int(RS[2 * i]) == 1:
                AX = "Y"
            elif int(RS[2 * i]) == 2:
                AX = "Z"
            else:
                pass
            if RotStep == "":
                RotStep = "{}:{}".format(AX, float(RS[2 * i + 1]))
            else:
                RotStep = ",{}:{}".format(AX, float(RS[2 * i + 1]))
    VA = XP.PutViewAxes()
    VA1 = [VA[0], VA[1], VA[2]]
    VA2 = [VA[4], VA[5], VA[6]]
    VA3 = [VA[8], VA[9], VA[10]]

    if type(Q) is list:
        Qlist = Q[:]
    else:
        Qs = Q.split(",")
        Qlist = [float(Qs[i]) for i in range(len(Qs))]

    CalcYRotAngleFromQ(LC, Uv, Vv, RotStep, VA1, VA2,
                       VA3, Qlist, Ei, hw, runNo, pixNum)

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


def CalcYRotAngleFromQString(LatticeConst="4.8,8.4,2.9", LatticeAngles="90.0,90.0,90.0", Uvect="0.0,1.0,0.0", Vvect="0.0,0.0,1.0", RotAngle="None", ViewAxis1="1,0,0", ViewAxis2="0,1,0", ViewAxis3="0,0,1", Q="1.0,1.0,1.0", Ei=45.56, hw=0.0, runNo=999999, pixNum=100):
    """
    Calc angle around Y-axis to measure given Q-hw position on caclucated S(Q,E) using lattice constants, U and V vectores etc.
    @param LatticeConst (string) "<a>,<b>,<c>"
    @param LatticeAngle (string) "<alpha>,<beta>,<gamma>"
    @param Uvect        (string) "<Ua>, <Ub>, <Uc>"
    @param Vvect        (string) "<Va>, <Vb>, <Vc>"
    @param RotAngle     (string) "None" or "<AX>:<deg>[,<AX>:<deg>,..]" <AX>="X","Y","Z"
    @param ViewAxis1    (string) "<Ax1_a*>,<Ax1_b*>,<Ax1_c*>"
    @param ViewAxis2    (string) "<Ax2_a*>,<Ax2_b*>,<Ax2_c*>"
    @param ViewAxis3    (string) "<Ax3_a*>,<Ax3_b*>,<Ax3_c*>"
    @param Q            (string) "<Q1>,<Q2>,<Q3>"
    @param Ei           (float)  Incident Energy [meV]
    @param hw           (float)  Energy Transfer [meV]
    @param runNo        (int)    Run Number used to select suitable DetecterInfo.xml
    @param pixNum       (int)    The number of pixels on one PSD
    @retval None
    """
    def Conv(II):
        IIV = II.split(",")
        ret = []
        for ii in IIV:
            ret.append(float(ii))
        return ret

    LC = Conv(LatticeConst + "," + LatticeAngles)
    UV = Conv(Uvect)
    VV = Conv(Vvect)
    AX1 = Conv(ViewAxis1)
    AX2 = Conv(ViewAxis2)
    AX3 = Conv(ViewAxis3)
    AX4 = [0.0, 0.0, 0.0, 1.0]

    Qlist = Conv(Q)

    CalcYRotAngleFromQ(LC, UV, VV, RotAngle, AX1, AX2,
                       AX3, Qlist, Ei, hw, runNo, pixNum)


##########################################################
# Facade functions for SIK
##########################################################
def RadialCollimatorCorrectSIK(dat, vdat, integRange="All", pixelRange="All"):
    """
    Data Correction for radial collimator on SIK

    @param dat[Def:DAT] (ElementContainerMatrix) Target data
    @param vdat[Def:DAT] (ElementContainerMatrix) Vanadium data
    @param integRange (string) Integrate range "All" or "<start>:<end>"
    @param pixelRange (string) Pixel range to be used "All" or "<start>:<end>"
    @retval None
    """
    if dat.PutSize() != vdat.PutSize():
        raise UserWarning("ERROR : Data sizes are different between dat and vdat.")

    v_integRange = integRange.split(":")
    isAll = True
    x_range = []
    if len(v_integRange) == 2:
        try:
            x_range = [float(v_integRange[0]), float(v_integRange[1])]
            isAll = False
        except:
            raise UserWarning("ERROR : invalid integRange argument")
    elif integRange.upper() != "ALL":
        raise UserWarning("ERROR : invalid integRange argument")

    start_pix = 0
    end_pix = dat(0).PutSize() - 1

    if pixelRange.upper() != "ALL":
        v_pixel = pixelRange.split(":")
        if len(v_pixel) != 2:
            raise UserWarning("ERROR : invalid pixelRange argument")
        start_pix = int(v_pixel[0])
        end_pix = int(v_pixel[1])
        if start_pix > end_pix:
            tmp = start_pix
            start_pix = end_pix
            end_pix = tmp
        if end_pix >= dat(0).PutSize():
            end_pix = dat(0).PutSize() - 1

    sum_vals = 0.0
    list_vals = []

    ignore_num = 0
    for i in range(vdat.PutSize()):
        num_of_ec = 0
        det_v = Manyo.MakeUInt4Vector()
        pix_v = Manyo.MakeUInt4Vector()
        for j in range(start_pix, (end_pix + 1)):
            if vdat(i, j).PutHeaderPointer().PutInt4("MASKED") == 0:
                det_v.append(i)
                pix_v.append(j)
                num_of_ec += 1
        tt = mm.AverageElementContainerMatrix(vdat, det_v, pix_v)
        ec = Manyo.ElementContainer()
        if tt.GetSum(ec):
            pass
        else:
            raise UserWarning("ERRROR : Failed GetSum.")
        if isAll:
            val = ec.Sum()
        else:
            p = ec.Sum(x_range[0], x_range[1])
            val = p.first
        if val == 0.0 or num_of_ec == 0:
            ignore_num += 1
        else:
            val /= float(num_of_ec)
            sum_vals += val
        list_vals.append(val)

    ave_vals = sum_vals / float(vdat.PutSize() - ignore_num)
    for i, val in enumerate(list_vals):
        if val != 0:
            dat(i).MulMySelf(1.0 / val * ave_vals)
