24#include <TGeoGlobalMagField.h>
27#include <fairlogger/Logger.h>
47Float_t CookedTracker::gzWin = 0.33;
48Float_t CookedTracker::gminPt = 0.05;
51Float_t CookedTracker::gmaxDCAxy = 3.;
52Float_t CookedTracker::gmaxDCAz = 3.;
54Int_t CookedTracker::gSeedingLayer1 = 6;
55Int_t CookedTracker::gSeedingLayer2 = 4;
56Int_t CookedTracker::gSeedingLayer3 = 5;
58Float_t CookedTracker::gSigma2 = 0.0005 * 0.0005;
60Float_t CookedTracker::gmaxChi2PerCluster = 20.;
61Float_t CookedTracker::gmaxChi2PerTrack = 30.;
63Float_t CookedTracker::gRoadY = 0.2;
64Float_t CookedTracker::gRoadZ = 0.3;
66Int_t CookedTracker::gminNumberOfClusters = 4;
68const float kPI = 3.14159f;
85 const Double_t klRadius[7] = {2.34, 3.15, 3.93, 19.61, 24.55, 34.39, 39.34};
88 sLayers[
i].
setR(klRadius[
i]);
99 Int_t noc = t.getNumberOfClusters();
100 std::map<Label, int> labelOccurence;
102 for (
int i = noc;
i--;) {
104 Int_t idx =
c - &mClusterCache[0] + mFirstInFrame;
105 auto labels = mClsLabels->
getLabels(idx);
107 for (
auto lab : labels) {
112 labelOccurence[lab]++;
125 if ((1. -
Float_t(maxL) / noc) > wrong) {
138static Double_t f1(Double_t
x1, Double_t
y1, Double_t x2, Double_t y2, Double_t x3, Double_t y3)
143 Double_t d = (x2 -
x1) * (y3 - y2) - (x3 - x2) * (y2 -
y1);
145 0.5 * ((y3 - y2) * (y2 * y2 -
y1 *
y1 + x2 * x2 -
x1 *
x1) - (y2 -
y1) * (y3 * y3 - y2 * y2 + x3 * x3 - x2 * x2));
147 0.5 * ((x2 -
x1) * (y3 * y3 - y2 * y2 + x3 * x3 - x2 * x2) - (x3 - x2) * (y2 * y2 -
y1 *
y1 + x2 * x2 -
x1 *
x1));
149 Double_t xr = TMath::Abs(d / (d *
x1 -
a)), yr = TMath::Abs(d / (d *
y1 -
b));
151 Double_t crv = xr * yr / sqrt(xr * xr + yr * yr);
159static Double_t f2(Double_t
x1, Double_t
y1, Double_t x2, Double_t y2, Double_t x3, Double_t y3)
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);
171static Double_t
f3(Double_t
x1, Double_t
y1, Double_t x2, Double_t y2, Double_t z1, Double_t z2)
176 return (z1 - z2) / sqrt((
x1 - x2) * (
x1 - x2) + (
y1 - y2) * (
y1 - y2));
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();
192 std::array<float, 5> par;
195 Double_t crv = f1(
x1,
y1, x2, y2, x3, y3);
196 Double_t
x0 = f2(
x1,
y1, x2, y2, x3, y3);
197 Double_t tgl12 = f3(
x1,
y1, x2, y2, z1, z2);
198 Double_t tgl23 = f3(x2, y2, x3, y3, z2, z3);
200 Double_t sf = crv * (x3 -
x0);
203 par[3] = 0.5 * (tgl12 + tgl23);
206 std::array<float, 15> cov;
215 const Double_t dlt = 0.0005;
216 Double_t fy = 1. / (rad2 - rad3);
220 if (TMath::Abs(bz) >=
Almost0) {
221 auto tmp = dlt * bz *
B2C;
222 cy = (f1(
x1,
y1, x2, y2 + dlt, x3, y3) - crv) / tmp;
225 Double_t s2 = gSigma2;
232 cov[5] = s2 * fy * fy;
236 cov[9] = s2 * tz * tz;
239 cov[12] = s2 * fy * cy;
241 cov[14] = s2 * cy * cy;
252 const float zv =
getZ();
254 Layer& layer1 = sLayers[gSeedingLayer1];
255 Layer& layer2 = sLayers[gSeedingLayer2];
256 Layer& layer3 = sLayers[gSeedingLayer3];
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);
264 for (Int_t n1 =
first; n1 < last; n1++) {
271 auto r1 = xyz1.rho();
274 auto tgl = std::abs((z1 - zv) / r1);
276 auto zr2 = zv + layer2.
getR() / r1 * (z1 - zv);
278 auto dz2 = gzWin * (1 + 2 * tgl);
280 std::vector<Int_t> selected2;
281 float dy2 = kpWin * layer2.
getR();
283 for (
auto n2 : selected2) {
290 auto r2 = xyz2.rho();
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());
296 auto zr3 = z1 + (layer3.
getR() - r1) / (r2 - r1) * (z2 - z1);
297 auto dz3 = 0.5f * dz2;
299 std::vector<Int_t> selected3;
300 float dy3 = 0.1 * kpWin * layer3.
getR();
302 for (
auto n3 : selected3) {
309 auto r3 = xyz3.rho();
311 zr3 = z1 + (r3 - r1) / (r2 - r1) * (z2 - z1);
312 if (std::abs(z3 - zr3) > 0.2 * dz3) {
322 if (TMath::Abs(ip[0]) > gmaxDCAxy) {
325 if (TMath::Abs(ip[1]) > gmaxDCAz) {
329 Double_t xx0 = 0.008;
330 Double_t radl = 9.36;
332 if (!seed.correctForMaterial(xx0, xx0 * radl * rho, kTRUE)) {
339 seeds.push_back(seed);
364 std::vector<bool> used[gSeedingLayer2];
365 std::vector<Int_t> selec[gSeedingLayer2];
366 for (Int_t l = gSeedingLayer2 - 1; l >= 0; l--) {
368 used[l].resize(
n,
false);
369 selec[l].reserve(
n / 100);
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);
380 auto z = track.getZ();
381 auto crv = track.getCurvature(
getBz());
382 auto tgl = track.getTgl();
385 for (Int_t l = gSeedingLayer2 - 1; l >= 0; l--) {
388 if (TMath::Abs(ip[0]) > r2) {
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]));
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));
398 sLayers[l].
selectClusters(selec[l], phi, gRoadY,
z, gRoadZ * (1 + 2 * std::abs(tgl)));
405 for (
auto& ci3 : selec[3]) {
413 if (t3.
isBetter(best, gmaxChi2PerTrack)) {
417 for (
auto& ci2 : selec[2]) {
425 if (t2.
isBetter(best, gmaxChi2PerTrack)) {
429 for (
auto& ci1 : selec[1]) {
437 if (
t1.isBetter(best, gmaxChi2PerTrack)) {
441 for (
auto& ci0 : selec[0]) {
449 if (
t0.isBetter(best, gmaxChi2PerTrack)) {
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);
475 std::vector<TrackITSExt> seeds;
476 seeds.reserve(last -
first + 1);
478 for (
const auto& vtx : *mVertices) {
485 std::sort(seeds.begin(), seeds.end());
495 gsl::span<const unsigned char>::iterator& pattIt,
497 TrackInserter& inserter,
503 if (mVertices ==
nullptr || mVertices->empty()) {
504 LOG(info) <<
"Not a single primary vertex provided. Skipping...\n";
507 LOG(info) <<
"\n CookedTracker::process(), number of threads: " << mNumOfThreads;
509 auto start = std::chrono::system_clock::now();
515 for (
const auto& comp : clusters_in_frame) {
517 auto pattID = comp.getPatternID();
519 float sigmaY2 = gSigma2, sigmaZ2 = gSigma2;
533 auto sensorID = comp.getSensorID();
540 c.setErrors(sigmaY2, sigmaZ2, 0.f);
541 mClusterCache.push_back(
c);
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";
557 end = std::chrono::system_clock::now();
559 LOG(info) <<
"Processing time/clusters for single frame : " << diff.count() <<
" / " << nClFrame <<
" s";
571 if (!numOfClusters) {
575 std::vector<std::future<std::vector<TrackITSExt>>> futures(mNumOfThreads);
576 std::vector<std::vector<TrackITSExt>> seedArray(mNumOfThreads);
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;
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) {
595 track.propagateToDCA(vtx,
getBz());
597 nAllTracks = inserter(track);
601 if (
label.getTrackID() >= 0) {
606 mTrkLabels->emplace_back(
label);
612 LOG(info) <<
"Found tracks: " << nTracks;
613 LOG(info) <<
"CookedTracker::processLoadedClusters(), good_tracks:/seeds: " << ngood <<
'/' << nSeeds <<
"-> "
614 <<
Float_t(ngood) / nSeeds <<
'\n';
618 return {nAllTracks - nTracks, nTracks};
625 for (
auto& track : seeds) {
626 if (track.getNumberOfClusters() < gminNumberOfClusters) {
637 auto backProp = track.getParamOut();
639 backProp.resetCovariance();
642 Int_t noc = track.getNumberOfClusters();
643 for (
int ic = noc; ic--;) {
644 Int_t
index = track.getClusterIndex(ic);
647 if (!backProp.rotate(
alpha)) {
650 if (!propagator->PropagateToXBxByBz(backProp,
c->getX())) {
657 track.getParamOut() = backProp;
668 if (mClusterCache.empty()) {
672 for (
const auto&
c : mClusterCache) {
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++) {
684 fut.push_back(std::move(
f));
686 for (
size_t t = 0; t < fut.size(); t++) {
691 return mClusterCache.size();
699 mClusterCache.clear();
710 Int_t l = (
index & 0xf0000000) >> 28;
711 Int_t
c = (
index & 0x0fffffff) >> 00;
727 std::sort(std::begin(mClusters), std::end(mClusters),
731 Int_t
m = mClusters.size();
732 for (Int_t
i = 0;
i <
m;
i++) {
740 o2::math_utils::bringTo02Pi(phi);
742 Int_t s = phi * (
int)kNSectors /
k2PI;
743 mSectors[s < kNSectors ? s : kNSectors - 1].emplace_back(
i,
c->getZ());
759 for (Int_t s = 0; s < kNSectors; s++) {
769 mClusters.push_back(
c);
778 auto found = std::upper_bound(std::begin(mClusters), std::end(mClusters),
z,
780 return found - std::begin(mClusters);
791 o2::math_utils::bringTo02Pi(phi);
795 int smin = (phi - dphi) /
k2PI * (
int)kNSectors;
796 int ds = (phi + dphi) /
k2PI * (
int)kNSectors - smin + 1;
798 smin = (smin + kNSectors) % kNSectors;
800 for (
int is = 0; is <
ds; is++) {
801 Int_t s = (smin + is) % kNSectors;
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);
811 cdphi =
k2PI - cdphi;
841 Double_t chi2 = t.getPredictedChi2(*
c);
842 if (chi2 > gmaxChi2PerCluster) {
851 Double_t xx0 = (nl > 2) ? 0.008 : 0.003;
854 t.correctForMaterial(xx0, xx0 *
x0 * rho, kTRUE);
General auxilliary methods.
Definition of the ITSMFT compact cluster.
Definition of the "Cooked Matrix" ITS tracker.
bool const GPUTPCGMMerger::trackCluster * c1
bool const GPUTPCGMMerger::trackCluster const clcomparestruct * c2
Definition of a container to keep Monte Carlo truth external to simulation objects.
Definition of the MagF class.
void setSensorID(std::int16_t sid)
math_utils::Point3D< T > getXYZGloRot(const o2::detectors::DetMatrixCache &dm) const
std::int16_t getSensorID() const
GPUd() value_type estimateLTFast(o2 static GPUd() float estimateLTIncrement(const o2 PropagatorImpl * Instance(bool uninitialized=false)
Int_t getNumberOfClusters() const
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)
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)
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)
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)
void getImpactParams(float x, float y, float z, float bz, float ip[2]) const
bool propagate(float alpha, float x, float bz)
bool isBetter(const TrackITS &best, float maxChi2) const
bool update(const Cluster &c, float chi2)
Cluster class for the ITSMFT.
static constexpr unsigned short InvalidPatternID
gsl::span< const T > getROFData(const gsl::span< const T > tfdata) const
void setFirstEntry(int idx)
int getFirstEntry() const
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.
GLfloat GLfloat GLfloat alpha
GLuint GLfloat GLfloat GLfloat GLfloat y1
GLuint GLfloat GLfloat GLfloat x1
GLboolean GLboolean GLboolean b
GLuint GLsizei const GLchar * label
GLenum GLuint GLint GLint layer
GLuint GLfloat GLfloat GLfloat GLfloat GLfloat GLfloat GLfloat t0
GLboolean GLboolean GLboolean GLboolean a
GLdouble GLdouble GLdouble z
GLuint GLfloat GLfloat GLfloat GLfloat GLfloat GLfloat GLfloat GLfloat GLfloat t1
constexpr float kMostProbablePt
LOG(info)<< "Compressed in "<< sw.CpuTime()<< " s"
std::vector< Cluster > clusters
char const *restrict const cmp