12#ifndef ALICEO2_ITSMFT_TRACKING_WORKFLOWSESSION_H_
13#define ALICEO2_ITSMFT_TRACKING_WORKFLOWSESSION_H_
49 for (
size_t rof = 0; rof <
source.rofs.size(); ++rof) {
53 if (timing.
mROFLength == 0 || begin < 0 || end > std::numeric_limits<o2::its::TimeStampType>::max()) {
54 throw std::runtime_error(std::format(
"Invalid ROF timing: source={} rof={}",
source.id.value(), rof));
61template <
typename Allocator,
typename Output,
typename Staged>
64 outputs.template make<std::decay_t<
decltype(staged.trackROFs)>>(rofs, staged.trackROFs.begin(), staged.trackROFs.end());
65 outputs.template make<std::decay_t<
decltype(staged.tracks)>>(
tracks, staged.tracks.begin(), staged.tracks.end());
66 outputs.template make<std::decay_t<
decltype(staged.clusterIndices)>>(
indices, staged.clusterIndices.begin(), staged.clusterIndices.end());
103 bool mResetFrame =
true;
120 template <
typename Alp
ideParameters>
121 std::vector<o2::its::LayerTiming>
layerTimings(
const AlpideParameters& alpide,
int nOrbits,
122 const std::vector<uint32_t>& addTimeError)
const
124 const int nLayers =
overlap.getEntries();
125 if (addTimeError.size() != nLayers) {
126 throw std::runtime_error{std::string(mDetectorName) +
" CA timing-error layer count differs from the workflow layout"};
128 std::vector<o2::its::LayerTiming> timings(nLayers);
130 const auto length = alpide.getROFLengthInBC(
layer);
132 throw std::runtime_error{std::string(mDetectorName) +
" CA per-layer ROF timing has a non-positive ROF length"};
134 const auto rofsPerOrbit = o2::constants::lhc::LHCMaxBunches /
static_cast<unsigned int>(
length);
135 timings[
layer] = {.mNROFsTF = rofsPerOrbit *
static_cast<unsigned int>(nOrbits),
136 .mROFLength =
static_cast<uint32_t
>(
length),
137 .mROFDelay =
static_cast<uint32_t
>(alpide.getROFDelayInBC(
layer)),
138 .mROFBias =
static_cast<uint32_t
>(alpide.getROFBiasInBC(
layer)),
139 .mROFAddTimeErr = addTimeError[
layer]};
140 if (timings[
layer].mNROFsTF == 0) {
141 throw std::runtime_error{std::string(mDetectorName) +
" CA per-layer ROF timing yields zero ROFs per TimeFrame"};
147 template <
typename AcceptROF>
148 void configureTiming(gsl::span<const o2::its::LayerTiming> timings, AcceptROF&& accept)
150 const int nLayers =
overlap.getEntries();
151 if (timings.size() != nLayers || timings.empty() ||
152 !std::all_of(timings.begin(), timings.end(), [&](
const auto& timing) {
153 const auto& first = timings.front();
154 return timing.mROFLength == first.mROFLength && timing.mROFDelay == first.mROFDelay &&
155 timing.mROFBias == first.mROFBias && timing.mROFAddTimeErr == first.mROFAddTimeErr;
157 throw std::runtime_error{std::string(mDetectorName) +
" CA per-layer ROF timing configuration has an unexpected layer count or is not uniform"};
162 if (!matchesTiming(timings)) {
166 nextOverlap.defineLayer(
layer, timings[
layer]);
167 nextVertices.defineLayer(
layer, timings[
layer]);
172 std::vector<o2::its::LayerTiming> nextTimingKey(timings.begin(), timings.end());
173 overlap = std::move(nextOverlap);
175 mask = std::move(nextMask);
176 mTimingKey = std::move(nextTimingKey);
183 for (
int rof = 0; rof < static_cast<int>(timings[0].mNROFsTF); ++rof) {
193 template <
typename Load>
200 LOGP(error,
"{} CA loading exceeded memory limit: {}", mDetectorName, error.what());
202 if (!dropOnFailure) {
205 }
catch (
const std::bad_alloc& error) {
206 LOGP(error,
"{} CA loading allocation failed: {}", mDetectorName, error.what());
208 if (!dropOnFailure) {
211 }
catch (
const std::exception& error) {
212 LOGP(error,
"{} CA loading failed: {}", mDetectorName, error.what());
219 template <
typename AfterLoad,
typename Complete>
221 AfterLoad&& afterLoad, Complete&& complete)
224 if (views.overlap.mLayerCount > 0 &&
source.rofs.size() != views.overlap.getLayer(0).mNROFsTF) {
225 LOGP(warn,
"{} CA ROF count differs from continuous timing expectation: received {} expected {}",
226 mDetectorName,
source.rofs.size(), views.overlap.getLayer(0).mNROFsTF);
230 if (!source.dictionary) {
231 throw std::runtime_error{std::string(mDetectorName) +
" CA tracker cluster dictionary is not available"};
233 if (views.overlap.mLayerCount <= 0) {
234 throw std::runtime_error{std::string(mDetectorName) +
" CA tracker received no adapter-owned runtime ROF timing view"};
236 const auto& clock = views.overlap.getLayer(0);
248 if (!tracker.run(frame, traits)) {
249 LOGP(warn,
"{} CA tracking failed for this TF", mDetectorName);
252 const auto& statistics = tracker.getRunStatistics();
253 complete(statistics);
254 LOGP(info,
"{} CA tracking produced {} tracks in {:.2f} ms", mDetectorName, frame.
getGenericTracks().size(), statistics.elapsedMs);
259 bool matchesTiming(gsl::span<const o2::its::LayerTiming> timings)
const noexcept
261 if (mTimingKey.size() != timings.size()) {
265 const auto& cached = mTimingKey[
layer];
266 const auto& next = timings[
layer];
267 if (cached.mNROFsTF != next.mNROFsTF || cached.mROFLength != next.mROFLength ||
268 cached.mROFDelay != next.mROFDelay || cached.mROFBias != next.mROFBias ||
269 cached.mROFAddTimeErr != next.mROFAddTimeErr) {
276 const char* mDetectorName;
277 std::vector<o2::its::LayerTiming> mTimingKey;
header::DataOrigin origin
Shared cluster I/O utilities for ITS and MFT (based on ITStracking/IOUtils.h)
std::vector< o2::its::TrackITS > tracks
Header to collect LHC related constants.
const TrackingExecutionPolicy & getExecutionPolicy() const noexcept
Cleanup(WorkflowSession &session)
void frameAlreadyReset() noexcept
Cleanup(const Cleanup &)=delete
Cleanup & operator=(const Cleanup &)=delete
void configureTiming(gsl::span< const o2::its::LayerTiming > timings, AcceptROF &&accept)
std::vector< std::vector< uint32_t > > clusterSizes
ROFVertexLookupTable vertices
void invalidatePublication() noexcept
bool process(Tracker &tracker, TrackerTraits &traits, ClusterSourceInput source, AfterLoad &&afterLoad, Complete &&complete)
WorkflowSession(const char *detectorName, int nLayers)
std::vector< o2::its::LayerTiming > layerTimings(const AlpideParameters &alpide, int nOrbits, const std::vector< uint32_t > &addTimeError) const
bool loadWithRecovery(bool dropOnFailure, Load &&load)
std::vector< std::vector< uint32_t > > externalIndices
GLsizei GLsizei GLchar * source
GLuint GLsizei GLsizei * length
GLsizei GLenum const void * indices
GLenum GLuint GLint GLint layer
if(ptInv< o2::track::MinPTInv)
void copyTrackingOutputColumns(Allocator &outputs, Output rofs, Output tracks, Output indices, const Staged &staged)
void validateSourceROFTiming(const ClusterSourceInput &source, const o2::InteractionRecord &origin, const o2::its::LayerTiming &timing)
uint32_t trackClusterIndicesSize noexcept
void loadTimeFrameSources(TimeFrame &, gsl::span< const ClusterSourceInput >, SurfaceCatalogView, std::vector< std::vector< uint32_t > > *externalIndicesBySurface=nullptr, std::vector< std::vector< uint32_t > > *clusterSizesBySurface=nullptr)
CATrackerPublicationAction decideCATrackerPublicationAction(bool active, bool success) noexcept
CATrackerPublicationAction
auto & getGenericTracks()
void resetTimeFrame() noexcept
const DetectorConfiguration & getDetectorConfiguration() const noexcept
const RuntimeROFViews & getROFViews() const noexcept
void setROFViews(RuntimeROFViews views) noexcept
gSystem Load("libO2DetectorsCommonDataFormats")