21 LOG(info) <<
"Initializing Global Forward Matcher";
25 setMFTRadLength(matchingParam.MFTRadLength);
26 LOG(info) <<
"MFT Radiation Length = " << mMFTDiskThicknessInX0 * 5.;
28 setAlignResiduals(matchingParam.alignResidual);
29 LOG(info) <<
"MFT Align residuals = " << mAlignResidual;
31 mMatchingPlaneZ = matchingParam.matchPlaneZ;
32 LOG(info) <<
"MFTMCH matchingPlaneZ = " << mMatchingPlaneZ;
34 auto& matchingFcnStr = matchingParam.matchFcn;
35 LOG(info) <<
"Match function string = " << matchingFcnStr;
37 if (matchingParam.isMatchUpstream()) {
38 LOG(info) <<
" ==> Setting Upstream matching.";
40 }
else if (matchingParam.matchingExternalFunction()) {
41 loadExternalMatchingFunction();
44 if (mMatchingFunctionMap.find(matchingFcnStr) != mMatchingFunctionMap.end()) {
45 mMatchFunc = mMatchingFunctionMap[matchingFcnStr];
47 LOG(info) <<
" Found built-in matching function " << matchingFcnStr;
49 throw std::invalid_argument(
"Invalid matching function! Aborting...");
53 auto& cutFcnStr = matchingParam.cutFcn;
54 LOG(info) <<
"MFTMCH pair candidate cut function string = " << cutFcnStr;
56 if (matchingParam.cutExternalFunction()) {
57 loadExternalCutFunction();
58 }
else if (mCutFunctionMap.find(cutFcnStr) != mCutFunctionMap.end()) {
59 mCutFunc = mCutFunctionMap[cutFcnStr];
60 LOG(info) <<
" Found built-in cut function " << cutFcnStr;
62 throw std::invalid_argument(
"Invalid cut function! Aborting...");
65 mUseMIDMCHMatch = matchingParam.useMIDMatch;
66 LOG(info) <<
"UseMIDMCH Matching = " << (mUseMIDMCHMatch ?
"true" :
"false");
68 mUseTrackTime = matchingParam.useTrackTime;
69 LOG(info) <<
"Use track time = " << (mUseTrackTime ?
"true" :
"false");
71 mSaveMode = matchingParam.saveMode;
72 LOG(info) <<
"Save mode MFTMCH candidates = " << mSaveMode;
74 mNCandidates = matchingParam.nCandidates;
88 if (!prepareMFTData() || !prepareMCHData() || !processMCHMIDMatches()) {
92 if (matchingParam.MCMatching) {
93 mMCTruthON ? doMCMatching() :
throw std::runtime_error(
"Label matching requries MC Labels!");
95 switch (mMatchingType) {
99 doMatching<kBestMatch>();
102 doMatching<kSaveAll>();
105 doMatching<kSaveTrainingData>();
108 doMatching<kSaveNCandidates>();
111 LOG(fatal) <<
"Invalid MFTMCH save mode";
118 LOG(fatal) <<
"Invalid MFTMCH matching mode";
129 LOG(info) <<
" Finalizing GlobalForwardMatch. Pushing " << mMatchedTracks.size() <<
" matched tracks";
135 mMCHROFTimes.clear();
137 mMFTROFTimes.clear();
139 mMFTClusters.clear();
140 mMatchedTracks.clear();
141 mMatchLabels.clear();
142 mMFTTrackROFContMapping.clear();
143 mMatchingInfo.clear();
148bool MatchGlobalFwd::prepareMCHData()
150 const auto& inp = *mRecoCont;
153 mMCHTracks = inp.getMCHTracks();
154 mMCHTrackROFRec = inp.getMCHTracksROFRecords();
156 mMCHTrkLabels = inp.getMCHTracksMCLabels();
158 int nROFs = mMCHTrackROFRec.size();
159 LOG(info) <<
"Loaded " << mMCHTracks.size() <<
" MCH Tracks in " << nROFs <<
" ROFs";
160 if (mMCHTracks.empty()) {
163 mMCHWork.reserve(mMCHTracks.size());
165 mMCHID2Work.resize(mMCHTracks.size(), -1);
166 static int BCDiffErrCount = 0;
167 constexpr int MAXBCDiffErrCount = 2;
169 for (
int irof = 0; irof < nROFs; irof++) {
170 const auto& rofRec = mMCHTrackROFRec[irof];
172 int nBC = rofRec.getBCData().differenceInBC(mStartIR);
174 if (BCDiffErrCount++ < MAXBCDiffErrCount) {
175 LOGP(alarm,
"wrong bunches diff. {} for current IR {} wrt 1st TF orbit {} in MCH data", nBC, rofRec.getBCData().asString(), mStartIR.
asString());
180 auto mchTime = rofRec.getTimeMUS(mStartIR).first;
182 mMCHROFTimes.emplace_back(tMin, tMax);
183 LOG(
debug) <<
"MCH ROF # " << irof <<
" " << rofRec.getBCData() <<
" [tMin;tMax] = [" << tMin <<
";" << tMax <<
"]";
184 int trlim = rofRec.getFirstIdx() + rofRec.getNEntries();
185 for (
int it = rofRec.getFirstIdx(); it < trlim; it++) {
186 auto& trcOrig = mMCHTracks[it];
187 int nWorkTracks = mMCHWork.size();
188 mMCHID2Work[it] = nWorkTracks;
190 o2::mch::TrackParam tempParam(trcOrig.getZ(), trcOrig.getParameters(), trcOrig.getCovariances());
192 LOG(warning) <<
"MCH track propagation to matching plane failed!";
195 auto convertedTrack =
MCHtoFwd(tempParam);
196 auto& thisMCHTrack = mMCHWork.emplace_back(
TrackLocMCH{convertedTrack, {tMin, tMax}});
197 thisMCHTrack.setMCHTrackID(it);
198 thisMCHTrack.setTimeMUS(mchTime);
205bool MatchGlobalFwd::processMCHMIDMatches()
207 if (mUseMIDMCHMatch) {
208 const auto& inp = *mRecoCont;
211 mMCHMIDMatches = inp.getMCHMIDMatches();
213 LOG(info) <<
"Loaded " << mMCHMIDMatches.size() <<
" MCHMID matches";
215 for (
const auto& MIDMatch : mMCHMIDMatches) {
216 const auto& MCHId = MIDMatch.getMCHRef().getIndex();
217 const auto& MIDId = MIDMatch.getMIDRef().getIndex();
218 auto& thisMuonTrack = mMCHWork[mMCHID2Work[MCHId]];
219 LOG(
debug) <<
" MCHId: " << MCHId <<
" --> mMCHID2Work[MCHId]:" << mMCHID2Work[MCHId];
220 const auto&
IR = MIDMatch.getIR();
224 thisMuonTrack.setMIDTrackID(MIDId);
225 thisMuonTrack.setTimeMUS(MIDMatch.getTimeMUS(mStartIR).first);
226 thisMuonTrack.tBracket.set(tMin, tMax);
227 thisMuonTrack.setMIDMatchingChi2(MIDMatch.getMatchChi2OverNDF());
234bool MatchGlobalFwd::prepareMFTData()
236 const auto& inp = *mRecoCont;
239 mMFTClusterROFRec = inp.getMFTClustersROFRecords();
240 mMFTTrackClusIdx = inp.getMFTTracksClusterRefs();
241 const auto clusMFT = inp.getMFTClusters();
242 if (mMFTClusterROFRec.empty() || clusMFT.empty()) {
245 const auto patterns = inp.getMFTClustersPatterns();
246 auto pattIt = patterns.begin();
247 mMFTClusters.reserve(clusMFT.size());
251 mMFTTracks = inp.getMFTTracks();
252 mMFTTrackROFRec = inp.getMFTTracksROFRecords();
254 mMFTTrkLabels = inp.getMFTTracksMCLabels();
256 int nROFs = mMFTTrackROFRec.size();
258 LOG(info) <<
"Loaded " << mMFTTracks.size() <<
" MFT Tracks in " << nROFs <<
" ROFs";
259 if (mMFTTracks.empty()) {
262 mMFTWork.reserve(mMFTTracks.size());
263 static int BCDiffErrCount = 0;
264 constexpr int MAXBCDiffErrCount = 2;
266 for (
int irof = 0; irof < nROFs; irof++) {
267 const auto& rofRec = mMFTTrackROFRec[irof];
268 int nBC = rofRec.getBCData().differenceInBC(mStartIR);
270 if (BCDiffErrCount++ < MAXBCDiffErrCount) {
271 LOGP(alarm,
"TF dropped: wrong bunches diff. {} for current IR {} wrt 1st TF orbit {} in MFT data", nBC, rofRec.getBCData().asString(), mStartIR.
asString());
277 if (!mMFTTriggered) {
278 auto irofCont = (nBC + mMFTROFrameBiasInBC) / mMFTROFrameLengthInBC;
279 if (mMFTTrackROFContMapping.size() <= irofCont) {
280 mMFTTrackROFContMapping.resize((1 + irofCont / 128) * 128, 0);
282 mMFTTrackROFContMapping[irofCont] = irof;
284 mMFTROFTimes.emplace_back(tMin, tMax);
285 LOG(
debug) <<
"MFT ROF # " << irof <<
" " << rofRec.getBCData() <<
" [tMin;tMax] = [" << tMin <<
";" << tMax <<
"]";
287 int trlim = rofRec.getFirstEntry() + rofRec.getNEntries();
288 for (
int it = rofRec.getFirstEntry(); it < trlim; it++) {
289 const auto& trcOrig = mMFTTracks[it];
291 int nWorkTracks = mMFTWork.size();
293 auto& trc = mMFTWork.emplace_back(
TrackLocMFT{trcOrig, {tMin, tMax}, irof});
294 trc.setParameters(trcOrig.getOutParam().getParameters());
295 trc.setZ(trcOrig.getOutParam().getZ());
296 trc.setCovariances(trcOrig.getOutParam().getCovariances());
297 trc.setTrackChi2(trcOrig.getOutParam().getTrackChi2());
301 trc.propagateToZ(mMatchingPlaneZ, mBz);
309void MatchGlobalFwd::loadMatches()
312 const auto& inp = *mRecoCont;
313 int nFakes = 0, nTrue = 0;
316 mMatchingInfoUpstream = inp.getMFTMCHMatches();
318 LOG(info) <<
"Loaded " << mMatchingInfoUpstream.size() <<
" MFTMCH Matches";
320 for (
const auto&
match : mMatchingInfoUpstream) {
321 auto MFTId =
match.getMFTTrackID();
322 auto MCHId =
match.getMCHTrackID();
323 LOG(
debug) <<
" ==> MFTId = " << MFTId <<
" MCHId = " << MCHId << std::endl;
325 auto& thisMCHTrack = mMCHWork[mMCHID2Work[MCHId]];
326 thisMCHTrack.setMatchInfo(
match);
327 mMatchedTracks.emplace_back(thisMCHTrack);
329 mMatchLabels.push_back(computeLabel(MCHId, MFTId));
330 mMatchLabels.back().isFake() ?
nFakes++ : nTrue++;
334 LOG(info) <<
" Done matching from upstream " << mMFTWork.size() <<
" MFT tracks with " << mMCHWork.size() <<
" MCH Tracks.";
336 LOG(info) <<
" nFakes = " <<
nFakes <<
" nTrue = " << nTrue;
341template <Int_t saveAllMode>
342void MatchGlobalFwd::doMatching()
345 int nMCHROFs = mMCHROFTimes.size();
347 LOG(info) <<
"Running MCH-MFT Track Matching.";
349 auto firstMFTTrackIdInROF = 0;
350 auto MFTROFId = mMFTWork.front().roFrame;
351 LOG(
debug) <<
"(*) nMCHROFs: " << nMCHROFs <<
", mMFTTracks.size(): " << mMFTTracks.size() <<
" MFTROFId: " << MFTROFId <<
", mMFTTrackROFRec.size(): " << mMFTTrackROFRec.size();
353 while ((firstMFTTrackIdInROF < mMFTTracks.size()) && (MFTROFId < mMFTTrackROFRec.size())) {
354 auto MFTROFId = mMFTWork[firstMFTTrackIdInROF].roFrame;
355 const auto& thisMFTBracket = mMFTROFTimes[MFTROFId];
356 auto nMFTTracksInROF = mMFTTrackROFRec[MFTROFId].getNEntries();
357 firstMFTTrackIdInROF = mMFTTrackROFRec[MFTROFId].getFirstEntry();
358 LOG(
debug) <<
"MFT ROF = " << MFTROFId <<
"; interval: [" << thisMFTBracket.getMin() <<
"," << thisMFTBracket.getMax() <<
"]";
359 LOG(
debug) <<
"ROF " << MFTROFId <<
" : firstMFTTrackIdInROF " << firstMFTTrackIdInROF <<
" ; nMFTTracksInROF = " << nMFTTracksInROF;
360 firstMFTTrackIdInROF += nMFTTracksInROF;
362 int mchROFMatchFirst = -1;
363 int mchROFMatchLast = -1;
366 while (mchROF < nMCHROFs && !(thisMFTBracket < mMCHROFTimes[mchROF])) {
368 if (mMCHTrackROFRec[mchROF].getNEntries() > 0 && !(thisMFTBracket.isOutside(mMCHROFTimes[mchROF]))) {
370 if (mchROFMatchFirst < 0) {
371 mchROFMatchFirst = mchROF;
374 mchROFMatchLast = mchROF;
379 if (mchROFMatchFirst < 0) {
382 LOG(
debug) <<
"FIRST MCH ROF " << mchROFMatchFirst <<
"; interval: ["
383 << mMCHROFTimes[mchROFMatchFirst].getMin() <<
","
384 << mMCHROFTimes[mchROFMatchFirst].getMax() <<
"] size: " << mMCHTrackROFRec[mchROFMatchFirst].getNEntries();
385 LOG(
debug) <<
"LAST MCH ROF " << mchROFMatchLast <<
"; interval: ["
386 << mMCHROFTimes[mchROFMatchLast].getMin() <<
","
387 << mMCHROFTimes[mchROFMatchLast].getMax() <<
"] size: " << mMCHTrackROFRec[mchROFMatchLast].getNEntries();
389 ROFMatch<saveAllMode>(MFTROFId, mchROFMatchFirst, mchROFMatchLast);
393 int nFakes = 0, nTrue = 0;
394 for (
auto& thisMCHTrack : mMCHWork) {
395 auto bestMFTMatchID = thisMCHTrack.getMFTTrackID();
396 if (bestMFTMatchID >= 0) {
398 mMatchLabels.push_back(computeLabel(thisMCHTrack.getMCHTrackID(), bestMFTMatchID));
399 mMatchLabels.back().isFake() ?
nFakes++ : nTrue++;
402 thisMCHTrack.setMFTTrackID(bestMFTMatchID);
403 LOG(
debug) <<
" thisMCHTrack.getMFTTrackID() = " << thisMCHTrack.getMFTTrackID()
404 <<
"; thisMCHTrack.getMFTMCHMatchingChi2() = " << thisMCHTrack.getMFTMCHMatchingChi2();
406 mMatchedTracks.emplace_back(thisMCHTrack);
407 mMatchingInfo.emplace_back(thisMCHTrack);
411 LOG(info) <<
" MFT-MCH Matching: nFakes = " <<
nFakes <<
" nTrue = " << nTrue;
414 int nFakes = 0, nTrue = 0;
415 auto& matchAllChi2 = mMatchingFunctionMap[
"matchALL"];
416 for (
auto MCHId = 0; MCHId < mMCHWork.size(); MCHId++) {
417 auto& thisMCHTrack = mMCHWork[MCHId];
418 for (
auto& pairCandidate : mCandidates[MCHId]) {
419 thisMCHTrack.setMFTTrackID(pairCandidate.second);
420 auto& thisMFTTrack = mMFTWork[pairCandidate.second];
421 auto chi2 = matchAllChi2(thisMCHTrack, thisMFTTrack);
422 thisMCHTrack.setMFTMCHMatchingScore(pairCandidate.first);
423 thisMCHTrack.setMFTMCHMatchingChi2(chi2);
424 mMatchedTracks.emplace_back(thisMCHTrack);
425 mMatchingInfo.emplace_back(thisMCHTrack);
427 mMatchLabels.push_back(computeLabel(MCHId, pairCandidate.second));
428 mMatchLabels.back().isFake() ?
nFakes++ : nTrue++;
436template <Int_t saveAllMode>
437void MatchGlobalFwd::ROFMatch(
int MFTROFId,
int firstMCHROFId,
int lastMCHROFId)
440 const auto& thisMFTROF = mMFTTrackROFRec[MFTROFId];
441 const auto& thisMFTBracket = mMFTROFTimes[MFTROFId];
442 const auto& firstMCHROF = mMCHTrackROFRec[firstMCHROFId];
443 const auto& lastMCHROF = mMCHTrackROFRec[lastMCHROFId];
444 int nFakes = 0, nTrue = 0;
446 auto compare = [](
const std::pair<int, int>&
a,
const std::pair<int, int>&
b) {
447 return a.first <
b.first;
450 auto firstMFTTrackID = thisMFTROF.getFirstEntry();
451 auto lastMFTTrackID = firstMFTTrackID + thisMFTROF.getNEntries() - 1;
453 auto firstMCHTrackID = firstMCHROF.getFirstIdx();
454 auto lastMCHTrackID = lastMCHROF.getLastIdx();
456 auto nMFTTracks = thisMFTROF.getNEntries();
457 auto nMCHTracks = lastMCHTrackID - firstMCHTrackID + 1;
459 auto& matchAllChi2 = mMatchingFunctionMap[
"matchALL"];
461 LOG(
debug) <<
"Matching MFT ROF " << MFTROFId <<
" with MCH ROFs [" << firstMCHROFId <<
"->" << lastMCHROFId <<
"]";
462 LOG(
debug) <<
" firstMFTTrackID = " << firstMFTTrackID <<
" ; lastMFTTrackID = " << lastMFTTrackID;
463 LOG(
debug) <<
" firstMCHTrackID = " << firstMCHTrackID <<
" ; lastMCHTrackID = " << lastMCHTrackID;
464 LOG(
debug) <<
" thisMFTROF: " << thisMFTROF.getBCData();
465 LOG(
debug) <<
" firstMCHROF: " << firstMCHROF;
466 LOG(
debug) <<
" lastMCHROF: " << lastMCHROF;
469 for (
auto MCHId = firstMCHTrackID; MCHId <= lastMCHTrackID; MCHId++) {
470 auto& thisMCHTrack = mMCHWork[MCHId];
473 if (mUseTrackTime && (thisMFTBracket.isOutside(thisMCHTrack.tBracket))) {
478 for (
auto MFTId = firstMFTTrackID; MFTId <= lastMFTTrackID; MFTId++) {
479 auto& thisMFTTrack = mMFTWork[MFTId];
481 matchLabel = computeLabel(MCHId, MFTId);
483 if (mCutFunc(thisMCHTrack, thisMFTTrack)) {
484 thisMCHTrack.countMFTCandidate();
487 thisMCHTrack.setCloseMatch();
490 auto score = mMatchFunc(thisMCHTrack, thisMFTTrack);
491 if (score < thisMCHTrack.getMFTMCHMatchingScore()) {
492 thisMCHTrack.setMFTTrackID(MFTId);
493 auto chi2 = matchAllChi2(thisMCHTrack, thisMFTTrack);
494 thisMCHTrack.setMFTMCHMatchingScore(score);
495 thisMCHTrack.setMFTMCHMatchingChi2(chi2);
498 thisMCHTrack.setMFTTrackID(MFTId);
499 mMatchedTracks.emplace_back(thisMCHTrack);
500 mMatchingInfo.emplace_back(thisMCHTrack);
502 mMatchLabels.push_back(matchLabel);
503 mMatchLabels.back().isFake() ?
nFakes++ : nTrue++;
508 auto score = mMatchFunc(thisMCHTrack, thisMFTTrack);
509 std::pair<float, int> scoreID = {score, MFTId};
510 mCandidates[MCHId].push_back(scoreID);
511 std::sort(mCandidates[MCHId].
begin(), mCandidates[MCHId].
end(),
compare);
512 if (mCandidates[MCHId].
size() > mNCandidates) {
513 mCandidates[MCHId].pop_back();
518 thisMCHTrack.setMFTTrackID(MFTId);
519 mMatchingInfo.emplace_back(thisMCHTrack);
520 mMCHMatchPlaneParams.emplace_back(thisMCHTrack);
523 mMatchLabels.push_back(matchLabel);
524 mMatchLabels.back().isFake() ?
nFakes++ : nTrue++;
529 auto bestMFTMatchID = thisMCHTrack.getMFTTrackID();
530 LOG(
debug) <<
" Matching MCHId = " << MCHId <<
" ==> bestMFTMatchID = " << thisMCHTrack.getMFTTrackID() <<
" ; thisMCHTrack.getMFTMCHMatchingChi2() = " << thisMCHTrack.getMFTMCHMatchingChi2();
531 LOG(
debug) <<
" MCH COV<X,X> = " << thisMCHTrack.getSigma2X() <<
" ; COV<Y,Y> = " << thisMCHTrack.getSigma2Y() <<
" ; pt = " << thisMCHTrack.getPt();
535 LOG(
debug) <<
"Finished matching MFT ROF " << MFTROFId <<
": " << nMFTTracks <<
" MFT tracks and " << nMCHTracks <<
" MCH Tracks.";
542o2::MCCompLabel MatchGlobalFwd::computeLabel(
const int MCHId,
const int MFTId)
544 const auto& mchlabel = mMCHTrkLabels[MCHId];
545 const auto& mftlabel = mMFTTrkLabels[MFTId];
547 matchLabel.
setFakeFlag(mftlabel.compare(mchlabel) != 1);
549 LOG(
debug) <<
" Computing MFTMCH matching label: MFTTruth = " << mftlabel <<
" ; MCHTruth = " << mchlabel <<
" ; Computed label = " << matchLabel;
555void MatchGlobalFwd::doMCMatching()
557 int nFakes = 0, nTrue = 0;
560 for (
auto MCHId = 0; MCHId < mMCHWork.size(); MCHId++) {
561 auto& thisMCHTrack = mMCHWork[MCHId];
562 const o2::MCCompLabel& thisMCHLabel = mMCHTrkLabels[mMCHID2Work[MCHId]];
564 LOG(
debug) <<
" MCH Track # " << MCHId <<
" Label: " << thisMCHLabel;
565 if (!((thisMCHLabel).isSet())) {
568 for (
auto MFTId = 0; MFTId < mMFTWork.size(); MFTId++) {
569 auto& thisMFTTrack = mMFTWork[MFTId];
574 thisMCHTrack.setCloseMatch();
575 auto chi2 = mMatchFunc(thisMCHTrack, thisMFTTrack);
576 thisMCHTrack.setMFTTrackID(MFTId);
577 thisMCHTrack.setMFTMCHMatchingChi2(chi2);
578 mMatchedTracks.emplace_back(thisMCHTrack);
579 mMatchingInfo.emplace_back(thisMCHTrack);
580 mMatchLabels.push_back(matchLabel);
581 auto bestMFTMatchID = thisMCHTrack.getMFTTrackID();
582 LOG(
debug) <<
" Matching MCHId = " << MCHId <<
" ==> bestMFTMatchID = " << thisMCHTrack.getMFTTrackID() <<
" ; thisMCHTrack.getMFTMCHMatchingChi2() = " << thisMCHTrack.getMFTMCHMatchingChi2();
583 LOG(
debug) <<
" MCH COV<X,X> = " << thisMCHTrack.getSigma2X() <<
" ; COV<Y,Y> = " << thisMCHTrack.getSigma2Y() <<
" ; pt = " << thisMCHTrack.getPt();
584 LOG(
debug) <<
" Label: " << matchLabel;
591 auto nMFTTracks = mMFTWork.size();
592 auto nMCHTracks = mMCHWork.size();
594 LOG(info) <<
" Done MC matching of " << nMFTTracks <<
" MFT tracks with " << nMCHTracks <<
" MCH Tracks. nFakes = " <<
nFakes <<
" nTrue = " << nTrue;
598void MatchGlobalFwd::fitTracks()
600 LOG(info) <<
"Fitting global muon tracks...";
604 for (
auto& track : mMatchedTracks) {
605 LOG(
debug) <<
" ==> Fitting Global Track # " <<
GTrackID <<
" with MFT track # " << track.getMFTTrackID() <<
":";
606 fitGlobalMuonTrack(track);
610 LOG(info) <<
"Finished fitting global muon tracks.";
617 const auto& mftTrack = mMFTTracks[MFTMatchId];
618 const auto& mftTrackOut = mMFTWork[MFTMatchId];
619 auto ncls = mftTrack.getNumberOfPoints();
620 auto offset = mftTrack.getExternalClusterIndexOffset();
622 LOG(
debug) <<
"***************************** Start Fitting new track *****************************";
623 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();
625 LOG(
debug) <<
"MFTTrack: X = " << mftTrackOut.getX()
626 <<
" Y = " << mftTrackOut.getY() <<
" Z = " << mftTrackOut.getZ()
627 <<
" Tgl = " << mftTrackOut.getTanl()
628 <<
" Phi = " << mftTrackOut.getPhi() <<
" pz = " << mftTrackOut.getPz()
629 <<
" qpt = " << 1.0 / mftTrackOut.getInvQPt();
630 LOG(
debug) <<
" initTrack GlobalTrack: q/pt = " << gTrack.
getInvQPt() << std::endl;
632 auto lastLayer = mMFTMapping.
ChipID2Layer[mMFTClusters[
offset + ncls - 1].getSensorID()];
633 LOG(
debug) <<
"Starting by MFTCluster offset " <<
offset + ncls - 1 <<
" at lastLayer " << lastLayer;
635 for (
int icls = ncls - 1; icls > -1; --icls) {
636 auto clsEntry = mMFTTrackClusIdx[
offset + icls];
637 auto& thiscluster = mMFTClusters[clsEntry];
638 LOG(
debug) <<
"Computing MFTCluster clsEntry " << clsEntry <<
" at Z = " << thiscluster.getZ();
640 computeCluster(gTrack, thiscluster, lastLayer);
652 const auto& clx = cluster.
getX();
653 const auto& cly = cluster.
getY();
654 const auto& clz = cluster.
getZ();
655 const auto& sigmaX2 = cluster.
getSigmaY2() * mAlignResidual * mAlignResidual;
657 const auto& sigmaY2 = cluster.
getSigmaZ2() * mAlignResidual * mAlignResidual;
661 LOG(
debug) <<
"computeCluster: X = " << clx <<
" Y = " << cly <<
" Z = " << clz <<
" nCluster = " << newLayerID;
663 if (!propagateToNextClusterWithMCS(track, clz, startingLayerID, newLayerID)) {
667 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();
668 LOG(
debug) <<
"Track covariances after extrap:" << std::endl
672 const std::array<float, 2>&
pos = {clx, cly};
673 const std::array<float, 2>& cov = {sigmaX2, sigmaY2};
676 LOG(
debug) <<
" New Cluster: X = " << clx <<
" Y = " << cly <<
" Z = " << clz;
677 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();
679 LOG(
debug) <<
"Track covariances after Kalman update: \n"
690 mMFTROFrameLengthMUS = fums;
691 mMFTROFrameLengthMUSInv = 1. / mMFTROFrameLengthMUS;
698 mMFTROFrameLengthInBC = nbc;
700 mMFTROFrameLengthMUSInv = 1. / mMFTROFrameLengthMUS;
706 mMFTROFrameBiasInBC = nbc;
708 mMFTROFrameBiasMUSInv = 1. / mMFTROFrameBiasMUS;
718 LOG(error) <<
"Empty bunch filling is provided to MatchGlobalFwd, checks using it should be ignored";
726 mClosestBunchAbove[
i] = bcAbove;
733 mClosestBunchBelow[
i] = bcBelow;
746 double alpha1, alpha3, alpha4, x2, x3, x4;
752 x2 = TMath::ATan2(-alpha3, -alpha1);
753 x3 = -1. / TMath::Sqrt(alpha3 * alpha3 + alpha1 * alpha1);
754 x4 = alpha4 * -x3 * TMath::Sqrt(1 + alpha3 * alpha3);
756 auto K = alpha1 * alpha1 + alpha3 * alpha3;
757 auto K32 = K * TMath::Sqrt(K);
758 auto L = TMath::Sqrt(alpha3 * alpha3 + 1);
766 std::cout <<
" MCHtoGlobal - MCH Covariances:\n";
767 std::cout <<
" mchParam.getCovariances()(0, 0) = "
769 <<
" ; mchParam.getCovariances()(2, 2) = "
796 jacobian(2, 1) = -alpha3 / K;
797 jacobian(2, 3) = alpha1 / K;
799 jacobian(3, 1) = alpha1 / K32;
800 jacobian(3, 3) = alpha3 / K32;
802 jacobian(4, 1) = -alpha1 * alpha4 * L / K32;
803 jacobian(4, 3) = alpha3 * alpha4 * (1 / (TMath::Sqrt(K) * L) - L / K32);
804 jacobian(4, 4) = L / TMath::Sqrt(K);
807 covariances = ROOT::Math::Similarity(jacobian, covariances);
812 convertedTrack.
setZ(mchParam.
getZ());
813 convertedTrack.
setPhi(x2);
819 return convertedTrack;
829 double alpha1, alpha3, alpha4, x2, x3, x4;
835 auto sinx2 = TMath::Sin(x2);
836 auto cosx2 = TMath::Cos(x2);
840 alpha4 = x4 / TMath::Sqrt(x3 * x3 + sinx2 * sinx2);
842 auto K = TMath::Sqrt(x3 * x3 + sinx2 * sinx2);
871 jacobian(1, 2) = -sinx2 / x3;
872 jacobian(1, 3) = -cosx2 / (x3 * x3);
876 jacobian(3, 2) = cosx2 / x3;
877 jacobian(3, 3) = -sinx2 / (x3 * x3);
879 jacobian(4, 2) = -x4 * sinx2 * cosx2 / K3;
880 jacobian(4, 3) = -x3 * x4 / K3;
881 jacobian(4, 4) = 1 / K;
883 covariances = ROOT::Math::Similarity(jacobian, covariances);
885 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)};
886 double param[] = {fwdtrack.
getX(), alpha1, fwdtrack.
getY(), alpha3, alpha4};
895 mClosestBunchAbove[0] = mClosestBunchAbove[0] = -1;
902 SMatrix55Sym I = ROOT::Math::SMatrixIdentity(), H_k, V_k;
903 SVector5 m_k(mftTrack.getX(), mftTrack.getY(), mftTrack.getPhi(),
904 mftTrack.getTanl(), mftTrack.getInvQPt()),
908 V_k(0, 0) = mftTrack.getCovariances()(0, 0);
909 V_k(1, 1) = mftTrack.getCovariances()(1, 1);
910 V_k(2, 2) = mftTrack.getCovariances()(2, 2);
911 V_k(3, 3) = mftTrack.getCovariances()(3, 3);
912 V_k(4, 4) = mftTrack.getCovariances()(4, 4);
920 SMatrix55Std invResCov = (V_k + ROOT::Math::Similarity(H_k, GlobalMuonTrackCovariances));
924 SMatrix55Std K_k = GlobalMuonTrackCovariances * ROOT::Math::Transpose(H_k) * invResCov;
927 r_k_kminus1 = m_k - H_k * GlobalMuonTrackParameters;
929 auto matchChi2Track = ROOT::Math::Similarity(r_k_kminus1, invResCov);
931 return matchChi2Track;
942 SVector4 m_k(mftTrack.getX(), mftTrack.getY(), mftTrack.getPhi(),
947 V_k(0, 0) = mftTrack.getCovariances()(0, 0);
948 V_k(1, 1) = mftTrack.getCovariances()(1, 1);
949 V_k(2, 2) = mftTrack.getCovariances()(2, 2);
950 V_k(3, 3) = mftTrack.getCovariances()(3, 3);
957 SMatrix44 invResCov = (V_k + ROOT::Math::Similarity(H_k, GlobalMuonTrackCovariances));
961 SMatrix54 K_k = GlobalMuonTrackCovariances * ROOT::Math::Transpose(H_k) * invResCov;
964 r_k_kminus1 = m_k - H_k * GlobalMuonTrackParameters;
966 auto matchChi2Track = ROOT::Math::Similarity(r_k_kminus1, invResCov);
968 return matchChi2Track; };
978 SVector2 m_k(mftTrack.getX(), mftTrack.getY()), r_k_kminus1;
981 V_k(0, 0) = mftTrack.getCovariances()(0, 0);
982 V_k(1, 1) = mftTrack.getCovariances()(1, 1);
987 SMatrix22 invResCov = (V_k + ROOT::Math::Similarity(H_k, GlobalMuonTrackCovariances));
991 SMatrix52 K_k = GlobalMuonTrackCovariances * ROOT::Math::Transpose(H_k) * invResCov;
994 r_k_kminus1 = m_k - H_k * GlobalMuonTrackParameters;
995 auto matchChi2Track = ROOT::Math::Similarity(r_k_kminus1, invResCov);
997 return matchChi2Track; };
1005 Double_t LAbs = 415.;
1006 Double_t mumass = 0.106;
1009 if (mMatchingPlaneZ >= -90.0) {
1012 l = 505.0 + mMatchingPlaneZ;
1017 auto dx = mftTrack.getX() - mchTrack.
getX();
1018 auto dy = mftTrack.getY() - mchTrack.
getY();
1019 auto dthetax = TMath::ATan(mftTrack.getPx() / TMath::Abs(mftTrack.getPz())) - TMath::ATan(mchTrack.
getPx() / TMath::Abs(mchTrack.
getPz()));
1020 auto dthetay = TMath::ATan(mftTrack.getPy() / TMath::Abs(mftTrack.getPz())) - TMath::ATan(mchTrack.
getPy() / TMath::Abs(mchTrack.
getPz()));
1024 auto pMCH = mchTrack.
getP();
1025 auto lorentzbeta = pMCH / TMath::Sqrt(mumass * mumass + pMCH * pMCH);
1026 auto zMS = copysign(1.0, mchTrack.
getCharge());
1027 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));
1028 auto xMS = thetaMS * l / TMath::Sqrt(3.0);
1033 auto dxnorm = dx / xMS;
1034 auto dynorm = dy / xMS;
1035 auto dthetaxnorm = dthetax / thetaMS;
1036 auto dthetaynorm = dthetay / thetaMS;
1040 auto dxrot = dxnorm * TMath::Cos(TMath::Pi() / 4.0) - dthetaxnorm * TMath::Sin(TMath::Pi() / 4.0);
1041 auto dthetaxrot = dxnorm * TMath::Sin(TMath::Pi() / 4.0) + dthetaxnorm * TMath::Cos(TMath::Pi() / 4.0);
1042 auto dyrot = dynorm * TMath::Cos(TMath::Pi() / 4.0) - dthetaynorm * TMath::Sin(TMath::Pi() / 4.0);
1043 auto dthetayrot = dynorm * TMath::Sin(TMath::Pi() / 4.0) + dthetaynorm * TMath::Cos(TMath::Pi() / 4.0);
1048 auto dxcircle = dxrot;
1049 auto dycircle = dyrot;
1050 auto dthetaxcircle = dthetaxrot / k;
1051 auto dthetaycircle = dthetayrot / k;
1055 auto scoreX = TMath::Sqrt(dxcircle * dxcircle + dthetaxcircle * dthetaxcircle);
1056 auto scoreY = TMath::Sqrt(dycircle * dycircle + dthetaycircle * dthetaycircle);
1057 auto score = TMath::Sqrt(scoreX * scoreX + scoreY * scoreY);
1070 auto dx = mchTrack.
getX() - mftTrack.getX();
1071 auto dy = mchTrack.
getY() - mftTrack.getY();
1072 auto dPhi = mchTrack.
getPhi() - mftTrack.getPhi();
1073 auto dTanl = TMath::Abs(mchTrack.
getTanl() - mftTrack.getTanl());
1074 auto dInvQPt = TMath::Abs(mchTrack.
getInvQPt() - mftTrack.getInvQPt());
1075 auto distanceSq = dx * dx + dy * dy;
1077 auto cutPhiSq = 9 * (mchTrack.
getSigma2Phi() + mftTrack.getSigma2Phi());
1078 auto cutTanlSq = 9 * (mchTrack.
getSigma2Tanl() + mftTrack.getSigma2Tanl());
1079 auto cutInvQPtSq = 9 * (mchTrack.
getSigma2InvQPt() + mftTrack.getSigma2InvQPt());
1080 return (distanceSq < cutDistanceSq) and (dPhi * dPhi < cutPhiSq) and (dTanl * dTanl < cutTanlSq) and (dInvQPt * dInvQPt < cutInvQPtSq);
1085 auto dx = mchTrack.
getX() - mftTrack.getX();
1086 auto dy = mchTrack.
getY() - mftTrack.getY();
1087 auto dPhi = mchTrack.
getPhi() - mftTrack.getPhi();
1088 auto dTanl = TMath::Abs(mchTrack.
getTanl() - mftTrack.getTanl());
1089 auto distanceSq = dx * dx + dy * dy;
1091 auto cutPhiSq = 9 * (mchTrack.
getSigma2Phi() + mftTrack.getSigma2Phi());
1092 auto cutTanlSq = 9 * (mchTrack.
getSigma2Tanl() + mftTrack.getSigma2Tanl());
1093 return (distanceSq < cutDistanceSq) and (dPhi * dPhi < cutPhiSq) and (dTanl * dTanl < cutTanlSq);
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
bool update(const std::array< float, 2 > &p, const std::array< float, 2 > &cov)
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
constexpr double LHCBunchSpacingMUS
constexpr int LHCMaxBunches
constexpr double LHCBunchSpacingNS
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"