#include "MlfDetectorEfficiencyCorrection.hh"
//////////////////////////////////////////////////////////////////////////
MlfDetectorEfficiencyCorrection::
MlfDetectorEfficiencyCorrection(){
    Initialize();
}
//////////////////////////////////////////////////////////////////////////
MlfDetectorEfficiencyCorrection::
MlfDetectorEfficiencyCorrection( std::string _detInfoName, std::string _detName, std::string _xsecDataName, std::string _xmlPath ){
    Initialize();
    SetXmlPath( _xmlPath );
    Initialize( _detInfoName, _detName, _xsecDataName);
}
//////////////////////////////////////////////////////////////////////////
MlfDetectorEfficiencyCorrection::
MlfDetectorEfficiencyCorrection( std::string _apDataPath ){
    Initialize();
    if (!LoadApproximateData( _apDataPath ))
        std::cout << _MessageTag+" Fails to load approximate data :"+_apDataPath<<std::endl;

}
//////////////////////////////////////////////////////////////////////////
MlfDetectorEfficiencyCorrection::
~MlfDetectorEfficiencyCorrection(){
    ClearMNG();
    if (EffiApproxBox!=NULL){
        for (UInt4 i=0; i<_num_of_Lambda; i++)
            delete [] EffiApproxBox[i];
        delete [] EffiApproxBox;
        EffiApproxBox = NULL;
    }
    delete _st;
}
//////////////////////////////////////////////////////////////////////////
bool MlfDetectorEfficiencyCorrection::
Initialize(){
    _MNG = NULL;
    _NumOfMulTh = MlfGetNumOfMulTh();
    _XmlSearchPaths.clear();
    _MessageTag="MlfDetectorEfficiencyCorrection::";
    _DetectorName="";
    EffiApproxBox=NULL;
    _st = new StringTools();
    _min_Lambda = 0.;
    _delta_Lambda = 0.;
    _min_Th = 0.;
    _delta_Th = 0.;

    return true;
}
//////////////////////////////////////////////////////////////////////////
void MlfDetectorEfficiencyCorrection::
ClearMNG(){
    if (_MNG!=NULL){
        for (UInt4 i=0; i<(_MNG->size()); i++)
            delete _MNG->at(i);
        delete _MNG;
        _MNG=NULL;
    }
}
//////////////////////////////////////////////////////////////////////////
void MlfDetectorEfficiencyCorrection::
SetXmlPath( std::string path ){
    _XmlSearchPaths.clear();
    _XmlSearchPaths.push_back(path);
}
//////////////////////////////////////////////////////////////////////////
void MlfDetectorEfficiencyCorrection::
AddXmlPath( std::string path ){
    _XmlSearchPaths.push_back(path);
}
//////////////////////////////////////////////////////////////////////////
void MlfDetectorEfficiencyCorrection::
SetXmlPath( std::vector<std::string> paths ){
    for (UInt4 i=0; i<paths.size(); i++)
        _XmlSearchPaths.push_back(paths[i]);
}
//////////////////////////////////////////////////////////////////////////
bool MlfDetectorEfficiencyCorrection::
Initialize( std::string _detInfoName, std::string _detName, std::string _xsecDataName){
    // check whether given file is existed or not
    std::vector<std::string> path_DI_list,path_XS_list;
    path_DI_list.push_back( _detInfoName );
    path_XS_list.push_back( _xsecDataName );
    for (UInt4 i=0; i<_XmlSearchPaths.size(); i++){
        if (_xsecDataName==""){
            MlfScatAbsoBodyManager* MSA = new MlfScatAbsoBodyManager();
            _xsecDataName=MSA->_XML_NAME_NISTDATA;
            delete MSA;
        }
        char tmp_path1[200], tmp_path2[200];
        std::snprintf( tmp_path1, sizeof(tmp_path1), "%s/%s", _XmlSearchPaths[i].c_str(), _detInfoName.c_str() );
        std::snprintf( tmp_path2, sizeof(tmp_path2), "%s/%s", _XmlSearchPaths[i].c_str(), _xsecDataName.c_str() );
        std::string a_path1( tmp_path1 );
        std::string a_path2( tmp_path2 );
        path_DI_list.push_back( tmp_path1 );
        path_XS_list.push_back( tmp_path2 );
    }
    struct stat st;
    for (UInt4 i=0; i<path_DI_list.size(); i++){
        const char* file =path_DI_list[i].c_str();
        UInt4 ret = stat( file, &st );
        if (ret==0) {
            _detInfoName = path_DI_list[i];
            break;
        }
    }
    if (_xsecDataName!=""){
        for (UInt4 i=0; i<path_XS_list.size(); i++){
            const char* file =path_XS_list[i].c_str();
            UInt4 ret = stat( file, &st );
            if (ret==0) {
                _xsecDataName = path_XS_list[i];
                break;
            }
        }
    }
    ClearMNG();
    _MNG = new std::vector< MlfScatAbsoBodyManager* >( _NumOfMulTh, NULL );
    for (UInt4 i=0; i<_NumOfMulTh; i++){
        _MNG->at(i) = new MlfScatAbsoBodyManager();
        bool ret1 = _MNG->at(i)->SetXmlInfoFile( _detInfoName, _xsecDataName );
        bool ret2 = false;
        if (ret1)
            ret2 = _MNG->at(i)->SetDetName( _detName );
        if (ret1&&ret2){
        }else{
            return false;
        }
    }
    _DetectorName = _detName;
    return true;
}
//////////////////////////////////////////////////////////////////////////
void MlfDetectorEfficiencyCorrection::
Execute( ElementContainerMatrix* _ecm ){

    HeaderBase* hh = _ecm->PutHeaderPointer();
    Double Ei = hh->PutDouble("Ei");
    UInt4 ThNum = 0;

#ifdef MULTH
    omp_set_num_threads( _NumOfMulTh );
#endif


    for (UInt4 i=0; i<(_ecm->PutSize()); i++){
        HeaderBase* hh_ECA = _ecm->PutPointer(i)->PutHeaderPointer();
        std::vector<Double> detPosi;
        detPosi.clear();
        if (hh_ECA->CheckKey("DETPOSINFO")==1) detPosi = hh_ECA->PutDoubleVector("DETPOSINFO");

        for (UInt4 j=0; j<(_ecm->PutPointer(i)->PutSize()); j++){
            ElementContainer* ec = _ecm->PutPointer(i)->PutPointer(j);
            HeaderBase* hh_ec = ec->PutHeaderPointer();

            Double theta = 0.0;
            std::vector<Double> pv = hh_ec->PutDoubleVector("PixelPosition");
            Double ll = sqrt( pv[0]*pv[0] + pv[1]*pv[1] + pv[2]*pv[2] );
            // No detector posiion info => assume that the detector direction is vertical (along Y-axis)
            if (detPosi.empty()){
                Double ll0= sqrt( pv[0]*pv[0] + pv[2]*pv[2] );
                theta = fabs( acos( ll0/ll )/M_PI*180.0 ); //degree
            }else{
                Double LL = sqrt( detPosi[3]*detPosi[3] + detPosi[4]*detPosi[4] + detPosi[5]*detPosi[5] );
                Double PL = pv[0]*detPosi[3]+pv[1]*detPosi[4]+pv[2]*detPosi[5];
                theta = fabs( acos(PL/ll/LL)/M_PI*180.0 ); //degree
                if (theta>90.0) theta=theta-90.0; // incident angle region -90< theta <90
                else theta = 90.0 -theta;
            }

            std::vector<Double>* hw = ec->PutP( ec->PutXKey() );
            std::vector<Double>* yy = ec->PutP( ec->PutYKey() );

#pragma omp parallel for
#if (_OPENMP >= 200805)  // OpenMP 3.0 and later
            for (UInt4 k=0; k<(yy->size()); k++){
#else
            for (Int4 k=0; k<(yy->size()); k++){
#endif
#ifdef MULTH
                ThNum = omp_get_thread_num();
#endif
                Double Ef = Ei - ((hw->at(k))+(hw->at(k+1)))/2.0;
                if (EffiApproxBox==NULL)
                    yy->at(k) = (yy->at(k))/(_MNG->at(ThNum)->GetEfficiency( Ef, theta ));
                else{
                    Double eff=GetEfficiencyApproximateVal( Ef, theta );
                    if (eff>0.0)
                        yy->at(k) = (yy->at(k))/(eff);
                    else
                        yy->at(k) = (yy->at(k))/(_MNG->at(ThNum)->GetEfficiency( Ef, theta ));
                }
            }
        }
    }
}

//////////////////////////////////////////////////////////////////////////
void MlfDetectorEfficiencyCorrection::
ReplaceWithEfficiency( ElementContainerMatrix* _ecm ){
    HeaderBase* hh = _ecm->PutHeaderPointer();
    Double Ei = hh->PutDouble("Ei");
    UInt4 ThNum = 0;

#ifdef MULTH
    omp_set_num_threads( _NumOfMulTh );
#endif
    Int4 ff=0;
    hh->Add("isHistogram", ff );
    for (UInt4 i=0; i<(_ecm->PutSize()); i++){
        HeaderBase* hh_eca = _ecm->PutPointer(i)->PutHeaderPointer();
        hh_eca->Add("isHistogram",ff);
        for (UInt4 j=0; j<(_ecm->PutPointer(i)->PutSize()); j++){
            ElementContainer* ec = _ecm->PutPointer(i)->PutPointer(j);
            HeaderBase* hh_ec = ec->PutHeaderPointer();

            std::vector<Double> pv = hh_ec->PutDoubleVector("PixelPosition");
            Double ll = pv[0]*pv[0] + pv[1]*pv[1] + pv[2]*pv[2];
            Double ll0= pv[0]*pv[0] + pv[2]*pv[2];
            Double theta = acos( ll0/ll )/M_PI*180.0; //degree

            std::vector<Double>* hw = ec->PutP( ec->PutXKey() );
            std::vector<Double>* yy = ec->PutP( ec->PutYKey() );

#pragma omp parallel for
#if (_OPENMP >= 200805)  // OpenMP 3.0 and later
            for (UInt4 k=0; k<(yy->size()); k++){
#else
            for (Int4 k=0; k<(yy->size()); k++){
#endif
#ifdef MULTH
                ThNum = omp_get_thread_num();
#endif
                Double Ef = Ei - ((hw->at(k))+(hw->at(k+1)))/2.0;
                if (EffiApproxBox==NULL)
                    yy->at(k) = (_MNG->at(ThNum)->GetEfficiency( Ef, theta ));
                else
                    yy->at(k) = (GetEfficiencyApproximateVal( Ef, theta ));
            }
        }
    }



}
//////////////////////////////////////////////////////////////////////////
Double MlfDetectorEfficiencyCorrection::
GetEfficiency( double Ef, double theta ){
    if (_MNG==NULL) return 0.0;
    return _MNG->at(0)->GetEfficiency( Ef, theta );
}
const UInt4 MlfDetectorEfficiencyCorrection::_APPROXDATA_HEADER_BUF_SIZE = 64;
//////////////////////////////////////////////////////////////////////////
bool MlfDetectorEfficiencyCorrection::
MakeApproximateData( std::string path, double Ef_min, double Ef_max, UInt4 Ef_num, double th_min, double th_max, UInt4 th_num ){
    if (_MNG==NULL) return false;
    std::string detectorStructureInfo = _MNG->at(0)->PutDetectorStructureInfo();
    if (detectorStructureInfo=="") return false;
    if (Ef_min>=Ef_max){
        std::cout << _MessageTag+"MakeApproximateData : Ef_min>=Ef_max " << std::endl;
        return false;
    }
    if (th_min>=th_max){
        std::cout << _MessageTag+"MakeApproximateData : theta_min>=theta_max " << std::endl;
        return false;
    }
    FILE* file;
    size_t retSize;
    char* tmpBuf = new char[_APPROXDATA_HEADER_BUF_SIZE];

    if ((file=fopen(path.c_str(),"wb"))==NULL){
    }else{
        // _DetectorName
        for (UInt4 i=0; i<_APPROXDATA_HEADER_BUF_SIZE; i++) tmpBuf[i]=0x00;
        if (0>std::snprintf(tmpBuf,sizeof(tmpBuf),"%s\n",_DetectorName.c_str())) {
            std::cout << _MessageTag+"MakeApproximateData : buf size of Detector Name ("+_DetectorName+") is over " << std::endl;
            return false;
        }
        retSize = std::fwrite(tmpBuf, sizeof(char), _APPROXDATA_HEADER_BUF_SIZE, file);
        if (retSize!=_APPROXDATA_HEADER_BUF_SIZE){
            std::cout << _MessageTag+"MakeApproximateData : fails to write  " << std::endl;
            return false;
        }

        // Ef range
        for (UInt4 i=0; i<_APPROXDATA_HEADER_BUF_SIZE; i++) tmpBuf[i]=0x00;
        if (0>std::snprintf(tmpBuf,sizeof(char)*_APPROXDATA_HEADER_BUF_SIZE,"%g,%g,%d\n",Ef_min,Ef_max,Ef_num)) {
            std::cout << _MessageTag+"MakeApproximateData : buf size of Ef range is over " << std::endl;
            return false;
        }
        retSize = std::fwrite(tmpBuf, sizeof(char), _APPROXDATA_HEADER_BUF_SIZE, file);
        if (retSize!=_APPROXDATA_HEADER_BUF_SIZE){
            std::cout << _MessageTag+"MakeApproximateData : fails to write  " << std::endl;
            return false;
        }

        // Theta range
        for (UInt4 i=0; i<_APPROXDATA_HEADER_BUF_SIZE; i++) tmpBuf[i]=0x00;
        if (0>std::snprintf(tmpBuf,sizeof(char)*_APPROXDATA_HEADER_BUF_SIZE,"%g,%g,%d\n",th_min,th_max,th_num)) {
            std::cout << _MessageTag+"MakeApproximateData : buf size of Theta range is over " << std::endl;
            return false;
        }
        retSize = std::fwrite(tmpBuf, sizeof(char), _APPROXDATA_HEADER_BUF_SIZE, file);
        if (retSize!=_APPROXDATA_HEADER_BUF_SIZE){
            std::cout << _MessageTag+"MakeApproximateData : fails to write  " << std::endl;
            return false;
        }

        // DetectorInfo size
        for (UInt4 i=0; i<_APPROXDATA_HEADER_BUF_SIZE; i++) tmpBuf[i]=0x00;
        UInt4 det_info_buf_size = (UInt4)(detectorStructureInfo.size())+10;
        if (0>std::snprintf(tmpBuf,sizeof(char)*_APPROXDATA_HEADER_BUF_SIZE,"%d\n",det_info_buf_size)) {
            std::cout << _MessageTag+"MakeApproximateData : buf size of detectorStructureInfo size is over " << std::endl;
            return false;
        }
        retSize = std::fwrite(tmpBuf, sizeof(char), _APPROXDATA_HEADER_BUF_SIZE, file);
        if (retSize!=_APPROXDATA_HEADER_BUF_SIZE){
            std::cout << _MessageTag+"MakeApproximateData : fails to write  " << std::endl;
            return false;
        }

        // DetectorInfo
        char* tmpDet = new char[ det_info_buf_size ];
        for (UInt4 i=0; i<det_info_buf_size; i++) tmpDet[i]=0x00;
        if (0>std::snprintf(tmpDet,sizeof(char)*det_info_buf_size,"%s\n",detectorStructureInfo.c_str())) {
            std::cout << _MessageTag+"MakeApproximateData : buf size of detectorStructureInfo is over " << std::endl;
            return false;
        }
        retSize = std::fwrite(tmpDet, sizeof(char), det_info_buf_size, file);
        if (retSize!=det_info_buf_size){
            std::cout << _MessageTag+"MakeApproximateData : fails to write  " << std::endl;
            return false;
        }

        delete [] tmpDet;
        delete [] tmpBuf;

        // Detector Efficiency
        // Ef -> Lambda

        double lamb_min = EToLambda(Ef_max);
        double lamb_max = EToLambda(Ef_min);
        double lamb_del = (lamb_max-lamb_min)/(double)Ef_num;
        _num_of_Lambda = Ef_num + 1;
        double th_del = (th_max-th_min)/(double)th_num;
        _num_of_Th = th_num + 1;

        /*
          std::cout << "lamb_min, lamb_max, lamb_del = "<<lamb_min<<","<<lamb_max<<","<<lamb_del<<std::endl;
          std::cout << "_num_of_Lambda="<<_num_of_Lambda<<std::endl;
          std::cout << "th_min, th_max, th_del = "<<th_min<<","<<th_max<<","<<th_del<<std::endl;
          std::cout << "_num_of_Th="<<_num_of_Th<<std::endl;
        */

        double **EffBox;
        EffBox = new double*[_num_of_Lambda];
        for (UInt4 i=0; i<_num_of_Lambda; i++)
            EffBox[i] = new double[_num_of_Th];

        for (UInt4 i=0; i<_num_of_Lambda; i++){
            for (UInt4 j=0; j<_num_of_Th; j++){
                double Ef = LambdaToE( lamb_min+lamb_del*(double)i );
                double theta = th_min+th_del*(double)j;
                EffBox[i][j] = _MNG->at(0)->GetEfficiency( Ef, theta );
            }
        }

        for (UInt4 i=0; i<_num_of_Lambda; i++){
            retSize = std::fwrite(EffBox[i], sizeof(double), _num_of_Th, file);
            if (retSize!=_num_of_Th){
                std::cout << _MessageTag+"MakeApproximateData : fails to write  " << std::endl;
                return false;
            }
        }

        for (UInt4 i=0; i<_num_of_Lambda; i++)
            delete [] EffBox[i];
        delete [] EffBox;
        fclose(file);
    }
    return true;
}
//////////////////////////////////////////////////////////////////////////
bool MlfDetectorEfficiencyCorrection::
LoadApproximateData( std::string path ){
    if (EffiApproxBox!=NULL){
        for (UInt4 i=0; i<_num_of_Lambda; i++)
            delete [] EffiApproxBox[i];
        delete [] EffiApproxBox;
        EffiApproxBox = NULL;
    }

    FILE* file;
    size_t retSize;
    char* tmpBuf = new char[_APPROXDATA_HEADER_BUF_SIZE];

    std::string load_DetectorName="";
    double load_Ef_min = 0.;
    double load_Ef_max = 0.;
    UInt4 load_Ef_num = 0;
    double load_Th_min = 0.;
    double load_Th_max = 0.;
    UInt4 load_Th_num = 0;
    UInt4 load_num_of_DetectorInfo =0;
    std::string load_DetectorInfo = "";
    if ((file=fopen(path.c_str(),"rb"))==NULL){
        std::cout << _MessageTag+"LoadApproximateData : file not found ("+path+")"<<std::endl;
    }else{
    // _DetectorName
        memset(tmpBuf,'\0',_APPROXDATA_HEADER_BUF_SIZE);
        retSize = fread(tmpBuf, sizeof(char), _APPROXDATA_HEADER_BUF_SIZE, file);
        if (retSize != _APPROXDATA_HEADER_BUF_SIZE) {
            std::cout << _MessageTag+"LoadApproximateData : retSize wrong"<<std::endl;
        } else {
            std::string tmp(tmpBuf);
            load_DetectorName = tmp;
        }
        // Ef range
        memset(tmpBuf,'\0',_APPROXDATA_HEADER_BUF_SIZE);
        retSize = fread(tmpBuf, sizeof(char), _APPROXDATA_HEADER_BUF_SIZE, file);
        if (retSize != _APPROXDATA_HEADER_BUF_SIZE) {
        } else {
            std::string tmp(tmpBuf);
            std::vector<std::string> p = _st->SplitString( tmp, "," );
            if (p.size()!=3){
                std::cout << "ERROR : failed to get load_Ef range >> p.size() = "<<p.size()<<std::endl;
                return false;
            }
            load_Ef_min = _st->StringToDouble( p[0] );
            load_Ef_max = _st->StringToDouble( p[1] );
            load_Ef_num = _st->StringToUInt4( p[2] );
        }

        // Th range
        memset(tmpBuf,'\0',_APPROXDATA_HEADER_BUF_SIZE);
        retSize = fread(tmpBuf, sizeof(char), _APPROXDATA_HEADER_BUF_SIZE, file);
        if (retSize != _APPROXDATA_HEADER_BUF_SIZE) {
        } else {
            std::string tmp(tmpBuf);
            std::vector<std::string> p = _st->SplitString( tmp, "," );
            if (p.size()!=3){
                std::cout << "ERROR : failed to get load_Th range >> p.size() = "<<p.size()<<std::endl;
                return false;
            }
            load_Th_min = _st->StringToDouble( p[0] );
            load_Th_max = _st->StringToDouble( p[1] );
            load_Th_num = _st->StringToUInt4( p[2] );
        }

        // DetectorInfo size
        memset(tmpBuf,'\0',_APPROXDATA_HEADER_BUF_SIZE);
        retSize = fread(tmpBuf, sizeof(char), _APPROXDATA_HEADER_BUF_SIZE, file);
        if (retSize != _APPROXDATA_HEADER_BUF_SIZE) {
        } else {
            std::string tmp(tmpBuf);
            load_num_of_DetectorInfo = _st->StringToUInt4( tmp );
        }
        delete [] tmpBuf;

        // DetectorInfo
        if (load_num_of_DetectorInfo!=0){
            char* tmpBufDet = new char[load_num_of_DetectorInfo];
            retSize = fread(tmpBufDet, sizeof(char), load_num_of_DetectorInfo, file);
            if (retSize != load_num_of_DetectorInfo) {
            } else {
                std::string tmp(tmpBufDet);
                load_DetectorInfo = tmp;
            }
            delete [] tmpBufDet;
        }

        // Efficiency Box
        _num_of_Lambda = load_Ef_num + 1;
        _num_of_Th = load_Th_num + 1;
        EffiApproxBox = new double*[_num_of_Lambda];
        for (UInt4 i=0; i<_num_of_Lambda; i++){
            EffiApproxBox[i] = new double[_num_of_Th];
            for (UInt4 j=0; j<_num_of_Th; j++)
                EffiApproxBox[i][j] = -100.0;
        }

        //std::cout << "_num_of_Lambda="<<_num_of_Lambda <<std::endl;
        //std::cout << "_num_of_Th="<<_num_of_Th <<std::endl;
        for (UInt4 i=0; i<_num_of_Lambda; i++){
            retSize = fread(EffiApproxBox[i], sizeof(double), _num_of_Th, file);
            if (retSize != _num_of_Th) {
                std::cout << _MessageTag+"LoadApproximateData : false to read Effi Box"<<std::endl;
            }
        }

        fclose(file);

        _min_Lambda = EToLambda( load_Ef_max );
        Double max_Lambda = EToLambda( load_Ef_min );
        _delta_Lambda = (max_Lambda - _min_Lambda)/(Double)load_Ef_num;
        _min_Th = load_Th_min;
        _delta_Th = (load_Th_max - load_Th_min)/(Double)load_Th_num;
        /*
          std::cout << "_min_Lambda, _max_Lambda, _delta_Lambda = "<<_min_Lambda<<","<< max_Lambda<<","<< _delta_Lambda<<std::endl;
          std::cout << "_min_Th, _max_Th, _delta_Th = "<<_min_Th<<","<< load_Th_max<<","<< _delta_Th<<std::endl;
        */
    }
    return true;
}
//////////////////////////////////////////////////////////////////////////
Double MlfDetectorEfficiencyCorrection::
GetEfficiencyApproximateVal(double Ef, double theta){
    if (EffiApproxBox==NULL){
        std::cout << "GetEfficiencyApproximateVal : EffiApproxBox is empty" << std::endl;
        return 0.0;
    }

    Double lambda = EToLambda( Ef );
    Double posi_lambda = (lambda - _min_Lambda)/_delta_Lambda;
    Double posi_theta  = (theta - _min_Th)/_delta_Th;
    UInt4 ind_lambda = (UInt4)( floor( posi_lambda ) );
    UInt4 ind_theta  = (UInt4)( floor( posi_theta ) );
    Double A = posi_lambda - floor( posi_lambda );
    Double B = posi_theta - floor( posi_theta );

    if ((A<0)||(A>1.0)){
        std::cout << "GetEfficiencyApproximateVal : Out of range on given Ef = " << Ef << std::endl;
        return -1.0;
    }else if ((B<0)||(B>1.0)){
        std::cout << "GetEfficiencyApproximateVal : Out of range on given Theta = " << theta << std::endl;
        return -2.0;
    }

    Double ret = (1.0-A)*(1.0-B)*EffiApproxBox[ind_lambda][ind_theta]
        + (1.0-A)*B*EffiApproxBox[ind_lambda][ind_theta+1]
        + A*(1.0-B)*EffiApproxBox[ind_lambda+1][ind_theta]
        + A*B*EffiApproxBox[ind_lambda+1][ind_theta+1];

    return ret;
}
//////////////////////////////////////////////////////////////////////////
Double MlfDetectorEfficiencyCorrection::
EToLambda( Double ene ){
    return MLF_HBAR*2.*MLF_PI/MLF_Mn*10000. * sqrt( MLF_Mn/2.0*MLF_J2MEV*1.0e12 ) /sqrt(ene);
}
//////////////////////////////////////////////////////////////////////////
Double MlfDetectorEfficiencyCorrection::
LambdaToE( Double lambda ){
    Double k=MLF_HBAR*2.*MLF_PI/MLF_Mn*10000./lambda;
    return k * k * (MLF_Mn/2.0*MLF_J2MEV*1.0e12);
    /*
      cMn = MLF_Mn;
      chver = MLF_HBAR;
      cPlanck = chver*2.*MLF_PI;
      cnvJtoE = MLF_J2MEV;

      cLEtoT = sqrt( cMn/2.0*cnvJtoE )*1000000.;
      cVtoE  = (cMn/2.0)*cnvJtoE*1.0e12;
      cEtoV  = 1.0/sqrt(cVtoE);
      cK2toE = chver*chver/(2.0*cMn)*1.0e20*cnvJtoE;
      cVtoLambda = cPlanck/cMn*10000.; // [meter/micro-sec]/[kg] -> [Ang]

      V = cEToV*sqrt( E )

      Lambda = cVtoLambda/V = cVtoLambda/(cEToV*sqrt( E ))
      = cPlank/cMn*10000. / ( ( 1.0/sqrt(cVtoE) )*sqrt( E ) )
      = cPlank/cMn*10000. * sqrt( cVtoE ) /sqrt(E)
      = cPlank/cMn*10000. * sqrt( cMn/2.0*cnvJtoE*1.0e12 ) /sqrt(E)
      = MLF_HBAR*2.*MLF_PI/MLF_Mn*10000. * sqrt( MLF_Mn/2.0*MLF_J2MEV*1.0e12 ) /sqrt(E)

      sqrt(E) = cVtoLambda/cEToV /Lambda
      = cPlank/cMn*10000. / (1.0/sqrt(cVtoE) ) /Lambda
      = cPlank/cMn*10000. * sqrt(cVtoE) /Lambda

      E = (cPlank/cMn*10000./Lambda)**2 * cVtoE
      =  (cPlank/cMn*10000./Lambda)**2 * (cMn/2.0*cnvJtoE*1.0e12)
      =  (MLF_HBAR*2.*MLF_PI/MLF_Mn*10000./Lambda)**2 * (MLF_Mn/2.0*MLF_JtoMEV*1.0e12)
     */


}
//////////////////////////////////////////////////////////////////////////
std::vector<Double> MlfDetectorEfficiencyCorrection::
PutApproximateDataRange( std::string path ){
    std::vector<Double> ret;
    if (EffiApproxBox==NULL){
        if (path!=""){
            if (LoadApproximateData( path )){
            }else{
                std::cout << "PutApproximateDataRange : given path is invalid. "<< path << std::endl;
                return ret;
            }
        }else{
            std::cout << "PutApproximateDataRange : EffiApproxBox is empty" << std::endl;
            return ret;
        }
    }
    ret.resize(6);
    ret[0] = LambdaToE( _min_Lambda+_delta_Lambda*_num_of_Lambda );
    ret[1] = LambdaToE(_min_Lambda);
    ret[2] = _num_of_Lambda;
    ret[3] = _min_Th;
    ret[4] = _min_Th+_delta_Th*_num_of_Th;
    ret[5] = _num_of_Th;

    return ret;
}
