Belle II Software development
EventT0Combiner.cc
1/**************************************************************************
2 * basf2 (Belle II Analysis Software Framework) *
3 * Author: The Belle II Collaboration *
4 * *
5 * See git log for contributors and copyright holders. *
6 * This file is licensed under LGPL-3.0, see LICENSE.md. *
7 **************************************************************************/
8
9#include <reconstruction/modules/EventT0Combiner/EventT0Combiner.h>
10
11#include <mdst/dataobjects/EventLevelTriggerTimeInfo.h>
12
13#include <cmath>
14
15using namespace Belle2;
16
17REG_MODULE(EventT0Combiner);
18
20{
21 setDescription("Module to combine the EventT0 values from multiple sub-detectors");
23}
24
26{
27 m_eventT0.isRequired();
28 m_eventLevelTriggerTimeInfo.isRequired();
29}
30
32{
33 if (!m_eventT0.isValid()) {
34 B2DEBUG(20, "EventT0 object not created, cannot do EventT0 combination");
35 // Unset all the EventT0 sources
36 if (m_eventLevelTriggerTimeInfo.isValid())
37 m_eventLevelTriggerTimeInfo->resetEventT0Sources();
38 return;
39 }
40
41 // NOT checking for m_eventT0.hasEventT0() here, as this would only indicate that so far no EventT0 has been set.
42 // However, this does not mean that we can't set one from the temporary values.
43 // But of course nothing can be done if no temporary EventT0s are present.
44 if (m_eventT0->getTemporaryEventT0s().empty()) {
45 B2DEBUG(20, "No temporary EventT0s available, can't chose the best one.");
46 // Unset all the EventT0 sources
47 if (m_eventLevelTriggerTimeInfo.isValid())
48 m_eventLevelTriggerTimeInfo->resetEventT0Sources();
49 return;
50 }
51
52 // We have an SVD based EventT0 and it currently is set as *THE* EventT0 -> nothing to do
53 if (m_eventT0->isSVDEventT0()) {
54 B2DEBUG(20, "EventT0 already based on SVD information, nothing to do.");
55 // Set SVD as the EventT0 source
56 if (m_eventLevelTriggerTimeInfo.isValid()) {
57 m_eventLevelTriggerTimeInfo->resetEventT0Sources();
58 m_eventLevelTriggerTimeInfo->addEventT0SourceFromSVD();
59 }
60 return;
61 }
62
63 // We have an SVD based EventT0 but it currently is *NOT* set as *THE* EventT0 -> set it as *THE* EventT0
64 // This might happen e.g. during calibration if the CDCFullGridChi2 ("chi2", see below) is run after the SVD EventT0 algorithm
65 if (m_eventT0->hasTemporaryEventT0(Const::SVD)) {
66 const auto& bestSVDT0 = m_eventT0->getBestSVDTemporaryEventT0();
67 m_eventT0->setEventT0(*bestSVDT0);
68 B2DEBUG(20, "EventT0 is set to SVD EventT0.");
69 // Set SVD as the EventT0 source
70 if (m_eventLevelTriggerTimeInfo.isValid()) {
71 m_eventLevelTriggerTimeInfo->resetEventT0Sources();
72 m_eventLevelTriggerTimeInfo->addEventT0SourceFromSVD();
73 }
74 return;
75 }
76
77 // If we don't have an SVD based EventT0, the second choice is the EventT0 estimate using CDC information calculabed by the
78 // FullGridChi2TrackTimeExtractor method. In principle, this algorithm can create EventT0 estimates using two methods:
79 // "grid" and "chi2". We are only interested in the latter one.
80 // If no SVD based EventT0 is present, but a CDC based one using the "chi2" algorithm is available -> nothing to do
81 if (m_eventT0->isCDCEventT0()) {
82 const auto& bestCDCT0 = m_eventT0->getBestCDCTemporaryEventT0();
83 if ((*bestCDCT0).algorithm == "chi2") {
84 B2DEBUG(20, "Using CDC chi2 EventT0.");
85 // Set CDC as the EventT0 source
86 if (m_eventLevelTriggerTimeInfo.isValid()) {
87 m_eventLevelTriggerTimeInfo->resetEventT0Sources();
88 m_eventLevelTriggerTimeInfo->addEventT0SourceFromCDC();
89 }
90 return;
91 }
92 B2DEBUG(20, "Current EventT0 is based on CDC, but it's not the chi2 value. Continue Search.");
93 }
94
95 // No CDC chi2 EventT0 present -> try to combine ECL and CDC hit based EventT0
96 // First, clear the EventT0 so that EventT0::hasEventT0() will return false
97 m_eventT0->clearEventT0();
98 const auto& bestECLT0 = m_eventT0->getBestECLTemporaryEventT0();
99 const auto& cdcT0Candidates = m_eventT0->getTemporaryEventT0s(Const::CDC);
100 const auto& hitBasedCDCT0Candidate = std::find_if(cdcT0Candidates.begin(), cdcT0Candidates.end(), [](const auto & a) { return a.algorithm == "hit based";});
101
102 // Strategy in case none of the SVD based or the CDC chi2 based EventT0 values is available:
103 // 1) If we have both an EventT0 estimate from ECL and a CDC hit based value, combine the two
104 // 2) If we only have one of the two, take that value
105 // 3) If we don't have either, we have a problem -> issue a B2WARNING and clear the EventT0
106 // If we arrive at 3), this means that we could only have TOP EventT0, or an EventT0 from a
107 // CDC based algorithm other than "hit based" or "chi2", and so far we don't want to use these.
108 if (bestECLT0 and hitBasedCDCT0Candidate != cdcT0Candidates.end()) {
109 B2DEBUG(20, "Combining ECL EventT0 and CDC hit based EventT0.");
110 const auto combined = computeCombination({ *bestECLT0, *hitBasedCDCT0Candidate });
111 m_eventT0->setEventT0(combined);
112 // Set ECL and CDC as the EventT0 sources
113 if (m_eventLevelTriggerTimeInfo.isValid()) {
114 m_eventLevelTriggerTimeInfo->resetEventT0Sources();
115 m_eventLevelTriggerTimeInfo->addEventT0SourceFromECL();
116 m_eventLevelTriggerTimeInfo->addEventT0SourceFromCDC();
117 }
118 return;
119 } else if (bestECLT0 and hitBasedCDCT0Candidate == cdcT0Candidates.end()) {
120 B2DEBUG(20, "Using ECL EventT0, as CDC hit based EventT0 is not available.");
121 m_eventT0->setEventT0(*bestECLT0);
122 // Set ECL as the EventT0 source
123 if (m_eventLevelTriggerTimeInfo.isValid()) {
124 m_eventLevelTriggerTimeInfo->resetEventT0Sources();
125 m_eventLevelTriggerTimeInfo->addEventT0SourceFromECL();
126 }
127 return;
128 } else if (hitBasedCDCT0Candidate != cdcT0Candidates.end() and not bestECLT0) {
129 B2DEBUG(20, "Using CDC hit based EventT0, as ECL EventT0 is not available.");
130 m_eventT0->setEventT0(*hitBasedCDCT0Candidate);
131 // Set CDC as the EventT0 source
132 if (m_eventLevelTriggerTimeInfo.isValid()) {
133 m_eventLevelTriggerTimeInfo->resetEventT0Sources();
134 m_eventLevelTriggerTimeInfo->addEventT0SourceFromCDC();
135 }
136 return;
137 } else {
138 B2DEBUG(20, "There is no EventT0 from neither \n" \
139 " * the SVD based algorithm\n" \
140 " * the CDC based chi^2 algorithm\n" \
141 " * the CDC based hit-based algorithm\n" \
142 " * the ECL algorithm.\n" \
143 "Thus, no EventT0 value can be calculated.");
144 // Unset all the EventT0 sources
145 if (m_eventLevelTriggerTimeInfo.isValid())
146 m_eventLevelTriggerTimeInfo->resetEventT0Sources();
147 }
148}
149
150EventT0::EventT0Component EventT0CombinerModule::computeCombination(std::vector<EventT0::EventT0Component> measurements) const
151{
152 if (measurements.size() == 0) {
153 B2FATAL("Need at least one EvenT0 Measurement to do a sensible combination.");
154 }
155
156 double eventT0 = 0.0f;
157 double preFactor = 0.0f;
158
159 Const::DetectorSet usedDetectorSet;
160
161 for (auto const& meas : measurements) {
162 usedDetectorSet += meas.detectorSet;
163 const double oneOverUncertaintySquared = 1.0f / std::pow(meas.eventT0Uncertainty, 2.0);
164 eventT0 += meas.eventT0 * oneOverUncertaintySquared;
165 preFactor += oneOverUncertaintySquared;
166 }
167
168 eventT0 /= preFactor;
169 const auto eventT0unc = std::sqrt(1.0f / preFactor);
170
171 return EventT0::EventT0Component(eventT0, eventT0unc, usedDetectorSet);
172}
The DetectorSet class for sets of detector IDs in the form of EDetector values.
Definition Const.h:80
StoreObjPtr< EventT0 > m_eventT0
Access to global EventT0 which will be read and updated.
void initialize() override
Initialize the module.
void event() override
This method is called for each event.
StoreObjPtr< EventLevelTriggerTimeInfo > m_eventLevelTriggerTimeInfo
Access to EventLevelTriggerTimeInfo object.
EventT0::EventT0Component computeCombination(std::vector< EventT0::EventT0Component > measurements) const
computes the new average between multiple, un-correlated sub-detector measurements
EventT0CombinerModule()
Default constructor.
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
Module()
Constructor.
Definition Module.cc:30
@ 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
#define REG_MODULE(moduleName)
Register the given module (without 'Module' suffix) with the framework.
Definition Module.h:649
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