#include <cmath>
#include <fstream>
#include <cstdlib>
#include <cstdio>

#include "Header.hh"

//#include "AdvPhysicalParameterDNA.hh"
#include "UtsusemiUnitConverter.hh"
#include "UtsusemiHeader.hh"
#include "AdvCorrectionAbsorptionDNA.hh"



AdvCorrectionAbsorptionDNA :: AdvCorrectionAbsorptionDNA(void){
  if (!(isReady())) {
    UtsusemiError("AdvCorrectionAbsorptionDNA >> Error Initializing (Maybe not found atomic data file).");
    return;
  }
  // read sample data

  //std::string filepath = getenv("HOME");
  filepath = UtsusemiEnvGetUserDir();
  std::string filename = "test_sample_data.dat";
  //filepath += "/ana/setup/";
  filepath += "/ana/DNA/setup/";
  filepath += filename;

  //filename="/home/dnaadmin/00Install/work.DNA/correction/test_sample_data.dat";
  std::cout << "database_filepath = " <<filepath <<std::endl;

  wallInfo.initialize();
  sampleInfo.initialize();

  SetInfoData(filepath, &wallInfo, &sampleInfo);
  // in the case of solid, not gas
  // "wall" means outer cylinder and "sample" means inner cylinder
  sampleInfo.totalDensity=sampleInfo.weightPerVolume*MLF_KG2G/sampleInfo.effectiveAtomicWeight*MLF_NA;
  wallInfo.totalDensity=wallInfo.weightPerVolume*MLF_KG2G/wallInfo.effectiveAtomicWeight*MLF_NA;

  std::cout << "wall" <<std::endl;
  std::cout << wallInfo.form << std::endl;
  std::cout << wallInfo.rl << std::endl;
  std::cout << wallInfo.rs << std::endl;
  std::cout << wallInfo.height << std::endl;


  std::cout << "body" <<std::endl;
  std::cout << sampleInfo.form << std::endl;
  std::cout << sampleInfo.rl << std::endl;
  std::cout << sampleInfo.rs << std::endl;
  std::cout << sampleInfo.height << std::endl;

  // Gauss-Legender parameter
  m=2;
  m_2=1;//20150123++
  xk.clear();
  Hk.clear();
  xk.push_back(-0.5773502692);
  xk.push_back(0.5773502692);
  Hk.push_back(1.0);
  Hk.push_back(1.0);


  // integral threshold for determination of convergence
  threZero=1.e-08;
  epsilon=threZero;
  epsilonRatio=1.0e-4;


  // maximum number of cylinder
  maxCylinderNum=3;

}

AdvCorrectionAbsorptionDNA :: AdvCorrectionAbsorptionDNA(std::string filepath){
  if (!(isReady())) {
    UtsusemiError("AdvCorrectionAbsorptionDNA >> Error Initializing (Maybe not found atomic data file).");
    return;
  }
  wallInfo.initialize();
  sampleInfo.initialize();
  std::cout << "database_filepath = " <<filepath <<std::endl;
  SetInfoData(filepath, &wallInfo, &sampleInfo);
  // in the case of solid, not gas
  // "wall" means outer cylinder and "sample" means inner cylinder
  sampleInfo.totalDensity=sampleInfo.weightPerVolume*MLF_KG2G/sampleInfo.effectiveAtomicWeight*MLF_NA;
  wallInfo.totalDensity=wallInfo.weightPerVolume*MLF_KG2G/wallInfo.effectiveAtomicWeight*MLF_NA;

  // Gauss-Legender parameter
  m=2;
  m_2=1;//20150123++
  xk.clear();
  Hk.clear();
  xk.push_back(-0.5773502692);
  xk.push_back(0.5773502692);
  Hk.push_back(1.0);
  Hk.push_back(1.0);

  // integral threshold for determination of convergence
  threZero=1.e-08;
  epsilon=threZero;
  epsilonRatio=1.0e-4;


  // maximum number of cylinder
  maxCylinderNum=3;

}

/////////////////////////////////////////////////////////////////////////////////////////////
// [20140410 AS start]
AdvCorrectionAbsorptionDNA :: AdvCorrectionAbsorptionDNA(std::string filepath,std::string datafilepath){

  wallInfo.initialize();
  sampleInfo.initialize();
  std::cout << "database_filepath = " <<filepath <<std::endl;
  SetAtomicDataFile(datafilepath);
  SetInfoData(filepath, &wallInfo, &sampleInfo);
  // in the case of solid, not gas
  // "wall" means outer cylinder and "sample" means inner cylinder
  sampleInfo.totalDensity=sampleInfo.weightPerVolume*MLF_KG2G/sampleInfo.effectiveAtomicWeight*MLF_NA;
  wallInfo.totalDensity=wallInfo.weightPerVolume*MLF_KG2G/wallInfo.effectiveAtomicWeight*MLF_NA;

  // Gauss-Legender parameter
  m=2;
  m_2=1;//20150123++
  xk.clear();
  Hk.clear();
  xk.push_back(-0.5773502692);
  xk.push_back(0.5773502692);
  Hk.push_back(1.0);
  Hk.push_back(1.0);

  // integral threshold for determination of convergence
  threZero=1.e-08;
  epsilon=threZero;
  epsilonRatio=1.0e-4;


  // maximum number of cylinder
  maxCylinderNum=3;

}
// [20140410 AS end]
/////////////////////////////////////////////////////////////////////////////////////////////
AdvCorrectionAbsorptionDNA :: ~AdvCorrectionAbsorptionDNA(void){
}

//void AdvCorrectionAbsorptionDNA :: SetIntegThresholdValue(Double a){
//  epsilon=a;
//}



/////////////////////////////////////////////////////////////////////////////////////////////
// [20140414 AS start]
Double AdvCorrectionAbsorptionDNA:: GetQVal(Double Ei, Double Ef, Double theta)
  {
  Double MASS_NEUTRON = 1.67492e-27;
  Double HBAR         = 1.05457e-34;
  Double m2A          = 1e10;
  Double J2meV        = 6.24151e21;
  Double fact=2*MASS_NEUTRON/(HBAR*HBAR*m2A*m2A*J2meV);
  return sqrt(fact*(Ef+Ei-2*sqrt(Ef*Ei*cos(theta))));
  }
// [20140414 AS end]
/////////////////////////////////////////////////////////////////////////////////////////////
Double AdvCorrectionAbsorptionDNA :: GetS1(Double rl, Double rs, Double height){
  // calculate flight length of neutron before scatteing in the cyliner, longer radius is rl and smaller radius is rs.
  // coodinate is in the manner of NeXus

  if(rl <= rs) return 0.0;

  Double s1;
  //Double x=scaPos.x;     // 20150123 --

  //if(x<0.0) x*=-1.0;

  Double x=fabs(scaPos.x); // 20150123 ++

  if(scaPos.x*scaPos.x+scaPos.z*scaPos.z > rl*rl ) {
    // in the case where scattering point is outsice of cylinder
    if (scaPos.z < 0.0 || x > rl) {
      // in the case where neutron does not pass the cylinder before scattering
      s1 = 0.0;
    }
    else {
      // in the case where neutron pass the cylinder before scattering
      s1 = 2.0*sqrt(rl*rl-scaPos.x*scaPos.x);
    }
  }else if( scaPos.x*scaPos.x+scaPos.z*scaPos.z < rs*rs ) {
      // in the case where scattering point is inside of cylinder
      s1 =sqrt(rl*rl-scaPos.x*scaPos.x)+scaPos.z;
      s1-=GetS1(rs, 0.0, height);
      //std::printf("case s1type1 :: s1=%f\n", s1);
  }else if (scaPos.z < 0.0 || x > rs) {
    // in the case where scattering point is with in the cyliner
    //  neutron does not pass the inner space of cylinder before scattering
    if(rl>scaPos.z){
      s1 = sqrt(rl*rl-scaPos.x*scaPos.x)+scaPos.z;
      //std::printf("case s1type2 :: s1=%f\n", s1);
    }
    else{
    // need ?
      //std::printf("case s1type3 :: s1=%f\n", s1);
      s1 = sqrt(rl*rl-scaPos.x*scaPos.x)+rl;
    }
  }
  else {
    // in the case where scattering point is with in the cyliner
    //  neutron passes the inner space of cylinder before scattering

      //std::printf("case s1type4 :: s1=%f\n", s1);

    //Double s1tmp1=sqrt((rl*rl-scaPos.x*scaPos.x))-sqrt((rs*rs-scaPos.x*scaPos.x)); //20150123 --
    //Double s1tmp2=s1tmp1 -(sqrt(rl*rl-scaPos.x*scaPos.x)-scaPos.z);
    //s1=s1tmp1+s1tmp2;

    s1 = sqrt(rl*rl-scaPos.x*scaPos.x) - 2*sqrt(rs*rs-scaPos.x*scaPos.x) + scaPos.z; //20150123 ++

  }
  return s1;
}

Double AdvCorrectionAbsorptionDNA :: GetS2(Double rl, Double rs, Double height){
  // calculate the length of flight of newtron in the cylinder after scattering

  if(rl==0.0) { //20150123 ++
    return 0.0;
  }

  Double s2;
  Double a, b, c, t, t1, t2, tTmp;
  //Double sinTheta, cosTheta, sinPhi, cosPhi;// 20150123 --
  //sinTheta=sin(theta); // 20150123 --
  //cosTheta=cos(theta); // 20150123 --
  //sinPhi=sin(phi);     // 20150123 --
  //cosPhi=cos(phi);     // 20150123 --
  a=sinTheta*sinTheta*cosPhi*cosPhi+cosTheta*cosTheta;
  b=scaPos.x*sinTheta*cosPhi+scaPos.z*cosTheta;
  c=scaPos.x*scaPos.x+scaPos.z*scaPos.z-rs*rs;

  s2=0.0;
  //if(rl==0.0) {//20150123 --
  //  return s2;
  // }

  if( scaPos.x*scaPos.x+scaPos.z*scaPos.z <= rs*rs) {
    // in the case where scattering point is incide of cylinder

    // neutron trajectory of flight is given by (rs)+t(kout),
    // where rs is scattering point and (kout) is wave std::vector of neutron after scattering.
    // crossing point of radius rs is given by (rs)+t1(kout) and that of raidus rl is
    // given by (rs)+t2(kout),
    // t1 and t2 is given as follows, and should be large than zero.

    //std::printf("case 1\n");

    t1=(-b+sqrt(b*b-a*c))/a;
    c=scaPos.x*scaPos.x+scaPos.z*scaPos.z-rl*rl;

    t2=(-b+sqrt(b*b-a*c))/a;
    //s2=sqrt( ((t2-t1)*sinTheta*cosPhi)*((t2-t1)*sinTheta*cosPhi)
    //        +((t2-t1)*sinTheta*sinPhi)*((t2-t1)*sinTheta*sinPhi)
    //        +((t2-t1)*cosTheta)*((t2-t1)*cosTheta));                 // 20150123 --

    s2=fabs(t2-t1);                                                    // 20150123 ++
    //std::printf(" case 1 ;; rl=%f, rs=%f, s2=%f, x=%f, z=%f, t2=%f\n", rl, rs, s2, scaPos.x, scaPos.z, t2);

  } else {
    // in the case where scattering point is not incide of cylinder

    //std::printf("case 2\n");

    Double d;
    d=b*b-a*c;
    Double s2tmp1=0.0;
    Double s2tmp2=0.0;

    if(d > 0.0) { // neutron after scatteing passes both the surface of inner circle with rs and outer circle with rl.
      // crossing points of radius rs are given by (rs)+t1(kout) and (rs)+t2(kout),
      // t1 and t2 is given as follows, and should be large than zero.

      //Double t1, t2;                     // 20150126 --
      //t1=(-b-sqrt(b*b-a*c))/a;
      //t2=(-b+sqrt(b*b-a*c))/a;

      Double t1, t2, tTmp;                 // 20150126 ++

      tTmp=sqrt(b*b-a*c);
      t1=(-b-tTmp)/a;
      t2=(-b+tTmp)/a;

      Double posY1, posY2;
      if(t1>0.0) {
        // in the case where croosing point is given by (rs)+t1(kout)
        //s2tmp1=sqrt( (t1*sinTheta*cosPhi*t1*sinTheta*cosPhi)
        //       +(t1*sinTheta*sinPhi*t1*sinTheta*sinPhi)
        //       +(t1*cosTheta*t1*cosTheta)); // 20150123 --
        s2tmp1 = t1;                          // 20150123 ++
        // check for y region
        posY1=scaPos.y;
        posY2=t1*sinTheta*sinPhi+scaPos.y;
        if(posY1>height/2 || posY1<-height/2){
          // in the case where the scattering point is outside of cylinder
          s2=0.0;
          return s2;
        }
        if(posY2>height/2 || posY2<-height/2){
          // in the case where the obtained crossing point is outside of cylinder
          if(posY2>0.0){
            s2=s2tmp1*((height/2-posY1)/(posY2-posY1));
          }
          else {
            s2=s2tmp1*((posY1+height/2)/(posY1-posY2));
          }
          return s2;
        }
      }
      if(t2>0.0) {
        // in the case where croosing point is given by (rs)+t2(kout)

        // Hereafter, crossing points of radius rs are given by (rs)+t(kout),
        // and crossing points of radius rl are given by (rs)+t1(kout),
        // t1 is given as follows, and should be large than zero.

        t=t2;
        c=scaPos.x*scaPos.x+scaPos.z*scaPos.z-rl*rl;

        //t1=(-b+sqrt(b*b-a*c))/a; // 20150126 --
        //t2=(-b-sqrt(b*b-a*c))/a;

        tTmp=sqrt(b*b-a*c);        // 20150126 ++
        t1=(-b+tTmp)/a;
        t2=(-b-tTmp)/a;

        if(t1<t2) t1=t2;
        //s2tmp2=sqrt( ((t1-t)*sinTheta*cosPhi*(t1-t)*sinTheta*cosPhi)
        //      +((t1-t)*sinTheta*sinPhi*(t1-t)*sinTheta*sinPhi)
        //      +((t1-t)*cosTheta*(t1-t)*cosTheta)); // 20151023 --

        s2tmp2 = fabs(t1-t);                         // 20151023 ++

        posY1=t*sinTheta*sinPhi+scaPos.y;
        posY2=t1*sinTheta*sinPhi+scaPos.y;

        if(posY1>height/2 || posY1<-height/2){
          // in the case where the crrosing point of radius rs is outside of cylinder
          s2=s2tmp1;
          return s2;
        }
        if(posY2>height/2 || posY2<-height/2){
          // in the case where the crossing point of radius rl is outside of cylinder
          if(posY2>0.0){
            s2=s2tmp1+s2tmp2*((height/2-posY1)/(posY2-posY1));
          }
          else {
            s2=s2tmp1+s2tmp2*((posY1+height/2)/(posY1-posY2));
          }
          return s2;
        }
        else {
          // in the case where the crossing points of radius rl and radius rs are in the cylinder
          s2=s2tmp1+s2tmp2;
          return s2;
        }
      }
    }
    else { // neutron after scatteing does not pass the surface of inner circle with rs.
      c=scaPos.x*scaPos.x+scaPos.z*scaPos.z-rl*rl;
      d=b*b-a*c;
      if(d<0.0) {
        // neutron after scatteing does not pass the surface of outer circle with rl.
        s2=0.0;
        return s2;
      }

      if(c<0.0){
        // in the case where the scattering point is within the cylinder
        // the crossing point of raius rl is given by (rs)+t(kout),
        // where t is given as follows.

        t=(-b+sqrt(b*b-a*c))/a;
        //s2=sqrt( (t*sinTheta*cosPhi)*(t*sinTheta*cosPhi)
        //        +(t*sinTheta*sinPhi)*(t*sinTheta*sinPhi)
        //       +(t*cosTheta)*(t*cosTheta) ); // 20150123 --

        s2=fabs(t);                            // 20150123 ++

        Double posY1, posY2;
        posY1=scaPos.y;
        posY2=t*sinTheta*sinPhi+scaPos.y;
        if(posY1>height/2 || posY1<-height/2){
          // in the case where the scattering point is outside of cylinder
          s2=0.0;
          return s2;
        }
        if(posY2>height/2 || posY2<-height/2){
          // in the case where the obtained crossing point of radius rl is outside of cylinder
          if(posY2>0.0){
            s2*=((height/2-posY1)/(posY2-posY1));
          }
          else {
            s2*=((posY1+height/2)/(posY1-posY2));
          }
          return s2;
        }
      } else {
        // in the case where the scattering point is outside of the cylinder
        // the crossing point of raius rl is given by (rs)+t1(kout) and (rs)+t2(kout),
        // where t1 and t2 should be large than zero, and are given as follows.
        s2=0.0;

        //t1=(-b-sqrt(b*b-a*c))/a;  // 20150126 --
        //t2=(-b+sqrt(b*b-a*c))/a;

        tTmp=sqrt(b*b-a*c);         // 20150126 ++
        t1=(-b-tTmp)/a;
        t2=(-b+tTmp)/a;

        if(t1>0.0 || t2>0.0){
          // in the case neutron pass into the cylinder
          t=t2-t1;
          //s2=sqrt( (t*sinTheta*cosPhi)*(t*sinTheta*cosPhi)
          //      +(t*sinTheta*sinPhi)*(t*sinTheta*sinPhi)
          //      +(t*cosTheta)*(t*cosTheta) ); // 20150123 --

          s2=fabs(t);                           // 20150123 ++
          Double posY1, posY2;
          posY1=t1*sinTheta*sinPhi+scaPos.y;
          posY2=t2*sinTheta*sinPhi+scaPos.y;
          if(posY1>height/2 || posY1<-height/2){
          // in the case where the obtained crossing point of radius rl for t1 outside of cylinder
            s2=0.0;
            return s2;
          }
          if(posY2>height/2 || posY2<-height/2){
          // in the case where the obtained crossing point of radius rl for t2 outside of cylinder
            if(posY2>0.0){
              s2*=((height/2-posY1)/(posY2-posY1));
            }
            else {
              s2*=((posY1+height/2)/(posY1-posY2));
            }
            return s2;
          }

        }
        else if(t1*t2<0.0){
          std::printf("something wrong\n");
          exit(1);
        }
      }
    }
  }
  return s2;
}

Double AdvCorrectionAbsorptionDNA :: ReturnIntegFunctionValueA_C_C(){
  Double s1c1=GetS1(wallInfo.rl,   sampleInfo.rl, wallInfo.height);
  Double s1c2=GetS1(sampleInfo.rs, wallInfo.rs,   wallInfo.height);
  Double s2c1=GetS2(wallInfo.rl,   sampleInfo.rl, wallInfo.height);
  Double s2c2=GetS2(sampleInfo.rs, wallInfo.rs,   wallInfo.height);
  Double s1c=s1c1+s1c2;
  Double s2c=s2c1+s2c2;

  Double f;
  //f=exp(-sigmaCEi*wallInfo.totalDensity*s1c)*exp(-sigmaCEo*wallInfo.totalDensity*s2c); //20150123 --
  f=exp((-sigmaCEi*s1c - sigmaCEo*s2c)*wallInfo.totalDensity);                           //20150123 ++
  return f;
}

Double AdvCorrectionAbsorptionDNA :: ReturnIntegFunctionValueA_CS_C(){
  Double s1c1=GetS1(wallInfo.rl,   sampleInfo.rl, wallInfo.height);
  Double s1c2=GetS1(sampleInfo.rs, wallInfo.rs,   wallInfo.height);
  Double s2c1=GetS2(wallInfo.rl,   sampleInfo.rl, wallInfo.height);
  Double s2c2=GetS2(sampleInfo.rs, wallInfo.rs,   wallInfo.height);
  Double s1s =GetS1(sampleInfo.rl, sampleInfo.rs, sampleInfo.height);
  Double s2s =GetS2(sampleInfo.rl, sampleInfo.rs, sampleInfo.height);
  Double s1c=s1c1+s1c2;
  Double s2c=s2c1+s2c2;

  Double f;
  //f=exp(-sigmaCEi*wallInfo.totalDensity*s1c)*exp(-sigmaSEi*sampleInfo.totalDensity*s1s)
  //  *exp(-sigmaCEo*wallInfo.totalDensity*s2c)*exp(-sigmaSEo*sampleInfo.totalDensity*s2s); //20150123 --
  f=exp(  (-sigmaCEi*s1c -sigmaCEo*s2c) *wallInfo.totalDensity
         +(-sigmaSEi*s1s- sigmaSEo*s2s) *sampleInfo.totalDensity);                          //20150123 ++

  return f;
}

Double AdvCorrectionAbsorptionDNA :: ReturnIntegFunctionValueA_CS_S(){
  Double s1c1=GetS1(wallInfo.rl,   sampleInfo.rl, wallInfo.height);
  Double s1c2=GetS1(sampleInfo.rs, wallInfo.rs,   wallInfo.height);
  Double s2c1=GetS2(wallInfo.rl,   sampleInfo.rl, wallInfo.height);
  Double s2c2=GetS2(sampleInfo.rs, wallInfo.rs,   wallInfo.height);
  Double s1s =GetS1(sampleInfo.rl, sampleInfo.rs, sampleInfo.height);
  Double s2s =GetS2(sampleInfo.rl, sampleInfo.rs, sampleInfo.height);
  Double s1c=s1c1+s1c2;
  Double s2c=s2c1+s2c2;

  Double f;
  //f=exp(-sigmaCEi*wallInfo.totalDensity*s1c)*exp(-sigmaSEi*sampleInfo.totalDensity*s1s)
  //  *exp(-sigmaCEo*wallInfo.totalDensity*s2c)*exp(-sigmaSEo*sampleInfo.totalDensity*s2s); //20150123 --
  f=exp( (-sigmaCEi*s1c -sigmaCEo*s2c) *wallInfo.totalDensity
         +(-sigmaSEi*s1s- sigmaSEo*s2s) *sampleInfo.totalDensity);                          //20150123 ++

  return f;
}

Double AdvCorrectionAbsorptionDNA :: ReturnIntegFunctionValueA_S_S(){
  Double s1s=GetS1(sampleInfo.rl, sampleInfo.rs, sampleInfo.height);
  Double s2s=GetS2(sampleInfo.rl, sampleInfo.rs, sampleInfo.height);
  Double f;
  //f=exp(-sigmaSEi*sampleInfo.totalDensity*s1s)*exp(-sigmaSEo*sampleInfo.totalDensity*s2s); //20150123 --
  f=exp((-sigmaSEi*s1s-sigmaSEo*s2s)*sampleInfo.totalDensity);                               //20150123 ++
  return f;
}


Double AdvCorrectionAbsorptionDNA :: GetACC(Double inputTheta, Double inputPhi, Double inputIncE, Double inputOutE){
  incEnergy=inputIncE*MLF_MEV2J;
  outEnergy=inputOutE*MLF_MEV2J;
  theta=inputTheta*MLF_DEGREE2RADIAN;
  phi=inputPhi*MLF_DEGREE2RADIAN;

  sinTheta=sin(theta); // 20150123 ++
  cosTheta=cos(theta); // 20150123 ++
  sinPhi=sin(phi);     // 20150123 ++
  cosPhi=cos(phi);     // 20150123 ++

  volume=0.0;

  Double qval=GetQVal(inputIncE, inputOutE, theta); // [AS 20140415]
  SetQForSigmaCoefficient(qval);                    // [AS 20140415]

  Double value=GetA_C_C1()+GetA_C_C2();
  return value/volume;
}

Double AdvCorrectionAbsorptionDNA :: GetACSS(Double inputTheta, Double inputPhi, Double inputIncE, Double inputOutE){
  incEnergy=inputIncE*MLF_MEV2J;
  outEnergy=inputOutE*MLF_MEV2J;
  theta=inputTheta*MLF_DEGREE2RADIAN;
  phi=inputPhi*MLF_DEGREE2RADIAN;

  sinTheta=sin(theta); // 20150123 ++
  cosTheta=cos(theta); // 20150123 ++
  sinPhi=sin(phi);     // 20150123 ++
  cosPhi=cos(phi);     // 20150123 ++

  volume=0.0;

  Double qval=GetQVal(inputIncE, inputOutE, theta); // [AS 20140415]
  SetQForSigmaCoefficient(qval);                    // [AS 20140415]

  Double value=GetA_CS_S();
  return value/volume;
}

Double AdvCorrectionAbsorptionDNA :: GetACSC(Double inputTheta, Double inputPhi, Double inputIncE, Double inputOutE){
  incEnergy=inputIncE*MLF_MEV2J;
  outEnergy=inputOutE*MLF_MEV2J;
  theta=inputTheta*MLF_DEGREE2RADIAN;
  phi=inputPhi*MLF_DEGREE2RADIAN;

  sinTheta=sin(theta); // 20150123 ++
  cosTheta=cos(theta); // 20150123 ++
  sinPhi=sin(phi);     // 20150123 ++
  cosPhi=cos(phi);     // 20150123 ++

  volume=0.0;

  Double qval=GetQVal(inputIncE, inputOutE, theta); // [AS 20140415]
  SetQForSigmaCoefficient(qval);                    // [AS 20140415]

  Double value=GetA_CS_C1()+GetA_CS_C2();
  return value/volume;
}

Double AdvCorrectionAbsorptionDNA :: GetASS(Double inputTheta, Double inputPhi, Double inputIncE, Double inputOutE){
  incEnergy=inputIncE*MLF_MEV2J;
  outEnergy=inputOutE*MLF_MEV2J;
  theta=inputTheta*MLF_DEGREE2RADIAN;
  phi=inputPhi*MLF_DEGREE2RADIAN;

  sinTheta=sin(theta); // 20150123 ++
  cosTheta=cos(theta); // 20150123 ++
  sinPhi=sin(phi);     // 20150123 ++
  cosPhi=cos(phi);     // 20150123 ++

  volume=0.0;

  Double qval=GetQVal(inputIncE, inputOutE, theta); // [AS 20140415]
  SetQForSigmaCoefficient(qval);                    // [AS 20140415]

  Double value=GetA_S_S();
  return value/volume;
}


Double AdvCorrectionAbsorptionDNA :: GetA_C_C1(){
  species=0;
  return GetAMain();
}

Double AdvCorrectionAbsorptionDNA :: GetA_CS_C1(){
  species=1;
  return GetAMain();
}

Double AdvCorrectionAbsorptionDNA :: GetA_CS_S(){
  species=2;
  return GetAMain();
}

Double AdvCorrectionAbsorptionDNA :: GetA_C_C2(){
  species=3;
  return GetAMain();
}

Double AdvCorrectionAbsorptionDNA :: GetA_CS_C2(){
  species=4;
  return GetAMain();
}

Double AdvCorrectionAbsorptionDNA :: GetA_S_S(){
  species=5;
  return GetAMain();
}


Double AdvCorrectionAbsorptionDNA :: GetAMain(){
  sigmaSEi=ReturnSigmaFromVelocityRule(&sampleInfo, incEnergy, 't');
  sigmaSEo=ReturnSigmaFromVelocityRule(&sampleInfo, outEnergy, 't');
  sigmaCEi=ReturnSigmaFromVelocityRule(&wallInfo, incEnergy, 't');
  sigmaCEo=ReturnSigmaFromVelocityRule(&wallInfo, outEnergy, 't');

  Double integral=CalcInteg();
  return integral;
}

Double AdvCorrectionAbsorptionDNA :: CalcInteg(){
  // calc 3D integral by use of cylindrical coordinate, Int(dz)Int(dr)Int(dtheta)
  // max iteration for devision of integrated region for Int(dz)
  UInt4 max=10;
  UInt4 nDiv;
  Double dx;
  Double z=sampleInfo.height;
  Double x1=-sampleInfo.height/2;
  Double xi;
  Double x[m],y[m_2], f[m];

  Double s1, s;
  s1=s=0.0;
  Double diff;
  nDiv=1;

  //clock_t start, end;
  //start=clock();
/* //20140126 --
  for (UInt4 i=0; i<max; i++) {
    nDiv*=2;
    dx=z/nDiv;
    for (UInt4 j=0; j<m_2; j++) {
      y[j]=0.0;
    }
    for (UInt4 j=0; j<nDiv; j++){
      xi=x1+((j+1)-0.5)*dx;
      for (UInt4 k=0; k<m; k++) {
        x[k]=xi+xk[k]*dx/2;
      }
      for (UInt4 k=0; k<m; k++) {
        f[k]=IntegRTheta(x[k]);
        // f[k]=1.0;
      }
      for (UInt4 k=0; k<m_2; k++) {
        y[k]+=f[k]+f[m-k-1];
      }
    }
    for (UInt4 j=0; j<m_2; j++) {
      y[j]*=Hk[j];
    }
    Double sum=0.0;
    for (UInt4 j=0; j<m_2; j++) {
      sum+=y[j];
    }
    s=0.5*dx*sum;
    diff=s-s1;
    if (diff<0.0) {
      diff=-diff;
    }
//    std::printf("main :: %d s=%e, diff=%e, diff_ratio=%f\n", i, s, diff, diff/s); fflush(stdout);
    if (i>0) {
      if (diff < epsilon ){
        break;
      }
      if (s>threZero && diff/s<epsilonRatio){
        break;
      }
    }
    s1=s;
  }
*/
  UInt4 i,j,k; //20140126 ++ start
  for (i=0; i<max; i++) {
    nDiv*=2;
    dx=z/nDiv;
    //---------------------
    std::fill_n(y,m_2,0.0);
    //---------------------
    for (j=0; j<nDiv; j++){

      xi=x1+((j+1)-0.5)*dx;
      for (k=0; k<m; k++) {
        x[k]=xi+xk[k]*dx*0.5;
      }
      for (k=0; k<m; k++) {
        f[k]=IntegRTheta(x[k]);
      }
      for (k=0; k<m_2; k++) {
        y[k]+=f[k]+f[m-k-1];
      }
    }
    //---------------------
    for (j=0; j<m_2; j++) {
      y[j]*=Hk[j];
    }
    //---------------------
    Double sum = std::accumulate(y,y+m_2,0.0);
    //---------------------
    s=0.5*dx*sum;

    //diff=s-s1;     // 20140126 --
    //if (diff<0.0) {
    //  diff=-diff;
    //}
    diff=fabs(s-s1); // 20140126 ++

//    std::printf("main :: %d s=%e, diff=%e, diff_ratio=%f\n", i, s, diff, diff/s); fflush(stdout);
    if (i>0) {
      if (diff < epsilon ){
        break;
      }
      if (s>threZero && diff/s<epsilonRatio){
        break;
      }
    }
    s1=s;
  } //20140126 ++ end

  switch (species) {
    case 0:
      radiusSmall=sampleInfo.rl;
      radiusLarge=wallInfo.rl;
      if(radiusSmall<radiusLarge){
        volume+=(radiusLarge*radiusLarge-radiusSmall*radiusSmall)*PI*wallInfo.height;
      }
      break;
    case 1:
      radiusSmall=sampleInfo.rl;
      radiusLarge=wallInfo.rl;
      if(radiusSmall<radiusLarge){
        volume+=(radiusLarge*radiusLarge-radiusSmall*radiusSmall)*PI*wallInfo.height;
      }
      break;
    case 2:
      radiusSmall=sampleInfo.rs;
      radiusLarge=sampleInfo.rl;
      if(radiusSmall<radiusLarge){
        volume+=(radiusLarge*radiusLarge-radiusSmall*radiusSmall)*PI*wallInfo.height;
      }
      break;
    case 3:
      radiusSmall=wallInfo.rs;
      radiusLarge=sampleInfo.rs;
      if(radiusSmall<radiusLarge){
        volume+=(radiusLarge*radiusLarge-radiusSmall*radiusSmall)*PI*wallInfo.height;
      }
      break;
    case 4:
      radiusSmall=wallInfo.rs;
      radiusLarge=sampleInfo.rs;
      if(radiusSmall<radiusLarge){
        volume+=(radiusLarge*radiusLarge-radiusSmall*radiusSmall)*PI*wallInfo.height;
      }
      break;
    case 5:
      radiusSmall=sampleInfo.rs;
      radiusLarge=sampleInfo.rl;
      if(radiusSmall<radiusLarge){
        volume+=(radiusLarge*radiusLarge-radiusSmall*radiusSmall)*PI*sampleInfo.height;
      }
      break;
    default:
      std::printf("species num is wrong\n");
      exit(1);
      break;
  }
  //end=clock();
  //std::printf("%e second need for %d steps\n", (double) (end-start)/CLOCKS_PER_SEC, m*nDiv);
  return s;
}

Double AdvCorrectionAbsorptionDNA :: IntegRTheta(Double z){
  // calc 2D integral by use of cylindrical coordinate, Int(dr)Int(dtheta)
  // max iteration for devision of integrated region for Int(dr)
  UInt4 max=10;
  UInt4 nDiv;
  Double dx;
  Double x1;
  Double xi;
  UInt4 cylinderNum;
  Double x[m],y[m_2], f[m];
  Double s1, s, stotal;
  s1=s=stotal=0.0;
  Double diff;

  for(cylinderNum=0; cylinderNum<maxCylinderNum; cylinderNum++){
    if(species==0 && cylinderNum!=0) continue; //A_C_C1
    if(species==1 && cylinderNum!=0) continue; //A_CS_C1
    if(species==2 && cylinderNum!=1) continue; //A_CS_S
    if(species==3 && cylinderNum!=2) continue; //A_C_C2
    if(species==4 && cylinderNum!=2) continue; //A_CS_C2
    if(species==5 && cylinderNum!=1) continue; //A_S_S

    switch (cylinderNum) {
      case 0:
        radiusSmall=sampleInfo.rl;
        radiusLarge=wallInfo.rl;
        break;
      case 1:
        radiusSmall=sampleInfo.rs;
        radiusLarge=sampleInfo.rl;
        break;
      case 2:
        radiusSmall=wallInfo.rs;
        radiusLarge=sampleInfo.rs;
        break;
      default:
        std::printf("cyliner num is wrong\n");
        exit(1);
        break;
    }
    if(radiusSmall>=radiusLarge){
      continue;
    }
    x1=radiusSmall;
    nDiv=1;
/* //20140126 --
    for (UInt4 i=0; i<max; i++) {
      nDiv*=2;
      dx=(radiusLarge-radiusSmall)/nDiv;
      for (UInt4 j=0; j<m_2; j++) {
        y[j]=0.0;
      }
      for (UInt4 j=0; j<nDiv; j++){
        xi=x1+((j+1)-0.5)*dx;
        if(xi+dx<radiusSmall || xi-dx>radiusLarge) {
          continue;
        }
        for (UInt4 k=0; k<m; k++) {
          x[k]=xi+xk[k]*dx/2;
        }
        for (UInt4 k=0; k<m; k++) {
          f[k]=x[k]*IntegTheta(species, z, x[k]);
        }
        for (UInt4 k=0; k<m_2; k++) {
          y[k]+=f[k]+f[m-k-1];
        }
      }
      for (UInt4 j=0; j<m_2; j++) {
        y[j]*=Hk[j];
      }
      Double sum=0.0;
      for (UInt4 j=0; j<m_2; j++) {
        sum+=y[j];
      }
      s=0.5*dx*sum;
      diff=s-s1;
      if (diff<0.0) {
        diff=-diff;
      }
      if(i>0) {
        if (diff < epsilon ) {
          break;
        }
        if (s>threZero && diff/s<epsilonRatio){
          break;
        }
      }
      s1=s;
    }
*/
    UInt4 i,j,k;
    for (i=0; i<max; i++) { //20140126 ++ start
      nDiv*=2;
      dx=(radiusLarge-radiusSmall)/nDiv;
      //---------------------
      std::fill_n(y,m_2,0.0);
      //---------------------
      for (j=0; j<nDiv; j++){
        xi=x1+((j+1)-0.5)*dx;

        if(xi+dx<radiusSmall || xi-dx>radiusLarge) {
          continue;
        }
        for (k=0; k<m; k++) {
          x[k]=xi+xk[k]*dx*0.5;
        }
        for (k=0; k<m; k++) {
          f[k]=x[k]*IntegTheta(species, z, x[k]);
        }
        for (k=0; k<m_2; k++) {
          y[k]+=f[k]+f[m-k-1];
        }
      }
      //---------------------
      for (j=0; j<m_2; j++) {
        y[j]*=Hk[j];
      }
      //---------------------
      Double sum = std::accumulate(y,y+m_2,0.0);
      //---------------------
      s=0.5*dx*sum;

      //diff=s-s1;     // 20140126 --
      //if (diff<0.0) {
      //  diff=-diff;
      //}
      diff=fabs(s-s1); // 20140126 ++

      if(i>0) {
        if (diff < epsilon ) {
          break;
        }
        if (s>threZero && diff/s<epsilonRatio){
          break;
        }
      }
      s1=s;
    }  //20140126 ++ end

    stotal+=s;
//  return s;
//  std::printf("break called\n");
  }
  return stotal;
}

Double AdvCorrectionAbsorptionDNA :: IntegTheta(UInt4 species, Double z, Double r){
  UInt4 max=10;
  Double x[m],y[m_2], f[m];
  Double s=0;
  Double s1=0;
  Double diff;
  Double x1, dx, xi;
  UInt4 nDiv;
  nDiv=2;
/* //20140126 --
  for (UInt4 i=0; i<max; i++) {
    s=0.0;
    nDiv*=2;
    x1=0.0;
    dx=2.0*PI/nDiv;
    for (UInt4 j=0; j<m_2; j++) {
      y[j]=0.0;
    }
    for (UInt4 j=0; j<nDiv; j++){
      xi=x1+((j+1)-0.5)*dx;
      for (UInt4 k=0; k<m; k++) {
        x[k]=xi+xk[k]*dx/2;
      }
      for (UInt4 k=0; k<m; k++) {

        scaPos.x=r*sin(x[k]);
        scaPos.y=z;
        scaPos.z=r*cos(x[k]);

        switch (species) {
          case 0:
            f[k]=ReturnIntegFunctionValueA_C_C();
            //f[k]=1.0;
            break;
          case 1:
            f[k]=ReturnIntegFunctionValueA_CS_C();
            //f[k]=1.0;
            break;
          case 2:
            f[k]=ReturnIntegFunctionValueA_CS_S();
            break;
          case 3:
            f[k]=ReturnIntegFunctionValueA_C_C();
            break;
          case 4:
            f[k]=ReturnIntegFunctionValueA_CS_C();
            break;
          case 5:
            f[k]=ReturnIntegFunctionValueA_S_S();
            break;
          default:
            std::printf("something wrong\n");
            exit(1);
        }
      }
      for (UInt4 k=0; k<m_2; k++) {
        y[k]+=f[k]+f[m-k-1];
      }
    }
    for (UInt4 j=0; j<m_2; j++) {
      y[j]*=Hk[j];
    }
    Double sum=0.0;
    for (UInt4 j=0; j<m_2; j++) {
      sum+=y[j];
    }
    s+=0.5*dx*sum;
    diff=s-s1;
    if (diff<0.0) {
      diff=-diff;
    }
//    std::printf("%d, ndiv=%d, s=%e, diff=%e\n", i, nDiv, s, diff); fflush(stdout);
//   std::fprintf(fp, "\n");
    if(i>0) {
      if (diff < epsilon) {
        break;
      }
      if (s>threZero && diff/s<epsilonRatio){
        break;
      }
    }
    s1=s;
  }
*/
//20140126 ++ start
  UInt4 i,j,k;
  for (i=0; i<max; i++) {
    s=0.0;
    nDiv*=2;
    x1=0.0;
    dx=2.0*PI/nDiv;
    //---------------------
    std::fill_n(y,m_2,0.0);
    //---------------------
    for (j=0; j<nDiv; j++){
      xi=x1+((j+1)-0.5)*dx;
      //---------------------
      for (k=0; k<m; k++) {
        x[k]=xi+xk[k]*dx*0.5;
      }
      //---------------------
      for (k=0; k<m; k++) {

        scaPos.x=r*sin(x[k]);
        scaPos.y=z;
        //scaPos.z=r*cos(x[k]); //implementation dependent

        //while (x[k]>2.0*PI)
        //    x[k]-=2.0*PI;

        //while (x[k]<0)
        //    x[k]+=2.0*PI;

        if (0.5*PI<x[k] && x[k]<PI*1.5)
            scaPos.z=-sqrt(r*r-scaPos.x*scaPos.x);
        else
            scaPos.z= sqrt(r*r-scaPos.x*scaPos.x);

        switch (species) {
          case 0:
            f[k]=ReturnIntegFunctionValueA_C_C();
            break;
          case 1:
            f[k]=ReturnIntegFunctionValueA_CS_C();
            break;
          case 2:
            f[k]=ReturnIntegFunctionValueA_CS_S();
            break;
          case 3:
            f[k]=ReturnIntegFunctionValueA_C_C();
            break;
          case 4:
            f[k]=ReturnIntegFunctionValueA_CS_C();
            break;
          case 5:
            f[k]=ReturnIntegFunctionValueA_S_S();
            break;
          default:
            std::printf("something wrong\n");
            exit(1);
        }
      }
      //---------------------
      for (k=0; k<m_2; k++) {
        y[k]+=f[k]+f[m-k-1];
      }
      //---------------------
    }
    //---------------------
    for (j=0; j<m_2; j++) {
      y[j]*=Hk[j];
    }
    //---------------------
    Double sum = std::accumulate(y,y+m_2,0.0);
    //---------------------

    s+=0.5*dx*sum;
    //diff=s-s1;     // 20140126 --
    //if (diff<0.0) {
    //  diff=-diff;
    //}
    diff=fabs(s-s1); // 20140126 ++

//    std::printf("%d, ndiv=%d, s=%e, diff=%e\n", i, nDiv, s, diff); fflush(stdout);
//   std::fprintf(fp, "\n");
    if(i>0) {
      if (diff < epsilon) {
        break;
      }
      if (s>threZero && diff/s<epsilonRatio){
        break;
      }
    }
    s1=s;
  } //20140126 ++ end

  return s;
}

void AdvCorrectionAbsorptionDNA :: GetModifiedIntensity(Double dE, char* sampleCellFilename, char* cellFilename){
//  FILE* fp1, *fp2;
//  fp1=fopen(sampleCellFilename.c_str(), "r");
//  fp2=fopen(sampleCellFilename.c_str(), "r");
  std::fstream fileSampleCell(sampleCellFilename, std::ios::in);
  if (fileSampleCell.fail()){
    std::cerr<<"cant open file" << sampleCellFilename<<std::endl;
    return;
  }

  UInt4 buffersize=3000;
  char buffer[buffersize];
  char w1[64], w2[64],w3[64],w4[64],w5[64],w6[64],w7[64],w8[64];

  char intensitySCList[buffersize], intensityCList[buffersize];
  char TOFSCList[buffersize], TOFCList[buffersize];

  Double detPosX, detPosY, detPosZ;
  UInt4 dataflag=0;
  UInt4 numData=0;

  std::printf("read sample data\n"); fflush(stdout);

  int k=0;

  while ( ! fileSampleCell.eof() ){
    fileSampleCell.getline(buffer, sizeof buffer);


    k++;

    if (strstr(buffer, "PixelPosition")!=NULL){
      std::sscanf(buffer, "%s %s %s %s %s, %s, %s %s",
              w1, w2, w3, w4, w5, w6, w7, w8);

      std::printf(" Pixel catched :: %s\n", buffer);
      char *p;
      p=std::strtok(buffer, "[] ,");
      for(int i=1; i<6; i++){
        p=std::strtok(NULL, "[] ,");
        if(i==3){
          detPosX=atof(p);
          std::printf("p=%s, detPosX=%f\n", p, detPosX); fflush(stdout);
        }
        if(i==4){
          detPosY=atof(p);
        }
        if(i==5){
          detPosZ=atof(p);
        }
      }

    }
    if (strstr(buffer,"Index")      !=NULL &&
        strstr(buffer, "Key" )      !=NULL &&
        strstr(buffer, "Size")      !=NULL &&
        strstr(buffer, "Unit")      !=NULL &&
        strstr(buffer, "Values")    !=NULL ) {
      dataflag=1;
    }
    if (dataflag==1){
      if(strstr(buffer, "Intensity") != NULL){
        std::sscanf(buffer, "%s %s %s %s %s",
               w1, w2, w3, w4, intensitySCList);
      }else if (strstr(buffer, "TOF") != NULL){
        std::sscanf(buffer, "%s %s %s %s %s",
               w1, w2, w3, w4, TOFSCList);
      }
    }

    std::sscanf(buffer, "%s", w1);
    if( strcmp(w1, "None")==0) break;

    if(k>100) exit(1);

  }
  fileSampleCell.close();

  std::printf("read sample data end\n"); fflush(stdout);

  dataflag=0;
  k=0;

  std::printf("read cell data begin\n"); fflush(stdout);

  std::fstream fileCell(cellFilename, std::ios::in);
  if (fileCell.fail()){
    std::cerr<<"cant open file" << cellFilename<<std::endl;
    return;
  }

  while ( ! fileCell.eof() ){


    fileCell.getline(buffer, sizeof buffer);


    k++;

    if (strstr(buffer,"Index")      !=NULL &&
        strstr(buffer, "Key" )      !=NULL &&
        strstr(buffer, "Size")      !=NULL &&
        strstr(buffer, "Unit")      !=NULL &&
        strstr(buffer, "Values")    !=NULL ) {
      dataflag=1;
    }
    if (dataflag==1){
      if(strstr(buffer, "Intensity") != NULL){
        std::sscanf(buffer, "%s %s %s %s %s",
               w1, w2, w3, w4, intensityCList);
        std::printf("Intensity catched\n"); fflush(stdout);

        numData=atoi(w3);

        std::printf("w1=%s, w2=%s, w3=%s, w4=%s\n", w1, w2, w3, w4); fflush(stdout);
        std::printf("numData=%d\n", numData); fflush(stdout);
      }else if (strstr(buffer, "TOF") != NULL){
        std::sscanf(buffer, "%s %s %s %s %s",
               w1, w2, w3, w4, TOFCList);
      }
    }
    std::sscanf(buffer, "%s %s", w1, w2);
    if( strcmp(w1, "None")==0) break;

    if(k>100) exit(1);

  }
  fileCell.close();

  std::cout<< "detPosX= "<<detPosX<<", detPosY="<<detPosY<<", detPosZ="<<detPosZ<<std::endl;
  std::cout.flush();

  Double theta=atan(detPosY/detPosZ)*MLF_RADIAN2DEGREE;
  std::cout<<" theta = "<<theta<<std::endl;
  Double phi=atan(detPosX/detPosY)*MLF_RADIAN2DEGREE;
  std::cout<<" phi   = "<<phi<<std::endl;
  std::cout.flush();


  Double intensitySC[numData];
  Double intensityC[numData];
  Double TOFSC[numData+1];
  Double TOFC[numData+1];

  std::printf(" intensitySCList\n"); fflush(stdout);


  char *p;

  std::printf(" intensitySCList\n"); fflush(stdout);
  std::printf("intensitySCList :: %s\n", intensitySCList); fflush(stdout);

  p=std::strtok(intensitySCList, "[,]");
  intensitySC[0]=atof(p);
  for (UInt4 i=1; i<numData; i++){
    p=std::strtok(NULL, "[,]");
    std::printf("i=%d, p=%s\n", i, p); fflush(stdout);
    intensitySC[i]=atof(p);
  }

  p=std::strtok(intensityCList, "[,]");
  intensityC[0]=atof(p);
  for (UInt4 i=1; i<numData; i++){
    p=std::strtok(NULL, "[,]");
    intensityC[i]=atof(p);
  }

  p=std::strtok(TOFSCList, "[,]");
  TOFSC[0]=atof(p);
  for (UInt4 i=1; i<numData+1; i++){
    p=std::strtok(NULL, "[,]");
    TOFSC[i]=atof(p)*MLF_MICROSEC2SEC;
  }

  p=std::strtok(TOFCList, "[,]");
  TOFC[0]=atof(p);
  for (UInt4 i=1; i<numData+1; i++){
    p=std::strtok(NULL, "[,]");
    TOFC[i]=atof(p)*MLF_MICROSEC2SEC;
  }

//  Double L1=42.0;
  Double L1=2.0;
  Double L2=0;
  //L2=sqrt (detPosX*detPosX+detPosY*detPosY+detPosZ*detPosZ) * MM2M;
  Double LTotal=L1+L2;


  Double ACC[numData], ACSS[numData], ACSC[numData];

  for (UInt4 i=0; i<numData; i++){
    printf ("%d-data\n", i); fflush(stdout);
    Double v1=LTotal/TOFSC[i];
    Double v2=LTotal/TOFSC[i+1];
    Double e1=0.5*MLF_Mn*v1*v1*MLF_J2MEV;
    Double e2=0.5*MLF_Mn*v2*v2*MLF_J2MEV;
    Double energy=(e1+e2)*0.5;
    ACC[i]=GetACC(theta, phi, energy, energy+dE);
    ACSS[i]=GetACSS(theta, phi, energy, energy+dE);
    ACSC[i]=GetACSC(theta, phi, energy, energy+dE);
  }

  Double background=0.0;

  Double modIntensity[numData];
  for (UInt4 i=0; i<numData; i++){
    modIntensity[i]=1.0/ACSS[i]*( (intensitySC[i]-background)-ACSC[i]/ACC[i]*(intensityC[i]-background) );
  }

  std::printf("*** mod intensity list *** \n");
  for (UInt4 i=0; i<numData; i++){
    std::printf("%f\n", modIntensity[i]);
  }

  char outfile[]="modifiedIntensityData.dat";
  FILE* fpout=fopen(outfile, "w");
  for (UInt4 i=0; i<numData; i++){

    Double v1=LTotal/TOFSC[i];
    Double v2=LTotal/TOFSC[i+1];
    Double e1=0.5*MLF_Mn*v1*v1*MLF_J2MEV;
    Double e2=0.5*MLF_Mn*v2*v2*MLF_J2MEV;
    Double energy=(e1+e2)*0.5;

   std::fprintf(fpout, "i=%d, energy=%e, intensity=%f\n", i, energy, modIntensity[i]);
  }
}

std::vector<Double>  AdvCorrectionAbsorptionDNA :: GetThetaPhi(PyObject *r){
  //int dimension=PyList_Size(r);
  //PyObject *thetaPhi;

/*
  std::printf("dimension=%d\n", dimension);
  if (dimension!=3){
    std::printf(" error \n");
    return thetaPhi;
  }

*/
  /* temporary */
  std::vector<Double> cppThetaPhi;
  Double scatTheta=10.0;
  Double scatPhi=10.0;
  cppThetaPhi.push_back(scatTheta);
  cppThetaPhi.push_back(scatPhi);

//  Map< std::vector< Double > > *DoubleVectorMap;




  return cppThetaPhi;
}

Double AdvCorrectionAbsorptionDNA :: GetCorrectIntensity(Double ACSS, Double ACSC, Double ACC, Double intensitySC, Double intensityC){
  Double background=0.0;
  return 1.0/ACSS*( (intensitySC-background)-ACSC/ACC*(intensityC-background) );
}





