15#include <TStopwatch.h>
56using T2VMap = std::unordered_map<GTrackID, size_t>;
62 : mDataRequest(dr), mGGCCDBRequest(gr), mTracksSrc(
src), mUseMC(useMC) {}
70 void process(
o2::globaltracking::RecoContainer& recoData);
72 std::vector<
o2::
BaseCluster<
float>> prepareITSClusters(const
o2::globaltracking::RecoContainer&
data) const;
73 bool selectTrack(
GTrackID trkID,
o2::globaltracking::RecoContainer& recoData,
bool checkMCTruth = true) const;
74 T2VMap buildT2V(
o2::globaltracking::RecoContainer& recoData,
bool includeCont = false,
bool requireMCMatch = true) const;
75 bool refitITSPVTrack(
o2::globaltracking::RecoContainer& recoData,
o2::track::
TrackParCov& trFit,
GTrackID gidx);
76 void doDCAStudy(
o2::globaltracking::RecoContainer& recoData);
77 void doDCARefitStudy(
o2::globaltracking::RecoContainer& recoData);
78 void doPullStudy(
o2::globaltracking::RecoContainer& recoData);
79 void doMCStudy(
o2::globaltracking::RecoContainer& recoData);
82 TrackCounter() =
default;
84 void operator+=(
int src)
86 if (
src >= 0 &&
src <
static_cast<int>(mSuccess.size())) {
91 void operator-=(
int src)
93 if (
src >= 0 &&
src <
static_cast<int>(mirrors.size())) {
98 void operator&=(
int src)
100 if (
src >= 0 &&
src <
static_cast<int>(mRejected.size())) {
107 LOGP(info,
"\t\t\tSuccess / Error / Rejected");
109 const auto cdm = GTrackID::getSourceDetectorsMask(cis);
111 LOGP(info,
"\t{:{}}\t{} / {} / {}",
GTrackID::getSourceName(cis), 15, mSuccess[cis], mirrors[cis], mRejected[cis]);
123 std::array<size_t, GTrackID::NSources> mSuccess{};
124 std::array<size_t, GTrackID::NSources> mirrors{};
125 std::array<size_t, GTrackID::NSources> mRejected{};
127 TrackCounter mTrackCounter;
129 std::unique_ptr<o2::utils::TreeStreamRedirector> mDBGOut;
130 std::shared_ptr<DataRequest> mDataRequest;
131 std::shared_ptr<o2::base::GRPGeomRequest> mGGCCDBRequest;
144 std::string dbgnm = maxLanes == 1 ?
"its3TrackStudy.root" : fmt::format(
"its3TrackStudy_{}.root", lane);
145 mDBGOut = std::make_unique<o2::utils::TreeStreamRedirector>(dbgnm.c_str(),
"recreate");
148 LOGP(fatal,
"initialization of MCKinematicsReader failed");
156 updateTimeDependentParams(pc);
163 if (
static bool initOnceDone{
false}; !initOnceDone) {
182 LOG(info) <<
"cluster dictionary updated";
192 doDCAStudy(recoData);
194 if (conf.doDCARefit) {
195 doDCARefitStudy(recoData);
197 if (mUseMC && conf.doPull) {
198 doPullStudy(recoData);
200 if (mUseMC && conf.doMC) {
207 std::vector<o2::BaseCluster<float>> itscl;
208 const auto& clusITS =
data.getITSClusters();
209 if (clusITS.size()) {
210 const auto& patterns =
data.getITSClustersPatterns();
211 itscl.reserve(clusITS.size());
212 auto pattIt = patterns.begin();
215 return std::move(itscl);
233 if (itsTrk.getChi2() > conf.maxChi2 || itsTrk.getNClusters() < conf.minITSCls) {
239 if (tpcTrk.getNClusters() < conf.minTPCCls) {
245 if (gTrk.getPt() < conf.minPt || gTrk.getPt() > conf.maxPt) {
248 if (std::abs(gTrk.getEta()) > conf.maxEta) {
251 if (mUseMC && checkMCTruth) {
253 if (!itsLbl.isValid()) {
258 if (itsLbl != tpcLbl) {
267 for (
const auto& lbl : tofLbls) {
284 auto nv = vtxRefs.size() - 1;
286 for (
size_t iv = 0; iv < nv; ++iv) {
287 const auto& pv = pvvec[iv];
288 if (pv.getNContributors() - 1 < conf.minPVCont) {
291 if (requireMCMatch) {
294 const auto& vtxRef = vtxRefs[iv];
295 int it = vtxRef.getFirstEntry(), itLim = it + vtxRef.getEntries();
296 for (; it < itLim; it++) {
297 const auto& tvid = trackIndex[it];
298 if (tvid.isAmbiguous()) {
304 if (mUseMC && requireMCMatch) {
314 const auto cdm = GTrackID::getSourceDetectorsMask(cis);
318 if (mUseMC && requireMCMatch) {
324 t2v[contributorsGID[cis]] = iv;
329 return std::move(t2v);
338 static auto t2v = buildT2V(recoData,
true,
true);
339 static const auto itsClusters = prepareITSClusters(recoData);
340 static std::vector<unsigned int> itsTracksROF;
341 if (
static bool done{
false}; !
done) {
345 for (
unsigned irf = 0, cnt = 0; irf < itsTracksROFRec.size(); irf++) {
346 int ntr = itsTracksROFRec[irf].getNEntries();
347 for (
int itr = 0; itr < ntr; itr++) {
348 itsTracksROF[cnt++] = irf;
354 std::array<o2::BaseCluster<float>, 8> clArr{};
355 std::array<float, 8> clAlpha{};
358 const auto& itsTrOrig = recoData.
getITSTrack(gidx);
359 int ncl = itsTrOrig.getNumberOfClusters(), rof = itsTracksROF[gidx.getIndex()];
361 int clEntry = itsTrOrig.getFirstClusterEntry();
364 const auto& pv = pvvec[t2v[gidx]];
366 if (!prop->propagateToDCA(pv, trkPV, prop->getNominalBz(), 2.0, conf.CorrType)) {
367 mTrackCounter -= gidx.getSource();
371 float cosAlp = NAN, sinAlp = NAN;
372 o2::math_utils::sincos(trkPV.getAlpha(), sinAlp, cosAlp);
374 clArr[0].setXYZ(pv.getX() * cosAlp + pv.getY() * sinAlp, -pv.getX() * sinAlp + pv.getY() * cosAlp, pv.getZ());
375 clArr[0].setSigmaY2(0.5 * (pv.getSigmaX2() + pv.getSigmaY2()));
376 clArr[0].setSigmaZ2(pv.getSigmaZ2());
377 clAlpha[0] = trkPV.getAlpha();
378 for (
int icl = 0; icl < ncl; ++icl) {
379 clArr[ncl - icl] = itsClusters[itsTrackClusRefs[clEntry + icl]];
384 trFit.resetCovariance(1'000);
386 for (
int icl = ncl; icl >= 0; --icl) {
387 if (!trFit.rotate(clAlpha[icl]) || !prop->propagateToX(trFit, clArr[icl].getX(), prop->getNominalBz(), 0.85, 2.0, conf.CorrType)) {
388 mTrackCounter -= gidx.getSource();
391 chi2 += trFit.getPredictedChi2(clArr[icl]);
392 if (!trFit.update(clArr[icl])) {
393 mTrackCounter -= gidx.getSource();
404 LOGP(info,
"Doing DCA study");
405 mTrackCounter.reset();
410 int nDCAFits{0}, nDCAFitsFail{0};
414 auto nv = vtxRefs.size() - 1;
415 auto&
stream = (*mDBGOut) <<
"dca";
416 for (
int iv = 0; iv < nv; iv++) {
417 const auto& pv = pvvec[iv];
418 const auto& vtref = vtxRefs[iv];
420 const auto dm = GTrackID::getSourceDetectorsMask(is);
425 int idMin = vtref.getFirstEntryOfSource(is), idMax = idMin + vtref.getEntriesOfSource(is);
426 for (
int i = idMin;
i < idMax;
i++) {
427 const auto vid = trackIndex[
i];
428 if (!vid.isPVContributor()) {
429 mTrackCounter &= vid.getSource();
437 const auto cdm = GTrackID::getSourceDetectorsMask(cis);
439 mTrackCounter &= cis;
442 if (!selectTrack(contributorsGID[cis], recoData)) {
443 mTrackCounter &= vid.getSource();
448 const auto& trk = recoData.
getTrackParam(contributorsGID[cis]);
451 if (conf.refitITS && cis ==
GTrackID::ITS && !refitITSPVTrack(recoData, trkRefit, contributorsGID[cis])) {
452 mTrackCounter -= cis;
455 trkRefit.invalidate();
459 if (!prop->propagateToDCABxByBz(pv, trkDCA, 2.f, conf.CorrType, &dcaInfo)) {
460 mTrackCounter -= cis;
468 <<
"trkRefit=" << trkRefit
469 <<
"trkAtPV=" << trkDCA
470 <<
"dca=" << dcaInfo;
476 const auto& eve = mcReader.
getMCEventHeader(lbl.getSourceID(), lbl.getEventID());
478 mcEve.setPos({(float)eve.GetX(), (float)eve.GetY(), (float)eve.GetZ()});
480 if (!prop->propagateToDCABxByBz(mcEve, trkC, 2.f, conf.CorrType, &dcaInfoMC)) {
481 mTrackCounter -= cis;
485 const auto& mcTrk = mcReader.
getTrack(lbl);
486 if (mcTrk ==
nullptr) {
487 LOGP(fatal,
"mcTrk is null did selection fail?");
489 stream <<
"mcTrk=" << *mcTrk
490 <<
"dca2MC=" << dcaInfoMC
496 mTrackCounter += cis;
502 LOGP(info,
"doDCAStudy: accepted {} fits, failed {} (in {:.2f} seconds)", nDCAFits, nDCAFitsFail,
sw.RealTime());
503 mTrackCounter.print();
509 LOGP(info,
"Doing DCARefit study");
510 mTrackCounter.reset();
519 auto nv = vtxRefs.size() - 1;
520 auto t2v = buildT2V(recoData);
521 std::vector<std::vector<GTrackID>> v2t;
523 auto creator = [&](
const auto& trk,
GTrackID trkID,
float _t0,
float terr) ->
bool {
524 if constexpr (!isBarrelTrack<decltype(trk)>()) {
525 mTrackCounter &= trkID.getSource();
529 mTrackCounter &= trkID.getSource();
533 if constexpr (isBarrelTrack<decltype(trk)>()) {
534 if (trk.getPt() < conf.minPt || trk.getPt() > conf.maxPt) {
535 mTrackCounter &= trkID.getSource();
538 if (std::abs(trk.getEta()) > conf.maxEta) {
539 mTrackCounter &= trkID.getSource();
542 if (!t2v.contains(trkID)) {
543 mTrackCounter &= trkID.getSource();
546 if (!selectTrack(trkID, recoData, mUseMC)) {
547 mTrackCounter &= trkID.getSource();
551 v2t[t2v[trkID]].push_back(trkID);
556 int nDCAFits{0}, nDCAFitsFail{0};
557 auto&
stream = (*mDBGOut) <<
"dcaRefit";
558 for (
size_t iv = 0; iv < nv; ++iv) {
559 const auto& pv = pvvec[iv];
560 const auto& trkIDs = v2t[iv];
561 if (trkIDs.size() - 1 < conf.minPVCont) {
564 std::vector<o2::track::TrackParCov> trks;
565 trks.reserve(trkIDs.size());
566 for (
const auto& trkID : trkIDs) {
573 std::vector<bool>
trkMask(trkIDs.size(),
true);
574 for (
size_t it{0}; it <
trkMask.size(); ++it) {
580 if (pvRefit.getChi2() < 0) {
587 auto trkC = trks[it];
588 if (!prop->propagateToDCABxByBz(pv, trkC, 2.f, conf.CorrType, &dcaInfo)) {
589 mTrackCounter -= trkIDs[it].getSource();
594 auto trkCRefit = trks[it];
595 if (!prop->propagateToDCABxByBz(pv, trkCRefit, 2.f, conf.CorrType, &dcaInfoRefit)) {
596 mTrackCounter -= trkIDs[it].getSource();
601 stream <<
"src=" << trkIDs[it].getSource()
603 <<
"trkAtPV=" << trkC
605 <<
"pvRefit=" << pvRefit
606 <<
"trkAtPVRefit=" << trkC
607 <<
"dcaRefit=" << dcaInfoRefit;
610 if (mcTrk ==
nullptr) {
611 LOGP(fatal,
"mcTrk is null did selection fail?");
613 stream <<
"mcTrk=" << *mcTrk;
617 mTrackCounter += trkIDs[it].getSource();
621 LOGP(info,
"doDCARefitStudy: accepted {} fits, failed {} (in {:.2f} seconds)", nDCAFits, nDCAFitsFail,
sw.RealTime());
622 mTrackCounter.print();
628 LOGP(info,
"Doing Pull study");
629 mTrackCounter.reset();
632 int nPulls{0}, nPullsFail{0};
636 auto checkInTrack = [&](
GTrackID trkID) {
637 if (!selectTrack(trkID, recoData)) {
638 mTrackCounter &= trkID.getSource();
648 if (conf.refitITS && trkID.getSource() ==
GTrackID::ITS && !refitITSPVTrack(recoData, trk, trkID)) {
649 mTrackCounter -= trkID.getSource();
654 std::array<float, 3> xyz{(float)mcTrk->GetStartVertexCoordinatesX(), (float)mcTrk->GetStartVertexCoordinatesY(), (float)mcTrk->GetStartVertexCoordinatesZ()},
655 pxyz{(float)mcTrk->GetStartVertexMomentumX(), (float)mcTrk->GetStartVertexMomentumY(), (float)mcTrk->GetStartVertexMomentumZ()};
656 TParticlePDG* pPDG = TDatabasePDG::Instance()->GetParticle(mcTrk->GetPdgCode());
658 mTrackCounter -= trkID.getSource();
664 if (!mcTrkO2.rotate(trk.getAlpha()) || !prop->PropagateToXBxByBz(mcTrkO2, trk.getX())) {
665 mTrackCounter -= trkID.getSource();
674 <<
"src=" << trkID.getSource()
675 <<
"itsTrk=" << itsTrk
676 <<
"mcTrk=" << mcTrkO2
677 <<
"mcPart=" << mcTrk
681 mTrackCounter += trkID.getSource();
700 LOGP(info,
"doPullStudy: accepted {} pulls; rejected {} (in {:.2f} seconds)", nPulls, nPullsFail,
sw.RealTime());
701 mTrackCounter.print();
706 LOGP(info,
"Doing MC study");
707 mTrackCounter.reset();
714 std::unordered_map<o2::MCCompLabel, ParticleInfoExt> info;
716 LOGP(info,
"** Filling particle table ... ");
717 for (
int iEve{0}; iEve < nev; ++iEve) {
718 const auto& mcTrks = mcReader.
getTracks(iSrc, iEve);
719 for (
int iTrk{0}; iTrk < mcTrks.size(); ++iTrk) {
720 const auto& mcTrk = mcTrks[iTrk];
721 const auto pdg = mcTrk.GetPdgCode();
725 const auto apdg = std::abs(pdg);
726 if (apdg != 11 && apdg != 211 && apdg != 321 && apdg != 2212) {
730 auto& part = info[lbl];
731 part.mcTrack = mcTrk;
734 LOGP(info,
"** Creating particle/clusters correspondence ... ");
737 for (
auto iCluster{0}; iCluster <
clusters.size(); ++iCluster) {
738 auto labs = clustersMCLCont->getLabels(iCluster);
739 for (
auto& lab : labs) {
740 if (!lab.isValid() || lab.getSourceID() != 0 || !lab.isCorrect()) {
743 int trackID = 0, evID = 0, srcID = 0;
745 lab.get(trackID, evID, srcID, fake);
748 auto& part = info[{trackID, evID, srcID}];
749 part.clusters |= (1 <<
layer);
751 part.fakeClusters |= (1 <<
layer);
755 LOGP(info,
"** Analysing tracks ... ");
757 if (contributorsGID[det].isIndexSet()) {
760 o2::MCCompLabel iLbl(lbl.getTrackID(), lbl.getEventID(), lbl.getSourceID());
761 if (info.contains(iLbl)) {
762 auto& part = info[iLbl];
763 SETBIT(part.recoTracks, det);
765 SETBIT(part.fakeTracks, det);
771 auto creator = [&](
const auto& trk,
GTrackID trkID,
float _t0,
float terr) ->
bool {
772 if constexpr (!isBarrelTrack<decltype(trk)>()) {
784 if (!gLbl.isValid()) {
787 o2::MCCompLabel iLbl(gLbl.getTrackID(), gLbl.getEventID(), gLbl.getSourceID());
788 if (!info.contains(iLbl)) {
791 auto& part = info[iLbl];
804 LOGP(info,
"Streaming output to tree");
805 for (
const auto& [_, part] : info) {
812 LOGP(info,
"doMCStudy: accounted {} MCParticles and {} tracks (in {:.2f} seconds)", info.size(), nTracks,
sw.RealTime());
817 std::vector<OutputSpec> outputs;
818 auto dataRequest = std::make_shared<DataRequest>();
820 dataRequest->requestTracks(srcTracks, useMC);
821 dataRequest->requestIT3Clusters(useMC);
822 dataRequest->requestClusters(srcClusters, useMC);
823 dataRequest->requestPrimaryVertices(useMC);
824 auto ggRequest = std::make_shared<o2::base::GRPGeomRequest>(
false,
834 .
name =
"its3-track-study",
835 .inputs = dataRequest->inputs,
837 .algorithm =
AlgorithmSpec{adaptFromTask<TrackingStudySpec>(dataRequest, ggRequest, srcTracks, useMC)},
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...
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)
static const ITS3TrackingStudyParam & Instance()
Static class with identifiers, bitmasks and names for ALICE detectors.
ServiceRegistryRef services()
void finaliseCCDB(ConcreteDataMatcher &matcher, void *obj) final
void run(ProcessingContext &pc) final
void endOfStream(EndOfStreamContext &ec) final
This is invoked whenever we have an EndOfStream event.
void init(InitContext &ic) final
~TrackingStudySpec() final=default
TrackingStudySpec(std::shared_ptr< DataRequest > dr, std::shared_ptr< o2::base::GRPGeomRequest > gr, GTrackID::mask_t src, bool useMC)
int getLayer(int index) const
Get chip layer, from 0.
float getSensorRefAlpha(int isn) const
static GeometryTGeo * Instance()
void fillMatrixCache(int mask) override
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)
GLenum GLuint GLint GLint layer
Defining PrimaryVertex explicitly as messageable.
void convertCompactClusters(gsl::span< const itsmft::CompClusterExt > clusters, gsl::span< const unsigned char >::iterator &pattIt, std::vector< o2::BaseCluster< float > > &output, const its3::TopologyDictionary *dict)
convert compact clusters to 3D spacepoints
std::unordered_map< GTrackID, size_t > T2VMap
o2::framework::DataProcessorSpec getTrackingStudySpec(o2::dataformats::GlobalTrackID::mask_t srcTracks, o2::dataformats::GlobalTrackID::mask_t srcClus, bool useMC)
o2::dataformats::GlobalTrackID GTrackID
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
GlobalIDSet getSingleDetectorRefs(GTrackID gidx) const
const o2::tpc::TrackTPC & getTPCTrack(GTrackID id) const
auto getITSClustersMCLabels() 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
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 getITSTracksROFRecords() const
auto getITSTPCTRDTOFMatches() const
std::array< GTrackID, GTrackID::NSources > GlobalIDSet
auto getITSClusters() const
LOG(info)<< "Compressed in "<< sw.CpuTime()<< " s"
std::vector< Cluster > clusters