9 #include <ecl/modules/eclEventT0/ECLEventT0Module.h>
15 #include <framework/dataobjects/EventT0.h>
18 #include <ecl/dataobjects/ECLCalDigit.h>
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);
42 setPropertyFlags(c_ParallelProcessingCertified);
48 m_eventT0.registerInDataStore();
49 m_eclCalDigitArray.isRequired();
57 std::vector<float> tLike;
58 std::vector<float> sigmaLike;
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);
71 itmin = tLike.size() - 1;
75 itmax = tLike.size() - 1;
79 int nLike = tLike.size();
84 double T0Unc = m_maxT0;
87 std::vector<float> localT0;
88 std::vector<float> localT0Unc;
89 std::vector<float> localquality;
96 localT0.push_back(T0);
97 localT0Unc.push_back(T0Unc);
98 localquality.push_back(0.);
100 }
else if (nLike >= 2) {
104 float minrange = 50.;
105 tmin = tLike[itmin] - 3 * sigmaLike[itmin];
106 if (tmin < -m_maxT0) {tmin = -m_maxT0;}
107 tmax = tLike[itmax] + 3 * sigmaLike[itmax];
108 if (tmax > m_maxT0) {tmax = m_maxT0;}
110 if (tmin > m_maxT0 - minrange) {
111 tmin = m_maxT0 - minrange;
113 }
else if (tmax < minrange - 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;
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);
133 std::vector<float> sigFracVsT0(nhypo, 0.);
134 std::vector<float> chiVsT0(nhypo, 0.);
135 float minChi2 = 99999.;
137 for (
int it0 = 0; it0 < nhypo; it0++) {
139 for (
int iLike = 0; iLike < nLike; iLike++) {
140 if (abs(tLike[iLike] - t0hypo[it0]) < 3.*sigmaLike[iLike]) {n3sig++;}
142 float signalFrac = n3sig / nLike;
143 sigFracVsT0[it0] = signalFrac;
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);
156 if (chi2 < minChi2) {
169 std::vector<float> LHslope(nhypo, 0.);
171 for (
int it0 = 1; it0 < nhypo; it0++) {
172 if (sigFracVsT0[it0 - 1] == sigFracVsT0[it0]) {
173 slope = chiVsT0[it0] - chiVsT0[it0 - 1];
175 LHslope[it0] = slope;
179 std::vector<float> HLslope(nhypo, 0.);
181 for (
int it0 = nhypo - 2; it0 >= 0; it0--) {
182 if (sigFracVsT0[it0] == sigFracVsT0[it0 + 1]) {
183 slope = chiVsT0[it0 + 1] - chiVsT0[it0];
185 HLslope[it0] = slope;
191 float minLocalChi2 = chiVsT0[0];
193 float T0ClosestTo0 = 99999.;
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];
206 if (abs(t0hypo[it0]) < abs(T0ClosestTo0)) {
207 T0ClosestTo0 = t0hypo[it0];
212 nT0Values = localT0.size();
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.;
226 localT0Unc.push_back(localUnc);
232 if (m_primaryT0 == 1) {itsel = it0minChi2;}
233 if (m_primaryT0 == 2) {itsel = itClosest;}
237 quality = chiVsT0[itsel];
240 if (itsel > 0 && itsel < nhypo) {
241 float chiTarget = chiVsT0[itsel] + 4.;
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];
249 if (cb != ca) {th = ta + (tb - ta) * (chiTarget - ca) / (cb - ca);}
251 while (il > 0 and chiVsT0[il] < chiTarget) {il--;}
255 cb = chiVsT0[il + 1];
257 if (cb != ca) {tl = ta + (tb - ta) * (chiTarget - ca) / (cb - ca);}
258 T0Unc = (th - tl) / 4.;
265 if (!m_eventT0) {m_eventT0.create();}
268 for (
int it = 0; it < nT0Values; it++) {
269 m_eventT0->addTemporaryEventT0(
EventT0::EventT0Component(localT0[it], localT0Unc[it], Const::ECL,
"", localquality[it]));
virtual void initialize() override
Register input and output data.
virtual void event() override
Event.
#define REG_MODULE(moduleName)
Register the given module (without 'Module' suffix) with the framework.
Abstract base class for different kinds of events.
Structure for storing the extracted event t0s together with its detector and its uncertainty.