1818#include " SpacePoints/TrackInterpolation.h"
1919#include " SpacePoints/TrackResiduals.h"
2020#include " ITStracking/IOUtils.h"
21+ #include " ITSBase/GeometryTGeo.h"
2122#include " TPCBase/ParameterElectronics.h"
2223#include " DataFormatsTPC/TrackTPC.h"
2324#include " DataFormatsTPC/Defs.h"
@@ -65,6 +66,9 @@ void TrackInterpolation::init(o2::dataformats::GlobalTrackID::mask_t src, o2::da
6566 mTrackTypes .insert ({GTrackID::ITSTPCTOF, 2 });
6667 mTrackTypes .insert ({GTrackID::ITSTPCTRDTOF, 3 });
6768
69+ o2::its::GeometryTGeo* geom = GeometryTGeo::Instance ();
70+ geom->fillMatrixCache (o2::math_utils::bit2Mask (o2::math_utils::TransformType::T2L, o2::math_utils::TransformType::L2G));
71+
6872 mInitDone = true ;
6973 LOGP (info, " Done initializing TrackInterpolation. Configured track input: {}. Track input specifically for map: {}" ,
7074 GTrackID::getSourcesNames (mSourcesConfigured ), mSingleSourcesConfigured ? " identical" : GTrackID::getSourcesNames (mSourcesConfiguredMap ));
@@ -273,6 +277,9 @@ void TrackInterpolation::process()
273277 trackIndices.insert (trackIndices.end (), mTrackIndices [mTrackTypes [GTrackID::ITSTPC]].begin (), mTrackIndices [mTrackTypes [GTrackID::ITSTPC]].end ());
274278
275279 int nSeeds = mSeeds .size (), lastChecked = 0 ;
280+ mParentID .clear ();
281+ mParentID .resize (nSeeds, -1 );
282+
276283 int maxOutputTracks = (mMaxTracksPerTF >= 0 ) ? mMaxTracksPerTF + mAddTracksForMapPerTF : nSeeds;
277284 mTrackData .reserve (maxOutputTracks);
278285 mClRes .reserve (maxOutputTracks * param::NPadRows);
@@ -292,6 +299,7 @@ void TrackInterpolation::process()
292299 this ->mGIDtables .push_back (this ->mRecoCont ->getSingleDetectorRefs (this ->mGIDs .back ()));
293300 this ->mTrackTimes .push_back (this ->mTrackTimes [seedIndex]);
294301 this ->mSeeds .push_back (this ->mSeeds [seedIndex]);
302+ this ->mParentID .push_back (seedIndex); // store parent seed id
295303 };
296304
297305 GTrackID::mask_t partsAdded;
@@ -457,41 +465,15 @@ void TrackInterpolation::interpolateTrack(int iSeed)
457465 (*trackDataExtended).trkTRD = trkTRD;
458466 }
459467 for (int iLayer = o2::trd::constants::NLAYER - 1 ; iLayer >= 0 ; --iLayer) {
460- int trkltIdx = trkTRD.getTrackletIndex (iLayer);
461- if (trkltIdx < 0 ) {
462- // no TRD tracklet in this layer
468+ std::array<float , 2 > trkltTRDYZ{};
469+ std::array<float , 3 > trkltTRDCov{};
470+ int res = processTRDLayer (trkTRD, iLayer, trkWork, &trkltTRDYZ, &trkltTRDCov);
471+ if (res == 0 ) { // no TRD tracklet in this layer
463472 continue ;
464473 }
465- const auto & trdSP = mRecoCont ->getTRDCalibratedTracklets ()[trkltIdx];
466- const auto & trdTrklt = mRecoCont ->getTRDTracklets ()[trkltIdx];
467- if (mDumpTrackPoints ) {
468- (*trackDataExtended).trkltTRD .push_back (trdTrklt);
469- (*trackDataExtended).clsTRD .push_back (trdSP);
470- }
471- auto trkltDet = trdTrklt.getDetector ();
472- auto trkltSec = trkltDet / (o2::trd::constants::NLAYER * o2::trd::constants::NSTACK);
473- if (trkltSec != o2::math_utils::angle2Sector (trkWork.getAlpha ())) {
474- if (!trkWork.rotate (o2::math_utils::sector2Angle (trkltSec))) {
475- LOG (debug) << " Track could not be rotated in TRD tracklet coordinate system in layer " << iLayer;
476- return ;
477- }
478- }
479- if (!propagator->PropagateToXBxByBz (trkWork, trdSP.getX (), mParams ->maxSnp , mParams ->maxStep , mMatCorr )) {
480- LOG (debug) << " Failed propagation to TRD layer " << iLayer;
474+ if (res < 0 ) { // failed to reach this layer
481475 return ;
482476 }
483-
484- const auto * pad = mGeoTRD ->getPadPlane (trkltDet);
485- float tilt = tan (TMath::DegToRad () * pad->getTiltingAngle ()); // tilt is signed! and returned in degrees
486- float tiltCorrUp = tilt * (trdSP.getZ () - trkWork.getZ ());
487- float zPosCorrUp = trdSP.getZ () + mRecoParam .getZCorrCoeffNRC () * trkWork.getTgl (); // maybe Z can be corrected on avarage already by the tracklet transformer?
488- float padLength = pad->getRowSize (trdTrklt.getPadRow ());
489- if (!((trkWork.getSigmaZ2 () < (padLength * padLength / 12 .f )) && (std::fabs (trdSP.getZ () - trkWork.getZ ()) < padLength))) {
490- tiltCorrUp = 0 .f ;
491- }
492- std::array<float , 2 > trkltTRDYZ{trdSP.getY () - tiltCorrUp, zPosCorrUp};
493- std::array<float , 3 > trkltTRDCov;
494- mRecoParam .recalcTrkltCov (tilt, trkWork.getSnp (), pad->getRowSize (trdTrklt.getPadRow ()), trkltTRDCov);
495477 if (!trkWork.update (trkltTRDYZ, trkltTRDCov)) {
496478 LOG (debug) << " Failed to update track at TRD layer " << iLayer;
497479 return ;
@@ -611,6 +593,46 @@ void TrackInterpolation::interpolateTrack(int iSeed)
611593 }
612594}
613595
596+ int TrackInterpolation::processTRDLayer (const o2::trd::TrackTRD& trkTRD, int iLayer, o2::track::TracParCov& trkWork,
597+ std::array<float , 2 >* trkltTRDYZ, std::array<float , 3 >* trkltTRDCov)
598+ {
599+ // return 1 in case of successful processing, 0 if there is no TRD tracklet at given layer, -1 if processing failed
600+ int trkltIdx = trkTRD.getTrackletIndex (iLayer);
601+ if (trkltIdx < 0 ) {
602+ return 0 ; // no TRD tracklet in this layer
603+ }
604+ const auto & trdSP = mRecoCont ->getTRDCalibratedTracklets ()[trkltIdx];
605+ const auto & trdTrklt = mRecoCont ->getTRDTracklets ()[trkltIdx];
606+ auto trkltDet = trdTrklt.getDetector ();
607+ auto trkltSec = trkltDet / (o2::trd::constants::NLAYER * o2::trd::constants::NSTACK);
608+ if (trkltSec != o2::math_utils::angle2Sector (trkWork.getAlpha ())) {
609+ if (!trkWork.rotate (o2::math_utils::sector2Angle (trkltSec))) {
610+ LOG (debug) << " Track could not be rotated in TRD tracklet coordinate system in layer " << iLayer;
611+ return -1 ;
612+ }
613+ }
614+ if (!propagator->PropagateToXBxByBz (trkWork, trdSP.getX (), mParams ->maxSnp , mParams ->maxStep , mMatCorr )) {
615+ LOG (debug) << " Failed propagation to TRD layer " << iLayer;
616+ return -1 ;
617+ }
618+ if (trkltTRDYZ) {
619+ const auto * pad = mGeoTRD ->getPadPlane (trkltDet);
620+ float tilt = tan (TMath::DegToRad () * pad->getTiltingAngle ()); // tilt is signed! and returned in degrees
621+ float tiltCorrUp = tilt * (trdSP.getZ () - trkWork.getZ ());
622+ float zPosCorrUp = trdSP.getZ () + mRecoParam .getZCorrCoeffNRC () * trkWork.getTgl (); // maybe Z can be corrected on avarage already by the tracklet transformer?
623+ float padLength = pad->getRowSize (trdTrklt.getPadRow ());
624+ if (!((trkWork.getSigmaZ2 () < (padLength * padLength / 12 .f )) && (std::fabs (trdSP.getZ () - trkWork.getZ ()) < padLength))) {
625+ tiltCorrUp = 0 .f ;
626+ }
627+ (*trkltTRDYZ)[0 ] = trdSP.getY () - tiltCorrUp;
628+ (*trkltTRDYZ)[1 ] = zPosCorrUp;
629+ if (trkltTRDCov) {
630+ mRecoParam .recalcTrkltCov (tilt, trkWork.getSnp (), pad->getRowSize (trdTrklt.getPadRow ()), *trkltTRDCov);
631+ }
632+ }
633+ return 1 ;
634+ }
635+
614636void TrackInterpolation::extrapolateTrack (int iSeed)
615637{
616638 // extrapolate ITS-only track through TPC and store residuals to TPC clusters in the output vectors
@@ -638,7 +660,7 @@ void TrackInterpolation::extrapolateTrack(int iSeed)
638660 trackData.gid = mGIDs [iSeed];
639661 trackData.par = mSeeds [iSeed];
640662
641- auto & trkWork = mSeeds [iSeed];
663+ auto trkWork = mSeeds [iSeed];
642664 float clusterTimeBinOffset = mTrackTimes [iSeed] / mTPCTimeBinMUS ;
643665 auto propagator = o2::base::Propagator::Instance ();
644666 unsigned short rowPrev = 0 ; // used to calculate dRow of two consecutive cluster residuals
@@ -681,6 +703,13 @@ void TrackInterpolation::extrapolateTrack(int iSeed)
681703 rowPrev = row;
682704 ++nMeasurements;
683705 }
706+
707+ TrackParams params; // for refitted track parameters and flagging rejected clusters
708+ if (clusterResiduals.size () > constants::MAXGLOBALPADROW) {
709+ LOGP (warn, " Extrapolated ITS-TPC track and found more reesiduals than possible ({})" , clusterResiduals.size ());
710+ return ;
711+ }
712+
684713 trackData.chi2TPC = trkTPC.getChi2 ();
685714 trackData.chi2ITS = trkITS.getChi2 ();
686715 trackData.nClsTPC = trkTPC.getNClusterReferences ();
@@ -691,19 +720,14 @@ void TrackInterpolation::extrapolateTrack(int iSeed)
691720 (*trackDataExtended).trkOuter = trkWork;
692721 }
693722
694- TrackParams params; // for refitted track parameters and flagging rejected clusters
695- if (clusterResiduals.size () > constants::MAXGLOBALPADROW) {
696- LOGP (warn, " Extrapolated ITS-TPC track and found more reesiduals than possible ({})" , clusterResiduals.size ());
697- return ;
698- }
699723 if (mParams ->skipOutlierFiltering || validateTrack (trackData, params, clusterResiduals)) {
700- // track is good
701- int nClValidated = 0 ;
702- int iRow = 0 ;
703- for (unsigned int iCl = 0 ; iCl < clusterResiduals.size (); ++iCl) {
724+ // track is good, store TPC part
725+
726+ int nClValidated = 0 , iRow = 0 ;
727+ unsigned int iCl = 0 ;
728+ for (iCl = 0 ; iCl < clusterResiduals.size (); ++iCl) {
704729 iRow += clusterResiduals[iCl].dRow ;
705- if (params.flagRej [iCl]) {
706- // skip masked cluster residual
730+ if (iRow < param::NPadRows && params.flagRej [iCl]) { // skip masked cluster residual
707731 continue ;
708732 }
709733 ++nClValidated;
@@ -720,9 +744,94 @@ void TrackInterpolation::extrapolateTrack(int iSeed)
720744 }
721745 }
722746 trackData.clIdx .setEntries (nClValidated);
747+
748+ // do we have TRD residuals to add?
749+ int iSeedFull = mParentID [iSeed] == -1 ? iSeed : mParentID [iSeed];
750+ auto gidFull = mGIDs [iSeedFull];
751+ const auto & gidTableFull = mGIDtables [iSeedFull];
752+ bool stopPropagation = false ;
753+ if (gidTableFull[GTrackID::TRD].isIndexSet ()) {
754+ const auto & trkTRD = mRecoCont ->getITSTPCTRDTrack <o2::trd::TrackTRD>(gidTableFull[GTrackID::ITSTPCTRD]);
755+ for (int iLayer = 0 ; iLayer < o2::trd::constants::NLAYER; iLayer++) {
756+ std::array<float , 2 > trkltTRDYZ{};
757+ int res = processTRDLayer (trkTRD, iLayer, trkWork, &trkltTRDYZ);
758+ if (res == 0 ) { // no traklet on this layer
759+ continue ;
760+ }
761+ if (res < 0 ) { // failed to reach this layer
762+ stopPropagation = true ;
763+ break ;
764+ }
765+
766+ float tgPhi = trkWork.getSnp () / std::sqrt ((1 .f - trkWork.getSnp ()) * (1 .f + trkWork.getSnp ()));
767+ auto dy = trkltTRDYZ[0 ] - trkWork.getY ();
768+ auto dz = trkltTRDYZ[1 ] - trkWork.getZ ();
769+ const auto sec = clusterResiduals[iCl].sec ;
770+ if ((std::abs (dy) < param::MaxResid) && (std::abs (dz) < param::MaxResid) && (std::abs (trkWork.getY ()) < param::MaxY) && (std::abs (trkWork.getZ ()) < param::MaxZ) && (std::abs (tgPhi) < param::MaxTgSlp)) {
771+ mClRes .emplace_back (dy, dz, tgPhi, trkWork.getY (), trkWork.getZ (), 160 + iLayer, o2::math_utils::angle2Sector (trkWork.getAlpha ()));
772+ trackData.nTrkltsTRD ++;
773+ trackData.nExtDetResid ++;
774+ // NEED TO STORE: TRD X
775+ }
776+ }
777+ }
778+
779+ // do we have TOF residual to add?
780+ while (gidTableFull[GTrackID::TOF].isIndexSet () && !stopPropagation) {
781+ const auto & clTOF = mRecoCont ->getTOFClusters ()[gidTableFull[GTrackID::TOF]];
782+ const float clTOFAlpha = o2::math_utils::sector2Angle (clTOF.getCount ());
783+ if (trkWork.getAlpha () != clTOFAlpha && !trkWork.rotate (clTOFAlpha)) {
784+ LOG (debug) << " Failed to rotate into TOF cluster sector frame" ;
785+ stopPropagation = true ;
786+ break ;
787+ }
788+ if (!propagator->PropagateToXBxByBz (trkWork, clTOF.getX (), mParams ->maxSnp , mParams ->maxStep , mMatCorr )) {
789+ LOG (debug) << " Failed final propagation to TOF radius" ;
790+ break ;
791+ }
792+
793+ float tgPhi = trkWork.getSnp () / std::sqrt ((1 .f - trkWork.getSnp ()) * (1 .f + trkWork.getSnp ()));
794+ auto dy = clTOF.getY () - trkWork.getY ();
795+ auto dz = clTOF.getZ () - trkWork.getZ ();
796+ if ((std::abs (dy) < param::MaxResid) && (std::abs (dz) < param::MaxResid) && (std::abs (trkWork.getY ()) < param::MaxY) && (std::abs (trkWork.getZ ()) < param::MaxZ) && (std::abs (tgPhi) < param::MaxTgSlp)) {
797+ mClRes .emplace_back (dy, dz, tgPhi, trkWork.getY (), trkWork.getZ (), 170 , clTOF.getCount ());
798+ trackData.clAvailTOF = 1 ;
799+ trackData.nExtDetResid ++;
800+ // NEED TO STORE: TOF X
801+ }
802+ break ;
803+ }
804+
805+ // add ITS residuals
806+ while (!stopPropagation) {
807+ auto trkWorkITS = trackData.par ; // this is ITS outer param
808+ auto nClITS = trkITS.getNumberOfClusters ();
809+ auto clEntryITS = trkITS.getFirstClusterEntry ();
810+ o2::its::GeometryTGeo* geom = GeometryTGeo::Instance ();
811+ for (int iCl = 0 ; iCl < nCl; iCl++) { // clusters are stored from outer to inner layers
812+ const auto & clsITS = mITSClustersArray [mITSTrackClusIdx [clEntry + iCl]];
813+ int chip = clsITS.getSensorID ();
814+ float chipX, chipAlpha;
815+ geom->getSensorXAlphaRefPlane (clsITS.getSensorID (), chipX, chipAlpha);
816+ if (!trkWorkITS.rotate (chipAlpha) || !propagator->PropagateToXBxByBz (trkWorkITS, chipX, mParams ->maxSnp , mParams ->maxStep , mMatCorr )) {
817+ LOGP (debug, " Failed final propagation to ITS X={} alpha={}" , chipX, chipAlpha);
818+ stopPropagation = true ;
819+ break ;
820+ }
821+ float tgPhi = trkWorkITS.getSnp () / std::sqrt ((1 .f - trkWorkITS.getSnp ()) * (1 .f + trkWorkITS.getSnp ()));
822+ auto dy = clsITS.getY () - trkWorkITS.getY ();
823+ auto dz = clsITS.getZ () - trkWorkITS.getZ ();
824+ if ((std::abs (dy) < param::MaxResid) && (std::abs (dz) < param::MaxResid) && (std::abs (trkWorkITS.getY ()) < param::MaxY) && (std::abs (trkWorkITS.getZ ()) < param::MaxZ) && (std::abs (tgPhi) < param::MaxTgSlp)) {
825+ mClRes .emplace_back (dy, dz, tgPhi, trkWorkITS.getY (), trkWorkITS.getZ (), 180 + geom->getLayer (clsITS.getSensorID ()), 0 );
826+ trackData.nExtDetResid ++;
827+ // NEED TO STORE: ITS X, alpha
828+ }
829+ }
830+ break ;
831+ }
723832 mTrackData .push_back (std::move (trackData));
724833 mGIDsSuccess .push_back (mGIDs [iSeed]);
725- mTrackDataCompact .emplace_back (mClRes .size () - nClValidated, nClValidated, mGIDs [iSeed].getSource ());
834+ mTrackDataCompact .emplace_back (mClRes .size () - nClValidated, nClValidated, mGIDs [iSeed].getSource ()); // RS Check
726835 if (mDumpTrackPoints ) {
727836 (*trackDataExtended).clIdx .setEntries (nClValidated);
728837 mTrackDataExtended .push_back (std::move (*trackDataExtended));
0 commit comments