Skip to content

Commit 3624dcc

Browse files
committed
Add PV-related rejections to cosmic matcher for interleaved mode
1 parent f3cc959 commit 3624dcc

8 files changed

Lines changed: 123 additions & 19 deletions

File tree

DataFormats/Reconstruction/include/ReconstructionDataFormats/DCA.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -54,13 +54,16 @@ class DCA
5454
mZ = z;
5555
}
5656

57+
GPUd() void setY(float y) { mY = y; }
58+
GPUd() void setZ(float z) { mZ = z; }
5759
GPUd() auto getY() const { return mY; }
5860
GPUd() auto getZ() const { return mZ; }
5961
GPUd() auto getR2() const { return mY * mY + mZ * mZ; }
6062
GPUd() auto getSigmaY2() const { return mCov[0]; }
6163
GPUd() auto getSigmaYZ() const { return mCov[1]; }
6264
GPUd() auto getSigmaZ2() const { return mCov[2]; }
6365
GPUd() const auto& getCovariance() const { return mCov; }
66+
GPUd() float calcChi2() const;
6467

6568
void print() const;
6669

DataFormats/Reconstruction/src/DCA.cxx

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,8 @@
99
// granted to it by virtue of its status as an Intergovernmental Organization
1010
// or submit itself to any jurisdiction.
1111

12+
#include "GPUCommonMath.h"
13+
#include "CommonConstants/MathConstants.h"
1214
#include "ReconstructionDataFormats/DCA.h"
1315
#include <iostream>
1416

@@ -20,6 +22,16 @@ namespace o2
2022
namespace dataformats
2123
{
2224

25+
float DCA::calcChi2() const
26+
{
27+
// Estimate the chi2 for DCA
28+
const auto sdd = mCov[0], sdz = mCov[1], szz = mCov[2], det = sdd * szz - sdz * sdz;
29+
if (o2::gpu::CAMath::Abs(det) < o2::constants::math::Almost0) {
30+
return constants::math::VeryBig;
31+
}
32+
return (mY * (szz * mY - sdz * mZ) + mZ * (sdd * mZ - mY * sdz)) / det;
33+
}
34+
2335
std::ostream& operator<<(std::ostream& os, const o2::dataformats::DCA& d)
2436
{
2537
// stream itself

Detectors/GlobalTracking/include/GlobalTracking/MatchCosmics.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -83,13 +83,16 @@ class MatchCosmics
8383
TBracket tBracket; ///< bracketing time-bins
8484
GTrackID origID; ///< track origin id
8585
int matchID = MinusOne; ///< entry (none if MinusOne) of its match in the vector of matches
86+
short vtIDMin = -1; ///< id of the 1st compatible vertex
87+
short vtIDMax = -1; ///< id of the last compatible vertex
8688
};
8789
void setTPCCorrMaps(const o2::gpu::TPCFastTransformPOD* maph);
8890
void setTPCVDrift(const o2::tpc::VDriftCorrFact& v);
8991
void setITSROFrameLengthMUS(float fums) { mITSROFrameLengthMUS = fums; }
9092
void setITSDict(const o2::itsmft::TopologyDictionary* dict) { mITSDict = dict; }
9193
void process(const o2::globaltracking::RecoContainer& data);
9294
void setUseMC(bool mc) { mUseMC = mc; }
95+
void setUsePVInfo(bool v) { mUsePVInfo = v; }
9396
void init();
9497
void end();
9598

@@ -146,6 +149,7 @@ class MatchCosmics
146149
float mTPCTBinMUS = 0.; ///< TPC time bin duration in microseconds
147150
float mBz = 0; ///< nominal Bz
148151
bool mFieldON = true;
152+
bool mUsePVInfo = false;
149153
bool mUseMC = true;
150154
float mITSROFrameLengthMUS = 0.;
151155
float mQ2PtCutoff = 1e9;

Detectors/GlobalTracking/include/GlobalTracking/MatchCosmicsParams.h

Lines changed: 12 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -17,22 +17,28 @@
1717
#include "CommonUtils/ConfigurableParam.h"
1818
#include "CommonUtils/ConfigurableParamHelper.h"
1919
#include "DetectorsBase/Propagator.h"
20+
#include "ReconstructionDataFormats/GlobalTrackID.h"
2021

2122
namespace o2
2223
{
2324
namespace globaltracking
2425
{
2526

2627
struct MatchCosmicsParams : public o2::conf::ConfigurableParamHelper<MatchCosmicsParams> {
28+
float dcaCutChi2[o2::dataformats::GlobalTrackID::NSources] = {}; // optional (>0) chi2 cut on track DCA to any of its compatible vertices
2729
float systSigma2[o2::track::kNParams] = {0.01f, 0.01f, 1e-4f, 1e-4f, 0.f}; // extra error to be added at legs comparison
2830
float crudeNSigma2Cut[o2::track::kNParams] = {49.f, 49.f, 49.f, 49.f, 49.f};
29-
float crudeChi2Cut = 999.;
30-
float timeToleranceMUS = 0.;
31-
float maxStep = 10.;
32-
float maxSnp = 0.99;
33-
float minSeedPt = 0.10; // use only tracks above this pT (scaled with field)
34-
float nSigmaTError = 4.; // number of sigmas on track time error for matching (except for TPC which provides an interval)
31+
float crudeChi2Cut = 999.f;
32+
float timeToleranceMUS = 0.f;
33+
float maxStep = 10.f;
34+
float maxSnp = 0.99f;
35+
float minSeedPt = 0.10f; // use only tracks above this pT (scaled with field)
36+
float nSigmaTError = 4.f; // number of sigmas on track time error for matching (except for TPC which provides an interval)
37+
float tpcExtraZError2 = 1.f; // extra error^2 on the TPC-only track Z coordinate
38+
float fiducialRIP = 1.0f; // consider track having |Y@x=0|< this as passing DCA cut (if requested)
39+
float fiducialZIP = 20.f; // consider track having |Z@x=0|< this as passing DCA cut (if requested)
3540
bool allowTPCOnly = true;
41+
bool discardPVContributors = true; // used only if the global option --use-pv-info is requested
3642
o2::base::Propagator::MatCorrType matCorr = o2::base::Propagator::MatCorrType::USEMatCorrLUT;
3743

3844
O2ParamDef(MatchCosmicsParams, "cosmicsMatch");

Detectors/GlobalTracking/src/MatchCosmics.cxx

Lines changed: 76 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,9 @@
2323
#include "ReconstructionDataFormats/TrackTPCITS.h"
2424
#include "ReconstructionDataFormats/TrackTPCTOF.h"
2525
#include "ReconstructionDataFormats/MatchInfoTOF.h"
26+
#include "ReconstructionDataFormats/PrimaryVertex.h"
27+
#include "ReconstructionDataFormats/VtxTrackRef.h"
28+
#include "ReconstructionDataFormats/DCA.h"
2629
#include "ITStracking/IOUtils.h"
2730
#include "ITSBase/GeometryTGeo.h"
2831
#include "TPCBase/ParameterElectronics.h"
@@ -35,6 +38,7 @@
3538
#include "TPCFastTransformPOD.h"
3639
#include <algorithm>
3740
#include <numeric>
41+
#include <unordered_map>
3842

3943
using namespace o2::globaltracking;
4044

@@ -52,21 +56,53 @@ void MatchCosmics::process(const o2::globaltracking::RecoContainer& data)
5256

5357
createSeeds(data);
5458
int ntr = mSeeds.size();
55-
59+
const auto prop = o2::base::Propagator::Instance();
5660
// propagate to DCA to origin
5761
const o2::math_utils::Point3D<float> v{0., 0., 0};
5862
for (int i = 0; i < ntr; i++) {
5963
auto& trc = mSeeds[i];
60-
if (!o2::base::Propagator::Instance()->propagateToDCABxByBz(v, trc, mMatchParams->maxStep, mMatchParams->matCorr)) {
61-
trc.matchID = Reject; // reject track
64+
if (!trc.matchID == Reject) {
65+
if (!prop->propagateToDCABxByBz(v, trc, mMatchParams->maxStep, mMatchParams->matCorr)) {
66+
trc.matchID = Reject; // reject track
67+
continue;
68+
}
69+
if (mMatchParams->dcaCutChi2[trc.origID.getSource()] > 0.f && mUsePVInfo && (std::abs(trc.getY()) < mMatchParams->fiducialRIP && std::abs(trc.getZ()) < mMatchParams->fiducialZIP)) {
70+
// do the propagation only if we are in the fiducial IP range.
71+
for (int iv = trc.vtIDMin; iv < trc.vtIDMax; iv++) {
72+
const auto& pv = data.getPrimaryVertex(iv);
73+
o2::track::TrackParCov trcatPV(trc);
74+
o2::dataformats::DCA dca;
75+
if (!trcatPV.propagateToDCA(pv, mBz, &dca)) {
76+
trc.matchID = Reject;
77+
break;
78+
}
79+
if (trc.origID.getSource() == GTrackID::TPC) { // correct the track Z position for the vertex time
80+
const auto& trcTPC = data.getTPCTrack(trc.origID.getSource());
81+
float deltaZ = trcTPC.hasBothSidesClusters() ? 0.f : (pv.getTimeStamp().getTimeStamp() - trcTPC.getTime0() * 8 * o2::constants::lhc::LHCBunchSpacingMUS) * mTPCVDrift;
82+
dca.setZ(dca.getZ() + (trcTPC.hasASideClustersOnly() ? deltaZ : -deltaZ));
83+
}
84+
if (dca.calcChi2() < mMatchParams->dcaCutChi2[trc.origID.getSource()]) {
85+
trc.matchID = Reject;
86+
break;
87+
}
88+
}
89+
}
6290
}
6391
}
6492

65-
// sort in time bracket lower edge
93+
// sort in time bracket lower edge, putting rejected tracks in the end
6694
std::vector<int> sortID(ntr);
6795
std::iota(sortID.begin(), sortID.end(), 0);
68-
std::sort(sortID.begin(), sortID.end(), [this](int a, int b) { return mSeeds[a].tBracket.getMin() < mSeeds[b].tBracket.getMin(); });
69-
96+
std::sort(sortID.begin(), sortID.end(), [this](int a, int b) { return (mSeeds[a].matchID != Reject) && (mSeeds[a].tBracket.getMin() < mSeeds[b].tBracket.getMin()); });
97+
int lastValid = ntr - 1;
98+
for (; lastValid >= 0; lastValid--) {
99+
if (mSeeds[sortID[lastValid]].matchID != Reject) {
100+
break;
101+
}
102+
}
103+
ntr = lastValid >= 0 ? lastValid + 1 : 0;
104+
LOGP(info, "Collected {} seeds, validated: {}", mSeeds.size(), ntr);
105+
sortID.resize(ntr);
70106
for (int i = 0; i < ntr; i++) {
71107
for (int j = i + 1; j < ntr; j++) {
72108
if (checkPair(sortID[i], sortID[j]) == RejTime) {
@@ -424,6 +460,8 @@ MatchCosmics::RejFlag MatchCosmics::checkPair(int i, int j)
424460
break;
425461
}
426462
bool ignoreZ = seed0.origID.getSource() == o2d::GlobalTrackID::TPC || seed1.origID.getSource() == o2d::GlobalTrackID::TPC;
463+
// RSTODO this is simplification: one should constraint the TPC-only track Z by the time of other candidate (at least their difference of both tracks are TPC only).
464+
// If the shift is large, eventually the tracks need to be refitted.
427465
if (!ignoreZ) { // cut on Z makes no sense for TPC only tracks
428466
auto dZ = seed0.getZ() - seed1Inv.getZ();
429467
if (dZ * dZ > (seed0.getSigmaZ2() + seed1Inv.getSigmaZ2()) * mMatchParams->crudeNSigma2Cut[o2::track::kZ]) {
@@ -492,8 +530,9 @@ void MatchCosmics::createSeeds(const o2::globaltracking::RecoContainer& data)
492530
// Scan all inputs and create seeding tracks
493531

494532
mSeeds.clear();
533+
std::unordered_map<GTrackID, int> trackEntry;
495534

496-
auto creator = [this](auto& _tr, GTrackID _origID, float t0, float terr) {
535+
auto creator = [this, &trackEntry](auto& _tr, GTrackID _origID, float t0, float terr) {
497536
if constexpr (std::is_base_of_v<o2::track::TrackParCov, std::decay_t<decltype(_tr)>>) {
498537
if (std::abs(_tr.getQ2Pt()) > this->mQ2PtCutoff) {
499538
return true;
@@ -512,7 +551,11 @@ void MatchCosmics::createSeeds(const o2::globaltracking::RecoContainer& data)
512551
terr *= this->mMatchParams->nSigmaTError;
513552
}
514553
terr += this->mMatchParams->timeToleranceMUS;
554+
trackEntry[_origID] = mSeeds.size();
515555
mSeeds.emplace_back(TrackSeed{_tr, {t0 - terr, t0 + terr}, _origID, MinusOne});
556+
if constexpr (isTPCTrack<decltype(_tr)>()) {
557+
mSeeds.back().setCov(this->mMatchParams->tpcExtraZError2 + _tr.getCov()[o2::track::kSigZ2], o2::track::kSigZ2);
558+
}
516559
return true;
517560
} else {
518561
return false;
@@ -521,7 +564,32 @@ void MatchCosmics::createSeeds(const o2::globaltracking::RecoContainer& data)
521564

522565
data.createTracksVariadic(creator);
523566

524-
LOG(info) << "collected " << mSeeds.size() << " seeds";
567+
if (mUsePVInfo) { // if needed, veto with the primary vertex info
568+
auto trackIndex = data.getPrimaryVertexMatchedTracks(); // Global ID's for associated tracks
569+
auto vtxRefs = data.getPrimaryVertexMatchedTrackRefs(); // references from vertex to these track IDs
570+
int nv = vtxRefs.size() - 1; // The last entry is for unassigned tracks, no need to check them
571+
const auto propagator = o2::base::Propagator::Instance();
572+
for (int iv = 0; iv < nv; iv++) {
573+
const auto& vtref = vtxRefs[iv];
574+
int it = vtref.getFirstEntry(), itLim = it + vtref.getEntries();
575+
for (; it < itLim; it++) {
576+
auto tvid = trackIndex[it];
577+
auto entry = trackEntry.find(tvid);
578+
if (entry == trackEntry.end()) {
579+
continue;
580+
}
581+
auto& seed = mSeeds[entry->second];
582+
if (seed.matchID == Reject || (mMatchParams->discardPVContributors && tvid.isPVContributor())) {
583+
seed.matchID = Reject;
584+
continue;
585+
}
586+
if (seed.vtIDMin < 0) {
587+
seed.vtIDMin = iv;
588+
}
589+
seed.vtIDMax = std::max(short(iv), seed.vtIDMax);
590+
}
591+
}
592+
}
525593
}
526594

527595
//________________________________________________________

Detectors/GlobalTrackingWorkflow/include/GlobalTrackingWorkflow/CosmicsMatchingSpec.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@ namespace globaltracking
2424
{
2525

2626
/// create a processor spec
27-
framework::DataProcessorSpec getCosmicsMatchingSpec(o2::dataformats::GlobalTrackID::mask_t src, bool useMC);
27+
framework::DataProcessorSpec getCosmicsMatchingSpec(o2::dataformats::GlobalTrackID::mask_t src, bool usePV, bool useMC);
2828

2929
} // namespace globaltracking
3030
} // namespace o2

Detectors/GlobalTrackingWorkflow/src/CosmicsMatchingSpec.cxx

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -62,7 +62,7 @@ namespace globaltracking
6262
class CosmicsMatchingSpec : public Task
6363
{
6464
public:
65-
CosmicsMatchingSpec(std::shared_ptr<DataRequest> dr, std::shared_ptr<o2::base::GRPGeomRequest> gr, bool useMC) : mDataRequest(dr), mGGCCDBRequest(gr), mUseMC(useMC) {}
65+
CosmicsMatchingSpec(std::shared_ptr<DataRequest> dr, std::shared_ptr<o2::base::GRPGeomRequest> gr, bool usePV, bool useMC) : mDataRequest(dr), mGGCCDBRequest(gr), mUsePVInfo(usePV), mUseMC(useMC) {}
6666
~CosmicsMatchingSpec() override = default;
6767
void init(InitContext& ic) final;
6868
void run(ProcessingContext& pc) final;
@@ -77,6 +77,7 @@ class CosmicsMatchingSpec : public Task
7777
const o2::gpu::TPCFastTransformPOD* mCorrMap{nullptr};
7878
o2::globaltracking::MatchCosmics mMatching; // matching engine
7979
bool mUseMC = true;
80+
bool mUsePVInfo = false;
8081
TStopwatch mTimer;
8182
};
8283

@@ -87,6 +88,7 @@ void CosmicsMatchingSpec::init(InitContext& ic)
8788
o2::base::GRPGeomHelper::instance().setRequest(mGGCCDBRequest);
8889
mMatching.setDebugFlag(ic.options().get<int>("debug-tree-flags"));
8990
mMatching.setUseMC(mUseMC);
91+
mMatching.setUsePVInfo(mUsePVInfo);
9092
//
9193
}
9294

@@ -160,7 +162,7 @@ void CosmicsMatchingSpec::endOfStream(EndOfStreamContext& ec)
160162
mTimer.CpuTime(), mTimer.RealTime(), mTimer.Counter() - 1);
161163
}
162164

163-
DataProcessorSpec getCosmicsMatchingSpec(GTrackID::mask_t src, bool useMC)
165+
DataProcessorSpec getCosmicsMatchingSpec(GTrackID::mask_t src, bool usePV, bool useMC)
164166
{
165167
std::vector<OutputSpec> outputs;
166168
Options opts{
@@ -171,6 +173,9 @@ DataProcessorSpec getCosmicsMatchingSpec(GTrackID::mask_t src, bool useMC)
171173

172174
dataRequest->requestTracks(src, useMC);
173175
dataRequest->requestClusters(src, false); // no MC labels for clusters needed for refit only
176+
if (usePV) {
177+
dataRequest->requestPrimaryVertices(useMC);
178+
}
174179

175180
outputs.emplace_back("GLO", "COSMICTRC", 0, Lifetime::Timeframe);
176181
if (useMC) {
@@ -192,7 +197,7 @@ DataProcessorSpec getCosmicsMatchingSpec(GTrackID::mask_t src, bool useMC)
192197
"cosmics-matcher",
193198
dataRequest->inputs,
194199
outputs,
195-
AlgorithmSpec{adaptFromTask<CosmicsMatchingSpec>(dataRequest, ggRequest, useMC)},
200+
AlgorithmSpec{adaptFromTask<CosmicsMatchingSpec>(dataRequest, ggRequest, usePV, useMC)},
196201
opts};
197202
}
198203

Detectors/GlobalTrackingWorkflow/src/cosmics-match-workflow.cxx

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,7 @@ void customize(std::vector<o2::framework::ConfigParamSpec>& workflowOptions)
5151
{"disable-mc", o2::framework::VariantType::Bool, false, {"disable MC propagation even if available"}},
5252
{"disable-root-input", o2::framework::VariantType::Bool, false, {"disable root-files input reader"}},
5353
{"disable-root-output", o2::framework::VariantType::Bool, false, {"disable root-files output writer"}},
54+
{"use-pv-info", o2::framework::VariantType::Bool, false, {"request primary vertex for relevant cuts in the collision/cosmics interleaved data"}},
5455
{"track-sources", VariantType::String, std::string{GID::ALL}, {"comma-separated list of sources to use"}},
5556
{"configKeyValues", VariantType::String, "", {"Semicolon separated key=value strings ..."}}};
5657
o2::itsmft::DPLAlpideParamInitializer::addITSConfigOption(options);
@@ -102,14 +103,19 @@ WorkflowSpec defineDataProcessing(ConfigContext const& configcontext)
102103
if (sclOpt.requestCTPLumi) {
103104
src = src | GID::getSourcesMask("CTP");
104105
}
106+
105107
GID::mask_t srcCl = src;
106108
GID::mask_t dummy;
107109
if (!configcontext.options().get<bool>("disable-root-input")) {
108110
specs.emplace_back(o2::tpc::getTPCScalerSpec(sclOpt.lumiType == o2::tpc::LumiScaleType::TPCScaler, sclOpt.enableMShapeCorrection, sclOpt));
109111
}
110-
specs.emplace_back(o2::globaltracking::getCosmicsMatchingSpec(src, useMC));
112+
bool usePV = configcontext.options().get<bool>("use-pv-info");
113+
specs.emplace_back(o2::globaltracking::getCosmicsMatchingSpec(src, usePV, useMC));
111114

112115
o2::globaltracking::InputHelper::addInputSpecs(configcontext, specs, src, src, src, useMC, dummy); // clusters MC is not needed
116+
if (usePV) {
117+
o2::globaltracking::InputHelper::addInputSpecsPVertex(configcontext, specs, useMC); // P-vertex is always needed
118+
}
113119

114120
if (!disableRootOut) {
115121
specs.emplace_back(o2::globaltracking::getTrackCosmicsWriterSpec(useMC));

0 commit comments

Comments
 (0)