Skip to content

Commit

Permalink
Adapt the converter for dealing with reversed ParticleID relations (#51)
Browse files Browse the repository at this point in the history
* Remove the ParticleID relation from the Clusters

* Remove the particleIDUsed from the reco particle

* Remove the particleID and make things compile again

* Convert ParticleIDs into separate collections from LCIO

* Update standalone converter tests to compare correctly for new layout

* Remove unnecessary map and unused parameters

* Remove no longer valid comment

* Make roundtrip tests check ParticleIDs in new format

* Convert ParticleIDs also from EDM4hep to LCIO

* Make interface const correct

* Use the EDM4hep PIDHandler in conversion to set meta info

* Try to keep 1-to-1 mapping for algorithmType in roundtrips

* Convert PID meta information in standalone conversion

* Move particle id metadata handling into reusable functionality

* Update docstrings

* Remove unused code, includes, and cmake config

* Use correct target name

---------

Co-authored-by: hegner <[email protected]>
  • Loading branch information
tmadlener and hegner authored May 1, 2024
1 parent a3dc779 commit f870d19
Show file tree
Hide file tree
Showing 19 changed files with 414 additions and 214 deletions.
4 changes: 3 additions & 1 deletion k4EDM4hep2LcioConv/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,9 @@ target_include_directories(k4EDM4hep2LcioConv PUBLIC

target_link_libraries(k4EDM4hep2LcioConv PUBLIC
LCIO::lcio
EDM4HEP::edm4hep)
EDM4HEP::edm4hep
EDM4HEP::utils
)

set(public_headers
include/${PROJECT_NAME}/k4EDM4hep2LcioConv.h
Expand Down
51 changes: 51 additions & 0 deletions k4EDM4hep2LcioConv/include/k4EDM4hep2LcioConv/k4EDM4hep2LcioConv.h
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@ namespace edm4hep {
#endif
#include <edm4hep/TrackerHitPlaneCollection.h>
#include <edm4hep/VertexCollection.h>
#include <edm4hep/utils/ParticleIDUtils.h>

#include "podio/Frame.h"

Expand All @@ -59,6 +60,7 @@ namespace edm4hep {
#include <lcio.h>

#include <memory>
#include <optional>

// Preprocessor symbol that can be used in downstream code to switch on the
// namespace for the conversion
Expand All @@ -85,8 +87,45 @@ namespace EDM4hep2LCIOConv {
ObjectMapT<lcio::VertexImpl*, edm4hep::Vertex> vertices {};
ObjectMapT<lcio::ReconstructedParticleImpl*, edm4hep::ReconstructedParticle> recoParticles {};
ObjectMapT<lcio::MCParticleImpl*, edm4hep::MCParticle> mcParticles {};
ObjectMapT<lcio::ParticleIDImpl*, edm4hep::ParticleID> particleIDs {};
};

/// The minimal necessary information to do late conversions of ParticleIDs,
/// which is necessary to have consistent algorithmType information in the
/// conversion
struct ParticleIDConvData {
std::string name;
const edm4hep::ParticleIDCollection* coll;
std::optional<edm4hep::utils::ParticleIDMeta> metadata;
};

/// Sort the ParticleIDs according to their algorithmType.
///
/// This sorting allows for a fully consistent roundtrip conversion under the
/// following conditions:
/// - All ParticleIDs are converted (where all means all that belong to a
/// given ReconstructedParticle collection)
/// - All of these conversions had the necessary metadata available
///
/// In case these conditions are not met, the assigned algorithmTypes might
/// differ between LCIO and EDM4hep, but the metadata that is set will be
/// consistent for usage.
void sortParticleIDs(std::vector<ParticleIDConvData>& pidCollections);

/// Attach the meta information for one ParticleID collection to the passed
/// LCIO Event
///
/// This returns the algorithmID according to the PIDHandler that is used to
/// attach the information to the LCIO reconstructed particle collection. If
/// there is no fitting reconstructed particle collection to attach this to
/// but the meta data in the ParticleIDConvData is valid, the algoType of that
/// will be returned. If there is no reconstructed particle collection or the
/// meta data is invalid an empty optional is returned.
std::optional<int32_t> attachParticleIDMetaData(
IMPL::LCEventImpl* lcEvent,
const podio::Frame& edmEvent,
const ParticleIDConvData& pidCollMetaInfo);

/**
* Convert EDM4hep Tracks to LCIO. Simultaneously populate the mapping from
* EDM4hep to LCIO objects for relation resolving in a second step.
Expand Down Expand Up @@ -321,6 +360,15 @@ namespace EDM4hep2LCIOConv {
return convertMCParticles(mcparticle_coll, mc_particles_vec).release();
}

/**
* Convert EDM4hep ParticleIDs to LCIO. NOTE: Since ParticleIDs cannot live in
* their own collections in LCIO this simply populates the pidMap that maps
* LCIO to EDM4hep particleIDs. **This just converts the data it is crucial to
* also resolve the relations afterwards!**
*/
template<typename PidMapT>
void convertParticleIDs(const edm4hep::ParticleIDCollection* const edmCollection, PidMapT& pidMap, const int algoId);

/**
* Convert EDM4hep EventHeader to LCIO. This will directly populate the
* corresponding information in the passed LCEvent. The input collection needs
Expand Down Expand Up @@ -389,6 +437,9 @@ namespace EDM4hep2LCIOConv {
template<typename ClusterMapT, typename CaloHitMapT>
void resolveRelationsClusters(ClusterMapT& clustersMap, const CaloHitMapT& caloHitMap);

template<typename PidMapT, typename RecoParticleMapT>
void resolveRelationsParticleIDs(PidMapT& pidMap, const RecoParticleMapT& recoMap);

/**
* Resolve all relations in all converted objects that are held in the map.
* Dispatch to the correpsonding implementation for all the types that have
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,6 @@ namespace EDM4hep2LCIOConv {
TrackMapT& trackMap)
{
auto tracks = std::make_unique<lcio::LCCollectionVec>(lcio::LCIO::TRACK);

// Loop over EDM4hep tracks converting them to lcio tracks.
for (const auto& edm_tr : (*edmCollection)) {
if (edm_tr.isAvailable()) {
Expand Down Expand Up @@ -392,23 +391,6 @@ namespace EDM4hep2LCIOConv {
subdetEnergies.push_back(edmEnergy);
}

// Convert ParticleIDs associated to the recoparticle
for (const auto& edm_pid : edm_cluster.getParticleIDs()) {
if (edm_pid.isAvailable()) {
auto* lcio_pid = new lcio::ParticleIDImpl;

lcio_pid->setType(edm_pid.getType());
lcio_pid->setPDG(edm_pid.getPDG());
lcio_pid->setLikelihood(edm_pid.getLikelihood());
lcio_pid->setAlgorithmType(edm_pid.getAlgorithmType());
for (const auto& param : edm_pid.getParameters()) {
lcio_pid->addParameter(param);
}

lcio_cluster->addParticleID(lcio_pid);
}
}

// Add LCIO and EDM4hep pair collections to vec
k4EDM4hep2LcioConv::detail::mapInsert(lcio_cluster, edm_cluster, clusterMap);

Expand Down Expand Up @@ -473,43 +455,6 @@ namespace EDM4hep2LCIOConv {
float rp[3] = {edm_rp.getReferencePoint()[0], edm_rp.getReferencePoint()[1], edm_rp.getReferencePoint()[2]};
lcio_recp->setReferencePoint(rp);
lcio_recp->setGoodnessOfPID(edm_rp.getGoodnessOfPID());

// Convert ParticleIDs associated to the recoparticle
for (const auto& edm_pid : edm_rp.getParticleIDs()) {
if (edm_pid.isAvailable()) {
auto* lcio_pid = new lcio::ParticleIDImpl;

lcio_pid->setType(edm_pid.getType());
lcio_pid->setPDG(edm_pid.getPDG());
lcio_pid->setLikelihood(edm_pid.getLikelihood());
lcio_pid->setAlgorithmType(edm_pid.getAlgorithmType());
for (const auto& param : edm_pid.getParameters()) {
lcio_pid->addParameter(param);
}

lcio_recp->addParticleID(lcio_pid);
}
}

// Link sinlge associated Particle
auto edm_pid_used = edm_rp.getParticleIDUsed();
if (edm_pid_used.isAvailable()) {
for (const auto& lcio_pid : lcio_recp->getParticleIDs()) {
bool is_same = true;
is_same = is_same && (lcio_pid->getType() == edm_pid_used.getType());
is_same = is_same && (lcio_pid->getPDG() == edm_pid_used.getPDG());
is_same = is_same && (lcio_pid->getLikelihood() == edm_pid_used.getLikelihood());
is_same = is_same && (lcio_pid->getAlgorithmType() == edm_pid_used.getAlgorithmType());
for (auto i = 0u; i < edm_pid_used.parameters_size(); ++i) {
is_same = is_same && (edm_pid_used.getParameters(i) == lcio_pid->getParameters()[i]);
}
if (is_same) {
lcio_recp->setParticleIDUsed(lcio_pid);
break;
}
}
}

// Add LCIO and EDM4hep pair collections to vec
k4EDM4hep2LcioConv::detail::mapInsert(lcio_recp, edm_rp, recoparticles_vec);

Expand Down Expand Up @@ -574,6 +519,22 @@ namespace EDM4hep2LCIOConv {
return mcparticles;
}

template<typename PidMapT>
void convertParticleIDs(const edm4hep::ParticleIDCollection* const edmCollection, PidMapT& pidMap, const int algoId)
{
for (const auto& edmPid : (*edmCollection)) {
auto [lcioPid, _] = k4EDM4hep2LcioConv::detail::mapInsert(new lcio::ParticleIDImpl(), edmPid, pidMap).first;

lcioPid->setType(edmPid.getType());
lcioPid->setPDG(edmPid.getPDG());
lcioPid->setLikelihood(edmPid.getLikelihood());
lcioPid->setAlgorithmType(algoId);
for (const auto& param : edmPid.getParameters()) {
lcioPid->addParameter(param);
}
}
}

template<typename MCParticleMapT, typename MCParticleLookupMapT>
void resolveRelationsMCParticles(MCParticleMapT& mcParticlesMap, const MCParticleLookupMapT& lookupMap)
{
Expand Down Expand Up @@ -762,6 +723,21 @@ namespace EDM4hep2LCIOConv {
}
}

template<typename PidMapT, typename RecoParticleMapT>
void resolveRelationsParticleIDs(PidMapT& pidMap, const RecoParticleMapT& recoMap)
{
for (auto& [lcioPid, edmPid] : pidMap) {
const auto edmReco = edmPid.getParticle();
const auto lcioReco = k4EDM4hep2LcioConv::detail::mapLookupFrom(edmReco, recoMap);
if (lcioReco) {
lcioReco.value()->addParticleID(lcioPid);
}
else {
std::cerr << "Cannot find a reconstructed particle to attach a ParticleID to" << std::endl;
}
}
}

template<typename ObjectMappingT>
void resolveRelations(ObjectMappingT& collection_pairs)
{
Expand All @@ -783,6 +759,7 @@ namespace EDM4hep2LCIOConv {
lookup_pairs.vertices,
lookup_pairs.clusters,
lookup_pairs.tracks);
resolveRelationsParticleIDs(lookup_pairs.particleIDs, update_pairs.recoParticles);
resolveRelationsVertices(update_pairs.vertices, lookup_pairs.recoParticles);
resolveRelationsSimCaloHit(update_pairs.simCaloHits, lookup_pairs.mcParticles);
resolveRelationsSimTrackerHits(update_pairs.simTrackerHits, lookup_pairs.mcParticles);
Expand Down
45 changes: 25 additions & 20 deletions k4EDM4hep2LcioConv/include/k4EDM4hep2LcioConv/k4Lcio2EDM4hepConv.h
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@ namespace edm4hep {
#endif
#include "edm4hep/TrackerHitPlaneCollection.h"
#include "edm4hep/VertexCollection.h"
#include "edm4hep/utils/ParticleIDUtils.h"

// LCIO
#include <EVENT/CalorimeterHit.h>
Expand Down Expand Up @@ -90,7 +91,6 @@ namespace LCIO2EDM4hepConv {
ObjectMapT<lcio::ReconstructedParticle*, edm4hep::MutableReconstructedParticle> recoParticles {};
ObjectMapT<lcio::MCParticle*, edm4hep::MutableMCParticle> mcParticles {};
ObjectMapT<lcio::TrackerHitPlane*, edm4hep::MutableTrackerHitPlane> trackerHitPlanes {};
ObjectMapT<lcio::ParticleID*, edm4hep::MutableParticleID> particleIDs {};
};

using CollNamePair = std::tuple<std::string, std::unique_ptr<podio::CollectionBase>>;
Expand Down Expand Up @@ -172,6 +172,21 @@ namespace LCIO2EDM4hepConv {

inline edm4hep::Vector3f Vector3fFrom(const EVENT::FloatVec& v) { return edm4hep::Vector3f(v[0], v[1], v[2]); }

/**
* Get the name of a ParticleID collection from the name of the reco
* collection (from which it is created) and the PID algorithm name.
*/
inline std::string getPIDCollName(const std::string& recoCollName, const std::string& algoName)
{
return recoCollName + "_PID_" + algoName;
}

/**
* Get the meta information for all particle id collections that are available
* from the PIDHandler
*/
std::vector<edm4hep::utils::ParticleIDMeta> getPIDMetaInfo(const EVENT::LCCollection* recoColl);

/**
* Convert a TrackState
*/
Expand Down Expand Up @@ -200,16 +215,13 @@ namespace LCIO2EDM4hepConv {
* Convert a ReconstructedParticle collection and return the resulting collection.
* Simultaneously populates the mapping from LCIO to EDM4hep objects.
*
* NOTE: Also populates a ParticleID collection, as those are persisted as
* NOTE: Also populates ParticleID collections, as those are persisted as
* part of the ReconstructedParticles in LCIO. The name of this collection is
* <name>_particleIDs
* <name>_PID_<pid_algo_name> (see getPIDCollName)
*/
template<typename RecoMapT, typename PIDMapT>
std::vector<CollNamePair> convertReconstructedParticles(
const std::string& name,
EVENT::LCCollection* LCCollection,
RecoMapT& recoparticlesMap,
PIDMapT& particleIDMap);
template<typename RecoMapT>
std::vector<CollNamePair>
convertReconstructedParticles(const std::string& name, EVENT::LCCollection* LCCollection, RecoMapT& recoparticlesMap);

/**
* Convert a Vertex collection and return the resulting collection.
Expand Down Expand Up @@ -286,17 +298,10 @@ namespace LCIO2EDM4hepConv {
/**
* Convert a Cluster collection and return the resulting collection.
* Simultaneously populates the mapping from LCIO to EDM4hep objects.
*
* NOTE: Also populates a ParticleID collection, as those are persisted as
* part of the Cluster collection in LCIO. The name of this collection is
* <name>_particleIDs
*/
template<typename ClusterMapT, typename PIDMapT>
std::vector<CollNamePair> convertClusters(
const std::string& name,
EVENT::LCCollection* LCCollection,
ClusterMapT& clusterMap,
PIDMapT& particleIDMap);
*/
template<typename ClusterMapT>
std::unique_ptr<edm4hep::ClusterCollection>
convertClusters(const std::string& name, EVENT::LCCollection* LCCollection, ClusterMapT& clusterMap);

/**
* Create an EventHeaderCollection and fills it with the Metadata.
Expand Down
Loading

0 comments on commit f870d19

Please sign in to comment.