Belle II Software  release-08-01-10
CDCMCHitCollectionLookUp.icc.h
1 /**************************************************************************
2  * basf2 (Belle II Analysis Software Framework) *
3  * Author: The Belle II Collaboration *
4  * *
5  * See git log for contributors and copyright holders. *
6  * This file is licensed under LGPL-3.0, see LICENSE.md. *
7  **************************************************************************/
8 #pragma once
9 
10 #include <tracking/trackFindingCDC/mclookup/CDCMCHitCollectionLookUp.h>
11 
12 #include <tracking/trackFindingCDC/eventdata/trajectories/CDCTrajectory3D.h>
13 
14 #include <tracking/trackFindingCDC/utilities/ReversedRange.h>
15 #include <tracking/trackFindingCDC/utilities/Functional.h>
16 
17 #include <cdc/dataobjects/CDCHit.h>
18 #include <cdc/dataobjects/CDCSimHit.h>
19 #include <mdst/dataobjects/MCParticle.h>
20 
21 #include <TDatabasePDG.h>
22 
23 namespace Belle2 {
28  namespace TrackFindingCDC {
29 
30  template <class ACDCHitCollection>
32  {
33  B2DEBUG(25, "Clearing CDCMCHitCollectionLookUp<ACDCHitCollection>");
34  }
35 
36  template <class ACDCHitCollection>
37  std::map<ITrackType, size_t>
39  const ACDCHitCollection& hits) const
40  {
41  const CDCMCHitLookUp& mcHitLookUp = CDCMCHitLookUp::getInstance();
42 
43  std::map<ITrackType, size_t> hitCountByMCTrackId;
44  for (const CDCHit* ptrHit : hits) {
45  ITrackType mcTrackId = mcHitLookUp.getMCTrackId(ptrHit);
46  // cppcheck-suppress stlFindInsert
47  if (hitCountByMCTrackId.count(mcTrackId) == 0) hitCountByMCTrackId[mcTrackId] = 0;
48  ++(hitCountByMCTrackId[mcTrackId]);
49  }
50  return hitCountByMCTrackId;
51  }
52 
53  template <class ACDCHitCollection>
55  const ACDCHitCollection& hits) const
56  {
57  std::map<ITrackType, size_t> hitCountByMCTrackId = getHitCountByMCTrackId(hits);
58 
59  size_t nHits = 0;
60  std::pair<ITrackType, size_t> highestHitCountMCTrackId(0, 0);
61  // cppcheck-suppress ignoredReturnValue
62  std::max_element(hitCountByMCTrackId.begin(), hitCountByMCTrackId.end(), LessOf<Second>());
63 
64  for (const auto& hitCountForMCTrackId : hitCountByMCTrackId) {
65 
66  nHits += hitCountForMCTrackId.second;
67 
68  if (highestHitCountMCTrackId.second < hitCountForMCTrackId.second) {
69  highestHitCountMCTrackId = hitCountForMCTrackId;
70  }
71  }
72 
73  const CDCMCHitLookUp& mcHitLookUp = CDCMCHitLookUp::getInstance();
74 
75  int correctRLVote = 0;
76  for (const auto& recoHit : hits) {
77  const CDCHit* hit = recoHit;
78  ERightLeft mcRLInfo = mcHitLookUp.getRLInfo(hit);
79  ERightLeft rlInfo = recoHit.getRLInfo();
80  if (rlInfo == mcRLInfo) {
81  ++correctRLVote;
82  } else {
83  --correctRLVote;
84  }
85  }
86 
87  const float purity = static_cast<float>(highestHitCountMCTrackId.second) / nHits;
88  return MCTrackIdPurityPair(highestHitCountMCTrackId.first, purity, correctRLVote);
89  }
90 
91  template <class ACDCHitCollection>
92  ITrackType
93  CDCMCHitCollectionLookUp<ACDCHitCollection>::getMCTrackId(const ACDCHitCollection* ptrHits) const
94  {
95  if (not ptrHits) return INVALID_ITRACK;
96  const ACDCHitCollection& hits = *ptrHits;
97  MCTrackIdPurityPair mcTrackIdAndPurity = getHighestPurity(hits);
98  if (mcTrackIdAndPurity.getPurity() >= m_minimalMatchPurity) {
99  return mcTrackIdAndPurity.getMCTrackId();
100  } else {
101  return INVALID_ITRACK;
102  }
103  }
104 
105  template <class ACDCHitCollection>
107  const ACDCHitCollection* ptrHits) const
108  {
109  if (not ptrHits) return INVALID_ITRACK;
110  const ACDCHitCollection& hits = *ptrHits;
111  MCTrackIdPurityPair mcTrackIdAndPurity = getHighestPurity(hits);
112  if (mcTrackIdAndPurity.getPurity() >= m_minimalMatchPurity) {
113  return mcTrackIdAndPurity.getCorrectRLVote();
114  } else {
115  return 0;
116  }
117  }
118 
119  template <class ACDCHitCollection>
120  double
121  CDCMCHitCollectionLookUp<ACDCHitCollection>::getRLPurity(const ACDCHitCollection* ptrHits) const
122  {
123  EForwardBackward fbInfo = isForwardOrBackwardToMCTrack(ptrHits);
124  if (fbInfo == EForwardBackward::c_Invalid) return NAN;
125 
126  int correctRLVote = getCorrectRLVote(ptrHits);
127 
128  if (fbInfo == EForwardBackward::c_Backward) {
129  correctRLVote = -correctRLVote;
130  }
131 
132  int nCorrectRL = (correctRLVote + ptrHits->size()) / 2;
133  float rlPurity = 1.0 * nCorrectRL / ptrHits->size();
134  return rlPurity;
135  }
136 
137  template <class ACDCHitCollection>
139  const ACDCHitCollection* ptrHits) const
140  {
141  const CDCHit* ptrHit = getFirstHit(ptrHits);
142  const CDCMCHitLookUp& mcHitLookUp = CDCMCHitLookUp::getInstance();
143  return mcHitLookUp.getMCParticle(ptrHit);
144  }
145 
146  template <class ACDCHitCollection>
147  const CDCHit*
148  CDCMCHitCollectionLookUp<ACDCHitCollection>::getFirstHit(const ACDCHitCollection* ptrHits) const
149  {
150  if (not ptrHits) return nullptr;
151  const ACDCHitCollection& hits = *ptrHits;
152 
153  ITrackType mcTrackId = getMCTrackId(ptrHits);
154  if (mcTrackId == INVALID_ITRACK) return nullptr;
155 
156  const CDCMCHitLookUp& mcHitLookUp = CDCMCHitLookUp::getInstance();
157 
158  for (const CDCHit* hit : hits) {
159  if (mcTrackId == mcHitLookUp.getMCTrackId(hit)) return hit;
160  }
161  return nullptr;
162  }
163 
164  template <class ACDCHitCollection>
165  const CDCHit*
166  CDCMCHitCollectionLookUp<ACDCHitCollection>::getLastHit(const ACDCHitCollection* ptrHits) const
167  {
168 
169  if (not ptrHits) return nullptr;
170  const ACDCHitCollection& hits = *ptrHits;
171 
172  ITrackType mcTrackId = getMCTrackId(ptrHits);
173  if (mcTrackId == INVALID_ITRACK) return nullptr;
174 
175  const CDCMCHitLookUp& mcHitLookUp = CDCMCHitLookUp::getInstance();
176 
177  for (const CDCHit* hit : reversedRange(hits)) {
178  if (mcTrackId == mcHitLookUp.getMCTrackId(hit)) return hit;
179  }
180  return nullptr;
181  }
182 
183  template <class ACDCHitCollection>
185  const ACDCHitCollection* ptrHits) const
186  {
187  Index firstInTrackId = getFirstInTrackId(ptrHits);
188  Index lastInTrackId = getLastInTrackId(ptrHits);
189  if (firstInTrackId == c_InvalidIndex or lastInTrackId == c_InvalidIndex) {
190  return EForwardBackward::c_Invalid;
191  } else if (firstInTrackId < lastInTrackId) {
192  return EForwardBackward::c_Forward;
193  } else if (firstInTrackId > lastInTrackId) {
194  return EForwardBackward::c_Backward;
195  } else if (firstInTrackId == lastInTrackId) {
196  return EForwardBackward::c_Unknown;
197  }
198  return EForwardBackward::c_Invalid;
199  }
200 
201  template <class ACDCHitCollection>
203  const ACDCHitCollection* ptrFromHits,
204  const ACDCHitCollection* ptrToHits) const
205  {
207  ITrackType fromMCTrackId = getMCTrackId(ptrFromHits);
208  if (fromMCTrackId == INVALID_ITRACK) return EForwardBackward::c_Invalid;
209 
210  ITrackType toMCTrackId = getMCTrackId(ptrToHits);
211  if (toMCTrackId == INVALID_ITRACK) return EForwardBackward::c_Invalid;
212 
213  if (fromMCTrackId != toMCTrackId) return EForwardBackward::c_Invalid;
214 
215  // Check if the segments are sensable on their own
216  EForwardBackward fromFBInfo = isForwardOrBackwardToMCTrack(ptrFromHits);
217  if (fromFBInfo == EForwardBackward::c_Invalid) return EForwardBackward::c_Invalid;
218 
219  EForwardBackward toFBInfo = isForwardOrBackwardToMCTrack(ptrToHits);
220  if (toFBInfo == EForwardBackward::c_Invalid) return EForwardBackward::c_Invalid;
221 
222  if (fromFBInfo != toFBInfo) return EForwardBackward::c_Invalid;
223 
224  {
225  // Now check if hits are aligned within their common track
226  // Index firstNPassedSuperLayersOfFromHits = getFirstNPassedSuperLayers(ptrFromHits);
227  Index lastNPassedSuperLayersOfFromHits = getLastNPassedSuperLayers(ptrFromHits);
228  // if (firstNPassedSuperLayersOfFromHits == c_InvalidIndex) return
229  // EForwardBackward::c_Invalid;
230  if (lastNPassedSuperLayersOfFromHits == c_InvalidIndex) return EForwardBackward::c_Invalid;
231 
232  Index firstNPassedSuperLayersOfToHits = getFirstNPassedSuperLayers(ptrToHits);
233  // Index lastNPassedSuperLayersOfToHits = getLastNPassedSuperLayers(ptrToHits);
234  if (firstNPassedSuperLayersOfToHits == c_InvalidIndex) return EForwardBackward::c_Invalid;
235  // if (lastNPassedSuperLayersOfToHits == c_InvalidIndex) return EForwardBackward::c_Invalid;
236 
237  if (lastNPassedSuperLayersOfFromHits < firstNPassedSuperLayersOfToHits) {
238  if (fromFBInfo == EForwardBackward::c_Forward and
239  toFBInfo == EForwardBackward::c_Forward) {
240  return EForwardBackward::c_Forward;
241  } else {
242  return EForwardBackward::c_Invalid;
243  }
244  } else if (firstNPassedSuperLayersOfToHits < lastNPassedSuperLayersOfFromHits) {
245  if (fromFBInfo == EForwardBackward::c_Backward and
246  toFBInfo == EForwardBackward::c_Backward) {
247  return EForwardBackward::c_Backward;
248  } else {
249  return EForwardBackward::c_Invalid;
250  }
251  }
252  }
253 
254  {
255  // Now we are in the same true segment with both segments
256  // Index firstInTrackSegmentIdOfFromHits = getFirstInTrackSegmentId(ptrFromHits);
257  Index lastInTrackSegmentIdOfFromHits = getLastInTrackSegmentId(ptrFromHits);
258  // if (firstInTrackSegmentIdOfFromHits == c_InvalidIndex) return
259  // EForwardBackward::c_Invalid;
260  if (lastInTrackSegmentIdOfFromHits == c_InvalidIndex) return EForwardBackward::c_Invalid;
261 
262  Index firstInTrackSegmentIdOfToHits = getFirstInTrackSegmentId(ptrToHits);
263  // Index lastInTrackSegmentIdOfToHits = getLastInTrackSegmentId(ptrToHits);
264  if (firstInTrackSegmentIdOfToHits == c_InvalidIndex) return EForwardBackward::c_Invalid;
265  // if (lastInTrackSegmentIdOfToHits == c_InvalidIndex) return EForwardBackward::c_Invalid;
266 
267  if (lastInTrackSegmentIdOfFromHits < firstInTrackSegmentIdOfToHits) {
268  if (fromFBInfo == EForwardBackward::c_Forward and
269  toFBInfo == EForwardBackward::c_Forward) {
270  return EForwardBackward::c_Forward;
271  } else {
272  return EForwardBackward::c_Invalid;
273  }
274  } else if (firstInTrackSegmentIdOfToHits < lastInTrackSegmentIdOfFromHits) {
275  // Test if to segment lies before in the mc track
276  // Hence the whole pair of segments is reverse to the track direction of flight
277  if (fromFBInfo == EForwardBackward::c_Backward and
278  toFBInfo == EForwardBackward::c_Backward) {
279  return EForwardBackward::c_Backward;
280  } else {
281  return EForwardBackward::c_Invalid;
282  }
283  }
284  }
285 
286  {
287  // Now we are in the same true segment with both of the hits
288  // Index firstInTrackIdOfFromHits = getFirstInTrackId(ptrFromHits);
289  Index lastInTrackIdOfFromHits = getLastInTrackId(ptrFromHits);
290  // if (firstInTrackIdOfFromHits == c_InvalidIndex) return EForwardBackward::c_Invalid;
291  if (lastInTrackIdOfFromHits == c_InvalidIndex) return EForwardBackward::c_Invalid;
292 
293  Index firstInTrackIdOfToHits = getFirstInTrackId(ptrToHits);
294  // Index lastInTrackIdOfToHits = getLastInTrackId(ptrToHits);
295  if (firstInTrackIdOfToHits == c_InvalidIndex) return EForwardBackward::c_Invalid;
296  // if (lastInTrackIdOfToHits == c_InvalidIndex) return EForwardBackward::c_Invalid;
297 
298  // Relax conditions somewhat such that segments may overlap at the borders.
299 
300  if (lastInTrackIdOfFromHits - 1 < firstInTrackIdOfToHits + 1) {
301  if (fromFBInfo == EForwardBackward::c_Forward and
302  toFBInfo == EForwardBackward::c_Forward) {
303  return EForwardBackward::c_Forward;
304  }
305  }
306 
307  if (firstInTrackIdOfToHits - 1 < lastInTrackIdOfFromHits + 1) {
308  if (fromFBInfo == EForwardBackward::c_Backward and
309  toFBInfo == EForwardBackward::c_Backward) {
310  return EForwardBackward::c_Backward;
311  }
312  }
313  }
314  // FIXME: Handle intertwined hits that are not cleanly consecutive along the track?
315  return EForwardBackward::c_Invalid;
316  }
317 
318  template <class ACDCHitCollection>
320  const ACDCHitCollection* ptrFromHits,
321  const ACDCHitCollection* ptrToHits) const
322  {
323  EForwardBackward result = areAlignedInMCTrack(ptrFromHits, ptrToHits);
324  if (result == EForwardBackward::c_Invalid) return result;
325 
326  int fromCorrectRLVote = getCorrectRLVote(ptrFromHits);
327  int toCorrectRLVote = getCorrectRLVote(ptrToHits);
328 
329  if (result == EForwardBackward::c_Backward) {
330  fromCorrectRLVote = -fromCorrectRLVote;
331  toCorrectRLVote = -toCorrectRLVote;
332  }
333 
334  int fromNCorrectRL = (fromCorrectRLVote + ptrFromHits->size()) / 2;
335  int toNCorrectRL = (toCorrectRLVote + ptrToHits->size()) / 2;
336 
337  float fromRLPurity = 1.0 * fromNCorrectRL / ptrFromHits->size();
338  float toRLPurity = 1.0 * toNCorrectRL / ptrToHits->size();
339 
340  // Require the minimal rl purity and also at least 2.5 correct hits
341  // (cut chosen to require all correct in single hit triplet segment)
342  if (fromRLPurity > m_minimalRLPurity and toRLPurity > m_minimalRLPurity and
343  fromNCorrectRL > 2.5 and toNCorrectRL > 2.5) {
344  return result;
345  }
346 
347  return EForwardBackward::c_Invalid;
348  }
349 
350  template <class ACDCHitCollection>
352  const ACDCHitCollection* ptrHits) const
353  {
354  if (not ptrHits) {
355  B2WARNING("Segment is nullptr. Could not get fit.");
356  return CDCTrajectory3D();
357  }
358 
359  const CDCMCHitLookUp& mcHitLookUp = CDCMCHitLookUp::getInstance();
360 
361  const CDCHit* ptrFirstHit = getFirstHit(ptrHits);
362  const CDCSimHit* ptrPrimarySimHit = mcHitLookUp.getClosestPrimarySimHit(ptrFirstHit);
363 
364  if (not ptrPrimarySimHit) {
365  // If there is no primary SimHit simply use the secondary simhit as reference
366  ptrPrimarySimHit = mcHitLookUp.getSimHit(ptrFirstHit);
367  if (not ptrPrimarySimHit) {
368  return CDCTrajectory3D();
369  }
370  }
371 
372  const CDCSimHit& primarySimHit = *ptrPrimarySimHit;
373 
374  Vector3D mom3D{primarySimHit.getMomentum()};
375  Vector3D pos3D{primarySimHit.getPosTrack()};
376  double time{primarySimHit.getFlightTime()};
377 
378  int pdgCode = primarySimHit.getPDGCode();
379  const TParticlePDG* ptrTPDGParticle = TDatabasePDG::Instance()->GetParticle(pdgCode);
380 
381  if (not ptrTPDGParticle) {
382  B2WARNING("No particle for PDG code " << pdgCode << ". Could not get fit");
383  return CDCTrajectory3D();
384  }
385 
386  const TParticlePDG& tPDGParticle = *ptrTPDGParticle;
387 
388  double charge = tPDGParticle.Charge() / 3.0;
389 
390  ESign chargeSign = sign(charge);
391 
392  CDCTrajectory3D trajectory3D(pos3D, time, mom3D, charge);
393 
394  ESign settedChargeSign = trajectory3D.getChargeSign();
395 
396  if (chargeSign != settedChargeSign) {
397  B2WARNING("Charge sign of mc particle is not the same as the one of the fit");
398  }
399 
400  return trajectory3D;
401  }
402  }
404 }
Class containing the result of the unpacker in raw data and the result of the digitizer in simulation...
Definition: CDCHit.h:40
Example Detector.
Definition: CDCSimHit.h:21
int getPDGCode() const
The method to get PDG code.
Definition: CDCSimHit.h:178
double getFlightTime() const
The method to get flight time.
Definition: CDCSimHit.h:184
B2Vector3D getPosTrack() const
The method to get position on the track.
Definition: CDCSimHit.h:217
B2Vector3D getMomentum() const
The method to get momentum.
Definition: CDCSimHit.h:193
A Class to store the Monte Carlo particle information.
Definition: MCParticle.h:32
EForwardBackward isForwardOrBackwardToMCTrack(const ACDCHitCollection *ptrHits) const
Returns the orientation of the collection of hits relative to its matched track.
ITrackType getMCTrackId(const ACDCHitCollection *ptrHits) const
Getter for the Monte Carlo track id matched to this collection of hits.
std::map< ITrackType, size_t > getHitCountByMCTrackId(const ACDCHitCollection &hits) const
Fill a map with the number of hits for each track id contained in the given hit range.
MCTrackIdPurityPair getHighestPurity(const ACDCHitCollection &hits) const
Get the track id with the highest corresponding purity.
const CDCHit * getLastHit(const ACDCHitCollection *ptrHits) const
Getter for the last hit in the collection of hits which has the Monte Carlo track id matched to this ...
EForwardBackward areAlignedInMCTrackWithRLCheck(const ACDCHitCollection *ptrFromHits, const ACDCHitCollection *ptrToHits) const
Returns if the second collection of hits follows the first collection of hits in their common Monte C...
const MCParticle * getMCParticle(const ACDCHitCollection *ptrHits) const
Getter for the mc particle matched to this collection of hits.
int getCorrectRLVote(const ACDCHitCollection *ptrHits) const
Getter for the difference of correct versus incorrect right left passage informations.
void clear()
Clears all Monte Carlo information left from the last event.
const CDCHit * getFirstHit(const ACDCHitCollection *ptrHits) const
Getter for the first hit in the collection of hits which has the Monte Carlo track id matched to this...
double getRLPurity(const ACDCHitCollection *ptrHits) const
Getter for the right left passge purity which respects the forward backward reconstruction.
CDCTrajectory3D getTrajectory3D(const ACDCHitCollection *ptrHits) const
Returns the trajectory of the collection of hits.
EForwardBackward areAlignedInMCTrack(const ACDCHitCollection *ptrFromHits, const ACDCHitCollection *ptrToHits) const
Returns if the second collection of hits follows the first collection of hits in their common Monte C...
Interface class to the Monte Carlo information for individual hits.
const CDCSimHit * getClosestPrimarySimHit(const CDCHit *ptrHit) const
Getter for the closest simulated hit of a primary particle to the given hit - may return nullptr of n...
ITrackType getMCTrackId(const CDCHit *ptrHit) const
Returns the track id for the hit.
const Belle2::MCParticle * getMCParticle(const CDCHit *ptrHit) const
Getter for the MCParticle which is related to the CDCHit contained in the given wire hit.
const Belle2::CDCSimHit * getSimHit(const CDCHit *ptrHit) const
Getter for the CDCSimHit which is related to the CDCHit contained in the given wire hit.
static const CDCMCHitLookUp & getInstance()
Getter for the singletone instance.
ERightLeft getRLInfo(const CDCHit *ptrHit) const
Returns the true right left passage information.
Particle full three dimensional trajectory.
ESign getChargeSign() const
Gets the charge sign of the trajectory.
A three dimensional vector.
Definition: Vector3D.h:33
ESign
Enumeration for the distinct sign values of floating point variables.
Definition: ESign.h:27
EForwardBackward
Enumeration to represent the distinct possibilities of the right left passage information.
ERightLeft
Enumeration to represent the distinct possibilities of the right left passage.
Definition: ERightLeft.h:25
Abstract base class for different kinds of events.
Functor factory turning a binary functor and two functors into a new functor which executes the binar...
Definition: Functional.h:127
Structure representing a matched Monte Carlo track id with the corresponding purity.
int getCorrectRLVote() const
Getter for the rl vote.
float getPurity() const
Getter for the purity.
ITrackType getMCTrackId() const
Getter for the Monte Carlo track Id.