diff --git a/Common/Core/PID/PIDTOF.h b/Common/Core/PID/PIDTOF.h index b3e8c0b215b..3c507223feb 100644 --- a/Common/Core/PID/PIDTOF.h +++ b/Common/Core/PID/PIDTOF.h @@ -40,8 +40,10 @@ namespace o2::pid::tof { -// Utility values -static constexpr float defaultReturnValue = -999.f; /// Default return value in case TOF measurement is not available +// Utility values (to remove!) +static constexpr float kCSPEED = TMath::C() * 1.0e2f * 1.0e-12f; /// Speed of light in TOF units (cm/ps) +static constexpr float kCSPEDDInv = 1.f / kCSPEED; /// Inverse of the Speed of light in TOF units (ps/cm) +static constexpr float defaultReturnValue = -999.f; /// Default return value in case TOF measurement is not available /// \brief Class to handle the the TOF detector response for the TOF beta measurement template @@ -206,24 +208,6 @@ class TOFResoParamsV2 : public o2::tof::Parameters<13> printMomentumChargeShiftParameters(); } - // Time shift for post calibration - void setTimeShiftParameters(std::unordered_map const& pars, bool positive) - { - std::string baseOpt = positive ? "TimeShift.Pos." : "TimeShift.Neg."; - - if (pars.count(baseOpt + "GetN") == 0) { // If the map does not contain the number of eta bins, we assume that no correction has to be applied - return; - } - const int nPoints = static_cast(pars.at(baseOpt + "GetN")); - if (nPoints <= 0) { - LOG(fatal) << "TOFResoParamsV2 shift: time must be positive"; - } - TGraph graph; - for (int i = 0; i < nPoints; ++i) { - graph.AddPoint(pars.at(Form("TimeShift.eta%i", i)), pars.at(Form("TimeShift.cor%i", i))); - } - setTimeShiftParameters(&graph, positive); - } void setTimeShiftParameters(std::string const& filename, std::string const& objname, bool positive) { TFile f(filename.c_str(), "READ"); @@ -235,7 +219,7 @@ class TOFResoParamsV2 : public o2::tof::Parameters<13> } f.Close(); } - LOG(info) << "Set the Time Shift parameters from file " << filename << " and object " << objname << " for " << (positive ? "positive" : "negative") << " example of shift at eta 0: " << getTimeShift(0, positive); + LOG(info) << "Set the Time Shift parameters from file " << filename << " and object " << objname << " for " << (positive ? "positive" : "negative"); } void setTimeShiftParameters(TGraph* g, bool positive) { @@ -277,14 +261,12 @@ class TOFResoParamsV2 : public o2::tof::Parameters<13> class TOFResoParamsV3 : public o2::tof::Parameters<13> { public: - TOFResoParamsV3() : Parameters(std::array{"TrkRes.Pi.P0", "TrkRes.Pi.P1", "TrkRes.Pi.P2", "TrkRes.Pi.P3", "time_resolution", - "TrkRes.Ka.P0", "TrkRes.Ka.P1", "TrkRes.Ka.P2", "TrkRes.Ka.P3", - "TrkRes.Pr.P0", "TrkRes.Pr.P1", "TrkRes.Pr.P2", "TrkRes.Pr.P3"}, + TOFResoParamsV3() : Parameters(std::array{"time_resolution", "time_resolution", "time_resolution", "time_resolution", "time_resolution", + "time_resolution", "time_resolution", "time_resolution", "time_resolution", + "time_resolution", "time_resolution", "time_resolution", "time_resolution"}, "TOFResoParamsV3") { - setParameters(std::array{0.008, 0.008, 0.002, 40.0, 60.0, - 0.008, 0.008, 0.002, 40.0, - 0.008, 0.008, 0.002, 40.0}); + setParameters(std::array{60.0}); } // Default constructor with default parameters ~TOFResoParamsV3() = default; @@ -410,7 +392,7 @@ class TOFResoParamsV3 : public o2::tof::Parameters<13> for (int i = 0; i < 9; ++i) { if (!mResolution[i]) { LOG(info) << "Resolution function for " << particleNames[i] << " not provided, using default " << mDefaultResoParams[i]; - continue; + mResolution[i] = new TF2(Form("tofResTrack.%s_Default", particleNames[i]), mDefaultResoParams[i], 0., 20, -1, 1.); } LOG(info) << "Resolution function for " << particleNames[i] << " is " << mResolution[i]->GetName() << " with formula " << mResolution[i]->GetFormula()->GetExpFormula(); } @@ -419,37 +401,9 @@ class TOFResoParamsV3 : public o2::tof::Parameters<13> template float getResolution(const float p, const float eta) const { - if (!mResolution[pid]) { - LOG(info) << "Making default resolution parametrization for id " << pid << " :" << mDefaultResoParams[pid]; - mResolution[pid] = new TF2(Form("tofResTrack.Default_id%i", pid), mDefaultResoParams[pid], 0., 20, -1, 1.); - } return mResolution[pid]->Eval(p, eta); } - void Save(const char* filename) - { - TFile f(filename, "RECREATE"); - for (auto* h : mResolution) { - h->Write(); - } - if (gPosEtaTimeCorr) { - // gPosEtaTimeCorr->SetName("gPosEtaTimeCorr"); - // gPosEtaTimeCorr->Write(); - } else { - TNamed("NOgPosEtaTimeCorr", "not available").Write("NOgPosEtaTimeCorr"); - } - if (gNegEtaTimeCorr) { - // gNegEtaTimeCorr->SetName("gNegEtaTimeCorr"); - // gNegEtaTimeCorr->Write("gNegEtaTimeCorr"); - } else { - TNamed("NOgNegEtaTimeCorr", "not available").Write("NOgNegEtaTimeCorr"); - } - TNamed(Form("mEtaN=%i", mEtaN), "value").Write(); - TNamed(Form("mEtaStart=%f", mEtaStart), "value").Write(); - TNamed(Form("mEtaStop=%f", mEtaStop), "value").Write(); - TNamed(Form("mInvEtaWidth=%f", mInvEtaWidth), "value").Write(); - } - private: // Charge calibration int mEtaN = 0; // Number of eta bins, 0 means no correction diff --git a/Common/TableProducer/PID/pidTOFMerge.cxx b/Common/TableProducer/PID/pidTOFMerge.cxx index cfd3c566c2b..b7902b9aeaf 100644 --- a/Common/TableProducer/PID/pidTOFMerge.cxx +++ b/Common/TableProducer/PID/pidTOFMerge.cxx @@ -71,6 +71,7 @@ struct TOFCalibConfig { mParamFileName = opt.cfgParamFileName.value; mParametrizationPath = opt.cfgParametrizationPath.value; mReconstructionPass = opt.cfgReconstructionPass.value; + mReconstructionPassDefault = opt.cfgReconstructionPassDefault.value; mLoadResponseFromCCDB = opt.cfgLoadResponseFromCCDB.value; mFatalOnPassNotAvailable = opt.cfgFatalOnPassNotAvailable.value; mEnableTimeDependentResponse = opt.cfgEnableTimeDependentResponse.value; @@ -81,7 +82,7 @@ struct TOFCalibConfig { template void getCfg(o2::framework::InitContext& initContext, const std::string name, VType& v, const std::string task) { - if (!getTaskOptionValue(initContext, task, name, v, true)) { + if (!getTaskOptionValue(initContext, task, name, v, false)) { LOG(fatal) << "Could not get " << name << " from " << task << " task"; } } @@ -93,7 +94,7 @@ struct TOFCalibConfig { getCfg(initContext, "ccdb-path-grplhcif", mPathGrpLhcIf, task); getCfg(initContext, "ccdb-timestamp", mTimestamp, task); getCfg(initContext, "timeShiftCCDBPathPos", mTimeShiftCCDBPathPos, task); - getCfg(initContext, "timeShiftCCDBPathNeg", mTimeShiftCCDBPathPos, task); + getCfg(initContext, "timeShiftCCDBPathNeg", mTimeShiftCCDBPathNeg, task); getCfg(initContext, "paramFileName", mParamFileName, task); getCfg(initContext, "parametrizationPath", mParametrizationPath, task); getCfg(initContext, "reconstructionPass", mReconstructionPass, task); @@ -129,49 +130,60 @@ struct TOFCalibConfig { } LOG(info) << "Using parameter collection, starting from pass '" << mReconstructionPass << "'"; - const std::string fname = mParamFileName; - if (!fname.empty()) { // Loading the parametrization from file - LOG(info) << "Loading exp. sigma parametrization from file " << fname << ", using param: " << mParametrizationPath; - if (1) { - o2::tof::ParameterCollection paramCollection; - paramCollection.loadParamFromFile(fname, mParametrizationPath); - LOG(info) << "+++ Loaded parameter collection from file +++"; - if (!paramCollection.retrieveParameters(mRespParamsV3, mReconstructionPass)) { - if (mFatalOnPassNotAvailable) { - LOGF(fatal, "Pass '%s' not available in the retrieved CCDB object", mReconstructionPass.data()); + if (!mParamFileName.empty()) { // Loading the parametrization from file + LOG(info) << "Loading exp. sigma parametrization from file " << mParamFileName << ", using param: " << mParametrizationPath << " and pass " << mReconstructionPass; + o2::tof::ParameterCollection paramCollection; + paramCollection.loadParamFromFile(mParamFileName, mParametrizationPath); + LOG(info) << "+++ Loaded parameter collection from file +++"; + if (!paramCollection.retrieveParameters(mRespParamsV3, mReconstructionPass)) { + if (mFatalOnPassNotAvailable) { + LOG(fatal) << "Pass '" << mReconstructionPass << "' not available in the retrieved object from file"; + } else { + LOG(warning) << "Pass '" << mReconstructionPass << "' not available in the retrieved object from file, fetching '" << mReconstructionPassDefault << "'"; + if (!paramCollection.retrieveParameters(mRespParamsV3, mReconstructionPassDefault)) { + paramCollection.print(); + LOG(fatal) << "Cannot get default pass for calibration " << mReconstructionPassDefault; } else { - LOGF(warning, "Pass '%s' not available in the retrieved CCDB object", mReconstructionPass.data()); + mRespParamsV3.setResolutionParametrization(paramCollection.getPars(mReconstructionPassDefault)); + mRespParamsV3.setMomentumChargeShiftParameters(paramCollection.getPars(mReconstructionPassDefault)); + mRespParamsV3.printMomentumChargeShiftParameters(); } - } else { - mRespParamsV3.setMomentumChargeShiftParameters(paramCollection.getPars(mReconstructionPass)); - mRespParamsV3.printMomentumChargeShiftParameters(); } - } else { - mRespParamsV3.loadParamFromFile(fname.data(), mParametrizationPath); + } else { // Pass is available, load non standard parameters + mRespParamsV3.setResolutionParametrization(paramCollection.getPars(mReconstructionPass)); + mRespParamsV3.setMomentumChargeShiftParameters(paramCollection.getPars(mReconstructionPass)); + mRespParamsV3.printMomentumChargeShiftParameters(); } - } else if (mLoadResponseFromCCDB) { // Loading it from CCDB - LOG(info) << "Loading exp. sigma parametrization from CCDB, using path: " << mParametrizationPath << " for timestamp " << mTimestamp; + } else if (mLoadResponseFromCCDB && !mEnableTimeDependentResponse) { // Loading it from CCDB + LOG(info) << "Loading initial exp. sigma parametrization from CCDB, using path: " << mParametrizationPath << " for timestamp " << mTimestamp; o2::tof::ParameterCollection* paramCollection = ccdb->template getForTimeStamp(mParametrizationPath, mTimestamp); paramCollection->print(); if (!paramCollection->retrieveParameters(mRespParamsV3, mReconstructionPass)) { // Attempt at loading the parameters with the pass defined if (mFatalOnPassNotAvailable) { - LOGF(fatal, "Pass '%s' not available in the retrieved CCDB object", mReconstructionPass.data()); + LOG(fatal) << "Pass '" << mReconstructionPass << "' not available in the retrieved CCDB object"; } else { - LOGF(warning, "Pass '%s' not available in the retrieved CCDB object", mReconstructionPass.data()); + LOG(warning) << "Pass '" << mReconstructionPass << "' not available in the retrieved CCDB object, fetching '" << mReconstructionPassDefault << "'"; + if (!paramCollection->retrieveParameters(mRespParamsV3, mReconstructionPassDefault)) { + paramCollection->print(); + LOG(fatal) << "Cannot get default pass for calibration " << mReconstructionPassDefault; + } else { + mRespParamsV3.setResolutionParametrization(paramCollection->getPars(mReconstructionPassDefault)); + mRespParamsV3.setMomentumChargeShiftParameters(paramCollection->getPars(mReconstructionPassDefault)); + mRespParamsV3.printMomentumChargeShiftParameters(); + } } } else { // Pass is available, load non standard parameters + mRespParamsV3.setResolutionParametrization(paramCollection->getPars(mReconstructionPass)); mRespParamsV3.setMomentumChargeShiftParameters(paramCollection->getPars(mReconstructionPass)); mRespParamsV3.printMomentumChargeShiftParameters(); } } - // Calibration object is defined - mRespParamsV3.print(); // Loading additional calibration objects if (mTimeShiftCCDBPathPos != "") { if (mTimeShiftCCDBPathPos.find(".root") != std::string::npos) { mRespParamsV3.setTimeShiftParameters(mTimeShiftCCDBPathPos, "ccdb_object", true); - } else { + } else if (!mEnableTimeDependentResponse) { if (mReconstructionPass == "") { mRespParamsV3.setTimeShiftParameters(ccdb->template getForTimeStamp(mTimeShiftCCDBPathPos, mTimestamp), true); } else { @@ -184,7 +196,7 @@ struct TOFCalibConfig { if (mTimeShiftCCDBPathNeg != "") { if (mTimeShiftCCDBPathNeg.find(".root") != std::string::npos) { mRespParamsV3.setTimeShiftParameters(mTimeShiftCCDBPathNeg, "ccdb_object", false); - } else { + } else if (!mEnableTimeDependentResponse) { if (mReconstructionPass == "") { mRespParamsV3.setTimeShiftParameters(ccdb->template getForTimeStamp(mTimeShiftCCDBPathNeg, mTimestamp), false); } else { @@ -194,6 +206,11 @@ struct TOFCalibConfig { } } } + + // Calibration object is defined + LOG(info) << "Parametrization at init time:"; + mRespParamsV3.print(); + // mRespParamsV3.Save("/tmp/calib.root"); } template @@ -221,14 +238,50 @@ struct TOFCalibConfig { if (!mEnableTimeDependentResponse) { return; } - LOG(debug) << "Updating parametrization from path '" << mParametrizationPath << "' and timestamp " << mTimestamp; - if (!ccdb->template getForTimeStamp(mParametrizationPath, mTimestamp)->retrieveParameters(mRespParamsV3, mReconstructionPass)) { - if (mFatalOnPassNotAvailable) { - LOGF(fatal, "Pass '%s' not available in the retrieved CCDB object", mReconstructionPass.data()); + LOG(info) << "Updating parametrization from path '" << mParametrizationPath << "' and timestamp " << mTimestamp << " and reconstruction pass '" << mReconstructionPass << "'"; + if (mParamFileName.empty()) { // Not loading if parametrization from file + if (!ccdb->template getForTimeStamp(mParametrizationPath, mTimestamp)->retrieveParameters(mRespParamsV3, mReconstructionPass)) { + if (mFatalOnPassNotAvailable) { + LOGF(fatal, "Pass '%s' not available in the retrieved CCDB object", mReconstructionPass.data()); + } else { + LOGF(warning, "Pass '%s' not available in the retrieved CCDB object, fetching '%s'", mReconstructionPass.data(), mReconstructionPassDefault.data()); + if (!ccdb->template getForTimeStamp(mParametrizationPath, mTimestamp)->retrieveParameters(mRespParamsV3, mReconstructionPassDefault)) { + ccdb->template getForTimeStamp(mParametrizationPath, mTimestamp)->print(); + LOG(fatal) << "Cannot get default pass for calibration " << mReconstructionPassDefault; + } + } + } + } + + // Loading additional calibration objects + if (mTimeShiftCCDBPathPos != "") { + if (mTimeShiftCCDBPathPos.find(".root") != std::string::npos) { + mRespParamsV3.setTimeShiftParameters(mTimeShiftCCDBPathPos, "ccdb_object", true); + } else { + if (mReconstructionPass == "") { + mRespParamsV3.setTimeShiftParameters(ccdb->template getForTimeStamp(mTimeShiftCCDBPathPos, mTimestamp), true); + } else { + std::map metadata; + metadata["RecoPassName"] = mReconstructionPass; + mRespParamsV3.setTimeShiftParameters(ccdb->template getSpecific(mTimeShiftCCDBPathPos, mTimestamp, metadata), true); + } + } + } + if (mTimeShiftCCDBPathNeg != "") { + if (mTimeShiftCCDBPathNeg.find(".root") != std::string::npos) { + mRespParamsV3.setTimeShiftParameters(mTimeShiftCCDBPathNeg, "ccdb_object", false); } else { - LOGF(warning, "Pass '%s' not available in the retrieved CCDB object", mReconstructionPass.data()); + if (mReconstructionPass == "") { + mRespParamsV3.setTimeShiftParameters(ccdb->template getForTimeStamp(mTimeShiftCCDBPathNeg, mTimestamp), false); + } else { + std::map metadata; + metadata["RecoPassName"] = mReconstructionPass; + mRespParamsV3.setTimeShiftParameters(ccdb->template getSpecific(mTimeShiftCCDBPathNeg, mTimestamp, metadata), false); + } } + LOG(info) << " test getTimeShift neg: " << mRespParamsV3.getTimeShift(0, false); } + return; } @@ -248,6 +301,7 @@ struct TOFCalibConfig { std::string mParamFileName; std::string mParametrizationPath; std::string mReconstructionPass; + std::string mReconstructionPassDefault; bool mLoadResponseFromCCDB; bool mFatalOnPassNotAvailable; bool mEnableTimeDependentResponse; @@ -289,6 +343,7 @@ struct tofSignal { Configurable cfgParamFileName{"paramFileName", "", "Path to the parametrization object. If empty the parametrization is not taken from file"}; Configurable cfgParametrizationPath{"parametrizationPath", "TOF/Calib/Params", "Path of the TOF parametrization on the CCDB or in the file, if the paramFileName is not empty"}; Configurable cfgReconstructionPass{"reconstructionPass", "", {"Apass to use when fetching the calibration tables. Empty (default) does not check for any pass. Use `metadata` to fetch it from the AO2D metadata. Otherwise it will override the metadata."}}; + Configurable cfgReconstructionPassDefault{"reconstructionPassDefault", "unanchored", {"Default pass to get if the standard one is not found"}}; Configurable cfgLoadResponseFromCCDB{"loadResponseFromCCDB", false, "Flag to load the response from the CCDB"}; Configurable cfgFatalOnPassNotAvailable{"fatalOnPassNotAvailable", true, "Flag to throw a fatal if the pass is not available in the retrieved CCDB object"}; Configurable cfgEnableTimeDependentResponse{"enableTimeDependentResponse", false, "Flag to use the collision timestamp to fetch the PID Response"}; diff --git a/Common/Tasks/CMakeLists.txt b/Common/Tasks/CMakeLists.txt index 2884d3b8b31..5e8f51e6f47 100644 --- a/Common/Tasks/CMakeLists.txt +++ b/Common/Tasks/CMakeLists.txt @@ -82,4 +82,4 @@ o2physics_add_dpl_workflow(qvectors-correction o2physics_add_dpl_workflow(centrality-study SOURCES centralityStudy.cxx PUBLIC_LINK_LIBRARIES O2::Framework O2Physics::AnalysisCore - COMPONENT_NAME Analysis) \ No newline at end of file + COMPONENT_NAME Analysis)