99// granted to it by virtue of its status as an Intergovernmental Organization
1010// or submit itself to any jurisdiction.
1111//
12- // / \file global-muon-matcher .cxx
12+ // / \file globalMuonMatching .cxx
1313// / \brief Global muon matching
1414//
1515#include " PWGDQ/Core/MuonMatchingMlResponse.h"
7171#include < utility>
7272#include < vector>
7373
74- #include < math.h>
75-
7674using namespace o2 ;
7775using namespace o2 ::framework;
7876using namespace o2 ::aod;
@@ -98,11 +96,16 @@ DECLARE_SOA_TABLE(GlobalMuonMatchCandidates, "AOD", "GMCAND",
9896
9997namespace globalmuonmatching
10098{
101- DECLARE_SOA_ARRAY_INDEX_COLUMN (GlobalMuonMatchCandidate, matchCandidate); // ! Array of GlobalMuonMatchCandidates indices
99+ DECLARE_SOA_ARRAY_INDEX_COLUMN (GlobalMuonMatchCandidate, globalMuonMatchCandidate); // ! Array of GlobalMuonMatchCandidates indices
100+ DECLARE_SOA_INDEX_COLUMN (FwdTrackReAlign, fwdTrackReAlign); // ! Index of ambiguous FwdTracksReAlign entry
101+ DECLARE_SOA_SLICE_INDEX_COLUMN (Bc, bc); // ! BC index slice compatible with the track time window
102102} // namespace globalmuonmatching
103103
104104DECLARE_SOA_TABLE (FwdTrkMatchCands, " AOD" , " FWDTRKMATCHCAND" , // ! Vectors of match-candidate indices stored per fwdtrack
105105 globalmuonmatching::GlobalMuonMatchCandidateIds, o2::soa::Marker<3 >);
106+
107+ DECLARE_SOA_TABLE (AmbiguousFwdTracksReAlign, " AOD" , " AMBIGFWDREALIGN" , // ! FwdTracksReAlign entries without a unique collision association
108+ o2::soa::Index<>, globalmuonmatching::FwdTrackReAlignId, globalmuonmatching::BcIdSlice);
106109} // namespace o2::aod
107110
108111using MyEvents = soa::Join<aod::Collisions, aod::EvSels, aod::FT0Mults, aod::MFTMults, aod::PVMults, aod::CentFT0Ms, aod::CentFT0As, aod::CentFT0Cs>;
@@ -121,6 +124,11 @@ struct GlobalMuonMatching {
121124
122125 static constexpr int GlobalTrackTypeMax = 2 ;
123126 static constexpr int MchMidTrackType = 3 ;
127+ static constexpr int NMchChambers = 10 ;
128+ static constexpr int MchDetElemNumberingBase = 100 ;
129+ static constexpr int NMchDetElems = 156 ;
130+ static constexpr int MinRemovableTrackClusters = 10 ;
131+ static constexpr double DefaultChamberResolution = 0.04 ;
124132 static constexpr int ThetaAbsBoundaryDeg = 3 ;
125133 static constexpr double SlopeResolutionZ = 535 .;
126134 static constexpr int MatchingDegreesOfFreedom = 5 ;
@@ -157,16 +165,16 @@ struct GlobalMuonMatching {
157165 Configurable<bool > cfgEnableMCHRealign{" cfgEnableMCHRealign" , true , " Enable re-alignment of MCH clusters and tracks" };
158166 Configurable<std::string> cfgGeoRefPath{" cfgGeoRefPath" , " GLO/Config/GeometryAligned" , " Path of the reference geometry file" };
159167 Configurable<std::string> cfgGeoNewPath{" cfgGeoNewPath" , " GLO/Config/GeometryAligned" , " Path of the new geometry file" };
160- Configurable<int64_t > nolaterthanRef{ " ccdb-no-later-than-ref " , std::chrono::duration_cast<std::chrono::milliseconds>(std::chrono::system_clock::now ().time_since_epoch ()).count (), " latest acceptable timestamp of creation for the object of reference basis" };
161- Configurable<int64_t > nolaterthanNew{ " ccdb-no-later-than-new " , std::chrono::duration_cast<std::chrono::milliseconds>(std::chrono::system_clock::now ().time_since_epoch ()).count (), " latest acceptable timestamp of creation for the object of new basis" };
162- Configurable<double > cfgChamberResolutionX{" cfgChamberResolutionX" , 0.04 , " Chamber resolution along X configuration for refit" }; // 0.4cm pp, 0.2cm PbPb
163- Configurable<double > cfgChamberResolutionY{" cfgChamberResolutionY" , 0.04 , " Chamber resolution along Y configuration for refit" }; // 0.4cm pp, 0.2cm PbPb
168+ Configurable<int64_t > cfgCcdbNoLaterThanRef{ " cfgCcdbNoLaterThanRef " , std::chrono::duration_cast<std::chrono::milliseconds>(std::chrono::system_clock::now ().time_since_epoch ()).count (), " latest acceptable timestamp of creation for the object of reference basis" };
169+ Configurable<int64_t > cfgCcdbNoLaterThanNew{ " cfgCcdbNoLaterThanNew " , std::chrono::duration_cast<std::chrono::milliseconds>(std::chrono::system_clock::now ().time_since_epoch ()).count (), " latest acceptable timestamp of creation for the object of new basis" };
170+ Configurable<double > cfgChamberResolutionX{" cfgChamberResolutionX" , DefaultChamberResolution , " Chamber resolution along X configuration for refit" }; // 0.4cm pp, 0.2cm PbPb
171+ Configurable<double > cfgChamberResolutionY{" cfgChamberResolutionY" , DefaultChamberResolution , " Chamber resolution along Y configuration for refit" }; // 0.4cm pp, 0.2cm PbPb
164172 Configurable<double > cfgSigmaCutImprove{" cfgSigmaCutImprove" , 6 ., " Sigma cut for track improvement" }; // 6 for pp, 4 for PbPb
165173 } configMchRealign;
166174
167175 // // Variables for MFT alignment corrections
168176 struct : ConfigurableGroup {
169- Configurable<bool > cfgEnableMftAlignmentCorrections{" cfgEnableMFTAlignmentCorrections " , true , " Enable alignment corrections for the MFT tracks" };
177+ Configurable<bool > cfgEnableMftAlignmentCorrections{" cfgEnableMftAlignmentCorrections " , true , " Enable alignment corrections for the MFT tracks" };
170178 // slope corrections
171179 // Configurable<float> cfgMFTAlignmentCorrXSlopeTop{"cfgMFTAlignmentCorrXSlopeTop", (-0.0006696 - 0.0005621) / 2.f, "MFT X slope correction - top half"};
172180 // Configurable<float> cfgMFTAlignmentCorrXSlopeBottom{"cfgMFTAlignmentCorrXSlopeBottom", (0.00105 + 0.001007) / 2.f, "MFT X slope correction - bottom half"};
@@ -196,7 +204,6 @@ struct GlobalMuonMatching {
196204 // 0 = chi2 (runChi2Matching), 1 = ML (runMlMatching)
197205 struct : ConfigurableGroup {
198206 Configurable<int > cfgCustomMatchingStrategy{" cfgCustomMatchingStrategy" , 0 , " 0=chi2, 1=ML for custom matches" };
199- Configurable<bool > cfgProduceCandidateFwdTracks{" cfgProduceCandidateFwdTracks" , true , " Produce GMMCANDTRK/GMMCANDTRKCOV tables (all FwdTracks + match candidates)" };
200207 Configurable<bool > cfgIncludeGlobalMuonsInFwdTracks{" cfgIncludeGlobalMuonsInFwdTracks" , false , " Include MFT-MCH-MID global muons in GMMCANDTRK table" };
201208 Configurable<int > cfgMaxCandidatesPerMchTrack{" cfgMaxCandidatesPerMchTrack" , -1 , " Maximum number of match candidates stored per MCH track (-1: no limit)" };
202209 Configurable<bool > cfgMatchAllTracks{" cfgMatchAllTracks" , false , " If true the matching is performed considering all the MFT tracks for which the covariances are available; if false the matching is performed considering only the global forward tracks stored at production" };
@@ -287,6 +294,12 @@ struct GlobalMuonMatching {
287294 Produces<o2::aod::FwdTrkMatchCands> fwdTrkMatchCands;
288295 Produces<o2::aod::StoredFwdTracksReAlign> gmCandidateFwdTracks;
289296 Produces<o2::aod::StoredFwdTrksCovReAlign> gmCandidateFwdTracksCov;
297+ Produces<o2::aod::AmbiguousFwdTracksReAlign> gmAmbiguousFwdTracksReAlign;
298+
299+ int32_t mGmmCandFwdTrackRowIndex {0 };
300+ std::unordered_map<int64_t , std::array<int32_t , 2 >> mAmbBcSliceByFwdTrackId ;
301+ bool mHasLastMchAmbiguousBcSlice {false };
302+ std::array<int32_t , 2 > mLastMchAmbiguousBcSlice {};
290303
291304 int32_t mMatchCandidateCounter {0 };
292305 std::unordered_map<int64_t , std::vector<int32_t >> mMchTrackToCandidateIndices ;
@@ -454,14 +467,14 @@ struct GlobalMuonMatching {
454467 {
455468 // make sure detector number is valid
456469 if (!(iDetElemNumber >= fgSNDetElemCh[0 ] &&
457- iDetElemNumber < fgSNDetElemCh[10 ])) {
470+ iDetElemNumber < fgSNDetElemCh[NMchChambers ])) {
458471 LOGF (fatal, " Invalid detector element number: %d" , iDetElemNumber);
459472 }
460473 // / get det element number from ID
461474 // get chamber and element number in chamber
462475 int iCh = 0 ;
463476 int iDet = 0 ;
464- for (int i = 1 ; i <= 10 ; i++) {
477+ for (int i = 1 ; i <= NMchChambers ; i++) {
465478 if (iDetElemNumber < fgSNDetElemCh[i]) {
466479 iCh = i;
467480 iDet = iDetElemNumber - fgSNDetElemCh[i - 1 ];
@@ -470,12 +483,12 @@ struct GlobalMuonMatching {
470483 }
471484
472485 // make sure detector index is valid
473- if (!(iCh > 0 && iCh <= 10 && iDet < fgNDetElemCh[iCh - 1 ])) {
474- LOGF (fatal, " Invalid detector element id: %d" , 100 * iCh + iDet);
486+ if (!(iCh > 0 && iCh <= NMchChambers && iDet < fgNDetElemCh[iCh - 1 ])) {
487+ LOGF (fatal, " Invalid detector element id: %d" , MchDetElemNumberingBase * iCh + iDet);
475488 }
476489
477490 // add number of detectors up to this chamber
478- return 100 * iCh + iDet;
491+ return MchDetElemNumberingBase * iCh + iDet;
479492 }
480493
481494 bool RemoveTrack (mch::Track& track)
@@ -527,7 +540,7 @@ struct GlobalMuonMatching {
527540 auto itNextToNextParam = (itNextParam == track.end ()) ? itNextParam : std::next (itNextParam);
528541 itStartingParam = track.rbegin ();
529542
530- if (track.getNClusters () < 10 ) {
543+ if (track.getNClusters () < MinRemovableTrackClusters ) {
531544 removeTrack = true ;
532545 break ;
533546 } else {
@@ -542,7 +555,7 @@ struct GlobalMuonMatching {
542555 }
543556
544557 if (!removeTrack) {
545- for (auto & param : track) {
558+ for (auto & param : track) { // o2-linter: disable=const-ref-in-for-loop (object is modified in loop)
546559 param.setParameters (param.getSmoothParameters ());
547560 param.setCovariances (param.getSmoothCovariances ());
548561 }
@@ -572,30 +585,30 @@ struct GlobalMuonMatching {
572585 mch::TrackExtrap::useExtrapV2 ();
573586
574587 // Load geometry information from CCDB/local
575- LOGF (info, " Loading reference aligned geometry from CCDB no later than %d" , configMchRealign.nolaterthanRef .value );
576- ccdbManager->setCreatedNotAfter (configMchRealign.nolaterthanRef .value ); // this timestamp has to be consistent with what has been used in reco
588+ LOGF (info, " Loading reference aligned geometry from CCDB no later than %d" , configMchRealign.cfgCcdbNoLaterThanRef .value );
589+ ccdbManager->setCreatedNotAfter (configMchRealign.cfgCcdbNoLaterThanRef .value ); // this timestamp has to be consistent with what has been used in reco
577590 geoRef = ccdbManager->getForTimeStamp <TGeoManager>(configMchRealign.cfgGeoRefPath , bc.timestamp ());
578591 ccdbManager->clearCache (configMchRealign.cfgGeoRefPath );
579592 if (geoRef != nullptr ) {
580593 transformation = mch::geo::transformationFromTGeoManager (*geoRef);
581594 } else {
582595 LOGF (fatal, " Reference aligned geometry object is not available in CCDB at timestamp=%llu" , bc.timestamp ());
583596 }
584- for (int i = 0 ; i < 156 ; i++) {
597+ for (int i = 0 ; i < NMchDetElems ; i++) {
585598 int iDEN = GetDetElemId (i);
586599 transformRef[iDEN] = transformation (iDEN);
587600 }
588601
589- LOGF (info, " Loading new aligned geometry from CCDB no later than %d" , configMchRealign.nolaterthanNew .value );
590- ccdbManager->setCreatedNotAfter (configMchRealign.nolaterthanNew .value ); // make sure this timestamp can be resolved regarding the reference one
602+ LOGF (info, " Loading new aligned geometry from CCDB no later than %d" , configMchRealign.cfgCcdbNoLaterThanNew .value );
603+ ccdbManager->setCreatedNotAfter (configMchRealign.cfgCcdbNoLaterThanNew .value ); // make sure this timestamp can be resolved regarding the reference one
591604 geoNew = ccdbManager->getForTimeStamp <TGeoManager>(configMchRealign.cfgGeoNewPath , bc.timestamp ());
592605 ccdbManager->clearCache (configMchRealign.cfgGeoNewPath );
593606 if (geoNew != nullptr ) {
594607 transformation = mch::geo::transformationFromTGeoManager (*geoNew);
595608 } else {
596609 LOGF (fatal, " New aligned geometry object is not available in CCDB at timestamp=%llu" , bc.timestamp ());
597610 }
598- for (int i = 0 ; i < 156 ; i++) {
611+ for (int i = 0 ; i < NMchDetElems ; i++) {
599612 int iDEN = GetDetElemId (i);
600613 transformNew[iDEN] = transformation (iDEN);
601614 }
@@ -881,6 +894,15 @@ struct GlobalMuonMatching {
881894 float matchScoreMCHMFT)
882895 {
883896 const int32_t collisionId = track.has_collision () ? track.collisionId () : -1 ;
897+ bool hasBcSlice = false ;
898+ std::array<int32_t , 2 > bcSlice{};
899+ if (collisionId < 0 ) {
900+ const auto ambIt = mAmbBcSliceByFwdTrackId .find (track.globalIndex ());
901+ if (ambIt != mAmbBcSliceByFwdTrackId .end ()) {
902+ bcSlice = ambIt->second ;
903+ hasBcSlice = true ;
904+ }
905+ }
884906
885907 gmCandidateFwdTracks (
886908 collisionId,
@@ -908,6 +930,16 @@ struct GlobalMuonMatching {
908930 track.trackTimeRes ());
909931
910932 storeFwdTrackCovariance (trackPar.getCovariances ());
933+ if (hasBcSlice) {
934+ int32_t bcSliceArray[2 ] = {bcSlice[0 ], bcSlice[1 ]};
935+ gmAmbiguousFwdTracksReAlign (mGmmCandFwdTrackRowIndex , bcSliceArray);
936+ }
937+ mGmmCandFwdTrackRowIndex += 1 ;
938+
939+ mHasLastMchAmbiguousBcSlice = hasBcSlice;
940+ if (hasBcSlice) {
941+ mLastMchAmbiguousBcSlice = bcSlice;
942+ }
911943 }
912944
913945 template <class TMCH , class TMFT >
@@ -937,6 +969,20 @@ struct GlobalMuonMatching {
937969
938970 const float chi2 = static_cast <float >(mchTrack.chi2 ());
939971 const int32_t collisionId = mchTrack.has_collision () ? mchTrack.collisionId () : -1 ;
972+ bool hasBcSlice = false ;
973+ std::array<int32_t , 2 > bcSlice{};
974+ if (collisionId < 0 ) {
975+ if (mHasLastMchAmbiguousBcSlice ) {
976+ bcSlice = mLastMchAmbiguousBcSlice ;
977+ hasBcSlice = true ;
978+ } else {
979+ const auto ambIt = mAmbBcSliceByFwdTrackId .find (mchTrack.globalIndex ());
980+ if (ambIt != mAmbBcSliceByFwdTrackId .end ()) {
981+ bcSlice = ambIt->second ;
982+ hasBcSlice = true ;
983+ }
984+ }
985+ }
940986
941987 bool isRemovable = mchPar.isRemovable ();
942988
@@ -966,6 +1012,11 @@ struct GlobalMuonMatching {
9661012 mchTrack.trackTimeRes ());
9671013
9681014 storeFwdTrackCovariance (globalMuonRefit.getCovariances ());
1015+ if (hasBcSlice) {
1016+ int32_t bcSliceArray[2 ] = {bcSlice[0 ], bcSlice[1 ]};
1017+ gmAmbiguousFwdTracksReAlign (mGmmCandFwdTrackRowIndex , bcSliceArray);
1018+ }
1019+ mGmmCandFwdTrackRowIndex += 1 ;
9691020 }
9701021
9711022 o2::track::TrackParCovFwd propagateToZMch (const o2::track::TrackParCovFwd& muon, const double z)
@@ -1223,7 +1274,7 @@ struct GlobalMuonMatching {
12231274 for (auto const & muon : muons) {
12241275 int mchIndex = muon.globalIndex ();
12251276 // skip global forward matches
1226- if (static_cast < int >( muon.trackType () > 2 ) ) {
1277+ if (muon.trackType () > GlobalTrackTypeMax ) {
12271278 continue ;
12281279 }
12291280
@@ -1505,13 +1556,17 @@ struct GlobalMuonMatching {
15051556
15061557 template <class TMUON , class TMFT >
15071558 void fillGmmCandidateFwdTracks (TMUON const & muonTracks,
1508- TMFT const & mftTracks)
1559+ TMFT const & mftTracks,
1560+ aod::AmbiguousFwdTracks const & ambFwdTracks)
15091561 {
1510- if (!configMatching.cfgProduceCandidateFwdTracks .value ) {
1511- return ;
1512- }
1513-
15141562 mFwdTrackToGmmCandTrkIndex .clear ();
1563+ mGmmCandFwdTrackRowIndex = 0 ;
1564+ mHasLastMchAmbiguousBcSlice = false ;
1565+ mAmbBcSliceByFwdTrackId .clear ();
1566+ for (const auto & ambFwdTrack : ambFwdTracks) {
1567+ const auto bcIds = ambFwdTrack.bcIds ();
1568+ mAmbBcSliceByFwdTrackId [ambFwdTrack.fwdtrackId ()] = {bcIds[0 ], bcIds[1 ]};
1569+ }
15151570
15161571 // First pass: assign GMMCANDTRK row indices for MCH/MCH-MID base entries so that
15171572 // MCHTrackId can be remapped consistently even when global muons appear first in FwdTracks.
@@ -1531,6 +1586,7 @@ struct GlobalMuonMatching {
15311586 const int trackType = static_cast <int >(track.trackType ());
15321587
15331588 if (trackType > GlobalTrackTypeMax) {
1589+ mHasLastMchAmbiguousBcSlice = false ;
15341590 const int64_t mchTrackIndex = track.globalIndex ();
15351591 const int32_t gmmMchTrackId = mFwdTrackToGmmCandTrkIndex .at (mchTrackIndex);
15361592
@@ -1597,7 +1653,8 @@ struct GlobalMuonMatching {
15971653 MyMuons const & muonTracks,
15981654 MyMFTs const & mftTracks,
15991655 MyMFTCovariances const & mftCovs,
1600- aod::FwdTrkCls const & clusters)
1656+ aod::FwdTrkCls const & clusters,
1657+ aod::AmbiguousFwdTracks const & ambFwdTracks)
16011658 {
16021659 auto bc = bcs.begin ();
16031660 initCcdb (bc);
@@ -1623,7 +1680,7 @@ struct GlobalMuonMatching {
16231680 // fill table with track/candidates index mapping
16241681 fillFwdTrkMatchCands (muonTracks);
16251682 // fill track tables
1626- fillGmmCandidateFwdTracks (muonTracks, mftTracks);
1683+ fillGmmCandidateFwdTracks (muonTracks, mftTracks, ambFwdTracks );
16271684 }
16281685
16291686 PROCESS_SWITCH (GlobalMuonMatching, processData, " processData" , true );
0 commit comments