Skip to content

Commit

Permalink
Add the roundtrip tests from k4MarlinWrapper
Browse files Browse the repository at this point in the history
  • Loading branch information
tmadlener committed Sep 27, 2023
1 parent 8a4068e commit bafa331
Show file tree
Hide file tree
Showing 4 changed files with 274 additions and 1 deletion.
9 changes: 8 additions & 1 deletion tests/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
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})

Expand All @@ -18,6 +18,13 @@ target_include_directories(edm4hep_to_lcio PRIVATE

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
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;
}
218 changes: 218 additions & 0 deletions tests/src/CompareEDM4hepEDM4hep.cc
Original file line number Diff line number Diff line change
@@ -0,0 +1,218 @@
#include "CompareEDM4hepEDM4hep.h"
#include "ComparisonUtils.h"

#include "edm4hep/CalorimeterHitCollection.h"
#include "edm4hep/MCParticleCollection.h"
#include "edm4hep/SimCalorimeterHitCollection.h"
#include "edm4hep/TrackCollection.h"
#include "edm4hep/TrackerHitCollection.h"

#include <edm4hep/TrackState.h>
#include <iostream>
#include <podio/RelationRange.h>

#define REQUIRE_SAME(expected, actual, msg) \
{ \
if (!((expected) == (actual))) { \
std::cerr << msg << " are not the same (expected: " << (expected) << ", actual: " << (actual) << ")" \
<< std::endl; \
return false; \
} \
}

bool compare(const edm4hep::CalorimeterHitCollection& origColl, const edm4hep::CalorimeterHitCollection& roundtripColl)
{
REQUIRE_SAME(origColl.size(), roundtripColl.size(), "collection sizes");
for (size_t i = 0; i < origColl.size(); ++i) {
const auto origHit = origColl[i];
const auto hit = roundtripColl[i];

REQUIRE_SAME(origHit.getCellID(), hit.getCellID(), "cellID in hit " << i);
REQUIRE_SAME(origHit.getEnergy(), hit.getEnergy(), "energy in hit " << i);
REQUIRE_SAME(origHit.getEnergyError(), hit.getEnergyError(), "energyError in hit " << i);
REQUIRE_SAME(origHit.getTime(), hit.getTime(), "time in hit " << i);
REQUIRE_SAME(origHit.getPosition(), hit.getPosition(), "position in hit " << i);
}

return true;
}

bool compare(const edm4hep::MCParticleCollection& origColl, const edm4hep::MCParticleCollection& roundtripColl)
{
REQUIRE_SAME(origColl.size(), roundtripColl.size(), "collection sizes");

for (size_t i = 0; i < origColl.size(); ++i) {
auto origPart = origColl[i];
auto part = roundtripColl[i];

REQUIRE_SAME(origPart.getPDG(), part.getPDG(), "pdg in particle " << i);
REQUIRE_SAME(origPart.getGeneratorStatus(), part.getGeneratorStatus(), "generatorStatus in particle " << i);
REQUIRE_SAME(origPart.getVertex(), part.getVertex(), "vertex in particle " << i);
REQUIRE_SAME(origPart.getTime(), part.getTime(), "time in particle " << i);
REQUIRE_SAME(origPart.getEndpoint(), part.getEndpoint(), "endpoint in particle " << i);
REQUIRE_SAME(origPart.getMomentum(), part.getMomentum(), "momentum in particle " << i);
REQUIRE_SAME(
origPart.getMomentumAtEndpoint(), part.getMomentumAtEndpoint(), "momentumAtEndpoint in particle " << i);
REQUIRE_SAME(origPart.getMass(), part.getMass(), "mass in particle " << i);
REQUIRE_SAME(origPart.getCharge(), part.getCharge(), "charge in particle " << i);
REQUIRE_SAME(origPart.getSpin(), part.getSpin(), "spin in particle " << i);
REQUIRE_SAME(origPart.getColorFlow(), part.getColorFlow(), "colorFlow in particle " << i);

REQUIRE_SAME(origPart.isCreatedInSimulation(), part.isCreatedInSimulation(), " in particle " << i);
REQUIRE_SAME(origPart.isBackscatter(), part.isBackscatter(), " in particle " << i);
REQUIRE_SAME(origPart.vertexIsNotEndpointOfParent(), part.vertexIsNotEndpointOfParent(), " in particle " << i);
REQUIRE_SAME(origPart.isDecayedInTracker(), part.isDecayedInTracker(), " in particle " << i);
REQUIRE_SAME(origPart.isDecayedInCalorimeter(), part.isDecayedInCalorimeter(), " in particle " << i);
REQUIRE_SAME(origPart.hasLeftDetector(), part.hasLeftDetector(), " in particle " << i);
REQUIRE_SAME(origPart.isStopped(), part.isStopped(), " in particle " << i);
REQUIRE_SAME(origPart.isOverlay(), part.isOverlay(), " in particle " << i);

// Check the mother / daughter relations. We use the ObjectIDs here
// (assuming that the collection names are the same!)
REQUIRE_SAME(origPart.getParents().size(), part.getParents().size(), "size of parents in particle " << i);
for (size_t iP = 0; iP < origPart.getParents().size(); ++iP) {
REQUIRE_SAME(
origPart.getParents()[iP].getObjectID(),
part.getParents()[iP].getObjectID(),
" parent " << iP << " in particle " << i);
}
REQUIRE_SAME(origPart.getDaughters().size(), part.getDaughters().size(), "size of daughters in particle " << i);
for (size_t iD = 0; iD < origPart.getDaughters().size(); ++iD) {
REQUIRE_SAME(
origPart.getDaughters()[iD].getObjectID(),
part.getDaughters()[iD].getObjectID(),
" parent " << iD << " in particle " << i);
}
}

return true;
}

bool compare(
const edm4hep::SimCalorimeterHitCollection& origColl,
const edm4hep::SimCalorimeterHitCollection& roundtripColl)
{
REQUIRE_SAME(origColl.size(), roundtripColl.size(), "collection sizes");
for (size_t i = 0; i < origColl.size(); ++i) {
auto origHit = origColl[i];
auto hit = roundtripColl[i];

REQUIRE_SAME(origHit.getCellID(), hit.getCellID(), "cellID in hit " << i);
REQUIRE_SAME(origHit.getEnergy(), hit.getEnergy(), "energy in hit " << i);
REQUIRE_SAME(origHit.getPosition(), hit.getPosition(), "position in hit " << i);

// Check the contributions
const auto origContribs = origHit.getContributions();
const auto contribs = hit.getContributions();
REQUIRE_SAME(origContribs.size(), contribs.size(), "size of contributions in hit " << i);
for (size_t iC = 0; iC < origHit.getContributions().size(); ++iC) {
const auto origCont = origContribs[iC];
const auto cont = contribs[iC];
REQUIRE_SAME(origCont.getPDG(), cont.getPDG(), "pdg of contribution " << iC << " in hit " << i);
REQUIRE_SAME(origCont.getEnergy(), cont.getEnergy(), "energy of contribution " << iC << " in hit " << i);
REQUIRE_SAME(origCont.getTime(), cont.getTime(), "time of contribution " << iC << " in hit " << i);
REQUIRE_SAME(
origCont.getStepPosition(), cont.getStepPosition(), "stepPosition of contribution " << iC << " in hit " << i);

// Check the MCParticles via ObjectID (asssuming collection names remain
// unchanged)
REQUIRE_SAME(
origCont.getParticle().getObjectID(),
cont.getParticle().getObjectID(),
"particle of contribution " << iC << " in hit " << i);
}
}

return true;
}

bool compare(const edm4hep::TrackState& orig, const edm4hep::TrackState& roundtrip)
{
REQUIRE_SAME(orig.location, roundtrip.location, "location in TrackState");
REQUIRE_SAME(orig.D0, roundtrip.D0, "D0 in TrackState");
REQUIRE_SAME(orig.Z0, roundtrip.Z0, "Z0 in TrackState");
REQUIRE_SAME(orig.phi, roundtrip.phi, "phi in TrackState");
REQUIRE_SAME(orig.omega, roundtrip.omega, "omega in TrackState");
REQUIRE_SAME(orig.tanLambda, roundtrip.tanLambda, "tanLambda in TrackState");
REQUIRE_SAME(orig.referencePoint, roundtrip.referencePoint, "referencePoint in TrackState");
// The time related covariance matrix elements are lost in the EDM4hep -> LCIO
// conversion and set to zero in the LCIO -> EDM4hep conversion
const auto redOrigCov = std::vector(orig.covMatrix.begin(), orig.covMatrix.begin() + 15);
const auto redCov = std::vector(roundtrip.covMatrix.begin(), roundtrip.covMatrix.begin() + 15);
REQUIRE_SAME(redOrigCov, redCov, "covMatrix in TrackState");

return true;
}

bool compare(const edm4hep::TrackCollection& origColl, const edm4hep::TrackCollection& roundtripColl)
{
REQUIRE_SAME(origColl.size(), roundtripColl.size(), "collection sizes");

for (size_t i = 0; i < origColl.size(); ++i) {
auto origTrack = origColl[i];
auto track = roundtripColl[i];

REQUIRE_SAME(origTrack.getChi2(), track.getChi2(), "chi2 in track " << i);
REQUIRE_SAME(origTrack.getNdf(), track.getNdf(), "chi2 in track " << i);
REQUIRE_SAME(origTrack.getDEdx(), track.getDEdx(), "dEdx in track " << i);
REQUIRE_SAME(origTrack.getDEdxError(), track.getDEdxError(), "dEdxError in track " << i);

const auto origSubDetHitNumbers = origTrack.getSubdetectorHitNumbers();
const auto subDetHitNumbers = track.getSubdetectorHitNumbers();
// Resizing in EDM4hep to LCIO conversion causes the roundtripped version to
// have 50 hits. So here we just compare the ones that are available in the
// original
for (size_t iSN = 0; iSN < origSubDetHitNumbers.size(); ++iSN) {
REQUIRE_SAME(
origSubDetHitNumbers[iSN], subDetHitNumbers[iSN], "subdetector hit numbers " << iSN << " in track " << i);
}
for (size_t iSN = origSubDetHitNumbers.size(); iSN < 50; ++iSN) {
REQUIRE_SAME(0, subDetHitNumbers[iSN], "additional subdetector hit number in track " << i);
}

const auto origHits = origTrack.getTrackerHits();
const auto hits = track.getTrackerHits();
REQUIRE_SAME(origHits.size(), hits.size(), "number of hits in track " << i);
for (size_t iH = 0; iH < origHits.size(); ++iH) {
REQUIRE_SAME(origHits[iH].getObjectID(), hits[iH].getObjectID(), "tracker hit " << iH << " in track " << i);
}

const auto origStates = origTrack.getTrackStates();
const auto states = track.getTrackStates();
REQUIRE_SAME(origStates.size(), states.size(), "number of track states in track " << i);
for (size_t iS = 0; iS < origStates.size(); ++iS) {
if (!compare(origStates[iS], states[iS])) {
std::cerr << "in track state " << iS << " in track " << i << std::endl;
return false;
}
}

const auto origTracks = origTrack.getTracks();
const auto tracks = track.getTracks();
REQUIRE_SAME(origTracks.size(), tracks.size(), "number of tracks in track " << i);
for (size_t iT = 0; iT < origTracks.size(); ++iT) {
REQUIRE_SAME(origTracks[iT].getObjectID(), tracks[iT].getObjectID(), "track " << iT << " in track " << i);
}
}
return true;
}

bool compare(const edm4hep::TrackerHitCollection& origColl, const edm4hep::TrackerHitCollection& roundtripColl)
{
REQUIRE_SAME(origColl.size(), roundtripColl.size(), "collection sizes");
for (size_t i = 0; i < origColl.size(); ++i) {
auto origHit = origColl[i];
auto hit = roundtripColl[i];

REQUIRE_SAME(origHit.getCellID(), hit.getCellID(), "cellID in hit " << i);
REQUIRE_SAME(origHit.getType(), hit.getType(), "type in hit " << i);
REQUIRE_SAME(origHit.getQuality(), hit.getQuality(), "quality in hit " << i);
REQUIRE_SAME(origHit.getTime(), hit.getTime(), "time in hit " << i);
REQUIRE_SAME(origHit.getEDep(), hit.getEDep(), "EDep in hit " << i);
REQUIRE_SAME(origHit.getEDepError(), hit.getEDepError(), "EDepError in hit " << i);
REQUIRE_SAME(origHit.getPosition(), hit.getPosition(), "Position in hit " << i);
REQUIRE_SAME(origHit.getCovMatrix(), hit.getCovMatrix(), "CovMatrix in hit " << i);
}

return true;
}
18 changes: 18 additions & 0 deletions tests/src/CompareEDM4hepEDM4hep.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
#ifndef K4EDM4HEP2LCIOCONV_TEST_COMPAREEDM4HEPEDM4HEP_H
#define K4EDM4HEP2LCIOCONV_TEST_COMPAREEDM4HEPEDM4HEP_H

#include "EDM4hep2LCIOUtilities.h"

bool compare(const edm4hep::CalorimeterHitCollection& origColl, const edm4hep::CalorimeterHitCollection& roundtripColl);

bool compare(const edm4hep::MCParticleCollection& origColl, const edm4hep::MCParticleCollection& roundtripColl);

bool compare(
const edm4hep::SimCalorimeterHitCollection& origColl,
const edm4hep::SimCalorimeterHitCollection& roundtripColl);

bool compare(const edm4hep::TrackCollection& origColl, const edm4hep::TrackCollection& roundtripColl);

bool compare(const edm4hep::TrackerHitCollection& origColl, const edm4hep::TrackerHitCollection& roundtripColl);

#endif // K4EDM4HEP2LCIOCONV_TEST_COMPAREEDM4HEPEDM4HEP_H

0 comments on commit bafa331

Please sign in to comment.