Project
Loading...
Searching...
No Matches
CookedTracker.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
15
16//-------------------------------------------------------------------------
17// A stand-alone ITS tracker
18// The pattern recongintion based on the "cooked covariance" approach
19//-------------------------------------------------------------------------
20#include <chrono>
21#include <future>
22#include <map>
23
24#include <TGeoGlobalMagField.h>
25#include <TMath.h>
26
27#include <fairlogger/Logger.h>
28
31#include "Field/MagneticField.h"
35#include "MathUtils/Utils.h"
38
39using namespace o2::its;
40using namespace o2::itsmft;
41using namespace o2::constants::math;
44
45/*** Tracking parameters ***/
46// seed "windows" in z and phi: makeSeeds
47Float_t CookedTracker::gzWin = 0.33;
48Float_t CookedTracker::gminPt = 0.05;
49Float_t CookedTracker::mMostProbablePt = o2::track::kMostProbablePt;
50// Maximal accepted impact parameters for the seeds
51Float_t CookedTracker::gmaxDCAxy = 3.;
52Float_t CookedTracker::gmaxDCAz = 3.;
53// Layers for the seeding
54Int_t CookedTracker::gSeedingLayer1 = 6;
55Int_t CookedTracker::gSeedingLayer2 = 4;
56Int_t CookedTracker::gSeedingLayer3 = 5;
57// Space point resolution
58Float_t CookedTracker::gSigma2 = 0.0005 * 0.0005;
59// Max accepted chi2
60Float_t CookedTracker::gmaxChi2PerCluster = 20.;
61Float_t CookedTracker::gmaxChi2PerTrack = 30.;
62// Tracking "road" from layer to layer
63Float_t CookedTracker::gRoadY = 0.2;
64Float_t CookedTracker::gRoadZ = 0.3;
65// Minimal number of attached clusters
66Int_t CookedTracker::gminNumberOfClusters = 4;
67
68const float kPI = 3.14159f;
69const float k2PI = 2 * kPI;
70
71//************************************************
72// TODO:
73//************************************************
74// Seeding:
75// Precalculate cylidnrical (r,phi) for the clusters;
76// use exact r's for the clusters
77
78CookedTracker::Layer CookedTracker::sLayers[CookedTracker::kNLayers];
79
80CookedTracker::CookedTracker(Int_t n) : mNumOfThreads(n), mBz(0.)
81{
82 //--------------------------------------------------------------------
83 // This default constructor needs to be provided
84 //--------------------------------------------------------------------
85 const Double_t klRadius[7] = {2.34, 3.15, 3.93, 19.61, 24.55, 34.39, 39.34}; // tdr6
86
87 for (Int_t i = 0; i < kNLayers; i++) {
88 sLayers[i].setR(klRadius[i]);
89 }
90}
91
92//__________________________________________________________________________
94{
95 //--------------------------------------------------------------------
96 // This function "cooks" a track label.
97 // A label<0 indicates that some of the clusters are wrongly assigned.
98 //--------------------------------------------------------------------
99 Int_t noc = t.getNumberOfClusters();
100 std::map<Label, int> labelOccurence;
101
102 for (int i = noc; i--;) {
103 const Cluster* c = getCluster(t.getClusterIndex(i));
104 Int_t idx = c - &mClusterCache[0] + mFirstInFrame; // Index of this cluster in event
105 auto labels = mClsLabels->getLabels(idx);
106
107 for (auto lab : labels) { // check all labels of the cluster
108 if (lab.isEmpty()) {
109 break; // all following labels will be empty also
110 }
111 // was this label already accounted for ?
112 labelOccurence[lab]++;
113 }
114 }
115 Label lab;
116 Int_t maxL = 0; // find most encountered label
117 for (auto [label, count] : labelOccurence) {
118 if (count <= maxL) {
119 continue;
120 }
121 maxL = count;
122 lab = label;
123 }
124
125 if ((1. - Float_t(maxL) / noc) > wrong) {
126 // change the track ID to negative
127 lab.setFakeFlag();
128 }
129 // t.SetFakeRatio((1.- Float_t(maxL)/noc));
130 return lab;
131}
132
133Double_t CookedTracker::getBz() const
134{
135 return mBz;
136}
137
138static Double_t f1(Double_t x1, Double_t y1, Double_t x2, Double_t y2, Double_t x3, Double_t y3)
139{
140 //-----------------------------------------------------------------
141 // Initial approximation of the track curvature
142 //-----------------------------------------------------------------
143 Double_t d = (x2 - x1) * (y3 - y2) - (x3 - x2) * (y2 - y1);
144 Double_t a =
145 0.5 * ((y3 - y2) * (y2 * y2 - y1 * y1 + x2 * x2 - x1 * x1) - (y2 - y1) * (y3 * y3 - y2 * y2 + x3 * x3 - x2 * x2));
146 Double_t b =
147 0.5 * ((x2 - x1) * (y3 * y3 - y2 * y2 + x3 * x3 - x2 * x2) - (x3 - x2) * (y2 * y2 - y1 * y1 + x2 * x2 - x1 * x1));
148
149 Double_t xr = TMath::Abs(d / (d * x1 - a)), yr = TMath::Abs(d / (d * y1 - b));
150
151 Double_t crv = xr * yr / sqrt(xr * xr + yr * yr);
152 if (d > 0) {
153 crv = -crv;
154 }
155
156 return crv;
157}
158
159static Double_t f2(Double_t x1, Double_t y1, Double_t x2, Double_t y2, Double_t x3, Double_t y3)
160{
161 //-----------------------------------------------------------------
162 // Initial approximation of the x-coordinate of the center of curvature
163 //-----------------------------------------------------------------
164
165 Double_t k1 = (y2 - y1) / (x2 - x1), k2 = (y3 - y2) / (x3 - x2);
166 Double_t x0 = 0.5 * (k1 * k2 * (y1 - y3) + k2 * (x1 + x2) - k1 * (x2 + x3)) / (k2 - k1);
167
168 return x0;
169}
170
171static Double_t f3(Double_t x1, Double_t y1, Double_t x2, Double_t y2, Double_t z1, Double_t z2)
172{
173 //-----------------------------------------------------------------
174 // Initial approximation of the tangent of the track dip angle
175 //-----------------------------------------------------------------
176 return (z1 - z2) / sqrt((x1 - x2) * (x1 - x2) + (y1 - y2) * (y1 - y2));
177}
178
179o2::its::TrackITSExt CookedTracker::cookSeed(const Point3Df& r1, Point3Df& r2, const Point3Df& tr3, float rad2, float rad3, float_t alpha, float_t bz)
180// const Float_t r1[4], const Float_t r2[4], const Float_t tr3[4], Double_t alpha, Double_t bz)
181{
182 //--------------------------------------------------------------------
183 // This is the main cooking function.
184 // Creates seed parameters out of provided clusters.
185 //--------------------------------------------------------------------
186
187 Double_t ca = TMath::Cos(alpha), sa = TMath::Sin(alpha);
188 Double_t x1 = r1.X() * ca + r1.Y() * sa, y1 = -r1.X() * sa + r1.Y() * ca, z1 = r1.Z();
189 Double_t x2 = r2.X() * ca + r2.Y() * sa, y2 = -r2.X() * sa + r2.Y() * ca, z2 = r2.Z();
190 Double_t x3 = tr3.X(), y3 = tr3.Y(), z3 = tr3.Z();
191
192 std::array<float, 5> par;
193 par[0] = y3;
194 par[1] = z3;
195 Double_t crv = f1(x1, y1, x2, y2, x3, y3); // curvature
196 Double_t x0 = f2(x1, y1, x2, y2, x3, y3); // x-coordinate of the center
197 Double_t tgl12 = f3(x1, y1, x2, y2, z1, z2);
198 Double_t tgl23 = f3(x2, y2, x3, y3, z2, z3);
199
200 Double_t sf = crv * (x3 - x0); // FIXME: sf must never be >= kAlmost1
201 par[2] = sf;
202
203 par[3] = 0.5 * (tgl12 + tgl23);
204 par[4] = (TMath::Abs(bz) < Almost0) ? 1 / CookedTracker::getMostProbablePt() : crv / (bz * B2C);
205
206 std::array<float, 15> cov;
207 /*
208 for (Int_t i=0; i<15; i++) cov[i]=0.;
209 cov[0] =gSigma2*10;
210 cov[2] =gSigma2*10;
211 cov[5] =0.007*0.007*10; //FIXME all these lines
212 cov[9] =0.007*0.007*10;
213 cov[14]=0.1*0.1*10;
214 */
215 const Double_t dlt = 0.0005;
216 Double_t fy = 1. / (rad2 - rad3);
217 Double_t tz = fy;
218 const auto big = sqrt(o2::constants::math::VeryBig);
219 auto cy = big;
220 if (TMath::Abs(bz) >= Almost0) {
221 auto tmp = dlt * bz * B2C;
222 cy = (f1(x1, y1, x2, y2 + dlt, x3, y3) - crv) / tmp;
223 cy *= 20; // FIXME: MS contribution to the cov[14]
224 }
225 Double_t s2 = gSigma2;
226
227 cov[0] = s2;
228 cov[1] = 0.;
229 cov[2] = s2;
230 cov[3] = s2 * fy;
231 cov[4] = 0.;
232 cov[5] = s2 * fy * fy;
233 cov[6] = 0.;
234 cov[7] = s2 * tz;
235 cov[8] = 0.;
236 cov[9] = s2 * tz * tz;
237 cov[10] = s2 * cy;
238 cov[11] = 0.;
239 cov[12] = s2 * fy * cy;
240 cov[13] = 0.;
241 cov[14] = s2 * cy * cy;
242
243 return o2::its::TrackITSExt(x3, alpha, par, cov);
244}
245
246void CookedTracker::makeSeeds(std::vector<TrackITSExt>& seeds, Int_t first, Int_t last)
247{
248 //--------------------------------------------------------------------
249 // This is the main pattern recongition function.
250 // Creates seeds out of two clusters and another point.
251 //--------------------------------------------------------------------
252 const float zv = getZ();
253
254 Layer& layer1 = sLayers[gSeedingLayer1];
255 Layer& layer2 = sLayers[gSeedingLayer2];
256 Layer& layer3 = sLayers[gSeedingLayer3];
257
258 auto bz = getBz();
259 const Double_t maxC = (TMath::Abs(bz) < Almost0) ? 0.03 : TMath::Abs(bz * B2C / gminPt);
260 const Double_t kpWinC = TMath::ASin(0.5 * maxC * layer1.getR()) - TMath::ASin(0.5 * maxC * layer2.getR());
261 const Double_t kpWinD = 2 * (TMath::ASin(gmaxDCAxy / layer2.getR()) - TMath::ASin(gmaxDCAxy / layer1.getR()));
262 const Double_t kpWin = std::max(kpWinC, kpWinD);
263
264 for (Int_t n1 = first; n1 < last; n1++) {
265 const Cluster* c1 = layer1.getCluster(n1);
266 //
267 //auto lab = (mClsLabels->getLabels(c1 - &mClusterCache[0] + mFirstInFrame))[0];
268 //
269 auto xyz1 = c1->getXYZGloRot(*mGeom);
270 auto z1 = xyz1.Z();
271 auto r1 = xyz1.rho();
272
273 auto phi1 = layer1.getClusterPhi(n1);
274 auto tgl = std::abs((z1 - zv) / r1);
275
276 auto zr2 = zv + layer2.getR() / r1 * (z1 - zv);
277 auto phir2 = phi1;
278 auto dz2 = gzWin * (1 + 2 * tgl);
279
280 std::vector<Int_t> selected2;
281 float dy2 = kpWin * layer2.getR();
282 layer2.selectClusters(selected2, phir2, dy2, zr2, dz2);
283 for (auto n2 : selected2) {
284 const Cluster* c2 = layer2.getCluster(n2);
285 //
286 //if ((mClsLabels->getLabels(c2 - &mClusterCache[0] + mFirstInFrame))[0] != lab) continue;
287 //
288 auto xyz2 = c2->getXYZGloRot(*mGeom);
289 auto z2 = xyz2.Z();
290 auto r2 = xyz2.rho();
291
292 auto dx = xyz2.X() - xyz1.X(), dy = xyz2.Y() - xyz1.Y();
293 auto d = (dx * xyz1.Y() - dy * xyz1.X()) / TMath::Sqrt(dx * dx + dy * dy);
294 auto phir3 = phi1 + TMath::ASin(d / r1) - TMath::ASin(d / layer3.getR());
295
296 auto zr3 = z1 + (layer3.getR() - r1) / (r2 - r1) * (z2 - z1);
297 auto dz3 = 0.5f * dz2;
298
299 std::vector<Int_t> selected3;
300 float dy3 = 0.1 * kpWin * layer3.getR(); //Fixme
301 layer3.selectClusters(selected3, phir3, dy3, zr3, dz3);
302 for (auto n3 : selected3) {
303 const Cluster* c3 = layer3.getCluster(n3);
304 //
305 //if ((mClsLabels->getLabels(c3 - &mClusterCache[0] + mFirstInFrame))[0] != lab) continue;
306 //
307 auto xyz3 = c3->getXYZGloRot(*mGeom);
308 auto z3 = xyz3.Z();
309 auto r3 = xyz3.rho();
310
311 zr3 = z1 + (r3 - r1) / (r2 - r1) * (z2 - z1);
312 if (std::abs(z3 - zr3) > 0.2 * dz3) {
313 continue;
314 }
315
316 const Point3Df& txyz2 = c2->getXYZ(); // tracking coordinates
317
318 TrackITSExt seed = cookSeed(xyz1, xyz3, txyz2, layer2.getR(), layer3.getR(), layer2.getAlphaRef(n2), getBz());
319
320 float ip[2];
321 seed.getImpactParams(getX(), getY(), getZ(), getBz(), ip);
322 if (TMath::Abs(ip[0]) > gmaxDCAxy) {
323 continue;
324 }
325 if (TMath::Abs(ip[1]) > gmaxDCAz) {
326 continue;
327 }
328 {
329 Double_t xx0 = 0.008; // Rough layer thickness
330 Double_t radl = 9.36; // Radiation length of Si [cm]
331 Double_t rho = 2.33; // Density of Si [g/cm^3]
332 if (!seed.correctForMaterial(xx0, xx0 * radl * rho, kTRUE)) {
333 continue;
334 }
335 }
336 seed.setClusterIndex(gSeedingLayer1, n1);
337 seed.setClusterIndex(gSeedingLayer3, n3);
338 seed.setClusterIndex(gSeedingLayer2, n2);
339 seeds.push_back(seed);
340 }
341 }
342 }
343 /*
344 for (Int_t n1 = 0; n1 < nClusters1; n1++) {
345 Cluster* c1 = layer1.getCluster(n1);
346 ((Cluster*)c1)->goToFrameTrk();
347 }
348 for (Int_t n2 = 0; n2 < nClusters2; n2++) {
349 Cluster* c2 = layer2.getCluster(n2);
350 ((Cluster*)c2)->goToFrameTrk();
351 }
352 for (Int_t n3 = 0; n3 < nClusters3; n3++) {
353 Cluster* c3 = layer3.getCluster(n3);
354 ((Cluster*)c3)->goToFrameTrk();
355 }
356 */
357}
358
359void CookedTracker::trackSeeds(std::vector<TrackITSExt>& seeds)
360{
361 //--------------------------------------------------------------------
362 // Loop over a subset of track seeds
363 //--------------------------------------------------------------------
364 std::vector<bool> used[gSeedingLayer2];
365 std::vector<Int_t> selec[gSeedingLayer2];
366 for (Int_t l = gSeedingLayer2 - 1; l >= 0; l--) {
367 Int_t n = sLayers[l].getNumberOfClusters();
368 used[l].resize(n, false);
369 selec[l].reserve(n / 100);
370 }
371
372 for (auto& track : seeds) {
373 auto x = track.getX();
374 auto y = track.getY();
375 Float_t phi = track.getAlpha() + TMath::ATan2(y, x);
376 o2::math_utils::bringTo02Pi(phi);
377 float ip[2];
378 track.getImpactParams(getX(), getY(), getZ(), getBz(), ip);
379
380 auto z = track.getZ();
381 auto crv = track.getCurvature(getBz());
382 auto tgl = track.getTgl();
383 Float_t r1 = sLayers[gSeedingLayer2].getR();
384
385 for (Int_t l = gSeedingLayer2 - 1; l >= 0; l--) {
386 Float_t r2 = sLayers[l].getR();
387 selec[l].clear();
388 if (TMath::Abs(ip[0]) > r2) {
389 break;
390 }
391 if (TMath::Abs(crv) < gRoadY / (0.5 * r1 * 0.5 * r1)) {
392 phi += TMath::ASin(ip[0] / r2) - TMath::ASin(ip[0] / r1);
393 z += tgl * (TMath::Sqrt(r2 * r2 - ip[0] * ip[0]) - TMath::Sqrt(r1 * r1 - ip[0] * ip[0]));
394 } else { // Fixme
395 phi += 0.5 * crv * (r2 - r1);
396 z += tgl / (0.5 * crv) * (TMath::ASin(0.5 * crv * r2) - TMath::ASin(0.5 * crv * r1));
397 }
398 sLayers[l].selectClusters(selec[l], phi, gRoadY, z, gRoadZ * (1 + 2 * std::abs(tgl)));
399 r1 = r2;
400 }
401
402 TrackITSExt best(track);
403
404 Int_t volID = -1;
405 for (auto& ci3 : selec[3]) {
406 TrackITSExt t3(track);
407 if (used[3][ci3]) {
408 continue;
409 }
410 if (!attachCluster(volID, 3, ci3, t3, track)) {
411 continue;
412 }
413 if (t3.isBetter(best, gmaxChi2PerTrack)) {
414 best = t3;
415 }
416
417 for (auto& ci2 : selec[2]) {
418 TrackITSExt t2(t3);
419 if (used[2][ci2]) {
420 continue;
421 }
422 if (!attachCluster(volID, 2, ci2, t2, t3)) {
423 continue;
424 }
425 if (t2.isBetter(best, gmaxChi2PerTrack)) {
426 best = t2;
427 }
428
429 for (auto& ci1 : selec[1]) {
430 TrackITSExt t1(t2);
431 if (used[1][ci1]) {
432 continue;
433 }
434 if (!attachCluster(volID, 1, ci1, t1, t2)) {
435 continue;
436 }
437 if (t1.isBetter(best, gmaxChi2PerTrack)) {
438 best = t1;
439 }
440
441 for (auto& ci0 : selec[0]) {
443 if (used[0][ci0]) {
444 continue;
445 }
446 if (!attachCluster(volID, 0, ci0, t0, t1)) {
447 continue;
448 }
449 if (t0.isBetter(best, gmaxChi2PerTrack)) {
450 best = t0;
451 }
452 volID = -1;
453 }
454 }
455 }
456 }
457
458 if (best.getNumberOfClusters() >= gminNumberOfClusters) {
459 Int_t noc = best.getNumberOfClusters();
460 for (Int_t ic = 3; ic < noc; ic++) {
461 Int_t index = best.getClusterIndex(ic);
462 Int_t l = (index & 0xf0000000) >> 28, c = (index & 0x0fffffff);
463 used[l][c] = true;
464 }
465 }
466 track = best;
467 }
468}
469
470std::vector<TrackITSExt> CookedTracker::trackInThread(Int_t first, Int_t last)
471{
472 //--------------------------------------------------------------------
473 // This function is passed to a tracking thread
474 //--------------------------------------------------------------------
475 std::vector<TrackITSExt> seeds;
476 seeds.reserve(last - first + 1);
477
478 for (const auto& vtx : *mVertices) {
479 mX = vtx.getX();
480 mY = vtx.getY();
481 mZ = vtx.getZ();
482 makeSeeds(seeds, first, last);
483 }
484
485 std::sort(seeds.begin(), seeds.end());
486
487 trackSeeds(seeds);
488
489 makeBackPropParam(seeds);
490
491 return seeds;
492}
493
494void CookedTracker::process(gsl::span<const o2::itsmft::CompClusterExt> const& clusters,
495 gsl::span<const unsigned char>::iterator& pattIt,
497 TrackInserter& inserter,
499{
500 //--------------------------------------------------------------------
501 // This is the main tracking function
502 //--------------------------------------------------------------------
503 if (mVertices == nullptr || mVertices->empty()) {
504 LOG(info) << "Not a single primary vertex provided. Skipping...\n";
505 return;
506 }
507 LOG(info) << "\n CookedTracker::process(), number of threads: " << mNumOfThreads;
508
509 auto start = std::chrono::system_clock::now();
510
511 mFirstInFrame = rof.getFirstEntry();
512
513 mClusterCache.reserve(rof.getNEntries());
514 auto clusters_in_frame = rof.getROFData(clusters);
515 for (const auto& comp : clusters_in_frame) {
516
517 auto pattID = comp.getPatternID();
519 float sigmaY2 = gSigma2, sigmaZ2 = gSigma2;
521 sigmaY2 = gSigma2; //dict.getErr2X(pattID);
522 sigmaZ2 = gSigma2; //dict.getErr2Z(pattID);
523 if (!dict->isGroup(pattID)) {
524 locXYZ = dict->getClusterCoordinates(comp);
525 } else {
526 o2::itsmft::ClusterPattern patt(pattIt);
527 locXYZ = dict->getClusterCoordinates(comp, patt);
528 }
529 } else {
530 o2::itsmft::ClusterPattern patt(pattIt);
531 locXYZ = dict->getClusterCoordinates(comp, patt, false);
532 }
533 auto sensorID = comp.getSensorID();
534 // Inverse transformation to the local --> tracking
535 auto trkXYZ = mGeom->getMatrixT2L(sensorID) ^ locXYZ;
536
537 Cluster c;
538 c.setSensorID(sensorID);
539 c.setPos(trkXYZ);
540 c.setErrors(sigmaY2, sigmaZ2, 0.f);
541 mClusterCache.push_back(c);
542 }
543
544 auto nClFrame = loadClusters();
545
546 auto end = std::chrono::system_clock::now();
547 std::chrono::duration<double> diff = end - start;
548 LOG(info) << "Loading clusters: " << nClFrame << " in a single frame : " << diff.count() << " s";
549
550 start = end;
551
552 auto [first, number] = processLoadedClusters(inserter);
553 rof.setFirstEntry(first);
554 rof.setNEntries(number);
555
557 end = std::chrono::system_clock::now();
558 diff = end - start;
559 LOG(info) << "Processing time/clusters for single frame : " << diff.count() << " / " << nClFrame << " s";
560
561 start = end;
562}
563
565{
566 //--------------------------------------------------------------------
567 // This is the main tracking function for single frame, it is assumed that only clusters
568 // which may contribute to this frame is loaded
569 //--------------------------------------------------------------------
570 Int_t numOfClusters = sLayers[gSeedingLayer1].getNumberOfClusters();
571 if (!numOfClusters) {
572 return {0, 0};
573 }
574
575 std::vector<std::future<std::vector<TrackITSExt>>> futures(mNumOfThreads);
576 std::vector<std::vector<TrackITSExt>> seedArray(mNumOfThreads);
577
578 for (Int_t t = 0, first = 0; t < mNumOfThreads; t++) {
579 Int_t rem = t < (numOfClusters % mNumOfThreads) ? 1 : 0;
580 Int_t last = first + (numOfClusters / mNumOfThreads) + rem;
581 futures[t] = std::async(std::launch::async, &CookedTracker::trackInThread, this, first, last);
582 first = last;
583 }
584 Int_t nSeeds = 0, ngood = 0;
585 int nAllTracks = 0, nTracks = 0;
586 for (Int_t t = 0; t < mNumOfThreads; t++) {
587 seedArray[t] = futures[t].get();
588 nSeeds += seedArray[t].size();
589 for (auto& track : seedArray[t]) {
590 if (track.getNumberOfClusters() < gminNumberOfClusters) {
591 continue;
592 }
593
595 track.propagateToDCA(vtx, getBz());
596
597 nAllTracks = inserter(track);
598 nTracks++;
599 if (mTrkLabels) {
600 Label label = cookLabel(track, 0.); // For comparison only
601 if (label.getTrackID() >= 0) {
602 ngood++;
603 }
604 // the inserter returns the size of the track vector, the index of the last
605 // inserted track is thus n - 1
606 mTrkLabels->emplace_back(label);
607 }
608 }
609 }
610
611 if (nSeeds) {
612 LOG(info) << "Found tracks: " << nTracks;
613 LOG(info) << "CookedTracker::processLoadedClusters(), good_tracks:/seeds: " << ngood << '/' << nSeeds << "-> "
614 << Float_t(ngood) / nSeeds << '\n';
615 }
616 // returning index of the first track and the number of add tracks
617 // inserted in this call
618 return {nAllTracks - nTracks, nTracks};
619}
620
621//____________________________________________________________
622void CookedTracker::makeBackPropParam(std::vector<TrackITSExt>& seeds) const
623{
624 // refit in backward direction
625 for (auto& track : seeds) {
626 if (track.getNumberOfClusters() < gminNumberOfClusters) {
627 continue;
628 }
629 makeBackPropParam(track);
630 }
631}
632
633//____________________________________________________________
635{
636 // refit in backward direction
637 auto backProp = track.getParamOut();
638 backProp = track;
639 backProp.resetCovariance();
640 auto propagator = o2::base::Propagator::Instance();
641
642 Int_t noc = track.getNumberOfClusters();
643 for (int ic = noc; ic--;) { // cluster indices are stored in inward direction
644 Int_t index = track.getClusterIndex(ic);
645 const Cluster* c = getCluster(index);
646 float alpha = mGeom->getSensorRefAlpha(c->getSensorID());
647 if (!backProp.rotate(alpha)) {
648 return false;
649 }
650 if (!propagator->PropagateToXBxByBz(backProp, c->getX())) {
651 return false;
652 }
653 if (!backProp.update(static_cast<const o2::BaseCluster<float>&>(*c))) {
654 return false;
655 }
656 }
657 track.getParamOut() = backProp;
658 return true;
659}
660
662{
663 //--------------------------------------------------------------------
664 // This function reads the ITSU clusters from the tree,
665 // sort them, distribute over the internal tracker arrays, etc
666 //--------------------------------------------------------------------
667
668 if (mClusterCache.empty()) {
669 return 0;
670 }
671
672 for (const auto& c : mClusterCache) {
673 Int_t layer = mGeom->getLayer(c.getSensorID());
674 sLayers[layer].insertCluster(&c);
675 }
676
677 std::vector<std::future<void>> fut;
678 for (Int_t l = 0; l < kNLayers; l += mNumOfThreads) {
679 for (Int_t t = 0; t < mNumOfThreads; t++) {
680 if (l + t >= kNLayers) {
681 break;
682 }
683 auto f = std::async(std::launch::async, &CookedTracker::Layer::init, sLayers + (l + t));
684 fut.push_back(std::move(f));
685 }
686 for (size_t t = 0; t < fut.size(); t++) {
687 fut[t].wait();
688 }
689 }
690
691 return mClusterCache.size();
692}
693
695{
696 //--------------------------------------------------------------------
697 // This function unloads ITSU clusters from the RAM
698 //--------------------------------------------------------------------
699 mClusterCache.clear();
700 for (Int_t i = 0; i < kNLayers; i++) {
701 sLayers[i].unloadClusters();
702 }
703}
704
706{
707 //--------------------------------------------------------------------
708 // Return pointer to a given cluster
709 //--------------------------------------------------------------------
710 Int_t l = (index & 0xf0000000) >> 28;
711 Int_t c = (index & 0x0fffffff) >> 00;
712 return sLayers[l].getCluster(c);
713}
714
716{
717 //--------------------------------------------------------------------
718 // This default constructor needs to be provided
719 //--------------------------------------------------------------------
720}
721
723{
724 //--------------------------------------------------------------------
725 // Sort clusters and cache their reference plane info in a thread
726 //--------------------------------------------------------------------
727 std::sort(std::begin(mClusters), std::end(mClusters),
728 [](const Cluster* c1, const Cluster* c2) { return (c1->getZ() < c2->getZ()); });
729
730 Double_t r = 0.;
731 Int_t m = mClusters.size();
732 for (Int_t i = 0; i < m; i++) {
733 const Cluster* c = mClusters[i];
734 // Float_t xRef, aRef;
735 // mGeom->getSensorXAlphaRefPlane(c->getSensorID(),xRef, aRef);
736 mAlphaRef.push_back(mGeom->getSensorRefAlpha(c->getSensorID()));
737 auto xyz = c->getXYZGloRot(*mGeom);
738 r += xyz.rho();
739 Float_t phi = xyz.Phi();
740 o2::math_utils::bringTo02Pi(phi);
741 mPhi.push_back(phi);
742 Int_t s = phi * (int)kNSectors / k2PI;
743 mSectors[s < kNSectors ? s : kNSectors - 1].emplace_back(i, c->getZ());
744 }
745
746 if (m) {
747 mR = r / m;
748 }
749}
750
752{
753 //--------------------------------------------------------------------
754 // Unload clusters from this layer
755 //--------------------------------------------------------------------
756 mClusters.clear();
757 mAlphaRef.clear();
758 mPhi.clear();
759 for (Int_t s = 0; s < kNSectors; s++) {
760 mSectors[s].clear();
761 }
762}
763
765{
766 //--------------------------------------------------------------------
767 // This function inserts a cluster to this layer
768 //--------------------------------------------------------------------
769 mClusters.push_back(c);
770 return kTRUE;
771}
772
774{
775 //--------------------------------------------------------------------
776 // This function returns the index of the first cluster with its fZ >= "z".
777 //--------------------------------------------------------------------
778 auto found = std::upper_bound(std::begin(mClusters), std::end(mClusters), z,
779 [](Float_t zc, const Cluster* c) { return (zc < c->getZ()); });
780 return found - std::begin(mClusters);
781}
782
783void CookedTracker::Layer::selectClusters(std::vector<Int_t>& selec, Float_t phi, Float_t dy, Float_t z, Float_t dz)
784{
785 //--------------------------------------------------------------------
786 // This function selects clusters within the "road"
787 //--------------------------------------------------------------------
788 Float_t zMin = z - dz;
789 Float_t zMax = z + dz;
790
791 o2::math_utils::bringTo02Pi(phi);
792
793 Float_t dphi = dy / mR;
794
795 int smin = (phi - dphi) / k2PI * (int)kNSectors;
796 int ds = (phi + dphi) / k2PI * (int)kNSectors - smin + 1;
797
798 smin = (smin + kNSectors) % kNSectors;
799
800 for (int is = 0; is < ds; is++) {
801 Int_t s = (smin + is) % kNSectors;
802
803 auto cmp = [](Float_t zc, std::pair<int, float> p) { return (zc < p.second); };
804 auto imin = std::upper_bound(std::begin(mSectors[s]), std::end(mSectors[s]), zMin, cmp);
805 auto imax = std::upper_bound(imin, std::end(mSectors[s]), zMax, cmp);
806 for (; imin != imax; imin++) {
807 auto [i, zz] = *imin;
808 auto cdphi = std::abs(mPhi[i] - phi);
809 if (cdphi > dphi) {
810 if (cdphi > kPI) {
811 cdphi = k2PI - cdphi;
812 }
813 if (cdphi > dphi) {
814 continue; // check in Phi
815 }
816 }
817 selec.push_back(i);
818 }
819 }
820}
821
822Bool_t CookedTracker::attachCluster(Int_t& volID, Int_t nl, Int_t ci, TrackITSExt& t, const TrackITSExt& o) const
823{
824 //--------------------------------------------------------------------
825 // Try to attach a clusters with index ci to running track hypothesis
826 //--------------------------------------------------------------------
827 Layer& layer = sLayers[nl];
828 const Cluster* c = layer.getCluster(ci);
829
830 Int_t vid = c->getSensorID();
831
832 if (vid != volID) {
833 volID = vid;
834 t = o;
835 Double_t alpha = layer.getAlphaRef(ci);
836 if (!t.propagate(alpha, c->getX(), getBz())) {
837 return kFALSE;
838 }
839 }
840
841 Double_t chi2 = t.getPredictedChi2(*c);
842 if (chi2 > gmaxChi2PerCluster) {
843 return kFALSE;
844 }
845
846 if (!t.update(*c, chi2)) {
847 return kFALSE;
848 }
849 t.setClusterIndex(nl, ci);
850
851 Double_t xx0 = (nl > 2) ? 0.008 : 0.003; // Rough layer thickness
852 Double_t x0 = 9.36; // Radiation length of Si [cm]
853 Double_t rho = 2.33; // Density of Si [g/cm^3]
854 t.correctForMaterial(xx0, xx0 * x0 * rho, kTRUE);
855 return kTRUE;
856}
857
859{
861 mGeom = geom;
862 for (Int_t i = 0; i < kNLayers; i++) {
863 sLayers[i].setGeometry(geom);
864 }
865}
General auxilliary methods.
Definition of the ITSMFT compact cluster.
const float k2PI
const float kPI
Definition of the "Cooked Matrix" ITS tracker.
Definition of the ClusterTopology class.
int32_t i
bool o
bool const GPUTPCGMMerger::trackCluster * c1
bool const GPUTPCGMMerger::trackCluster const clcomparestruct * c2
float float float & zMax
float float & zMin
Definition of a container to keep Monte Carlo truth external to simulation objects.
Definition of the MagF class.
useful math constants
uint32_t c
Definition RawData.h:2
void setSensorID(std::int16_t sid)
Definition BaseCluster.h:92
math_utils::Point3D< T > getXYZGloRot(const o2::detectors::DetMatrixCache &dm) const
Definition BaseCluster.h:78
std::int16_t getSensorID() const
Definition BaseCluster.h:81
GPUd() value_type estimateLTFast(o2 static GPUd() float estimateLTIncrement(const o2 PropagatorImpl * Instance(bool uninitialized=false)
Definition Propagator.h:143
gsl::span< TruthElement > getLabels(uint32_t dataindex)
Int_t findClusterIndex(Float_t z) const
void selectClusters(std::vector< Int_t > &s, Float_t phi, Float_t dy, Float_t z, Float_t dz)
Float_t getAlphaRef(Int_t i) const
void setGeometry(o2::its::GeometryTGeo *geom)
Float_t getClusterPhi(Int_t i) const
const Cluster * getCluster(Int_t i) const
Bool_t insertCluster(const Cluster *c)
void makeSeeds(std::vector< TrackITSExt > &seeds, Int_t first, Int_t last)
void process(gsl::span< const CompClusterExt > clusters, gsl::span< const unsigned char >::iterator &it, const o2::itsmft::TopologyDictionary *dict, U &tracks, V &clusIdx, o2::itsmft::ROFRecord &rof)
void setGeometry(o2::its::GeometryTGeo *geom)
Double_t getZ() const
std::tuple< int, int > processLoadedClusters(TrackInserter &inserter)
o2::its::TrackITSExt cookSeed(const Point3Df &r1, Point3Df &r2, const Point3Df &tr3, float rad2, float rad3, float_t alpha, float_t bz)
std::function< int(const TrackITSExt &t)> TrackInserter
void makeBackPropParam(std::vector< TrackITSExt > &seeds) const
void trackSeeds(std::vector< TrackITSExt > &seeds)
std::vector< TrackITSExt > trackInThread(Int_t first, Int_t last)
Double_t getY() const
static auto getMostProbablePt()
const Cluster * getCluster(Int_t index) const
static constexpr int kNLayers
o2::MCCompLabel cookLabel(TrackITSExt &t, Float_t wrong) const
Bool_t attachCluster(Int_t &volID, Int_t nl, Int_t ci, TrackITSExt &t, const TrackITSExt &o) const
CookedTracker(Int_t nThreads=1)
Double_t getX() const
const Mat3D & getMatrixT2L(int lay, int hba, int sta, int det) const
int getLayer(int index) const
Get chip layer, from 0.
float getSensorRefAlpha(int isn) const
void setClusterIndex(int l, int i)
Definition TrackITS.h:188
void getImpactParams(float x, float y, float z, float bz, float ip[2]) const
Definition TrackITS.cxx:40
bool propagate(float alpha, float x, float bz)
Definition TrackITS.cxx:72
bool isBetter(const TrackITS &best, float maxChi2) const
Definition TrackITS.cxx:94
bool update(const Cluster &c, float chi2)
Definition TrackITS.cxx:82
Cluster class for the ITSMFT.
Definition Cluster.h:34
static constexpr unsigned short InvalidPatternID
Definition CompCluster.h:46
void setNEntries(int n)
Definition ROFRecord.h:48
int getNEntries() const
Definition ROFRecord.h:62
gsl::span< const T > getROFData(const gsl::span< const T > tfdata) const
Definition ROFRecord.h:73
void setFirstEntry(int idx)
Definition ROFRecord.h:47
int getFirstEntry() const
Definition ROFRecord.h:63
math_utils::Point3D< T > getClusterCoordinates(const CompCluster &cl) const
bool isGroup(int n) const
Returns true if the element corresponds to a group of rare topologies.
GLdouble n
Definition glcorearb.h:1982
GLfloat GLfloat GLfloat alpha
Definition glcorearb.h:279
GLint GLenum GLint x
Definition glcorearb.h:403
const GLfloat * m
Definition glcorearb.h:4066
GLint GLsizei count
Definition glcorearb.h:399
GLuint GLfloat GLfloat GLfloat GLfloat y1
Definition glcorearb.h:5034
GLuint GLuint end
Definition glcorearb.h:469
GLuint GLfloat GLfloat GLfloat x1
Definition glcorearb.h:5034
GLuint index
Definition glcorearb.h:781
GLint first
Definition glcorearb.h:399
GLdouble f
Definition glcorearb.h:310
GLboolean GLboolean GLboolean b
Definition glcorearb.h:1233
GLuint GLsizei const GLchar * label
Definition glcorearb.h:2519
GLuint GLfloat x0
Definition glcorearb.h:5034
GLenum GLuint GLint GLint layer
Definition glcorearb.h:1310
GLboolean r
Definition glcorearb.h:1233
GLuint GLfloat GLfloat GLfloat GLfloat GLfloat GLfloat GLfloat t0
Definition glcorearb.h:5034
GLuint start
Definition glcorearb.h:469
GLboolean GLboolean GLboolean GLboolean a
Definition glcorearb.h:1233
GLdouble GLdouble GLdouble z
Definition glcorearb.h:843
GLuint GLfloat GLfloat GLfloat GLfloat GLfloat GLfloat GLfloat GLfloat GLfloat t1
Definition glcorearb.h:5034
constexpr float Almost0
constexpr float B2C
constexpr float VeryBig
value_T f3
Definition TrackUtils.h:93
constexpr float kMostProbablePt
o2::mch::DsIndex ds
LOG(info)<< "Compressed in "<< sw.CpuTime()<< " s"
std::vector< Cluster > clusters
char const *restrict const cmp
Definition x9.h:96