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