22 LOG(info) <<
"Initializing Global Forward Matcher";
26 setMFTRadLength(matchingParam.MFTRadLength);
27 LOG(info) <<
"MFT Radiation Length = " << mMFTDiskThicknessInX0 * 5.;
29 setAlignResiduals(matchingParam.alignResidual);
30 LOG(info) <<
"MFT Align residuals = " << mAlignResidual;
32 mMatchingPlaneZ = matchingParam.matchPlaneZ;
33 LOG(info) <<
"MFTMCH matchingPlaneZ = " << mMatchingPlaneZ;
35 auto& matchingFcnStr = matchingParam.matchFcn;
36 LOG(info) <<
"Match function string = " << matchingFcnStr;
38 if (matchingParam.isMatchUpstream()) {
39 LOG(info) <<
" ==> Setting Upstream matching.";
41 }
else if (matchingParam.matchingExternalFunction()) {
42 loadExternalMatchingFunction();
45 if (mMatchingFunctionMap.find(matchingFcnStr) != mMatchingFunctionMap.end()) {
46 mMatchFunc = mMatchingFunctionMap[matchingFcnStr];
48 LOG(info) <<
" Found built-in matching function " << matchingFcnStr;
50 throw std::invalid_argument(
"Invalid matching function! Aborting...");
54 auto& cutFcnStr = matchingParam.cutFcn;
55 LOG(info) <<
"MFTMCH pair candidate cut function string = " << cutFcnStr;
57 if (matchingParam.cutExternalFunction()) {
58 loadExternalCutFunction();
59 }
else if (mCutFunctionMap.find(cutFcnStr) != mCutFunctionMap.end()) {
60 mCutFunc = mCutFunctionMap[cutFcnStr];
61 LOG(info) <<
" Found built-in cut function " << cutFcnStr;
63 throw std::invalid_argument(
"Invalid cut function! Aborting...");
66 mUseMIDMCHMatch = matchingParam.useMIDMatch;
67 LOG(info) <<
"UseMIDMCH Matching = " << (mUseMIDMCHMatch ?
"true" :
"false");
69 mUseTrackTime = matchingParam.useTrackTime;
70 LOG(info) <<
"Use track time = " << (mUseTrackTime ?
"true" :
"false");
72 mSaveMode = matchingParam.saveMode;
73 LOG(info) <<
"Save mode MFTMCH candidates = " << mSaveMode;
75 mNCandidates = matchingParam.nCandidates;
89 if (!prepareMFTData() || !prepareMCHData() || !processMCHMIDMatches()) {
93 if (matchingParam.MCMatching) {
94 mMCTruthON ? doMCMatching() :
throw std::runtime_error(
"Label matching requries MC Labels!");
96 switch (mMatchingType) {
100 doMatching<kBestMatch>();
103 doMatching<kSaveAll>();
106 doMatching<kSaveTrainingData>();
109 doMatching<kSaveNCandidates>();
112 LOG(fatal) <<
"Invalid MFTMCH save mode";
119 LOG(fatal) <<
"Invalid MFTMCH matching mode";
130 LOG(info) <<
" Finalizing GlobalForwardMatch. Pushing " << mMatchedTracks.size() <<
" matched tracks";
136 mMCHROFTimes.clear();
138 mMFTROFTimes.clear();
140 mMFTClusters.clear();
141 mMatchedTracks.clear();
142 mMatchLabels.clear();
143 mMFTTrackROFContMapping.clear();
144 mMatchingInfo.clear();
149bool MatchGlobalFwd::prepareMCHData()
151 const auto& inp = *mRecoCont;
154 mMCHTracks = inp.getMCHTracks();
155 mMCHTrackROFRec = inp.getMCHTracksROFRecords();
157 mMCHTrkLabels = inp.getMCHTracksMCLabels();
159 int nROFs = mMCHTrackROFRec.size();
160 LOG(info) <<
"Loaded " << mMCHTracks.size() <<
" MCH Tracks in " << nROFs <<
" ROFs";
161 if (mMCHTracks.empty()) {
164 mMCHWork.reserve(mMCHTracks.size());
166 mMCHID2Work.resize(mMCHTracks.size(), -1);
167 static int BCDiffErrCount = 0;
168 constexpr int MAXBCDiffErrCount = 2;
170 for (
int irof = 0; irof < nROFs; irof++) {
171 const auto& rofRec = mMCHTrackROFRec[irof];
173 int nBC = rofRec.getBCData().differenceInBC(mStartIR);
175 if (BCDiffErrCount++ < MAXBCDiffErrCount) {
176 LOGP(alarm,
"wrong bunches diff. {} for current IR {} wrt 1st TF orbit {} in MCH data", nBC, rofRec.getBCData().asString(), mStartIR.
asString());
179 float tMin = nBC * o2::constants::lhc::LHCBunchSpacingMUS;
180 float tMax = (nBC + rofRec.getBCWidth()) * o2::constants::lhc::LHCBunchSpacingMUS;
181 auto mchTime = rofRec.getTimeMUS(mStartIR).first;
183 mMCHROFTimes.emplace_back(tMin, tMax);
184 LOG(
debug) <<
"MCH ROF # " << irof <<
" " << rofRec.getBCData() <<
" [tMin;tMax] = [" << tMin <<
";" << tMax <<
"]";
185 int trlim = rofRec.getFirstIdx() + rofRec.getNEntries();
186 for (
int it = rofRec.getFirstIdx(); it < trlim; it++) {
187 auto& trcOrig = mMCHTracks[it];
188 int nWorkTracks = mMCHWork.size();
189 mMCHID2Work[it] = nWorkTracks;
191 o2::mch::TrackParam tempParam(trcOrig.getZ(), trcOrig.getParameters(), trcOrig.getCovariances());
193 LOG(warning) <<
"MCH track propagation to matching plane failed!";
196 auto convertedTrack =
MCHtoFwd(tempParam);
197 auto& thisMCHTrack = mMCHWork.emplace_back(
TrackLocMCH{convertedTrack, {tMin, tMax}});
198 thisMCHTrack.setMCHTrackID(it);
199 thisMCHTrack.setTimeMUS(mchTime);
206bool MatchGlobalFwd::processMCHMIDMatches()
208 if (mUseMIDMCHMatch) {
209 const auto& inp = *mRecoCont;
212 mMCHMIDMatches = inp.getMCHMIDMatches();
214 LOG(info) <<
"Loaded " << mMCHMIDMatches.size() <<
" MCHMID matches";
216 for (
const auto& MIDMatch : mMCHMIDMatches) {
217 const auto& MCHId = MIDMatch.getMCHRef().getIndex();
218 const auto& MIDId = MIDMatch.getMIDRef().getIndex();
219 auto& thisMuonTrack = mMCHWork[mMCHID2Work[MCHId]];
220 LOG(
debug) <<
" MCHId: " << MCHId <<
" --> mMCHID2Work[MCHId]:" << mMCHID2Work[MCHId];
221 const auto&
IR = MIDMatch.getIR();
223 float tMin = (nBC - 1) * o2::constants::lhc::LHCBunchSpacingMUS;
224 float tMax = (nBC + 2) * o2::constants::lhc::LHCBunchSpacingMUS;
225 thisMuonTrack.setMIDTrackID(MIDId);
226 thisMuonTrack.setTimeMUS(MIDMatch.getTimeMUS(mStartIR).first);
227 thisMuonTrack.tBracket.set(tMin, tMax);
228 thisMuonTrack.setMIDMatchingChi2(MIDMatch.getMatchChi2OverNDF());
235bool MatchGlobalFwd::prepareMFTData()
237 const auto& inp = *mRecoCont;
240 mMFTClusterROFRec = inp.getMFTClustersROFRecords();
241 mMFTTrackClusIdx = inp.getMFTTracksClusterRefs();
242 const auto clusMFT = inp.getMFTClusters();
243 if (mMFTClusterROFRec.empty() || clusMFT.empty()) {
246 const auto patterns = inp.getMFTClustersPatterns();
247 auto pattIt = patterns.begin();
248 mMFTClusters.reserve(clusMFT.size());
252 mMFTTracks = inp.getMFTTracks();
253 mMFTTrackROFRec = inp.getMFTTracksROFRecords();
255 mMFTTrkLabels = inp.getMFTTracksMCLabels();
257 int nROFs = mMFTTrackROFRec.size();
259 LOG(info) <<
"Loaded " << mMFTTracks.size() <<
" MFT Tracks in " << nROFs <<
" ROFs";
260 if (mMFTTracks.empty()) {
263 mMFTWork.reserve(mMFTTracks.size());
264 static int BCDiffErrCount = 0;
265 constexpr int MAXBCDiffErrCount = 2;
267 for (
int irof = 0; irof < nROFs; irof++) {
268 const auto& rofRec = mMFTTrackROFRec[irof];
269 int nBC = rofRec.getBCData().differenceInBC(mStartIR);
271 if (BCDiffErrCount++ < MAXBCDiffErrCount) {
272 LOGP(alarm,
"TF dropped: wrong bunches diff. {} for current IR {} wrt 1st TF orbit {} in MFT data", nBC, rofRec.getBCData().asString(), mStartIR.
asString());
276 float tMin = (nBC + mMFTROFrameBiasInBC) * o2::constants::lhc::LHCBunchSpacingMUS;
277 float tMax = (nBC + mMFTROFrameLengthInBC + mMFTROFrameBiasInBC) * o2::constants::lhc::LHCBunchSpacingMUS;
278 if (!mMFTTriggered) {
279 auto irofCont = (nBC + mMFTROFrameBiasInBC) / mMFTROFrameLengthInBC;
280 if (mMFTTrackROFContMapping.size() <= irofCont) {
281 mMFTTrackROFContMapping.resize((1 + irofCont / 128) * 128, 0);
283 mMFTTrackROFContMapping[irofCont] = irof;
285 mMFTROFTimes.emplace_back(tMin, tMax);
286 LOG(
debug) <<
"MFT ROF # " << irof <<
" " << rofRec.getBCData() <<
" [tMin;tMax] = [" << tMin <<
";" << tMax <<
"]";
288 int trlim = rofRec.getFirstEntry() + rofRec.getNEntries();
289 for (
int it = rofRec.getFirstEntry(); it < trlim; it++) {
290 const auto& trcOrig = mMFTTracks[it];
292 int nWorkTracks = mMFTWork.size();
294 auto& trc = mMFTWork.emplace_back(
TrackLocMFT{trcOrig, {tMin, tMax}, irof});
295 trc.setParameters(trcOrig.getOutParam().getParameters());
296 trc.setZ(trcOrig.getOutParam().getZ());
297 trc.setCovariances(trcOrig.getOutParam().getCovariances());
298 trc.setTrackChi2(trcOrig.getOutParam().getTrackChi2());
302 trc.propagateToZ(mMatchingPlaneZ, mBz);
310void MatchGlobalFwd::loadMatches()
313 const auto& inp = *mRecoCont;
314 int nFakes = 0, nTrue = 0;
317 mMatchingInfoUpstream = inp.getMFTMCHMatches();
319 LOG(info) <<
"Loaded " << mMatchingInfoUpstream.size() <<
" MFTMCH Matches";
321 for (
const auto&
match : mMatchingInfoUpstream) {
322 auto MFTId =
match.getMFTTrackID();
323 auto MCHId =
match.getMCHTrackID();
324 LOG(
debug) <<
" ==> MFTId = " << MFTId <<
" MCHId = " << MCHId << std::endl;
326 auto& thisMCHTrack = mMCHWork[mMCHID2Work[MCHId]];
327 thisMCHTrack.setMatchInfo(
match);
328 mMatchedTracks.emplace_back(thisMCHTrack);
330 mMatchLabels.push_back(computeLabel(MCHId, MFTId));
331 mMatchLabels.back().isFake() ?
nFakes++ : nTrue++;
335 LOG(info) <<
" Done matching from upstream " << mMFTWork.size() <<
" MFT tracks with " << mMCHWork.size() <<
" MCH Tracks.";
337 LOG(info) <<
" nFakes = " <<
nFakes <<
" nTrue = " << nTrue;
342template <Int_t saveAllMode>
343void MatchGlobalFwd::doMatching()
346 int nMCHROFs = mMCHROFTimes.size();
348 LOG(info) <<
"Running MCH-MFT Track Matching.";
350 auto firstMFTTrackIdInROF = 0;
351 auto MFTROFId = mMFTWork.front().roFrame;
352 LOG(
debug) <<
"(*) nMCHROFs: " << nMCHROFs <<
", mMFTTracks.size(): " << mMFTTracks.size() <<
" MFTROFId: " << MFTROFId <<
", mMFTTrackROFRec.size(): " << mMFTTrackROFRec.size();
354 while ((firstMFTTrackIdInROF < mMFTTracks.size()) && (MFTROFId < mMFTTrackROFRec.size())) {
355 auto MFTROFId = mMFTWork[firstMFTTrackIdInROF].roFrame;
356 const auto& thisMFTBracket = mMFTROFTimes[MFTROFId];
357 auto nMFTTracksInROF = mMFTTrackROFRec[MFTROFId].getNEntries();
358 firstMFTTrackIdInROF = mMFTTrackROFRec[MFTROFId].getFirstEntry();
359 LOG(
debug) <<
"MFT ROF = " << MFTROFId <<
"; interval: [" << thisMFTBracket.getMin() <<
"," << thisMFTBracket.getMax() <<
"]";
360 LOG(
debug) <<
"ROF " << MFTROFId <<
" : firstMFTTrackIdInROF " << firstMFTTrackIdInROF <<
" ; nMFTTracksInROF = " << nMFTTracksInROF;
361 firstMFTTrackIdInROF += nMFTTracksInROF;
363 int mchROFMatchFirst = -1;
364 int mchROFMatchLast = -1;
367 while (mchROF < nMCHROFs && !(thisMFTBracket < mMCHROFTimes[mchROF])) {
369 if (mMCHTrackROFRec[mchROF].getNEntries() > 0 && !(thisMFTBracket.isOutside(mMCHROFTimes[mchROF]))) {
371 if (mchROFMatchFirst < 0) {
372 mchROFMatchFirst = mchROF;
375 mchROFMatchLast = mchROF;
380 if (mchROFMatchFirst < 0) {
383 LOG(
debug) <<
"FIRST MCH ROF " << mchROFMatchFirst <<
"; interval: ["
384 << mMCHROFTimes[mchROFMatchFirst].getMin() <<
","
385 << mMCHROFTimes[mchROFMatchFirst].getMax() <<
"] size: " << mMCHTrackROFRec[mchROFMatchFirst].getNEntries();
386 LOG(
debug) <<
"LAST MCH ROF " << mchROFMatchLast <<
"; interval: ["
387 << mMCHROFTimes[mchROFMatchLast].getMin() <<
","
388 << mMCHROFTimes[mchROFMatchLast].getMax() <<
"] size: " << mMCHTrackROFRec[mchROFMatchLast].getNEntries();
390 ROFMatch<saveAllMode>(MFTROFId, mchROFMatchFirst, mchROFMatchLast);
394 int nFakes = 0, nTrue = 0;
395 for (
auto& thisMCHTrack : mMCHWork) {
396 auto bestMFTMatchID = thisMCHTrack.getMFTTrackID();
397 if (bestMFTMatchID >= 0) {
399 mMatchLabels.push_back(computeLabel(thisMCHTrack.getMCHTrackID(), bestMFTMatchID));
400 mMatchLabels.back().isFake() ?
nFakes++ : nTrue++;
403 thisMCHTrack.setMFTTrackID(bestMFTMatchID);
404 LOG(
debug) <<
" thisMCHTrack.getMFTTrackID() = " << thisMCHTrack.getMFTTrackID()
405 <<
"; thisMCHTrack.getMFTMCHMatchingChi2() = " << thisMCHTrack.getMFTMCHMatchingChi2();
407 mMatchedTracks.emplace_back(thisMCHTrack);
408 mMatchingInfo.emplace_back(thisMCHTrack);
412 LOG(info) <<
" MFT-MCH Matching: nFakes = " <<
nFakes <<
" nTrue = " << nTrue;
415 int nFakes = 0, nTrue = 0;
416 auto& matchAllChi2 = mMatchingFunctionMap[
"matchALL"];
417 for (
auto MCHId = 0; MCHId < mMCHWork.size(); MCHId++) {
418 auto& thisMCHTrack = mMCHWork[MCHId];
419 for (
auto& pairCandidate : mCandidates[MCHId]) {
420 thisMCHTrack.setMFTTrackID(pairCandidate.second);
421 auto& thisMFTTrack = mMFTWork[pairCandidate.second];
422 auto chi2 = matchAllChi2(thisMCHTrack, thisMFTTrack);
423 thisMCHTrack.setMFTMCHMatchingScore(pairCandidate.first);
424 thisMCHTrack.setMFTMCHMatchingChi2(
chi2);
425 mMatchedTracks.emplace_back(thisMCHTrack);
426 mMatchingInfo.emplace_back(thisMCHTrack);
428 mMatchLabels.push_back(computeLabel(MCHId, pairCandidate.second));
429 mMatchLabels.back().isFake() ?
nFakes++ : nTrue++;
437template <Int_t saveAllMode>
438void MatchGlobalFwd::ROFMatch(
int MFTROFId,
int firstMCHROFId,
int lastMCHROFId)
441 const auto& thisMFTROF = mMFTTrackROFRec[MFTROFId];
442 const auto& thisMFTBracket = mMFTROFTimes[MFTROFId];
443 const auto& firstMCHROF = mMCHTrackROFRec[firstMCHROFId];
444 const auto& lastMCHROF = mMCHTrackROFRec[lastMCHROFId];
445 int nFakes = 0, nTrue = 0;
447 auto compare = [](
const std::pair<int, int>&
a,
const std::pair<int, int>&
b) {
448 return a.first <
b.first;
451 auto firstMFTTrackID = thisMFTROF.getFirstEntry();
452 auto lastMFTTrackID = firstMFTTrackID + thisMFTROF.getNEntries() - 1;
454 auto firstMCHTrackID = firstMCHROF.getFirstIdx();
455 auto lastMCHTrackID = lastMCHROF.getLastIdx();
457 auto nMFTTracks = thisMFTROF.getNEntries();
458 auto nMCHTracks = lastMCHTrackID - firstMCHTrackID + 1;
460 auto& matchAllChi2 = mMatchingFunctionMap[
"matchALL"];
462 LOG(
debug) <<
"Matching MFT ROF " << MFTROFId <<
" with MCH ROFs [" << firstMCHROFId <<
"->" << lastMCHROFId <<
"]";
463 LOG(
debug) <<
" firstMFTTrackID = " << firstMFTTrackID <<
" ; lastMFTTrackID = " << lastMFTTrackID;
464 LOG(
debug) <<
" firstMCHTrackID = " << firstMCHTrackID <<
" ; lastMCHTrackID = " << lastMCHTrackID;
465 LOG(
debug) <<
" thisMFTROF: " << thisMFTROF.getBCData();
466 LOG(
debug) <<
" firstMCHROF: " << firstMCHROF;
467 LOG(
debug) <<
" lastMCHROF: " << lastMCHROF;
470 for (
auto MCHId = firstMCHTrackID; MCHId <= lastMCHTrackID; MCHId++) {
471 auto& thisMCHTrack = mMCHWork[MCHId];
474 if (mUseTrackTime && (thisMFTBracket.isOutside(thisMCHTrack.tBracket))) {
479 for (
auto MFTId = firstMFTTrackID; MFTId <= lastMFTTrackID; MFTId++) {
480 auto& thisMFTTrack = mMFTWork[MFTId];
482 matchLabel = computeLabel(MCHId, MFTId);
484 if (mCutFunc(thisMCHTrack, thisMFTTrack)) {
485 thisMCHTrack.countMFTCandidate();
488 thisMCHTrack.setCloseMatch();
491 auto score = mMatchFunc(thisMCHTrack, thisMFTTrack);
492 if (score < thisMCHTrack.getMFTMCHMatchingScore()) {
493 thisMCHTrack.setMFTTrackID(MFTId);
494 auto chi2 = matchAllChi2(thisMCHTrack, thisMFTTrack);
495 thisMCHTrack.setMFTMCHMatchingScore(score);
496 thisMCHTrack.setMFTMCHMatchingChi2(
chi2);
499 thisMCHTrack.setMFTTrackID(MFTId);
500 mMatchedTracks.emplace_back(thisMCHTrack);
501 mMatchingInfo.emplace_back(thisMCHTrack);
503 mMatchLabels.push_back(matchLabel);
504 mMatchLabels.back().isFake() ?
nFakes++ : nTrue++;
509 auto score = mMatchFunc(thisMCHTrack, thisMFTTrack);
510 std::pair<float, int> scoreID = {score, MFTId};
511 mCandidates[MCHId].push_back(scoreID);
512 std::sort(mCandidates[MCHId].
begin(), mCandidates[MCHId].
end(),
compare);
513 if (mCandidates[MCHId].
size() > mNCandidates) {
514 mCandidates[MCHId].pop_back();
519 thisMCHTrack.setMFTTrackID(MFTId);
520 mMatchingInfo.emplace_back(thisMCHTrack);
521 mMCHMatchPlaneParams.emplace_back(thisMCHTrack);
524 mMatchLabels.push_back(matchLabel);
525 mMatchLabels.back().isFake() ?
nFakes++ : nTrue++;
530 auto bestMFTMatchID = thisMCHTrack.getMFTTrackID();
531 LOG(
debug) <<
" Matching MCHId = " << MCHId <<
" ==> bestMFTMatchID = " << thisMCHTrack.getMFTTrackID() <<
" ; thisMCHTrack.getMFTMCHMatchingChi2() = " << thisMCHTrack.getMFTMCHMatchingChi2();
532 LOG(
debug) <<
" MCH COV<X,X> = " << thisMCHTrack.getSigma2X() <<
" ; COV<Y,Y> = " << thisMCHTrack.getSigma2Y() <<
" ; pt = " << thisMCHTrack.getPt();
536 LOG(
debug) <<
"Finished matching MFT ROF " << MFTROFId <<
": " << nMFTTracks <<
" MFT tracks and " << nMCHTracks <<
" MCH Tracks.";
543o2::MCCompLabel MatchGlobalFwd::computeLabel(
const int MCHId,
const int MFTId)
545 const auto& mchlabel = mMCHTrkLabels[MCHId];
546 const auto& mftlabel = mMFTTrkLabels[MFTId];
548 matchLabel.
setFakeFlag(mftlabel.compare(mchlabel) != 1);
550 LOG(
debug) <<
" Computing MFTMCH matching label: MFTTruth = " << mftlabel <<
" ; MCHTruth = " << mchlabel <<
" ; Computed label = " << matchLabel;
556void MatchGlobalFwd::doMCMatching()
558 int nFakes = 0, nTrue = 0;
561 for (
auto MCHId = 0; MCHId < mMCHWork.size(); MCHId++) {
562 auto& thisMCHTrack = mMCHWork[MCHId];
563 const o2::MCCompLabel& thisMCHLabel = mMCHTrkLabels[mMCHID2Work[MCHId]];
565 LOG(
debug) <<
" MCH Track # " << MCHId <<
" Label: " << thisMCHLabel;
566 if (!((thisMCHLabel).isSet())) {
569 for (
auto MFTId = 0; MFTId < mMFTWork.size(); MFTId++) {
570 auto& thisMFTTrack = mMFTWork[MFTId];
575 thisMCHTrack.setCloseMatch();
576 auto chi2 = mMatchFunc(thisMCHTrack, thisMFTTrack);
577 thisMCHTrack.setMFTTrackID(MFTId);
578 thisMCHTrack.setMFTMCHMatchingChi2(
chi2);
579 mMatchedTracks.emplace_back(thisMCHTrack);
580 mMatchingInfo.emplace_back(thisMCHTrack);
581 mMatchLabels.push_back(matchLabel);
582 auto bestMFTMatchID = thisMCHTrack.getMFTTrackID();
583 LOG(
debug) <<
" Matching MCHId = " << MCHId <<
" ==> bestMFTMatchID = " << thisMCHTrack.getMFTTrackID() <<
" ; thisMCHTrack.getMFTMCHMatchingChi2() = " << thisMCHTrack.getMFTMCHMatchingChi2();
584 LOG(
debug) <<
" MCH COV<X,X> = " << thisMCHTrack.getSigma2X() <<
" ; COV<Y,Y> = " << thisMCHTrack.getSigma2Y() <<
" ; pt = " << thisMCHTrack.getPt();
585 LOG(
debug) <<
" Label: " << matchLabel;
592 auto nMFTTracks = mMFTWork.size();
593 auto nMCHTracks = mMCHWork.size();
595 LOG(info) <<
" Done MC matching of " << nMFTTracks <<
" MFT tracks with " << nMCHTracks <<
" MCH Tracks. nFakes = " <<
nFakes <<
" nTrue = " << nTrue;
599void MatchGlobalFwd::fitTracks()
601 LOG(info) <<
"Fitting global muon tracks...";
605 for (
auto& track : mMatchedTracks) {
606 LOG(
debug) <<
" ==> Fitting Global Track # " <<
GTrackID <<
" with MFT track # " <<
track.getMFTTrackID() <<
":";
607 fitGlobalMuonTrack(track);
611 LOG(info) <<
"Finished fitting global muon tracks.";
618 const auto& mftTrack = mMFTTracks[MFTMatchId];
619 const auto& mftTrackOut = mMFTWork[MFTMatchId];
620 auto ncls = mftTrack.getNumberOfPoints();
621 auto offset = mftTrack.getExternalClusterIndexOffset();
623 LOG(
debug) <<
"***************************** Start Fitting new track *****************************";
624 LOG(
debug) <<
"N Clusters = " << ncls <<
" Best MFT Track Match ID " << gTrack.
getMFTTrackID() <<
" MCHTrack: X = " << gTrack.
getX() <<
" Y = " << gTrack.
getY() <<
" Z = " << gTrack.
getZ() <<
" Tgl = " << gTrack.
getTanl() <<
" Phi = " << gTrack.
getPhi() <<
" pz = " << gTrack.
getPz() <<
" qpt = " << 1.0 / gTrack.
getInvQPt();
626 LOG(
debug) <<
"MFTTrack: X = " << mftTrackOut.getX()
627 <<
" Y = " << mftTrackOut.getY() <<
" Z = " << mftTrackOut.getZ()
628 <<
" Tgl = " << mftTrackOut.getTanl()
629 <<
" Phi = " << mftTrackOut.getPhi() <<
" pz = " << mftTrackOut.getPz()
630 <<
" qpt = " << 1.0 / mftTrackOut.getInvQPt();
631 LOG(
debug) <<
" initTrack GlobalTrack: q/pt = " << gTrack.
getInvQPt() << std::endl;
633 auto lastLayer = mMFTMapping.
ChipID2Layer[mMFTClusters[
offset + ncls - 1].getSensorID()];
634 LOG(
debug) <<
"Starting by MFTCluster offset " <<
offset + ncls - 1 <<
" at lastLayer " << lastLayer;
636 for (
int icls = ncls - 1; icls > -1; --icls) {
637 auto clsEntry = mMFTTrackClusIdx[
offset + icls];
638 auto& thiscluster = mMFTClusters[clsEntry];
639 LOG(
debug) <<
"Computing MFTCluster clsEntry " << clsEntry <<
" at Z = " << thiscluster.getZ();
641 computeCluster(gTrack, thiscluster, lastLayer);
653 const auto& clx = cluster.
getX();
654 const auto& cly = cluster.
getY();
655 const auto& clz = cluster.
getZ();
656 const auto& sigmaX2 = cluster.
getSigmaY2() * mAlignResidual * mAlignResidual;
658 const auto& sigmaY2 = cluster.
getSigmaZ2() * mAlignResidual * mAlignResidual;
662 LOG(
debug) <<
"computeCluster: X = " << clx <<
" Y = " << cly <<
" Z = " << clz <<
" nCluster = " << newLayerID;
664 if (!propagateToNextClusterWithMCS(track, clz, startingLayerID, newLayerID)) {
668 LOG(
debug) <<
" AfterExtrap: X = " <<
track.getX() <<
" Y = " <<
track.getY() <<
" Z = " <<
track.getZ() <<
" Tgl = " <<
track.getTanl() <<
" Phi = " <<
track.getPhi() <<
" pz = " <<
track.getPz() <<
" q/pt = " <<
track.getInvQPt();
669 LOG(
debug) <<
"Track covariances after extrap:" << std::endl
670 <<
track.getCovariances() << std::endl;
673 const std::array<float, 2>&
pos = {clx, cly};
674 const std::array<float, 2>& cov = {sigmaX2, sigmaY2};
677 LOG(
debug) <<
" New Cluster: X = " << clx <<
" Y = " << cly <<
" Z = " << clz;
678 LOG(
debug) <<
" AfterKalman: X = " <<
track.getX() <<
" Y = " <<
track.getY() <<
" Z = " <<
track.getZ() <<
" Tgl = " <<
track.getTanl() <<
" Phi = " <<
track.getPhi() <<
" pz = " <<
track.getPz() <<
" q/pt = " <<
track.getInvQPt();
680 LOG(
debug) <<
"Track covariances after Kalman update: \n"
681 <<
track.getCovariances() << std::endl;
691 mMFTROFrameLengthMUS = fums;
692 mMFTROFrameLengthMUSInv = 1. / mMFTROFrameLengthMUS;
693 mMFTROFrameLengthInBC = std::max(1,
int(mMFTROFrameLengthMUS / (o2::constants::lhc::LHCBunchSpacingNS * 1e-3)));
699 mMFTROFrameLengthInBC = nbc;
700 mMFTROFrameLengthMUS = nbc * o2::constants::lhc::LHCBunchSpacingNS * 1e-3;
701 mMFTROFrameLengthMUSInv = 1. / mMFTROFrameLengthMUS;
707 mMFTROFrameBiasInBC = nbc;
708 mMFTROFrameBiasMUS = nbc * o2::constants::lhc::LHCBunchSpacingNS * 1e-3;
709 mMFTROFrameBiasMUSInv = 1. / mMFTROFrameBiasMUS;
719 LOG(error) <<
"Empty bunch filling is provided to MatchGlobalFwd, checks using it should be ignored";
723 for (
int i = o2::constants::lhc::LHCMaxBunches;
i--;) {
727 mClosestBunchAbove[
i] = bcAbove;
730 for (
int i = 0;
i < o2::constants::lhc::LHCMaxBunches;
i++) {
734 mClosestBunchBelow[
i] = bcBelow;
747 double alpha1, alpha3, alpha4, x2, x3, x4;
753 x2 = TMath::ATan2(-alpha3, -alpha1);
754 x3 = -1. / TMath::Sqrt(alpha3 * alpha3 + alpha1 * alpha1);
755 x4 = alpha4 * -x3 * TMath::Sqrt(1 + alpha3 * alpha3);
757 auto K = alpha1 * alpha1 + alpha3 * alpha3;
758 auto K32 = K * TMath::Sqrt(K);
759 auto L = TMath::Sqrt(alpha3 * alpha3 + 1);
767 std::cout <<
" MCHtoGlobal - MCH Covariances:\n";
768 std::cout <<
" mchParam.getCovariances()(0, 0) = "
770 <<
" ; mchParam.getCovariances()(2, 2) = "
797 jacobian(2, 1) = -alpha3 / K;
798 jacobian(2, 3) = alpha1 / K;
800 jacobian(3, 1) = alpha1 / K32;
801 jacobian(3, 3) = alpha3 / K32;
803 jacobian(4, 1) = -alpha1 * alpha4 * L / K32;
804 jacobian(4, 3) = alpha3 * alpha4 * (1 / (TMath::Sqrt(K) * L) - L / K32);
805 jacobian(4, 4) = L / TMath::Sqrt(K);
808 covariances = ROOT::Math::Similarity(jacobian, covariances);
813 convertedTrack.
setZ(mchParam.
getZ());
814 convertedTrack.
setPhi(x2);
820 return convertedTrack;
830 double alpha1, alpha3, alpha4, x2, x3, x4;
836 auto sinx2 = TMath::Sin(x2);
837 auto cosx2 = TMath::Cos(x2);
841 alpha4 = x4 / TMath::Sqrt(x3 * x3 + sinx2 * sinx2);
843 auto K = TMath::Sqrt(x3 * x3 + sinx2 * sinx2);
872 jacobian(1, 2) = -sinx2 / x3;
873 jacobian(1, 3) = -cosx2 / (x3 * x3);
877 jacobian(3, 2) = cosx2 / x3;
878 jacobian(3, 3) = -sinx2 / (x3 * x3);
880 jacobian(4, 2) = -x4 * sinx2 * cosx2 / K3;
881 jacobian(4, 3) = -x3 * x4 / K3;
882 jacobian(4, 4) = 1 / K;
884 covariances = ROOT::Math::Similarity(jacobian, covariances);
886 double cov[] = {covariances(0, 0), covariances(1, 0), covariances(1, 1), covariances(2, 0), covariances(2, 1), covariances(2, 2), covariances(3, 0), covariances(3, 1), covariances(3, 2), covariances(3, 3), covariances(4, 0), covariances(4, 1), covariances(4, 2), covariances(4, 3), covariances(4, 4)};
887 double param[] = {fwdtrack.
getX(), alpha1, fwdtrack.
getY(), alpha3, alpha4};
896 mClosestBunchAbove[0] = mClosestBunchAbove[0] = -1;
903 SMatrix55Sym I = ROOT::Math::SMatrixIdentity(), H_k, V_k;
904 SVector5 m_k(mftTrack.getX(), mftTrack.getY(), mftTrack.getPhi(),
905 mftTrack.getTanl(), mftTrack.getInvQPt()),
909 V_k(0, 0) = mftTrack.getCovariances()(0, 0);
910 V_k(1, 1) = mftTrack.getCovariances()(1, 1);
911 V_k(2, 2) = mftTrack.getCovariances()(2, 2);
912 V_k(3, 3) = mftTrack.getCovariances()(3, 3);
913 V_k(4, 4) = mftTrack.getCovariances()(4, 4);
921 SMatrix55Std invResCov = (V_k + ROOT::Math::Similarity(H_k, GlobalMuonTrackCovariances));
925 SMatrix55Std K_k = GlobalMuonTrackCovariances * ROOT::Math::Transpose(H_k) * invResCov;
928 r_k_kminus1 = m_k - H_k * GlobalMuonTrackParameters;
933 auto matchChi2Track = ROOT::Math::Similarity(r_k_kminus1, invResCov);
935 return matchChi2Track;
946 SVector4 m_k(mftTrack.getX(), mftTrack.getY(), mftTrack.getPhi(),
951 V_k(0, 0) = mftTrack.getCovariances()(0, 0);
952 V_k(1, 1) = mftTrack.getCovariances()(1, 1);
953 V_k(2, 2) = mftTrack.getCovariances()(2, 2);
954 V_k(3, 3) = mftTrack.getCovariances()(3, 3);
961 SMatrix44 invResCov = (V_k + ROOT::Math::Similarity(H_k, GlobalMuonTrackCovariances));
965 SMatrix54 K_k = GlobalMuonTrackCovariances * ROOT::Math::Transpose(H_k) * invResCov;
968 r_k_kminus1 = m_k - H_k * GlobalMuonTrackParameters;
973 auto matchChi2Track = ROOT::Math::Similarity(r_k_kminus1, invResCov);
975 return matchChi2Track; };
985 SVector2 m_k(mftTrack.getX(), mftTrack.getY()), r_k_kminus1;
988 V_k(0, 0) = mftTrack.getCovariances()(0, 0);
989 V_k(1, 1) = mftTrack.getCovariances()(1, 1);
994 SMatrix22 invResCov = (V_k + ROOT::Math::Similarity(H_k, GlobalMuonTrackCovariances));
998 SMatrix52 K_k = GlobalMuonTrackCovariances * ROOT::Math::Transpose(H_k) * invResCov;
1001 r_k_kminus1 = m_k - H_k * GlobalMuonTrackParameters;
1002 auto matchChi2Track = ROOT::Math::Similarity(r_k_kminus1, invResCov);
1004 return matchChi2Track; };
1012 Double_t LAbs = 415.;
1013 Double_t mumass = 0.106;
1016 if (mMatchingPlaneZ >= -90.0) {
1019 l = 505.0 + mMatchingPlaneZ;
1024 auto dx = mftTrack.getX() - mchTrack.
getX();
1025 auto dy = mftTrack.getY() - mchTrack.
getY();
1026 auto dthetax = TMath::ATan(mftTrack.getPx() / TMath::Abs(mftTrack.getPz())) - TMath::ATan(mchTrack.
getPx() / TMath::Abs(mchTrack.
getPz()));
1027 auto dthetay = TMath::ATan(mftTrack.getPy() / TMath::Abs(mftTrack.getPz())) - TMath::ATan(mchTrack.
getPy() / TMath::Abs(mchTrack.
getPz()));
1031 auto pMCH = mchTrack.
getP();
1032 auto lorentzbeta = pMCH / TMath::Sqrt(mumass * mumass + pMCH * pMCH);
1033 auto zMS = copysign(1.0, mchTrack.
getCharge());
1034 auto thetaMS = 13.6 / (1000.0 * pMCH * lorentzbeta * 1.0) * zMS * TMath::Sqrt(60.0 * l / LAbs) * (1.0 + 0.038 * TMath::Log(60.0 * l / LAbs));
1035 auto xMS = thetaMS * l / TMath::Sqrt(3.0);
1040 auto dxnorm = dx / xMS;
1041 auto dynorm = dy / xMS;
1042 auto dthetaxnorm = dthetax / thetaMS;
1043 auto dthetaynorm = dthetay / thetaMS;
1047 auto dxrot = dxnorm * TMath::Cos(TMath::Pi() / 4.0) - dthetaxnorm * TMath::Sin(TMath::Pi() / 4.0);
1048 auto dthetaxrot = dxnorm * TMath::Sin(TMath::Pi() / 4.0) + dthetaxnorm * TMath::Cos(TMath::Pi() / 4.0);
1049 auto dyrot = dynorm * TMath::Cos(TMath::Pi() / 4.0) - dthetaynorm * TMath::Sin(TMath::Pi() / 4.0);
1050 auto dthetayrot = dynorm * TMath::Sin(TMath::Pi() / 4.0) + dthetaynorm * TMath::Cos(TMath::Pi() / 4.0);
1055 auto dxcircle = dxrot;
1056 auto dycircle = dyrot;
1057 auto dthetaxcircle = dthetaxrot / k;
1058 auto dthetaycircle = dthetayrot / k;
1062 auto scoreX = TMath::Sqrt(dxcircle * dxcircle + dthetaxcircle * dthetaxcircle);
1063 auto scoreY = TMath::Sqrt(dycircle * dycircle + dthetaycircle * dthetaycircle);
1064 auto score = TMath::Sqrt(scoreX * scoreX + scoreY * scoreY);
1077 auto dx = mchTrack.
getX() - mftTrack.getX();
1078 auto dy = mchTrack.
getY() - mftTrack.getY();
1079 auto dPhi = mchTrack.
getPhi() - mftTrack.getPhi();
1080 auto dTanl = TMath::Abs(mchTrack.
getTanl() - mftTrack.getTanl());
1081 auto dInvQPt = TMath::Abs(mchTrack.
getInvQPt() - mftTrack.getInvQPt());
1082 auto distanceSq = dx * dx + dy * dy;
1084 auto cutPhiSq = 9 * (mchTrack.
getSigma2Phi() + mftTrack.getSigma2Phi());
1085 auto cutTanlSq = 9 * (mchTrack.
getSigma2Tanl() + mftTrack.getSigma2Tanl());
1086 auto cutInvQPtSq = 9 * (mchTrack.
getSigma2InvQPt() + mftTrack.getSigma2InvQPt());
1087 return (distanceSq < cutDistanceSq) and (dPhi * dPhi < cutPhiSq) and (dTanl * dTanl < cutTanlSq) and (dInvQPt * dInvQPt < cutInvQPtSq);
1092 auto dx = mchTrack.
getX() - mftTrack.getX();
1093 auto dy = mchTrack.
getY() - mftTrack.getY();
1094 auto dPhi = mchTrack.
getPhi() - mftTrack.getPhi();
1095 auto dTanl = TMath::Abs(mchTrack.
getTanl() - mftTrack.getTanl());
1096 auto distanceSq = dx * dx + dy * dy;
1098 auto cutPhiSq = 9 * (mchTrack.
getSigma2Phi() + mftTrack.getSigma2Phi());
1099 auto cutTanlSq = 9 * (mchTrack.
getSigma2Tanl() + mftTrack.getSigma2Tanl());
1100 return (distanceSq < cutDistanceSq) and (dPhi * dPhi < cutPhiSq) and (dTanl * dTanl < cutTanlSq);
General auxilliary methods.
Class to perform MFT MCH (and MID) matching.
std::int16_t getSensorID() const
int getLastFilledBC(int dir=-1) const
bool testBC(int bcID, int dir=-1) const
int getFirstFilledBC(int dir=-1) const
void setFakeFlag(bool v=true)
static const GlobalFwdMatchingParam & Instance()
void setBunchFilling(const o2::BunchFilling &bf)
set Bunch filling and init helpers for validation by BCs
void setMFTROFrameLengthMUS(float fums)
set MFT ROFrame duration in BC (continuous mode only)
void setMFTROFrameLengthInBC(int nbc)
set MFT ROFrame bias in BC (continuous mode only) or time shift applied already as MFTAlpideParam....
void setMFTROFrameBiasInBC(int nbc)
void run(const o2::globaltracking::RecoContainer &inp)
@ MATCHINGFUNC
MFT-MCH matching modes.
@ MATCHINGUPSTREAM
MFT-MCH track matching loaded from input file.
o2::mch::TrackParam FwdtoMCH(const o2::dataformats::GlobalFwdTrack &fwdtrack)
Converts FwdTrack parameters to MCH coordinate system.
o2::dataformats::GlobalFwdTrack MCHtoFwd(const o2::mch::TrackParam &mchTrack)
Converts mchTrack parameters to Forward coordinate system.
static constexpr std::array< int, NChips > ChipID2Layer
track parameters for internal use
Double_t getInverseBendingMomentum() const
return inverse bending momentum (GeV/c ** -1) times the charge (assumed forward motion)
Double_t getNonBendingCoor() const
return non bending coordinate (cm)
Double_t getZ() const
return Z coordinate (cm)
Double_t getNonBendingSlope() const
return non bending slope (cm ** -1)
const TMatrixD & getCovariances() const
Double_t getBendingCoor() const
return bending coordinate (cm)
Double_t getBendingSlope() const
return bending slope (cm ** -1)
Double_t getCharge() const
return the charge (assumed forward motion)
void setCovariances(const SMatrix55Sym &covariances)
Double_t getSigma2Y() const
const SMatrix55Sym & getCovariances() const
Double_t getSigma2InvQPt() const
Double_t getSigma2Phi() const
Double_t getSigma2Tanl() const
Double_t getSigma2X() const
void setCharge(Double_t charge)
set the charge (assumed forward motion)
void setTanl(Double_t tanl)
void setInvQPt(Double_t invqpt)
Double_t getZ() const
return Z coordinate (cm)
void setPhi(Double_t phi)
const SMatrix5 & getParameters() const
return track parameters
Double_t getCharge() const
return the charge (assumed forward motion)
void setZ(Double_t z)
set Z coordinate (cm)
Double_t getInvQPt() const
bool match(const std::vector< std::string > &queries, const char *pattern)
GLboolean GLboolean GLboolean b
GLboolean GLboolean GLboolean GLboolean a
const bool const int TrackITSInternal< NLayers > & track
void bringToPMPiGend(double &phi)
void convertCompactClusters(gsl::span< const itsmft::CompClusterExt > clusters, gsl::span< const unsigned char >::iterator &pattIt, std::vector< o2::BaseCluster< float > > &output, const itsmft::TopologyDictionary *dict)
convert compact clusters to 3D spacepoints into std::vector<o2::BaseCluster<float>>
Enum< T >::Iterator begin(Enum< T >)
std::string asString() const
int64_t differenceInBC(const InteractionRecord &other) const
o2::InteractionRecord startIR
void compare(std::string_view s1, std::string_view s2)
LOG(info)<< "Compressed in "<< sw.CpuTime()<< " s"