#include "AdvSolidAngleCorrectionDNA.hh"
// AS 120229 start

//////////////////////////////////////////////////////////
AdvSolidAngleCorrectionDNA::
AdvSolidAngleCorrectionDNA()
{
    Initialize();
}
//////////////////////////////////////////////////////////
AdvSolidAngleCorrectionDNA::
AdvSolidAngleCorrectionDNA(ElementContainerMatrix *ecm)
{
    Initialize();
    SetTarget(ecm);
}

//////////////////////////////////////////////////////////
AdvSolidAngleCorrectionDNA::
~AdvSolidAngleCorrectionDNA()
{
}
//////////////////////////////////////////////////////////
void AdvSolidAngleCorrectionDNA::
Initialize(){
    commentHead = "AdvSolidAngleCorrectionDNA >> ";
    stools = new StringTools();
}
//////////////////////////////////////////////////////////

ElementContainerMatrix AdvSolidAngleCorrectionDNA::
SACorrection(ElementContainerMatrix ecm,bool UseDetectorEfficiency,bool UseSampleAbsoCorr,bool UseCorrEfficiency,std::string sampleType,std::string sampleDataPath,std::string detectorDataPath,char* corrEffDataPath){
  ElementContainerMatrix* ret_ecm;
  SACorrection(ret_ecm, &ecm, UseDetectorEfficiency, UseSampleAbsoCorr, UseCorrEfficiency, sampleType, sampleDataPath, detectorDataPath, corrEffDataPath);
  return *ret_ecm;
}
bool AdvSolidAngleCorrectionDNA::
SACorrection(ElementContainerMatrix* ret_ecm,ElementContainerMatrix* ecm,bool UseDetectorEfficiency,bool UseSampleAbsoCorr,bool UseCorrEfficiency,std::string sampleType,std::string sampleDataPath,std::string detectorDataPath,char* corrEffDataPath){


//////////////////////////////////////////////////
//initialize
//char* corrEffDataPath="/home/dnaadmin/advancesoft/miyasita/data_eff.csv";
    std::ifstream ifs(corrEffDataPath);


    ElementContainerArray eca;
    ElementContainer ec;
    ElementContainer ec0;

    HeaderBase hhm;
    hhm = ecm->PutHeader();
    ret_ecm->InputHeader(hhm);

    UInt4 num_of_psd, num_of_pixel;
    num_of_psd = ecm->PutTableSize();

    AdvDetectorManagerDNA *DeMan = new AdvDetectorManagerDNA(detectorDataPath);
    AdvCorrectionAbsorptionDNA *CoAbs = new AdvCorrectionAbsorptionDNA(sampleDataPath);
    //std::string sampleType="sample";

    //////////////////////////////////////////////////
    // psd loop
    std::cout <<std::endl;
    std::cout << "AdvSolidAngleCorrectionDNA-start"<<std::endl;

    //////////////////////////////////////////////////////////////////////////////////////////////////////////
    std::vector< std::vector <double> > eff_data_list;
    eff_data_list.clear();
    eca = ecm->Put(0);
    num_of_pixel = eca.PutTableSize();

    if(UseCorrEfficiency)
        {
        std::string buf;

        size_t found;

        std::vector< std::vector <double> > word_list;
        word_list.clear();
        while(ifs && getline(ifs, buf))
            {
            size_t count =0;
            UInt4 numm=0;
            std::vector<double> word;
            word.clear();
            while((found = buf.find(" ", count)) != std::string::npos)
                {
                std::string StringBuf = std::string(buf, count, found - count);
                if (StringBuf != "")
                    {
                    double rt;
                    std::stringstream ss;
                    ss << StringBuf;
                    ss >> rt;
                    word.push_back(rt);
                    }
                count = found+1;
                numm = numm+1;
                }
            if(buf.size() != count)
                {
                double rt;
                std::stringstream ss;
                std::string StringBuf = std::string(buf, count, buf.size() - count);
                ss << StringBuf;
                ss >> rt;
                word.push_back(rt);
                }
            word_list.push_back(word);
            }

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

        if (word_list.size()==num_of_psd)
            {
            for(UInt4 i=0;i<word_list.size();i++)
                {
                std::vector<double> eff_data;
                eff_data.clear();
                for(UInt4 j=0;j<num_of_pixel;j++)
                  {
                    if (word_list[i].size()==2)
                        {
                        eff_data.push_back(word_list[i][1]);
                        }
                    else if (word_list[i].size()==num_of_pixel+1)
                        {
                        eff_data.push_back(word_list[i][j+1]);
                        }
                    else
                        {
                        std::cout << "correction efficiency file format is incorrect" << std::endl;
                        std::cout << "please check collumn number(2 or num_of_pixel+1)"<<std::endl;
                        std::cout << "correction efficiency of psd no."<<i<<" is set 1" <<std::endl;
                        eff_data.push_back(1);
                        }
                    }
                eff_data_list.push_back(eff_data);
                }
            }
        else
            {
            std::cout << "correction efficiency file format is incorrect" << std::endl;
            std::cout << "please check line number(224)"<<std::endl;
            std::cout << "correction efficiencies of all psd are set 1" <<std::endl;
            for(UInt4 i=0;i<num_of_psd;i++)
                {
                std::vector<double> eff_data;
                eff_data.clear();
                for(UInt4 j=0;j<num_of_pixel;j++)
                    {
                    eff_data.push_back(1);
                    }
                eff_data_list.push_back(eff_data);
                }
            }
        }//-from L60
    else
        {
        for(UInt4 i=0;i<num_of_psd;i++)
            {
            std::vector<double> eff_data;
            eff_data.clear();
            for(UInt4 j=0;j<num_of_pixel;j++)
                {
                eff_data.push_back(1);
                }
            eff_data_list.push_back(eff_data);
            }
        }

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

    for (UInt4 psd=0;psd<num_of_psd;psd++)
        {
        eca = ecm->Put(psd);

        ElementContainerArray *ECA = new ElementContainerArray(eca.PutHeader() );

        num_of_pixel = eca.PutTableSize();
        ec0 = eca.Put(num_of_pixel-1);

        if (ec0.PutHeaderPointer()->CheckKey("Ef")==0)
            {
            if(psd==0)
                {
                std::cout << "Neutron beam trajectroy has not been calculated yet."<<std::endl;
                UseDetectorEfficiency=false;
                UseSampleAbsoCorr=false;
                }
            }

        if(psd==0)
            {
            if(UseDetectorEfficiency==0)
                {
                std::cout << "UseDetectorEfficiency = False"<<std::endl;
                }
            else
                {
                std::cout << "UseDetectorEfficiency = True"<<std::endl;
                }
            if(UseSampleAbsoCorr==0)
                {
                std::cout << "UseSampleAbsoCorr = False"<<std::endl;
                }
            else
                {
                std::cout << "UseSampleAbsoCorr = True"<<std::endl;
                }
            }
        if(psd%22==0){std::cout << "  "<<psd/22*10<<" %"<<std::endl;}

//////////////////////////////////////////////////////
// pixel loop

        for (UInt4 pixel=0; pixel<num_of_pixel; pixel++)
            {
            std::vector<double> Xin,Yin,Ein,Yout;
            std::vector<double> X0out;
            std::vector<double> RefPos;

            double solidangle,thetaDetectorRad,thetaDetectorDeg,Ef,DetectEff,PolarAngle,AzimAngle;
            double Acc, Ascs, Ascc, Ass;
            Xin.clear();
            Yin.clear();
            Ein.clear();
            std::vector<double> Y_corr;
            std::vector<double> E_corr;

            thetaDetectorRad=0;
            Ef=0;
            PolarAngle=0;
            AzimAngle=0;

            ec = eca.Put(pixel);
            Xin = ec.PutX();
            Yin = ec.PutY();
            Ein = ec.PutE();

            Y_corr.clear();
            E_corr.clear();
            Y_corr.resize(Yin.size());
            E_corr.resize(Yin.size());

            RefPos.clear();

            if (ec.PutHeaderPointer()->CheckKey("Ef")==0)
                {
                solidangle=1;
                }
            else
                {
                solidangle = ec.PutHeaderPointer()->PutDouble("SolidAngle");
                PolarAngle = ec.PutHeaderPointer()->PutDouble("PolarAngle");
                AzimAngle = ec.PutHeaderPointer()->PutDouble("AzimAngle");
                Ef = ec.PutHeaderPointer()->PutDouble("Ef");

                thetaDetectorRad = ec.PutHeaderPointer()->PutDouble("thetaDetector");
                thetaDetectorDeg = thetaDetectorRad/M_PI*180;
                }

            if(UseDetectorEfficiency)
                {
                DetectEff=DeMan->GetEfficiency(Ef,thetaDetectorRad);
                }
            else
                {
                DetectEff=1;
                }

            ElementContainer *ec_corr = new ElementContainer(ec.PutHeader());

            for(UInt4 Y_bin=0; Y_bin<Yin.size(); Y_bin++ )
                {
                if(UseSampleAbsoCorr)
                    {
                    Acc  = CoAbs->GetACC(PolarAngle,AzimAngle,(Xin.at(Y_bin)+Xin.at(Y_bin+1))/2+Ef,Ef);
                    Ascs = CoAbs->GetACSS(PolarAngle,AzimAngle,(Xin.at(Y_bin)+Xin.at(Y_bin+1))/2+Ef,Ef);
                    Ascc = CoAbs->GetACSC(PolarAngle,AzimAngle,(Xin.at(Y_bin)+Xin.at(Y_bin+1))/2+Ef,Ef);
                    Ass  = CoAbs->GetASS(PolarAngle,AzimAngle,(Xin.at(Y_bin)+Xin.at(Y_bin+1))/2+Ef,Ef);
                    }
                else
                    {
                    Acc  = 1;
                    Ascs = 1;
                    Ascc = 1;
                    Ass  = 1;
                    }

                if(sampleType == "sample")
                    {
                    Y_corr.at(Y_bin)=Yin.at(Y_bin)/solidangle/DetectEff*Ascc/Acc/Ascs*eff_data_list[psd][pixel];
                    E_corr.at(Y_bin)=Ein.at(Y_bin)/solidangle/DetectEff*Ascc/Acc/Ascs*eff_data_list[psd][pixel];
                    }
                else if(sampleType == "cell")
                    {
                    Y_corr.at(Y_bin)=Yin.at(Y_bin)/solidangle/DetectEff/Ascs*eff_data_list[psd][pixel];
                    E_corr.at(Y_bin)=Ein.at(Y_bin)/solidangle/DetectEff/Ascs*eff_data_list[psd][pixel];
                    }
                else
                    {
                    Y_corr.at(Y_bin)=Yin.at(Y_bin)/solidangle/DetectEff*eff_data_list[psd][pixel];
                    E_corr.at(Y_bin)=Ein.at(Y_bin)/solidangle/DetectEff*eff_data_list[psd][pixel];
                    }
                }

            ec_corr->Add("HW", Xin);
            ec_corr->Add("Intensity", Y_corr);
            ec_corr->Add("Error", E_corr);
            ec_corr->SetKeys( "HW", "Intensity", "Error" );

            double Total = 0;

            for (UInt4 i=0;i<Y_corr.size();i++)
                {
                Total = Y_corr[i] + Total;
                }

            HeaderBase hh;
            hh = ec_corr->PutHeader();
            hh.Erase("TotalCounts");
            hh.Add("TotalCounts",Total);
            ec_corr->InputHeader(hh);

            ECA->Add( *ec_corr );
            delete ec_corr;
            }
        ret_ecm->Add(*ECA);
        delete ECA;
        }

    delete CoAbs;
    delete DeMan;

    std::cout << "AdvSolidAngleCorrectionDNA-end"<<std::endl;
    return true;

    }// ILCorrection end

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



