HighLAND
SecondaryInteractionSystematic.hxx
1 #ifndef SecondaryInteractionSystematic_h
2 #define SecondaryInteractionSystematic_h
3 
4 #include "AnalysisUtils.hxx"
5 
6 #include "HEPConstants.hxx"
7 #include "Units.hxx"
8 
9 //For geometry stuff.
10 #include "GeometryManager.hxx"
11 #include <TGeoManager.h>
12 #include <TGeoNode.h>
13 #include <TGeoVolume.h>
14 #include <TGeoMaterial.h>
15 #include "ParticleId.hxx"
16 #include "CoreUtils.hxx"
17 
18 #include <string>
19 #include <set>
20 
21 /// A general class to do various business related to secondary interactions: retrieve particles of intereset
22 /// and
23 
24 
25 
26 
27 namespace si_syst{
28 
29  // **********
30  /// Constants
31 
32  /// The magnetic field is 0.2 T in the x direction --> used for stepping --> keep it general
33  const TVector3 field = TVector3(0.2, 0., 0.);
34 
35  /// Bethe-Bloch constants
36  const Double_t K = 0.307075;
37 
38  // **********
39 
40 
41  // **********
42  /// Enums
43 
44  /// Interaction types, keep a wide list here, one can add what needed
46  kNoInteraction = 0, // particle does not interact in the volume of interest
47  kElastic,
48  kInelastic
49  };
50 
51 
52  /// Enumerate various materials of interest
53  /// Will be moved to secondary interactions syst...
55  kCarbon = 0, // probably better to use exact Z values, but want to be able to do simple loops etc
56  kOxygen,
57  kAluminium,
58  kIron,
59  kAlG10,
60  kWaterSystem,
61  kG10,
62  kFGDGlue,
63  kG10Roha,
64  kCounter
65  };
66  // **********
67 
68 
69  // **********
70  /// General kinematics methods
71  /// ZoverA, material properties retrieved from node
72  Double_t GetZoverAMaterial(TGeoNode*);
73 
74  /// Calculates the effective mean excitation energy for
75  /// Equation taken from Leo p.29.
76  /// Material properties retrieved from node
77  Double_t GetIMaterial(TGeoNode* node);
78 
79  /// Takes in an atomic number and returns the Mean Ionization Potential for
80  /// that element, from http://physics.nist.gov/PhysRefData/XrayMassCoef/tab1.html
81  /// Only filled for elements present in ND280UserDetectorConstruction.cc
82  /// Uses units of eV. Must be converted to MeV later.
83  Double_t GetIElement(Int_t Z);
84 
85 
86  /// Get the material enum given a material name
87  MaterialEnum GetMaterialEnum(const std::string&);
88 
89  // **********
90 
91  // **********
92  /// A simple structure to represent a state object: position, direction, momentum, charge
93  struct ParticleState{
94 
95  ParticleState(){}
96 
97  ParticleState(const AnaTrueParticleB& track){
98  Pos = anaUtils::ArrayToTLorentzVector(track.Position).Vect();
99  Dir = anaUtils::ArrayToTVector3(track.Direction);
100  Charge = track.Charge;
101  Momentum = track.Momentum;
102  Mass = units::pdgBase->GetParticle(track.PDG)->Mass() * units::GeV;
103  }
104 
105  TVector3 Pos;
106  TVector3 Dir;
107  Float_t Charge;
108  Float_t Momentum;
109  Float_t Mass;
110 
111 
112  };
113  // **********
114 
115  // **********
116  /// Propagation
117  /// Bethe-Bloch dEdX given particle state + TGeoNode (the particle is currently crossing) to specify material properties
118  Double_t BetheBloch(const ParticleState&);
119 
120  /// Bethe-Bloch dEdX given particle state + TGeoNode (the particle is currently crossing) to specify material properties
121  /// this is not to read the node if already avaiable
122  Double_t BetheBloch(const ParticleState&, TGeoNode*);
123 
124  /// Propagate a state in a small step
125  void TakeSmallStep(ParticleState&, const Double_t&);
126 
127  /// Propagate a state in a small step provided the node (material properties) and a step
128  /// this is not to read the node if already avaiable
129  void TakeSmallStep(ParticleState&, const Double_t&, TGeoNode*);
130 
131  // **********
132 
133  // **********
134  /// A simple structure to repesent a pair: xsection value and its uncertainty
135  struct SIXSecData{
136 
137  SIXSecData(Double_t xsec, Double_t err){
138  XSec = xsec;
139  XSecErr = err;
140  }
141  Float_t XSec;
142  Float_t XSecErr;
143 
144  };
145  // **********
146 
147 
148 
149 
150  // **********
151  /// A class to store all the info of a true particle relevant for SI systematics evaluation
152  /// Includes also weights for possible MC re-weighting
154 
155  public:
156  /// Each step is charactarized with the corresponding n*sigma*step_length and uncertainty value (!)
157  /// various channels can be involved --> hence a vector
158  typedef std::vector<SIXSecData> StepInfo;
159 
160  /// A default ctor
162  XSecData(0, 0),
163  XSecDataReference(0, 0){}
164 
165  virtual ~ParticleHistory(){}
166 
167 
168  /// A ctor given the interaction type and true particle
170  XSecData(0, 0),
171  XSecDataReference(0, 0){
172  intType = type;
173  stateStart = ParticleState(track);
174  trueTrack = &track;
175  Reset();
176  }
177 
178  /// Dump the history
179  void Print(){}
180 
181  /// Reset the history of the particle
182  void Reset(){
183  // Reset the current state
184  stateCurrent = stateStart;
185 
186  // Clear the steps
187  propSteps.clear();
188  propSteps.reserve(200);
189 
190  // Clear the reference steps
191  propStepsReference.clear();
192  propStepsReference.reserve(200);
193 
194  // Reset the xsec data
195  XSecData = si_syst::SIXSecData(0., 0.);
196 
197  // Reset the reference xsec data
198  XSecDataReference = si_syst::SIXSecData(0., 0.);
199 
200  Weight = 1.;
201 
202 
203  }
204 
205  /*!
206  * Interaction type
207  */
209 
210  /// Initial state of the particle
212 
213  /// Current state of the particle
215 
216  /// A pointer to the original true track
218 
219  /// Vector of steps considered with the corresponding info
220  std::vector<StepInfo> propSteps;
221 
222  /// Vector of steps considered with the corresponding info
223  /// but with reference cross-section, this is to calculate the weight
224  std::vector<StepInfo> propStepsReference;
225 
226  /// Store both the cross-section and error
228 
229  /// Store data for reference cross-section
231 
232  /// Weight for this particle, to be applied to correspond to a reference cross-section
233  Float_t Weight;
234 
235  };
236 
237  // **********
238 
239 
240  // **********
241  /// Basic structures to be able to associate a track with its "relatives"
242  typedef std::vector<std::pair<AnaTrueParticleB*, std::vector<AnaTrueParticleB*> > > ParentsAndDaughters;
243  typedef std::vector<std::pair<AnaTrueParticleB*, std::vector<AnaTrueParticleB*> > >::iterator ParentsAndDaughtersIt;
244  // **********
245 
246 
247 
248  // **********
249  /// A simple class to provide the data for the systematic itself: a collection of particles with the relevant history
250  class SISystInput{
251 
252  public:
253 
254  int nParticles;
255 
256  ParticleHistory* Particles;
257 
258  SISystInput(){
259  nParticles = 0;
260  Particles = NULL;
261  }
262 
263  virtual ~SISystInput(){
264  if (Particles)
265  delete [] Particles;
266  Particles = NULL;
267  nParticles = 0;
268 
269  }
270 
271  };
272  // **********
273 
274 
275  // **********
276  /// A class that does the actual propagation of a true track, taking into account and storing the xsec
277  /// values and uncertainties
279  public:
280 
282  _initialized = false;
283 
284  _det = SubDetId::kInvalid;
285 
286  // No external weights by default
287  _computeReWeightInfo = false;
288  }
289 
290  virtual ~ParticleSIPropagator(){}
291 
292 
293  /// Initialization
294  void Initialize(){
295  if (_initialized) return;
296  SetParameters();
297  _initialized = true;
298  }
299 
300 
301  /// Propagates a particle to a given pos filling all the history info
302  virtual void Propagate(ParticleHistory&, const TVector3&) const;
303 
304  /// Whether the propagator was initialized
305  bool IsInitialized(){return _initialized;}
306 
307 
308  /// Is a point inside a volume of interest: the region where the propagation is relevant
309  virtual Bool_t InVOI(const TVector3&) const = 0;
310 
311 
312 
313 
314  /// The function that gives a x-section value given a channel, momentum value, and node
315  /// + particle type so to make it fully general
316  virtual Double_t GetCrossSection(const si_syst::InteractionType&, const Float_t&, const Int_t&, TGeoNode*) const = 0;
317 
318 
319  /// Same but given the state
320  Double_t GetCrossSection(const si_syst::InteractionType& type, const ParticleState& state, const Int_t& PDG){
321 
322  TGeoNode *node = ND::hgman().GeoManager()->FindNode(state.Pos.X(), state.Pos.Y(), state.Pos.Z());
323 
324  return GetCrossSection(type, state.Momentum, PDG, node);
325 
326  }
327 
328  /// The function that gives a x-section value` uncertainty given a channel, momentum value and
329  /// + particle type so to make it fully general
330  virtual Double_t GetCrossSectionError(const si_syst::InteractionType&, const Float_t&, const Int_t&, TGeoNode*) const = 0;
331 
332  /// Same but given the state
333  Double_t GetCrossSectionError(const si_syst::InteractionType& type, const ParticleState& state, const Int_t& PDG){
334 
335  TGeoNode *node = ND::hgman().GeoManager()->FindNode(state.Pos.X(), state.Pos.Y(), state.Pos.Z());
336 
337  return GetCrossSectionError(type, state.Momentum, PDG, node);
338  }
339 
340  /// If one wants to re-weight to a given cross-section
341  /// Default implementation returns zero
342  virtual Double_t GetReferenceCrossSection(const si_syst::InteractionType&, const Float_t&, const Int_t&, TGeoNode*) const{
343  std::cout << " si_syst::ParticleSIPropagator::GetReferenceCrossSection() - the function has to be properly implemented " <<
344  " in the derived class if the re-weighting is needed " << std::endl;
345  return 0.;
346  }
347 
348  /// Same but given the state
349  Double_t GetReferenceCrossSection(const si_syst::InteractionType& type, const si_syst::ParticleState& state, const Int_t& PDG){
350 
351  TGeoNode *node = ND::hgman().GeoManager()->FindNode(state.Pos.X(), state.Pos.Y(), state.Pos.Z());
352 
353  return GetReferenceCrossSection(type, state.Momentum, PDG, node);
354  }
355 
356  /// Get interaction types
357  const std::set<si_syst::InteractionType>& GetInteractionTypes() const{
358  return _intTypes;
359  }
360 
361  /// Get particle PDGs
362  const std::set<ParticleId::PdgEnum>& GetParticlePDGs() const{
363  return _particlePDGs;
364  }
365 
366  /// Add an interaction type
368  _intTypes.insert(type);
369  }
370 
371  /// Add particle PDG
372  void AddParticlePDG(ParticleId::PdgEnum pdg){
373  _particlePDGs.insert(pdg);
374  }
375 
376  /// Set detector of interest
378  _det = det;
379  }
380 
381  /// Get detector of interest
383  return _det;
384  }
385 
386 
387  /// Whether to calculate correction weight, w.r.t to reference cross-section
388  void SetComputeReWeightStatus(bool status){
389  _computeReWeightInfo = status;
390  }
391 
392  /// Whether to calculate correction weight, w.r.t to reference cross-section
394  return _computeReWeightInfo;
395  }
396 
397 
398  protected:
399 
400  // Set the parameters for propagator: step length, momentum bins, relevant particles,
401  // whatever needed, is called in initialization
402  virtual void SetParameters() = 0;
403 
404  /// Density of scattering centers: n/cm^3
405  /// keep virtual if need fine tuning material based
406  virtual Double_t DScattCenters(TGeoNode*) const;
407 
408  /// The step size in terms of length
409  Double_t _lengthStepSize;
410 
411  /// The step size in terms of monetum
412  Double_t _momStepSize;
413 
414  /// Relevant interaction types to be considered while propagating
415  std::set<si_syst::InteractionType> _intTypes;
416 
417  /// PDG of relevant particles, keep here for the moment
418  std::set<ParticleId::PdgEnum> _particlePDGs;
419 
420  /// Keep the relevant sub-detector here for the moment
422 
423 
424  /// Whether to caculate weight for re-weighting (using the reference cross-section)
426 
427  private:
428  bool _initialized;
429  };
430 
431 
432  /// Manager
434 
435  public:
436 
437  /// ctor
439  _propagator = NULL;
440  }
441 
442  /// dtor
444  if (_propagator)
445  delete _propagator;
446  _propagator = NULL;
447  }
448 
449  /// Set the propagator
450  virtual void SetPropagator(ParticleSIPropagator* propagator){
451 
452  if (_propagator)
453  delete _propagator;
454 
455  _propagator = propagator;
456  _propagator->Initialize();
457  }
458 
459  /// Get propagator
461  return _propagator;
462  }
463 
464  /// Calculates the information needed to compute an event weight
465  si_syst::SISystInput* CollectParticleInteractions(AnaTrueParticleB**, int, const SubDetId::SubDetEnum&) const;
466 
467  protected:
468 
469  /// Get relevant particles
470  /// Given array of input true tracks, its size
471  /// The propagator provides the information on relevant tracks, interactions and VOI, so one has to set them first
472  /// Default method just splits between inelastic and no-interaction in VOI
473  virtual si_syst::SISystInput* GetRelevantParticles(AnaTrueParticleB**, int) const;
474 
475  ParticleSIPropagator* _propagator;
476 
477  };
478 
479 };
480 
481 std::ostream& operator<<(std::ostream& os, const TVector3& vect);
482 std::ostream& operator<<(std::ostream& os, const TLorentzVector& vect);
483 
484 
485 #endif
std::vector< std::pair< AnaTrueParticleB *, std::vector< AnaTrueParticleB * > > > ParentsAndDaughters
Basic structures to be able to associate a track with its "relatives".
si_syst::SIXSecData XSecDataReference
Store data for reference cross-section.
ParticleState stateStart
Initial state of the particle.
std::set< si_syst::InteractionType > _intTypes
Relevant interaction types to be considered while propagating.
bool _computeReWeightInfo
Whether to caculate weight for re-weighting (using the reference cross-section)
SubDetId::SubDetEnum GetDetector() const
Get detector of interest.
virtual void SetPropagator(ParticleSIPropagator *propagator)
Set the propagator.
Double_t GetCrossSectionError(const si_syst::InteractionType &type, const ParticleState &state, const Int_t &PDG)
Same but given the state.
Double_t _lengthStepSize
The step size in terms of length.
Double_t GetIMaterial(TGeoNode *node)
si_syst::SIXSecData XSecData
Store both the cross-section and error.
Float_t Momentum
The initial momentum of the true particle.
ParticleHistory(const InteractionType &type, const AnaTrueParticleB &track)
A ctor given the interaction type and true particle.
bool IsInitialized()
Whether the propagator was initialized.
const std::set< si_syst::InteractionType > & GetInteractionTypes() const
Get interaction types.
Double_t _momStepSize
The step size in terms of monetum.
Double_t GetCrossSection(const si_syst::InteractionType &type, const ParticleState &state, const Int_t &PDG)
Same but given the state.
std::set< ParticleId::PdgEnum > _particlePDGs
PDG of relevant particles, keep here for the moment.
void AddInteractionType(si_syst::InteractionType type)
Add an interaction type.
si_syst::ParticleSIPropagator * GetPropagator() const
Get propagator.
void AddParticlePDG(ParticleId::PdgEnum pdg)
Add particle PDG.
Representation of a true Monte Carlo trajectory/particle.
A simple structure to repesent a pair: xsection value and its uncertainty.
const TVector3 field
Constants.
SubDetEnum
Enumeration of all detector systems and subdetectors.
Definition: SubDetId.hxx:25
Int_t PDG
The PDG code of this particle.
Float_t Weight
Weight for this particle, to be applied to correspond to a reference cross-section.
const AnaTrueParticleB * trueTrack
A pointer to the original true track.
MaterialEnum GetMaterialEnum(const std::string &)
Get the material enum given a material name.
const Double_t K
Bethe-Bloch constants.
A simple structure to represent a state object: position, direction, momentum, charge.
Double_t GetReferenceCrossSection(const si_syst::InteractionType &type, const si_syst::ParticleState &state, const Int_t &PDG)
Same but given the state.
void TakeSmallStep(ParticleState &, const Double_t &)
Propagate a state in a small step.
Double_t BetheBloch(const ParticleState &)
void SetComputeReWeightStatus(bool status)
Whether to calculate correction weight, w.r.t to reference cross-section.
std::vector< StepInfo > propSteps
Vector of steps considered with the corresponding info.
void Reset()
Reset the history of the particle.
const std::set< ParticleId::PdgEnum > & GetParticlePDGs() const
Get particle PDGs.
Double_t GetIElement(Int_t Z)
Float_t Position[4]
The initial position of the true particle.
void SetDetector(const SubDetId::SubDetEnum &det)
Set detector of interest.
bool GetComputeReWeightStatus() const
Whether to calculate correction weight, w.r.t to reference cross-section.
A simple class to provide the data for the systematic itself: a collection of particles with the rele...
virtual Double_t GetReferenceCrossSection(const si_syst::InteractionType &, const Float_t &, const Int_t &, TGeoNode *) const
Double_t GetZoverAMaterial(TGeoNode *)
Float_t Charge
The true charge of the particle.
Float_t Direction[3]
The initial direction of the true particle.
SubDetId::SubDetEnum _det
Keep the relevant sub-detector here for the moment.
ParticleState stateCurrent
Current state of the particle.