11 #include <ecl/modules/eclEventT0/ECLEventT0Module.h>
17 #include <framework/dataobjects/EventT0.h>
20 #include <ecl/dataobjects/ECLCalDigit.h>
37 setDescription(
"EventT0 calculated using ECLCalDigits");
38 addParam(
"ethresh", m_ethresh,
"Minimum energy (GeV) for an ECLCalDigit to be used", 0.06);
39 addParam(
"maxDigitT", m_maxDigitT,
"Maximum absolute time (ns) for an ECLCalDigit to be used", 150.);
40 addParam(
"sigmaScale", m_sigmaScale,
"Scale factor between dt99 and ECLCalDigit time resolution", 0.15);
41 addParam(
"maxT0", m_maxT0,
"Maximum absolute value (ns) for T0", 135.);
42 addParam(
"T0bin", m_T0bin,
"Step size between T0 hypotheses (ns)", 1.);
43 addParam(
"primaryT0", m_primaryT0,
"Select which T0 estimate is primary", 0);
44 setPropertyFlags(c_ParallelProcessingCertified);
50 m_eventT0.registerInDataStore();
51 m_eclCalDigitArray.isRequired();
59 std::vector<float> tLike;
60 std::vector<float> sigmaLike;
65 for (
auto& eclCalDigit : m_eclCalDigitArray) {
66 float digitT = eclCalDigit.getTime();
67 float dt99 = eclCalDigit.getTimeResolution();
68 if (eclCalDigit.getEnergy() > m_ethresh && abs(digitT) < m_maxDigitT && dt99 < 1000.) {
69 tLike.push_back(digitT);
70 sigmaLike.push_back(dt99 * m_sigmaScale);
73 itmin = tLike.size() - 1;
77 itmax = tLike.size() - 1;
81 int nLike = tLike.size();
86 double T0Unc = m_maxT0;
89 std::vector<float> localT0;
90 std::vector<float> localT0Unc;
91 std::vector<float> localquality;
98 localT0.push_back(T0);
99 localT0Unc.push_back(T0Unc);
100 localquality.push_back(0.);
102 }
else if (nLike >= 2) {
106 float minrange = 50.;
107 tmin = tLike[itmin] - 3 * sigmaLike[itmin];
108 if (tmin < -m_maxT0) {tmin = -m_maxT0;}
109 tmax = tLike[itmax] + 3 * sigmaLike[itmax];
110 if (tmax > m_maxT0) {tmax = m_maxT0;}
112 if (tmin > m_maxT0 - minrange) {
113 tmin = m_maxT0 - minrange;
115 }
else if (tmax < minrange - m_maxT0) {
117 tmax = minrange - m_maxT0;
118 }
else if (tmax - tmin < minrange) {
119 float drange = 0.5 * (minrange + tmin - tmax);
120 tmin = tmin - drange;
121 tmax = tmax + drange;
126 int nhypo = (0.5 + tmax - tmin) / m_T0bin;
127 float trange = nhypo * m_T0bin;
128 std::vector<float> t0hypo;
129 for (
int it0 = 0; it0 < nhypo; it0++) {
130 t0hypo.push_back(tmin + (it0 + 0.5)*m_T0bin);
135 std::vector<float> sigFracVsT0(nhypo, 0.);
136 std::vector<float> chiVsT0(nhypo, 0.);
137 float minChi2 = 99999.;
139 for (
int it0 = 0; it0 < nhypo; it0++) {
141 for (
int iLike = 0; iLike < nLike; iLike++) {
142 if (abs(tLike[iLike] - t0hypo[it0]) < 3.*sigmaLike[iLike]) {n3sig++;}
144 float signalFrac = n3sig / nLike;
145 sigFracVsT0[it0] = signalFrac;
149 for (
int iLike = 0; iLike < nLike; iLike++) {
150 float arg = (tLike[iLike] - t0hypo[it0]) / sigmaLike[iLike];
151 float sigProb = sigFracVsT0[it0] * TMath::Exp(-0.5 * arg * arg) / sigmaLike[iLike] / sqrt(2.*TMath::Pi()) +
152 (1. - sigFracVsT0[it0]) / trange;
153 chi2 += -2.*TMath::Log(sigProb);
158 if (chi2 < minChi2) {
171 std::vector<float> LHslope(nhypo, 0.);
173 for (
int it0 = 1; it0 < nhypo; it0++) {
174 if (sigFracVsT0[it0 - 1] == sigFracVsT0[it0]) {
175 slope = chiVsT0[it0] - chiVsT0[it0 - 1];
177 LHslope[it0] = slope;
181 std::vector<float> HLslope(nhypo, 0.);
183 for (
int it0 = nhypo - 2; it0 >= 0; it0--) {
184 if (sigFracVsT0[it0] == sigFracVsT0[it0 + 1]) {
185 slope = chiVsT0[it0 + 1] - chiVsT0[it0];
187 HLslope[it0] = slope;
193 float minLocalChi2 = chiVsT0[0];
195 float T0ClosestTo0 = 99999.;
197 std::vector<int> itlocal;
198 for (
int it0 = 1; it0 < nhypo - 1; it0++) {
199 if ((LHslope[it0] < 0. && HLslope[it0] > 0.) || (LHslope[it0] == 0. && HLslope[it0] > 0. && LHslope[it0 - 1] < 0.
200 && HLslope[it0 - 1] == 0.)) {
201 localT0.push_back(t0hypo[it0]);
202 localquality.push_back(chiVsT0[it0]);
203 itlocal.push_back(it0);
204 if (chiVsT0[it0] < minLocalChi2) {
205 minLocalChi2 = chiVsT0[it0];
208 if (abs(t0hypo[it0]) < abs(T0ClosestTo0)) {
209 T0ClosestTo0 = t0hypo[it0];
214 nT0Values = localT0.size();
218 for (
int imin = 0; imin < nT0Values; imin++) {
219 float localUnc = m_maxT0;
220 if (itlocal[imin] > 0 && itlocal[imin] < nhypo) {
221 float chiTarget = chiVsT0[itlocal[imin]] + 4.;
222 int ih = itlocal[imin];
223 while (ih < nhypo - 1 and chiVsT0[ih] < chiTarget) {ih++;}
224 int il = itlocal[imin];
225 while (il > 0 and chiVsT0[il] < chiTarget) {il--;};
226 localUnc = (t0hypo[ih] - t0hypo[il]) / 4.;
228 localT0Unc.push_back(localUnc);
234 if (m_primaryT0 == 1) {itsel = it0minChi2;}
235 if (m_primaryT0 == 2) {itsel = itClosest;}
239 quality = chiVsT0[itsel];
242 if (itsel > 0 && itsel < nhypo) {
243 float chiTarget = chiVsT0[itsel] + 4.;
245 while (ih < nhypo - 1 and chiVsT0[ih] < chiTarget) {ih++;}
246 float ta = t0hypo[ih - 1];
247 float tb = t0hypo[ih];
248 float ca = chiVsT0[ih - 1];
249 float cb = chiVsT0[ih];
251 if (cb != ca) {th = ta + (tb - ta) * (chiTarget - ca) / (cb - ca);}
253 while (il > 0 and chiVsT0[il] < chiTarget) {il--;}
257 cb = chiVsT0[il + 1];
259 if (cb != ca) {tl = ta + (tb - ta) * (chiTarget - ca) / (cb - ca);}
260 T0Unc = (th - tl) / 4.;
267 if (!m_eventT0) {m_eventT0.create();}
270 for (
int it = 0; it < nT0Values; it++) {
271 m_eventT0->addTemporaryEventT0(
EventT0::EventT0Component(localT0[it], localT0Unc[it], Const::ECL,
"", localquality[it]));