Skip to content

Commit

Permalink
Switch from association to link (#200)
Browse files Browse the repository at this point in the history
* Switch from assocation to link

Accomodate for the new naming

* Switch to non-deprecated function

* Add tests for converting links from EDM4hep to LCIO

* Remove leftover docstring

* Make comparisons a bit easier to read
  • Loading branch information
tmadlener authored Sep 9, 2024
1 parent 4bf4188 commit 8e0eb80
Show file tree
Hide file tree
Showing 6 changed files with 243 additions and 7 deletions.
10 changes: 5 additions & 5 deletions k4MarlinWrapper/src/components/EDM4hep2Lcio.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -381,13 +381,13 @@ StatusCode EDM4hep2LcioTool::convertCollections(lcio::LCEventImpl* lcio_event) {
std::vector<EDM4hep2LCIOConv::ParticleIDConvData> pidCollections{};
std::vector<EDM4hep2LCIOConv::TrackDqdxConvData> dQdxCollections{};

std::vector<std::tuple<std::string, const podio::CollectionBase*>> associations{};
std::vector<std::tuple<std::string, const podio::CollectionBase*>> linkCollections{};

for (const auto& [edm4hepName, lcioName] : collsToConvert) {
const auto coll = getEDM4hepCollection(edm4hepName);
if (coll->getTypeName().find("Association") != std::string_view::npos) {
debug() << edm4hepName << " is an association collection, converting it later" << endmsg;
associations.emplace_back(lcioName, coll);
if (coll->getTypeName().find("LinkCollection") != std::string_view::npos) {
debug() << edm4hepName << " is a link collection, converting it later" << endmsg;
linkCollections.emplace_back(lcioName, coll);
continue;
}
debug() << "Converting collection " << edm4hepName << " (storing it as " << lcioName << ")" << endmsg;
Expand Down Expand Up @@ -435,7 +435,7 @@ StatusCode EDM4hep2LcioTool::convertCollections(lcio::LCEventImpl* lcio_event) {
EDM4hep2LCIOConv::resolveRelations(collection_pairs, globalObjMap);

// Now we can convert the assocations and add them to the event
for (auto& [name, coll] : EDM4hep2LCIOConv::createLCRelationCollections(associations, globalObjMap)) {
for (auto& [name, coll] : EDM4hep2LCIOConv::createLCRelationCollections(linkCollections, globalObjMap)) {
lcio_event->addCollection(coll.release(), name);
}

Expand Down
2 changes: 1 addition & 1 deletion k4MarlinWrapper/src/components/Lcio2EDM4hep.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -238,7 +238,7 @@ StatusCode Lcio2EDM4hepTool::convertCollections(lcio::LCEventImpl* the_event) {
registerCollection(name, LCIO2EDM4hepConv::fillSubset(coll, globalObjMap, type), coll);
}

for (auto&& assocColl : LCIO2EDM4hepConv::createAssociations(globalObjMap, lcRelationColls)) {
for (auto&& assocColl : LCIO2EDM4hepConv::createLinks(globalObjMap, lcRelationColls)) {
registerCollection(std::move(assocColl)); // TODO: Potentially handle metadata here?
}

Expand Down
12 changes: 11 additions & 1 deletion test/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ gaudi_add_module(GaudiTestAlgorithms
SOURCES
src/MCRecoLinkChecker.cc
src/PseudoRecoAlgorithm.cc
src/TrivialMCRecoLinker.cc
LINK
Gaudi::GaudiKernel
k4FWCore::k4FWCore
Expand All @@ -37,7 +38,10 @@ set(ExternalData_URL_TEMPLATES
# Compile the Marlin test processors into a shared library
find_package(Marlin REQUIRED)

add_library(MarlinTestProcessors SHARED src/TrivialMCTruthLinkerProcessor.cc)
add_library(MarlinTestProcessors SHARED
src/TrivialMCTruthLinkerProcessor.cc
src/MarlinMCRecoLinkChecker.cc
)
target_link_libraries(MarlinTestProcessors PUBLIC ${Marlin_LIBRARIES})
target_include_directories(MarlinTestProcessors PUBLIC ${Marlin_INCLUDE_DIRS})

Expand Down Expand Up @@ -85,6 +89,11 @@ add_test( clic_geo_test ${K4RUN} ${CMAKE_CURRENT_SOURCE_DIR}/gaudi_opts/geoTest_
# multiple processors
ExternalData_Add_Test( marlinwrapper_tests NAME global_converter_maps COMMAND ${K4RUN} ${CMAKE_CURRENT_SOURCE_DIR}/gaudi_opts/test_global_converter_maps.py --EventDataSvc.input DATA{${PROJECT_SOURCE_DIR}/test/input_files/ttbar_20240223_edm4hep.root})

ExternalData_Add_Test( marlinwrapper_tests
NAME link_conversion_edm4hep_to_lcio
COMMAND ${K4RUN} ${CMAKE_CURRENT_SOURCE_DIR}/gaudi_opts/test_link_conversion_edm4hep.py --inputfile DATA{${PROJECT_SOURCE_DIR}/test/input_files/ttbar_20240223_edm4hep.root}
)

add_test( event_header_conversion bash -c "k4run ${CMAKE_CURRENT_SOURCE_DIR}/gaudi_opts/createEventHeader.py && anajob test.slcio | grep 'EVENT: 42'" )

ExternalData_Add_Target(marlinwrapper_tests)
Expand All @@ -102,6 +111,7 @@ set_tests_properties (
clic_geo_test
global_converter_maps
event_header_conversion
link_conversion_edm4hep_to_lcio
PROPERTIES
ENVIRONMENT "TEST_DIR=${CMAKE_CURRENT_SOURCE_DIR};LD_LIBRARY_PATH=${CMAKE_INSTALL_PREFIX}/lib:${CMAKE_INSTALL_PREFIX}/lib64:$ENV{LD_LIBRARY_PATH};PYTHONPATH=${CMAKE_INSTALL_PREFIX}/python:$ENV{PYTHONPATH};EXAMPLE_DIR=${PROJECT_SOURCE_DIR}/k4MarlinWrapper/examples;MARLIN_DLL=$ENV{MARLIN_DLL}:${CMAKE_CURRENT_BINARY_DIR}/libMarlinTestProcessors.so"
)
Expand Down
84 changes: 84 additions & 0 deletions test/gaudi_opts/test_link_conversion_edm4hep.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,84 @@
#!/usr/bin/env python3
#
# Copyright (c) 2019-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.
#

from Gaudi.Configuration import INFO, DEBUG

from Configurables import (
PodioInput,
k4DataSvc,
ApplicationMgr,
PseudoRecoAlgorithm,
TrivialMCRecoLinker,
MarlinProcessorWrapper,
EDM4hep2LcioTool,
)

from k4FWCore.parseArgs import parser

parser.add_argument("--inputfile", help="Input file")
my_args = parser.parse_known_args()[0]

evtsvc = k4DataSvc("EventDataSvc")
evtsvc.input = my_args.inputfile

podioInput = PodioInput("InputReader")
podioInput.collections = ["MCParticles"]
podioInput.OutputLevel = INFO


PseudoRecoAlg = PseudoRecoAlgorithm(
"PseudoRecoAlgorithm", InputMCs=["MCParticles"], OutputRecos=["PseudoRecoParticles"]
)

MCRecoLinker = TrivialMCRecoLinker(
InputMCs=["MCParticles"],
InputRecos=["PseudoRecoParticles"],
OutputLinks=["TrivialMCRecoLinks"],
)


MarlinMCLinkChecker = MarlinProcessorWrapper(
"MarlinMCRecoLinkChecker",
ProcessorType="MarlinMCRecoLinkChecker",
Parameters={
"MCRecoLinks": ["TrivialMCRecoLinks"],
"InputMCs": ["MCParticles"],
"InputRecos": ["PseudoRecoParticles"],
},
)

mcLinkConverter = EDM4hep2LcioTool("MCLinkConverterToEDM4hep")
mcLinkConverter.convertAll = False
mcLinkConverter.collNameMapping = {
"TrivialMCRecoLinks": "TrivialMCRecoLinks",
"MCParticles": "MCParticles",
"PseudoRecoParticles": "PseudoRecoParticles",
}
mcLinkConverter.OutputLevel = DEBUG
MarlinMCLinkChecker.EDM4hep2LcioTool = mcLinkConverter


ApplicationMgr(
TopAlg=[podioInput, PseudoRecoAlg, MCRecoLinker, MarlinMCLinkChecker],
ExtSvc=[evtsvc],
EvtMax=-1,
EvtSel="NONE",
OutputLevel=INFO,
)
86 changes: 86 additions & 0 deletions test/src/MarlinMCRecoLinkChecker.cc
Original file line number Diff line number Diff line change
@@ -0,0 +1,86 @@
/*
* Copyright (c) 2019-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.
*/
#include "marlin/Processor.h"

#include <EVENT/LCCollection.h>
#include <EVENT/LCEvent.h>
#include <EVENT/LCRelation.h>
#include <EVENT/MCParticle.h>
#include <EVENT/ReconstructedParticle.h>

#include <stdexcept>
#include <string>

class MarlinMCRecoLinkChecker : public marlin::Processor {
public:
MarlinMCRecoLinkChecker();

marlin::Processor* newProcessor() override { return new MarlinMCRecoLinkChecker; }

void processEvent(LCEvent* evt) override;

private:
std::string m_mcCollName{};
std::string m_recoCollName{};
std::string m_relCollName{};
};

MarlinMCRecoLinkChecker::MarlinMCRecoLinkChecker() : marlin::Processor("MarlinMCRecoLinkChecker") {
registerInputCollection(LCIO::MCPARTICLE, "InputMCs", "Name of the input MCParticle collection", m_mcCollName,
std::string("MCParticles"));

registerInputCollection(LCIO::RECONSTRUCTEDPARTICLE, "InputRecos",
"Name of the input ReconstructedParticle collection", m_recoCollName,
std::string("PseudoRecoParticles"));
registerInputCollection(LCIO::LCRELATION, "MCRecoLinks", "Name of the input Reco - MC Truth link collection",
m_relCollName, std::string("TrivialMCRecoLinks"));
}

void MarlinMCRecoLinkChecker::processEvent(LCEvent* evt) {
const auto mcColl = evt->getCollection(m_mcCollName);
const auto recoColl = evt->getCollection(m_recoCollName);
const auto relColl = evt->getCollection(m_relCollName);

if (relColl->getNumberOfElements() != mcColl->getNumberOfElements()) {
throw std::runtime_error("The LCRelation collection does not have the expected number of elements: (expected " +
std::to_string(mcColl->getNumberOfElements()) + ", actual " +
std::to_string(relColl->getNumberOfElements()) + ")");
}

for (size_t i = 0; i < mcColl->getNumberOfElements(); ++i) {
const auto mc = static_cast<EVENT::MCParticle*>(mcColl->getElementAt(i));
const auto reco = static_cast<EVENT::ReconstructedParticle*>(recoColl->getElementAt(i));
const auto rel = static_cast<EVENT::LCRelation*>(relColl->getElementAt(i));

if (rel->getWeight() != i) {
throw std::runtime_error("Relation " + std::to_string(i) + " does not have the correct weight (expected: " +
std::to_string(i) + ", actual: " + std::to_string(rel->getWeight()) + ")");
}

if (rel->getTo() != mc) {
throw std::runtime_error("Relation " + std::to_string(i) + " does not point to the correct MCParticle");
}

if (rel->getFrom() != reco) {
throw std::runtime_error("Relation " + std::to_string(i) + " does not point to the correct MCParticle");
}
}
}

MarlinMCRecoLinkChecker aMarlinMCRecoLinkChecker{};
56 changes: 56 additions & 0 deletions test/src/TrivialMCRecoLinker.cc
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
/*
* Copyright (c) 2019-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.
*/

#include <GaudiKernel/ISvcLocator.h>
#include "edm4hep/MCParticleCollection.h"
#include "edm4hep/RecoMCParticleLinkCollection.h"
#include "edm4hep/ReconstructedParticleCollection.h"

#include "k4FWCore/Transformer.h"

#include <string>

struct TrivialMCRecoLinker final
: k4FWCore::Transformer<edm4hep::RecoMCParticleLinkCollection(const edm4hep::MCParticleCollection&,
const edm4hep::ReconstructedParticleCollection&)> {
TrivialMCRecoLinker(const std::string& name, ISvcLocator* svcLoc)
: Transformer(name, svcLoc,
{KeyValues("InputMCs", {"MCParticles"}), KeyValues("InputRecos", {"PseudoRecoParticles"})},
KeyValues("OutputLinks", {"TrivialMCRecoLinks"})) {}

edm4hep::RecoMCParticleLinkCollection operator()(
const edm4hep::MCParticleCollection& mcParticles,
const edm4hep::ReconstructedParticleCollection& recoParticles) const override {
auto links = edm4hep::RecoMCParticleLinkCollection{};

for (size_t i = 0; i < mcParticles.size(); ++i) {
const auto mc = mcParticles[i];
const auto reco = recoParticles[i];

auto link = links.create();
link.setFrom(reco);
link.setTo(mc);
link.setWeight(i);
}

return links;
}
};

DECLARE_COMPONENT(TrivialMCRecoLinker)

0 comments on commit 8e0eb80

Please sign in to comment.