Belle II Software development
ECLEventT0Module.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//This module
9#include <ecl/modules/eclEventT0/ECLEventT0Module.h>
10
11//Root
12#include <TMath.h>
13
14//Frameork
15#include <framework/dataobjects/EventT0.h>
16
17//ECL
18#include <ecl/dataobjects/ECLCalDigit.h>
19
20using namespace Belle2;
21using namespace std;
22
23//-----------------------------------------------------------------
24// Register the Module
25//-----------------------------------------------------------------
26REG_MODULE(ECLEventT0);
27
28//-----------------------------------------------------------------
29// Implementation
30//-----------------------------------------------------------------
31
33{
34 // Set module properties
35 setDescription("EventT0 calculated using ECLCalDigits");
36 addParam("ethresh", m_ethresh, "Minimum energy (GeV) for an ECLCalDigit to be used", 0.06);
37 addParam("maxDigitT", m_maxDigitT, "Maximum absolute time (ns) for an ECLCalDigit to be used", 150.);
38 addParam("sigmaScale", m_sigmaScale, "Scale factor between dt99 and ECLCalDigit time resolution", 0.15);
39 addParam("maxT0", m_maxT0, "Maximum absolute value (ns) for T0", 135.);
40 addParam("T0bin", m_T0bin, "Step size between T0 hypotheses (ns)", 1.);
41 addParam("primaryT0", m_primaryT0, "Select which T0 estimate is primary", 0);
43}
44
46{
48 m_eventT0.registerInDataStore();
49 m_eclCalDigitArray.isRequired();
50}
51
53{
54
55 //-----------------------------------------------------------------
57 std::vector<float> tLike;
58 std::vector<float> sigmaLike;
59 float tmin = 9999.;
60 int itmin = -1;
61 float tmax = -9999.;
62 int itmax = -1;
63 for (auto& eclCalDigit : m_eclCalDigitArray) {
64 float digitT = eclCalDigit.getTime();
65 float dt99 = eclCalDigit.getTimeResolution();
66 if (eclCalDigit.getEnergy() > m_ethresh && abs(digitT) < m_maxDigitT && dt99 < 1000.) {
67 tLike.push_back(digitT);
68 sigmaLike.push_back(dt99 * m_sigmaScale);
69 if (digitT < tmin) {
70 tmin = digitT;
71 itmin = tLike.size() - 1;
72 }
73 if (digitT > tmax) {
74 tmax = digitT;
75 itmax = tLike.size() - 1;
76 }
77 }
78 }
79 int nLike = tLike.size();
80
81 //-----------------------------------------------------------------
83 double T0 = -99999.;
84 double T0Unc = m_maxT0;
85 double quality = NAN;
86 int nT0Values = 0;
87 std::vector<float> localT0;
88 std::vector<float> localT0Unc;
89 std::vector<float> localquality;
90
91 if (nLike == 1) {
92 nT0Values = 1;
93 T0 = tLike[0];
94 T0Unc = sigmaLike[0];
95 quality = 0;
96 localT0.push_back(T0);
97 localT0Unc.push_back(T0Unc);
98 localquality.push_back(0.);
99
100 } else if (nLike >= 2) {
101
102 //-----------------------------------------------------------------
104 float minrange = 50.; /* performance is not sensitive to the particular value */
105 tmin = tLike[itmin] - 3 * sigmaLike[itmin]; /* 3 sigma to ensure minima is away from boundary. Specific value is not important. */
106 if (tmin < -m_maxT0) {tmin = -m_maxT0;}
107 tmax = tLike[itmax] + 3 * sigmaLike[itmax];
108 if (tmax > m_maxT0) {tmax = m_maxT0;}
109
110 if (tmin > m_maxT0 - minrange) {
111 tmin = m_maxT0 - minrange;
112 tmax = m_maxT0;
113 } else if (tmax < minrange - m_maxT0) {
114 tmin = -m_maxT0;
115 tmax = minrange - m_maxT0;
116 } else if (tmax - tmin < minrange) {
117 float drange = 0.5 * (minrange + tmin - tmax);
118 tmin = tmin - drange;
119 tmax = tmax + drange;
120 }
121
122 //-----------------------------------------------------------------
124 int nhypo = (0.5 + tmax - tmin) / m_T0bin;
125 float trange = nhypo * m_T0bin;
126 std::vector<float> t0hypo;
127 for (int it0 = 0; it0 < nhypo; it0++) {
128 t0hypo.push_back(tmin + (it0 + 0.5)*m_T0bin);
129 }
130
131 //-----------------------------------------------------------------
133 std::vector<float> sigFracVsT0(nhypo, 0.);
134 std::vector<float> chiVsT0(nhypo, 0.);
135 float minChi2 = 99999.;
136 int it0minChi2 = -1;
137 for (int it0 = 0; it0 < nhypo; it0++) {
138 float n3sig = 0.;
139 for (int iLike = 0; iLike < nLike; iLike++) {
140 if (abs(tLike[iLike] - t0hypo[it0]) < 3.*sigmaLike[iLike]) {n3sig++;}
141 }
142 float signalFrac = n3sig / nLike;
143 sigFracVsT0[it0] = signalFrac;
144
146 float chi2 = 0.;
147 for (int iLike = 0; iLike < nLike; iLike++) {
148 float arg = (tLike[iLike] - t0hypo[it0]) / sigmaLike[iLike];
149 float sigProb = sigFracVsT0[it0] * TMath::Exp(-0.5 * arg * arg) / sigmaLike[iLike] / sqrt(2.*TMath::Pi()) +
150 (1. - sigFracVsT0[it0]) / trange;
151 chi2 += -2.*TMath::Log(sigProb);
152 }
153 chiVsT0[it0] = chi2;
154
156 if (chi2 < minChi2) {
157 minChi2 = chi2;
158 it0minChi2 = it0;
159 }
160 }
161
162 //-----------------------------------------------------------------
163 /* Look for local minima in the chi square vs T0 hypothesis distribution. */
164 /* Local minima have negative slope on the lower side, positive slope on the upper. */
165 /* Calculate slope using the bin and its neighbour, if they have the same sigFrac; */
166 /* otherwise, use the closest adjacent pair that do have the same sigFrac. */
167
169 std::vector<float> LHslope(nhypo, 0.);
170 float slope = 0.;
171 for (int it0 = 1; it0 < nhypo; it0++) {
172 if (sigFracVsT0[it0 - 1] == sigFracVsT0[it0]) {
173 slope = chiVsT0[it0] - chiVsT0[it0 - 1];
174 }
175 LHslope[it0] = slope;
176 }
177
179 std::vector<float> HLslope(nhypo, 0.);
180 slope = 0.;
181 for (int it0 = nhypo - 2; it0 >= 0; it0--) {
182 if (sigFracVsT0[it0] == sigFracVsT0[it0 + 1]) {
183 slope = chiVsT0[it0 + 1] - chiVsT0[it0];
184 }
185 HLslope[it0] = slope;
186 }
187
188 //-----------------------------------------------------------------
190 /* and the one closest to 0 */
191 float minLocalChi2 = chiVsT0[0];
192 int it0min = -1;
193 float T0ClosestTo0 = 99999.;
194 int itClosest = -1;
195 std::vector<int> itlocal;
196 for (int it0 = 1; it0 < nhypo - 1; it0++) {
197 if ((LHslope[it0] < 0. && HLslope[it0] > 0.) || (LHslope[it0] == 0. && HLslope[it0] > 0. && LHslope[it0 - 1] < 0.
198 && HLslope[it0 - 1] == 0.)) {
199 localT0.push_back(t0hypo[it0]);
200 localquality.push_back(chiVsT0[it0]);
201 itlocal.push_back(it0);
202 if (chiVsT0[it0] < minLocalChi2) {
203 minLocalChi2 = chiVsT0[it0];
204 it0min = it0;
205 }
206 if (abs(t0hypo[it0]) < abs(T0ClosestTo0)) {
207 T0ClosestTo0 = t0hypo[it0];
208 itClosest = it0;
209 }
210 }
211 }
212 nT0Values = localT0.size();
213
214 //-----------------------------------------------------------------
216 for (int imin = 0; imin < nT0Values; imin++) {
217 float localUnc = m_maxT0;
218 if (itlocal[imin] > 0 && itlocal[imin] < nhypo) {
219 float chiTarget = chiVsT0[itlocal[imin]] + 4.;
220 int ih = itlocal[imin];
221 while (ih < nhypo - 1 and chiVsT0[ih] < chiTarget) {ih++;}
222 int il = itlocal[imin];
223 while (il > 0 and chiVsT0[il] < chiTarget) {il--;};
224 localUnc = (t0hypo[ih] - t0hypo[il]) / 4.;
225 }
226 localT0Unc.push_back(localUnc);
227 }
228
229 //-----------------------------------------------------------------
231 int itsel = it0min;
232 if (m_primaryT0 == 1) {itsel = it0minChi2;}
233 if (m_primaryT0 == 2) {itsel = itClosest;}
234
235 if (itsel >= 0) {
236 T0 = t0hypo[itsel];
237 quality = chiVsT0[itsel];
238
240 if (itsel > 0 && itsel < nhypo) {
241 float chiTarget = chiVsT0[itsel] + 4.;
242 int ih = itsel;
243 while (ih < nhypo - 1 and chiVsT0[ih] < chiTarget) {ih++;}
244 float ta = t0hypo[ih - 1];
245 float tb = t0hypo[ih];
246 float ca = chiVsT0[ih - 1];
247 float cb = chiVsT0[ih];
248 float th = tb;
249 if (cb != ca) {th = ta + (tb - ta) * (chiTarget - ca) / (cb - ca);}
250 int il = itsel;
251 while (il > 0 and chiVsT0[il] < chiTarget) {il--;}
252 ta = t0hypo[il];
253 tb = t0hypo[il + 1];
254 ca = chiVsT0[il];
255 cb = chiVsT0[il + 1];
256 float tl = ta;
257 if (cb != ca) {tl = ta + (tb - ta) * (chiTarget - ca) / (cb - ca);}
258 T0Unc = (th - tl) / 4.;
259 }
260 }
261 }
262
263 //-----------------------------------------------------------------
265 if (!m_eventT0) {m_eventT0.create();}
266
268 for (int it = 0; it < nT0Values; it++) {
269 m_eventT0->addTemporaryEventT0(EventT0::EventT0Component(localT0[it], localT0Unc[it], Const::ECL, "", localquality[it]));
270 }
271
273 if (T0 > -99998.0) {
274 m_eventT0->setEventT0(EventT0::EventT0Component(T0, T0Unc, Const::ECL, "", quality));
275 }
276}
double m_ethresh
minimum energy for ECLCalDigit to be used (0.06 GeV)
StoreObjPtr< EventT0 > m_eventT0
StoreObj EventT0
virtual void initialize() override
Register input and output data.
double m_sigmaScale
scale factor for time resolution (ie dt99) of ECLCalDigit (0.15)
virtual void event() override
Event.
double m_maxDigitT
maximum absolute value of ECLCalDigit time to be used (150 ns)
double m_maxT0
maximum allowed absolute value of T0, in ns (135 ns)
StoreArray< ECLCalDigit > m_eclCalDigitArray
eclCalDigits
double m_T0bin
step size between T0 hypotheses (1 ns)
int m_primaryT0
select which T0 is primary, ie first one reported.
ECLEventT0Module()
Constructor: Sets the description, the properties and the parameters of the module.
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
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
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