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

Read edm4hep #1371

Merged
merged 26 commits into from
Jan 20, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
26 commits
Select commit Hold shift + click to select a range
8d10213
DDG4: add EDM4hepFile Reader
andresailer Dec 13, 2024
9532565
DDSim: allow EDM4hep File reader
andresailer Dec 13, 2024
7762ef9
ReadEDM4hep: use objectID.index to identify particles
andresailer Dec 16, 2024
6252193
EDM4hepReader: ingest all kinds of parameters
andresailer Dec 16, 2024
08774b4
ReadEDM4hep: read runs entry for run parameters
andresailer Dec 17, 2024
be8a5b1
DDTest: add edm4hep to eventreader test
andresailer Dec 17, 2024
6a575e9
ReadEDM4hep: read EventHeader information
andresailer Dec 17, 2024
6f4ea9b
Geant4Output2EDM4hep: get EventHeader context if it exists
andresailer Dec 17, 2024
8474640
ReadEDM4hep: protect against missing g4context, minor cleanups
andresailer Dec 17, 2024
2370526
LCIOReader: protect against missing Gean4InputAction, like in test_ev…
andresailer Dec 17, 2024
fe57767
test_EventReaders: typos, tweaks, testing EDM4hep with direct access
andresailer Dec 17, 2024
f677865
ReadEDM4hep: make metadata and runs frame optional
andresailer Dec 17, 2024
d6c969e
ReadEDM4hep: do not treat colorflow, since it will be gone soon
andresailer Dec 18, 2024
f5e0ef3
ReadEDM4hep: simplify ingestion functions
andresailer Dec 18, 2024
6c62fbc
ReadEDM4hep: use generic Reader
andresailer Dec 18, 2024
d779cfc
ReadEDM4hep: allow sio extension
andresailer Jan 8, 2025
54b8c12
ReadEDM4hep: add fileParameter, refactor parameters
andresailer Jan 8, 2025
ad9fb57
ReadEDM4hep: comment the order of file extension checks for input rea…
andresailer Jan 16, 2025
abbcb5a
ReadEDM4hep: registerRunParameters, split error message between run a…
andresailer Jan 16, 2025
530ef74
EDM4hep: drop checks for podio > 0.16.2
andresailer Jan 16, 2025
e0d302a
WriteEDM4hep: drop check for EDM4hep < 0.10.2
andresailer Jan 16, 2025
3c454b5
ReadEDM4hep: only when we have podioIO target (podio > 1.0)
andresailer Jan 17, 2025
e4d099b
WriteEDM4hep: version guards around getWeights
andresailer Jan 17, 2025
d0c2691
ReadEDM4hep: add message about enabling or disabling the reader
andresailer Jan 20, 2025
573696e
ReadEDM4hep: fix target check, add to test
andresailer Jan 20, 2025
2c6f463
ReadEDM4hep: correct cmake status message about requirements.
andresailer Jan 20, 2025
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
14 changes: 12 additions & 2 deletions DDG4/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -104,12 +104,22 @@ ENDIF()

IF(TARGET EDM4HEP::edm4hep)
dd4hep_add_plugin(DDG4EDM4HEP
SOURCES edm4hep/*.cpp
SOURCES edm4hep/Geant4Output2EDM4hep.cpp
USES DD4hep::DDG4 EDM4HEP::edm4hep EDM4HEP::edm4hepDict podio::podio podio::podioDict podio::podioRootIO
)
install(TARGETS DDG4EDM4HEP EXPORT DD4hep LIBRARY DESTINATION lib)
set_target_properties(DDG4EDM4HEP PROPERTIES VERSION ${DD4hep_VERSION} SOVERSION ${DD4hep_SOVERSION})

if(TARGET podio::podioIO)
dd4hep_add_plugin(DDG4EDM4HEPReader
SOURCES edm4hep/EDM4hepFileReader.cpp
USES DD4hep::DDG4 EDM4HEP::edm4hep EDM4HEP::edm4hepDict podio::podio podio::podioDict podio::podioIO
)
install(TARGETS DDG4EDM4HEPReader EXPORT DD4hep LIBRARY DESTINATION lib)
set_target_properties(DDG4EDM4HEPReader PROPERTIES VERSION ${DD4hep_VERSION} SOVERSION ${DD4hep_SOVERSION})
MESSAGE(STATUS "EDM4hepFileReader enabled")
else()
MESSAGE(STATUS "EDM4hepFileReader requires at least PODIO 1.0, disabled")
endif()
ENDIF()

IF(DD4HEP_USE_HEPMC3)
Expand Down
332 changes: 332 additions & 0 deletions DDG4/edm4hep/EDM4hepFileReader.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,332 @@
//==========================================================================
// AIDA Detector description implementation
//--------------------------------------------------------------------------
// Copyright (C) Organisation europeenne pour la Recherche nucleaire (CERN)
// All rights reserved.
//
// For the licensing terms see $DD4hepINSTALL/LICENSE.
// For the list of contributors see $DD4hepINSTALL/doc/CREDITS.
//
// Author : A.Sailer
//
//==========================================================================

/** \addtogroup Geant4EventReader
*
@{
\package EDM4hepFileReader
* \brief Plugin to read EDM4hep files
*
*
@}
*/

#include <CLHEP/Units/SystemOfUnits.h>

#include <DDG4/EventParameters.h>
#include <DDG4/Factories.h>
#include <DDG4/FileParameters.h>
#include <DDG4/Geant4InputAction.h>
#include <DDG4/RunParameters.h>

#include <edm4hep/EventHeaderCollection.h>
#include <edm4hep/MCParticleCollection.h>

#include <podio/Frame.h>
#include <podio/Reader.h>

typedef dd4hep::detail::ReferenceBitMask<int> PropertyMask;


namespace dd4hep::sim {

// we use the index of the objectID to identify particles
// we will not support MCParticles from different collections
andresailer marked this conversation as resolved.
Show resolved Hide resolved
using MCPARTICLE_MAP=std::map<int, int>;

/// get the parameters from the GenericParameters of the input EDM4hep frame and store them in the EventParameters
/// extension
template <class T=podio::GenericParameters> void EventParameters::ingestParameters(T const& source) {
for(auto const& key: source.template getKeys<int>()) {
m_intValues[key] = source.template get<std::vector<int>>(key).value();
}
for(auto const& key: source.template getKeys<float>()) {
m_fltValues[key] = source.template get<std::vector<float>>(key).value();
}
for(auto const& key: source.template getKeys<double>()) {
m_dblValues[key] = source.template get<std::vector<double>>(key).value();
}
for(auto const& key: source.template getKeys<std::string>()) {
m_strValues[key] = source.template get<std::vector<std::string>>(key).value();
}
}

/// get the parameters from the GenericParameters of the input EDM4hep run frame and store them in the RunParameters
/// extension
template <class T=podio::GenericParameters> void RunParameters::ingestParameters(T const& source) {
for(auto const& key: source.template getKeys<int>()) {
m_intValues[key] = source.template get<std::vector<int>>(key).value();
}
for(auto const& key: source.template getKeys<float>()) {
m_fltValues[key] = source.template get<std::vector<float>>(key).value();
}
for(auto const& key: source.template getKeys<double>()) {
m_dblValues[key] = source.template get<std::vector<double>>(key).value();
}
for(auto const& key: source.template getKeys<std::string>()) {
m_strValues[key] = source.template get<std::vector<std::string>>(key).value();
}
}

template <class T=podio::GenericParameters> void FileParameters::ingestParameters(T const& source) {
for(auto const& key: source.template getKeys<int>()) {
m_intValues[key] = source.template get<std::vector<int>>(key).value();
}
for(auto const& key: source.template getKeys<float>()) {
m_fltValues[key] = source.template get<std::vector<float>>(key).value();
}
for(auto const& key: source.template getKeys<double>()) {
m_dblValues[key] = source.template get<std::vector<double>>(key).value();
}
for(auto const& key: source.template getKeys<std::string>()) {
m_strValues[key] = source.template get<std::vector<std::string>>(key).value();
}
}

/// Class to read EDM4hep files
/**
* \version 1.0
* \ingroup DD4HEP_SIMULATION
*/
class EDM4hepFileReader : public Geant4EventReader {
protected:
/// Reference to reader object
podio::Reader m_reader;
andresailer marked this conversation as resolved.
Show resolved Hide resolved
/// Name of the MCParticle collection to read
std::string m_collectionName;
/// Name of the EventHeader collection to read
std::string m_eventHeaderCollectionName;

public:
/// Initializing constructor
EDM4hepFileReader(const std::string& nam);

/// Read parameters set for this action
andresailer marked this conversation as resolved.
Show resolved Hide resolved
virtual EventReaderStatus setParameters(std::map< std::string, std::string >& parameters);

/// Read an event and fill a vector of MCParticles.
virtual EventReaderStatus readParticles(int event_number, Vertices& vertices, std::vector<Particle*>& particles);
/// Call to register the run parameters
void registerRunParameters();

};

/// Initializing constructor
dd4hep::sim::EDM4hepFileReader::EDM4hepFileReader(const std::string& nam)
: Geant4EventReader(nam)
, m_reader(podio::makeReader(nam))
, m_collectionName("MCParticles")
, m_eventHeaderCollectionName("EventHeader")
{
printout(INFO,"EDM4hepFileReader","Created file reader. Try to open input %s",nam.c_str());
m_directAccess = true;
}

void EDM4hepFileReader::registerRunParameters() {
andresailer marked this conversation as resolved.
Show resolved Hide resolved
try {
auto *parameters = new RunParameters();
try {
podio::Frame runFrame = m_reader.readFrame("runs", 0);
andresailer marked this conversation as resolved.
Show resolved Hide resolved
parameters->ingestParameters(runFrame.getParameters());
} catch (std::runtime_error& e) {
// we ignore if we do not have runs information
} catch(std::invalid_argument&) {
// we ignore if we do not have runs information
}
context()->run().addExtension<RunParameters>(parameters);
} catch(std::exception &e) {
printout(ERROR,"EDM4hepFileReader::registerRunParameters","Failed to register run parameters: %s", e.what());
}

try {
auto *fileParameters = new FileParameters();
try {
podio::Frame metaFrame = m_reader.readFrame("metadata", 0);
fileParameters->ingestParameters(metaFrame.getParameters());
} catch (std::runtime_error& e) {
// we ignore if we do not have metadata information
} catch(std::invalid_argument&) {
// we ignore if we do not have metadata information
}
context()->run().addExtension<FileParameters>(fileParameters);
} catch(std::exception &e) {
printout(ERROR,"EDM4hepFileReader::registerRunParameters","Failed to register file parameters: %s", e.what());
}
}

namespace {
/// Helper function to look up MCParticles from mapping
inline int GET_ENTRY(MCPARTICLE_MAP const& mcparts, int partID) {
MCPARTICLE_MAP::const_iterator ip = mcparts.find(partID);
if ( ip == mcparts.end() ) {
throw std::runtime_error("Unknown particle identifier look-up!");
}
return (*ip).second;
}
}

/// Read an event and fill a vector of MCParticles
EDM4hepFileReader::EventReaderStatus
EDM4hepFileReader::readParticles(int event_number, Vertices& vertices, std::vector<Particle*>& particles) {
m_currEvent = event_number;
podio::Frame frame = m_reader.readFrame("events", event_number);
andresailer marked this conversation as resolved.
Show resolved Hide resolved
const auto& primaries = frame.get<edm4hep::MCParticleCollection>(m_collectionName);
int eventNumber = event_number, runNumber = 0;
if (primaries.isValid()) {
//Read the event header collection and add it to the context as an extension
const auto& eventHeaderCollection = frame.get<edm4hep::EventHeaderCollection>(m_eventHeaderCollectionName);
if(eventHeaderCollection.isValid() && eventHeaderCollection.size() == 1){
const auto& eh = eventHeaderCollection.at(0);
eventNumber = eh.getEventNumber();
runNumber = eh.getRunNumber();
try {
Geant4Context* ctx = context();
ctx->event().addExtension<edm4hep::MutableEventHeader>(new edm4hep::MutableEventHeader(eh.clone()));
} catch(std::exception& ) {}
// Create input event parameters context
try {
Geant4Context* ctx = context();
EventParameters *parameters = new EventParameters();
parameters->setRunNumber(runNumber);
parameters->setEventNumber(eventNumber);
parameters->ingestParameters(frame.getParameters());
ctx->event().addExtension<EventParameters>(parameters);
} catch(std::exception &) {}
} else {
printout(WARNING,"EDM4hepFileReader","No EventHeader collection found or too many event headers!");
try {
Geant4Context* ctx = context();
EventParameters *parameters = new EventParameters();
parameters->setRunNumber(0);
parameters->setEventNumber(event_number);
parameters->ingestParameters(frame.getParameters());
ctx->event().addExtension<EventParameters>(parameters);
} catch(std::exception &) {}
}
printout(INFO,"EDM4hepFileReader","read collection %s from event %d in run %d ",
m_collectionName.c_str(), eventNumber, runNumber);

} else {
return EVENT_READER_EOF;
}

printout(INFO,"EDM4hepFileReader", "We read the particle collection");
int NHEP = primaries.size();
// check if there is at least one particle
if ( NHEP == 0 ) {
printout(WARNING,"EDM4hepFileReader", "We have no particles");
return EVENT_READER_NO_PRIMARIES;
}

MCPARTICLE_MAP mcparts;
std::vector<int> mcpcoll;
mcpcoll.resize(NHEP);
andresailer marked this conversation as resolved.
Show resolved Hide resolved
for(int i=0; i<NHEP; ++i ) {
edm4hep::MCParticle p = primaries.at(i);
mcparts[p.getObjectID().index] = i;
mcpcoll[i] = p.getObjectID().index;
andresailer marked this conversation as resolved.
Show resolved Hide resolved
}

// build collection of MCParticles
for(int i=0; i<NHEP; ++i ) {
const auto& mcp = primaries.at(i);
Geant4ParticleHandle p(new Particle(i));
const auto mom = mcp.getMomentum();
const auto vsx = mcp.getVertex();
const auto vex = mcp.getEndpoint();
const auto spin = mcp.getSpin();
const int pdg = mcp.getPDG();
p->pdgID = pdg;
p->charge = int(mcp.getCharge()*3.0);
p->psx = mom[0]*CLHEP::GeV;
p->psy = mom[1]*CLHEP::GeV;
p->psz = mom[2]*CLHEP::GeV;
p->time = mcp.getTime()*CLHEP::ns;
p->properTime = mcp.getTime()*CLHEP::ns;
p->vsx = vsx[0]*CLHEP::mm;
p->vsy = vsx[1]*CLHEP::mm;
p->vsz = vsx[2]*CLHEP::mm;
p->vex = vex[0]*CLHEP::mm;
p->vey = vex[1]*CLHEP::mm;
p->vez = vex[2]*CLHEP::mm;
p->process = 0;
p->spin[0] = spin[0];
p->spin[1] = spin[1];
p->spin[2] = spin[2];
p->colorFlow[0] = 0;
p->colorFlow[1] = 0;
andresailer marked this conversation as resolved.
Show resolved Hide resolved
p->mass = mcp.getMass()*CLHEP::GeV;
const auto par = mcp.getParents(), &dau=mcp.getDaughters();
for(int num=dau.size(),k=0; k<num; ++k) {
edm4hep::MCParticle dau_k = dau[k];
p->daughters.insert(GET_ENTRY(mcparts,dau_k.getObjectID().index));
}
for(int num=par.size(),k=0; k<num; ++k) {
auto par_k = par[k];
p->parents.insert(GET_ENTRY(mcparts, par_k.getObjectID().index));
}

PropertyMask status(p->status);
int genStatus = mcp.getGeneratorStatus();
// Copy raw generator status
p->genStatus = genStatus&G4PARTICLE_GEN_STATUS_MASK;
if(m_inputAction) {
// in some tests we do not set up the inputAction
m_inputAction->setGeneratorStatus(genStatus, status);
}

//fg: we simply add all particles without parents as with their own vertex.
// This might include the incoming beam particles, e.g. in
// the case of lcio files written with Whizard2, which is slightly odd,
// however should be treated correctly in Geant4InputHandling.cpp.
// We no longer make an attempt to identify the incoming particles
// based on the generator status, as this varies widely with different
// generators.

if ( p->parents.size() == 0 ) {

Geant4Vertex* vtx = new Geant4Vertex ;
vertices.emplace_back( vtx );
vtx->x = p->vsx;
vtx->y = p->vsy;
vtx->z = p->vsz;
vtx->time = p->time;

vtx->out.insert(p->id) ;
}

if ( mcp.isCreatedInSimulation() ) status.set(G4PARTICLE_SIM_CREATED);
if ( mcp.isBackscatter() ) status.set(G4PARTICLE_SIM_BACKSCATTER);
if ( mcp.vertexIsNotEndpointOfParent() ) status.set(G4PARTICLE_SIM_PARENT_RADIATED);
if ( mcp.isDecayedInTracker() ) status.set(G4PARTICLE_SIM_DECAY_TRACKER);
if ( mcp.isDecayedInCalorimeter() ) status.set(G4PARTICLE_SIM_DECAY_CALO);
if ( mcp.hasLeftDetector() ) status.set(G4PARTICLE_SIM_LEFT_DETECTOR);
if ( mcp.isStopped() ) status.set(G4PARTICLE_SIM_STOPPED);
if ( mcp.isOverlay() ) status.set(G4PARTICLE_SIM_OVERLAY);
particles.emplace_back(p);
}
return EVENT_READER_OK;
}

/// Set the parameters for the class, in particular the name of the MCParticle
/// list
Geant4EventReader::EventReaderStatus
dd4hep::sim::EDM4hepFileReader::setParameters( std::map< std::string, std::string > & parameters ) {
_getParameterValue(parameters, "MCParticleCollectionName", m_collectionName, m_collectionName);
_getParameterValue(parameters, "EventHeaderCollectionName", m_eventHeaderCollectionName, m_eventHeaderCollectionName);
return EVENT_READER_OK;
}

} //end dd4hep::sim

DECLARE_GEANT4_EVENT_READER_NS(dd4hep::sim,EDM4hepFileReader)
Loading
Loading