diff --git a/NPLib/Physics/NPQFS.cxx b/NPLib/Physics/NPQFS.cxx
index 391ffa6c0571bf27e68b88a1156b365ab328e086..1b20bfbde3c40df7b0cb83bac4de05360e7e40d0 100644
--- a/NPLib/Physics/NPQFS.cxx
+++ b/NPLib/Physics/NPQFS.cxx
@@ -7,29 +7,32 @@
 
 /*****************************************************************************
  *                                                                           *
- * Original Author :  F. Flavigny contact address: flavigny@ipno.in2p3.fr    *
+ * Original Author :  F. Flavigny contact address: flavigny@lpccaen.in2p3.fr *
  *                                                                           *
  * Creation Date   : April 2019                                              *
- * Last update     : April 2019                                              *
+ * Last update     : Nov 2019                                                *
  *---------------------------------------------------------------------------*
  * Decription:                                                               *
  *  This class deal with Quasi Free Scattering Reaction in which a cluster   *
  *  or a nucleon is removed from a projectile  by interaction with a target  *
  *  nucleon (proton target in general)                                       *
  *                                                                           *
- * Labeling is:                                                              *
- *              A --> i  ==> B + (i -> a) =>  B + 1 + 2                      *
+ *  First step (dissociation):  A -> B + c                                   *
+ *  Second step (scattering) :  c + T -> 1 + 2                               *
+ *  Labeling is:                                                             *
+ *                                                                           *
+ *              A --> T  ==> B + (c -> T) =>  B + 1 + 2                      *
  *                                                                           *
  *  where:                                                                   *
  *    +  A is the beam nucleus                                               *
- *    +  i is the target nucleon (proton)                                    *
+ *    +  T is the target nucleon (proton)                                    *
  *                                                                           *
  *    +  B is the residual fragment (beam-like)                              *
- *    +  1 is the scattered target nucleon  (former i)                       *
- *    +  2 is the knocked-out cluster/nucleon (noted a) in the intermediate  *
+ *    +  1 is the scattered target nucleon  (former T)                       *
+ *    +  2 is the knocked-out cluster/nucleon (noted c) in the intermediate  *
  *---------------------------------------------------------------------------*
  * Comment:                                                                  *
- *    +                                                                      *
+ *    +  Adapted from original event generator from V. Panin (R3B collab)    *
  *                                                                           *
  *****************************************************************************/
 
@@ -55,16 +58,625 @@ using namespace NPUNITS;
 
 // ROOT
 #include"TF1.h"
+#include"TRandom3.h"
 
 ClassImp(QFS)
-/*
-//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
+
+////////////////////////////////////////////////////////////////////////////////
+
 QFS::QFS(){
-    fVerboseLevel=0;
+
+    //------------- Default Constructor -------------
+    fVerboseLevel         = NPOptionManager::getInstance()->GetVerboseLevel();
+    fBeamEnergy           = 0;
+    fThetaCM              = 0;
+    fPhiCM                = 0;
+ 
+    fExcitationA          = 0;
+    fExcitationB          = 0;
+    fMomentumSigma        = 0;
+    fshootB=false;
+    fshoot1=true;
+    fshoot2=true;
+    fisotropic = true;
+
+    fTheta2VsTheta1 = 0;
+    fPhi2VsPhi1 = 0;
 
 }
-//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
+
+////////////////////////////////////////////////////////////////////////////////
+
 QFS::~QFS(){
+
+}
+
+/////////////////////////////////////////////////////////////////////////////////////////////////////////
+
+void QFS::ReadConfigurationFile(string Path){
+  ifstream ReactionFile;
+  string GlobalPath = getenv("NPTOOL");
+  string StandardPath = GlobalPath + "/Inputs/EventGenerator/" + Path;
+  ReactionFile.open(Path.c_str());
+  if (!ReactionFile.is_open()) {
+    ReactionFile.open(StandardPath.c_str());
+    if(ReactionFile.is_open()) {
+      Path = StandardPath;
+    }
+    else {cout << "QFS File " << Path << " not found" << endl;exit(1);}
+  }
+  NPL::InputParser parser(Path);
+  ReadConfigurationFile(parser);
+}
+
+////////////////////////////////////////////////////////////////////////////////
+
+void QFS::ReadConfigurationFile(NPL::InputParser parser){
+
+  cout << " In QFS ReadConfiguration " << endl;
+  vector<NPL::InputBlock*> blocks = parser.GetAllBlocksWithToken("QFSReaction");
+  if(blocks.size()>0 && NPOptionManager::getInstance()->GetVerboseLevel())
+      cout << endl << "\033[1;35m//// QFS reaction found " << endl;
+
+  vector<string> token1 = {"Beam","Target","Scattered","KnockedOut","Heavy"};
+  for(unsigned int i = 0 ; i < blocks.size() ; i++){
+      if(blocks[i]->HasTokenList(token1)){
+          int v = NPOptionManager::getInstance()->GetVerboseLevel();
+          NPOptionManager::getInstance()->SetVerboseLevel(0);
+          fNucleiA.ReadConfigurationFile(parser);
+          NPOptionManager::getInstance()->SetVerboseLevel(v);
+
+          fBeamEnergy= fNucleiA.GetEnergy();
+          GetNucleus(blocks[i]->GetString("Beam"),parser);
+          fNucleiT = GetNucleus(blocks[i]->GetString("Target"),parser);
+          fNucleiB = GetNucleus(blocks[i]->GetString("Heavy"),parser);
+          fNuclei1 = GetNucleus(blocks[i]->GetString("Scattered"),parser);
+          fNuclei2 = GetNucleus(blocks[i]->GetString("KnockedOut"),parser);
+      }
+      else{
+          cout << "ERROR: check your input file formatting \033[0m" << endl;
+          exit(1);
+      }
+      if(blocks[i]->HasToken("ExcitationEnergyBeam")){
+          fExcitationA = blocks[i]->GetDouble("ExcitationEnergyBeam","MeV");
+      }
+      if(blocks[i]->HasToken("ExcitationEnergyHeavy")){
+          fExcitationB = blocks[i]->GetDouble("ExcitationEnergyHeavy","MeV");
+      }
+      if(blocks[i]->HasToken("MomentumSigma")){
+          fMomentumSigma = blocks[i]->GetDouble("MomentumSigma","MeV");
+      }
+      if(blocks[i]->HasToken("ShootHeavy")){
+          fshootB = blocks[i]->GetInt("ShootHeavy");
+      }
+      if(blocks[i]->HasToken("ShootLight")){
+          fshoot1 = blocks[i]->GetInt("ShootLight");
+          fshoot2 = blocks[i]->GetInt("ShootLight");
+      }
+  }
+
+  cout << "\033[0m" ;
+}
+
+////////////////////////////////////////////////////////////////////////////////
+Nucleus QFS::GetNucleus(string name, NPL::InputParser parser){
+
+  vector<NPL::InputBlock*> blocks = parser.GetAllBlocksWithTokenAndValue("DefineNucleus",name);
+  unsigned int size = blocks.size();
+  if(size==0)
+    return NPL::Nucleus(name);
+  else if(size==1){
+    cout << " -- User defined nucleus " << name << " -- " << endl;
+    vector<string> token = {"SubPart","BindingEnergy"};
+    if(blocks[0]->HasTokenList(token)){
+      NPL::Nucleus N(name,blocks[0]->GetVectorString("SubPart"),blocks[0]->GetDouble("BindingEnergy","MeV"));
+      if(blocks[0]->HasToken("ExcitationEnergy"))
+        N.SetExcitationEnergy(blocks[0]->GetDouble("ExcitationEnergy","MeV"));
+      if(blocks[0]->HasToken("SpinParity"))
+        N.SetSpinParity(blocks[0]->GetString("SpinParity").c_str());
+      if(blocks[0]->HasToken("Spin"))
+        N.SetSpin(blocks[0]->GetDouble("Spin",""));
+      if(blocks[0]->HasToken("Parity"))
+        N.SetParity(blocks[0]->GetString("Parity").c_str());
+      if(blocks[0]->HasToken("LifeTime"))
+        N.SetLifeTime(blocks[0]->GetDouble("LifeTime","s"));
+
+    cout << " -- -- -- -- -- -- -- -- -- -- --" << endl;
+      return N;
+    }
+  }
+  else{
+    NPL::SendErrorAndExit("NPL::QFS","Too many nuclei define with the same name");
+  }
+}
+
+
+////////////////////////////////////////////////////////////////////////////////////////////
+void QFS::CalculateVariables(){
+
+  if(fBeamEnergy < 0)
+    fBeamEnergy = 0 ; 
+
+    //cout<<"---- COMPUTE ------"<<endl;
+   // cout<<"--CM--"<<endl; 
+
+    mA = fNucleiA.Mass();            // Beam mass in MeV
+    mT =  fNucleiT.Mass();           // Target mass in MeV 
+    mB =  fNucleiB.Mass();           // Heavy residual mass in MeV 
+    m1 =  mT;                        // scattered target nucleon (same mass);
+    m2 =  fNuclei2.Mass();           // knocked out cluster mass in MeV 
+    ma =  m2;                        // intermediate cluster mass in MeV (same);
+ 
+    double TA = fBeamEnergy;                 // Beam kinetic energy
+    double PA = sqrt(TA*(TA+2*mA));          // Beam momentum (norm)
+    double EA = sqrt(mA*mA + PA*PA);         // Beam total energy
+    fEnergyImpulsionLab_A = TLorentzVector(0.,0.,PA,EA);
+    
+    //Internal momentum of removed cluster/nucleon
+    static TRandom3 r;
+    //r.SetSeed(0);
+    //double mom_sigma = 0; // MeV/c
+    Pa.SetX(r.Gaus(0.,fMomentumSigma));
+    Pa.SetY(r.Gaus(0.,fMomentumSigma));
+    Pa.SetZ(r.Gaus(0.,fMomentumSigma));
+
+    //Internal momentum of heavy recoil after removal
+    PB.SetXYZ( (-Pa.X()) , (-Pa.Y()) , (-Pa.Z()) );
+
+    //cout<<"Pa_cm=\t("<<Pa.Px()<<","<<Pa.Py()<<","<<Pa.Pz()<<")"<<endl;
+    //cout<<"||Pa||^2=\t("<<Pa.Mag2()<<endl;
+    //cout<<"mA^2=\t"<<mA*mA<<endl;
+    //cout<<"mB^2=\t"<<mB*mB<<endl;
+ 
+
+    // Off-shell mass of the bound nucleon from E conservation
+    // in virtual dissociation of A -> B + a
+    double buffer = mA*mA + mB*mB - 2*mA*sqrt(mB*mB+Pa.Mag2()) ; 
+    if(buffer<=0) { cout<<"ERROR off shell mass ma_off=\t"<<buffer<<endl; return;}
+    ma_off = sqrt(buffer);
+
+    //deduced total energies of "a" and "B" in restframe of A
+    double Ea = sqrt(ma_off*ma_off + Pa.Mag2());
+    double EB = sqrt(mB*mB + PB.Mag2());
+
+    //cout<<"ma_off^2=\t"<<buffer<<endl;
+    //cout<<"Ea=\t"<<Ea<<endl;
+    //cout<<"EB=\t"<<EB<<endl;
+
+    fEnergyImpulsionLab_a = TLorentzVector(Pa,Ea);
+    fEnergyImpulsionLab_B = TLorentzVector(PB,EB);
+    fEnergyImpulsionLab_a.Boost(0,0,fEnergyImpulsionLab_A.Beta());
+    fEnergyImpulsionLab_B.Boost(0,0,fEnergyImpulsionLab_A.Beta());
+    Ea_lab = fEnergyImpulsionLab_a.E();
+    EB_lab = fEnergyImpulsionLab_B.E();
+    Pa = fEnergyImpulsionLab_a.Vect();
+    PB = fEnergyImpulsionLab_B.Vect();
+   
+    // Scattering part (2-body kinematics)
+    // virtual cluster of mass "ma_off" scattering on target T
+    // to give scattered  cluster with real mass (ma=m2)
+    // and scattered target (mT=m1)
+
+    fQValue =ma_off+mT-m1-m2;
+
+    s = ma_off*ma_off + mT*mT + 2*mT*Ea_lab ; 
+    fTotalEnergyImpulsionCM = TLorentzVector(0,0,0,sqrt(s));
+    fEcm = sqrt(s) - m1 -m2;
+    if(fEcm<=0) { cout<<"ERROR Ecm negative =\t"<<fEcm<<endl; return;}
+
+    ECM_a = (s + ma_off*ma_off - mT*mT)/(2*sqrt(s));
+    ECM_T = (s + mT*mT - ma_off*ma_off)/(2*sqrt(s));
+    ECM_1 = (s + m1*m1 - m2*m2)/(2*sqrt(s));
+    ECM_2 = (s + m2*m2 - m1*m1)/(2*sqrt(s));
+
+    pCM_a = sqrt(ECM_a*ECM_a - ma_off*ma_off);
+    pCM_T = sqrt(ECM_T*ECM_T - mT*mT);
+    pCM_1 = sqrt(ECM_1*ECM_1 - m1*m1);
+    pCM_2 = sqrt(ECM_2*ECM_2 - m2*m2);
+
+    BetaCM = Pa.Mag() / (Ea_lab + mT);
+
+    //if(ECM_a<0 || ECM_T<0 || ECM_1<0 || ECM_2<0 ) { 
+    /*
+    if(pCM_a<0 || pCM_T<0 || pCM_1<0 || pCM_2<0 ) { 
+    cout<<"--LAB after Boost--"<<endl; 
+    cout<<"Pa_lab=\t("<<Pa.Px()<<","<<Pa.Py()<<","<<Pa.Pz()<<")"<<endl;
+    cout<<"PB_lab=\t("<<PB.Px()<<","<<PB.Py()<<","<<PB.Pz()<<")"<<endl;
+    cout<<"Ea_lab=\t"<<Ea_lab<<endl;
+    cout<<"EB_lab=\t"<<EB_lab<<endl;
+    cout<<"--Back to CM--"<<endl; 
+    cout<<"fQValue=\t"<<fQValue<<endl;
+    cout<<"s=\t"<<s<<endl;
+    cout<<"Ecm=\t"<<fEcm<<endl;
+    cout<<"ea*=\t"<<ECM_a<<endl;
+    cout<<"eT*=\t"<<ECM_T<<endl;
+    cout<<"e1*=\t"<<ECM_1<<endl;
+    cout<<"p1*=\t"<<pCM_1<<endl;
+    cout<<"e2*=\t"<<ECM_2<<endl;
+    cout<<"p2*=\t"<<pCM_2<<endl;
+    cout<<"beta_cm=\t"<<BetaCM<<endl;
+    }
+    */
+}
+
+////////////////////////////////////////////////////////////////////////////////////////////
+
+void QFS::KineRelativistic(double& ThetaLab1, double& PhiLab1, double& KineticEnergyLab1, double& ThetaLab2, double& PhiLab2, double& KineticEnergyLab2){
+
+    CalculateVariables();
+
+    //double thetaCM_1 = fThetaCM*TMath::Pi()/180.;
+    double thetaCM_1 = fThetaCM;
+    double thetaCM_2 =  M_PI - thetaCM_1;
+    //double phiCM_1 = fPhiCM*TMath::Pi()/180.;
+    double phiCM_1 = fPhiCM;
+    double phiCM_2 =  2*M_PI - phiCM_1;
+
+    TVector3 z_axis(0.,0.,1.);
+
+    fEnergyImpulsionCM_2	= TLorentzVector(
+                                        pCM_2*sin(thetaCM_2)*cos(phiCM_2),
+                                        pCM_2*cos(thetaCM_2)*sin(phiCM_2),
+                                        pCM_2*cos(thetaCM_2),
+                                        ECM_2);
+    fEnergyImpulsionCM_1	= fTotalEnergyImpulsionCM - fEnergyImpulsionCM_2;
+
+    fEnergyImpulsionLab_1 = fEnergyImpulsionCM_1;
+    fEnergyImpulsionLab_1.Boost(0,0,BetaCM);
+    fEnergyImpulsionLab_2 = fEnergyImpulsionCM_2;
+    fEnergyImpulsionLab_2.Boost(0,0,BetaCM);
+
+    // Angle in the lab frame
+    //ThetaLab1 = fEnergyImpulsionLab_1.Angle(fEnergyImpulsionLab_A.Vect());
+    ThetaLab1 = fEnergyImpulsionLab_1.Angle(z_axis);
+    if (ThetaLab1 < 0) ThetaLab1 += M_PI;
+    //ThetaLab2 = fEnergyImpulsionLab_4.Angle(fEnergyImpulsionLab_A.Vect());
+    ThetaLab2 = fEnergyImpulsionLab_2.Angle(z_axis);
+    if (fabs(ThetaLab1) < 1e-6) ThetaLab1 = 0;
+    ThetaLab2 = fabs(ThetaLab2);
+    if (fabs(ThetaLab2) < 1e-6) ThetaLab2 = 0;
+
+    PhiLab1 = M_PI + fEnergyImpulsionLab_1.Vect().Phi(); 
+    if (fabs(PhiLab1) < 1e-6) PhiLab1 = 0;
+    PhiLab2 = M_PI + fEnergyImpulsionLab_2.Vect().Phi(); 
+    if (fabs(PhiLab2) < 1e-6) PhiLab2 = 0;
+
+    // Kinetic Energy in the lab frame
+    KineticEnergyLab1 = fEnergyImpulsionLab_1.E() - m1;
+    KineticEnergyLab2 = fEnergyImpulsionLab_2.E() - m2;
+
+    // test for total energy conversion
+    //if (fabs(fTotalEnergyImpulsionLab.E() - (fEnergyImpulsionLab_1.E()+fEnergyImpulsionLab_2.E())) > 1e-6)
+    //    cout << "Problem for energy conservation" << endl;
+
+/*
+    cout<<"--KINE RELATIVISTIC--"<<endl;
+    cout<<"theta_cm:"<<fThetaCM*180./TMath::Pi()<<endl;
+    cout<<"phi_cm:"<<fPhiCM*180./TMath::Pi()<<endl;
+    cout<<"P1_CM=\t("<<fEnergyImpulsionCM_1.Px()<<","<<fEnergyImpulsionCM_1.Py()<<","<<fEnergyImpulsionCM_1.Pz()<<")"<<endl;
+    cout<<"P2_CM=\t("<<fEnergyImpulsionCM_2.Px()<<","<<fEnergyImpulsionCM_2.Py()<<","<<fEnergyImpulsionCM_2.Pz()<<")"<<endl;
+    cout<<"P1_lab=\t("<<fEnergyImpulsionLab_1.Px()<<","<<fEnergyImpulsionLab_1.Py()<<","<<fEnergyImpulsionLab_1.Pz()<<")"<<endl;
+    cout<<"P2_lab=\t("<<fEnergyImpulsionLab_2.Px()<<","<<fEnergyImpulsionLab_2.Py()<<","<<fEnergyImpulsionLab_2.Pz()<<")"<<endl;
+    cout<<"Theta1:\t"<<fEnergyImpulsionLab_1.Vect().Theta()*180./TMath::Pi()<<endl;
+    cout<<"Theta2:\t"<<fEnergyImpulsionLab_2.Vect().Theta()*180./TMath::Pi()<<endl;
+    cout<<"Phi1:\t"<<M_PI+fEnergyImpulsionLab_1.Vect().Phi()*180./TMath::Pi()<<endl;
+    cout<<"Phi2:\t"<<M_PI+fEnergyImpulsionLab_2.Vect().Phi()*180./TMath::Pi()<<endl;
+*/
+
 }
+
+////////////////////////////////////////////////////////////////////////////////////////////
+
+double QFS::ShootRandomThetaCM(){
+
+  double theta; // CM
+/*
+  if(fDoubleDifferentialCrossSectionHist){
+    // Take a slice in energy
+    TAxis* Y = fDoubleDifferentialCrossSectionHist->GetYaxis();
+    int binY;
+
+    // Those test are there for the tail event of the energy distribution
+    // In case the energy is outside the range of the 2D histo we take the
+    // closest available CS
+    if(Y->FindBin(fBeamEnergy) > Y->GetLast())
+      binY = Y->GetLast()-1;
+
+    else if(Y->FindBin(fBeamEnergy) < Y->GetFirst())
+      binY = Y->GetFirst()+1;
+
+    else
+      binY = Y->FindBin(fBeamEnergy);
+
+    TH1D* Proj = fDoubleDifferentialCrossSectionHist->ProjectionX("proj",binY,binY);
+    SetThetaCM( theta=Proj->GetRandom()*deg );
+  }
+  else if (fLabCrossSection){
+    double thetalab=-1;
+    double energylab=-1;
+    while(energylab<0){
+      thetalab=fCrossSectionHist->GetRandom()*deg; //shoot in lab
+      energylab=EnergyLabFromThetaLab(thetalab);   //get corresponding energy
+    }
+    theta = EnergyLabToThetaCM(energylab, thetalab); //transform to theta CM
+    SetThetaCM( theta );
+  }
+  else{
+    // When root perform a Spline interpolation to shoot random number out of
+    // the distribution, it can over shoot and output a number larger that 180
+    // this lead to an additional signal at 0-4 deg Lab, especially when using a
+    // flat distribution.
+    // This fix it.
+    theta=181;
+    if(theta/deg>180)
+      theta=fCrossSectionHist->GetRandom();
+    //cout << " Shooting Random ThetaCM "  << theta << endl;
+    SetThetaCM( theta*deg );
+  }
 */
+  return theta;
+}
+
+////////////////////////////////////////////////////////////////////////////////////////////
+
+TGraph* QFS::GetTheta2VsTheta1(double AngleStep_CM){
+
+  vector<double> vx;
+  vector<double> vy;
+  double theta1,phi1,E1,theta2,phi2,E2;
+
+  for (double angle=0 ; angle <= 180 ; angle+=AngleStep_CM){
+    SetThetaCM(angle*TMath::Pi()/180.);
+    KineRelativistic(theta1, phi1, E1, theta2, phi2, E2);
+
+    vx.push_back(theta1*180./M_PI);
+    vy.push_back(theta2*180./M_PI);
+  }
+  fTheta2VsTheta1 = new TGraph(vx.size(),&vx[0],&vy[0]);
+
+  return(fTheta2VsTheta1);
+}
+
+////////////////////////////////////////////////////////////////////////////////////////////
+
+TGraph* QFS::GetPhi2VsPhi1(double AngleStep_CM){
+
+  vector<double> vx;
+  vector<double> vy;
+  double theta1,phi1,E1,theta2,phi2,E2;
+
+  for (double theta=0 ; theta <= 180 ; theta+=AngleStep_CM){
+      for (double angle=0 ; angle <= 180 ; angle+=AngleStep_CM){
+          SetThetaCM(theta*TMath::Pi()/180.);
+          SetPhiCM(angle*TMath::Pi()/180.);
+          KineRelativistic(theta1, phi1, E1, theta2, phi2, E2);
+          vx.push_back(phi1*180./M_PI);
+          vy.push_back(phi2*180./M_PI);
+      }
+  }
+  fPhi2VsPhi1 = new TGraph(vx.size(),&vx[0],&vy[0]);
+
+  return(fPhi2VsPhi1);
+}
+
+///////////////////////////////////////////////////////////////////////////////
+// Check whenever the reaction is allowed at a given energy
+bool QFS::IsAllowed(){//double Energy){
+  //double AvailableEnergy = Energy + fNuclei1.Mass() + fNuclei2.Mass();
+  //double RequiredEnergy  = fNuclei3.Mass() + fNuclei4.Mass();
+
+  //if(AvailableEnergy>RequiredEnergy)
+    return true;
+  //else
+  //  return false;
+}
+
+////////////////////////////////////////////////////////////////////////////////////////////
+////////////////////////////////////////////////////////////////////////////////////////////
+///////////////// Old R3B method not using TLorentz Vector  ////////////////////////////////
+/////////////////// (used as a reference)///////////////////////////////////////////////////
+////////////////////////////////////////////////////////////////////////////////////////////
+/*
+void QFS::CalculateVariablesOld(){
+
+    initializePrecomputeVariable();
+
+    vector<double> theta1;
+    vector<double> theta2;
+    vector<double> phi1;
+    vector<double> phi2;
+
+    //for(int i=0; i<=180; i++){
+    int i = 29;
+        KineR3B(s, ma_off, mT, ma, (double)i);
+        if(!good) { cout<<"ERROR CM calculations!!!"<<endl; return;}
+
+        TVector3 P1_cm(0.,0.,1.), P2_cm(0.,0.,1.);
+        P2_cm.SetMag(p_clust);
+        P2_cm.SetTheta(theta_clust);
+        TRandom3 ra;
+        ra.SetSeed(0);
+        //P2_cm.SetPhi(ra.Uniform(-1*TMath::Pi(),+1*TMath::Pi()));
+        P2_cm.SetPhi(0.);
+        P1_cm.SetX(-P2_cm.X());
+        P1_cm.SetY(-P2_cm.Y());
+        P1_cm.SetZ(-P2_cm.Z());
+        cout<<"FFFFFFFFFFFFFFFFF"<<endl;
+        cout<<"P1_CM=\t("<<P1_cm.X()<<","<<P1_cm.Y()<<","<<P1_cm.Z()<<")"<<endl;
+        cout<<"P2_CM=\t("<<P2_cm.X()<<","<<P2_cm.Y()<<","<<P2_cm.Z()<<")"<<endl;
+ 
+
+        // Calculate relative to direction of quasi-particle (cluster)
+
+        double beta_cm = -Pa.Mag() / (Ea_lab + mT);
+        double gamma_cm = 1/sqrt(1-beta_cm*beta_cm);
+
+        pair<double,double> lor_a1 = Lorentz(gamma_cm,beta_cm,e_scat,P1_cm.Z());
+        pair<double,double> lor_a2 = Lorentz(gamma_cm,beta_cm,e_clust,P2_cm.Z());
+
+        P1_cm.SetZ(lor_a1.second);
+        P2_cm.SetZ(lor_a2.second);
+
+        //Rotating back to beam direction
+        //TVector3 P1_L = Rotations(P1_cm, Pa);
+        //TVector3 P2_L = Rotations(P2_cm, Pa);
+        
+        TVector3 P1_L = P1_cm;
+        TVector3 P2_L = P2_cm;
+        TVector3 direction = Pa.Unit();
+        //P1_L.RotateUz(direction);
+        //P1_L.RotateUz(direction);
+
+        cout<<"----Calculate variables output------"<<endl;
+       cout<<"--CM--"<<endl;
+        cout<<"theta1*=\t"<<theta_scat*180/TMath::Pi()<<endl;
+        cout<<"theta2*=\t"<<theta_clust*180/TMath::Pi()<<endl;
+        cout<<"e1*=\t"<<e_scat<<endl;
+        cout<<"p1*=\t"<<p_scat<<endl;
+        cout<<"e2*=\t"<<e_clust<<endl;
+        cout<<"p2*=\t"<<p_clust<<endl;
+        cout<<"T=\t"<<T<<endl;
+        cout<<"beta_cm=\t"<<beta_cm<<endl;
+        cout<<"gamma_cm=\t"<<gamma_cm<<endl;
+
+        cout<<"--LAB (cluster dir)--"<<endl;
+        cout<<"P1_lab=\t("<<P1_cm.X()<<","<<P1_cm.Y()<<","<<P1_cm.Z()<<")"<<endl;
+        cout<<"P2_lab=\t("<<P2_cm.X()<<","<<P2_cm.Y()<<","<<P2_cm.Z()<<")"<<endl;
+        cout<<"Theta1:\t"<<P1_cm.Theta()*180./TMath::Pi()<<endl;
+        cout<<"Theta2:\t"<<P2_cm.Theta()*180./TMath::Pi()<<endl;
+
+        cout<<"--LAB--"<<endl;
+        cout<<"Theta1L:\t"<<P1_L.Theta()*180./TMath::Pi()<<endl;
+        cout<<"Theta2L:\t"<<P2_L.Theta()*180./TMath::Pi()<<endl;
+        cout<<"Phi1L:\t"<<P1_L.Phi()*180./TMath::Pi()<<endl;
+        cout<<"Phi2L:\t"<<P2_L.Phi()*180./TMath::Pi()<<endl;
 
+
+        //cout<<P1_cm.Theta()*180./TMath::Pi()<<"\t"<<P2_cm.Theta()*180./TMath::Pi()<<endl;
+        //cout<<P1_L.Phi()*180./TMath::Pi()<<"\t"<<P2_L.Phi()*180./TMath::Pi()<<endl;
+        
+       theta1.push_back(P1_L.Theta()*180./TMath::Pi());
+       theta2.push_back(P2_L.Theta()*180./TMath::Pi());
+      
+       double temp_phi1 = P1_L.Phi(); 
+       double temp_phi2 = P2_L.Phi(); 
+       phi1.push_back(180. + P1_L.Phi()*180./TMath::Pi());
+       phi2.push_back(180. + P2_L.Phi()*180./TMath::Pi());
+
+    //}
+    TGraph* fTheta2VsTheta1 = new TGraph(theta1.size(),&theta1[0],&theta2[0]);
+    TGraph* fPhi2VsPhi1 = new TGraph(phi1.size(),&phi1[0],&phi2[0]);
+    fTheta2VsTheta1->SetName("Theta2VsTheta1");
+    fPhi2VsPhi1->SetName("Phi2VsPhi1");
+    TFile* f = new TFile("graphs.root","RECREATE");
+    fTheta2VsTheta1->Write();
+    fPhi2VsPhi1->Write();
+    f->Close();
+
+
+}
+
+// Calculate elastic scattering kinematics in CM-system (1-target proton, 2-cluster)
+void QFS::KineR3B(double s,double m2off,double m1,double m2,double thetacm)
+{
+     if(thetacm>180 || thetacm<0){
+        cout << "\nERROR! ThetaCM (in deg) should be between 0 and 180"<<endl;
+        return;
+    }
+
+	e_clust = 0;
+	p_clust = 0;
+	theta_clust = 0;
+	e_scat = 0;
+	p_scat = 0;
+	theta_scat = 0;
+	T = 0;
+	good = false;
+
+
+	double X = s;
+	double Y = m2off*m2off;
+	double Z = m1*m1;
+	double sqrt_s = sqrt(s);
+
+	// Kinematics before the scattering process
+	// (with one off-shell mass)
+	double p2_off = sqrt(function(X,Y,Z))/2/sqrt_s;
+	double p1_off = p2_off;
+	// CM energies
+	double e1_off = (s+Z-Y)/2/sqrt_s;
+	double e2_off = (s+Y-Z)/2/sqrt_s;
+
+	// Now take the real masses (after scattering)
+	Y = m2*m2;  Z = m1*m1;
+	//And check whether the kinematical function is ok
+	//for this specific kinematical case
+	double ERROR_CI = function(X,Y,Z);
+	if(ERROR_CI <= 0.){
+		cout << "\nERROR!!! Kinematical function is negative!";
+		return;
+	}
+
+	// Kinematics after the scattering process
+	// (with all real masses)
+	double p2 = sqrt(function(X,Y,Z))/2/sqrt_s;
+	double p1 = p2;
+	double e1 = (s+Z-Y)/2/sqrt_s;
+	double e2 = (s+Y-Z)/2/sqrt_s;
+
+	// Let's consider momentum transfer <t> from the
+	// target particle 1 to the cluster 2
+    double t = 2*(m1*m1 - e1_off*e1 + p1_off*p1*cos(thetacm*TMath::Pi()/180.));
+
+    //CM scattering angles
+    double theta1 = thetacm*TMath::Pi()/180.;
+    double theta2 = TMath::Pi() - theta1;
+
+    e_clust = e2;
+    p_clust = p2;
+    theta_clust = theta2;
+
+    e_scat = e1;
+    p_scat = p1;
+    theta_scat = theta1;
+
+    T = t;
+    good = true;
+
+
+}
+
+
+
+double QFS::function(double x,double y,double z)
+{	
+	double lambda = x*x + y*y + z*z - 2*x*y - 2*x*z - 2*y*z;
+	return lambda;
+}
+
+//---- Two consecutive rotations 
+//first around Z on <phi>, then around new X' on <theta> (1=Pcm, 2=Pa in lab)
+TVector3 QFS::Rotations(TVector3 v1,TVector3 v2) 
+{
+	double CT = v2.Z()/v2.Mag(); // cos(theta) of v2 wrt. Z-axis
+	double ST = sqrt(1-CT*CT);   // sin(theta)
+	double CF = v2.X()/v2.Mag()/ST;
+	double SF = v2.Y()/v2.Mag()/ST;
+
+	TVector3 v3;
+	double _v3x =  v1.X()*CT*CF - v1.Y()*SF + v1.Z()*ST*CF;
+	double _v3y =  v1.X()*CT*SF + v1.Y()*CF + v1.Z()*ST*SF;
+	double _v3z = -v1.X()*ST   +  v1.Z()*CT;
+	v3.SetXYZ(_v3x,_v3y,_v3z);
+	return v3;
+}
+
+
+
+pair<double, double> QFS::Lorentz(double gamma,double beta,double e,double p)
+{
+	double eL = gamma*e - gamma*beta*p;
+	double pL = gamma*p - gamma*beta*e;
+	return make_pair(eL, pL);
+}
+*/
diff --git a/NPLib/Physics/NPQFS.h b/NPLib/Physics/NPQFS.h
index b0107b6c85c3def61911987017ee613fa918ed36..0d7f63c753157247acd905f10497bcd11f7eb4a7 100644
--- a/NPLib/Physics/NPQFS.h
+++ b/NPLib/Physics/NPQFS.h
@@ -1,6 +1,5 @@
 #ifndef NPQFS_h
 #define NPQFS_h
-/*****************************************************************************/
 /*****************************************************************************
  * Copyright (C) 2009-2019   this file is part of the NPTool Project         *
  *                                                                           *
@@ -10,29 +9,32 @@
 
 /*****************************************************************************
  *                                                                           *
- * Original Author :  F. Flavigny contact address: flavigny@ipno.in2p3.fr    *
+ * Original Author :  F. Flavigny contact address: flavigny@lpccaen.in2p3.fr *
  *                                                                           *
  * Creation Date   : April 2019                                              *
- * Last update     : April 2019                                              *
+ * Last update     : Nov 2019                                                *
  *---------------------------------------------------------------------------*
  * Decription:                                                               *
  *  This class deal with Quasi Free Scattering Reaction in which a cluster   *
  *  or a nucleon is removed from a projectile  by interaction with a target  *
  *  nucleon (proton target in general)                                       *
  *                                                                           *
- * Labeling is:                                                              *
- *              A --> i  ==> B + (i -> a) =>  B + 1 + 2                      *
+ *  First step (dissociation):  A -> B + c                                   *
+ *  Second step (scattering) :  c + T -> 1 + 2                               *
+ *  Labeling is:                                                             *
+ *                                                                           *
+ *              A --> T  ==> B + (c -> T) =>  B + 1 + 2                      *
  *                                                                           *
  *  where:                                                                   *
  *    +  A is the beam nucleus                                               *
- *    +  i is the target nucleon (proton)                                    *
+ *    +  T is the target nucleon (proton)                                    *
  *                                                                           *
  *    +  B is the residual fragment (beam-like)                              *
- *    +  1 is the scattered target nucleon  (former i)                       *
- *    +  2 is the knocked-out cluster/nucleon (noted a) in the intermediate  *
+ *    +  1 is the scattered target nucleon  (former T)                       *
+ *    +  2 is the knocked-out cluster/nucleon (noted c) in the intermediate  *
  *---------------------------------------------------------------------------*
  * Comment:                                                                  *
- *    +                                                                      *
+ *    +  Adapted from original event generator from V. Panin (R3B collab)    *
  *                                                                           *
  *****************************************************************************/
 
@@ -41,6 +43,7 @@
 
 // NPL
 #include "NPNucleus.h"
+#include "NPBeam.h"
 #include "NPInputParser.h"
 using namespace NPL;
 
@@ -60,12 +63,138 @@ namespace NPL{
   class QFS{
 
     public:  // Constructors and Destructors
-      QFS(){};
-      ~QFS(){};
+      QFS();
+      ~QFS();
 
     private:
     int fVerboseLevel;
+    Beam     fNucleiA;                 // Beam (A)
+    Nucleus  fNucleiT;                 // Target (T)
+    Nucleus  fNucleiB;                 // Beam-like ejectile (B)
+    Nucleus  fNuclei1;                 // Target-like ejectile (1)
+    Nucleus  fNuclei2;                 // Knocked-out nucleon/cluster (2)
+    double   fQValue;                  // Q-value in MeV
+    double   fEcm;                     // Ecm in MeV
+    double   fThetaCM;                 // Center-of-mass theta angle in radian
+    double   fPhiCM;                   // Center-of-mass Phi angle in radian
+    double   fBeamEnergy;              // Beam energy in MeV
+    double   fExcitationA;             // Excitation energy in MeV of the beam, useful for isomers 
+    double   fExcitationB;             // Excitation energy in MeV of beam-like ejectile
+    double   fMomentumSigma;          // Width of the momentum distribution of the removed cluster (sigma)             
+    double   fisotropic;               
+
+    TGraph* fTheta2VsTheta1;
+    TGraph* fPhi2VsPhi1;
+
+    // used for MC simulations
+    bool fshootB; // shoot beam-like ejectile
+    bool fshoot1; // shoot light ejectile &
+    bool fshoot2; // shoot light ejectile 2
+    
+    public:
+    Nucleus GetNucleus(string name, NPL::InputParser parser);
+    void ReadConfigurationFile(string Path);
+    void ReadConfigurationFile(NPL::InputParser);
+    void CalculateVariables();
+    void KineRelativistic(double &ThetaLab1, double &PhiLab1, double &KineticEnergyLab1, double &ThetaLab2, double &PhiLab2, double &KineticEnergyLab2);
+    double ShootRandomThetaCM();
+    bool IsAllowed();
+
+    private: // intern precompute variable
+    double mA;
+    double mB;
+    double ma_off;
+    double ma;
+    double mT;
+    double m1;
+    double m2;
+
+    TVector3 Pa, PB;
+    double Ea_lab,EB_lab;
+
+    // Lorentz Vector
+    TLorentzVector fEnergyImpulsionLab_A;
+    TLorentzVector fEnergyImpulsionLab_B;
+    TLorentzVector fEnergyImpulsionLab_a;
+    TLorentzVector fEnergyImpulsionLab_T;
+    TLorentzVector fEnergyImpulsionLab_1;
+    TLorentzVector fEnergyImpulsionLab_2;
+    TLorentzVector fTotalEnergyImpulsionLab;
+
+    TLorentzVector fEnergyImpulsionCM_a;
+    TLorentzVector fEnergyImpulsionCM_T;
+    TLorentzVector fEnergyImpulsionCM_1;
+    TLorentzVector fEnergyImpulsionCM_2;
+    TLorentzVector fTotalEnergyImpulsionCM;
+
+    // Impulsion Vector3
+    TVector3 fImpulsionLab_a;
+    TVector3 fImpulsionLab_T;
+    TVector3 fImpulsionLab_1;
+    TVector3 fImpulsionLab_2;
+
+    TVector3 fImpulsionCM_a;
+    TVector3 fImpulsionCM_T;
+    TVector3 fImpulsionCM_1;
+    TVector3 fImpulsionCM_2;
+
+    // CM Energy composante & CM impulsion norme
+    Double_t ECM_a;
+    Double_t ECM_T;
+    Double_t ECM_1;
+    Double_t ECM_2;
+    Double_t pCM_a;
+    Double_t pCM_T;
+    Double_t pCM_1;
+    Double_t pCM_2;
+
+    // Mandelstam variable
+    Double_t s;
+
+    // Center of Mass Kinematic
+    Double_t BetaCM;
+
+    public:
+    //SETTERS
+    void SetBeamEnergy(const double& eBeam) {fBeamEnergy = eBeam;}
+    void SetThetaCM(const double& angle) {fThetaCM = angle;}
+    void SetPhiCM(const double& angle) {fPhiCM = angle;}
+
+    //GETTERS
+    Nucleus*  GetNucleusA()               {return &fNucleiA;}
+    Nucleus*  GetNucleusT()               {return &fNucleiT;}
+    Nucleus*  GetNucleusB()               {return &fNucleiB;}
+    Nucleus*  GetNucleus1()               {return &fNuclei1;}
+    Nucleus*  GetNucleus2()               {return &fNuclei2;}
+    bool     GetShoot1()         const        {return fshoot1;}
+    bool     GetShoot2()         const        {return fshoot2;}
+    bool     GetShootB()         const        {return fshootB;}
  
+    TLorentzVector*  GetEnergyImpulsionLab_B() {return &fEnergyImpulsionLab_B;}
+    TGraph* GetTheta2VsTheta1(double AngleStep_CM=1);
+    TGraph* GetPhi2VsPhi1(double AngleStep_CM=1);
+
+
+
+    /*
+    //TO REMOVE AT SOME POINT WHEN CLASS IS ROBUSTLY TESTED
+    private:
+    // R3B Methods and Variables used as a starting point for this class (useful for checks)
+    void CalculateVariablesOld();
+    pair<double,double> Lorentz(double, double, double, double);
+    double function(double, double, double);
+    void KineR3B(double, double, double, double, double);
+    TVector3 Rotations(TVector3,TVector3);
+    double e_clust;
+    double p_clust;
+    double theta_clust;
+    double e_scat;
+    double p_scat;
+    double theta_scat;
+    bool good;
+    double T;
+    */
+
     ClassDef(QFS,0)
   };
 }
diff --git a/NPSimulation/Process/BeamReaction.cc b/NPSimulation/Process/BeamReaction.cc
index 5a94c3020a0e63b004ac278a9c5469f4e5780139..07f42fcf5a43f69cea71093467eedfa6b5a1896a 100644
--- a/NPSimulation/Process/BeamReaction.cc
+++ b/NPSimulation/Process/BeamReaction.cc
@@ -58,19 +58,37 @@ void NPS::BeamReaction::AttachReactionConditions() {
 ////////////////////////////////////////////////////////////////////////////////
 void NPS::BeamReaction::ReadConfiguration() {
   NPL::InputParser input(NPOptionManager::getInstance()->GetReactionFile());
-  m_Reaction.ReadConfigurationFile(input);
-  m_BeamName = NPL::ChangeNameToG4Standard(m_Reaction.GetNucleus1()->GetName());
-
-  if (m_Reaction.GetNucleus3()->GetName() != "") {
-    m_active             = true;
-    m_ReactionConditions = new TReactionConditions();
-    AttachReactionConditions();
-    if (!RootOutput::getInstance()->GetTree()->FindBranch("ReactionConditions"))
-      RootOutput::getInstance()->GetTree()->Branch(
-          "ReactionConditions", "TReactionConditions", &m_ReactionConditions);
-
-  } else {
-    m_active = false;
+
+  //vector<NPL::InputBlock*> blocks;
+  //blocks = input.GetAllBlocksWithToken("TwoBodyReaction");
+  //if(blocks.size()>0) m_ReactionType ="TwoBodyReaction";
+  //
+  //blocks = input.GetAllBlocksWithToken("QFSReaction");
+  //if(blocks.size()>0) m_ReactionType ="QFSReaction";
+
+  if(input.GetAllBlocksWithToken("TwoBodyReaction").size()>0) m_ReactionType ="TwoBodyReaction";
+  if(input.GetAllBlocksWithToken("QFSReaction").size()>0) m_ReactionType ="QFSReaction";
+
+
+  if (m_ReactionType=="TwoBodyReaction" ) {
+      m_Reaction.ReadConfigurationFile(input);
+      m_BeamName = NPL::ChangeNameToG4Standard(m_Reaction.GetNucleus1()->GetName());
+      if(m_Reaction.GetNucleus3()->GetName() != ""){
+          m_active             = true;
+          m_ReactionConditions = new TReactionConditions();
+          AttachReactionConditions();
+          if (!RootOutput::getInstance()->GetTree()->FindBranch("ReactionConditions"))
+              RootOutput::getInstance()->GetTree()->Branch(
+                      "ReactionConditions", "TReactionConditions", &m_ReactionConditions);
+      }
+  } else  if (m_ReactionType=="QFSReaction") {
+      m_QFS.ReadConfigurationFile(input);
+      m_BeamName = NPL::ChangeNameToG4Standard(m_QFS.GetNucleusA()->GetName());
+      m_active             = true;
+      m_ReactionConditions = new TReactionConditions();
+  }
+  else {
+      m_active = false;
   }
 }
 
@@ -90,6 +108,8 @@ NPS::BeamReaction::IsApplicable(const G4ParticleDefinition& particleType) {
 
 ////////////////////////////////////////////////////////////////////////////////
 G4bool NPS::BeamReaction::ModelTrigger(const G4FastTrack& fastTrack) {
+
+  //cout<< "MODEL TRIG"<<endl;
   static bool    shoot        = false;
   static double  rand         = 0;
   const G4Track* PrimaryTrack = fastTrack.GetPrimaryTrack();
@@ -103,9 +123,13 @@ G4bool NPS::BeamReaction::ModelTrigger(const G4FastTrack& fastTrack) {
   double out   = solid->DistanceToOut(P, -V);
   double ratio = in / (out + in);
 
+  //cout<< "in:"<<in<<std::scientific<<endl;
+  //cout<< "ou:"<<out<<std::scientific<<endl;
+  //cout<< "ratio:"<<ratio<<std::scientific<<endl;
   // m_StepSize = m_StepSize/100000.;
 
   if (out == 0) { // first step of current event
+    //cout<< "FIRST"<<endl;
     rand             = G4RandFlat::shoot();
     m_PreviousLength = m_StepSize;
     m_PreviousEnergy = PrimaryTrack->GetKineticEnergy();
@@ -113,21 +137,35 @@ G4bool NPS::BeamReaction::ModelTrigger(const G4FastTrack& fastTrack) {
     m_ReactionConditions->Clear();
     shoot = true;
   }
-
-  else if (in == 0) { // last step
+  else if ((in-m_StepSize) <= 1E-9) { // last step
+    //cout<< "LAST"<<endl;
     return true;
   }
 
+  //cout.precision(17); 
+  //cout<< "rand:"<<rand<<std::scientific<<endl;
+
   // If the condition is met, the event is generated
   if (ratio < rand) {
+
     // Reset the static for next event
     //  shoot = false;
-    if (shoot && m_Reaction.IsAllowed(PrimaryTrack->GetKineticEnergy())) {
-      shoot = false;
-      return true;
-
-    } else {
-      return false;
+    if(m_ReactionType=="QFSReaction"){
+        if ( shoot && m_QFS.IsAllowed() ) {
+            shoot = false;
+            return true;
+        } else {
+            return false;
+        }
+    }else if(m_ReactionType=="TwoBodyReaction"){
+        if ( shoot && m_Reaction.IsAllowed(PrimaryTrack->GetKineticEnergy()) ) {
+            shoot = false;
+            return true;
+        } else {
+            return false;
+        }
+    }else{
+        return false;
     }
   }
 
@@ -135,6 +173,7 @@ G4bool NPS::BeamReaction::ModelTrigger(const G4FastTrack& fastTrack) {
   // so it can be used in the next one
   if (!PrimaryTrack->GetStep()->IsLastStepInVolume()) {
     m_PreviousLength = PrimaryTrack->GetStep()->GetStepLength();
+    //cout<< "PreviousLength="<<m_PreviousLength<<endl;
     m_PreviousEnergy = PrimaryTrack->GetKineticEnergy();
   }
 
@@ -143,207 +182,337 @@ G4bool NPS::BeamReaction::ModelTrigger(const G4FastTrack& fastTrack) {
 
 ////////////////////////////////////////////////////////////////////////////////
 void NPS::BeamReaction::DoIt(const G4FastTrack& fastTrack,
-                             G4FastStep&        fastStep) {
-
-  // Get the track info
-  const G4Track* PrimaryTrack = fastTrack.GetPrimaryTrack();
-  G4ThreeVector  pdirection   = PrimaryTrack->GetMomentum().unit();
-  G4ThreeVector  localdir     = fastTrack.GetPrimaryTrackLocalDirection();
-
-  G4ThreeVector worldPosition = PrimaryTrack->GetPosition();
-  G4ThreeVector localPosition = fastTrack.GetPrimaryTrackLocalPosition();
-
-  double energy = PrimaryTrack->GetKineticEnergy();
-  double time   = PrimaryTrack->GetGlobalTime();
-
-  // Randomize within the step
-  // Assume energy loss is linear within the step
-  // Assume no scattering
-  double rand   = G4RandFlat::shoot();
-  double length = rand * (m_PreviousLength);
-  energy -= (1 - rand) * (m_PreviousEnergy - energy);
-  G4ThreeVector ldir = pdirection;
-  ldir *= length;
-  localPosition = localPosition - ldir;
-  // Set the end of the step conditions
-  fastStep.SetPrimaryTrackFinalKineticEnergyAndDirection(0, pdirection);
-  fastStep.SetPrimaryTrackFinalPosition(worldPosition);
-  fastStep.SetTotalEnergyDeposited(0);
-  fastStep.SetPrimaryTrackFinalTime(time);
-  fastStep.KillPrimaryTrack();
-  fastStep.SetPrimaryTrackPathLength(0.0);
-
-  /////////////////////////////////////////////////
-  //////Define the kind of particle to shoot////////
-  //////////////////////////////////////////////////
-
-  // Nucleus 3
-  int                LightZ = m_Reaction.GetNucleus3()->GetZ();
-  int                LightA = m_Reaction.GetNucleus3()->GetA();
-  static G4IonTable* IonTable
-      = G4ParticleTable::GetParticleTable()->GetIonTable();
-
-  G4ParticleDefinition* LightName;
-
-  if (LightZ == 0 && LightA == 1) // neutron is special case
-  {
-    LightName = G4Neutron::Definition();
-  } else {
-    if (m_Reaction.GetUseExInGeant4())
-      LightName
-          = IonTable->GetIon(LightZ, LightA, m_Reaction.GetExcitation3() * MeV);
-    else
-      LightName = IonTable->GetIon(LightZ, LightA);
-  }
+        G4FastStep&        fastStep) {
+
+    // Get the track info
+    const G4Track* PrimaryTrack = fastTrack.GetPrimaryTrack();
+    G4ThreeVector  pdirection   = PrimaryTrack->GetMomentum().unit();
+    G4ThreeVector  localdir     = fastTrack.GetPrimaryTrackLocalDirection();
+
+    G4ThreeVector worldPosition = PrimaryTrack->GetPosition();
+    G4ThreeVector localPosition = fastTrack.GetPrimaryTrackLocalPosition();
+
+    double energy = PrimaryTrack->GetKineticEnergy();
+    double time   = PrimaryTrack->GetGlobalTime();
+
+    // Randomize within the step
+    // Assume energy loss is linear within the step
+    // Assume no scattering
+    double rand   = G4RandFlat::shoot();
+    double length = rand * (m_PreviousLength);
+    energy -= (1 - rand) * (m_PreviousEnergy - energy);
+    G4ThreeVector ldir = pdirection;
+    ldir *= length;
+    localPosition = localPosition - ldir;
+    // Set the end of the step conditions
+    fastStep.SetPrimaryTrackFinalKineticEnergyAndDirection(0, pdirection);
+    fastStep.SetPrimaryTrackFinalPosition(worldPosition);
+    fastStep.SetTotalEnergyDeposited(0);
+    fastStep.SetPrimaryTrackFinalTime(time);
+    fastStep.KillPrimaryTrack();
+    fastStep.SetPrimaryTrackPathLength(0.0);
+
+
+    if (m_ReactionType=="TwoBodyReaction" ) {
+
+        ///////////////////////////////
+        // Two-Body Reaction Case /////
+        ///////////////////////////////
+
+        //////Define the kind of particle to shoot////////
+        // Nucleus 3
+        int LightZ = m_Reaction.GetNucleus3()->GetZ();
+        int LightA = m_Reaction.GetNucleus3()->GetA();
+        static G4IonTable* IonTable
+            = G4ParticleTable::GetParticleTable()->GetIonTable();
+
+        G4ParticleDefinition* LightName;
+
+        if (LightZ == 0 && LightA == 1) // neutron is special case
+        {
+            LightName = G4Neutron::Definition();
+        } else {
+            if (m_Reaction.GetUseExInGeant4())
+                LightName
+                    = IonTable->GetIon(LightZ, LightA, m_Reaction.GetExcitation3() * MeV);
+            else
+                LightName = IonTable->GetIon(LightZ, LightA);
+        }
+
+        // Nucleus 4
+        G4int HeavyZ = m_Reaction.GetNucleus4()->GetZ();
+        G4int HeavyA = m_Reaction.GetNucleus4()->GetA();
+
+        // Generate the excitation energy if a distribution is given
+        m_Reaction.ShootRandomExcitationEnergy();
+
+        // Use to clean up the IonTable in case of the Ex changing at every event
+        G4ParticleDefinition* HeavyName;
+
+        if (m_Reaction.GetUseExInGeant4())
+            HeavyName
+                = IonTable->GetIon(HeavyZ, HeavyA, m_Reaction.GetExcitation4() * MeV);
+        else
+            HeavyName = IonTable->GetIon(HeavyZ, HeavyA);
+
+        // Set the Energy of the reaction
+        m_Reaction.SetBeamEnergy(energy);
+
+        double Beam_theta = pdirection.theta();
+        double Beam_phi   = pdirection.phi();
+
+        ///////////////////////////
+        ///// Beam Parameters /////
+        ///////////////////////////
+        m_ReactionConditions->SetBeamParticleName(
+                PrimaryTrack->GetParticleDefinition()->GetParticleName());
+
+        m_ReactionConditions->SetBeamReactionEnergy(energy);
+        m_ReactionConditions->SetVertexPositionX(localPosition.x());
+        m_ReactionConditions->SetVertexPositionY(localPosition.y());
+        m_ReactionConditions->SetVertexPositionZ(localPosition.z());
+
+        G4ThreeVector U(1, 0, 0);
+        G4ThreeVector V(0, 1, 0);
+        G4ThreeVector ZZ(0, 0, 1);
+        m_ReactionConditions->SetBeamEmittanceTheta(
+                PrimaryTrack->GetMomentumDirection().theta() / deg);
+        m_ReactionConditions->SetBeamEmittancePhi(
+                PrimaryTrack->GetMomentumDirection().phi() / deg);
+        m_ReactionConditions->SetBeamEmittanceThetaX(
+                PrimaryTrack->GetMomentumDirection().angle(U) / deg);
+        m_ReactionConditions->SetBeamEmittancePhiY(
+                PrimaryTrack->GetMomentumDirection().angle(V) / deg);
+
+        //////////////////////////////////////////////////////////
+        ///// Build rotation matrix to go from the incident //////
+        ///// beam frame to the "world" frame               //////
+        //////////////////////////////////////////////////////////
+
+        
+        //   G4ThreeVector col1(cos(Beam_theta) * cos(Beam_phi),
+        //   cos(Beam_theta) * sin(Beam_phi),
+        //   -sin(Beam_theta));
+        //   G4ThreeVector col2(-sin(Beam_phi),
+        //   cos(Beam_phi),
+        //   0);
+        //   G4ThreeVector col3(sin(Beam_theta) * cos(Beam_phi),
+        //   sin(Beam_theta) * sin(Beam_phi),
+        //   cos(Beam_theta));
+        //   G4RotationMatrix BeamToWorld(col1, col2, col3);
+
+        /////////////////////////////////////////////////////////////////
+        ///// Angles for emitted particles following Cross Section //////
+        ///// Angles are in the beam frame                         //////
+        /////////////////////////////////////////////////////////////////
+
+        // Angles
+        // Shoot and Set a Random ThetaCM
+        m_Reaction.ShootRandomThetaCM();
+        double phi = RandFlat::shoot() * 2. * pi;
+
+        //////////////////////////////////////////////////
+        /////  Momentum and angles from  kinematics  /////
+        /////  Angles are in the beam frame          /////
+        //////////////////////////////////////////////////
+        // Variable where to store results
+        double Theta3, Energy3, Theta4, Energy4;
+
+        // Compute Kinematic using previously defined ThetaCM
+        m_Reaction.KineRelativistic(Theta3, Energy3, Theta4, Energy4);
+        // Momentum in beam frame for light particle
+        G4ThreeVector momentum_kine3_beam(sin(Theta3) * cos(phi),
+                sin(Theta3) * sin(phi), cos(Theta3));
+        // Momentum in World frame //to go from the incident beam frame to the "world"
+        // frame
+        G4ThreeVector momentum_kine3_world = momentum_kine3_beam;
+        momentum_kine3_world.rotate(Beam_theta,
+                V); // rotation of Beam_theta on Y axis
+        momentum_kine3_world.rotate(Beam_phi, ZZ); // rotation of Beam_phi on Z axis
+
+        // Momentum in beam frame for heavy particle
+        G4ThreeVector momentum_kine4_beam(sin(Theta4) * cos(phi + pi),
+                sin(Theta4) * sin(phi + pi), cos(Theta4));
+        // Momentum in World frame
+        G4ThreeVector momentum_kine4_world = momentum_kine4_beam;
+        momentum_kine4_world.rotate(Beam_theta,
+                V); // rotation of Beam_theta on Y axis
+        momentum_kine4_world.rotate(Beam_phi, ZZ); // rotation of Beam_phi on Z axis
+
+        // Emitt secondary
+        if (m_Reaction.GetShoot3()) {
+            G4DynamicParticle particle3(LightName, momentum_kine3_world, Energy3);
+            fastStep.CreateSecondaryTrack(particle3, localPosition, time);
+        }
+
+        if (m_Reaction.GetShoot4()) {
+            G4DynamicParticle particle4(HeavyName, momentum_kine4_world, Energy4);
+            fastStep.CreateSecondaryTrack(particle4, localPosition, time);
+        }
+
+        // Reinit for next event
+        m_PreviousEnergy = 0;
+        m_PreviousLength = 0;
+
+        ///////////////////////////////////////
+        ///// Emitted particle Parameters /////
+        ///////////////////////////////////////
+        // Names 3 and 4//
+        m_ReactionConditions->SetParticleName(LightName->GetParticleName());
+        m_ReactionConditions->SetParticleName(HeavyName->GetParticleName());
+        // Angle 3 and 4 //
+        m_ReactionConditions->SetTheta(Theta3 / deg);
+        m_ReactionConditions->SetTheta(Theta4 / deg);
+
+        m_ReactionConditions->SetPhi(phi / deg);
+        if ((phi + pi) / deg > 360)
+            m_ReactionConditions->SetPhi((phi - pi) / deg);
+        else
+            m_ReactionConditions->SetPhi((phi + pi) / deg);
+
+        // Energy 3 and 4 //
+        m_ReactionConditions->SetKineticEnergy(Energy3);
+        m_ReactionConditions->SetKineticEnergy(Energy4);
+        // ThetaCM and Ex//
+        m_ReactionConditions->SetThetaCM(m_Reaction.GetThetaCM() / deg);
+        m_ReactionConditions->SetExcitationEnergy3(m_Reaction.GetExcitation3());
+        m_ReactionConditions->SetExcitationEnergy4(m_Reaction.GetExcitation4());
+        // Momuntum X 3 and 4 //
+        m_ReactionConditions->SetMomentumDirectionX(momentum_kine3_world.x());
+        m_ReactionConditions->SetMomentumDirectionX(momentum_kine4_world.x());
+        // Momuntum Y 3 and 4 //
+        m_ReactionConditions->SetMomentumDirectionY(momentum_kine3_world.y());
+        m_ReactionConditions->SetMomentumDirectionY(momentum_kine4_world.y());
+        // Momuntum Z 3 and 4 //
+        m_ReactionConditions->SetMomentumDirectionZ(momentum_kine3_world.z());
+        m_ReactionConditions->SetMomentumDirectionZ(momentum_kine4_world.z());
+
+    }// end if TwoBodyReaction
+
+    else if (m_ReactionType=="QFSReaction" ) {
+
+        //////Define the kind of particle to shoot////////
+        //    A --> T  ==> B + (c -> T) =>  B + 1 + 2      
+           
+        int Light1_Z = m_QFS.GetNucleus1()->GetZ();
+        int Light1_A = m_QFS.GetNucleus1()->GetA();
+        int Light2_Z = m_QFS.GetNucleus2()->GetZ();
+        int Light2_A = m_QFS.GetNucleus2()->GetA();
+
+        static G4IonTable* IonTable
+            = G4ParticleTable::GetParticleTable()->GetIonTable();
+
+        G4ParticleDefinition* Light1Name;
+        G4ParticleDefinition* Light2Name;
+
+        if (Light1_Z == 0 && Light1_A == 1) // neutron is special case
+        {
+            Light1Name = G4Neutron::Definition();
+        } else {
+            Light1Name = IonTable->GetIon(Light1_Z, Light1_A);
+        }
+
+        if (Light2_Z == 0 && Light2_A == 1) // neutron is special case
+        {
+            Light2Name = G4Neutron::Definition();
+        } else {
+            Light2Name = IonTable->GetIon(Light2_Z, Light2_A);
+        }
+
+        // Nucleus B
+        G4int Heavy_Z = m_QFS.GetNucleusB()->GetZ();
+        G4int Heavy_A = m_QFS.GetNucleusB()->GetA();
+
+        G4ParticleDefinition* HeavyName;
+        HeavyName = IonTable->GetIon(Heavy_Z, Heavy_A);
+
+        // Set the Energy of the reaction
+        m_QFS.SetBeamEnergy(energy);
+
+        double Beam_theta = pdirection.theta();
+        double Beam_phi   = pdirection.phi();
+
+
+        /////////////////////////////////////////////////////////////////
+        ///// Angles for emitted particles following Cross Section //////
+        ///// Angles are in the beam frame                         //////
+        /////////////////////////////////////////////////////////////////
+
+        // Angles
+        // Shoot and Set a Random ThetaCM
+        //m_QFS.ShootRandomThetaCM();
+        //m_QFS.ShootRandomPhiCM();
+        double theta = RandFlat::shoot() *  pi;
+        double phi = RandFlat::shoot() * 2. * pi;
+
+        m_QFS.SetThetaCM(theta);
+        m_QFS.SetPhiCM(phi);
+
+        //////////////////////////////////////////////////
+        /////  Momentum and angles from  kinematics  /////
+        //////////////////////////////////////////////////
+        // Variable where to store results
+        double Theta1, Phi1, Energy1, Theta2, Phi2, Energy2;
+
+        // Compute Kinematic using previously defined ThetaCM
+        m_QFS.KineRelativistic(Theta1, Phi1, Energy1, Theta2, Phi2, Energy2);
+
+        G4ThreeVector U(1, 0, 0);
+        G4ThreeVector V(0, 1, 0);
+        G4ThreeVector ZZ(0, 0, 1);
+
+        // Momentum in beam and world frame for light particle 1
+        G4ThreeVector momentum_kine1_beam(sin(Theta1) * cos(Phi1),
+                sin(Theta1) * sin(Phi1), cos(Theta1));
+        G4ThreeVector momentum_kine1_world = momentum_kine1_beam;
+        momentum_kine1_world.rotate(Beam_theta, V); // rotation of Beam_theta on Y axis
+        momentum_kine1_world.rotate(Beam_phi, ZZ); // rotation of Beam_phi on Z axis
+
+       // Momentum in beam and world frame for light particle 2
+        G4ThreeVector momentum_kine2_beam(sin(Theta2) * cos(Phi2),
+                sin(Theta2) * sin(Phi2), cos(Theta2));
+        G4ThreeVector momentum_kine2_world = momentum_kine2_beam;
+        momentum_kine2_world.rotate(Beam_theta, V); // rotation of Beam_theta on Y axis
+        momentum_kine2_world.rotate(Beam_phi, ZZ); // rotation of Beam_phi on Z axis
+
+        // Momentum in beam and world frame for heavy residual
+        //
+        //G4ThreeVector momentum_kineB_beam(sin(ThetaB) * cos(PhiB + pi),
+        //        sin(ThetaB) * sin(PhiB + pi), cos(ThetaB));
+        //G4ThreeVector momentum_kineB_world =  momentum_kineB_beam;
+        //momentum_kineB_world.rotate(Beam_theta, V); // rotation of Beam_theta on Y axis
+        //momentum_kineB_world.rotate(Beam_phi, ZZ); // rotation of Beam_phi on Z axis
+        
+        TLorentzVector* P_B = m_QFS.GetEnergyImpulsionLab_B();
+        
+        G4ThreeVector momentum_kineB_beam( P_B->Px(), P_B->Py(), P_B->Pz() );
+        momentum_kineB_beam = momentum_kineB_beam.unit();
+        double EnergyB = m_QFS.GetEnergyImpulsionLab_B()->Energy();
+        G4ThreeVector momentum_kineB_world =  momentum_kineB_beam;
+        momentum_kineB_world.rotate(Beam_theta, V); // rotation of Beam_theta on Y axis
+        momentum_kineB_world.rotate(Beam_phi, ZZ); // rotation of Beam_phi on Z axis
   
-  // Nucleus 4
-  G4int HeavyZ = m_Reaction.GetNucleus4()->GetZ();
-  G4int HeavyA = m_Reaction.GetNucleus4()->GetA();
-
-  // Generate the excitation energy if a distribution is given
-  m_Reaction.ShootRandomExcitationEnergy();
-
-  // Use to clean up the IonTable in case of the Ex changing at every event
-  G4ParticleDefinition* HeavyName;
-
-  if (m_Reaction.GetUseExInGeant4())
-    HeavyName
-        = IonTable->GetIon(HeavyZ, HeavyA, m_Reaction.GetExcitation4() * MeV);
-  else
-    HeavyName = IonTable->GetIon(HeavyZ, HeavyA);
-
-  // Set the Energy of the reaction
-  m_Reaction.SetBeamEnergy(energy);
-
-  double Beam_theta = pdirection.theta();
-  double Beam_phi   = pdirection.phi();
-
-  ///////////////////////////
-  ///// Beam Parameters /////
-  ///////////////////////////
-  m_ReactionConditions->SetBeamParticleName(
-      PrimaryTrack->GetParticleDefinition()->GetParticleName());
-
-  m_ReactionConditions->SetBeamReactionEnergy(energy);
-  m_ReactionConditions->SetVertexPositionX(localPosition.x());
-  m_ReactionConditions->SetVertexPositionY(localPosition.y());
-  m_ReactionConditions->SetVertexPositionZ(localPosition.z());
-
-  G4ThreeVector U(1, 0, 0);
-  G4ThreeVector V(0, 1, 0);
-  G4ThreeVector ZZ(0, 0, 1);
-  m_ReactionConditions->SetBeamEmittanceTheta(
-      PrimaryTrack->GetMomentumDirection().theta() / deg);
-  m_ReactionConditions->SetBeamEmittancePhi(
-      PrimaryTrack->GetMomentumDirection().phi() / deg);
-  m_ReactionConditions->SetBeamEmittanceThetaX(
-      PrimaryTrack->GetMomentumDirection().angle(U) / deg);
-  m_ReactionConditions->SetBeamEmittancePhiY(
-      PrimaryTrack->GetMomentumDirection().angle(V) / deg);
- 
-  //////////////////////////////////////////////////////////
-  ///// Build rotation matrix to go from the incident //////
-  ///// beam frame to the "world" frame               //////
-  //////////////////////////////////////////////////////////
-
-  /*
-
-  G4ThreeVector col1(cos(Beam_theta) * cos(Beam_phi),
-                     cos(Beam_theta) * sin(Beam_phi),
-                     -sin(Beam_theta));
-  G4ThreeVector col2(-sin(Beam_phi),
-                     cos(Beam_phi),
-                     0);
-  G4ThreeVector col3(sin(Beam_theta) * cos(Beam_phi),
-                     sin(Beam_theta) * sin(Beam_phi),
-                     cos(Beam_theta));
-  G4RotationMatrix BeamToWorld(col1, col2, col3);
-
-  */
-
-  /////////////////////////////////////////////////////////////////
-  ///// Angles for emitted particles following Cross Section //////
-  ///// Angles are in the beam frame                         //////
-  /////////////////////////////////////////////////////////////////
-
-  // Angles
-  // Shoot and Set a Random ThetaCM
-  m_Reaction.ShootRandomThetaCM();
-  double phi = RandFlat::shoot() * 2. * pi;
-
-  //////////////////////////////////////////////////
-  /////  Momentum and angles from  kinematics  /////
-  /////  Angles are in the beam frame          /////
-  //////////////////////////////////////////////////
-  // Variable where to store results
-  double Theta3, Energy3, Theta4, Energy4;
-
-  // Compute Kinematic using previously defined ThetaCM
-  m_Reaction.KineRelativistic(Theta3, Energy3, Theta4, Energy4);
-  // Momentum in beam frame for light particle
-  G4ThreeVector momentum_kine3_beam(sin(Theta3) * cos(phi),
-                                    sin(Theta3) * sin(phi), cos(Theta3));
-  // Momentum in World frame //to go from the incident beam frame to the "world"
-  // frame
-  G4ThreeVector momentum_kine3_world = /*BeamToWorld */ momentum_kine3_beam;
-  momentum_kine3_world.rotate(Beam_theta,
-                              V); // rotation of Beam_theta on Y axis
-  momentum_kine3_world.rotate(Beam_phi, ZZ); // rotation of Beam_phi on Z axis
-
-  // Momentum in beam frame for heavy particle
-  G4ThreeVector momentum_kine4_beam(sin(Theta4) * cos(phi + pi),
-                                    sin(Theta4) * sin(phi + pi), cos(Theta4));
-  // Momentum in World frame
-  G4ThreeVector momentum_kine4_world = /*BeamToWorld */ momentum_kine4_beam;
-  momentum_kine4_world.rotate(Beam_theta,
-                              V); // rotation of Beam_theta on Y axis
-  momentum_kine4_world.rotate(Beam_phi, ZZ); // rotation of Beam_phi on Z axis
-
-  // Emitt secondary
-  if (m_Reaction.GetShoot3()) {
-    G4DynamicParticle particle3(LightName, momentum_kine3_world, Energy3);
-    fastStep.CreateSecondaryTrack(particle3, localPosition, time);
-  }
+        // Emitt secondary
+        if (m_QFS.GetShoot1()) {
+            G4DynamicParticle particle1(Light1Name, momentum_kine1_world, Energy1);
+            fastStep.CreateSecondaryTrack(particle1, localPosition, time);
+        }
 
-  if (m_Reaction.GetShoot4()) {
-    G4DynamicParticle particle4(HeavyName, momentum_kine4_world, Energy4);
-    fastStep.CreateSecondaryTrack(particle4, localPosition, time);
-  }
+        if (m_QFS.GetShoot2()) {
+            G4DynamicParticle particle2(Light2Name, momentum_kine2_world, Energy2);
+            fastStep.CreateSecondaryTrack(particle2, localPosition, time);
+        }
+        if (m_QFS.GetShootB()) {
+            G4DynamicParticle particleB(HeavyName, momentum_kineB_world, EnergyB);
+            fastStep.CreateSecondaryTrack(particleB, localPosition, time);
+        }
 
-  // Reinit for next event
-  m_PreviousEnergy = 0;
-  m_PreviousLength = 0;
 
-  ///////////////////////////////////////
-  ///// Emitted particle Parameters /////
-  ///////////////////////////////////////
-  // Names 3 and 4//
-  m_ReactionConditions->SetParticleName(LightName->GetParticleName());
-  m_ReactionConditions->SetParticleName(HeavyName->GetParticleName());
-  // Angle 3 and 4 //
-  m_ReactionConditions->SetTheta(Theta3 / deg);
-  m_ReactionConditions->SetTheta(Theta4 / deg);
-
-  m_ReactionConditions->SetPhi(phi / deg);
-  if ((phi + pi) / deg > 360)
-    m_ReactionConditions->SetPhi((phi - pi) / deg);
-  else
-    m_ReactionConditions->SetPhi((phi + pi) / deg);
-
-  // Energy 3 and 4 //
-  m_ReactionConditions->SetKineticEnergy(Energy3);
-  m_ReactionConditions->SetKineticEnergy(Energy4);
-  // ThetaCM and Ex//
-  m_ReactionConditions->SetThetaCM(m_Reaction.GetThetaCM() / deg);
-  m_ReactionConditions->SetExcitationEnergy3(m_Reaction.GetExcitation3());
-  m_ReactionConditions->SetExcitationEnergy4(m_Reaction.GetExcitation4());
-  // Momuntum X 3 and 4 //
-  m_ReactionConditions->SetMomentumDirectionX(momentum_kine3_world.x());
-  m_ReactionConditions->SetMomentumDirectionX(momentum_kine4_world.x());
-  // Momuntum Y 3 and 4 //
-  m_ReactionConditions->SetMomentumDirectionY(momentum_kine3_world.y());
-  m_ReactionConditions->SetMomentumDirectionY(momentum_kine4_world.y());
-  // Momuntum Z 3 and 4 //
-  m_ReactionConditions->SetMomentumDirectionZ(momentum_kine3_world.z());
-  m_ReactionConditions->SetMomentumDirectionZ(momentum_kine4_world.z());
+        // Reinit for next event
+        m_PreviousEnergy = 0;
+        m_PreviousLength = 0;
+
+
+
+    }
 }
diff --git a/NPSimulation/Process/BeamReaction.hh b/NPSimulation/Process/BeamReaction.hh
index cb81602f18eb28cde9f4fcbd6af5d146f307e288..b77c424d8885112d5152c7b1f2bf32b37999e16d 100644
--- a/NPSimulation/Process/BeamReaction.hh
+++ b/NPSimulation/Process/BeamReaction.hh
@@ -27,6 +27,7 @@
 #include "G4VFastSimulationModel.hh"
 #include "PhysicsList.hh"
 #include "NPReaction.h"
+#include "NPQFS.h"
 #include "TReactionConditions.h"
 class G4VPhysicalVolume;
 namespace NPS{
@@ -44,7 +45,9 @@ namespace NPS{
  
     private:
       NPL::Reaction m_Reaction;
+      NPL::QFS m_QFS;
       string m_BeamName;
+      string m_ReactionType;
       double m_PreviousEnergy;
       double m_PreviousLength;
       bool   m_active;// is the process active