Skip to content

Commit a1b7faf

Browse files
committed
TRD: correction for pile-up
1 parent 74098a4 commit a1b7faf

File tree

11 files changed

+370
-15
lines changed

11 files changed

+370
-15
lines changed

Detectors/TRD/qc/include/TRDQC/Tracking.h

Lines changed: 19 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@
2323
#include "DataFormatsTRD/Constants.h"
2424
#include "ReconstructionDataFormats/TrackTPCITS.h"
2525
#include "ReconstructionDataFormats/GlobalTrackID.h"
26+
#include "DataFormatsTRD/TrackTriggerRecord.h"
2627
#include "DataFormatsTPC/TrackTPC.h"
2728
#include "DetectorsBase/Propagator.h"
2829
#include "GPUTRDRecoParam.h"
@@ -102,6 +103,10 @@ class Tracking
102103
{
103104
mLocalGain = localGain;
104105
}
106+
107+
// quantities necessary for pile-up correction
108+
void setTriggeredBCFT0(std::vector<int> t) { mTriggeredBCFT0 = t; }
109+
void setFirstOrbit(uint32_t o) { mFirstOrbit = o; }
105110

106111
private:
107112
float mMaxSnp{o2::base::Propagator::MAX_SIN_PHI}; ///< max snp when propagating tracks
@@ -115,12 +120,20 @@ class Tracking
115120
std::vector<TrackQC> mTrackQC;
116121

117122
// input from DPL
118-
gsl::span<const o2::dataformats::TrackTPCITS> mTracksITSTPC; ///< ITS-TPC seeding tracks
119-
gsl::span<const o2::tpc::TrackTPC> mTracksTPC; ///< TPC seeding tracks
120-
gsl::span<const TrackTRD> mTracksITSTPCTRD; ///< TRD tracks reconstructed from TPC or ITS-TPC seeds
121-
gsl::span<const TrackTRD> mTracksTPCTRD; ///< TRD tracks reconstructed from TPC or TPC seeds
122-
gsl::span<const Tracklet64> mTrackletsRaw; ///< array of raw tracklets needed for TRD refit
123-
gsl::span<const CalibratedTracklet> mTrackletsCalib; ///< array of calibrated tracklets needed for TRD refit
123+
gsl::span<const o2::dataformats::TrackTPCITS> mTracksITSTPC; ///< ITS-TPC seeding tracks
124+
gsl::span<const o2::tpc::TrackTPC> mTracksTPC; ///< TPC seeding tracks
125+
gsl::span<const TrackTRD> mTracksITSTPCTRD; ///< TRD tracks reconstructed from TPC or ITS-TPC seeds
126+
gsl::span<const TrackTRD> mTracksTPCTRD; ///< TRD tracks reconstructed from TPC or TPC seeds
127+
gsl::span<const TrackTriggerRecord> mTrackTriggerRecordsITSTPCTRD; ///< TRD tracks reconstructed from TPC or ITS-TPC seeds
128+
gsl::span<const TrackTriggerRecord> mTrackTriggerRecordsTPCTRD; ///< TRD tracks reconstructed from TPC or TPC seeds
129+
gsl::span<const Tracklet64> mTrackletsRaw; ///< array of raw tracklets needed for TRD refit
130+
gsl::span<const CalibratedTracklet> mTrackletsCalib; ///< array of calibrated tracklets needed for TRD refit
131+
132+
// quantities necessary for pile-up correction
133+
std::vector<int> mTriggeredBCFT0; ///< array with the FT0 trigger times
134+
int mCurrentTriggerRecord;
135+
uint32_t mFirstOrbit;
136+
int mCurrentTrackId;
124137

125138
// corrections from ccdb, some need to be loaded only once hence an init flag
126139
o2::trd::LocalGainFactor mLocalGain; ///< local gain factors from krypton calibration

Detectors/TRD/qc/src/Tracking.cxx

Lines changed: 70 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -37,15 +37,23 @@ void Tracking::setInput(const o2::globaltracking::RecoContainer& input)
3737
mTracksTPCTRD = input.getTPCTRDTracks<TrackTRD>();
3838
mTrackletsRaw = input.getTRDTracklets();
3939
mTrackletsCalib = input.getTRDCalibratedTracklets();
40+
mTrackTriggerRecordsITSTPCTRD = input.getITSTPCTRDTriggers();
41+
mTrackTriggerRecordsTPCTRD = input.getTPCTRDTriggers();
4042
}
4143

4244
void Tracking::run()
4345
{
46+
mCurrentTriggerRecord = 0;
47+
mCurrentTrackId = 0;
4448
for (const auto& trkTrd : mTracksTPCTRD) {
4549
checkTrack(trkTrd, true);
50+
mCurrentTrackId++;
4651
}
52+
mCurrentTriggerRecord = 0;
53+
mCurrentTrackId = 0;
4754
for (const auto& trkTrd : mTracksITSTPCTRD) {
4855
checkTrack(trkTrd, false);
56+
mCurrentTrackId++;
4957
}
5058
}
5159

@@ -64,6 +72,60 @@ void Tracking::checkTrack(const TrackTRD& trkTrd, bool isTPCTRD)
6472
if (mPID) {
6573
qcStruct.dEdxTotTPC = isTPCTRD ? mTracksTPC[id].getdEdx().dEdxTotTPC : mTracksTPC[mTracksITSTPC[id].getRefTPC()].getdEdx().dEdxTotTPC;
6674
}
75+
76+
// find corresponding track trigger record to get track timing
77+
int triggeredBC = 0;
78+
for (; mCurrentTriggerRecord < (isTPCTRD ? mTrackTriggerRecordsTPCTRD.size() : mTrackTriggerRecordsITSTPCTRD.size()); mCurrentTriggerRecord++) {
79+
auto& tRecord = (isTPCTRD ? mTrackTriggerRecordsTPCTRD[mCurrentTriggerRecord] : mTrackTriggerRecordsITSTPCTRD[mCurrentTriggerRecord]);
80+
if (mCurrentTrackId >= tRecord.getFirstTrack() && mCurrentTrackId < tRecord.getFirstTrack() + tRecord.getNumberOfTracks()) {
81+
uint32_t currentOrbit = tRecord.getBCData().orbit;
82+
triggeredBC = tRecord.getBCData().bc + (currentOrbit - mFirstOrbit) * o2::constants::lhc::LHCMaxBunches;
83+
break;
84+
}
85+
}
86+
87+
// Find most probable BCs and RMS for pile-up correction and error. Same BC is assumed for all tracklets
88+
float tCorrPileUp = 0.;
89+
float tErrPileUp2 = 0;
90+
float maxProb = 0.f;
91+
// The uncertainty is the RMS wrt the default correction of all possible corrections weighted by their probability
92+
float sumCorr = 0.f;
93+
float sumCorr2 = 0.f;
94+
float sumProb = 0.f;
95+
for (int iBC = 0; iBC < mTriggeredBCFT0.size(); iBC++) {
96+
int deltaBC = roundf(mTriggeredBCFT0[iBC] - triggeredBC);
97+
if (deltaBC <= mRecoParam.getPileUpRangeBefore()) {
98+
continue;
99+
}
100+
if (deltaBC >= mRecoParam.getPileUpRangeAfter()) {
101+
break;
102+
}
103+
// collect the charges
104+
std::array<int, 6> q0;
105+
std::array<int, 6> q1;
106+
for (int iLy = 0; iLy < NLAYER; iLy++) {
107+
int trkltId = trkTrd.getTrackletIndex(iLy);
108+
if (trkltId < 0) {
109+
q0[iLy] = -1;
110+
q1[iLy] = -1;
111+
}
112+
else {
113+
q0[iLy] = mTrackletsRaw[trkltId].getQ0();
114+
q1[iLy] = mTrackletsRaw[trkltId].getQ1();
115+
}
116+
}
117+
// get pile-up probability
118+
float probBC = mRecoParam.getPileUpProbTrack(deltaBC, q0, q1);
119+
sumCorr += probBC * deltaBC;
120+
sumCorr2 += probBC * deltaBC * deltaBC;
121+
sumProb += probBC;
122+
if (probBC > maxProb) {
123+
maxProb = probBC;
124+
tCorrPileUp = - deltaBC;
125+
}
126+
}
127+
if (sumProb > 1e-6) tErrPileUp2 = sumCorr2 / sumProb - 2 * tCorrPileUp * sumCorr / sumProb + tCorrPileUp * tCorrPileUp;
128+
67129

68130
for (int iLayer = 0; iLayer < NLAYER; ++iLayer) {
69131
int trkltId = trkTrd.getTrackletIndex(iLayer);
@@ -93,9 +155,16 @@ void Tracking::checkTrack(const TrackTRD& trkTrd, bool isTPCTRD)
93155
if (!((trk.getSigmaZ2() < (padLength * padLength / 12.f)) && (std::fabs(mTrackletsCalib[trkltId].getZ() - trk.getZ()) < padLength))) {
94156
tiltCorrUp = 0.f;
95157
}
96-
std::array<float, 2> trkltPosUp{mTrackletsCalib[trkltId].getY() - tiltCorrUp, zPosCorrUp};
158+
159+
// conversion from slope in pad per time bin to slope in cm per BC = tracklets[trkltIdx].getSlopeFloat() * padWidth / BCperTimeBin
160+
float slopeFactor = mTrackletsRaw[trkltId].getSlopeFloat() * pad->getWidthIPad() / 4.f;
161+
float yCorrPileUp = tCorrPileUp * slopeFactor;
162+
float yAddErrPileUp2 = tErrPileUp2 * slopeFactor * slopeFactor;
163+
164+
std::array<float, 2> trkltPosUp{mTrackletsCalib[trkltId].getY() - tiltCorrUp + yCorrPileUp, zPosCorrUp};
97165
std::array<float, 3> trkltCovUp;
98166
mRecoParam.recalcTrkltCov(tilt, trk.getSnp(), pad->getRowSize(tracklet.getPadRow()), trkltCovUp);
167+
trkltCovUp[0] += yAddErrPileUp2;
99168
auto chi2trklt = trk.getPredictedChi2(trkltPosUp, trkltCovUp);
100169

101170
qcStruct.trackProp[iLayer] = trk;

Detectors/TRD/workflow/include/TRDWorkflow/TRDGlobalTrackingQCSpec.h

Lines changed: 22 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,8 @@
3030
#include "DataFormatsParameters/GRPObject.h"
3131
#include "ReconstructionDataFormats/GlobalTrackID.h"
3232
#include "DataFormatsGlobalTracking/RecoContainer.h"
33+
#include "DataFormatsFT0/RecPoints.h"
34+
#include "FT0Reconstruction/InteractionTag.h"
3335
#include "TRDQC/Tracking.h"
3436
#include <cstring>
3537

@@ -47,7 +49,7 @@ namespace trd
4749
class TRDGlobalTrackingQC : public Task
4850
{
4951
public:
50-
TRDGlobalTrackingQC(std::shared_ptr<DataRequest> dr, std::shared_ptr<o2::base::GRPGeomRequest> gr, bool tpcAvailable) : mDataRequest(dr), mGGCCDBRequest(gr), mTPCavailable(tpcAvailable) {}
52+
TRDGlobalTrackingQC(std::shared_ptr<DataRequest> dr, std::shared_ptr<o2::base::GRPGeomRequest> gr, bool tpcAvailable, o2::dataformats::GlobalTrackID::mask_t src) : mDataRequest(dr), mGGCCDBRequest(gr), mTPCavailable(tpcAvailable), mTrkMask(src) {}
5153
~TRDGlobalTrackingQC() override = default;
5254
void init(InitContext& ic) final
5355
{
@@ -67,6 +69,23 @@ class TRDGlobalTrackingQC : public Task
6769
updateTimeDependentParams(pc); // Make sure this is called after recoData.collectData, which may load some conditions
6870
mQC.reset();
6971
mQC.setInput(recoData);
72+
std::vector<int> triggeredBCFT0;
73+
if (mTrkMask[GTrackID::FT0]) { // pile-up tagging was requested
74+
auto ft0recPoints = recoData.getFT0RecPoints();
75+
uint32_t firstOrbit = 0;
76+
for (size_t ft0id = 0; ft0id < ft0recPoints.size(); ft0id++) {
77+
const auto& f0rec = ft0recPoints[ft0id];
78+
if (ft0id == 0) {
79+
firstOrbit = f0rec.getInteractionRecord().orbit;
80+
mQC.setFirstOrbit(firstOrbit);
81+
}
82+
if (o2::ft0::InteractionTag::Instance().isSelected(f0rec)) {
83+
uint32_t currentOrbit = f0rec.getInteractionRecord().orbit;
84+
triggeredBCFT0.push_back(f0rec.getInteractionRecord().bc + (currentOrbit - firstOrbit) * o2::constants::lhc::LHCMaxBunches);
85+
}
86+
}
87+
}
88+
mQC.setTriggeredBCFT0(triggeredBCFT0);
7089
mQC.run();
7190
pc.outputs().snapshot(Output{"TRD", "TRACKINGQC", 0}, mQC.getTrackQC());
7291
}
@@ -94,6 +113,7 @@ class TRDGlobalTrackingQC : public Task
94113
}
95114
}
96115

116+
o2::dataformats::GlobalTrackID::mask_t mTrkMask; ///< seeding track sources (TPC, ITS-TPC)
97117
std::shared_ptr<DataRequest> mDataRequest;
98118
std::shared_ptr<o2::base::GRPGeomRequest> mGGCCDBRequest;
99119
bool mTPCavailable{false};
@@ -133,7 +153,7 @@ DataProcessorSpec getTRDGlobalTrackingQCSpec(o2::dataformats::GlobalTrackID::mas
133153
"trd-tracking-qc",
134154
dataRequest->inputs,
135155
outputs,
136-
AlgorithmSpec{adaptFromTask<TRDGlobalTrackingQC>(dataRequest, ggRequest, isTPCavailable)},
156+
AlgorithmSpec{adaptFromTask<TRDGlobalTrackingQC>(dataRequest, ggRequest, isTPCavailable, src)},
137157
Options{}};
138158
}
139159

Detectors/TRD/workflow/include/TRDWorkflow/TRDGlobalTrackingSpec.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -109,6 +109,7 @@ class TRDGlobalTracking : public o2::framework::Task
109109
#endif
110110
std::array<float, 5> mCovDiagInner{}; ///< total cov.matrix extra diagonal error from TrackTuneParams
111111
std::array<float, 5> mCovDiagOuter{}; ///< total cov.matrix extra diagonal error from TrackTuneParams
112+
std::vector<int> mTriggeredBCFT0; ///< array with the FT0 trigger times
112113
// PID
113114
PIDPolicy mPolicy{PIDPolicy::DEFAULT}; ///< Model to load an evaluate
114115
std::unique_ptr<PIDBase> mBase; ///< PID engine

Detectors/TRD/workflow/src/TRDGlobalTrackingSpec.cxx

Lines changed: 64 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -414,6 +414,23 @@ void TRDGlobalTracking::run(ProcessingContext& pc)
414414
LOGF(debug, "Loaded TPC track %i with time %f. Window from %f to %f", nTracksLoadedTPC, trkAttribs.mTime, trkAttribs.mTime - trkAttribs.mTimeSubMax, trkAttribs.mTime + trkAttribs.mTimeAddMax);
415415
}
416416
LOGF(info, "%i tracks are loaded into the TRD tracker. Out of those %i ITS-TPC tracks and %i TPC tracks", nTracksLoadedITSTPC + nTracksLoadedTPC, nTracksLoadedITSTPC, nTracksLoadedTPC);
417+
418+
// Load the FT0 triggered BCs if this is requested
419+
420+
if (mTrkMask[GTrackID::FT0]) { // pile-up tagging was requested
421+
auto ft0recPoints = inputTracks.getFT0RecPoints();
422+
uint32_t firstOrbit = 0;
423+
for (size_t ft0id = 0; ft0id < ft0recPoints.size(); ft0id++) {
424+
const auto& f0rec = ft0recPoints[ft0id];
425+
if (ft0id == 0) firstOrbit = f0rec.getInteractionRecord().orbit;
426+
if (o2::ft0::InteractionTag::Instance().isSelected(f0rec)) {
427+
uint32_t currentOrbit = f0rec.getInteractionRecord().orbit;
428+
mTriggeredBCFT0.push_back(f0rec.getInteractionRecord().bc + (currentOrbit - firstOrbit) * o2::constants::lhc::LHCMaxBunches);
429+
}
430+
}
431+
}
432+
433+
mTracker->SetFT0TriggeredBC(mTriggeredBCFT0.data(), mTriggeredBCFT0.size());
417434

418435
// start the tracking
419436
// mTracker->DumpTracks();
@@ -796,6 +813,46 @@ bool TRDGlobalTracking::refitTRDTrack(TrackTRD& trk, float& chi2, bool inwards,
796813
}
797814
}
798815
}
816+
817+
// Find most probable BCs and RMS for pile-up correction and error. Same BC is assumed for all tracklets
818+
float tCorrPileUp = 0.;
819+
float tErrPileUp2 = 0;
820+
float maxProb = 0.f;
821+
// The uncertainty is the RMS wrt the default correction of all possible corrections weighted by their probability
822+
float sumCorr = 0.f;
823+
float sumCorr2 = 0.f;
824+
float sumProb = 0.f;
825+
for (int iBC = 0; iBC < mTriggeredBCFT0.size(); iBC++) {
826+
int deltaBC = roundf(mTriggeredBCFT0[iBC] - mChainTracking->mIOPtrs.trdTriggerTimes[trk.getCollisionId()] / o2::constants::lhc::LHCBunchSpacingMUS);
827+
if (deltaBC <= mRecoParam.getPileUpRangeBefore() || deltaBC >= mRecoParam.getPileUpRangeAfter()) {
828+
continue;
829+
}
830+
// collect the charges
831+
std::array<int, 6> q0;
832+
std::array<int, 6> q1;
833+
for (int iLy = 0; iLy < NLAYER; iLy++) {
834+
int trkltId = trk.getTrackletIndex(iLy);
835+
if (trkltId < 0) {
836+
q0[iLy] = -1;
837+
q1[iLy] = -1;
838+
}
839+
else {
840+
q0[iLy] = mTrackletsRaw[trkltId].getQ0();
841+
q1[iLy] = mTrackletsRaw[trkltId].getQ1();
842+
}
843+
}
844+
// get pile-up probability
845+
float probBC = mRecoParam.getPileUpProbTrack(deltaBC, q0, q1);
846+
sumCorr += probBC * deltaBC;
847+
sumCorr2 += probBC * deltaBC * deltaBC;
848+
sumProb += probBC;
849+
if (probBC > maxProb) {
850+
maxProb = probBC;
851+
tCorrPileUp = - deltaBC;
852+
}
853+
}
854+
if (sumProb > 1e-6) tErrPileUp2 = sumCorr2 / sumProb - 2 * tCorrPileUp * sumCorr / sumProb + tCorrPileUp * tCorrPileUp;
855+
799856

800857
if (inwards) {
801858
// reset covariance to something big for inwards refit
@@ -826,10 +883,16 @@ bool TRDGlobalTracking::refitTRDTrack(TrackTRD& trk, float& chi2, bool inwards,
826883
if (!((trkParam->getSigmaZ2() < (padLength * padLength / 12.f)) && (std::fabs(mTrackletsCalib[trkltId].getZ() - trkParam->getZ()) < padLength))) {
827884
tiltCorrUp = 0.f;
828885
}
886+
887+
// conversion from slope in pad per time bin to slope in cm per BC = tracklets[trkltIdx].getSlopeFloat() * padWidth / BCperTimeBin
888+
float slopeFactor = mTrackletsRaw[trkltId].getSlopeFloat() * pad->getWidthIPad() / 4.f;
889+
float yCorrPileUp = tCorrPileUp * slopeFactor;
890+
float yAddErrPileUp2 = tErrPileUp2 * slopeFactor * slopeFactor;
829891

830-
std::array<float, 2> trkltPosUp{mTrackletsCalib[trkltId].getY() - tiltCorrUp, zPosCorrUp};
892+
std::array<float, 2> trkltPosUp{mTrackletsCalib[trkltId].getY() - tiltCorrUp + yCorrPileUp, zPosCorrUp};
831893
std::array<float, 3> trkltCovUp;
832894
mRecoParam.recalcTrkltCov(tilt, trkParam->getSnp(), pad->getRowSize(mTrackletsRaw[trkltId].getPadRow()), trkltCovUp);
895+
trkltCovUp[0] += yAddErrPileUp2;
833896

834897
chi2 += trkParam->getPredictedChi2(trkltPosUp, trkltCovUp);
835898
if (!trkParam->update(trkltPosUp, trkltCovUp)) {

GPU/GPUTracking/DataTypes/GPUTRDRecoParam.cxx

Lines changed: 68 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -77,3 +77,71 @@ void GPUTRDRecoParam::recalcTrkltCov(const float tilt, const float snp, const fl
7777
cov[1] = c2 * tilt * (sz2 - sy2);
7878
cov[2] = c2 * (t2 * sy2 + sz2);
7979
}
80+
81+
82+
float GPUTRDRecoParam::getPileUpProbTracklet(int nBC, int Q0, int Q1) const
83+
{
84+
// get the probability that the tracklet with charges Q0 and Q1 belongs to a given BC, with a (signed) distance nBC from the TRD-triggered BC
85+
// parametrization depends on whether charges are 0 or not
86+
int maxBC = mPileUpRangeAfter;
87+
int minBC = mPileUpRangeBefore;
88+
int maxProbBC = mPileUpMaxProb;
89+
if (Q0 > 0 && Q1 > 0) {
90+
maxBC = mPileUpRangeAfter11;
91+
minBC = mPileUpRangeBefore11;
92+
maxProbBC = mPileUpMaxProb11;
93+
}
94+
if (Q0 == 0 && Q1 > 0) {
95+
maxBC = mPileUpRangeAfter01;
96+
minBC = mPileUpRangeBefore01;
97+
maxProbBC = mPileUpMaxProb01;
98+
}
99+
if (Q0 > 0 && Q1 == 0) {
100+
maxBC = mPileUpRangeAfter10;
101+
minBC = mPileUpRangeBefore10;
102+
maxProbBC = mPileUpMaxProb10;
103+
}
104+
if (Q0 == 0 && Q1 == 0) {
105+
maxBC = mPileUpRangeAfter00;
106+
minBC = mPileUpRangeBefore00;
107+
maxProbBC = mPileUpMaxProb00;
108+
}
109+
110+
// prob is 0 if the BC is too far, maximal for a given nBC, and with two linear functions in between. The maximum is chosen so that the integral is 1.
111+
if (nBC <= minBC || nBC >= maxBC)
112+
return 0.;
113+
float maxProb = 2./(maxBC - minBC);
114+
if (nBC > minBC && nBC <= maxProbBC)
115+
return maxProb / (maxProbBC - minBC) * (nBC - minBC);
116+
else
117+
return maxProb / (maxProbBC - maxBC) * (nBC - maxBC);
118+
}
119+
120+
float GPUTRDRecoParam::getPileUpProbTrack(int nBC, std::array<int, 6> Q0, std::array<int, 6> Q1) const
121+
{
122+
// get the probability that the track belongs to a given BC, with a (signed) distance nBC from the TRD-triggered BC
123+
// it depends on the individual probabilities for every of its tracklets.
124+
//
125+
// If P(BC|L0,L1,...) is the probability that the track belongs to a given BC, given the information on the tracklet charges in L0,L1, ...
126+
// P(BC|L0,L1,...) proportional to P(BC)*P(L0,L1,...|BC), prop to P(BC)*P(L0|BC)*P(L1|BC)*... since for a given track and BC, charge in different layers are independent
127+
// prop to P(BC) * P(BC|L0)/P(BC) * P(BC|L1)/P(BC) * ...
128+
//
129+
// P(BC) is the probability with no charge information: we start from this probability, and each tracklet adds new information on pileup probability
130+
131+
132+
// basic probability, if we had no info on the charges
133+
float probNoInfo = GPUTRDRecoParam::getPileUpProbTracklet(nBC, -1, -1);
134+
135+
float probTrack = probNoInfo;
136+
if (probNoInfo < 1e-6f) return 0.;
137+
138+
// For each tracklet, we add the info on its charge
139+
for (int i = 0; i < 6; i++) {
140+
// negative charge values if the tracklet is not present
141+
if (Q0[i] < 0 || Q1[i] < 0) continue;
142+
float probTracklet = GPUTRDRecoParam::getPileUpProbTracklet(nBC, Q0[i], Q1[i]);
143+
probTrack *= probTracklet / probNoInfo;
144+
}
145+
146+
return probTrack;
147+
}

0 commit comments

Comments
 (0)