Skip to content

Commit f0636b6

Browse files
committed
Add filling of mixed event matching candidates
1 parent 8cd759e commit f0636b6

1 file changed

Lines changed: 169 additions & 0 deletions

File tree

PWGDQ/Tasks/global-muon-matcher.cxx

Lines changed: 169 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -118,6 +118,22 @@ using SMatrix5 = o2::track::SMatrix5;
118118
constexpr std::array<int, 10> NDetElemCh = {4, 4, 4, 4, 18, 18, 26, 26, 26, 26};
119119
constexpr std::array<int, 11> SNDetElemCh = {0, 4, 8, 12, 16, 34, 52, 78, 104, 130, 156};
120120

121+
// compute minimum difference between azimuthal angles
122+
static float getDeltaPhi(float phi1, float phi2)
123+
{
124+
float dphi = phi1 - phi2;
125+
static constexpr float pi = TMath::Pi();
126+
static constexpr float twopi = pi;
127+
if (dphi > pi) {
128+
dphi -= twopi;
129+
}
130+
if (dphi < pi) {
131+
dphi += twopi;
132+
}
133+
return dphi;
134+
};
135+
136+
121137
struct GlobalMuonMatching {
122138

123139
static constexpr int GlobalTrackTypeMax = 2;
@@ -138,6 +154,15 @@ struct GlobalMuonMatching {
138154
int matchRanking{-1};
139155
};
140156

157+
struct MchTrackInfo {
158+
int64_t index{-1};
159+
int nMatchAttempts{-1};
160+
// vector of MFT-MCH matching candidates
161+
std::vector<MatchingCandidate> matchingCandidates;
162+
// vector of vectors of MFT-MCH matching candidates from mixed events
163+
std::vector<std::vector<MatchingCandidate>> mixedMatchingCandidates;
164+
};
165+
141166
//// Variables for selecting tagged muons
142167
struct : ConfigurableGroup {
143168
Configurable<int> cfgMuonTaggingNCrossedMftPlanesLow{"cfgMuonTaggingNCrossedMftPlanesLow", 5, ""};
@@ -299,6 +324,7 @@ struct GlobalMuonMatching {
299324
std::array<int32_t, 2> mLastMchAmbiguousBcSlice{};
300325

301326
int32_t mMatchCandidateCounter{0};
327+
std::unordered_map<int64_t, MchTrackInfo> mMchTrackInfos;
302328
std::unordered_map<int64_t, std::vector<int32_t>> mMchTrackToCandidateIndices;
303329
std::unordered_map<int64_t, std::vector<MatchingCandidate>> mMchTrackMatchingCandidates;
304330
std::unordered_map<int64_t, int32_t> mFwdTrackToGmmCandTrkIndex;
@@ -1119,6 +1145,41 @@ struct GlobalMuonMatching {
11191145
return std::fabs(deltaTrackTime) <= trackTimeResTot;
11201146
}
11211147

1148+
template <class EVT, class BC, class TMUON, class TMFTS>
1149+
int getMftMchMatchAttempts(EVT const& collisions,
1150+
BC const& bcs,
1151+
TMUON const& mchTrack,
1152+
TMFTS const& mftTracks)
1153+
{
1154+
if (!mchTrack.has_collision()) {
1155+
return 0;
1156+
}
1157+
const auto& collMch = collisions.rawIteratorAt(mchTrack.collisionId());
1158+
const auto& bcMch = bcs.rawIteratorAt(collMch.bcId());
1159+
1160+
int attempts{0};
1161+
for (const auto& mftTrack : mftTracks) {
1162+
if (!mftTrack.has_collision()) {
1163+
continue;
1164+
}
1165+
1166+
const auto& collMft = collisions.rawIteratorAt(mftTrack.collisionId());
1167+
const auto& bcMft = bcs.rawIteratorAt(collMft.bcId());
1168+
1169+
int64_t deltaBc = static_cast<int64_t>(bcMft.globalBC()) - static_cast<int64_t>(bcMch.globalBC());
1170+
double deltaBcNS = o2::constants::lhc::LHCBunchSpacingNS * deltaBc;
1171+
double deltaTrackTime = mftTrack.trackTime() - mchTrack.trackTime() + deltaBcNS;
1172+
double trackTimeResTot = mftTrack.trackTimeRes() + mchTrack.trackTimeRes();
1173+
1174+
if (std::fabs(deltaTrackTime) > trackTimeResTot) {
1175+
continue;
1176+
}
1177+
attempts += 1;
1178+
}
1179+
1180+
return attempts;
1181+
}
1182+
11221183
template <class EVT, class BC, class TMUON, class TMFT>
11231184
void prepareMatchingCandidates(EVT const& collisions,
11241185
BC const& bcs,
@@ -1140,6 +1201,9 @@ struct GlobalMuonMatching {
11401201

11411202
// initialize the MCH track parameters, which will be updated by the realignment if enabled
11421203
mMchTrackPars.try_emplace(mchTrackIndex, TrackParExt(fwdtrackutils::getTrackParCovFwd(muonTrack, muonTrack), muonTrack.nClusters()));
1204+
1205+
auto& mchTrackInfo = mMchTrackInfos[mchTrackIndex];
1206+
mchTrackInfo.index = mchTrackIndex;
11431207
}
11441208

11451209
for (const auto& mftTrack : mftTracks) {
@@ -1170,12 +1234,26 @@ struct GlobalMuonMatching {
11701234
continue;
11711235
}
11721236

1237+
auto& mchTrackInfo = mMchTrackInfos[mchTrackIndex];
1238+
mchTrackInfo.index = mchTrackIndex;
1239+
mchTrackInfo.matchingCandidates.emplace_back(MatchingCandidate{
1240+
.muonTrackId = muonTrack.globalIndex(),
1241+
.mftTrackId = mftTrackIndex,
1242+
.matchScore = muonTrack.matchScoreMCHMFT(),
1243+
.matchChi2 = muonTrack.chi2MatchMCHMFT()});
1244+
11731245
mMatchingCandidates[mchTrackIndex].emplace_back(MatchingCandidate{
11741246
.muonTrackId = muonTrack.globalIndex(),
11751247
.mftTrackId = mftTrackIndex,
11761248
.matchScore = muonTrack.matchScoreMCHMFT(),
11771249
.matchChi2 = muonTrack.chi2MatchMCHMFT()});
11781250
}
1251+
1252+
// set the number of match attempts for this track
1253+
for (auto& mchTrackInfo : mMchTrackInfos) {
1254+
const auto& mchTrack = muonTracks.rawIteratorAt(mchTrackInfo.first);
1255+
mchTrackInfo.second.nMatchAttempts = getMftMchMatchAttempts(collisions, bcs, mchTrack, mftTracks);
1256+
}
11791257
} else {
11801258
// build matching candidates from all time-compatible MFT-MCH pairs
11811259
for (const auto& muonTrack : muonTracks) {
@@ -1191,10 +1269,20 @@ struct GlobalMuonMatching {
11911269
continue;
11921270
}
11931271

1272+
auto& mchTrackInfo = mMchTrackInfos[mchTrackIndex];
1273+
mchTrackInfo.index = mchTrackIndex;
1274+
mchTrackInfo.matchingCandidates.emplace_back(MatchingCandidate{
1275+
.mftTrackId = mftTrack.globalIndex()});
1276+
11941277
mMatchingCandidates[mchTrackIndex].emplace_back(MatchingCandidate{
11951278
.mftTrackId = mftTrack.globalIndex()});
11961279
}
11971280
}
1281+
1282+
// set the number of match attempts for this track
1283+
for (auto& mchTrackInfo : mMchTrackInfos) {
1284+
mchTrackInfo.second.nMatchAttempts = mchTrackInfo.second.matchingCandidates.size();
1285+
}
11981286
}
11991287

12001288
// sort the vectors of matching candidates in ascending order based on the matching chi2 value
@@ -1207,6 +1295,85 @@ struct GlobalMuonMatching {
12071295
}
12081296
}
12091297

1298+
template <class EVT, class BC, class TMUON, class TMFT>
1299+
void prepareEventMixingMatchingCandidates(EVT const& collisions,
1300+
BC const& bcs,
1301+
TMUON const& muonTracks,
1302+
TMFT const& mftTracks,
1303+
MyMFTCovariances const& mftCovs)
1304+
{
1305+
LOGF(info, "Filling mixed matching candidate tables");
1306+
1307+
constexpr float deltaPhiMax = TMath::Pi() / 10;
1308+
1309+
for (auto& [mchIndex1, mchTrackInfo1] : mMchTrackInfos) {
1310+
const auto& mchTrack1 = muonTracks.rawIteratorAt(mchIndex1);
1311+
1312+
if (!mchTrack1.has_collision()) {
1313+
continue;
1314+
}
1315+
1316+
const auto& collision1 = collisions.rawIteratorAt(mchTrack1.collisionId());
1317+
const auto& bc1 = bcs.rawIteratorAt(collision1.bcId());
1318+
1319+
auto phi1 = std::atan2(mchTrack1.y(), mchTrack1.x());
1320+
auto r1 = std::hypot(mchTrack1.x(), mchTrack1.y());
1321+
1322+
auto nAttempts1 = mchTrackInfo1.nMatchAttempts;
1323+
1324+
auto vz1 = collision1.posZ();
1325+
1326+
for (const auto& [mchIndex2, mchTrackInfo2] : mMchTrackInfos) {
1327+
const auto& mchTrack2 = muonTracks.rawIteratorAt(mchIndex2);
1328+
1329+
if (!mchTrack2.has_collision()) {
1330+
continue;
1331+
}
1332+
1333+
const auto& collision2 = collisions.rawIteratorAt(mchTrack2.collisionId());
1334+
const auto& bc2 = bcs.rawIteratorAt(collision2.bcId());
1335+
1336+
auto deltaBc = std::abs(static_cast<int64_t>(bc2.globalBC()) - static_cast<int64_t>(bc1.globalBC()));
1337+
if (deltaBc < 3564) {
1338+
continue;
1339+
}
1340+
1341+
auto phi2 = std::atan2(mchTrack2.y(), mchTrack2.x());
1342+
auto deltaPhi = std::fabs(getDeltaPhi(phi1, phi2));
1343+
if (deltaPhi > deltaPhiMax) {
1344+
continue;
1345+
}
1346+
1347+
auto r2 = std::hypot(mchTrack2.x(), mchTrack2.y());
1348+
auto deltaR = r2 - r1;
1349+
if (deltaR > 10) {
1350+
continue;
1351+
}
1352+
1353+
auto nAttempts2 = mchTrackInfo2.nMatchAttempts;
1354+
1355+
float deltaAttempts = nAttempts2 - nAttempts1;
1356+
float deltaAttemptsRel = (nAttempts1 > 0) ? deltaAttempts / nAttempts1 : 0;
1357+
if (deltaAttemptsRel > 0.1) {
1358+
continue;
1359+
}
1360+
1361+
auto vz2 = collision2.posZ();
1362+
auto deltaZ = std::fabs(vz2 - vz1);
1363+
if (deltaZ > 1) {
1364+
continue;
1365+
}
1366+
1367+
// add the candidates of MCH track #2 to the list of mixed candidates of track #1
1368+
mchTrackInfo1.mixedMatchingCandidates.push_back(mchTrackInfo2.matchingCandidates);
1369+
// update the muon track index of the mixed candidates to the index of track #1
1370+
for (auto& candidate : mchTrackInfo1.mixedMatchingCandidates.back()) {
1371+
candidate.muonTrackId = mchIndex1;
1372+
}
1373+
}
1374+
}
1375+
}
1376+
12101377
template <typename TMFT, typename TMFTCOV>
12111378
o2::track::TrackParCovFwd transformMft(TMFT& mftTrack, TMFTCOV const& mftTrackCov)
12121379
{
@@ -1653,9 +1820,11 @@ struct GlobalMuonMatching {
16531820
mMchTrackToCandidateIndices.clear();
16541821
mMchTrackMatchingCandidates.clear();
16551822
mFwdTrackToGmmCandTrkIndex.clear();
1823+
mMchTrackInfos.clear();
16561824

16571825
LOGF(info, "Preparing candidates");
16581826
prepareMatchingCandidates(collisions, bcs, muonTracks, mftTracks, mftCovs);
1827+
prepareEventMixingMatchingCandidates(collisions, bcs, muonTracks, mftTracks, mftCovs);
16591828

16601829
LOGF(info, "Processing candidates");
16611830
processMatchingCandidates(collisions, muonTracks, mftTracks, mftCovs, clusters);

0 commit comments

Comments
 (0)