From 5036d9ed46c8434c195e8fc8528838be2f9618c8 Mon Sep 17 00:00:00 2001 From: Giulio Eulisse <10544+ktf@users.noreply.github.com> Date: Tue, 28 Apr 2026 13:30:02 +0200 Subject: [PATCH 1/3] Add command to migrate away from BasicCCDBManager in Analysis --- .claude/commands/migrate-ccdb.md | 148 +++++++++++++++++++++++++++++++ 1 file changed, 148 insertions(+) create mode 100644 .claude/commands/migrate-ccdb.md diff --git a/.claude/commands/migrate-ccdb.md b/.claude/commands/migrate-ccdb.md new file mode 100644 index 00000000000..48d0f49c971 --- /dev/null +++ b/.claude/commands/migrate-ccdb.md @@ -0,0 +1,148 @@ +Migrate the specified file (or all files mentioned in the conversation) from `Service` to the declarative CCDB table approach. + +## Background + +The old approach uses `Service` and calls `ccdb->getForTimeStamp(path, timestamp)` at runtime. The new approach declares CCDB columns and timestamped tables using macros, so the framework fetches objects automatically and exposes them as columns on BC rows. + +**New API summary:** + +```cpp +// In namespace o2::aod (or a sub-namespace): +DECLARE_SOA_CCDB_COLUMN(StructName, getterName, ConcreteType, "CCDB/Object/Path"); + +DECLARE_SOA_TIMESTAMPED_TABLE(TableName, aod::Timestamps, o2::aod::timestamp::Timestamp, 1, "TABLEDESC", + ns::StructName, ns::OtherColumn); + +// In the task — basic usage: +using MyBCs = soa::Join; +void process(MyBCs const& bcs) { + for (auto const& bc : bcs) { + auto const& obj = bc.getterName(); // reference to cached deserialized object; treat as immutable + } +} +``` + +**Configurable CCDB paths** (`ConfigurableCCDBPath`): + +If the original task used a `Configurable` to supply the CCDB path, the path can remain user-overridable after migration using `ConfigurableCCDBPath`. This is a typed `Configurable` whose option name is automatically set to `"ccdb:" + Column::mLabel` (where `mLabel = "f" + StructName`), defaulting to the compile-time path in the column declaration. The framework reads this option name when resolving CCDB URLs, so users can still redirect the path via JSON config. + +The Configurable is purely declarative for the path-override mechanism: declaring it is sufficient — you do **not** pass `.value` to a getter or fetcher. The accessor remains `bc.getterName()`. The `.value` member is still available if the task wants to log the resolved path. + +```cpp +struct MyTask { + // Replaces: Configurable grpmagPath{"grpmagPath", "GLO/Config/GRPMagField", "..."}; + ConfigurableCCDBPath grpMagFieldPath; // option name = "ccdb:fGRPMagField" + + void process(MyBCs const& bcs) { + auto const& grpmag = bcs.iteratorAt(0).grpMagField(); // path override is honoured automatically + LOGP(info, "Using GRPMagField path: {}", grpMagFieldPath.value); + } +}; +``` + +Required headers (add if missing): ``, ``, `` +Headers to remove (if no longer needed): `` + +## What to do + +Read the target file(s) and perform the following migration. Do NOT do a complete migration if the patterns are ambiguous or out of scope — instead note what was skipped and why. + +### Step 1 — Inventory + +Find every `ccdb->getForTimeStamp(path, ts)` call (and variants like `fCCDB->getForTimeStamp`, `mCcdb->getForTimeStamp`). For each call record: +- The concrete C++ type `T` +- The CCDB path string (may be a `Configurable` variable — record the default value and the Configurable's name) +- The timestamp source (BC timestamp, computed value, etc.) +- Where the result is used + +**Deduplicate**: for the same (type, path) pair, declare only one CCDB column. Multiple call sites collapse into multiple uses of the same getter. + +### Step 2 — Identify scope + +Determine whether each fetch is: +- **Per-BC/per-collision** (called inside `process()` with a timestamp from a BC) — these can be migrated +- **Per-run** (called once when `runNumber` changes, guarded by `mRunNumber == ...`) — these can be migrated; the framework caches per unique timestamp automatically +- **Global/init-time** (called in `init()` with a fixed timestamp, not keyed to a BC) — these **cannot** be migrated to CCDB tables; leave them as-is and note this + +Skip the migration for any global/init-time fetches. Skip the whole file if all fetches are global. + +### Step 3 — Declare CCDB columns and table + +In the `o2::aod` namespace (or a private sub-namespace inside the file, before the task struct), declare: + +```cpp +namespace o2::aod +{ +namespace myccdbtask // use a short, unique snake_case name derived from the task name +{ +DECLARE_SOA_CCDB_COLUMN(StructName, getterName, fully::qualified::ConcreteType, "CCDB/Path"); //! +// one per unique (type, path) pair +} // namespace myccdbtask + +DECLARE_SOA_TIMESTAMPED_TABLE(MyTaskCCDBObjects, aod::Timestamps, o2::aod::timestamp::Timestamp, 1, "MYTASKCCDB", //! + myccdbtask::StructName /*, ... */); +} // namespace o2::aod +``` + +Rules for naming: +- `StructName` / `getterName`: derive from the type name, e.g. `GRPMagField` / `grpMagField`, `MeanVertex` / `meanVertex` +- Table name: `CCDBObjects`, e.g. `SkimmerDalitzEECCDBObjects` +- `_Desc_` string: short ALL-CAPS string unique within the binary (≤ 16 chars to fit the AOD descriptor), e.g. `"DALZECC"`, `"TOFCALIB"` +- Namespace: lowercase snake-case derived from the task name (avoid collisions with other CCDB column namespaces in the file) +- Use the **default value** of any `Configurable` path as the compile-time path in the `DECLARE_SOA_CCDB_COLUMN` macro; if the path has no obvious default, leave a `// TODO: verify path` comment + +### Step 4 — Update the task struct + +1. **Remove** `Service ccdb;` (and any variant field name) +2. **Remove** `int mRunNumber;` (or similar run-caching variables) **only if** their sole purpose was to guard CCDB re-fetches +3. **Remove** `ccdb->setURL(...)`, `ccdb->setCaching(...)`, `ccdb->setLocalObjectValidityChecking()`, `ccdb->setCreatedNotAfter(...)`, `ccdb->setFatalWhenNull(...)` from `init()` +4. **Remove** the entire `initCCDB()`/`initMagField()` helper method if it only did CCDB fetching; otherwise remove just the CCDB lines from it +5. **Handle path Configurables** — for each `Configurable` that held a CCDB path: + - If the path was used as the sole argument to `getForTimeStamp` and the user may want to override it at runtime: **replace** it with `ConfigurableCCDBPath` (e.g. `ConfigurableCCDBPath grpMagFieldPath;`). The member name should match the getter for clarity. Keep a comment explaining what path it controls. + - If the path was never intended to be user-facing (e.g. internal fixed paths): **remove** it outright; the compile-time path in `DECLARE_SOA_CCDB_COLUMN` is sufficient. + - Always remove Configurables that were only used for CCDB manager setup and not for paths: `ccdb-url`, `ccdb-no-later-than`, `skipGRPOquery`, `d_bz_input` (if only used to bypass CCDB), etc. +6. **Remove** cached pointer member variables (e.g. `GRPMagField* grpmag = nullptr`) if they were only populated by CCDB fetches that are now replaced + +### Step 5 — Update process() signatures + +Define one alias near the top of the task or just below the table declaration: +```cpp +using MyBCs = soa::Join; +``` + +Then for each `process()` that used to call `getForTimeStamp`: + +- If `process()` already takes `aod::BCsWithTimestamps const&` directly: change it to `MyBCs const&`. +- If `process()` accesses BCs via `collision.bc_as()`: add `MyBCs const&` to the process signature (so the framework knows to provide it) and replace the `bc_as<>` type with `MyBCs`. +- If `process()` does not currently mention BCs but called `ccdb->getForTimeStamp(path, collision.bc_as<...>().timestamp())`: add `MyBCs const&` to the signature and obtain the BC via `collision.bc_as()`. +- Replace every `ccdb->getForTimeStamp(path, ts)` call with `bc.getterName()`. The returned reference is to a cached deserialized object; treat it as immutable. +- Null-pointer checks (`if (!grpmag)`) on the result become unnecessary — the framework guarantees the object is present (or the task fails early). Remove them. +- If a helper template like `initCCDB(collision)` was called per-collision, inline its remaining (non-CCDB) work or drop it. + +### Step 6 — Fix includes + +- Remove `#include ` if no other code in the file still uses `BasicCCDBManager` +- Ensure `#include ` is present (may already be included transitively) +- Keep all type headers (e.g. ``) since they are still needed for the concrete type + +### Step 7 — Final review + +After making changes: +- Check that every remaining use of `ccdb` / `fCCDB` / `mCcdb` has been handled +- Check that `mRunNumber` (or similar) is fully removed if unused +- Check that any leftover `Configurable` for a path is either replaced by `ConfigurableCCDBPath<>` or removed +- Search for stale references to removed Configurables (e.g. `grpmagPath.value` lingering in log messages — switch to `grpMagFieldPath.value`) +- If `init()` is now empty, it can be removed +- Note any patterns that were intentionally skipped + +## Important limitations — tell the user if any apply + +- **Configurable paths**: CCDB column paths are compile-time constants in the macro. Add `ConfigurableCCDBPath` to allow runtime override; its default is `Column::query` so it always agrees with the macro by construction. +- **`getRunDuration()` calls**: these use `BasicCCDBManager` statically and are unrelated to per-BC fetching — do not touch them. +- **`ctpRateFetcher` / other helpers**: out of scope. +- **Multiple tasks in one file**: tasks can share a single CCDB table declaration if they need the same objects; otherwise each task gets its own with a unique `_Desc_`. +- **Non-BC timestamps**: if the timestamp comes from something other than a BC (e.g. computed manually), the migration is non-trivial — flag it instead of forcing it. +- **Global/init-time fetches** (e.g. `efficiencyGlobal.cxx` style): not migratable — the timestamped-table mechanism requires a row in a BC-keyed table. +- **Magnetic-field side effects**: tasks that compute `d_bz` from a fetched `GRPMagField` and seed a propagator can keep that logic, just sourcing the object from `bc.grpMagField()` instead of `ccdb->getForTimeStamp(...)`. + +$ARGUMENTS From a7857ad0d855e2ad51a4dbd28258946e6e4de03d Mon Sep 17 00:00:00 2001 From: Giulio Eulisse <10544+ktf@users.noreply.github.com> Date: Tue, 28 Apr 2026 20:54:27 +0200 Subject: [PATCH 2/3] Add additional propagationServiceV2 for refactoring --- Common/TableProducer/CMakeLists.txt | 5 + Common/TableProducer/propagationServiceV2.cxx | 148 ++++++++++++++++++ 2 files changed, 153 insertions(+) create mode 100644 Common/TableProducer/propagationServiceV2.cxx diff --git a/Common/TableProducer/CMakeLists.txt b/Common/TableProducer/CMakeLists.txt index 69cd6084a09..8f8d64b443d 100644 --- a/Common/TableProducer/CMakeLists.txt +++ b/Common/TableProducer/CMakeLists.txt @@ -79,6 +79,11 @@ o2physics_add_dpl_workflow(propagationservice PUBLIC_LINK_LIBRARIES O2Physics::AnalysisCore O2::DCAFitter KFParticle::KFParticle O2Physics::TPCDriftManager COMPONENT_NAME Analysis) +o2physics_add_dpl_workflow(propagationservice-v2 + SOURCES propagationServiceV2.cxx + PUBLIC_LINK_LIBRARIES O2Physics::AnalysisCore O2::DCAFitter KFParticle::KFParticle O2Physics::TPCDriftManager + COMPONENT_NAME Analysis) + o2physics_add_dpl_workflow(propagationservice-run2 SOURCES propagationServiceRun2.cxx PUBLIC_LINK_LIBRARIES O2Physics::AnalysisCore O2::DCAFitter KFParticle::KFParticle O2Physics::TPCDriftManager diff --git a/Common/TableProducer/propagationServiceV2.cxx b/Common/TableProducer/propagationServiceV2.cxx new file mode 100644 index 00000000000..25c951ef396 --- /dev/null +++ b/Common/TableProducer/propagationServiceV2.cxx @@ -0,0 +1,148 @@ +// Copyright 2019-2020 CERN and copyright holders of ALICE O2. +// See https://alice-o2.web.cern.ch/copyright for details of the copyright holders. +// All rights not expressly granted are reserved. +// +// This software is distributed under the terms of the GNU General Public +// License v3 (GPL Version 3), copied verbatim in the file "COPYING". +// +// In applying this license CERN does not waive the privileges and immunities +// granted to it by virtue of its status as an Intergovernmental Organization +// or submit itself to any jurisdiction. + +/// \file propagationService.cxx +/// \brief +/// \author ALICE + +//=============================================================== +// +// Merged track propagation + strangeness building task +// +// Provides a common task to deal with track propagation and +// strangeness building in a single DPL device that is particularly +// adequate for pipelining. +// +//=============================================================== + +#include "PWGLF/Utils/strangenessBuilderModule.h" + +#include "Common/DataModel/EventSelection.h" +#include "Common/DataModel/PIDResponseTPC.h" +#include "Common/Tools/StandardCCDBLoader.h" +#include "Common/Tools/TrackPropagationModule.h" +#include "Common/Tools/TrackTuner.h" + +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +#include + +using namespace o2; +using namespace o2::framework; +// using namespace o2::framework::expressions; + +// use parameters + cov mat non-propagated, aux info + (extension propagated) +using FullTracksExt = soa::Join; +using FullTracksExtIU = soa::Join; +using FullTracksExtWithPID = soa::Join; +using FullTracksExtIUWithPID = soa::Join; +using FullTracksExtLabeled = soa::Join; +using FullTracksExtLabeledIU = soa::Join; +using FullTracksExtLabeledWithPID = soa::Join; +using FullTracksExtLabeledIUWithPID = soa::Join; +using TracksWithExtra = soa::Join; + +// For dE/dx association in pre-selection +using TracksExtraWithPID = soa::Join; + +struct propagationService { + // CCDB boilerplate declarations + o2::framework::Configurable ccdburl{"ccdburl", "http://alice-ccdb.cern.ch", "url of the ccdb repository"}; + Service ccdb; + + // propagation stuff + o2::common::StandardCCDBLoaderConfigurables standardCCDBLoaderConfigurables; + o2::common::StandardCCDBLoader ccdbLoader; + + // boilerplate: strangeness builder stuff + o2::pwglf::strangenessbuilder::products products; + o2::pwglf::strangenessbuilder::coreConfigurables baseOpts; + o2::pwglf::strangenessbuilder::v0Configurables v0BuilderOpts; + o2::pwglf::strangenessbuilder::cascadeConfigurables cascadeBuilderOpts; + o2::pwglf::strangenessbuilder::preSelectOpts preSelectOpts; + o2::pwglf::strangenessbuilder::BuilderModule strangenessBuilderModule; + + // the track tuner object -> needs to be here as it inherits from ConfigurableGroup (+ has its own copy of ccdbApi) + TrackTuner trackTunerObj; + + // track propagation + o2::common::TrackPropagationProducts trackPropagationProducts; + o2::common::TrackPropagationConfigurables trackPropagationConfigurables; + o2::common::TrackPropagationModule trackPropagation; + + // registry + HistogramRegistry histos{"histos"}; + + void init(o2::framework::InitContext& initContext) + { + // CCDB boilerplate init + ccdb->setCaching(true); + ccdb->setLocalObjectValidityChecking(); + ccdb->setURL(ccdburl.value); + + // task-specific + trackPropagation.init(trackPropagationConfigurables, trackTunerObj, histos, initContext); + strangenessBuilderModule.init(baseOpts, v0BuilderOpts, cascadeBuilderOpts, preSelectOpts, histos, initContext); + } + + void processRealData(soa::Join const& collisions, aod::V0s const& v0s, aod::Cascades const& cascades, aod::TrackedCascades const& trackedCascades, FullTracksExtIU const& tracks, aod::BCsWithTimestamps const& bcs) + { + ccdbLoader.initCCDBfromBCs(standardCCDBLoaderConfigurables, ccdb, bcs); + trackPropagation.fillTrackTables(trackPropagationConfigurables, trackTunerObj, ccdbLoader, collisions, tracks, trackPropagationProducts, histos); + strangenessBuilderModule.dataProcess(ccdb, histos, collisions, static_cast(nullptr), v0s, cascades, trackedCascades, tracks, bcs, static_cast(nullptr), products); + } + + void processMonteCarlo(soa::Join const& collisions, aod::McCollisions const& mccollisions, aod::V0s const& v0s, aod::Cascades const& cascades, aod::TrackedCascades const& trackedCascades, FullTracksExtLabeledIU const& tracks, aod::BCsWithTimestamps const& bcs, aod::McParticles const& mcParticles) + { + ccdbLoader.initCCDBfromBCs(standardCCDBLoaderConfigurables, ccdb, bcs); + trackPropagation.fillTrackTables(trackPropagationConfigurables, trackTunerObj, ccdbLoader, collisions, tracks, trackPropagationProducts, histos); + strangenessBuilderModule.dataProcess(ccdb, histos, collisions, mccollisions, v0s, cascades, trackedCascades, tracks, bcs, mcParticles, products); + } + + void processRealDataWithPID(soa::Join const& collisions, aod::V0s const& v0s, aod::Cascades const& cascades, aod::TrackedCascades const& trackedCascades, FullTracksExtIUWithPID const& tracks, aod::BCsWithTimestamps const& bcs) + { + ccdbLoader.initCCDBfromBCs(standardCCDBLoaderConfigurables, ccdb, bcs); + trackPropagation.fillTrackTables(trackPropagationConfigurables, trackTunerObj, ccdbLoader, collisions, tracks, trackPropagationProducts, histos); + strangenessBuilderModule.dataProcess(ccdb, histos, collisions, static_cast(nullptr), v0s, cascades, trackedCascades, tracks, bcs, static_cast(nullptr), products); + } + + void processMonteCarloWithPID(soa::Join const& collisions, aod::McCollisions const& mccollisions, aod::V0s const& v0s, aod::Cascades const& cascades, aod::TrackedCascades const& trackedCascades, FullTracksExtLabeledIUWithPID const& tracks, aod::BCsWithTimestamps const& bcs, aod::McParticles const& mcParticles) + { + ccdbLoader.initCCDBfromBCs(standardCCDBLoaderConfigurables, ccdb, bcs); + trackPropagation.fillTrackTables(trackPropagationConfigurables, trackTunerObj, ccdbLoader, collisions, tracks, trackPropagationProducts, histos); + strangenessBuilderModule.dataProcess(ccdb, histos, collisions, mccollisions, v0s, cascades, trackedCascades, tracks, bcs, mcParticles, products); + } + + PROCESS_SWITCH(propagationService, processRealData, "process real data", true); + PROCESS_SWITCH(propagationService, processMonteCarlo, "process monte carlo", false); + PROCESS_SWITCH(propagationService, processRealDataWithPID, "process real data", false); + PROCESS_SWITCH(propagationService, processMonteCarloWithPID, "process monte carlo", false); +}; + +//**************************************************************************************** +/** + * Workflow definition. + */ +//**************************************************************************************** +WorkflowSpec defineDataProcessing(ConfigContext const& cfgc) +{ + WorkflowSpec workflow{adaptAnalysisTask(cfgc)}; + return workflow; +} From df493bd88648c77418c97067db934b2486f4c05b Mon Sep 17 00:00:00 2001 From: Giulio Eulisse <10544+ktf@users.noreply.github.com> Date: Tue, 28 Apr 2026 20:57:42 +0200 Subject: [PATCH 3/3] Migrate the propagation service to CCDB tables - Add a central table for common CCDB Objects --- Common/DataModel/GloCCDBObjects.h | 65 ++++++++++++++ Common/TableProducer/CMakeLists.txt | 1 + Common/TableProducer/propagationServiceV2.cxx | 86 ++++++++++++++----- 3 files changed, 132 insertions(+), 20 deletions(-) create mode 100644 Common/DataModel/GloCCDBObjects.h diff --git a/Common/DataModel/GloCCDBObjects.h b/Common/DataModel/GloCCDBObjects.h new file mode 100644 index 00000000000..f97b684b0a1 --- /dev/null +++ b/Common/DataModel/GloCCDBObjects.h @@ -0,0 +1,65 @@ +// Copyright 2019-2026 CERN and copyright holders of ALICE O2. +// See https://alice-o2.web.cern.ch/copyright for details of the copyright holders. +// All rights not expressly granted are reserved. +// +// This software is distributed under the terms of the GNU General Public +// License v3 (GPL Version 3), copied verbatim in the file "COPYING". +// +// In applying this license CERN does not waive the privileges and immunities +// granted to it by virtue of its status as an Intergovernmental Organization +// or submit itself to any jurisdiction. + +/// \file GloCCDBObjects.h +/// \brief Declarative CCDB columns for the most-commonly needed GLO/ objects. +/// +/// Provides a single shared timestamped table (`aod::GloCCDBObjects`) that +/// tasks can join with `aod::BCsWithTimestamps` to obtain the four GLO/ +/// calibration objects without using `Service`. +/// +/// Usage: +/// \code +/// #include "Common/DataModel/GloCCDBObjects.h" +/// // ... +/// using BCsWithCCDB = soa::Join; +/// void process(BCsWithCCDB const& bcs) { +/// const auto& grpmag = bcs.begin().grpMagField(); +/// const auto& meanvtx = bcs.begin().meanVertex(); +/// const auto& grpecs = bcs.begin().grpECS(); +/// const auto& grplhcif= bcs.begin().grpLHCIF(); +/// } +/// \endcode +/// +/// If you need only a subset of the four objects, declare your own +/// `DECLARE_SOA_TIMESTAMPED_TABLE` with the relevant subset of columns from +/// the `o2::aod::ccdbGlo` namespace rather than joining `aod::GloCCDBObjects`. +/// +/// Note: MatLayerCylSet is intentionally omitted — it requires +/// `MatLayerCylSet::rectifyPtrFromFile()` after deserialisation, which the +/// CCDB column mechanism does not perform. + +#ifndef COMMON_DATAMODEL_GLOCCDBOBJECTS_H_ +#define COMMON_DATAMODEL_GLOCCDBOBJECTS_H_ + +#include +#include +#include +#include +#include +#include + +namespace o2::aod +{ +namespace ccdbGlo +{ +DECLARE_SOA_CCDB_COLUMN(GRPMagField, grpMagField, o2::parameters::GRPMagField, "GLO/Config/GRPMagField"); //! +DECLARE_SOA_CCDB_COLUMN(MeanVertex, meanVertex, o2::dataformats::MeanVertexObject, "GLO/Calib/MeanVertex"); //! +DECLARE_SOA_CCDB_COLUMN(GRPECSObject, grpECS, o2::parameters::GRPECSObject, "GLO/Config/GRPECS"); //! +DECLARE_SOA_CCDB_COLUMN(GRPLHCIFData, grpLHCIF, o2::parameters::GRPLHCIFData, "GLO/Config/GRPLHCIF"); //! +} // namespace ccdbGlo + +/// Full table — join with aod::BCsWithTimestamps to obtain all four objects. +DECLARE_SOA_TIMESTAMPED_TABLE(GloCCDBObjects, aod::Timestamps, o2::aod::timestamp::Timestamp, 1, "GLOCCDBOBJ", //! + ccdbGlo::GRPMagField, ccdbGlo::MeanVertex, ccdbGlo::GRPECSObject, ccdbGlo::GRPLHCIFData); +} // namespace o2::aod + +#endif // COMMON_DATAMODEL_GLOCCDBOBJECTS_H_ diff --git a/Common/TableProducer/CMakeLists.txt b/Common/TableProducer/CMakeLists.txt index 8f8d64b443d..26af3c092f1 100644 --- a/Common/TableProducer/CMakeLists.txt +++ b/Common/TableProducer/CMakeLists.txt @@ -74,6 +74,7 @@ o2physics_add_dpl_workflow(track-propagation PUBLIC_LINK_LIBRARIES O2Physics::AnalysisCore COMPONENT_NAME Analysis) + o2physics_add_dpl_workflow(propagationservice SOURCES propagationService.cxx PUBLIC_LINK_LIBRARIES O2Physics::AnalysisCore O2::DCAFitter KFParticle::KFParticle O2Physics::TPCDriftManager diff --git a/Common/TableProducer/propagationServiceV2.cxx b/Common/TableProducer/propagationServiceV2.cxx index 25c951ef396..74b07490ccb 100644 --- a/Common/TableProducer/propagationServiceV2.cxx +++ b/Common/TableProducer/propagationServiceV2.cxx @@ -9,8 +9,8 @@ // granted to it by virtue of its status as an Intergovernmental Organization // or submit itself to any jurisdiction. -/// \file propagationService.cxx -/// \brief +/// \file propagationServiceV2.cxx +/// \brief V2: GRPMagField and MeanVertexObject sourced from aod::GloCCDBObjects declarative CCDB table. /// \author ALICE //=============================================================== @@ -26,12 +26,16 @@ #include "PWGLF/Utils/strangenessBuilderModule.h" #include "Common/DataModel/EventSelection.h" +#include "Common/DataModel/GloCCDBObjects.h" #include "Common/DataModel/PIDResponseTPC.h" #include "Common/Tools/StandardCCDBLoader.h" #include "Common/Tools/TrackPropagationModule.h" #include "Common/Tools/TrackTuner.h" #include +#include +#include +#include #include #include #include @@ -46,7 +50,6 @@ using namespace o2; using namespace o2::framework; -// using namespace o2::framework::expressions; // use parameters + cov mat non-propagated, aux info + (extension propagated) using FullTracksExt = soa::Join; @@ -62,15 +65,22 @@ using TracksWithExtra = soa::Join; // For dE/dx association in pre-selection using TracksExtraWithPID = soa::Join; -struct propagationService { - // CCDB boilerplate declarations +struct propagationServiceV2 { + // Service kept for MatLUT (rectifyPtrFromFile) and + // strangenessBuilderModule (V-drift via ccdb->instance()). + // GRPMagField and MeanVertex are sourced from CCDB columns instead. o2::framework::Configurable ccdburl{"ccdburl", "http://alice-ccdb.cern.ch", "url of the ccdb repository"}; Service ccdb; - // propagation stuff + // propagation stuff — ccdbLoader used only for lut + mMeanVtx (set from column) + runNumber o2::common::StandardCCDBLoaderConfigurables standardCCDBLoaderConfigurables; o2::common::StandardCCDBLoader ccdbLoader; + // Declarative CCDB path overrides (replace grpmagPath / mVtxPath in StandardCCDBLoaderConfigurables) + // Option names: "ccdb:fGRPMagField" and "ccdb:fMeanVertex" respectively. + ConfigurableCCDBPath grpmagPath; + ConfigurableCCDBPath mVtxPath; + // boilerplate: strangeness builder stuff o2::pwglf::strangenessbuilder::products products; o2::pwglf::strangenessbuilder::coreConfigurables baseOpts; @@ -87,12 +97,14 @@ struct propagationService { o2::common::TrackPropagationConfigurables trackPropagationConfigurables; o2::common::TrackPropagationModule trackPropagation; + using BCsWithCCDB = soa::Join; + // registry HistogramRegistry histos{"histos"}; void init(o2::framework::InitContext& initContext) { - // CCDB boilerplate init + // Only needed for MatLUT fetch and strangenessBuilderModule V-drift ccdb->setCaching(true); ccdb->setLocalObjectValidityChecking(); ccdb->setURL(ccdburl.value); @@ -102,38 +114,72 @@ struct propagationService { strangenessBuilderModule.init(baseOpts, v0BuilderOpts, cascadeBuilderOpts, preSelectOpts, histos, initContext); } - void processRealData(soa::Join const& collisions, aod::V0s const& v0s, aod::Cascades const& cascades, aod::TrackedCascades const& trackedCascades, FullTracksExtIU const& tracks, aod::BCsWithTimestamps const& bcs) + // Load MatLUT once (needs rectifyPtrFromFile, kept manual), set B-field per run from + // GRPMagField CCDB column, and refresh mMeanVtx pointer every call (pointer into current + // BC table, valid only for the duration of this process() invocation). + template + void initCCDB(TBC const& bc0) + { + if (!ccdbLoader.lut) { + LOG(info) << "Loading material look-up table for run: " << bc0.runNumber(); + ccdbLoader.lut = o2::base::MatLayerCylSet::rectifyPtrFromFile( + ccdb->template getForRun(standardCCDBLoaderConfigurables.lutPath.value, bc0.runNumber())); + o2::base::Propagator::Instance()->setMatLUT(ccdbLoader.lut); + } + // Always refresh: pointer into current BC table, invalidated after process() returns + ccdbLoader.mMeanVtx = &bc0.meanVertex(); + if (ccdbLoader.runNumber != bc0.runNumber()) { + const auto& grpmag = bc0.grpMagField(); // from declarative CCDB column + LOG(info) << "Setting B-field to current " << grpmag.getL3Current() << " A for run " << bc0.runNumber() << " from GRPMagField CCDB column"; + o2::base::Propagator::initFieldFromGRP(&grpmag); + ccdbLoader.runNumber = bc0.runNumber(); + } + } + + void processRealData(soa::Join const& collisions, aod::V0s const& v0s, aod::Cascades const& cascades, aod::TrackedCascades const& trackedCascades, FullTracksExtIU const& tracks, BCsWithCCDB const& bcs) { - ccdbLoader.initCCDBfromBCs(standardCCDBLoaderConfigurables, ccdb, bcs); + if (bcs.size() == 0) { + return; + } + initCCDB(bcs.begin()); trackPropagation.fillTrackTables(trackPropagationConfigurables, trackTunerObj, ccdbLoader, collisions, tracks, trackPropagationProducts, histos); strangenessBuilderModule.dataProcess(ccdb, histos, collisions, static_cast(nullptr), v0s, cascades, trackedCascades, tracks, bcs, static_cast(nullptr), products); } - void processMonteCarlo(soa::Join const& collisions, aod::McCollisions const& mccollisions, aod::V0s const& v0s, aod::Cascades const& cascades, aod::TrackedCascades const& trackedCascades, FullTracksExtLabeledIU const& tracks, aod::BCsWithTimestamps const& bcs, aod::McParticles const& mcParticles) + void processMonteCarlo(soa::Join const& collisions, aod::McCollisions const& mccollisions, aod::V0s const& v0s, aod::Cascades const& cascades, aod::TrackedCascades const& trackedCascades, FullTracksExtLabeledIU const& tracks, BCsWithCCDB const& bcs, aod::McParticles const& mcParticles) { - ccdbLoader.initCCDBfromBCs(standardCCDBLoaderConfigurables, ccdb, bcs); + if (bcs.size() == 0) { + return; + } + initCCDB(bcs.begin()); trackPropagation.fillTrackTables(trackPropagationConfigurables, trackTunerObj, ccdbLoader, collisions, tracks, trackPropagationProducts, histos); strangenessBuilderModule.dataProcess(ccdb, histos, collisions, mccollisions, v0s, cascades, trackedCascades, tracks, bcs, mcParticles, products); } - void processRealDataWithPID(soa::Join const& collisions, aod::V0s const& v0s, aod::Cascades const& cascades, aod::TrackedCascades const& trackedCascades, FullTracksExtIUWithPID const& tracks, aod::BCsWithTimestamps const& bcs) + void processRealDataWithPID(soa::Join const& collisions, aod::V0s const& v0s, aod::Cascades const& cascades, aod::TrackedCascades const& trackedCascades, FullTracksExtIUWithPID const& tracks, BCsWithCCDB const& bcs) { - ccdbLoader.initCCDBfromBCs(standardCCDBLoaderConfigurables, ccdb, bcs); + if (bcs.size() == 0) { + return; + } + initCCDB(bcs.begin()); trackPropagation.fillTrackTables(trackPropagationConfigurables, trackTunerObj, ccdbLoader, collisions, tracks, trackPropagationProducts, histos); strangenessBuilderModule.dataProcess(ccdb, histos, collisions, static_cast(nullptr), v0s, cascades, trackedCascades, tracks, bcs, static_cast(nullptr), products); } - void processMonteCarloWithPID(soa::Join const& collisions, aod::McCollisions const& mccollisions, aod::V0s const& v0s, aod::Cascades const& cascades, aod::TrackedCascades const& trackedCascades, FullTracksExtLabeledIUWithPID const& tracks, aod::BCsWithTimestamps const& bcs, aod::McParticles const& mcParticles) + void processMonteCarloWithPID(soa::Join const& collisions, aod::McCollisions const& mccollisions, aod::V0s const& v0s, aod::Cascades const& cascades, aod::TrackedCascades const& trackedCascades, FullTracksExtLabeledIUWithPID const& tracks, BCsWithCCDB const& bcs, aod::McParticles const& mcParticles) { - ccdbLoader.initCCDBfromBCs(standardCCDBLoaderConfigurables, ccdb, bcs); + if (bcs.size() == 0) { + return; + } + initCCDB(bcs.begin()); trackPropagation.fillTrackTables(trackPropagationConfigurables, trackTunerObj, ccdbLoader, collisions, tracks, trackPropagationProducts, histos); strangenessBuilderModule.dataProcess(ccdb, histos, collisions, mccollisions, v0s, cascades, trackedCascades, tracks, bcs, mcParticles, products); } - PROCESS_SWITCH(propagationService, processRealData, "process real data", true); - PROCESS_SWITCH(propagationService, processMonteCarlo, "process monte carlo", false); - PROCESS_SWITCH(propagationService, processRealDataWithPID, "process real data", false); - PROCESS_SWITCH(propagationService, processMonteCarloWithPID, "process monte carlo", false); + PROCESS_SWITCH(propagationServiceV2, processRealData, "process real data", true); + PROCESS_SWITCH(propagationServiceV2, processMonteCarlo, "process monte carlo", false); + PROCESS_SWITCH(propagationServiceV2, processRealDataWithPID, "process real data", false); + PROCESS_SWITCH(propagationServiceV2, processMonteCarloWithPID, "process monte carlo", false); }; //**************************************************************************************** @@ -143,6 +189,6 @@ struct propagationService { //**************************************************************************************** WorkflowSpec defineDataProcessing(ConfigContext const& cfgc) { - WorkflowSpec workflow{adaptAnalysisTask(cfgc)}; + WorkflowSpec workflow{adaptAnalysisTask(cfgc)}; return workflow; }