13#include <TStopwatch.h>
58#include "GPUParam.inc"
62#include <unordered_map>
80using VTIndexV = std::pair<int, o2::dataformats::VtxTrackIndex>;
90 : mDataRequest(dr), mGGCCDBRequest(gr), mTracksSrc(
src), mCheckSV(checkSV)
101 void process(const
o2::globaltracking::RecoContainer& recoData);
104 void processTPCTrackRefs();
105 void processITSTracks(const
o2::globaltracking::RecoContainer& recoData);
106 void loadTPCOccMap(const
o2::globaltracking::RecoContainer& recoData);
107 void fillMCClusterInfo(const
o2::globaltracking::RecoContainer& recoData);
108 void prepareITSData(const
o2::globaltracking::RecoContainer& recoData);
109 bool processMCParticle(
int src,
int ev,
int trid);
110 bool addMCParticle(const
MCTrack& mctr, const
o2::
MCCompLabel& lb, TParticlePDG* pPDG =
nullptr);
113 bool refitV0(
int i,
o2::dataformats::
V0&
v0, const
o2::globaltracking::RecoContainer& recoData);
115 float getDCAYCut(
float pt) const;
117 const
std::vector<
o2::
MCTrack>* mCurrMCTracks =
nullptr;
118 TVector3 mCurrMCVertex;
119 o2::tpc::VDriftHelper mTPCVDriftHelper{};
121 std::shared_ptr<DataRequest> mDataRequest;
122 std::shared_ptr<o2::base::GRPGeomRequest> mGGCCDBRequest;
123 std::unique_ptr<o2::utils::TreeStreamRedirector> mDBGOut;
124 std::vector<float> mTBinClOcc;
125 std::vector<float> mTBinClOccHist;
126 std::vector<long> mIntBC;
127 std::vector<float> mTPCOcc;
128 std::vector<int> mITSOcc;
129 std::vector<o2::BaseCluster<float>> mITSClustersArray;
132 bool mCheckSV =
false;
133 bool mRecProcStage =
false;
134 int mNTPCOccBinLength = 0;
135 float mNTPCOccBinLengthInv = -1.f;
137 float mITSTimeBiasMUS = 0.f;
138 float mITSROFrameLengthMUS = 0.f;
139 float mTPCTBinMUS = 0.;
141 int mNCheckDecays = 0;
145 std::vector<int> mITSROF;
146 std::vector<TBracket> mITSROFBracket;
147 std::vector<o2::MCCompLabel> mDecProdLblPool;
148 std::vector<MCVertex> mMCVtVec{};
154 int daughterFirst = -1;
155 int daughterLast = -1;
158 std::vector<std::vector<DecayRef>> mDecaysMaps;
159 std::unordered_map<o2::MCCompLabel, TrackFamily> mSelMCTracks;
160 std::unordered_map<o2::MCCompLabel, std::pair<int, int>> mSelTRefIdx;
161 std::vector<o2::track::TrackPar> mSelTRefs;
163 static constexpr float MaxSnp = 0.9;
171 mDBGOut = std::make_unique<o2::utils::TreeStreamRedirector>(
"trackMCStudy.root",
"recreate");
172 mVerbose = ic.
options().
get<
int>(
"device-verbosity");
175 for (
int id = 0;
id <
sizeof(
params.decayPDG) /
sizeof(
int);
id++) {
176 if (
params.decayPDG[
id] < 0) {
181 mDecaysMaps.resize(mNCheckDecays);
182 mTPCCorrMapsLoader.
init(ic);
188 for (
int i = 0;
i < mNCheckDecays;
i++) {
189 mDecaysMaps[
i].clear();
191 mDecProdLblPool.clear();
193 mCurrMCTracks =
nullptr;
196 updateTimeDependentParams(pc);
197 mRecProcStage =
false;
206 bool updateMaps =
false;
212 LOGP(info,
"Updating TPC fast transform map with new VDrift factor of {} wrt reference {} and DriftTimeOffset correction {} wrt {} from source {}",
222 static bool initOnceDone =
false;
227 LOGP(info,
"VertexTrackMatcher ITSROFrameLengthMUS:{}", mITSROFrameLengthMUS);
230 mTPCTBinMUS = elParam.ZbinWidth;
235 mFitterV0.setUseAbsDCA(svparam.useAbsDCA);
236 mFitterV0.setPropagateToPCA(
false);
237 mFitterV0.setMaxR(svparam.maxRIni);
238 mFitterV0.setMinParamChange(svparam.minParamChange);
239 mFitterV0.setMinRelChi2Change(svparam.minRelChi2Change);
240 mFitterV0.setMaxDZIni(svparam.maxDZIni);
241 mFitterV0.setMaxDXYIni(svparam.maxDXYIni);
242 mFitterV0.setMaxChi2(svparam.maxChi2);
244 mFitterV0.setUsePropagator(svparam.usePropagator);
245 mFitterV0.setRefitWithMatCorr(svparam.refitWithMatCorr);
246 mFitterV0.setMaxStep(svparam.maxStep);
247 mFitterV0.setMaxSnp(svparam.maxSnp);
248 mFitterV0.setMinXSeed(svparam.minXSeed);
255 constexpr float SQRT12Inv = 0.288675f;
262 int nv = vtxRefs.size();
266 prepareITSData(recoData);
267 loadTPCOccMap(recoData);
268 auto getITSPatt = [&](
GTrackID gid, uint8_t& ncl) {
272 ncl = itsTrf.getNClusters();
273 for (
int il = 0; il < 7; il++) {
274 if (itsTrf.hasHitOnLayer(il)) {
281 for (
int il = 0; il < 7; il++) {
282 if (itsTr.hasHitOnLayer(il)) {
293 uint8_t clSect = 0, clRow = 0, lowestR = -1;
298 for (
int ic = 0; ic < trc.getNClusterReferences(); ic++) {
299 trc.getClusterReference(clRefs, ic, clSect, clRow, clIdx);
300 if (clRow < lowestR) {
304 unsigned int absoluteIndex = tpcClusAcc.clusterOffset[clSect][clRow] + clIdx;
309 tref.lowestPadRow = lowestR;
310 const auto& clus = tpcClusAcc.clusters[clSect][clRow][clIdx];
311 int padFromEdge =
int(clus.getPad()), npads = o2::gpu::GPUTPCGeometry::NPads(clRow);
312 if (padFromEdge > npads / 2) {
313 padFromEdge = npads - 1 - padFromEdge;
315 tref.padFromEdge = uint8_t(padFromEdge);
316 trc.getClusterReference(clRefs, 0, clSect, clRow, clIdx);
317 tref.rowMaxTPC = clRow;
324 const auto* TPCClMClab = recoData.
inputsTPCclusters->clusterIndex.clustersMCTruth;
326 for (
int ic = 0; ic < trc.getNClusterReferences(); ic++) {
327 uint8_t clSect = 0, clRow = 0;
329 trc.getClusterReference(clRefs, ic, clSect, clRow, clIdx);
330 auto labels = TPCClMClab->getLabels(clIdx + TPCClusterIdxStruct.clusterOffset[clSect][clRow]);
331 for (
auto& lbl :
labels) {
346 unsigned int rofCount = 0;
348 for (
const auto& mcIR : mcEvRecords) {
349 long tbc = mcIR.differenceInBC(recoData.
startIR);
350 auto& mcVtx = mMCVtVec.emplace_back();
352 mcVtx.ID = mIntBC.size();
353 mIntBC.push_back(tbc);
354 int occBin = tbc / 8 * mNTPCOccBinLengthInv;
355 mTPCOcc.push_back(occBin < 0 ? mTBinClOcc[0] : (occBin >= mTBinClOcc.size() ? mTBinClOcc.back() : mTBinClOcc[occBin]));
357 long gbc = mcIR.toLong();
358 while (rofCount < ITSClusROFRec.size()) {
359 long rofbcMin = ITSClusROFRec[rofCount].getBCData().toLong() + ITSTimeBias, rofbcMax = rofbcMin + ITSROFLen;
360 if (gbc < rofbcMin) {
361 mITSOcc.push_back(0);
362 }
else if (gbc < rofbcMax) {
363 mITSOcc.push_back(ITSClusROFRec[rofCount].getNEntries());
370 if (mNTPCOccBinLengthInv > 0.f) {
371 mcVtx.occTPCV.resize(
params.nOccBinsDrift);
372 int grp = TMath::Max(1, TMath::Nint(
params.nTBPerOccBin * mNTPCOccBinLengthInv));
373 for (
int ib = 0; ib <
params.nOccBinsDrift; ib++) {
375 int tbs = occBin + TMath::Nint(ib *
params.nTBPerOccBin * mNTPCOccBinLengthInv);
376 for (
int ig = 0; ig < grp; ig++) {
377 if (tbs >= 0 && tbs <
int(mTBinClOccHist.size())) {
378 smb += mTBinClOccHist[tbs];
382 mcVtx.occTPCV[ib] = smb;
385 if (rofCount >= ITSClusROFRec.size()) {
386 mITSOcc.push_back(0);
391 int curSrcMC = 0, curEvMC = 0;
392 for (curSrcMC = 0; curSrcMC < (
int)mcReader.
getNSources(); curSrcMC++) {
394 LOGP(info,
"Source {}", curSrcMC);
397 bool okAccVtx =
true;
398 if (nev != (
int)mMCVtVec.size()) {
399 LOGP(
debug,
"source {} has {} events while {} MC vertices were booked", curSrcMC, nev, mMCVtVec.size());
401 if (nev > (
int)mMCVtVec.size()) {
405 for (curEvMC = 0; curEvMC < nev; curEvMC++) {
407 LOGP(info,
"Event {}", curEvMC);
409 mCurrMCTracks = &mcReader.
getTracks(curSrcMC, curEvMC);
412 auto&
pos = mMCVtVec[curEvMC].pos;
414 pos[0] = mCurrMCVertex.X();
415 pos[1] = mCurrMCVertex.Y();
416 pos[2] = mCurrMCVertex.Z();
419 for (
int itr = 0; itr < mCurrMCTracks->size(); itr++) {
420 processMCParticle(curSrcMC, curEvMC, itr);
425 for (
int id = 0;
id < mNCheckDecays;
id++) {
426 LOGP(info,
"Decay PDG={} : {} entries",
params.decayPDG[
id], mDecaysMaps[
id].size());
431 mRecProcStage =
true;
432 for (
int iv = 0; iv < nv; iv++) {
434 LOGP(info,
"processing PV {} of {}", iv, nv);
438 if (iv < (
int)pvvecLbl.size()) {
439 pvLbl = pvvecLbl[iv];
442 mMCVtVec[pvLbl.
getEventID()].recVtx.emplace_back(
RecPV{pvvec[iv], pvLbl});
445 const auto& vtref = vtxRefs[iv];
451 int idMin = vtref.getFirstEntryOfSource(is), idMax = idMin + vtref.getEntriesOfSource(is);
452 for (
int i = idMin;
i < idMax;
i++) {
453 auto vid = trackIndex[
i];
455 if (trc.getPt() <
params.minPt || std::abs(trc.getTgl()) >
params.maxTgl) {
461 auto entry = mSelMCTracks.find(lbl);
462 if (
entry == mSelMCTracks.end()) {
463 if (lbl.getSourceID() != curSrcMC || lbl.getEventID() != curEvMC) {
464 curSrcMC = lbl.getSourceID();
465 curEvMC = lbl.getEventID();
466 mCurrMCTracks = &mcReader.
getTracks(curSrcMC, curEvMC);
469 if (!acceptMCCharged((*mCurrMCTracks)[lbl.getTrackID()], lbl)) {
472 entry = mSelMCTracks.find(lbl);
474 auto& trackFamily =
entry->second;
475 if (vid.isAmbiguous()) {
476 if (trackFamily.contains(vid)) {
480 auto& trf = trackFamily.recTracks.emplace_back();
490 if (lblITS == trackFamily.mcTrackInfo.label) {
494 if (trcITSF.getPt() <
params.minPt || std::abs(trcITSF.getTgl()) >
params.maxTgl) {
497 auto entryOfFake = mSelMCTracks.find(lblITS);
498 if (entryOfFake == mSelMCTracks.end()) {
501 auto& trackFamilyOfFake = entryOfFake->second;
502 auto& trfOfFake = trackFamilyOfFake.recTracks.emplace_back();
507 LOGP(info,
"Matched rec track {} to MC track {}", vid.asString(),
entry->first.asString());
516 LOGP(info,
"collected {} MC tracks", mSelMCTracks.size());
517 if (
params.minTPCRefsToExtractClRes > 0 ||
params.storeTPCTrackRefs) {
518 processTPCTrackRefs();
522 for (
auto&
entry : mSelMCTracks) {
523 auto& trackFam =
entry.second;
524 auto& tracks = trackFam.recTracks;
526 if (tracks.empty()) {
530 LOGP(info,
"Processing MC track#{} {} -> {} reconstructed tracks", mcnt - 1,
entry.first.asString(), tracks.size());
533 std::sort(tracks.begin(), tracks.end(), [](
const RecTrack& lhs,
const RecTrack& rhs) {
534 const auto mskL = lhs.gid.getSourceDetectorsMask();
535 const auto mskR = rhs.gid.getSourceDetectorsMask();
536 bool itstpcL = mskL[DetID::ITS] && mskL[DetID::TPC], itstpcR = mskR[DetID::ITS] && mskR[DetID::TPC];
537 if (itstpcL && !itstpcR) {
540 return lhs.gid.getSource() > rhs.gid.getSource();
542 if (
params.storeTPCTrackRefs) {
543 auto rft = mSelTRefIdx.find(
entry.first);
544 if (rft != mSelTRefIdx.end()) {
545 auto rfent = rft->second;
546 for (
int irf = rfent.first; irf < rfent.second; irf++) {
547 trackFam.mcTrackInfo.trackRefsTPC.push_back(mSelTRefs[irf]);
553 for (
auto& tref : tracks) {
554 if (tref.gid.isSourceSet()) {
560 auto msk = tref.gid.getSourceDetectorsMask();
563 tref.pattITS = getITSPatt(gidSet[
GTrackID::ITS], tref.nClITS);
564 if (trackFam.entITS < 0) {
565 trackFam.entITS = tcnt;
568 if (lblITS.isFake()) {
571 if (lblITS == trackFam.mcTrackInfo.label) {
572 trackFam.entITSFound = tcnt;
581 if (trackFam.entITSTPC < 0) {
582 trackFam.entITSTPC = tcnt;
608 tref.nClTPC = trtpc.getNClusters();
609 if (trtpc.hasBothSidesClusters()) {
612 fillTPCClusterInfo(trtpc, tref);
613 flagTPCClusters(trtpc,
entry.first);
614 if (trackFam.entTPC < 0) {
615 trackFam.entTPC = tcnt;
616 trackFam.tpcT0 = trtpc.getTime0();
640 float ts = 0, terr = 0;
645 const auto& itsBra = mITSROFBracket[mITSROF[tref.gid.getIndex()]];
646 tref.ts =
timeEst{itsBra.mean(), itsBra.delta() * SQRT12Inv};
649 LOGP(info,
"Invalid entry {} of {} getTrackMCLabel {}", tcnt, tracks.size(), tref.gid.asString());
653 if (trackFam.entITS > -1 && trackFam.entTPC > -1) {
658 if (propagateToRefX(trcTPC, trcITS)) {
659 trackFam.trackITSProp = trcITS;
660 trackFam.trackTPCProp = trcTPC;
662 trackFam.trackITSProp.invalidate();
663 trackFam.trackTPCProp.invalidate();
666 trackFam.trackITSProp.invalidate();
667 trackFam.trackTPCProp.invalidate();
673 auto v0s = recoData.getV0sIdx();
676 s += fmt::format(
" par {} Ntpccl={} Nitscl={} ",
f.mcTrackInfo.pdgParent,
f.mcTrackInfo.nTPCCl,
f.mcTrackInfo.nITSCl);
677 for (
auto& t :
f.recTracks) {
678 s += t.gid.asString();
683 for (
int svID; svID < (
int)v0s.size(); svID++) {
684 const auto& v0idx = v0s[svID];
685 int nOKProngs = 0, realMCSVID = -1;
686 int8_t decTypeID = -1;
687 for (
int ipr = 0; ipr < v0idx.getNProngs(); ipr++) {
688 auto mcl = recoData.getTrackMCLabel(v0idx.getProngID(ipr));
689 auto itl = mSelMCTracks.find(mcl);
690 if (itl == mSelMCTracks.end()) {
694 auto& trackFamily = itl->second;
695 int decayParentIndex = trackFamily.mcTrackInfo.parentEntry;
696 if (decayParentIndex < 0) {
700 realMCSVID = decayParentIndex;
701 decTypeID = trackFamily.mcTrackInfo.parentDecID;
703 LOGP(
debug,
"Prong{} {} comes from {}/{}", ipr, prpr(trackFamily), decTypeID, realMCSVID);
706 if (realMCSVID != decayParentIndex || decTypeID != trackFamily.mcTrackInfo.parentDecID) {
709 LOGP(
debug,
"Prong{} {} comes from {}/{}", ipr, prpr(trackFamily), decTypeID, realMCSVID);
712 if (nOKProngs == v0idx.getNProngs()) {
713 LOGP(
debug,
"Decay {}/{} was found", decTypeID, realMCSVID);
714 mDecaysMaps[decTypeID][realMCSVID].foundSVID = svID;
720 fillMCClusterInfo(recoData);
723 for (
auto&
entry : mSelMCTracks) {
724 auto& trackFam =
entry.second;
725 (*mDBGOut) <<
"tracks" <<
"tr=" << trackFam <<
"\n";
729 std::vector<TrackFamily> decFam;
730 for (
int id = 0;
id < mNCheckDecays;
id++) {
731 std::string decTreeName = fmt::format(
"dec{}",
params.decayPDG[
id]);
732 for (
const auto& dec : mDecaysMaps[
id]) {
735 for (
int idd = dec.daughterFirst; idd <= dec.daughterLast; idd++) {
736 auto dtLbl = mDecProdLblPool[idd];
737 const auto& dtFamily = mSelMCTracks[dtLbl];
738 if (dtFamily.mcTrackInfo.pdgParent != dec.pdg) {
739 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);
743 decFam.push_back(dtFamily);
747 if (dec.foundSVID >= 0 && !refitV0(dec.foundSVID,
v0, recoData)) {
750 (*mDBGOut) << decTreeName.c_str() <<
"pdgPar=" << dec.pdg <<
"trPar=" << dec.parent <<
"prod=" << decFam <<
"found=" << dec.foundSVID <<
"sv=" <<
v0 <<
"\n";
755 for (
auto& mcVtx : mMCVtVec) {
756 std::sort(mcVtx.recVtx.begin(), mcVtx.recVtx.end(), [](
const RecPV& lhs,
const RecPV& rhs) {
757 return lhs.pv.getNContributors() > rhs.pv.getNContributors();
759 (*mDBGOut) <<
"mcVtxTree" <<
"mcVtx=" << mcVtx <<
"\n";
762 if (
params.storeITSInfo) {
763 processITSTracks(recoData);
767void TrackMCStudy::processTPCTrackRefs()
769 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};
770 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};
771 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};
773 for (
auto&
entry : mSelMCTracks) {
774 auto lb =
entry.first;
775 auto trspan = mcReader.getTrackRefs(lb.getSourceID(), lb.getEventID(), lb.getTrackID());
776 int q =
entry.second.mcTrackInfo.track.getCharge();
780 int ref0entry = mSelTRefs.size(), nrefsSel = 0;
781 for (
const auto& trf : trspan) {
782 if (trf.getDetectorId() != 1) {
785 float pT = std::sqrt(trf.Px() * trf.Px() + trf.Py() * trf.Py());
789 float secX, secY,
phi = std::atan2(trf.Y(), trf.X());
792 float phiPt = std::atan2(trf.Py(), trf.Px());
793 o2::math_utils::bringTo02Pi(phiPt);
794 auto dphiPt = phiPt - alpsec[sector];
802 float tgL = trf.Pz() / pT;
803 std::array<float, 5> pars = {secY, trf.Z(), std::sin(dphiPt), tgL, q / pT};
804 auto& refTrack = mSelTRefs.emplace_back(secX, alpsec[sector], pars);
805 refTrack.setUserField(uint16_t(sector));
808 if (nrefsSel <
params.minTPCRefsToExtractClRes) {
809 mSelTRefs.resize(ref0entry);
812 mSelTRefIdx[lb] = std::make_pair(ref0entry, ref0entry + nrefsSel);
821 const auto* TPCClMClab = recoData.
inputsTPCclusters->clusterIndex.clustersMCTruth;
825 for (uint8_t
row = 0;
row < 152;
row++) {
826 for (uint8_t sector = 0; sector < 36; sector++) {
827 unsigned int offs = TPCClusterIdxStruct.clusterOffset[sector][
row];
828 for (
unsigned int icl0 = 0; icl0 < TPCClusterIdxStruct.nClusters[sector][
row]; icl0++) {
829 const auto labels = TPCClMClab->getLabels(icl0 + offs);
831 for (
const auto& lbl :
labels) {
832 if (!lbl.isValid()) {
837 const auto& clus = TPCClusterIdxStruct.clusters[sector][
row][icl0];
838 int tbinH =
int(clus.getTime() * mNTPCOccBinLengthInv);
839 clRes.contTracks.clear();
840 bool doClusRes = (
params.minTPCRefsToExtractClRes > 0) && (
params.rejectClustersResStat <= 0. || gRandom->Rndm() <
params.rejectClustersResStat);
842 bool corrAttach = lbl.isFake();
843 lbl.setFakeFlag(
false);
844 auto entry = mSelMCTracks.find(lbl);
845 if (
entry == mSelMCTracks.end()) {
848 auto& mctr =
entry->second.mcTrackInfo;
850 if (
row > mctr.maxTPCRow) {
851 mctr.maxTPCRow =
row;
852 mctr.maxTPCRowSect = sector;
854 }
else if (
row == 0 && mctr.nUsedPadRows == 0) {
857 if (
row < mctr.minTPCRow) {
858 mctr.minTPCRow =
row;
859 mctr.minTPCRowSect = sector;
861 if (mctr.minTPCRowSect == sector &&
row > mctr.maxTPCRowInner) {
862 mctr.maxTPCRowInner =
row;
869 auto entTRefIDsIt = mSelTRefIdx.find(lbl);
870 if (entTRefIDsIt == mSelTRefIdx.end()) {
874 mTPCCorrMapsLoader.Transform(sector,
row, clus.getPad(), clus.getTime(), xc, yc, zc, mctr.bcInTF / 8.);
876 const auto& entTRefIDs = entTRefIDsIt->second;
878 int entIDBelow = -1, entIDAbove = -1;
879 float xBelow = -1e6, xAbove = 1e6;
881 for (
int entID = entTRefIDs.first; entID < entTRefIDs.second; entID++) {
882 const auto& refTr = mSelTRefs[entID];
883 if (refTr.getUserField() != sector % 18) {
886 if ((refTr.getX() < xc) && (refTr.getX() > xBelow) && (refTr.getX() > xc -
params.maxTPCRefExtrap)) {
887 xBelow = refTr.getX();
890 if ((refTr.getX() > xc) && (refTr.getX() < xAbove) && (refTr.getX() < xc +
params.maxTPCRefExtrap)) {
891 xAbove = refTr.getX();
895 if ((entIDBelow < 0 && entIDAbove < 0) || (
params.requireTopBottomRefs && (entIDBelow < 0 || entIDAbove < 0))) {
900 bool okBelow = entIDBelow >= 0 && prop->PropagateToXBxByBz((tparBelow = mSelTRefs[entIDBelow]), xc, 0.99, 2.);
901 bool okAbove = entIDAbove >= 0 && prop->PropagateToXBxByBz((tparAbove = mSelTRefs[entIDAbove]), xc, 0.99, 2.);
902 if ((!okBelow && !okAbove) || (
params.requireTopBottomRefs && (!okBelow || !okAbove))) {
907 auto& clCont = clRes.contTracks.emplace_back();
908 clCont.corrAttach = corrAttach;
910 clCont.below = {mSelTRefs[entIDBelow].getX(), tparBelow.getY(), tparBelow.getZ()};
911 clCont.snp += tparBelow.getSnp();
912 clCont.tgl += tparBelow.getTgl();
913 clCont.q2pt += tparBelow.getQ2Pt();
917 clCont.above = {mSelTRefs[entIDAbove].getX(), tparAbove.getY(), tparAbove.getZ()};
918 clCont.snp += tparAbove.getSnp();
919 clCont.tgl += tparAbove.getTgl();
920 clCont.q2pt += tparAbove.getQ2Pt();
924 if (clRes.contTracks.size() == 1) {
925 int occBin = mctr.bcInTF / 8 * mNTPCOccBinLengthInv;
926 clRes.occ = occBin < 0 ? mTBinClOcc[0] : (occBin >= mTBinClOcc.size() ? mTBinClOcc.back() : mTBinClOcc[occBin]);
928 clCont.xyz = {xc, yc, zc};
935 clRes.contTracks.pop_back();
939 if (clRes.getNCont()) {
942 clRes.qtot = clus.getQtot();
943 clRes.qmax = clus.getQmax();
944 clRes.flags = clus.getFlags();
945 clRes.sigmaTimePacked = clus.sigmaTimePacked;
946 clRes.sigmaPadPacked = clus.sigmaPadPacked;
947 clRes.ncont = ncontLb;
952 }
else if (tbinH >=
int(mTBinClOccHist.size())) {
953 tbinH = (
int)mTBinClOccHist.size() - 1;
955 clRes.occBin = mTBinClOccHist[tbinH];
957 (*mDBGOut) <<
"clres" <<
"clr=" << clRes <<
"\n";
965 for (
unsigned int icl = 0; icl <
ITSClusters.size(); icl++) {
966 const auto labels = mcITSClusters->getLabels(icl);
967 for (
const auto& lbl :
labels) {
968 auto entry = mSelMCTracks.find(lbl);
969 if (
entry == mSelMCTracks.end()) {
972 auto& mctr =
entry->second.mcTrackInfo;
981 bool refReached =
false;
982 constexpr float TgHalfSector = 0.17632698f;
990 if (fabs(trcTPC.getY()) <
par.XMatchingRef * TgHalfSector) {
998 if (!trcTPC.rotate(alphaNew) != 0) {
1006 float alp = trcTPC.getAlpha();
1023 if (mTPCVDriftHelper.accountCCDBInputs(matcher, obj)) {
1026 if (mTPCCorrMapsLoader.accountCCDBInputs(matcher, obj)) {
1030 LOG(info) <<
"ITS Alpide param updated";
1032 par.printKeyValues();
1038 LOG(info) <<
"cluster dictionary updated";
1049 int nROFs = ITSTrackROFRec.size();
1051 mITSROFBracket.clear();
1052 mITSROF.reserve(ITSTracksArray.size());
1053 mITSROFBracket.reserve(ITSTracksArray.size());
1054 for (
int irof = 0; irof < nROFs; irof++) {
1055 const auto& rofRec = ITSTrackROFRec[irof];
1056 long nBC = rofRec.getBCData().differenceInBC(recoData.
startIR);
1058 float tMax = tMin + mITSROFrameLengthMUS;
1059 mITSROFBracket.emplace_back(tMin, tMax);
1060 for (
int it = 0; it < rofRec.getNEntries(); it++) {
1061 mITSROF.push_back(irof);
1073bool TrackMCStudy::processMCParticle(
int src,
int ev,
int trid)
1075 const auto& mcPart = (*mCurrMCTracks)[trid];
1076 int pdg = mcPart.GetPdgCode();
1082 if (mcPart.T() <
params.decayMotherMaxT) {
1083 for (
int id = 0;
id < mNCheckDecays;
id++) {
1084 if (
params.decayPDG[
id] == std::abs(pdg)) {
1090 auto& decayPool = mDecaysMaps[decay];
1091 int idd0 = mcPart.getFirstDaughterTrackId(), idd1 = mcPart.getLastDaughterTrackId();
1092 int dtStart = mDecProdLblPool.size(), dtEnd = -1;
1096 for (
int idd = idd0; idd <= idd1; idd++) {
1097 const auto& product = (*mCurrMCTracks)[idd];
1099 if (!acceptMCCharged(product, lbld, decay)) {
1101 mDecProdLblPool.resize(dtStart);
1104 mDecProdLblPool.push_back(lbld);
1108 dtEnd = mDecProdLblPool.size();
1109 for (
int dtid = dtStart; dtid < dtEnd; dtid++) {
1110 mSelMCTracks[mDecProdLblPool[dtid]].mcTrackInfo.parentEntry = decayPool.size();
1111 mSelMCTracks[mDecProdLblPool[dtid]].mcTrackInfo.parentDecID = int8_t(decay);
1114 std::array<float, 3> xyz{(float)mcPart.GetStartVertexCoordinatesX(), (float)mcPart.GetStartVertexCoordinatesY(), (float)mcPart.GetStartVertexCoordinatesZ()};
1115 std::array<float, 3> pxyz{(float)mcPart.GetStartVertexMomentumX(), (float)mcPart.GetStartVertexMomentumY(), (float)mcPart.GetStartVertexMomentumZ()};
1116 decayPool.emplace_back(DecayRef{lbl,
1118 mcPart.GetPdgCode(), dtStart, dtEnd});
1120 LOGP(info,
"Adding MC parent pdg={} {}, with prongs in {}:{} range", pdg, lbl.asString(), dtStart, dtEnd);
1128 if (mSelMCTracks.find(lbl) == mSelMCTracks.end()) {
1129 res = acceptMCCharged(mcPart, lbl);
1142 if (mVerbose > 1 && followDecay > -1) {
1143 LOGP(info,
"rejecting decay {} prong : pdg={}, pT={}, tgL={}, r={}", followDecay, tr.
GetPdgCode(), tr.
GetPt(), tr.
GetTgl(), std::sqrt(tr.
R2()));
1148 float r2 = dx * dx + dy * dy;
1149 float posTgl2 = r2 > 1 && std::abs(dz) < 20 ? dz * dz / r2 : 0;
1150 if (posTgl2 >
params.maxPosTglMC *
params.maxPosTglMC) {
1151 if (mVerbose > 1 && followDecay > -1) {
1152 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));
1156 if (
params.requireITSorTPCTrackRefs) {
1159 for (
const auto& trf : trspan) {
1174 if (pPDG->Charge() == 0.) {
1177 return addMCParticle(tr, lb, pPDG);
1188 auto& mcEntry = mSelMCTracks[lb];
1189 mcEntry.mcTrackInfo.pdg = mcPart.
GetPdgCode();
1190 mcEntry.mcTrackInfo.track =
o2::track::TrackPar(xyz, pxyz, TMath::Nint(pPDG->Charge() / 3),
true);
1191 mcEntry.mcTrackInfo.label = lb;
1192 mcEntry.mcTrackInfo.bcInTF = mIntBC[lb.
getEventID()];
1193 mcEntry.mcTrackInfo.occTPC = mTPCOcc[lb.
getEventID()];
1194 mcEntry.mcTrackInfo.occITS = mITSOcc[lb.
getEventID()];
1195 mcEntry.mcTrackInfo.occTPCV = mMCVtVec[lb.
getEventID()].occTPCV;
1196 if (mRecProcStage) {
1197 mcEntry.mcTrackInfo.setAddedAtRecStage();
1200 mcEntry.mcTrackInfo.setPrimary();
1205 const auto& mcPartPar = (*mCurrMCTracks)[moth];
1206 mcEntry.mcTrackInfo.pdgParent = mcPartPar.GetPdgCode();
1224 if (svparam.mTPCTrackPhotonTune && isTPConly) {
1225 mFitterV0.setMaxDZIni(svparam.mTPCTrackMaxDZIni);
1226 mFitterV0.setMaxDXYIni(svparam.mTPCTrackMaxDXYIni);
1227 mFitterV0.setMaxChi2(svparam.mTPCTrackMaxChi2);
1228 mFitterV0.setCollinear(
true);
1230 int nCand = mFitterV0.process(seedP, seedN);
1231 if (svparam.mTPCTrackPhotonTune && isTPConly) {
1233 mFitterV0.setMaxDZIni(svparam.maxDZIni);
1234 mFitterV0.setMaxDXYIni(svparam.maxDXYIni);
1235 mFitterV0.setMaxChi2(svparam.maxChi2);
1236 mFitterV0.setCollinear(
false);
1242 if (!mFitterV0.isPropagateTracksToVertexDone(cand) && !mFitterV0.propagateTracksToVertex(cand)) {
1245 const auto& trPProp = mFitterV0.getTrack(0, cand);
1246 const auto& trNProp = mFitterV0.getTrack(1, cand);
1247 std::array<float, 3> pP{}, pN{};
1248 trPProp.getPxPyPzGlo(pP);
1249 trNProp.getPxPyPzGlo(pN);
1250 std::array<float, 3> pV0 = {pP[0] + pN[0], pP[1] + pN[1], pP[2] + pN[2]};
1251 auto p2V0 = pV0[0] * pV0[0] + pV0[1] * pV0[1] + pV0[2] * pV0[2];
1253 const auto v0XYZ = mFitterV0.getPCACandidatePos(cand);
1254 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];
1255 float cosPA = prodXYZv0 / std::sqrt((dx * dx + dy * dy + dz * dz) * p2V0);
1257 v0.
setDCA(mFitterV0.getChi2AtPCACandidate(cand));
1267 auto TPCRefitter = std::make_unique<o2::gpu::GPUO2InterfaceRefit>(&recoData.
inputsTPCclusters->clusterIndex, &mTPCCorrMapsLoader, prop->getNominalBz(),
1269 mNTPCOccBinLength = TPCRefitter->getParam()->rec.tpc.occupancyMapTimeBins;
1271 if (mNTPCOccBinLength > 1 && TPCOccMap.size()) {
1272 mNTPCOccBinLengthInv = 1. / mNTPCOccBinLength;
1275 mTBinClOcc.resize(nTPCOccBins);
1276 mTBinClOccHist.resize(nTPCOccBins);
1277 float sm = 0., tb = 0.5 * mNTPCOccBinLength;
1278 for (
int i = 0;
i < nTPCOccBins;
i++) {
1279 mTBinClOccHist[
i] = TPCRefitter->getParam()->GetUnscaledMult(tb);
1280 tb += mNTPCOccBinLength;
1282 for (
int i = nTPCOccBins;
i--;) {
1283 sm += mTBinClOccHist[
i];
1284 if (
i + sumBins < nTPCOccBins) {
1285 sm -= mTBinClOccHist[
i + sumBins];
1290 mTBinClOcc.resize(1);
1291 mTBinClOccHist.resize(1);
1298 LOGP(warn,
"ITS data is not loaded");
1306 auto pattIt = patterns.begin();
1307 mITSClustersArray.clear();
1308 mITSClustersArray.reserve(clusITS.size());
1312 int ntr = itsLbls.size();
1313 LOGP(info,
"We have {} ITS clusters and the number of patterns is {}, ITSdict:{} NMCLabels: {}", clusITS.size(), patterns.size(), mITSDict !=
nullptr, itsLbls.size());
1315 std::vector<int> evord(ntr);
1316 std::iota(evord.begin(), evord.end(), 0);
1317 std::sort(evord.begin(), evord.end(), [&](
int i,
int j) { return itsLbls[i] < itsLbls[j]; });
1318 std::vector<ITSHitInfo> outHitInfo;
1319 std::array<int, 7> cl2arr{};
1321 for (
int itr0 = 0; itr0 < ntr; itr0++) {
1322 auto itr = evord[itr0];
1323 const auto& itsTr = itsTracks[itr];
1324 const auto& itsLb = itsLbls[itr];
1326 int nCl = itsTr.getNClusters();
1327 if (itsLb.isFake() || nCl != 7) {
1330 auto entrySel = mSelMCTracks.find(itsLb);
1331 if (entrySel == mSelMCTracks.end()) {
1336 auto clEntry = itsTr.getFirstClusterEntry();
1337 for (
int iCl = nCl; iCl--;) {
1338 const auto& cls = mITSClustersArray[itsClRefs[clEntry + iCl]];
1339 int hpos = outHitInfo.size();
1340 auto& hinf = outHitInfo.emplace_back();
1342 hinf.clus.setCount(geom->getLayer(cls.getSensorID()));
1343 geom->getSensorXAlphaRefPlane(cls.getSensorID(), hinf.chipX, hinf.chipAlpha);
1344 cl2arr[hinf.clus.getCount()] = hpos;
1346 auto trspan = mcReader.getTrackRefs(itsLb.getSourceID(), itsLb.getEventID(), itsLb.getTrackID());
1347 int ilrc = -1, nrefAcc = 0;
1348 for (
const auto& trf : trspan) {
1349 if (trf.getDetectorId() != 0) {
1352 int lrt = trf.getUserId();
1353 int clEnt = cl2arr[lrt];
1357 auto& hinf = outHitInfo[clEnt];
1360 if (hinf.trefXT < 1 || std::abs(traX - hinf.chipX) < std::abs(hinf.trefXT - hinf.chipX)) {
1361 if (hinf.trefXT < 1) {
1369 (*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";
1375 std::vector<OutputSpec> outputs;
1377 {
"device-verbosity", VariantType::Int, 0, {
"Verbosity level"}},
1378 {
"dcay-vs-pt", VariantType::String,
"0.0105 + 0.0350 / pow(x, 1.1)", {
"Formula for global tracks DCAy vs pT cut"}},
1379 {
"min-tpc-clusters", VariantType::Int, 60, {
"Cut on TPC clusters"}},
1380 {
"max-tpc-dcay", VariantType::Float, 2.f, {
"Cut on TPC dcaY"}},
1381 {
"max-tpc-dcaz", VariantType::Float, 2.f, {
"Cut on TPC dcaZ"}},
1382 {
"min-x-prop", VariantType::Float, 6.f, {
"track should be propagated to this X at least"}}};
1383 auto dataRequest = std::make_shared<DataRequest>();
1385 dataRequest->requestTracks(srcTracks, useMC);
1386 dataRequest->requestClusters(srcClusters, useMC);
1387 dataRequest->requestPrimaryVertices(useMC);
1389 dataRequest->requestSecondaryVertices(useMC);
1393 auto ggRequest = std::make_shared<o2::base::GRPGeomRequest>(
false,
1399 dataRequest->inputs,
1406 AlgorithmSpec{adaptFromTask<TrackMCStudy>(dataRequest, ggRequest, srcTracks, sclOpts, checkSV)},
std::vector< std::string > labels
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...
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()
void setLumiScaleType(int32_t v)
void setLumiScaleMode(int32_t v)
void setCheckCTPIDCConsistency(bool v)
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
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)
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
Node par(int index)
Parameters.
Defining PrimaryVertex 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
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 ...
Defining DataPointCompositeObject explicitly as copiable.
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
int lumiType
what estimator to used for corrections scaling: 0: no scaling, 1: CTP, 2: IDC
bool checkCTPIDCconsistency
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"