2323#include " ReconstructionDataFormats/TrackTPCITS.h"
2424#include " ReconstructionDataFormats/TrackTPCTOF.h"
2525#include " ReconstructionDataFormats/MatchInfoTOF.h"
26+ #include " ReconstructionDataFormats/PrimaryVertex.h"
27+ #include " ReconstructionDataFormats/VtxTrackRef.h"
28+ #include " ReconstructionDataFormats/DCA.h"
2629#include " ITStracking/IOUtils.h"
2730#include " ITSBase/GeometryTGeo.h"
2831#include " TPCBase/ParameterElectronics.h"
3538#include " TPCFastTransformPOD.h"
3639#include < algorithm>
3740#include < numeric>
41+ #include < unordered_map>
3842
3943using namespace o2 ::globaltracking;
4044
@@ -52,21 +56,53 @@ void MatchCosmics::process(const o2::globaltracking::RecoContainer& data)
5256
5357 createSeeds (data);
5458 int ntr = mSeeds .size ();
55-
59+ const auto prop = o2::base::Propagator::Instance ();
5660 // propagate to DCA to origin
5761 const o2::math_utils::Point3D<float > v{0 ., 0 ., 0 };
5862 for (int i = 0 ; i < ntr; i++) {
5963 auto & trc = mSeeds [i];
60- if (!o2::base::Propagator::Instance ()->propagateToDCABxByBz (v, trc, mMatchParams ->maxStep , mMatchParams ->matCorr )) {
61- trc.matchID = Reject; // reject track
64+ if (!trc.matchID == Reject) {
65+ if (!prop->propagateToDCABxByBz (v, trc, mMatchParams ->maxStep , mMatchParams ->matCorr )) {
66+ trc.matchID = Reject; // reject track
67+ continue ;
68+ }
69+ if (mMatchParams ->dcaCutChi2 [trc.origID .getSource ()] > 0 .f && mUsePVInfo && (std::abs (trc.getY ()) < mMatchParams ->fiducialRIP && std::abs (trc.getZ ()) < mMatchParams ->fiducialZIP )) {
70+ // do the propagation only if we are in the fiducial IP range.
71+ for (int iv = trc.vtIDMin ; iv < trc.vtIDMax ; iv++) {
72+ const auto & pv = data.getPrimaryVertex (iv);
73+ o2::track::TrackParCov trcatPV (trc);
74+ o2::dataformats::DCA dca;
75+ if (!trcatPV.propagateToDCA (pv, mBz , &dca)) {
76+ trc.matchID = Reject;
77+ break ;
78+ }
79+ if (trc.origID .getSource () == GTrackID::TPC) { // correct the track Z position for the vertex time
80+ const auto & trcTPC = data.getTPCTrack (trc.origID .getSource ());
81+ float deltaZ = trcTPC.hasBothSidesClusters () ? 0 .f : (pv.getTimeStamp ().getTimeStamp () - trcTPC.getTime0 () * 8 * o2::constants::lhc::LHCBunchSpacingMUS) * mTPCVDrift ;
82+ dca.setZ (dca.getZ () + (trcTPC.hasASideClustersOnly () ? deltaZ : -deltaZ));
83+ }
84+ if (dca.calcChi2 () < mMatchParams ->dcaCutChi2 [trc.origID .getSource ()]) {
85+ trc.matchID = Reject;
86+ break ;
87+ }
88+ }
89+ }
6290 }
6391 }
6492
65- // sort in time bracket lower edge
93+ // sort in time bracket lower edge, putting rejected tracks in the end
6694 std::vector<int > sortID (ntr);
6795 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 (); });
69-
96+ std::sort (sortID.begin (), sortID.end (), [this ](int a, int b) { return (mSeeds [a].matchID != Reject) && (mSeeds [a].tBracket .getMin () < mSeeds [b].tBracket .getMin ()); });
97+ int lastValid = ntr - 1 ;
98+ for (; lastValid >= 0 ; lastValid--) {
99+ if (mSeeds [sortID[lastValid]].matchID != Reject) {
100+ break ;
101+ }
102+ }
103+ ntr = lastValid >= 0 ? lastValid + 1 : 0 ;
104+ LOGP (info, " Collected {} seeds, validated: {}" , mSeeds .size (), ntr);
105+ sortID.resize (ntr);
70106 for (int i = 0 ; i < ntr; i++) {
71107 for (int j = i + 1 ; j < ntr; j++) {
72108 if (checkPair (sortID[i], sortID[j]) == RejTime) {
@@ -424,6 +460,8 @@ MatchCosmics::RejFlag MatchCosmics::checkPair(int i, int j)
424460 break ;
425461 }
426462 bool ignoreZ = seed0.origID .getSource () == o2d::GlobalTrackID::TPC || seed1.origID .getSource () == o2d::GlobalTrackID::TPC;
463+ // RSTODO this is simplification: one should constraint the TPC-only track Z by the time of other candidate (at least their difference of both tracks are TPC only).
464+ // If the shift is large, eventually the tracks need to be refitted.
427465 if (!ignoreZ) { // cut on Z makes no sense for TPC only tracks
428466 auto dZ = seed0.getZ () - seed1Inv.getZ ();
429467 if (dZ * dZ > (seed0.getSigmaZ2 () + seed1Inv.getSigmaZ2 ()) * mMatchParams ->crudeNSigma2Cut [o2::track::kZ ]) {
@@ -492,8 +530,9 @@ void MatchCosmics::createSeeds(const o2::globaltracking::RecoContainer& data)
492530 // Scan all inputs and create seeding tracks
493531
494532 mSeeds .clear ();
533+ std::unordered_map<GTrackID, int > trackEntry;
495534
496- auto creator = [this ](auto & _tr, GTrackID _origID, float t0, float terr) {
535+ auto creator = [this , &trackEntry ](auto & _tr, GTrackID _origID, float t0, float terr) {
497536 if constexpr (std::is_base_of_v<o2::track::TrackParCov, std::decay_t <decltype (_tr)>>) {
498537 if (std::abs (_tr.getQ2Pt ()) > this ->mQ2PtCutoff ) {
499538 return true ;
@@ -512,7 +551,11 @@ void MatchCosmics::createSeeds(const o2::globaltracking::RecoContainer& data)
512551 terr *= this ->mMatchParams ->nSigmaTError ;
513552 }
514553 terr += this ->mMatchParams ->timeToleranceMUS ;
554+ trackEntry[_origID] = mSeeds .size ();
515555 mSeeds .emplace_back (TrackSeed{_tr, {t0 - terr, t0 + terr}, _origID, MinusOne});
556+ if constexpr (isTPCTrack<decltype (_tr)>()) {
557+ mSeeds .back ().setCov (this ->mMatchParams ->tpcExtraZError2 + _tr.getCov ()[o2::track::kSigZ2 ], o2::track::kSigZ2 );
558+ }
516559 return true ;
517560 } else {
518561 return false ;
@@ -521,7 +564,32 @@ void MatchCosmics::createSeeds(const o2::globaltracking::RecoContainer& data)
521564
522565 data.createTracksVariadic (creator);
523566
524- LOG (info) << " collected " << mSeeds .size () << " seeds" ;
567+ if (mUsePVInfo ) { // if needed, veto with the primary vertex info
568+ auto trackIndex = data.getPrimaryVertexMatchedTracks (); // Global ID's for associated tracks
569+ auto vtxRefs = data.getPrimaryVertexMatchedTrackRefs (); // references from vertex to these track IDs
570+ int nv = vtxRefs.size () - 1 ; // The last entry is for unassigned tracks, no need to check them
571+ const auto propagator = o2::base::Propagator::Instance ();
572+ for (int iv = 0 ; iv < nv; iv++) {
573+ const auto & vtref = vtxRefs[iv];
574+ int it = vtref.getFirstEntry (), itLim = it + vtref.getEntries ();
575+ for (; it < itLim; it++) {
576+ auto tvid = trackIndex[it];
577+ auto entry = trackEntry.find (tvid);
578+ if (entry == trackEntry.end ()) {
579+ continue ;
580+ }
581+ auto & seed = mSeeds [entry->second ];
582+ if (seed.matchID == Reject || (mMatchParams ->discardPVContributors && tvid.isPVContributor ())) {
583+ seed.matchID = Reject;
584+ continue ;
585+ }
586+ if (seed.vtIDMin < 0 ) {
587+ seed.vtIDMin = iv;
588+ }
589+ seed.vtIDMax = std::max (short (iv), seed.vtIDMax );
590+ }
591+ }
592+ }
525593}
526594
527595// ________________________________________________________
0 commit comments