Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add the possibility to set edm4hep::utils::ParticleIDMeta via the IMetadataSvc #273

Merged
merged 15 commits into from
Jan 29, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@ find_package(ROOT COMPONENTS RIO Tree REQUIRED)
find_package(Gaudi REQUIRED)
find_package(podio 1.0.1 REQUIRED)
find_package(EDM4HEP 0.99 REQUIRED)
find_package(fmt REQUIRED)
tmadlener marked this conversation as resolved.
Show resolved Hide resolved

include(cmake/Key4hepConfig.cmake)

Expand Down
2 changes: 2 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -74,6 +74,8 @@ print(my_opts[0].foo)

* EDM4HEP

* fmt

## Installation and downstream usage.

k4FWCore is a CMake project. After setting up the dependencies (use for example `source /cvmfs/sw.hsf.org/key4hep/setup.sh`)
Expand Down
1 change: 1 addition & 0 deletions cmake/k4FWCoreConfig.cmake.in
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ find_dependency(podio @podio_VERSION@)
find_dependency(Gaudi @Gaudi_VERSION@)
find_dependency(EDM4HEP @EDM4HEP_VERSION@)
find_dependency(ROOT @ROOT_VERSION@ COMPONENTS RIO Tree)
find_dependency(fmt @fmt_VERSION@)

if(NOT TARGET k4FWCore::k4FWCore)
include("${CMAKE_CURRENT_LIST_DIR}/k4FWCoreTargets.cmake")
Expand Down
2 changes: 1 addition & 1 deletion k4FWCore/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ gaudi_install(PYTHON)
gaudi_add_library(k4FWCore
SOURCES src/PodioDataSvc.cpp
src/KeepDropSwitch.cpp
LINK Gaudi::GaudiKernel podio::podioIO ROOT::Core ROOT::RIO ROOT::Tree
LINK Gaudi::GaudiKernel podio::podioIO ROOT::Core ROOT::RIO ROOT::Tree EDM4HEP::utils
)
target_include_directories(k4FWCore PUBLIC
$<BUILD_INTERFACE:${CMAKE_CURRENT_LIST_DIR}/include>
Expand Down
34 changes: 28 additions & 6 deletions k4FWCore/include/k4FWCore/IMetadataSvc.h
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,8 @@

#include "GaudiKernel/IInterface.h"

#include "edm4hep/utils/ParticleIDUtils.h"

#include "podio/Frame.h"

class IMetadataSvc : virtual public IInterface {
Expand All @@ -31,12 +33,7 @@ class IMetadataSvc : virtual public IInterface {

virtual void setFrame(podio::Frame frame) = 0;

template <typename T> void put(const std::string& name, const T& obj) {
if (!getFrame()) {
setFrame(podio::Frame{});
}
getFrame()->putParameter(name, obj);
}
template <typename T> void put(const std::string& name, const T& obj) { getFrameForWrite()->putParameter(name, obj); }

template <typename T> std::optional<T> get(const std::string& name) const {
const auto* frame = getFrame();
Expand All @@ -49,6 +46,31 @@ class IMetadataSvc : virtual public IInterface {
protected:
virtual podio::Frame* getFrame() = 0;
virtual const podio::Frame* getFrame() const = 0;

private:
podio::Frame* getFrameForWrite() {
if (!getFrame()) {
setFrame(podio::Frame());
}
return getFrame();
}
};

template <>
inline void IMetadataSvc::put<edm4hep::utils::ParticleIDMeta>(const std::string& collName,
const edm4hep::utils::ParticleIDMeta& pidMetaInfo) {
edm4hep::utils::PIDHandler::setAlgoInfo(*getFrameForWrite(), collName, pidMetaInfo);
}

template <>
inline std::optional<edm4hep::utils::ParticleIDMeta> IMetadataSvc::get<edm4hep::utils::ParticleIDMeta>(
const std::string& collName) const {
const auto* frame = getFrame();
if (!frame) {
return std::nullopt;
}

return edm4hep::utils::PIDHandler::getAlgoInfo(*frame, collName);
}

#endif
9 changes: 9 additions & 0 deletions test/k4FWCoreTest/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -195,6 +195,8 @@ add_test_with_env(FunctionalProducerRNTuple options/ExampleFunctionalProducerRNT
add_test_with_env(FunctionalTTreeToRNTuple options/ExampleFunctionalTTreeToRNTuple.py PROPERTIES FIXTURES_REQUIRED ProducerFile ADD_TO_CHECK_FILES)
add_test_with_env(GaudiFunctional options/ExampleGaudiFunctional.py PROPERTIES FIXTURES_REQUIRED ProducerFile ADD_TO_CHECK_FILES)

add_test_with_env(ParticleIDMetadataFramework options/ExampleParticleIDMetadata.py)


# The following is done to make the tests work without installing the files in
# the installation directory. The k4FWCore in the build directory is populated by
Expand All @@ -204,3 +206,10 @@ add_test_with_env(GaudiFunctional options/ExampleGaudiFunctional.py PROPERTIES F
add_custom_command(TARGET k4FWCoreTestPlugins POST_BUILD
COMMAND ${CMAKE_COMMAND} -E copy_directory
${PROJECT_SOURCE_DIR}/python/k4FWCore/ ${PROJECT_BINARY_DIR}/k4FWCore/genConfDir/k4FWCore)


add_executable(check_ParticleIDOutputs src/check_ParticleIDOutputs.cpp)
target_link_libraries(check_ParticleIDOutputs PRIVATE podio::podioIO EDM4HEP::edm4hep EDM4HEP::utils fmt::fmt)
jmcarcell marked this conversation as resolved.
Show resolved Hide resolved
add_test(NAME check_ParticleIDOutputs COMMAND check_ParticleIDOutputs example_with_particleids.root)
set_test_env(check_ParticleIDOutputs)
set_tests_properties(check_ParticleIDOutputs PROPERTIES DEPENDS ParticleIDMetadataFramework)
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@
OutputCollectionSimTrackerHits=["SimTrackerHits0"],
OutputCollectionTrackerHits=["TrackerHits0"],
OutputCollectionTracks=["Tracks0"],
OutputCollectionRecoParticles=["Recos0"],
ExampleInt=5,
)
producer1 = ExampleFunctionalProducerMultiple(
Expand All @@ -47,6 +48,7 @@
OutputCollectionSimTrackerHits=["SimTrackerHits1"],
OutputCollectionTrackerHits=["TrackerHits1"],
OutputCollectionTracks=["Tracks1"],
OutputCollectionRecoParticles=["Recos1"],
ExampleInt=5,
)
producer2 = ExampleFunctionalProducerMultiple(
Expand All @@ -57,6 +59,7 @@
OutputCollectionSimTrackerHits=["SimTrackerHits2"],
OutputCollectionTrackerHits=["TrackerHits2"],
OutputCollectionTracks=["Tracks2"],
OutputCollectionRecoParticles=["Recos2"],
ExampleInt=5,
)

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@
OutputCollectionSimTrackerHits=["SimTrackerHits0"],
OutputCollectionTrackerHits=["TrackerHits0"],
OutputCollectionTracks=["Tracks0"],
OutputCollectionRecoParticles=["Recos0"],
ExampleInt=5,
)
producer1 = ExampleFunctionalProducerMultiple(
Expand All @@ -48,6 +49,7 @@
OutputCollectionSimTrackerHits=["SimTrackerHits1"],
OutputCollectionTrackerHits=["TrackerHits1"],
OutputCollectionTracks=["Tracks1"],
OutputCollectionRecoParticles=["Recos1"],
ExampleInt=5,
)
producer2 = ExampleFunctionalProducerMultiple(
Expand All @@ -58,6 +60,7 @@
OutputCollectionSimTrackerHits=["SimTrackerHits2"],
OutputCollectionTrackerHits=["TrackerHits2"],
OutputCollectionTracks=["Tracks2"],
OutputCollectionRecoParticles=["Recos2"],
ExampleInt=5,
)

Expand Down
80 changes: 80 additions & 0 deletions test/k4FWCoreTest/options/ExampleParticleIDMetadata.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,80 @@
#!/usr/bin/env python3
#
# Copyright (c) 2014-2024 Key4hep-Project.
#
# This file is part of Key4hep.
# See https://key4hep.github.io/key4hep-doc/ for further info.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
#

"""Example showcasing how to use ParticleID related metadata"""

from Gaudi.Configuration import INFO
from Configurables import (
ExampleParticleIDProducer,
ExampleParticleIDConsumer,
ExampleFunctionalProducerMultiple,
EventDataSvc,
)
from k4FWCore import ApplicationMgr, IOSvc

# NOTE: If you are not using the IOSvc (e.g. because you don't need I/O), make
# sure to add the MetadataSvc to the ExtSvc as that is necessary to store /
# retrieve the metadata for ParticleIDs
iosvc = IOSvc()
iosvc.Output = "example_with_particleids.root"
iosvc.outputCommands = ["drop *", "keep RecoParticles*"]

reco_producer = ExampleFunctionalProducerMultiple(
"RecoProducer", OutputCollectionRecoParticles=["RecoParticles"]
)

pid_producer1 = ExampleParticleIDProducer(
"PIDProducer1",
InputCollection=["RecoParticles"],
ParticleIDCollection=["RecoParticlesPIDs_1"],
PIDAlgoName="PIDAlgo1",
PIDParamNames=["single_param"],
)

pid_producer2 = ExampleParticleIDProducer(
"PIDProducer2",
InputCollection=["RecoParticles"],
ParticleIDCollection=["RecoParticlesPIDs_2"],
PIDAlgoName="PIDAlgo2",
PIDParamNames=["param_1", "param_2", "param_3"],
)

pid_consumer = ExampleParticleIDConsumer(
"PIDConsumer",
RecoParticleCollection=reco_producer.OutputCollectionRecoParticles,
# From first producer
ParticleIDCollection1=pid_producer1.ParticleIDCollection,
PIDAlgoName1=pid_producer1.PIDAlgoName,
PIDParamNames1=pid_producer1.PIDParamNames,
ParamName1="single_param",
# From second producer
ParticleIDCollection2=pid_producer2.ParticleIDCollection,
PIDAlgoName2=pid_producer2.PIDAlgoName,
PIDParamNames2=pid_producer2.PIDParamNames,
ParamName2="param_2",
)

ApplicationMgr(
TopAlg=[reco_producer, pid_producer1, pid_producer2, pid_consumer],
EvtSel="NONE",
EvtMax=10,
ExtSvc=[EventDataSvc("EventDataSvc")],
OutputLevel=INFO,
)
1 change: 1 addition & 0 deletions test/k4FWCoreTest/options/runFunctionalMix.py
Original file line number Diff line number Diff line change
Expand Up @@ -90,6 +90,7 @@
OutputCollectionSimTrackerHits=["FunctionalSimTrackerHits"],
OutputCollectionTrackerHits=["FunctionalTrackerHits"],
OutputCollectionTracks=["FunctionalTracks"],
OutputCollectionRecoParticles=["FunctionalRecos"],
ExampleInt=5,
)

Expand Down
13 changes: 12 additions & 1 deletion test/k4FWCoreTest/scripts/CheckOutputFiles.py
Original file line number Diff line number Diff line change
Expand Up @@ -83,11 +83,19 @@ def check_metadata(filename, expected_metadata):
"Tracks",
"Counter",
"NewMCParticles",
"RecoParticles",
],
)
check_collections(
"functional_transformer_multiple_output_commands.root",
["VectorFloat", "MCParticles1", "MCParticles2", "SimTrackerHits", "TrackerHits"],
[
"VectorFloat",
"MCParticles1",
"MCParticles2",
"SimTrackerHits",
"TrackerHits",
"RecoParticles",
],
)
check_collections("/tmp/a/b/c/functional_producer.root", ["MCParticles"])
check_collections(
Expand All @@ -104,6 +112,7 @@ def check_metadata(filename, expected_metadata):
"TrackerHits",
"Tracks",
"NewMCParticles",
"RecoParticles",
],
)

Expand All @@ -116,13 +125,15 @@ def check_metadata(filename, expected_metadata):
"SimTrackerHits",
"TrackerHits",
"Tracks",
"RecoParticles",
# Produced by functional
"FunctionalVectorFloat",
"FunctionalMCParticles",
"FunctionalMCParticles2",
"FunctionalSimTrackerHits",
"FunctionalTrackerHits",
"FunctionalTracks",
"FunctionalRecos",
# Produced by an old algorithm
"OldAlgorithmMCParticles",
"OldAlgorithmSimTrackerHits",
Expand Down
Loading
Loading