Skip to content

Commit

Permalink
Fix accessing input file metadata in MetadataSvc (#223)
Browse files Browse the repository at this point in the history
  • Loading branch information
m-fila authored Sep 17, 2024
1 parent 6a1b3b1 commit 9b69494
Show file tree
Hide file tree
Showing 8 changed files with 156 additions and 42 deletions.
7 changes: 3 additions & 4 deletions k4FWCore/components/MetadataSvc.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -38,14 +38,13 @@ StatusCode MetadataSvc::initialize() {
error() << "Unable to locate the EventDataSvc" << endmsg;
return StatusCode::FAILURE;
}

m_frame = std::make_unique<podio::Frame>();

return StatusCode::SUCCESS;
}

StatusCode MetadataSvc::finalize() { return Service::finalize(); }

void MetadataSvc::setFrame(podio::Frame&& fr) { m_frame = std::make_unique<podio::Frame>(std::move(fr)); }
const podio::Frame* MetadataSvc::getFrame() const { return m_frame.get(); }
podio::Frame* MetadataSvc::getFrame() { return m_frame.get(); }
void MetadataSvc::setFrame(podio::Frame&& frame) { m_frame = std::make_unique<podio::Frame>(std::move(frame)); }

DECLARE_COMPONENT(MetadataSvc)
6 changes: 5 additions & 1 deletion k4FWCore/components/MetadataSvc.h
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,8 @@

#include "k4FWCore/IMetadataSvc.h"

#include <memory>

class MetadataSvc : public extends<Service, IMetadataSvc> {
using extends::extends;

Expand All @@ -38,7 +40,9 @@ class MetadataSvc : public extends<Service, IMetadataSvc> {

std::unique_ptr<podio::Frame> m_frame;

void setFrame(podio::Frame&& frame) override;
const podio::Frame* getFrame() const override;
podio::Frame* getFrame() override;
void setFrame(podio::Frame&& frame) override;
};

#endif
5 changes: 3 additions & 2 deletions k4FWCore/components/Writer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@

#include <GaudiKernel/IHiveWhiteBoard.h>
#include <memory>
#include <utility>

class Writer final : public Gaudi::Functional::Consumer<void(const EventContext&)> {
public:
Expand Down Expand Up @@ -121,8 +122,8 @@ class Writer final : public Gaudi::Functional::Consumer<void(const EventContext&
}
iosvc->getWriter()->writeFrame(config_metadata_frame, "configuration_metadata");

if (m_metadataSvc->m_frame) {
iosvc->getWriter()->writeFrame(*std::move(m_metadataSvc->m_frame), podio::Category::Metadata);
if (const auto* metadata_frame = m_metadataSvc->getFrame(); metadata_frame) {
iosvc->getWriter()->writeFrame(*metadata_frame, podio::Category::Metadata);
}

iosvc->deleteWriter();
Expand Down
26 changes: 18 additions & 8 deletions k4FWCore/include/k4FWCore/IMetadataSvc.h
Original file line number Diff line number Diff line change
Expand Up @@ -19,26 +19,36 @@
#ifndef FWCORE_IMETADATASERVICE_H
#define FWCORE_IMETADATASERVICE_H

#include <memory>

#include "GaudiKernel/IInterface.h"

#include "podio/Frame.h"

class IMetadataSvc : virtual public IInterface {
friend class Writer;

public:
DeclareInterfaceID(IMetadataSvc, 1, 0);

std::unique_ptr<podio::Frame> m_frame;
virtual void setFrame(podio::Frame&& frame) = 0;

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

template <typename T> std::optional<T> get(const std::string& name) const {
const auto* frame = getFrame();
if (!frame) {
return std::nullopt;
}
m_frame->putParameter(name, obj);
return frame->getParameter<T>(name);
}
template <typename T> std::optional<T> get(const std::string& name) { return m_frame->getParameter<T>(name); }

protected:
virtual podio::Frame* getFrame() = 0;
virtual const podio::Frame* getFrame() const = 0;
};

#endif
5 changes: 4 additions & 1 deletion test/k4FWCoreTest/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -136,15 +136,18 @@ add_test_with_env(FunctionalTransformerHist options/ExampleFunctionalTransformer
add_test_with_env(FunctionalCollectionMerger options/ExampleFunctionalCollectionMerger.py)
add_test_with_env(FunctionalFilterFile options/ExampleFunctionalFilterFile.py)
add_test_with_env(FunctionalMetadata options/ExampleFunctionalMetadata.py)
add_test_with_env(FunctionalMetadataRead options/ExampleFunctionalMetadataRead.py PROPERTIES DEPENDS FunctionalMetadata)
add_test_with_env(FunctionalMetadataOldAlgorithm options/ExampleFunctionalMetadataOldAlgorithm.py)
add_test_with_env(createEventHeaderConcurrent options/createEventHeaderConcurrent.py)
add_test_with_env(FunctionalMetadataReadOldAlgorithm options/ExampleFunctionalMetadataReadOldAlgorithm.py PROPERTIES DEPENDS ExampleFunctionalMetadataOldAlgorithm)

add_test_with_env(FunctionalWrongImport options/ExampleFunctionalWrongImport.py)
set_tests_properties(FunctionalWrongImport PROPERTIES PASS_REGULAR_EXPRESSION "ImportError: Importing ApplicationMgr or IOSvc from Configurables is not allowed.")
add_test_with_env(FunctionalReadNthEvent options/ExampleFunctionalReadNthEvent.py)

add_test(NAME FunctionalCheckFiles COMMAND python3 ${CMAKE_CURRENT_LIST_DIR}/options/CheckOutputFiles.py)
set_tests_properties(FunctionalCheckFiles PROPERTIES DEPENDS "FunctionalFile;FunctionalMTFile;FunctionalMultipleFile;FunctionalOutputCommands;FunctionalProducerAbsolutePath;FunctionalTransformerRuntimeEmpty;FunctionalMix;FunctionalMixIOSvc;FunctionalTransformerHist;FunctionalCollectionMerger;FunctionalFilterFile;FunctionalMetadata;FunctionalMetadataOldAlgorithm;createEventHeaderConcurrent;FunctionalReadNthEvent")

set_tests_properties(FunctionalCheckFiles PROPERTIES DEPENDS "FunctionalFile;FunctionalMTFile;FunctionalMultipleFile;FunctionalOutputCommands;FunctionalProducerAbsolutePath;FunctionalTransformerRuntimeEmpty;FunctionalMix;FunctionalMixIOSvc;FunctionalTransformerHist;FunctionalCollectionMerger;FunctionalFilterFile;FunctionalMetadata;FunctionalMetadataRead;FunctionalMetadataOldAlgorithm;FunctionalMetadataReadOldAlgorithm;createEventHeaderConcurrent;FunctionalReadNthEvent")

# Do this after checking the files not to overwrite them
add_test_with_env(FunctionalFile_toolong options/ExampleFunctionalFile.py -n 999 PROPERTIES DEPENDS FunctionalCheckFiles PASS_REGULAR_EXPRESSION
Expand Down
71 changes: 45 additions & 26 deletions test/k4FWCoreTest/options/CheckOutputFiles.py
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,17 @@ def check_events(filename, number):
raise RuntimeError("Number of events does not match expected number")


def check_metadata(filename, expected_metadata):
print(f'Checking file "{filename}" for metadata')
podio_reader = podio.root_io.Reader(filename)
metadata = podio_reader.get("metadata")[0]
for key, value in expected_metadata.items():
if (metaval := metadata.get_parameter(key)) != value:
raise RuntimeError(
f"Metadata parameter {key} does not match the expected value, got {metaval} but expected {value}"
)


check_collections("functional_transformer.root", ["MCParticles", "NewMCParticles"])
check_collections(
"functional_transformer_multiple.root",
Expand Down Expand Up @@ -161,33 +172,41 @@ def check_events(filename, number):

check_collections("functional_metadata.root", ["MCParticles"])

reader = podio.root_io.Reader("functional_metadata.root")
metadata = reader.get("metadata")[0]
for key, value in zip(
[
"NumberOfParticles",
"ParticleTime",
"PDGValues",
"MetadataString",
"FinalizeMetadataInt",
],
[3, 1.5, [1, 2, 3, 4], "hello", 10],
):
if metadata.get_parameter(key) != value:
raise RuntimeError(
f"Metadata parameter {key} does not match the expected value, got {metadata.get_parameter(key)} but expected {value}"
)
check_metadata(
"functional_metadata.root",
{
"NumberOfParticles": 3,
"ParticleTime": 1.5,
"PDGValues": [1, 2, 3, 4],
"MetadataString": "hello",
"FinalizeMetadataInt": 10,
},
)

reader = podio.root_io.Reader("functional_metadata_old_algorithm.root")
metadata = reader.get("metadata")[0]
for key, value in zip(
["SimTrackerHits__CellIDEncoding"],
["M:3,S-1:3,I:9,J:9,K-1:6"],
):
if metadata.get_parameter(key) != value:
raise RuntimeError(
f"Metadata parameter {key} does not match the expected value, got {metadata.get_parameter(key)} but expected {value}"
)
check_metadata(
"functional_metadata_propagate.root",
{
"NumberOfParticles": 3,
"ParticleTime": 1.5,
"PDGValues": [1, 2, 3, 4],
"MetadataString": "hello",
"FinalizeMetadataInt": 10,
},
)

check_metadata(
"functional_metadata_old_algorithm.root",
{
"SimTrackerHits__CellIDEncoding": "M:3,S-1:3,I:9,J:9,K-1:6",
},
)

check_metadata(
"functional_metadata_old_algorithm_propagate.root",
{
"SimTrackerHits__CellIDEncoding": "M:3,S-1:3,I:9,J:9,K-1:6",
},
)

reader = podio.root_io.Reader("eventHeaderConcurrent.root")
events = reader.get("events")
Expand Down
39 changes: 39 additions & 0 deletions test/k4FWCoreTest/options/ExampleFunctionalMetadataRead.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
#
# 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.
#

# This is an example accessing matadata read from input file using MetadataSvc

from Gaudi.Configuration import INFO
from Configurables import ExampleFunctionalMetadataConsumer
from k4FWCore import ApplicationMgr, IOSvc
from Configurables import EventDataSvc

iosvc = IOSvc()
iosvc.Input = "functional_metadata.root"
iosvc.Output = "functional_metadata_propagate.root"

consumer = ExampleFunctionalMetadataConsumer("Consumer", InputCollection=["MCParticles"])

ApplicationMgr(
TopAlg=[consumer],
EvtSel="NONE",
EvtMax=10,
ExtSvc=[EventDataSvc("EventDataSvc")],
OutputLevel=INFO,
)
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
#
# 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.
#

# This is an example accessing matadata read from input file using MetaDataHandle

from Gaudi.Configuration import INFO
from Configurables import k4FWCoreTest_cellID_reader
from k4FWCore import ApplicationMgr, IOSvc

iosvc = IOSvc()
iosvc.Input = "functional_metadata_old_algorithm.root"
iosvc.Output = "functional_metadata_old_algorithm_propagate.root"

consumer = k4FWCoreTest_cellID_reader()

ApplicationMgr(
TopAlg=[consumer],
EvtSel="NONE",
EvtMax=10,
ExtSvc=[],
OutputLevel=INFO,
StopOnSignal=True,
)

0 comments on commit 9b69494

Please sign in to comment.