13#include <TStopwatch.h>
55#include "GPUParam.inc"
59#include <unordered_map>
77using VTIndexV = std::pair<int, o2::dataformats::VtxTrackIndex>;
87 : mDataRequest(dr), mGGCCDBRequest(gr), mTracksSrc(
src), mCheckSV(checkSV)
97 void process(const
o2::globaltracking::RecoContainer& recoData);
100 void processTPCTrackRefs();
101 void loadTPCOccMap(const
o2::globaltracking::RecoContainer& recoData);
102 void fillMCClusterInfo(const
o2::globaltracking::RecoContainer& recoData);
103 void prepareITSData(const
o2::globaltracking::RecoContainer& recoData);
104 bool processMCParticle(
int src,
int ev,
int trid);
105 bool addMCParticle(const
MCTrack& mctr, const
o2::
MCCompLabel& lb, TParticlePDG* pPDG =
nullptr);
108 bool refitV0(
int i,
o2::dataformats::
V0&
v0, const
o2::globaltracking::RecoContainer& recoData);
110 float getDCAYCut(
float pt) const;
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 bool mCheckSV =
false;
125 bool mRecProcStage =
false;
126 int mNTPCOccBinLength = 0;
127 float mNTPCOccBinLengthInv = -1.f;
129 float mITSTimeBiasMUS = 0.f;
130 float mITSROFrameLengthMUS = 0.f;
131 float mTPCTBinMUS = 0.;
133 int mNCheckDecays = 0;
137 std::vector<int> mITSROF;
138 std::vector<TBracket> mITSROFBracket;
139 std::vector<o2::MCCompLabel> mDecProdLblPool;
140 std::vector<MCVertex> mMCVtVec{};
146 int daughterFirst = -1;
147 int daughterLast = -1;
150 std::vector<std::vector<DecayRef>> mDecaysMaps;
151 std::unordered_map<o2::MCCompLabel, TrackFamily> mSelMCTracks;
152 std::unordered_map<o2::MCCompLabel, std::pair<int, int>> mSelTRefIdx;
153 std::vector<o2::track::TrackPar> mSelTRefs;
155 static constexpr float MaxSnp = 0.9;
163 mDBGOut = std::make_unique<o2::utils::TreeStreamRedirector>(
"trackMCStudy.root",
"recreate");
164 mVerbose = ic.
options().
get<
int>(
"device-verbosity");
167 for (
int id = 0;
id <
sizeof(
params.decayPDG) /
sizeof(
int);
id++) {
168 if (
params.decayPDG[
id] < 0) {
173 mDecaysMaps.resize(mNCheckDecays);
174 mTPCCorrMapsLoader.
init(ic);
180 for (
int i = 0;
i < mNCheckDecays;
i++) {
181 mDecaysMaps[
i].clear();
183 mDecProdLblPool.clear();
185 mCurrMCTracks =
nullptr;
188 updateTimeDependentParams(pc);
189 mRecProcStage =
false;
198 bool updateMaps =
false;
204 LOGP(info,
"Updating TPC fast transform map with new VDrift factor of {} wrt reference {} and DriftTimeOffset correction {} wrt {} from source {}",
214 static bool initOnceDone =
false;
219 LOGP(info,
"VertexTrackMatcher ITSROFrameLengthMUS:{}", mITSROFrameLengthMUS);
222 mTPCTBinMUS = elParam.ZbinWidth;
227 mFitterV0.setUseAbsDCA(svparam.useAbsDCA);
228 mFitterV0.setPropagateToPCA(
false);
229 mFitterV0.setMaxR(svparam.maxRIni);
230 mFitterV0.setMinParamChange(svparam.minParamChange);
231 mFitterV0.setMinRelChi2Change(svparam.minRelChi2Change);
232 mFitterV0.setMaxDZIni(svparam.maxDZIni);
233 mFitterV0.setMaxDXYIni(svparam.maxDXYIni);
234 mFitterV0.setMaxChi2(svparam.maxChi2);
236 mFitterV0.setUsePropagator(svparam.usePropagator);
237 mFitterV0.setRefitWithMatCorr(svparam.refitWithMatCorr);
238 mFitterV0.setMaxStep(svparam.maxStep);
239 mFitterV0.setMaxSnp(svparam.maxSnp);
240 mFitterV0.setMinXSeed(svparam.minXSeed);
247 constexpr float SQRT12Inv = 0.288675f;
254 int nv = vtxRefs.size();
258 prepareITSData(recoData);
259 loadTPCOccMap(recoData);
260 auto getITSPatt = [&](
GTrackID gid, uint8_t& ncl) {
264 ncl = itsTrf.getNClusters();
265 for (
int il = 0; il < 7; il++) {
266 if (itsTrf.hasHitOnLayer(il)) {
273 for (
int il = 0; il < 7; il++) {
274 if (itsTr.hasHitOnLayer(il)) {
285 uint8_t clSect = 0, clRow = 0, lowestR = -1;
290 for (
int ic = 0; ic < trc.getNClusterReferences(); ic++) {
291 trc.getClusterReference(clRefs, ic, clSect, clRow, clIdx);
292 if (clRow < lowestR) {
296 unsigned int absoluteIndex = tpcClusAcc.clusterOffset[clSect][clRow] + clIdx;
301 tref.lowestPadRow = lowestR;
302 const auto& clus = tpcClusAcc.clusters[clSect][clRow][clIdx];
303 int padFromEdge =
int(clus.getPad()), npads = o2::gpu::GPUTPCGeometry::NPads(clRow);
304 if (padFromEdge > npads / 2) {
305 padFromEdge = npads - 1 - padFromEdge;
307 tref.padFromEdge = uint8_t(padFromEdge);
308 trc.getClusterReference(clRefs, 0, clSect, clRow, clIdx);
309 tref.rowMaxTPC = clRow;
316 const auto* TPCClMClab = recoData.
inputsTPCclusters->clusterIndex.clustersMCTruth;
318 for (
int ic = 0; ic < trc.getNClusterReferences(); ic++) {
319 uint8_t clSect = 0, clRow = 0;
321 trc.getClusterReference(clRefs, ic, clSect, clRow, clIdx);
322 auto labels = TPCClMClab->getLabels(clIdx + TPCClusterIdxStruct.clusterOffset[clSect][clRow]);
323 for (
auto& lbl : labels) {
338 unsigned int rofCount = 0;
340 for (
const auto& mcIR : mcEvRecords) {
341 long tbc = mcIR.differenceInBC(recoData.
startIR);
342 auto& mcVtx = mMCVtVec.emplace_back();
344 mcVtx.ID = mIntBC.size();
345 mIntBC.push_back(tbc);
346 int occBin = tbc / 8 * mNTPCOccBinLengthInv;
347 mTPCOcc.push_back(occBin < 0 ? mTBinClOcc[0] : (occBin >= mTBinClOcc.size() ? mTBinClOcc.back() : mTBinClOcc[occBin]));
349 long gbc = mcIR.toLong();
350 while (rofCount < ITSClusROFRec.size()) {
351 long rofbcMin = ITSClusROFRec[rofCount].getBCData().toLong() + ITSTimeBias, rofbcMax = rofbcMin + ITSROFLen;
352 if (gbc < rofbcMin) {
353 mITSOcc.push_back(0);
354 }
else if (gbc < rofbcMax) {
355 mITSOcc.push_back(ITSClusROFRec[rofCount].getNEntries());
362 if (mNTPCOccBinLengthInv > 0.f) {
363 mcVtx.occTPCV.resize(
params.nOccBinsDrift);
364 int grp = TMath::Max(1, TMath::Nint(
params.nTBPerOccBin * mNTPCOccBinLengthInv));
365 for (
int ib = 0; ib <
params.nOccBinsDrift; ib++) {
367 int tbs = occBin + TMath::Nint(ib *
params.nTBPerOccBin * mNTPCOccBinLengthInv);
368 for (
int ig = 0; ig < grp; ig++) {
369 if (tbs >= 0 && tbs <
int(mTBinClOccHist.size())) {
370 smb += mTBinClOccHist[tbs];
374 mcVtx.occTPCV[ib] = smb;
377 if (rofCount >= ITSClusROFRec.size()) {
378 mITSOcc.push_back(0);
383 int curSrcMC = 0, curEvMC = 0;
384 for (curSrcMC = 0; curSrcMC < (
int)mcReader.
getNSources(); curSrcMC++) {
386 LOGP(info,
"Source {}", curSrcMC);
389 bool okAccVtx =
true;
390 if (nev != (
int)mMCVtVec.size()) {
391 LOGP(
debug,
"source {} has {} events while {} MC vertices were booked", curSrcMC, nev, mMCVtVec.size());
393 if (nev > (
int)mMCVtVec.size()) {
397 for (curEvMC = 0; curEvMC < nev; curEvMC++) {
399 LOGP(info,
"Event {}", curEvMC);
401 mCurrMCTracks = &mcReader.
getTracks(curSrcMC, curEvMC);
404 auto&
pos = mMCVtVec[curEvMC].pos;
406 pos[0] = mCurrMCVertex.X();
407 pos[1] = mCurrMCVertex.Y();
408 pos[2] = mCurrMCVertex.Z();
411 for (
int itr = 0; itr < mCurrMCTracks->size(); itr++) {
412 processMCParticle(curSrcMC, curEvMC, itr);
417 for (
int id = 0;
id < mNCheckDecays;
id++) {
418 LOGP(info,
"Decay PDG={} : {} entries",
params.decayPDG[
id], mDecaysMaps[
id].size());
423 mRecProcStage =
true;
424 for (
int iv = 0; iv < nv; iv++) {
426 LOGP(info,
"processing PV {} of {}", iv, nv);
430 if (iv < (
int)pvvecLbl.size()) {
431 pvLbl = pvvecLbl[iv];
434 mMCVtVec[pvLbl.
getEventID()].recVtx.emplace_back(
RecPV{pvvec[iv], pvLbl});
437 const auto& vtref = vtxRefs[iv];
443 int idMin = vtref.getFirstEntryOfSource(is), idMax = idMin + vtref.getEntriesOfSource(is);
444 for (
int i = idMin;
i < idMax;
i++) {
445 auto vid = trackIndex[
i];
447 if (trc.getPt() <
params.minPt || std::abs(trc.getTgl()) >
params.maxTgl) {
453 auto entry = mSelMCTracks.find(lbl);
454 if (
entry == mSelMCTracks.end()) {
455 if (lbl.getSourceID() != curSrcMC || lbl.getEventID() != curEvMC) {
456 curSrcMC = lbl.getSourceID();
457 curEvMC = lbl.getEventID();
458 mCurrMCTracks = &mcReader.
getTracks(curSrcMC, curEvMC);
461 if (!acceptMCCharged((*mCurrMCTracks)[lbl.getTrackID()], lbl)) {
464 entry = mSelMCTracks.find(lbl);
466 auto& trackFamily =
entry->second;
467 if (vid.isAmbiguous()) {
468 if (trackFamily.contains(vid)) {
472 auto& trf = trackFamily.recTracks.emplace_back();
482 if (lblITS == trackFamily.mcTrackInfo.label) {
486 if (trcITSF.getPt() <
params.minPt || std::abs(trcITSF.getTgl()) >
params.maxTgl) {
489 auto entryOfFake = mSelMCTracks.find(lblITS);
490 if (entryOfFake == mSelMCTracks.end()) {
493 auto& trackFamilyOfFake = entryOfFake->second;
494 auto& trfOfFake = trackFamilyOfFake.recTracks.emplace_back();
499 LOGP(info,
"Matched rec track {} to MC track {}", vid.asString(),
entry->first.asString());
508 LOGP(info,
"collected {} MC tracks", mSelMCTracks.size());
509 if (
params.minTPCRefsToExtractClRes > 0) {
510 processTPCTrackRefs();
514 for (
auto&
entry : mSelMCTracks) {
515 auto& trackFam =
entry.second;
516 auto& tracks = trackFam.recTracks;
518 if (tracks.empty()) {
522 LOGP(info,
"Processing MC track#{} {} -> {} reconstructed tracks", mcnt - 1,
entry.first.asString(), tracks.size());
525 std::sort(tracks.begin(), tracks.end(), [](
const RecTrack& lhs,
const RecTrack& rhs) {
526 const auto mskL = lhs.gid.getSourceDetectorsMask();
527 const auto mskR = rhs.gid.getSourceDetectorsMask();
528 bool itstpcL = mskL[DetID::ITS] && mskL[DetID::TPC], itstpcR = mskR[DetID::ITS] && mskR[DetID::TPC];
529 if (itstpcL && !itstpcR) {
532 return lhs.gid.getSource() > rhs.gid.getSource();
536 for (
auto& tref : tracks) {
537 if (tref.gid.isSourceSet()) {
543 auto msk = tref.gid.getSourceDetectorsMask();
546 tref.pattITS = getITSPatt(gidSet[
GTrackID::ITS], tref.nClITS);
547 if (trackFam.entITS < 0) {
548 trackFam.entITS = tcnt;
551 if (lblITS.isFake()) {
554 if (lblITS == trackFam.mcTrackInfo.label) {
555 trackFam.entITSFound = tcnt;
563 if (msk[
DetID::TPC] && trackFam.entITSTPC < 0) {
564 trackFam.entITSTPC = tcnt;
572 tref.nClTPC = trtpc.getNClusters();
573 if (trtpc.hasBothSidesClusters()) {
576 fillTPCClusterInfo(trtpc, tref);
577 flagTPCClusters(trtpc,
entry.first);
578 if (trackFam.entTPC < 0) {
579 trackFam.entTPC = tcnt;
580 trackFam.tpcT0 = trtpc.getTime0();
586 float ts = 0, terr = 0;
591 const auto& itsBra = mITSROFBracket[mITSROF[tref.gid.getIndex()]];
592 tref.ts =
timeEst{itsBra.mean(), itsBra.delta() * SQRT12Inv};
595 LOGP(info,
"Invalid entry {} of {} getTrackMCLabel {}", tcnt, tracks.size(), tref.gid.asString());
599 if (trackFam.entITS > -1 && trackFam.entTPC > -1) {
600 auto vidITS = tracks[trackFam.entITS].gid;
601 auto vidTPC = tracks[trackFam.entTPC].gid;
604 if (propagateToRefX(trcTPC, trcITS)) {
605 trackFam.trackITSProp = trcITS;
606 trackFam.trackTPCProp = trcTPC;
608 trackFam.trackITSProp.invalidate();
609 trackFam.trackTPCProp.invalidate();
612 trackFam.trackITSProp.invalidate();
613 trackFam.trackTPCProp.invalidate();
619 auto v0s = recoData.getV0sIdx();
622 s += fmt::format(
" par {} Ntpccl={} Nitscl={} ",
f.mcTrackInfo.pdgParent,
f.mcTrackInfo.nTPCCl,
f.mcTrackInfo.nITSCl);
623 for (
auto& t :
f.recTracks) {
624 s += t.gid.asString();
629 for (
int svID; svID < (
int)v0s.size(); svID++) {
630 const auto& v0idx = v0s[svID];
631 int nOKProngs = 0, realMCSVID = -1;
632 int8_t decTypeID = -1;
633 for (
int ipr = 0; ipr < v0idx.getNProngs(); ipr++) {
634 auto mcl = recoData.getTrackMCLabel(v0idx.getProngID(ipr));
635 auto itl = mSelMCTracks.find(mcl);
636 if (itl == mSelMCTracks.end()) {
640 auto& trackFamily = itl->second;
641 int decayParentIndex = trackFamily.mcTrackInfo.parentEntry;
642 if (decayParentIndex < 0) {
646 realMCSVID = decayParentIndex;
647 decTypeID = trackFamily.mcTrackInfo.parentDecID;
649 LOGP(
debug,
"Prong{} {} comes from {}/{}", ipr, prpr(trackFamily), decTypeID, realMCSVID);
652 if (realMCSVID != decayParentIndex || decTypeID != trackFamily.mcTrackInfo.parentDecID) {
655 LOGP(
debug,
"Prong{} {} comes from {}/{}", ipr, prpr(trackFamily), decTypeID, realMCSVID);
658 if (nOKProngs == v0idx.getNProngs()) {
659 LOGP(
debug,
"Decay {}/{} was found", decTypeID, realMCSVID);
660 mDecaysMaps[decTypeID][realMCSVID].foundSVID = svID;
666 fillMCClusterInfo(recoData);
669 for (
auto&
entry : mSelMCTracks) {
670 auto& trackFam =
entry.second;
671 (*mDBGOut) <<
"tracks" <<
"tr=" << trackFam <<
"\n";
675 std::vector<TrackFamily> decFam;
676 for (
int id = 0;
id < mNCheckDecays;
id++) {
677 std::string decTreeName = fmt::format(
"dec{}",
params.decayPDG[
id]);
678 for (
const auto& dec : mDecaysMaps[
id]) {
681 for (
int idd = dec.daughterFirst; idd <= dec.daughterLast; idd++) {
682 auto dtLbl = mDecProdLblPool[idd];
683 const auto& dtFamily = mSelMCTracks[dtLbl];
684 if (dtFamily.mcTrackInfo.pdgParent != dec.pdg) {
685 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);
689 decFam.push_back(dtFamily);
693 if (dec.foundSVID >= 0 && !refitV0(dec.foundSVID,
v0, recoData)) {
696 (*mDBGOut) << decTreeName.c_str() <<
"pdgPar=" << dec.pdg <<
"trPar=" << dec.parent <<
"prod=" << decFam <<
"found=" << dec.foundSVID <<
"sv=" <<
v0 <<
"\n";
701 for (
auto& mcVtx : mMCVtVec) {
702 std::sort(mcVtx.recVtx.begin(), mcVtx.recVtx.end(), [](
const RecPV& lhs,
const RecPV& rhs) {
703 return lhs.pv.getNContributors() > rhs.pv.getNContributors();
705 (*mDBGOut) <<
"mcVtxTree" <<
"mcVtx=" << mcVtx <<
"\n";
709void TrackMCStudy::processTPCTrackRefs()
711 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};
712 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};
713 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};
715 for (
auto&
entry : mSelMCTracks) {
716 auto lb =
entry.first;
717 auto trspan = mcReader.getTrackRefs(lb.getSourceID(), lb.getEventID(), lb.getTrackID());
718 int q =
entry.second.mcTrackInfo.track.getCharge();
722 int ref0entry = mSelTRefs.size(), nrefsSel = 0;
723 for (
const auto& trf : trspan) {
724 if (trf.getDetectorId() != 1) {
727 float pT = std::sqrt(trf.Px() * trf.Px() + trf.Py() * trf.Py());
731 float secX, secY,
phi = std::atan2(trf.Y(), trf.X());
734 float phiPt = std::atan2(trf.Py(), trf.Px());
735 o2::math_utils::bringTo02Pi(phiPt);
736 auto dphiPt = phiPt - alpsec[sector];
744 float tgL = trf.Pz() / pT;
745 std::array<float, 5> pars = {secY, trf.Z(), std::sin(dphiPt), tgL, q / pT};
746 auto& refTrack = mSelTRefs.emplace_back(secX, alpsec[sector], pars);
747 refTrack.setUserField(uint16_t(sector));
750 if (nrefsSel <
params.minTPCRefsToExtractClRes) {
751 mSelTRefs.resize(ref0entry);
754 mSelTRefIdx[lb] = std::make_pair(ref0entry, ref0entry + nrefsSel);
763 const auto* TPCClMClab = recoData.
inputsTPCclusters->clusterIndex.clustersMCTruth;
767 for (uint8_t
row = 0;
row < 152;
row++) {
768 for (uint8_t sector = 0; sector < 36; sector++) {
769 unsigned int offs = TPCClusterIdxStruct.clusterOffset[sector][
row];
770 for (
unsigned int icl0 = 0; icl0 < TPCClusterIdxStruct.nClusters[sector][
row]; icl0++) {
771 const auto labels = TPCClMClab->getLabels(icl0 + offs);
773 for (
const auto& lbl : labels) {
774 if (!lbl.isValid()) {
779 const auto& clus = TPCClusterIdxStruct.clusters[sector][
row][icl0];
780 int tbinH =
int(clus.getTime() * mNTPCOccBinLengthInv);
781 clRes.contTracks.clear();
782 bool doClusRes = (
params.minTPCRefsToExtractClRes > 0) && (
params.rejectClustersResStat <= 0. || gRandom->Rndm() <
params.rejectClustersResStat);
783 for (
auto lbl : labels) {
784 bool corrAttach = lbl.isFake();
785 lbl.setFakeFlag(
false);
786 auto entry = mSelMCTracks.find(lbl);
787 if (
entry == mSelMCTracks.end()) {
790 auto& mctr =
entry->second.mcTrackInfo;
792 if (
row > mctr.maxTPCRow) {
793 mctr.maxTPCRow =
row;
794 mctr.maxTPCRowSect = sector;
796 }
else if (
row == 0 && mctr.nUsedPadRows == 0) {
799 if (
row < mctr.minTPCRow) {
800 mctr.minTPCRow =
row;
801 mctr.minTPCRowSect = sector;
803 if (mctr.minTPCRowSect == sector &&
row > mctr.maxTPCRowInner) {
804 mctr.maxTPCRowInner =
row;
811 auto entTRefIDsIt = mSelTRefIdx.find(lbl);
812 if (entTRefIDsIt == mSelTRefIdx.end()) {
816 mTPCCorrMapsLoader.Transform(sector,
row, clus.getPad(), clus.getTime(), xc, yc, zc, mctr.bcInTF / 8.);
818 const auto& entTRefIDs = entTRefIDsIt->second;
820 int entIDBelow = -1, entIDAbove = -1;
821 float xBelow = -1e6, xAbove = 1e6;
823 for (
int entID = entTRefIDs.first; entID < entTRefIDs.second; entID++) {
824 const auto& refTr = mSelTRefs[entID];
825 if (refTr.getUserField() != sector % 18) {
828 if ((refTr.getX() < xc) && (refTr.getX() > xBelow) && (refTr.getX() > xc -
params.maxTPCRefExtrap)) {
829 xBelow = refTr.getX();
832 if ((refTr.getX() > xc) && (refTr.getX() < xAbove) && (refTr.getX() < xc +
params.maxTPCRefExtrap)) {
833 xAbove = refTr.getX();
837 if ((entIDBelow < 0 && entIDAbove < 0) || (
params.requireTopBottomRefs && (entIDBelow < 0 || entIDAbove < 0))) {
842 bool okBelow = entIDBelow >= 0 && prop->PropagateToXBxByBz((tparBelow = mSelTRefs[entIDBelow]), xc, 0.99, 2.);
843 bool okAbove = entIDAbove >= 0 && prop->PropagateToXBxByBz((tparAbove = mSelTRefs[entIDAbove]), xc, 0.99, 2.);
844 if ((!okBelow && !okAbove) || (
params.requireTopBottomRefs && (!okBelow || !okAbove))) {
849 auto& clCont = clRes.contTracks.emplace_back();
850 clCont.corrAttach = corrAttach;
852 clCont.below = {mSelTRefs[entIDBelow].getX(), tparBelow.getY(), tparBelow.getZ()};
853 clCont.snp += tparBelow.getSnp();
854 clCont.tgl += tparBelow.getTgl();
855 clCont.q2pt += tparBelow.getQ2Pt();
859 clCont.above = {mSelTRefs[entIDAbove].getX(), tparAbove.getY(), tparAbove.getZ()};
860 clCont.snp += tparAbove.getSnp();
861 clCont.tgl += tparAbove.getTgl();
862 clCont.q2pt += tparAbove.getQ2Pt();
866 if (clRes.contTracks.size() == 1) {
867 int occBin = mctr.bcInTF / 8 * mNTPCOccBinLengthInv;
868 clRes.occ = occBin < 0 ? mTBinClOcc[0] : (occBin >= mTBinClOcc.size() ? mTBinClOcc.back() : mTBinClOcc[occBin]);
870 clCont.xyz = {xc, yc, zc};
877 clRes.contTracks.pop_back();
881 if (clRes.getNCont()) {
884 clRes.qtot = clus.getQtot();
885 clRes.qmax = clus.getQmax();
886 clRes.flags = clus.getFlags();
887 clRes.sigmaTimePacked = clus.sigmaTimePacked;
888 clRes.sigmaPadPacked = clus.sigmaPadPacked;
889 clRes.ncont = ncontLb;
894 }
else if (tbinH >=
int(mTBinClOccHist.size())) {
895 tbinH = (
int)mTBinClOccHist.size() - 1;
897 clRes.occBin = mTBinClOccHist[tbinH];
899 (*mDBGOut) <<
"clres" <<
"clr=" << clRes <<
"\n";
907 for (
unsigned int icl = 0; icl <
ITSClusters.size(); icl++) {
908 const auto labels = mcITSClusters->getLabels(icl);
909 for (
const auto& lbl : labels) {
910 auto entry = mSelMCTracks.find(lbl);
911 if (
entry == mSelMCTracks.end()) {
914 auto& mctr =
entry->second.mcTrackInfo;
923 bool refReached =
false;
924 constexpr float TgHalfSector = 0.17632698f;
932 if (fabs(trcTPC.getY()) <
par.XMatchingRef * TgHalfSector) {
940 if (!trcTPC.rotate(alphaNew) != 0) {
948 float alp = trcTPC.getAlpha();
965 if (mTPCVDriftHelper.accountCCDBInputs(matcher, obj)) {
968 if (mTPCCorrMapsLoader.accountCCDBInputs(matcher, obj)) {
972 LOG(info) <<
"ITS Alpide param updated";
974 par.printKeyValues();
986 int nROFs = ITSTrackROFRec.size();
988 mITSROFBracket.clear();
989 mITSROF.reserve(ITSTracksArray.size());
990 mITSROFBracket.reserve(ITSTracksArray.size());
991 for (
int irof = 0; irof < nROFs; irof++) {
992 const auto& rofRec = ITSTrackROFRec[irof];
993 long nBC = rofRec.getBCData().differenceInBC(recoData.
startIR);
995 float tMax = tMin + mITSROFrameLengthMUS;
996 mITSROFBracket.emplace_back(tMin, tMax);
997 for (
int it = 0; it < rofRec.getNEntries(); it++) {
998 mITSROF.push_back(irof);
1010bool TrackMCStudy::processMCParticle(
int src,
int ev,
int trid)
1012 const auto& mcPart = (*mCurrMCTracks)[trid];
1013 int pdg = mcPart.GetPdgCode();
1019 if (mcPart.T() <
params.decayMotherMaxT) {
1020 for (
int id = 0;
id < mNCheckDecays;
id++) {
1021 if (
params.decayPDG[
id] == std::abs(pdg)) {
1027 auto& decayPool = mDecaysMaps[decay];
1028 int idd0 = mcPart.getFirstDaughterTrackId(), idd1 = mcPart.getLastDaughterTrackId();
1029 int dtStart = mDecProdLblPool.size(), dtEnd = -1;
1033 for (
int idd = idd0; idd <= idd1; idd++) {
1034 const auto& product = (*mCurrMCTracks)[idd];
1036 if (!acceptMCCharged(product, lbld, decay)) {
1038 mDecProdLblPool.resize(dtStart);
1041 mDecProdLblPool.push_back(lbld);
1045 dtEnd = mDecProdLblPool.size();
1046 for (
int dtid = dtStart; dtid < dtEnd; dtid++) {
1047 mSelMCTracks[mDecProdLblPool[dtid]].mcTrackInfo.parentEntry = decayPool.size();
1048 mSelMCTracks[mDecProdLblPool[dtid]].mcTrackInfo.parentDecID = int8_t(decay);
1051 std::array<float, 3> xyz{(float)mcPart.GetStartVertexCoordinatesX(), (float)mcPart.GetStartVertexCoordinatesY(), (float)mcPart.GetStartVertexCoordinatesZ()};
1052 std::array<float, 3> pxyz{(float)mcPart.GetStartVertexMomentumX(), (float)mcPart.GetStartVertexMomentumY(), (float)mcPart.GetStartVertexMomentumZ()};
1053 decayPool.emplace_back(DecayRef{lbl,
1055 mcPart.GetPdgCode(), dtStart, dtEnd});
1057 LOGP(info,
"Adding MC parent pdg={} {}, with prongs in {}:{} range", pdg, lbl.asString(), dtStart, dtEnd);
1065 if (mSelMCTracks.find(lbl) == mSelMCTracks.end()) {
1066 res = acceptMCCharged(mcPart, lbl);
1079 if (mVerbose > 1 && followDecay > -1) {
1080 LOGP(info,
"rejecting decay {} prong : pdg={}, pT={}, tgL={}, r={}", followDecay, tr.
GetPdgCode(), tr.
GetPt(), tr.
GetTgl(), std::sqrt(tr.
R2()));
1085 float r2 = dx * dx + dy * dy;
1086 float posTgl2 = r2 > 1 && std::abs(dz) < 20 ? dz * dz / r2 : 0;
1087 if (posTgl2 >
params.maxPosTglMC *
params.maxPosTglMC) {
1088 if (mVerbose > 1 && followDecay > -1) {
1089 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));
1093 if (
params.requireITSorTPCTrackRefs) {
1096 for (
const auto& trf : trspan) {
1111 if (pPDG->Charge() == 0.) {
1114 return addMCParticle(tr, lb, pPDG);
1125 auto& mcEntry = mSelMCTracks[lb];
1126 mcEntry.mcTrackInfo.pdg = mcPart.
GetPdgCode();
1127 mcEntry.mcTrackInfo.track =
o2::track::TrackPar(xyz, pxyz, TMath::Nint(pPDG->Charge() / 3),
true);
1128 mcEntry.mcTrackInfo.label = lb;
1129 mcEntry.mcTrackInfo.bcInTF = mIntBC[lb.
getEventID()];
1130 mcEntry.mcTrackInfo.occTPC = mTPCOcc[lb.
getEventID()];
1131 mcEntry.mcTrackInfo.occITS = mITSOcc[lb.
getEventID()];
1132 mcEntry.mcTrackInfo.occTPCV = mMCVtVec[lb.
getEventID()].occTPCV;
1133 if (mRecProcStage) {
1134 mcEntry.mcTrackInfo.setAddedAtRecStage();
1137 mcEntry.mcTrackInfo.setPrimary();
1142 const auto& mcPartPar = (*mCurrMCTracks)[moth];
1143 mcEntry.mcTrackInfo.pdgParent = mcPartPar.GetPdgCode();
1161 if (svparam.mTPCTrackPhotonTune && isTPConly) {
1162 mFitterV0.setMaxDZIni(svparam.mTPCTrackMaxDZIni);
1163 mFitterV0.setMaxDXYIni(svparam.mTPCTrackMaxDXYIni);
1164 mFitterV0.setMaxChi2(svparam.mTPCTrackMaxChi2);
1165 mFitterV0.setCollinear(
true);
1167 int nCand = mFitterV0.process(seedP, seedN);
1168 if (svparam.mTPCTrackPhotonTune && isTPConly) {
1170 mFitterV0.setMaxDZIni(svparam.maxDZIni);
1171 mFitterV0.setMaxDXYIni(svparam.maxDXYIni);
1172 mFitterV0.setMaxChi2(svparam.maxChi2);
1173 mFitterV0.setCollinear(
false);
1179 if (!mFitterV0.isPropagateTracksToVertexDone(cand) && !mFitterV0.propagateTracksToVertex(cand)) {
1182 const auto& trPProp = mFitterV0.getTrack(0, cand);
1183 const auto& trNProp = mFitterV0.getTrack(1, cand);
1184 std::array<float, 3> pP{}, pN{};
1185 trPProp.getPxPyPzGlo(pP);
1186 trNProp.getPxPyPzGlo(pN);
1187 std::array<float, 3> pV0 = {pP[0] + pN[0], pP[1] + pN[1], pP[2] + pN[2]};
1188 auto p2V0 = pV0[0] * pV0[0] + pV0[1] * pV0[1] + pV0[2] * pV0[2];
1190 const auto v0XYZ = mFitterV0.getPCACandidatePos(cand);
1191 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];
1192 float cosPA = prodXYZv0 / std::sqrt((dx * dx + dy * dy + dz * dz) * p2V0);
1194 v0.
setDCA(mFitterV0.getChi2AtPCACandidate(cand));
1204 auto TPCRefitter = std::make_unique<o2::gpu::GPUO2InterfaceRefit>(&recoData.
inputsTPCclusters->clusterIndex, &mTPCCorrMapsLoader, prop->getNominalBz(),
1206 mNTPCOccBinLength = TPCRefitter->getParam()->rec.tpc.occupancyMapTimeBins;
1208 if (mNTPCOccBinLength > 1 && TPCOccMap.size()) {
1209 mNTPCOccBinLengthInv = 1. / mNTPCOccBinLength;
1212 mTBinClOcc.resize(nTPCOccBins);
1213 mTBinClOccHist.resize(nTPCOccBins);
1214 float sm = 0., tb = 0.5 * mNTPCOccBinLength;
1215 for (
int i = 0;
i < nTPCOccBins;
i++) {
1216 mTBinClOccHist[
i] = TPCRefitter->getParam()->GetUnscaledMult(tb);
1217 tb += mNTPCOccBinLength;
1219 for (
int i = nTPCOccBins;
i--;) {
1220 sm += mTBinClOccHist[
i];
1221 if (
i + sumBins < nTPCOccBins) {
1222 sm -= mTBinClOccHist[
i + sumBins];
1227 mTBinClOcc.resize(1);
1228 mTBinClOccHist.resize(1);
1234 std::vector<OutputSpec> outputs;
1236 {
"device-verbosity", VariantType::Int, 0, {
"Verbosity level"}},
1237 {
"dcay-vs-pt", VariantType::String,
"0.0105 + 0.0350 / pow(x, 1.1)", {
"Formula for global tracks DCAy vs pT cut"}},
1238 {
"min-tpc-clusters", VariantType::Int, 60, {
"Cut on TPC clusters"}},
1239 {
"max-tpc-dcay", VariantType::Float, 2.f, {
"Cut on TPC dcaY"}},
1240 {
"max-tpc-dcaz", VariantType::Float, 2.f, {
"Cut on TPC dcaZ"}},
1241 {
"min-x-prop", VariantType::Float, 6.f, {
"track should be propagated to this X at least"}}};
1242 auto dataRequest = std::make_shared<DataRequest>();
1244 dataRequest->requestTracks(srcTracks, useMC);
1245 dataRequest->requestClusters(srcClusters, useMC);
1246 dataRequest->requestPrimaryVertices(useMC);
1248 dataRequest->requestSecondaryVertices(useMC);
1252 auto ggRequest = std::make_shared<o2::base::GRPGeomRequest>(
false,
1258 dataRequest->inputs,
1265 AlgorithmSpec{adaptFromTask<TrackMCStudy>(dataRequest, ggRequest, srcTracks, sclOpts, checkSV)},
Helper class to access load maps from CCDB.
Defintions for N-prongs secondary vertex fit.
Definition of the GeometryManager class.
Helper for geometry and GRP related CCDB requests.
Global index for barrel track: provides provenance (detectors combination), index in respective array...
Utility functions for MC particles.
Configurable params for TPC ITS matching.
Definition of the Names Generator class.
Definition of the parameter class for the detector electronics.
Wrapper container for different reconstructed object types.
o2::track::TrackParCov TrackParCov
Configurable params for secondary vertexer.
Result of refitting TPC-ITS matched track.
Reference on ITS/MFT clusters set.
Helper class to extract VDrift from different sources.
Referenc on track indices contributing to the vertex, with possibility chose tracks from specific sou...
void setFakeFlag(bool v=true)
std::string asString() const
Double_t GetStartVertexMomentumZ() const
Double_t GetStartVertexMomentumX() const
Double_t GetStartVertexCoordinatesY() const
Double_t GetStartVertexCoordinatesZ() const
Double_t R2() const
production radius squared
Double_t GetStartVertexMomentumY() const
Double_t GetStartVertexCoordinatesX() const
Int_t GetPdgCode() const
Accessors.
Int_t getMotherTrackId() const
static TDatabasePDG * Instance()
void checkUpdates(o2::framework::ProcessingContext &pc)
static GRPGeomHelper & instance()
void setRequest(std::shared_ptr< GRPGeomRequest > req)
GPUd() value_type estimateLTFast(o2 static GPUd() float estimateLTIncrement(const o2 PropagatorImpl * Instance(bool uninitialized=false)
static const TrackMCStudyConfig & Instance()
Static class with identifiers, bitmasks and names for ALICE detectors.
T get(const char *key) const
ConfigParamRegistry const & options()
void setLumiScaleType(int32_t v)
void setLumiScaleMode(int32_t v)
static constexpr int getLayer(int chipSW)
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
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
bool isTrackSourceLoaded(int src) const
o2::InteractionRecord startIR
GlobalIDSet getSingleDetectorRefs(GTrackID gidx) const
const o2::tpc::TrackTPC & getTPCTrack(GTrackID id) const
auto getITSClustersMCLabels() const
auto getPrimaryVertices() const
auto getPrimaryVertexMatchedTracks() const
const o2::tpc::ClusterNativeAccess & getTPCClusters() const
auto getITSABRefs() const
auto getTPCTracksClusterRefs() const
auto getPrimaryVertexMatchedTrackRefs() const
o2::MCCompLabel getTrackMCLabel(GTrackID id) const
auto getITSClustersROFRecords() const
const o2::track::TrackParCov & getTrackParam(GTrackID gidx) const
gsl::span< const unsigned char > clusterShMapTPC
externally set TPC clusters sharing map
void collectData(o2::framework::ProcessingContext &pc, const DataRequest &request)
const o2::track::TrackParCov & getTrackParamOut(GTrackID gidx) const
auto getPrimaryVertexMCLabels() const
const o2::dataformats::PrimaryVertex & getPrimaryVertex(int i) const
const o2::its::TrackITS & getITSTrack(GTrackID gid) const
std::unique_ptr< o2::tpc::internal::getWorkflowTPCInput_ret > inputsTPCclusters
auto getITSTracksROFRecords() const
void getTrackTime(GTrackID gid, float &t, float &tErr) const
gsl::span< const unsigned int > occupancyMapTPC
externally set TPC clusters occupancy map
auto getITSClusters() const
int lumiType
what estimator to used for corrections scaling: 0: no scaling, 1: CTP, 2: IDC
int lumiMode
what corrections method to use: 0: classical scaling, 1: Using of the derivative map,...
float refTimeOffset
additive time offset reference (\mus)
float refVDrift
reference vdrift for which factor was extracted
float getTimeOffset() const
float timeOffsetCorr
additive time offset correction (\mus)
float corrFact
drift velocity correction factor (multiplicative)
LOG(info)<< "Compressed in "<< sw.CpuTime()<< " s"