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 EDM4hep to LCIO conversion tests from MarlinWrapper #29

Merged
merged 8 commits into from
Oct 5, 2023
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
11 changes: 11 additions & 0 deletions k4EDM4hep2LcioConv/include/k4EDM4hep2LcioConv/k4EDM4hep2LcioConv.h
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,8 @@ namespace edm4hep {
#include <edm4hep/TrackerHitPlaneCollection.h>
#include <edm4hep/VertexCollection.h>

#include "podio/Frame.h"

// LCIO
#include <IMPL/CalorimeterHitImpl.h>
#include <IMPL/ClusterImpl.h>
Expand All @@ -57,6 +59,8 @@ namespace edm4hep {
#include <UTIL/CellIDEncoder.h>
#include <lcio.h>

#include <memory>

// Preprocessor symbol that can be used in downstream code to switch on the
// namespace for the conversion
#define EDM4HEP2LCIOCONV_NAMESPACE 1
Expand Down Expand Up @@ -142,6 +146,13 @@ namespace EDM4hep2LCIOConv {

bool collectionExist(const std::string& collection_name, const lcio::LCEventImpl* lcio_event);

/**
* Convert an edm4hep event to an LCEvent
*/
std::unique_ptr<lcio::LCEventImpl> convEvent(
const podio::Frame& edmEvent,
const podio::Frame& metadata = podio::Frame {});

} // namespace EDM4hep2LCIOConv

#endif
87 changes: 86 additions & 1 deletion k4EDM4hep2LcioConv/src/k4EDM4hep2LcioConv.cpp
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
#include "k4EDM4hep2LcioConv/k4EDM4hep2LcioConv.h"

#include "IMPL/LCEventImpl.h"

#if __has_include("edm4hep/EDM4hepVersion.h")
#include "edm4hep/EDM4hepVersion.h"
#else
Expand Down Expand Up @@ -871,7 +873,11 @@ namespace EDM4hep2LCIOConv {
// << std::endl;
}
} // all emd4hep contributions
} // SimCaloHit

// We need to reset the energy to the original one, because adding
// contributions alters the energy in LCIO
lcio_sch->setEnergy(edm_sch.getEnergy());
} // SimCaloHit

// Fill missing SimTrackerHit collections
for (auto& [lcio_strh, edm_strh] : collection_pairs.simtrackerhits) {
Expand Down Expand Up @@ -901,4 +907,83 @@ namespace EDM4hep2LCIOConv {
return false;
}

std::unique_ptr<lcio::LCEventImpl> convEvent(const podio::Frame& edmEvent, const podio::Frame& metadata)
{
auto lcioEvent = std::make_unique<lcio::LCEventImpl>();
auto objectMappings = CollectionsPairVectors {};

const auto& collections = edmEvent.getAvailableCollections();
for (const auto& name : collections) {
const auto edmCollection = edmEvent.get(name);

const auto& cellIDStr = metadata.getParameter<std::string>(podio::collMetadataParamName(name, "CellIDEncoding"));

if (auto coll = dynamic_cast<const edm4hep::TrackCollection*>(edmCollection)) {
auto lcColl = convTracks(coll, objectMappings.tracks, objectMappings.trackerhits);
lcioEvent->addCollection(lcColl, name);
}
else if (auto coll = dynamic_cast<const edm4hep::TrackerHitCollection*>(edmCollection)) {
auto lcColl = convTrackerHits(coll, cellIDStr, objectMappings.trackerhits);
lcioEvent->addCollection(lcColl, name);
}
else if (auto coll = dynamic_cast<const edm4hep::SimTrackerHitCollection*>(edmCollection)) {
auto lcColl = convSimTrackerHits(coll, cellIDStr, objectMappings.simtrackerhits, objectMappings.mcparticles);
lcioEvent->addCollection(lcColl, name);
}
else if (auto coll = dynamic_cast<const edm4hep::CalorimeterHitCollection*>(edmCollection)) {
auto lcColl = convCalorimeterHits(coll, cellIDStr, objectMappings.calohits);
lcioEvent->addCollection(lcColl, name);
}
else if (auto coll = dynamic_cast<const edm4hep::RawCalorimeterHitCollection*>(edmCollection)) {
auto lcColl = convRawCalorimeterHits(coll, objectMappings.rawcalohits);
lcioEvent->addCollection(lcColl, name);
}
else if (auto coll = dynamic_cast<const edm4hep::SimCalorimeterHitCollection*>(edmCollection)) {
auto lcColl = convSimCalorimeterHits(coll, cellIDStr, objectMappings.simcalohits, objectMappings.mcparticles);
lcioEvent->addCollection(lcColl, name);
}
else if (auto coll = dynamic_cast<const edm4hep::RawTimeSeriesCollection*>(edmCollection)) {
auto lcColl = convTPCHits(coll, objectMappings.tpchits);
lcioEvent->addCollection(lcColl, name);
}
else if (auto coll = dynamic_cast<const edm4hep::ClusterCollection*>(edmCollection)) {
auto lcColl = convClusters(coll, objectMappings.clusters, objectMappings.calohits);
lcioEvent->addCollection(lcColl, name);
}
else if (auto coll = dynamic_cast<const edm4hep::VertexCollection*>(edmCollection)) {
auto lcColl = convVertices(coll, objectMappings.vertices, objectMappings.recoparticles);
lcioEvent->addCollection(lcColl, name);
}
else if (auto coll = dynamic_cast<const edm4hep::MCParticleCollection*>(edmCollection)) {
auto lcColl = convMCParticles(coll, objectMappings.mcparticles);
lcioEvent->addCollection(lcColl, name);
}
else if (auto coll = dynamic_cast<const edm4hep::ReconstructedParticleCollection*>(edmCollection)) {
auto lcColl = convReconstructedParticles(
coll, objectMappings.recoparticles, objectMappings.tracks, objectMappings.vertices, objectMappings.clusters);
lcioEvent->addCollection(lcColl, name);
}
else if (auto coll = dynamic_cast<const edm4hep::EventHeaderCollection*>(edmCollection)) {
convEventHeader(coll, lcioEvent.get());
}
else if (auto coll = dynamic_cast<const edm4hep::CaloHitContributionCollection*>(edmCollection)) {
// "converted" as part of FillMissingCollectoins at the end
continue;
}
else {
std::cerr << "Error trying to convert requested " << edmCollection->getValueTypeName() << " with name " << name
<< "\n"
<< "List of supported types: "
<< "Track, TrackerHit, SimTrackerHit, "
<< "Cluster, CalorimeterHit, RawCalorimeterHit, "
<< "SimCalorimeterHit, Vertex, ReconstructedParticle, "
<< "MCParticle." << std::endl;
}
}

FillMissingCollections(objectMappings);

return lcioEvent;
}

} // namespace EDM4hep2LCIOConv
20 changes: 19 additions & 1 deletion tests/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -1,12 +1,30 @@
add_library(edmCompare SHARED src/CompareEDM4hepLCIO.cc src/ObjectMapping.cc)
add_library(edmCompare SHARED src/CompareEDM4hepLCIO.cc src/ObjectMapping.cc src/CompareEDM4hepEDM4hep.cc)
target_link_libraries(edmCompare PUBLIC EDM4HEP::edm4hep ${LCIO_LIBRARIES})
target_include_directories(edmCompare PUBLIC ${LCIO_INCLUDE_DIRS})

add_library(TestUtils SHARED src/EDM4hep2LCIOUtilities.cc)
target_link_libraries(TestUtils PUBLIC EDM4HEP::edm4hep ${LCIO_LIBRARIES})
target_include_directories(TestUtils PUBLIC ${LCIO_INCLUDE_DIRS})

add_executable(compare-contents compare_contents.cpp)
target_link_libraries(compare-contents PRIVATE edmCompare podio::podioRootIO)
target_include_directories(compare-contents PRIVATE
$<BUILD_INTERFACE:${CMAKE_CURRENT_LIST_DIR}/src>)

add_executable(edm4hep_to_lcio edm4hep_to_lcio.cpp)
target_link_libraries(edm4hep_to_lcio PRIVATE edmCompare TestUtils k4EDM4hep2LcioConv)
target_include_directories(edm4hep_to_lcio PRIVATE
$<BUILD_INTERFACE:${CMAKE_CURRENT_LIST_DIR}/src>)

add_test(NAME edm4hep_to_lcio COMMAND edm4hep_to_lcio)

add_executable(edm4hep_roundtrip edm4hep_roundtrip.cpp)
target_link_libraries(edm4hep_roundtrip PRIVATE k4EDM4hep2LcioConv TestUtils edmCompare)
target_include_directories(edm4hep_roundtrip PRIVATE
$<BUILD_INTERFACE:${CMAKE_CURRENT_LIST_DIR}/src>)

add_test(NAME edm4hep_roundtrip COMMAND edm4hep_roundtrip)

find_program(BASH_PROGRAM bash)

add_test(fetch_test_inputs ${BASH_PROGRAM} ${CMAKE_CURRENT_SOURCE_DIR}/scripts/get_test_data.sh)
Expand Down
10 changes: 1 addition & 9 deletions tests/compare_contents.cpp
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
#include "CompareEDM4hepLCIO.h"
#include "ObjectMapping.h"
#include "ComparisonUtils.h"

#include "podio/ROOTFrameReader.h"
#include "podio/Frame.h"
Expand All @@ -9,15 +10,6 @@
#include <iostream>
#include <string_view>

#define ASSERT_COMPARE_OR_EXIT(collType) \
if (type == #collType) { \
auto& edmcoll = edmEvent.get<collType>(name); \
if (!compare(lcioColl, edmcoll, objectMapping)) { \
std::cerr << "in collection: " << name << std::endl; \
return 1; \
} \
}

constexpr auto usageMsg = R"(usage: compare-contents lciofile edm4hepfile)";

int main(int argc, char* argv[])
Expand Down
30 changes: 30 additions & 0 deletions tests/edm4hep_roundtrip.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
#include "CompareEDM4hepEDM4hep.h"
#include "EDM4hep2LCIOUtilities.h"

#include "k4EDM4hep2LcioConv/k4EDM4hep2LcioConv.h"
#include "k4EDM4hep2LcioConv/k4Lcio2EDM4hepConv.h"

#include "podio/Frame.h"

#include <iostream>

#define ASSERT_SAME_OR_ABORT(type, name) \
if (!compare(origEvent.get<type>(name), roundtripEvent.get<type>(name))) { \
std::cerr << "Comparison failure in " << name << std::endl; \
return 1; \
}

int main()
{
const auto origEvent = createExampleEvent();
const auto lcioEvent = EDM4hep2LCIOConv::convEvent(origEvent);
const auto roundtripEvent = LCIO2EDM4hepConv::convertEvent(lcioEvent.get());

ASSERT_SAME_OR_ABORT(edm4hep::CalorimeterHitCollection, "caloHits");
ASSERT_SAME_OR_ABORT(edm4hep::MCParticleCollection, "mcParticles");
ASSERT_SAME_OR_ABORT(edm4hep::SimCalorimeterHitCollection, "simCaloHits");
ASSERT_SAME_OR_ABORT(edm4hep::TrackCollection, "tracks");
ASSERT_SAME_OR_ABORT(edm4hep::TrackerHitCollection, "trackerHits");

return 0;
}
68 changes: 68 additions & 0 deletions tests/edm4hep_to_lcio.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
#include "EDM4hep2LCIOUtilities.h"
#include "CompareEDM4hepLCIO.h"
#include "ObjectMapping.h"
#include "ComparisonUtils.h"

#include "k4EDM4hep2LcioConv/k4EDM4hep2LcioConv.h"

#include "Exceptions.h"

#include "podio/Frame.h"

int main()
{
const auto edmEvent = createExampleEvent();
const auto lcioEvent = EDM4hep2LCIOConv::convEvent(edmEvent);

if (!compareEventHeader(lcioEvent.get(), &edmEvent)) {
return 1;
}

for (const auto& name : edmEvent.getAvailableCollections()) {
const auto edmColl = edmEvent.get(name);
const auto typeName = edmColl->getValueTypeName();
if (
typeName == "edm4hep::CaloHitContribution" || typeName == "edm4hep::ParticleID" ||
typeName == "edm4hep::EventHeader") {
continue;
}
try {
const auto* lcColl = lcioEvent->getCollection(name);
if (lcColl->getNumberOfElements() != edmColl->size()) {
std::cerr << "Collection " << name << " has different sizes. EDM4hep: " << edmColl->size()
<< ", LCIO: " << lcColl->getNumberOfElements() << std::endl;
return 1;
}
} catch (EVENT::DataNotAvailableException& ex) {
std::cerr << "Collection " << name << " is not available in LCEvent" << std::endl;
return 1;
}
}

const auto objectMapping = ObjectMappings::fromEvent(lcioEvent.get(), edmEvent);

for (const auto& name : edmEvent.getAvailableCollections()) {
const auto type = edmEvent.get(name)->getTypeName();
if (
type == "edm4hep::CaloHitContributionCollection" || type == "edm4hep::ParticleIDCollection" ||
type == "edm4hep::EventHeaderCollection") {
continue;
}
const auto* lcioColl = lcioEvent->getCollection(name);

ASSERT_COMPARE_OR_EXIT(edm4hep::MCParticleCollection)
ASSERT_COMPARE_OR_EXIT(edm4hep::ReconstructedParticleCollection)
ASSERT_COMPARE_OR_EXIT(edm4hep::TrackCollection)
ASSERT_COMPARE_OR_EXIT(edm4hep::TrackerHitCollection)
ASSERT_COMPARE_OR_EXIT(edm4hep::TrackerHitPlaneCollection)
ASSERT_COMPARE_OR_EXIT(edm4hep::SimTrackerHitCollection)
ASSERT_COMPARE_OR_EXIT(edm4hep::CalorimeterHitCollection)
ASSERT_COMPARE_OR_EXIT(edm4hep::RawCalorimeterHitCollection)
ASSERT_COMPARE_OR_EXIT(edm4hep::SimCalorimeterHitCollection)
ASSERT_COMPARE_OR_EXIT(edm4hep::RawTimeSeriesCollection)
ASSERT_COMPARE_OR_EXIT(edm4hep::ClusterCollection)
ASSERT_COMPARE_OR_EXIT(edm4hep::VertexCollection)
}

return 0;
}
Loading
Loading