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