Belle II Software  release-06-00-14
TOPBunchFinderModule.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 // Own include
10 #include <top/modules/TOPBunchFinder/TOPBunchFinderModule.h>
11 #include <top/geometry/TOPGeometryPar.h>
12 #include <top/reconstruction_cpp/TOPTrack.h>
13 #include <top/reconstruction_cpp/PDFConstructor.h>
14 #include <top/reconstruction_cpp/TOPRecoManager.h>
15 #include <top/reconstruction_cpp/PDF1Dim.h>
16 #include <top/utilities/Chi2MinimumFinder1D.h>
17 
18 // Dataobject classes
19 #include <mdst/dataobjects/TrackFitResult.h>
20 #include <mdst/dataobjects/HitPatternCDC.h>
21 #include <tracking/dataobjects/ExtHit.h>
22 #include <mdst/dataobjects/MCParticle.h>
23 #include <top/dataobjects/TOPBarHit.h>
24 #include <reconstruction/dataobjects/CDCDedxLikelihood.h>
25 #include <reconstruction/dataobjects/VXDDedxLikelihood.h>
26 #include <mdst/dataobjects/PIDLikelihood.h>
27 
28 // framework aux
29 #include <framework/gearbox/Const.h>
30 #include <framework/logging/Logger.h>
31 #include <set>
32 
33 using namespace std;
34 
35 namespace Belle2 {
40  using namespace TOP;
41 
42  //-----------------------------------------------------------------
43  // Register module
44  //-----------------------------------------------------------------
45 
46  REG_MODULE(TOPBunchFinder)
47 
48  //-----------------------------------------------------------------
49  // Implementation
50  //-----------------------------------------------------------------
51 
53  {
54  // set module description (e.g. insert text)
55  setDescription("A precise event T0 determination w.r.t local time reference of TOP counter. "
56  "Results available in TOPRecBunch.");
57  setPropertyFlags(c_ParallelProcessingCertified);
58 
59  // Add parameters
60  addParam("numBins", m_numBins, "number of bins of fine search region", 200);
61  addParam("timeRangeFine", m_timeRangeFine,
62  "time range in which to do fine search [ns]", 10.0);
63  addParam("timeRangeCoarse", m_timeRangeCoarse,
64  "time range in which to do coarse search, if autoRange turned off [ns]", 100.0);
65  addParam("autoRange", m_autoRange,
66  "turn on/off automatic determination of the coarse search region (false means off)", false);
67  addParam("sigmaSmear", m_sigmaSmear,
68  "sigma in [ns] for additional smearing of PDF", 0.0);
69  addParam("minSignal", m_minSignal,
70  "minimal number of signal photons to accept track", 10.0);
71  addParam("minSBRatio", m_minSBRatio,
72  "minimal signal-to-background ratio to accept track", 0.0);
73  addParam("minDERatio", m_minDERatio,
74  "minimal ratio of detected-to-expected photons to accept track", 0.2);
75  addParam("maxDERatio", m_maxDERatio,
76  "maximal ratio of detected-to-expected photons to accept track", 2.5);
77  addParam("minPt", m_minPt, "minimal p_T of the track", 0.3);
78  addParam("maxPt", m_maxPt, "maximal p_T of the track", 6.0);
79  addParam("maxD0", m_maxD0, "maximal absolute value of helix perigee distance", 2.0);
80  addParam("maxZ0", m_maxZ0, "maximal absolute value of helix perigee z coordinate", 4.0);
81  addParam("minNHitsCDC", m_minNHitsCDC, "minimal number of hits in CDC", 20);
82  addParam("useMCTruth", m_useMCTruth,
83  "if true, use MC truth for particle mass instead of the most probable from dEdx",
84  false);
85  addParam("saveHistograms", m_saveHistograms,
86  "if true, save histograms to TOPRecBunch", false);
87  addParam("tau", m_tau,
88  "first order filter time constant [number of events]", 100.0);
89  addParam("fineSearch", m_fineSearch,
90  "if true, do fine search with two-dimensional PDF", true);
91  addParam("correctDigits", m_correctDigits,
92  "if true, subtract bunch time in TOPDigits", true);
93  addParam("subtractRunningOffset", m_subtractRunningOffset,
94  "if true and correctDigits = True, subtract running offset in TOPDigits "
95  "when running in HLT mode. It must be set to false when running calibration.",
96  true);
97  addParam("bunchesPerSSTclk", m_bunchesPerSSTclk,
98  "number of bunches per SST clock period", 24);
99  addParam("usePIDLikelihoods", m_usePIDLikelihoods,
100  "use PIDLikelihoods instead of DedxLikelihoods (only if run on cdst files)",
101  false);
102  }
103 
104 
105  void TOPBunchFinderModule::initialize()
106  {
107  // input collections
108 
109  m_topDigits.isRequired();
110  m_topRawDigits.isOptional();
111  m_tracks.isRequired();
112  StoreArray<ExtHit> extHits;
113  extHits.isRequired();
114  m_initialParticles.isOptional();
115 
116  if (m_useMCTruth) {
117  StoreArray<MCParticle> mcParticles;
118  mcParticles.isRequired();
119  StoreArray<TOPBarHit> barHits;
120  barHits.isRequired();
121  } else {
122  if (m_usePIDLikelihoods) {
123  StoreArray<PIDLikelihood> pidLikelihoods;
124  pidLikelihoods.isRequired();
125  } else {
126  StoreArray<CDCDedxLikelihood> cdcDedxLikelihoods;
127  cdcDedxLikelihoods.isRequired();
128  StoreArray<VXDDedxLikelihood> vxdDedxLikelihoods;
129  vxdDedxLikelihoods.isOptional();
130  }
131  }
132 
133  // output
134 
135  m_recBunch.registerInDataStore();
136  m_timeZeros.registerInDataStore();
137  m_timeZeros.registerRelationTo(extHits);
138  m_eventT0.registerInDataStore(); // usually it is already registered in tracking
139 
140  // bunch separation in time
141 
142  const auto* geo = TOPGeometryPar::Instance()->getGeometry();
143  m_bunchTimeSep = geo->getNominalTDC().getSyncTimeBase() / m_bunchesPerSSTclk;
144 
145  // prior probabilities: from generic BBbar simulation
146  // - MCParticles with reconstructed track and at least 5 detected Cherenkov photons
147 
148  m_priors[11] = 0.062; // electrons
149  m_priors[13] = 0.086; // muons
150  m_priors[211] = 0.734; // pions
151  m_priors[321] = 0.106; // kaons
152  m_priors[2212] = 0.013; // protons
153  m_priors[1000010020] = 0; // deuterons
154 
155  double s = 0;
156  for (const auto& prior : m_priors) s += prior.second;
157  for (auto& prior : m_priors) prior.second /= s;
158 
159  if (not m_commonT0.isValid()) {
160  B2ERROR("Common T0 calibration payload requested but not available");
161  return;
162  }
163 
164  /*************************************************************************
165  * auto detection of HLT/express reco mode via status of common T0 payload:
166  * c_Default -> HLT/express reco mode
167  * c_Calibrated -> data processing mode
168  * c_Unusable -> HLT/express reco mode
169  * c_roughlyCalibrated -> HLT/express reco mode
170  *************************************************************************/
171 
172  if (m_commonT0->isCalibrated()) {
173  m_HLTmode = false;
174  m_runningOffset = 0; // since digits are already commonT0 calibrated
175  m_runningError = m_commonT0->getT0Error();
176  } else if (m_commonT0->isRoughlyCalibrated()) {
177  m_HLTmode = true;
178  m_runningOffset = m_commonT0->getT0(); // since digits are not commonT0 calibrated
179  m_runningError = m_commonT0->getT0Error();
180  } else {
181  m_HLTmode = true;
182  m_runningOffset = 0;
183  m_runningError = m_bunchTimeSep / sqrt(12.0);
184  }
185 
186  if (m_HLTmode) {
187  B2INFO("TOPBunchFinder: running in HLT/express reco mode");
188  } else {
189  B2INFO("TOPBunchFinder: running in data processing mode");
190  }
191 
192  }
193 
194 
195  void TOPBunchFinderModule::beginRun()
196  {
197  StoreObjPtr<EventMetaData> evtMetaData;
198 
199  if (not m_commonT0.isValid()) {
200  B2FATAL("Common T0 calibration payload requested but not available for run "
201  << evtMetaData->getRun()
202  << " of experiment " << evtMetaData->getExperiment());
203  }
204 
205  }
206 
207 
208  void TOPBunchFinderModule::event()
209  {
210 
211  m_processed++;
212  TOPRecoManager::setDefaultTimeWindow();
213 
214  // define output for the reconstructed bunch
215 
216  if (not m_recBunch.isValid()) {
217  m_recBunch.create();
218  } else {
219  m_recBunch->clearReconstructed();
220  }
221  m_timeZeros.clear();
222 
223  if (not m_eventT0.isValid()) m_eventT0.create();
224 
225  // set MC truth if available
226 
227  if (m_initialParticles.isValid()) {
228  double simTime = m_initialParticles->getTime();
229  int simBunchNumber = round(simTime / m_bunchTimeSep);
230  m_recBunch->setSimulated(simBunchNumber, simTime);
231  }
232 
233  // set revo9 counter from the first raw digit if available (all should be the same)
234 
235  if (m_topRawDigits.getEntries() > 0) {
236  const auto* rawDigit = m_topRawDigits[0];
237  m_recBunch->setRevo9Counter(rawDigit->getRevo9Counter());
238  }
239 
240  // full time window in which data are taken (smaller time window is used in reconstruction)
241 
242  const auto& tdc = TOPGeometryPar::Instance()->getGeometry()->getNominalTDC();
243  double timeWindow = m_feSetting->getReadoutWindows() * tdc.getSyncTimeBase() / TOPNominalTDC::c_syncWindows;
244 
245  // counters and temporary containers
246 
247  int numTrk = 0;
248  m_nodEdxCount = 0;
249  std::vector<TOPTrack> topTracks;
250  std::vector<PDFConstructor> pdfConstructors;
251  std::vector<PDF1Dim> top1Dpdfs;
252  std::vector<int> numPhotons;
253  std::vector<Chi2MinimumFinder1D> finders;
254 
255  // loop over reconstructed tracks, make a selection and push to containers
256 
257  for (const auto& track : m_tracks) {
258  TOPTrack trk(track);
259  if (not trk.isValid()) continue;
260 
261  // track selection
262  const auto* fitResult = track.getTrackFitResultWithClosestMass(Const::pion);
263  if (not fitResult) {
264  B2ERROR("No TrackFitResult available. Must be a bug somewhere.");
265  continue;
266  }
267  if (fitResult->getHitPatternCDC().getNHits() < m_minNHitsCDC) continue;
268  if (fabs(fitResult->getD0()) > m_maxD0) continue;
269  if (fabs(fitResult->getZ0()) > m_maxZ0) continue;
270  auto pt = fitResult->getTransverseMomentum();
271  if (pt < m_minPt or pt > m_maxPt) continue;
272 
273  // determine most probable particle mass
274  auto chargedStable = Const::pion;
275  if (m_useMCTruth) {
276  if (not trk.getMCParticle()) continue;
277  if (not trk.getBarHit()) continue;
278  chargedStable = Const::chargedStableSet.find(abs(trk.getMCParticle()->getPDG()));
279  if (chargedStable == Const::invalidParticle) continue;
280  } else {
281  chargedStable = getMostProbable(track);
282  }
283 
284  // construct PDF
285  PDFConstructor pdfConstructor(trk, chargedStable, PDFConstructor::c_Rough);
286  if (not pdfConstructor.isValid()) continue;
287  numTrk++;
288 
289  // make PDF projection to time axis with bin size of ~0.5 ns
290  PDF1Dim pdf1d(pdfConstructor, 0.5, timeWindow);
291  pdfConstructor.switchOffDeltaRayPDF(); // to speed-up fine search
292 
293  // do further track selection
294  double expSignal = pdf1d.getExpectedSignal() + pdf1d.getExpectedDeltaPhotons();
295  double expBG = pdf1d.getExpectedBG();
296  double expPhot = expSignal + expBG;
297  double numPhot = pdf1d.getNumOfPhotons();
298  if (expSignal < m_minSignal) continue;
299  if (expSignal < m_minSBRatio * expBG) continue;
300  if (numPhot < m_minDERatio * expPhot) continue;
301  if (numPhot > m_maxDERatio * expPhot) continue;
302 
303  topTracks.push_back(trk);
304  pdfConstructors.push_back(pdfConstructor);
305  top1Dpdfs.push_back(pdf1d);
306  numPhotons.push_back(numPhot);
307  }
308  m_recBunch->setNumTracks(numTrk, topTracks.size(), m_nodEdxCount);
309  if (topTracks.empty()) return;
310 
311  // set time region for coarse search
312 
313  double minT0 = -m_timeRangeCoarse / 2;
314  double maxT0 = m_timeRangeCoarse / 2;
315  if (m_autoRange) {
316  minT0 = top1Dpdfs[0].getMinT0();
317  maxT0 = top1Dpdfs[0].getMaxT0();
318  for (const auto& pdf : top1Dpdfs) {
319  minT0 = std::min(minT0, pdf.getMinT0());
320  maxT0 = std::max(maxT0, pdf.getMaxT0());
321  }
322  }
323  double binSize = top1Dpdfs[0].getBinSize();
324  int numBins = (maxT0 - minT0) / binSize;
325  maxT0 = minT0 + binSize * numBins;
326 
327  // find coarse T0
328 
329  for (const auto& pdf : top1Dpdfs) {
330  finders.push_back(Chi2MinimumFinder1D(numBins, minT0, maxT0));
331  auto& finder = finders.back();
332  const auto& bins = finder.getBinCenters();
333  for (unsigned i = 0; i < bins.size(); i++) {
334  double t0 = bins[i];
335  finder.add(i, -2 * pdf.getLogL(t0));
336  }
337  }
338  auto coarseFinder = finders[0];
339  for (size_t i = 1; i < finders.size(); i++) {
340  coarseFinder.add(finders[i]);
341  }
342 
343  const auto& t0Coarse = coarseFinder.getMinimum();
344  if (m_saveHistograms) {
345  m_recBunch->addHistogram(coarseFinder.getHistogram("chi2_coarse_",
346  "coarse T0; t_{0} [ns]; -2 log L"));
347  }
348  if (t0Coarse.position < minT0 or t0Coarse.position > maxT0 or not t0Coarse.valid) {
349  B2DEBUG(20, "Coarse T0 finder: returning invalid or out of range T0");
350  return;
351  }
352 
353  auto T0 = t0Coarse;
354 
355  // find precise T0
356 
357  if (m_fineSearch) {
358  finders.clear();
359  numPhotons.clear();
360 
361  double timeMin = TOPRecoManager::getMinTime() + t0Coarse.position;
362  double timeMax = TOPRecoManager::getMaxTime() + t0Coarse.position;
363  double t0min = t0Coarse.position - m_timeRangeFine / 2;
364  double t0max = t0Coarse.position + m_timeRangeFine / 2;
365 
366  for (const auto& reco : pdfConstructors) {
367  finders.push_back(Chi2MinimumFinder1D(m_numBins, t0min, t0max));
368  numPhotons.push_back(0);
369  auto& finder = finders.back();
370  std::set<int> nfotSet; // for control only
371  const auto& binCenters = finder.getBinCenters();
372  for (unsigned i = 0; i < binCenters.size(); i++) {
373  double t0 = binCenters[i];
374  auto LL = reco.getLogL(t0, timeMin, timeMax, m_sigmaSmear);
375  finder.add(i, -2 * LL.logL);
376  if (i == 0) numPhotons.back() = LL.numPhotons;
377  nfotSet.insert(LL.numPhotons);
378  }
379  if (nfotSet.size() != 1) B2ERROR("Different number of photons used for log likelihood of different time shifts");
380  }
381 
382  if (finders.size() == 0) return; // just in case
383  auto finder = finders[0];
384  for (size_t i = 1; i < finders.size(); i++) {
385  finder.add(finders[i]);
386  }
387 
388  const auto& t0Fine = finder.getMinimum();
389  if (m_saveHistograms) {
390  m_recBunch->addHistogram(finder.getHistogram("chi2_fine_",
391  "precise T0; t_{0} [ns]; -2 log L"));
392  }
393  if (t0Fine.position < t0min or t0Fine.position > t0max or not t0Fine.valid) {
394  B2DEBUG(20, "Fine T0 finder: returning invalid or out of range T0");
395  return;
396  }
397 
398  T0 = t0Fine;
399  }
400 
401  // bunch time and current offset
402 
403  int bunchNo = lround(T0.position / m_bunchTimeSep); // round to nearest integer
404  double offset = T0.position - m_bunchTimeSep * bunchNo;
405  if (not m_commonT0->isCalibrated()) { // auto set offset range
406  double deltaOffset = offset - m_runningOffset;
407  if (fabs(deltaOffset + m_bunchTimeSep) < fabs(deltaOffset)) {
408  offset += m_bunchTimeSep;
409  bunchNo--;
410  } else if (fabs(deltaOffset - m_bunchTimeSep) < fabs(deltaOffset)) {
411  offset -= m_bunchTimeSep;
412  bunchNo++;
413  }
414  }
415  double error = T0.error;
416 
417  // averaging with first order filter (with adoptable time constant)
418 
419  double tau = 10 + m_success / 2; // empirically with toy MC
420  if (tau > m_tau) tau = m_tau;
421  double a = exp(-1.0 / tau);
422  m_runningOffset = a * m_runningOffset + (1 - a) * offset;
423  double err1 = a * m_runningError;
424  double err2 = (1 - a) * error;
425  m_runningError = sqrt(err1 * err1 + err2 * err2);
426 
427  // store the results
428 
429  double bunchTime = bunchNo * m_bunchTimeSep;
430  m_recBunch->setReconstructed(bunchNo, bunchTime, offset, error,
431  m_runningOffset, m_runningError, m_fineSearch);
432  m_eventT0->addTemporaryEventT0(EventT0::EventT0Component(bunchTime, error,
433  Const::TOP, "bunchFinder"));
434  m_success++;
435 
436  // store T0 of single tracks relative to bunchTime
437 
438  if (finders.size() == topTracks.size()) {
439  for (size_t itrk = 0; itrk < topTracks.size(); itrk++) {
440  const auto& trk = topTracks[itrk];
441  const auto& reco = pdfConstructors[itrk];
442  auto& finder = finders[itrk];
443  const auto& t0trk = finder.getMinimum();
444  auto* timeZero = m_timeZeros.appendNew(trk.getModuleID(),
445  t0trk.position - bunchTime,
446  t0trk.error, numPhotons[itrk]);
447  timeZero->setAssumedMass(reco.getHypothesis().getMass());
448  if (not t0trk.valid) timeZero->setInvalid();
449  timeZero->addRelationTo(trk.getExtHit());
450 
451  if (m_saveHistograms) {
452  std::string num = std::to_string(itrk);
453  auto chi2 = finder.getHistogram("chi2_" + num,
454  "precise T0 single track; t_{0} [ns]; -2 log L");
455  auto pdf = top1Dpdfs[itrk].getHistogram("pdf1D_" + num,
456  "PDF projected to time axis; time [ns]");
457  TH1F hits(("hits_" + num).c_str(),
458  "time distribution of hits (t0-subtracted); time [ns]",
459  pdf.GetNbinsX(), pdf.GetXaxis()->GetXmin(), pdf.GetXaxis()->GetXmax());
460  for (const auto& hit : trk.getSelectedHits()) {
461  hits.Fill(hit.time - t0trk.position);
462  }
463  timeZero->setHistograms(chi2, pdf, hits);
464  }
465  }
466  }
467 
468  // correct time in TOPDigits
469 
470  if (m_correctDigits) {
471  for (auto& digit : m_topDigits) {
472  digit.subtractT0(bunchTime);
473  digit.addStatus(TOPDigit::c_EventT0Subtracted);
474  if (m_HLTmode and m_subtractRunningOffset) {
475  digit.subtractT0(m_runningOffset);
476  double err = digit.getTimeError();
477  digit.setTimeError(sqrt(err * err + m_runningError * m_runningError));
478  digit.addStatus(TOPDigit::c_BunchOffsetSubtracted);
479  }
480  }
481  }
482 
483  }
484 
485 
486  void TOPBunchFinderModule::terminate()
487  {
488  B2RESULT("TOPBunchFinder: event T0 determined for " << m_success << "/"
489  << m_processed << " events");
490  }
491 
492 
493  Const::ChargedStable TOPBunchFinderModule::getMostProbable(const Track& track)
494  {
495 
496  std::vector<double> logL;
497  std::vector<double> priors;
498 
499  if (m_usePIDLikelihoods) {
500  const auto* pid = track.getRelated<PIDLikelihood>();
501  if (not pid) {
502  m_nodEdxCount++;
503  return Const::pion;
504  }
505  auto subset = Const::PIDDetectorSet(Const::SVD);
506  subset += Const::PIDDetectorSet(Const::CDC);
507  for (const auto& type : Const::chargedStableSet) {
508  logL.push_back(pid->getLogL(type, subset));
509  priors.push_back(m_priors[abs(type.getPDGCode())]);
510  }
511  } else {
512  const auto* cdcdedx = track.getRelated<CDCDedxLikelihood>();
513  const auto* vxddedx = track.getRelated<VXDDedxLikelihood>();
514  if (not cdcdedx and not vxddedx) {
515  m_nodEdxCount++;
516  return Const::pion;
517  }
518  for (const auto& type : Const::chargedStableSet) {
519  if (cdcdedx and vxddedx) {
520  logL.push_back(cdcdedx->getLogL(type) + vxddedx->getLogL(type));
521  } else if (cdcdedx) {
522  logL.push_back(cdcdedx->getLogL(type));
523  } else {
524  logL.push_back(vxddedx->getLogL(type));
525  }
526  priors.push_back(m_priors[abs(type.getPDGCode())]);
527  }
528  }
529 
530  // get maximal logL
531  auto logL_max = logL[0];
532  for (auto x : logL) {
533  if (x > logL_max) logL_max = x;
534  }
535 
536  // calculate probabilities, normalizaton is not needed
537  std::vector<double> probability(logL.size());
538  for (unsigned i = 0; i < logL.size(); ++i) {
539  probability[i] = exp(logL[i] - logL_max) * priors[i];
540  }
541 
542  // find most probable
543  unsigned i0 = 0;
544  for (unsigned i = 0; i < probability.size(); ++i) {
545  if (probability[i] > probability[i0]) i0 = i;
546  }
547  return Const::chargedStableSet.at(i0);
548 
549  }
550 
552 } // end Belle2 namespace
Container for likelihoods obtained by the CDC dE/dx PID (CDCDedxPIDModule).
Provides a type-safe way to pass members of the chargedStableSet set.
Definition: Const.h:470
A class for sets of detector IDs whose content is limited to restricted set of valid detector IDs.
Definition: Const.h:177
int getPDG() const
Return PDG code of particle.
Definition: MCParticle.h:112
Base class for Modules.
Definition: Module.h:72
Class to collect log likelihoods from TOP, ARICH, dEdx, ECL and KLM aimed for output to mdst includes...
Definition: PIDLikelihood.h:26
bool isRequired(const std::string &name="")
Ensure this array/object has been registered previously.
bool isOptional(const std::string &name="")
Tell the DataStore about an optional input.
Accessor to arrays stored in the data store.
Definition: StoreArray.h:113
Type-safe access to single objects in the data store.
Definition: StoreObjPtr.h:95
Bunch finder: searches for the bunch crossing where the interaction happened using track-based TOP li...
Minimum finder using tabulated chi^2 values in one dimension.
Binned one dimensional PDF (a projection of PDF to time axis)
Definition: PDF1Dim.h:25
double getExpectedSignal() const
Returns expected number of signal photons.
Definition: PDF1Dim.h:73
double getExpectedDeltaPhotons() const
Returns expected number of delta-ray photons.
Definition: PDF1Dim.h:79
double getExpectedBG() const
Returns expected number of background photons.
Definition: PDF1Dim.h:85
int getNumOfPhotons() const
Returns number of photons.
Definition: PDF1Dim.h:67
PDF construction and log likelihood determination for a given track and particle hypothesis.
void switchOffDeltaRayPDF() const
Exclude delta-ray PDF in log likelihood calculation.
bool isValid() const
Checks the object status.
Reconstructed track at TOP.
Definition: TOPTrack.h:40
bool isValid() const
Checks if track is successfully constructed.
Definition: TOPTrack.h:139
const TOPBarHit * getBarHit() const
Returns bar hit of MC particle assigned to this track (if any)
Definition: TOPTrack.h:240
const MCParticle * getMCParticle() const
Returns MC particle assigned to this track (if any)
Definition: TOPTrack.h:224
Class that bundles various TrackFitResults.
Definition: Track.h:25
Container for likelihoods obtained by the VXD dE/dx PID (VXDDedxPIDModule).
#define REG_MODULE(moduleName)
Register the given module (without 'Module' suffix) with the framework.
Definition: Module.h:650
Abstract base class for different kinds of events.
Structure for storing the extracted event t0s together with its detector and its uncertainty.
Definition: EventT0.h:34