2222#include " Common/Tools/TrackTuner.h"
2323
2424#include < CommonConstants/GeomConstants.h>
25+ #include < DataFormatsCalibration/MeanVertexObject.h>
2526#include < DetectorsBase/Propagator.h>
2627#include < Framework/AnalysisDataModel.h>
2728#include < Framework/AnalysisHelpers.h>
3132#include < Framework/HistogramRegistry.h>
3233#include < Framework/HistogramSpec.h>
3334#include < Framework/Logger.h>
34- #include < Framework/RunningWorkflowInfo.h>
3535#include < ReconstructionDataFormats/DCA.h>
3636#include < ReconstructionDataFormats/TrackParametrization.h>
3737#include < ReconstructionDataFormats/TrackParametrizationWithError.h>
3838
3939#include < TH1.h>
4040#include < TH2.h>
41+ #include < TList.h>
4142
4243#include < array>
4344#include < cmath>
@@ -109,7 +110,9 @@ class TrackPropagationModule
109110 bool autoDetectDcaCalib = false ; // track tuner setting
110111
111112 template <typename TConfigurableGroup, typename TInitContext, typename THistoRegistry>
112- void init (TConfigurableGroup const & cGroup, TrackTuner& trackTunerObj, THistoRegistry& registry, TInitContext& initContext)
113+ // / \param calibFromCCDBColumns the task supplies the TrackTuner calibrations from the
114+ // / aod::TrackTunerCCDBObjects columns, so nothing is fetched from CCDB here.
115+ void init (TConfigurableGroup const & cGroup, TrackTuner& trackTunerObj, THistoRegistry& registry, TInitContext& initContext, bool calibFromCCDBColumns = false )
113116 {
114117 // Checking if the tables are requested in the workflow and enabling them
115118 fillTracks = o2::common::core::isTableRequiredInWorkflow (initContext, " Tracks" );
@@ -176,23 +179,31 @@ class TrackPropagationModule
176179 // / read the track tuner instance configurations,
177180 // / to understand whether the TrackTuner::getDcaGraphs function can be called here (input path from string/configurables)
178181 // / or inside the process function, to "auto-detect" the input file based on the run number
179- const auto & workflows = initContext.services ().template get <o2::framework::RunningWorkflowInfo const >();
180- for (o2::framework::DeviceSpec const & device : workflows.devices ) { // / loop over devices
181- if (device.name == " propagation-service" ) {
182- // loop over the options
183- // to find the value of TrackTuner::autoDetectDcaCalib
184- for (const auto & option : device.options ) { // / loop over options
185- if (option.name == " trackTuner.autoDetectDcaCalib" ) {
186- // found it!
187- autoDetectDcaCalib = option.defaultValue .get <bool >();
188- break ;
189- }
190- } // / end loop over options
182+ // Read the option off the device we are actually running in. This used to search
183+ // the workflow for a device literally named "propagation-service", which silently
184+ // matched nothing in any other task (propagation-service-v2, -run2, ...), leaving
185+ // autoDetectDcaCalib at its default no matter how the task was configured.
186+ o2::framework::DeviceSpec const & device = initContext.services ().template get <o2::framework::DeviceSpec const >();
187+ for (const auto & option : device.options ) { // / loop over options
188+ if (option.name == " trackTuner.autoDetectDcaCalib" ) {
189+ // found it!
190+ autoDetectDcaCalib = option.defaultValue .get <bool >();
191191 break ;
192192 }
193- } // / end loop over devices
193+ } // / end loop over options
194194 LOG (info) << " [TrackPropagationModule] trackTuner.autoDetectDcaCalib it's equal to " << autoDetectDcaCalib;
195- if (!autoDetectDcaCalib) {
195+ if (calibFromCCDBColumns && trackTunerObj.isInputFileFromCCDB ) {
196+ // The column is the single source of truth for the path: its default carries the
197+ // per-period mapping and it is overridden through "ccdb:fTrackTunerDca". Silently
198+ // preferring one of two path settings is how calibrations diverge unnoticed, so a
199+ // leftover trackTuner.pathInputFile is an error rather than a shadowed value.
200+ if (!trackTunerObj.pathInputFile .empty ()) {
201+ LOG (fatal) << " [TrackPropagationModule] trackTuner.pathInputFile is set to '" << trackTunerObj.pathInputFile
202+ << " ' while the TrackTuner calibrations are taken from the aod::TrackTunerCCDBObjects columns. "
203+ << " Set the path through the \" ccdb:fTrackTunerDca\" option instead, or unset trackTuner.pathInputFile." ;
204+ }
205+ LOG (info) << " [TrackPropagationModule] TrackTuner calibrations come from CCDB columns; graphs retrieved in the process function" ;
206+ } else if (!autoDetectDcaCalib) {
196207 LOG (info) << " [TrackPropagationModule] retrieve the graphs already (we are in propagationService::Init() function)" ;
197208 trackTunerObj.getDcaGraphs ();
198209 } else {
@@ -215,24 +226,50 @@ class TrackPropagationModule
215226 registry.template get <TH1 >(HIST (" hPropagation" ))->GetXaxis ()->SetBinLabel (3 , " Propagation OK" );
216227 }
217228
229+ // / Legacy overload for callers still holding a StandardCCDBLoader; forwards the two
230+ // / run-scoped values actually used. Prefer the overload below, which lets the caller
231+ // / source them from CCDB columns instead of a CCDB query.
218232 template <bool isMc, typename TConfigurableGroup, typename TCCDBLoader, typename TCollisions, typename TTracks, typename TOutputGroup, typename THistoRegistry>
219233 void fillTrackTables (TConfigurableGroup const & cGroup, TrackTuner& trackTunerObj, TCCDBLoader const & ccdbLoader, TCollisions const & collisions, TTracks const & tracks, TOutputGroup& cursors, THistoRegistry& registry)
234+ {
235+ fillTrackTables<isMc>(cGroup, trackTunerObj, ccdbLoader.runNumber , ccdbLoader.mMeanVtx , collisions, tracks, cursors, registry);
236+ }
237+
238+ // / Takes the run-scoped conditions it actually needs (run number for the TrackTuner
239+ // / path, mean vertex for the DCA reference) rather than a CCDB loader object, so that
240+ // / callers are free to source them from CCDB columns instead of a CCDB query.
241+ template <bool isMc, typename TConfigurableGroup, typename TCollisions, typename TTracks, typename TOutputGroup, typename THistoRegistry>
242+ void fillTrackTables (TConfigurableGroup const & cGroup, TrackTuner& trackTunerObj, int currentRunNumber, o2::dataformats::MeanVertexObject const * meanVtx, TCollisions const & collisions, TTracks const & tracks, TOutputGroup& cursors, THistoRegistry& registry)
243+ {
244+ fillTrackTables<isMc>(cGroup, trackTunerObj, currentRunNumber, meanVtx, nullptr , nullptr , collisions, tracks, cursors, registry);
245+ }
246+
247+ // / As above, plus the TrackTuner calibration lists taken from the
248+ // / aod::TrackTunerCCDBObjects columns. When they are given, the run-range table that
249+ // / getPathInputFileAutomaticFromCCDB() would have walked has already been applied by
250+ // / the CCDB fetcher, so no CCDB query happens here at all.
251+ template <bool isMc, typename TConfigurableGroup, typename TCollisions, typename TTracks, typename TOutputGroup, typename THistoRegistry>
252+ void fillTrackTables (TConfigurableGroup const & cGroup, TrackTuner& trackTunerObj, int currentRunNumber, o2::dataformats::MeanVertexObject const * meanVtx, TList* dcaCalib, TList* qOverPtCalib, TCollisions const & collisions, TTracks const & tracks, TOutputGroup& cursors, THistoRegistry& registry)
220253 {
221254
222255 // / retrieve the TrackTuner calibration graphs *if not done yet*
223256 // / i.e. if autodetect is required
224- if (cGroup.useTrackTuner .value && autoDetectDcaCalib && !trackTunerObj. areGraphsConfigured ) {
257+ if (cGroup.useTrackTuner .value && !trackTunerObj. areGraphsConfigured && (autoDetectDcaCalib || dcaCalib != nullptr ) ) {
225258
226- // / get the run number from the ccdb loader, already initialized
227- const int runNumber = ccdbLoader.runNumber ;
228- trackTunerObj.setRunNumber (runNumber);
259+ trackTunerObj.setRunNumber (currentRunNumber);
229260
230- // / setup the "auto-detected" path based on the run number
231- trackTunerObj.getPathInputFileAutomaticFromCCDB ();
232- trackTunedTracks->SetTitle (trackTunerObj.outputString .c_str ());
261+ if (dcaCalib != nullptr ) {
262+ // / the path was resolved by the CCDB fetcher from the column's run-range mapping
263+ trackTunedTracks->SetTitle (trackTunerObj.outputString .c_str ());
264+ trackTunerObj.getDcaGraphs (dcaCalib, qOverPtCalib);
265+ } else {
266+ // / setup the "auto-detected" path based on the run number
267+ trackTunerObj.getPathInputFileAutomaticFromCCDB ();
268+ trackTunedTracks->SetTitle (trackTunerObj.outputString .c_str ());
233269
234- // / now that the path is ok, retrieve the graphs
235- trackTunerObj.getDcaGraphs ();
270+ // / now that the path is ok, retrieve the graphs
271+ trackTunerObj.getDcaGraphs ();
272+ }
236273 }
237274
238275 if (!fillTracks) {
@@ -314,11 +351,11 @@ class TrackPropagationModule
314351 }
315352 } else {
316353 if (fillTracksCov) {
317- mVtx .setPos ({ccdbLoader. mMeanVtx ->getX (), ccdbLoader. mMeanVtx ->getY (), ccdbLoader. mMeanVtx ->getZ ()});
318- mVtx .setCov (ccdbLoader. mMeanVtx ->getSigmaX () * ccdbLoader. mMeanVtx ->getSigmaX (), 0 .0f , ccdbLoader. mMeanVtx ->getSigmaY () * ccdbLoader. mMeanVtx ->getSigmaY (), 0 .0f , 0 .0f , ccdbLoader. mMeanVtx ->getSigmaZ () * ccdbLoader. mMeanVtx ->getSigmaZ ());
354+ mVtx .setPos ({meanVtx ->getX (), meanVtx ->getY (), meanVtx ->getZ ()});
355+ mVtx .setCov (meanVtx ->getSigmaX () * meanVtx ->getSigmaX (), 0 .0f , meanVtx ->getSigmaY () * meanVtx ->getSigmaY (), 0 .0f , 0 .0f , meanVtx ->getSigmaZ () * meanVtx ->getSigmaZ ());
319356 isPropagationOK = o2::base::Propagator::Instance ()->propagateToDCABxByBz (mVtx , mTrackParCov , 2 .f , matCorr, &mDcaInfoCov );
320357 } else {
321- isPropagationOK = o2::base::Propagator::Instance ()->propagateToDCABxByBz ({ccdbLoader. mMeanVtx ->getX (), ccdbLoader. mMeanVtx ->getY (), ccdbLoader. mMeanVtx ->getZ ()}, mTrackPar , 2 .f , matCorr, &mDcaInfo );
358+ isPropagationOK = o2::base::Propagator::Instance ()->propagateToDCABxByBz ({meanVtx ->getX (), meanVtx ->getY (), meanVtx ->getZ ()}, mTrackPar , 2 .f , matCorr, &mDcaInfo );
322359 }
323360 }
324361 if (isPropagationOK) {
0 commit comments