Project
Loading...
Searching...
No Matches
VertexerTraits.cxx
Go to the documentation of this file.
1// Copyright 2019-2020 CERN and copyright holders of ALICE O2.
2// See https://alice-o2.web.cern.ch/copyright for details of the copyright holders.
3// All rights not expressly granted are reserved.
4//
5// This software is distributed under the terms of the GNU General Public
6// License v3 (GPL Version 3), copied verbatim in the file "COPYING".
7//
8// In applying this license CERN does not waive the privileges and immunities
9// granted to it by virtue of its status as an Intergovernmental Organization
10// or submit itself to any jurisdiction.
12
13#include <boost/histogram.hpp>
14#include <boost/format.hpp>
15#include <iostream>
16#include <string>
17#include <chrono>
18
22
23#ifdef VTX_DEBUG
24#include "TTree.h"
25#include "TFile.h"
26#include <fstream>
27#include <ostream>
28#endif
29
30#ifdef WITH_OPENMP
31#include <omp.h>
32#endif
33
34namespace o2
35{
36namespace its
37{
38using boost::histogram::indexed;
40
41float smallestAngleDifference(float a, float b)
42{
44 return (diff < -constants::math::Pi) ? diff + constants::math::TwoPi : ((diff > constants::math::Pi) ? diff - constants::math::TwoPi : diff);
45}
46
47template <TrackletMode Mode, bool EvalRun>
49 const gsl::span<const Cluster>& clustersNextLayer, // 0 2
50 const gsl::span<const Cluster>& clustersCurrentLayer, // 1 1
51 const gsl::span<unsigned char>& usedClustersNextLayer, // 0 2
52 int* indexTableNext,
53 const float phiCut,
54 std::vector<Tracklet>& tracklets,
55 gsl::span<int> foundTracklets,
57 const short pivotRof,
58 const short targetRof,
59 gsl::span<int> rofFoundTrackletsOffsets, // we want to change those, to keep track of the offset in deltaRof>0
60 const int maxTrackletsPerCluster = static_cast<int>(2e3))
61{
62 const int PhiBins{utils.getNphiBins()};
63 const int ZBins{utils.getNzBins()};
64 // loop on layer1 clusters
65 for (int iCurrentLayerClusterIndex = 0; iCurrentLayerClusterIndex < clustersCurrentLayer.size(); ++iCurrentLayerClusterIndex) {
66 int storedTracklets{0};
67 const Cluster& currentCluster{clustersCurrentLayer[iCurrentLayerClusterIndex]};
68 const int4 selectedBinsRect{VertexerTraits::getBinsRect(currentCluster, (int)Mode, 0.f, 50.f, phiCut / 2, utils)};
69 if (selectedBinsRect.x != 0 || selectedBinsRect.y != 0 || selectedBinsRect.z != 0 || selectedBinsRect.w != 0) {
70 int phiBinsNum{selectedBinsRect.w - selectedBinsRect.y + 1};
71 if (phiBinsNum < 0) {
72 phiBinsNum += PhiBins;
73 }
74 // loop on phi bins next layer
75 for (int iPhiBin{selectedBinsRect.y}, iPhiCount{0}; iPhiCount < phiBinsNum; iPhiBin = ++iPhiBin == PhiBins ? 0 : iPhiBin, iPhiCount++) {
76 const int firstBinIndex{utils.getBinIndex(selectedBinsRect.x, iPhiBin)};
77 const int firstRowClusterIndex{indexTableNext[firstBinIndex]};
78 const int maxRowClusterIndex{indexTableNext[firstBinIndex + ZBins]};
79 // loop on clusters next layer
80 for (int iNextLayerClusterIndex{firstRowClusterIndex}; iNextLayerClusterIndex < maxRowClusterIndex && iNextLayerClusterIndex < static_cast<int>(clustersNextLayer.size()); ++iNextLayerClusterIndex) {
81 if (usedClustersNextLayer[iNextLayerClusterIndex]) {
82 continue;
83 }
84 const Cluster& nextCluster{clustersNextLayer[iNextLayerClusterIndex]};
85 if (o2::gpu::GPUCommonMath::Abs(smallestAngleDifference(currentCluster.phi, nextCluster.phi)) < phiCut) {
86 if (storedTracklets < maxTrackletsPerCluster) {
87 if constexpr (!EvalRun) {
88 if constexpr (Mode == TrackletMode::Layer0Layer1) {
89 tracklets[rofFoundTrackletsOffsets[iCurrentLayerClusterIndex] + storedTracklets] = Tracklet{iNextLayerClusterIndex, iCurrentLayerClusterIndex, nextCluster, currentCluster, targetRof, pivotRof};
90 } else {
91 tracklets[rofFoundTrackletsOffsets[iCurrentLayerClusterIndex] + storedTracklets] = Tracklet{iCurrentLayerClusterIndex, iNextLayerClusterIndex, currentCluster, nextCluster, pivotRof, targetRof};
92 }
93 }
94 ++storedTracklets;
95 }
96 }
97 }
98 }
99 }
100 if constexpr (EvalRun) {
101 foundTracklets[iCurrentLayerClusterIndex] += storedTracklets;
102 } else {
103 rofFoundTrackletsOffsets[iCurrentLayerClusterIndex] += storedTracklets;
104 }
105 }
106}
107
109 const gsl::span<const Cluster> clusters0, // 0
110 const gsl::span<const Cluster> clusters1, // 1
111 gsl::span<unsigned char> usedClusters0, // Layer 0
112 gsl::span<unsigned char> usedClusters2, // Layer 2
113 const gsl::span<const Tracklet>& tracklets01,
114 const gsl::span<const Tracklet>& tracklets12,
115 std::vector<bool>& usedTracklets,
116 const gsl::span<int> foundTracklets01,
117 const gsl::span<int> foundTracklets12,
118 std::vector<Line>& lines,
119 const gsl::span<const MCCompLabel>& trackletLabels,
120 std::vector<MCCompLabel>& linesLabels,
121 const short pivotRofId,
122 const short targetRofId,
123 const float tanLambdaCut = 0.025f,
124 const float phiCut = 0.005f,
125 const int maxTracklets = static_cast<int>(1e2))
126{
127 int offset01{0}, offset12{0};
128 for (unsigned int iCurrentLayerClusterIndex{0}; iCurrentLayerClusterIndex < clusters1.size(); ++iCurrentLayerClusterIndex) {
129 int validTracklets{0};
130 for (int iTracklet12{offset12}; iTracklet12 < offset12 + foundTracklets12[iCurrentLayerClusterIndex]; ++iTracklet12) {
131 for (int iTracklet01{offset01}; iTracklet01 < offset01 + foundTracklets01[iCurrentLayerClusterIndex]; ++iTracklet01) {
132 const auto& tracklet01{tracklets01[iTracklet01]};
133 const auto& tracklet12{tracklets12[iTracklet12]};
134 if (tracklet01.rof[0] != targetRofId || tracklet12.rof[1] != targetRofId) {
135 continue;
136 }
137 const float deltaTanLambda{o2::gpu::GPUCommonMath::Abs(tracklet01.tanLambda - tracklet12.tanLambda)};
138 const float deltaPhi{o2::gpu::GPUCommonMath::Abs(smallestAngleDifference(tracklet01.phi, tracklet12.phi))};
139 if (!usedTracklets[iTracklet01] && deltaTanLambda < tanLambdaCut && deltaPhi < phiCut && validTracklets != maxTracklets) {
140 usedClusters0[tracklet01.firstClusterIndex] = true;
141 usedClusters2[tracklet12.secondClusterIndex] = true;
142 usedTracklets[iTracklet01] = true;
143 lines.emplace_back(tracklet01, clusters0.data(), clusters1.data());
144 if (trackletLabels.size()) {
145 linesLabels.emplace_back(trackletLabels[iTracklet01]);
146 }
147 ++validTracklets;
148 }
149 }
150 }
151 offset01 += foundTracklets01[iCurrentLayerClusterIndex];
152 offset12 += foundTracklets12[iCurrentLayerClusterIndex];
153 }
154}
155
156const std::vector<std::pair<int, int>> VertexerTraits::selectClusters(const int* indexTable,
157 const std::array<int, 4>& selectedBinsRect,
158 const IndexTableUtils& utils)
159{
160 std::vector<std::pair<int, int>> filteredBins{};
161 int phiBinsNum{selectedBinsRect[3] - selectedBinsRect[1] + 1};
162 if (phiBinsNum < 0) {
163 phiBinsNum += utils.getNphiBins();
164 }
165 filteredBins.reserve(phiBinsNum);
166 for (int iPhiBin{selectedBinsRect[1]}, iPhiCount{0}; iPhiCount < phiBinsNum;
167 iPhiBin = ++iPhiBin == utils.getNphiBins() ? 0 : iPhiBin, iPhiCount++) {
168 const int firstBinIndex{utils.getBinIndex(selectedBinsRect[0], iPhiBin)};
169 filteredBins.emplace_back(
170 indexTable[firstBinIndex],
171 utils.countRowSelectedBins(indexTable, iPhiBin, selectedBinsRect[0], selectedBinsRect[2]));
172 }
173 return filteredBins;
174}
175
176void VertexerTraits::updateVertexingParameters(const std::vector<VertexingParameters>& vrtPar, const TimeFrameGPUParameters& tfPar)
177{
178 mVrtParams = vrtPar;
180 for (auto& par : mVrtParams) {
181 par.phiSpan = static_cast<int>(std::ceil(mIndexTableUtils.getNphiBins() * par.phiCut / constants::math::TwoPi));
182 par.zSpan = static_cast<int>(std::ceil(par.zCut * mIndexTableUtils.getInverseZCoordinate(0)));
183 }
184 setNThreads(vrtPar[0].nThreads);
185}
186
187// Main functions
188void VertexerTraits::computeTracklets(const int iteration)
189{
190#pragma omp parallel num_threads(mNThreads)
191 {
192#pragma omp for schedule(dynamic)
193 for (short pivotRofId = 0; pivotRofId < mTimeFrame->getNrof(); ++pivotRofId) { // Pivot rofId: the rof for which the tracklets are computed
194 bool skipROF = iteration && (int)mTimeFrame->getPrimaryVertices(pivotRofId).size() > mVrtParams[iteration].vertPerRofThreshold;
195 short startROF{std::max((short)0, static_cast<short>(pivotRofId - mVrtParams[iteration].deltaRof))};
196 short endROF{std::min(static_cast<short>(mTimeFrame->getNrof()), static_cast<short>(pivotRofId + mVrtParams[iteration].deltaRof + 1))};
197 for (auto targetRofId = startROF; targetRofId < endROF; ++targetRofId) {
198 trackleterKernelHost<TrackletMode::Layer0Layer1, true>(
199 !skipROF ? mTimeFrame->getClustersOnLayer(targetRofId, 0) : gsl::span<Cluster>(), // Clusters to be matched with the next layer in target rof
200 !skipROF ? mTimeFrame->getClustersOnLayer(pivotRofId, 1) : gsl::span<Cluster>(), // Clusters to be matched with the current layer in pivot rof
201 mTimeFrame->getUsedClustersROF(targetRofId, 0), // Span of the used clusters in the target rof
202 mTimeFrame->getIndexTable(targetRofId, 0).data(), // Index table to access the data on the next layer in target rof
203 mVrtParams[iteration].phiCut,
204 mTimeFrame->getTracklets()[0], // Flat tracklet buffer
205 mTimeFrame->getNTrackletsCluster(pivotRofId, 0), // Span of the number of tracklets per each cluster in pivot rof
207 pivotRofId,
208 targetRofId,
209 gsl::span<int>(), // Offset in the tracklet buffer
210 mVrtParams[iteration].maxTrackletsPerCluster);
211 trackleterKernelHost<TrackletMode::Layer1Layer2, true>(
212 !skipROF ? mTimeFrame->getClustersOnLayer(targetRofId, 2) : gsl::span<Cluster>(),
213 !skipROF ? mTimeFrame->getClustersOnLayer(pivotRofId, 1) : gsl::span<Cluster>(),
214 mTimeFrame->getUsedClustersROF(targetRofId, 2),
215 mTimeFrame->getIndexTable(targetRofId, 2).data(),
216 mVrtParams[iteration].phiCut,
218 mTimeFrame->getNTrackletsCluster(pivotRofId, 1), // Span of the number of tracklets per each cluster in pivot rof
220 pivotRofId,
221 targetRofId,
222 gsl::span<int>(), // Offset in the tracklet buffer
223 mVrtParams[iteration].maxTrackletsPerCluster);
224 }
225 mTimeFrame->getNTrackletsROF(pivotRofId, 0) = std::accumulate(mTimeFrame->getNTrackletsCluster(pivotRofId, 0).begin(), mTimeFrame->getNTrackletsCluster(pivotRofId, 0).end(), 0);
226 mTimeFrame->getNTrackletsROF(pivotRofId, 1) = std::accumulate(mTimeFrame->getNTrackletsCluster(pivotRofId, 1).begin(), mTimeFrame->getNTrackletsCluster(pivotRofId, 1).end(), 0);
227 }
228#pragma omp single
230#pragma omp single
232#pragma omp single
234
235#pragma omp for schedule(dynamic)
236 for (int pivotRofId = 0; pivotRofId < mTimeFrame->getNrof(); ++pivotRofId) {
237 bool skipROF = iteration && (int)mTimeFrame->getPrimaryVertices(pivotRofId).size() > mVrtParams[iteration].vertPerRofThreshold;
238 short startROF{std::max((short)0, static_cast<short>(pivotRofId - mVrtParams[iteration].deltaRof))};
239 short endROF{std::min(static_cast<short>(mTimeFrame->getNrof()), static_cast<short>(pivotRofId + mVrtParams[iteration].deltaRof + 1))};
240 auto mobileOffset0 = mTimeFrame->getNTrackletsROF(pivotRofId, 0);
241 auto mobileOffset1 = mTimeFrame->getNTrackletsROF(pivotRofId, 1);
242 for (auto targetRofId = startROF; targetRofId < endROF; ++targetRofId) {
243 trackleterKernelHost<TrackletMode::Layer0Layer1, false>(
244 !skipROF ? mTimeFrame->getClustersOnLayer(targetRofId, 0) : gsl::span<Cluster>(),
245 !skipROF ? mTimeFrame->getClustersOnLayer(pivotRofId, 1) : gsl::span<Cluster>(),
246 mTimeFrame->getUsedClustersROF(targetRofId, 0),
247 mTimeFrame->getIndexTable(targetRofId, 0).data(),
248 mVrtParams[iteration].phiCut,
250 mTimeFrame->getNTrackletsCluster(pivotRofId, 0),
252 pivotRofId,
253 targetRofId,
255 mVrtParams[iteration].maxTrackletsPerCluster);
256 trackleterKernelHost<TrackletMode::Layer1Layer2, false>(
257 !skipROF ? mTimeFrame->getClustersOnLayer(targetRofId, 2) : gsl::span<Cluster>(),
258 !skipROF ? mTimeFrame->getClustersOnLayer(pivotRofId, 1) : gsl::span<Cluster>(),
259 mTimeFrame->getUsedClustersROF(targetRofId, 2),
260 mTimeFrame->getIndexTable(targetRofId, 2).data(),
261 mVrtParams[iteration].phiCut,
263 mTimeFrame->getNTrackletsCluster(pivotRofId, 1),
265 pivotRofId,
266 targetRofId,
268 mVrtParams[iteration].maxTrackletsPerCluster);
269 }
270 }
271 }
272
275 for (auto& trk : mTimeFrame->getTracklets()[0]) {
277 int sortedId0{mTimeFrame->getSortedIndex(trk.rof[0], 0, trk.firstClusterIndex)};
278 int sortedId1{mTimeFrame->getSortedIndex(trk.rof[1], 1, trk.secondClusterIndex)};
279 for (auto& lab0 : mTimeFrame->getClusterLabels(0, mTimeFrame->getClusters()[0][sortedId0].clusterId)) {
280 for (auto& lab1 : mTimeFrame->getClusterLabels(1, mTimeFrame->getClusters()[1][sortedId1].clusterId)) {
281 if (lab0 == lab1 && lab0.isValid()) {
282 label = lab0;
283 break;
284 }
285 }
286 if (label.isValid()) {
287 break;
288 }
289 }
290 mTimeFrame->getTrackletsLabel(0).emplace_back(label);
291 }
292 }
293
294#ifdef VTX_DEBUG
295 // Dump on file
296 TFile* trackletFile = TFile::Open("artefacts_tf.root", "recreate");
297 TTree* tr_tre = new TTree("tracklets", "tf");
298 std::vector<o2::its::Tracklet> trkl_vec_0(0);
299 std::vector<o2::its::Tracklet> trkl_vec_1(0);
300 std::vector<o2::its::Cluster> clus0(0);
301 std::vector<o2::its::Cluster> clus1(0);
302 std::vector<o2::its::Cluster> clus2(0);
303 tr_tre->Branch("Tracklets0", &trkl_vec_0);
304 tr_tre->Branch("Tracklets1", &trkl_vec_1);
305 for (int rofId{0}; rofId < mTimeFrame->getNrof(); ++rofId) {
306 trkl_vec_0.clear();
307 trkl_vec_1.clear();
308 for (auto& tr : mTimeFrame->getFoundTracklets(rofId, 0)) {
309 trkl_vec_0.push_back(tr);
310 }
311 for (auto& tr : mTimeFrame->getFoundTracklets(rofId, 1)) {
312 trkl_vec_1.push_back(tr);
313 }
314 tr_tre->Fill();
315 }
316 trackletFile->cd();
317 tr_tre->Write();
318 trackletFile->Close();
319
320 std::ofstream out01("NTC01_cpu.txt"), out12("NTC12_cpu.txt");
321 for (int iRof{0}; iRof < mTimeFrame->getNrof(); ++iRof) {
322 out01 << "ROF: " << iRof << std::endl;
323 out12 << "ROF: " << iRof << std::endl;
324 std::copy(mTimeFrame->getNTrackletsCluster(iRof, 0).begin(), mTimeFrame->getNTrackletsCluster(iRof, 0).end(), std::ostream_iterator<double>(out01, "\t"));
325 out01 << std::endl;
326 std::copy(mTimeFrame->getExclusiveNTrackletsCluster(iRof, 0).begin(), mTimeFrame->getExclusiveNTrackletsCluster(iRof, 0).end(), std::ostream_iterator<double>(out01, "\t"));
327 std::copy(mTimeFrame->getNTrackletsCluster(iRof, 1).begin(), mTimeFrame->getNTrackletsCluster(iRof, 1).end(), std::ostream_iterator<double>(out12, "\t"));
328 out12 << std::endl;
329 std::copy(mTimeFrame->getExclusiveNTrackletsCluster(iRof, 1).begin(), mTimeFrame->getExclusiveNTrackletsCluster(iRof, 1).end(), std::ostream_iterator<double>(out12, "\t"));
330 out01 << std::endl;
331 out12 << std::endl;
332 }
333 out01.close();
334 out12.close();
335#endif
336} // namespace its
337
339{
340#pragma omp parallel for num_threads(mNThreads) schedule(dynamic)
341 for (int pivotRofId = 0; pivotRofId < mTimeFrame->getNrof(); ++pivotRofId) {
342 if (iteration && (int)mTimeFrame->getPrimaryVertices(pivotRofId).size() > mVrtParams[iteration].vertPerRofThreshold) {
343 continue;
344 }
345 mTimeFrame->getLines(pivotRofId).reserve(mTimeFrame->getNTrackletsCluster(pivotRofId, 0).size());
346 std::vector<bool> usedTracklets(mTimeFrame->getFoundTracklets(pivotRofId, 0).size(), false);
347 int startROF{std::max((short)0, static_cast<short>(pivotRofId - mVrtParams[iteration].deltaRof))};
348 int endROF{std::min(static_cast<short>(mTimeFrame->getNrof()), static_cast<short>(pivotRofId + mVrtParams[iteration].deltaRof + 1))};
349 for (auto targetRofId = startROF; targetRofId < endROF; ++targetRofId) {
351 mTimeFrame->getClustersOnLayer(targetRofId, 0),
352 mTimeFrame->getClustersOnLayer(pivotRofId, 1),
353 mTimeFrame->getUsedClustersROF(targetRofId, 0),
354 mTimeFrame->getUsedClustersROF(targetRofId, 2),
355 mTimeFrame->getFoundTracklets(pivotRofId, 0),
356 mTimeFrame->getFoundTracklets(pivotRofId, 1),
357 usedTracklets,
358 mTimeFrame->getNTrackletsCluster(pivotRofId, 0),
359 mTimeFrame->getNTrackletsCluster(pivotRofId, 1),
360 mTimeFrame->getLines(pivotRofId),
361 mTimeFrame->getLabelsFoundTracklets(pivotRofId, 0),
362 mTimeFrame->getLinesLabel(pivotRofId),
363 pivotRofId,
364 targetRofId,
365 mVrtParams[iteration].tanLambdaCut,
366 mVrtParams[iteration].phiCut);
367 }
368 }
369
370#ifdef VTX_DEBUG
371 TFile* trackletFile = TFile::Open("artefacts_tf.root", "update");
372 TTree* ln_tre = new TTree("lines", "tf");
373 std::vector<o2::its::Line> lines_vec(0);
374 std::vector<int> nTrackl01(0);
375 std::vector<int> nTrackl12(0);
376 ln_tre->Branch("Lines", &lines_vec);
377 ln_tre->Branch("NTrackletCluster01", &nTrackl01);
378 ln_tre->Branch("NTrackletCluster12", &nTrackl12);
379 for (int rofId{0}; rofId < mTimeFrame->getNrof(); ++rofId) {
380 lines_vec.clear();
381 nTrackl01.clear();
382 nTrackl12.clear();
383 for (auto& ln : mTimeFrame->getLines(rofId)) {
384 lines_vec.push_back(ln);
385 }
386 for (auto& n : mTimeFrame->getNTrackletsCluster(rofId, 0)) {
387 nTrackl01.push_back(n);
388 }
389 for (auto& n : mTimeFrame->getNTrackletsCluster(rofId, 1)) {
390 nTrackl12.push_back(n);
391 }
392
393 ln_tre->Fill();
394 }
395 trackletFile->cd();
396 ln_tre->Write();
397 trackletFile->Close();
398#endif
399}
400
401void VertexerTraits::computeVertices(const int iteration)
402{
403 auto nsigmaCut{std::min(mVrtParams[iteration].vertNsigmaCut * mVrtParams[iteration].vertNsigmaCut * (mVrtParams[iteration].vertRadiusSigma * mVrtParams[iteration].vertRadiusSigma + mVrtParams[iteration].trackletSigma * mVrtParams[iteration].trackletSigma), 1.98f)};
404 std::vector<Vertex> vertices;
405 std::vector<std::pair<o2::MCCompLabel, float>> polls;
406#ifdef VTX_DEBUG
407 std::vector<std::vector<ClusterLines>> dbg_clusLines(mTimeFrame->getNrof());
408#endif
409 std::vector<int> noClustersVec(mTimeFrame->getNrof(), 0);
410 for (int rofId{0}; rofId < mTimeFrame->getNrof(); ++rofId) {
411 if (iteration && (int)mTimeFrame->getPrimaryVertices(rofId).size() > mVrtParams[iteration].vertPerRofThreshold) {
412 continue;
413 }
414 const int numTracklets{static_cast<int>(mTimeFrame->getLines(rofId).size())};
415
416 std::vector<bool> usedTracklets(numTracklets, false);
417 for (int line1{0}; line1 < numTracklets; ++line1) {
418 if (usedTracklets[line1]) {
419 continue;
420 }
421 for (int line2{line1 + 1}; line2 < numTracklets; ++line2) {
422 if (usedTracklets[line2]) {
423 continue;
424 }
425 auto dca{Line::getDCA(mTimeFrame->getLines(rofId)[line1], mTimeFrame->getLines(rofId)[line2])};
426 if (dca < mVrtParams[iteration].pairCut) {
427 mTimeFrame->getTrackletClusters(rofId).emplace_back(line1, mTimeFrame->getLines(rofId)[line1], line2, mTimeFrame->getLines(rofId)[line2]);
428 std::array<float, 3> tmpVertex{mTimeFrame->getTrackletClusters(rofId).back().getVertex()};
429 if (tmpVertex[0] * tmpVertex[0] + tmpVertex[1] * tmpVertex[1] > 4.f) {
430 mTimeFrame->getTrackletClusters(rofId).pop_back();
431 break;
432 }
433 usedTracklets[line1] = true;
434 usedTracklets[line2] = true;
435 for (int tracklet3{0}; tracklet3 < numTracklets; ++tracklet3) {
436 if (usedTracklets[tracklet3]) {
437 continue;
438 }
439 if (Line::getDistanceFromPoint(mTimeFrame->getLines(rofId)[tracklet3], tmpVertex) < mVrtParams[iteration].pairCut) {
440 mTimeFrame->getTrackletClusters(rofId).back().add(tracklet3, mTimeFrame->getLines(rofId)[tracklet3]);
441 usedTracklets[tracklet3] = true;
442 tmpVertex = mTimeFrame->getTrackletClusters(rofId).back().getVertex();
443 }
444 }
445 break;
446 }
447 }
448 }
449 if (mVrtParams[iteration].allowSingleContribClusters) {
450 auto beamLine = Line{{mTimeFrame->getBeamX(), mTimeFrame->getBeamY(), -50.f}, {mTimeFrame->getBeamX(), mTimeFrame->getBeamY(), 50.f}}; // use beam position as contributor
451 for (size_t iLine{0}; iLine < numTracklets; ++iLine) {
452 if (!usedTracklets[iLine]) {
453 auto dca = Line::getDCA(mTimeFrame->getLines(rofId)[iLine], beamLine);
454 if (dca < mVrtParams[iteration].pairCut) {
455 mTimeFrame->getTrackletClusters(rofId).emplace_back(iLine, mTimeFrame->getLines(rofId)[iLine], -1, beamLine); // beamline must be passed as second line argument
456 }
457 }
458 }
459 }
460
461 // Cluster merging
462 std::sort(mTimeFrame->getTrackletClusters(rofId).begin(), mTimeFrame->getTrackletClusters(rofId).end(),
463 [](ClusterLines& cluster1, ClusterLines& cluster2) { return cluster1.getSize() > cluster2.getSize(); });
464 noClustersVec[rofId] = static_cast<int>(mTimeFrame->getTrackletClusters(rofId).size());
465 for (int iCluster1{0}; iCluster1 < noClustersVec[rofId]; ++iCluster1) {
466 std::array<float, 3> vertex1{mTimeFrame->getTrackletClusters(rofId)[iCluster1].getVertex()};
467 std::array<float, 3> vertex2{};
468 for (int iCluster2{iCluster1 + 1}; iCluster2 < noClustersVec[rofId]; ++iCluster2) {
469 vertex2 = mTimeFrame->getTrackletClusters(rofId)[iCluster2].getVertex();
470 if (o2::gpu::GPUCommonMath::Abs(vertex1[2] - vertex2[2]) < mVrtParams[iteration].clusterCut) {
471 float distance{(vertex1[0] - vertex2[0]) * (vertex1[0] - vertex2[0]) +
472 (vertex1[1] - vertex2[1]) * (vertex1[1] - vertex2[1]) +
473 (vertex1[2] - vertex2[2]) * (vertex1[2] - vertex2[2])};
474 if (distance < mVrtParams[iteration].pairCut * mVrtParams[iteration].pairCut) {
475 for (auto label : mTimeFrame->getTrackletClusters(rofId)[iCluster2].getLabels()) {
476 mTimeFrame->getTrackletClusters(rofId)[iCluster1].add(label, mTimeFrame->getLines(rofId)[label]);
477 vertex1 = mTimeFrame->getTrackletClusters(rofId)[iCluster1].getVertex();
478 }
479 mTimeFrame->getTrackletClusters(rofId).erase(mTimeFrame->getTrackletClusters(rofId).begin() + iCluster2);
480 --iCluster2;
481 --noClustersVec[rofId];
482 }
483 }
484 }
485 }
486 }
487 for (int rofId{0}; rofId < mTimeFrame->getNrof(); ++rofId) {
488 vertices.clear();
489 std::sort(mTimeFrame->getTrackletClusters(rofId).begin(), mTimeFrame->getTrackletClusters(rofId).end(),
490 [](ClusterLines& cluster1, ClusterLines& cluster2) { return cluster1.getSize() > cluster2.getSize(); }); // ensure clusters are ordered by contributors, so that we can cat after the first.
491#ifdef VTX_DEBUG
492 for (auto& cl : mTimeFrame->getTrackletClusters(rofId)) {
493 dbg_clusLines[rofId].push_back(cl);
494 }
495#endif
496 bool atLeastOneFound{false};
497 for (int iCluster{0}; iCluster < noClustersVec[rofId]; ++iCluster) {
498 bool lowMultCandidate{false};
499 double beamDistance2{(mTimeFrame->getBeamX() - mTimeFrame->getTrackletClusters(rofId)[iCluster].getVertex()[0]) * (mTimeFrame->getBeamX() - mTimeFrame->getTrackletClusters(rofId)[iCluster].getVertex()[0]) +
500 (mTimeFrame->getBeamY() - mTimeFrame->getTrackletClusters(rofId)[iCluster].getVertex()[1]) * (mTimeFrame->getBeamY() - mTimeFrame->getTrackletClusters(rofId)[iCluster].getVertex()[1])};
501 if (atLeastOneFound && (lowMultCandidate = mTimeFrame->getTrackletClusters(rofId)[iCluster].getSize() < mVrtParams[iteration].clusterContributorsCut)) { // We might have pile up with nContr > cut.
502 lowMultCandidate &= (beamDistance2 < mVrtParams[iteration].lowMultBeamDistCut * mVrtParams[iteration].lowMultBeamDistCut);
503 if (!lowMultCandidate) { // Not the first cluster and not a low multiplicity candidate, we can remove it
504 mTimeFrame->getTrackletClusters(rofId).erase(mTimeFrame->getTrackletClusters(rofId).begin() + iCluster);
505 noClustersVec[rofId]--;
506 continue;
507 }
508 }
509
510 if (beamDistance2 < nsigmaCut && o2::gpu::GPUCommonMath::Abs(mTimeFrame->getTrackletClusters(rofId)[iCluster].getVertex()[2]) < mVrtParams[iteration].maxZPositionAllowed) {
511 atLeastOneFound = true;
512 vertices.emplace_back(o2::math_utils::Point3D<float>(mTimeFrame->getTrackletClusters(rofId)[iCluster].getVertex()[0],
513 mTimeFrame->getTrackletClusters(rofId)[iCluster].getVertex()[1],
514 mTimeFrame->getTrackletClusters(rofId)[iCluster].getVertex()[2]),
515 mTimeFrame->getTrackletClusters(rofId)[iCluster].getRMS2(), // Symm matrix. Diagonal: RMS2 components,
516 // off-diagonal: square mean of projections on planes.
517 mTimeFrame->getTrackletClusters(rofId)[iCluster].getSize(), // Contributors
518 mTimeFrame->getTrackletClusters(rofId)[iCluster].getAvgDistance2()); // In place of chi2
519
520 if (iteration) {
521 vertices.back().setFlags(Vertex::UPCMode);
522 }
523 vertices.back().setTimeStamp(mTimeFrame->getTrackletClusters(rofId)[iCluster].getROF());
525 std::vector<o2::MCCompLabel> labels;
526 for (auto& index : mTimeFrame->getTrackletClusters(rofId)[iCluster].getLabels()) {
527 labels.push_back(mTimeFrame->getLinesLabel(rofId)[index]); // then we can use nContributors from vertices to get the labels
528 }
529 polls.push_back(computeMain(labels));
530 }
531 }
532 }
533 if (!iteration) {
534 mTimeFrame->addPrimaryVertices(vertices, rofId, iteration);
537 }
538 } else {
539 mTimeFrame->addPrimaryVerticesInROF(vertices, rofId, iteration);
542 }
543 }
544 if (!vertices.size() && !(iteration && (int)mTimeFrame->getPrimaryVertices(rofId).size() > mVrtParams[iteration].vertPerRofThreshold)) {
546 }
547 }
548#ifdef VTX_DEBUG
549 TFile* dbg_file = TFile::Open("artefacts_tf.root", "update");
550 TTree* ln_clus_lines_tree = new TTree("clusterlines", "tf");
551 std::vector<o2::its::ClusterLines> cl_lines_vec_pre(0);
552 std::vector<o2::its::ClusterLines> cl_lines_vec_post(0);
553 ln_clus_lines_tree->Branch("cllines_pre", &cl_lines_vec_pre);
554 ln_clus_lines_tree->Branch("cllines_post", &cl_lines_vec_post);
555 for (auto rofId{0}; rofId < mTimeFrame->getNrof(); ++rofId) {
556 cl_lines_vec_pre.clear();
557 cl_lines_vec_post.clear();
558 for (auto& clln : mTimeFrame->getTrackletClusters(rofId)) {
559 cl_lines_vec_post.push_back(clln);
560 }
561 for (auto& cl : dbg_clusLines[rofId]) {
562 cl_lines_vec_pre.push_back(cl);
563 }
564 ln_clus_lines_tree->Fill();
565 }
566 dbg_file->cd();
567 ln_clus_lines_tree->Write();
568 dbg_file->Close();
569#endif
570}
571
573{
574#ifdef WITH_OPENMP
575 mNThreads = n > 0 ? n : 1;
576#else
577 mNThreads = 1;
578#endif
579 LOGP(info, "Setting seeding vertexer with {} threads.", mNThreads);
580}
581
583 gsl::span<const o2::its::Line>& lines,
584 std::vector<bool>& usedLines,
585 std::vector<o2::its::ClusterLines>& clusterLines,
586 std::array<float, 2>& beamPosXY,
587 std::vector<Vertex>& vertices,
588 std::vector<int>& verticesInRof,
589 TimeFrame* tf,
590 std::vector<o2::MCCompLabel>* labels,
591 const int iteration)
592{
593 int foundVertices{0};
594 auto nsigmaCut{std::min(mVrtParams[iteration].vertNsigmaCut * mVrtParams[iteration].vertNsigmaCut * (mVrtParams[iteration].vertRadiusSigma * mVrtParams[iteration].vertRadiusSigma + mVrtParams[iteration].trackletSigma * mVrtParams[iteration].trackletSigma), 1.98f)};
595 const int numTracklets{static_cast<int>(lines.size())};
596 for (int line1{0}; line1 < numTracklets; ++line1) {
597 if (usedLines[line1]) {
598 continue;
599 }
600 for (int line2{line1 + 1}; line2 < numTracklets; ++line2) {
601 if (usedLines[line2]) {
602 continue;
603 }
604 auto dca{Line::getDCA(lines[line1], lines[line2])};
605 if (dca < mVrtParams[iteration].pairCut) {
606 clusterLines.emplace_back(line1, lines[line1], line2, lines[line2]);
607 std::array<float, 3> tmpVertex{clusterLines.back().getVertex()};
608 if (tmpVertex[0] * tmpVertex[0] + tmpVertex[1] * tmpVertex[1] > 4.f) {
609 clusterLines.pop_back();
610 break;
611 }
612 usedLines[line1] = true;
613 usedLines[line2] = true;
614 for (int tracklet3{0}; tracklet3 < numTracklets; ++tracklet3) {
615 if (usedLines[tracklet3]) {
616 continue;
617 }
618 if (Line::getDistanceFromPoint(lines[tracklet3], tmpVertex) < mVrtParams[iteration].pairCut) {
619 clusterLines.back().add(tracklet3, lines[tracklet3]);
620 usedLines[tracklet3] = true;
621 tmpVertex = clusterLines.back().getVertex();
622 }
623 }
624 break;
625 }
626 }
627 }
628
629 if (mVrtParams[iteration].allowSingleContribClusters) {
630 auto beamLine = Line{{tf->getBeamX(), tf->getBeamY(), -50.f}, {tf->getBeamX(), tf->getBeamY(), 50.f}}; // use beam position as contributor
631 for (size_t iLine{0}; iLine < numTracklets; ++iLine) {
632 if (!usedLines[iLine]) {
633 auto dca = Line::getDCA(lines[iLine], beamLine);
634 if (dca < mVrtParams[iteration].pairCut) {
635 clusterLines.emplace_back(iLine, lines[iLine], -1, beamLine); // beamline must be passed as second line argument
636 }
637 }
638 }
639 }
640
641 // Cluster merging
642 std::sort(clusterLines.begin(), clusterLines.end(), [](ClusterLines& cluster1, ClusterLines& cluster2) { return cluster1.getSize() > cluster2.getSize(); });
643 size_t nClusters{clusterLines.size()};
644 for (int iCluster1{0}; iCluster1 < nClusters; ++iCluster1) {
645 std::array<float, 3> vertex1{clusterLines[iCluster1].getVertex()};
646 std::array<float, 3> vertex2{};
647 for (int iCluster2{iCluster1 + 1}; iCluster2 < nClusters; ++iCluster2) {
648 vertex2 = clusterLines[iCluster2].getVertex();
649 if (o2::gpu::GPUCommonMath::Abs(vertex1[2] - vertex2[2]) < mVrtParams[iteration].clusterCut) {
650 float distance{(vertex1[0] - vertex2[0]) * (vertex1[0] - vertex2[0]) +
651 (vertex1[1] - vertex2[1]) * (vertex1[1] - vertex2[1]) +
652 (vertex1[2] - vertex2[2]) * (vertex1[2] - vertex2[2])};
653 if (distance < mVrtParams[iteration].pairCut * mVrtParams[iteration].pairCut) {
654 for (auto label : clusterLines[iCluster2].getLabels()) {
655 clusterLines[iCluster1].add(label, lines[label]);
656 vertex1 = clusterLines[iCluster1].getVertex();
657 }
658 clusterLines.erase(clusterLines.begin() + iCluster2);
659 --iCluster2;
660 --nClusters;
661 }
662 }
663 }
664 }
665
666 std::sort(clusterLines.begin(), clusterLines.end(),
667 [](ClusterLines& cluster1, ClusterLines& cluster2) { return cluster1.getSize() > cluster2.getSize(); }); // ensure clusters are ordered by contributors, so that we can cut after the first.
668 bool atLeastOneFound{false};
669 for (int iCluster{0}; iCluster < nClusters; ++iCluster) {
670 bool lowMultCandidate{false};
671 double beamDistance2{(tf->getBeamX() - clusterLines[iCluster].getVertex()[0]) * (tf->getBeamX() - clusterLines[iCluster].getVertex()[0]) +
672 (tf->getBeamY() - clusterLines[iCluster].getVertex()[1]) * (tf->getBeamY() - clusterLines[iCluster].getVertex()[1])};
673
674 if (atLeastOneFound && (lowMultCandidate = clusterLines[iCluster].getSize() < mVrtParams[iteration].clusterContributorsCut)) { // We might have pile up with nContr > cut.
675 lowMultCandidate &= (beamDistance2 < mVrtParams[iteration].lowMultBeamDistCut * mVrtParams[iteration].lowMultBeamDistCut);
676 if (!lowMultCandidate) { // Not the first cluster and not a low multiplicity candidate, we can remove it
677 clusterLines.erase(clusterLines.begin() + iCluster);
678 nClusters--;
679 continue;
680 }
681 }
682 if (beamDistance2 < nsigmaCut && o2::gpu::GPUCommonMath::Abs(clusterLines[iCluster].getVertex()[2]) < mVrtParams[iteration].maxZPositionAllowed) {
683 atLeastOneFound = true;
684 ++foundVertices;
685 vertices.emplace_back(o2::math_utils::Point3D<float>(clusterLines[iCluster].getVertex()[0],
686 clusterLines[iCluster].getVertex()[1],
687 clusterLines[iCluster].getVertex()[2]),
688 clusterLines[iCluster].getRMS2(), // Symm matrix. Diagonal: RMS2 components,
689 // off-diagonal: square mean of projections on planes.
690 clusterLines[iCluster].getSize(), // Contributors
691 clusterLines[iCluster].getAvgDistance2()); // In place of chi2
692 vertices.back().setTimeStamp(clusterLines[iCluster].getROF());
693 if (labels) {
694 for (auto& index : clusterLines[iCluster].getLabels()) {
695 labels->push_back(tf->getLinesLabel(rofId)[index]); // then we can use nContributors from vertices to get the labels
696 }
697 }
698 }
699 }
700 verticesInRof.push_back(foundVertices);
701}
702} // namespace its
703} // namespace o2
Mode
Definition Utils.h:89
Class to compute the primary vertex in ITS from tracklets.
int nClusters
void setTrackingParameters(const T &params)
float getInverseZCoordinate(const int layerIndex) const
gsl::span< const Vertex > getPrimaryVertices(int rofId) const
Definition TimeFrame.h:355
std::vector< ClusterLines > & getTrackletClusters(int rofId)
Definition TimeFrame.h:543
void addPrimaryVerticesInROF(const std::vector< Vertex > &vertices, const int rofId, const int iteration)
int getSortedIndex(int rofId, int layer, int i) const
Definition TimeFrame.h:391
void addPrimaryVerticesLabels(std::vector< std::pair< MCCompLabel, float > > &labels)
Definition TimeFrame.cxx:96
void computeTrackletsPerROFScans()
bool hasMCinformation() const
Definition TimeFrame.h:565
std::vector< std::vector< Tracklet > > & getTracklets()
Definition TimeFrame.h:582
std::vector< std::vector< Cluster > > & getClusters()
Definition TimeFrame.h:638
gsl::span< int > getIndexTable(int rofId, int layerId)
Definition TimeFrame.h:529
uint32_t getTotalTrackletsTF(const int iLayer)
Definition TimeFrame.h:204
gsl::span< int > getExclusiveNTrackletsCluster(int rofId, int combId)
Definition TimeFrame.h:618
gsl::span< unsigned char > getUsedClustersROF(int rofId, int layerId)
Definition TimeFrame.h:431
gsl::span< int > getNTrackletsCluster(int rofId, int combId)
Definition TimeFrame.h:609
float getBeamY() const
Definition TimeFrame.h:406
gsl::span< Cluster > getClustersOnLayer(int rofId, int layerId)
Definition TimeFrame.h:413
int getNrof() const
Definition TimeFrame.h:395
std::vector< MCCompLabel > & getTrackletsLabel(int layer)
Definition TimeFrame.h:141
void addPrimaryVerticesLabelsInROF(const std::vector< std::pair< MCCompLabel, float > > &labels, const int rofId)
std::vector< MCCompLabel > & getLinesLabel(const int rofId)
Definition TimeFrame.h:171
gsl::span< const MCCompLabel > getLabelsFoundTracklets(int rofId, int combId) const
Definition TimeFrame.h:678
void addPrimaryVertices(const std::vector< Vertex > &vertices)
Definition TimeFrame.cxx:77
unsigned int & getNoVertexROF()
Definition TimeFrame.h:207
float getBeamX() const
Definition TimeFrame.h:404
gsl::span< const Tracklet > getFoundTracklets(int rofId, int combId) const
Definition TimeFrame.h:669
std::vector< Line > & getLines(int rofId)
Definition TimeFrame.h:538
int & getNTrackletsROF(int rofId, int combId)
Definition TimeFrame.h:628
const gsl::span< const MCCompLabel > getClusterLabels(int layerId, const Cluster &cl) const
Definition TimeFrame.h:509
virtual void computeTrackletMatching(const int iteration=0)
virtual void updateVertexingParameters(const std::vector< VertexingParameters > &vrtPar, const TimeFrameGPUParameters &gpuTfPar)
void computeVerticesInRof(int, gsl::span< const o2::its::Line > &, std::vector< bool > &, std::vector< o2::its::ClusterLines > &, std::array< float, 2 > &, std::vector< Vertex > &, std::vector< int > &, TimeFrame *, std::vector< o2::MCCompLabel > *, const int iteration=0)
virtual void computeTracklets(const int iteration=0)
static std::pair< T, float > computeMain(const std::vector< T > &elements)
static const std::vector< std::pair< int, int > > selectClusters(const int *indexTable, const std::array< int, 4 > &selectedBinsRect, const IndexTableUtils &utils)
std::vector< VertexingParameters > mVrtParams
virtual void computeVertices(const int iteration=0)
IndexTableUtils mIndexTableUtils
GLdouble n
Definition glcorearb.h:1982
GLuint index
Definition glcorearb.h:781
GLboolean GLboolean GLboolean b
Definition glcorearb.h:1233
GLsizei GLsizei GLfloat distance
Definition glcorearb.h:5506
GLuint GLsizei const GLchar * label
Definition glcorearb.h:2519
GLboolean GLboolean GLboolean GLboolean a
Definition glcorearb.h:1233
constexpr float Pi
Definition Constants.h:43
constexpr float TwoPi
Definition Constants.h:44
void trackletSelectionKernelHost(const gsl::span< const Cluster > clusters0, const gsl::span< const Cluster > clusters1, gsl::span< unsigned char > usedClusters0, gsl::span< unsigned char > usedClusters2, const gsl::span< const Tracklet > &tracklets01, const gsl::span< const Tracklet > &tracklets12, std::vector< bool > &usedTracklets, const gsl::span< int > foundTracklets01, const gsl::span< int > foundTracklets12, std::vector< Line > &lines, const gsl::span< const MCCompLabel > &trackletLabels, std::vector< MCCompLabel > &linesLabels, const short pivotRofId, const short targetRofId, const float tanLambdaCut=0.025f, const float phiCut=0.005f, const int maxTracklets=static_cast< int >(1e2))
void trackleterKernelHost(const gsl::span< const Cluster > &clustersNextLayer, const gsl::span< const Cluster > &clustersCurrentLayer, const gsl::span< unsigned char > &usedClustersNextLayer, int *indexTableNext, const float phiCut, std::vector< Tracklet > &tracklets, gsl::span< int > foundTracklets, const IndexTableUtils &utils, const short pivotRof, const short targetRof, gsl::span< int > rofFoundTrackletsOffsets, const int maxTrackletsPerCluster=static_cast< int >(2e3))
float smallestAngleDifference(float a, float b)
a couple of static helper functions to create timestamp values for CCDB queries or override obsolete ...
Common utility functions.
std::unique_ptr< GPUReconstructionTimeframe > tf
int32_t w
const Cluster const Cluster *static float getDistanceFromPoint(const Line &line, const std::array< float, 3 > &point)
std::vector< Tracklet64 > tracklets