#include "UtsusemiFilterTrignetConditionDNA.hh"
//////////////////////////////////////////////////////////
UtsusemiFilterTrignetConditionDNA::
UtsusemiFilterTrignetConditionDNA(){
    //LChopper = NULL;
    //LBand    = NULL;
    //L1       = NULL;

    //TOFminSource = NULL;
    //TOFmaxSource = NULL;

    LChopper = 0.0;
    LBand    = 0.0;
    L1       = 0.0;

    TOFminSource = 0.0;
    TOFmaxSource = 0.0;

    LChopper = 7.5;  // high speed chopper
    LBand    = 10.0; // low speed band-chopper
    L1       = 42.0;

    TOFminSource = 0.0;
    TOFmaxSource = 0.0;

    LambdaCenter = 1.0;
    DeltaLambda  = 0.5;
    LambdaMin    = 0.5;
    LambdaMax    = 1.5;
    TOFoffset    = 0.0;
    TOFresolver1  = 0.0;
    TOFresolver2  = 0.0;

    _eiRange.clear();
    _tofRange.clear();
    _tofSlit.clear();
}

//////////////////////////////////////////////////////////
UtsusemiFilterTrignetConditionDNA::
~UtsusemiFilterTrignetConditionDNA(){
}

//////////////////////////////////////////////////////////
void UtsusemiFilterTrignetConditionDNA::
Clear(){
    _eiRange.clear();
    _tofRange.clear();
    _tofSlit.clear();
}

//////////////////////////////////////////////////////////
std::vector<Double>  UtsusemiFilterTrignetConditionDNA::
CalcBandRange(){

    Double MASS_NEUTRON    = 1.674928e-27; // in unit of [kg]
    Double HBAR            = 1.054571596e-34; // in unit of [J][s]
    Double J2meV           = 0.624*1e22;

    // std::cout << "##DEBUG" << LambdaMax << std::endl;
    // std::cout << "##DEBUG" << LambdaMin << std::endl;

    Double LambdaMaxM = LambdaMax*1e-10;
    Double LambdaMinM = LambdaMin*1e-10;

    Double Emin   = 2.0*M_PI*M_PI*(HBAR/LambdaMaxM)*(HBAR/LambdaMaxM)/MASS_NEUTRON*J2meV; //[meV]
    Double Emax   = 2.0*M_PI*M_PI*(HBAR/LambdaMinM)*(HBAR/LambdaMinM)/MASS_NEUTRON*J2meV; //[meV]

    Double us2count =40.0;

    //Double tofmin = 2286.2869 * (LBand) / sqrt(Emax) * us2count; //[count]
    //Double tofmax = 2286.2869 * (LBand) / sqrt(Emin) * us2count; //[count]

    Double tofmin = 2286.2869 * (LChopper) / sqrt(Emax) * us2count; //[count]
    Double tofmax = 2286.2869 * (LChopper) / sqrt(Emin) * us2count; //[count]

    // std::cout <<"DEBUG >> LChopper >> " << LChopper <<std::endl;

    std::vector<Double> vals;

    vals.push_back(tofmin);
    vals.push_back(tofmax);
    return vals;
    }

//////////////////////////////////////////////////////////
std::vector<std::vector<Double> > UtsusemiFilterTrignetConditionDNA::
CalcTOFRange(std::vector<std::vector<Double> > ChopperCaseTablesIn)
    {
    std::vector<std::vector<Double> > ChopperCaseTablesOut;

    std::vector<Double> TOFband = CalcBandRange();
    //std::cout << "DEBUG >> TOFband >> "<< TOFband[0] <<"\t"<< TOFband[1] <<std::endl;
    //std::cout << "DEBUG >> TOFRangeSource >> " << TOFminSource <<"\t"<< TOFmaxSource << std::endl;
    UInt4 vectFrameSize = ChopperCaseTablesIn.size();
    for (UInt4 i=0;i<vectFrameSize;i++)
        {
        std::vector<Double> tmpVect;
        UInt4 vectChopSize=ChopperCaseTablesIn.at(i).size();
        for (UInt4 j=0;j<vectChopSize;j++)
            {
            Double TOFslit = ChopperCaseTablesIn.at(i).at(j);
            UInt4 k = j%fastChopperNumOfSlit;

            Double s2us=1e6;
            Double us2count =40;
            Double deltaTChop = fastChopperSlitWidths.at(k)/360.0/fastChopperFrequency/fastChopperMode*s2us*us2count;

            //Double TOFminSample = (L1-LChopper)/LChopper*(TOFslit - deltaTChop*0.5 - TOFmaxSource*us2count) + TOFslit;
            //Double TOFmaxSample = (L1-LChopper)/LChopper*(TOFslit + deltaTChop*0.5 - TOFminSource*us2count) + TOFslit;

            Double TOFminSample = L1/LChopper*(TOFslit - deltaTChop*0.5 - TOFmaxSource*us2count) + TOFslit;
            Double TOFmaxSample = L1/LChopper*(TOFslit + deltaTChop*0.5 - TOFminSource*us2count) + TOFslit;

/* correct ?
            if (TOFminSample<TOFband[0]){
                tmpVect.push_back(TOFband[0]);
                }
            else if (TOFminSample>TOFband[1]){
                tmpVect.push_back(TOFband[1]);
                }
            else{
                tmpVect.push_back(TOFminSample);
                }
*/
            //tmpVect.push_back(TOFslit);
/* correct ?
            if (TOFmaxSample<TOFband[0]){
                tmpVect.push_back(TOFband[0]);
                }
            else if (TOFmaxSample>TOFband[1]){
                tmpVect.push_back(TOFband[1]);
                }
            else{
                tmpVect.push_back(TOFmaxSample);
                }
*/

            tmpVect.push_back(TOFminSample);
            tmpVect.push_back(TOFmaxSample);
            }
        ChopperCaseTablesOut.push_back(tmpVect);
        }

    return ChopperCaseTablesOut;
    }

//////////////////////////////////////////////////////////

std::vector<std::vector<Double> > UtsusemiFilterTrignetConditionDNA::
CalcTOFRange(std::vector<std::vector<UInt4> > ChopperCaseTablesIn1, std::vector<Double> ChopperInstClockTablesIn)
    {
    std::vector<std::vector<Double> >  ChopperCaseTablesOut;

    std::vector<Double> TOFband = CalcBandRange();

    std::vector<std::vector<Double> > ChopperCaseTablesIn = _CalcTOFSlit(ChopperCaseTablesIn1, ChopperInstClockTablesIn);

    std::vector<Double> _tmpTOFRange;
    std::vector<Double> _tmpEiRange;

    UInt4 vectFrameSize = ChopperCaseTablesIn.size();
    for (UInt4 i=0;i<vectFrameSize;i++)
        {
        std::vector<Double> tmpVect;
        UInt4 vectChopSize=ChopperCaseTablesIn.at(i).size();
        for (UInt4 j=0;j<vectChopSize;j++)
            {
            Double TOFslit = ChopperCaseTablesIn.at(i).at(j);
            UInt4 k = j%fastChopperNumOfSlit;

            Double s2us=1e6;
            Double us2count =40.0;
            Double deltaTChop = fastChopperSlitWidths.at(k)/360.0/fastChopperFrequency/fastChopperMode*s2us*us2count;

            Double TOFminSample = L1/LChopper*(TOFslit - deltaTChop*0.5 - TOFmaxSource*us2count) + TOFslit;
            Double TOFmaxSample = L1/LChopper*(TOFslit + deltaTChop*0.5 - TOFminSource*us2count) + TOFslit;

            if (TOFband[0] <= TOFslit && TOFslit < TOFband[1])
                {
                tmpVect.push_back(TOFminSample);
                tmpVect.push_back(TOFmaxSample);

                //EiRange option start//
                Double _TOFMax = (TOFmaxSample-TOFslit)/us2count;
                Double _TOFMin = (TOFminSample-TOFslit)/us2count;

                if (_tmpTOFRange.empty())
                    {
                    _tmpTOFRange.push_back(_TOFMin);
                    _tmpTOFRange.push_back(_TOFMax);
                    }
                else
                    {
                    Double t3 = _TOFMin;
                    Double t4 = _TOFMax;
                    UInt4 vectSize = (UInt4)(_tmpTOFRange.size()/2);
                    for (UInt4 i=0;i<vectSize;i++)
                        {
                        Double t1 = _tmpTOFRange[2*i];
                        Double t2 = _tmpTOFRange[2*i+1];
                        if ((t3<=t1) && (t1<t4) && (t4<=t2) ){
                            _tmpTOFRange[2*i]  =t3;
                            break;
                        }else if ((t1<=t3) && (t3<=t2) && (t2<=t4) ){
                            _tmpTOFRange[2*i+1]=t4;
                            break;
                        }else if ((t1<=t3) && (t3<=t4) && (t4<=t2) ){
                            break;
                        }else if ((t3<=t1) && (t1<=t2) && (t2<=t4) ){
                            _tmpTOFRange[2*i]  =t3;
                            _tmpTOFRange[2*i+1]=t4;
                            break;
                            }

                        if (i==vectSize-1){
                            _tmpTOFRange.push_back(t3);
                            _tmpTOFRange.push_back(t4);
                            }
                        }
                    }
                //EiRange option end  //
                }
            }
        ChopperCaseTablesOut.push_back(tmpVect);
        }

    for (UInt4 i=0;i<_tmpTOFRange.size()/2;i++)
        {
        Double _TOFMin = _tmpTOFRange[2*i];
        Double _TOFMax = _tmpTOFRange[2*i+1];
        Double _EiMax = (2286.2869*L1/_TOFMin)*(2286.2869*L1/_TOFMin);
        Double _EiMin = (2286.2869*L1/_TOFMax)*(2286.2869*L1/_TOFMax);
        _tmpEiRange.push_back(_EiMax);
        _tmpEiRange.push_back(_EiMin);
        }
    reverse(_tmpEiRange.begin(),_tmpEiRange.end());
    _tofRange = _tmpTOFRange;
    _eiRange  = _tmpEiRange;

    return ChopperCaseTablesOut;
    }

//////////////////////////////////////////////////////////

std::vector<std::vector<Double> > UtsusemiFilterTrignetConditionDNA::
CalcTOFRange(std::vector<std::vector<UInt4> > ChopperCaseTablesIn1,std::vector<std::vector<UInt4> > ChopperCaseTablesIn2, std::vector<Double> ChopperInstClockTablesIn)
    {
    std::vector<std::vector<Double> >  ChopperCaseTablesOut;

    std::vector<Double> TOFband = CalcBandRange();

    std::vector<std::vector<Double> > ChopperCaseTablesIn = _CalcTOFSlit(ChopperCaseTablesIn1, ChopperCaseTablesIn2, ChopperInstClockTablesIn);

    std::vector<Double> _tmpTOFRange;
    std::vector<Double> _tmpEiRange;

    UInt4 vectFrameSize = ChopperCaseTablesIn.size();
    for (UInt4 i=0;i<vectFrameSize;i++)
        {
        std::vector<Double> tmpVect;
        UInt4 vectChopSize=ChopperCaseTablesIn.at(i).size();
        for (UInt4 j=0;j<vectChopSize;j++)
            {
            Double TOFslit = ChopperCaseTablesIn.at(i).at(j);
            UInt4 k = j%fastChopperNumOfSlit;

            Double s2us=1e6;
            Double us2count =40;
            Double deltaTChop = fastChopperSlitWidths.at(k)/360.0/fastChopperFrequency/fastChopperMode*s2us*us2count;

            Double TOFminSample = L1/LChopper*(TOFslit - deltaTChop*0.5 - TOFmaxSource*us2count) + TOFslit;
            Double TOFmaxSample = L1/LChopper*(TOFslit + deltaTChop*0.5 - TOFminSource*us2count) + TOFslit;

              if (TOFband[0] <= TOFslit && TOFslit < TOFband[1])
                {
                tmpVect.push_back(TOFminSample);
                tmpVect.push_back(TOFmaxSample);

                //EiRange option start//
                Double _TOFMax = (TOFmaxSample-TOFslit)/us2count;
                Double _TOFMin = (TOFminSample-TOFslit)/us2count;

                if (_tmpTOFRange.empty())
                    {
                    _tmpTOFRange.push_back(_TOFMin);
                    _tmpTOFRange.push_back(_TOFMax);
                    }
                else
                    {
                    Double t3 = _TOFMin;
                    Double t4 = _TOFMax;
                    UInt4 vectSize = (UInt4)(_tmpTOFRange.size()/2);
                    for (UInt4 i=0;i<vectSize;i++)
                        {
                        Double t1 = _tmpTOFRange[2*i];
                        Double t2 = _tmpTOFRange[2*i+1];
                        if ((t3<=t1) && (t1<t4) && (t4<=t2) ){
                            _tmpTOFRange[2*i]  =t3;
                            break;
                        }else if ((t1<=t3) && (t3<=t2) && (t2<=t4) ){
                            _tmpTOFRange[2*i+1]=t4;
                            break;
                        }else if ((t1<=t3) && (t3<=t4) && (t4<=t2) ){
                            break;
                        }else if ((t3<=t1) && (t1<=t2) && (t2<=t4) ){
                            _tmpTOFRange[2*i]  =t3;
                            _tmpTOFRange[2*i+1]=t4;
                            break;
                            }

                        if (i==vectSize-1){
                            _tmpTOFRange.push_back(t3);
                            _tmpTOFRange.push_back(t4);
                            }
                        }
                    }
                //EiRange option end  //

                }
            }
        ChopperCaseTablesOut.push_back(tmpVect);
        }

    for (UInt4 i=0;i<_tmpTOFRange.size()/2;i++)
        {
        Double _TOFMin = _tmpTOFRange[2*i];
        Double _TOFMax = _tmpTOFRange[2*i+1];
        Double _EiMax = (2286.2869*L1/_TOFMin)*(2286.2869*L1/_TOFMin);
        Double _EiMin = (2286.2869*L1/_TOFMax)*(2286.2869*L1/_TOFMax);
        _tmpEiRange.push_back(_EiMax);
        _tmpEiRange.push_back(_EiMin);
        }
    reverse(_tmpEiRange.begin(),_tmpEiRange.end());
    _tofRange = _tmpTOFRange;
    _eiRange  = _tmpEiRange;

    return ChopperCaseTablesOut;
    }

//////////////////////////////////////////////////////////
std::vector<Double> UtsusemiFilterTrignetConditionDNA::
CalcTOFRange()
    {
    std::vector<Double> TOFRange;

    std::vector<Double> TOFband = CalcBandRange();
    std::vector<Double> TOFSlitVec = _CalcTOFSlit();

    UInt4 vectSize = TOFSlitVec.size();
    for (UInt4 j=0;j<vectSize;j++)
        {
        Double TOFslit = TOFSlitVec.at(j);

        if (TOFband[0] <= TOFslit && TOFslit < TOFband[1])
            {
            UInt4 k = j%fastChopperNumOfSlit;
            Double s2us=1e6;
            Double us2count =40;
            Double deltaTChop = fastChopperSlitWidths.at(k)/360.0/fastChopperFrequency*s2us*us2count;       // [count]

            //Double TOFminSample = (L1-LChopper)/LChopper*(TOFslit - deltaTChop*0.5 - TOFmaxSource*us2count) + TOFslit;
            //Double TOFmaxSample = (L1-LChopper)/LChopper*(TOFslit + deltaTChop*0.5 - TOFminSource*us2count) + TOFslit;

            Double TOFminSample = L1/LChopper*(TOFslit - deltaTChop*0.5 - TOFmaxSource*us2count) + TOFslit; // [count]
            Double TOFmaxSample = L1/LChopper*(TOFslit + deltaTChop*0.5 - TOFminSource*us2count) + TOFslit; // [count]

            TOFRange.push_back(TOFminSample);
            TOFRange.push_back(TOFmaxSample);
            }
        }

    _tofRange = TOFRange;

    return TOFRange;
    }
//////////////////////////////////////////////////////////
std::vector<Double> UtsusemiFilterTrignetConditionDNA::
CalcEiRange(){
    std::vector<Double> EiRange;

    std::vector<Double> TOFSlitVec  = CalcTOFSlit();
    std::vector<Double> TOFRangeVec = CalcTOFRange();

    Double us2count =40;
    if (TOFSlitVec.size()>0 && TOFRangeVec.size() >= TOFSlitVec.size()*2)
        {
        for (UInt4 i=0;i<TOFSlitVec.size();i++)
            {
            Double TOFmin  = TOFRangeVec.at(i*2)/us2count;
            Double TOFmax  = TOFRangeVec.at(i*2+1)/us2count;
            Double TOFslit = TOFSlitVec.at(i)/us2count;
            Double EiMin = (2286.2869*L1/(TOFmax-TOFslit))*(2286.2869*L1/(TOFmax-TOFslit));
            Double EiMax = (2286.2869*L1/(TOFmin-TOFslit))*(2286.2869*L1/(TOFmin-TOFslit));

            EiRange.push_back(EiMin);
            EiRange.push_back(EiMax);
            }
        }
    _eiRange=EiRange;
    return EiRange;
    }
//////////////////////////////////////////////////////////
std::vector<Double> UtsusemiFilterTrignetConditionDNA::
CalcEiShift(){
    std::vector<Double> EiShifts;

    std::vector<Double> TOFSlitVec  = CalcTOFSlit();
    std::vector<Double> TOFRangeVec = CalcTOFRange();

    Double us2count =40;
    if (TOFSlitVec.size()>0 && TOFRangeVec.size() >= TOFSlitVec.size()*2)
        {
        for (UInt4 i=0;i<TOFSlitVec.size();i++)
            {
            Double TOFmin  = TOFRangeVec.at(i*2)/us2count;
            Double TOFmax  = TOFRangeVec.at(i*2+1)/us2count;
            Double TOFslit = TOFSlitVec.at(i)/us2count;
            Double EiCenter       = (2286.2869*L1/((TOFmax+TOFmin)/2.0))*(2286.2869*L1/(TOFmax-TOFslit));
            Double EiCenter_shift = (2286.2869*L1/((TOFmax+TOFmin)/2.0-TOFslit))*(2286.2869*L1/(TOFmax-TOFslit));

            Double EiShift = EiCenter - EiCenter_shift;
            EiShifts.push_back(EiShift);
            }
        }

    return EiShifts;
    }

//////////////////////////////////////////////////////////
std::vector<std::vector<Double> > UtsusemiFilterTrignetConditionDNA::
CalcTOFRangeDebug(std::vector<std::vector<Double> > ChopperCaseTablesIn)
    {
    std::vector<std::vector<Double> > ChopperCaseTablesOut;

    UInt4 vectFrameSize = ChopperCaseTablesIn.size();
    for (UInt4 i=0;i<vectFrameSize;i++)
        {
        std::vector<Double> tmpVect;
        UInt4 l=0;
        UInt4 vectChopSize=ChopperCaseTablesIn.at(i).size();
        for (UInt4 j=0;j<vectChopSize;j++)
            {
            Double chopValLow=l*44444.44*3;
            Double chopValUp =(l+1)*44444.44*3;
            tmpVect.push_back(chopValLow);
            tmpVect.push_back(chopValUp);
            l++;
            }
        ChopperCaseTablesOut.push_back(tmpVect);
        }

    return ChopperCaseTablesOut;
    }

//////////////////////////////////////////////////////////

std::vector<std::vector<Double> > UtsusemiFilterTrignetConditionDNA::
CalcTOFSlit(std::vector<std::vector<UInt4> > ChopperCaseTablesIn1, std::vector<Double> ChopperInstClockTablesIn)
    {
    // In the case of fastChopperMode=1 (j=1), one Fast Chopper Disk was used
    //ChopperCaseTablesIn      : from Trignet Digital data(0x54) TOF @24bit by 40MHz:
    //ChopperInstClockTablesIn1 : from Trignet Instrument clock data(0x5c) TOF @11bit by 40MHz:

    std::vector<std::vector<Double> > ChopperCaseTablesOut;
    std::vector<Double> TOFband = CalcBandRange();
    std::vector<std::vector<Double> > ChopperCaseTablesIn = _CalcTOFSlit(ChopperCaseTablesIn1, ChopperInstClockTablesIn);

    UInt4 vectFrameSize = ChopperCaseTablesIn.size();
    for (UInt4 i=0;i<vectFrameSize;i++)
        {
        std::vector<Double> tmpVect;
        UInt4 vectChopSize=ChopperCaseTablesIn.at(i).size();
        for (UInt4 j=0;j<vectChopSize;j++)
            {
            Double TOFslit = ChopperCaseTablesIn.at(i).at(j);
              if (TOFband[0] <= TOFslit && TOFslit < TOFband[1])
                {
                tmpVect.push_back(TOFslit);
                }
            }
        ChopperCaseTablesOut.push_back(tmpVect);
        }

    //_tofSlit = ChopperCaseTablesOut;
    return ChopperCaseTablesOut;
    }

//////////////////////////////////////////////////////////

std::vector<std::vector<Double> > UtsusemiFilterTrignetConditionDNA::
_CalcTOFSlit(std::vector<std::vector<UInt4> > ChopperCaseTablesIn, std::vector<Double> ChopperInstClockTablesIn)
    {
    // In the case of fastChopperMode=1 (j=1), one Fast Chopper Disk was used
    //ChopperCaseTablesIn      : from Trignet Digital data(0x54) TOF @24bit by 40MHz:
    //ChopperInstClockTablesIn : from Trignet Instrument clock data(0x5c) TOF @11bit by 40MHz:
    //@local variable
    //fastChopperFrequency;
    //fastChopperNumOfSlit;
    //fastChopperSlitWidths;
    //fastChopperSlitAngles;
    //fastChopperMode;

    std::vector<std::vector<Double> > ChopperCaseTablesOut;
    UInt4 vectFrameSize = ChopperCaseTablesIn.size();
    for (UInt4 i=0;i<vectFrameSize;i++)
        {
        std::vector<Double> tmpVect;
        UInt4 vectChopSize=ChopperCaseTablesIn.at(i).size();
        for (UInt4 j=0;j<vectChopSize;j++)
            {
            if (j==vectChopSize-1 && i==vectFrameSize-1)
                {
                }
            else
                {
                //TOF diff calc - start  //usec
                Double TOFdiff;
                Double TOFstart=(Double)(ChopperCaseTablesIn.at(i).at(j));
                if (j==vectChopSize-1)
                    {
                    TOFdiff =ChopperInstClockTablesIn.at(i+1)-ChopperInstClockTablesIn.at(i);
                    TOFdiff += (Double)(ChopperCaseTablesIn.at(i+1).at(0)) - (Double)(ChopperCaseTablesIn.at(i).at(j));
                    }
                else
                    {
                    TOFdiff = (Double)(ChopperCaseTablesIn.at(i).at(j+1)) - (Double)(ChopperCaseTablesIn.at(i).at(j));
                    }
                //TOF diff calc - end
                Double deltaTj = TOFresolver1;

                //calc summary - start

                for (UInt4 k=0; k<fastChopperNumOfSlit;k++)
                    {
                    Double s2us=1e6;
                    Double us2count =40.0;
                    //Double deltaTChop = fastChopperSlitWidths.at(k)/360.0/fastChopperFrequency/fastChopperMode*s2us*us2count;
                    ////Double TOFslit = TOFstart + deltaTChop + TOFdiff / fastChopperNumOfSlit*k - deltaTj;
                    //Double TOFslit = TOFstart + deltaTChop + TOFdiff *fastChopperSlitAngles.at(k)/360.0 - deltaTj;

                    Double TOFslit = TOFstart + TOFdiff *fastChopperSlitAngles.at(k)/360.0 - deltaTj*us2count;
                    tmpVect.push_back(TOFslit);

                    }
                //calc summary - end
                }
            }
        ChopperCaseTablesOut.push_back(tmpVect);
        }

    return ChopperCaseTablesOut;
    }


//////////////////////////////////////////////////////////

std::vector<std::vector<Double> > UtsusemiFilterTrignetConditionDNA::
CalcTOFSlit(std::vector<std::vector<UInt4> > ChopperCaseTablesIn1,std::vector<std::vector<UInt4> > ChopperCaseTablesIn2, std::vector<Double> ChopperInstClockTablesIn)
    {
    // In the case of fastChopperMode=2 (j=2), two Fast Chopper Disks were used

    //ChopperCaseTablesIn1      : from Trignet Digital data(0x54) TOF @24bit by 40MHz: fastCopper 1
    //ChopperCaseTablesIn2      : from Trignet Digital data(0x54) TOF @24bit by 40MHz: fastCopper 2

    //ChopperInstClockTablesIn : from Trignet Instrument clock data(0x5c) TOF @11bit by 40MHz:

    std::vector<std::vector<Double> > ChopperCaseTablesOut;
    std::vector<Double> TOFband = CalcBandRange();
    std::vector<std::vector<Double> > ChopperCaseTablesIn = _CalcTOFSlit(ChopperCaseTablesIn1, ChopperCaseTablesIn2, ChopperInstClockTablesIn);

    UInt4 vectFrameSize = ChopperCaseTablesIn.size();
    for (UInt4 i=0;i<vectFrameSize;i++)
        {
        std::vector<Double> tmpVect;
        UInt4 vectChopSize=ChopperCaseTablesIn.at(i).size();
        for (UInt4 j=0;j<vectChopSize;j++)
            {
            Double TOFslit = ChopperCaseTablesIn.at(i).at(j);
              if (TOFband[0] <= TOFslit && TOFslit < TOFband[1])
                {
                tmpVect.push_back(TOFslit);
                }
            }
        ChopperCaseTablesOut.push_back(tmpVect);
        }

    //_tofSlit = ChopperCaseTablesOut;
    return ChopperCaseTablesOut;

    }

//////////////////////////////////////////////////////////

std::vector<std::vector<Double> > UtsusemiFilterTrignetConditionDNA::
_CalcTOFSlit(std::vector<std::vector<UInt4> > ChopperCaseTablesIn1,std::vector<std::vector<UInt4> > ChopperCaseTablesIn2, std::vector<Double> ChopperInstClockTablesIn)
    {
    // In the case of fastChopperMode=2 (j=2), two Fast Chopper Disks were used

    //ChopperCaseTablesIn1      : from Trignet Digital data(0x54) TOF @24bit by 40MHz: fastCopper 1
    //ChopperCaseTablesIn2      : from Trignet Digital data(0x54) TOF @24bit by 40MHz: fastCopper 2

    //ChopperInstClockTablesIn : from Trignet Instrument clock data(0x5c) TOF @11bit by 40MHz:
    //@local variable
    //fastChopperFrequency;
    //fastChopperNumOfSlit;
    //fastChopperSlitWidths;
    //fastChopperSlitAngles;
    //fastChopperMode;

    std::vector<std::vector<Double> > ChopperCaseTablesOut;

    UInt4 vectFrameSize1 = ChopperCaseTablesIn1.size();
    UInt4 vectFrameSize2 = ChopperCaseTablesIn2.size();
    UInt4 vectFrameSize;

    if (vectFrameSize1>vectFrameSize2)
        {
        vectFrameSize=vectFrameSize2;
        }
    else
        {
        vectFrameSize=vectFrameSize1;
        }

    for (UInt4 i=0;i<vectFrameSize;i++)
        {
        std::vector<Double> tmpVect;
        UInt4 vectChopSize1=ChopperCaseTablesIn1.at(i).size();
        UInt4 vectChopSize2=ChopperCaseTablesIn2.at(i).size();
        UInt4 vectChopSize;

        if (vectChopSize1>vectChopSize2)
            {
            vectChopSize=vectChopSize2;
            }
        else
            {
            vectChopSize=vectChopSize1;
            }

        for (UInt4 j=0;j<vectChopSize;j++)
            {
            if (j==vectChopSize-1 && i==vectFrameSize-1)
                {
                }
            else
                {
                //TOF diff calc - start  //usec
                Double TOFdiff1;
                Double TOFstart1=(Double)(ChopperCaseTablesIn1.at(i).at(j));
                Double TOFdiff2;
                Double TOFstart2=(Double)(ChopperCaseTablesIn2.at(i).at(j));

                if (j==vectChopSize-1)
                    {
                    TOFdiff1 =ChopperInstClockTablesIn.at(i+1)-ChopperInstClockTablesIn.at(i);
                    TOFdiff2 =ChopperInstClockTablesIn.at(i+1)-ChopperInstClockTablesIn.at(i);
                    TOFdiff1 += (Double)(ChopperCaseTablesIn1.at(i+1).at(0)) - (Double)(ChopperCaseTablesIn1.at(i).at(j));
                    TOFdiff2 += (Double)(ChopperCaseTablesIn2.at(i+1).at(0)) - (Double)(ChopperCaseTablesIn2.at(i).at(j));
                    }
                else
                    {
                    TOFdiff1 = (Double)(ChopperCaseTablesIn1.at(i).at(j+1)) - (Double)(ChopperCaseTablesIn1.at(i).at(j));
                    TOFdiff2 = (Double)(ChopperCaseTablesIn2.at(i).at(j+1)) - (Double)(ChopperCaseTablesIn2.at(i).at(j));
                    }
                //TOF diff calc - end

                Double deltaTj1 = TOFresolver1;
                Double deltaTj2 = TOFresolver2;
                //calc summary - start
                for (UInt4 k=0; k<fastChopperNumOfSlit;k++)
                    {
                    Double s2us=1e6;
                    Double us2count =40;

                    Double TOFslit1 = TOFstart1 + TOFdiff1 *fastChopperSlitAngles.at(k)/360.0 - deltaTj1;
                    Double TOFslit2 = TOFstart2 + TOFdiff2 *fastChopperSlitAngles.at(k)/360.0 - deltaTj2;

                    // From the instruction in E-mail (2014/8/8)
                    Double TOFslitBoth = (TOFslit1 + TOFslit2)*0.5;

                    Double a1 = 2.0*M_PI/TOFdiff1;
                    Double b1 = -a1*TOFslit1;

                    // Yamada Start[20141212]
                    Double YCP = a1*TOFslitBoth + b1;
                    Double YB = YCP + fastChopperSlitAngles.at(k)/2.0*M_PI/180;
                    Double YD = YCP - fastChopperSlitAngles.at(k)/2.0*M_PI/180;

                    Double YG1 = 5.73/2.0*M_PI/180; // 5.73[deg] is open the open angle of the neutron guide.
                    Double YG2 = -5.73/2.0*M_PI/180;
                    // Yamada End[20141212]

                    if ((TOFslit1<TOFslit2 && YD<YG1) || (TOFslit1>=TOFslit2 && YB>YG2))
                        {
                        tmpVect.push_back(TOFslitBoth);
                        }
                    }
                //calc summary - end
                }
            }
        ChopperCaseTablesOut.push_back(tmpVect);
        }

    return ChopperCaseTablesOut;
    }

//////////////////////////////////////////////////////////

std::vector<Double> UtsusemiFilterTrignetConditionDNA::
_CalcTOFSlit()
    {
    // In the case of Fast Chopper Disk used, trignet log not used

    std::vector<Double> tmpVect;
    UInt4 numberOfRotations=(UInt4)(fastChopperFrequency/25.0);
    Double s2us = 1e6;
    //Double offset = TOFoffset;
    Double offset = TOFresolver1;

    Double TOFdiff = (1.0/fastChopperFrequency)*s2us; // [us]

    for (UInt4 i=0;i<numberOfRotations;i++)
        {
        for (UInt4 k=0; k<fastChopperNumOfSlit;k++)
            {
            Double us2count = 40;
    std::cout << "TY i,k,offset,TOFdiff,angle >>" << i << ", k= "<<  k << ", offset= "<<  offset<< ", TOFdiff=" << TOFdiff<< ", angle= " <<fastChopperSlitAngles.at(k)  << std::endl;

            Double TOFslit = - offset + TOFdiff *(i + fastChopperSlitAngles.at(k)/360.0);  // [us]
    std::cout << "TY" << " TOFSlit=" << TOFslit << std::endl;
            TOFslit *= us2count; // [count]

            tmpVect.push_back(TOFslit);
            }
        }

    return tmpVect;
    }

//////////////////////////////////////////////////////////

std::vector<Double> UtsusemiFilterTrignetConditionDNA::
CalcTOFSlit()
    {
    // In the case of Fast Chopper Disk used, trignet log not used
    std::vector<Double> tmpVect;
    std::vector<Double> TOFSlitVec = _CalcTOFSlit();
    std::vector<Double> TOFband = CalcBandRange();

    UInt4 vectSize = TOFSlitVec.size();
    for (UInt4 j=0;j<vectSize;j++)
        {
        Double TOFslit = TOFSlitVec.at(j);
        if (TOFband[0] <= TOFslit && TOFslit < TOFband[1])
            {
            tmpVect.push_back(TOFslit);
            }
        }

    _tofSlit = tmpVect;
    return tmpVect;
    }

//////////////////////////////////////////////////////////

std::vector<Double> UtsusemiFilterTrignetConditionDNA::
GetTOFRange()
    {
    return _tofRange;
    }

//////////////////////////////////////////////////////////
std::vector<Double> UtsusemiFilterTrignetConditionDNA::
GetEiRange()
    {
    return _eiRange;
    }

//////////////////////////////////////////////////////////
std::vector<Double> UtsusemiFilterTrignetConditionDNA::
GetTOFSlit()
    {
    return _tofSlit;
    }

