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

Adapt the converter for dealing with reversed ParticleID relations #51

Merged
merged 18 commits into from
May 1, 2024
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
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
Loading