Belle II Software development
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
34using namespace std;
35
36namespace Belle2 {
41 using namespace TOP;
42
43 //-----------------------------------------------------------------
45 //-----------------------------------------------------------------
46
47 REG_MODULE(TOPBunchFinder);
48
49 //-----------------------------------------------------------------
50 // Implementation
51 //-----------------------------------------------------------------
52
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 {
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
571 const auto* pid = track.getRelated<PIDLikelihood>();
572 if (not pid) {
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) {
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:589
const ParticleType & at(unsigned int index) const
Return particle at given index, or end() if out of range.
Definition: Const.h:549
const ParticleType & find(int pdg) const
Returns particle in set with given PDG code, or invalidParticle if not found.
Definition: Const.h:571
RestrictedDetectorSet< PIDDetectors > PIDDetectorSet
Typedef for set of PID detectors.
Definition: Const.h:379
static const ParticleSet chargedStableSet
set of charged stable particles
Definition: Const.h:618
static const ChargedStable pion
charged pion particle
Definition: Const.h:661
static const ChargedStable proton
proton particle
Definition: Const.h:663
static const ParticleType invalidParticle
Invalid particle, used internally.
Definition: Const.h:681
static const ChargedStable kaon
charged kaon particle
Definition: Const.h:662
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:29
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
const MCParticle * getMCParticle() const
Returns MC particle assigned to this track (if any)
Definition: TOPTrack.h:222
bool isValid() const
Checks if track is successfully constructed.
Definition: TOPTrack.h:137
double getMomentumMag() const
Returns momentum magnitude (extrapolated to TOP)
Definition: TOPTrack.h:149
const TOPBarHit * getBarHit() const
Returns bar hit of MC particle assigned to this track (if any)
Definition: TOPTrack.h:238
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.
STL namespace.
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