13#include <TStopwatch.h>
55#include "GPUParam.inc"
59#include <unordered_map>
77using VTIndexV = std::pair<int, o2::dataformats::VtxTrackIndex>;
87 : mDataRequest(dr), mGGCCDBRequest(gr), mTracksSrc(
src), mCheckSV(checkSV)
97 void process(const
o2::globaltracking::RecoContainer& recoData);
100 void processTPCTrackRefs();
101 void loadTPCOccMap(const
o2::globaltracking::RecoContainer& recoData);
102 void fillMCClusterInfo(const
o2::globaltracking::RecoContainer& recoData);
103 void prepareITSData(const
o2::globaltracking::RecoContainer& recoData);
104 bool processMCParticle(
int src,
int ev,
int trid);
105 bool addMCParticle(const
MCTrack& mctr, const
o2::
MCCompLabel& lb, TParticlePDG* pPDG =
nullptr);
108 bool refitV0(
int i,
o2::dataformats::
V0&
v0, const
o2::globaltracking::RecoContainer& recoData);
110 float getDCAYCut(
float pt) const;
113 TVector3 mCurrMCVertex;
114 o2::tpc::VDriftHelper mTPCVDriftHelper{};
116 std::shared_ptr<DataRequest> mDataRequest;
117 std::shared_ptr<o2::base::GRPGeomRequest> mGGCCDBRequest;
118 std::unique_ptr<o2::utils::TreeStreamRedirector> mDBGOut;
119 std::vector<float> mTBinClOcc;
120 std::vector<float> mTBinClOccHist;
121 std::vector<long> mIntBC;
122 std::vector<float> mTPCOcc;
123 std::vector<int> mITSOcc;
124 bool mCheckSV =
false;
125 int mNTPCOccBinLength = 0;
126 float mNTPCOccBinLengthInv;
128 float mITSTimeBiasMUS = 0.f;
129 float mITSROFrameLengthMUS = 0.f;
130 float mTPCTBinMUS = 0.;
132 int mNCheckDecays = 0;
136 std::vector<int> mITSROF;
137 std::vector<TBracket> mITSROFBracket;
138 std::vector<o2::MCCompLabel> mDecProdLblPool;
139 std::vector<MCVertex> mMCVtVec{};
145 int daughterFirst = -1;
146 int daughterLast = -1;
149 std::vector<std::vector<DecayRef>> mDecaysMaps;
150 std::unordered_map<o2::MCCompLabel, TrackFamily> mSelMCTracks;
151 std::unordered_map<o2::MCCompLabel, std::pair<int, int>> mSelTRefIdx;
152 std::vector<o2::track::TrackPar> mSelTRefs;
154 static constexpr float MaxSnp = 0.9;
162 mDBGOut = std::make_unique<o2::utils::TreeStreamRedirector>(
"trackMCStudy.root",
"recreate");
163 mVerbose = ic.
options().
get<
int>(
"device-verbosity");
166 for (
int id = 0;
id <
sizeof(
params.decayPDG) /
sizeof(
int);
id++) {
167 if (
params.decayPDG[
id] < 0) {
172 mDecaysMaps.resize(mNCheckDecays);
173 mTPCCorrMapsLoader.
init(ic);
179 for (
int i = 0;
i < mNCheckDecays;
i++) {
180 mDecaysMaps[
i].clear();
182 mDecProdLblPool.clear();
187 updateTimeDependentParams(pc);
196 bool updateMaps =
false;
202 LOGP(info,
"Updating TPC fast transform map with new VDrift factor of {} wrt reference {} and DriftTimeOffset correction {} wrt {} from source {}",
212 static bool initOnceDone =
false;
217 LOGP(info,
"VertexTrackMatcher ITSROFrameLengthMUS:{}", mITSROFrameLengthMUS);
220 mTPCTBinMUS = elParam.ZbinWidth;
225 mFitterV0.setUseAbsDCA(svparam.useAbsDCA);
226 mFitterV0.setPropagateToPCA(
false);
227 mFitterV0.setMaxR(svparam.maxRIni);
228 mFitterV0.setMinParamChange(svparam.minParamChange);
229 mFitterV0.setMinRelChi2Change(svparam.minRelChi2Change);
230 mFitterV0.setMaxDZIni(svparam.maxDZIni);
231 mFitterV0.setMaxDXYIni(svparam.maxDXYIni);
232 mFitterV0.setMaxChi2(svparam.maxChi2);
234 mFitterV0.setUsePropagator(svparam.usePropagator);
235 mFitterV0.setRefitWithMatCorr(svparam.refitWithMatCorr);
236 mFitterV0.setMaxStep(svparam.maxStep);
237 mFitterV0.setMaxSnp(svparam.maxSnp);
238 mFitterV0.setMinXSeed(svparam.minXSeed);
245 constexpr float SQRT12Inv = 0.288675f;
252 int nv = vtxRefs.size();
256 prepareITSData(recoData);
257 loadTPCOccMap(recoData);
258 auto getITSPatt = [&](
GTrackID gid, uint8_t& ncl) {
262 ncl = itsTrf.getNClusters();
263 for (
int il = 0; il < 7; il++) {
264 if (itsTrf.hasHitOnLayer(il)) {
271 for (
int il = 0; il < 7; il++) {
272 if (itsTr.hasHitOnLayer(il)) {
283 uint8_t clSect = 0, clRow = 0;
286 trc.getClusterReference(clRefs, trc.getNClusterReferences() - 1, clSect, clRow, clIdx);
295 const auto* TPCClMClab = recoData.
inputsTPCclusters->clusterIndex.clustersMCTruth;
297 for (
int ic = 0; ic < trc.getNClusterReferences(); ic++) {
298 uint8_t clSect = 0, clRow = 0;
300 trc.getClusterReference(clRefs, ic, clSect, clRow, clIdx);
301 auto labels = TPCClMClab->getLabels(clIdx + TPCClusterIdxStruct.clusterOffset[clSect][clRow]);
302 for (
auto& lbl : labels) {
317 unsigned int rofCount = 0;
319 for (
const auto& mcIR : mcEvRecords) {
320 long tbc = mcIR.differenceInBC(recoData.
startIR);
321 auto& mcVtx = mMCVtVec.emplace_back();
323 mcVtx.ID = mIntBC.size();
324 mIntBC.push_back(tbc);
325 int occBin = tbc / 8 * mNTPCOccBinLengthInv;
326 mTPCOcc.push_back(occBin < 0 ? mTBinClOcc[0] : (occBin >= mTBinClOcc.size() ? mTBinClOcc.back() : mTBinClOcc[occBin]));
328 long gbc = mcIR.toLong();
329 while (rofCount < ITSClusROFRec.size()) {
330 long rofbcMin = ITSClusROFRec[rofCount].getBCData().toLong() + ITSTimeBias, rofbcMax = rofbcMin + ITSROFLen;
331 if (gbc < rofbcMin) {
332 mITSOcc.push_back(0);
333 }
else if (gbc < rofbcMax) {
334 mITSOcc.push_back(ITSClusROFRec[rofCount].getNEntries());
341 if (rofCount >= ITSClusROFRec.size()) {
342 mITSOcc.push_back(0);
347 int curSrcMC = 0, curEvMC = 0;
348 for (curSrcMC = 0; curSrcMC < (
int)mcReader.
getNSources(); curSrcMC++) {
350 LOGP(info,
"Source {}", curSrcMC);
353 bool okAccVtx =
true;
354 if (nev != (
int)mMCVtVec.size()) {
355 LOGP(error,
"source {} has {} events while {} MC vertices were booked", curSrcMC, nev, mMCVtVec.size());
358 for (curEvMC = 0; curEvMC < nev; curEvMC++) {
360 LOGP(info,
"Event {}", curEvMC);
362 const auto& mt = mcReader.
getTracks(curSrcMC, curEvMC);
363 mCurrMCTracks = gsl::span<const MCTrack>(mt.data(), mt.size());
366 auto&
pos = mMCVtVec[curEvMC].pos;
368 pos[0] = mCurrMCVertex.X();
369 pos[1] = mCurrMCVertex.Y();
370 pos[2] = mCurrMCVertex.Z();
373 for (
int itr = 0; itr < mCurrMCTracks.size(); itr++) {
374 processMCParticle(curSrcMC, curEvMC, itr);
379 for (
int id = 0;
id < mNCheckDecays;
id++) {
380 LOGP(info,
"Decay PDG={} : {} entries",
params.decayPDG[
id], mDecaysMaps[
id].size());
385 for (
int iv = 0; iv < nv; iv++) {
387 LOGP(info,
"processing PV {} of {}", iv, nv);
391 if (iv < (
int)pvvecLbl.size()) {
392 pvLbl = pvvecLbl[iv];
395 mMCVtVec[pvLbl.
getEventID()].recVtx.emplace_back(
RecPV{pvvec[iv], pvLbl});
398 const auto& vtref = vtxRefs[iv];
404 int idMin = vtref.getFirstEntryOfSource(is), idMax = idMin + vtref.getEntriesOfSource(is);
405 for (
int i = idMin;
i < idMax;
i++) {
406 auto vid = trackIndex[
i];
408 if (trc.getPt() <
params.minPt || std::abs(trc.getTgl()) >
params.maxTgl) {
414 auto entry = mSelMCTracks.find(lbl);
415 if (
entry == mSelMCTracks.end()) {
416 if (lbl.getSourceID() != curSrcMC || lbl.getEventID() != curEvMC) {
417 curSrcMC = lbl.getSourceID();
418 curEvMC = lbl.getEventID();
419 const auto& mt = mcReader.
getTracks(curSrcMC, curEvMC);
420 mCurrMCTracks = gsl::span<const MCTrack>(mt.data(), mt.size());
423 if (!acceptMCCharged(mCurrMCTracks[lbl.getTrackID()], lbl)) {
426 entry = mSelMCTracks.find(lbl);
428 auto& trackFamily =
entry->second;
429 if (vid.isAmbiguous()) {
430 if (trackFamily.contains(vid)) {
434 auto& trf = trackFamily.recTracks.emplace_back();
444 if (lblITS == trackFamily.mcTrackInfo.label) {
448 if (trcITSF.getPt() <
params.minPt || std::abs(trcITSF.getTgl()) >
params.maxTgl) {
451 auto entryOfFake = mSelMCTracks.find(lblITS);
452 if (entryOfFake == mSelMCTracks.end()) {
455 auto& trackFamilyOfFake = entryOfFake->second;
456 auto& trfOfFake = trackFamilyOfFake.recTracks.emplace_back();
461 LOGP(info,
"Matched rec track {} to MC track {}", vid.asString(),
entry->first.asString());
470 LOGP(info,
"collected {} MC tracks", mSelMCTracks.size());
471 if (
params.minTPCRefsToExtractClRes > 0) {
472 processTPCTrackRefs();
476 for (
auto&
entry : mSelMCTracks) {
477 auto& trackFam =
entry.second;
478 auto& tracks = trackFam.recTracks;
480 if (tracks.empty()) {
484 LOGP(info,
"Processing MC track#{} {} -> {} reconstructed tracks", mcnt - 1,
entry.first.asString(), tracks.size());
487 std::sort(tracks.begin(), tracks.end(), [](
const RecTrack& lhs,
const RecTrack& rhs) {
488 const auto mskL = lhs.gid.getSourceDetectorsMask();
489 const auto mskR = rhs.gid.getSourceDetectorsMask();
490 bool itstpcL = mskL[DetID::ITS] && mskL[DetID::TPC], itstpcR = mskR[DetID::ITS] && mskR[DetID::TPC];
491 if (itstpcL && !itstpcR) {
494 return lhs.gid.getSource() > rhs.gid.getSource();
498 for (
auto& tref : tracks) {
499 if (tref.gid.isSourceSet()) {
505 auto msk = tref.gid.getSourceDetectorsMask();
508 tref.pattITS = getITSPatt(gidSet[
GTrackID::ITS], tref.nClITS);
509 if (trackFam.entITS < 0) {
510 trackFam.entITS = tcnt;
513 if (lblITS.isFake()) {
516 if (lblITS == trackFam.mcTrackInfo.label) {
517 trackFam.entITSFound = tcnt;
525 if (msk[
DetID::TPC] && trackFam.entITSTPC < 0) {
526 trackFam.entITSTPC = tcnt;
534 tref.nClTPC = trtpc.getNClusters();
535 tref.lowestPadRow = getLowestPadrow(trtpc);
536 flagTPCClusters(trtpc,
entry.first);
537 if (trackFam.entTPC < 0) {
538 trackFam.entTPC = tcnt;
539 trackFam.tpcT0 = trtpc.getTime0();
545 float ts = 0, terr = 0;
550 const auto& itsBra = mITSROFBracket[mITSROF[tref.gid.getIndex()]];
551 tref.ts =
timeEst{itsBra.mean(), itsBra.delta() * SQRT12Inv};
554 LOGP(info,
"Invalid entry {} of {} getTrackMCLabel {}", tcnt, tracks.size(), tref.gid.asString());
558 if (trackFam.entITS > -1 && trackFam.entTPC > -1) {
559 auto vidITS = tracks[trackFam.entITS].gid;
560 auto vidTPC = tracks[trackFam.entTPC].gid;
563 if (propagateToRefX(trcTPC, trcITS)) {
564 trackFam.trackITSProp = trcITS;
565 trackFam.trackTPCProp = trcTPC;
567 trackFam.trackITSProp.invalidate();
568 trackFam.trackTPCProp.invalidate();
571 trackFam.trackITSProp.invalidate();
572 trackFam.trackTPCProp.invalidate();
578 auto v0s = recoData.getV0sIdx();
581 s += fmt::format(
" par {} Ntpccl={} Nitscl={} ",
f.mcTrackInfo.pdgParent,
f.mcTrackInfo.nTPCCl,
f.mcTrackInfo.nITSCl);
582 for (
auto& t :
f.recTracks) {
583 s += t.gid.asString();
588 for (
int svID; svID < (
int)v0s.size(); svID++) {
589 const auto& v0idx = v0s[svID];
590 int nOKProngs = 0, realMCSVID = -1;
591 int8_t decTypeID = -1;
592 for (
int ipr = 0; ipr < v0idx.getNProngs(); ipr++) {
593 auto mcl = recoData.getTrackMCLabel(v0idx.getProngID(ipr));
594 auto itl = mSelMCTracks.find(mcl);
595 if (itl == mSelMCTracks.end()) {
599 auto& trackFamily = itl->second;
600 int decayParentIndex = trackFamily.mcTrackInfo.parentEntry;
601 if (decayParentIndex < 0) {
605 realMCSVID = decayParentIndex;
606 decTypeID = trackFamily.mcTrackInfo.parentDecID;
608 LOGP(
debug,
"Prong{} {} comes from {}/{}", ipr, prpr(trackFamily), decTypeID, realMCSVID);
611 if (realMCSVID != decayParentIndex || decTypeID != trackFamily.mcTrackInfo.parentDecID) {
614 LOGP(
debug,
"Prong{} {} comes from {}/{}", ipr, prpr(trackFamily), decTypeID, realMCSVID);
617 if (nOKProngs == v0idx.getNProngs()) {
618 LOGP(
debug,
"Decay {}/{} was found", decTypeID, realMCSVID);
619 mDecaysMaps[decTypeID][realMCSVID].foundSVID = svID;
625 fillMCClusterInfo(recoData);
628 for (
auto&
entry : mSelMCTracks) {
629 auto& trackFam =
entry.second;
630 (*mDBGOut) <<
"tracks" <<
"tr=" << trackFam <<
"\n";
634 std::vector<TrackFamily> decFam;
635 for (
int id = 0;
id < mNCheckDecays;
id++) {
636 std::string decTreeName = fmt::format(
"dec{}",
params.decayPDG[
id]);
637 for (
const auto& dec : mDecaysMaps[
id]) {
640 for (
int idd = dec.daughterFirst; idd <= dec.daughterLast; idd++) {
641 auto dtLbl = mDecProdLblPool[idd];
642 const auto& dtFamily = mSelMCTracks[dtLbl];
643 if (dtFamily.mcTrackInfo.pdgParent != dec.pdg) {
644 LOGP(error,
"{}-th decay (pdg={}): {} in {}:{} range refers to MC track with pdgParent = {}",
id,
params.decayPDG[
id], idd, dec.daughterFirst, dec.daughterLast, dtFamily.mcTrackInfo.pdgParent);
648 decFam.push_back(dtFamily);
652 if (dec.foundSVID >= 0 && !refitV0(dec.foundSVID,
v0, recoData)) {
655 (*mDBGOut) << decTreeName.c_str() <<
"pdgPar=" << dec.pdg <<
"trPar=" << dec.parent <<
"prod=" << decFam <<
"found=" << dec.foundSVID <<
"sv=" <<
v0 <<
"\n";
660 for (
auto& mcVtx : mMCVtVec) {
661 std::sort(mcVtx.recVtx.begin(), mcVtx.recVtx.end(), [](
const RecPV& lhs,
const RecPV& rhs) {
662 return lhs.pv.getNContributors() > rhs.pv.getNContributors();
664 (*mDBGOut) <<
"mcVtxTree" <<
"mcVtx=" << mcVtx <<
"\n";
668void TrackMCStudy::processTPCTrackRefs()
670 constexpr float alpsec[18] = {0.174533, 0.523599, 0.872665, 1.221730, 1.570796, 1.919862, 2.268928, 2.617994, 2.967060, 3.316126, 3.665191, 4.014257, 4.363323, 4.712389, 5.061455, 5.410521, 5.759587, 6.108652};
671 constexpr float sinAlp[18] = {0.173648, 0.500000, 0.766044, 0.939693, 1.000000, 0.939693, 0.766044, 0.500000, 0.173648, -0.173648, -0.500000, -0.766044, -0.939693, -1.000000, -0.939693, -0.766044, -0.500000, -0.173648};
672 constexpr float cosAlp[18] = {0.984808, 0.866025, 0.642788, 0.342020, 0.000000, -0.342020, -0.642788, -0.866025, -0.984808, -0.984808, -0.866025, -0.642788, -0.342020, -0.000000, 0.342020, 0.642788, 0.866025, 0.984808};
674 for (
auto&
entry : mSelMCTracks) {
675 auto lb =
entry.first;
676 auto trspan = mcReader.getTrackRefs(lb.getSourceID(), lb.getEventID(), lb.getTrackID());
677 int q =
entry.second.mcTrackInfo.track.getCharge();
681 int ref0entry = mSelTRefs.size(), nrefsSel = 0;
682 for (
const auto& trf : trspan) {
683 if (trf.getDetectorId() != 1) {
686 float pT = std::sqrt(trf.Px() * trf.Px() + trf.Py() * trf.Py());
690 float secX, secY,
phi = std::atan2(trf.Y(), trf.X());
693 float phiPt = std::atan2(trf.Py(), trf.Px());
694 o2::math_utils::bringTo02Pi(phiPt);
695 auto dphiPt = phiPt - alpsec[sector];
703 float tgL = trf.Pz() / pT;
704 std::array<float, 5> pars = {secY, trf.Z(), std::sin(dphiPt), tgL, q / pT};
705 auto& refTrack = mSelTRefs.emplace_back(secX, alpsec[sector], pars);
706 refTrack.setUserField(uint16_t(sector));
709 if (nrefsSel <
params.minTPCRefsToExtractClRes) {
710 mSelTRefs.resize(ref0entry);
713 mSelTRefIdx[lb] = std::make_pair(ref0entry, ref0entry + nrefsSel);
722 const auto* TPCClMClab = recoData.
inputsTPCclusters->clusterIndex.clustersMCTruth;
726 for (uint8_t sector = 0; sector < 36; sector++) {
727 for (uint8_t
row = 0;
row < 152;
row++) {
728 unsigned int offs = TPCClusterIdxStruct.clusterOffset[sector][
row];
729 for (
unsigned int icl0 = 0; icl0 < TPCClusterIdxStruct.nClusters[sector][
row]; icl0++) {
730 const auto labels = TPCClMClab->getLabels(icl0 + offs);
732 for (
const auto& lbl : labels) {
733 if (!lbl.isValid()) {
738 const auto& clus = TPCClusterIdxStruct.clusters[sector][
row][icl0];
739 int tbinH =
int(clus.getTime() * mNTPCOccBinLengthInv);
740 clRes.contTracks.clear();
741 bool doClusRes = (
params.minTPCRefsToExtractClRes > 0) && (
params.rejectClustersResStat <= 0. || gRandom->Rndm() <
params.rejectClustersResStat);
742 for (
auto lbl : labels) {
743 bool corrAttach = lbl.isFake();
744 lbl.setFakeFlag(
false);
745 auto entry = mSelMCTracks.find(lbl);
746 if (
entry == mSelMCTracks.end()) {
749 auto& mctr =
entry->second.mcTrackInfo;
751 if (
row > mctr.maxTPCRow) {
752 mctr.maxTPCRow =
row;
753 mctr.maxTPCRowSect = sector;
755 }
else if (
row == 0 && mctr.nUsedPadRows == 0) {
758 if (
row < mctr.minTPCRow) {
759 mctr.minTPCRow =
row;
760 mctr.minTPCRowSect = sector;
762 if (mctr.minTPCRowSect == sector &&
row > mctr.maxTPCRowInner) {
763 mctr.maxTPCRowInner =
row;
770 auto entTRefIDsIt = mSelTRefIdx.find(lbl);
771 if (entTRefIDsIt == mSelTRefIdx.end()) {
775 mTPCCorrMapsLoader.Transform(sector,
row, clus.getPad(), clus.getTime(), xc, yc, zc, mctr.bcInTF / 8.);
777 const auto& entTRefIDs = entTRefIDsIt->second;
779 int entIDBelow = -1, entIDAbove = -1;
780 float xBelow = -1e6, xAbove = 1e6;
782 for (
int entID = entTRefIDs.first; entID < entTRefIDs.second; entID++) {
783 const auto& refTr = mSelTRefs[entID];
784 if (refTr.getUserField() != sector % 18) {
787 if ((refTr.getX() < xc) && (refTr.getX() > xBelow) && (refTr.getX() > xc -
params.maxTPCRefExtrap)) {
788 xBelow = refTr.getX();
791 if ((refTr.getX() > xc) && (refTr.getX() < xAbove) && (refTr.getX() < xc +
params.maxTPCRefExtrap)) {
792 xAbove = refTr.getX();
796 if ((entIDBelow < 0 && entIDAbove < 0) || (
params.requireTopBottomRefs && (entIDBelow < 0 || entIDAbove < 0))) {
801 bool okBelow = entIDBelow >= 0 && prop->PropagateToXBxByBz((tparBelow = mSelTRefs[entIDBelow]), xc, 0.99, 2.);
802 bool okAbove = entIDAbove >= 0 && prop->PropagateToXBxByBz((tparAbove = mSelTRefs[entIDAbove]), xc, 0.99, 2.);
803 if ((!okBelow && !okAbove) || (
params.requireTopBottomRefs && (!okBelow || !okAbove))) {
808 auto& clCont = clRes.contTracks.emplace_back();
809 clCont.corrAttach = corrAttach;
811 clCont.below = {mSelTRefs[entIDBelow].getX(), tparBelow.getY(), tparBelow.getZ()};
812 clCont.snp += tparBelow.getSnp();
813 clCont.tgl += tparBelow.getTgl();
814 clCont.q2pt += tparBelow.getQ2Pt();
818 clCont.above = {mSelTRefs[entIDAbove].getX(), tparAbove.getY(), tparAbove.getZ()};
819 clCont.snp += tparAbove.getSnp();
820 clCont.tgl += tparAbove.getTgl();
821 clCont.q2pt += tparAbove.getQ2Pt();
825 if (clRes.contTracks.size() == 1) {
826 int occBin = mctr.bcInTF / 8 * mNTPCOccBinLengthInv;
827 clRes.occ = occBin < 0 ? mTBinClOcc[0] : (occBin >= mTBinClOcc.size() ? mTBinClOcc.back() : mTBinClOcc[occBin]);
829 clCont.xyz = {xc, yc, zc};
836 clRes.contTracks.pop_back();
840 if (clRes.getNCont()) {
843 clRes.qtot = clus.getQtot();
844 clRes.qmax = clus.getQmax();
845 clRes.flags = clus.getFlags();
846 clRes.sigmaTimePacked = clus.sigmaTimePacked;
847 clRes.sigmaPadPacked = clus.sigmaPadPacked;
848 clRes.ncont = ncontLb;
853 }
else if (tbinH >=
int(mTBinClOccHist.size())) {
854 tbinH = (
int)mTBinClOccHist.size() - 1;
856 clRes.occBin = mTBinClOccHist[tbinH];
858 (*mDBGOut) <<
"clres" <<
"clr=" << clRes <<
"\n";
866 for (
unsigned int icl = 0; icl <
ITSClusters.size(); icl++) {
867 const auto labels = mcITSClusters->getLabels(icl);
868 for (
const auto& lbl : labels) {
869 auto entry = mSelMCTracks.find(lbl);
870 if (
entry == mSelMCTracks.end()) {
873 auto& mctr =
entry->second.mcTrackInfo;
882 bool refReached =
false;
883 constexpr float TgHalfSector = 0.17632698f;
891 if (fabs(trcTPC.getY()) < par.XMatchingRef * TgHalfSector) {
899 if (!trcTPC.rotate(alphaNew) != 0) {
907 float alp = trcTPC.getAlpha();
924 if (mTPCVDriftHelper.accountCCDBInputs(matcher, obj)) {
927 if (mTPCCorrMapsLoader.accountCCDBInputs(matcher, obj)) {
931 LOG(info) <<
"ITS Alpide param updated";
933 par.printKeyValues();
945 int nROFs = ITSTrackROFRec.size();
947 mITSROFBracket.clear();
948 mITSROF.reserve(ITSTracksArray.size());
949 mITSROFBracket.reserve(ITSTracksArray.size());
950 for (
int irof = 0; irof < nROFs; irof++) {
951 const auto& rofRec = ITSTrackROFRec[irof];
952 long nBC = rofRec.getBCData().differenceInBC(recoData.
startIR);
954 float tMax = tMin + mITSROFrameLengthMUS;
955 mITSROFBracket.emplace_back(tMin, tMax);
956 for (
int it = 0; it < rofRec.getNEntries(); it++) {
957 mITSROF.push_back(irof);
969bool TrackMCStudy::processMCParticle(
int src,
int ev,
int trid)
971 const auto& mcPart = mCurrMCTracks[trid];
972 int pdg = mcPart.GetPdgCode();
978 if (mcPart.T() <
params.decayMotherMaxT) {
979 for (
int id = 0;
id < mNCheckDecays;
id++) {
980 if (
params.decayPDG[
id] == std::abs(pdg)) {
986 auto& decayPool = mDecaysMaps[decay];
987 int idd0 = mcPart.getFirstDaughterTrackId(), idd1 = mcPart.getLastDaughterTrackId();
988 int dtStart = mDecProdLblPool.size(), dtEnd = -1;
992 for (
int idd = idd0; idd <= idd1; idd++) {
993 const auto& product = mCurrMCTracks[idd];
995 if (!acceptMCCharged(product, lbld, decay)) {
997 mDecProdLblPool.resize(dtStart);
1000 mDecProdLblPool.push_back(lbld);
1004 dtEnd = mDecProdLblPool.size();
1005 for (
int dtid = dtStart; dtid < dtEnd; dtid++) {
1006 mSelMCTracks[mDecProdLblPool[dtid]].mcTrackInfo.parentEntry = decayPool.size();
1007 mSelMCTracks[mDecProdLblPool[dtid]].mcTrackInfo.parentDecID = int8_t(decay);
1010 std::array<float, 3> xyz{(
float)mcPart.GetStartVertexCoordinatesX(), (
float)mcPart.GetStartVertexCoordinatesY(), (
float)mcPart.GetStartVertexCoordinatesZ()};
1011 std::array<float, 3> pxyz{(
float)mcPart.GetStartVertexMomentumX(), (
float)mcPart.GetStartVertexMomentumY(), (
float)mcPart.GetStartVertexMomentumZ()};
1012 decayPool.emplace_back(DecayRef{lbl,
1014 mcPart.GetPdgCode(), dtStart, dtEnd});
1016 LOGP(info,
"Adding MC parent pdg={} {}, with prongs in {}:{} range", pdg, lbl.asString(), dtStart, dtEnd);
1024 if (mSelMCTracks.find(lbl) == mSelMCTracks.end()) {
1025 res = acceptMCCharged(mcPart, lbl);
1038 if (mVerbose > 1 && followDecay > -1) {
1039 LOGP(info,
"rejecting decay {} prong : pdg={}, pT={}, tgL={}, r={}", followDecay, tr.
GetPdgCode(), tr.
GetPt(), tr.
GetTgl(), std::sqrt(tr.
R2()));
1044 float r2 = dx * dx + dy * dy;
1045 float posTgl2 = r2 > 1 && std::abs(dz) < 20 ? dz * dz / r2 : 0;
1046 if (posTgl2 >
params.maxPosTglMC *
params.maxPosTglMC) {
1047 if (mVerbose > 1 && followDecay > -1) {
1048 LOGP(info,
"rejecting decay {} prong : pdg={}, pT={}, tgL={}, dr={}, dz={} r={}, z={}, posTgl={}", followDecay, tr.
GetPdgCode(), tr.
GetPt(), tr.
GetTgl(), std::sqrt(r2), dz, std::sqrt(tr.
R2()), tr.
GetStartVertexCoordinatesZ(), std::sqrt(posTgl2));
1052 if (
params.requireITSorTPCTrackRefs) {
1055 for (
const auto& trf : trspan) {
1070 if (pPDG->Charge() == 0.) {
1073 return addMCParticle(tr, lb, pPDG);
1084 auto& mcEntry = mSelMCTracks[lb];
1085 mcEntry.mcTrackInfo.pdg = mcPart.
GetPdgCode();
1086 mcEntry.mcTrackInfo.track =
o2::track::TrackPar(xyz, pxyz, TMath::Nint(pPDG->Charge() / 3),
true);
1087 mcEntry.mcTrackInfo.label = lb;
1088 mcEntry.mcTrackInfo.bcInTF = mIntBC[lb.
getEventID()];
1089 mcEntry.mcTrackInfo.occTPC = mTPCOcc[lb.
getEventID()];
1090 mcEntry.mcTrackInfo.occITS = mITSOcc[lb.
getEventID()];
1094 const auto& mcPartPar = mCurrMCTracks[moth];
1095 mcEntry.mcTrackInfo.pdgParent = mcPartPar.GetPdgCode();
1113 if (svparam.mTPCTrackPhotonTune && isTPConly) {
1114 mFitterV0.setMaxDZIni(svparam.mTPCTrackMaxDZIni);
1115 mFitterV0.setMaxDXYIni(svparam.mTPCTrackMaxDXYIni);
1116 mFitterV0.setMaxChi2(svparam.mTPCTrackMaxChi2);
1117 mFitterV0.setCollinear(
true);
1119 int nCand = mFitterV0.process(seedP, seedN);
1120 if (svparam.mTPCTrackPhotonTune && isTPConly) {
1122 mFitterV0.setMaxDZIni(svparam.maxDZIni);
1123 mFitterV0.setMaxDXYIni(svparam.maxDXYIni);
1124 mFitterV0.setMaxChi2(svparam.maxChi2);
1125 mFitterV0.setCollinear(
false);
1131 if (!mFitterV0.isPropagateTracksToVertexDone(cand) && !mFitterV0.propagateTracksToVertex(cand)) {
1134 const auto& trPProp = mFitterV0.getTrack(0, cand);
1135 const auto& trNProp = mFitterV0.getTrack(1, cand);
1136 std::array<float, 3> pP{}, pN{};
1137 trPProp.getPxPyPzGlo(pP);
1138 trNProp.getPxPyPzGlo(pN);
1139 std::array<float, 3> pV0 = {pP[0] + pN[0], pP[1] + pN[1], pP[2] + pN[2]};
1140 auto p2V0 = pV0[0] * pV0[0] + pV0[1] * pV0[1] + pV0[2] * pV0[2];
1142 const auto v0XYZ = mFitterV0.getPCACandidatePos(cand);
1143 float dx = v0XYZ[0] - pv.getX(), dy = v0XYZ[1] - pv.getY(), dz = v0XYZ[2] - pv.getZ(), prodXYZv0 = dx * pV0[0] + dy * pV0[1] + dz * pV0[2];
1144 float cosPA = prodXYZv0 / std::sqrt((dx * dx + dy * dy + dz * dz) * p2V0);
1146 v0.
setDCA(mFitterV0.getChi2AtPCACandidate(cand));
1156 auto TPCRefitter = std::make_unique<o2::gpu::GPUO2InterfaceRefit>(&recoData.
inputsTPCclusters->clusterIndex, &mTPCCorrMapsLoader, prop->getNominalBz(),
1158 mNTPCOccBinLength = TPCRefitter->getParam()->rec.tpc.occupancyMapTimeBins;
1160 if (mNTPCOccBinLength > 1 && TPCOccMap.size()) {
1161 mNTPCOccBinLengthInv = 1. / mNTPCOccBinLength;
1164 mTBinClOcc.resize(nTPCOccBins);
1165 mTBinClOccHist.resize(nTPCOccBins);
1166 float sm = 0., tb = 0.5 * mNTPCOccBinLength;
1167 for (
int i = 0;
i < nTPCOccBins;
i++) {
1168 mTBinClOccHist[
i] = TPCRefitter->getParam()->GetUnscaledMult(tb);
1169 tb += mNTPCOccBinLength;
1171 for (
int i = nTPCOccBins;
i--;) {
1172 sm += mTBinClOccHist[
i];
1173 if (
i + sumBins < nTPCOccBins) {
1174 sm -= mTBinClOccHist[
i + sumBins];
1179 mTBinClOcc.resize(1);
1180 mTBinClOccHist.resize(1);
1186 std::vector<OutputSpec> outputs;
1188 {
"device-verbosity", VariantType::Int, 0, {
"Verbosity level"}},
1189 {
"dcay-vs-pt", VariantType::String,
"0.0105 + 0.0350 / pow(x, 1.1)", {
"Formula for global tracks DCAy vs pT cut"}},
1190 {
"min-tpc-clusters", VariantType::Int, 60, {
"Cut on TPC clusters"}},
1191 {
"max-tpc-dcay", VariantType::Float, 2.f, {
"Cut on TPC dcaY"}},
1192 {
"max-tpc-dcaz", VariantType::Float, 2.f, {
"Cut on TPC dcaZ"}},
1193 {
"min-x-prop", VariantType::Float, 6.f, {
"track should be propagated to this X at least"}}};
1194 auto dataRequest = std::make_shared<DataRequest>();
1196 dataRequest->requestTracks(srcTracks, useMC);
1197 dataRequest->requestClusters(srcClusters, useMC);
1198 dataRequest->requestPrimaryVertices(useMC);
1200 dataRequest->requestSecondaryVertices(useMC);
1204 auto ggRequest = std::make_shared<o2::base::GRPGeomRequest>(
false,
1210 dataRequest->inputs,
1217 AlgorithmSpec{adaptFromTask<TrackMCStudy>(dataRequest, ggRequest, srcTracks, sclOpts, checkSV)},
Helper class to access load maps from CCDB.
Defintions for N-prongs secondary vertex fit.
Definition of the GeometryManager class.
Helper for geometry and GRP related CCDB requests.
Global index for barrel track: provides provenance (detectors combination), index in respective array...
Utility functions for MC particles.
Configurable params for TPC ITS matching.
Definition of the Names Generator class.
Definition of the parameter class for the detector electronics.
Wrapper container for different reconstructed object types.
o2::track::TrackParCov TrackParCov
Configurable params for secondary vertexer.
Result of refitting TPC-ITS matched track.
Reference on ITS/MFT clusters set.
Helper class to extract VDrift from different sources.
Referenc on track indices contributing to the vertex, with possibility chose tracks from specific sou...
void setFakeFlag(bool v=true)
std::string asString() const
Double_t GetStartVertexMomentumZ() const
Double_t GetStartVertexMomentumX() const
Double_t GetStartVertexCoordinatesY() const
Double_t GetStartVertexCoordinatesZ() const
Double_t R2() const
production radius squared
Double_t GetStartVertexMomentumY() const
Double_t GetStartVertexCoordinatesX() const
Int_t GetPdgCode() const
Accessors.
Int_t getMotherTrackId() const
static TDatabasePDG * Instance()
void checkUpdates(o2::framework::ProcessingContext &pc)
static GRPGeomHelper & instance()
void setRequest(std::shared_ptr< GRPGeomRequest > req)
GPUd() value_type estimateLTFast(o2 static GPUd() float estimateLTIncrement(const o2 PropagatorImpl * Instance(bool uninitialized=false)
static const TrackMCStudyConfig & Instance()
Static class with identifiers, bitmasks and names for ALICE detectors.
T get(const char *key) const
ConfigParamRegistry const & options()
void setLumiScaleType(int32_t v)
void setLumiScaleMode(int32_t v)
static constexpr int getLayer(int chipSW)
std::vector< o2::InteractionTimeRecord > & getEventRecords(bool withQED=false)
bool initFromDigitContext(std::string_view filename)
DigitizationContext const * getDigitizationContext() const
size_t getNEvents(int source) const
Get number of events.
o2::dataformats::MCEventHeader const & getMCEventHeader(int source, int event) const
retrieves the MCEventHeader for a given eventID and sourceID
size_t getNSources() const
Get number of sources.
std::vector< MCTrack > const & getTracks(int source, int event) const
variant returning all tracks for source and event at once
void extractCCDBInputs(o2::framework::ProcessingContext &pc)
void updateVDrift(float vdriftCorr, float vdrifRef, float driftTimeOffset=0)
static void requestCCDBInputs(std::vector< o2::framework::InputSpec > &inputs, std::vector< o2::framework::ConfigParamSpec > &options, const CorrectionMapsLoaderGloOpts &gloOpts)
recalculate inverse correction
void init(o2::framework::InitContext &ic)
static void requestCCDBInputs(std::vector< o2::framework::InputSpec > &inputs, bool laser=true, bool itstpcTgl=true)
void extractCCDBInputs(o2::framework::ProcessingContext &pc, bool laser=true, bool itstpcTgl=true)
const VDriftCorrFact & getVDriftObject() const
static std::string_view getSourceName(Source s)
TrackMCStudy(std::shared_ptr< DataRequest > dr, std::shared_ptr< o2::base::GRPGeomRequest > gr, GTrackID::mask_t src, const o2::tpc::CorrectionMapsLoaderGloOpts &sclOpts, bool checkSV)
void endOfStream(EndOfStreamContext &ec) final
This is invoked whenever we have an EndOfStream event.
void init(InitContext &ic) final
void finaliseCCDB(ConcreteDataMatcher &matcher, void *obj) final
void run(ProcessingContext &pc) final
void process(const o2::globaltracking::RecoContainer &recoData)
~TrackMCStudy() final=default
GLenum const GLfloat * params
constexpr double LHCBunchSpacingMUS
constexpr int LHCMaxBunches
constexpr double LHCBunchSpacingNS
Defining PrimaryVertex explicitly as messageable.
std::vector< ConfigParamSpec > Options
detail::Bracket< float > Bracketf_t
float angle2Alpha(float phi)
int angle2Sector(float phi)
std::tuple< float, float > rotateZInv(float xG, float yG, float snAlp, float csAlp)
std::pair< int, o2::dataformats::VtxTrackIndex > VTIndexV
o2::dataformats::VtxTrackRef V2TRef
o2::framework::DataProcessorSpec getTrackMCStudySpec(o2::dataformats::GlobalTrackID::mask_t srcTracks, o2::dataformats::GlobalTrackID::mask_t srcClus, const o2::tpc::CorrectionMapsLoaderGloOpts &sclOpts, bool checkSV)
create a processor spec
o2::dataformats::VtxTrackIndex VTIndex
a couple of static helper functions to create timestamp values for CCDB queries or override obsolete ...
auto getITSTracks() const
bool isTrackSourceLoaded(int src) const
o2::InteractionRecord startIR
GlobalIDSet getSingleDetectorRefs(GTrackID gidx) const
const o2::tpc::TrackTPC & getTPCTrack(GTrackID id) const
auto getITSClustersMCLabels() const
auto getPrimaryVertices() const
auto getPrimaryVertexMatchedTracks() const
auto getITSABRefs() const
auto getTPCTracksClusterRefs() const
auto getPrimaryVertexMatchedTrackRefs() const
o2::MCCompLabel getTrackMCLabel(GTrackID id) const
auto getITSClustersROFRecords() const
const o2::track::TrackParCov & getTrackParam(GTrackID gidx) const
gsl::span< const unsigned char > clusterShMapTPC
externally set TPC clusters sharing map
void collectData(o2::framework::ProcessingContext &pc, const DataRequest &request)
const o2::track::TrackParCov & getTrackParamOut(GTrackID gidx) const
auto getPrimaryVertexMCLabels() const
const o2::dataformats::PrimaryVertex & getPrimaryVertex(int i) const
const o2::its::TrackITS & getITSTrack(GTrackID gid) const
std::unique_ptr< o2::tpc::internal::getWorkflowTPCInput_ret > inputsTPCclusters
auto getITSTracksROFRecords() const
void getTrackTime(GTrackID gid, float &t, float &tErr) const
gsl::span< const unsigned int > occupancyMapTPC
externally set TPC clusters occupancy map
auto getITSClusters() const
int lumiType
what estimator to used for corrections scaling: 0: no scaling, 1: CTP, 2: IDC
int lumiMode
what corrections method to use: 0: classical scaling, 1: Using of the derivative map,...
float refTimeOffset
additive time offset reference (\mus)
float refVDrift
reference vdrift for which factor was extracted
float getTimeOffset() const
float timeOffsetCorr
additive time offset correction (\mus)
float corrFact
drift velocity correction factor (multiplicative)
LOG(info)<< "Compressed in "<< sw.CpuTime()<< " s"