13#include <TStopwatch.h>
57#include "GPUParam.inc"
62#include <unordered_map>
80using VTIndexV = std::pair<int, o2::dataformats::VtxTrackIndex>;
90 : mDataRequest(dr), mGGCCDBRequest(gr), mTracksSrc(
src), mCheckSV(checkSV) {}
96 void process(const
o2::globaltracking::RecoContainer& recoData);
99 void processTPCTrackRefs();
100 void processITSTracks(const
o2::globaltracking::RecoContainer& recoData);
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;
112 const
std::vector<
o2::
MCTrack>* mCurrMCTracks =
nullptr;
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 std::vector<o2::BaseCluster<float>> mITSClustersArray;
127 bool mCheckSV =
false;
128 bool mRecProcStage =
false;
129 int mNTPCOccBinLength = 0;
130 float mNTPCOccBinLengthInv = -1.f;
132 float mITSTimeBiasMUS = 0.f;
133 float mITSROFrameLengthMUS = 0.f;
134 float mTPCTBinMUS = 0.;
136 int mNCheckDecays = 0;
140 std::vector<int> mITSROF;
141 std::vector<TBracket> mITSROFBracket;
142 std::vector<o2::MCCompLabel> mDecProdLblPool;
143 std::vector<MCVertex> mMCVtVec{};
149 int daughterFirst = -1;
150 int daughterLast = -1;
153 std::vector<std::vector<DecayRef>> mDecaysMaps;
154 std::unordered_map<o2::MCCompLabel, TrackFamily> mSelMCTracks;
155 std::unordered_map<o2::MCCompLabel, std::pair<int, int>> mSelTRefIdx;
156 std::vector<o2::track::TrackPar> mSelTRefs;
158 static constexpr float MaxSnp = 0.9;
166 mDBGOut = std::make_unique<o2::utils::TreeStreamRedirector>(
"trackMCStudy.root",
"recreate");
167 mVerbose = ic.
options().
get<
int>(
"device-verbosity");
170 for (
int id = 0;
id <
sizeof(
params.decayPDG) /
sizeof(
int);
id++) {
171 if (
params.decayPDG[
id] < 0) {
176 mDecaysMaps.resize(mNCheckDecays);
182 for (
int i = 0;
i < mNCheckDecays;
i++) {
183 mDecaysMaps[
i].clear();
185 mDecProdLblPool.clear();
187 mCurrMCTracks =
nullptr;
190 updateTimeDependentParams(pc);
191 mRecProcStage =
false;
199 auto const&
raw = pc.
inputs().
get<
const char*>(
"corrMap");
200 mTPCCorrMaps = &o2::gpu::TPCFastTransformPOD::get(raw);
201 static bool initOnceDone =
false;
206 LOGP(info,
"VertexTrackMatcher ITSROFrameLengthMUS:{}", mITSROFrameLengthMUS);
209 mTPCTBinMUS = elParam.ZbinWidth;
214 mFitterV0.
setOldMode(svparam.oldDCAFitterMode);
215 mFitterV0.setUseAbsDCA(svparam.useAbsDCA);
216 mFitterV0.setPropagateToPCA(
false);
217 mFitterV0.setMaxR(svparam.maxRIni);
218 mFitterV0.setMinParamChange(svparam.minParamChange);
219 mFitterV0.setMinRelChi2Change(svparam.minRelChi2Change);
220 mFitterV0.setMaxDZIni(svparam.maxDZIni);
221 mFitterV0.setMaxDXYIni(svparam.maxDXYIni);
222 mFitterV0.setMaxChi2(svparam.maxChi2);
224 mFitterV0.setUsePropagator(svparam.usePropagator);
225 mFitterV0.setRefitWithMatCorr(svparam.refitWithMatCorr);
226 mFitterV0.setMaxStep(svparam.maxStep);
227 mFitterV0.setMaxSnp(svparam.maxSnp);
228 mFitterV0.setMinXSeed(svparam.minXSeed);
235 constexpr float SQRT12Inv = 0.288675f;
242 int nv = vtxRefs.size();
246 prepareITSData(recoData);
247 loadTPCOccMap(recoData);
248 auto getITSPatt = [&](
GTrackID gid, uint8_t& ncl) {
252 ncl = itsTrf.getNClusters();
253 for (
int il = 0; il < 7; il++) {
254 if (itsTrf.hasHitOnLayer(il)) {
261 for (
int il = 0; il < 7; il++) {
262 if (itsTr.hasHitOnLayer(il)) {
273 uint8_t clSect = 0, clRow = 0, lowestR = -1;
278 for (
int ic = 0; ic < trc.getNClusterReferences(); ic++) {
279 trc.getClusterReference(clRefs, ic, clSect, clRow, clIdx);
280 if (clRow < lowestR) {
284 unsigned int absoluteIndex = tpcClusAcc.clusterOffset[clSect][clRow] + clIdx;
289 tref.lowestPadRow = lowestR;
290 const auto& clus = tpcClusAcc.clusters[clSect][clRow][clIdx];
291 int padFromEdge =
int(clus.getPad()), npads = o2::gpu::GPUTPCGeometry::NPads(clRow);
292 if (padFromEdge > npads / 2) {
293 padFromEdge = npads - 1 - padFromEdge;
295 tref.padFromEdge = uint8_t(padFromEdge);
296 trc.getClusterReference(clRefs, 0, clSect, clRow, clIdx);
297 tref.rowMaxTPC = clRow;
304 const auto* TPCClMClab = recoData.
inputsTPCclusters->clusterIndex.clustersMCTruth;
306 for (
int ic = 0; ic < trc.getNClusterReferences(); ic++) {
307 uint8_t clSect = 0, clRow = 0;
309 trc.getClusterReference(clRefs, ic, clSect, clRow, clIdx);
310 auto labels = TPCClMClab->getLabels(clIdx + TPCClusterIdxStruct.clusterOffset[clSect][clRow]);
311 for (
auto& lbl :
labels) {
326 unsigned int rofCount = 0;
328 for (
const auto& mcIR : mcEvRecords) {
329 long tbc = mcIR.differenceInBC(recoData.
startIR);
330 auto& mcVtx = mMCVtVec.emplace_back();
332 mcVtx.ID = mIntBC.size();
333 mIntBC.push_back(tbc);
334 int occBin = tbc / 8 * mNTPCOccBinLengthInv;
335 mTPCOcc.push_back(occBin < 0 ? mTBinClOcc[0] : (occBin >= mTBinClOcc.size() ? mTBinClOcc.back() : mTBinClOcc[occBin]));
337 long gbc = mcIR.toLong();
338 while (rofCount < ITSClusROFRec.size()) {
339 long rofbcMin = ITSClusROFRec[rofCount].getBCData().toLong() + ITSTimeBias, rofbcMax = rofbcMin + ITSROFLen;
340 if (gbc < rofbcMin) {
341 mITSOcc.push_back(0);
342 }
else if (gbc < rofbcMax) {
343 mITSOcc.push_back(ITSClusROFRec[rofCount].getNEntries());
350 if (mNTPCOccBinLengthInv > 0.f) {
351 mcVtx.occTPCV.resize(
params.nOccBinsDrift);
352 int grp = TMath::Max(1, TMath::Nint(
params.nTBPerOccBin * mNTPCOccBinLengthInv));
353 for (
int ib = 0; ib <
params.nOccBinsDrift; ib++) {
355 int tbs = occBin + TMath::Nint(ib *
params.nTBPerOccBin * mNTPCOccBinLengthInv);
356 for (
int ig = 0; ig < grp; ig++) {
357 if (tbs >= 0 && tbs <
int(mTBinClOccHist.size())) {
358 smb += mTBinClOccHist[tbs];
362 mcVtx.occTPCV[ib] = smb;
365 if (rofCount >= ITSClusROFRec.size()) {
366 mITSOcc.push_back(0);
371 int curSrcMC = 0, curEvMC = 0;
372 for (curSrcMC = 0; curSrcMC < (
int)mcReader.
getNSources(); curSrcMC++) {
374 LOGP(info,
"Source {}", curSrcMC);
377 bool okAccVtx =
true;
378 if (nev != (
int)mMCVtVec.size()) {
379 LOGP(
debug,
"source {} has {} events while {} MC vertices were booked", curSrcMC, nev, mMCVtVec.size());
381 if (nev > (
int)mMCVtVec.size()) {
385 for (curEvMC = 0; curEvMC < nev; curEvMC++) {
387 LOGP(info,
"Event {}", curEvMC);
389 mCurrMCTracks = &mcReader.
getTracks(curSrcMC, curEvMC);
392 auto&
pos = mMCVtVec[curEvMC].pos;
394 pos[0] = mCurrMCVertex.X();
395 pos[1] = mCurrMCVertex.Y();
396 pos[2] = mCurrMCVertex.Z();
399 for (
int itr = 0; itr < mCurrMCTracks->size(); itr++) {
400 processMCParticle(curSrcMC, curEvMC, itr);
405 for (
int id = 0;
id < mNCheckDecays;
id++) {
406 LOGP(info,
"Decay PDG={} : {} entries",
params.decayPDG[
id], mDecaysMaps[
id].size());
411 mRecProcStage =
true;
412 for (
int iv = 0; iv < nv; iv++) {
414 LOGP(info,
"processing PV {} of {}", iv, nv);
418 if (iv < (
int)pvvecLbl.size()) {
419 pvLbl = pvvecLbl[iv];
422 mMCVtVec[pvLbl.
getEventID()].recVtx.emplace_back(
RecPV{pvvec[iv], pvLbl});
425 const auto& vtref = vtxRefs[iv];
431 int idMin = vtref.getFirstEntryOfSource(is), idMax = idMin + vtref.getEntriesOfSource(is);
432 for (
int i = idMin;
i < idMax;
i++) {
433 auto vid = trackIndex[
i];
435 if (trc.getPt() <
params.minPt || std::abs(trc.getTgl()) >
params.maxTgl) {
441 auto entry = mSelMCTracks.find(lbl);
442 if (
entry == mSelMCTracks.end()) {
443 if (lbl.getSourceID() != curSrcMC || lbl.getEventID() != curEvMC) {
444 curSrcMC = lbl.getSourceID();
445 curEvMC = lbl.getEventID();
446 mCurrMCTracks = &mcReader.
getTracks(curSrcMC, curEvMC);
449 if (!acceptMCCharged((*mCurrMCTracks)[lbl.getTrackID()], lbl)) {
452 entry = mSelMCTracks.find(lbl);
454 auto& trackFamily =
entry->second;
455 if (vid.isAmbiguous()) {
456 if (trackFamily.contains(vid)) {
460 auto& trf = trackFamily.recTracks.emplace_back();
470 if (lblITS == trackFamily.mcTrackInfo.label) {
474 if (trcITSF.getPt() <
params.minPt || std::abs(trcITSF.getTgl()) >
params.maxTgl) {
477 auto entryOfFake = mSelMCTracks.find(lblITS);
478 if (entryOfFake == mSelMCTracks.end()) {
481 auto& trackFamilyOfFake = entryOfFake->second;
482 auto& trfOfFake = trackFamilyOfFake.recTracks.emplace_back();
487 LOGP(info,
"Matched rec track {} to MC track {}", vid.asString(),
entry->first.asString());
496 LOGP(info,
"collected {} MC tracks", mSelMCTracks.size());
497 if (
params.minTPCRefsToExtractClRes > 0 ||
params.storeTPCTrackRefs) {
498 processTPCTrackRefs();
502 for (
auto&
entry : mSelMCTracks) {
503 auto& trackFam =
entry.second;
504 auto& tracks = trackFam.recTracks;
506 if (tracks.empty()) {
510 LOGP(info,
"Processing MC track#{} {} -> {} reconstructed tracks", mcnt - 1,
entry.first.asString(), tracks.size());
513 std::sort(tracks.begin(), tracks.end(), [](
const RecTrack& lhs,
const RecTrack& rhs) {
514 const auto mskL = lhs.gid.getSourceDetectorsMask();
515 const auto mskR = rhs.gid.getSourceDetectorsMask();
516 bool itstpcL = mskL[DetID::ITS] && mskL[DetID::TPC], itstpcR = mskR[DetID::ITS] && mskR[DetID::TPC];
517 if (itstpcL && !itstpcR) {
520 return lhs.gid.getSource() > rhs.gid.getSource();
522 if (
params.storeTPCTrackRefs) {
523 auto rft = mSelTRefIdx.find(
entry.first);
524 if (rft != mSelTRefIdx.end()) {
525 auto rfent = rft->second;
526 for (
int irf = rfent.first; irf < rfent.second; irf++) {
527 trackFam.mcTrackInfo.trackRefsTPC.push_back(mSelTRefs[irf]);
533 for (
auto& tref : tracks) {
534 if (tref.gid.isSourceSet()) {
540 auto msk = tref.gid.getSourceDetectorsMask();
543 tref.pattITS = getITSPatt(gidSet[
GTrackID::ITS], tref.nClITS);
544 if (trackFam.entITS < 0) {
545 trackFam.entITS = tcnt;
548 if (lblITS.isFake()) {
551 if (lblITS == trackFam.mcTrackInfo.label) {
552 trackFam.entITSFound = tcnt;
561 if (trackFam.entITSTPC < 0) {
562 trackFam.entITSTPC = tcnt;
588 tref.nClTPC = trtpc.getNClusters();
589 if (trtpc.hasBothSidesClusters()) {
592 fillTPCClusterInfo(trtpc, tref);
593 flagTPCClusters(trtpc,
entry.first);
594 if (trackFam.entTPC < 0) {
595 trackFam.entTPC = tcnt;
596 trackFam.tpcT0 = trtpc.getTime0();
620 float ts = 0, terr = 0;
625 const auto& itsBra = mITSROFBracket[mITSROF[tref.gid.getIndex()]];
626 tref.ts =
timeEst{itsBra.mean(), itsBra.delta() * SQRT12Inv};
629 LOGP(info,
"Invalid entry {} of {} getTrackMCLabel {}", tcnt, tracks.size(), tref.gid.asString());
633 if (trackFam.entITS > -1 && trackFam.entTPC > -1) {
638 if (propagateToRefX(trcTPC, trcITS)) {
639 trackFam.trackITSProp = trcITS;
640 trackFam.trackTPCProp = trcTPC;
642 trackFam.trackITSProp.invalidate();
643 trackFam.trackTPCProp.invalidate();
646 trackFam.trackITSProp.invalidate();
647 trackFam.trackTPCProp.invalidate();
653 auto v0s = recoData.getV0sIdx();
656 s += fmt::format(
" par {} Ntpccl={} Nitscl={} ",
f.mcTrackInfo.pdgParent,
f.mcTrackInfo.nTPCCl,
f.mcTrackInfo.nITSCl);
657 for (
auto& t :
f.recTracks) {
658 s += t.gid.asString();
663 for (
int svID; svID < (
int)v0s.size(); svID++) {
664 const auto& v0idx = v0s[svID];
665 int nOKProngs = 0, realMCSVID = -1;
666 int8_t decTypeID = -1;
667 for (
int ipr = 0; ipr < v0idx.getNProngs(); ipr++) {
668 auto mcl = recoData.getTrackMCLabel(v0idx.getProngID(ipr));
669 auto itl = mSelMCTracks.find(mcl);
670 if (itl == mSelMCTracks.end()) {
674 auto& trackFamily = itl->second;
675 int decayParentIndex = trackFamily.mcTrackInfo.parentEntry;
676 if (decayParentIndex < 0) {
680 realMCSVID = decayParentIndex;
681 decTypeID = trackFamily.mcTrackInfo.parentDecID;
683 LOGP(
debug,
"Prong{} {} comes from {}/{}", ipr, prpr(trackFamily), decTypeID, realMCSVID);
686 if (realMCSVID != decayParentIndex || decTypeID != trackFamily.mcTrackInfo.parentDecID) {
689 LOGP(
debug,
"Prong{} {} comes from {}/{}", ipr, prpr(trackFamily), decTypeID, realMCSVID);
692 if (nOKProngs == v0idx.getNProngs()) {
693 LOGP(
debug,
"Decay {}/{} was found", decTypeID, realMCSVID);
694 mDecaysMaps[decTypeID][realMCSVID].foundSVID = svID;
700 fillMCClusterInfo(recoData);
703 for (
auto&
entry : mSelMCTracks) {
704 auto& trackFam =
entry.second;
705 (*mDBGOut) <<
"tracks" <<
"tr=" << trackFam <<
"\n";
709 std::vector<TrackFamily> decFam;
710 for (
int id = 0;
id < mNCheckDecays;
id++) {
711 std::string decTreeName = fmt::format(
"dec{}",
params.decayPDG[
id]);
712 for (
const auto& dec : mDecaysMaps[
id]) {
715 for (
int idd = dec.daughterFirst; idd <= dec.daughterLast; idd++) {
716 auto dtLbl = mDecProdLblPool[idd];
717 const auto& dtFamily = mSelMCTracks[dtLbl];
718 if (dtFamily.mcTrackInfo.pdgParent != dec.pdg) {
719 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);
723 decFam.push_back(dtFamily);
727 if (dec.foundSVID >= 0 && !refitV0(dec.foundSVID,
v0, recoData)) {
730 (*mDBGOut) << decTreeName.c_str() <<
"pdgPar=" << dec.pdg <<
"trPar=" << dec.parent <<
"prod=" << decFam <<
"found=" << dec.foundSVID <<
"sv=" <<
v0 <<
"\n";
735 for (
auto& mcVtx : mMCVtVec) {
736 std::sort(mcVtx.recVtx.begin(), mcVtx.recVtx.end(), [](
const RecPV& lhs,
const RecPV& rhs) {
737 return lhs.pv.getNContributors() > rhs.pv.getNContributors();
739 (*mDBGOut) <<
"mcVtxTree" <<
"mcVtx=" << mcVtx <<
"\n";
742 if (
params.storeITSInfo) {
743 processITSTracks(recoData);
747void TrackMCStudy::processTPCTrackRefs()
749 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};
750 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};
751 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};
753 for (
auto&
entry : mSelMCTracks) {
754 auto lb =
entry.first;
755 auto trspan = mcReader.getTrackRefs(lb.getSourceID(), lb.getEventID(), lb.getTrackID());
756 int q =
entry.second.mcTrackInfo.track.getCharge();
760 int ref0entry = mSelTRefs.size(), nrefsSel = 0;
761 for (
const auto& trf : trspan) {
762 if (trf.getDetectorId() != 1) {
765 float pT = std::sqrt(trf.Px() * trf.Px() + trf.Py() * trf.Py());
769 float secX, secY,
phi = std::atan2(trf.Y(), trf.X());
772 float phiPt = std::atan2(trf.Py(), trf.Px());
773 o2::math_utils::bringTo02Pi(phiPt);
774 auto dphiPt = phiPt - alpsec[sector];
782 float tgL = trf.Pz() / pT;
783 std::array<float, 5> pars = {secY, trf.Z(), std::sin(dphiPt), tgL, q / pT};
784 auto& refTrack = mSelTRefs.emplace_back(secX, alpsec[sector], pars);
785 refTrack.setUserField(uint16_t(sector));
788 if (nrefsSel <
params.minTPCRefsToExtractClRes) {
789 mSelTRefs.resize(ref0entry);
792 mSelTRefIdx[lb] = std::make_pair(ref0entry, ref0entry + nrefsSel);
801 const auto* TPCClMClab = recoData.
inputsTPCclusters->clusterIndex.clustersMCTruth;
805 for (uint8_t
row = 0;
row < 152;
row++) {
806 for (uint8_t sector = 0; sector < 36; sector++) {
807 unsigned int offs = TPCClusterIdxStruct.clusterOffset[sector][
row];
808 for (
unsigned int icl0 = 0; icl0 < TPCClusterIdxStruct.nClusters[sector][
row]; icl0++) {
809 const auto labels = TPCClMClab->getLabels(icl0 + offs);
811 for (
const auto& lbl :
labels) {
812 if (!lbl.isValid()) {
817 const auto& clus = TPCClusterIdxStruct.clusters[sector][
row][icl0];
818 int tbinH =
int(clus.getTime() * mNTPCOccBinLengthInv);
819 clRes.contTracks.clear();
820 bool doClusRes = (
params.minTPCRefsToExtractClRes > 0) && (
params.rejectClustersResStat <= 0. || gRandom->Rndm() <
params.rejectClustersResStat);
822 bool corrAttach = lbl.isFake();
823 lbl.setFakeFlag(
false);
824 auto entry = mSelMCTracks.find(lbl);
825 if (
entry == mSelMCTracks.end()) {
828 auto& mctr =
entry->second.mcTrackInfo;
830 if (
row > mctr.maxTPCRow) {
831 mctr.maxTPCRow =
row;
832 mctr.maxTPCRowSect = sector;
834 }
else if (
row == 0 && mctr.nUsedPadRows == 0) {
837 if (
row < mctr.minTPCRow) {
838 mctr.minTPCRow =
row;
839 mctr.minTPCRowSect = sector;
841 if (mctr.minTPCRowSect == sector &&
row > mctr.maxTPCRowInner) {
842 mctr.maxTPCRowInner =
row;
849 auto entTRefIDsIt = mSelTRefIdx.find(lbl);
850 if (entTRefIDsIt == mSelTRefIdx.end()) {
854 mTPCCorrMaps->Transform(sector,
row, clus.getPad(), clus.getTime(), xc, yc, zc, mctr.bcInTF / 8.);
856 const auto& entTRefIDs = entTRefIDsIt->second;
858 int entIDBelow = -1, entIDAbove = -1;
859 float xBelow = -1e6, xAbove = 1e6;
861 for (
int entID = entTRefIDs.first; entID < entTRefIDs.second; entID++) {
862 const auto& refTr = mSelTRefs[entID];
863 if (refTr.getUserField() != sector % 18) {
866 if ((refTr.getX() < xc) && (refTr.getX() > xBelow) && (refTr.getX() > xc -
params.maxTPCRefExtrap)) {
867 xBelow = refTr.getX();
870 if ((refTr.getX() > xc) && (refTr.getX() < xAbove) && (refTr.getX() < xc +
params.maxTPCRefExtrap)) {
871 xAbove = refTr.getX();
875 if ((entIDBelow < 0 && entIDAbove < 0) || (
params.requireTopBottomRefs && (entIDBelow < 0 || entIDAbove < 0))) {
880 bool okBelow = entIDBelow >= 0 && prop->PropagateToXBxByBz((tparBelow = mSelTRefs[entIDBelow]), xc, 0.99, 2.);
881 bool okAbove = entIDAbove >= 0 && prop->PropagateToXBxByBz((tparAbove = mSelTRefs[entIDAbove]), xc, 0.99, 2.);
882 if ((!okBelow && !okAbove) || (
params.requireTopBottomRefs && (!okBelow || !okAbove))) {
887 auto& clCont = clRes.contTracks.emplace_back();
888 clCont.corrAttach = corrAttach;
890 clCont.below = {mSelTRefs[entIDBelow].getX(), tparBelow.getY(), tparBelow.getZ()};
891 clCont.snp += tparBelow.getSnp();
892 clCont.tgl += tparBelow.getTgl();
893 clCont.q2pt += tparBelow.getQ2Pt();
897 clCont.above = {mSelTRefs[entIDAbove].getX(), tparAbove.getY(), tparAbove.getZ()};
898 clCont.snp += tparAbove.getSnp();
899 clCont.tgl += tparAbove.getTgl();
900 clCont.q2pt += tparAbove.getQ2Pt();
904 if (clRes.contTracks.size() == 1) {
905 int occBin = mctr.bcInTF / 8 * mNTPCOccBinLengthInv;
906 clRes.occ = occBin < 0 ? mTBinClOcc[0] : (occBin >= mTBinClOcc.size() ? mTBinClOcc.back() : mTBinClOcc[occBin]);
908 clCont.xyz = {xc, yc, zc};
915 clRes.contTracks.pop_back();
919 if (clRes.getNCont()) {
922 clRes.qtot = clus.getQtot();
923 clRes.qmax = clus.getQmax();
924 clRes.flags = clus.getFlags();
925 clRes.sigmaTimePacked = clus.sigmaTimePacked;
926 clRes.sigmaPadPacked = clus.sigmaPadPacked;
927 clRes.ncont = ncontLb;
932 }
else if (tbinH >=
int(mTBinClOccHist.size())) {
933 tbinH = (
int)mTBinClOccHist.size() - 1;
935 clRes.occBin = mTBinClOccHist[tbinH];
937 (*mDBGOut) <<
"clres" <<
"clr=" << clRes <<
"\n";
945 for (
unsigned int icl = 0; icl <
ITSClusters.size(); icl++) {
946 const auto labels = mcITSClusters->getLabels(icl);
947 for (
const auto& lbl :
labels) {
948 auto entry = mSelMCTracks.find(lbl);
949 if (
entry == mSelMCTracks.end()) {
952 auto& mctr =
entry->second.mcTrackInfo;
958 for (
auto&
entry : mSelMCTracks) {
959 const auto& trackFam =
entry.second;
960 const auto& mctr = trackFam.mcTrackInfo;
961 if (mctr.getLowestITSLayer() == 0 && mctr.getNITSClusCont() > 3) {
962 auto& mcev = mMCVtVec[mctr.label.getEventID()];
963 mcev.nTrackSelRCBL0++;
964 if (mctr.isPrimary()) {
965 mcev.nTrackSelRCBL0P++;
967 if (trackFam.entITSFound >= 0) {
968 mcev.nTrackRecRCBL0++;
971 if (mctr.maxTPCRow - mctr.minTPCRow >=
params.nMinTPCRowSpan) {
972 mcev.nTrackSelRCBL1++;
973 if (mctr.isPrimary()) {
974 mcev.nTrackSelRCBL1P++;
976 if (trackFam.entITSTPC >= 0) {
977 mcev.nTrackRecRCBL1++;
986 bool refReached =
false;
987 constexpr float TgHalfSector = 0.17632698f;
995 if (fabs(trcTPC.getY()) <
par.XMatchingRef * TgHalfSector) {
1003 if (!trcTPC.rotate(alphaNew) != 0) {
1011 float alp = trcTPC.getAlpha();
1028 if (mTPCVDriftHelper.accountCCDBInputs(matcher, obj)) {
1032 LOG(info) <<
"ITS Alpide param updated";
1034 par.printKeyValues();
1040 LOG(info) <<
"cluster dictionary updated";
1051 int nROFs = ITSTrackROFRec.size();
1053 mITSROFBracket.clear();
1054 mITSROF.reserve(ITSTracksArray.size());
1055 mITSROFBracket.reserve(ITSTracksArray.size());
1056 for (
int irof = 0; irof < nROFs; irof++) {
1057 const auto& rofRec = ITSTrackROFRec[irof];
1058 long nBC = rofRec.getBCData().differenceInBC(recoData.
startIR);
1060 float tMax = tMin + mITSROFrameLengthMUS;
1061 mITSROFBracket.emplace_back(tMin, tMax);
1062 for (
int it = 0; it < rofRec.getNEntries(); it++) {
1063 mITSROF.push_back(irof);
1075bool TrackMCStudy::processMCParticle(
int src,
int ev,
int trid)
1077 const auto& mcPart = (*mCurrMCTracks)[trid];
1078 int pdg = mcPart.GetPdgCode();
1084 if (mcPart.T() <
params.decayMotherMaxT) {
1085 for (
int id = 0;
id < mNCheckDecays;
id++) {
1086 if (
params.decayPDG[
id] == std::abs(pdg)) {
1092 auto& decayPool = mDecaysMaps[decay];
1093 int idd0 = mcPart.getFirstDaughterTrackId(), idd1 = mcPart.getLastDaughterTrackId();
1094 int dtStart = mDecProdLblPool.size(), dtEnd = -1;
1098 for (
int idd = idd0; idd <= idd1; idd++) {
1099 const auto& product = (*mCurrMCTracks)[idd];
1101 if (!acceptMCCharged(product, lbld, decay)) {
1103 mDecProdLblPool.resize(dtStart);
1106 mDecProdLblPool.push_back(lbld);
1110 dtEnd = mDecProdLblPool.size();
1111 for (
int dtid = dtStart; dtid < dtEnd; dtid++) {
1112 mSelMCTracks[mDecProdLblPool[dtid]].mcTrackInfo.parentEntry = decayPool.size();
1113 mSelMCTracks[mDecProdLblPool[dtid]].mcTrackInfo.parentDecID = int8_t(decay);
1116 std::array<float, 3> xyz{(float)mcPart.GetStartVertexCoordinatesX(), (float)mcPart.GetStartVertexCoordinatesY(), (float)mcPart.GetStartVertexCoordinatesZ()};
1117 std::array<float, 3> pxyz{(float)mcPart.GetStartVertexMomentumX(), (float)mcPart.GetStartVertexMomentumY(), (float)mcPart.GetStartVertexMomentumZ()};
1118 decayPool.emplace_back(DecayRef{lbl,
1120 mcPart.GetPdgCode(), dtStart, dtEnd});
1122 LOGP(info,
"Adding MC parent pdg={} {}, with prongs in {}:{} range", pdg, lbl.asString(), dtStart, dtEnd);
1130 if (mSelMCTracks.find(lbl) == mSelMCTracks.end()) {
1131 res = acceptMCCharged(mcPart, lbl);
1144 if (mVerbose > 1 && followDecay > -1) {
1145 LOGP(info,
"rejecting decay {} prong : pdg={}, pT={}, tgL={}, r={}", followDecay, tr.
GetPdgCode(), tr.
GetPt(), tr.
GetTgl(), std::sqrt(tr.
R2()));
1150 float r2 = dx * dx + dy * dy;
1151 float posTgl2 = r2 > 1 && std::abs(dz) < 20 ? dz * dz / r2 : 0;
1152 if (posTgl2 >
params.maxPosTglMC *
params.maxPosTglMC) {
1153 if (mVerbose > 1 && followDecay > -1) {
1154 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));
1158 if (
params.requireITSorTPCTrackRefs) {
1161 for (
const auto& trf : trspan) {
1176 if (pPDG->Charge() == 0.) {
1179 return addMCParticle(tr, lb, pPDG);
1190 auto& mcEntry = mSelMCTracks[lb];
1191 mcEntry.mcTrackInfo.pdg = mcPart.
GetPdgCode();
1192 mcEntry.mcTrackInfo.track =
o2::track::TrackPar(xyz, pxyz, TMath::Nint(pPDG->Charge() / 3),
true);
1193 mcEntry.mcTrackInfo.label = lb;
1194 mcEntry.mcTrackInfo.bcInTF = mIntBC[lb.
getEventID()];
1195 mcEntry.mcTrackInfo.occTPC = mTPCOcc[lb.
getEventID()];
1196 mcEntry.mcTrackInfo.occITS = mITSOcc[lb.
getEventID()];
1197 mcEntry.mcTrackInfo.occTPCV = mMCVtVec[lb.
getEventID()].occTPCV;
1198 if (mRecProcStage) {
1199 mcEntry.mcTrackInfo.setAddedAtRecStage();
1202 mcEntry.mcTrackInfo.setPrimary();
1207 const auto& mcPartPar = (*mCurrMCTracks)[moth];
1208 mcEntry.mcTrackInfo.pdgParent = mcPartPar.GetPdgCode();
1212 if (mcPart.
GetPt() > 0.1) {
1229 if (svparam.mTPCTrackPhotonTune && isTPConly) {
1230 mFitterV0.setMaxDZIni(svparam.mTPCTrackMaxDZIni);
1231 mFitterV0.setMaxDXYIni(svparam.mTPCTrackMaxDXYIni);
1232 mFitterV0.setMaxChi2(svparam.mTPCTrackMaxChi2);
1233 mFitterV0.setCollinear(
true);
1235 int nCand = mFitterV0.process(seedP, seedN);
1236 if (svparam.mTPCTrackPhotonTune && isTPConly) {
1238 mFitterV0.setMaxDZIni(svparam.maxDZIni);
1239 mFitterV0.setMaxDXYIni(svparam.maxDXYIni);
1240 mFitterV0.setMaxChi2(svparam.maxChi2);
1241 mFitterV0.setCollinear(
false);
1247 if (!mFitterV0.isPropagateTracksToVertexDone(cand) && !mFitterV0.propagateTracksToVertex(cand)) {
1250 const auto& trPProp = mFitterV0.getTrack(0, cand);
1251 const auto& trNProp = mFitterV0.getTrack(1, cand);
1252 std::array<float, 3> pP{}, pN{};
1253 trPProp.getPxPyPzGlo(pP);
1254 trNProp.getPxPyPzGlo(pN);
1255 std::array<float, 3> pV0 = {pP[0] + pN[0], pP[1] + pN[1], pP[2] + pN[2]};
1256 auto p2V0 = pV0[0] * pV0[0] + pV0[1] * pV0[1] + pV0[2] * pV0[2];
1258 const auto v0XYZ = mFitterV0.getPCACandidatePos(cand);
1259 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];
1260 float cosPA = prodXYZv0 / std::sqrt((dx * dx + dy * dy + dz * dz) * p2V0);
1262 v0.
setDCA(mFitterV0.getChi2AtPCACandidate(cand));
1272 auto TPCRefitter = std::make_unique<o2::gpu::GPUO2InterfaceRefit>(&recoData.
inputsTPCclusters->clusterIndex, mTPCCorrMaps, prop->getNominalBz(),
1274 mNTPCOccBinLength = TPCRefitter->getParam()->rec.tpc.occupancyMapTimeBins;
1276 if (mNTPCOccBinLength > 1 && TPCOccMap.size()) {
1277 mNTPCOccBinLengthInv = 1. / mNTPCOccBinLength;
1280 mTBinClOcc.resize(nTPCOccBins);
1281 mTBinClOccHist.resize(nTPCOccBins);
1282 float sm = 0., tb = 0.5 * mNTPCOccBinLength;
1283 for (
int i = 0;
i < nTPCOccBins;
i++) {
1284 mTBinClOccHist[
i] = TPCRefitter->getParam()->GetUnscaledMult(tb);
1285 tb += mNTPCOccBinLength;
1287 for (
int i = nTPCOccBins;
i--;) {
1288 sm += mTBinClOccHist[
i];
1289 if (
i + sumBins < nTPCOccBins) {
1290 sm -= mTBinClOccHist[
i + sumBins];
1295 mTBinClOcc.resize(1);
1296 mTBinClOccHist.resize(1);
1303 LOGP(warn,
"ITS data is not loaded");
1312 auto pattIt = patterns.begin();
1313 mITSClustersArray.clear();
1314 mITSClustersArray.reserve(clusITS.size());
1318 int ntr = itsLbls.size();
1319 LOGP(info,
"We have {} ITS clusters and the number of patterns is {}, ITSdict:{} NMCLabels: {}", clusITS.size(), patterns.size(), mITSDict !=
nullptr, itsLbls.size());
1321 std::vector<int> evord(ntr);
1322 std::iota(evord.begin(), evord.end(), 0);
1323 std::sort(evord.begin(), evord.end(), [&](
int i,
int j) { return itsLbls[i] < itsLbls[j]; });
1324 std::vector<ITSHitInfo> outHitInfo;
1325 std::array<int, 7> cl2arr{};
1327 for (
int itr0 = 0; itr0 < ntr; itr0++) {
1328 auto itr = evord[itr0];
1329 const auto& itsTr = itsTracks[itr];
1330 const auto& itsLb = itsLbls[itr];
1332 int nCl = itsTr.getNClusters();
1333 if (itsLb.isFake() || nCl <
params.minITSClForITSoutput) {
1336 auto entrySel = mSelMCTracks.find(itsLb);
1337 if (entrySel == mSelMCTracks.end()) {
1342 auto clEntry = itsTr.getFirstClusterEntry();
1343 for (
int iCl = nCl; iCl--;) {
1344 const auto& cls = mITSClustersArray[itsClRefs[clEntry + iCl]];
1345 int hpos = outHitInfo.size();
1346 auto& hinf = outHitInfo.emplace_back();
1348 hinf.clus.setCount(geom->getLayer(cls.getSensorID()));
1349 geom->getSensorXAlphaRefPlane(cls.getSensorID(), hinf.chipX, hinf.chipAlpha);
1350 cl2arr[hinf.clus.getCount()] = hpos;
1352 auto trspan = mcReader.getTrackRefs(itsLb.getSourceID(), itsLb.getEventID(), itsLb.getTrackID());
1353 int ilrc = -1, nrefAcc = 0;
1354 for (
const auto& trf : trspan) {
1355 if (trf.getDetectorId() != 0) {
1358 int lrt = trf.getUserId();
1359 int clEnt = cl2arr[lrt];
1363 auto& hinf = outHitInfo[clEnt];
1366 if (hinf.trefXT < 1 || std::abs(traX - hinf.chipX) < std::abs(hinf.trefXT - hinf.chipX)) {
1367 if (hinf.trefXT < 1) {
1375 (*mDBGOut) <<
"itsTree" <<
"hits=" << outHitInfo <<
"trIn=" << ((
o2::track::TrackParCov&)itsTr) <<
"trOut=" << itsTr.getParamOut() <<
"mcTr=" << entrySel->second.mcTrackInfo.track <<
"mcPDG=" << entrySel->second.mcTrackInfo.pdg <<
"nTrefs=" << nrefAcc <<
"\n";
1381 std::vector<OutputSpec> outputs;
1383 {
"device-verbosity", VariantType::Int, 0, {
"Verbosity level"}},
1384 {
"dcay-vs-pt", VariantType::String,
"0.0105 + 0.0350 / pow(x, 1.1)", {
"Formula for global tracks DCAy vs pT cut"}},
1385 {
"min-tpc-clusters", VariantType::Int, 60, {
"Cut on TPC clusters"}},
1386 {
"max-tpc-dcay", VariantType::Float, 2.f, {
"Cut on TPC dcaY"}},
1387 {
"max-tpc-dcaz", VariantType::Float, 2.f, {
"Cut on TPC dcaZ"}},
1388 {
"min-x-prop", VariantType::Float, 6.f, {
"track should be propagated to this X at least"}}};
1389 auto dataRequest = std::make_shared<DataRequest>();
1391 dataRequest->requestTracks(srcTracks, useMC);
1392 dataRequest->requestClusters(srcClusters, useMC);
1393 dataRequest->requestPrimaryVertices(useMC);
1395 dataRequest->requestSecondaryVertices(useMC);
1399 auto ggRequest = std::make_shared<o2::base::GRPGeomRequest>(
false,
1405 dataRequest->inputs,
1412 AlgorithmSpec{adaptFromTask<TrackMCStudy>(dataRequest, ggRequest, srcTracks, checkSV)},
std::vector< std::string > labels
Defintions for N-prongs secondary vertex fit.
Definition of the GeometryManager class.
o2::raw::RawFileWriter * raw
Helper for geometry and GRP related CCDB requests.
Global index for barrel track: provides provenance (detectors combination), index in respective array...
Definition of the GeometryTGeo class.
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()
InputRecord & inputs()
The inputs associated with this processing context.
static GeometryTGeo * Instance()
void fillMatrixCache(int mask) override
static constexpr int getLayer(int chipSW)
static bool isPhysicalPrimary(o2::MCTrack const &p, std::vector< o2::MCTrack > const &pcontainer)
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
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
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(std::shared_ptr< DataRequest > dr, std::shared_ptr< o2::base::GRPGeomRequest > gr, GTrackID::mask_t src, bool checkSV)
~TrackMCStudy() final=default
GLenum const GLfloat * params
constexpr o2::header::DataOrigin gDataOriginTPC
constexpr double LHCBunchSpacingMUS
constexpr int LHCMaxBunches
constexpr double LHCBunchSpacingNS
Node par(int index)
Parameters.
Defining ITS Vertex explicitly as messageable.
std::vector< ConfigParamSpec > Options
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
o2::track::TrackParCov int int int float int nCl
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::framework::DataProcessorSpec getTrackMCStudySpec(o2::dataformats::GlobalTrackID::mask_t srcTracks, o2::dataformats::GlobalTrackID::mask_t srcClus, bool checkSV)
create a processor spec
o2::dataformats::VtxTrackRef V2TRef
o2::dataformats::VtxTrackIndex VTIndex
a couple of static helper functions to create timestamp values for CCDB queries or override obsolete ...
auto getITSTracks() const
GTrackID getITSContributorGID(GTrackID source) 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 getITSTracksClusterRefs() const
auto getPrimaryVertices() const
auto getPrimaryVertexMatchedTracks() const
const o2::tpc::ClusterNativeAccess & getTPCClusters() const
auto getITSABRefs() const
auto getTPCTracksClusterRefs() const
auto getPrimaryVertexMatchedTrackRefs() const
auto getITSClustersPatterns() const
o2::MCCompLabel getTrackMCLabel(GTrackID id) const
GTrackID getTPCContributorGID(GTrackID source) 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 getITSTracksMCLabels() const
auto getITSClusters() const
LOG(info)<< "Compressed in "<< sw.CpuTime()<< " s"