@@ -220,7 +220,7 @@ void MatchTPCITS::init()
220220 // make sure T2GRot matrices are loaded into ITS geometry helper
221221 o2::its::GeometryTGeo::Instance ()->fillMatrixCache (o2::math_utils::bit2Mask (o2::math_utils::TransformType::T2GRot) | o2::math_utils::bit2Mask (o2::math_utils::TransformType::T2L));
222222
223- mSectEdgeMargin2 = mParams ->crudeAbsDiffCut [o2::track::kY ] * mParams -> crudeAbsDiffCut [o2::track:: kY ]; // /< precalculated ^2
223+ mSectEdgeMargin = mParams ->crudeAbsDiffCut [o2::track::kY ] / std::sqrt (Cos70I2);
224224
225225#ifdef _ALLOW_DEBUG_TREES_
226226 // debug streamer
@@ -446,7 +446,6 @@ void MatchTPCITS::addTPCSeed(const o2::track::TrackParCov& _tr, float t0, float
446446 if (mMCTruthON ) {
447447 mTPCLblWork .emplace_back (mTPCTrkLabels [tpcID]);
448448 }
449-
450449 // cache work track index
451450 mTPCSectIndexCache [o2::math_utils::angle2Sector (trc.getAlpha ())].push_back (mTPCWork .size () - 1 );
452451}
@@ -638,6 +637,8 @@ bool MatchTPCITS::prepareITSData()
638637 }
639638 long nHBF = o2::base::GRPGeomHelper::getNHBFPerTF ();
640639 long maxBCs = nHBF * long (o2::constants::lhc::LHCMaxBunches);
640+ o2::track::TrackLTIntegral trackLTInt;
641+ trackLTInt.setTimeNotNeeded ();
641642
642643 for (int irof = 0 ; irof < nROFs; irof++) {
643644 const auto & rofRec = mITSTrackROFRec [irof];
@@ -685,10 +686,14 @@ bool MatchTPCITS::prepareITSData()
685686 continue ;
686687 }
687688 // make sure the track is at the ref. radius
688- if (!propagateToRefX (trc)) {
689+ trackLTInt.clearFast ();
690+ if (!propagateToRefX (trc, &trackLTInt)) {
689691 mITSWork .pop_back (); // discard failed track
690692 continue ; // add to cache only those ITS tracks which reached ref.X and have reasonable snp
691693 }
694+ trc.xrho = trackLTInt.getXRho (); // we collect seen x*rho and distance to the reference X for further PID correcrions
695+ trc.dL = trackLTInt.getL ();
696+
692697 if (mMCTruthON ) {
693698 mITSLblWork .emplace_back (mITSTrkLabels [it]);
694699 }
@@ -702,19 +707,16 @@ bool MatchTPCITS::prepareITSData()
702707 // when propagated to Xr (in this neighbouring sector) and the edge will be (neglecting the curvature)
703708 // [(Xr*tg(10)-Yr)/(tgPhir+tg70)]^2 / cos(70)^2 // for the next sector
704709 // [(Xr*tg(10)+Yr)/(tgPhir-tg70)]^2 / cos(70)^2 // for the prev sector
705- // Distances to the sector edges in neighbourings sectors (at Xref in theit proper frames)
710+ // Distances to the sector edges in neighbourings sectors (at Xref in their proper frames)
706711 float trcY = trc.getY (), tgp = trc.getSnp ();
707712 tgp /= std::sqrt ((1 .f - tgp) * (1 .f + tgp)); // tan of track direction XY
708713
709- // sector up
710- float dy2Up = (YMaxAtXMatchingRef - trcY) / (tgp + Tan70);
711- if ((dy2Up * dy2Up * Cos70I2) < mSectEdgeMargin2 ) { // need to check this track for matching in sector up
712- addLastTrackCloneForNeighbourSector (sector < (o2::constants::math::NSectors - 1 ) ? sector + 1 : 0 );
713- }
714- // sector down
715- float dy2Dn = (YMaxAtXMatchingRef + trcY) / (tgp - Tan70);
716- if ((dy2Dn * dy2Dn * Cos70I2) < mSectEdgeMargin2 ) { // need to check this track for matching in sector down
717- addLastTrackCloneForNeighbourSector (sector > 1 ? sector - 1 : o2::constants::math::NSectors - 1 );
714+ float dyUpDn[2 ] = {std::abs ((YMaxAtXMatchingRef - trcY) / (tgp + Tan70)), std::abs ((YMaxAtXMatchingRef + trcY) / (tgp - Tan70))}; // sector up, down edge distances
715+ // we do the cloning for closest edge only
716+ int sel = dyUpDn[0 ] < dyUpDn[1 ] ? 0 : 1 ;
717+ if (dyUpDn[sel] < mSectEdgeMargin ) { // need to check this track for matching in sector up or down
718+ int sectNeib = sel == 0 ? (sector < (o2::constants::math::NSectors - 1 ) ? sector + 1 : 0 ) : (sector > 1 ? sector - 1 : o2::constants::math::NSectors - 1 );
719+ addLastTrackCloneForNeighbourSector (sectNeib, &trackLTInt);
718720 }
719721 }
720722 }
@@ -1014,7 +1016,7 @@ bool MatchTPCITS::registerMatchRecordTPC(int iITS, int iTPC, float chi2, int can
10141016}
10151017
10161018// ______________________________________________
1017- void MatchTPCITS::registerMatchRecordITS (int iITS, int iTPC, float chi2, int candIC)
1019+ void MatchTPCITS::registerMatchRecordITS (const int iITS, int iTPC, float chi2, int candIC)
10181020{
10191021 // /< register TPC match in ITS tracks match records, ordering them in quality
10201022 auto & tITS = mITSWork [iITS];
@@ -1068,7 +1070,26 @@ int MatchTPCITS::compareTPCITSTracks(const TrackLocITS& tITS, const TrackLocTPC&
10681070 if ((rejFlag = roughCheckDif (diff, mParams ->crudeNSigma2Cut [o2::track::kTgl ], RejectOnTgl + NSigmaShift))) {
10691071 return rejFlag;
10701072 }
1071- diff = tITS.getParam (o2::track::kY ) - tTPC.getParam (o2::track::kY );
1073+ // do we need to account for different PID hypotheses used for ITS and TPC tracks propagation to ref. X?
1074+ bool testOtherPID = false ;
1075+ float itsParam[5 ] = {tITS.getY (), tITS.getZ (), tITS.getSnp (), tITS.getTgl (), tITS.getQ2Pt ()};
1076+ if (tTPC.getPID () > tITS.getPID () && tITS.dL > 0 .f && tTPC.getP2 () / tTPC.getPID ().getMass2 () < mParams ->minBetaGammaForPIDDiff ) {
1077+ o2::track::TrackPar tPID (mITSTracksArray [tITS.sourceID ].getParamOut ()); // clone original ITS track at highest update point
1078+ tPID.setPID (tTPC.getPID (), true );
1079+ if (!tPID.correctForELoss (tITS.xrho )) {
1080+ return RejectoOnPIDCorr;
1081+ }
1082+ float dCurv = (tPID.getQ2Pt () - tITS.getQ2Pt ()) * mBz * o2::constants::math::B2C, dLEff = tITS.dL * mParams ->ITSStepEffFraction , dCurvL = dCurv * dLEff;
1083+ itsParam[o2::track::kQ2Pt ] = tPID.getQ2Pt ();
1084+ itsParam[o2::track::kSnp ] += dCurvL;
1085+ if (std::abs (itsParam[o2::track::kSnp ]) >= 1 .) {
1086+ itsParam[o2::track::kSnp ] = std::copysign (0.99 , itsParam[o2::track::kSnp ]);
1087+ }
1088+ itsParam[o2::track::kY ] += dCurvL * dLEff * 0.5 ;
1089+ testOtherPID = true ;
1090+ }
1091+
1092+ diff = itsParam[o2::track::kY ] - tTPC.getParam (o2::track::kY );
10721093 if ((rejFlag = roughCheckDif (diff, mParams ->crudeAbsDiffCut [o2::track::kY ], RejectOnY))) {
10731094 return rejFlag;
10741095 }
@@ -1078,7 +1099,7 @@ int MatchTPCITS::compareTPCITSTracks(const TrackLocITS& tITS, const TrackLocTPC&
10781099 }
10791100
10801101 if (tTPC.constraint == TrackLocTPC::Constrained) { // in continuous only constrained tracks can be compared in Z
1081- diff = tITS. getParam ( o2::track::kZ ) - tTPC.getParam (o2::track::kZ );
1102+ diff = itsParam[ o2::track::kZ ] - tTPC.getParam (o2::track::kZ );
10821103 if ((rejFlag = roughCheckDif (diff, mParams ->crudeAbsDiffCut [o2::track::kZ ], RejectOnZ))) {
10831104 return rejFlag;
10841105 }
@@ -1088,7 +1109,7 @@ int MatchTPCITS::compareTPCITSTracks(const TrackLocITS& tITS, const TrackLocTPC&
10881109 }
10891110 }
10901111
1091- diff = tITS. getParam ( o2::track::kSnp ) - tTPC.getParam (o2::track::kSnp );
1112+ diff = itsParam[ o2::track::kSnp ] - tTPC.getParam (o2::track::kSnp );
10921113 if ((rejFlag = roughCheckDif (diff, mParams ->crudeAbsDiffCut [o2::track::kSnp ], RejectOnSnp))) {
10931114 return rejFlag;
10941115 }
@@ -1097,17 +1118,26 @@ int MatchTPCITS::compareTPCITSTracks(const TrackLocITS& tITS, const TrackLocTPC&
10971118 return rejFlag;
10981119 }
10991120
1100- diff = tITS. getParam ( o2::track::kQ2Pt ) - tTPC.getParam (o2::track::kQ2Pt );
1121+ diff = itsParam[ o2::track::kQ2Pt ] - tTPC.getParam (o2::track::kQ2Pt );
11011122 if ((rejFlag = roughCheckDif (diff, mParams ->crudeAbsDiffCut [o2::track::kQ2Pt ], RejectOnQ2Pt))) {
11021123 return rejFlag;
11031124 }
11041125 diff *= diff / (tITS.getDiagError2 (o2::track::kQ2Pt ) + tTPC.getDiagError2 (o2::track::kQ2Pt ));
11051126 if ((rejFlag = roughCheckDif (diff, mParams ->crudeNSigma2Cut [o2::track::kQ2Pt ], RejectOnQ2Pt + NSigmaShift))) {
11061127 return rejFlag;
11071128 }
1108- // calculate mutual chi2 excluding Z in continuos mode
1109- chi2 = getPredictedChi2NoZ (tITS, tTPC);
1110- if (chi2 > mParams ->cutMatchingChi2 || chi2 < 0 .) { // sometime due to the numerical stability the chi2 is negative, reject it.
1129+ // calculate mutual chi2 excluding Z in continuous mode
1130+ if (testOtherPID) { // temporarily substitute pion params by alternative ones
1131+ auto tITSAlt = tITS;
1132+ tITSAlt.setPID (tTPC.getPID ());
1133+ tITSAlt.setParam (itsParam[o2::track::kY ], o2::track::kY );
1134+ tITSAlt.setParam (itsParam[o2::track::kSnp ], o2::track::kSnp );
1135+ tITSAlt.setParam (itsParam[o2::track::kQ2Pt ], o2::track::kQ2Pt );
1136+ chi2 = getPredictedChi2NoZ (tITSAlt, tTPC);
1137+ } else {
1138+ chi2 = getPredictedChi2NoZ (tITS, tTPC);
1139+ }
1140+ if (chi2 > mParams ->cutMatchingChi2 || chi2 < 0 .) { // sometimes due to the numerical stability the chi2 is negative, reject it.
11111141 return RejectOnChi2;
11121142 }
11131143
@@ -1206,19 +1236,23 @@ float MatchTPCITS::getPredictedChi2NoZ(const o2::track::TrackParCov& trITS, cons
12061236}
12071237
12081238// ______________________________________________
1209- void MatchTPCITS::addLastTrackCloneForNeighbourSector (int sector)
1239+ void MatchTPCITS::addLastTrackCloneForNeighbourSector (int sector, o2::track::TrackLTIntegral* trackLTInt )
12101240{
12111241 // add clone of the src ITS track cache, propagate it to ref.X in requested sector
12121242 // and register its index in the sector cache. Used for ITS tracks which are so close
12131243 // to their setctor edge that their matching should be checked also in the neighbouring sector
12141244 mITSWork .push_back (mITSWork .back ()); // clone the last track defined in given sector
12151245 auto & trc = mITSWork .back ();
12161246 if (trc.rotate (o2::math_utils::sector2Angle (sector)) &&
1217- o2::base::Propagator::Instance ()->PropagateToXBxByBz (trc, mParams ->XMatchingRef , MaxSnp, 2 ., MatCorrType::USEMatCorrNONE )) {
1247+ o2::base::Propagator::Instance ()->PropagateToXBxByBz (trc, mParams ->XMatchingRef , MaxSnp, 2 ., mUseMatCorrFlag , trackLTInt )) {
12181248 // TODO: use faster prop here, no 3d field, materials
12191249 mITSSectIndexCache [sector].push_back (mITSWork .size () - 1 ); // register track CLONE
12201250 // flag clone
12211251 mITSWork .back ().setCloneBefore ();
1252+ if (trackLTInt) {
1253+ mITSWork .back ().xrho = trackLTInt->getXRho (); // we collect seen x*rho and distance to the reference X for further PID correcrions
1254+ mITSWork .back ().dL = trackLTInt->getL ();
1255+ }
12221256 mITSWork [mITSWork .size () - 2 ].setCloneAfter ();
12231257 if (mMCTruthON ) {
12241258 mITSLblWork .emplace_back (mITSTrkLabels [trc.sourceID ]);
@@ -1229,14 +1263,14 @@ void MatchTPCITS::addLastTrackCloneForNeighbourSector(int sector)
12291263}
12301264
12311265// ______________________________________________
1232- bool MatchTPCITS::propagateToRefX (o2::track::TrackParCov& trc)
1266+ bool MatchTPCITS::propagateToRefX (o2::track::TrackParCov& trc, o2::track::TrackLTIntegral* lti )
12331267{
12341268 // propagate track to matching reference X, making sure its assigned alpha
12351269 // is consistent with TPC sector
12361270 bool refReached = false ;
12371271 refReached = mParams ->XMatchingRef < 10 .; // RS: tmp, to cover XMatchingRef~0
12381272 int trialsLeft = 2 ;
1239- while (o2::base::Propagator::Instance ()->PropagateToXBxByBz (trc, mParams ->XMatchingRef , MaxSnp, 2 ., mUseMatCorrFlag )) {
1273+ while (o2::base::Propagator::Instance ()->PropagateToXBxByBz (trc, mParams ->XMatchingRef , MaxSnp, 2 ., mUseMatCorrFlag , lti )) {
12401274 if (refReached) {
12411275 break ;
12421276 }
@@ -1421,10 +1455,30 @@ bool MatchTPCITS::refitTrackTPCITS(int iTPC, int& iITS, pmr::vector<o2::dataform
14211455 maxStep, MatCorrType::USEMatCorrNONE, nullptr , &trfit.getLTIntegralOut ())) {
14221456 LOG (error) << " LTOF integral might be incorrect" ;
14231457 }
1458+ auto & tofL = trfit.getLTIntegralOut (); // this is TL integral calculated from the RefX to the DCA to the beamline, invert material integrals for outward propagation
1459+ tofL.setX2X0 (-tofL.getX2X0 ());
1460+ tofL.setXRho (-tofL.getXRho ());
14241461
14251462 // outward refit
1463+ #ifdef _ALLOW_DEBUG_TREES_
1464+ o2::track::TrackParCov itsRefAltPID;
1465+ #endif
14261466 auto & tracOut = trfit.getParamOut (); // this is a clone of ITS outward track already at the matching reference X
1427- auto & tofL = trfit.getLTIntegralOut ();
1467+ if (tTPC.getPID () > tITS.getPID () && tTPC.getP2 () / tTPC.getPID ().getMass2 () < mParams ->minBetaGammaForPIDDiff ) {
1468+ // in case the TPC track hypothesis is not pion, we redo the outward propagation to ref.x with TPC PID
1469+ tracOut = mITSTracksArray [tITS.sourceID ].getParamOut ();
1470+ tracOut.setPID (tTPC.getPID (), true );
1471+ if (!tracOut.rotate (tTPC.getAlpha ()) || !o2::base::Propagator::Instance ()->PropagateToXBxByBz (tracOut, mParams ->XMatchingRef , MaxSnp, 2 ., mUseMatCorrFlag )) {
1472+ LOGP (debug, " Failed to rotate ITSouter with imposed PID to TPC alpha {} or propagate to X={}: {:s}" , tTPC.getAlpha (), mParams ->XMatchingRef , tracOut.asString ());
1473+ matchedTracks.pop_back (); // destroy failed track
1474+ return false ;
1475+ }
1476+ #ifdef _ALLOW_DEBUG_TREES_
1477+ if (mDBGOut ) {
1478+ itsRefAltPID = tracOut;
1479+ }
1480+ #endif
1481+ }
14281482 {
14291483 float xtogo = 0 ;
14301484 if (!tracOut.getXatLabR (o2::constants::geom::XTPCInnerRef, xtogo, mBz , o2::track::DirOutward) ||
@@ -1509,14 +1563,36 @@ bool MatchTPCITS::refitTrackTPCITS(int iTPC, int& iITS, pmr::vector<o2::dataform
15091563 }
15101564#ifdef _ALLOW_DEBUG_TREES_
15111565 if (mDBGOut ) {
1566+ o2::track::TrackPar itsRefPIDCorr (tITS);
1567+ itsRefPIDCorr.setX (0 );
1568+ if (tTPC.getPID () > tITS.getPID () && tITS.dL > 0 .f && tTPC.getP2 () / tTPC.getPID ().getMass2 () < mParams ->minBetaGammaForPIDDiff ) {
1569+ itsRefPIDCorr = mITSTracksArray [tITS.sourceID ].getParamOut (); // clone original ITS track at highest update point
1570+ itsRefPIDCorr.setPID (tTPC.getPID (), true );
1571+ if (!itsRefPIDCorr.correctForELoss (tITS.xrho )) {
1572+ itsRefPIDCorr.setX (-10 );
1573+ } else {
1574+ float q2ptPID = itsRefPIDCorr.getQ2Pt ();
1575+ float dCurv = (q2ptPID - tITS.getQ2Pt ()) * mBz * o2::constants::math::B2C, dLEff = tITS.dL * mParams ->ITSStepEffFraction , dCurvL = dCurv * dLEff;
1576+ itsRefPIDCorr = tITS;
1577+ itsRefPIDCorr.setPID (tTPC.getPID (), true );
1578+ itsRefPIDCorr.setQ2Pt (q2ptPID);
1579+ auto snp = tITS.getSnp () + dCurvL;
1580+ if (std::abs (snp) >= 1 .) {
1581+ snp = std::copysign (0.99 , snp);
1582+ }
1583+ itsRefPIDCorr.setSnp (snp);
1584+ itsRefPIDCorr.setY (tITS.getY () + dCurvL * dLEff * 0.5 );
1585+ }
1586+ }
15121587 (*mDBGOut ) << " refit"
1513- << " tpcOrig=" << mTPCTracksArray [tTPC.sourceID ] << " itsOrig=" << itsTrOrig << " itsRef=" << tITS << " tpcRef=" << tTPC << " matchRefit=" << trfit << " timeCorr=" << timeC << " dTimeFT0=" << minDiffFT0 << " dTimes=" << dtimes;
1588+ << " tpcOrig=" << mTPCTracksArray [tTPC.sourceID ] << " itsOrig=" << itsTrOrig << " itsRef=" << tITS << " tpcRef=" << tTPC << " matchRefit=" << trfit << " timeCorr=" << timeC << " dTimeFT0=" << minDiffFT0 << " dTimes=" << dtimes
1589+ << " itsRefAltPID=" << itsRefAltPID << " itsRefPIDCorr=" << itsRefPIDCorr;
15141590 if (mMCTruthON ) {
15151591 (*mDBGOut ) << " refit"
15161592 << " itsLbl=" << mITSLblWork [iITS] << " tpcLbl=" << mTPCLblWork [iTPC];
15171593 }
15181594 (*mDBGOut ) << " refit"
1519- << " \n " ;
1595+ << " tf= " << mTFCount << " \n " ;
15201596 }
15211597#endif
15221598
0 commit comments