Skip to content
Snippets Groups Projects
Analysis.cxx 15.4 KiB
Newer Older
/*****************************************************************************
 * Copyright (C) 2009-2014    this file is part of the NPTool Project        *
 *                                                                           *
 * For the licensing terms see $NPTOOL/Licence/NPTool_Licence                *
 * For the list of contributors see $NPTOOL/Licence/Contributors             *
 *****************************************************************************/

/*****************************************************************************
 * Original Author: Adrien MATTA  contact address: a.matta@surrey.ac.uk      *
 *                                                                           *
Adrien Matta's avatar
Adrien Matta committed
 * Creation Date  : july  2020                                               *
 * Last update    :                                                          *
 *---------------------------------------------------------------------------*
 * Decription:                                                               *
 * Class describing the property of an Analysis object                       *
 *                                                                           *
 *---------------------------------------------------------------------------*
 * Comment:                                                                  *
 *                                                                           *
 *                                                                           *
 *****************************************************************************/
#include <iostream>
using namespace std;
#include "Analysis.h"
#include "NPAnalysisFactory.h"
#include "NPDetectorManager.h"
#include "NPFunction.h"
#include "NPOptionManager.h"
#include "NPPhysicalConstants.h"
#include "NPTrackingUtility.h"
#include "TRandom3.h"
////////////////////////////////////////////////////////////////////////////////
Analysis::Analysis() {}
////////////////////////////////////////////////////////////////////////////////
Analysis::~Analysis() {}

////////////////////////////////////////////////////////////////////////////////
void Analysis::Init() {
  IC = new TInitialConditions;
  DC = new TInteractionCoordinates;
  RC = new TReactionConditions;

  InitOutputBranch();
  InitInputBranch();

  Strasse = (TStrassePhysics*)m_DetectorManager->GetDetector("Strasse");
  //  Catana = (TCatanaPhysics*)  m_DetectorManager -> GetDetector("Catana");
  // reaction properties
  m_QFS = new NPL::QFS();
  m_QFS->ReadConfigurationFile(NPOptionManager::getInstance()->GetReactionFile());
  // reaction properties
  myBeam = new NPL::Beam();
  myBeam->ReadConfigurationFile(NPOptionManager::getInstance()->GetReactionFile());
  InitialBeamEnergy = myBeam->GetEnergy() /* * myBeam->GetA()*/;
  // target thickness
  //  TargetThickness = m_DetectorManager->GetTargetThickness();
  //  string TargetMaterial = m_DetectorManager->GetTargetMaterial();
  TargetThickness = 150 * mm;
  string TargetMaterial = "LH2";
  // EnergyLoss Tables
  string BeamName = NPL::ChangeNameToG4Standard(myBeam->GetName());
  BeamTarget = NPL::EnergyLoss(BeamName + "_" + TargetMaterial + ".G4table", "G4Table", 100);
  protonTarget = NPL::EnergyLoss("proton_" + TargetMaterial + ".G4table", "G4Table", 100);
  protonAl = NPL::EnergyLoss("proton_Al.G4table", "G4Table", 100);
  protonSi = NPL::EnergyLoss("proton_Si.G4table", "G4Table", 100);
  LV_T.SetVectM(TVector3(0, 0, 0), NPUNITS::proton_mass_c2);
  rand = new TRandom3();
}

////////////////////////////////////////////////////////////////////////////////
void Analysis::TreatEvent() {
  // Reinitiate calculated variable
  ReInitValue();
  bool perfectBeamEnergy = false;
  bool perfectBeamTracking = false;
  bool perfectProtonTracking = false;
  bool perfectProtonEnergy = false;
  bool CATANAEnergyReco = false;
  unsigned int size = Strasse->GetEventMultiplicity();
  if (size == 2) { // 2 proton detected

    ////////////////////////////////////////////////
    ////////////Protons (E,P) Reconstruction ///////
    ////////////////////////////////////////////////
    // Proton 1
    TVector3 InnerPos1 = Strasse->GetInnerPositionOfInteraction(0);
    TVector3 OuterPos1 = Strasse->GetOuterPositionOfInteraction(0);
    TVector3 Proton1 = OuterPos1 - InnerPos1;
    Proton1 = Proton1.Unit();
    // Proton 2
    TVector3 InnerPos2 = Strasse->GetInnerPositionOfInteraction(1);
    TVector3 OuterPos2 = Strasse->GetOuterPositionOfInteraction(1);
    TVector3 Proton2 = OuterPos2 - InnerPos2;
    Proton2 = Proton2.Unit();
    deltaPhi = abs(Proton1.Phi() / deg - Proton2.Phi() / deg);
    sumTheta = Proton1.Theta() / deg + Proton2.Theta() / deg;
    Theta12 = Proton1.Angle(Proton2) / deg;
    // computing minimum distance of the two lines
    TVector3 Vertex;
    Distance = NPL::MinimumDistanceTwoLines(InnerPos1, OuterPos1, InnerPos2, OuterPos2, Vertex, delta);
    VertexX = Vertex.X();
    VertexY = Vertex.Y();
    VertexZ = Vertex.Z();
    deltaX = delta.X();
    deltaY = delta.Y();
    deltaZ = delta.Z();

    if (perfectProtonTracking) {
      // From Reaction Conditions
      VertexX = RC->GetVertexPositionX();
      VertexY = RC->GetVertexPositionY();
      VertexZ = RC->GetVertexPositionZ();
      Proton2 = RC->GetParticleDirection(0).Unit();
      Proton1 = RC->GetParticleDirection(1).Unit();
      deltaX = 0;
      deltaY = 0;
      deltaZ = 0;
    if (perfectProtonEnergy) {
      E1 = RC->GetKineticEnergy(1);
      E2 = RC->GetKineticEnergy(0);
      // General CATANA resolution for proton (1.4 % FWHM)
      //  simply applied to E, crude approximation (no CATANA reco.)
      E1 = ApplyCATANAResoProton(RC->GetKineticEnergy(1));
      E2 = ApplyCATANAResoProton(RC->GetKineticEnergy(0));
    if (CATANAEnergyReco) {
      // if true, bypass previous proton energy calc. and use full CATANA Reco.
      ///////////
      // TO DO //
      ///////////
    double P1 = sqrt(E1 * (E1 + 2 * NPUNITS::proton_mass_c2));
    double P2 = sqrt(E2 * (E2 + 2 * NPUNITS::proton_mass_c2));

    ///////////////////////////////////////
    //////Beam (E,P) Reconstruction ///////
    ///////////////////////////////////////

    TVector3 BeamDirection;
    if (perfectBeamTracking)
      BeamDirection = RC->GetBeamDirection();
    else
      BeamDirection = TVector3(0, 0, 1);

    // Beam Energy at vertex
    TA = RC->GetBeamEnergy();
    if (perfectBeamEnergy) {
      TAcalc = TA;
    }
    else if (VertexZ > -100) {
      TAcalc = BeamTarget.Slow(InitialBeamEnergy, abs(VertexZ + 75), BeamDirection.Angle(TVector3(0, 0, 1)));
    }
    double beam_mom = sqrt(TAcalc * (TAcalc + 2 * m_QFS->GetParticleA()->Mass()));
    TVector3 PA = beam_mom * BeamDirection.Unit();

    ///////////////////////////////////
    ///// Angles Protons /  Beam //////
    ///////////////////////////////////
    Theta1 = Proton1.Angle(BeamDirection) / deg;
    Theta2 = Proton2.Angle(BeamDirection) / deg;

    //////////////////////////////////////////////
    ///// Missing mass using Lorentz Vector //////
    //////////////////////////////////////////////

    LV_A.SetVectM(PA, m_QFS->GetParticleA()->Mass());
    LV_p1.SetVectM(Proton1.Unit() * P1, NPUNITS::proton_mass_c2);
    LV_p2.SetVectM(Proton2.Unit() * P2, NPUNITS::proton_mass_c2);
    // computing Ex from Missing Mass
    LV_B = LV_A + LV_T - LV_p1 - LV_p2;
    // LV_B = RC->GetParticleMomentum(2);
    Ex = LV_B.M() - m_QFS->GetParticleB()->Mass();

  } // endif size==2
}

/*   ///////////////////////////////////
 *   //OLD Tentative CATANA treatment///
 *   ///////////////////////////////////
 *
    // Look for associated Catana event
    double d1,d2;
    unsigned int i1,i2;
    i1 = Catana->FindClosestHitToLine(InnerPos1,OuterPos1,d1);
    i2 = Catana->FindClosestHitToLine(InnerPos2,OuterPos2,d2);
cout<<"------------------------"<<endl;
cout<<"d1="<<d1<<endl;
cout<<"d2="<<d2<<endl;
cout<<"Catana mult="<<Catana->GetEventMultiplicity()<<endl;
    //if(i1!=i2){
    if(true){
      double TA = BeamTarget.Slow(InitialBeamEnergy,abs(VertexZ-75),RC->GetBeamDirection().Angle(TVector3(0,0,1)));
      ////////////////////////////////////
      // From Reaction Conditions
      double E1s = RC->GetKineticEnergy(0);
      double E2s = RC->GetKineticEnergy(1);
      TVector3 Proton1s=RC->GetParticleMomentum(0).Unit();
      TVector3 Proton2s=RC->GetParticleMomentum(1).Unit();
      // Matching the right energy with the right proton
      if((Proton1s-Proton1).Mag()<(Proton1s-Proton2).Mag()){
        E1=E1s;
        E2=E2s;
        alpha=Proton1s.Angle(Proton1)/deg;
        Theta1=Proton1.Theta();
        Phi1=Proton1.Phi();
        Theta2=Proton2.Theta();
        Phi2=Proton2.Phi();
        Theta1s=Proton1s.Theta();
        Phi1s=Proton1s.Phi();
        Theta2s=Proton2s.Theta();
        Phi2s=Proton2s.Phi();
        }
      else{
        E2=E1s;
        E1=E2s;
        alpha=Proton2s.Angle(Proton1)/deg;
        Theta1=Proton1.Theta()/deg;
        Phi1=Proton1.Phi()/deg;
        Theta2=Proton2.Theta()/deg;
        Phi2=Proton2.Phi()/deg;
        Theta1s=Proton2s.Theta()/deg;
        Phi1s=Proton2s.Phi()/deg;
        Theta2s=Proton1s.Theta()/deg;
        Phi2s=Proton1s.Phi()/deg;
        }
      // From detectors
      E1 = ReconstructProtonEnergy(Vertex,Proton1,Catana->Energy[i1]);
      E2 = ReconstructProtonEnergy(Vertex,Proton2,Catana->Energy[i2]);
      //E1 = Catana->Energy[i1];
      //E2 = Catana->Energy[i2];
      cout<<"------------------------"<<endl;
////////////////////////////////////////////////////////////////////////////////
double Analysis::ReconstructProtonEnergy(const TVector3& x0, const TVector3& dir, const double& Ecatana) {

  TVector3 Normal = TVector3(0, 1, 0);
  Normal.SetPhi(dir.Phi());
  double Theta = dir.Angle(Normal);
  // Catana Al housing
  double E = protonAl.EvaluateInitialEnergy(Ecatana, 0.5 * mm, Theta);
  cout << "Ecatana=" << Ecatana << endl;
  cout << "Erec0=" << E << endl;
  // Strasse Chamber
  // E = protonAl.EvaluateInitialEnergy(E,3*mm,Theta);
  // Outer Barrel
  E = protonSi.EvaluateInitialEnergy(E, 300 * micrometer, Theta);
  // Inner Barrel
  E = protonSi.EvaluateInitialEnergy(E, 200 * micrometer, Theta);
  // LH2 target
  static TVector3 x1;
  x1 = x0 + dir;
  TVector3 T1(0, 15, 0);
  TVector3 T2(0, 15, 1);
  T1.SetPhi(dir.Phi());
  T2.SetPhi(dir.Phi());
  //    double d = NPL::MinimumDistancePointLine(T1,T2,x0);
  double d = 0;

  cout << "d=" << d << endl;
  cout << "Theta=" << Theta << endl;
  E = protonTarget.EvaluateInitialEnergy(E, d, Theta);
  cout << "Erec=" << E << endl;
  return E;

  // return 0;
////////////////////////////////////////////////////////////////////////////////
double Analysis::ApplyCATANAResoProton(double Ein) {
  // Function applying overall CATANA crystal resolution
  // For protons (1.4% FWHM)
  double FWHM = 1.4 / 100 * Ein;
  double sigma = FWHM / 2.35;
  double Eout = rand->Gaus(Ein, sigma);
  return Eout;
}
////////////////////////////////////////////////////////////////////////////////
double Analysis::ApplyCATANAResoGamma(double Ein) {
  // Function applying overall CATANA crystal resolution
  // For gammas defined in smsimulator package
  double a = 0.686569;
  double b = 0.564352;
  // Ein from MeV to keV
  Ein = Ein * 1000;
  double SigmaE = a * pow(Ein, b);
  double Eout = rand->Gaus(Ein, SigmaE);
  return Eout / 1000.;
////////////////////////////////////////////////////////////////////////////////
TVector3 Analysis::InterpolateInPlaneZ(TVector3 V0, TVector3 V1, double Zproj) {
  TVector3 Vproj(-999, -999, -999);
  double t = (Zproj - V1.Z()) / (V1.Z() - V0.Z());
  double Xproj = V1.X() + (V1.X() - V0.X()) * t;
  double Yproj = V1.Y() + (V1.Y() - V0.Y()) * t;
  Vproj.SetXYZ(Xproj, Yproj, Zproj);
  return Vproj;
}
////////////////////////////////////////////////////////////////////////////////
void Analysis::End() {}
////////////////////////////////////////////////////////////////////////////////
void Analysis::InitOutputBranch() {
  RootOutput::getInstance()->GetTree()->Branch("Ex", &Ex, "Ex/D");
  RootOutput::getInstance()->GetTree()->Branch("E1", &E1, "E1/D");
  RootOutput::getInstance()->GetTree()->Branch("E2", &E2, "E2/D");
  RootOutput::getInstance()->GetTree()->Branch("Theta12", &Theta12, "Theta12/D");
  RootOutput::getInstance()->GetTree()->Branch("ThetaCM", &ThetaCM, "ThetaCM/D");
  RootOutput::getInstance()->GetTree()->Branch("VertexX", &VertexX, "VertexX/D");
  RootOutput::getInstance()->GetTree()->Branch("VertexY", &VertexY, "VertexY/D");
  RootOutput::getInstance()->GetTree()->Branch("VertexZ", &VertexZ, "VertexZ/D");
  RootOutput::getInstance()->GetTree()->Branch("deltaX", &deltaX, "deltaX/D");
  RootOutput::getInstance()->GetTree()->Branch("deltaY", &deltaY, "deltaY/D");
  RootOutput::getInstance()->GetTree()->Branch("deltaZ", &deltaZ, "deltaZ/D");
  RootOutput::getInstance()->GetTree()->Branch("deltaPhi", &deltaPhi, "deltaPhi/D");
  RootOutput::getInstance()->GetTree()->Branch("sumTheta", &sumTheta, "sumTheta/D");

  RootOutput::getInstance()->GetTree()->Branch("alpha", &alpha, "alpha/D");

  RootOutput::getInstance()->GetTree()->Branch("Theta1", &Theta1, "Theta1/D");
  RootOutput::getInstance()->GetTree()->Branch("Phi1", &Phi1, "Phi1/D");
  RootOutput::getInstance()->GetTree()->Branch("Theta2", &Theta2, "Theta2/D");
  RootOutput::getInstance()->GetTree()->Branch("Phi2", &Phi2, "Phi2/D");
  RootOutput::getInstance()->GetTree()->Branch("Theta1s", &Theta1s, "Theta1s/D");
  RootOutput::getInstance()->GetTree()->Branch("Phi1s", &Phi1s, "Phi1s/D");
  RootOutput::getInstance()->GetTree()->Branch("Theta2s", &Theta2s, "Theta2s/D");
  RootOutput::getInstance()->GetTree()->Branch("Phi2s", &Phi2s, "Phi2s/D");
  RootOutput::getInstance()->GetTree()->Branch("TA", &TA, "TA/D");
  RootOutput::getInstance()->GetTree()->Branch("TAcalc", &TAcalc, "TAcalc/D");

  RootOutput::getInstance()->GetTree()->Branch("Distance", &Distance, "Distance/D");
  RootOutput::getInstance()->GetTree()->Branch("InteractionCoordinates", "TInteractionCoordinates", &DC);
  RootOutput::getInstance()->GetTree()->Branch("ReactionConditions", "TReactionConditions", &RC);
}

////////////////////////////////////////////////////////////////////////////////
void Analysis::InitInputBranch() {
  RootInput::getInstance()->GetChain()->SetBranchAddress("InteractionCoordinates", &DC);
  RootInput::getInstance()->GetChain()->SetBranchAddress("ReactionConditions", &RC);
}
////////////////////////////////////////////////////////////////////////////////
void Analysis::ReInitValue() {
  Ex = -1000;
  E1 = -1000;
  Theta12 = -1000;
  ThetaCM = -1000;
  VertexX = -1000;
  VertexY = -1000;
  VertexZ = -1000;
  deltaX = -1000;
  deltaY = -1000;
  deltaZ = -1000;
  Distance = -1000;
  sumTheta = -1000;
  deltaPhi = -1000;
  alpha = -1000;
  Theta1 = -1000;
  Phi1 = -1000;
  Theta2 = -1000;
  Phi2 = -1000;
  Theta1s = -1000;
  Phi1s = -1000;
  Theta2s = -1000;
  Phi2s = -1000;
  TA = -1000;
  TAcalc = -1000;
}

////////////////////////////////////////////////////////////////////////////////
//            Construct Method to be pass to the AnalysisFactory              //
////////////////////////////////////////////////////////////////////////////////
NPL::VAnalysis* Analysis::Construct() { return (NPL::VAnalysis*)new Analysis(); }

////////////////////////////////////////////////////////////////////////////////
//            Registering the construct method to the factory                 //
////////////////////////////////////////////////////////////////////////////////
extern "C" {
class proxy {
 public:
  proxy() { NPL::AnalysisFactory::getInstance()->SetConstructor(Analysis::Construct); }