Belle II Software  release-08-01-10
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 
20 using namespace Belle2;
21 using namespace std;
22 
23 //-----------------------------------------------------------------
24 // Register the Module
25 //-----------------------------------------------------------------
26 REG_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
REG_MODULE(arichBtest)
Register the Module.
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
double sqrt(double a)
sqrt for double
Definition: beamHelpers.h:28
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