15#include <TStopwatch.h>
61using T2VMap = std::unordered_map<GTrackID, size_t>;
71 : mDataRequest(dr), mGGCCDBRequest(gr), mTracksSrc(
src), mUseMC(useMC), mWithPV(withPV) {}
81 void prepareITSClusters();
82 bool selectTrack(
GTrackID trkID,
bool checkMCTruth = true) const;
83 T2VMap buildT2V(
bool includeCont = false,
bool requireMCMatch = true) const;
85 void getImpactParams(const
o2::track::
TrackParCov& trk, const
o2::dataformats::VertexBase& pv,
float ip[2],
float bz);
88 void doDCARefitStudy();
92 void doMisalignmentStudy();
95 TrackCounter() =
default;
97 void operator+=(
int src)
99 if (
src >= 0 &&
src <
static_cast<int>(mSuccess.size())) {
104 void operator-=(
int src)
106 if (
src >= 0 &&
src <
static_cast<int>(mirrors.size())) {
111 void operator&=(
int src)
113 if (
src >= 0 &&
src <
static_cast<int>(mRejected.size())) {
120 LOGP(info,
"\t\t\tSuccess / Error / Rejected");
122 const auto cdm = GTrackID::getSourceDetectorsMask(cis);
123 if (cdm[DetID::ITS]) {
124 LOGP(info,
"\t{:{}}\t{} / {} / {}",
GTrackID::getSourceName(cis), 15, mSuccess[cis], mirrors[cis], mRejected[cis]);
136 std::array<size_t, GTrackID::NSources> mSuccess{};
137 std::array<size_t, GTrackID::NSources> mirrors{};
138 std::array<size_t, GTrackID::NSources> mRejected{};
140 TrackCounter mTrackCounter;
144 std::span<const int> mITSclRef;
147 std::unique_ptr<o2::utils::TreeStreamRedirector> mDBGOut;
148 std::shared_ptr<DataRequest> mDataRequest;
149 std::shared_ptr<o2::base::GRPGeomRequest> mGGCCDBRequest;
157 align::MisalignmentModel mMisalignment;
165 std::string dbgnm = maxLanes == 1 ?
"its3TrackStudy.root" : fmt::format(
"its3TrackStudy_{}.root", lane);
166 mDBGOut = std::make_unique<o2::utils::TreeStreamRedirector>(dbgnm.c_str(),
"recreate");
169 LOGP(fatal,
"initialization of MCKinematicsReader failed");
176 updateTimeDependentParams(pc);
183 if (
static bool initOnceDone{
false}; !initOnceDone) {
210 LOG(info) <<
"cluster dictionary updated";
216void TrackingStudySpec::process()
218 prepareITSClusters();
219 if (mParams->
doDCA) {
225 if (mUseMC && mParams->
doPull) {
228 if (mUseMC && mParams->
doMC) {
235 doMisalignmentStudy();
239void TrackingStudySpec::prepareITSClusters()
245 for (
int lr = 0; lr < nLr; lr++) {
246 mITScl.beginLayer(lr);
249 LOGP(info,
"Preparing {} measurments of the layer slot {}", clusITS.size(), lr);
250 mITScl.getClusters().reserve(mITScl.size() + clusITS.size());
251 auto pattIt = patterns.begin();
252 for (
const auto& cls : clusITS) {
253 const auto sens = cls.getSensorID();
254 float sigmaY2{0}, sigmaZ2{0};
257 const auto gloXYZ = geom->getMatrixL2G(sens) * locXYZ;
264 float alpha = geom->getSensorRefAlpha(sens);
268 trkXYZ.SetX(std::hypot(gloXYZ.x(), gloXYZ.y()));
269 alpha = std::atan2(gloXYZ.y(), gloXYZ.x());
271 auto& cl3d = mITScl.getClusters().emplace_back(sens, trkXYZ);
272 cl3d.setErrors(sigmaY2, sigmaZ2, 0.f);
274 math_utils::detail::bringToPMPi(cl3d.alpha);
280bool TrackingStudySpec::selectTrack(
GTrackID trkID,
bool checkMCTruth)
const
294 if (itsTrk.getChi2() > mParams->
maxChi2 || itsTrk.getNClusters() < mParams->
minITSCls) {
300 if (tpcTrk.getNClusters() < mParams->
minTPCCls) {
306 if (gTrk.getPt() < mParams->
minPt || gTrk.getPt() > mParams->
maxPt) {
309 if (std::abs(gTrk.getEta()) > mParams->
maxEta) {
312 if (mUseMC && checkMCTruth) {
314 if (!itsLbl.isValid()) {
319 if (itsLbl != tpcLbl) {
328 for (
const auto& lbl : tofLbls) {
338T2VMap TrackingStudySpec::buildT2V(
bool includeCont,
bool requireMCMatch)
const
344 auto nv = vtxRefs.size() - 1;
346 for (
size_t iv = 0; iv < nv; ++iv) {
347 const auto& pv = pvvec[iv];
348 if (pv.getNContributors() - 1 < mParams->
minPVCont) {
351 if (requireMCMatch) {
354 const auto& vtxRef = vtxRefs[iv];
355 int it = vtxRef.getFirstEntry(), itLim = it + vtxRef.getEntries();
356 for (; it < itLim; it++) {
357 const auto& tvid = trackIndex[it];
358 if (tvid.isAmbiguous()) {
364 if (mUseMC && requireMCMatch) {
374 const auto cdm = GTrackID::getSourceDetectorsMask(cis);
375 if (!mRecoData.
isTrackSourceLoaded(cis) || !cdm[DetID::ITS] || !contributorsGID[cis].isIndexSet()) {
378 if (mUseMC && requireMCMatch) {
384 t2v[contributorsGID[cis]] = iv;
389 return std::move(t2v);
400 std::array<const TrackingCluster*, 8> clArr{
nullptr};
402 const auto& itsTrOrig = mRecoData.
getITSTrack(gidx);
406 if (!prop->propagateToDCA(pv, trkPV, prop->getNominalBz(), 2.0, mParams->
CorrType)) {
407 mTrackCounter -= gidx.getSource();
411 float cosAlp = NAN, sinAlp = NAN;
412 o2::math_utils::sincos(trkPV.getAlpha(), sinAlp, cosAlp);
414 TrackingCluster pvCls;
415 pvCls.alpha = trkPV.getAlpha();
416 pvCls.setXYZ((pv.getX() * cosAlp) + (pv.getY() * sinAlp), (-pv.getX() * sinAlp) + (pv.getY() * cosAlp), pv.getZ());
417 pvCls.setErrors(0.5f * (pv.getSigmaX2() + pv.getSigmaY2()), pv.getSigmaZ2(), 0.f);
418 pvCls.setSensorID(-1);
421 const int ncl = itsTrOrig.getNumberOfClusters();
422 for (
int icl = 0; icl <
ncl; ++icl) {
423 const auto& curClu = mITScl[mITSclRef[itsTrOrig.getClusterEntry(icl)]];
424 const int llr = geom->getLayer(curClu.getSensorID());
425 if (clArr[1 + llr]) {
426 LOGP(fatal,
"Cluster at lr {} was already assigned, old sens {}, new sens {}", llr, clArr[1 + llr]->
getSensorID(), curClu.getSensorID());
428 clArr[1 + llr] = &curClu;
432 trFit.resetCovariance(1'000);
434 for (
int icl = clArr.size() - 1; icl >= 0; --icl) {
438 if (!trFit.rotate(clArr[icl]->alpha) || !prop->propagateToX(trFit, clArr[icl]->
getX(), prop->getNominalBz(), 0.85, 2.0, mParams->
CorrType)) {
439 mTrackCounter -= gidx.getSource();
442 chi2 += trFit.getPredictedChi2(*clArr[icl]);
443 if (!trFit.update(*clArr[icl])) {
444 mTrackCounter -= gidx.getSource();
451void TrackingStudySpec::doDCAStudy()
454 LOGP(info,
"Doing DCA study");
455 mTrackCounter.reset();
459 int nDCAFits{0}, nDCAFitsFail{0};
463 auto nv = vtxRefs.size() - 1;
464 auto&
stream = (*mDBGOut) <<
"dca";
465 for (
int iv = 0; iv < nv; iv++) {
466 const auto& pv = pvvec[iv];
467 const auto& vtref = vtxRefs[iv];
469 const auto dm = GTrackID::getSourceDetectorsMask(is);
474 int idMin = vtref.getFirstEntryOfSource(is), idMax = idMin + vtref.getEntriesOfSource(is);
475 for (
int i = idMin;
i < idMax;
i++) {
476 const auto vid = trackIndex[
i];
477 if (!vid.isPVContributor()) {
478 mTrackCounter &= vid.getSource();
486 const auto cdm = GTrackID::getSourceDetectorsMask(cis);
487 if (!mRecoData.
isTrackSourceLoaded(cis) || !cdm[DetID::ITS] || !contributorsGID[cis].isIndexSet()) {
488 mTrackCounter &= cis;
491 if (!selectTrack(contributorsGID[cis])) {
492 mTrackCounter &= vid.getSource();
497 const auto& trk = mRecoData.
getTrackParam(contributorsGID[cis]);
500 if (mWithPV && mParams->
refitITS && cis ==
GTrackID::ITS && !refitITSPVTrack(trkRefit, contributorsGID[cis], pv)) {
501 mTrackCounter -= cis;
504 trkRefit.invalidate();
508 if (!prop->propagateToDCABxByBz(pv, trkDCA, 2.f, mParams->
CorrType, &dcaInfo)) {
509 mTrackCounter -= cis;
517 <<
"trkRefit=" << trkRefit
518 <<
"trkAtPV=" << trkDCA
519 <<
"dca=" << dcaInfo;
525 const auto& eve = mMCReader.
getMCEventHeader(lbl.getSourceID(), lbl.getEventID());
527 mcEve.setPos({(float)eve.GetX(), (float)eve.GetY(), (float)eve.GetZ()});
529 if (!prop->propagateToDCABxByBz(mcEve, trkC, 2.f, mParams->
CorrType, &dcaInfoMC)) {
530 mTrackCounter -= cis;
534 const auto& mcTrk = mMCReader.
getTrack(lbl);
535 if (mcTrk ==
nullptr) {
536 LOGP(fatal,
"mcTrk is null did selection fail?");
538 stream <<
"mcTrk=" << *mcTrk
539 <<
"dca2MC=" << dcaInfoMC
545 mTrackCounter += cis;
551 LOGP(info,
"doDCAStudy: accepted {} fits, failed {} (in {:.2f} seconds)", nDCAFits, nDCAFitsFail,
sw.RealTime());
552 mTrackCounter.print();
555void TrackingStudySpec::doDCARefitStudy()
558 LOGP(info,
"Doing DCARefit study");
559 mTrackCounter.reset();
567 auto nv = vtxRefs.size() - 1;
568 auto t2v = buildT2V();
569 std::vector<std::vector<GTrackID>> v2t;
571 auto creator = [&](
const auto& trk,
GTrackID trkID,
float _t0,
float terr) ->
bool {
572 if constexpr (!isBarrelTrack<decltype(trk)>()) {
573 mTrackCounter &= trkID.getSource();
577 mTrackCounter &= trkID.getSource();
581 if constexpr (isBarrelTrack<decltype(trk)>()) {
582 if (trk.getPt() < mParams->
minPt || trk.getPt() > mParams->
maxPt) {
583 mTrackCounter &= trkID.getSource();
586 if (std::abs(trk.getEta()) > mParams->
maxEta) {
587 mTrackCounter &= trkID.getSource();
590 if (!t2v.contains(trkID)) {
591 mTrackCounter &= trkID.getSource();
594 if (!selectTrack(trkID, mUseMC)) {
595 mTrackCounter &= trkID.getSource();
599 v2t[t2v[trkID]].push_back(trkID);
604 int nDCAFits{0}, nDCAFitsFail{0};
605 auto&
stream = (*mDBGOut) <<
"dcaRefit";
606 for (
size_t iv = 0; iv < nv; ++iv) {
607 const auto& pv = pvvec[iv];
608 const auto& trkIDs = v2t[iv];
609 if (trkIDs.size() - 1 < mParams->
minPVCont) {
612 std::vector<o2::track::TrackParCov> trks;
613 trks.reserve(trkIDs.size());
614 for (
const auto& trkID : trkIDs) {
621 std::vector<bool>
trkMask(trkIDs.size(),
true);
622 for (
size_t it{0}; it <
trkMask.size(); ++it) {
628 if (pvRefit.getChi2() < 0) {
635 auto trkC = trks[it];
636 if (!prop->propagateToDCABxByBz(pv, trkC, 2.f, mParams->
CorrType, &dcaInfo)) {
637 mTrackCounter -= trkIDs[it].getSource();
642 auto trkCRefit = trks[it];
643 if (!prop->propagateToDCABxByBz(pv, trkCRefit, 2.f, mParams->
CorrType, &dcaInfoRefit)) {
644 mTrackCounter -= trkIDs[it].getSource();
649 stream <<
"src=" << trkIDs[it].getSource()
651 <<
"trkAtPV=" << trkC
653 <<
"pvRefit=" << pvRefit
654 <<
"trkAtPVRefit=" << trkC
655 <<
"dcaRefit=" << dcaInfoRefit;
658 if (mcTrk ==
nullptr) {
659 LOGP(fatal,
"mcTrk is null did selection fail?");
661 stream <<
"mcTrk=" << *mcTrk;
665 mTrackCounter += trkIDs[it].getSource();
669 LOGP(info,
"doDCARefitStudy: accepted {} fits, failed {} (in {:.2f} seconds)", nDCAFits, nDCAFitsFail,
sw.RealTime());
670 mTrackCounter.print();
673void TrackingStudySpec::doPullStudy()
676 LOGP(info,
"Doing Pull study");
677 mTrackCounter.reset();
680 int nPulls{0}, nPullsFail{0};
683 auto checkInTrack = [&](
GTrackID trkID) {
684 if (!selectTrack(trkID)) {
685 mTrackCounter &= trkID.getSource();
689 const auto mcTrk = mMCReader.
getTrack(lbl);
693 if (!mcTrk->isPrimary()) {
694 mTrackCounter &= trkID.getSource();
701 const auto& eve = mMCReader.
getMCEventHeader(lbl.getSourceID(), lbl.getEventID());
703 mcEve.setXYZ((
float)eve.GetX(), (float)eve.GetY(), (float)eve.GetZ());
704 mcEve.setSigmaX(20e-4f);
705 mcEve.setSigmaY(20e-4f);
706 mcEve.setSigmaZ(20e-4f);
707 if (!refitITSPVTrack(trk, trkID, mcEve)) {
708 mTrackCounter -= trkID.getSource();
714 std::array<float, 3> xyz{(float)mcTrk->GetStartVertexCoordinatesX(), (float)mcTrk->GetStartVertexCoordinatesY(), (float)mcTrk->GetStartVertexCoordinatesZ()},
715 pxyz{(float)mcTrk->GetStartVertexMomentumX(), (float)mcTrk->GetStartVertexMomentumY(), (float)mcTrk->GetStartVertexMomentumZ()};
716 TParticlePDG* pPDG = TDatabasePDG::Instance()->GetParticle(mcTrk->GetPdgCode());
718 mTrackCounter -= trkID.getSource();
724 if (!mcTrkO2.rotate(trk.getAlpha()) || !prop->PropagateToXBxByBz(mcTrkO2, trk.getX())) {
725 mTrackCounter -= trkID.getSource();
734 <<
"src=" << trkID.getSource()
735 <<
"itsTrk=" << itsTrk
736 <<
"mcTrk=" << mcTrkO2
737 <<
"mcPart=" << mcTrk
741 mTrackCounter += trkID.getSource();
760 LOGP(info,
"doPullStudy: accepted {} pulls; rejected {} (in {:.2f} seconds)", nPulls, nPullsFail,
sw.RealTime());
761 mTrackCounter.print();
764void TrackingStudySpec::doMCStudy()
766 LOGP(info,
"Doing MC study");
767 mTrackCounter.reset();
774 std::unordered_map<o2::MCCompLabel, ParticleInfoExt>
info;
776 LOGP(info,
"** Filling particle table ... ");
777 for (
int iEve{0}; iEve < nev; ++iEve) {
778 const auto& mcTrks = mMCReader.
getTracks(iSrc, iEve);
779 for (
int iTrk{0}; iTrk < mcTrks.size(); ++iTrk) {
780 const auto& mcTrk = mcTrks[iTrk];
781 const auto pdg = mcTrk.GetPdgCode();
785 const auto apdg = std::abs(pdg);
786 if (apdg != 11 && apdg != 211 && apdg != 321 && apdg != 2212) {
790 auto& part =
info[lbl];
791 part.mcTrack = mcTrk;
794 LOGP(info,
"** Creating particle/clusters correspondence ... ");
796 for (
int lr = 0; lr < nLrCl; lr++) {
799 for (
auto iCluster{0}; iCluster <
clusters.size(); ++iCluster) {
800 auto labs = clustersMCLCont->getLabels(iCluster);
801 for (
auto& lab : labs) {
802 if (!lab.isValid() || lab.getSourceID() != 0 || !lab.isCorrect()) {
805 int trackID = 0, evID = 0, srcID = 0;
807 lab.get(trackID, evID, srcID, fake);
810 auto& part =
info[{trackID, evID, srcID}];
811 part.clusters |= (1 <<
layer);
813 part.fakeClusters |= (1 <<
layer);
818 LOGP(info,
"** Analysing tracks ... ");
820 if (contributorsGID[det].isIndexSet()) {
823 o2::MCCompLabel iLbl(lbl.getTrackID(), lbl.getEventID(), lbl.getSourceID());
824 if (
info.contains(iLbl)) {
825 auto& part =
info[iLbl];
826 SETBIT(part.recoTracks, det);
828 SETBIT(part.fakeTracks, det);
834 auto creator = [&](
const auto& trk,
GTrackID trkID,
float _t0,
float terr) ->
bool {
835 if constexpr (!isBarrelTrack<decltype(trk)>()) {
847 if (!gLbl.isValid()) {
850 o2::MCCompLabel iLbl(gLbl.getTrackID(), gLbl.getEventID(), gLbl.getSourceID());
851 if (!
info.contains(iLbl)) {
854 auto& part =
info[iLbl];
857 accountLbl(contributorsGID, DetID::ITS);
858 accountLbl(contributorsGID, DetID::TPC);
859 accountLbl(contributorsGID, DetID::TRD);
860 accountLbl(contributorsGID, DetID::TOF);
867 LOGP(info,
"Streaming output to tree");
868 for (
const auto& [_, part] :
info) {
875 LOGP(info,
"doMCStudy: accounted {} MCParticles and {} tracks (in {:.2f} seconds)",
info.size(), nTracks,
sw.RealTime());
878void TrackingStudySpec::doResidStudy()
880 LOGP(info,
"Doing residual study");
883 const float bz = prop->getNominalBz();
885 int goodRefit{0}, notPassedSel{0}, fitFail{0};
888 std::array<TrackingCluster, 8> cl;
889 std::array<const TrackingCluster*, 8> clArr{
nullptr};
891 float ip[2]{0.f, 0.f};
898 const auto& eve = mMCReader.
getMCEventHeader(lbl.getSourceID(), lbl.getEventID());
899 pv.setXYZ(eve.GetX(), eve.GetY(), eve.GetZ());
901 auto trFitOut = iTrack.getParamIn();
902 if (!prop->propagateToDCA(pv, trFitOut, bz, base::Propagator::MAX_STEP, mParams->
CorrType)) {
905 pv.setSigmaX(20e-4f);
906 pv.setSigmaY(20e-4f);
907 pv.setSigmaZ(20e-4f);
908 float cosAlp = NAN, sinAlp = NAN;
909 o2::math_utils::sincos(trFitOut.getAlpha(), sinAlp, cosAlp);
910 cl[0].alpha = trFitOut.getAlpha();
911 cl[0].setXYZ((pv.getX() * cosAlp) + (pv.getY() * sinAlp), (-pv.getX() * sinAlp) + (pv.getY() * cosAlp), pv.getZ());
912 cl[0].setErrors(0.5f * (pv.getSigmaX2() + pv.getSigmaY2()), pv.getSigmaZ2(), 0.f);
913 cl[0].setSensorID(-1);
918 int nCl = iTrack.getNClusters();
919 for (
int i = 0;
i <
nCl;
i++) {
921 int sens = curClu.getSensorID();
922 int llr = geom->getLayer(sens);
923 if (clArr[1 + llr]) {
924 LOGP(fatal,
"Cluster at lr {} was already assigned, old sens {}, new sens {}", llr, clArr[1 + llr]->
getSensorID(), sens);
926 clArr[1 + llr] = &curClu;
929 std::array<o2::track::TrackParCov, 8> extrapOut, extrapInw;
936 for (
int i = 0;
i <= 7;
i++) {
939 if (!tInt.isValid()) {
942 auto phi =
i == 0 ? tInt.getPhi() : tInt.getPhiPos();
943 o2::math_utils::bringTo02Pi(phi);
946 getImpactParams(tInt, pv, ip, bz);
948 <<
"dYInt=" << clArr[
i]->getY() - tInt.getY()
949 <<
"dZInt=" << clArr[
i]->getZ() - tInt.getZ()
950 <<
"dYIn=" << clArr[
i]->getY() - extrapInw[
i].getY()
951 <<
"dZIn=" << clArr[
i]->getZ() - extrapInw[
i].getZ()
952 <<
"dYOut=" << clArr[
i]->getY() - extrapOut[
i].getY()
953 <<
"dZOut=" << clArr[
i]->getZ() - extrapOut[
i].getZ()
955 <<
"clY=" << clArr[
i]->getY()
956 <<
"clZ=" << clArr[
i]->getZ()
957 <<
"clX=" << clArr[
i]->getX()
958 <<
"alpha=" << clArr[
i]->alpha
959 <<
"sens=" << clArr[
i]->getSensorID()
963 <<
"pt=" << tInt.getPt()
974 for (
size_t iTrk{0}; iTrk < itsTracks.size(); ++iTrk) {
975 const auto& iTrack = itsTracks[iTrk];
976 const auto& lbl = itsMC[iTrk];
977 const auto& mc = mMCReader.
getTrack(lbl);
978 if (std::abs(iTrack.getEta()) > mParams->
maxEta || iTrack.getChi2() > mParams->
maxChi2 || iTrack.getNClusters() < mParams->
minITSCls || iTrack.getPt() < mParams->
minPt || !lbl.isCorrect() || !mc->isPrimary()) {
982 doRefits(iTrack, lbl);
985 LOGP(info,
"\trefitted {} out of {} tracks ({} !sel, {} !fit)", goodRefit, itsTracks.size(), notPassedSel, fitFail);
988void TrackingStudySpec::doMisalignmentStudy()
990 LOGP(info,
"Doing misalignment study");
994 int goodRefit{0}, notPassedSel{0}, fitFail{0}, fitFailMis{0};
996 float ip[2]{0.f, 0.f};
998 auto writeTree = [&](
const char* treeName,
999 const std::array<const TrackingCluster*, 8>& clArr,
1000 const std::array<o2::track::TrackParCov, 8>& extrapOut,
1001 const std::array<o2::track::TrackParCov, 8>& extrapInw,
1003 const auto mcTrk = mMCReader.
getTrack(lbl);
1007 TParticlePDG* pPDG = TDatabasePDG::Instance()->GetParticle(mcTrk->GetPdgCode());
1011 const std::array<float, 3> xyz{(float)mcTrk->
GetStartVertexCoordinatesX(), (float)mcTrk->GetStartVertexCoordinatesY(), (float)mcTrk->GetStartVertexCoordinatesZ()};
1012 const std::array<float, 3> pxyz{(float)mcTrk->GetStartVertexMomentumX(), (float)mcTrk->GetStartVertexMomentumY(), (float)mcTrk->GetStartVertexMomentumZ()};
1013 const int mcCharge = TMath::Nint(pPDG->Charge() / 3);
1018 if (!mcTrkAtX.rotate(tInt.getAlpha()) || !prop->PropagateToXBxByBz(mcTrkAtX, tInt.getX())) {
1021 auto phi = (layOut < 0) ? tInt.getPhi() : tInt.getPhiPos();
1022 o2::math_utils::bringTo02Pi(phi);
1026 getImpactParams(tInt, pv, ip, prop->getNominalBz());
1027 (*mDBGOut) << treeName
1029 <<
"mcTrk=" << mcTrkAtX
1033 <<
"dcaXY=" << ip[0]
1036 <<
"eta=" << tInt.getEta()
1054 for (
int i = 1;
i <= 7; ++
i) {
1059 if (!tFull.isValid() || !tFull.update(*clArr[
i])) {
1062 writeRow(tFull, 0.f, 0.f, -1);
1067 for (
int i = 0;
i <= 7;
i++) {
1073 if (!tInt.isValid()) {
1076 writeRow(tInt, clArr[
i]->
getY() - tInt.getY(), clArr[
i]->getZ() - tInt.getZ(),
i - 1);
1082 for (
size_t iTrk{0}; iTrk < itsTracks.size(); ++iTrk) {
1083 const auto& iTrack = itsTracks[iTrk];
1084 if (std::abs(iTrack.getEta()) > mParams->
maxEta || iTrack.getChi2() > mParams->
maxChi2 || iTrack.getNClusters() < mParams->
minITSCls || iTrack.getPt() < mParams->
minPt) {
1088 const auto& lbl = itsMC[iTrk];
1089 if (!lbl.isCorrect() || !lbl.isValid()) {
1093 const auto& mc = mMCReader.
getTrack(lbl);
1094 if (!mc->isPrimary()) {
1100 std::array<TrackingCluster, 8> cl;
1101 std::array<const TrackingCluster*, 8> clArr{
nullptr};
1104 const auto& eve = mMCReader.
getMCEventHeader(lbl.getSourceID(), lbl.getEventID());
1105 pv.setXYZ(eve.GetX(), eve.GetY(), eve.GetZ());
1107 auto trFitOut = iTrack.getParamIn();
1108 if (!prop->propagateToDCA(pv, trFitOut, prop->getNominalBz(), base::Propagator::MAX_STEP, mParams->
CorrType)) {
1111 pv.setSigmaX(20e-4f);
1112 pv.setSigmaY(20e-4f);
1113 pv.setSigmaZ(20e-4f);
1114 float cosAlp = NAN, sinAlp = NAN;
1115 o2::math_utils::sincos(trFitOut.getAlpha(), sinAlp, cosAlp);
1116 cl[0].alpha = trFitOut.getAlpha();
1117 cl[0].setXYZ((pv.getX() * cosAlp) + (pv.getY() * sinAlp), (-pv.getX() * sinAlp) + (pv.getY() * cosAlp), pv.getZ());
1118 cl[0].setErrors(0.5f * (pv.getSigmaX2() + pv.getSigmaY2()), pv.getSigmaZ2(), 0.f);
1119 cl[0].setSensorID(-1);
1124 int nCl = iTrack.getNClusters();
1125 for (
int i = 0;
i <
nCl;
i++) {
1127 int sens = curClu.getSensorID();
1128 int llr = geom->getLayer(sens);
1129 if (clArr[1 + llr]) {
1130 LOGP(fatal,
"Cluster at lr {} was already assigned, old sens {}, new sens {}", llr, clArr[1 + llr]->
getSensorID(), sens);
1132 clArr[1 + llr] = &curClu;
1134 std::array<o2::track::TrackParCov, 8> extrapOut, extrapInw;
1140 writeTree(
"idealRes", clArr, extrapOut, extrapInw, lbl);
1144 const auto mcTrk = mMCReader.
getTrack(lbl);
1148 std::array<float, 3> xyz{(float)mcTrk->
GetStartVertexCoordinatesX(), (float)mcTrk->GetStartVertexCoordinatesY(), (float)mcTrk->GetStartVertexCoordinatesZ()};
1149 std::array<float, 3> pxyz{(float)mcTrk->GetStartVertexMomentumX(), (float)mcTrk->GetStartVertexMomentumY(), (float)mcTrk->GetStartVertexMomentumZ()};
1150 TParticlePDG* pPDG = TDatabasePDG::Instance()->GetParticle(mcTrk->GetPdgCode());
1156 std::array<TrackingCluster, 3> misClArr;
1157 std::array<const TrackingCluster*, 8> clArrMis{};
1158 for (
int i = 0;
i <= 7;
i++) {
1159 clArrMis[
i] = clArr[
i];
1161 for (
int iLay = 0; iLay < 3; ++iLay) {
1162 if (!clArr[1 + iLay]) {
1165 const auto& orig = *clArr[1 + iLay];
1166 const int sens = orig.getSensorID();
1172 const auto& sensorMis = mMisalignment[sensorID];
1175 auto mcAtCl = mcPar;
1176 if (!mcAtCl.rotate(orig.alpha) || !prop->PropagateToXBxByBz(mcAtCl, orig.getX())) {
1177 clArrMis[1 + iLay] =
nullptr;
1180 const align::MisalignmentFrame misFrame{
1181 .sensorID = sensorID,
1184 .alpha = orig.alpha,
1188 align::MisalignmentShift totalShift;
1189 if (sensorMis.hasLegendre) {
1191 if (!shift.accepted) {
1192 clArrMis[1 + iLay] =
nullptr;
1195 totalShift += shift;
1197 if (sensorMis.hasInextensional) {
1202 misClArr[iLay] = orig;
1203 misClArr[iLay].setY(orig.getY() + totalShift.dy);
1204 misClArr[iLay].setZ(orig.getZ() + totalShift.dz);
1205 misClArr[iLay].setSigmaY2(orig.getSigmaY2() + (mParams->
misAlgExtCY[sensorID] * mParams->
misAlgExtCY[sensorID]));
1206 misClArr[iLay].setSigmaZ2(orig.getSigmaZ2() + (mParams->
misAlgExtCZ[sensorID] * mParams->
misAlgExtCZ[sensorID]));
1207 clArrMis[1 + iLay] = &misClArr[iLay];
1217 writeTree(
"misRes", clArrMis, extrapOut, extrapInw, lbl);
1222 LOGP(info,
"\tdoMisalignmentStudy: refitted {} out of {} tracks ({} !sel, {} !fit, {} !fitMis)", goodRefit, itsTracks.size(), notPassedSel, fitFail, fitFailMis);
1229 float x = pv.getX(),
y = pv.getY(),
z = pv.getZ();
1230 float f1 = trk.getSnp(), r1 = std::sqrt((1.f - f1) * (1.f + f1));
1231 float xt = trk.getX(), yt = trk.getY();
1232 float sn = std::sin(trk.getAlpha()), cs = std::cos(trk.getAlpha());
1233 float a = (
x * cs) + (
y * sn);
1234 y = (-
x * sn) + (
y * cs);
1238 float rp4 = trk.getCurvature(bz);
1239 if ((std::abs(bz) < o2::constants::math::Almost0) || (std::abs(rp4) < o2::constants::math::Almost0)) {
1240 ip[0] = -((xt *
f1) - (yt * r1));
1241 ip[1] = trk.getZ() + ((ip[0] *
f1 - xt) / r1 * trk.getTgl()) -
z;
1244 sn = (rp4 * xt) - f1;
1245 cs = (rp4 * yt) + r1;
1246 a = (2 * (xt *
f1 - yt * r1)) - (rp4 * (xt * xt + yt * yt));
1247 float rr = std::sqrt((sn * sn) + (cs * cs));
1248 ip[0] = -
a / (1 + rr);
1249 float f2 = -sn / rr, r2 = std::sqrt((1.f - f2) * (1.f + f2));
1250 ip[1] = trk.getZ() + (trk.getTgl() / rp4 * std::asin((f2 * r1) - (f1 * r2))) -
z;
1255 std::vector<OutputSpec> outputs;
1256 auto dataRequest = std::make_shared<DataRequest>();
1257 dataRequest->setITSPerLayer(itsStag);
1259 dataRequest->requestTracks(srcTracks, useMC);
1260 dataRequest->requestIT3Clusters(useMC);
1261 dataRequest->requestClusters(srcClusters, useMC);
1263 dataRequest->requestPrimaryVertices(useMC);
1265 auto ggRequest = std::make_shared<o2::base::GRPGeomRequest>(
false,
1271 dataRequest->inputs,
1275 .
name =
"its3-track-study",
1276 .inputs = dataRequest->inputs,
1278 .algorithm =
AlgorithmSpec{adaptFromTask<TrackingStudySpec>(dataRequest, ggRequest, srcTracks, useMC, withPV)},
Container of the ITS/MFT clusters addressed by the composed (layer,index) ID.
Definition of the GeometryManager class.
Definition of the ITSMFT Hit class.
Definition of the BuildTopologyDictionary class for ITS3.
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.
Wrapper container for different reconstructed object types.
o2::track::TrackParCov TrackParCov
Referenc on track indices contributing to the vertex, with possibility chose tracks from specific sou...
Double_t GetStartVertexCoordinatesX() const
static TDatabasePDG * Instance()
void checkUpdates(o2::framework::ProcessingContext &pc)
static GRPGeomHelper & instance()
void setRequest(std::shared_ptr< GRPGeomRequest > req)
static std::string getCollisionContextFileName(const std::string_view prefix="")
GPUd() value_type estimateLTFast(o2 static GPUd() float estimateLTIncrement(const o2 PropagatorImpl * Instance(bool uninitialized=false)
void printKeyValues(bool showProv=true, bool useLogger=false, bool withPadding=true, bool showHash=true) const final
static const ITS3TrackingStudyParam & Instance()
Static class with identifiers, bitmasks and names for ALICE detectors.
int ID
Detector identifiers: continuous, starting from 0.
ServiceRegistryRef services()
void finaliseCCDB(ConcreteDataMatcher &matcher, void *obj) final
TrackingStudySpec & operator=(TrackingStudySpec &&)=delete
void run(ProcessingContext &pc) final
void endOfStream(EndOfStreamContext &ec) final
This is invoked whenever we have an EndOfStream event.
TrackingStudySpec(const TrackingStudySpec &)=delete
void init(InitContext &ic) final
TrackingStudySpec(TrackingStudySpec &&)=delete
~TrackingStudySpec() final=default
TrackingStudySpec(std::shared_ptr< DataRequest > dr, std::shared_ptr< o2::base::GRPGeomRequest > gr, GTrackID::mask_t src, bool useMC, bool withPV)
TrackingStudySpec & operator=(const TrackingStudySpec &)=delete
static GeometryTGeo * Instance()
int getLayer(int index) const final
Get chip layer, from 0.
void fillMatrixCache(int mask) override
int getClusterEntry(int i) const
bool initFromDigitContext(std::string_view filename)
MCTrack const * getTrack(o2::MCCompLabel const &) 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
std::vector< MCTrack > const & getTracks(int source, int event) const
variant returning all tracks for source and event at once
bool prepareVertexRefit(const TR &tracks, const o2d::VertexBase &vtxSeed)
PVertex refitVertex(const std::vector< bool > useTrack, const o2d::VertexBase &vtxSeed)
GLfloat GLfloat GLfloat alpha
GLenum GLuint GLint GLint layer
GLboolean GLboolean GLboolean GLboolean a
GLdouble GLdouble GLdouble z
Defining ITS Vertex explicitly as messageable.
constexpr int MaxITSLayers
MisalignmentShift evaluateInextensionalShift(const SensorMisalignment &sensor, const MisalignmentFrame &frame, const TrackSlopes &slopes)
bool doBidirRefit(const o2::its::TrackITS &iTrack, std::array< const TrackingCluster< T > *, 8 > &clArr, std::array< o2::track::TrackParametrizationWithError< T >, 8 > &extrapOut, std::array< o2::track::TrackParametrizationWithError< T >, 8 > &extrapInw, T &chi2, bool useStableRef, typename o2::base::PropagatorImpl< T >::MatCorrType corrType)
MisalignmentModel loadMisalignmentModel(const std::string &jsonPath)
o2::track::TrackParametrizationWithError< T > interpolateTrackParCov(const o2::track::TrackParametrizationWithError< T > &tA, const o2::track::TrackParametrizationWithError< T > &tB)
MisalignmentShift evaluateLegendreShift(const SensorMisalignment &sensor, const MisalignmentFrame &frame, const TrackSlopes &slopes)
TrackSlopes computeTrackSlopes(double snp, double tgl)
T getDetID2Layer(T detID)
o2::math_utils::Point3D< T > extractClusterData(const itsmft::CompClusterExt &c, iterator &iter, const o2::its3::TopologyDictionary *dict, T &sig2y, T &sig2z)
std::unordered_map< GTrackID, size_t > T2VMap
o2::dataformats::GlobalTrackID GTrackID
o2::framework::DataProcessorSpec getTrackingStudySpec(o2::dataformats::GlobalTrackID::mask_t srcTracks, o2::dataformats::GlobalTrackID::mask_t srcClus, bool useMC, bool withPV, bool itsStag)
o2::track::TrackParCov int int int float int nCl
const float const float const float bz
double * getX(double *xyDxy, int N)
double * getY(double *xyDxy, int N)
a couple of static helper functions to create timestamp values for CCDB queries or override obsolete ...
auto getITSPerLayer() const
auto getITSTracks() const
bool isTrackSourceLoaded(int src) const
GlobalIDSet getSingleDetectorRefs(GTrackID gidx) const
const o2::tpc::TrackTPC & getTPCTrack(GTrackID id) const
auto getITSTPCTOFMatches() const
auto getITSTPCTRDTracksMCLabels() const
auto getITSTracksClusterRefs() const
auto getPrimaryVertices() const
auto getPrimaryVertexMatchedTracks() const
auto getTPCITSTracks() const
void createTracksVariadic(T creator, GTrackID::mask_t srcSel=GTrackID::getSourcesMask("all")) const
auto getPrimaryVertexMatchedTrackRefs() const
auto getITSClustersPatterns(int layer=0) const
o2::MCCompLabel getTrackMCLabel(GTrackID id) const
auto getTOFClustersMCLabels() const
const o2::track::TrackParCov & getTrackParam(GTrackID gidx) const
const o2::MCEventLabel & getPrimaryVertexMCLabel(int i) const
void collectData(o2::framework::ProcessingContext &pc, const DataRequest &request)
const o2::track::TrackParCov & getTrackParamOut(GTrackID gidx) const
const o2::its::TrackITS & getITSTrack(GTrackID gid) const
auto getITSClusters(int layer=0) const
auto getITSTPCTRDTOFMatches() const
std::array< GTrackID, GTrackID::NSources > GlobalIDSet
auto getITSTracksMCLabels() const
auto getITSClustersMCLabels(int layer=0) const
int minTPCCls
TPC track selection.
o2::base::PropagatorImpl< float >::MatCorrType CorrType
float maxChi2
general track selection
int minPVCont
PV selection.
int minITSCls
ITS track selection.
LOG(info)<< "Compressed in "<< sw.CpuTime()<< " s"
std::vector< Cluster > clusters