NAIA  1.1.1
MCTruthFill.cpp
Go to the documentation of this file.
1 #include "Containers/MCTruth.h"
2 
3 #include "TDatabasePDG.h"
4 
5 #include <algorithm>
6 #include <optional>
7 
8 namespace NAIA {
9 
10 constexpr float amu = 0.93146;
11 
12 MCParticle GetMCParticle(const MCEventgR &mcp) {
13  // FIXME: It looks like G3 vs G4 is only determined by the absolute value of PartInfo.
14  // The sign is mainly used to distinguish between primary (positive) and secondary (negative) particles
15  // Except for the primary generation point. In that case PartInfo has a large value (and it could also be
16  // negative... KUDOS TO WHOEVER MADE THIS BRILLIANT AND IDIOTIC DECISION)
17  int pdg{0};
18  switch (std::abs(mcp.PartInfo)) {
19  case 1:
20  pdg = TDatabasePDG::Instance()->ConvertGeant3ToPdg(mcp.Particle);
21  break;
22  case 2:
23  pdg = mcp.Particle;
24  break;
25  default:
26  // FIXME: Check if the primary is always G3-coded
27  pdg = TDatabasePDG::Instance()->ConvertGeant3ToPdg(mcp.Particle);
28  break;
29  }
30 
31  return {pdg,
32  static_cast<int>(mcp.Charge),
33  static_cast<unsigned int>(TMath::Nint(mcp.Mass / amu)),
34  mcp.Mass,
35  {TVector3{mcp.Coo[0], mcp.Coo[1], mcp.Coo[2]}},
36  {mcp.Momentum * TVector3{mcp.Dir[0], mcp.Dir[1], mcp.Dir[2]}},
37  mcp.trkID,
38  mcp.parentID,
39  mcp.Nskip >> 24,
40  mcp.Nskip & 0xFFFFFF};
41 }
42 
43 unsigned int TkIDToLayerJ(int tkID) {
44  tkID = abs(tkID);
45 
46  unsigned int layerOld = tkID / 100;
47  switch (layerOld) {
48  case 8:
49  return 1;
50  break;
51  case 9:
52  return 9;
53  default:
54  return layerOld + 1;
55  }
56 }
57 
58 std::optional<MCTruthPlusData::TrMCHit> GetTrMCHit(TrTrackR *pTrTrack, unsigned int jLayer, float tof_beta,
59  double match_radius = 0.1) {
60  AMSEventR *event = AMSEventR::Head();
61  if (!event)
62  throw std::runtime_error("Invalid pointer for AMSEventR::Head");
63  if (event->nMCEventgC() == 0)
64  throw std::runtime_error("No MCEventg information in this event");
65 
66  if (!pTrTrack->TestHitLayerJ(jLayer))
67  return {};
68 
69  AMSPlaneM plm = pTrTrack->GetHitCooLJN(jLayer);
70  TVector3 mglob = plm.getMGlobal();
71  AMSPoint point = AMSPoint(mglob.x(), mglob.y(), mglob.z());
72 
73  // Get all MCClusters within the match radius
74  std::vector<TrMCClusterR> mcHits{};
75  std::copy_if(begin(event->TrMCCluster()), end(event->TrMCCluster()), std::back_inserter(mcHits),
76  [&point, &match_radius](TrMCClusterR &hit) { return hit.GetXgl().dist(point) < match_radius; });
77 
78  // Fail if no hits within match_radius
79  if (mcHits.empty())
80  return {};
81 
82  decltype(mcHits)::iterator mcclusterIt;
83 
84  if (pTrTrack->GetInnerQ(tof_beta) > 1.5) {
85  // Get the cluster with the maximum edep within match_radius
86  mcclusterIt = std::max_element(begin(mcHits), end(mcHits),
87  [](TrMCClusterR &cl1, TrMCClusterR &cl2) { return cl1.GetEdep() < cl2.GetEdep(); });
88  } else {
89  // Get the cluster closest to the track
90  mcclusterIt = std::min_element(begin(mcHits), end(mcHits), [&point](TrMCClusterR &cl1, TrMCClusterR &cl2) {
91  return cl1.GetXgl().dist(point) < cl2.GetXgl().dist(point);
92  });
93  }
94 
96  mcHit.pID = TDatabasePDG::Instance()->ConvertGeant3ToPdg(mcclusterIt->GetPart());
97  for (unsigned int ic = 0; ic < 3; ic++) {
98  mcHit.Coo[ic] = mcclusterIt->GetXgl()[ic];
99  mcHit.Mom[ic] = mcclusterIt->GetMom()[ic];
100  }
101 
102  return mcHit;
103 }
104 
105 auto particleSorter = [](const MCEventgR &a, const MCEventgR &b) -> bool {
106  if (a.parentID < b.parentID)
107  return true;
108  else if (a.parentID > b.parentID)
109  return false;
110  else {
111  if (a.Coo[2] > b.Coo[2])
112  return true;
113  else if (a.Coo[2] < b.Coo[2])
114  return false;
115  else
116  return a.Momentum > b.Momentum;
117  }
118 };
119 
120 bool MCTruthBaseData::Fill(AMSEventR *evPtr) {
121 
122  // sort all MC particles by interaction point/momentum
123  std::sort(begin(evPtr->MCEventg()), end(evPtr->MCEventg()), particleSorter);
124 
125  auto primIt = std::find_if(begin(evPtr->MCEventg()), end(evPtr->MCEventg()),
126  [](const MCEventgR &mcp) { return mcp.Coo[2] > 160.0; });
127 
128  if (primIt == end(evPtr->MCEventg())) {
129  throw std::runtime_error("No generation point found for primary particle (with CooZ > 160 cm)");
130  }
131 
132  constexpr float z_tolerance = 2.0f;
133 
134  Primary = GetMCParticle(*primIt);
135  for (const auto &mcp : evPtr->MCEventg()) {
136  if (mcp.parentID != 0)
137  break;
138 
139  auto hIt = std::find_if(std::next(begin(MCTruth::MCHeightsZ)), end(MCTruth::MCHeightsZ),
140  [&mcp](float height) { return fabs(mcp.Coo[2] - height) < z_tolerance; });
141  if (hIt != end(MCTruth::MCHeightsZ)) {
142  auto position = std::distance(begin(MCTruth::MCHeightsZ), hIt);
143  Primary.Momentum.resize(position + 1);
144  Primary.Momentum[position] = mcp.Momentum * TVector3{mcp.Dir[0], mcp.Dir[1], mcp.Dir[2]};
145 
146  Primary.Position.resize(position + 1);
147  Primary.Position[position] = TVector3{mcp.Coo[0], mcp.Coo[1], mcp.Coo[2]};
148  }
149  }
150 
151  return true;
152 }
153 
154 bool MCTruthPlusData::Fill(AMSEventR *evPtr) {
155 
156  // this should already be sorted, but you never know...
157  if (!std::is_sorted(begin(evPtr->MCEventg()), end(evPtr->MCEventg()), particleSorter)) {
158  // sort all MC particles by interaction point/momentum
159  std::sort(begin(evPtr->MCEventg()), end(evPtr->MCEventg()), particleSorter);
160  }
161 
162  const MCEventgR &firstPrim = evPtr->MCEventg()[0];
163  for (MCEventgR &mcp : evPtr->MCEventg()) {
164  // don't store the primary
165  if (mcp.parentID == 0)
166  continue;
167 
168  if (mcp.Momentum / firstPrim.Momentum > 0.005) {
169  Secondaries.push_back(GetMCParticle(mcp));
170  }
171  }
172 
173  return true;
174 }
175 
176 bool MCTruthPlusData::FillTrMCHit(TrTrackR *pTrTrack, float tof_beta) {
177  for (unsigned int ij = 0; ij < 9; ij++) {
178  if (auto mcHit = GetTrMCHit(pTrTrack, ij + 1, tof_beta); mcHit)
179  TrackMCHits[ij] = mcHit.value();
180  }
181  return true;
182 }
183 } // namespace NAIA
NAIA::end
NAIAChain::EventItr end(NAIAChain &chain)
Definition: NAIAChain.h:298
NAIA::GetMCParticle
MCParticle GetMCParticle(const MCEventgR &mcp)
Definition: MCTruthFill.cpp:12
NAIA::amu
constexpr float amu
Definition: MCTruthFill.cpp:10
NAIA::MCParticle
Simple struct to describe a MC particle.
Definition: MCTruth.h:32
NAIA::MCTruthPlusData::TrMCHit::Coo
std::array< float, 3 > Coo
hit position
Definition: MCTruth.h:132
NAIA
Definition: Event.h:13
MCTruth.h
MCTruth container class description.
NAIA::MCParticle::Mass
float Mass
particle mass in GeV/c^2
Definition: MCTruth.h:36
NAIA::particleSorter
auto particleSorter
Definition: MCTruthFill.cpp:105
NAIA::MCTruth::MCHeightsZ
constexpr std::array< float, numMCHeights > MCHeightsZ
Definition: Utils.h:394
NAIA::MCTruthPlusData::TrMCHit::pID
int pID
particle PID
Definition: MCTruth.h:131
NAIA::MCTruthPlusData::TrMCHit
Simple struct for MC tracker hits.
Definition: MCTruth.h:130
NAIA::GetTrMCHit
std::optional< MCTruthPlusData::TrMCHit > GetTrMCHit(TrTrackR *pTrTrack, unsigned int jLayer, float tof_beta, double match_radius=0.1)
Definition: MCTruthFill.cpp:58
NAIA::begin
NAIAChain::EventItr begin(NAIAChain &chain)
Definition: NAIAChain.h:297
NAIA::MCTruthPlusData::TrMCHit::Mom
std::array< float, 3 > Mom
hit momentum
Definition: MCTruth.h:133
NAIA::TkIDToLayerJ
unsigned int TkIDToLayerJ(int tkID)
Definition: MCTruthFill.cpp:43