Skip to content

Commit df9672a

Browse files
committed
templatize PVertexer inputs
1 parent 1db48b2 commit df9672a

File tree

5 files changed

+196
-179
lines changed

5 files changed

+196
-179
lines changed

Detectors/GlobalTrackingWorkflow/include/GlobalTrackingWorkflow/PrimaryVertexingSpec.h

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,7 @@ using namespace o2::framework;
2828
class PrimaryVertexingSpec : public Task
2929
{
3030
public:
31-
PrimaryVertexingSpec(bool validateWithFT0, bool useMC) : mUseMC(useMC), mValidateWithFT0(validateWithFT0) {}
31+
PrimaryVertexingSpec(bool validateWithIR, bool useMC) : mUseMC(useMC), mValidateWithIR(validateWithIR) {}
3232
~PrimaryVertexingSpec() override = default;
3333
void init(InitContext& ic) final;
3434
void run(ProcessingContext& pc) final;
@@ -37,7 +37,7 @@ class PrimaryVertexingSpec : public Task
3737
private:
3838
o2::vertexing::PVertexer mVertexer;
3939
bool mUseMC{false}; ///< MC flag
40-
bool mValidateWithFT0{false}; ///< require vertex validation with FT0
40+
bool mValidateWithIR{false}; ///< require vertex validation with IR (e.g. from FT0)
4141
TStopwatch mTimer;
4242
};
4343

Detectors/GlobalTrackingWorkflow/src/PrimaryVertexingSpec.cxx

Lines changed: 23 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -12,14 +12,17 @@
1212

1313
#include <vector>
1414
#include "ReconstructionDataFormats/TrackTPCITS.h"
15+
#include "ReconstructionDataFormats/GlobalTrackID.h"
1516
#include "DetectorsBase/Propagator.h"
1617
#include "DetectorsBase/GeometryManager.h"
1718
#include "GlobalTrackingWorkflow/PrimaryVertexingSpec.h"
1819
#include "SimulationDataFormat/MCEventLabel.h"
1920
#include "CommonDataFormat/BunchFilling.h"
2021
#include "SimulationDataFormat/DigitizationContext.h"
2122
#include "DetectorsCommonDataFormats/NameConf.h"
23+
#include "DataFormatsFT0/RecPoints.h"
2224
#include "Framework/ConfigParamRegistry.h"
25+
#include "FT0Reconstruction/InteractionTag.h"
2326

2427
using namespace o2::framework;
2528

@@ -45,7 +48,7 @@ void PrimaryVertexingSpec::init(InitContext& ic)
4548
}
4649
mTimer.Stop();
4750
mTimer.Reset();
48-
mVertexer.setValidateWithFT0(mValidateWithFT0);
51+
mVertexer.setValidateWithIR(mValidateWithIR);
4952

5053
// set bunch filling. Eventually, this should come from CCDB
5154
const auto* digctx = o2::steer::DigitizationContext::loadFromFile("collisioncontext.root");
@@ -60,10 +63,6 @@ void PrimaryVertexingSpec::run(ProcessingContext& pc)
6063
mTimer.Start(false);
6164
const auto tracksITSTPC = pc.inputs().get<gsl::span<o2::dataformats::TrackTPCITS>>("match");
6265
gsl::span<const o2::MCCompLabel> lblITS, lblTPC;
63-
gsl::span<const o2::ft0::RecPoints> ft0Data;
64-
if (mValidateWithFT0) {
65-
ft0Data = pc.inputs().get<gsl::span<o2::ft0::RecPoints>>("fitInfo");
66-
}
6766
if (mUseMC) {
6867
lblITS = pc.inputs().get<gsl::span<o2::MCCompLabel>>("lblITS");
6968
lblTPC = pc.inputs().get<gsl::span<o2::MCCompLabel>>("lblTPC");
@@ -76,8 +75,26 @@ void PrimaryVertexingSpec::run(ProcessingContext& pc)
7675
// RS FIXME this will not have effect until the 1st orbit is propagated, until that will work only for TF starting at orbit 0
7776
const auto* dh = o2::header::get<o2::header::DataHeader*>(pc.inputs().get("match").header);
7877
mVertexer.setStartIR({0, dh->firstTForbit});
78+
std::vector<o2::dataformats::GlobalTrackID> idxVec; // here we will the global IDs of all used tracks
79+
80+
// eventually we will mix here the tracks from different sources
81+
idxVec.reserve(tracksITSTPC.size());
82+
for (unsigned i = 0; i < tracksITSTPC.size(); i++) {
83+
idxVec.emplace_back(i, o2::dataformats::GlobalTrackID::ITSTPC);
84+
}
85+
86+
std::vector<o2::ft0::RecPoints> ft0Data;
87+
if (mValidateWithIR) { // select BCs for validation
88+
const o2::ft0::InteractionTag& ft0Params = o2::ft0::InteractionTag::Instance();
89+
auto ftall = pc.inputs().get<gsl::span<o2::ft0::RecPoints>>("fitInfo");
90+
for (const auto& ftRP : ftall) {
91+
if (ft0Params.isSelected(ftRP)) {
92+
ft0Data.push_back(ftRP);
93+
}
94+
}
95+
}
7996

80-
mVertexer.process(tracksITSTPC, ft0Data, vertices, vertexTrackIDs, v2tRefs, lblITS, lblTPC, lblVtx);
97+
mVertexer.process(tracksITSTPC, idxVec, ft0Data, vertices, vertexTrackIDs, v2tRefs, lblITS, lblTPC, lblVtx);
8198
pc.outputs().snapshot(Output{"GLO", "PVTX", 0, Lifetime::Timeframe}, vertices);
8299
pc.outputs().snapshot(Output{"GLO", "PVTX_CONTIDREFS", 0, Lifetime::Timeframe}, v2tRefs);
83100
pc.outputs().snapshot(Output{"GLO", "PVTX_CONTID", 0, Lifetime::Timeframe}, vertexTrackIDs);

Detectors/Vertexing/include/DetectorsVertexing/PVertexer.h

Lines changed: 169 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -23,14 +23,14 @@
2323
#include "SimulationDataFormat/MCEventLabel.h"
2424
#include "SimulationDataFormat/MCCompLabel.h"
2525
#include "MathUtils/Utils.h"
26-
#include "ReconstructionDataFormats/TrackTPCITS.h"
2726
#include "ReconstructionDataFormats/Track.h"
27+
#include "ReconstructionDataFormats/DCA.h"
2828
#include "ReconstructionDataFormats/PrimaryVertex.h"
29-
#include "DataFormatsFT0/RecPoints.h"
3029
#include "DetectorsVertexing/PVertexerHelpers.h"
3130
#include "DetectorsVertexing/PVertexerParams.h"
32-
#include "FT0Reconstruction/InteractionTag.h"
31+
#include "ReconstructionDataFormats/GlobalTrackID.h"
3332
#include "gsl/span"
33+
#include <numeric>
3434

3535
namespace o2
3636
{
@@ -50,11 +50,21 @@ class PVertexer
5050
OK };
5151

5252
void init();
53-
int process(gsl::span<const o2d::TrackTPCITS> tracksITSTPC, gsl::span<const o2::ft0::RecPoints> ft0Data,
53+
54+
template <typename TR, typename BC>
55+
int process(const TR& tracks, const gsl::span<o2d::GlobalTrackID> gids, const BC& bcData,
5456
std::vector<PVertex>& vertices, std::vector<o2d::VtxTrackIndex>& vertexTrackIDs, std::vector<V2TRef>& v2tRefs,
55-
gsl::span<const o2::MCCompLabel> lblITS, gsl::span<const o2::MCCompLabel> lblTPC, std::vector<o2::MCEventLabel>& lblVtx);
57+
gsl::span<const o2::MCCompLabel> lblITS, gsl::span<const o2::MCCompLabel> lblTPC, std::vector<o2::MCEventLabel>& lblVtx)
58+
{
59+
auto nv = process(tracks, gids, bcData, vertices, vertexTrackIDs, v2tRefs);
60+
if (lblITS.size() && lblTPC.size()) {
61+
createMCLabels(lblITS, lblTPC, vertices, vertexTrackIDs, v2tRefs, lblVtx);
62+
}
63+
return nv;
64+
}
5665

57-
int process(gsl::span<const o2d::TrackTPCITS> tracksITSTPC, gsl::span<const o2::ft0::RecPoints> ft0Data,
66+
template <typename TR, typename BC>
67+
int process(const TR& tracks, const gsl::span<o2d::GlobalTrackID> gids, const BC& bcData,
5868
std::vector<PVertex>& vertices, std::vector<o2d::VtxTrackIndex>& vertexTrackIDs, std::vector<V2TRef>& v2tRefs);
5969

6070
static void createMCLabels(gsl::span<const o2::MCCompLabel> lblITS, gsl::span<const o2::MCCompLabel> lblTPC,
@@ -76,8 +86,8 @@ class PVertexer
7686
void setBunchFilling(const o2::BunchFilling& bf);
7787

7888
void setBz(float bz) { mBz = bz; }
79-
void setValidateWithFT0(bool v) { mValidateWithFT0 = v; }
80-
bool getValidateWithFT0() const { return mValidateWithFT0; }
89+
void setValidateWithIR(bool v) { mValidateWithIR = v; }
90+
bool getValidateWithIR() const { return mValidateWithIR; }
8191

8292
auto& getTracksPool() const { return mTracksPool; }
8393
auto& getTimeZClusters() const { return mTimeZClusters; }
@@ -106,9 +116,14 @@ class PVertexer
106116
void initMeanVertexConstraint();
107117
void applyConstraint(VertexSeed& vtxSeed) const;
108118
bool upscaleSigma(VertexSeed& vtxSeed) const;
109-
void createTracksPool(gsl::span<const o2d::TrackTPCITS> tracksITSTPC);
119+
120+
template <typename TR>
121+
void createTracksPool(const TR& tracks, gsl::span<const o2d::GlobalTrackID> gids);
122+
110123
int findVertices(const VertexingInput& input, std::vector<PVertex>& vertices, std::vector<GTrackID>& vertexTrackIDs, std::vector<V2TRef>& v2tRefs);
111-
std::pair<int, int> getBestFT0Trigger(const PVertex& vtx, gsl::span<const o2::ft0::RecPoints> ft0Data, int& currEntry) const;
124+
125+
template <typename BC>
126+
std::pair<int, int> getBestIR(const PVertex& vtx, const BC& bcData, int& currEntry) const;
112127

113128
int dbscan_RangeQuery(int idxs, std::vector<int>& cand, const std::vector<int>& status);
114129
void dbscan_clusterize();
@@ -127,13 +142,12 @@ class PVertexer
127142
std::vector<int> mClusterTrackIDs; ///< IDs of tracks making the clusters
128143

129144
float mBz = 0.; ///< mag.field at beam line
130-
bool mValidateWithFT0 = false; ///< require vertex validation with FT0 (if available)
145+
bool mValidateWithIR = false; ///< require vertex validation with InteractionRecords (if available)
131146

132147
o2::InteractionRecord mStartIR{0, 0}; ///< IR corresponding to the start of the TF
133148

134149
///========== Parameters to be set externally, e.g. from CCDB ====================
135150
const PVertexerParams* mPVParams = nullptr;
136-
const o2::ft0::InteractionTag* mFT0Params = nullptr;
137151
float mTukey2I = 0; ///< 1./[Tukey parameter]^2
138152
static constexpr float kDefTukey = 5.0f; ///< def.value for tukey constant
139153
static constexpr float kHugeF = 1.e12; ///< very large float
@@ -166,6 +180,149 @@ inline bool PVertexer::upscaleSigma(VertexSeed& vtxSeed) const
166180
return false;
167181
}
168182

183+
//___________________________________________________________________
184+
template <typename TR>
185+
void PVertexer::createTracksPool(const TR& tracks, gsl::span<const o2d::GlobalTrackID> gids)
186+
{
187+
// create pull of all candidate tracks in a global array ordered in time
188+
mTracksPool.clear();
189+
mSortedTrackID.clear();
190+
191+
auto ntGlo = tracks.size();
192+
mTracksPool.reserve(ntGlo);
193+
// check all containers
194+
float vtxErr2 = 0.5 * (mMeanVertex.getSigmaX2() + mMeanVertex.getSigmaY2());
195+
float pullIniCut = 9.; // RS FIXME pullIniCut should be a parameter
196+
o2d::DCA dca;
197+
198+
for (uint32_t i = 0; i < ntGlo; i++) {
199+
o2::track::TrackParCov trc = tracks[i];
200+
if (!trc.propagateToDCA(mMeanVertex, mBz, &dca, mPVParams->dcaTolerance) ||
201+
dca.getY() * dca.getY() / (dca.getSigmaY2() + vtxErr2) > mPVParams->pullIniCut) {
202+
continue;
203+
}
204+
auto& tvf = mTracksPool.emplace_back(trc, tracks[i].getTimeMUS(), gids[i]);
205+
mStatZErr.add(std::sqrt(trc.getSigmaZ2()));
206+
mStatTErr.add(tvf.timeEst.getTimeStampError());
207+
}
208+
// TODO: try to narrow timestamps using tof times
209+
auto [zerrMean, zerrRMS] = mStatZErr.getMeanRMS2<float>();
210+
211+
auto [terrMean, terrRMS] = mStatTErr.getMeanRMS2<float>();
212+
213+
if (mTracksPool.empty()) {
214+
return;
215+
}
216+
//
217+
mSortedTrackID.resize(mTracksPool.size());
218+
std::iota(mSortedTrackID.begin(), mSortedTrackID.end(), 0);
219+
220+
std::sort(mSortedTrackID.begin(), mSortedTrackID.end(), [this](int i, int j) {
221+
return this->mTracksPool[i].timeEst.getTimeStamp() < this->mTracksPool[j].timeEst.getTimeStamp();
222+
});
223+
224+
auto tMin = mTracksPool[mSortedTrackID.front()].timeEst.getTimeStamp();
225+
auto tMax = mTracksPool[mSortedTrackID.back()].timeEst.getTimeStamp();
226+
}
227+
228+
//___________________________________________________________________
229+
template <typename TR, typename BC>
230+
int PVertexer::process(const TR& tracks, gsl::span<o2d::GlobalTrackID> gids, const BC& bcData,
231+
std::vector<PVertex>& vertices, std::vector<o2d::VtxTrackIndex>& vertexTrackIDs, std::vector<V2TRef>& v2tRefs)
232+
{
233+
createTracksPool(tracks, gids);
234+
dbscan_clusterize();
235+
236+
std::vector<PVertex> verticesLoc;
237+
std::vector<GTrackID> vertexTrackIDsLoc;
238+
std::vector<V2TRef> v2tRefsLoc;
239+
std::vector<float> validationTimes;
240+
241+
for (auto tc : mTimeZClusters) {
242+
VertexingInput inp;
243+
// inp.idRange = gsl::span<int>((int*)&mSortedTrackID[tc.first], tc.count);
244+
inp.idRange = gsl::span<int>((int*)&mClusterTrackIDs[tc.first], tc.count);
245+
inp.scaleSigma2 = 3. * estimateScale2();
246+
inp.timeEst = tc.timeEst;
247+
findVertices(inp, verticesLoc, vertexTrackIDsLoc, v2tRefsLoc);
248+
}
249+
250+
// sort in time
251+
std::vector<int> vtTimeSortID(verticesLoc.size());
252+
std::iota(vtTimeSortID.begin(), vtTimeSortID.end(), 0);
253+
std::sort(vtTimeSortID.begin(), vtTimeSortID.end(), [&verticesLoc](int i, int j) {
254+
return verticesLoc[i].getTimeStamp().getTimeStamp() < verticesLoc[j].getTimeStamp().getTimeStamp();
255+
});
256+
257+
vertices.clear();
258+
v2tRefs.clear();
259+
vertexTrackIDs.clear();
260+
vertices.reserve(verticesLoc.size());
261+
v2tRefs.reserve(v2tRefsLoc.size());
262+
vertexTrackIDs.reserve(vertexTrackIDsLoc.size());
263+
264+
int trCopied = 0, count = 0, vtimeID = 0;
265+
for (auto i : vtTimeSortID) {
266+
auto& vtx = verticesLoc[i];
267+
268+
bool irSet = setCompatibleIR(vtx);
269+
if (!irSet) {
270+
continue;
271+
}
272+
// do we need to validate by Int. records ?
273+
if (mValidateWithIR) {
274+
auto bestMatch = getBestIR(vtx, bcData, vtimeID);
275+
if (bestMatch.first >= 0) {
276+
vtx.setFlags(PVertex::TimeValidated);
277+
if (bestMatch.second == 1) {
278+
vtx.setIR(bcData[bestMatch.first].getInteractionRecord());
279+
}
280+
LOG(DEBUG) << "Validated with t0 " << bestMatch.first << " with " << bestMatch.second << " candidates";
281+
} else if (vtx.getNContributors() >= mPVParams->minNContributorsForIRcut) {
282+
LOG(DEBUG) << "Discarding " << vtx;
283+
continue; // reject
284+
}
285+
}
286+
vertices.push_back(vtx);
287+
int it = v2tRefsLoc[i].getFirstEntry(), itEnd = it + v2tRefsLoc[i].getEntries(), dest0 = vertexTrackIDs.size();
288+
for (; it < itEnd; it++) {
289+
auto& gid = vertexTrackIDs.emplace_back(vertexTrackIDsLoc[it]);
290+
gid.setPVContributor();
291+
}
292+
v2tRefs.emplace_back(dest0, v2tRefsLoc[i].getEntries());
293+
LOG(DEBUG) << "#" << count++ << " " << vertices.back() << " | " << v2tRefs.back().getEntries() << " indices from " << v2tRefs.back().getFirstEntry(); // RS REM
294+
}
295+
296+
return vertices.size();
297+
}
298+
299+
//___________________________________________________________________
300+
template <typename BC>
301+
std::pair<int, int> PVertexer::getBestIR(const PVertex& vtx, const BC& bcData, int& currEntry) const
302+
{
303+
// select best matching interaction record
304+
int best = -1, n = bcData.size();
305+
while (currEntry < n && bcData[currEntry].getInteractionRecord() < vtx.getIRMin()) {
306+
currEntry++; // skip all times which have no chance to be matched
307+
}
308+
int i = currEntry, nCompatible = 0;
309+
float bestDf = 1e12;
310+
auto tVtxNS = (vtx.getTimeStamp().getTimeStamp() + mPVParams->timeBiasMS) * 1e3; // time in ns
311+
while (i < n) {
312+
if (bcData[i].getInteractionRecord() > vtx.getIRMax()) {
313+
break;
314+
}
315+
nCompatible++;
316+
auto dfa = std::abs(bcData[i].getInteractionRecord().differenceInBCNS(mStartIR) - tVtxNS);
317+
if (dfa <= bestDf) {
318+
bestDf = dfa;
319+
best = i;
320+
}
321+
i++;
322+
}
323+
return {best, nCompatible};
324+
}
325+
169326
} // namespace vertexing
170327
} // namespace o2
171328
#endif

Detectors/Vertexing/include/DetectorsVertexing/PVertexerParams.h

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -47,9 +47,8 @@ struct PVertexerParams : public o2::conf::ConfigurableParamHelper<PVertexerParam
4747
float upscaleFactor = 9.; ///< factor for upscaling if not candidate is found
4848
float slowConvergenceFactor = 0.5; ///< consider convergence as slow if ratio new/old scale2 exceeds it
4949
//
50-
// validation with FT0
51-
bool requireFT0ValidTimeMean = false; //true;///< require both FT0A/C
52-
int minNContributorsForFT0cut = 4; ///< do not apply FT0 cut to vertice below FT0 efficiency threshold
50+
// validation with externally provided InteractionRecords (e.g. from FT0)
51+
int minNContributorsForIRcut = 4; ///< do not apply IR cut to vertices below IR tagging efficiency threshold
5352
float maxTError = 0.2; ///< use min of vertex time error or this for nsigma evaluation
5453
float minTError = 0.003; ///< don't use error smaller than that (~BC/2/minNContributorsForFT0cut)
5554
float nSigmaTimeCut = 4.; ///< eliminate vertex if there is no FT0 signal within this cut

0 commit comments

Comments
 (0)