From 64f155985bb57e1897607dd9981ffeca5d6c865d Mon Sep 17 00:00:00 2001 From: noferini <9963644+noferini@users.noreply.github.com> Date: Sun, 19 Nov 2023 12:23:34 +0100 Subject: [PATCH] TOF matching multi-threaded --- .../include/GlobalTracking/MatchTOF.h | 28 +- Detectors/GlobalTracking/src/MatchTOF.cxx | 407 ++++++++++++------ .../GlobalTrackingWorkflow/TOFMatcherSpec.h | 2 +- .../src/TOFMatcherSpec.cxx | 8 +- .../src/tof-matcher-workflow.cxx | 5 +- 5 files changed, 302 insertions(+), 148 deletions(-) diff --git a/Detectors/GlobalTracking/include/GlobalTracking/MatchTOF.h b/Detectors/GlobalTracking/include/GlobalTracking/MatchTOF.h index 0e19b15d9a401..607ad27eb3c20 100644 --- a/Detectors/GlobalTracking/include/GlobalTracking/MatchTOF.h +++ b/Detectors/GlobalTracking/include/GlobalTracking/MatchTOF.h @@ -201,10 +201,14 @@ class MatchTOF void storeMatchable(bool val = true) { mStoreMatchable = val; } + void setNlanes(int lanes) { mNlanes = lanes; } + private: bool prepareFITData(); int prepareInteractionTimes(); bool prepareTPCData(); + void propagateTPCTracks(int sec); + void propagateConstrTracks(int sec); void addTPCSeed(const o2::tpc::TrackTPC& _tr, o2::dataformats::GlobalTrackID srcGID, float time0, float terr); void addITSTPCSeed(const o2::dataformats::TrackTPCITS& _tr, o2::dataformats::GlobalTrackID srcGID, float time0, float terr); void addTRDSeed(const o2::trd::TrackTRD& _tr, o2::dataformats::GlobalTrackID srcGID, float time0, float terr); @@ -215,7 +219,7 @@ class MatchTOF void doMatching(int sec); void doMatchingForTPC(int sec); - void selectBestMatches(); + void selectBestMatches(int sec); void BestMatches(std::vector& matchedTracksPairs, std::vector* matchedTracks, std::vector* matchedTracksIndex, int* matchedClustersIndex, const gsl::span& FITRecPoints, const std::vector& TOFClusWork, const std::vector* TracksWork, std::vector& CalibInfoTOF, unsigned long Timestamp, bool MCTruthON, const o2::dataformats::MCTruthContainer* TOFClusLabels, const std::vector* TracksLblWork, std::vector* OutTOFLabels, float calibMaxChi2); void BestMatchesHP(std::vector& matchedTracksPairs, std::vector* matchedTracks, std::vector* matchedTracksIndex, int* matchedClustersIndex, const gsl::span& FITRecPoints, const std::vector& TOFClusWork, std::vector& CalibInfoTOF, unsigned long Timestamp, bool MCTruthON, const o2::dataformats::MCTruthContainer* TOFClusLabels, const std::vector* TracksLblWork, std::vector* OutTOFLabels); bool propagateToRefX(o2::track::TrackParCov& trc, float xRef /*in cm*/, float stepInCm /*in cm*/, o2::track::TrackLTIntegral& intLT); @@ -232,6 +236,8 @@ class MatchTOF const o2::globaltracking::RecoContainer* mRecoCont = nullptr; o2::InteractionRecord mStartIR{0, 0}; ///< IR corresponding to the start of the TF + int mNlanes = 3; ///< for multi-threading in matching + // TOF matching params (work in progress) const MatchTOFParams* mMatchParams = nullptr; @@ -299,22 +305,22 @@ class MatchTOF /// <<<----- /// mTracksWork[trkType::SIZE]; /// mTracksLblWork[trkType::SIZE]; /// mLTinfos[trkType::SIZE]; /// mTrackGid[trkType::SIZE]; /// mTracksWork[o2::constants::math::NSectors][trkType::SIZE]; ///< track params prepared for matching + time value + std::vector mTracksLblWork[o2::constants::math::NSectors][trkType::SIZE]; ///< TPCITS track labels + std::vector mLTinfos[o2::constants::math::NSectors][trkType::SIZE]; ///< expected times and others + std::vector mTrackGid[o2::constants::math::NSectors][trkType::SIZE]; ///< expected times and others ///< per sector indices of track entry in mTracksWork std::array, o2::constants::math::NSectors> mTracksSectIndexCache[trkType::SIZE]; + std::array, o2::constants::math::NSectors> mTracksSeed[trkType::SIZE]; - std::vector mExtraTPCFwdTime; /// mTOFClusWork; /// mSideTPC; /// mExtraTPCFwdTime[o2::constants::math::NSectors]; ///< track extra params for TPC tracks: Fws Max time + std::vector mTOFClusWork; ///< track params prepared for matching + std::vector mSideTPC[o2::constants::math::NSectors]; ///< track side for TPC tracks ///< per sector indices of TOF cluster entry in mTOFClusWork std::array, o2::constants::math::NSectors> mTOFClusSectIndexCache; - /// mMatchedTracksPairs; + ///< array of track-TOFCluster pairs from the matching std::vector mMatchedTracksPairsSec[o2::constants::math::NSectors]; /// mMatchedTracks[trkType::SIZEALL]; // this is the output of the matching -> UNCONS, CONSTR std::vector mOutTOFLabels[trkType::SIZEALL]; ///< TOF label of matched tracks - std::vector mMatchedTracksIndex[trkType::SIZE]; // vector of indexes of the tracks to be matched + std::vector mMatchedTracksIndex[o2::constants::math::NSectors][trkType::SIZE]; // vector of indexes of the tracks to be matched int mNumOfClusters; // number of clusters to be matched int* mMatchedClustersIndex = nullptr; //[mNumOfClusters] diff --git a/Detectors/GlobalTracking/src/MatchTOF.cxx b/Detectors/GlobalTracking/src/MatchTOF.cxx index 3283f14b0bdde..0eb9cf430beec 100644 --- a/Detectors/GlobalTracking/src/MatchTOF.cxx +++ b/Detectors/GlobalTracking/src/MatchTOF.cxx @@ -46,6 +46,10 @@ #include "DataFormatsGlobalTracking/RecoContainerCreateTracksVariadic.h" #include "TOFBase/Utils.h" +#ifdef WITH_OPENMP +#include +#endif + using namespace o2::globaltracking; using evGIdx = o2::dataformats::EvIndex; using trkType = o2::dataformats::MatchInfoTOFReco::TrackType; @@ -84,23 +88,24 @@ void MatchTOF::run(const o2::globaltracking::RecoContainer& inp, unsigned long f mOutTOFLabels[i].clear(); } - for (int i = 0; i < trkType::SIZE; i++) { - mTracksWork[i].clear(); - mTrackGid[i].clear(); - } for (int it = 0; it < trkType::SIZE; it++) { - mMatchedTracksIndex[it].clear(); - mLTinfos[it].clear(); - if (mMCTruthON) { - mTracksLblWork[it].clear(); - } - for (int sec = o2::constants::math::NSectors; sec--;) { + for (int sec = o2::constants::math::NSectors - 1; sec > -1; sec--) { + mMatchedTracksIndex[sec][it].clear(); + mTracksWork[sec][it].clear(); + mTrackGid[sec][it].clear(); + mLTinfos[sec][it].clear(); + if (mMCTruthON) { + mTracksLblWork[sec][it].clear(); + } mTracksSectIndexCache[it][sec].clear(); + mTracksSeed[it][sec].clear(); } } - mSideTPC.clear(); - mExtraTPCFwdTime.clear(); + for (int sec = o2::constants::math::NSectors - 1; sec > -1; sec--) { + mSideTPC[sec].clear(); + mExtraTPCFwdTime[sec].clear(); + } mTimerTot.Start(); bool isPrepareTOFClusters = prepareTOFClusters(); @@ -127,32 +132,46 @@ void MatchTOF::run(const o2::globaltracking::RecoContainer& inp, unsigned long f mTimerTot.Start(); std::array nMatches = {0}; - for (int sec = o2::constants::math::NSectors; sec--;) { - mMatchedTracksPairs.clear(); // new sector - LOG(debug) << "Doing matching for sector " << sec << "..."; - if (mIsITSTPCused || mIsTPCTRDused || mIsITSTPCTRDused) { - mTimerMatchITSTPC.Start(sec == o2::constants::math::NSectors - 1); + // run matching (this can be multi-thread) + mTimerMatchITSTPC.Start(); + + for (int sec = o2::constants::math::NSectors - 1; sec > -1; sec--) { + mMatchedTracksPairsSec[sec].clear(); // new sector + } + + o2::tof::Geo::Init(); + + if (mIsITSTPCused || mIsTPCTRDused || mIsITSTPCTRDused) { +#ifdef WITH_OPENMP +#pragma omp parallel for schedule(dynamic) num_threads(mNlanes) +#endif + for (int sec = o2::constants::math::NSectors - 1; sec > -1; sec--) { doMatching(sec); - mTimerMatchITSTPC.Stop(); } - if (mIsTPCused) { - mTimerMatchTPC.Start(sec == o2::constants::math::NSectors - 1); + } + mTimerMatchITSTPC.Stop(); + + mTimerMatchTPC.Start(); + if (mIsTPCused) { +#ifdef WITH_OPENMP +#pragma omp parallel for schedule(dynamic) num_threads(mNlanes) +#endif + for (int sec = o2::constants::math::NSectors - 1; sec > -1; sec--) { doMatchingForTPC(sec); - mTimerMatchTPC.Stop(); } + } + mTimerMatchTPC.Stop(); + // finalize + for (int sec = o2::constants::math::NSectors - 1; sec > -1; sec--) { if (mStoreMatchable) { - // fill per sector - mMatchedTracksPairsSec[sec].clear(); - mMatchedTracksPairsSec[sec].insert(mMatchedTracksPairsSec[sec].end(), mMatchedTracksPairs.begin(), mMatchedTracksPairs.end()); - // if MC check if good or fake matches if (mMCTruthON) { for (auto& matchingPair : mMatchedTracksPairsSec[sec]) { int trkType = (int)matchingPair.getTrackType(); int itrk = matchingPair.getIdLocal(); const auto& labelsTOF = mTOFClusLabels->getLabels(matchingPair.getTOFClIndex()); - const auto& labelTrack = mTracksLblWork[trkType][itrk]; + const auto& labelTrack = mTracksLblWork[sec][trkType][itrk]; // we have not found the track label among those associated to the TOF cluster --> fake match! We will associate the label of the main channel, but negative bool fake = true; @@ -169,11 +188,11 @@ void MatchTOF::run(const o2::globaltracking::RecoContainer& inp, unsigned long f } LOG(debug) << "...done. Now check the best matches"; - nMatches[sec] = mMatchedTracksPairs.size(); - selectBestMatches(); + nMatches[sec] = mMatchedTracksPairsSec[sec].size(); + selectBestMatches(sec); } std::string nMatchesStr = "Number of pairs matched per sector: "; - for (int sec = o2::constants::math::NSectors; sec--;) { + for (int sec = o2::constants::math::NSectors - 1; sec > -1; sec--) { nMatchesStr += fmt::format("{} : {} ; ", sec, nMatches[sec]); } LOG(info) << nMatchesStr; @@ -361,24 +380,85 @@ bool MatchTOF::prepareTPCData() }; mRecoCont->createTracksVariadic(creator); +#ifdef WITH_OPENMP +#pragma omp parallel for schedule(dynamic) num_threads(mNlanes) +#endif + for (int sec = o2::constants::math::NSectors - 1; sec > -1; sec--) { + if (mIsTPCused) { + propagateTPCTracks(sec); + } + if (mIsITSTPCused || mIsTPCTRDused || mIsITSTPCTRDused) { + propagateConstrTracks(sec); + } + } + + // re-assign tracks which change sector (no multi-threading) + std::array globalPos; + for (int sec = o2::constants::math::NSectors - 1; sec > -1; sec--) { + if (mIsTPCused) { + for (auto& it : mTracksSeed[trkType::UNCONS][sec]) { + auto& pair = mTracksWork[sec][trkType::UNCONS][it]; + auto& trc = pair.first; + trc.getXYZGlo(globalPos); + int sector = o2::math_utils::angle2Sector(TMath::ATan2(globalPos[1], globalPos[0])); + + int itnew = mTracksWork[sector][trkType::UNCONS].size(); + + mSideTPC[sector].push_back(mSideTPC[sec][it]); + mExtraTPCFwdTime[sector].push_back(mExtraTPCFwdTime[sec][it]); + mTracksWork[sector][trkType::UNCONS].emplace_back(pair); + mTrackGid[sector][trkType::UNCONS].emplace_back(mTrackGid[sec][trkType::UNCONS][it]); + + if (mMCTruthON) { + mTracksLblWork[sector][trkType::UNCONS].emplace_back(mTracksLblWork[sec][trkType::UNCONS][it]); + } + mLTinfos[sector][trkType::UNCONS].emplace_back(mLTinfos[sec][trkType::UNCONS][it]); + mTracksSectIndexCache[trkType::UNCONS][sector].push_back(itnew); + } + } + + for (auto& it : mTracksSeed[trkType::CONSTR][sec]) { + auto& pair = mTracksWork[sec][trkType::CONSTR][it]; + auto& trc = pair.first; + trc.getXYZGlo(globalPos); + int sector = o2::math_utils::angle2Sector(TMath::ATan2(globalPos[1], globalPos[0])); + + int itnew = mTracksWork[sector][trkType::CONSTR].size(); + + mTracksWork[sector][trkType::CONSTR].emplace_back(pair); + mTrackGid[sector][trkType::CONSTR].emplace_back(mTrackGid[sec][trkType::CONSTR][it]); + + if (mMCTruthON) { + mTracksLblWork[sector][trkType::CONSTR].emplace_back(mTracksLblWork[sec][trkType::CONSTR][it]); + } + mLTinfos[sector][trkType::CONSTR].emplace_back(mLTinfos[sec][trkType::CONSTR][it]); + mTracksSectIndexCache[trkType::CONSTR][sector].push_back(itnew); + } + } + for (int it = 0; it < trkType::SIZE; it++) { - mMatchedTracksIndex[it].resize(mTracksWork[it].size()); - std::fill(mMatchedTracksIndex[it].begin(), mMatchedTracksIndex[it].end(), -1); // initializing all to -1 + for (int sec = o2::constants::math::NSectors - 1; sec > -1; sec--) { + mMatchedTracksIndex[sec][it].resize(mTracksWork[sec][it].size()); + std::fill(mMatchedTracksIndex[sec][it].begin(), mMatchedTracksIndex[sec][it].end(), -1); // initializing all to -1 + } } if (mIsTPCused) { LOG(debug) << "Number of UNCONSTRAINED tracks that failed to be propagated to TOF = " << mNotPropagatedToTOF[trkType::UNCONS]; // sort tracks in each sector according to their time (increasing in time) - for (int sec = o2::constants::math::NSectors; sec--;) { +#ifdef WITH_OPENMP +#pragma omp parallel for schedule(dynamic) num_threads(mNlanes) +#endif + for (int sec = o2::constants::math::NSectors - 1; sec > -1; sec--) { auto& indexCache = mTracksSectIndexCache[trkType::UNCONS][sec]; LOG(debug) << "Sorting sector" << sec << " | " << indexCache.size() << " tracks"; if (!indexCache.size()) { continue; } - std::sort(indexCache.begin(), indexCache.end(), [this](int a, int b) { - auto& trcA = mTracksWork[trkType::UNCONS][a].second; - auto& trcB = mTracksWork[trkType::UNCONS][b].second; + std::sort(indexCache.begin(), indexCache.end(), [this, sec](int a, int b) { + auto& trcA = mTracksWork[sec][trkType::UNCONS][a].second; + auto& trcB = mTracksWork[sec][trkType::UNCONS][b].second; return ((trcA.getTimeStamp() - trcA.getTimeStampError()) - (trcB.getTimeStamp() - trcB.getTimeStampError()) < 0.); }); } // loop over tracks of single sector @@ -387,15 +467,18 @@ bool MatchTOF::prepareTPCData() LOG(debug) << "Number of CONSTRAINED tracks that failed to be propagated to TOF = " << mNotPropagatedToTOF[trkType::CONSTR]; // sort tracks in each sector according to their time (increasing in time) - for (int sec = o2::constants::math::NSectors; sec--;) { +#ifdef WITH_OPENMP +#pragma omp parallel for schedule(dynamic) num_threads(mNlanes) +#endif + for (int sec = o2::constants::math::NSectors - 1; sec > -1; sec--) { auto& indexCache = mTracksSectIndexCache[trkType::CONSTR][sec]; LOG(debug) << "Sorting sector" << sec << " | " << indexCache.size() << " tracks"; if (!indexCache.size()) { continue; } - std::sort(indexCache.begin(), indexCache.end(), [this](int a, int b) { - auto& trcA = mTracksWork[trkType::CONSTR][a].second; - auto& trcB = mTracksWork[trkType::CONSTR][b].second; + std::sort(indexCache.begin(), indexCache.end(), [this, sec](int a, int b) { + auto& trcA = mTracksWork[sec][trkType::CONSTR][a].second; + auto& trcB = mTracksWork[sec][trkType::CONSTR][b].second; return ((trcA.getTimeStamp() - mSigmaTimeCut * trcA.getTimeStampError()) - (trcB.getTimeStamp() - mSigmaTimeCut * trcB.getTimeStampError()) < 0.); }); } // loop over tracks of single sector @@ -403,6 +486,94 @@ bool MatchTOF::prepareTPCData() return true; } + +//______________________________________________ +void MatchTOF::propagateTPCTracks(int sec) +{ + auto& trkWork = mTracksWork[sec][trkType::UNCONS]; + + for (int it = 0; it < trkWork.size(); it++) { + o2::track::TrackParCov& trc = trkWork[it].first; + + o2::track::TrackLTIntegral& intLT0 = mLTinfos[sec][trkType::UNCONS][it]; + + const auto& trackTune = o2::globaltracking::TrackTuneParams::Instance(); + if (!trackTune.sourceLevelTPC) { // correct only if TPC track was not corrected at the source level + if (trackTune.useTPCOuterCorr) { + trc.updateParams(trackTune.tpcParOuter); + } + if (trackTune.tpcCovOuterType != o2::globaltracking::TrackTuneParams::AddCovType::Disable) { // only TRD-refitted track have cov.matrix already man> + trc.updateCov(trackTune.tpcCovOuter, trackTune.tpcCovOuterType == o2::globaltracking::TrackTuneParams::AddCovType::WithCorrelations); + } + } + if (!propagateToRefXWithoutCov(trc, mXRef, 10, mBz)) { // we first propagate to 371 cm without considering the covariance matri + mNotPropagatedToTOF[trkType::UNCONS]++; + continue; + } + + if (trc.getX() < o2::constants::geom::XTPCOuterRef - 1.) { + if (!propagateToRefX(trc, o2::constants::geom::XTPCOuterRef, 10, intLT0) || TMath::Abs(trc.getZ()) > Geo::MAXHZTOF) { // we check that the propagat> + mNotPropagatedToTOF[trkType::UNCONS]++; + continue; + } + } + + o2::base::Propagator::Instance()->estimateLTFast(intLT0, trc); + + // the "rough" propagation worked; now we can propagate considering also the cov matrix + if (!propagateToRefX(trc, mXRef, 2, intLT0)) { // || TMath::Abs(trc.getZ()) > Geo::MAXHZTOF) { // we check that the propagation with the cov matrix w> + mNotPropagatedToTOF[trkType::UNCONS]++; + continue; + } + + // printf("time0 %f -> %f (diff = %f, err = %f)\n",trackTime0, time0, trackTime0 - time0, terr); + // printf("time errors %f,%f -> %f,%f\n",(_tr.getDeltaTBwd() + 5) * mTPCTBinMUS,(_tr.getDeltaTFwd() + 5) * mTPCTBinMUS,trackTime0 - time0 + terr, ti> + + std::array globalPos; + trc.getXYZGlo(globalPos); + int sector = o2::math_utils::angle2Sector(TMath::ATan2(globalPos[1], globalPos[0])); + + if (sector == sec) { + mTracksSectIndexCache[trkType::UNCONS][sector].push_back(it); + } else { + mTracksSeed[trkType::UNCONS][sec].push_back(it); // to be moved to another sector + } + } +} +//______________________________________________ +void MatchTOF::propagateConstrTracks(int sec) +{ + std::array globalPos; + + auto& trkWork = mTracksWork[sec][trkType::CONSTR]; + + for (int it = 0; it < trkWork.size(); it++) { + o2::track::TrackParCov& trc = trkWork[it].first; + o2::track::TrackLTIntegral& intLT0 = mLTinfos[sec][trkType::CONSTR][it]; + + // propagate to matching Xref + if (!propagateToRefXWithoutCov(trc, mXRef, 2, mBz)) { // we first propagate to 371 cm without considering the covariance matrix + mNotPropagatedToTOF[trkType::CONSTR]++; + continue; + } + + // the "rough" propagation worked; now we can propagate considering also the cov matrix + if (!propagateToRefX(trc, mXRef, 2, intLT0) || TMath::Abs(trc.getZ()) > Geo::MAXHZTOF) { // we check that the propagation with the cov matrix worked;> + mNotPropagatedToTOF[trkType::CONSTR]++; + continue; + } + + trc.getXYZGlo(globalPos); + + int sector = o2::math_utils::angle2Sector(TMath::ATan2(globalPos[1], globalPos[0])); + + if (sector == sec) { + mTracksSectIndexCache[trkType::CONSTR][sector].push_back(it); + } else { + mTracksSeed[trkType::CONSTR][sec].push_back(it); // to be moved to another sector + } + } +} //______________________________________________ void MatchTOF::addITSTPCSeed(const o2::dataformats::TrackTPCITS& _tr, o2::dataformats::GlobalTrackID srcGID, float time0, float terr) { @@ -418,44 +589,19 @@ void MatchTOF::addITSTPCSeed(const o2::dataformats::TrackTPCITS& _tr, o2::datafo void MatchTOF::addConstrainedSeed(o2::track::TrackParCov& trc, o2::dataformats::GlobalTrackID srcGID, o2::track::TrackLTIntegral intLT0, timeEst timeMUS) { std::array globalPos; - // current track index - int it = mTracksWork[trkType::CONSTR].size(); - - // propagate to matching Xref trc.getXYZGlo(globalPos); - LOG(debug) << "Global coordinates Before propagating to 371 cm: globalPos[0] = " << globalPos[0] << ", globalPos[1] = " << globalPos[1] << ", globalPos[2] = " << globalPos[2]; - LOG(debug) << "Radius xy Before propagating to 371 cm = " << TMath::Sqrt(globalPos[0] * globalPos[0] + globalPos[1] * globalPos[1]); - LOG(debug) << "Radius xyz Before propagating to 371 cm = " << TMath::Sqrt(globalPos[0] * globalPos[0] + globalPos[1] * globalPos[1] + globalPos[2] * globalPos[2]); - if (!propagateToRefXWithoutCov(trc, mXRef, 2, mBz)) { // we first propagate to 371 cm without considering the covariance matrix - mNotPropagatedToTOF[trkType::CONSTR]++; - return; - } - - // the "rough" propagation worked; now we can propagate considering also the cov matrix - if (!propagateToRefX(trc, mXRef, 2, intLT0) || TMath::Abs(trc.getZ()) > Geo::MAXHZTOF) { // we check that the propagation with the cov matrix worked; CHECK: can it happen that it does not if the prop> - mNotPropagatedToTOF[trkType::CONSTR]++; - return; - } - - trc.getXYZGlo(globalPos); - - LOG(debug) << "Global coordinates After propagating to 371 cm: globalPos[0] = " << globalPos[0] << ", globalPos[1] = " << globalPos[1] << ", globalPos[2] = " << globalPos[2]; - LOG(debug) << "Radius xy After propagating to 371 cm = " << TMath::Sqrt(globalPos[0] * globalPos[0] + globalPos[1] * globalPos[1]); - LOG(debug) << "Radius xyz After propagating to 371 cm = " << TMath::Sqrt(globalPos[0] * globalPos[0] + globalPos[1] * globalPos[1] + globalPos[2] * globalPos[2]); - LOG(debug) << "The track will go to sector " << o2::math_utils::angle2Sector(TMath::ATan2(globalPos[1], globalPos[0])); int sector = o2::math_utils::angle2Sector(TMath::ATan2(globalPos[1], globalPos[0])); // create working copy of track param - mTracksWork[trkType::CONSTR].emplace_back(std::make_pair(trc, timeMUS)); - mTrackGid[trkType::CONSTR].emplace_back(srcGID); - mLTinfos[trkType::CONSTR].emplace_back(intLT0); + mTracksWork[sector][trkType::CONSTR].emplace_back(std::make_pair(trc, timeMUS)); + mTrackGid[sector][trkType::CONSTR].emplace_back(srcGID); + mLTinfos[sector][trkType::CONSTR].emplace_back(intLT0); if (mMCTruthON) { - mTracksLblWork[trkType::CONSTR].emplace_back(mRecoCont->getTPCITSTrackMCLabel(srcGID)); + mTracksLblWork[sector][trkType::CONSTR].emplace_back(mRecoCont->getTPCITSTrackMCLabel(srcGID)); } - mTracksSectIndexCache[trkType::CONSTR][sector].push_back(it); //delete trc; // Check: is this needed? } //______________________________________________ void MatchTOF::addTRDSeed(const o2::trd::TrackTRD& _tr, o2::dataformats::GlobalTrackID srcGID, float time0, float terr) @@ -471,7 +617,6 @@ void MatchTOF::addTRDSeed(const o2::trd::TrackTRD& _tr, o2::dataformats::GlobalT auto trc = _tr.getOuterParam(); o2::track::TrackLTIntegral intLT0 = _tr.getLTIntegralOut(); - ; // empty for the moment // o2::dataformats::TimeStampWithError timeEst ts(time0, terr + mExtraTimeToleranceTRD); @@ -485,9 +630,6 @@ void MatchTOF::addTPCSeed(const o2::tpc::TrackTPC& _tr, o2::dataformats::GlobalT std::array globalPos; - // current track index - int it = mTracksWork[trkType::UNCONS].size(); - // create working copy of track param timeEst timeInfo; // set @@ -496,65 +638,66 @@ void MatchTOF::addTPCSeed(const o2::tpc::TrackTPC& _tr, o2::dataformats::GlobalT extraErr = 100; } - auto trc = _tr.getOuterParam(); - const auto& trackTune = o2::globaltracking::TrackTuneParams::Instance(); - if (!trackTune.sourceLevelTPC) { // correct only if TPC track was not corrected at the source level - if (trackTune.useTPCOuterCorr) { - trc.updateParams(trackTune.tpcParOuter); - } - if (trackTune.tpcCovOuterType != o2::globaltracking::TrackTuneParams::AddCovType::Disable) { // only TRD-refitted track have cov.matrix already manipulated - trc.updateCov(trackTune.tpcCovOuter, trackTune.tpcCovOuterType == o2::globaltracking::TrackTuneParams::AddCovType::WithCorrelations); - } - } - if (!propagateToRefXWithoutCov(trc, mXRef, 10, mBz)) { // we first propagate to 371 cm without considering the covariance matri - mNotPropagatedToTOF[trkType::UNCONS]++; - return; - } - - o2::track::TrackLTIntegral intLT0; //mTPCTracksWork.back().getLTIntegralOut(); // we get the integrated length from TPC-ITC outward propagation - // compute track length up to now - o2::base::Propagator::Instance()->estimateLTFast(intLT0, trc); - - if (trc.getX() < o2::constants::geom::XTPCOuterRef - 1.) { - if (!propagateToRefX(trc, o2::constants::geom::XTPCOuterRef, 10, intLT0) || TMath::Abs(trc.getZ()) > Geo::MAXHZTOF) { // we check that the propagation with the cov matrix worked; CHECK: can it happ - mNotPropagatedToTOF[trkType::UNCONS]++; - return; - } - } - - // the "rough" propagation worked; now we can propagate considering also the cov matrix - if (!propagateToRefX(trc, mXRef, 2, intLT0)) { // || TMath::Abs(trc.getZ()) > Geo::MAXHZTOF) { // we check that the propagation with the cov matrix worked; CHECK: can it happen that it does not if the prop> - mNotPropagatedToTOF[trkType::UNCONS]++; - return; - } - float trackTime0 = _tr.getTime0() * mTPCTBinMUS; - timeInfo.setTimeStampError((_tr.getDeltaTBwd() + 5) * mTPCTBinMUS + extraErr); - mExtraTPCFwdTime.push_back((_tr.getDeltaTFwd() + 5) * mTPCTBinMUS + extraErr); - // timeInfo.setTimeStampError(trackTime0 - time0 + terr + extraErr); - // mExtraTPCFwdTime.push_back(time0 + terr - trackTime0 + extraErr); - timeInfo.setTimeStamp(trackTime0); - mSideTPC.push_back(_tr.hasASideClustersOnly() ? 1 : (_tr.hasCSideClustersOnly() ? -1 : 0)); - - // printf("time0 %f -> %f (diff = %f, err = %f)\n",trackTime0, time0, trackTime0 - time0, terr); - // printf("time errors %f,%f -> %f,%f\n",(_tr.getDeltaTBwd() + 5) * mTPCTBinMUS,(_tr.getDeltaTFwd() + 5) * mTPCTBinMUS,trackTime0 - time0 + terr, time0 + terr - trackTime0); + auto trc = _tr.getOuterParam(); trc.getXYZGlo(globalPos); + int sector = o2::math_utils::angle2Sector(TMath::ATan2(globalPos[1], globalPos[0])); - mTracksWork[trkType::UNCONS].emplace_back(std::make_pair(trc, timeInfo)); - mTrackGid[trkType::UNCONS].emplace_back(srcGID); + mSideTPC[sector].push_back(_tr.hasASideClustersOnly() ? 1 : (_tr.hasCSideClustersOnly() ? -1 : 0)); + mExtraTPCFwdTime[sector].push_back((_tr.getDeltaTFwd() + 5) * mTPCTBinMUS + extraErr); + // mExtraTPCFwdTime[sector].push_back(time0 + terr - trackTime0 + extraErr); + mTracksWork[sector][trkType::UNCONS].emplace_back(std::make_pair(trc, timeInfo)); + mTrackGid[sector][trkType::UNCONS].emplace_back(srcGID); if (mMCTruthON) { - mTracksLblWork[trkType::UNCONS].emplace_back(mRecoCont->getTPCTrackMCLabel(srcGID)); + mTracksLblWork[sector][trkType::UNCONS].emplace_back(mRecoCont->getTPCTrackMCLabel(srcGID)); } - mLTinfos[trkType::UNCONS].emplace_back(intLT0); + o2::track::TrackLTIntegral intLT0; // mTPCTracksWork.back().getLTIntegralOut(); // we get the integrated length from TPC-ITC outward propagation + // compute track length up to now + mLTinfos[sector][trkType::UNCONS].emplace_back(intLT0); - mTracksSectIndexCache[trkType::UNCONS][sector].push_back(it); - //delete trc; // Check: is this needed? + /* + const auto& trackTune = o2::globaltracking::TrackTuneParams::Instance(); + if (!trackTune.sourceLevelTPC) { // correct only if TPC track was not corrected at the source level + if (trackTune.useTPCOuterCorr) { + trc.updateParams(trackTune.tpcParOuter); + } + if (trackTune.tpcCovOuterType != o2::globaltracking::TrackTuneParams::AddCovType::Disable) { // only TRD-refitted track have cov.matrix already manipulated + trc.updateCov(trackTune.tpcCovOuter, trackTune.tpcCovOuterType == o2::globaltracking::TrackTuneParams::AddCovType::WithCorrelations); + } + } + if (!propagateToRefXWithoutCov(trc, mXRef, 10, mBz)) { // we first propagate to 371 cm without considering the covariance matri + mNotPropagatedToTOF[trkType::UNCONS]++; + return; + } + + if (trc.getX() < o2::constants::geom::XTPCOuterRef - 1.) { + if (!propagateToRefX(trc, o2::constants::geom::XTPCOuterRef, 10, intLT0) || TMath::Abs(trc.getZ()) > Geo::MAXHZTOF) { // we check that the propagation with the cov matrix worked; CHECK: can it happ + mNotPropagatedToTOF[trkType::UNCONS]++; + return; + } + } + + // the "rough" propagation worked; now we can propagate considering also the cov matrix + if (!propagateToRefX(trc, mXRef, 2, intLT0)) { // || TMath::Abs(trc.getZ()) > Geo::MAXHZTOF) { // we check that the propagation with the cov matrix worked; CHECK: can it happen that it does not if the prop> + mNotPropagatedToTOF[trkType::UNCONS]++; + return; + } + + // printf("time0 %f -> %f (diff = %f, err = %f)\n",trackTime0, time0, trackTime0 - time0, terr); + // printf("time errors %f,%f -> %f,%f\n",(_tr.getDeltaTBwd() + 5) * mTPCTBinMUS,(_tr.getDeltaTFwd() + 5) * mTPCTBinMUS,trackTime0 - time0 + terr, time0 + terr - trackTime0); + + trc.getXYZGlo(globalPos); + int sector = o2::math_utils::angle2Sector(TMath::ATan2(globalPos[1], globalPos[0])); + + mTracksSectIndexCache[trkType::UNCONS][sector].push_back(it); + */ + // delete trc; // Check: is this needed? } //______________________________________________ bool MatchTOF::prepareTOFClusters() @@ -573,7 +716,7 @@ bool MatchTOF::prepareTOFClusters() // mTOFClusLblWork.reserve(mNumOfClusters); // } - for (int sec = o2::constants::math::NSectors; sec--;) { + for (int sec = o2::constants::math::NSectors - 1; sec > -1; sec--) { mTOFClusSectIndexCache[sec].clear(); //mTOFClusSectIndexCache[sec].reserve(100 + 1.2 * mNumOfClusters / o2::constants::math::NSectors); // we cannot do this, we don't have mNumOfClusters yet } @@ -594,7 +737,7 @@ bool MatchTOF::prepareTOFClusters() } // sort clusters in each sector according to their time (increasing in time) - for (int sec = o2::constants::math::NSectors; sec--;) { + for (int sec = o2::constants::math::NSectors - 1; sec > -1; sec--) { auto& indexCache = mTOFClusSectIndexCache[sec]; LOG(debug) << "Sorting sector" << sec << " | " << indexCache.size() << " TOF clusters"; if (!indexCache.size()) { @@ -647,9 +790,9 @@ void MatchTOF::doMatching(int sec) nStepsInsideSameStrip[ii] = 0; } int nStripsCrossedInPropagation = 0; // how many strips were hit during the propagation - auto& trackWork = mTracksWork[type][cacheTrk[itrk]]; + auto& trackWork = mTracksWork[sec][type][cacheTrk[itrk]]; auto& trefTrk = trackWork.first; - auto& intLT = mLTinfos[type][cacheTrk[itrk]]; + auto& intLT = mLTinfos[sec][type][cacheTrk[itrk]]; float timeShift = intLT.getL() * 33.35641; // integrated time for 0.75 beta particles in ps, to take into account the t.o.f. delay with respect the interaction BC // using beta=0.75 to cover beta range [0.59 , 1.04] also for a 8 m track lenght with a 10 ns track resolution (TRD) @@ -850,7 +993,7 @@ void MatchTOF::doMatching(int sec) foundCluster = true; // set event indexes (to be checked) int eventIndexTOFCluster = mTOFClusSectIndexCache[indices[0]][itof]; - mMatchedTracksPairs.emplace_back(cacheTrk[itrk], eventIndexTOFCluster, mTOFClusWork[cacheTOF[itof]].getTime(), chi2, trkLTInt[iPropagation], mTrackGid[type][cacheTrk[itrk]], type, (trefTOF.getTime() - (minTrkTime + maxTrkTime - 100E3) * 0.5) * 1E-6, 0., resX, resZ); // subracting 100 ns to max track which was artificially added + mMatchedTracksPairsSec[sec].emplace_back(cacheTrk[itrk], eventIndexTOFCluster, mTOFClusWork[cacheTOF[itof]].getTime(), chi2, trkLTInt[iPropagation], mTrackGid[sec][type][cacheTrk[itrk]], type, (trefTOF.getTime() - (minTrkTime + maxTrkTime - 100E3) * 0.5) * 1E-6, 0., resX, resZ); // subracting 100 ns to max track which was artificially added } } } @@ -894,9 +1037,9 @@ void MatchTOF::doMatchingForTPC(int sec) LOG(debug) << "Trying to match %d tracks" << cacheTrk.size(); for (int itrk = 0; itrk < cacheTrk.size(); itrk++) { - auto& trackWork = mTracksWork[trkType::UNCONS][cacheTrk[itrk]]; + auto& trackWork = mTracksWork[sec][trkType::UNCONS][cacheTrk[itrk]]; auto& trefTrk = trackWork.first; - auto& intLT = mLTinfos[trkType::UNCONS][cacheTrk[itrk]]; + auto& intLT = mLTinfos[sec][trkType::UNCONS][cacheTrk[itrk]]; float timeShift = intLT.getL() * 33.35641; // integrated time for 0.75 beta particles in ps, to take into account the t.o.f. delay with respect the interaction BC // using beta=0.75 to cover beta range [0.59 , 1.04] also for a 8 m track lenght with a 10 ns track resolution (TRD) @@ -904,11 +1047,11 @@ void MatchTOF::doMatchingForTPC(int sec) BCcand.clear(); nStripsCrossedInPropagation.clear(); - int side = mSideTPC[cacheTrk[itrk]]; + int side = mSideTPC[sec][cacheTrk[itrk]]; // look at BC candidates for the track double minTrkTime = (trackWork.second.getTimeStamp() - trackWork.second.getTimeStampError()) * 1.E6 + timeShift; // minimum time in ps minTrkTime = int(minTrkTime / BCgranularity) * BCgranularity; // align min to a BC - double maxTrkTime = (trackWork.second.getTimeStamp() + mExtraTPCFwdTime[cacheTrk[itrk]]) * 1.E6 + timeShift; // maximum time in ps + double maxTrkTime = (trackWork.second.getTimeStamp() + mExtraTPCFwdTime[sec][cacheTrk[itrk]]) * 1.E6 + timeShift; // maximum time in ps if (mIsCosmics) { for (double tBC = minTrkTime; tBC < maxTrkTime; tBC += BCgranularity) { @@ -1179,7 +1322,7 @@ void MatchTOF::doMatchingForTPC(int sec) foundCluster = true; // set event indexes (to be checked) int eventIndexTOFCluster = mTOFClusSectIndexCache[indices[0]][itof]; - mMatchedTracksPairs.emplace_back(cacheTrk[itrk], eventIndexTOFCluster, mTOFClusWork[cacheTOF[itof]].getTime(), chi2, trkLTInt[ibc][iPropagation], mTrackGid[trkType::UNCONS][cacheTrk[itrk]], trkType::UNCONS, resZ / mTPCVDrift * side, trefTOF.getZ(), resX, resZ); // TODO: check if this is correct! + mMatchedTracksPairsSec[sec].emplace_back(cacheTrk[itrk], eventIndexTOFCluster, mTOFClusWork[cacheTOF[itof]].getTime(), chi2, trkLTInt[ibc][iPropagation], mTrackGid[sec][trkType::UNCONS][cacheTrk[itrk]], trkType::UNCONS, resZ / mTPCVDrift * side, trefTOF.getZ(), resX, resZ); // TODO: check if this is correct! } } } @@ -1231,13 +1374,13 @@ int MatchTOF::findFITIndex(int bc, const gsl::span& FI return index; } //______________________________________________ -void MatchTOF::selectBestMatches() +void MatchTOF::selectBestMatches(int sec) { if (mSetHighPurity) { - BestMatchesHP(mMatchedTracksPairs, mMatchedTracks, mMatchedTracksIndex, mMatchedClustersIndex, mFITRecPoints, mTOFClusWork, mCalibInfoTOF, mTimestamp, mMCTruthON, mTOFClusLabels, mTracksLblWork, mOutTOFLabels); + BestMatchesHP(mMatchedTracksPairsSec[sec], mMatchedTracks, mMatchedTracksIndex[sec], mMatchedClustersIndex, mFITRecPoints, mTOFClusWork, mCalibInfoTOF, mTimestamp, mMCTruthON, mTOFClusLabels, mTracksLblWork[sec], mOutTOFLabels); return; } - BestMatches(mMatchedTracksPairs, mMatchedTracks, mMatchedTracksIndex, mMatchedClustersIndex, mFITRecPoints, mTOFClusWork, mTracksWork, mCalibInfoTOF, mTimestamp, mMCTruthON, mTOFClusLabels, mTracksLblWork, mOutTOFLabels, mMatchParams->calibMaxChi2); + BestMatches(mMatchedTracksPairsSec[sec], mMatchedTracks, mMatchedTracksIndex[sec], mMatchedClustersIndex, mFITRecPoints, mTOFClusWork, mTracksWork[sec], mCalibInfoTOF, mTimestamp, mMCTruthON, mTOFClusLabels, mTracksLblWork[sec], mOutTOFLabels, mMatchParams->calibMaxChi2); } //______________________________________________ void MatchTOF::BestMatches(std::vector& matchedTracksPairs, std::vector* matchedTracks, std::vector* matchedTracksIndex, int* matchedClustersIndex, const gsl::span& FITRecPoints, const std::vector& TOFClusWork, const std::vector* TracksWork, std::vector& CalibInfoTOF, unsigned long Timestamp, bool MCTruthON, const o2::dataformats::MCTruthContainer* TOFClusLabels, const std::vector* TracksLblWork, std::vector* OutTOFLabels, float calibMaxChi2) diff --git a/Detectors/GlobalTrackingWorkflow/include/GlobalTrackingWorkflow/TOFMatcherSpec.h b/Detectors/GlobalTrackingWorkflow/include/GlobalTrackingWorkflow/TOFMatcherSpec.h index b9874dab1cdd4..79a4ee0ce0360 100644 --- a/Detectors/GlobalTrackingWorkflow/include/GlobalTrackingWorkflow/TOFMatcherSpec.h +++ b/Detectors/GlobalTrackingWorkflow/include/GlobalTrackingWorkflow/TOFMatcherSpec.h @@ -29,7 +29,7 @@ namespace globaltracking { /// create a processor spec -framework::DataProcessorSpec getTOFMatcherSpec(o2::dataformats::GlobalTrackID::mask_t src, bool useMC, bool useFIT, bool tpcRefit, bool strict, float extratolerancetrd, bool pushMatchable, const o2::tpc::CorrectionMapsLoaderGloOpts& sclOpts); +framework::DataProcessorSpec getTOFMatcherSpec(o2::dataformats::GlobalTrackID::mask_t src, bool useMC, bool useFIT, bool tpcRefit, bool strict, float extratolerancetrd, bool pushMatchable, const o2::tpc::CorrectionMapsLoaderGloOpts& sclOpts, int nlanes = 1); } // namespace globaltracking } // namespace o2 diff --git a/Detectors/GlobalTrackingWorkflow/src/TOFMatcherSpec.cxx b/Detectors/GlobalTrackingWorkflow/src/TOFMatcherSpec.cxx index 35d1d5736f5ea..0c8fd7a809a1c 100644 --- a/Detectors/GlobalTrackingWorkflow/src/TOFMatcherSpec.cxx +++ b/Detectors/GlobalTrackingWorkflow/src/TOFMatcherSpec.cxx @@ -58,7 +58,7 @@ namespace globaltracking class TOFMatcherSpec : public Task { public: - TOFMatcherSpec(std::shared_ptr dr, std::shared_ptr gr, bool useMC, bool useFIT, bool tpcRefit, bool strict, bool pushMatchable) : mDataRequest(dr), mGGCCDBRequest(gr), mUseMC(useMC), mUseFIT(useFIT), mDoTPCRefit(tpcRefit), mStrict(strict), mPushMatchable(pushMatchable) {} + TOFMatcherSpec(std::shared_ptr dr, std::shared_ptr gr, bool useMC, bool useFIT, bool tpcRefit, bool strict, bool pushMatchable, int lanes = 1) : mDataRequest(dr), mGGCCDBRequest(gr), mUseMC(useMC), mUseFIT(useFIT), mDoTPCRefit(tpcRefit), mStrict(strict), mPushMatchable(pushMatchable), mNlanes(lanes) {} ~TOFMatcherSpec() override = default; void init(InitContext& ic) final; void run(ProcessingContext& pc) final; @@ -77,6 +77,7 @@ class TOFMatcherSpec : public Task bool mStrict = false; bool mPushMatchable = false; float mExtraTolTRD = 0.; + int mNlanes = 1; MatchTOF mMatcher; ///< Cluster finder TStopwatch mTimer; }; @@ -92,6 +93,7 @@ void TOFMatcherSpec::init(InitContext& ic) mTPCCorrMapsLoader.init(ic); mMatcher.storeMatchable(mPushMatchable); mMatcher.setExtraTimeToleranceTRD(mExtraTolTRD); + mMatcher.setNlanes(mNlanes); } void TOFMatcherSpec::updateTimeDependentParams(ProcessingContext& pc) @@ -237,7 +239,7 @@ void TOFMatcherSpec::endOfStream(EndOfStreamContext& ec) mTimer.CpuTime(), mTimer.RealTime(), mTimer.Counter() - 1); } -DataProcessorSpec getTOFMatcherSpec(GID::mask_t src, bool useMC, bool useFIT, bool tpcRefit, bool strict, float extratolerancetrd, bool pushMatchable, const o2::tpc::CorrectionMapsLoaderGloOpts& sclOpts) +DataProcessorSpec getTOFMatcherSpec(GID::mask_t src, bool useMC, bool useFIT, bool tpcRefit, bool strict, float extratolerancetrd, bool pushMatchable, const o2::tpc::CorrectionMapsLoaderGloOpts& sclOpts, int nlanes) { uint32_t ss = o2::globaltracking::getSubSpec(strict ? o2::globaltracking::MatchingType::Strict : o2::globaltracking::MatchingType::Standard); Options opts; @@ -314,7 +316,7 @@ DataProcessorSpec getTOFMatcherSpec(GID::mask_t src, bool useMC, bool useFIT, bo "tof-matcher", dataRequest->inputs, outputs, - AlgorithmSpec{adaptFromTask(dataRequest, ggRequest, useMC, useFIT, tpcRefit, strict, pushMatchable)}, + AlgorithmSpec{adaptFromTask(dataRequest, ggRequest, useMC, useFIT, tpcRefit, strict, pushMatchable, nlanes)}, opts}; } diff --git a/Detectors/GlobalTrackingWorkflow/src/tof-matcher-workflow.cxx b/Detectors/GlobalTrackingWorkflow/src/tof-matcher-workflow.cxx index ad009d266239b..1af69d003036d 100644 --- a/Detectors/GlobalTrackingWorkflow/src/tof-matcher-workflow.cxx +++ b/Detectors/GlobalTrackingWorkflow/src/tof-matcher-workflow.cxx @@ -55,6 +55,7 @@ void customize(std::vector& workflowOptions) // option allowing to set parameters std::vector options{ {"disable-mc", o2::framework::VariantType::Bool, false, {"disable MC propagation even if available"}}, + {"tof-lanes", o2::framework::VariantType::Int, 3, {"number of parallel lanes up to the matcher"}}, {"disable-root-input", o2::framework::VariantType::Bool, false, {"disable root-files input reader"}}, {"disable-root-output", o2::framework::VariantType::Bool, false, {"disable root-files output writer"}}, {"track-sources", VariantType::String, std::string{GID::ALL}, {"comma-separated list of sources to use: allowed TPC,ITS-TPC,TPC-TRD,ITS-TPC-TRD (all)"}}, @@ -98,6 +99,7 @@ WorkflowSpec defineDataProcessing(ConfigContext const& configcontext) bool writematching = 0; bool writecalib = 0; auto outputType = configcontext.options().get("output-type"); + auto nLanes = configcontext.options().get("tof-lanes"); if (outputType.rfind("matching-info") < outputType.size()) { writematching = 1; } @@ -124,6 +126,7 @@ WorkflowSpec defineDataProcessing(ConfigContext const& configcontext) LOG(debug) << "TOF matching in strict mode = " << strict; LOG(debug) << "TOF extra time tolerance for TRD tracks = " << extratolerancetrd; LOG(debug) << "Store all matchables = " << writeMatchable; + LOG(debug) << "TOF Nlanes for matcher = " << nLanes; //GID::mask_t alowedSources = GID::getSourcesMask("TPC,ITS-TPC"); GID::mask_t alowedSources = GID::getSourcesMask("TPC,ITS-TPC,TPC-TRD,ITS-TPC-TRD"); @@ -160,7 +163,7 @@ WorkflowSpec defineDataProcessing(ConfigContext const& configcontext) } } - specs.emplace_back(o2::globaltracking::getTOFMatcherSpec(src, useMC, useFIT, false, strict, extratolerancetrd, writeMatchable, sclOpt)); // doTPCrefit not yet supported (need to load TPC clusters?) + specs.emplace_back(o2::globaltracking::getTOFMatcherSpec(src, useMC, useFIT, false, strict, extratolerancetrd, writeMatchable, sclOpt, nLanes)); // doTPCrefit not yet supported (need to load TPC clusters?) if (!disableRootOut) { std::vector writers;