NAIA
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups
MCTruthFill.cpp
Go to the documentation of this file.
1 #include "Containers/MCTruth.h"
2 
3 #include "TDatabasePDG.h"
4 
5 #include <algorithm>
6 
7 namespace NAIA {
8 
9 static float amu = 0.93146;
10 
11 MCParticle GetMCParticle(const MCEventgR &mcp) {
12  MCParticle particle{TDatabasePDG::Instance()->ConvertGeant3ToPdg(mcp.Particle),
13  static_cast<int>(mcp.Charge),
14  TMath::Nint(mcp.Mass / amu),
15  TVector3{mcp.Coo[0], mcp.Coo[1], mcp.Coo[2]},
16  {mcp.Momentum * TVector3{mcp.Dir[0], mcp.Dir[1], mcp.Dir[2]}},
17  mcp.trkID,
18  mcp.parentID,
19  mcp.Nskip >> 24,
20  mcp.Nskip & 0xFFFFFF};
21 
22  return particle;
23 }
24 
25 unsigned int TkIDToLayerJ(int tkID) {
26  tkID = abs(tkID);
27 
28  unsigned int layerOld = tkID / 100;
29  switch (layerOld) {
30  case 8:
31  return 1;
32  break;
33  case 9:
34  return 9;
35  default:
36  return layerOld + 1;
37  }
38 }
39 
40 MCTruthPlusData::TrMCHit GetTrMCHit(TrTrackR *pTrTrack, unsigned int jLayer, double match_radius = 0.1) {
41  AMSEventR *event = AMSEventR::Head();
42  if (!event)
43  throw std::runtime_error("Invalid pointer for AMSEventR::Head");
44  if (event->nMCEventgC() == 0)
45  throw std::runtime_error("No MCEventg information in this event");
46 
48 
49  TrRecHitR *hit = pTrTrack->GetHitLJ(jLayer);
50  if (!hit)
51  return mcHit;
52 
53  AMSPoint point = hit->GetCoord();
54 
55  auto mcclusterIt =
56  std::min_element(begin(event->TrMCCluster()), end(event->TrMCCluster()),
57  [&point](auto &cl1, auto &cl2) { return cl1.GetXgl().dist(point) < cl2.GetXgl().dist(point); });
58 
59  if (mcclusterIt == end(event->TrMCCluster()))
60  return mcHit;
61 
62  // Fail if minimal distance is not in match_radius
63  auto rmin = mcclusterIt->GetXgl().dist(point);
64  if (rmin > match_radius)
65  return mcHit;
66 
67  mcHit.pID = mcclusterIt->GetPart();
68  for (unsigned int ic = 0; ic < 3; ic++) {
69  mcHit.Coo[ic] = mcclusterIt->GetXgl()[ic];
70  mcHit.Mom[ic] = mcclusterIt->GetMom()[ic];
71  }
72 
73  return mcHit;
74 }
75 
76 auto particleSorter = [](const MCEventgR &a, const MCEventgR &b) -> bool {
77  if (a.parentID < b.parentID)
78  return true;
79  else if (a.parentID > b.parentID)
80  return false;
81  else {
82  if (a.Coo[2] > b.Coo[2])
83  return true;
84  else if (a.Coo[2] < b.Coo[2])
85  return false;
86  else
87  return a.Momentum > b.Momentum;
88  }
89 };
90 
91 void MCTruthBaseData::Fill(AMSEventR *evPtr) {
92 
93  // sort all MC particles by interaction point/momentum
94  std::sort(begin(evPtr->MCEventg()), end(evPtr->MCEventg()), particleSorter);
95 
96  auto primIt = std::find_if(begin(evPtr->MCEventg()), end(evPtr->MCEventg()),
97  [](const MCEventgR &mcp) { return mcp.Coo[2] > 160.0; });
98 
99  if (primIt == end(evPtr->MCEventg())) {
100  throw std::runtime_error("No generation point found for primary particle (with CooZ > 160 cm)");
101  }
102 
103  Primary = GetMCParticle(*primIt);
104  for (const auto &mcp : evPtr->MCEventg()) {
105  if (mcp.parentID != 0)
106  break;
107 
108  auto hIt = std::find_if(std::next(begin(MCTruth::MCHeightsZ)), end(MCTruth::MCHeightsZ),
109  [&mcp](float height) { return fabs(mcp.Coo[2] - height) < 3.5e-1; });
110  if (hIt != end(MCTruth::MCHeightsZ)) {
111  auto position = std::distance(begin(MCTruth::MCHeightsZ), hIt);
112  Primary.Momentum.resize(position + 1);
113  Primary.Momentum[position] = mcp.Momentum * TVector3{mcp.Dir[0], mcp.Dir[1], mcp.Dir[2]};
114  }
115  }
116 }
117 
118 void MCTruthPlusData::Fill(AMSEventR *evPtr) {
119 
120  // this should already be sorted, but you never know...
121  if (!std::is_sorted(begin(evPtr->MCEventg()), end(evPtr->MCEventg()), particleSorter)) {
122  // sort all MC particles by interaction point/momentum
123  std::sort(begin(evPtr->MCEventg()), end(evPtr->MCEventg()), particleSorter);
124  }
125 
126  const MCEventgR &firstPrim = evPtr->MCEventg()[0];
127 
128  const auto lastPrimIt = std::find_if(rbegin(evPtr->MCEventg()), rend(evPtr->MCEventg()),
129  [](const MCEventgR &mcp) { return mcp.parentID == 0; });
130 
131  if (lastPrimIt == rend(evPtr->MCEventg()))
132  return;
133 
134  for (MCEventgR &mcp : evPtr->MCEventg()) {
135  if (mcp.Momentum / firstPrim.Momentum > 0.01 && mcp.Coo[2] <= lastPrimIt->Coo[2]) {
136  Secondaries.push_back(GetMCParticle(mcp));
137  }
138  }
139 }
140 
141 void MCTruthPlusData::FillTrMCHit(TrTrackR *pTrTrack) {
142  for (unsigned int ij = 0; ij < 9; ij++) {
143  auto mcHit = GetTrMCHit(pTrTrack, ij + 1);
144  if (mcHit.pID > 0)
145  TrackMCHits[ij] = mcHit;
146  }
147 }
148 } // namespace NAIA
MCTruthPlusData::TrMCHit GetTrMCHit(TrTrackR *pTrTrack, unsigned int jLayer, double match_radius=0.1)
Definition: MCTruthFill.cpp:40
std::vector< TVector3 > Momentum
particle momentum at different z-heights. See MCTruth::MCHeights for a description of the possible he...
Definition: MCTruth.h:37
auto particleSorter
Definition: MCTruthFill.cpp:76
static float amu
Definition: MCTruthFill.cpp:9
MCParticle GetMCParticle(const MCEventgR &mcp)
Definition: MCTruthFill.cpp:11
constexpr std::array< float, numMCHeights > MCHeightsZ
Definition: Utils.h:384
std::array< float, 3 > Coo
hit position
Definition: MCTruth.h:104
Simple struct for MC tracker hits.
Definition: MCTruth.h:102
MCParticle Primary
primary particle
Definition: MCTruth.h:83
unsigned int TkIDToLayerJ(int tkID)
Definition: MCTruthFill.cpp:25
TVector3 Coo
generation position
Definition: MCTruth.h:35
SingleTreeChain::EventItr end(SingleTreeChain &chain)
std::vector< MCParticle > Secondaries
list of particles created by interaction of the primary particle
Definition: MCTruth.h:125
MCTruth container class description.
Simple struct to describe a MC particle.
Definition: MCTruth.h:31
std::array< float, 3 > Mom
hit momentum
Definition: MCTruth.h:105
SingleTreeChain::EventItr begin(SingleTreeChain &chain)
LayerVariable< TrMCHit > TrackMCHits
MC hits of the primary particle on tracker layers.
Definition: MCTruth.h:126
unsigned int pID
particle PID
Definition: MCTruth.h:103