Skip to content

Commit b09e484

Browse files
committed
ITS: fishbone cleanup
Signed-off-by: Felix Schlepper <felix.schlepper@cern.ch>
1 parent 22b8053 commit b09e484

10 files changed

Lines changed: 287 additions & 57 deletions

File tree

Detectors/ITSMFT/ITS/tracking/include/ITStracking/Configuration.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -80,6 +80,8 @@ struct TrackingParameters {
8080
float PVres = 1.e-2f;
8181
/// Trackleting cuts
8282
float TrackletMinPt = 0.3f;
83+
LayerMask FishboneCleaningLayerMask = 0;
84+
float FishboneAngularCut = 0.0031623f;
8385
/// Cell finding cuts
8486
float CellDeltaTanLambdaSigma = 0.007f;
8587
/// Fitter parameters
Lines changed: 105 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,105 @@
1+
// Copyright 2019-2026 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.
11+
///
12+
/// \file Fishbone.h
13+
/// \brief Helpers and bookkeeping for fishbone tracklet cleaning.
14+
///
15+
16+
#ifndef TRACKINGITSU_INCLUDE_FISHBONE_H_
17+
#define TRACKINGITSU_INCLUDE_FISHBONE_H_
18+
19+
#include "ITStracking/LayerMask.h"
20+
#include "ITStracking/Cluster.h"
21+
#include "ITStracking/MathUtils.h"
22+
#include "ITStracking/Constants.h"
23+
24+
namespace o2::its
25+
{
26+
27+
struct Fishbone {
28+
29+
GPUhdi() static bool isLinkEnabled(LayerMask mask, int fromLayer, int toLayer)
30+
{
31+
return mask.has(fromLayer) && mask.has(toLayer);
32+
}
33+
34+
GPUhdi() static float openingAngle2(const Cluster& a, const Cluster& b, const Cluster& c, const Cluster& d)
35+
{
36+
const float ux = b.xCoordinate - a.xCoordinate;
37+
const float uy = b.yCoordinate - a.yCoordinate;
38+
const float uz = b.zCoordinate - a.zCoordinate;
39+
const float vx = d.xCoordinate - c.xCoordinate;
40+
const float vy = d.yCoordinate - c.yCoordinate;
41+
const float vz = d.zCoordinate - c.zCoordinate;
42+
const float uLenSq = math_utils::SqSum(ux, uy, uz);
43+
const float vLenSq = math_utils::SqSum(vx, vy, vz);
44+
if (uLenSq <= constants::Tolerance || vLenSq <= constants::Tolerance) {
45+
return 0.0f;
46+
}
47+
const float cx = (uy * vz) - (uz * vy);
48+
const float cy = (uz * vx) - (ux * vz);
49+
const float cz = (ux * vy) - (uy * vx);
50+
const float crossSq = math_utils::SqSum(cx, cy, cz);
51+
return crossSq / (uLenSq * vLenSq);
52+
}
53+
54+
GPUhdi() static float openingAngle(const Cluster& a, const Cluster& b, const Cluster& c, const Cluster& d)
55+
{
56+
return o2::gpu::CAMath::Sqrt(openingAngle2(a, b, c, d));
57+
}
58+
59+
struct FishboneClusterLink {
60+
int fromLayer{constants::UnusedIndex};
61+
int survivorFromClusterId{constants::UnusedIndex};
62+
int toLayer{constants::UnusedIndex};
63+
int survivorToClusterId{constants::UnusedIndex};
64+
int killedFromClusterId{constants::UnusedIndex};
65+
};
66+
67+
struct FishboneCandidate {
68+
int trackletIndex{constants::UnusedIndex};
69+
int firstClusterIndex{constants::UnusedIndex};
70+
int secondClusterIndex{constants::UnusedIndex};
71+
float length2{0.f};
72+
};
73+
74+
struct FishboneGroup {
75+
int begin{0};
76+
int end{0};
77+
};
78+
79+
struct FishboneCandidateOrder {
80+
GPUhdi() bool operator()(const FishboneCandidate& left, const FishboneCandidate& right) const
81+
{
82+
if (left.secondClusterIndex != right.secondClusterIndex) {
83+
return left.secondClusterIndex < right.secondClusterIndex;
84+
}
85+
if (left.length2 != right.length2) {
86+
return left.length2 > right.length2;
87+
}
88+
return left.firstClusterIndex < right.firstClusterIndex;
89+
}
90+
};
91+
92+
struct FishboneLinkOrder {
93+
GPUhdi() bool operator()(const FishboneClusterLink& left, const FishboneClusterLink& right) const
94+
{
95+
if (left.survivorFromClusterId != right.survivorFromClusterId) {
96+
return left.survivorFromClusterId < right.survivorFromClusterId;
97+
}
98+
return left.survivorToClusterId < right.survivorToClusterId;
99+
}
100+
};
101+
};
102+
103+
} // namespace o2::its
104+
105+
#endif

Detectors/ITSMFT/ITS/tracking/include/ITStracking/TimeFrame.h

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@
2727
#include "ITStracking/Cluster.h"
2828
#include "ITStracking/Configuration.h"
2929
#include "ITStracking/ClusterLines.h"
30+
#include "ITStracking/Fishbone.h"
3031
#include "ITStracking/Tracklet.h"
3132
#include "ITStracking/IndexTableUtils.h"
3233
#include "ITStracking/ExternalAllocator.h"
@@ -192,6 +193,8 @@ struct TimeFrame {
192193

193194
auto& getTracklets() { return mTracklets; }
194195
auto& getTrackletsLookupTable() { return mTrackletsLookupTable; }
196+
auto& getFishboneClusterLinks() { return mFishboneClusterLinks; }
197+
const auto& getFishboneClusterLinks() const { return mFishboneClusterLinks; }
195198

196199
auto& getClusters() { return mClusters; }
197200
auto& getUnsortedClusters() { return mUnsortedClusters; }
@@ -220,9 +223,6 @@ struct TimeFrame {
220223
/// memory management
221224
void setMemoryPool(std::shared_ptr<BoundedMemoryResource> pool);
222225
auto& getMemoryPool() const noexcept { return mMemoryPool; }
223-
bool checkMemory(unsigned long max) { return getArtefactsMemory() < max; }
224-
unsigned long getArtefactsMemory() const;
225-
void printArtefactsMemory() const;
226226

227227
/// staggering
228228
void setIsStaggered(bool b) noexcept { mIsStaggered = b; }
@@ -281,6 +281,7 @@ struct TimeFrame {
281281

282282
std::array<bounded_vector<Cluster>, NLayers> mUnsortedClusters;
283283
std::vector<bounded_vector<Tracklet>> mTracklets;
284+
std::vector<bounded_vector<Fishbone::FishboneClusterLink>> mFishboneClusterLinks;
284285
std::vector<bounded_vector<CellSeed>> mCells;
285286
bounded_vector<TrackITSExt> mTracks;
286287
bounded_vector<MCCompLabel> mTracksLabel;

Detectors/ITSMFT/ITS/tracking/include/ITStracking/TrackerTraits.h

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -88,7 +88,8 @@ class TrackerTraits
8888
std::shared_ptr<BoundedMemoryResource> mMemoryPool;
8989
std::shared_ptr<tbb::task_arena> mTaskArena;
9090

91-
protected:
91+
void cleanFishboneTracklets(int iteration, int linkId);
92+
9293
struct TrackFollowerScratch {
9394
explicit TrackFollowerScratch(std::pmr::memory_resource* memoryResource)
9495
: activeHypotheses(memoryResource), nextHypotheses(memoryResource)
@@ -106,11 +107,11 @@ class TrackerTraits
106107
const Cluster* const* unsortedClusters,
107108
const o2::base::Propagator* propagator);
108109

110+
protected:
109111
o2::gpu::GPUChainITS* mChain = nullptr;
110112
TimeFrame<NLayers>* mTimeFrame;
111113
std::vector<TrackingParameters> mTrkParams;
112-
113-
float mBz{-999.f};
114+
float mBz{constants::UnsetValue};
114115
};
115116

116117
} // namespace its

Detectors/ITSMFT/ITS/tracking/include/ITStracking/TrackingConfigParam.h

Lines changed: 19 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -63,39 +63,41 @@ struct VertexerParamConfig : public o2::conf::ConfigurableParamHelper<VertexerPa
6363
};
6464

6565
struct TrackerParamConfig : public o2::conf::ConfigurableParamHelper<TrackerParamConfig> {
66-
static const int MinTrackLength = 4;
67-
static const int MaxTrackLength = 7;
66+
static constexpr int MinTrackLength = 4;
67+
static constexpr int MaxTrackLength = 7;
6868

6969
bool useMatCorrTGeo = false; // use full geometry to corect for material budget accounting in the fits. Default is to use the material budget LUT.
7070
bool useFastMaterial = false; // use faster material approximation for material budget accounting in the fits.
7171
int addTimeError[7] = {0}; // configure the width of the window in BC to be considered for the tracking.
7272
int minTrackLgtIter[constants::MaxIter] = {}; // minimum track length at each iteration, used only if >0, otherwise use code defaults
7373
uint8_t startLayerMask[constants::MaxIter] = {}; // mask of start layer for this iteration (if >0)
7474
int maxHolesIter[constants::MaxIter] = {}; // maximum number of missing internal layers allowed in the CA topology for each iteration
75-
uint16_t holeLayerMaskIter[constants::MaxIter] = {}; // layers that may be skipped by the CA topology for each iteration
75+
uint8_t holeLayerMaskIter[constants::MaxIter] = {}; // layers that may be skipped by the CA topology for each iteration
76+
uint8_t fishboneCleaningLayerMaskIter[constants::MaxIter] = {}; // layers enabled for tracklet fishbone cleaning in each iteration
7677
float minPtIterLgt[constants::MaxIter * (MaxTrackLength - MinTrackLength + 1)] = {}; // min.pT for given track length at this iteration, used only if >0, otherwise use code defaults
77-
float sysErrY2[7] = {0}; // systematic error^2 in Y per layer
78-
float sysErrZ2[7] = {0}; // systematic error^2 in Z per layer
78+
float sysErrY2[MaxTrackLength] = {0}; // systematic error^2 in Y per layer
79+
float sysErrZ2[MaxTrackLength] = {0}; // systematic error^2 in Z per layer
7980
float maxChi2ClusterAttachment = -1.f;
8081
float maxChi2NDF = -1.f;
8182
float nSigmaCut = -1.f;
8283
float deltaTanLres = -1.f;
8384
float minPt = -1.f;
85+
float fishboneAngularCut = 0.0031623f;
8486
float pvRes = -1.f;
8587
int LUTbinsPhi = -1;
8688
int LUTbinsZ = -1;
87-
float diamondPos[3] = {0.f, 0.f, 0.f}; // override the position of the vertex
88-
bool useDiamond = false; // enable overriding the vertex position
89-
bool perPrimaryVertexProcessing = false; // perform the full tracking considering the vertex hypotheses one at the time.
90-
bool saveTimeBenchmarks = false; // dump metrics on file
91-
bool overrideBeamEstimation = false; // use beam position from meanVertex CCDB object
92-
int trackingMode = -1; // -1: unset, 0=sync, 1=async, 2=cosmics used by gpuwf only
93-
bool doUPCIteration = false; // Perform an additional iteration for UPC events on tagged vertices. You want to combine this config with VertexerParamConfig.nIterations=2
94-
int nIterations = constants::MaxIter; // overwrite the number of iterations
95-
int reseedIfShorter = 6; // for the final refit reseed the track with circle if they are shorter than this value
96-
bool shiftRefToCluster{true}; // TrackFit: after update shift the linearization reference to cluster
97-
bool repeatRefitOut{false}; // repeat outward refit using inward refit as a seed
98-
bool createArtefactLabels{false}; // create on-the-fly labels for the artefacts
89+
float diamondPos[3] = {0.f, 0.f, 0.f}; // override the position of the vertex
90+
bool useDiamond = false; // enable overriding the vertex position
91+
bool perPrimaryVertexProcessing = false; // perform the full tracking considering the vertex hypotheses one at the time.
92+
bool saveTimeBenchmarks = false; // dump metrics on file
93+
bool overrideBeamEstimation = false; // use beam position from meanVertex CCDB object
94+
int trackingMode = -1; // -1: unset, 0=sync, 1=async, 2=cosmics used by gpuwf only
95+
bool doUPCIteration = false; // Perform an additional iteration for UPC events on tagged vertices. You want to combine this config with VertexerParamConfig.nIterations=2
96+
int nIterations = constants::MaxIter; // overwrite the number of iterations
97+
int reseedIfShorter = MaxTrackLength - 1; // for the final refit reseed the track with circle if they are shorter than this value
98+
bool shiftRefToCluster{true}; // TrackFit: after update shift the linearization reference to cluster
99+
bool repeatRefitOut{false}; // repeat outward refit using inward refit as a seed
100+
bool createArtefactLabels{false}; // create on-the-fly labels for the artefacts
99101
bool trackFollowerTop[constants::MaxIter] = {};
100102
bool trackFollowerBot[constants::MaxIter] = {};
101103
float trackFollowerNSigmaCutZ = 1.f;

Detectors/ITSMFT/ITS/tracking/include/ITStracking/Tracklet.h

Lines changed: 18 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,8 @@
1616
#ifndef TRACKINGITS_INCLUDE_TRACKLET_H_
1717
#define TRACKINGITS_INCLUDE_TRACKLET_H_
1818

19+
#include <cstdint>
20+
1921
#include "ITStracking/Constants.h"
2022
#include "DataFormatsITS/TimeEstBC.h"
2123
#include "ITStracking/Cluster.h"
@@ -29,6 +31,12 @@ namespace o2::its
2931

3032
// tracklets are entirely determined by their two cluster idx
3133
struct Tracklet final {
34+
enum Status : uint8_t {
35+
Live = 0,
36+
FishboneSurvivor = 1,
37+
FishboneKilled = 2
38+
};
39+
3240
GPUhdDefault() Tracklet() = default;
3341
GPUhdi() Tracklet(const int firstClusterOrderingIndex, const int secondClusterOrderingIndex,
3442
const Cluster& firstCluster, const Cluster& secondCluster, const TimeEstBC& t)
@@ -53,6 +61,14 @@ struct Tracklet final {
5361
return firstClusterIndex == o.firstClusterIndex && secondClusterIndex == o.secondClusterIndex;
5462
}
5563
GPUhdi() bool isCompatible(const Tracklet& o) const { return mTime.isCompatible(o.mTime); }
64+
GPUhdi() bool isFishboneKilled() const { return mStatus == FishboneKilled; }
65+
GPUhdi() void markFishboneSurvivor()
66+
{
67+
if (mStatus != FishboneKilled) {
68+
mStatus = FishboneSurvivor;
69+
}
70+
}
71+
GPUhdi() void markFishboneKilled() { mStatus = FishboneKilled; }
5672
GPUhd() void print() const
5773
{
5874
LOGP(info, "TRKLT: fClIdx:{} sClIdx:{} ts:{}+/-{} TgL={} Phi={}", firstClusterIndex, secondClusterIndex, mTime.getTimeStamp(), mTime.getTimeStampError(), tanLambda, phi);
@@ -65,8 +81,9 @@ struct Tracklet final {
6581
float tanLambda{constants::UnsetValue};
6682
float phi{constants::UnsetValue};
6783
TimeEstBC mTime;
84+
uint8_t mStatus{Live};
6885

69-
ClassDefNV(Tracklet, 1);
86+
ClassDefNV(Tracklet, 2);
7087
};
7188

7289
} // namespace o2::its

Detectors/ITSMFT/ITS/tracking/src/Configuration.cxx

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -59,6 +59,9 @@ std::string TrackingParameters::asString() const
5959
if (MaxHoles) {
6060
str += std::format(" MaxHoles:{} HoleMask:{}", MaxHoles, HoleLayerMask.asString());
6161
}
62+
if (!FishboneCleaningLayerMask.empty()) {
63+
str += std::format(" FishboneMask:{} FishboneAngularCut:{:.6f}", FishboneCleaningLayerMask.asString(), FishboneAngularCut);
64+
}
6265
if (PassFlags[IterationStep::TrackFollowerTop] || PassFlags[IterationStep::TrackFollowerBot]) {
6366
const bool top = PassFlags[IterationStep::TrackFollowerTop], bot = PassFlags[IterationStep::TrackFollowerBot];
6467
str += std::format(" TrackFollower:{} NSigmaZ/Phi:{:.2f}/{:.2f}",
@@ -219,6 +222,7 @@ std::vector<TrackingParameters> TrackingMode::getTrackingParameters(TrackingMode
219222
p.TrackFollowerNSigmaCutZ = tc.trackFollowerNSigmaCutZ;
220223
p.TrackFollowerNSigmaCutPhi = tc.trackFollowerNSigmaCutPhi;
221224
p.TrackFollowerMaxHypotheses = std::max(1, tc.trackFollowerMaxHypotheses);
225+
p.FishboneAngularCut = tc.fishboneAngularCut;
222226

223227
p.PrintMemory = tc.printMemory;
224228
p.MaxMemory = tc.maxMemory;
@@ -233,6 +237,7 @@ std::vector<TrackingParameters> TrackingMode::getTrackingParameters(TrackingMode
233237
if (iter < constants::MaxIter) {
234238
p.MaxHoles = tc.maxHolesIter[iter];
235239
p.HoleLayerMask = tc.holeLayerMaskIter[iter];
240+
p.FishboneCleaningLayerMask = tc.fishboneCleaningLayerMaskIter[iter];
236241
if (tc.trackFollowerTop[iter]) {
237242
p.PassFlags.set(IterationStep::TrackFollowerTop);
238243
}

Detectors/ITSMFT/ITS/tracking/src/TimeFrame.cxx

Lines changed: 2 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -377,31 +377,6 @@ void TimeFrame<NLayers>::initialise(const TrackingParameters& trkParam, const in
377377
}
378378
}
379379

380-
template <int NLayers>
381-
unsigned long TimeFrame<NLayers>::getArtefactsMemory() const
382-
{
383-
unsigned long size{0};
384-
for (const auto& trkl : mTracklets) {
385-
size += sizeof(Tracklet) * trkl.size();
386-
}
387-
for (const auto& cells : mCells) {
388-
size += sizeof(CellSeed) * cells.size();
389-
}
390-
for (const auto& cellsN : mCellsNeighbours) {
391-
size += sizeof(int) * cellsN.size();
392-
}
393-
for (const auto& cellsN : mCellsNeighboursTopology) {
394-
size += sizeof(int) * cellsN.size();
395-
}
396-
return size;
397-
}
398-
399-
template <int NLayers>
400-
void TimeFrame<NLayers>::printArtefactsMemory() const
401-
{
402-
LOGP(info, "TimeFrame: Artefacts occupy {:.2f} MB", getArtefactsMemory() / constants::MB);
403-
}
404-
405380
template <int NLayers>
406381
void TimeFrame<NLayers>::computeTrackletsPerROFScans()
407382
{
@@ -447,6 +422,7 @@ void TimeFrame<NLayers>::setMemoryPool(std::shared_ptr<BoundedMemoryResource> po
447422
initContainers(mTrackletsIndexROF);
448423
initVector(mTracks);
449424
initContainers(mTracklets);
425+
initContainers(mFishboneClusterLinks);
450426
initContainers(mCells);
451427
initContainers(mCellsNeighbours);
452428
initContainers(mCellsLookupTable);
@@ -478,6 +454,7 @@ void TimeFrame<NLayers>::wipe()
478454
resetTrackExtensionCounters();
479455
deepVectorClear(mTracks);
480456
deepVectorClear(mTracklets);
457+
deepVectorClear(mFishboneClusterLinks);
481458
deepVectorClear(mCells);
482459
deepVectorClear(mCellsNeighbours);
483460
deepVectorClear(mCellsNeighboursTopology);

Detectors/ITSMFT/ITS/tracking/src/Tracker.cxx

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -51,8 +51,8 @@ float Tracker<NLayers>::clustersToTracks(const LogFunc& logger, const LogFunc& e
5151
auto handleException = [&](const auto& err) {
5252
LOGP(error, "Too much memory in {} in iteration {} iVtx={}: {:.2f} GB. Current limit is {:.2f} GB, check the detector status and/or the selections.",
5353
StateNames[mCurStep], iteration, iVertex,
54-
(double)mTimeFrame->getArtefactsMemory() / GB,
55-
(double)mTrkParams[iteration].MaxMemory / GB);
54+
mTimeFrame->getMemoryPool()->getUsedMemory() / GB,
55+
mTimeFrame->getMemoryPool()->getMaxMemory() / GB);
5656
if (typeid(err) != typeid(std::bad_alloc)) { // only print if the exceptions is different from what is expected
5757
LOGP(error, "Exception: {}", err.what());
5858
}
@@ -125,6 +125,9 @@ float Tracker<NLayers>::clustersToTracks(const LogFunc& logger, const LogFunc& e
125125
template <int NLayers>
126126
void Tracker<NLayers>::computeTracksMClabels()
127127
{
128+
auto& trackLabels = mTimeFrame->getTracksLabel();
129+
trackLabels.clear();
130+
trackLabels.reserve(mTimeFrame->getTracks().size());
128131
for (auto& track : mTimeFrame->getTracks()) {
129132
std::vector<std::pair<MCCompLabel, size_t>> occurrences;
130133
occurrences.clear();
@@ -175,7 +178,7 @@ void Tracker<NLayers>::computeTracksMClabels()
175178
if (occurrences[0].second < track.getNumberOfClusters()) {
176179
maxOccurrencesValue.setFakeFlag();
177180
}
178-
mTimeFrame->getTracksLabel().emplace_back(maxOccurrencesValue);
181+
trackLabels.emplace_back(maxOccurrencesValue);
179182
}
180183
}
181184

0 commit comments

Comments
 (0)