From 95a8929fb2bddee70ce15d812fa9f49ac400b4d5 Mon Sep 17 00:00:00 2001 From: Thomas Madlener Date: Mon, 6 Nov 2023 14:12:15 +0100 Subject: [PATCH] Fix the conversion of edm4hep::Clusters to LCIO::Clusters (#36) * Add the conversion of subdetector energies * Fix missing relations to calo hits * Set the contribution weight to 1.0 * Make tests also compare related clusters * Make sure to check cluster relations in non roundtrip tests --- .../k4EDM4hep2LcioConv/k4EDM4hep2LcioConv.ipp | 39 ++++++++++++------- tests/edm4hep_roundtrip.cpp | 1 + tests/src/CompareEDM4hepEDM4hep.cc | 36 +++++++++++++++++ tests/src/CompareEDM4hepEDM4hep.h | 2 + tests/src/CompareEDM4hepLCIO.cc | 12 ++++++ tests/src/EDM4hep2LCIOUtilities.cc | 36 +++++++++++++++++ tests/src/EDM4hep2LCIOUtilities.h | 20 ++++++++++ 7 files changed, 133 insertions(+), 13 deletions(-) diff --git a/k4EDM4hep2LcioConv/include/k4EDM4hep2LcioConv/k4EDM4hep2LcioConv.ipp b/k4EDM4hep2LcioConv/include/k4EDM4hep2LcioConv/k4EDM4hep2LcioConv.ipp index f0dd49a7..d62e9fb9 100644 --- a/k4EDM4hep2LcioConv/include/k4EDM4hep2LcioConv/k4EDM4hep2LcioConv.ipp +++ b/k4EDM4hep2LcioConv/include/k4EDM4hep2LcioConv/k4EDM4hep2LcioConv.ipp @@ -427,6 +427,11 @@ namespace EDM4hep2LCIOConv { } lcio_cluster->setShape(shape_vec); + auto& subdetEnergies = lcio_cluster->subdetectorEnergies(); + for (const auto edmEnergy : edm_cluster.getSubdetectorEnergies()) { + subdetEnergies.push_back(edmEnergy); + } + // Convert ParticleIDs associated to the recoparticle for (const auto& edm_pid : edm_cluster.getParticleIDs()) { if (edm_pid.isAvailable()) { @@ -452,19 +457,6 @@ namespace EDM4hep2LCIOConv { } } - // Link associated clusters after converting all clusters - for (auto& [lcio_cluster, edm_cluster] : cluster_vec) { - for (const auto& edm_linked_cluster : edm_cluster.getClusters()) { - if (edm_linked_cluster.isAvailable()) { - if ( - const auto lcio_cluster_linked = - k4EDM4hep2LcioConv::detail::mapLookupFrom(edm_linked_cluster, cluster_vec)) { - lcio_cluster->addCluster(lcio_cluster_linked.value()); - } - } - } - } - return clusters; } @@ -833,6 +825,27 @@ namespace EDM4hep2LCIOConv { } } // SimTrackerHits + + // Resolve relations for clusters + for (auto& [lcio_cluster, edm_cluster] : update_pairs.clusters) { + for (const auto& edm_linked_cluster : edm_cluster.getClusters()) { + if (edm_linked_cluster.isAvailable()) { + if ( + const auto lcio_cluster_linked = + k4EDM4hep2LcioConv::detail::mapLookupFrom(edm_linked_cluster, lookup_pairs.clusters)) { + lcio_cluster->addCluster(lcio_cluster_linked.value()); + } + } + } + + for (const auto& edm_calohit : edm_cluster.getHits()) { + if (edm_calohit.isAvailable()) { + if (const auto lcio_calohit = k4EDM4hep2LcioConv::detail::mapLookupFrom(edm_calohit, lookup_pairs.caloHits)) { + lcio_cluster->addHit(lcio_calohit.value(), 1.0); + } + } + } + } } } // namespace EDM4hep2LCIOConv diff --git a/tests/edm4hep_roundtrip.cpp b/tests/edm4hep_roundtrip.cpp index a4b0f960..1cfa5ebe 100644 --- a/tests/edm4hep_roundtrip.cpp +++ b/tests/edm4hep_roundtrip.cpp @@ -25,6 +25,7 @@ int main() ASSERT_SAME_OR_ABORT(edm4hep::SimCalorimeterHitCollection, "simCaloHits"); ASSERT_SAME_OR_ABORT(edm4hep::TrackCollection, "tracks"); ASSERT_SAME_OR_ABORT(edm4hep::TrackerHitCollection, "trackerHits"); + ASSERT_SAME_OR_ABORT(edm4hep::ClusterCollection, "clusters"); return 0; } diff --git a/tests/src/CompareEDM4hepEDM4hep.cc b/tests/src/CompareEDM4hepEDM4hep.cc index be72e9e7..4d115bd3 100644 --- a/tests/src/CompareEDM4hepEDM4hep.cc +++ b/tests/src/CompareEDM4hepEDM4hep.cc @@ -6,6 +6,7 @@ #include "edm4hep/SimCalorimeterHitCollection.h" #include "edm4hep/TrackCollection.h" #include "edm4hep/TrackerHitCollection.h" +#include "edm4hep/ClusterCollection.h" #include #include @@ -216,3 +217,38 @@ bool compare(const edm4hep::TrackerHitCollection& origColl, const edm4hep::Track return true; } + +bool compare(const edm4hep::ClusterCollection& origColl, const edm4hep::ClusterCollection& roundtripColl) +{ + REQUIRE_SAME(origColl.size(), roundtripColl.size(), "collection sizes"); + for (size_t i = 0; i < origColl.size(); ++i) { + auto origCluster = origColl[i]; + auto cluster = roundtripColl[i]; + + const auto origRelClusters = origCluster.getClusters(); + const auto relClusters = cluster.getClusters(); + REQUIRE_SAME(origRelClusters.size(), relClusters.size(), "number of related clusters in cluster " << i); + for (size_t iC = 0; iC < origRelClusters.size(); ++iC) { + REQUIRE_SAME( + origRelClusters[iC].getObjectID(), + relClusters[iC].getObjectID(), + "related cluster " << iC << " in cluster " << i); + } + + const auto origHits = origCluster.getHits(); + const auto hits = cluster.getHits(); + REQUIRE_SAME(origHits.size(), hits.size(), "number of calorimeter hits in cluster " << i); + for (size_t iH = 0; iH < origHits.size(); ++iH) { + REQUIRE_SAME(origHits[iH].getObjectID(), hits[iH].getObjectID(), "calorimeter hit " << iH << " in cluster " << i); + } + + const auto& origSubdetE = origCluster.getSubdetectorEnergies(); + const auto& subdetE = cluster.getSubdetectorEnergies(); + REQUIRE_SAME(origSubdetE.size(), subdetE.size(), "sizes of subdetector energies in cluster " << i); + for (size_t iSE = 0; iSE < origSubdetE.size(); ++iSE) { + REQUIRE_SAME(origSubdetE[iSE], subdetE[iSE], "subdetector energy " << iSE << " in cluster " << i); + } + } + + return true; +} diff --git a/tests/src/CompareEDM4hepEDM4hep.h b/tests/src/CompareEDM4hepEDM4hep.h index e9a5924d..890ebc5f 100644 --- a/tests/src/CompareEDM4hepEDM4hep.h +++ b/tests/src/CompareEDM4hepEDM4hep.h @@ -15,4 +15,6 @@ bool compare(const edm4hep::TrackCollection& origColl, const edm4hep::TrackColle bool compare(const edm4hep::TrackerHitCollection& origColl, const edm4hep::TrackerHitCollection& roundtripColl); +bool compare(const edm4hep::ClusterCollection& origColl, const edm4hep::ClusterCollection& roundtripColl); + #endif // K4EDM4HEP2LCIOCONV_TEST_COMPAREEDM4HEPEDM4HEP_H diff --git a/tests/src/CompareEDM4hepLCIO.cc b/tests/src/CompareEDM4hepLCIO.cc index 5ec11710..8854dbd2 100644 --- a/tests/src/CompareEDM4hepLCIO.cc +++ b/tests/src/CompareEDM4hepLCIO.cc @@ -72,6 +72,18 @@ bool compare(const EVENT::Cluster* lcioElem, const edm4hep::Cluster& edm4hepElem // LCIO has getIPhi and EDM4hep has getPhi ASSERT_COMPARE_VALS(lcioElem->getIPhi(), edm4hepElem.getPhi(), "phi in Cluster"); ASSERT_COMPARE(lcioElem, edm4hepElem, getDirectionError, "directionError in Cluster"); + + ASSERT_COMPARE(lcioElem, edm4hepElem, getSubdetectorEnergies, "subdetectorEnergies in Cluster"); + ASSERT_COMPARE_VALS(lcioElem->getShape(), edm4hepElem.getShapeParameters(), "shape / shapeParameters in Cluster"); + + ASSERT_COMPARE_RELATION(lcioElem, edm4hepElem, getClusters, objectMaps.clusters, "related clusters in Cluster"); + + // Different names of related calorimeter hits in interfaces + if (!compareRelation( + lcioElem->getCalorimeterHits(), edm4hepElem.getHits(), objectMaps.caloHits, "calorimeter hits in Cluster")) { + return false; + } + return true; } diff --git a/tests/src/EDM4hep2LCIOUtilities.cc b/tests/src/EDM4hep2LCIOUtilities.cc index d3a3edfb..336e4d37 100644 --- a/tests/src/EDM4hep2LCIOUtilities.cc +++ b/tests/src/EDM4hep2LCIOUtilities.cc @@ -10,6 +10,7 @@ #include "edm4hep/TrackCollection.h" #include "edm4hep/SimCalorimeterHitCollection.h" #include "edm4hep/CaloHitContributionCollection.h" +#include "edm4hep/ClusterCollection.h" #include "podio/Frame.h" @@ -266,6 +267,33 @@ edm4hep::EventHeaderCollection createEventHeader() return evtHeaderColl; } +edm4hep::ClusterCollection createClusters( + const int num_elements, + const edm4hep::CalorimeterHitCollection& caloHits, + const int num_subdet_energies, + const std::vector& clusterHitIdcs, + const std::vector& clusterClusterIdcs) +{ + auto clusterColl = edm4hep::ClusterCollection {}; + for (int i = 0; i < num_elements; ++i) { + auto cluster = clusterColl.create(); + + for (int j = 0; j < num_subdet_energies; ++j) { + cluster.addToSubdetectorEnergies(j); + } + } + + for (const auto [cluIdx, hitIdx] : clusterHitIdcs) { + clusterColl[cluIdx].addToHits(caloHits[hitIdx]); + } + + for (const auto [targetI, sourceI] : clusterHitIdcs) { + clusterColl[targetI].addToClusters(clusterColl[sourceI]); + } + + return clusterColl; +} + podio::Frame createExampleEvent() { podio::Frame event; @@ -286,6 +314,14 @@ podio::Frame createExampleEvent() test_config::trackTrackerHitIdcs, test_config::trackTrackIdcs), "tracks"); + event.put( + createClusters( + test_config::nClusters, + caloHits, + test_config::nSubdetectorEnergies, + test_config::clusterHitIdcs, + test_config::clusterClusterIdcs), + "clusters"); auto [tmpSimCaloHits, tmpCaloHitConts] = createSimCalorimeterHits( test_config::nSimCaloHits, test_config::nCaloHitContributions, mcParticles, test_config::simCaloHitMCIdcs); diff --git a/tests/src/EDM4hep2LCIOUtilities.h b/tests/src/EDM4hep2LCIOUtilities.h index 30dec37c..0751f300 100644 --- a/tests/src/EDM4hep2LCIOUtilities.h +++ b/tests/src/EDM4hep2LCIOUtilities.h @@ -16,6 +16,7 @@ namespace edm4hep { class SimCalorimeterHitCollection; class CaloHitContributionCollection; class EventHeaderCollection; + class ClusterCollection; } // namespace edm4hep namespace podio { @@ -67,6 +68,17 @@ namespace test_config { {2, 2, 2}, {2, 3, 0}}; + /// The number of clusters to create + constexpr static int nClusters = 5; + /// The number of subdetector energy entries to create + constexpr static int nSubdetectorEnergies = 6; + /// The calorimeter hits that should be associated with each cluster. First + /// index is the cluster, second is the calorimeter hit + const static std::vector clusterHitIdcs = {{0, 0}, {0, 1}, {1, 0}, {2, 1}, {2, 0}, {3, 0}, {3, 0}}; + /// The clustes (from inside the same collection) that should be added to each + /// cluster. First index is the cluster to which the second index cluster will + /// be added + const static std::vector clusterClusterIdcs = {{0, 4}, {0, 3}, {0, 1}, {4, 3}, {4, 2}, {2, 3}, {1, 1}}; } // namespace test_config /** @@ -123,6 +135,13 @@ std::pair& clusterHitIdcs, + const std::vector& clusterClusterIdcs); + /** * Create an example event that can be used to test the converter. * @@ -140,6 +159,7 @@ edm4hep::EventHeaderCollection createEventHeader(); * | trackerHits | TrackerHit | createTrackerHits | * | simCaloHits | SimCalorimeterHit | createSimCalorimeterHits | * | caloHitContributions | CaloHitContribution | createSimCalorimeterHits | + * | clusters | ClusterCollection | createClusters | */ podio::Frame createExampleEvent();