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(),
101 const auto& itsClusters = prepareITSClusters(
data);
103 std::vector<int> itsTracksROF;
105 const auto& itsTracksROFRec =
data.getITSTracksROFRecords();
106 itsTracksROF.resize(
data.getITSTracks().size());
107 for (
unsigned irf = 0, cnt = 0; irf < itsTracksROFRec.size(); irf++) {
108 int ntr = itsTracksROFRec[irf].getNEntries();
109 for (
int itr = 0; itr < ntr; itr++) {
110 itsTracksROF[cnt++] = irf;
115 const auto& itsTrOrig =
data.getITSTrack(gidx);
116 int nclRefit = 0, ncl = itsTrOrig.getNumberOfClusters(), rof = itsTracksROF[gidx.getIndex()];
117 const auto& itsTrackClusRefs =
data.getITSTracksClusterRefs();
118 int clEntry = itsTrOrig.getFirstClusterEntry();
121 int from = ncl - 1, to = -1,
step = -1;
127 for (
int icl = from; icl != to; icl +=
step) {
128 const auto& clus = itsClusters[itsTrackClusRefs[clEntry + icl]];
129 float alpha = geomITS->getSensorRefAlpha(clus.getSensorID()),
x = clus.getX();
130 if (!trFit.rotate(
alpha) || !propagator->propagateToX(trFit,
x, propagator->getNominalBz(),
this->mMatchParams->maxSnp,
this->mMatchParams->maxStep,
this->mMatchParams->matCorr)) {
133 chi2 += trFit.getPredictedChi2(clus);
134 if (!trFit.update(clus)) {
139 return nclRefit == ncl ? ncl : -1;
142 for (
auto winRID : mWinners) {
143 const auto&
rec = mRecords[winRID];
144 int poolEntryID[2] = {
rec.id0,
rec.id1};
146 auto tOverlap = mSeeds[
rec.id0].tBracket.getOverlap(mSeeds[
rec.id1].tBracket);
147 float t0 = tOverlap.mean(), dt = tOverlap.delta() * 0.5;
148 auto pnt0 = outerLegs[0].getXYZGlo(), pnt1 = outerLegs[1].getXYZGlo();
149 int btm = 0,
top = 1;
151 if (pnt0.Y() > pnt1.Y()) {
155 LOG(
debug) <<
"Winner " <<
count++ <<
" Record " << winRID <<
" Partners:"
156 <<
" B: " << mSeeds[poolEntryID[btm]].origID <<
"/" << mSeeds[poolEntryID[btm]].origID.getSourceName()
157 <<
" U: " << mSeeds[poolEntryID[
top]].origID <<
"/" << mSeeds[poolEntryID[
top]].origID.getSourceName()
158 <<
" | T:" << tOverlap.asString();
166 if (mSeeds[poolEntryID[btm]].origID.getSource() ==
GTrackID::TPC) {
167 const auto& tpcTrOrig =
data.getTPCTrack(mSeeds[poolEntryID[btm]].origID);
168 trCosm = outerLegs[btm];
169 trCosm.resetCovariance();
174 int retVal = tpcRefitter->RefitTrackAsTrackParCov(trCosm, tpcTrOrig.getClusterRef(),
t0 * tpcTBinMUSInv, &chi2,
false,
false);
176 LOG(
debug) <<
"Inward refit of btm TPC track failed.";
180 LOG(
debug) <<
"chi2 after btm TPC refit with " <<
retVal <<
" clusters : " << chi2 <<
" orig.chi2 was " << tpcTrOrig.getChi2();
184 trCosm.setQ2Pt(-trCosm.getQ2Pt());
186 auto gidxListBtm =
data.getSingleDetectorRefs(mSeeds[poolEntryID[btm]].origID);
189 nclTot += tpcTrOrig.getNClusters();
190 chi2 += tpcTrOrig.getChi2();
194 nclTot += itsTrOrig.getNClusters();
195 chi2 += itsTrOrig.getChi2();
199 if (!trCosm.rotate(mSeeds[poolEntryID[
top]].getAlpha()) ||
201 LOG(
debug) <<
"Rotation/propagation of btm-track to top-track frame failed.";
205 auto trCosmBtm = trCosm;
209 auto gidxListTop =
data.getSingleDetectorRefs(mSeeds[poolEntryID[
top]].origID);
213 auto nclfit = refitITSTrack(trCosm, gidxListTop[
GTrackID::ITS], chi2,
false);
217 LOG(
debug) <<
"chi2 after top ITS refit with " << nclfit <<
" clusters : " << chi2 <<
" orig.chi2 was " <<
data.getITSTrack(gidxListTop[
GTrackID::ITS]).getChi2();
227 LOG(
debug) <<
"Propagation to inner TPC boundary X=" << xtogo <<
" failed";
232 int retVal = tpcRefitter->RefitTrackAsTrackParCov(trCosm, tpcTrOrig.getClusterRef(),
t0 * tpcTBinMUSInv, &chi2,
true,
false);
234 LOG(
debug) <<
"Outward refit of top TPC track failed.";
237 LOG(
debug) <<
"chi2 after top TPC refit with " <<
retVal <<
" clusters : " << chi2 <<
" orig.chi2 was " << tpcTrOrig.getChi2();
243 auto trCosmTop = outerLegs[
top];
246 int retVal = tpcRefitter->RefitTrackAsTrackParCov(trCosmTop, tpcTrOrig.getClusterRef(),
t0 * tpcTBinMUSInv, &chi2Dummy,
false,
true);
248 LOG(
debug) <<
"Outward refit of top TPC track failed.";
254 auto nclfit = refitITSTrack(trCosmTop, gidxListTop[
GTrackID::ITS], chi2Dummy,
true);
261 if (!trCosmTop.rotate(trCosmBtm.getAlpha()) ||
263 LOG(
debug) <<
"Rotation/propagation of top-track to bottom-track frame failed.";
267 o2::track::TrackParCov::MatrixDSym5 cov5;
268 float chi2Match = trCosmBtm.getPredictedChi2(trCosmTop, cov5);
269 if (!trCosmBtm.update(trCosmTop, cov5)) {
270 LOG(
debug) <<
"Top/Bottom update failed";
274 mCosmicTracks.emplace_back(mSeeds[poolEntryID[btm]].origID, mSeeds[poolEntryID[
top]].origID, trCosmBtm, trCosmTop, chi2, chi2Match, nclTot,
t0, dt);
276 o2::MCCompLabel lbl[2] = {
data.getTrackMCLabel(mSeeds[poolEntryID[btm]].origID),
data.getTrackMCLabel(mSeeds[poolEntryID[
top]].origID)};
277 auto& tlb = mCosmicTracksLbl.emplace_back((nclBtm > nclTot - nclBtm ? lbl[0] : lbl[1]));
278 tlb.setFakeFlag(lbl[0] != lbl[1]);
281 LOG(info) <<
"Validated " << mCosmicTracks.size() <<
" top-bottom tracks in TF# " << mTFCount;
285void MatchCosmics::selectWinners()
288 int ntr = mSeeds.size(), iter = 0, nValidated = 0;
289 mWinners.reserve(mRecords.size() / 2);
293 for (
int i = 0;
i < ntr;
i++) {
294 if (mSeeds[
i].matchID < 0 || mRecords[mSeeds[
i].matchID].next ==
Validated) {
298 if (validateMatch(
i)) {
299 mWinners.push_back(mSeeds[
i].matchID);
304 LOGF(info,
"iter %d Validated %d of %d remaining matches", iter, nValidated, nRemaining);
306 }
while (nValidated);
310bool MatchCosmics::validateMatch(
int partner0)
313 auto& matchRec = mRecords[mSeeds[partner0].matchID];
314 auto partner1 = matchRec.id1;
315 auto& patnerRec = mRecords[mSeeds[partner1].matchID];
319 if (patnerRec.id1 == partner0) {
321 auto next0 = matchRec.next;
323 auto& nextRec = mRecords[next0];
324 suppressMatch(partner0, nextRec.id1);
325 next0 = nextRec.next;
330 auto next1 = patnerRec.next;
332 auto& nextRec = mRecords[next1];
333 suppressMatch(partner1, nextRec.id1);
334 next1 = nextRec.next;
343void MatchCosmics::suppressMatch(
int partner0,
int partner1)
346 if (mSeeds[partner1].matchID < 0 || mRecords[mSeeds[partner1].matchID].next ==
Validated) {
347 LOG(warning) <<
"Attempt to remove null or validated partner match " << mSeeds[partner1].matchID;
350 int topID =
MinusOne, next = mSeeds[partner1].matchID;
352 auto& matchRec = mRecords[next];
353 if (matchRec.id1 == partner0) {
355 mSeeds[partner1].matchID = matchRec.next;
357 mRecords[topID].next = matchRec.next;
362 next = matchRec.next;
371 auto& seed0 = mSeeds[
i];
372 auto& seed1 = mSeeds[
j];
373 if (seed0.matchID ==
Reject) {
376 if (seed1.matchID ==
Reject) {
380 LOG(
debug) <<
"Seed " <<
i <<
" [" << seed0.tBracket.getMin() <<
" : " << seed0.tBracket.getMax() <<
"] | "
381 <<
"Seed " <<
j <<
" [" << seed1.tBracket.getMin() <<
" : " << seed1.tBracket.getMax() <<
"] | ";
382 LOG(
debug) << seed0.origID <<
" | " << seed0.o2::track::TrackPar::asString();
383 LOG(
debug) << seed1.origID <<
" | " << seed1.o2::track::TrackPar::asString();
385 if (seed1.tBracket > seed0.tBracket) {
393 auto dTgl = seed0.getTgl() + seed1.getTgl();
399 auto dQ2Pt = seed0.getQ2Pt() + seed1.getQ2Pt();
408 seed1Inv.updateCov(mMatchParams->
systSigma2[
i], o2::track::DiagMap[
i]);
411 if (!seed1Inv.rotate(seed0.getAlpha()) ||
416 auto dSnp = seed0.getSnp() - seed1Inv.getSnp();
421 auto dY = seed0.getY() - seed1Inv.getY();
426 bool ignoreZ = seed0.origID.getSource() == o2d::GlobalTrackID::TPC || seed1.origID.getSource() == o2d::GlobalTrackID::TPC;
428 auto dZ = seed0.getZ() - seed1Inv.getZ();
434 seed1Inv.setCov(250. * 250., o2::track::DiagMap[
o2::track::kZ]);
441 chi2 = seed0.getPredictedChi2(seed1Inv);
447 registerMatch(
i,
j, chi2);
448 registerMatch(
j,
i, chi2);
449 LOG(
debug) <<
"Chi2 = " << chi2 <<
" NMatches " << mRecords.size();
453#ifdef _ALLOW_DEBUG_TREES_
459 (*mDBGOut) <<
"match"
460 <<
"tf=" << mTFCount <<
"seed0=" << seed0 <<
"seed1=" << seed1I <<
"chi2Match=" << chi2 <<
"rej=" << rejI <<
"\n";
469void MatchCosmics::registerMatch(
int i,
int j,
float chi2)
472 int newRef = mRecords.size();
474 auto* best = &mSeeds[
i].matchID;
476 auto& oldMatchRec = mRecords[*best];
477 if (oldMatchRec.chi2 > chi2) {
478 matchRec.next = *best;
482 best = &oldMatchRec.next;
496 auto creator = [
this](
auto& _tr,
GTrackID _origID,
float t0,
float terr) {
498 if (std::abs(_tr.getQ2Pt()) > this->mQ2PtCutoff) {
501 if constexpr (isTPCTrack<decltype(_tr)>()) {
506 t0 *= this->mTPCTBinMUS;
507 terr *= this->mTPCTBinMUS;
509 t0 += 0.5 * this->mITSROFrameLengthMUS;
510 terr *= this->mITSROFrameLengthMUS;
515 mSeeds.emplace_back(TrackSeed{_tr, {
t0 - terr,
t0 + terr}, _origID,
MinusOne});
522 data.createTracksVariadic(creator);
524 LOG(info) <<
"collected " << mSeeds.size() <<
" seeds";
528void MatchCosmics::updateTimeDependentParams()
532 mTPCTBinMUS = elParam.ZbinWidth;
534 mFieldON = std::abs(mBz) > 0.01;
535 mQ2PtCutoff = 1.f / std::max(0.05f, mMatchParams->
minSeedPt);
537 mQ2PtCutoff *= 5.00668 / std::abs(mBz);
548#ifdef _ALLOW_DEBUG_TREES_COSM
551 mDBGOut = std::make_unique<o2::utils::TreeStreamRedirector>(mDebugTreeFileName.data(),
"recreate");
559 std::vector<o2::BaseCluster<float>> itscl;
560 const auto& clusITS =
data.getITSClusters();
561 if (clusITS.size()) {
562 const auto& patterns =
data.getITSClustersPatterns();
563 itscl.reserve(clusITS.size());
564 auto pattIt = patterns.begin();
567 return std::move(itscl);
573#ifdef _ALLOW_DEBUG_TREES_COSM
578#ifdef _ALLOW_DEBUG_TREES_
593 mTPCVDrift =
v.refVDrift *
v.corrFact;
594 mTPCVDriftCorrFact =
v.corrFact;
595 mTPCVDriftRef =
v.refVDrift;
596 mTPCDriftTimeOffset =
v.getTimeOffset();
602 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"