diff --git a/Analysis/Tutorials/CMakeLists.txt b/Analysis/Tutorials/CMakeLists.txt index 52bb47e3f52a1..9388a83462d13 100644 --- a/Analysis/Tutorials/CMakeLists.txt +++ b/Analysis/Tutorials/CMakeLists.txt @@ -234,3 +234,9 @@ o2_add_dpl_workflow(conditional-expressions JOB_POOL analysis PUBLIC_LINK_LIBRARIES O2::Framework O2::AnalysisCore O2::AnalysisDataModel COMPONENT_NAME AnalysisTutorial) + +o2_add_dpl_workflow(using-pdg + SOURCES src/usingPDGService.cxx + JOB_POOL analysis + PUBLIC_LINK_LIBRARIES O2::Framework O2::AnalysisCore O2::AnalysisDataModel + COMPONENT_NAME AnalysisTutorial) diff --git a/Analysis/Tutorials/src/usingPDGService.cxx b/Analysis/Tutorials/src/usingPDGService.cxx new file mode 100644 index 0000000000000..65bec77cde455 --- /dev/null +++ b/Analysis/Tutorials/src/usingPDGService.cxx @@ -0,0 +1,41 @@ +// 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. + +#include "Framework/AnalysisTask.h" +#include "AnalysisCore/MC.h" +#include "TDatabasePDG.h" +#include "Framework/runDataProcessing.h" + +using namespace o2; +using namespace o2::framework; + +struct UsePdgDatabase { + Service pdg; + OutputObj particleCharges{TH1F("charges", ";charge;entries", 201, -10.1, 10.1)}; + + void process(aod::McCollision const&, aod::McParticles const& particles) + { + for (auto& particle : particles) { + auto pdgInfo = pdg->GetParticle(particle.pdgCode()); + if (pdgInfo != nullptr) { + particleCharges->Fill(pdgInfo->Charge()); + } else { + LOGF(warn, "[%d] unknown particle with PDG code %d", particle.globalIndex(), particle.pdgCode()); + } + } + } +}; + +WorkflowSpec defineDataProcessing(ConfigContext const& cfgc) +{ + return WorkflowSpec{ + adaptAnalysisTask(cfgc)}; +} diff --git a/Framework/Core/include/Framework/AnalysisManagers.h b/Framework/Core/include/Framework/AnalysisManagers.h index 3792849121358..3859a5ab85095 100644 --- a/Framework/Core/include/Framework/AnalysisManagers.h +++ b/Framework/Core/include/Framework/AnalysisManagers.h @@ -24,6 +24,7 @@ #include "Framework/ConfigContext.h" #include "Framework/RootConfigParamHelpers.h" #include "Framework/ExpressionHelpers.h" +#include "Framework/CommonServices.h" namespace o2::framework { @@ -344,6 +345,12 @@ class has_instance template struct ServiceManager { + template + static bool add(std::vector&, ANY&) + { + return false; + } + template static bool prepare(InitContext&, ANY&) { @@ -353,13 +360,19 @@ struct ServiceManager { template struct ServiceManager> { + static bool add(std::vector& specs, Service&) + { + CommonAnalysisServices::addAnalysisService(specs); + return true; + } + static bool prepare(InitContext& context, Service& service) { if constexpr (has_instance::value) { service.service = &(T::instance()); // Sigh... return true; } else { - service.service = context.services().get(); + service.service = &(context.services().get()); return true; } return false; diff --git a/Framework/Core/include/Framework/AnalysisTask.h b/Framework/Core/include/Framework/AnalysisTask.h index 29c16c15b0b36..98db621c20601 100644 --- a/Framework/Core/include/Framework/AnalysisTask.h +++ b/Framework/Core/include/Framework/AnalysisTask.h @@ -779,6 +779,9 @@ DataProcessorSpec adaptAnalysisTask(ConfigContext const& ctx, Args&&... args) homogeneous_apply_refs([&outputs, &hash](auto& x) { return OutputManager>::appendOutput(outputs, x, hash); }, *task.get()); + std::vector requiredServices = CommonServices::defaultServices(); + homogeneous_apply_refs([&requiredServices](auto& x) { return ServiceManager>::add(requiredServices, x); }, *task.get()); + auto algo = AlgorithmSpec::InitCallback{[task = task, expressionInfos](InitContext& ic) mutable { homogeneous_apply_refs([&ic](auto&& x) { return OptionManager>::prepare(ic, x); }, *task.get()); homogeneous_apply_refs([&ic](auto&& x) { return ServiceManager>::prepare(ic, x); }, *task.get()); @@ -840,7 +843,8 @@ DataProcessorSpec adaptAnalysisTask(ConfigContext const& ctx, Args&&... args) inputs, outputs, algo, - options}; + options, + requiredServices}; return spec; } diff --git a/Framework/Core/include/Framework/CommonServices.h b/Framework/Core/include/Framework/CommonServices.h index 69767a8e5128c..a25485ad8d1ca 100644 --- a/Framework/Core/include/Framework/CommonServices.h +++ b/Framework/Core/include/Framework/CommonServices.h @@ -14,6 +14,8 @@ #include "Framework/ServiceSpec.h" #include "Framework/TypeIdHelpers.h" +class TDatabasePDG; + namespace o2::framework { @@ -69,6 +71,18 @@ struct CommonServices { static std::vector requiredServices(); }; +struct CommonAnalysisServices { + static ServiceSpec databasePDGSpec(); + + template + static void addAnalysisService(std::vector& specs) + { + if constexpr (std::is_same_v) { + specs.push_back(databasePDGSpec()); + } + } +}; + } // namespace o2::framework #endif // O2_FRAMEWORK_COMMONSERVICES_H_ diff --git a/Framework/Core/include/Framework/runDataProcessing.h b/Framework/Core/include/Framework/runDataProcessing.h index 957a543826291..d9c82af43ad4d 100644 --- a/Framework/Core/include/Framework/runDataProcessing.h +++ b/Framework/Core/include/Framework/runDataProcessing.h @@ -90,7 +90,9 @@ void defaultConfiguration(std::vector& dispatchPo void defaultConfiguration(std::vector& resourcePolicies) {} void defaultConfiguration(std::vector& services) { - services = o2::framework::CommonServices::defaultServices(); + if (services.empty()) { + services = o2::framework::CommonServices::defaultServices(); + } } /// Workflow options which are required by DPL in order to work. diff --git a/Framework/Core/src/CommonServices.cxx b/Framework/Core/src/CommonServices.cxx index 2811770a1e6cc..fa9c0d31d55e3 100644 --- a/Framework/Core/src/CommonServices.cxx +++ b/Framework/Core/src/CommonServices.cxx @@ -33,6 +33,7 @@ #include "../src/DataProcessingStatus.h" #include "ArrowSupport.h" #include "DPLMonitoringBackend.h" +#include "TDatabasePDG.h" #include #include @@ -528,5 +529,18 @@ std::vector CommonServices::defaultServices(int numThreads) return specs; } +o2::framework::ServiceSpec CommonAnalysisServices::databasePDGSpec() +{ + return ServiceSpec{ + .name = "database-pdg", + .init = [](ServiceRegistry&, DeviceState&, fair::mq::ProgOptions&) -> ServiceHandle { + auto* ptr = new TDatabasePDG(); + ptr->ReadPDGTable(); + return ServiceHandle{TypeIdHelpers::uniqueId(), ptr, ServiceKind::Serial, "database-pdg"}; + }, + .configure = CommonServices::noConfiguration(), + .exit = [](ServiceRegistry&, void* service) { reinterpret_cast(service)->Delete(); }, + .kind = ServiceKind::Serial}; +} } // namespace o2::framework #pragma GCC diagnostic pop diff --git a/Framework/Core/src/DeviceSpecHelpers.cxx b/Framework/Core/src/DeviceSpecHelpers.cxx index f502028ef1198..269a9afe0654c 100644 --- a/Framework/Core/src/DeviceSpecHelpers.cxx +++ b/Framework/Core/src/DeviceSpecHelpers.cxx @@ -764,7 +764,6 @@ void DeviceSpecHelpers::dataProcessorSpecs2DeviceSpecs(const WorkflowSpec& workf unsigned short resourcesMonitoringInterval, std::string const& channelPrefix) { - std::vector availableForwardsInfo; std::vector logicalEdges; std::vector connections;