Skip to content

Commit 122c0d8

Browse files
committed
Rationalise the track publication
1 parent a96d9fd commit 122c0d8

12 files changed

Lines changed: 521 additions & 874 deletions

File tree

‎Detectors/ITSMFT/ITS/workflow-ca/include/ITSCAWorkflow/CATrackerSpec.h‎

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -22,12 +22,10 @@
2222

2323
#include <gsl/span>
2424

25-
#include "DataFormatsITS/TrackITS.h"
2625
#include "DataFormatsITSMFT/ROFRecord.h"
2726
#include "DetectorsBase/GRPGeomHelper.h"
2827
#include "Framework/DataProcessorSpec.h"
2928
#include "Framework/Task.h"
30-
#include "ITSMFTTracking/GenericTrackOutputAdapter.h"
3129
#include "ITSMFTTracking/Configuration.h"
3230
#include "ITSCAWorkflow/ConfigPreflight.h"
3331
#include "ITSMFTTracking/ClusterDecoding.h"

‎Detectors/ITSMFT/ITS/workflow-ca/src/CATrackerSpec.cxx‎

Lines changed: 138 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@
2525

2626
#include <gsl/span>
2727

28+
#include "DataFormatsITS/TrackITS.h"
2829
#include "DataFormatsITSMFT/CompCluster.h"
2930
#include "DataFormatsITSMFT/DPLAlpideParam.h"
3031
#include "DataFormatsITSMFT/ROFRecord.h"
@@ -35,7 +36,7 @@
3536
#include "Framework/Logger.h"
3637
#include "ITSBase/GeometryTGeo.h"
3738
#include "ITSMFTTracking/Tracker.h"
38-
#include "ITSMFTTracking/GenericTrackOutputAdapter.h"
39+
#include "ITSMFTTracking/TrackPublicationHelpers.h"
3940
#include "ITSMFTTracking/IOUtils.h"
4041
#include "ITSMFTTracking/SurfaceTiming.h"
4142
#include "ITSMFTTracking/ITSMFTDetectorDefinitions.h"
@@ -72,6 +73,138 @@ constexpr std::array<LayerId, NLayers> detectorLocalToLayoutLayers()
7273

7374
inline constexpr auto kLayerToLayout = detectorLocalToLayoutLayers<ITSNLayers>();
7475

76+
struct TrackOutput {
77+
std::vector<o2::its::TrackITS> tracks;
78+
std::vector<int> clusterIndices;
79+
std::vector<o2::itsmft::ROFRecord> trackROFs;
80+
std::vector<o2::MCCompLabel> labels;
81+
};
82+
83+
bool exportTrackState(const SurfaceTrackState& source, o2::track::TrackParCovF& destination) noexcept
84+
{
85+
if (source.kind != SurfaceKind::Cylinder) {
86+
return false;
87+
}
88+
o2::track::TrackParCovF::params_t parameters{};
89+
o2::track::TrackParCovF::covMat_t covariance{};
90+
for (uint8_t i = 0; i < 5; ++i) {
91+
parameters[i] = source.parameters[i];
92+
}
93+
for (uint8_t i = 0; i < 15; ++i) {
94+
covariance[i] = source.covariance[i];
95+
}
96+
const o2::track::TrackParCovF scratch{source.referenceCoordinate, source.alpha, parameters, covariance, source.absCharge, source.pid};
97+
destination = scratch;
98+
return true;
99+
}
100+
101+
bool collectReferences(const TimeFrame& frame, const GenericTrack& common, std::vector<int>& outputIndices, o2::its::TrackITS& output,
102+
uint32_t& pattern,
103+
const std::vector<std::vector<uint32_t>>* externalIndicesBySurface,
104+
const std::vector<std::vector<uint32_t>>* clusterSizesBySurface)
105+
{
106+
constexpr uint32_t maxLayers = ITSNLayers;
107+
const auto& layerMapping = kLayerToLayout;
108+
const auto& references = frame.getTrackClusterIndices();
109+
std::array<const TrackClusterReference*, maxLayers> byLayer{};
110+
for (uint32_t ref = common.firstClusterRef; ref < common.clusterRefEnd; ++ref) {
111+
const auto& key = references[ref];
112+
if (!key.isValid()) {
113+
return false;
114+
}
115+
const auto where = std::find(layerMapping.begin(), layerMapping.end(), key.layer);
116+
if (where == layerMapping.end() || static_cast<uint32_t>(where - layerMapping.begin()) >= maxLayers) {
117+
return false;
118+
}
119+
const auto layer = static_cast<uint32_t>(where - layerMapping.begin());
120+
if (byLayer[layer] != nullptr) {
121+
return false;
122+
}
123+
byLayer[layer] = &key;
124+
}
125+
const int first = static_cast<int>(outputIndices.size());
126+
uint32_t count = 0;
127+
for (uint32_t layer = maxLayers; layer-- > 0;) {
128+
const auto* reference = byLayer[layer];
129+
if (reference == nullptr) {
130+
continue;
131+
}
132+
uint32_t externalIndex = reference->clusterId;
133+
if (externalIndicesBySurface != nullptr) {
134+
if (reference->layer.value() >= externalIndicesBySurface->size() ||
135+
reference->clusterId >= (*externalIndicesBySurface)[reference->layer.value()].size()) {
136+
return false;
137+
}
138+
externalIndex = (*externalIndicesBySurface)[reference->layer.value()][reference->clusterId];
139+
}
140+
if (externalIndex > static_cast<uint32_t>(std::numeric_limits<int>::max())) {
141+
return false;
142+
}
143+
if (clusterSizesBySurface == nullptr ||
144+
reference->layer.value() >= clusterSizesBySurface->size() ||
145+
reference->clusterId >= (*clusterSizesBySurface)[reference->layer.value()].size()) {
146+
return false;
147+
}
148+
outputIndices.push_back(static_cast<int>(externalIndex));
149+
output.setClusterSize(layer, (*clusterSizesBySurface)[reference->layer.value()][reference->clusterId]);
150+
pattern |= 1u << layer;
151+
++count;
152+
}
153+
output.setClusterRefs(first, static_cast<int>(count));
154+
return true;
155+
}
156+
157+
std::optional<TrackOutput> stageTrackOutput(const TimeFrame& frame,
158+
const TrackPublicationTimingContext& context,
159+
gsl::span<const uint8_t> sharedClusterFlags,
160+
bool withMC,
161+
const std::vector<std::vector<uint32_t>>* externalIndicesBySurface = nullptr,
162+
const std::vector<std::vector<uint32_t>>* clusterSizesBySurface = nullptr)
163+
{
164+
const auto selection = selectGenericTracksForSurfaces(frame, kLayerToLayout);
165+
if (!selection) {
166+
return std::nullopt;
167+
}
168+
if (withMC && frame.getTrackLabels().size() != frame.getGenericTracks().size()) {
169+
return std::nullopt;
170+
}
171+
const auto ordered = makeLegacyOutputOrder(frame, *selection, context.clock);
172+
if (!ordered) {
173+
return std::nullopt;
174+
}
175+
TrackOutput staged;
176+
staged.trackROFs.assign(context.inputROFs.begin(), context.inputROFs.end());
177+
staged.tracks.reserve(ordered->size());
178+
staged.labels.reserve(withMC ? ordered->size() : 0);
179+
std::vector<o2::its::TimeStamp> times;
180+
times.reserve(ordered->size());
181+
for (const auto& orderedTrack : *ordered) {
182+
const auto index = orderedTrack.globalIndex;
183+
o2::track::TrackParCovF inner, outer;
184+
const auto& common = frame.getGenericTracks()[index];
185+
if (!exportTrackState(common.innerState, inner) || !exportTrackState(common.outerState, outer)) {
186+
return std::nullopt;
187+
}
188+
if (index >= sharedClusterFlags.size() || sharedClusterFlags[index] > 1) {
189+
return std::nullopt;
190+
}
191+
o2::its::TrackITS output{inner, common.chi2, outer};
192+
uint32_t pattern = 0;
193+
if (!collectReferences(frame, common, staged.clusterIndices, output, pattern,
194+
externalIndicesBySurface, clusterSizesBySurface))
195+
return std::nullopt;
196+
output.setPattern(pattern);
197+
output.setSharedClusters(sharedClusterFlags[index] != 0);
198+
output.getTimeStamp() = orderedTrack.timestamp;
199+
staged.tracks.push_back(std::move(output));
200+
times.push_back(orderedTrack.timestamp);
201+
if (withMC)
202+
staged.labels.push_back(frame.getTrackLabels()[index]);
203+
}
204+
finalizeROFs(staged.trackROFs, times, context);
205+
return staged;
206+
}
207+
75208
bool completePublication(PublicationAdapter& publication,
76209
const TimeFrame& frame,
77210
const Tracker& tracker,
@@ -287,12 +420,10 @@ void CATrackerDPL::run(ProcessingContext& pc)
287420

288421
{
289422
mSession.publicationClock.emplace(mSession.overlap.getView().getClockLayer());
290-
const o2::itsmft::tracking::GenericTrackPublicationContext context{
291-
o2::detectors::DetID::ITS, o2::itsmft::tracking::ClusterSourceId{0},
292-
gsl::span<const o2::itsmft::ROFRecord>{rofsinput.data(), rofsinput.size()}, *mSession.publicationClock,
293-
kLayerToLayout,
294-
&mSession.externalIndices, &mSession.clusterSizes};
295-
const auto staged = o2::itsmft::tracking::stageITSGenericTrackOutput(mSession.frame, context, mPublication.sharedClusterFlags(), mUseMC);
423+
const o2::itsmft::tracking::TrackPublicationTimingContext context{
424+
gsl::span<const o2::itsmft::ROFRecord>{rofsinput.data(), rofsinput.size()}, *mSession.publicationClock};
425+
const auto staged = stageTrackOutput(mSession.frame, context, mPublication.sharedClusterFlags(), mUseMC,
426+
&mSession.externalIndices, &mSession.clusterSizes);
296427
if (!staged) {
297428
throw std::runtime_error{"ITS GenericTrack output staging failed"};
298429
}

‎Detectors/ITSMFT/MFT/workflow/include/MFTWorkflow/CATrackerSpec.h‎

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,6 @@
2323
#include "CommonDataFormat/IRFrame.h"
2424
#include "Framework/DataProcessorSpec.h"
2525
#include "Framework/Task.h"
26-
#include "ITSMFTTracking/GenericTrackOutputAdapter.h"
2726
#include "ITSMFTTracking/Configuration.h"
2827
#include "MFTWorkflow/CAWorkflowOptions.h"
2928
#include "ITSMFTTracking/ClusterDecoding.h"

‎Detectors/ITSMFT/MFT/workflow/src/CATrackerSpec.cxx‎

Lines changed: 152 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,7 @@
3434
#include "Framework/DataProcessorSpec.h"
3535
#include "Framework/Logger.h"
3636
#include "ITSMFTTracking/Tracker.h"
37-
#include "ITSMFTTracking/GenericTrackOutputAdapter.h"
37+
#include "ITSMFTTracking/TrackPublicationHelpers.h"
3838
#include "ITSMFTTracking/IOUtils.h"
3939
#include "ITSMFTTracking/SurfaceTiming.h"
4040
#include "ITSMFTTracking/ITSMFTDetectorDefinitions.h"
@@ -69,6 +69,153 @@ constexpr std::array<LayerId, NLayers> detectorLocalToLayoutLayers()
6969

7070
inline constexpr auto kLayerToLayout = detectorLocalToLayoutLayers<MFTNLayers>();
7171

72+
struct TrackOutput {
73+
std::vector<o2::mft::TrackMFT> tracks;
74+
std::vector<int> clusterIndices;
75+
std::vector<o2::itsmft::ROFRecord> trackROFs;
76+
std::vector<uint16_t> seedPatterns;
77+
std::vector<o2::MCCompLabel> labels;
78+
};
79+
80+
bool exportTrackState(const SurfaceTrackState& source, o2::track::TrackParCovFwd& destination) noexcept
81+
{
82+
if (source.kind != SurfaceKind::Disk) {
83+
return false;
84+
}
85+
o2::track::SMatrix5 parameters{};
86+
o2::track::SMatrix55Sym covariance{};
87+
for (uint8_t i = 0; i < 5; ++i) {
88+
if (!o2::gpu::GPUCommonMath::Finite(source.parameters[i])) {
89+
return false;
90+
}
91+
parameters[i] = source.parameters[i];
92+
}
93+
for (uint8_t row = 0; row < 5; ++row) {
94+
for (uint8_t column = 0; column <= row; ++column) {
95+
const auto value = source.covariance[packedCovarianceIndex(row, column)];
96+
if (!o2::gpu::GPUCommonMath::Finite(value)) {
97+
return false;
98+
}
99+
covariance(row, column) = value;
100+
}
101+
}
102+
if (!o2::gpu::GPUCommonMath::Finite(source.referenceCoordinate)) {
103+
return false;
104+
}
105+
destination = o2::track::TrackParCovFwd{source.referenceCoordinate, parameters, covariance, 0.};
106+
return true;
107+
}
108+
109+
bool collectReferences(const TimeFrame& frame, const GenericTrack& common, std::vector<int>& outputIndices, o2::mft::TrackMFT& output,
110+
uint32_t& pattern,
111+
const std::vector<std::vector<uint32_t>>* externalIndicesBySurface,
112+
const std::vector<std::vector<uint32_t>>* clusterSizesBySurface)
113+
{
114+
constexpr uint32_t maxLayers = MFTNLayers;
115+
const auto& layerMapping = kLayerToLayout;
116+
const auto& references = frame.getTrackClusterIndices();
117+
std::array<const TrackClusterReference*, maxLayers> byLayer{};
118+
for (uint32_t ref = common.firstClusterRef; ref < common.clusterRefEnd; ++ref) {
119+
const auto& key = references[ref];
120+
if (!key.isValid()) {
121+
return false;
122+
}
123+
const auto where = std::find(layerMapping.begin(), layerMapping.end(), key.layer);
124+
if (where == layerMapping.end() || static_cast<uint32_t>(where - layerMapping.begin()) >= maxLayers) {
125+
return false;
126+
}
127+
const auto layer = static_cast<uint32_t>(where - layerMapping.begin());
128+
if (byLayer[layer] != nullptr) {
129+
return false;
130+
}
131+
byLayer[layer] = &key;
132+
}
133+
const int first = static_cast<int>(outputIndices.size());
134+
uint32_t count = 0;
135+
for (uint32_t layer = maxLayers; layer-- > 0;) {
136+
const auto* reference = byLayer[layer];
137+
if (reference == nullptr) {
138+
continue;
139+
}
140+
uint32_t externalIndex = reference->clusterId;
141+
if (externalIndicesBySurface != nullptr) {
142+
if (reference->layer.value() >= externalIndicesBySurface->size() ||
143+
reference->clusterId >= (*externalIndicesBySurface)[reference->layer.value()].size()) {
144+
return false;
145+
}
146+
externalIndex = (*externalIndicesBySurface)[reference->layer.value()][reference->clusterId];
147+
}
148+
if (externalIndex > static_cast<uint32_t>(std::numeric_limits<int>::max())) {
149+
return false;
150+
}
151+
if (clusterSizesBySurface == nullptr ||
152+
reference->layer.value() >= clusterSizesBySurface->size() ||
153+
reference->clusterId >= (*clusterSizesBySurface)[reference->layer.value()].size()) {
154+
return false;
155+
}
156+
outputIndices.push_back(static_cast<int>(externalIndex));
157+
output.setClusterSize(layer, (*clusterSizesBySurface)[reference->layer.value()][reference->clusterId]);
158+
pattern |= 1u << layer;
159+
++count;
160+
}
161+
output.setExternalClusterIndexOffset(first);
162+
output.setNumberOfPoints(static_cast<int>(count));
163+
return true;
164+
}
165+
166+
std::optional<TrackOutput> stageTrackOutput(const TimeFrame& frame,
167+
const TrackPublicationTimingContext& context,
168+
bool withMC,
169+
const std::vector<std::vector<uint32_t>>* externalIndicesBySurface = nullptr,
170+
const std::vector<std::vector<uint32_t>>* clusterSizesBySurface = nullptr)
171+
{
172+
const auto selection = selectGenericTracksForSurfaces(frame, kLayerToLayout);
173+
if (!selection)
174+
return std::nullopt;
175+
if (withMC && frame.getTrackLabels().size() != frame.getGenericTracks().size()) {
176+
return std::nullopt;
177+
}
178+
const auto ordered = makeLegacyOutputOrder(frame, *selection, context.clock);
179+
if (!ordered) {
180+
return std::nullopt;
181+
}
182+
TrackOutput staged;
183+
staged.trackROFs.assign(context.inputROFs.begin(), context.inputROFs.end());
184+
staged.tracks.reserve(ordered->size());
185+
staged.seedPatterns.reserve(ordered->size());
186+
std::vector<o2::its::TimeStamp> times;
187+
times.reserve(ordered->size());
188+
for (const auto& orderedTrack : *ordered) {
189+
const auto index = orderedTrack.globalIndex;
190+
const auto& common = frame.getGenericTracks()[index];
191+
o2::track::TrackParCovFwd inner, outer;
192+
if (!exportTrackState(common.innerState, inner) || !exportTrackState(common.outerState, outer)) {
193+
return std::nullopt;
194+
}
195+
// Preserve the legacy TrackMFT object shape without claiming a seed-pT
196+
// estimate from this tracker. TrackMFT does not initialize mInvQPtSeed.
197+
outer.setTrackChi2(0.f);
198+
o2::mft::TrackMFT output;
199+
static_cast<o2::track::TrackParCovFwd&>(output) = inner;
200+
output.setOutParam(outer);
201+
output.setTrackChi2(common.chi2);
202+
output.setCA(true);
203+
output.setInvQPtSeed(0.);
204+
output.setChi2QPtSeed(0.);
205+
uint32_t pattern = 0;
206+
if (!collectReferences(frame, common, staged.clusterIndices, output, pattern,
207+
externalIndicesBySurface, clusterSizesBySurface))
208+
return std::nullopt;
209+
staged.tracks.push_back(std::move(output));
210+
staged.seedPatterns.push_back(static_cast<uint16_t>(pattern));
211+
times.push_back(orderedTrack.timestamp);
212+
if (withMC)
213+
staged.labels.push_back(frame.getTrackLabels()[index]);
214+
}
215+
finalizeROFs(staged.trackROFs, times, context);
216+
return staged;
217+
}
218+
72219
bool rofOverlapsIRFrames(const o2::itsmft::ROFRecord& rof, int rofLengthInBC,
73220
gsl::span<const o2::dataformats::IRFrame> irFrames)
74221
{
@@ -219,12 +366,10 @@ void CATrackerDPL::run(ProcessingContext& pc)
219366

220367
{
221368
mSession.publicationClock.emplace(mSession.overlap.getView().getClockLayer());
222-
const o2::itsmft::tracking::GenericTrackPublicationContext context{
223-
o2::detectors::DetID::MFT, o2::itsmft::tracking::ClusterSourceId{0},
224-
gsl::span<const o2::itsmft::ROFRecord>{rofsinput.data(), rofsinput.size()}, *mSession.publicationClock,
225-
kLayerToLayout,
226-
&mSession.externalIndices, &mSession.clusterSizes};
227-
const auto staged = o2::itsmft::tracking::stageMFTGenericTrackOutput(mSession.frame, context, mUseMC);
369+
const o2::itsmft::tracking::TrackPublicationTimingContext context{
370+
gsl::span<const o2::itsmft::ROFRecord>{rofsinput.data(), rofsinput.size()}, *mSession.publicationClock};
371+
const auto staged = stageTrackOutput(mSession.frame, context, mUseMC,
372+
&mSession.externalIndices, &mSession.clusterSizes);
228373
if (!staged) {
229374
throw std::runtime_error{"MFT GenericTrack output staging failed"};
230375
}

‎Detectors/ITSMFT/common/tracking/CMakeLists.txt‎

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -57,7 +57,6 @@ o2_add_library(ITSMFTTracking
5757
O2::SimulationDataFormat
5858
O2::ReconstructionDataFormats
5959
O2::DataFormatsCalibration
60-
O2::DataFormatsMFT
6160
TBB::tbb
6261
PRIVATE_LINK_LIBRARIES
6362
O2::Framework

0 commit comments

Comments
 (0)