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