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