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 *
* *
* Last update : *
*---------------------------------------------------------------------------*
* Decription: *
* Class describing the property of an Analysis object *
* *
*---------------------------------------------------------------------------*
* Comment: *
* *
* *
*****************************************************************************/
#include "Analysis.h"
#include "NPAnalysisFactory.h"
#include "NPDetectorManager.h"
#include "NPFunction.h"
#include "NPOptionManager.h"
#include "NPPhysicalConstants.h"
#include "NPTrackingUtility.h"
#include "TRandom3.h"
////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////
void Analysis::Init() {
IC = new TInitialConditions;
DC = new TInteractionCoordinates;
RC = new TReactionConditions;
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()*/;
// 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);
////////////////////////////////////////////////////////////////////////////////
// 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
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
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();
}
/* ///////////////////////////////////
* //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;
}
E1 = ReconstructProtonEnergy(Vertex,Proton1,Catana->Energy[i1]);
E2 = ReconstructProtonEnergy(Vertex,Proton2,Catana->Energy[i2]);
//E2 = Catana->Energy[i2];
cout<<"------------------------"<<endl;
////////////////////////////////////////////////////////////////////////////////
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
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::InitOutputBranch() {
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
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;
E2 = -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); }