Project
Loading...
Searching...
No Matches
EventTimeMaker.cxx
Go to the documentation of this file.
1// Copyright 2019-2020 CERN and copyright holders of ALICE O2.
2// See https://alice-o2.web.cern.ch/copyright for details of the copyright holders.
3// All rights not expressly granted are reserved.
4//
5// This software is distributed under the terms of the GNU General Public
6// License v3 (GPL Version 3), copied verbatim in the file "COPYING".
7//
8// In applying this license CERN does not waive the privileges and immunities
9// granted to it by virtue of its status as an Intergovernmental Organization
10// or submit itself to any jurisdiction.
11
19
20#include "TRandom.h"
21#include "TMath.h"
23#include "TOFBase/Geo.h"
24
26
27namespace o2
28{
29
30namespace tof
31{
32
33int eventTimeContainer::maxNtracksInSet = -1;
34// usefull constants
35constexpr unsigned long combinatorial[20] = {1, 3, 9, 27, 81, 243, 729, 2187, 6561, 19683, 59049, 177147, 531441, 1594323, 4782969, 14348907, 43046721, 129140163, 387420489, 1162261467};
36//---------------
37
38void computeEvTime(const std::vector<eventTimeTrack>& tracks, const std::vector<int>& trkIndex, eventTimeContainer& evtime)
39{
40 static constexpr int maxNumberOfSets = 200;
41 static constexpr float weightLimit = 1E-6; // Limit in the weights
42
43 const int ntracks = tracks.size();
44 LOG(debug) << "For the collision time using " << ntracks << " tracks";
45
46 // find the int BC as the more frequent BC
47 std::map<int, int> bcCand;
48 for (const auto& trk : tracks) {
49 int bc = int(trk.tofSignal() * o2::tof::Geo::BC_TIME_INPS_INV);
50 bcCand[bc]++;
51 }
52
53 int maxcount = 0;
54 int maxbc = 0;
55 for (const auto& [bc, count] : bcCand) {
56 if (count > maxcount) {
57 maxbc = bc;
58 maxcount = count;
59 }
60 }
61
62 double t0fill = maxbc * o2::tof::Geo::BC_TIME_INPS;
63
64 // LOG(info) << "Int bc candidate from TOF : " << maxbc << " - time_in_ps = " << t0fill;
65
66 if (ntracks < 2) { // at least 2 tracks required
67 LOG(debug) << "Skipping event because at least 2 tracks are required";
68 return;
69 }
70
71 const int maxNtrackInSet = evtime.getMaxNtracksInSet();
72 int hypo[maxNtrackInSet];
73
74 int nmaxtracksinset = ntracks > 22 ? 6 : maxNtrackInSet; // max number of tracks in a set for event time computation
75 // int nmaxtracksinset = maxNtrackInSet;
76
77 LOG(debug) << "nmaxtracksinset " << nmaxtracksinset;
78 int ntracksinset = std::min(ntracks, nmaxtracksinset);
79 LOG(debug) << "ntracksinset " << ntracksinset;
80
81 int nset = ((ntracks - 1) / ntracksinset) + 1;
82 LOG(debug) << "nset " << nset;
83 int ntrackUsable = ntracks;
84 LOG(debug) << "ntrackUsable " << ntrackUsable;
85
86 if (nset > maxNumberOfSets) {
87 nset = maxNumberOfSets;
88 LOG(debug) << "resetting nset " << nset;
89 ntrackUsable = nmaxtracksinset * nset;
90 LOG(debug) << "resetting ntrackUsable " << ntrackUsable;
91 }
92
93 // list of tracks in set
94 std::vector<int> trackInSet[maxNumberOfSets];
95
96 for (int i = 0; i < ntrackUsable; i++) {
97 int iset = i % nset;
98
99 trackInSet[iset].push_back(i);
100 }
101
102 int status;
103 // compute event time for each set
104 for (int iset = 0; iset < nset; iset++) {
105 LOG(debug) << "iset " << iset << " has size " << trackInSet[iset].size();
106 unsigned long bestComb = 0;
107 while (!(status = getStartTimeInSet(tracks, trackInSet[iset], bestComb, t0fill))) {
108 ;
109 }
110 if (status == 1) {
111 int ntracks = trackInSet[iset].size();
112 // set the best in set
113 for (int itrk = 0; itrk < ntracks; itrk++) {
114 hypo[itrk] = bestComb % 3;
115 bestComb /= 3;
116
117 int index = trkIndex[trackInSet[iset][itrk]];
118 const eventTimeTrack& ctrack = tracks[trackInSet[iset][itrk]];
119 LOG(debug) << "Using hypothesis: " << hypo[itrk] << " tofSignal: " << ctrack.mSignal << " exp. time: " << ctrack.expTimes[hypo[itrk]] << " exp. sigma: " << ctrack.expSigma[hypo[itrk]];
120 LOG(debug) << "0= " << ctrack.expTimes[0] << " +- " << ctrack.expSigma[0] << " 1= " << ctrack.expTimes[1] << " +- " << ctrack.expSigma[1] << " 2= " << ctrack.expTimes[2] << " +- " << ctrack.expSigma[2];
121
122 evtime.mWeights[index] = 1. / (ctrack.expSigma[hypo[itrk]] * ctrack.expSigma[hypo[itrk]]);
123 evtime.mTrackTimes[index] = ctrack.mSignal - ctrack.expTimes[hypo[itrk]];
124 }
125 }
126 LOG(debug) << "iset " << iset << " did not have good status";
127 } // end loop in set
128
129 // do average among all tracks
130 int worse = 0;
131 int nRemoved = 0;
132 double finalTime = 0, allweights = 0;
133 int ntrackUsed = 0;
134 while (worse > -1) {
135 float errworse = EventTimeTOFParams::Instance().maxNsigma;
136 finalTime = 0, allweights = 0;
137 ntrackUsed = 0;
138 worse = -1;
139 for (int i = 0; i < evtime.mWeights.size(); i++) {
140 if (evtime.mWeights[i] < weightLimit) {
141 continue;
142 }
143 ntrackUsed++;
144 allweights += evtime.mWeights[i];
145 finalTime += evtime.mTrackTimes[i] * evtime.mWeights[i];
146 }
147
148 double averageBest = finalTime / allweights;
149 for (int i = 0; i < evtime.mWeights.size(); i++) {
150 if (evtime.mWeights[i] < weightLimit) {
151 continue;
152 }
153 float err = evtime.mTrackTimes[i] - averageBest;
154 err *= sqrt(evtime.mWeights[i]);
155 err = std::abs(err);
156 if (err > errworse) {
157 errworse = err;
158 worse = i;
159 }
160 }
161 if (worse > -1) { // remove track
162 // LOG(info) << "err " << errworse;
163 evtime.mWeights[worse] = 0;
164 nRemoved++;
165 }
166 }
167
168 LOG(debug) << "Removed " << nRemoved << " tracks from start time calculation";
169
170 if (allweights < weightLimit) {
171 LOG(debug) << "Skipping because allweights " << allweights << " are lower than " << weightLimit;
172 return;
173 }
174
175 evtime.mEventTime = finalTime / allweights;
176 evtime.mEventTimeError = sqrt(1. / allweights);
177 evtime.mEventTimeMultiplicity = ntrackUsed;
178}
179
180void computeEvTimeFast(const std::vector<eventTimeTrack>& tracks, const std::vector<int>& trkIndex, eventTimeContainer& evtime)
181{
182 static constexpr int maxNumberOfSets = 200;
183 static constexpr float weightLimit = 1E-6; // Limit in the weights
184
185 const int ntracks = tracks.size();
186 LOG(debug) << "For the collision time using " << ntracks;
187
188 if (ntracks < 2) { // at least 2 tracks required
189 LOG(debug) << "Skipping event because at least 2 tracks are required";
190 return;
191 }
192 const int maxNtrackInSet = evtime.getMaxNtracksInSet();
193
194 int hypo[maxNtrackInSet];
195
196 int nmaxtracksinset = ntracks > 22 ? 6 : maxNtrackInSet; // max number of tracks in a set for event time computation
197 int ntracksinset = std::min(ntracks, nmaxtracksinset);
198
199 int nset = ((ntracks - 1) / ntracksinset) + 1;
200 int ntrackUsable = ntracks;
201
202 if (nset > maxNumberOfSets) {
203 nset = maxNumberOfSets;
204 ntrackUsable = nmaxtracksinset * nset;
205 }
206
207 // list of tracks in set
208 std::vector<int> trackInSet[maxNumberOfSets];
209
210 for (int i = 0; i < ntrackUsable; i++) {
211 int iset = i % nset;
212
213 trackInSet[iset].push_back(i);
214 }
215
216 int status;
217 // compute event time for each set
218 for (int iset = 0; iset < nset; iset++) {
219 unsigned long bestComb = 0;
220 while (!(status = getStartTimeInSetFast(tracks, trackInSet[iset], bestComb))) {
221 ;
222 }
223 if (status == 1) {
224 int ntracks = trackInSet[iset].size();
225 // set the best in set
226 for (int itrk = 0; itrk < ntracks; itrk++) {
227 hypo[itrk] = bestComb % 3;
228 bestComb /= 3;
229
230 int index = trkIndex[trackInSet[iset][itrk]];
231 const eventTimeTrack& ctrack = tracks[trackInSet[iset][itrk]];
232 LOG(debug) << "Using hypothesis: " << hypo[itrk] << " tofSignal: " << ctrack.mSignal << " exp. time: " << ctrack.expTimes[hypo[itrk]] << " exp. sigma: " << ctrack.expSigma[hypo[itrk]];
233 LOG(debug) << "0= " << ctrack.expTimes[0] << " +- " << ctrack.expSigma[0] << " 1= " << ctrack.expTimes[1] << " +- " << ctrack.expSigma[1] << " 2= " << ctrack.expTimes[2] << " +- " << ctrack.expSigma[2];
234
235 evtime.mWeights[index] = 1. / (ctrack.expSigma[hypo[itrk]] * ctrack.expSigma[hypo[itrk]]);
236 evtime.mTrackTimes[index] = ctrack.mSignal - ctrack.expTimes[hypo[itrk]];
237 }
238 }
239 } // end loop in set
240
241 // do average among all tracks
242 double finalTime = 0, allweights = 0;
243 int ntrackUsed = 0;
244 for (int i = 0; i < evtime.mWeights.size(); i++) {
245 if (evtime.mWeights[i] < weightLimit) {
246 continue;
247 }
248 ntrackUsed++;
249 allweights += evtime.mWeights[i];
250 finalTime += evtime.mTrackTimes[i] * evtime.mWeights[i];
251 }
252
253 if (allweights < weightLimit) {
254 LOG(debug) << "Skipping because allweights " << allweights << " are lower than " << weightLimit;
255 return;
256 }
257
258 evtime.mEventTime = finalTime / allweights;
259 evtime.mEventTimeError = sqrt(1. / allweights);
260 evtime.mEventTimeMultiplicity = ntrackUsed;
261}
262
263int getStartTimeInSet(const std::vector<eventTimeTrack>& tracks, std::vector<int>& trackInSet, unsigned long& bestComb, double refT0)
264{
265 const auto& params = EventTimeTOFParams::Instance();
266 float errworse = params.maxNsigma;
267 const int maxNtrackInSet = eventTimeContainer::getMaxNtracksInSet();
268 float chi2, chi2best;
269 double averageBest = 0;
270 int hypo[maxNtrackInSet];
271 double starttime[maxNtrackInSet], weighttime[maxNtrackInSet];
272
273 chi2best = 10000;
274 int ntracks = trackInSet.size();
275 LOG(debug) << "Computing the start time in set with " << ntracks << " tracks";
276
277 if (ntracks < 3) {
278 LOG(debug) << "Not enough tracks!";
279 return 2; // no event time in the set
280 }
281
282 unsigned long ncomb = combinatorial[ntracks];
283 for (unsigned long comb = 0; comb < ncomb; comb++) {
284 unsigned long curr = comb;
285
286 int ngood = 0;
287 double average = 0;
288 double sumweights = 0;
289 // get track info in the set for current combination
290 for (int itrk = 0; itrk < ntracks; itrk++) {
291 hypo[itrk] = curr % 3;
292 curr /= 3;
293 const eventTimeTrack& ctrack = tracks[trackInSet[itrk]];
294 starttime[itrk] = ctrack.mSignal - ctrack.expTimes[hypo[itrk]];
295
296 if (std::abs(starttime[itrk] - refT0) < 2000) { // otherwise time inconsistent with the int BC
297 weighttime[itrk] = 1. / (ctrack.expSigma[hypo[itrk]] * ctrack.expSigma[hypo[itrk]]);
298 average += starttime[itrk] * weighttime[itrk];
299 sumweights += weighttime[itrk];
300 ngood++;
301 }
302 }
303
304 average /= sumweights;
305
306 // compute chi2
307 chi2 = 0;
308 double deltat;
309 for (int itrk = 0; itrk < ntracks; itrk++) {
310 deltat = starttime[itrk] - average;
311 chi2 += deltat * deltat * weighttime[itrk];
312 }
313 chi2 /= (ngood - 1);
314
315 if (chi2 < chi2best) {
316 bestComb = comb;
317 chi2best = chi2;
318 averageBest = average;
319 }
320 } // end loop in combinations
321
322 int worse = -1;
323 // check the best combination
324 unsigned long curr = bestComb;
325 for (int itrk = 0; itrk < ntracks; itrk++) {
326 hypo[itrk] = curr % 3;
327 curr /= 3;
328
329 const eventTimeTrack& ctrack = tracks[trackInSet[itrk]];
330 float err = ctrack.mSignal - ctrack.expTimes[hypo[itrk]] - averageBest;
331 err /= ctrack.expSigma[hypo[itrk]];
332 err = std::abs(err);
333 if (err > errworse) {
334 errworse = err;
335 worse = itrk;
336 }
337 }
338
339 if (worse > -1) {
340 const eventTimeTrack& ctrack = tracks[trackInSet[worse]];
341 // remove the track and try again
342 trackInSet.erase(trackInSet.begin() + worse);
343 return 0;
344 }
345
346 return 1; // good event time in the set
347}
348
349int getStartTimeInSetFast(const std::vector<eventTimeTrack>& tracks, std::vector<int>& trackInSet, unsigned long& bestComb)
350{
351 const int maxNtrackInSet = eventTimeContainer::getMaxNtracksInSet();
352 float chi2, chi2best;
353 double averageBest = 0;
354 int hypo[maxNtrackInSet];
355 double starttime[maxNtrackInSet], weighttime[maxNtrackInSet];
356
357 chi2best = 10000;
358 int ntracks = trackInSet.size();
359
360 if (ntracks < 3) {
361 return 2; // no event time in the set
362 }
363
364 unsigned long ncomb = combinatorial[ntracks];
365
366 unsigned long comb = 0; // use only pions
367
368 int ngood = 0;
369 double average = 0;
370 double sumweights = 0;
371
372 // get track info in the set for current combination
373 for (int itrk = 0; itrk < ntracks; itrk++) {
374 hypo[itrk] = 0;
375 const eventTimeTrack& ctrack = tracks[trackInSet[itrk]];
376 starttime[itrk] = ctrack.mSignal - ctrack.expTimes[hypo[itrk]];
377 weighttime[itrk] = 1. / (ctrack.expSigma[hypo[itrk]] * ctrack.expSigma[hypo[itrk]]);
378
379 average += starttime[itrk] * weighttime[itrk];
380 sumweights += weighttime[itrk];
381 ngood++;
382 }
383
384 average /= sumweights;
385
386 // compute chi2
387 chi2 = 0;
388 double deltat;
389 for (int itrk = 0; itrk < ntracks; itrk++) {
390 deltat = starttime[itrk] - average;
391 chi2 += deltat * deltat * weighttime[itrk];
392 }
393 chi2 /= (ngood - 1);
394
395 bestComb = comb;
396 chi2best = chi2;
397 averageBest = average;
398
399 int worse = -1;
400 float errworse = 4;
401
402 // check the best combination
403 for (int itrk = 0; itrk < ntracks; itrk++) {
404 const eventTimeTrack& ctrack = tracks[trackInSet[itrk]];
405 float err = ctrack.mSignal - ctrack.expTimes[hypo[itrk]] - averageBest;
406 err /= ctrack.expSigma[hypo[itrk]];
407 err = std::abs(err);
408 if (err > errworse) {
409 errworse = err;
410 worse = itrk;
411 }
412 }
413
414 if (worse > -1) {
415 const eventTimeTrack& ctrack = tracks[trackInSet[worse]];
416 // remove the track and try again
417 trackInSet.erase(trackInSet.begin() + worse);
418 return 0;
419 }
420
421 return 1; // good event time in the set
422}
423
424void generateEvTimeTracks(std::vector<eventTimeTrackTest>& tracks, int ntracks, float evTime)
425{
426 eventTimeTrackTest track;
427 constexpr float masses[3] = {0.13957000, 0.49367700, 0.93827200};
428 constexpr float kCSPEED = TMath::C() * 1.0e2f * 1.0e-12f;
429 float energy = 0.f;
430 float betas[3] = {0.f};
431
432 float pMismatch = ntracks * 0.00005;
433
434 for (int i = 0; i < ntracks; i++) {
435 track.mTOFChi2 = 1.f;
436 track.mP = gRandom->Exp(1);
437 track.mPt = track.mP;
438 track.mLength = 400.;
439 track.mHypo = gRandom->Exp(1);
440 if (track.mHypo > 2) {
441 track.mHypo = 2;
442 }
443 for (int j = 0; j < 3; j++) {
444 energy = sqrt(masses[j] * masses[j] + track.mP * track.mP);
445 betas[j] = track.mP / energy;
446 track.expTimes[j] = track.mLength / (betas[j] * kCSPEED);
447 track.expSigma[j] = 100.f;
448 if (j == track.mHypo) {
449 track.mSignal = track.expTimes[j] + gRandom->Gaus(0.f, track.expSigma[j]);
450
451 if (gRandom->Rndm() < pMismatch) { // assign time from a different particle
452 float p = gRandom->Exp(1);
453 float l = 400;
454 int hypo = gRandom->Exp(1);
455 if (hypo > 2) {
456 hypo = 2;
457 }
458 energy = sqrt(masses[hypo] * masses[hypo] + p * p);
459 float beta = p / energy;
460 track.mSignal = l / (beta * kCSPEED) + gRandom->Gaus(0.f, track.expSigma[j]);
461 }
462 }
463 }
464 tracks.push_back(track);
465 }
466}
467
468} // namespace tof
469} // namespace o2
#define O2ParamImpl(classname)
Definition of the TOF event time maker.
uint64_t bc
Definition RawEventData.h:5
int32_t i
uint32_t j
Definition RawData.h:0
std::ostringstream debug
static constexpr Double_t BC_TIME_INPS
Definition Geo.h:103
static constexpr Double_t BC_TIME_INPS_INV
Definition Geo.h:104
GLint GLsizei count
Definition glcorearb.h:399
GLuint index
Definition glcorearb.h:781
GLenum const GLfloat * params
Definition glcorearb.h:272
int getStartTimeInSet(const std::vector< eventTimeTrack > &tracks, std::vector< int > &trackInSet, unsigned long &bestComb, double refT0=0)
void computeEvTimeFast(const std::vector< eventTimeTrack > &tracks, const std::vector< int > &trkIndex, eventTimeContainer &evtime)
void computeEvTime(const std::vector< eventTimeTrack > &tracks, const std::vector< int > &trkIndex, eventTimeContainer &evtime)
int getStartTimeInSetFast(const std::vector< eventTimeTrack > &tracks, std::vector< int > &trackInSet, unsigned long &bestComb)
void generateEvTimeTracks(std::vector< eventTimeTrackTest > &tracks, int ntracks, float evTime=0.0)
constexpr unsigned long combinatorial[20]
a couple of static helper functions to create timestamp values for CCDB queries or override obsolete ...
std::vector< double > mTrackTimes
weights (1/sigma^2) associated to a track in event time computation, 0 if track not used
double mEventTimeError
Value of the event time.
unsigned short mEventTimeMultiplicity
Uncertainty on the computed event time.
std::vector< float > mWeights
sum of weights of all track contributors
LOG(info)<< "Compressed in "<< sw.CpuTime()<< " s"