Belle II Software  release-06-02-00
TrackFinderMCTruthRecoTracksModule.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/modules/trackFinderMCTruth/TrackFinderMCTruthRecoTracksModule.h>
10 
11 #include <framework/datastore/StoreArray.h>
12 #include <framework/datastore/RelationArray.h>
13 #include <framework/datastore/StoreObjPtr.h>
14 #include <framework/dataobjects/EventMetaData.h>
15 #include <framework/gearbox/Const.h>
16 #include <mdst/dataobjects/MCParticle.h>
17 #include <cdc/dataobjects/CDCHit.h>
18 #include <cdc/dataobjects/CDCSimHit.h>
19 #include <cdc/geometry/CDCGeometryPar.h>
20 #include <pxd/dataobjects/PXDTrueHit.h>
21 #include <pxd/dataobjects/PXDCluster.h>
22 #include <svd/dataobjects/SVDTrueHit.h>
23 #include <svd/dataobjects/SVDCluster.h>
24 #include <top/dataobjects/TOPBarHit.h>
25 #include <tracking/dataobjects/RecoTrack.h>
26 #include <simulation/monopoles/MonopoleConstants.h>
27 
28 #include <framework/geometry/BFieldManager.h>
29 #include <framework/dataobjects/Helix.h>
30 
31 #include <TRandom.h>
32 
33 #include <vector>
34 #include <string>
35 #include <sstream>
36 #include <cmath>
37 
38 
39 using namespace Belle2;
40 
41 //-----------------------------------------------------------------
42 // Register the Module
43 //-----------------------------------------------------------------
44 REG_MODULE(TrackFinderMCTruthRecoTracks)
45 
46 //-----------------------------------------------------------------
47 // Implementation
48 //-----------------------------------------------------------------
49 
51 {
52  //Set module properties
53  setDescription("Uses the MC information to create genfit::TrackCandidates for primary MCParticles and Relations between them. "
54  "Fills the created genfit::TrackCandidates with all information (start values, hit indices) needed for the fitting.");
55  setPropertyFlags(c_ParallelProcessingCertified);
56 
57  // choose which hits to use, all hits assigned to the track candidate will be used in the fit
58  addParam("UsePXDHits",
59  m_usePXDHits,
60  "Set true if PXDHits or PXDClusters should be used",
61  true);
62  addParam("UseSVDHits",
63  m_useSVDHits,
64  "Set true if SVDHits or SVDClusters should be used",
65  true);
66  addParam("UseCDCHits",
67  m_useCDCHits,
68  "Set true if CDCHits should be used",
69  true);
70  addParam("UseOnlyAxialCDCHits",
71  m_useOnlyAxialCDCHits,
72  "Set true if only the axial CDCHits should be used",
73  false);
74  addParam("UseNLoops",
75  m_useNLoops,
76  "Set the number of loops whose hits will be marked as priortiy hits. All other hits "
77  "will be marked as auxiliary and therfore not considered for efficiency computations "
78  "By default, all hits will be priority hits.",
79  INFINITY);
80  addParam("UseOnlyBeforeTOP",
81  m_useOnlyBeforeTOP,
82  "Mark hits as auxiliary after the track left the CDC and touched the TOP detector "
83  "(only implemented for CDCHits).",
84  false);
85  addParam("UseReassignedHits",
86  m_useReassignedHits,
87  "Include hits reassigned from discarded seconardy daughters in the tracks.",
88  false);
89  addParam("UseSecondCDCHits",
90  m_useSecondCDCHits,
91  "Also includes the CDC 2nd hit information in the MC tracks.",
92  false);
93  addParam("MinPXDHits",
94  m_minPXDHits,
95  "Minimum number of PXD hits needed to allow the created of a track candidate",
96  0);
97  addParam("MinSVDHits",
98  m_minSVDHits,
99  "Minimum number of SVD hits needed to allow the created of a track candidate",
100  0);
101  addParam("MinCDCAxialHits",
102  m_minCDCAxialHits,
103  "Minimum number of CDC hits form an axial wire needed to allow the created of a track candidate",
104  0);
105  addParam("MinCDCStereoHits",
106  m_minCDCStereoHits,
107  "Minimum number of CDC hits form a stereo wire needed to allow the created of a track candidate",
108  0);
109  addParam("AllowFirstCDCSuperLayerOnly",
110  m_allowFirstCDCSuperLayerOnly,
111  "Allow tracks to pass the stereo hit requirement if they touched only the first (axial) CDC layer",
112  false);
113 
114  addParam("MinimalNDF",
115  m_minimalNdf,
116  "Minimum number of total hits needed to allow the creation of a track candidate. "
117  "It is called NDF (number of degrees of freedom) because it counts the dimensionality. "
118  "2D hits are counted as 2",
119  5);
120 
121  //choose for which particles a track candidate should be created
122  //this is just an attempt to find out what is the most suitable way to select particles, if you have other/better ideas, communicate it to the tracking group...
123  addParam("WhichParticles",
124  m_whichParticles,
125  "List of keywords to mark what properties particles must have to get a track candidate. "
126  "If several properties are given all of them must be true: "
127  "\"primary\" particle must come from the generator, "
128  "\"PXD\", \"SVD\", \"CDC\", \"TOP\", \"ARICH\", \"ECL\" or \"KLM\" particle must have hits in the subdetector with that name. "
129  "\"is:X\" where X is a PDG code: particle must have this code. "
130  "\"from:X\" any of the particles's ancestors must have this (X) code",
131  std::vector<std::string>(1, "primary"));
132 
133  addParam("EnergyCut",
134  m_energyCut,
135  "Track candidates are only created for MCParticles with energy larger than this cut ",
136  double(0.0));
137 
138  addParam("Neutrals",
139  m_neutrals,
140  "Set true if track candidates should be created also for neutral particles",
141  bool(false));
142 
143  addParam("MergeDecayInFlight",
144  m_mergeDecayInFlight,
145  "Merge decay in flights that produce a single charged particle to the mother particle",
146  bool(false));
147 
148  addParam("SetTimeSeed",
149  m_setTimeSeed,
150  "Set true to forward the production time as time seed of the particles to the RecoTrack",
151  true);
152 
153  //smearing of MCMomentum
154  addParam("Smearing",
155  m_smearing,
156  "Smearing of MCMomentum/MCVertex prior to storing it in genfit::TrackCandidate (in %). "
157  "A negative value will switch off smearing. This is also the default.",
158  -1.0);
159 
160  addParam("SmearingCov",
161  m_smearingCov,
162  "Covariance matrix used to smear the true pos and mom before passed to track candidate. "
163  "This matrix will also passed to Genfit as the initial covarance matrix. "
164  "If any diagonal value is negative this feature will not be used. "
165  "OFF DIAGONAL ELEMENTS DO NOT HAVE AN EFFECT AT THE MOMENT",
166  std::vector<double>(36, -1.0));
167 
168  addParam("SplitAfterDeltaT",
169  m_splitAfterDeltaT,
170  "Minimal time delay between two sim hits (in ns) after which MC reco track will be "
171  "split into seperate tracks. If < 0, don't do splitting."
172  "This feature was designed to be used in MC cosmics reconstruction to get two MCRecoTracks"
173  "when track pass through empty SVD region, so that number of MCRecoTracks can be compared with"
174  "number of non merged reco tracks. ",
175  -1.0);
176 
177  // names of output containers
178  addParam("RecoTracksStoreArrayName",
179  m_recoTracksStoreArrayName,
180  "Name of store array holding the RecoTracks (output)",
181  std::string(""));
182 
183  addParam("TrueHitMustExist",
184  m_enforceTrueHit,
185  "If set true only cluster hits that have a relation to a TrueHit will be included in the track candidate",
186  false);
187 
188  addParam("discardAuxiliaryHits",
189  m_discardAuxiliaryHits,
190  "If set true hits marked as auxiliary (e.g. hits in higher loops) will not be included in the track candidate.",
191  m_discardAuxiliaryHits);
192 
193  addParam("useCDCSuperLayers",
194  m_param_useCDCSuperLayers,
195  "List of CDC super layers to be used.",
196  m_param_useCDCSuperLayers);
197 
198  addParam("useCDCLayers",
199  m_param_useCDCLayers,
200  "List of layers to be used. "
201  "If a layer number is given in 'ignoreLayers', too, this will result on a B2FATAL. "
202  "Either use 'useLayers' and provide a set of layers to be used, "
203  "or use 'ignoreLayers' and provide a list of layers to be ignored, but not both at the same time.",
204  m_param_useCDCLayers);
205 
206  addParam("ignoreCDCLayers",
207  m_param_ignoreCDCLayers,
208  "List of layers to be ignored. "
209  "If a layer number is given in 'useLayers', too, this will result on a B2FATAL. "
210  "Either use 'useLayers' and provide a set of layers to be used, "
211  "or use 'ignoreLayers' and provide a list of layers to be ignored, but not both at the same time.",
212  m_param_ignoreCDCLayers);
213 
214 
215 
216 }
217 
219 {
220  StoreArray<MCParticle> mcparticles;
221  if (mcparticles.isOptional()) {
222  m_mcParticlesPresent = true;
223 
224  //output store arrays have to be registered in initialize()
227 
228  recoTracks.registerRelationTo(mcparticles);
229 
231 
232  // build a bit mask with all properties a MCParticle should have to lead to the creation of a track candidate
234  int aPdgCode = 0;
235  const int nProperties = m_whichParticles.size();
236  for (int i = 0; i not_eq nProperties; ++i) {
237  if (m_whichParticles[i] == "primary") {
239  } else if (m_whichParticles[i] == "PXD") {
241  } else if (m_whichParticles[i] == "SVD") {
243  } else if (m_whichParticles[i] == "CDC") {
245  } else if (m_whichParticles[i] == "TOP") {
246  m_particleProperties += 16;
247  } else if (m_whichParticles[i] == "ARICH") {
248  m_particleProperties += 32;
249  } else if (m_whichParticles[i] == "ECL") {
250  m_particleProperties += 64;
251  } else if (m_whichParticles[i] == "KLM") {
252  m_particleProperties += 128;
253  } else if (m_whichParticles[i].substr(0, 3) == "is:") {
254  std::string pdgCodeString = m_whichParticles[i].substr(3);
255  std::stringstream(pdgCodeString) >> aPdgCode;
256  B2DEBUG(20, "PDG code added to m_particlePdgCodes " << aPdgCode << " *******");
257  m_particlePdgCodes.push_back(aPdgCode);
258  } else if (m_whichParticles[i].substr(0, 5) == "from:") {
259  std::string pdgCodeString = m_whichParticles[i].substr(5);
260  std::stringstream(pdgCodeString) >> aPdgCode;
261  B2DEBUG(20, "PDG code added to m_fromPdgCodes " << aPdgCode << " *******");
262  m_fromPdgCodes.push_back(aPdgCode);
263  } else {
264  B2FATAL("Invalid values were given to the MCTrackFinder parameter WhichParticles");
265  }
266  }
267 
268 
269 
270  //transfom the smearingCov vector into a TMatrixD
271  //first check if it can be transformed into a 6x6 matrix
272  if (m_smearingCov.size() != 36) {
273  B2FATAL("SmearingCov does not have exactly 36 elements. So 6x6 covariance matrix can be formed from it");
274  }
275  m_initialCov.ResizeTo(6, 6);
276  m_initialCov = TMatrixDSym(6, &m_smearingCov[0]);
277  for (int i = 0; i != 6; ++i) {
278  if (m_initialCov(i, i) < 0.0) {
279  m_initialCov(0, 0) = -1.0; // if first element of matrix is negative this using this matrix will be switched off
280  }
281  }
282 
283  if (m_smearing > 0.0 && m_initialCov(0, 0) > 0.0) {
284  B2FATAL("Both relative smearing (Smearing) and using a smearing cov (SmearingCov) is activated but only one of both can be used");
285  }
286  }
287 
288  if (not m_param_useCDCSuperLayers.empty()) {
289  for (const uint useSuperLayer : m_param_useCDCSuperLayers) {
290  m_useCDCSuperLayers.at(useSuperLayer) = true;
291  }
292  } else {
293  m_useCDCSuperLayers.fill(true);
294  }
295 
296  // Check for common value in the two vectors for using / ignoring layers
297  for (const uint useLayer : m_param_useCDCLayers) {
298  for (const uint ingoreLayer : m_param_ignoreCDCLayers) {
299  if (useLayer == ingoreLayer) {
300  B2FATAL("You chose to use and ignore CDC layer " << useLayer << " at the same time. "
301  "Please decide to either use or to ignore the layer.");
302  }
303  }
304  }
305 
306  // fill all layers that should be used
307  if (not m_param_useCDCLayers.empty()) {
308  for (const uint layer : m_param_useCDCLayers) {
309  m_useCDCLayers.at(layer) = true;
310  }
311  } else {
312  m_useCDCLayers.fill(true);
313  }
314  // set layers that should be ignored to false
315  if (not m_param_ignoreCDCLayers.empty()) {
316  for (const uint layer : m_param_ignoreCDCLayers) {
317  m_useCDCLayers.at(layer) = false;
318  }
319  }
320 
321 }
322 
324 {
326  m_noTrueHitCounter = 0;
327  m_nRecoTracks = 0;
328 }
329 
330 
332 {
333  // Skip in the case there are no MC particles present.
334  if (not m_mcParticlesPresent) {
335  B2DEBUG(20, "Skipping MC Track Finder as there are no MC Particles registered in the DataStore.");
336  return;
337  }
338 
339  StoreObjPtr<EventMetaData> eventMetaDataPtr("EventMetaData", DataStore::c_Event);
340  const int eventCounter = eventMetaDataPtr->getEvent();
341  B2DEBUG(20, "******* MCTrackFinderModule processing event number: " << eventCounter << " *******");
342 
343  //all the input containers. First: MCParticles
344  StoreArray<MCParticle> mcParticles;
345  const int nMcParticles = mcParticles.getEntries();
346  B2DEBUG(20, "MCTrackFinder: total Number of MCParticles: " << nMcParticles);
347 
348  //PXD trueHits
349  StoreArray<PXDTrueHit> pxdTrueHits;
350  const int nPXDHits = pxdTrueHits.getEntries();
351  B2DEBUG(20, "MCTrackFinder: Number of PXDTrueHits: " << nPXDHits);
352 
353  RelationArray mcPartToPXDTrueHits(mcParticles, pxdTrueHits);
354  const int nMcPartToPXDHits = mcPartToPXDTrueHits.getEntries();
355  B2DEBUG(20, "MCTrackFinder: Number of relations between MCParticles and PXDHits: " << nMcPartToPXDHits);
356 
357  //PXD clusters
358  StoreArray<PXDCluster> pxdClusters;
359  const int nPXDClusters = pxdClusters.getEntries();
360  B2DEBUG(20, "MCTrackFinder: Number of PXDClusters: " << nPXDClusters);
361 
362  RelationArray pxdClusterToMCParticle(pxdClusters, mcParticles);
363  const int nPxdClusterToMCPart = pxdClusterToMCParticle.getEntries();
364  B2DEBUG(20, "MCTrackFinder: Number of relations between PXDCluster and MCParticles: " << nPxdClusterToMCPart);
365 
366  //SVD truehits
367  StoreArray<SVDTrueHit> svdTrueHits;
368  const int nSVDHits = svdTrueHits.getEntries();
369  B2DEBUG(20, "MCTrackFinder: Number of SVDDHits: " << nSVDHits);
370 
371  RelationArray mcPartToSVDTrueHits(mcParticles, svdTrueHits);
372  const int nMcPartToSVDHits = mcPartToSVDTrueHits.getEntries();
373  B2DEBUG(20, "MCTrackFinder: Number of relations between MCParticles and SVDHits: " << nMcPartToSVDHits);
374 
375  //SVD clusters
376  StoreArray<SVDCluster> svdClusters;
377  const int nSVDClusters = svdClusters.getEntries();
378  B2DEBUG(20, "MCTrackFinder: Number of SVDClusters: " << nSVDClusters);
379 
380  RelationArray svdClusterToMCParticle(svdClusters, mcParticles);
381  const int nSvdClusterToMCPart = svdClusterToMCParticle.getEntries();
382  B2DEBUG(20, "MCTrackFinder: Number of relations between SVDCluster and MCParticles: " << nSvdClusterToMCPart);
383 
384  //CDC
385  StoreArray<CDCHit> cdcHits;
386  const int nCDCHits = cdcHits.getEntries();
387  B2DEBUG(20, "MCTrackFinder: Number of CDCHits: " << nCDCHits);
388 
389  RelationArray mcPartToCDCHits(mcParticles, cdcHits);
390  const int nMcPartToCDCHits = mcPartToCDCHits.getEntries();
391  B2DEBUG(20, "MCTrackFinder: Number of relations between MCParticles and CDCHits: " << nMcPartToCDCHits);
392 
393  StoreArray<CDCSimHit> cdcSimHits("");
394  const int nCDCSimHits = cdcSimHits.getEntries();
395  B2DEBUG(20, "MCTrackFinder: Number of CDCSimHits: " << nCDCSimHits);
396 
397  RelationArray cdcSimHitToHitRel(cdcSimHits, cdcHits);
398  const int nCdcSimHitToHitRel = cdcSimHitToHitRel.getEntries();
399  B2DEBUG(20, "MCTrackFinder: Number of relations between CDCSimHit and CDCHits: " << nCdcSimHitToHitRel);
400 
401  // prepare rejection of CDC/PXD/SVD hits from higher order loops
402  const double Bz = BFieldManager::getField(0, 0, 0).Z() / Unit::T;
403 
404  //register StoreArray which will be filled by this module
406 
407  // loop over MCParticles. And check several user selected properties. Make a track candidate only if MCParticle has properties wanted by user options.
408  std::set<int> alreadyConsumedMCParticles;
409  for (int iPart = 0; iPart < nMcParticles; ++iPart) {
410  if (alreadyConsumedMCParticles.count(iPart)) continue;
411  alreadyConsumedMCParticles.insert(iPart);
412 
413  MCParticle* aMcParticlePtr = mcParticles[iPart];
414  // Ignore particles that didn't propagate significantly, they cannot make tracks.
415  if ((aMcParticlePtr->getDecayVertex() - aMcParticlePtr->getProductionVertex()).Mag() < 1 * Unit::cm) {
416  B2DEBUG(20, "Particle that did not propagate significantly cannot make track.");
417  continue;
418  }
419 
420  //set the property mask for this particle and compare it to the one generated from user input
421  int mcParticleProperties = 0;
422  if (aMcParticlePtr->hasStatus(MCParticle::c_PrimaryParticle)) {
423  mcParticleProperties += 1;
424  }
425  if (aMcParticlePtr->hasSeenInDetector(Const::PXD)) {
426  mcParticleProperties += 2;
427  }
428  if (aMcParticlePtr->hasSeenInDetector(Const::SVD)) {
429  mcParticleProperties += 4;
430  }
431  if (aMcParticlePtr->hasSeenInDetector(Const::CDC)) {
432  mcParticleProperties += 8;
433  }
434  if (aMcParticlePtr->hasSeenInDetector(Const::TOP)) {
435  mcParticleProperties += 16;
436  }
437  if (aMcParticlePtr->hasSeenInDetector(Const::ARICH)) {
438  mcParticleProperties += 32;
439  }
440  if (aMcParticlePtr->hasSeenInDetector(Const::ECL)) {
441  mcParticleProperties += 64;
442  }
443  if (aMcParticlePtr->hasSeenInDetector(Const::KLM)) {
444  mcParticleProperties += 128;
445  }
446  // check all "seen in" properties that the mcparticle should have in one line.
447  if ((mcParticleProperties bitand m_particleProperties) != m_particleProperties) {
448  B2DEBUG(20, "PDG: " << aMcParticlePtr->getPDG() << " | property mask of particle " << mcParticleProperties <<
449  " demanded property mask " << m_particleProperties);
450  continue; //goto next mcParticle, do not make track candidate
451  }
452  //make links only for interesting MCParticles: energy cut
453  if (aMcParticlePtr->getEnergy() < m_energyCut) {
454  B2DEBUG(20, "particle energy too low. MC particle will be skipped");
455  continue; //goto next mcParticle, do not make track candidate
456  }
457 
458  //check if particle has the pdg code the user wants to have. If user did not set any pdg code every code is fine for track candidate creation
459 
460  const int nPdgCodes = m_particlePdgCodes.size();
461  if (nPdgCodes not_eq 0) {
462  const int currentPdgCode = aMcParticlePtr->getPDG();
463  int nFalsePdgCodes = 0;
464  for (int i = 0; i not_eq nPdgCodes; ++i) {
465  if (m_particlePdgCodes[i] not_eq currentPdgCode) {
466  ++nFalsePdgCodes;
467  }
468  }
469  if (nFalsePdgCodes == nPdgCodes) {
470  B2DEBUG(20, "particle does not have one of the user provided pdg codes and will therefore be skipped");
471  continue; //goto next mcParticle, do not make track candidate
472  }
473  }
474 
475 
476  //check if particle has an ancestor selected by the user. If user did not set any pdg code every code is fine for track candidate creation
477  const int nFromPdgCodes = m_fromPdgCodes.size();
478  if (nFromPdgCodes not_eq 0) {
479  MCParticle* currentMother = aMcParticlePtr->getMother();
480  int nFalsePdgCodes = 0;
481  int nAncestor = 0;
482  while (currentMother not_eq nullptr) {
483  int currentMotherPdgCode = currentMother->getPDG();
484  for (int i = 0; i not_eq nFromPdgCodes; ++i) {
485  if (m_fromPdgCodes[i] not_eq currentMotherPdgCode) {
486  ++nFalsePdgCodes;
487  }
488  }
489 
490  currentMother = currentMother->getMother();
491  ++nAncestor;
492  }
493  if (nFalsePdgCodes == (nAncestor * nFromPdgCodes)) {
494  B2DEBUG(20, "particle does not have and ancestor with one of the user provided pdg codes and will therefore be skipped");
495  continue; //goto next mcParticle, do not make track candidate
496  }
497  }
498 
499  // Ignore baryons, except for deuteron. The purpose is mainly to
500  // avoid an error message when getCharge() is called below.
501  if (abs(aMcParticlePtr->getPDG()) > 1000000000
502  && abs(aMcParticlePtr->getPDG()) != Const::deuteron.getPDGCode()) {
503  B2DEBUG(20, "Skipped Baryon.");
504  continue; //goto next mcParticle, do not make track candidate
505 
506  }
507 
508  // ignore neutrals (unless requested) (and unless monopoles)
509  if (!m_neutrals && (aMcParticlePtr->getCharge() == 0 && abs(aMcParticlePtr->getPDG()) != Monopoles::c_monopolePDGCode)) {
510  B2DEBUG(20, "particle does not have the right charge. MC particle will be skipped");
511  continue; //goto next mcParticle, do not make track candidate
512  }
513 
514 
515  B2DEBUG(20, "Build a track for the MCParticle with index: " << iPart << " (PDG: " << aMcParticlePtr->getPDG() << ")");
516 
517  std::vector<const MCParticle*> trackMCParticles;
518  trackMCParticles.push_back(aMcParticlePtr);
519 
520  if (m_mergeDecayInFlight and aMcParticlePtr->getCharge() != 0) {
521  std::vector<MCParticle*> daughters = aMcParticlePtr->getDaughters();
522  std::vector<MCParticle*> decayInFlightParticles;
523  for (MCParticle* daughter : daughters) {
524  if (daughter->getSecondaryPhysicsProcess() > 200 and daughter->getCharge() != 0) {
525  decayInFlightParticles.push_back(daughter);
526  }
527  }
528  if (decayInFlightParticles.size() == 1) {
529  trackMCParticles.push_back(decayInFlightParticles.front());
530  alreadyConsumedMCParticles.insert(trackMCParticles.back()->getArrayIndex());
531  }
532  }
533 
534  //assign indices of the Hits from all detectors.
535  // entry 0: global event of each hit
536  // entry 1: indices in the respective hit arrays (PXD, SVD, CDC, ...)
537  // entry 2: the category of the hit: either a high priority and should be found or not so important
538  // entry 3: identifier for the detector type
539  typedef std::tuple<double, int, RecoHitInformation::OriginTrackFinder, Const::EDetector> TimeHitIDDetector;
540  std::vector<TimeHitIDDetector> hitsWithTimeAndDetectorInformation;
541 
542  int ndf = 0; // count the ndf of one track candidate
543 
544  // create a list containing the indices to the PXDHits that belong to one track
545  if (m_usePXDHits) {
546  int hitCounter = 0;
547  for (const MCParticle* trackMCParticle : trackMCParticles) {
548  const RelationVector<PXDCluster>& relatedClusters = trackMCParticle->getRelationsFrom<PXDCluster>();
549 
550  for (size_t i = 0; i < relatedClusters.size(); ++i) {
551  bool isReassigned = relatedClusters.weight(i) < 0;
552  if (!m_useReassignedHits && isReassigned) continue; // skip hits from secondary particles
553 
554  // currently only priority Hits for PXD
555  auto mcFinder = RecoHitInformation::OriginTrackFinder::c_MCTrackFinderPriorityHit;
556 
557  // Reassigned hits are auxiliary
558  if (isReassigned) {
559  mcFinder = RecoHitInformation::OriginTrackFinder::c_MCTrackFinderAuxiliaryHit;
560  }
561 
562  // Mark higher order hits as auxiliary, if m_useNLoops has been set
563  if (std::isfinite(m_useNLoops) and not isWithinNLoops<PXDCluster, PXDTrueHit>(Bz, relatedClusters.object(i), m_useNLoops)) {
564  mcFinder = RecoHitInformation::OriginTrackFinder::c_MCTrackFinderAuxiliaryHit;
565  }
566 
567  // if flag is set discard all auxiliary hits:
568  if (m_discardAuxiliaryHits and mcFinder == RecoHitInformation::OriginTrackFinder::c_MCTrackFinderAuxiliaryHit) continue;
569 
570  const PXDCluster* pxdCluster = relatedClusters.object(i);
571  const RelationVector<PXDTrueHit>& relatedTrueHits = pxdCluster->getRelationsTo<PXDTrueHit>();
572 
573  if (relatedTrueHits.size() == 0 and m_enforceTrueHit) {
574  // there is not trueHit! throw away hit because there is no time information for sorting
576  continue;
577  }
578 
579  float time = NAN;
580  for (const PXDTrueHit& pxdTrueHit : relatedTrueHits) {
581  // Make sure only a true hit is taken that really comes from the current mcParticle.
582  // This must be carefully checked because several trueHits from different real tracks can be melted into one cluster
583  const RelationVector<MCParticle>& relatedMCParticles = pxdTrueHit.getRelationsFrom<MCParticle>();
584  if (std::find_if(relatedMCParticles.begin(),
585  relatedMCParticles.end(),
586  [trackMCParticle](const MCParticle & mcParticle) {
587  return &mcParticle == trackMCParticle;
588  }) != relatedMCParticles.end()) {
589  time = pxdTrueHit.getGlobalTime();
590  break;
591  }
592  }
593  if (not std::isnan(time)) {
594  hitsWithTimeAndDetectorInformation.emplace_back(time, pxdCluster->getArrayIndex(), mcFinder, Const::PXD);
595  ++hitCounter;
596  ndf += 2;
597  }
598  }
599 
600  B2DEBUG(20, " add " << hitCounter << " PXDClusters. " << relatedClusters.size() - hitCounter <<
601  " PXDClusters were not added because they do not have a corresponding PXDTrueHit");
602  } // next trackMCParticle
603 
604  if (hitCounter < m_minPXDHits) {
606  continue; //goto next mcParticle, do not make track candidate
607  }
608  } // end if m_usePXDHits
609 
610  // create a list containing the indices to the SVDHits that belong to one track
611  if (m_useSVDHits) {
612  int hitCounter = 0;
613  for (const MCParticle* trackMCParticle : trackMCParticles) {
614  const RelationVector<SVDCluster>& relatedClusters = trackMCParticle->getRelationsFrom<SVDCluster>();
615 
616  for (size_t i = 0; i < relatedClusters.size(); ++i) {
617  bool isReassigned = relatedClusters.weight(i) < 0;
618  if (!m_useReassignedHits && isReassigned) continue; // skip hits from secondary particles
619 
620  auto mcFinder = RecoHitInformation::OriginTrackFinder::c_MCTrackFinderPriorityHit;
621 
622  // Reassigned hits are auxiliary
623  if (isReassigned) {
624  mcFinder = RecoHitInformation::OriginTrackFinder::c_MCTrackFinderAuxiliaryHit;
625  }
626 
627  // Mark higher order hits as auxiliary, if m_useNLoops has been set
628  if (std::isfinite(m_useNLoops) and not isWithinNLoops<SVDCluster, SVDTrueHit>(Bz, relatedClusters.object(i), m_useNLoops)) {
629  mcFinder = RecoHitInformation::OriginTrackFinder::c_MCTrackFinderAuxiliaryHit;
630  }
631 
632  // if flag is set discard all auxiliary hits:
633  if (m_discardAuxiliaryHits and mcFinder == RecoHitInformation::OriginTrackFinder::c_MCTrackFinderAuxiliaryHit) continue;
634 
635  const SVDCluster* svdCluster = relatedClusters.object(i);
636  const RelationVector<SVDTrueHit>& relatedTrueHits = svdCluster->getRelationsTo<SVDTrueHit>();
637 
638  if (relatedTrueHits.size() == 0 and m_enforceTrueHit) {
639  // there is not trueHit! throw away hit because there is no time information for sorting
641  continue;
642  }
643 
644  float time = NAN;
645  for (const SVDTrueHit& svdTrueHit : relatedTrueHits) {
646  // Make sure only a true hit is taken that really comes from the current mcParticle.
647  // This must be carefully checked because several trueHits from different real tracks can be melted into one cluster
648  const RelationVector<MCParticle>& relatedMCParticles = svdTrueHit.getRelationsFrom<MCParticle>();
649  if (std::find_if(relatedMCParticles.begin(),
650  relatedMCParticles.end(),
651  [trackMCParticle](const MCParticle & mcParticle) {
652  return &mcParticle == trackMCParticle;
653  }) != relatedMCParticles.end()) {
654  time = svdTrueHit.getGlobalTime();
655  break;
656  }
657  }
658  if (not std::isnan(time)) {
659  hitsWithTimeAndDetectorInformation.emplace_back(time, svdCluster->getArrayIndex(), mcFinder, Const::SVD);
660  ++hitCounter;
661  ndf += 1;
662  }
663  }
664 
665  B2DEBUG(20, " add " << hitCounter << " SVDClusters. " << relatedClusters.size() - hitCounter <<
666  " SVDClusters were not added because they do not have a corresponding SVDTrueHit");
667  }
668 
669  if (hitCounter < m_minSVDHits) {
671  continue; //goto next mcParticle, do not make track candidate
672  }
673  } // end if m_useSVDHits
674 
675 
676  auto didParticleExitCDC = [](const CDCHit * hit) {
677  const CDCSimHit* simHit = hit->getRelated<CDCSimHit>();
678  if (not simHit) return false;
679 
680  const MCParticle* mcParticle = simHit->getRelated<MCParticle>();
681  if (not mcParticle) return false;
682  if (not mcParticle->hasSeenInDetector(Const::TOP)) return false;
683 
684  RelationVector<TOPBarHit> topHits = mcParticle->getRelationsWith<TOPBarHit>();
685  if (topHits.size() == 0) return false;
686 
687  // Get hit with the smallest time.
688  auto lessTime = [](const TOPBarHit & lhs, const TOPBarHit & rhs) {
689  return lhs.getTime() < rhs.getTime();
690  };
691  auto itFirstTopHit = std::min_element(topHits.begin(), topHits.end(), lessTime);
692 
693  return simHit->getGlobalTime() > itFirstTopHit->getTime();
694  };
695 
696  if (m_useCDCHits) {
697  // create a list containing the indices to the CDCHits that belong to one track
698  int nAxialHits = 0;
699  int nStereoHits = 0;
700  std::array<int, 9> nHitsBySuperLayerId{};
701 
702  for (const MCParticle* trackMCParticle : trackMCParticles) {
703  const RelationVector<CDCHit>& relatedHits = trackMCParticle->getRelationsTo<CDCHit>();
704 
705  for (size_t i = 0; i < relatedHits.size(); ++i) {
706  bool isReassigned = relatedHits.weight(i) < 0;
707  if (!m_useReassignedHits && isReassigned) continue; // skip hits from secondary particles
708 
709  const CDCHit* cdcHit = relatedHits.object(i);
710 
711  unsigned short superLayerId = cdcHit->getISuperLayer();
712  if (not m_useCDCSuperLayers[superLayerId]) continue;
713  unsigned short layerID = cdcHit->getICLayer();
714  if (not m_useCDCLayers[layerID]) continue;
715 
716  // continue if this is a 2nd CDC hit information and we do not want to use it
717  if (!m_useSecondCDCHits && cdcHit->is2ndHit()) {
718  continue;
719  }
720 
721  auto mcFinder = RecoHitInformation::OriginTrackFinder::c_MCTrackFinderPriorityHit;
722 
723  // Reassigned hits are auxiliary
724  if (isReassigned) {
725  mcFinder = RecoHitInformation::OriginTrackFinder::c_MCTrackFinderAuxiliaryHit;
726  }
727 
728  // Mark higher order hits as auxiliary, if m_useNLoops has been set
729  if (std::isfinite(m_useNLoops) and not isWithinNLoops<CDCHit, CDCSimHit>(Bz, cdcHit, m_useNLoops)) {
730  mcFinder = RecoHitInformation::OriginTrackFinder::c_MCTrackFinderAuxiliaryHit;
731  }
732 
733  // check if the particle left hits in TOP and add mark hits after that as auxiliary.
734  if (m_useOnlyBeforeTOP and didParticleExitCDC(cdcHit)) {
735  mcFinder = RecoHitInformation::OriginTrackFinder::c_MCTrackFinderAuxiliaryHit;
736  }
737 
738  // if flag is set discard all auxiliary hits:
739  if (m_discardAuxiliaryHits and mcFinder == RecoHitInformation::OriginTrackFinder::c_MCTrackFinderAuxiliaryHit) continue;
740 
741 
742  const CDCSimHit* aCDCSimHitPtr = cdcHit->getRelatedFrom<CDCSimHit>();
743  if (not aCDCSimHitPtr) {
744  B2DEBUG(20, " Skipping CDCHit without related CDCSimHit.");
745  continue;
746  }
747  double time = aCDCSimHitPtr->getFlightTime();
748 
749  // Here it is hardcoded what superlayer has axial wires and what has stereo wires.
750  // Maybe it would be better if the WireId would know this
751  if (superLayerId % 2 == 0) {
752  hitsWithTimeAndDetectorInformation.emplace_back(time, cdcHit->getArrayIndex(), mcFinder, Const::CDC);
753  ndf += 1;
754  ++nAxialHits;
755  ++nHitsBySuperLayerId[superLayerId];
756  } else {
757  if (not m_useOnlyAxialCDCHits) {
758  hitsWithTimeAndDetectorInformation.emplace_back(time, cdcHit->getArrayIndex(), mcFinder, Const::CDC);
759  ndf += 1;
760  ++nStereoHits;
761  ++nHitsBySuperLayerId[superLayerId];
762  }
763  }
764  }
765  } // next trackMCParticle
766  B2DEBUG(20, " added " << nAxialHits << " axial and " << nStereoHits << " stereo CDCHits");
767  if (nAxialHits < m_minCDCAxialHits) {
768  // Not enough axial hits. Next MCParticle.
770  continue;
771  }
772 
773  if (not m_useOnlyAxialCDCHits and (nStereoHits < m_minCDCStereoHits)) {
775  nHitsBySuperLayerId[0] == nAxialHits and
776  (nAxialHits + nStereoHits >= m_minCDCAxialHits + m_minCDCStereoHits)) {
777  // Special rule for low momentum tracks that only touch the first axial superlayer
778  // If there still enough hits combined from the axial and stereo hit limit -> keep the track.
779  } else {
780  // Not enough stereo hits. Next MCParticle.
782  continue;
783  }
784  }
785  } // end if m_useCDCHits
786 
787  if (m_initialCov(0, 0) > 0.0) { //using a user set initial cov and corresponding smearing of inital state adds information
788  ndf += 5;
789  }
790  if (ndf < m_minimalNdf) {
792  continue; //goto next mcParticle, do not make track candidate
793  }
794 
795  std::sort(hitsWithTimeAndDetectorInformation.begin(), hitsWithTimeAndDetectorInformation.end(),
796  [](const TimeHitIDDetector & rhs, const TimeHitIDDetector & lhs) {
797  return std::get<0>(rhs) < std::get<0>(lhs);
798  });
799 
800  // Now create vectors of vectors, which will either contain hits the full vector WithTimeanddetectorInformation
801  // or slices of it, when cutting SplitAfterDeltaT is positive, each slice corresponding to a (sub-) reco track
802  // created by the MC particle.
803  std::vector< std::vector<TimeHitIDDetector> > hitsWithTimeAndDetectorInformationVectors;
804 
805  if (m_splitAfterDeltaT < 0.0) { // no splitting, vector will only contain a single hitInformation vector
806  hitsWithTimeAndDetectorInformationVectors.push_back(hitsWithTimeAndDetectorInformation);
807  } else { // split on delta t
808 
809  std::vector<TimeHitIDDetector>::size_type splitFromIdx = 0; // whenever splitting subtrack, start slice from this index
810  for (std::vector<TimeHitIDDetector>::size_type i = 1; i != hitsWithTimeAndDetectorInformation.size(); i++) {
811 
812  double delta_t = (std::get<0>(hitsWithTimeAndDetectorInformation[i])
813  - std::get<0>(hitsWithTimeAndDetectorInformation[i - 1]));
814 
815  if (delta_t > m_splitAfterDeltaT) {
816  // push slice of `hitsWithTimeAndDetectorInformation' between splitFromidx and previous index
817  hitsWithTimeAndDetectorInformationVectors
818  .emplace_back(hitsWithTimeAndDetectorInformation.begin() + splitFromIdx,
819  hitsWithTimeAndDetectorInformation.begin() + i);
820  splitFromIdx = i;
821  }
822  }
823  // add subtrack after last splitting to list of tracks
824  hitsWithTimeAndDetectorInformationVectors
825  .emplace_back(hitsWithTimeAndDetectorInformation.begin() + splitFromIdx,
826  hitsWithTimeAndDetectorInformation.end());
827  }
828 
829  //Now create TrackCandidate
830  int counter = recoTracks.getEntries();
831  B2DEBUG(20, "We came pass all filter of the MCPartile and hit properties. TrackCandidate " << counter <<
832  " will be created from the MCParticle with index: " << iPart << " (PDG: " << aMcParticlePtr->getPDG() << ")");
833 
834 
835 
836  //set track parameters from MCParticle information
837  TVector3 positionTrue = aMcParticlePtr->getProductionVertex();
838  TVector3 momentumTrue = aMcParticlePtr->getMomentum();
839  double timeTrue = aMcParticlePtr->getProductionTime();
840 
841  // if no kind of smearing is activated the initial values (seeds) for track fit will be the simulated truth
842  TVector3 momentum = momentumTrue;
843  TVector3 position = positionTrue;
844  double time = timeTrue;
845  TVectorD stateSeed(6); //this will
846  TMatrixDSym covSeed(6);
847  covSeed.Zero(); // just to be save
848  covSeed(0, 0) = 1; covSeed(1, 1) = 1; covSeed(2, 2) = 2 * 2;
849  covSeed(3, 3) = 0.1 * 0.1; covSeed(4, 4) = 0.1 * 0.1; covSeed(5, 5) = 0.2 * 0.2;
850  //it may have positive effect on the fit not to start with exactly precise true values (or it may be just interesting to study this)
851  //one can smear the starting momentum values with a gaussian
852  //this calculation is always performed, but with the default value of m_smearing = 0 it has no effect on momentum and position (true values are taken)
853 
854  if (m_smearing > 0.0) {
855  double smearing = m_smearing / 100.0; //the module parameter m_smearing goes from 0 to 100, smearing should go from 0 to 1
856 
857  double smearedX = gRandom->Gaus(positionTrue.x(), smearing * positionTrue.x());
858  double smearedY = gRandom->Gaus(positionTrue.y(), smearing * positionTrue.y());
859  double smearedZ = gRandom->Gaus(positionTrue.z(), smearing * positionTrue.z());
860  position.SetXYZ(smearedX, smearedY, smearedZ);
861  double smearedPX = gRandom->Gaus(momentumTrue.x(), smearing * momentumTrue.x());
862  double smearedPY = gRandom->Gaus(momentumTrue.y(), smearing * momentumTrue.y());
863  double smearedPZ = gRandom->Gaus(momentumTrue.z(), smearing * momentumTrue.z());
864  momentum.SetXYZ(smearedPX, smearedPY, smearedPZ);
865  }
866 
867  //Errors for the position/momentum values can also be passed to genfit::TrackCandidate
868  //Default values in Genfit are (1.,1.,1.,), they seem to be not good!!
869  //The best way to set the 'correct' errors has to be investigated....
870  if (m_initialCov(0, 0) > 0.0) { // alternative seamring with according to a covariance matrix
871  double smearedX = gRandom->Gaus(positionTrue.x(), sqrt(m_initialCov(0, 0)));
872  double smearedY = gRandom->Gaus(positionTrue.y(), sqrt(m_initialCov(1, 1)));
873  double smearedZ = gRandom->Gaus(positionTrue.z(), sqrt(m_initialCov(2, 2)));
874  position.SetXYZ(smearedX, smearedY, smearedZ);
875  double smearedPX = gRandom->Gaus(momentumTrue.x(), sqrt(m_initialCov(3, 3)));
876  double smearedPY = gRandom->Gaus(momentumTrue.y(), sqrt(m_initialCov(4, 4)));
877  double smearedPZ = gRandom->Gaus(momentumTrue.z(), sqrt(m_initialCov(5, 5)));
878  momentum.SetXYZ(smearedPX, smearedPY, smearedPZ);
879  covSeed = m_initialCov;
880  }
881 
882  // Finally create RecoTracks for MC particle.
883  // Either only one or multiple tracks, if SplitAfterDeltaT is positive
884  for (const auto& hitInformationVector : hitsWithTimeAndDetectorInformationVectors) {
885 
886  // TODO: In former times, the track candidate also stored the PDG code!!!
887  short int charge = static_cast<short int>(aMcParticlePtr->getCharge());
888 
889  // extrapolate the position and momentum to the point of the first hit on the helix
890  if (hitInformationVector.size() != 0) {
891  // reset the time to the time of the first hit (assumes time > production time)
892  time = std::get<0>(hitInformationVector.at(0));
893  const double deltaT = time - aMcParticlePtr->getProductionTime();
894  // build the 4-vector with the smeared momentum
895  TLorentzVector lorentzV;
896  lorentzV.SetVectM(momentum, aMcParticlePtr->get4Vector().M());
897  const double beta_xy = momentum.Perp() / lorentzV.E();
898  // calculate arclength in 2D of the track
899  const double arclength2D = beta_xy * Const::speedOfLight * deltaT;
900 
901  // get the position and momentum from the helix at the acrlength corresponding to the first hit
902  Belle2::Helix helix = Belle2::Helix(position, momentum, charge, Bz);
903  momentum = helix.getMomentumAtArcLength2D(arclength2D, Bz);
904  position = helix.getPositionAtArcLength2D(arclength2D);
905  }
906 
907 
908  RecoTrack* newRecoTrack = recoTracks.appendNew(position, momentum, charge);
909  if (m_setTimeSeed) {
910  newRecoTrack->setTimeSeed(time);
911  }
912  ++m_nRecoTracks;
913 
914  //create relation between the track candidates and the mcParticle (redundant to saving the MCId)
915  newRecoTrack->addRelationTo(aMcParticlePtr);
916  B2DEBUG(20, " --- Create relation between genfit::TrackCand " << counter << " and MCParticle " << iPart);
917 
918  int hitCounter = 0;
919  for (const TimeHitIDDetector& hitInformation : hitInformationVector) {
920 
921  const Const::EDetector& detectorInformation = std::get<3>(hitInformation);
922  const int hitID = std::get<1>(hitInformation);
923  const auto hitOriginMCFinderType = std::get<2>(hitInformation);
924 
925 
926  if (detectorInformation == Const::CDC) {
927  const CDCHit* cdcHit = cdcHits[hitID];
928  const CDCSimHit* aCDCSimHitPtr = cdcHit->getRelatedFrom<CDCSimHit>();
929 
930  //now determine the correct sign to resolve the left right ambiguity in the fitter
931  TVector3 simHitPos = aCDCSimHitPtr->getPosTrack();
932  TVector3 simMom = aCDCSimHitPtr->getMomentum();
933  TVector3 simHitPosOnWire = aCDCSimHitPtr->getPosWire();
934 
936  const unsigned short isRightHit = cdcGeometry.getNewLeftRightRaw(simHitPosOnWire, simHitPos, simMom);
937 
938  if (isRightHit) {
939  newRecoTrack->addCDCHit(cdcHit, hitCounter, RecoHitInformation::RightLeftInformation::c_right, hitOriginMCFinderType);
940  } else {
941  newRecoTrack->addCDCHit(cdcHit, hitCounter, RecoHitInformation::RightLeftInformation::c_left, hitOriginMCFinderType);
942  }
943  B2DEBUG(20, "CDC hit " << hitID << " has reft/right sign " << isRightHit);
944  } else if (detectorInformation == Const::PXD) {
945  const PXDCluster* pxdCluster = pxdClusters[hitID];
946  newRecoTrack->addPXDHit(pxdCluster, hitCounter, hitOriginMCFinderType);
947  } else if (detectorInformation == Const::SVD) {
948  const SVDCluster* svdCluster = svdClusters[hitID];
949  newRecoTrack->addSVDHit(svdCluster, hitCounter, hitOriginMCFinderType);
950  }
951  ++hitCounter;
952  } // end loop over hits
953 
954  B2DEBUG(20, "New RecoTrack: #PXDHits: " << newRecoTrack->getPXDHitList().size() <<
955  " #SVDHits: " << newRecoTrack->getSVDHitList().size() <<
956  " #CDCHits: " << newRecoTrack->getCDCHitList().size());
957 
958  } // end loop over vector
959  }//end loop over MCParticles
960 }
961 
962 
963 
964 template< class THit, class TSimHit>
965 bool TrackFinderMCTruthRecoTracksModule::isWithinNLoops(double Bz, const THit* aHit, double nLoops)
966 {
967  // for SVD there are cases with more than one simhit attached
968  const RelationVector<TSimHit>& relatedSimHits = aHit->template getRelationsWith<TSimHit>();
969 
970  // take the first best simhit with mcParticle attached
971  const MCParticle* mcParticle = nullptr;
972  const TSimHit* aSimHit = nullptr;
973  for (const auto& thisSimHit : relatedSimHits) {
974  mcParticle = thisSimHit.template getRelated<MCParticle>();
975  aSimHit = &thisSimHit;
976  if (mcParticle) break;
977  }
978  if (not mcParticle or not aSimHit) {
979  return false;
980  }
981 
982  // subtract the production time here in order for this classification to also work
983  // for particles produced at times t' > t0
984  const double tof = aSimHit->getGlobalTime() - mcParticle->getProductionTime();
985  const double speed = mcParticle->get4Vector().Beta() * Const::speedOfLight;
986  const float absMom3D = mcParticle->getMomentum().Mag();
987 
988  const double loopLength = 2 * M_PI * absMom3D / (Bz * 0.00299792458);
989  const double loopTOF = loopLength / speed;
990  if (tof > loopTOF * nLoops) {
991  return false;
992  } else {
993  return true;
994  }
995 }
996 
997 
998 
1000 {
1001  if (m_notEnoughtHitsCounter != 0) {
1002  B2WARNING(m_notEnoughtHitsCounter << " tracks had not enough hits to have at least " << m_minimalNdf <<
1003  " number of degrees of freedom (NDF). No Track Candidates were created from them so they will not be passed to the track fitter");
1004  }
1005  if (m_noTrueHitCounter != 0) {
1006  B2WARNING(m_noTrueHitCounter <<
1007  " cluster hits did not have a relation to a true hit and were therefore not included in a track candidate");
1008  }
1009  B2INFO("The MCTrackFinder created a total of " << m_nRecoTracks << " track candidates");
1010 }
Class containing the result of the unpacker in raw data and the result of the digitizer in simulation...
Definition: CDCHit.h:40
bool is2ndHit() const
Getter for 2nd hit flag.
Definition: CDCHit.h:205
unsigned short getICLayer() const
Getter for iCLayer (0-55).
Definition: CDCHit.h:178
unsigned short getISuperLayer() const
Getter for iSuperLayer.
Definition: CDCHit.h:184
Example Detector.
Definition: CDCSimHit.h:22
TVector3 getPosWire() const
The method to get position on wire.
Definition: CDCSimHit.h:205
double getFlightTime() const
The method to get flight time.
Definition: CDCSimHit.h:190
float getGlobalTime() const override
The method to get global time.
Definition: CDCSimHit.h:254
TVector3 getMomentum() const
The method to get momentum.
Definition: CDCSimHit.h:199
TVector3 getPosTrack() const
The method to get position on the track.
Definition: CDCSimHit.h:223
The Class for CDC Geometry Parameters.
unsigned short getNewLeftRightRaw(const TVector3 &posOnWire, const TVector3 &posOnTrack, const TVector3 &momentum) const
Returns new left/right_raw.
static CDCGeometryPar & Instance(const CDCGeometry *=nullptr)
Static method to get a reference to the CDCGeometryPar instance.
Helix parameter class.
Definition: Helix.h:48
int getPDGCode() const
PDG code.
Definition: Const.h:354
EDetector
Enum for identifying the detector components (detector and subdetector).
Definition: Const.h:42
static const double speedOfLight
[cm/ns]
Definition: Const.h:575
static const ChargedStable deuteron
deuteron particle
Definition: Const.h:545
@ c_ErrorIfAlreadyRegistered
If the object/array was already registered, produce an error (aborting initialisation).
Definition: DataStore.h:72
@ c_Event
Different object in each event, all objects/arrays are invalidated after event() function has been ca...
Definition: DataStore.h:59
A Class to store the Monte Carlo particle information.
Definition: MCParticle.h:32
float getEnergy() const
Return particle energy in GeV.
Definition: MCParticle.h:147
@ c_PrimaryParticle
bit 0: Particle is primary particle.
Definition: MCParticle.h:47
bool hasSeenInDetector(Const::DetectorSet set) const
Return if the seen-in flag for a specific subdetector is set or not.
Definition: MCParticle.h:307
std::vector< Belle2::MCParticle * > getDaughters() const
Get vector of all daughter particles, empty vector if none.
Definition: MCParticle.cc:50
bool hasStatus(unsigned short int bitmask) const
Return if specific status bit is set.
Definition: MCParticle.h:129
TVector3 getMomentum() const
Return momentum.
Definition: MCParticle.h:198
TVector3 getDecayVertex() const
Return decay vertex.
Definition: MCParticle.h:219
float getCharge() const
Return the particle charge defined in TDatabasePDG.
Definition: MCParticle.cc:34
int getPDG() const
Return PDG code of particle.
Definition: MCParticle.h:112
float getProductionTime() const
Return production time in ns.
Definition: MCParticle.h:159
TLorentzVector get4Vector() const
Return 4Vector of particle.
Definition: MCParticle.h:207
TVector3 getProductionVertex() const
Return production vertex position.
Definition: MCParticle.h:189
Base class for Modules.
Definition: Module.h:72
The PXD Cluster class This class stores all information about reconstructed PXD clusters The position...
Definition: PXDCluster.h:30
Class PXDTrueHit - Records of tracks that either enter or leave the sensitive volume.
Definition: PXDTrueHit.h:31
This is the Reconstruction Event-Data Model Track.
Definition: RecoTrack.h:76
bool addCDCHit(const UsedCDCHit *cdcHit, const unsigned int sortingParameter, RightLeftInformation rightLeftInformation=RightLeftInformation::c_undefinedRightLeftInformation, OriginTrackFinder foundByTrackFinder=OriginTrackFinder::c_undefinedTrackFinder)
Adds a cdc hit with the given information to the reco track.
Definition: RecoTrack.h:238
std::vector< Belle2::RecoTrack::UsedSVDHit * > getSVDHitList() const
Return an unsorted list of svd hits.
Definition: RecoTrack.h:448
bool addPXDHit(const UsedPXDHit *pxdHit, const unsigned int sortingParameter, OriginTrackFinder foundByTrackFinder=OriginTrackFinder::c_undefinedTrackFinder)
Adds a pxd hit with the given information to the reco track.
Definition: RecoTrack.h:253
std::vector< Belle2::RecoTrack::UsedPXDHit * > getPXDHitList() const
Return an unsorted list of pxd hits.
Definition: RecoTrack.h:451
std::vector< Belle2::RecoTrack::UsedCDCHit * > getCDCHitList() const
Return an unsorted list of cdc hits.
Definition: RecoTrack.h:445
void setTimeSeed(const double timeSeed)
Set the time seed. ATTENTION: This is not the fitted time.
Definition: RecoTrack.h:519
static void registerRequiredRelations(StoreArray< RecoTrack > &recoTracks, std::string const &pxdHitsStoreArrayName="", std::string const &svdHitsStoreArrayName="", std::string const &cdcHitsStoreArrayName="", std::string const &bklmHitsStoreArrayName="", std::string const &eklmHitsStoreArrayName="", std::string const &recoHitInformationStoreArrayName="")
Convenience method which registers all relations required to fully use a RecoTrack.
Definition: RecoTrack.cc:49
bool addSVDHit(const UsedSVDHit *svdHit, const unsigned int sortingParameter, OriginTrackFinder foundByTrackFinder=OriginTrackFinder::c_undefinedTrackFinder)
Adds a svd hit with the given information to the reco track.
Definition: RecoTrack.h:267
Low-level class to create/modify relations between StoreArrays.
Definition: RelationArray.h:62
int getEntries() const
Get the number of elements.
Class for type safe access to objects that are referred to in relations.
size_t size() const
Get number of relations.
T * object(int index) const
Get object with index.
iterator end()
Return iterator to last entry +1.
iterator begin()
Return iterator to first entry.
float weight(int index) const
Get weight with index.
void addRelationTo(const RelationsInterface< BASE > *object, float weight=1.0, const std::string &namedRelation="") const
Add a relation from this object to another object (with caching).
int getArrayIndex() const
Returns this object's array index (in StoreArray), or -1 if not found.
RelationVector< TO > getRelationsTo(const std::string &name="", const std::string &namedRelation="") const
Get the relations that point from this object to another store array.
FROM * getRelatedFrom(const std::string &name="", const std::string &namedRelation="") const
Get the object from which this object has a relation.
T * getRelated(const std::string &name="", const std::string &namedRelation="") const
Get the object to or from which this object has a relation.
RelationVector< T > getRelationsWith(const std::string &name="", const std::string &namedRelation="") const
Get the relations between this object and another store array.
The SVD Cluster class This class stores all information about reconstructed SVD clusters.
Definition: SVDCluster.h:28
Class SVDTrueHit - Records of tracks that either enter or leave the sensitive volume.
Definition: SVDTrueHit.h:33
bool isOptional(const std::string &name="")
Tell the DataStore about an optional input.
bool registerInDataStore(DataStore::EStoreFlags storeFlags=DataStore::c_WriteOut)
Register the object/array in the DataStore.
T * appendNew()
Construct a new T object at the end of the array.
Definition: StoreArray.h:246
int getEntries() const
Get the number of objects in the array.
Definition: StoreArray.h:216
bool registerRelationTo(const StoreArray< TO > &toArray, DataStore::EDurability durability=DataStore::c_Event, DataStore::EStoreFlags storeFlags=DataStore::c_WriteOut, const std::string &namedRelation="") const
Register a relation to the given StoreArray.
Definition: StoreArray.h:140
Type-safe access to single objects in the data store.
Definition: StoreObjPtr.h:95
Class to store track parameters of incoming MC particles relation to MCParticle filled in top/simulat...
Definition: TOPBarHit.h:26
double getTime() const
Returns time of impact.
Definition: TOPBarHit.h:127
This module uses the simulated truth information (MCParticles and their relations) to determine which...
bool m_useCDCHits
Boolean to select if CDCHits should be used.
bool m_enforceTrueHit
If set true only cluster hits that have a relation to a TrueHit will be included in the track candida...
std::vector< int > m_fromPdgCodes
if size() is not 0, only for particles having an ancestor (mother or mother of mother etc) with PDG c...
std::vector< int > m_particlePdgCodes
if size() is not 0, only for particles with PDG codes same as in this vector a track candidate will b...
double m_energyCut
Create track candidates only for MCParticles with energy above this cut.
std::vector< std::string > m_whichParticles
List of keywords to mark what properties particles must have to get a track candidate .
bool m_discardAuxiliaryHits
if true hits marked as auxiliary will not be included in the RecoTrack
void event() override
This method is the core of the module.
int m_minimalNdf
Minimum number of total hits per track to allow track candidate creation.
void endRun() override
This method is called if the current run ends.
int m_particleProperties
Internal encoding of m_whichParticles to avoid string comparisons.
bool m_useReassignedHits
Boolean to select the inclusion of hits form discarded secondary daughters.
std::vector< double > m_smearingCov
Covariance matrix used to smear the true pos and mom before passed to track candidate.
bool m_mcParticlesPresent
This flag is set to false if there are no MC Particles in the data store (probably data run?...
bool m_allowFirstCDCSuperLayerOnly
Boolean to allow tracks to pass the stereo hit requirement if they touched only the first (axial) CDC...
bool m_mergeDecayInFlight
Boolean to merge decay in flight chains that involve a single charged particle.
bool m_setTimeSeed
Boolean to forward the production time as seed time.
float m_useNLoops
Number of loops to include in the MC tracks - effects only CDC.
double m_splitAfterDeltaT
Minimal time delay between two sim hits (in ns) after which MC reco track will be split into seperate...
bool m_useSecondCDCHits
Also includes the CDC 2nd hit information in the mc tracks.
int m_minCDCStereoHits
Minimum number of CDC hits from stereo wires per track to allow track candidate creation.
bool m_usePXDHits
Boolean to select if PXDHits should be used.
void beginRun() override
Called when entering a new run.
std::vector< uint > m_param_useCDCLayers
List of layers to be used.
bool m_useOnlyBeforeTOP
Boolean to select if CDC hits after TOP detector are discarded.
std::vector< uint > m_param_ignoreCDCLayers
List of layers to be ignored in tracking.
std::vector< uint > m_param_useCDCSuperLayers
List of super layers to be used.
int m_minCDCAxialHits
Minimum number of CDC hits from axial wires per track to allow track candidate creation.
int m_noTrueHitCounter
will hold number of cluster hits that do not have a corresponding true hit
int m_minSVDHits
Minimum number of SVD hits per track to allow track candidate creation.
int m_notEnoughtHitsCounter
will hold number of tracks that do not have enough hits to form a track candidate (total NDF less tha...
bool m_useOnlyAxialCDCHits
Boolean to select if only axial CDCHits should be used.
std::array< bool, 56 > m_useCDCLayers
Bits for the used layers ATTENTION: hardcoded value for number of layers.
double m_smearing
Smearing of MCMomentum and MCVertex in %.
std::array< bool, 9 > m_useCDCSuperLayers
Bits for the used super layers ATTENTION: hardcoded value for number of super layers.
std::string m_recoTracksStoreArrayName
RecoTracks StoreArray name.
int m_minPXDHits
Minimum number of PXD hits per track to allow track candidate creation.
bool m_neutrals
Boolean to mark if track candidates should also be created for neutral particles.
TMatrixDSym m_initialCov
The std::vector m_smearingCov will be translated into this TMatrixD.
int m_nRecoTracks
will hold the total number of created track candidates
bool isWithinNLoops(double Bz, const THit *aHit, double nLoops)
helper function which returns true if the current hit is within n loops the template give the hit typ...
bool m_useSVDHits
Boolean to select if SVDHits should be used.
static const double cm
Standard units with the value = 1.
Definition: Unit.h:47
static const double T
[tesla]
Definition: Unit.h:120
#define REG_MODULE(moduleName)
Register the given module (without 'Module' suffix) with the framework.
Definition: Module.h:650
static void getField(const double *pos, double *field)
return the magnetic field at a given position.
MCParticle * getMother() const
Returns a pointer to the mother particle.
Definition: MCParticle.h:582
Abstract base class for different kinds of events.