Skip to content

Commit 028ef2a

Browse files
committed
Add TOF Response parameters as a service
1 parent a343f5e commit 028ef2a

File tree

4 files changed

+503
-0
lines changed

4 files changed

+503
-0
lines changed

Common/Core/CMakeLists.txt

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ o2physics_add_library(AnalysisCore
1414
OrbitRange.cxx
1515
PID/ParamBase.cxx
1616
PID/PIDTOF.cxx
17+
PID/PIDTOFService.cxx
1718
CollisionAssociation.cxx
1819
TrackSelectionDefaults.cxx
1920
EventPlaneHelper.cxx
@@ -34,6 +35,7 @@ o2physics_target_root_dictionary(AnalysisCore
3435
PID/DetectorResponse.h
3536
PID/PIDTOF.h
3637
PID/TPCPIDResponse.h
38+
PID/PIDTOFService.h
3739
CollisionTypeHelper.h
3840
FFitWeights.h
3941
LINKDEF AnalysisCoreLinkDef.h)

Common/Core/PID/PIDTOFService.cxx

Lines changed: 293 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,293 @@
1+
// Copyright 2019-2020 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+
///
13+
/// \file PIDTOFService.cxx
14+
/// \author Nicolò Jacazio nicolo.jacazio@cern.ch
15+
/// \since 30/06/2025
16+
/// \brief Implementation of the TOF PID service for the detector response
17+
///
18+
19+
#include "PIDTOFService.h"
20+
21+
#include <Framework/CommonServices.h>
22+
#include <Framework/Plugins.h>
23+
#include <Framework/ServiceHandle.h>
24+
#include <Framework/ServiceSpec.h>
25+
26+
#include <map>
27+
#include <string>
28+
29+
using namespace o2::framework;
30+
31+
o2::pid::tof::TOFResoParamsV3 o2::pid::tof::TOFResponseImpl::parameters;
32+
o2::common::core::MetadataHelper o2::pid::tof::TOFResponseImpl::metadataInfo;
33+
bool o2::pid::tof::TOFResponseImpl::mIsInit = false;
34+
int o2::pid::tof::TOFResponseImpl::mLastRunNumber = -1;
35+
36+
void o2::pid::tof::TOFResponseImpl::inheritFromBaseTask(o2::framework::InitContext& initContext, const std::string task)
37+
{
38+
if (mIsInit) {
39+
LOG(fatal) << "TOFResponseImpl already initialized, cannot re-initialize";
40+
}
41+
getCfg(initContext, "ccdb-url", mUrl, task);
42+
getCfg(initContext, "ccdb-path-grplhcif", mPathGrpLhcIf, task);
43+
getCfg(initContext, "ccdb-timestamp", mTimestamp, task);
44+
getCfg(initContext, "timeShiftCCDBPathPos", mTimeShiftCCDBPathPos, task);
45+
getCfg(initContext, "timeShiftCCDBPathNeg", mTimeShiftCCDBPathNeg, task);
46+
getCfg(initContext, "timeShiftCCDBPathPosMC", mTimeShiftCCDBPathPosMC, task);
47+
getCfg(initContext, "timeShiftCCDBPathNegMC", mTimeShiftCCDBPathNegMC, task);
48+
getCfg(initContext, "paramFileName", mParamFileName, task);
49+
getCfg(initContext, "parametrizationPath", mParametrizationPath, task);
50+
getCfg(initContext, "reconstructionPass", mReconstructionPass, task);
51+
getCfg(initContext, "reconstructionPassDefault", mReconstructionPassDefault, task);
52+
getCfg(initContext, "fatalOnPassNotAvailable", mFatalOnPassNotAvailable, task);
53+
getCfg(initContext, "enableTimeDependentResponse", mEnableTimeDependentResponse, task);
54+
getCfg(initContext, "collisionSystem", mCollisionSystem, task);
55+
getCfg(initContext, "autoSetProcessFunctions", mAutoSetProcessFunctions, task);
56+
}
57+
58+
void o2::pid::tof::TOFResponseImpl::initSetup(o2::ccdb::BasicCCDBManager* ccdb,
59+
o2::framework::InitContext& initContext)
60+
{
61+
if (mIsInit) {
62+
LOG(fatal) << "TOFResponseImpl already initialized, cannot re-initialize";
63+
}
64+
65+
if (!ccdb) {
66+
LOG(fatal) << "CCDB manager is not set, cannot initialize TOFResponseImpl";
67+
}
68+
inheritFromBaseTask(initContext); // Gets the configuration parameters from the base task (tof-signal)
69+
mCcdb = ccdb; // Set the CCDB manager
70+
mCcdb->setURL(mUrl);
71+
mCcdb->setTimestamp(mTimestamp);
72+
mCcdb->setCaching(true);
73+
mCcdb->setLocalObjectValidityChecking();
74+
// Not later than now objects
75+
mCcdb->setCreatedNotAfter(std::chrono::duration_cast<std::chrono::milliseconds>(std::chrono::system_clock::now().time_since_epoch()).count());
76+
77+
mIsInit = true; // Set the initialization flag
78+
79+
// Then the information about the metadata
80+
if (mReconstructionPass == "metadata") {
81+
LOG(info) << "Getting pass from metadata";
82+
if (metadataInfo.isMC()) {
83+
mReconstructionPass = metadataInfo.get("AnchorPassName");
84+
} else {
85+
mReconstructionPass = metadataInfo.get("RecoPassName");
86+
}
87+
LOG(info) << "Passed autodetect mode for pass. Taking '" << mReconstructionPass << "'";
88+
}
89+
LOG(info) << "Using parameter collection, starting from pass '" << mReconstructionPass << "'";
90+
91+
if (!mParamFileName.empty()) { // Loading the parametrization from file
92+
LOG(info) << "Loading exp. sigma parametrization from file " << mParamFileName << ", using param: " << mParametrizationPath << " and pass " << mReconstructionPass;
93+
o2::tof::ParameterCollection paramCollection;
94+
paramCollection.loadParamFromFile(mParamFileName, mParametrizationPath);
95+
LOG(info) << "+++ Loaded parameter collection from file +++";
96+
if (!paramCollection.retrieveParameters(parameters, mReconstructionPass)) {
97+
if (mFatalOnPassNotAvailable) {
98+
LOG(fatal) << "Pass '" << mReconstructionPass << "' not available in the retrieved object from file";
99+
} else {
100+
LOG(warning) << "Pass '" << mReconstructionPass << "' not available in the retrieved object from file, fetching '" << mReconstructionPassDefault << "'";
101+
if (!paramCollection.retrieveParameters(parameters, mReconstructionPassDefault)) {
102+
paramCollection.print();
103+
LOG(fatal) << "Cannot get default pass for calibration " << mReconstructionPassDefault;
104+
} else {
105+
if (metadataInfo.isRun3()) {
106+
parameters.setResolutionParametrization(paramCollection.getPars(mReconstructionPassDefault));
107+
} else {
108+
parameters.setResolutionParametrizationRun2(paramCollection.getPars(mReconstructionPassDefault));
109+
}
110+
parameters.setMomentumChargeShiftParameters(paramCollection.getPars(mReconstructionPassDefault));
111+
}
112+
}
113+
} else { // Pass is available, load non standard parameters
114+
if (metadataInfo.isRun3()) {
115+
parameters.setResolutionParametrization(paramCollection.getPars(mReconstructionPass));
116+
} else {
117+
parameters.setResolutionParametrizationRun2(paramCollection.getPars(mReconstructionPass));
118+
}
119+
parameters.setMomentumChargeShiftParameters(paramCollection.getPars(mReconstructionPass));
120+
}
121+
} else if (!mEnableTimeDependentResponse) { // Loading it from CCDB
122+
LOG(info) << "Loading initial exp. sigma parametrization from CCDB, using path: " << mParametrizationPath << " for timestamp " << mTimestamp;
123+
o2::tof::ParameterCollection* paramCollection = mCcdb->getSpecific<o2::tof::ParameterCollection>(mParametrizationPath, mTimestamp);
124+
if (!paramCollection->retrieveParameters(parameters, mReconstructionPass)) { // Attempt at loading the parameters with the pass defined
125+
if (mFatalOnPassNotAvailable) {
126+
LOG(fatal) << "Pass '" << mReconstructionPass << "' not available in the retrieved CCDB object";
127+
} else {
128+
LOG(warning) << "Pass '" << mReconstructionPass << "' not available in the retrieved CCDB object, fetching '" << mReconstructionPassDefault << "'";
129+
if (!paramCollection->retrieveParameters(parameters, mReconstructionPassDefault)) {
130+
paramCollection->print();
131+
LOG(fatal) << "Cannot get default pass for calibration " << mReconstructionPassDefault;
132+
} else {
133+
if (metadataInfo.isRun3()) {
134+
parameters.setResolutionParametrization(paramCollection->getPars(mReconstructionPassDefault));
135+
} else {
136+
parameters.setResolutionParametrizationRun2(paramCollection->getPars(mReconstructionPassDefault));
137+
}
138+
parameters.setMomentumChargeShiftParameters(paramCollection->getPars(mReconstructionPassDefault));
139+
}
140+
}
141+
} else { // Pass is available, load non standard parameters
142+
if (metadataInfo.isRun3()) {
143+
parameters.setResolutionParametrization(paramCollection->getPars(mReconstructionPass));
144+
} else {
145+
parameters.setResolutionParametrizationRun2(paramCollection->getPars(mReconstructionPass));
146+
}
147+
parameters.setMomentumChargeShiftParameters(paramCollection->getPars(mReconstructionPass));
148+
}
149+
}
150+
151+
// Loading additional calibration objects
152+
std::map<std::string, std::string> metadata;
153+
if (!mReconstructionPass.empty()) {
154+
metadata["RecoPassName"] = mReconstructionPass;
155+
}
156+
157+
auto updateTimeShift = [&](const std::string& nameShift, bool isPositive) {
158+
if (nameShift.empty()) {
159+
return;
160+
}
161+
const bool isFromFile = nameShift.find(".root") != std::string::npos;
162+
if (isFromFile) {
163+
LOG(info) << "Initializing the time shift for " << (isPositive ? "positive" : "negative") << " from file '" << nameShift << "'";
164+
parameters.setTimeShiftParameters(nameShift, "ccdb_object", isPositive);
165+
} else if (!mEnableTimeDependentResponse) { // If the response is fixed fetch it at the init time
166+
LOG(info) << "Initializing the time shift for " << (isPositive ? "positive" : "negative")
167+
<< " from ccdb '" << nameShift << "' and timestamp " << mTimestamp
168+
<< " and pass '" << mReconstructionPass << "'";
169+
mCcdb->setFatalWhenNull(false);
170+
parameters.setTimeShiftParameters(mCcdb->getSpecific<TGraph>(nameShift, mTimestamp, metadata), isPositive);
171+
mCcdb->setFatalWhenNull(true);
172+
}
173+
LOG(info) << " test getTimeShift at 0 " << (isPositive ? "pos" : "neg") << ": "
174+
<< parameters.getTimeShift(0, isPositive);
175+
};
176+
177+
const std::string nameShiftPos = metadataInfo.isMC() ? mTimeShiftCCDBPathPosMC : mTimeShiftCCDBPathPos;
178+
updateTimeShift(nameShiftPos, true);
179+
const std::string nameShiftNeg = metadataInfo.isMC() ? mTimeShiftCCDBPathNegMC : mTimeShiftCCDBPathNeg;
180+
updateTimeShift(nameShiftNeg, false);
181+
182+
// Calibration object is defined
183+
LOG(info) << "Parametrization at init time:";
184+
parameters.printFullConfig();
185+
}
186+
187+
void o2::pid::tof::TOFResponseImpl::processSetup(const int runNumber, const int64_t timeStamp)
188+
{
189+
LOG(debug) << "Processing setup for run number " << runNumber << " from run " << mLastRunNumber;
190+
// First we check if this run number was already processed
191+
if (mLastRunNumber == runNumber) {
192+
return;
193+
}
194+
LOG(info) << "Updating the parametrization from last run " << mLastRunNumber << " to " << runNumber << " and timestamp from " << mTimestamp << " " << timeStamp;
195+
mLastRunNumber = runNumber;
196+
mTimestamp = timeStamp;
197+
198+
// Check the beam type
199+
if (mCollisionSystem == o2::common::core::CollisionSystemType::kCollSysUndef) {
200+
o2::parameters::GRPLHCIFData* grpo = mCcdb->getSpecific<o2::parameters::GRPLHCIFData>(mPathGrpLhcIf,
201+
mTimestamp);
202+
mCollisionSystem = CollisionSystemType::getCollisionTypeFromGrp(grpo);
203+
} else {
204+
LOG(debug) << "Not setting collisions system as already set to " << mCollisionSystem << " " << CollisionSystemType::getCollisionSystemName(mCollisionSystem);
205+
}
206+
207+
if (!mEnableTimeDependentResponse) {
208+
return;
209+
}
210+
LOG(info) << "Updating parametrization from path '" << mParametrizationPath << "' and timestamp " << mTimestamp << " and reconstruction pass '" << mReconstructionPass << "' for run number " << runNumber;
211+
if (mParamFileName.empty()) { // Not loading if parametrization was taken from file
212+
LOG(info) << "Updating parametrization from ccdb";
213+
const o2::tof::ParameterCollection* paramCollection = mCcdb->getSpecific<o2::tof::ParameterCollection>(mParametrizationPath, mTimestamp);
214+
if (!paramCollection->retrieveParameters(parameters, mReconstructionPass)) {
215+
if (mFatalOnPassNotAvailable) {
216+
LOGF(fatal, "Pass '%s' not available in the retrieved CCDB object", mReconstructionPass.data());
217+
} else {
218+
LOGF(warning, "Pass '%s' not available in the retrieved CCDB object, fetching '%s'", mReconstructionPass.data(), mReconstructionPassDefault.data());
219+
if (!paramCollection->retrieveParameters(parameters, mReconstructionPassDefault)) {
220+
paramCollection->print();
221+
LOG(fatal) << "Cannot get default pass for calibration " << mReconstructionPassDefault;
222+
} else { // Found the default case
223+
if (metadataInfo.isRun3()) {
224+
parameters.setResolutionParametrization(paramCollection->getPars(mReconstructionPassDefault));
225+
} else {
226+
parameters.setResolutionParametrizationRun2(paramCollection->getPars(mReconstructionPassDefault));
227+
}
228+
parameters.setMomentumChargeShiftParameters(paramCollection->getPars(mReconstructionPassDefault));
229+
}
230+
}
231+
} else { // Found the non default case
232+
if (metadataInfo.isRun3()) {
233+
parameters.setResolutionParametrization(paramCollection->getPars(mReconstructionPass));
234+
} else {
235+
parameters.setResolutionParametrizationRun2(paramCollection->getPars(mReconstructionPass));
236+
}
237+
parameters.setMomentumChargeShiftParameters(paramCollection->getPars(mReconstructionPass));
238+
}
239+
}
240+
241+
// Loading additional calibration objects
242+
std::map<std::string, std::string> metadata;
243+
if (!mReconstructionPass.empty()) {
244+
metadata["RecoPassName"] = mReconstructionPass;
245+
}
246+
247+
auto updateTimeShift = [&](const std::string& nameShift, bool isPositive) {
248+
if (nameShift.empty()) {
249+
return;
250+
}
251+
const bool isFromFile = nameShift.find(".root") != std::string::npos;
252+
if (isFromFile) {
253+
return;
254+
}
255+
LOG(info) << "Updating the time shift for " << (isPositive ? "positive" : "negative")
256+
<< " from ccdb '" << nameShift << "' and timestamp " << mTimestamp
257+
<< " and pass '" << mReconstructionPass << "'";
258+
mCcdb->setFatalWhenNull(false);
259+
parameters.setTimeShiftParameters(mCcdb->getSpecific<TGraph>(nameShift, mTimestamp, metadata), isPositive);
260+
mCcdb->setFatalWhenNull(true);
261+
LOG(info) << " test getTimeShift at 0 " << (isPositive ? "pos" : "neg") << ": "
262+
<< parameters.getTimeShift(0, isPositive);
263+
};
264+
265+
updateTimeShift(metadataInfo.isMC() ? mTimeShiftCCDBPathPosMC : mTimeShiftCCDBPathPos, true);
266+
updateTimeShift(metadataInfo.isMC() ? mTimeShiftCCDBPathNegMC : mTimeShiftCCDBPathNeg, false);
267+
268+
LOG(info) << "Parametrization at setup time:";
269+
parameters.printFullConfig();
270+
}
271+
272+
struct TOFSupport : o2::framework::ServicePlugin {
273+
o2::framework::ServiceSpec* create() final
274+
{
275+
return new ServiceSpec{
276+
.name = "tof-response",
277+
.init = [](ServiceRegistryRef, DeviceState&, fair::mq::ProgOptions&) -> ServiceHandle {
278+
auto* wrapper = new o2::pid::tof::TOFResponse();
279+
auto* ptr = new o2::pid::tof::TOFResponseImpl();
280+
wrapper->setInstance(ptr);
281+
return ServiceHandle{TypeIdHelpers::uniqueId<o2::pid::tof::TOFResponse>(), wrapper, ServiceKind::Serial, "database-pdg"};
282+
},
283+
.configure = CommonServices::noConfiguration(),
284+
.exit = [](ServiceRegistryRef, void* service) {
285+
auto* resp = reinterpret_cast<o2::pid::tof::TOFResponse*>(service);
286+
delete resp; },
287+
.kind = ServiceKind::Serial};
288+
}
289+
};
290+
291+
DEFINE_DPL_PLUGINS_BEGIN
292+
DEFINE_DPL_PLUGIN_INSTANCE(TOFSupport, CustomService);
293+
DEFINE_DPL_PLUGINS_END

0 commit comments

Comments
 (0)