HighLAND
SecondaryInteractionSystematic.cxx
1 #include "SecondaryInteractionSystematic.hxx"
2 #include "Parameters.hxx"
3 #include <math.h>
4 #include <cmath>
5 #include <cassert>
6 
7 //#define DEBUG
8 //#define DDEBUG
9 
10 //********************************************************************
11 si_syst::MaterialEnum si_syst::GetMaterialEnum(const std::string& matName){
12  //********************************************************************
13 
14  // From pion SI, should be moved to te base pakage, once the psyche event model is ready
15 
16  //Air, use O.
17  if (matName == "Air") return kOxygen;
18  //Oxygen, use O
19  else if (matName == "Oxygen") return kOxygen;
20  //CO2, use O.
21  else if (matName == "CO2") return kOxygen;
22  //Carbon
23  else if (matName == "Carbon") return kCarbon;
24  //Aluminum
25  else if (matName == "Aluminum") return kAluminium;
26  //Aluminium
27  else if (matName == "Aluminium") return kAluminium;
28  //Steel, use Fe.
29  else if (matName == "Steel") return kIron;
30  //Iron
31  else if (matName == "Iron") return kIron;
32  //AlRoha2 or AlRoha, use Aluminum.
33  else if (matName == "AlRoha" || matName == "AlRoha2") return kAluminium;
34  //AlG10
35  else if (matName == "AlG10") return kAlG10;
36  //WaterSystem
37  else if (matName == "WaterSystem") return kWaterSystem;
38  //G10FGD1/G10
39  else if (matName == "G10FGD1" || matName == "G10") return kG10;
40  //FGDScintillator (use Carbon)
41  //There are some extra letters beyond "FGDScintillator" possible
42  //in the name of this material.
43  else if (matName.find("FGDScintillator") != std::string::npos) return kCarbon;
44  //FGDGlue
45  else if (matName == "FGDGlue") return kFGDGlue;
46  //G10Roha
47  else if (matName == "G10Roha") return kG10Roha;
48  //-----------------------------
49  //New materials added for 2014.
50  //-----------------------------
51  //G10FGD2 has the same composition as G10 and G10FGD1, as far as molar
52  //fractions of elements are concerned.
53  else if (matName == "G10FGD2") return kG10;
54  //ActiveWater gets approximated by Oxygen.
55  else if (matName == "ActiveWater") return kOxygen;
56  //Polypropylene is just Carbon and (ignored) Hydrogen
57  else if (matName == "Polypropylene") return kCarbon;
58  //FGDWaterModuleEpoxy has the same composition as FGDGlue (70 series).
59  else if (matName == "FGDWaterModuleEpoxy") return kFGDGlue;
60  //GasMixtureTPC is mostly Argon. The closest element we have to Argon is
61  //Aluminum, which is not a great approximation, but with such a low density
62  //of scattering centres in the TPC Gas, should be good enough, and is
63  //certainly closer than the Carbon we would otherwise default to.
64  //NB: The Material Series is only for which set of pion cross sections to
65  //use. Other properties (like density) are determined from data taken from
66  //the geometry.
67  else if (matName == "GasMixtureTPC") return kAluminium;
68  //If it was something we've somehow missed, just use Carbon.
69  else return kCarbon;
70 
71 }
72 
73 //********************************************************************
74 Double_t si_syst::GetIElement(Int_t Z){
75  //********************************************************************
76  switch(Z){
77  case 1: //Hydrogen
78  return 19.2;
79  case 5: //Boron
80  return 76.0;
81  case 6: //Carbon
82  return 78.0;
83  case 7: //Nitrogen
84  return 82.0;
85  case 8: //Oxygen
86  return 95.0;
87  case 9: //Fluorine
88  return 115.0;
89  case 11: //Sodium
90  return 149.0;
91  case 13: //Aluminum
92  return 166.0;
93  case 14: //Silicon
94  return 173.0;
95  case 17: //Chlorine
96  return 174.0;
97  case 18: //Argon
98  return 188.0;
99  case 22: //Titanium
100  return 233.0;
101  case 26: //Iron
102  return 286.0;
103  case 27: //Cobalt
104  return 297.0;
105  case 29: //Copper
106  return 322.0;
107  case 30: //Zinc
108  return 330.0;
109  case 50: //Tin
110  return 488.0;
111  case 82: //Lead
112  return 823.0;
113  default: //If unrecognized, just assume FGD scintillator.
114  return 68.7;
115  }
116 }
117 
118 //********************************************************************
119 Double_t si_syst::GetZoverAMaterial(TGeoNode* node){
120  //********************************************************************
121  TGeoVolume *volume = node->GetVolume();
122  TGeoMaterial *material = volume->GetMaterial();
123  TGeoMixture *mixture = (TGeoMixture*)material;
124 
125  Double_t ZoverA = 0;
126 
127  // Get the number of elements
128  Int_t NElements = mixture->GetNelements();
129 
130  // Get the Z values for the material constituents.
131  Double_t* Zmixt = mixture->GetZmixt();
132 
133  // Get the A values for the material constituents.
134  Double_t* Amixt = mixture->GetAmixt();
135 
136  // Get the weight by mass of the elements.
137  Double_t* Wmixt = mixture->GetWmixt();
138 
139  // Compute Z/A
140  for(Int_t i = 0; i < NElements; i++){
141 
142  ZoverA += Wmixt[i]*(Zmixt[i]/Amixt[i]);
143 
144  }
145  return ZoverA;
146 }
147 
148 //********************************************************************
149 Double_t si_syst::GetIMaterial(TGeoNode* node){
150  //********************************************************************
151 
152  TGeoVolume *volume = node->GetVolume();
153  TGeoMaterial *material = volume->GetMaterial();
154  TGeoMixture *mixture = (TGeoMixture*)material;
155 
156  Double_t ZoverA = GetZoverAMaterial(node);
157 
158  Double_t lnI = 0;
159 
160  //Get the number of elements
161  Int_t NElements = mixture->GetNelements();
162 
163  //Get the Z values for the material constituents.
164  Double_t* Zmixt = mixture->GetZmixt();
165 
166  //Get the A values for the material constituents.
167  Double_t* Amixt = mixture->GetAmixt();
168 
169  //Get the weight by mass of the elements.
170  Double_t* Wmixt = mixture->GetWmixt();
171 
172  //lnIeff = sum(w_i*(Z_i/A_i)*lnI_i)/(Z/A)
173  for(Int_t i = 0; i < NElements; i++){
174 
175  lnI += (Wmixt[i]*(Zmixt[i]/Amixt[i])*log(GetIElement((Int_t)Zmixt[i])))/ZoverA;
176  }
177 
178  return exp(lnI);
179 }
180 
181 
182 
183 //********************************************************************
184 Double_t si_syst::BetheBloch(const ParticleState& state, TGeoNode* node){
185  //********************************************************************
186 
187 
188  TGeoVolume *volume = node->GetVolume();
189  TGeoMaterial *material = volume->GetMaterial();
190 
191  // Now, set up the values that we need for the dEdX
192  Double_t betagamma = state.Momentum/state.Mass;
193  Double_t energy = sqrt(state.Momentum*state.Momentum + state.Mass*state.Mass);
194  Double_t beta = state.Momentum/energy;
195  Double_t gamma = betagamma/beta;
196  Double_t T_max = (2*units::mass_electron*pow(betagamma,2))/(1 + 2*gamma*(units::mass_electron/state.Mass) + pow(units::mass_electron/state.Mass,2));
197 
198  // Potential
199  Double_t I = GetIMaterial(node)*(1E-6); //Make sure to convert to MeV!
200 
201  // The conversion factor converts the density stored in the geometry to g/cm^3
202  Double_t rho = (1000.0/(6.2415e21))*(material->GetDensity());
203 
204  Double_t ZoverA = si_syst::GetZoverAMaterial(node);
205  //0.1 to convert to mm
206  return 0.1*rho*K*1.*(ZoverA)*(1/pow(beta,2))*((1.0/2.0)*log(2*units::mass_electron*pow(betagamma,2)*T_max/pow(I,2)) - pow(beta,2));
207 
208 }
209 
210 //********************************************************************
211 void si_syst::TakeSmallStep(ParticleState& state, const Double_t& stepLength, TGeoNode* node){
212  //********************************************************************
213 
214  //Find the initial kinetic energy.
215  Double_t initEkin = anaUtils::ComputeKineticEnergy(state.Momentum, state.Mass);
216 
217  //Find the initial direction at the beginning of the step
218  TVector3 initDir = state.Dir;
219 
220  Double_t p = state.Momentum;
221  Double_t betagamma = p / state.Mass;
222  Double_t beta = p /(initEkin + state.Mass);
223  Double_t gamma = betagamma / beta;
224 
225  Double_t dEdx = BetheBloch(state, node);
226 
227  //Remember, it is dE/dx * length in material * density of material
228  //Used 1.032 g/cm^3, the density of the scintillator bars (from TN-91), as opposed
229  //to the full module density which took into account the G10, glue, and fiber.
230  //Factor of 0.1 to convert the mm tracklength to cm.
231  Double_t finalEkin = initEkin - dEdx*(0.1)*stepLength;
232 
233  if (finalEkin <= 0 ){
234  state.Dir = TVector3(0., 0., 0.);
235  state.Momentum = 0.;
236  return;
237  }
238 
239  //Now, since we're taking small steps, we're assuming that the change in momentum is small, so we'll
240  //just use the initial momentum as the feed through into the helix code.
241  //The velocity of the pion in m/s)
242  //PDG speed of light value: 299 792 458 m/s
243  Double_t c = 299792458;
244  TVector3 initVelocity = beta*c*initDir;
245 
246  //dp/dt = q(v x B), where p = \beta\gamma*mc
247  //1 unit of charge is 1.602176e-19 Coulombs
248  TVector3 dpdt = 1.*(1.602176e-19)*initVelocity.Cross(field);
249 
250  //So the change in momentum is therefore dpdt*dt, where dt = stepLength/initVelocity.Mag()
251  //0.001 converts stepLength from mm to m.
252  Double_t dt = ((0.001*stepLength)/initVelocity.Mag());
253  TVector3 dp = dpdt*dt;
254 
255  //So that we're working all in the same units, use gamma*m*initVelocity to get the initial momentum back
256  //(i.e. p = gamma*m*v)
257  //Convert m_pi from MeV/c^2 to kg with factor of 1.782662e-30
258  TVector3 pFinal = gamma*state.Mass*(1.782662e-30)*initVelocity + dp;
259 
260  //Now we know the final momentum in kg*m/s. The Lorentz force only changes the direction and not the
261  //magnitude of the momentum. So, all we care about is the direction.
262  state.Dir = pFinal*(1/pFinal.Mag());
263 
264  //The final position of a step is going to be
265  //the result of going the step length in the direction of the initial momentum.
266  //The final momentum is going to be the final kinetic energy converted back to a momentum
267  //and in the direction of the final direction.
268  // set new position
269  state.Pos += stepLength*initDir;
270 
271  state.Momentum = sqrt(pow(finalEkin + state.Mass, 2) - pow(state.Mass, 2));
272 
273  return;
274 
275 }
276 
277 // Stuff related to the full propagation taken into account the xsec etc
278 
279 //********************************************************************
280 Double_t si_syst::ParticleSIPropagator::DScattCenters(TGeoNode* node) const{
281  //********************************************************************
282 
283  TGeoVolume *volume = node->GetVolume();
284  TGeoMaterial *material = volume->GetMaterial();
285  TGeoMixture *mixture = (TGeoMixture*)material;
286 
287  //Get the atomic number, mass (i.e. molar mass) and weight by mass arrays,
288  //as well as the number of elements.
289  // Double_t* ZArray = mixture->GetZmixt();
290  Double_t* AArray = mixture->GetAmixt();
291  Double_t* WArray = mixture->GetWmixt();
292  Int_t NElts = mixture->GetNelements();
293 
294  //Go through and compute the number of scattering centres of each element per unit
295  //volume. Add them together to get the total number of scattering centres per
296  //unit volume.
297  Double_t result = 0;
298  for(Int_t i = 0; i< NElts; i++)
299  //Extra factor required to convert density to g/cm^3
300  result += (units::Avogadro/AArray[i])*WArray[i]*((1000.0/(6.2415e21))*mixture->GetDensity());
301 
302  //All constituents having now been looped over, return the value.
303  return result;
304 }
305 
306 
307 
308 //********************************************************************
309 void si_syst::ParticleSIPropagator::Propagate(si_syst::ParticleHistory& particle, const TVector3& finalPos) const{
310  //********************************************************************
311 
312  // We are talking about steps here but in principle (and what is done for the moment) we assumes all materials are fully correlated,
313  // hence is enough just to store the information once (although still keep the steps functionality so to be able to differentiate between
314  // material uncerainties in a more detailed way if needed)
315 
316 
317 #ifdef DDEBUG
318  std::cout << " ======= " << std::endl;
319  std::cout << " si_syst::ParticleSIPropagator::Propagate: in det " << det << std::endl;
320  particle_in.trueTrack->Print();
321 #endif
322 
323  // Do nothing if a state is not in VOI
324  if (!InVOI(particle.stateCurrent.Pos)){
325 
326 #ifdef DDEBUG
327  std::cout << " no VOI" << std::endl;
328 #endif
329  return;
330  }
331 
332 
333  // Do nothing if no interactions are available
334  if (_intTypes.size() == 0){
335 
336 #ifdef DDEBUG
337  std::cout << " no Interactions" << std::endl;
338 #endif
339  return;
340  }
341 
342 
343  //Loop over taking steps until the separation from start to end point
344  //is the is the same from oaAnalysis saved and from stepping.
345 
346  Double_t initPointSep = (finalPos - particle.stateCurrent.Pos).Mag();
347  Double_t stepPointSep = 0.0;
348 
349  // Reference point
350  TVector3 initPos = particle.stateCurrent.Pos;
351 
352 #ifdef DDEBUG
353  std::cout << " ======= " << std::endl;
354  std::cout << " si_syst::ParticleSIPropagator::Propagate: " << std::endl;
355  particle.Print();
356  std::cout << " finalPos: " << finalPos << std::endl;
357  std::cout << " initPointSep: " << initPointSep << std::endl;
358 
359 #endif
360 
361  // The variables to accumulate while stepping:
362  // cross-section inputs Sum_i(sigma_i * ND_i * step_length_i)
363  // and uncertainties (fully correlated!) Sum_i(err_sigma_i * ND_i * step_length_i
364  // One may wonder why do we need cross-section at all, this is to deal with too big fluctuations later (avoid negative cross-sections)
365  std::vector<si_syst::SIXSecData> xSecAccum;
366  xSecAccum.resize(_intTypes.size(), si_syst::SIXSecData(0., 0.));
367 
368  std::vector<si_syst::SIXSecData> xSecRefAccum;
369  xSecRefAccum.resize(_intTypes.size(), si_syst::SIXSecData(0., 0.));
370 
371 
372  // Do the loop until go beyond the VOI or stop (zero mom)
373  while (stepPointSep < initPointSep){
374 
375  // Grab the material information for this step.
376  TGeoNode *node = ND::hgman().GeoManager()->FindNode(particle.stateCurrent.Pos.X(),
377  particle.stateCurrent.Pos.Y(), particle.stateCurrent.Pos.Z());
378 
379  // Store the momentum before the step
380  Double_t momStartStep = particle.stateCurrent.Momentum;
381 
382 #ifdef DDDEBUG
383  std::cout << " Start of step: " << std::endl;
384  particle.Print();
385  std::cout << " momStartStep: " << momStartStep << std::endl;
386 #endif
387 
388  // Given the information supplied, take a small step.
389  TakeSmallStep(particle.stateCurrent, _lengthStepSize, node);
390 
391  // Also compute the separation between the step end point and the initial point.
392  stepPointSep = (particle.stateCurrent.Pos - initPos).Mag();
393 
394 #ifdef DDDEBUG
395  std::cout << " End of step: " << std::endl;
396  particle.Print();
397  std::cout << " stepPointSep: " << stepPointSep << std::endl;
398 #endif
399 
400 
401  // Define the number density of scattering centres for the material (mixture)
402  Double_t NDMat = DScattCenters(node); // nuclei/cm^3
403 
404 
405 #ifdef DDDEBUG
406 
407  TGeoVolume *volume = node->GetVolume();
408  TGeoMaterial *material = volume->GetMaterial();
409  std::string materialName = material->GetName();
410  TGeoMixture *mixture = (TGeoMixture*)material;
411 
412  std::cout << " out of VOI/zero-mom, int: " << *iter << std::endl;
413  std::cout << " out of VOI/zero-mom, xsec: " << xsec << std::endl;
414  std::cout << " material: " << materialName << std::endl;
415  std::cout << " material Z: " << mixture->GetZ() << std::endl;
416  std::cout << " material A: " << mixture->GetA() << std::endl;
417  std::cout << " momStartStep : " << momStartStep << std::endl;
418  std::cout << " NDMat: " << NDMat << std::endl;
419  std::cout << " factor: " << factor << std::endl;
420  std::cout << " factor_ref: " << factor_ref << std::endl;
421 #endif
422 
423  // Loop over the interactions of interest
424  std::set<si_syst::InteractionType>::const_iterator iter = _intTypes.begin();
425  int i = 0;
426  for (; iter != _intTypes.end(); iter++, i++){
427 
428  Double_t xsec = GetCrossSection(*iter, momStartStep, particle.trueTrack->PDG, node) *
429  NDMat * _lengthStepSize * 1.e-3; // length to cm and xsec to cm
430 
431  // Increment the xsec and error data
432  xSecAccum[i].XSec += xsec;
433  xSecAccum[i].XSecErr += xsec * GetCrossSectionError(*iter, momStartStep, particle.trueTrack->PDG, node);;
434 
435 
436 
437  // Fill the same but with the reference cross-section if needed
439  Float_t xsecRef = NDMat * _lengthStepSize * 1.e-3 * GetReferenceCrossSection(*iter, momStartStep, particle.trueTrack->PDG, node);
440  xSecRefAccum[i].XSec += xsecRef;
441  xSecRefAccum[i].XSecErr += 0.;
442 
443  }
444  }
445  }//End while loop
446 
447  // Add one step (see comment about correlated uncertainties)
448  particle.propSteps.push_back(xSecAccum);
449  particle.propStepsReference.push_back(xSecRefAccum);
450 
451 #ifdef DDEBUG
452  std::cout << " ======= " << std::endl;
453 #endif
454 
455 
456  return;
457 
458 }
459 
460 //********************************************************************
462  //********************************************************************
463 
464 #ifdef DEBUG
465  std::cout << " ======= " << std::endl;
466  std::cout << " si_syst::ParticleSIManager::CollectParticleInteractions " << std::endl;
467 #endif
468 
469  assert(GetPropagator());
470 
471  assert(GetPropagator()->IsInitialized());
472 
473  GetPropagator()->SetDetector(det);
474 
475 
476  // This will create a collection of particles` histories (yet to be filled) with the corresponding interactions etc
477  si_syst::SISystInput* result = GetRelevantParticles(allTrajs, nTrajs);
478 
479 
480  for (int i = 0; i < result->nParticles; i++){
481 
482  // Fill the steps information for this particle
483  GetPropagator()->Propagate(result->Particles[i], result->Particles[i].trueTrack->PositionEnd);
484 
485  // Set the uncertainty at the interaction point
486  result->Particles[i].XSecData = si_syst::SIXSecData(
487  _propagator->GetCrossSection(
488  result->Particles[i].intType,
489  result->Particles[i].stateCurrent,
490  result->Particles[i].trueTrack->PDG),
491  _propagator->GetCrossSectionError(
492  result->Particles[i].intType,
493  result->Particles[i].stateCurrent,
494  result->Particles[i].trueTrack->PDG)
495  );
496 
497 
498 
499  // Calculate the "correction" weight
500  result->Particles[i].Weight = 1.;
501 
502  if (!GetPropagator()->GetComputeReWeightStatus())
503  continue;
504 
505 
506  // Set the reference one
507  result->Particles[i].XSecDataReference = si_syst::SIXSecData(
508  GetPropagator()->GetReferenceCrossSection(
509  result->Particles[i].intType,
510  result->Particles[i].stateCurrent,
511  result->Particles[i].trueTrack->PDG),
512  0.
513  );
514 
515  // Suvrvival probabilities for the current cross-section and the reference one
516  Float_t survProb = 0.;
517  Float_t survProbReference = 0.;
518 
519 
520  size_t nSteps = result->Particles[i].propSteps.size();
521 
522 #ifdef DEBUG
523  std::cout << " particle i: " << i << " nSteps " << nSteps << std::endl;
524 #endif
525 
526  for (size_t ns = 0; ns < nSteps; ns++){
527  // For each step loop over the interactions
528  size_t nInts = result->Particles[i].propSteps[ns].size();
529  for (size_t nint = 0; nint < nInts; nint++){
530  survProb += result->Particles[i].propSteps[ns][nint].XSec;
531  survProbReference += result->Particles[i].propStepsReference[ns][nint].XSec;
532  }
533  }
534 
535  result->Particles[i].Weight *= exp( - (survProbReference - survProb));
536 
537  if (result->Particles[i].XSecData.XSec != 0)
538  result->Particles[i].Weight *= result->Particles[i].XSecData.XSec / result->Particles[i].XSecDataReference.XSec;
539 
540 
541 #ifdef DEBUG
542  std::cout << " particle i: " << i << " weight " << result->Particles[i].Weight << std::endl;
543  std::cout << " particle i: " << i << " int type " << result->Particles[i].intType << std::endl;
544 #endif
545 
546 
547  }
548 
549 #ifdef DEBUG
550  std::cout << " ======= " << std::endl;
551 #endif
552  return result;
553 }
554 
555 
556 
557 
558 // SI manager
559 //********************************************************************
561  //********************************************************************
562 
563 #ifdef DEBUG
564  std::cout << " ======= " << std::endl;
565  std::cout << " si_syst::ParticleSIManager::GetRelevantParticles " << std::endl;
566 #endif
567 
568  assert(GetPropagator());
569 
570  assert(GetPropagator()->IsInitialized());
571 
572 
574 
575  // We want to count all particles of interest (PDG) that originate in particular volume
576  // and group them (if exist) with the daughters of their probable interactions
577  si_syst::ParentsAndDaughters ParticlesAndInteractions;
578 
579  for (Int_t it = 0; it < nTrajs; it++){
580 
581  AnaTrueParticleB* track = allTrajs[it];
582 
583  // Should be inside PDGs of interest
584  // not using set::find here since then need to cast int to PdgEnum, not sure it will always succeed
585  bool ok = false;
586  std::set<ParticleId::PdgEnum>::const_iterator it_set = GetPropagator()->GetParticlePDGs().begin();
587 
588  for (; it_set != GetPropagator()->GetParticlePDGs().end(); it_set++){
589  if (*it_set == track->PDG){
590  ok = true;
591  break;
592  }
593  }
594 
595  if (!ok)
596  continue;
597 
598  // Should start in the VOI
599  if (!GetPropagator()->InVOI(track->Position)) continue;
600 
601  ParticlesAndInteractions.push_back(std::make_pair(track, std::vector<AnaTrueParticleB*>()));
602 
603  // Now loop over trajectories and find those that mention this particle as parent
604  // those daughtes should start in the volume of interest as well
605  for (Int_t jt = 0; jt < nTrajs; jt++){
606  AnaTrueParticleB* track2 = allTrajs[jt];
607 
608  if (track->ID == track2->ParentID &&
609  GetPropagator()->InVOI(track->Position)){
610 
611  // Add this trajectory to interaction list
612  ParticlesAndInteractions.back().second.push_back(track2);
613 
614  }
615 
616  } //second loop over true tracks
617  }//first loop over true tracks
618 
619  //now we have all primary particles grouped together with their possible daughters
620  //we can so arrange them into interactions
621 
622  result->nParticles = ParticlesAndInteractions.size();
623 
624  result->Particles = new si_syst::ParticleHistory[result->nParticles];
625 
626 
627  /// Fill the interaction types
628  for(Int_t i = 0; i < result->nParticles; i++){
629 
630  result->Particles[i] = si_syst::ParticleHistory(si_syst::kInelastic, *(ParticlesAndInteractions[i].first));
631 
632  // No interactions in the volume
633  if (ParticlesAndInteractions[i].second.size() == 0)
634  result->Particles[i].intType = si_syst::kNoInteraction;
635 
636  }
637 
638 #ifdef DEBUG
639  std::cout << " nParticles: " << result->nParticles << std::endl;
640 #endif
641 
642 #ifdef DEBUG
643  std::cout << " ======= " << std::endl;
644 #endif
645  return result;
646 }
647 
648 
649 
650 //********************************************************************
651 std::ostream& operator<<(std::ostream& os, const TLorentzVector& vect){
652  //********************************************************************
653  os << " X " << vect.X() << " Y " << vect.Y() << " Z " << vect.Z() << " T " << vect.T() << std::endl;
654  return os;
655 }
656 
657 //********************************************************************
658 std::ostream& operator<<(std::ostream& os, const TVector3& vect){
659  //********************************************************************
660  os << " X " << vect.X() << " Y " << vect.Y() << " Z " << vect.Z() << std::endl;
661  return os;
662 }
663 
664 
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.
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)
virtual Double_t GetCrossSectionError(const si_syst::InteractionType &, const Float_t &, const Int_t &, TGeoNode *) const =0
Double_t _lengthStepSize
The step size in terms of length.
virtual si_syst::SISystInput * GetRelevantParticles(AnaTrueParticleB **, int) const
Double_t GetIMaterial(TGeoNode *node)
si_syst::SIXSecData XSecData
Store both the cross-section and error.
bool IsInitialized()
Whether the propagator was initialized.
Int_t ID
The ID of the trueObj, which corresponds to the ID of the TTruthParticle that created it...
Representation of a true Monte Carlo trajectory/particle.
A simple structure to repesent a pair: xsection value and its uncertainty.
si_syst::SISystInput * CollectParticleInteractions(AnaTrueParticleB **, int, const SubDetId::SubDetEnum &) const
Calculates the information needed to compute an event weight.
const TVector3 field
Constants.
SubDetEnum
Enumeration of all detector systems and subdetectors.
Definition: SubDetId.hxx:25
virtual Double_t GetCrossSection(const si_syst::InteractionType &, const Float_t &, const Int_t &, TGeoNode *) const =0
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.
virtual Double_t DScattCenters(TGeoNode *) const
void TakeSmallStep(ParticleState &, const Double_t &)
Propagate a state in a small step.
Double_t BetheBloch(const ParticleState &)
virtual void Propagate(ParticleHistory &, const TVector3 &) const
Propagates a particle to a given pos filling all the history info.
std::vector< StepInfo > propSteps
Vector of steps considered with the corresponding info.
Int_t ParentID
The ID of this particle&#39;s immediate parent, or 0 if there is no parent.
Float_t PositionEnd[4]
The end position of the true particle.
Double_t GetIElement(Int_t Z)
Float_t Position[4]
The initial position of the true particle.
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 ComputeKineticEnergy(Float_t mom, Float_t mass)
Compute kinetic energy given momentum and mass.
virtual Bool_t InVOI(const TVector3 &) const =0
Is a point inside a volume of interest: the region where the propagation is relevant.
ParticleState stateCurrent
Current state of the particle.