10#include <top/modules/TOPBunchFinder/TOPBunchFinderModule.h>
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>
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>
31#include <framework/logging/Logger.h>
56 setDescription(
"A precise event T0 determination w.r.t local time reference of TOP counter. "
57 "Results available in TOPRecBunch.");
63 "time range in which to do fine search [ns]", 10.0);
65 "time range in which to do coarse search, if autoRange turned off [ns]", 100.0);
67 "turn on/off automatic determination of the coarse search region (false means off)",
false);
69 "sigma in [ns] for additional smearing of PDF", 0.0);
71 "minimal number of signal photons to accept track", 8.0);
73 "minimal signal-to-background ratio to accept track", 0.0);
75 "minimal ratio of detected-to-expected photons to accept track", 0.2);
77 "maximal ratio of detected-to-expected photons to accept track", 2.5);
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);
84 "if true, use MC truth for particle mass instead of the most probable from dEdx",
87 "if true, save histograms to TOPRecBunch and TOPTimeZeros",
false);
89 "first order filter time constant [number of events]", 100.0);
91 "if true, subtract bunch time in TOPDigits",
true);
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.",
97 "number of bunches per SST clock period", 24);
99 "use PIDLikelihoods instead of DedxLikelihoods (only if run on cdst files)",
102 "maximum number of tracks (inclusive) to use three particle hypotheses in fine search "
103 "(only when running in data processing mode).",
unsigned(3));
105 "(only when running in data processing mode and autoRange turned off).",
true);
107 "(only when running in data processing mode).",
true);
162 for (
const auto& prior :
m_priors) s += prior.second;
163 for (
auto& prior :
m_priors) prior.second /= s;
166 B2ERROR(
"Common T0 calibration payload requested but not available");
182 }
else if (
m_commonT0->isRoughlyCalibrated()) {
194 B2INFO(
"TOPBunchFinder: running in HLT/express reco mode");
196 B2INFO(
"TOPBunchFinder: running in data processing mode");
207 B2FATAL(
"Common T0 calibration payload requested but not available for run "
208 << evtMetaData->getRun()
209 <<
" of experiment " << evtMetaData->getExperiment());
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.");
222 B2WARNING(
"BunchStructure not available for run "
223 << evtMetaData->getRun()
224 <<
" of experiment " << evtMetaData->getExperiment()
225 <<
": fill pattern will not be used.");
228 B2WARNING(
"FillPatternOffset not available for run "
229 << evtMetaData->getRun()
230 <<
" of experiment " << evtMetaData->getExperiment()
231 <<
": fill pattern will not be used.");
261 m_recBunch->setSimulated(simBunchNumber, simTime);
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;
291 for (
const auto& track :
m_tracks) {
293 if (not trk.
isValid())
continue;
296 const auto* fitResult = track.getTrackFitResultWithClosestMass(
Const::pion);
298 B2ERROR(
"No TrackFitResult available. Must be a bug somewhere.");
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;
320 if (not pdfConstructor.
isValid())
continue;
324 PDF1Dim pdf1d(pdfConstructor, 0.5, timeWindow);
331 double expPhot = expSignal + expDelta + expBG;
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());
345 if (topTracks.empty())
return;
351 if (timeSeed.sigma == 0) {
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());
365 double binSize = top1Dpdfs[0].getBinSize();
366 int numBins = (maxT0 - minT0) / binSize;
367 maxT0 = minT0 + binSize * numBins;
371 for (
const auto& pdf : top1Dpdfs) {
373 auto& finder = finders.back();
374 const auto& bins = finder.getBinCenters();
375 for (
unsigned i = 0; i < bins.size(); i++) {
377 finder.add(i, -2 * pdf.getLogL(t0));
380 auto coarseFinder = finders[0];
381 for (
size_t i = 1; i < finders.size(); i++) {
382 coarseFinder.add(finders[i]);
385 const auto& t0Coarse = coarseFinder.getMinimum();
387 m_recBunch->addHistogram(coarseFinder.getHistogram(
"chi2_coarse_",
388 "coarse T0; t_{0} [ns]; -2 log L"));
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");
394 timeSeed.t0 = t0Coarse.position;
404 double t0min = timeSeed.t0 - timeRangeFine / 2;
405 double t0max = timeSeed.t0 + timeRangeFine / 2;
407 for (
size_t itrk = 0; itrk < topTracks.size(); itrk++) {
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();
414 std::vector<Const::ChargedStable> other;
425 for (
const auto& chargedStable : other) {
427 if (not pdfConstructor.
isValid())
continue;
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();
442 if (finders.size() == 0)
return;
443 auto finderSum = finders[0];
444 for (
size_t i = 1; i < finders.size(); i++) {
445 finderSum.add(finders[i]);
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));
456 const auto& T0 = finderSum.getMinimum();
458 m_recBunch->addHistogram(finderSum.getHistogram(
"chi2_fine_",
"precise T0; t_{0} [ns]; -2 log L"));
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");
474 }
else if (fabs(deltaOffset -
m_bunchTimeSep) < fabs(deltaOffset)) {
479 double error = T0.error;
485 double a = exp(-1.0 / tau);
488 double err2 = (1 - a) * error;
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());
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);
534 timeZero->setHistograms(chi2, pdf, hits);
543 digit.subtractT0(bunchTime);
544 digit.addStatus(TOPDigit::c_EventT0Subtracted);
547 double err = digit.getTimeError();
549 digit.addStatus(TOPDigit::c_BunchOffsetSubtracted);
559 B2RESULT(
"TOPBunchFinder: event T0 determined for " <<
m_success <<
"/"
567 std::vector<double> logL;
568 std::vector<double> priors;
579 logL.push_back(pid->getLogL(type, subset));
580 priors.push_back(
m_priors[abs(type.getPDGCode())]);
585 if (not cdcdedx and not vxddedx) {
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));
595 logL.push_back(vxddedx->getLogL(type));
597 priors.push_back(
m_priors[abs(type.getPDGCode())]);
602 auto logL_max = logL[0];
603 for (
auto x : logL) {
604 if (x > logL_max) logL_max = x;
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];
615 for (
unsigned i = 0; i < probability.size(); ++i) {
616 if (probability[i] > probability[i0]) i0 = i;
625 std::set<int> nfotSet;
626 const auto& binCenters = finder.getBinCenters();
629 for (
unsigned i = 0; i < binCenters.size(); i++) {
630 double t0 = binCenters[i];
632 finder.add(i, -2 * (LL.logL - logL_bkg));
633 if (i == 0) numPhotons = LL.numPhotons;
634 nfotSet.insert(LL.numPhotons);
637 if (nfotSet.size() != 1) B2ERROR(
"Different number of photons used for log likelihood of different time shifts");
652 for (
auto detector : {Const::SVD, Const::CDC}) {
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;
Container for likelihoods obtained by the CDC dE/dx PID (CDCDedxPIDModule).
Provides a type-safe way to pass members of the chargedStableSet set.
const ParticleType & at(unsigned int index) const
Return particle at given index, or end() if out of range.
const ParticleType & find(int pdg) const
Returns particle in set with given PDG code, or invalidParticle if not found.
RestrictedDetectorSet< PIDDetectors > PIDDetectorSet
Typedef for set of PID detectors.
static const ParticleSet chargedStableSet
set of charged stable particles
static const ChargedStable pion
charged pion particle
static const ChargedStable proton
proton particle
static const ParticleType invalidParticle
Invalid particle, used internally.
static const ChargedStable kaon
charged kaon particle
int getPDG() const
Return PDG code of particle.
void setDescription(const std::string &description)
Sets the description of the module.
void setPropertyFlags(unsigned int propertyFlags)
Sets the flags for the module properties.
@ c_ParallelProcessingCertified
This module can be run in parallel processing mode safely (All I/O must be done through the data stor...
Class to collect log likelihoods from TOP, ARICH, dEdx, ECL and KLM aimed for output to mdst includes...
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.
Type-safe access to single objects in the data store.
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
bool m_isMC
is Monte Carlo
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.
@ c_syncWindows
number of windows corresponding to syncTimeBase
int getBucketNumber() const
Returns reconstructed bucket number stored in private member.
Minimum finder using tabulated chi^2 values in one dimension.
Binned one dimensional PDF (a projection of PDF to time axis)
double getExpectedSignal() const
Returns expected number of signal photons.
double getExpectedDeltaPhotons() const
Returns expected number of delta-ray photons.
double getExpectedBG() const
Returns expected number of background photons.
int getNumOfPhotons() const
Returns number of photons.
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.
const MCParticle * getMCParticle() const
Returns MC particle assigned to this track (if any)
bool isValid() const
Checks if track is successfully constructed.
double getMomentumMag() const
Returns momentum magnitude (extrapolated to TOP)
const TOPBarHit * getBarHit() const
Returns bar hit of MC particle assigned to this track (if any)
Class that bundles various TrackFitResults.
Container for likelihoods obtained by the VXD dE/dx PID (VXDDedxPIDModule).
void addParam(const std::string &name, T ¶mVariable, const std::string &description, const T &defaultValue)
Adds a new parameter to the module.
#define REG_MODULE(moduleName)
Register the given module (without 'Module' suffix) with the framework.
double sqrt(double a)
sqrt for double
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.
TOPBunchFinderModule()
Constructor.
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.
Structure to hold the time seed from a chosen detector component.
Const::EDetector detector
detector component
double sigma
time resolution
double logL
extended log likelihood