47 updateTimeDependentParams();
50 mCosmicTracks.clear();
51 mCosmicTracksLbl.clear();
54 int ntr = mSeeds.size();
58 for (
int i = 0;
i < ntr;
i++) {
59 auto& trc = mSeeds[
i];
66 std::vector<int> sortID(ntr);
67 std::iota(sortID.begin(), sortID.end(), 0);
68 std::sort(sortID.begin(), sortID.end(), [
this](
int a,
int b) { return mSeeds[a].tBracket.getMin() < mSeeds[b].tBracket.getMin(); });
70 for (
int i = 0;
i < ntr;
i++) {
71 for (
int j =
i + 1;
j < ntr;
j++) {
72 if (checkPair(sortID[
i], sortID[
j]) ==
RejTime) {
87 LOG(info) <<
"Refitting " << mWinners.size() <<
" winner matches";
89 auto tpcTBinMUSInv = 1. / mTPCTBinMUS;
90 const auto& tpcClusRefs =
data.getTPCTracksClusterRefs();
91 const auto& tpcClusShMap =
data.clusterShMapTPC;
92 const auto& tpcClusOccMap =
data.occupancyMapTPC;
93 std::unique_ptr<o2::gpu::GPUO2InterfaceRefit> tpcRefitter;
94 if (
data.inputsTPCclusters) {
95 tpcRefitter = std::make_unique<o2::gpu::GPUO2InterfaceRefit>(&
data.inputsTPCclusters->clusterIndex,
96 mTPCCorrMapsHelper, mBz,
97 tpcClusRefs.data(), 0, tpcClusShMap.data(),
99 tpcRefitter->setTrackReferenceX(900);
102 const auto& itsClusters = prepareITSClusters(
data);
104 std::vector<int> itsTracksROF;
106 const auto& itsTracksROFRec =
data.getITSTracksROFRecords();
107 itsTracksROF.resize(
data.getITSTracks().size());
108 for (
unsigned irf = 0, cnt = 0; irf < itsTracksROFRec.size(); irf++) {
109 int ntr = itsTracksROFRec[irf].getNEntries();
110 for (
int itr = 0; itr < ntr; itr++) {
111 itsTracksROF[cnt++] = irf;
116 const auto& itsTrOrig =
data.getITSTrack(gidx);
117 int nclRefit = 0, ncl = itsTrOrig.getNumberOfClusters(), rof = itsTracksROF[gidx.getIndex()];
118 const auto& itsTrackClusRefs =
data.getITSTracksClusterRefs();
119 int clEntry = itsTrOrig.getFirstClusterEntry();
122 int from = ncl - 1, to = -1,
step = -1;
128 for (
int icl = from; icl != to; icl +=
step) {
129 const auto& clus = itsClusters[itsTrackClusRefs[clEntry + icl]];
130 float alpha = geomITS->getSensorRefAlpha(clus.getSensorID()),
x = clus.getX();
131 if (!trFit.rotate(
alpha) || !propagator->propagateToX(trFit,
x, propagator->getNominalBz(),
this->mMatchParams->maxSnp,
this->mMatchParams->maxStep,
this->mMatchParams->matCorr)) {
134 chi2 += trFit.getPredictedChi2(clus);
135 if (!trFit.update(clus)) {
140 return nclRefit == ncl ? ncl : -1;
143 for (
auto winRID : mWinners) {
144 const auto&
rec = mRecords[winRID];
145 int poolEntryID[2] = {
rec.id0,
rec.id1};
147 auto tOverlap = mSeeds[
rec.id0].tBracket.getOverlap(mSeeds[
rec.id1].tBracket);
148 float t0 = tOverlap.mean(), dt = tOverlap.delta() * 0.5;
149 auto pnt0 = outerLegs[0].getXYZGlo(), pnt1 = outerLegs[1].getXYZGlo();
150 int btm = 0,
top = 1;
152 if (pnt0.Y() > pnt1.Y()) {
156 LOG(
debug) <<
"Winner " <<
count++ <<
" Record " << winRID <<
" Partners:"
157 <<
" B: " << mSeeds[poolEntryID[btm]].origID <<
"/" << mSeeds[poolEntryID[btm]].origID.getSourceName()
158 <<
" U: " << mSeeds[poolEntryID[
top]].origID <<
"/" << mSeeds[poolEntryID[
top]].origID.getSourceName()
159 <<
" | T:" << tOverlap.asString();
167 if (mSeeds[poolEntryID[btm]].origID.getSource() ==
GTrackID::TPC) {
168 const auto& tpcTrOrig =
data.getTPCTrack(mSeeds[poolEntryID[btm]].origID);
169 trCosm = outerLegs[btm];
170 trCosm.resetCovariance();
175 int retVal = tpcRefitter->RefitTrackAsTrackParCov(trCosm, tpcTrOrig.getClusterRef(),
t0 * tpcTBinMUSInv, &chi2,
false,
false);
177 LOG(
debug) <<
"Inward refit of btm TPC track failed.";
181 LOG(
debug) <<
"chi2 after btm TPC refit with " <<
retVal <<
" clusters : " << chi2 <<
" orig.chi2 was " << tpcTrOrig.getChi2();
185 trCosm.setQ2Pt(-trCosm.getQ2Pt());
187 auto gidxListBtm =
data.getSingleDetectorRefs(mSeeds[poolEntryID[btm]].origID);
190 nclTot += tpcTrOrig.getNClusters();
191 chi2 += tpcTrOrig.getChi2();
195 nclTot += itsTrOrig.getNClusters();
196 chi2 += itsTrOrig.getChi2();
200 if (!trCosm.rotate(mSeeds[poolEntryID[
top]].getAlpha()) ||
202 LOG(
debug) <<
"Rotation/propagation of btm-track to top-track frame failed.";
206 auto trCosmBtm = trCosm;
210 auto gidxListTop =
data.getSingleDetectorRefs(mSeeds[poolEntryID[
top]].origID);
214 auto nclfit = refitITSTrack(trCosm, gidxListTop[
GTrackID::ITS], chi2,
false);
218 LOG(
debug) <<
"chi2 after top ITS refit with " << nclfit <<
" clusters : " << chi2 <<
" orig.chi2 was " <<
data.getITSTrack(gidxListTop[
GTrackID::ITS]).getChi2();
228 LOG(
debug) <<
"Propagation to inner TPC boundary X=" << xtogo <<
" failed";
233 int retVal = tpcRefitter->RefitTrackAsTrackParCov(trCosm, tpcTrOrig.getClusterRef(),
t0 * tpcTBinMUSInv, &chi2,
true,
false);
235 LOG(
debug) <<
"Outward refit of top TPC track failed.";
238 LOG(
debug) <<
"chi2 after top TPC refit with " <<
retVal <<
" clusters : " << chi2 <<
" orig.chi2 was " << tpcTrOrig.getChi2();
244 auto trCosmTop = outerLegs[
top];
247 int retVal = tpcRefitter->RefitTrackAsTrackParCov(trCosmTop, tpcTrOrig.getClusterRef(),
t0 * tpcTBinMUSInv, &chi2Dummy,
false,
true);
249 LOG(
debug) <<
"Outward refit of top TPC track failed.";
255 auto nclfit = refitITSTrack(trCosmTop, gidxListTop[
GTrackID::ITS], chi2Dummy,
true);
262 if (!trCosmTop.rotate(trCosmBtm.getAlpha()) ||
264 LOG(
debug) <<
"Rotation/propagation of top-track to bottom-track frame failed.";
268 o2::track::TrackParCov::MatrixDSym5 cov5;
269 float chi2Match = trCosmBtm.getPredictedChi2(trCosmTop, cov5);
270 if (!trCosmBtm.update(trCosmTop, cov5)) {
271 LOG(
debug) <<
"Top/Bottom update failed";
275 mCosmicTracks.emplace_back(mSeeds[poolEntryID[btm]].origID, mSeeds[poolEntryID[
top]].origID, trCosmBtm, trCosmTop, chi2, chi2Match, nclTot,
t0, dt);
277 o2::MCCompLabel lbl[2] = {
data.getTrackMCLabel(mSeeds[poolEntryID[btm]].origID),
data.getTrackMCLabel(mSeeds[poolEntryID[
top]].origID)};
278 auto& tlb = mCosmicTracksLbl.emplace_back((nclBtm > nclTot - nclBtm ? lbl[0] : lbl[1]));
279 tlb.setFakeFlag(lbl[0] != lbl[1]);
282 LOG(info) <<
"Validated " << mCosmicTracks.size() <<
" top-bottom tracks in TF# " << mTFCount;
286void MatchCosmics::selectWinners()
289 int ntr = mSeeds.size(), iter = 0, nValidated = 0;
290 mWinners.reserve(mRecords.size() / 2);
294 for (
int i = 0;
i < ntr;
i++) {
295 if (mSeeds[
i].matchID < 0 || mRecords[mSeeds[
i].matchID].next ==
Validated) {
299 if (validateMatch(
i)) {
300 mWinners.push_back(mSeeds[
i].matchID);
305 LOGF(info,
"iter %d Validated %d of %d remaining matches", iter, nValidated, nRemaining);
307 }
while (nValidated);
311bool MatchCosmics::validateMatch(
int partner0)
314 auto& matchRec = mRecords[mSeeds[partner0].matchID];
315 auto partner1 = matchRec.id1;
316 auto& patnerRec = mRecords[mSeeds[partner1].matchID];
320 if (patnerRec.id1 == partner0) {
322 auto next0 = matchRec.next;
324 auto& nextRec = mRecords[next0];
325 suppressMatch(partner0, nextRec.id1);
326 next0 = nextRec.next;
331 auto next1 = patnerRec.next;
333 auto& nextRec = mRecords[next1];
334 suppressMatch(partner1, nextRec.id1);
335 next1 = nextRec.next;
344void MatchCosmics::suppressMatch(
int partner0,
int partner1)
347 if (mSeeds[partner1].matchID < 0 || mRecords[mSeeds[partner1].matchID].next ==
Validated) {
348 LOG(warning) <<
"Attempt to remove null or validated partner match " << mSeeds[partner1].matchID;
351 int topID =
MinusOne, next = mSeeds[partner1].matchID;
353 auto& matchRec = mRecords[next];
354 if (matchRec.id1 == partner0) {
356 mSeeds[partner1].matchID = matchRec.next;
358 mRecords[topID].next = matchRec.next;
363 next = matchRec.next;
372 auto& seed0 = mSeeds[
i];
373 auto& seed1 = mSeeds[
j];
374 if (seed0.matchID ==
Reject) {
377 if (seed1.matchID ==
Reject) {
381 LOG(
debug) <<
"Seed " <<
i <<
" [" << seed0.tBracket.getMin() <<
" : " << seed0.tBracket.getMax() <<
"] | "
382 <<
"Seed " <<
j <<
" [" << seed1.tBracket.getMin() <<
" : " << seed1.tBracket.getMax() <<
"] | ";
383 LOG(
debug) << seed0.origID <<
" | " << seed0.o2::track::TrackPar::asString();
384 LOG(
debug) << seed1.origID <<
" | " << seed1.o2::track::TrackPar::asString();
386 if (seed1.tBracket > seed0.tBracket) {
394 auto dTgl = seed0.getTgl() + seed1.getTgl();
400 auto dQ2Pt = seed0.getQ2Pt() + seed1.getQ2Pt();
409 seed1Inv.updateCov(mMatchParams->
systSigma2[
i], o2::track::DiagMap[
i]);
412 if (!seed1Inv.rotate(seed0.getAlpha()) ||
417 auto dSnp = seed0.getSnp() - seed1Inv.getSnp();
422 auto dY = seed0.getY() - seed1Inv.getY();
427 bool ignoreZ = seed0.origID.getSource() == o2d::GlobalTrackID::TPC || seed1.origID.getSource() == o2d::GlobalTrackID::TPC;
429 auto dZ = seed0.getZ() - seed1Inv.getZ();
435 seed1Inv.setCov(250. * 250., o2::track::DiagMap[
o2::track::kZ]);
442 chi2 = seed0.getPredictedChi2(seed1Inv);
448 registerMatch(
i,
j, chi2);
449 registerMatch(
j,
i, chi2);
450 LOG(
debug) <<
"Chi2 = " << chi2 <<
" NMatches " << mRecords.size();
454#ifdef _ALLOW_DEBUG_TREES_
460 (*mDBGOut) <<
"match"
461 <<
"tf=" << mTFCount <<
"seed0=" << seed0 <<
"seed1=" << seed1I <<
"chi2Match=" << chi2 <<
"rej=" << rejI <<
"\n";
470void MatchCosmics::registerMatch(
int i,
int j,
float chi2)
473 int newRef = mRecords.size();
475 auto* best = &mSeeds[
i].matchID;
477 auto& oldMatchRec = mRecords[*best];
478 if (oldMatchRec.chi2 > chi2) {
479 matchRec.next = *best;
483 best = &oldMatchRec.next;
497 auto creator = [
this](
auto& _tr,
GTrackID _origID,
float t0,
float terr) {
499 if (std::abs(_tr.getQ2Pt()) > this->mQ2PtCutoff) {
502 if constexpr (isTPCTrack<decltype(_tr)>()) {
507 t0 *= this->mTPCTBinMUS;
508 terr *= this->mTPCTBinMUS;
510 t0 += 0.5 * this->mITSROFrameLengthMUS;
511 terr *= this->mITSROFrameLengthMUS;
516 mSeeds.emplace_back(TrackSeed{_tr, {
t0 - terr,
t0 + terr}, _origID,
MinusOne});
523 data.createTracksVariadic(creator);
525 LOG(info) <<
"collected " << mSeeds.size() <<
" seeds";
529void MatchCosmics::updateTimeDependentParams()
533 mTPCTBinMUS = elParam.ZbinWidth;
535 mFieldON = std::abs(mBz) > 0.01;
536 mQ2PtCutoff = 1.f / std::max(0.05f, mMatchParams->
minSeedPt);
538 mQ2PtCutoff *= 5.00668 / std::abs(mBz);
549#ifdef _ALLOW_DEBUG_TREES_COSM
552 mDBGOut = std::make_unique<o2::utils::TreeStreamRedirector>(mDebugTreeFileName.data(),
"recreate");
560 std::vector<o2::BaseCluster<float>> itscl;
561 const auto& clusITS =
data.getITSClusters();
562 if (clusITS.size()) {
563 const auto& patterns =
data.getITSClustersPatterns();
564 itscl.reserve(clusITS.size());
565 auto pattIt = patterns.begin();
568 return std::move(itscl);
574#ifdef _ALLOW_DEBUG_TREES_COSM
579#ifdef _ALLOW_DEBUG_TREES_
594 mTPCVDrift =
v.refVDrift *
v.corrFact;
595 mTPCVDriftCorrFact =
v.corrFact;
596 mTPCVDriftRef =
v.refVDrift;
597 mTPCDriftTimeOffset =
v.getTimeOffset();
603 mTPCCorrMapsHelper = maph;
Definition of the ITSMFT compact cluster.
Helper class to access correction maps.
Some ALICE geometry constants of common interest.
Accessor for TrackParCov derived objects from multiple containers.
Definition of the GeometryTGeo class.
Class to perform matching/refit of cosmic tracks legs.
Class to store the output of the matching to TOF.
Class to perform TPC ITS matching.
Definition of the parameter class for the detector electronics.
Wrapper container for different reconstructed object types.
constexpr auto isITSTrack()
Definition of the ITS track.
Result of refitting TPC-ITS matched track.
Result of refitting TPC with TOF match constraint.
calibration data from laser track calibration
Helper class to obtain TPC clusters / digits / labels from DPL.
GPUd() value_type estimateLTFast(o2 static GPUd() float estimateLTIncrement(const o2 PropagatorImpl * Instance(bool uninitialized=false)
static const ParameterElectronics & Instance()
@ MatchTreeAll
produce matching candidates tree for all candidates
@ MatchTreeAccOnly
fill the matching candidates tree only once the cut is passed
static constexpr int Validated
void setTPCCorrMaps(o2::gpu::CorrectionMapsHelper *maph)
bool isDebugFlag(UInt_t flags) const
get debug trees flags
void setDebugFlag(UInt_t flag, bool on=true)
set the name of output debug file
void setTPCVDrift(const o2::tpc::VDriftCorrFact &v)
static constexpr int Reject
void process(const o2::globaltracking::RecoContainer &data)
static constexpr int MinusOne
static GeometryTGeo * Instance()
GLfloat GLfloat GLfloat alpha
GLdouble GLdouble GLdouble GLdouble top
GLboolean GLboolean GLboolean b
GLuint GLfloat GLfloat GLfloat GLfloat GLfloat GLfloat GLfloat t0
GLboolean GLboolean GLboolean GLboolean a
constexpr float XTPCInnerRef
reference radius at which TPC provides the tracks
void convertCompactClusters(gsl::span< const itsmft::CompClusterExt > clusters, gsl::span< const unsigned char >::iterator &pattIt, std::vector< o2::BaseCluster< float > > &output, const itsmft::TopologyDictionary *dict)
convert compact clusters to 3D spacepoints
constexpr float kMostProbablePt
float crudeNSigma2Cut[o2::track::kNParams]
o2::base::Propagator::MatCorrType matCorr
float systSigma2[o2::track::kNParams]
LOG(info)<< "Compressed in "<< sw.CpuTime()<< " s"