Belle II Software development
CDCMCTrackStore.cc
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
9#include <tracking/trackFindingCDC/mclookup/CDCMCTrackStore.h>
10
11#include <tracking/trackFindingCDC/mclookup/CDCSimHitLookUp.h>
12#include <tracking/trackFindingCDC/mclookup/CDCMCMap.h>
13#include <tracking/trackFindingCDC/mclookup/CDCMCManager.h>
14
15#include <cdc/topology/CDCWireTopology.h>
16
17#include <tracking/trackingUtilities/utilities/Functional.h>
18#include <tracking/trackingUtilities/utilities/Algorithms.h>
19
20#include <cdc/dataobjects/CDCHit.h>
21#include <cdc/dataobjects/CDCSimHit.h>
22#include <mdst/dataobjects/MCParticle.h>
23
24#include <Math/Vector3D.h>
25
26using namespace Belle2;
27using namespace CDC;
28using namespace TrackFindingCDC;
29using namespace TrackingUtilities;
30
35
36
38{
39
40 B2DEBUG(29, "In CDCMCTrackStore::clear()");
41
42 m_ptrMCMap = nullptr;
43
46
47 m_inTrackIds.clear();
48 m_inTrackSegmentIds.clear();
50 m_nLoops.clear();
51
52}
53
54
55
56void CDCMCTrackStore::fill(const CDCMCMap* ptrMCMap, const CDCSimHitLookUp* ptrSimHitLookUp)
57{
58
59 B2DEBUG(29, "In CDCMCTrackStore::fill()");
60 clear();
61
62 m_ptrMCMap = ptrMCMap;
63 m_ptrSimHitLookUp = ptrSimHitLookUp;
64
65 // Put the right hits into the right track
67
68 // Split the tracks into segments
70
71 // Assign the reverse mapping from CDCHits to position in track
73
74 // Assigns the reverse mapping from CDCHits to segment ids
76
77 // Assigns the reverse mapping from CDCHits to the number of already traversed superlayers
79
80 B2DEBUG(28, "m_mcTracksByMCParticleIdx.size(): " << m_mcTracksByMCParticleIdx.size());
81 B2DEBUG(28, "m_mcSegmentsByMCParticleIdx.size(): " << m_mcSegmentsByMCParticleIdx.size());
82
83 B2DEBUG(28, "m_inTrackIds.size(): " << m_inTrackIds.size());
84 B2DEBUG(28, "m_inTrackSegmentIds.size() " << m_inTrackSegmentIds.size());
85 B2DEBUG(28, "m_nPassedSuperLayers.size(): " << m_nPassedSuperLayers.size());
86 B2DEBUG(28, "m_nLoops.size(): " << m_nLoops.size());
87
88}
89
90
92{
93 if (not m_ptrMCMap) {
94 B2WARNING("CDCMCMap not set. Cannot create tracks");
95 return;
96 }
97
98 const CDCMCMap& mcMap = *m_ptrMCMap;
99
100 for (const auto& relation : mcMap.getHitsByMCParticle()) {
101
102 const MCParticle* ptrMCParticle = std::get<const MCParticle* const>(relation);
103 const CDCHit* ptrHit = std::get<const CDCHit*>(relation);
104
105 if (not mcMap.isBackground(ptrHit) and ptrMCParticle) {
106
107 ITrackType mcParticleIdx = ptrMCParticle->getArrayIndex();
108 //Append hit to its own track
109 m_mcTracksByMCParticleIdx[mcParticleIdx].push_back(ptrHit);
110 }
111 }
112
113
114 //Sort the tracks along the time of flight
115 for (std::pair<const ITrackType, CDCHitVector>& mcTrackAndMCParticleIdx : m_mcTracksByMCParticleIdx) {
116
117 //int mcParticleIdx = mcTrackAndMCParticleIdx.first;
118 CDCHitVector& mcTrack = mcTrackAndMCParticleIdx.second;
119 arrangeMCTrack(mcTrack);
120
121 }
122
123}
124
126{
127 for (std::pair<const ITrackType, CDCHitVector>& mcTrackAndMCParticleIdx : m_mcTracksByMCParticleIdx) {
128
129 ITrackType mcParticleIdx = mcTrackAndMCParticleIdx.first;
130 CDCHitVector& mcTrack = mcTrackAndMCParticleIdx.second;
131
132 if (mcTrack.empty()) continue;
133 std::vector<CDCHitVector>& mcSegments = m_mcSegmentsByMCParticleIdx[mcParticleIdx];
134 mcSegments.clear();
135
136 // Split track into runs in the same superlayer
137 auto superLayerRanges = adjacent_groupby(mcTrack.begin(), mcTrack.end(), [](const CDCHit * hit) {
138 return hit->getISuperLayer();
139 });
140
141 std::vector<CDCHitVector> superLayerRuns;
142 for (const auto& superLayerRange : superLayerRanges) {
143 superLayerRuns.push_back({superLayerRange.begin(), superLayerRange.end()});
144 }
145
146 std::vector<std::vector<CDCHitVector>::iterator> smallSuperLayerRuns;
147 for (auto itSuperLayerRun = superLayerRuns.begin();
148 itSuperLayerRun != superLayerRuns.end();
149 ++itSuperLayerRun) {
150 if (itSuperLayerRun->size() < 3) smallSuperLayerRuns.push_back(itSuperLayerRun);
151 }
152
153 // Merge small run to an adjacent run
154 for (auto itSuperLayerRun : smallSuperLayerRuns) {
155 ISuperLayer iSL = itSuperLayerRun->front()->getISuperLayer();
156
157 // Look in both directions to adopt the hits in this small runs
158 auto itSuperLayerRunBefore = superLayerRuns.end();
159 int hitDistanceBefore = INT_MAX;
160 if (std::distance(superLayerRuns.begin(), itSuperLayerRun) >= 2) {
161 itSuperLayerRunBefore = itSuperLayerRun - 2;
162 if (itSuperLayerRunBefore->front()->getISuperLayer() == iSL) {
163 hitDistanceBefore = (itSuperLayerRunBefore - 1)->size();
164 } else {
165 itSuperLayerRunBefore = superLayerRuns.end();
166 }
167 }
168
169 auto itSuperLayerRunAfter = superLayerRuns.end();
170 int hitDistanceAfter = INT_MAX;
171 if (std::distance(itSuperLayerRun, superLayerRuns.end()) > 2) {
172 itSuperLayerRunAfter = itSuperLayerRun + 2;
173 if (itSuperLayerRunAfter->front()->getISuperLayer() == iSL) {
174 hitDistanceAfter = (itSuperLayerRunAfter + 1)->size();
175 } else {
176 itSuperLayerRunAfter = superLayerRuns.end();
177 }
178 }
179
180 auto itMergeSuperLayerRun = superLayerRuns.end();
181 bool mergeBefore = false;
182 if (hitDistanceBefore < hitDistanceAfter) {
183 itMergeSuperLayerRun = itSuperLayerRunBefore;
184 mergeBefore = true;
185 } else {
186 itMergeSuperLayerRun = itSuperLayerRunAfter;
187 mergeBefore = false;
188 }
189
190 if (itMergeSuperLayerRun == superLayerRuns.end()) continue;
191 else if (mergeBefore) {
192 itMergeSuperLayerRun->insert(itMergeSuperLayerRun->end(), itSuperLayerRun->begin(), itSuperLayerRun->end());
193 itSuperLayerRun->clear();
194 } else {
195 itMergeSuperLayerRun->insert(itMergeSuperLayerRun->begin(), itSuperLayerRun->begin(), itSuperLayerRun->end());
196 itSuperLayerRun->clear();
197 }
198 }
199
200 // Remove empty small runs
201 erase_remove_if(superLayerRuns, Size() == 0u);
202
203 // Concat the runs that are now in the same superlayer
204 auto mergeSameSuperLayer = [](CDCHitVector & lhs, CDCHitVector & rhs) {
205 if (lhs.empty() or rhs.empty()) return true;
206 if (lhs.front()->getISuperLayer() != rhs.front()->getISuperLayer()) return false;
207 lhs.insert(lhs.end(), rhs.begin(), rhs.end());
208 rhs.clear();
209 return true;
210 };
211 erase_unique(superLayerRuns, mergeSameSuperLayer);
212
213 // Now analyse the runs in turn and break them in the connected segments
214 for (const CDCHitVector& superLayerRun : superLayerRuns) {
215 const CDCWireTopology& wireTopology = CDCWireTopology::getInstance();
216 auto areNeighbors = [&wireTopology](const CDCHit * lhs, const CDCHit * rhs) {
217 WireID lhsWireID(lhs->getISuperLayer(), lhs->getILayer(), lhs->getIWire());
218 WireID rhsWireID(rhs->getISuperLayer(), rhs->getILayer(), rhs->getIWire());
219
220 return (wireTopology.arePrimaryNeighbors(lhsWireID, rhsWireID) or
221 wireTopology.areSeconaryNeighbors(lhsWireID, rhsWireID) or
222 lhsWireID == rhsWireID);
223 };
224
225 auto segmentRanges = unique_ranges(superLayerRun.begin(), superLayerRun.end(), areNeighbors);
226
227 for (const ConstVectorRange<const CDCHit*>& segmentRange : segmentRanges) {
228 mcSegments.emplace_back(segmentRange.begin(), segmentRange.end());
229 }
230 } // end for superLayerRuns
231
232 // Lets sort them along for the time of flight.
233 for (CDCHitVector& mcSegment : mcSegments) {
234 arrangeMCTrack(mcSegment);
235 }
236 } // End for mc track
237}
238
240{
241 if (not m_ptrMCMap) {
242 B2WARNING("CDCMCMap not set. Cannot sort track");
243 return;
244 }
245
246 const CDCSimHitLookUp& simHitLookUp = *m_ptrSimHitLookUp;
247
248 std::stable_sort(mcTrack.begin(), mcTrack.end(),
249 [&simHitLookUp](const CDCHit * ptrHit, const CDCHit * ptrOtherHit) -> bool {
250
251 const CDCSimHit* ptrSimHit = simHitLookUp.getClosestPrimarySimHit(ptrHit);
252 const CDCSimHit* ptrOtherSimHit = simHitLookUp.getClosestPrimarySimHit(ptrOtherHit);
253
254 if (not ptrSimHit)
255 {
256 B2FATAL("No CDCSimHit for CDCHit");
257 }
258
259 if (not ptrOtherSimHit)
260 {
261 B2FATAL("No CDCSimHit for CDCHit");
262 }
263
264 double secondaryFlightTime = ptrSimHit->getFlightTime();
265 double otherSecondaryFlightTime = ptrOtherSimHit->getFlightTime();
266
268 return (secondaryFlightTime < std::fmin(INFINITY, otherSecondaryFlightTime));
269 });
270
271}
272
273
274
275
276
277
279{
280
281 for (const std::pair<ITrackType, CDCHitVector> mcTrackAndMCParticleIdx : getMCTracksByMCParticleIdx()) {
282
283 const CDCHitVector& mcTrack = mcTrackAndMCParticleIdx.second;
284
285 //Fill the in track ids
286 int iHit = -1;
287 for (const CDCHit* ptrHit : mcTrack) {
288 ++iHit;
289 m_inTrackIds[ptrHit] = iHit;
290 }
291 }
292
293}
294
296{
297 for (const std::pair<ITrackType, std::vector<CDCHitVector> > mcSegmentsAndMCParticleIdx : getMCSegmentsByMCParticleIdx()) {
298 const std::vector<CDCHitVector>& mcSegments = mcSegmentsAndMCParticleIdx.second;
299
300 int iSegment = -1;
301 for (const CDCHitVector& mcSegment : mcSegments) {
302 ++iSegment;
303 for (const CDCHit* ptrHit : mcSegment) {
304
305 m_inTrackSegmentIds[ptrHit] = iSegment;
306 }
307 }
308 }
309
310}
311
313{
314
315 for (const std::pair<ITrackType, std::vector<CDCHitVector> > mcSegmentsAndMCParticleIdx : getMCSegmentsByMCParticleIdx()) {
316 const std::vector<CDCHitVector>& mcSegments = mcSegmentsAndMCParticleIdx.second;
317
318 const CDCHitVector* ptrLastMCSegment = nullptr;
319 int nPassedSuperLayers = 0;
320 int nLoops = 0;
321
322 for (const CDCHitVector& mcSegment : mcSegments) {
323 if (ptrLastMCSegment and changedSuperLayer(*ptrLastMCSegment, mcSegment)) {
324 ++nPassedSuperLayers;
325
326 // Increase the superlayer number if the track leaves the CDC for the inner volume.
327 // Feel free to do something smarter here.
328 if (ptrLastMCSegment->front()->getISuperLayer() == 0 and
329 mcSegment.front()->getISuperLayer() == 0) {
330 ++nLoops;
331 }
332 }
333
334 for (const CDCHit* ptrHit : mcSegment) {
335 m_nPassedSuperLayers[ptrHit] = nPassedSuperLayers;
336 m_nLoops[ptrHit] = nLoops;
337 }
338
339 ptrLastMCSegment = &mcSegment;
340
341 }
342 }
343}
344
345bool CDCMCTrackStore::changedSuperLayer(const CDCHitVector& mcSegment, const CDCHitVector& nextMCSegment) const
346{
347 const CDCSimHitLookUp& simHitLookUp = *m_ptrSimHitLookUp;
348 const CDCHit* ptrHit = mcSegment.front();
349 const CDCHit* ptrNextHit = nextMCSegment.front();
350
351 assert(ptrHit);
352 assert(ptrNextHit);
353
354 const CDCHit& hit = *ptrHit;
355 const CDCHit& nextHit = *ptrNextHit;
356
357 if (hit.getISuperLayer() != nextHit.getISuperLayer()) {
358 return true;
359 } else if (hit.getISuperLayer() == 0) {
360 const CDCSimHit* ptrSimHit = simHitLookUp.getClosestPrimarySimHit(ptrHit);
361 const CDCSimHit* ptrNextSimHit = simHitLookUp.getClosestPrimarySimHit(ptrNextHit);
362
363 ROOT::Math::XYZVector pos(ptrSimHit->getPosTrack());
364 ROOT::Math::XYZVector mom(ptrSimHit->getMomentum());
365 ROOT::Math::XYZVector nextMom(ptrNextSimHit->getMomentum());
366 ROOT::Math::XYZVector nextPos(ptrNextSimHit->getPosTrack());
367
368 const auto dotXY = [](const ROOT::Math::XYZVector & lhs, const ROOT::Math::XYZVector & rhs) { return lhs.X() * rhs.X() + lhs.Y() * rhs.Y(); };
369 if (dotXY(pos, nextPos) < 0) return true;
370 if (dotXY(nextPos - pos, nextMom) < 0) return true;
371 if (dotXY(nextPos - pos, mom) < 0) return true;
372
373 // TODO introduce a smarter check here
374 return false;
375 } else {
376 return false;
377 }
378}
379
380
381Index CDCMCTrackStore::getInTrackId(const CDCHit* ptrHit) const
382{
383
384 auto itFoundHit = m_inTrackIds.find(ptrHit);
385 return itFoundHit == m_inTrackIds.end() ? c_InvalidIndex : itFoundHit->second;
386
387}
388
389
390
392{
393
394 auto itFoundHit = m_inTrackSegmentIds.find(ptrHit);
395 return itFoundHit == m_inTrackSegmentIds.end() ? c_InvalidIndex : itFoundHit->second;
396
397}
398
399
401{
402
403 auto itFoundHit = m_nPassedSuperLayers.find(ptrHit);
404 return itFoundHit == m_nPassedSuperLayers.end() ? c_InvalidIndex : itFoundHit->second;
405
406}
407
408Index CDCMCTrackStore::getNLoops(const CDCHit* ptrHit) const
409{
410
411 auto itFoundHit = m_nLoops.find(ptrHit);
412 return itFoundHit == m_nLoops.end() ? c_InvalidIndex : itFoundHit->second;
413
414}
Class containing the result of the unpacker in raw data and the result of the digitizer in simulation...
Definition CDCHit.h:40
unsigned short getIWire() const
Getter for iWire.
Definition CDCHit.h:166
unsigned short getISuperLayer() const
Getter for iSuperLayer.
Definition CDCHit.h:184
unsigned short getILayer() const
Getter for iLayer.
Definition CDCHit.h:172
Example Detector.
Definition CDCSimHit.h:21
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
Class representing the sense wire arrangement in the whole of the central drift chamber.
bool arePrimaryNeighbors(const WireID &wireID, const WireID &otherWireID) const
Checks if two wires are primary neighbors.
bool areSeconaryNeighbors(const WireID &wireID, const WireID &otherWireID) const
Checks if two wires are secondary neighbors.
static CDCWireTopology & getInstance()
Getter for the singleton instance of the wire topology.
A Class to store the Monte Carlo particle information.
Definition MCParticle.h:32
int getArrayIndex() const
Get 0-based index of the particle in the corresponding MCParticle list.
Definition MCParticle.h:233
static const CDCMCTrackStore & getMCTrackStore()
Getter for the singleton instance of the CDCMCTrackStore.
Class to organize and present the Monte Carlo hit information.
Definition CDCMCMap.h:28
bool isBackground(const CDCSimHit *simHit) const
Indicates if the CDCSimHit is considered background.
Definition CDCMCMap.cc:260
const std::multimap< const MCParticle *, const CDCHit * > & getHitsByMCParticle() const
Getter for the MCParticle -> CDCHit relations.
Definition CDCMCMap.h:140
std::map< const CDCHit *, int > m_inTrackIds
Look up table for index of the hit within its track.
TrackingUtilities::Index getNPassedSuperLayers(const CDCHit *ptrHit) const
Getter for the number of super layers traversed until this hit.
std::map< ITrackType, std::vector< CDCHitVector > > m_mcSegmentsByMCParticleIdx
The memory for the segments made of CDCHits sorted for the time of flight and associated to the Monte...
void fillMCTracks()
Construct the tracks by grouping the hits by the mc particle id and sorted them for the FlightTime of...
void fillNLoopsAndNPassedSuperLayers()
Fill the look up table of the number of traversed super layers until each hit.
static const CDCMCTrackStore & getInstance()
Getter for the singletone instance.
TrackingUtilities::Index getInTrackSegmentId(const CDCHit *ptrHit) const
Getter for the index of the segment of the hit within its track.
std::vector< const CDCHit * > CDCHitVector
Type for an ordered sequence of pointers to the CDCHit.
const CDCSimHitLookUp * m_ptrSimHitLookUp
Reference to the CDCSimHit look up for additional information about related primary sim hits.
std::map< const CDCHit *, int > m_nPassedSuperLayers
Look up table for the number of super layers the particle traversed before making the individual hit.
const std::map< ITrackType, Belle2::TrackFindingCDC::CDCMCTrackStore::CDCHitVector > & getMCTracksByMCParticleIdx() const
Getter for the stored Monte Carlo tracks ordered by their Monte Carlo Id.
const CDCMCMap * m_ptrMCMap
Reference to the MC map of the current event.
void fill(const CDCMCMap *ptrMCMap, const CDCSimHitLookUp *ptrSimHitLookUp)
Fill the store with the tracks from Monte Carlo information.
TrackingUtilities::Index getNLoops(const CDCHit *ptrHit) const
Getter for the number of traversed loops until this hit.
std::map< const CDCHit *, int > m_nLoops
Look up table for the number of loops the particle traversed before making the individual hit.
const std::map< ITrackType, std::vector< Belle2::TrackFindingCDC::CDCMCTrackStore::CDCHitVector > > & getMCSegmentsByMCParticleIdx() const
Getter for the stored Monte Carlo segments ordered by their Monte Carlo Id.
void clear()
Clear all Monte Carlo hits.
void arrangeMCTrack(CDCHitVector &mcTrack) const
Sorts the given track for the FlightTime of the associated CDCSimHits.
void fillInTrackId()
Fill the look up table for the in track index of each hit.
CDCMCTrackStore()=default
Default constructor - for cppcheck.
TrackingUtilities::Index getInTrackId(const CDCHit *ptrHit) const
Getter for the index of the hit within its track.
void fillMCSegments()
Construct the segments by dividing the mc tracks in to disconnected parts and sorted them for the Fli...
std::map< const CDCHit *, int > m_inTrackSegmentIds
Look up table for index of the segment of the hits within their respective tracks.
void fillInTrackSegmentId()
Fill the look up table for the in track segment index of each hit.
bool changedSuperLayer(const CDCHitVector &mcSegment, const CDCHitVector &nextMCSegment) const
Helper function to decide whether the number of passed superlayers changed from one segment to the ne...
std::map< ITrackType, CDCHitVector > m_mcTracksByMCParticleIdx
The memory for the tracks made of CDCHits sorted for the time of flight and associated to the Monte C...
Singletone class to gather local information about the hits.
TrackingUtilities::MayBePtr< const CDCSimHit > getClosestPrimarySimHit(const CDCSimHit *ptrSimHit) const
Helper function to find the closest primary hit for the given CDCSimHit from the same MCParticle - nu...
Class to identify a wire inside the CDC.
Definition WireID.h:34
signed short ISuperLayer
The type of the layer and superlayer ids.
Definition ISuperLayer.h:24
Abstract base class for different kinds of events.
Functor to get the .size() from an arbitrary objects.
Definition Functional.h:318