Belle II Software  release-08-01-10
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 header.
10 #include <top/modules/TOPBunchFinder/TOPBunchFinderModule.h>
11 
12 // TOP headers.
13 #include <top/geometry/TOPGeometryPar.h>
14 #include <top/reconstruction_cpp/TOPTrack.h>
15 #include <top/reconstruction_cpp/PDFConstructor.h>
16 #include <top/reconstruction_cpp/TOPRecoManager.h>
17 #include <top/reconstruction_cpp/PDF1Dim.h>
18 #include <top/utilities/Chi2MinimumFinder1D.h>
19 
20 // Dataobject classes
21 #include <mdst/dataobjects/TrackFitResult.h>
22 #include <mdst/dataobjects/HitPatternCDC.h>
23 #include <tracking/dataobjects/ExtHit.h>
24 #include <mdst/dataobjects/MCParticle.h>
25 #include <top/dataobjects/TOPBarHit.h>
26 #include <reconstruction/dataobjects/CDCDedxLikelihood.h>
27 #include <reconstruction/dataobjects/VXDDedxLikelihood.h>
28 #include <mdst/dataobjects/PIDLikelihood.h>
29 
30 // framework aux
31 #include <framework/logging/Logger.h>
32 #include <set>
33 
34 using namespace std;
35 
36 namespace Belle2 {
41  using namespace TOP;
42 
43  //-----------------------------------------------------------------
45  //-----------------------------------------------------------------
46 
47  REG_MODULE(TOPBunchFinder);
48 
49  //-----------------------------------------------------------------
50  // Implementation
51  //-----------------------------------------------------------------
52 
53  TOPBunchFinderModule::TOPBunchFinderModule() : Module()
54  {
55  // set module description (e.g. insert text)
56  setDescription("A precise event T0 determination w.r.t local time reference of TOP counter. "
57  "Results available in TOPRecBunch.");
59 
60  // Add parameters
61  addParam("numBins", m_numBins, "number of bins of fine search region", 200);
62  addParam("timeRangeFine", m_timeRangeFine,
63  "time range in which to do fine search [ns]", 10.0);
64  addParam("timeRangeCoarse", m_timeRangeCoarse,
65  "time range in which to do coarse search, if autoRange turned off [ns]", 100.0);
66  addParam("autoRange", m_autoRange,
67  "turn on/off automatic determination of the coarse search region (false means off)", false);
68  addParam("sigmaSmear", m_sigmaSmear,
69  "sigma in [ns] for additional smearing of PDF", 0.0);
70  addParam("minSignal", m_minSignal,
71  "minimal number of signal photons to accept track", 8.0);
72  addParam("minSBRatio", m_minSBRatio,
73  "minimal signal-to-background ratio to accept track", 0.0);
74  addParam("minDERatio", m_minDERatio,
75  "minimal ratio of detected-to-expected photons to accept track", 0.2);
76  addParam("maxDERatio", m_maxDERatio,
77  "maximal ratio of detected-to-expected photons to accept track", 2.5);
78  addParam("minPt", m_minPt, "minimal p_T of the track", 0.3);
79  addParam("maxPt", m_maxPt, "maximal p_T of the track", 6.0);
80  addParam("maxD0", m_maxD0, "maximal absolute value of helix perigee distance", 2.0);
81  addParam("maxZ0", m_maxZ0, "maximal absolute value of helix perigee z coordinate", 4.0);
82  addParam("minNHitsCDC", m_minNHitsCDC, "minimal number of hits in CDC", 20);
83  addParam("useMCTruth", m_useMCTruth,
84  "if true, use MC truth for particle mass instead of the most probable from dEdx",
85  false);
86  addParam("saveHistograms", m_saveHistograms,
87  "if true, save histograms to TOPRecBunch and TOPTimeZeros", false);
88  addParam("tau", m_tau,
89  "first order filter time constant [number of events]", 100.0);
90  addParam("correctDigits", m_correctDigits,
91  "if true, subtract bunch time in TOPDigits", true);
92  addParam("subtractRunningOffset", m_subtractRunningOffset,
93  "if true and correctDigits = True, subtract running offset in TOPDigits "
94  "when running in HLT mode. It must be set to false when running calibration.",
95  true);
96  addParam("bunchesPerSSTclk", m_bunchesPerSSTclk,
97  "number of bunches per SST clock period", 24);
98  addParam("usePIDLikelihoods", m_usePIDLikelihoods,
99  "use PIDLikelihoods instead of DedxLikelihoods (only if run on cdst files)",
100  false);
101  addParam("nTrackLimit", m_nTrackLimit,
102  "maximum number of tracks (inclusive) to use three particle hypotheses in fine search "
103  "(only when running in data processing mode).", unsigned(3));
104  addParam("useTimeSeed", m_useTimeSeed, "use SVD or CDC event T0 as a seed "
105  "(only when running in data processing mode and autoRange turned off).", true);
106  addParam("useFillPattern", m_useFillPattern, "use known accelerator fill pattern to enhance efficiency "
107  "(only when running in data processing mode).", true);
108  }
109 
110 
112  {
113  // input collections
114 
115  m_topDigits.isRequired();
116  m_topRawDigits.isOptional();
117  m_tracks.isRequired();
118  StoreArray<ExtHit> extHits;
119  extHits.isRequired();
120  m_initialParticles.isOptional();
121 
122  if (m_useMCTruth) {
123  StoreArray<MCParticle> mcParticles;
124  mcParticles.isRequired();
125  StoreArray<TOPBarHit> barHits;
126  barHits.isRequired();
127  } else {
128  if (m_usePIDLikelihoods) {
129  StoreArray<PIDLikelihood> pidLikelihoods;
130  pidLikelihoods.isRequired();
131  } else {
132  StoreArray<CDCDedxLikelihood> cdcDedxLikelihoods;
133  cdcDedxLikelihoods.isRequired();
134  StoreArray<VXDDedxLikelihood> vxdDedxLikelihoods;
135  vxdDedxLikelihoods.isOptional();
136  }
137  }
138 
139  // output
140 
141  m_recBunch.registerInDataStore();
142  m_timeZeros.registerInDataStore();
143  m_timeZeros.registerRelationTo(extHits);
144  m_eventT0.registerInDataStore(); // usually it is already registered in tracking
145 
146  // bunch separation in time
147 
148  const auto* geo = TOPGeometryPar::Instance()->getGeometry();
149  m_bunchTimeSep = geo->getNominalTDC().getSyncTimeBase() / m_bunchesPerSSTclk;
150 
151  // prior probabilities: from generic BBbar simulation
152  // - MCParticles with reconstructed track and at least 5 detected Cherenkov photons
153 
154  m_priors[11] = 0.062; // electrons
155  m_priors[13] = 0.086; // muons
156  m_priors[211] = 0.734; // pions
157  m_priors[321] = 0.106; // kaons
158  m_priors[2212] = 0.013; // protons
159  m_priors[1000010020] = 0; // deuterons
160 
161  double s = 0;
162  for (const auto& prior : m_priors) s += prior.second;
163  for (auto& prior : m_priors) prior.second /= s;
164 
165  if (not m_commonT0.isValid()) {
166  B2ERROR("Common T0 calibration payload requested but not available");
167  return;
168  }
169 
170  /*************************************************************************
171  * auto detection of HLT/express reco mode via status of common T0 payload:
172  * c_Default -> HLT/express reco mode
173  * c_Calibrated -> data processing mode
174  * c_Unusable -> HLT/express reco mode
175  * c_roughlyCalibrated -> HLT/express reco mode
176  *************************************************************************/
177 
178  if (m_commonT0->isCalibrated()) {
179  m_HLTmode = false;
180  m_runningOffset = 0; // since digits are already commonT0 calibrated
181  m_runningError = m_commonT0->getT0Error();
182  } else if (m_commonT0->isRoughlyCalibrated()) {
183  m_HLTmode = true;
184  m_runningOffset = m_commonT0->getT0(); // since digits are not commonT0 calibrated
185  m_runningError = m_commonT0->getT0Error();
186  } else {
187  m_HLTmode = true;
188  m_runningOffset = 0;
190  }
191 
192  if (m_HLTmode) {
193  m_nTrackLimit = 0; // use single particle hypothesis to save execution time
194  B2INFO("TOPBunchFinder: running in HLT/express reco mode");
195  } else {
196  B2INFO("TOPBunchFinder: running in data processing mode");
197  }
198 
199  }
200 
201 
203  {
204  StoreObjPtr<EventMetaData> evtMetaData;
205 
206  if (not m_commonT0.isValid()) {
207  B2FATAL("Common T0 calibration payload requested but not available for run "
208  << evtMetaData->getRun()
209  << " of experiment " << evtMetaData->getExperiment());
210  }
211 
212  if (m_HLTmode) return;
213 
214  if (m_useTimeSeed and not m_eventT0Offset.isValid()) {
215  B2WARNING("EventT0Offset not available for run "
216  << evtMetaData->getRun()
217  << " of experiment " << evtMetaData->getExperiment()
218  << ": seeding with SVD or CDC eventT0 will not be done.");
219  }
220  if (m_useFillPattern) {
221  if (not m_bunchStructure->isSet()) {
222  B2WARNING("BunchStructure not available for run "
223  << evtMetaData->getRun()
224  << " of experiment " << evtMetaData->getExperiment()
225  << ": fill pattern will not be used.");
226  }
227  if (not m_fillPatternOffset.isValid()) {
228  B2WARNING("FillPatternOffset not available for run "
229  << evtMetaData->getRun()
230  << " of experiment " << evtMetaData->getExperiment()
231  << ": fill pattern will not be used.");
232  }
233  }
234 
235  }
236 
237 
239  {
240 
241  m_processed++;
243 
244  // define output for the reconstructed bunch
245 
246  if (not m_recBunch.isValid()) {
247  m_recBunch.create();
248  } else {
249  m_revo9Counter = m_recBunch->getRevo9Counter();
250  m_recBunch->clearReconstructed();
251  }
252  m_timeZeros.clear();
253 
254  if (not m_eventT0.isValid()) m_eventT0.create();
255 
256  // set MC truth if available
257 
258  if (m_initialParticles.isValid()) {
259  double simTime = m_initialParticles->getTime();
260  int simBunchNumber = round(simTime / m_bunchTimeSep);
261  m_recBunch->setSimulated(simBunchNumber, simTime);
262  }
263  m_isMC = m_recBunch->isSimulated();
264 
265  // set revo9 counter from the first raw digit if available (all should be the same)
266 
267  if (m_topRawDigits.getEntries() > 0) {
268  const auto* rawDigit = m_topRawDigits[0];
269  m_revo9Counter = rawDigit->getRevo9Counter();
270  m_recBunch->setRevo9Counter(m_revo9Counter);
271  }
272 
273  // full time window in which data are taken (smaller time window is used in reconstruction)
274 
275  const auto& tdc = TOPGeometryPar::Instance()->getGeometry()->getNominalTDC();
276  double timeWindow = m_feSetting->getReadoutWindows() * tdc.getSyncTimeBase() / static_cast<double>(TOPNominalTDC::c_syncWindows);
277 
278  // counters and temporary containers
279 
280  int numTrk = 0;
281  m_nodEdxCount = 0;
282  std::vector<TOPTrack> topTracks;
283  std::vector<PDFConstructor> pdfConstructors;
284  std::vector<PDF1Dim> top1Dpdfs;
285  std::vector<int> numPhotons;
286  std::vector<double> assumedMasses;
287  std::vector<Chi2MinimumFinder1D> finders;
288 
289  // loop over reconstructed tracks, make a selection and push to containers
290 
291  for (const auto& track : m_tracks) {
292  TOPTrack trk(track);
293  if (not trk.isValid()) continue;
294 
295  // track selection
296  const auto* fitResult = track.getTrackFitResultWithClosestMass(Const::pion);
297  if (not fitResult) {
298  B2ERROR("No TrackFitResult available. Must be a bug somewhere.");
299  continue;
300  }
301  if (fitResult->getHitPatternCDC().getNHits() < m_minNHitsCDC) continue;
302  if (fabs(fitResult->getD0()) > m_maxD0) continue;
303  if (fabs(fitResult->getZ0()) > m_maxZ0) continue;
304  auto pt = fitResult->getTransverseMomentum();
305  if (pt < m_minPt or pt > m_maxPt) continue;
306 
307  // determine most probable particle mass
308  auto chargedStable = Const::pion;
309  if (m_useMCTruth) {
310  if (not trk.getMCParticle()) continue;
311  if (not trk.getBarHit()) continue;
312  chargedStable = Const::chargedStableSet.find(abs(trk.getMCParticle()->getPDG()));
313  if (chargedStable == Const::invalidParticle) continue;
314  } else {
315  if (trk.getMomentumMag() < 4.0) chargedStable = getMostProbable(track);
316  }
317 
318  // construct PDF
319  PDFConstructor pdfConstructor(trk, chargedStable, PDFConstructor::c_Rough);
320  if (not pdfConstructor.isValid()) continue;
321  numTrk++;
322 
323  // make PDF projection to time axis with bin size of ~0.5 ns
324  PDF1Dim pdf1d(pdfConstructor, 0.5, timeWindow);
325  pdfConstructor.switchOffDeltaRayPDF(); // to speed-up fine search
326 
327  // do further track selection
328  double expSignal = pdf1d.getExpectedSignal();
329  double expDelta = pdf1d.getExpectedDeltaPhotons();
330  double expBG = pdf1d.getExpectedBG();
331  double expPhot = expSignal + expDelta + expBG;
332  double numPhot = pdf1d.getNumOfPhotons();
333  if (expSignal < m_minSignal) continue;
334  if (expSignal < m_minSBRatio * expBG) continue;
335  if (numPhot < m_minDERatio * expPhot) continue;
336  if (numPhot > m_maxDERatio * expPhot) continue;
337 
338  topTracks.push_back(trk);
339  pdfConstructors.push_back(pdfConstructor);
340  top1Dpdfs.push_back(pdf1d);
341  numPhotons.push_back(numPhot);
342  assumedMasses.push_back(pdfConstructors.back().getHypothesis().getMass());
343  }
344  m_recBunch->setNumTracks(numTrk, topTracks.size(), m_nodEdxCount);
345  if (topTracks.empty()) return;
346 
347  // get time seed
348 
349  auto timeSeed = getTimeSeed();
350 
351  if (timeSeed.sigma == 0) { // time seed is not given - perform coarse search
352 
353  // set time region for coarse search
354 
355  double minT0 = -m_timeRangeCoarse / 2;
356  double maxT0 = m_timeRangeCoarse / 2;
357  if (m_autoRange) {
358  minT0 = top1Dpdfs[0].getMinT0();
359  maxT0 = top1Dpdfs[0].getMaxT0();
360  for (const auto& pdf : top1Dpdfs) {
361  minT0 = std::min(minT0, pdf.getMinT0());
362  maxT0 = std::max(maxT0, pdf.getMaxT0());
363  }
364  }
365  double binSize = top1Dpdfs[0].getBinSize();
366  int numBins = (maxT0 - minT0) / binSize;
367  maxT0 = minT0 + binSize * numBins;
368 
369  // find coarse T0
370 
371  for (const auto& pdf : top1Dpdfs) {
372  finders.push_back(Chi2MinimumFinder1D(numBins, minT0, maxT0));
373  auto& finder = finders.back();
374  const auto& bins = finder.getBinCenters();
375  for (unsigned i = 0; i < bins.size(); i++) {
376  double t0 = bins[i];
377  finder.add(i, -2 * pdf.getLogL(t0));
378  }
379  }
380  auto coarseFinder = finders[0];
381  for (size_t i = 1; i < finders.size(); i++) {
382  coarseFinder.add(finders[i]);
383  }
384 
385  const auto& t0Coarse = coarseFinder.getMinimum();
386  if (m_saveHistograms) {
387  m_recBunch->addHistogram(coarseFinder.getHistogram("chi2_coarse_",
388  "coarse T0; t_{0} [ns]; -2 log L"));
389  }
390  if (t0Coarse.position < minT0 or t0Coarse.position > maxT0 or not t0Coarse.valid) {
391  B2DEBUG(20, "Coarse T0 finder: returning invalid or out of range T0");
392  return;
393  }
394  timeSeed.t0 = t0Coarse.position;
395  }
396 
397  // find precise T0
398 
399  finders.clear();
400 
401  double timeMin = TOPRecoManager::getMinTime() + timeSeed.t0;
402  double timeMax = TOPRecoManager::getMaxTime() + timeSeed.t0;
403  double timeRangeFine = std::max(m_timeRangeFine, timeSeed.sigma * 6);
404  double t0min = timeSeed.t0 - timeRangeFine / 2;
405  double t0max = timeSeed.t0 + timeRangeFine / 2;
406 
407  for (size_t itrk = 0; itrk < topTracks.size(); itrk++) {
408  finders.push_back(Chi2MinimumFinder1D(m_numBins, t0min, t0max));
409  const auto& reco = pdfConstructors[itrk];
410  numPhotons[itrk] = setFinder(finders.back(), reco, timeMin, timeMax);
411  const auto& trk = topTracks[itrk];
412  double momentum = trk.getMomentumMag();
413  if (not m_useMCTruth and momentum > 0.7 and topTracks.size() <= m_nTrackLimit) {
414  std::vector<Const::ChargedStable> other;
415  if (reco.getHypothesis() == Const::kaon) {
416  other.push_back(Const::pion);
417  if (momentum < 4.0) other.push_back(Const::proton);
418  } else if (reco.getHypothesis() == Const::proton) {
419  other.push_back(Const::pion);
420  if (momentum < 2.0) other.push_back(Const::kaon);
421  } else {
422  if (momentum < 2.0) other.push_back(Const::kaon);
423  if (momentum < 4.0) other.push_back(Const::proton);
424  }
425  for (const auto& chargedStable : other) {
426  PDFConstructor pdfConstructor(trk, chargedStable, PDFConstructor::c_Rough);
427  if (not pdfConstructor.isValid()) continue;
428  pdfConstructor.switchOffDeltaRayPDF(); // to speed-up fine search
429  if (pdfConstructor.getExpectedSignalPhotons() < m_minSignal) continue;
430  Chi2MinimumFinder1D finder(m_numBins, t0min, t0max);
431  int numPhot = setFinder(finder, pdfConstructor, timeMin, timeMax);
432  if (numPhot != numPhotons[itrk])
433  B2ERROR("Different number of photons used for log likelihood of different mass hypotheses");
434  if (finder.getMinChi2() < finders.back().getMinChi2()) {
435  finders.back() = finder;
436  assumedMasses[itrk] = chargedStable.getMass();
437  }
438  }
439  }
440  }
441 
442  if (finders.size() == 0) return; // just in case
443  auto finderSum = finders[0];
444  for (size_t i = 1; i < finders.size(); i++) {
445  finderSum.add(finders[i]);
446  }
447 
448  if (timeSeed.sigma > 0) {
449  const auto& binCenters = finderSum.getBinCenters();
450  for (unsigned i = 0; i < binCenters.size(); i++) {
451  double t0 = binCenters[i];
452  finderSum.add(i, pow((t0 - timeSeed.t0) / timeSeed.sigma, 2)); // add chi2 according to timeSeed resolution
453  }
454  }
455 
456  const auto& T0 = finderSum.getMinimum();
457  if (m_saveHistograms) {
458  m_recBunch->addHistogram(finderSum.getHistogram("chi2_fine_", "precise T0; t_{0} [ns]; -2 log L"));
459  }
460  if (T0.position < t0min or T0.position > t0max or not T0.valid) {
461  B2DEBUG(20, "Fine T0 finder: returning invalid or out of range T0");
462  return;
463  }
464 
465  // bunch time and current offset
466 
467  int bunchNo = lround(T0.position / m_bunchTimeSep); // round to nearest integer
468  double offset = T0.position - m_bunchTimeSep * bunchNo;
469  if (not m_commonT0->isCalibrated()) { // auto set offset range
470  double deltaOffset = offset - m_runningOffset;
471  if (fabs(deltaOffset + m_bunchTimeSep) < fabs(deltaOffset)) {
472  offset += m_bunchTimeSep;
473  bunchNo--;
474  } else if (fabs(deltaOffset - m_bunchTimeSep) < fabs(deltaOffset)) {
475  offset -= m_bunchTimeSep;
476  bunchNo++;
477  }
478  }
479  double error = T0.error;
480 
481  // averaging with first order filter (with adoptable time constant)
482 
483  double tau = 10 + m_success / 2; // empirically with toy MC
484  if (tau > m_tau) tau = m_tau;
485  double a = exp(-1.0 / tau);
486  m_runningOffset = a * m_runningOffset + (1 - a) * offset;
487  double err1 = a * m_runningError;
488  double err2 = (1 - a) * error;
489  m_runningError = sqrt(err1 * err1 + err2 * err2);
490 
491  // when not running in HLT mode, check if reconstructed bunch is filled
492 
493  if (not m_HLTmode) {
494  bool isFilled = isBucketFilled(bunchNo); // stores in addition the bucket number and fill status in m_recBunch
495  if (m_useFillPattern and not isFilled) return;
496  }
497 
498  // store the results
499 
500  double bunchTime = bunchNo * m_bunchTimeSep;
501  m_recBunch->setReconstructed(bunchNo, bunchTime, offset, error, m_runningOffset, m_runningError, timeSeed.detector);
502  m_recBunch->setMinChi2(T0.chi2);
503  double svdOffset = m_eventT0Offset.isValid() and not m_isMC ? m_eventT0Offset->get(Const::SVD).offset : 0;
504  m_eventT0->addTemporaryEventT0(EventT0::EventT0Component(bunchTime + svdOffset, error, Const::TOP, "bunchFinder"));
505  m_success++;
506 
507  // store T0 of single tracks relative to bunchTime
508 
509  if (finders.size() == topTracks.size()) {
510  for (size_t itrk = 0; itrk < topTracks.size(); itrk++) {
511  const auto& trk = topTracks[itrk];
512  auto& finder = finders[itrk];
513  const auto& t0trk = finder.getMinimum();
514  auto* timeZero = m_timeZeros.appendNew(trk.getModuleID(),
515  t0trk.position - bunchTime,
516  t0trk.error, numPhotons[itrk]);
517  timeZero->setAssumedMass(assumedMasses[itrk]);
518  if (not t0trk.valid) timeZero->setInvalid();
519  timeZero->setMinChi2(finder.getMinChi2());
520  timeZero->addRelationTo(trk.getExtHit());
521 
522  if (m_saveHistograms) {
523  std::string num = std::to_string(itrk);
524  auto chi2 = finder.getHistogram("chi2_" + num,
525  "precise T0 single track; t_{0} [ns]; -2 log L");
526  auto pdf = top1Dpdfs[itrk].getHistogram("pdf1D_" + num,
527  "PDF projected to time axis; time [ns]");
528  TH1F hits(("hits_" + num).c_str(),
529  "time distribution of hits (t0-subtracted); time [ns]",
530  pdf.GetNbinsX(), pdf.GetXaxis()->GetXmin(), pdf.GetXaxis()->GetXmax());
531  for (const auto& hit : trk.getSelectedHits()) {
532  hits.Fill(hit.time - t0trk.position);
533  }
534  timeZero->setHistograms(chi2, pdf, hits);
535  }
536  }
537  }
538 
539  // correct time in TOPDigits
540 
541  if (m_correctDigits) {
542  for (auto& digit : m_topDigits) {
543  digit.subtractT0(bunchTime);
544  digit.addStatus(TOPDigit::c_EventT0Subtracted);
546  digit.subtractT0(m_runningOffset);
547  double err = digit.getTimeError();
548  digit.setTimeError(sqrt(err * err + m_runningError * m_runningError));
549  digit.addStatus(TOPDigit::c_BunchOffsetSubtracted);
550  }
551  }
552  }
553 
554  }
555 
556 
558  {
559  B2RESULT("TOPBunchFinder: event T0 determined for " << m_success << "/"
560  << m_processed << " events");
561  }
562 
563 
565  {
566 
567  std::vector<double> logL;
568  std::vector<double> priors;
569 
570  if (m_usePIDLikelihoods) {
571  const auto* pid = track.getRelated<PIDLikelihood>();
572  if (not pid) {
573  m_nodEdxCount++;
574  return Const::pion;
575  }
576  auto subset = Const::PIDDetectorSet(Const::SVD);
577  subset += Const::PIDDetectorSet(Const::CDC);
578  for (const auto& type : Const::chargedStableSet) {
579  logL.push_back(pid->getLogL(type, subset));
580  priors.push_back(m_priors[abs(type.getPDGCode())]);
581  }
582  } else {
583  const auto* cdcdedx = track.getRelated<CDCDedxLikelihood>();
584  const auto* vxddedx = track.getRelated<VXDDedxLikelihood>();
585  if (not cdcdedx and not vxddedx) {
586  m_nodEdxCount++;
587  return Const::pion;
588  }
589  for (const auto& type : Const::chargedStableSet) {
590  if (cdcdedx and vxddedx) {
591  logL.push_back(cdcdedx->getLogL(type) + vxddedx->getLogL(type));
592  } else if (cdcdedx) {
593  logL.push_back(cdcdedx->getLogL(type));
594  } else {
595  logL.push_back(vxddedx->getLogL(type));
596  }
597  priors.push_back(m_priors[abs(type.getPDGCode())]);
598  }
599  }
600 
601  // get maximal logL
602  auto logL_max = logL[0];
603  for (auto x : logL) {
604  if (x > logL_max) logL_max = x;
605  }
606 
607  // calculate probabilities, normalizaton is not needed
608  std::vector<double> probability(logL.size());
609  for (unsigned i = 0; i < logL.size(); ++i) {
610  probability[i] = exp(logL[i] - logL_max) * priors[i];
611  }
612 
613  // find most probable
614  unsigned i0 = 0;
615  for (unsigned i = 0; i < probability.size(); ++i) {
616  if (probability[i] > probability[i0]) i0 = i;
617  }
618  return Const::chargedStableSet.at(i0);
619 
620  }
621 
622 
623  int TOPBunchFinderModule::setFinder(Chi2MinimumFinder1D& finder, const PDFConstructor& reco, double timeMin, double timeMax)
624  {
625  std::set<int> nfotSet; // for control only
626  const auto& binCenters = finder.getBinCenters();
627  int numPhotons = 0;
628  double logL_bkg = reco.getBackgroundLogL(timeMin, timeMax).logL;
629  for (unsigned i = 0; i < binCenters.size(); i++) {
630  double t0 = binCenters[i];
631  auto LL = reco.getLogL(t0, timeMin, timeMax, m_sigmaSmear);
632  finder.add(i, -2 * (LL.logL - logL_bkg));
633  if (i == 0) numPhotons = LL.numPhotons;
634  nfotSet.insert(LL.numPhotons);
635  }
636 
637  if (nfotSet.size() != 1) B2ERROR("Different number of photons used for log likelihood of different time shifts");
638 
639  return numPhotons;
640  }
641 
642 
644  {
645  TimeSeed timeSeed; // default time seed; sigma == 0 signals that the seed is not given
646 
647  if (m_HLTmode) return timeSeed;
648  if (m_autoRange) return timeSeed;
649  if (not m_useTimeSeed) return timeSeed;
650  if (not m_eventT0Offset.isValid()) return timeSeed;
651 
652  for (auto detector : {Const::SVD, Const::CDC}) {
653  if (m_eventT0Offset->isAvailable(detector) and m_eventT0->hasTemporaryEventT0(detector)) {
654  auto eventT0s = m_eventT0->getTemporaryEventT0s(detector);
655  if (eventT0s.empty()) continue;
656  if (detector == Const::CDC and eventT0s.back().algorithm != "chi2") continue;
657  double t0 = eventT0s.back().eventT0;
658  if (std::abs(t0) > m_timeRangeCoarse / 2) continue;
659  timeSeed.t0 = m_isMC ? t0 : t0 - m_eventT0Offset->get(detector).offset;
660  timeSeed.sigma = m_eventT0Offset->get(detector).sigma;
661  timeSeed.detector = detector;
662  break;
663  }
664  }
665 
666  return timeSeed;
667  }
668 
669 
671  {
672  // return true if needed information is not available
673 
674  if (not m_bunchStructure->isSet()) return true;
675  if (m_revo9Counter == 0xFFFF) return true;
676 
677  // fill pattern offset; it is always zero on MC.
678 
679  int offset = 0;
680  if (not m_isMC) {
681  if (not m_fillPatternOffset.isValid()) return true;
682  if (not m_fillPatternOffset->isCalibrated()) return true;
683  offset = m_fillPatternOffset->get();
684  }
685 
686  // corresponding bucket number and fill status
687 
688  int RFBuckets = m_bunchStructure->getRFBucketsPerRevolution();
689  int bucket = TOPRecBunch::getBucketNumber(bunchNo, m_revo9Counter, offset, RFBuckets);
690  bool isFilled = m_bunchStructure->getBucket(bucket);
691 
692  // store them in TOPRecBunch
693 
694  m_recBunch->setBucketNumber(bucket);
695  m_recBunch->setBucketFillStatus(isFilled);
696 
697  return isFilled;
698  }
699 
700 
702 } // 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:580
const ParticleType & at(unsigned int index) const
Return particle at given index, or end() if out of range.
Definition: Const.h:540
const ParticleType & find(int pdg) const
Returns particle in set with given PDG code, or invalidParticle if not found.
Definition: Const.h:562
RestrictedDetectorSet< PIDDetectors > PIDDetectorSet
Typedef for set of PID detectors.
Definition: Const.h:370
static const ParticleSet chargedStableSet
set of charged stable particles
Definition: Const.h:609
static const ChargedStable pion
charged pion particle
Definition: Const.h:652
static const ChargedStable proton
proton particle
Definition: Const.h:654
static const ParticleType invalidParticle
Invalid particle, used internally.
Definition: Const.h:672
static const ChargedStable kaon
charged kaon particle
Definition: Const.h:653
int getPDG() const
Return PDG code of particle.
Definition: MCParticle.h:112
Base class for Modules.
Definition: Module.h:72
void setDescription(const std::string &description)
Sets the description of the module.
Definition: Module.cc:214
void setPropertyFlags(unsigned int propertyFlags)
Sets the flags for the module properties.
Definition: Module.cc:208
@ c_ParallelProcessingCertified
This module can be run in parallel processing mode safely (All I/O must be done through the data stor...
Definition: Module.h:80
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:96
double m_maxD0
maximal absolute value of helix perigee distance
unsigned m_nTrackLimit
maximum number of tracks (inclusive) to use three particle hypotheses in fine search
StoreObjPtr< TOPRecBunch > m_recBunch
reconstructed bunch
bool m_correctDigits
subtract bunch time in TOPDigits
DBObjPtr< TOPFrontEndSetting > m_feSetting
front-end settings
StoreObjPtr< EventT0 > m_eventT0
event T0
double m_minDERatio
minimal ratio of detected over expected photons
double m_sigmaSmear
additional smearing of PDF in [ns]
DBObjPtr< TOPCalCommonT0 > m_commonT0
common T0 calibration constants
bool m_HLTmode
use running average to correct digits
unsigned short m_revo9Counter
number of system clocks since last revo9 marker
int m_nodEdxCount
counter of tracks with no dEdx, reset at each event
double m_runningError
error on running average
int m_bunchesPerSSTclk
number of bunches per SST clock
bool m_useTimeSeed
use CDC or SVD event T0 as seed
bool m_saveHistograms
flag to save histograms
double m_minSignal
minimal number of signal photons
double m_maxZ0
maximal absolute value of helix perigee z coordnate
bool m_useFillPattern
use know fill pattern to enhance efficiency
int m_numBins
number of bins to which the fine search region is divided
bool m_subtractRunningOffset
subtract running offset when running in HLT mode
bool m_autoRange
determine coarse range automatically
double m_runningOffset
running average of bunch offset
int m_minNHitsCDC
minimal number of hits in CDC
unsigned m_success
events with reconstructed bunch
OptionalDBObjPtr< TOPCalFillPatternOffset > m_fillPatternOffset
fill pattern offset
double m_timeRangeFine
time range in which to do fine search [ns]
StoreArray< Track > m_tracks
collection of tracks
DBObjPtr< BunchStructure > m_bunchStructure
fill pattern
bool m_useMCTruth
use MC truth for mass instead of dEdx most probable
double m_minPt
minimal p_T of track
double m_tau
first order filter time constant [events]
OptionalDBObjPtr< TOPCalEventT0Offset > m_eventT0Offset
detector components offsets w.r.t TOP
double m_maxDERatio
maximal ratio of detected over expected photons
bool m_usePIDLikelihoods
if true, use PIDLikelihoods (only on cdst files)
double m_maxPt
maximal p_T of track
StoreArray< TOPRawDigit > m_topRawDigits
collection of TOP raw digits
unsigned m_processed
processed events
StoreArray< TOPTimeZero > m_timeZeros
collection of T0 of individual tracks
double m_bunchTimeSep
time between two bunches
double m_timeRangeCoarse
time range in which to do coarse search if autoRange turned off [ns]
std::map< int, double > m_priors
map of PDG codes to prior probabilities
StoreArray< TOPDigit > m_topDigits
collection of TOP digits
StoreObjPtr< MCInitialParticles > m_initialParticles
simulated beam particles
double m_minSBRatio
minimal signal-to-background ratio
const TOPNominalTDC & getNominalTDC() const
Returns nominal time-to-digit conversion parameters.
Definition: TOPGeometry.h:218
@ c_syncWindows
number of windows corresponding to syncTimeBase
Definition: TOPNominalTDC.h:29
int getBucketNumber() const
Returns reconstructed bucket number stored in private member.
Definition: TOPRecBunch.h:188
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.
LogL getBackgroundLogL() const
Returns extended log likelihood for background hypothesis using default time window.
void switchOffDeltaRayPDF() const
Exclude delta-ray PDF in log likelihood calculation.
LogL getLogL() const
Returns extended log likelihood (using the default time window)
bool isValid() const
Checks the object status.
double getExpectedSignalPhotons() const
Returns the expected number of signal photons within the default time window.
@ c_Rough
no dependence on y
const TOPGeometry * getGeometry() const
Returns pointer to geometry object using basf2 units.
static TOPGeometryPar * Instance()
Static method to obtain the pointer to its instance.
static void setDefaultTimeWindow()
Sets default time window (functions getMinTime(), getMaxTime() will then return default values from D...
static double getMaxTime()
Returns time window upper edge.
static double getMinTime()
Returns time window lower edge.
Reconstructed track at TOP.
Definition: TOPTrack.h:39
bool isValid() const
Checks if track is successfully constructed.
Definition: TOPTrack.h:137
const TOPBarHit * getBarHit() const
Returns bar hit of MC particle assigned to this track (if any)
Definition: TOPTrack.h:238
const MCParticle * getMCParticle() const
Returns MC particle assigned to this track (if any)
Definition: TOPTrack.h:222
double getMomentumMag() const
Returns momentum magnitude (extrapolated to TOP)
Definition: TOPTrack.h:149
Class that bundles various TrackFitResults.
Definition: Track.h:25
Container for likelihoods obtained by the VXD dE/dx PID (VXDDedxPIDModule).
void addParam(const std::string &name, T &paramVariable, const std::string &description, const T &defaultValue)
Adds a new parameter to the module.
Definition: Module.h:560
#define REG_MODULE(moduleName)
Register the given module (without 'Module' suffix) with the framework.
Definition: Module.h:650
double sqrt(double a)
sqrt for double
Definition: beamHelpers.h:28
virtual void initialize() override
Initialize the Module.
virtual void event() override
Event processor.
Const::ChargedStable getMostProbable(const Track &track)
Returns most probable charged stable particle according to dEdx and predefined prior probabilities.
virtual void terminate() override
Termination action.
bool isBucketFilled(int bunchNo)
Does reconstructed bunch number correspond to filled bucket.
virtual void beginRun() override
Called when entering a new run.
int setFinder(TOP::Chi2MinimumFinder1D &finder, const TOP::PDFConstructor &reco, double timeMin, double timeMax)
Sets finder object with chi2 values.
TimeSeed getTimeSeed()
Returns a time seed.
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:33
Structure to hold the time seed from a chosen detector component.
double logL
extended log likelihood