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.setUseAbsDCA(svparam.useAbsDCA);
215 mFitterV0.setPropagateToPCA(
false);
216 mFitterV0.setMaxR(svparam.maxRIni);
217 mFitterV0.setMinParamChange(svparam.minParamChange);
218 mFitterV0.setMinRelChi2Change(svparam.minRelChi2Change);
219 mFitterV0.setMaxDZIni(svparam.maxDZIni);
220 mFitterV0.setMaxDXYIni(svparam.maxDXYIni);
221 mFitterV0.setMaxChi2(svparam.maxChi2);
223 mFitterV0.setUsePropagator(svparam.usePropagator);
224 mFitterV0.setRefitWithMatCorr(svparam.refitWithMatCorr);
225 mFitterV0.setMaxStep(svparam.maxStep);
226 mFitterV0.setMaxSnp(svparam.maxSnp);
227 mFitterV0.setMinXSeed(svparam.minXSeed);
234 constexpr float SQRT12Inv = 0.288675f;
241 int nv = vtxRefs.size();
245 prepareITSData(recoData);
246 loadTPCOccMap(recoData);
247 auto getITSPatt = [&](
GTrackID gid, uint8_t& ncl) {
251 ncl = itsTrf.getNClusters();
252 for (
int il = 0; il < 7; il++) {
253 if (itsTrf.hasHitOnLayer(il)) {
260 for (
int il = 0; il < 7; il++) {
261 if (itsTr.hasHitOnLayer(il)) {
272 uint8_t clSect = 0, clRow = 0, lowestR = -1;
277 for (
int ic = 0; ic < trc.getNClusterReferences(); ic++) {
278 trc.getClusterReference(clRefs, ic, clSect, clRow, clIdx);
279 if (clRow < lowestR) {
283 unsigned int absoluteIndex = tpcClusAcc.clusterOffset[clSect][clRow] + clIdx;
288 tref.lowestPadRow = lowestR;
289 const auto& clus = tpcClusAcc.clusters[clSect][clRow][clIdx];
290 int padFromEdge =
int(clus.getPad()), npads = o2::gpu::GPUTPCGeometry::NPads(clRow);
291 if (padFromEdge > npads / 2) {
292 padFromEdge = npads - 1 - padFromEdge;
294 tref.padFromEdge = uint8_t(padFromEdge);
295 trc.getClusterReference(clRefs, 0, clSect, clRow, clIdx);
296 tref.rowMaxTPC = clRow;
303 const auto* TPCClMClab = recoData.
inputsTPCclusters->clusterIndex.clustersMCTruth;
305 for (
int ic = 0; ic < trc.getNClusterReferences(); ic++) {
306 uint8_t clSect = 0, clRow = 0;
308 trc.getClusterReference(clRefs, ic, clSect, clRow, clIdx);
309 auto labels = TPCClMClab->getLabels(clIdx + TPCClusterIdxStruct.clusterOffset[clSect][clRow]);
310 for (
auto& lbl :
labels) {
325 unsigned int rofCount = 0;
327 for (
const auto& mcIR : mcEvRecords) {
328 long tbc = mcIR.differenceInBC(recoData.
startIR);
329 auto& mcVtx = mMCVtVec.emplace_back();
331 mcVtx.ID = mIntBC.size();
332 mIntBC.push_back(tbc);
333 int occBin = tbc / 8 * mNTPCOccBinLengthInv;
334 mTPCOcc.push_back(occBin < 0 ? mTBinClOcc[0] : (occBin >= mTBinClOcc.size() ? mTBinClOcc.back() : mTBinClOcc[occBin]));
336 long gbc = mcIR.toLong();
337 while (rofCount < ITSClusROFRec.size()) {
338 long rofbcMin = ITSClusROFRec[rofCount].getBCData().toLong() + ITSTimeBias, rofbcMax = rofbcMin + ITSROFLen;
339 if (gbc < rofbcMin) {
340 mITSOcc.push_back(0);
341 }
else if (gbc < rofbcMax) {
342 mITSOcc.push_back(ITSClusROFRec[rofCount].getNEntries());
349 if (mNTPCOccBinLengthInv > 0.f) {
350 mcVtx.occTPCV.resize(
params.nOccBinsDrift);
351 int grp = TMath::Max(1, TMath::Nint(
params.nTBPerOccBin * mNTPCOccBinLengthInv));
352 for (
int ib = 0; ib <
params.nOccBinsDrift; ib++) {
354 int tbs = occBin + TMath::Nint(ib *
params.nTBPerOccBin * mNTPCOccBinLengthInv);
355 for (
int ig = 0; ig < grp; ig++) {
356 if (tbs >= 0 && tbs <
int(mTBinClOccHist.size())) {
357 smb += mTBinClOccHist[tbs];
361 mcVtx.occTPCV[ib] = smb;
364 if (rofCount >= ITSClusROFRec.size()) {
365 mITSOcc.push_back(0);
370 int curSrcMC = 0, curEvMC = 0;
371 for (curSrcMC = 0; curSrcMC < (
int)mcReader.
getNSources(); curSrcMC++) {
373 LOGP(info,
"Source {}", curSrcMC);
376 bool okAccVtx =
true;
377 if (nev != (
int)mMCVtVec.size()) {
378 LOGP(
debug,
"source {} has {} events while {} MC vertices were booked", curSrcMC, nev, mMCVtVec.size());
380 if (nev > (
int)mMCVtVec.size()) {
384 for (curEvMC = 0; curEvMC < nev; curEvMC++) {
386 LOGP(info,
"Event {}", curEvMC);
388 mCurrMCTracks = &mcReader.
getTracks(curSrcMC, curEvMC);
391 auto&
pos = mMCVtVec[curEvMC].pos;
393 pos[0] = mCurrMCVertex.X();
394 pos[1] = mCurrMCVertex.Y();
395 pos[2] = mCurrMCVertex.Z();
398 for (
int itr = 0; itr < mCurrMCTracks->size(); itr++) {
399 processMCParticle(curSrcMC, curEvMC, itr);
404 for (
int id = 0;
id < mNCheckDecays;
id++) {
405 LOGP(info,
"Decay PDG={} : {} entries",
params.decayPDG[
id], mDecaysMaps[
id].size());
410 mRecProcStage =
true;
411 for (
int iv = 0; iv < nv; iv++) {
413 LOGP(info,
"processing PV {} of {}", iv, nv);
417 if (iv < (
int)pvvecLbl.size()) {
418 pvLbl = pvvecLbl[iv];
421 mMCVtVec[pvLbl.
getEventID()].recVtx.emplace_back(
RecPV{pvvec[iv], pvLbl});
424 const auto& vtref = vtxRefs[iv];
430 int idMin = vtref.getFirstEntryOfSource(is), idMax = idMin + vtref.getEntriesOfSource(is);
431 for (
int i = idMin;
i < idMax;
i++) {
432 auto vid = trackIndex[
i];
434 if (trc.getPt() <
params.minPt || std::abs(trc.getTgl()) >
params.maxTgl) {
440 auto entry = mSelMCTracks.find(lbl);
441 if (
entry == mSelMCTracks.end()) {
442 if (lbl.getSourceID() != curSrcMC || lbl.getEventID() != curEvMC) {
443 curSrcMC = lbl.getSourceID();
444 curEvMC = lbl.getEventID();
445 mCurrMCTracks = &mcReader.
getTracks(curSrcMC, curEvMC);
448 if (!acceptMCCharged((*mCurrMCTracks)[lbl.getTrackID()], lbl)) {
451 entry = mSelMCTracks.find(lbl);
453 auto& trackFamily =
entry->second;
454 if (vid.isAmbiguous()) {
455 if (trackFamily.contains(vid)) {
459 auto& trf = trackFamily.recTracks.emplace_back();
469 if (lblITS == trackFamily.mcTrackInfo.label) {
473 if (trcITSF.getPt() <
params.minPt || std::abs(trcITSF.getTgl()) >
params.maxTgl) {
476 auto entryOfFake = mSelMCTracks.find(lblITS);
477 if (entryOfFake == mSelMCTracks.end()) {
480 auto& trackFamilyOfFake = entryOfFake->second;
481 auto& trfOfFake = trackFamilyOfFake.recTracks.emplace_back();
486 LOGP(info,
"Matched rec track {} to MC track {}", vid.asString(),
entry->first.asString());
495 LOGP(info,
"collected {} MC tracks", mSelMCTracks.size());
496 if (
params.minTPCRefsToExtractClRes > 0 ||
params.storeTPCTrackRefs) {
497 processTPCTrackRefs();
501 for (
auto&
entry : mSelMCTracks) {
502 auto& trackFam =
entry.second;
503 auto& tracks = trackFam.recTracks;
505 if (tracks.empty()) {
509 LOGP(info,
"Processing MC track#{} {} -> {} reconstructed tracks", mcnt - 1,
entry.first.asString(), tracks.size());
512 std::sort(tracks.begin(), tracks.end(), [](
const RecTrack& lhs,
const RecTrack& rhs) {
513 const auto mskL = lhs.gid.getSourceDetectorsMask();
514 const auto mskR = rhs.gid.getSourceDetectorsMask();
515 bool itstpcL = mskL[DetID::ITS] && mskL[DetID::TPC], itstpcR = mskR[DetID::ITS] && mskR[DetID::TPC];
516 if (itstpcL && !itstpcR) {
519 return lhs.gid.getSource() > rhs.gid.getSource();
521 if (
params.storeTPCTrackRefs) {
522 auto rft = mSelTRefIdx.find(
entry.first);
523 if (rft != mSelTRefIdx.end()) {
524 auto rfent = rft->second;
525 for (
int irf = rfent.first; irf < rfent.second; irf++) {
526 trackFam.mcTrackInfo.trackRefsTPC.push_back(mSelTRefs[irf]);
532 for (
auto& tref : tracks) {
533 if (tref.gid.isSourceSet()) {
539 auto msk = tref.gid.getSourceDetectorsMask();
542 tref.pattITS = getITSPatt(gidSet[
GTrackID::ITS], tref.nClITS);
543 if (trackFam.entITS < 0) {
544 trackFam.entITS = tcnt;
547 if (lblITS.isFake()) {
550 if (lblITS == trackFam.mcTrackInfo.label) {
551 trackFam.entITSFound = tcnt;
560 if (trackFam.entITSTPC < 0) {
561 trackFam.entITSTPC = tcnt;
587 tref.nClTPC = trtpc.getNClusters();
588 if (trtpc.hasBothSidesClusters()) {
591 fillTPCClusterInfo(trtpc, tref);
592 flagTPCClusters(trtpc,
entry.first);
593 if (trackFam.entTPC < 0) {
594 trackFam.entTPC = tcnt;
595 trackFam.tpcT0 = trtpc.getTime0();
619 float ts = 0, terr = 0;
624 const auto& itsBra = mITSROFBracket[mITSROF[tref.gid.getIndex()]];
625 tref.ts =
timeEst{itsBra.mean(), itsBra.delta() * SQRT12Inv};
628 LOGP(info,
"Invalid entry {} of {} getTrackMCLabel {}", tcnt, tracks.size(), tref.gid.asString());
632 if (trackFam.entITS > -1 && trackFam.entTPC > -1) {
637 if (propagateToRefX(trcTPC, trcITS)) {
638 trackFam.trackITSProp = trcITS;
639 trackFam.trackTPCProp = trcTPC;
641 trackFam.trackITSProp.invalidate();
642 trackFam.trackTPCProp.invalidate();
645 trackFam.trackITSProp.invalidate();
646 trackFam.trackTPCProp.invalidate();
652 auto v0s = recoData.getV0sIdx();
655 s += fmt::format(
" par {} Ntpccl={} Nitscl={} ",
f.mcTrackInfo.pdgParent,
f.mcTrackInfo.nTPCCl,
f.mcTrackInfo.nITSCl);
656 for (
auto& t :
f.recTracks) {
657 s += t.gid.asString();
662 for (
int svID; svID < (
int)v0s.size(); svID++) {
663 const auto& v0idx = v0s[svID];
664 int nOKProngs = 0, realMCSVID = -1;
665 int8_t decTypeID = -1;
666 for (
int ipr = 0; ipr < v0idx.getNProngs(); ipr++) {
667 auto mcl = recoData.getTrackMCLabel(v0idx.getProngID(ipr));
668 auto itl = mSelMCTracks.find(mcl);
669 if (itl == mSelMCTracks.end()) {
673 auto& trackFamily = itl->second;
674 int decayParentIndex = trackFamily.mcTrackInfo.parentEntry;
675 if (decayParentIndex < 0) {
679 realMCSVID = decayParentIndex;
680 decTypeID = trackFamily.mcTrackInfo.parentDecID;
682 LOGP(
debug,
"Prong{} {} comes from {}/{}", ipr, prpr(trackFamily), decTypeID, realMCSVID);
685 if (realMCSVID != decayParentIndex || decTypeID != trackFamily.mcTrackInfo.parentDecID) {
688 LOGP(
debug,
"Prong{} {} comes from {}/{}", ipr, prpr(trackFamily), decTypeID, realMCSVID);
691 if (nOKProngs == v0idx.getNProngs()) {
692 LOGP(
debug,
"Decay {}/{} was found", decTypeID, realMCSVID);
693 mDecaysMaps[decTypeID][realMCSVID].foundSVID = svID;
699 fillMCClusterInfo(recoData);
702 for (
auto&
entry : mSelMCTracks) {
703 auto& trackFam =
entry.second;
704 (*mDBGOut) <<
"tracks" <<
"tr=" << trackFam <<
"\n";
708 std::vector<TrackFamily> decFam;
709 for (
int id = 0;
id < mNCheckDecays;
id++) {
710 std::string decTreeName = fmt::format(
"dec{}",
params.decayPDG[
id]);
711 for (
const auto& dec : mDecaysMaps[
id]) {
714 for (
int idd = dec.daughterFirst; idd <= dec.daughterLast; idd++) {
715 auto dtLbl = mDecProdLblPool[idd];
716 const auto& dtFamily = mSelMCTracks[dtLbl];
717 if (dtFamily.mcTrackInfo.pdgParent != dec.pdg) {
718 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);
722 decFam.push_back(dtFamily);
726 if (dec.foundSVID >= 0 && !refitV0(dec.foundSVID,
v0, recoData)) {
729 (*mDBGOut) << decTreeName.c_str() <<
"pdgPar=" << dec.pdg <<
"trPar=" << dec.parent <<
"prod=" << decFam <<
"found=" << dec.foundSVID <<
"sv=" <<
v0 <<
"\n";
734 for (
auto& mcVtx : mMCVtVec) {
735 std::sort(mcVtx.recVtx.begin(), mcVtx.recVtx.end(), [](
const RecPV& lhs,
const RecPV& rhs) {
736 return lhs.pv.getNContributors() > rhs.pv.getNContributors();
738 (*mDBGOut) <<
"mcVtxTree" <<
"mcVtx=" << mcVtx <<
"\n";
741 if (
params.storeITSInfo) {
742 processITSTracks(recoData);
746void TrackMCStudy::processTPCTrackRefs()
748 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};
749 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};
750 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};
752 for (
auto&
entry : mSelMCTracks) {
753 auto lb =
entry.first;
754 auto trspan = mcReader.getTrackRefs(lb.getSourceID(), lb.getEventID(), lb.getTrackID());
755 int q =
entry.second.mcTrackInfo.track.getCharge();
759 int ref0entry = mSelTRefs.size(), nrefsSel = 0;
760 for (
const auto& trf : trspan) {
761 if (trf.getDetectorId() != 1) {
764 float pT = std::sqrt(trf.Px() * trf.Px() + trf.Py() * trf.Py());
768 float secX, secY,
phi = std::atan2(trf.Y(), trf.X());
771 float phiPt = std::atan2(trf.Py(), trf.Px());
772 o2::math_utils::bringTo02Pi(phiPt);
773 auto dphiPt = phiPt - alpsec[sector];
781 float tgL = trf.Pz() / pT;
782 std::array<float, 5> pars = {secY, trf.Z(), std::sin(dphiPt), tgL, q / pT};
783 auto& refTrack = mSelTRefs.emplace_back(secX, alpsec[sector], pars);
784 refTrack.setUserField(uint16_t(sector));
787 if (nrefsSel <
params.minTPCRefsToExtractClRes) {
788 mSelTRefs.resize(ref0entry);
791 mSelTRefIdx[lb] = std::make_pair(ref0entry, ref0entry + nrefsSel);
800 const auto* TPCClMClab = recoData.
inputsTPCclusters->clusterIndex.clustersMCTruth;
804 for (uint8_t
row = 0;
row < 152;
row++) {
805 for (uint8_t sector = 0; sector < 36; sector++) {
806 unsigned int offs = TPCClusterIdxStruct.clusterOffset[sector][
row];
807 for (
unsigned int icl0 = 0; icl0 < TPCClusterIdxStruct.nClusters[sector][
row]; icl0++) {
808 const auto labels = TPCClMClab->getLabels(icl0 + offs);
810 for (
const auto& lbl :
labels) {
811 if (!lbl.isValid()) {
816 const auto& clus = TPCClusterIdxStruct.clusters[sector][
row][icl0];
817 int tbinH =
int(clus.getTime() * mNTPCOccBinLengthInv);
818 clRes.contTracks.clear();
819 bool doClusRes = (
params.minTPCRefsToExtractClRes > 0) && (
params.rejectClustersResStat <= 0. || gRandom->Rndm() <
params.rejectClustersResStat);
821 bool corrAttach = lbl.isFake();
822 lbl.setFakeFlag(
false);
823 auto entry = mSelMCTracks.find(lbl);
824 if (
entry == mSelMCTracks.end()) {
827 auto& mctr =
entry->second.mcTrackInfo;
829 if (
row > mctr.maxTPCRow) {
830 mctr.maxTPCRow =
row;
831 mctr.maxTPCRowSect = sector;
833 }
else if (
row == 0 && mctr.nUsedPadRows == 0) {
836 if (
row < mctr.minTPCRow) {
837 mctr.minTPCRow =
row;
838 mctr.minTPCRowSect = sector;
840 if (mctr.minTPCRowSect == sector &&
row > mctr.maxTPCRowInner) {
841 mctr.maxTPCRowInner =
row;
848 auto entTRefIDsIt = mSelTRefIdx.find(lbl);
849 if (entTRefIDsIt == mSelTRefIdx.end()) {
853 mTPCCorrMaps->Transform(sector,
row, clus.getPad(), clus.getTime(), xc, yc, zc, mctr.bcInTF / 8.);
855 const auto& entTRefIDs = entTRefIDsIt->second;
857 int entIDBelow = -1, entIDAbove = -1;
858 float xBelow = -1e6, xAbove = 1e6;
860 for (
int entID = entTRefIDs.first; entID < entTRefIDs.second; entID++) {
861 const auto& refTr = mSelTRefs[entID];
862 if (refTr.getUserField() != sector % 18) {
865 if ((refTr.getX() < xc) && (refTr.getX() > xBelow) && (refTr.getX() > xc -
params.maxTPCRefExtrap)) {
866 xBelow = refTr.getX();
869 if ((refTr.getX() > xc) && (refTr.getX() < xAbove) && (refTr.getX() < xc +
params.maxTPCRefExtrap)) {
870 xAbove = refTr.getX();
874 if ((entIDBelow < 0 && entIDAbove < 0) || (
params.requireTopBottomRefs && (entIDBelow < 0 || entIDAbove < 0))) {
879 bool okBelow = entIDBelow >= 0 && prop->PropagateToXBxByBz((tparBelow = mSelTRefs[entIDBelow]), xc, 0.99, 2.);
880 bool okAbove = entIDAbove >= 0 && prop->PropagateToXBxByBz((tparAbove = mSelTRefs[entIDAbove]), xc, 0.99, 2.);
881 if ((!okBelow && !okAbove) || (
params.requireTopBottomRefs && (!okBelow || !okAbove))) {
886 auto& clCont = clRes.contTracks.emplace_back();
887 clCont.corrAttach = corrAttach;
889 clCont.below = {mSelTRefs[entIDBelow].getX(), tparBelow.getY(), tparBelow.getZ()};
890 clCont.snp += tparBelow.getSnp();
891 clCont.tgl += tparBelow.getTgl();
892 clCont.q2pt += tparBelow.getQ2Pt();
896 clCont.above = {mSelTRefs[entIDAbove].getX(), tparAbove.getY(), tparAbove.getZ()};
897 clCont.snp += tparAbove.getSnp();
898 clCont.tgl += tparAbove.getTgl();
899 clCont.q2pt += tparAbove.getQ2Pt();
903 if (clRes.contTracks.size() == 1) {
904 int occBin = mctr.bcInTF / 8 * mNTPCOccBinLengthInv;
905 clRes.occ = occBin < 0 ? mTBinClOcc[0] : (occBin >= mTBinClOcc.size() ? mTBinClOcc.back() : mTBinClOcc[occBin]);
907 clCont.xyz = {xc, yc, zc};
914 clRes.contTracks.pop_back();
918 if (clRes.getNCont()) {
921 clRes.qtot = clus.getQtot();
922 clRes.qmax = clus.getQmax();
923 clRes.flags = clus.getFlags();
924 clRes.sigmaTimePacked = clus.sigmaTimePacked;
925 clRes.sigmaPadPacked = clus.sigmaPadPacked;
926 clRes.ncont = ncontLb;
931 }
else if (tbinH >=
int(mTBinClOccHist.size())) {
932 tbinH = (
int)mTBinClOccHist.size() - 1;
934 clRes.occBin = mTBinClOccHist[tbinH];
936 (*mDBGOut) <<
"clres" <<
"clr=" << clRes <<
"\n";
944 for (
unsigned int icl = 0; icl <
ITSClusters.size(); icl++) {
945 const auto labels = mcITSClusters->getLabels(icl);
946 for (
const auto& lbl :
labels) {
947 auto entry = mSelMCTracks.find(lbl);
948 if (
entry == mSelMCTracks.end()) {
951 auto& mctr =
entry->second.mcTrackInfo;
960 bool refReached =
false;
961 constexpr float TgHalfSector = 0.17632698f;
969 if (fabs(trcTPC.getY()) <
par.XMatchingRef * TgHalfSector) {
977 if (!trcTPC.rotate(alphaNew) != 0) {
985 float alp = trcTPC.getAlpha();
1002 if (mTPCVDriftHelper.accountCCDBInputs(matcher, obj)) {
1006 LOG(info) <<
"ITS Alpide param updated";
1008 par.printKeyValues();
1014 LOG(info) <<
"cluster dictionary updated";
1025 int nROFs = ITSTrackROFRec.size();
1027 mITSROFBracket.clear();
1028 mITSROF.reserve(ITSTracksArray.size());
1029 mITSROFBracket.reserve(ITSTracksArray.size());
1030 for (
int irof = 0; irof < nROFs; irof++) {
1031 const auto& rofRec = ITSTrackROFRec[irof];
1032 long nBC = rofRec.getBCData().differenceInBC(recoData.
startIR);
1034 float tMax = tMin + mITSROFrameLengthMUS;
1035 mITSROFBracket.emplace_back(tMin, tMax);
1036 for (
int it = 0; it < rofRec.getNEntries(); it++) {
1037 mITSROF.push_back(irof);
1049bool TrackMCStudy::processMCParticle(
int src,
int ev,
int trid)
1051 const auto& mcPart = (*mCurrMCTracks)[trid];
1052 int pdg = mcPart.GetPdgCode();
1058 if (mcPart.T() <
params.decayMotherMaxT) {
1059 for (
int id = 0;
id < mNCheckDecays;
id++) {
1060 if (
params.decayPDG[
id] == std::abs(pdg)) {
1066 auto& decayPool = mDecaysMaps[decay];
1067 int idd0 = mcPart.getFirstDaughterTrackId(), idd1 = mcPart.getLastDaughterTrackId();
1068 int dtStart = mDecProdLblPool.size(), dtEnd = -1;
1072 for (
int idd = idd0; idd <= idd1; idd++) {
1073 const auto& product = (*mCurrMCTracks)[idd];
1075 if (!acceptMCCharged(product, lbld, decay)) {
1077 mDecProdLblPool.resize(dtStart);
1080 mDecProdLblPool.push_back(lbld);
1084 dtEnd = mDecProdLblPool.size();
1085 for (
int dtid = dtStart; dtid < dtEnd; dtid++) {
1086 mSelMCTracks[mDecProdLblPool[dtid]].mcTrackInfo.parentEntry = decayPool.size();
1087 mSelMCTracks[mDecProdLblPool[dtid]].mcTrackInfo.parentDecID = int8_t(decay);
1090 std::array<float, 3> xyz{(float)mcPart.GetStartVertexCoordinatesX(), (float)mcPart.GetStartVertexCoordinatesY(), (float)mcPart.GetStartVertexCoordinatesZ()};
1091 std::array<float, 3> pxyz{(float)mcPart.GetStartVertexMomentumX(), (float)mcPart.GetStartVertexMomentumY(), (float)mcPart.GetStartVertexMomentumZ()};
1092 decayPool.emplace_back(DecayRef{lbl,
1094 mcPart.GetPdgCode(), dtStart, dtEnd});
1096 LOGP(info,
"Adding MC parent pdg={} {}, with prongs in {}:{} range", pdg, lbl.asString(), dtStart, dtEnd);
1104 if (mSelMCTracks.find(lbl) == mSelMCTracks.end()) {
1105 res = acceptMCCharged(mcPart, lbl);
1118 if (mVerbose > 1 && followDecay > -1) {
1119 LOGP(info,
"rejecting decay {} prong : pdg={}, pT={}, tgL={}, r={}", followDecay, tr.
GetPdgCode(), tr.
GetPt(), tr.
GetTgl(), std::sqrt(tr.
R2()));
1124 float r2 = dx * dx + dy * dy;
1125 float posTgl2 = r2 > 1 && std::abs(dz) < 20 ? dz * dz / r2 : 0;
1126 if (posTgl2 >
params.maxPosTglMC *
params.maxPosTglMC) {
1127 if (mVerbose > 1 && followDecay > -1) {
1128 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));
1132 if (
params.requireITSorTPCTrackRefs) {
1135 for (
const auto& trf : trspan) {
1150 if (pPDG->Charge() == 0.) {
1153 return addMCParticle(tr, lb, pPDG);
1164 auto& mcEntry = mSelMCTracks[lb];
1165 mcEntry.mcTrackInfo.pdg = mcPart.
GetPdgCode();
1166 mcEntry.mcTrackInfo.track =
o2::track::TrackPar(xyz, pxyz, TMath::Nint(pPDG->Charge() / 3),
true);
1167 mcEntry.mcTrackInfo.label = lb;
1168 mcEntry.mcTrackInfo.bcInTF = mIntBC[lb.
getEventID()];
1169 mcEntry.mcTrackInfo.occTPC = mTPCOcc[lb.
getEventID()];
1170 mcEntry.mcTrackInfo.occITS = mITSOcc[lb.
getEventID()];
1171 mcEntry.mcTrackInfo.occTPCV = mMCVtVec[lb.
getEventID()].occTPCV;
1172 if (mRecProcStage) {
1173 mcEntry.mcTrackInfo.setAddedAtRecStage();
1176 mcEntry.mcTrackInfo.setPrimary();
1181 const auto& mcPartPar = (*mCurrMCTracks)[moth];
1182 mcEntry.mcTrackInfo.pdgParent = mcPartPar.GetPdgCode();
1200 if (svparam.mTPCTrackPhotonTune && isTPConly) {
1201 mFitterV0.setMaxDZIni(svparam.mTPCTrackMaxDZIni);
1202 mFitterV0.setMaxDXYIni(svparam.mTPCTrackMaxDXYIni);
1203 mFitterV0.setMaxChi2(svparam.mTPCTrackMaxChi2);
1204 mFitterV0.setCollinear(
true);
1206 int nCand = mFitterV0.process(seedP, seedN);
1207 if (svparam.mTPCTrackPhotonTune && isTPConly) {
1209 mFitterV0.setMaxDZIni(svparam.maxDZIni);
1210 mFitterV0.setMaxDXYIni(svparam.maxDXYIni);
1211 mFitterV0.setMaxChi2(svparam.maxChi2);
1212 mFitterV0.setCollinear(
false);
1218 if (!mFitterV0.isPropagateTracksToVertexDone(cand) && !mFitterV0.propagateTracksToVertex(cand)) {
1221 const auto& trPProp = mFitterV0.getTrack(0, cand);
1222 const auto& trNProp = mFitterV0.getTrack(1, cand);
1223 std::array<float, 3> pP{}, pN{};
1224 trPProp.getPxPyPzGlo(pP);
1225 trNProp.getPxPyPzGlo(pN);
1226 std::array<float, 3> pV0 = {pP[0] + pN[0], pP[1] + pN[1], pP[2] + pN[2]};
1227 auto p2V0 = pV0[0] * pV0[0] + pV0[1] * pV0[1] + pV0[2] * pV0[2];
1229 const auto v0XYZ = mFitterV0.getPCACandidatePos(cand);
1230 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];
1231 float cosPA = prodXYZv0 / std::sqrt((dx * dx + dy * dy + dz * dz) * p2V0);
1233 v0.
setDCA(mFitterV0.getChi2AtPCACandidate(cand));
1243 auto TPCRefitter = std::make_unique<o2::gpu::GPUO2InterfaceRefit>(&recoData.
inputsTPCclusters->clusterIndex, mTPCCorrMaps, prop->getNominalBz(),
1245 mNTPCOccBinLength = TPCRefitter->getParam()->rec.tpc.occupancyMapTimeBins;
1247 if (mNTPCOccBinLength > 1 && TPCOccMap.size()) {
1248 mNTPCOccBinLengthInv = 1. / mNTPCOccBinLength;
1251 mTBinClOcc.resize(nTPCOccBins);
1252 mTBinClOccHist.resize(nTPCOccBins);
1253 float sm = 0., tb = 0.5 * mNTPCOccBinLength;
1254 for (
int i = 0;
i < nTPCOccBins;
i++) {
1255 mTBinClOccHist[
i] = TPCRefitter->getParam()->GetUnscaledMult(tb);
1256 tb += mNTPCOccBinLength;
1258 for (
int i = nTPCOccBins;
i--;) {
1259 sm += mTBinClOccHist[
i];
1260 if (
i + sumBins < nTPCOccBins) {
1261 sm -= mTBinClOccHist[
i + sumBins];
1266 mTBinClOcc.resize(1);
1267 mTBinClOccHist.resize(1);
1274 LOGP(warn,
"ITS data is not loaded");
1283 auto pattIt = patterns.begin();
1284 mITSClustersArray.clear();
1285 mITSClustersArray.reserve(clusITS.size());
1289 int ntr = itsLbls.size();
1290 LOGP(info,
"We have {} ITS clusters and the number of patterns is {}, ITSdict:{} NMCLabels: {}", clusITS.size(), patterns.size(), mITSDict !=
nullptr, itsLbls.size());
1292 std::vector<int> evord(ntr);
1293 std::iota(evord.begin(), evord.end(), 0);
1294 std::sort(evord.begin(), evord.end(), [&](
int i,
int j) { return itsLbls[i] < itsLbls[j]; });
1295 std::vector<ITSHitInfo> outHitInfo;
1296 std::array<int, 7> cl2arr{};
1298 for (
int itr0 = 0; itr0 < ntr; itr0++) {
1299 auto itr = evord[itr0];
1300 const auto& itsTr = itsTracks[itr];
1301 const auto& itsLb = itsLbls[itr];
1303 int nCl = itsTr.getNClusters();
1304 if (itsLb.isFake() || nCl <
params.minITSClForITSoutput) {
1307 auto entrySel = mSelMCTracks.find(itsLb);
1308 if (entrySel == mSelMCTracks.end()) {
1313 auto clEntry = itsTr.getFirstClusterEntry();
1314 for (
int iCl = nCl; iCl--;) {
1315 const auto& cls = mITSClustersArray[itsClRefs[clEntry + iCl]];
1316 int hpos = outHitInfo.size();
1317 auto& hinf = outHitInfo.emplace_back();
1319 hinf.clus.setCount(geom->getLayer(cls.getSensorID()));
1320 geom->getSensorXAlphaRefPlane(cls.getSensorID(), hinf.chipX, hinf.chipAlpha);
1321 cl2arr[hinf.clus.getCount()] = hpos;
1323 auto trspan = mcReader.getTrackRefs(itsLb.getSourceID(), itsLb.getEventID(), itsLb.getTrackID());
1324 int ilrc = -1, nrefAcc = 0;
1325 for (
const auto& trf : trspan) {
1326 if (trf.getDetectorId() != 0) {
1329 int lrt = trf.getUserId();
1330 int clEnt = cl2arr[lrt];
1334 auto& hinf = outHitInfo[clEnt];
1337 if (hinf.trefXT < 1 || std::abs(traX - hinf.chipX) < std::abs(hinf.trefXT - hinf.chipX)) {
1338 if (hinf.trefXT < 1) {
1346 (*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";
1352 std::vector<OutputSpec> outputs;
1354 {
"device-verbosity", VariantType::Int, 0, {
"Verbosity level"}},
1355 {
"dcay-vs-pt", VariantType::String,
"0.0105 + 0.0350 / pow(x, 1.1)", {
"Formula for global tracks DCAy vs pT cut"}},
1356 {
"min-tpc-clusters", VariantType::Int, 60, {
"Cut on TPC clusters"}},
1357 {
"max-tpc-dcay", VariantType::Float, 2.f, {
"Cut on TPC dcaY"}},
1358 {
"max-tpc-dcaz", VariantType::Float, 2.f, {
"Cut on TPC dcaZ"}},
1359 {
"min-x-prop", VariantType::Float, 6.f, {
"track should be propagated to this X at least"}}};
1360 auto dataRequest = std::make_shared<DataRequest>();
1362 dataRequest->requestTracks(srcTracks, useMC);
1363 dataRequest->requestClusters(srcClusters, useMC);
1364 dataRequest->requestPrimaryVertices(useMC);
1366 dataRequest->requestSecondaryVertices(useMC);
1370 auto ggRequest = std::make_shared<o2::base::GRPGeomRequest>(
false,
1376 dataRequest->inputs,
1383 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
int int int float float 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"