@@ -105,8 +105,10 @@ class TrackMCStudy : public Task
105105 bool addMCParticle (const MCTrack& mctr, const o2::MCCompLabel& lb, TParticlePDG* pPDG = nullptr );
106106 bool acceptMCCharged (const MCTrack& tr, const o2::MCCompLabel& lb, int followDec = -1 );
107107 bool propagateToRefX (o2::track::TrackParCov& trcTPC, o2::track::TrackParCov& trcITS);
108- bool refitV0 (int i, o2::dataformats::V0& v0, const o2::globaltracking::RecoContainer& recoData);
108+ bool refitV0 (int i, o2::dataformats::V0& v0, o2::dataformats::V0Index& v0id, const o2::globaltracking::RecoContainer& recoData);
109+ bool fitV0 (GTrackID prID0, GTrackID prID1, int idPV, o2::dataformats::V0& v0, o2::dataformats::V0Index& v0id, const o2::globaltracking::RecoContainer& recoData);
109110 void updateTimeDependentParams (ProcessingContext& pc);
111+ o2::track::TrackParCov getCorrectedTPCTrack (const o2::tpc::TrackTPC& trTPC, float timeMUS);
110112 float getDCAYCut (float pt) const ;
111113
112114 const std::vector<o2::MCTrack>* mCurrMCTracks = nullptr ;
@@ -125,6 +127,7 @@ class TrackMCStudy : public Task
125127 bool mRecProcStage = false ; // < flag that the MC particle was added only at the stage of reco tracks processing
126128 int mNTPCOccBinLength = 0 ; // /< TPC occ. histo bin length in TBs
127129 float mNTPCOccBinLengthInv = -1 .f;
130+ float mVDriftTB = -1 .f;
128131 int mVerbose = 0 ;
129132 float mITSTimeBiasMUS = 0 .f;
130133 float mITSROFrameLengthMUS = 0 .f; // /< ITS RO frame in mus
@@ -145,7 +148,7 @@ class TrackMCStudy : public Task
145148 int pdg = 0 ;
146149 int daughterFirst = -1 ;
147150 int daughterLast = -1 ;
148- int foundSVID = - 1 ;
151+ std::vector< int > foundSVIdx ;
149152 };
150153 std::vector<std::vector<DecayRef>> mDecaysMaps ; // for every parent particle to watch, store its label and entries of 1st/last decay product labels in mDecProdLblPool
151154 std::unordered_map<o2::MCCompLabel, TrackFamily> mSelMCTracks ;
@@ -252,8 +255,6 @@ void TrackMCStudy::process(const o2::globaltracking::RecoContainer& recoData)
252255 auto vtxRefs = recoData.getPrimaryVertexMatchedTrackRefs (); // references from vertex to these track IDs
253256 auto prop = o2::base::Propagator::Instance ();
254257 int nv = vtxRefs.size ();
255- float vdriftTB = mTPCVDriftHelper .getVDriftObject ().getVDrift () * o2::tpc::ParameterElectronics::Instance ().ZbinWidth ; // VDrift expressed in cm/TimeBin
256- float itsBias = 0.5 * mITSROFrameLengthMUS + o2::itsmft::DPLAlpideParam<o2::detectors::DetID::ITS>::Instance ().roFrameBiasInBC * o2::constants::lhc::LHCBunchSpacingMUS; // ITS time is supplied in \mus as beginning of ROF
257258
258259 prepareITSData (recoData);
259260 loadTPCOccMap (recoData);
@@ -431,7 +432,7 @@ void TrackMCStudy::process(const o2::globaltracking::RecoContainer& recoData)
431432 pvLbl = pvvecLbl[iv];
432433 pvID = iv;
433434 if (pvLbl.isSet () && pvLbl.getEventID () < mMCVtVec .size ()) {
434- mMCVtVec [pvLbl.getEventID ()].recVtx .emplace_back (RecPV{pvvec[iv], pvLbl});
435+ mMCVtVec [pvLbl.getEventID ()].recVtx .emplace_back (RecPV{pvvec[iv], pvLbl, iv });
435436 }
436437 }
437438 const auto & vtref = vtxRefs[iv];
@@ -626,7 +627,7 @@ void TrackMCStudy::process(const o2::globaltracking::RecoContainer& recoData)
626627 }
627628 return s;
628629 };
629- for (int svID; svID < (int )v0s.size (); svID++) {
630+ for (int svID = 0 ; svID < (int )v0s.size (); svID++) {
630631 const auto & v0idx = v0s[svID];
631632 int nOKProngs = 0 , realMCSVID = -1 ;
632633 int8_t decTypeID = -1 ;
@@ -657,22 +658,32 @@ void TrackMCStudy::process(const o2::globaltracking::RecoContainer& recoData)
657658 }
658659 if (nOKProngs == v0idx.getNProngs ()) { // all prongs are from the decay of MC parent which deemed to be interesting, flag it
659660 LOGP (debug, " Decay {}/{} was found" , decTypeID, realMCSVID);
660- mDecaysMaps [decTypeID][realMCSVID].foundSVID = svID;
661+ mDecaysMaps [decTypeID][realMCSVID].foundSVIdx . push_back ( svID) ;
661662 }
662663 }
663664 }
664665
665666 // collect ITS/TPC cluster info for selected MC particles
666667 fillMCClusterInfo (recoData);
667668
669+ for (auto & mcVtx : mMCVtVec ) { // sort rec.vertices in mult. order
670+ std::sort (mcVtx.recVtx .begin (), mcVtx.recVtx .end (), [](const RecPV& lhs, const RecPV& rhs) {
671+ return lhs.pv .getNContributors () > rhs.pv .getNContributors ();
672+ });
673+ (*mDBGOut ) << " mcVtxTree" << " mcVtx=" << mcVtx << " \n " ;
674+ }
675+
668676 // single tracks
669677 for (auto & entry : mSelMCTracks ) {
670678 auto & trackFam = entry.second ;
671679 (*mDBGOut ) << " tracks" << " tr=" << trackFam << " \n " ;
672680 }
673681
674682 // decays
683+ std::vector<o2::dataformats::V0> foundV0s, testV0s;
684+ std::vector<o2::dataformats::V0Index> foundV0IDs, testV0IDs;
675685 std::vector<TrackFamily> decFam;
686+ std::vector<int > corrPVs;
676687 for (int id = 0 ; id < mNCheckDecays ; id++) {
677688 std::string decTreeName = fmt::format (" dec{}" , params.decayPDG [id]);
678689 for (const auto & dec : mDecaysMaps [id]) {
@@ -689,21 +700,51 @@ void TrackMCStudy::process(const o2::globaltracking::RecoContainer& recoData)
689700 decFam.push_back (dtFamily);
690701 }
691702 if (!skip) {
692- o2::dataformats::V0 v0;
693- if (dec.foundSVID >= 0 && !refitV0 (dec.foundSVID , v0, recoData)) {
694- v0.invalidate ();
703+ corrPVs.clear ();
704+ const auto & recPVs = mMCVtVec [dec.mother .getEventID ()].recVtx ;
705+ for (const auto & rpv : recPVs) {
706+ corrPVs.push_back (rpv.id );
707+ }
708+ foundV0s.clear ();
709+ foundV0s.resize (dec.foundSVIdx .size ());
710+ foundV0IDs.resize (dec.foundSVIdx .size ());
711+ testV0s.clear ();
712+ testV0IDs.clear ();
713+ int corrSVPV = -1 ;
714+ for (int ivf = 0 ; ivf < (int )dec.foundSVIdx .size (); ivf++) {
715+ if (!refitV0 (dec.foundSVIdx [ivf], foundV0s[ivf], foundV0IDs[ivf], recoData)) {
716+ foundV0s[ivf].invalidate ();
717+ }
718+ if (recPVs.size () && recoData.getV0sIdx ()[dec.foundSVIdx [ivf]].getVertexID () == recPVs[0 ].id ) {
719+ corrSVPV = ivf;
720+ }
721+ }
722+ if (decFam.size () == 2 && recPVs.size ()) {
723+
724+ for (const auto & pr0 : decFam[0 ].recTracks ) {
725+ if (pr0.gid .getSource () == GTrackID::ITS) { // don't consider ITS only tracks
726+ continue ;
727+ }
728+ for (const auto & pr1 : decFam[1 ].recTracks ) {
729+ if (pr1.gid .getSource () == GTrackID::ITS) { // don't consider ITS only tracks
730+ continue ;
731+ }
732+ auto & v0t = testV0s.emplace_back ();
733+ auto & v0tid = testV0IDs.emplace_back ();
734+ if (!fitV0 (pr0.gid , pr1.gid , recPVs[0 ].id , v0t, v0tid, recoData)) {
735+ v0t.invalidate ();
736+ }
737+ }
738+ }
695739 }
696- (*mDBGOut ) << decTreeName.c_str () << " pdgPar=" << dec.pdg << " trPar=" << dec.parent << " prod=" << decFam << " found=" << dec.foundSVID << " sv=" << v0 << " \n " ;
740+ (*mDBGOut ) << decTreeName.c_str () << " pdgPar=" << dec.pdg << " trPar=" << dec.parent << " prod=" << decFam << " foundSVIdx="
741+ << dec.foundSVIdx << " corrSVPV=" << corrSVPV << " corrPV=" << corrPVs
742+ << " foundSVID=" << foundV0IDs << " foundSV=" << foundV0s
743+ << " testSVID=" << testV0IDs << " testSV=" << testV0s
744+ << " \n " ;
697745 }
698746 }
699747 }
700-
701- for (auto & mcVtx : mMCVtVec ) { // sort rec.vertices in mult. order
702- std::sort (mcVtx.recVtx .begin (), mcVtx.recVtx .end (), [](const RecPV& lhs, const RecPV& rhs) {
703- return lhs.pv .getNContributors () > rhs.pv .getNContributors ();
704- });
705- (*mDBGOut ) << " mcVtxTree" << " mcVtx=" << mcVtx << " \n " ;
706- }
707748}
708749
709750void TrackMCStudy::processTPCTrackRefs ()
@@ -963,6 +1004,7 @@ void TrackMCStudy::finaliseCCDB(ConcreteDataMatcher& matcher, void* obj)
9631004 return ;
9641005 }
9651006 if (mTPCVDriftHelper .accountCCDBInputs (matcher, obj)) {
1007+ mVDriftTB = mTPCVDriftHelper .getVDriftObject ().getVDrift () * o2::tpc::ParameterElectronics::Instance ().ZbinWidth ; // VDrift expressed in cm/TimeBin
9661008 return ;
9671009 }
9681010 if (mTPCCorrMapsLoader .accountCCDBInputs (matcher, obj)) {
@@ -1151,27 +1193,38 @@ bool TrackMCStudy::addMCParticle(const MCTrack& mcPart, const o2::MCCompLabel& l
11511193 return true ;
11521194}
11531195
1154- bool TrackMCStudy::refitV0 (int i, o2::dataformats::V0& v0, const o2::globaltracking::RecoContainer& recoData)
1196+ bool TrackMCStudy::refitV0 (int i, o2::dataformats::V0& v0, o2::dataformats::V0Index& v0id, const o2::globaltracking::RecoContainer& recoData)
11551197{
11561198 const auto & id = recoData.getV0sIdx ()[i];
1157- auto seedP = recoData.getTrackParam (id.getProngID (0 ));
1158- auto seedN = recoData.getTrackParam (id.getProngID (1 ));
1159- bool isTPConly = (id.getProngID (0 ).getSource () == GTrackID::TPC) || (id.getProngID (1 ).getSource () == GTrackID::TPC);
1199+ return fitV0 (id.getProngID (0 ), id.getProngID (1 ), id.getVertexID (), v0, v0id, recoData);
1200+ }
1201+
1202+ bool TrackMCStudy::fitV0 (GTrackID prID0, GTrackID prID1, int idPV, o2::dataformats::V0& v0, o2::dataformats::V0Index& v0id, const o2::globaltracking::RecoContainer& recoData)
1203+ {
1204+ const auto & pv = recoData.getPrimaryVertex (idPV);
1205+
1206+ auto seedP = recoData.getTrackParam (prID0);
1207+ auto seedN = recoData.getTrackParam (prID1);
1208+ bool isTPConlyP = (prID0.getSource () == GTrackID::TPC), isTPConlyN = (prID1.getSource () == GTrackID::TPC), isTPConly = isTPConlyP || isTPConlyN;
11601209 const auto & svparam = o2::vertexing::SVertexerParams::Instance ();
11611210 if (svparam.mTPCTrackPhotonTune && isTPConly) {
11621211 mFitterV0 .setMaxDZIni (svparam.mTPCTrackMaxDZIni );
11631212 mFitterV0 .setMaxDXYIni (svparam.mTPCTrackMaxDXYIni );
11641213 mFitterV0 .setMaxChi2 (svparam.mTPCTrackMaxChi2 );
11651214 mFitterV0 .setCollinear (true );
11661215 }
1167- int nCand = mFitterV0 .process (seedP, seedN);
1216+ int nCand = mFitterV0 .process (isTPConlyP ? getCorrectedTPCTrack (recoData.getTPCTrack (prID0), pv.getTimeStamp ().getTimeStamp ()) : recoData.getTrackParam (prID0),
1217+ isTPConlyN ? getCorrectedTPCTrack (recoData.getTPCTrack (prID1), pv.getTimeStamp ().getTimeStamp ()) : recoData.getTrackParam (prID1));
11681218 if (svparam.mTPCTrackPhotonTune && isTPConly) { // restore
11691219 // Reset immediately to the defaults
11701220 mFitterV0 .setMaxDZIni (svparam.maxDZIni );
11711221 mFitterV0 .setMaxDXYIni (svparam.maxDXYIni );
11721222 mFitterV0 .setMaxChi2 (svparam.maxChi2 );
11731223 mFitterV0 .setCollinear (false );
11741224 }
1225+ v0id.setVertexID (idPV);
1226+ v0id.setProngID (0 , prID0);
1227+ v0id.setProngID (1 , prID1);
11751228 if (nCand == 0 ) { // discard this pair
11761229 return false ;
11771230 }
@@ -1186,7 +1239,6 @@ bool TrackMCStudy::refitV0(int i, o2::dataformats::V0& v0, const o2::globaltrack
11861239 trNProp.getPxPyPzGlo (pN);
11871240 std::array<float , 3 > pV0 = {pP[0 ] + pN[0 ], pP[1 ] + pN[1 ], pP[2 ] + pN[2 ]};
11881241 auto p2V0 = pV0[0 ] * pV0[0 ] + pV0[1 ] * pV0[1 ] + pV0[2 ] * pV0[2 ];
1189- const auto & pv = recoData.getPrimaryVertex (id.getVertexID ());
11901242 const auto v0XYZ = mFitterV0 .getPCACandidatePos (cand);
11911243 float dx = v0XYZ[0 ] - pv.getX (), dy = v0XYZ[1 ] - pv.getY (), dz = v0XYZ[2 ] - pv.getZ (), prodXYZv0 = dx * pV0[0 ] + dy * pV0[1 ] + dz * pV0[2 ];
11921244 float cosPA = prodXYZv0 / std::sqrt ((dx * dx + dy * dy + dz * dz) * p2V0);
@@ -1229,6 +1281,19 @@ void TrackMCStudy::loadTPCOccMap(const o2::globaltracking::RecoContainer& recoDa
12291281 }
12301282}
12311283
1284+ o2::track::TrackParCov TrackMCStudy::getCorrectedTPCTrack (const o2::tpc::TrackTPC& trTPC, float timeMUS)
1285+ {
1286+ const float MUS2TPCBin = 1 .f / (8 * o2::constants::lhc::LHCBunchSpacingMUS);
1287+ o2::track::TrackParCov tr{trTPC};
1288+ if (trTPC.hasBothSidesClusters () || timeMUS < -1e6 ) {
1289+ return tr;
1290+ }
1291+ float tTB = timeMUS * MUS2TPCBin;
1292+ float dDrift = (tTB - trTPC.getTime0 ()) * mVDriftTB ;
1293+ tr.setZ (trTPC.getZ () + (trTPC.hasASideClustersOnly () ? dDrift : -dDrift));
1294+ return tr;
1295+ }
1296+
12321297DataProcessorSpec getTrackMCStudySpec (GTrackID::mask_t srcTracks, GTrackID::mask_t srcClusters, const o2::tpc::CorrectionMapsLoaderGloOpts& sclOpts, bool checkSV)
12331298{
12341299 std::vector<OutputSpec> outputs;
0 commit comments