diff --git a/DDDigi/include/DDDigi/DigiData.h b/DDDigi/include/DDDigi/DigiData.h index d7ae0215f772236f13be3ba3c26b4f6e5a3d886c..3ec987f15dff063fef764e33db20fa7a602b805b 100644 --- a/DDDigi/include/DDDigi/DigiData.h +++ b/DDDigi/include/DDDigi/DigiData.h @@ -873,6 +873,84 @@ namespace dd4hep { } typedef DetectorHistory DepositsHistory; + /// Detector history vector definition for digitization + /** + * + * \author M.Frank + * \version 1.0 + * \ingroup DD4HEP_DIGITIZATION + */ + class DataParameters : public SegmentEntry { + public: + template <typename T> using map_type_t = std::map<std::string, std::vector<T> >; + struct header_data { + map_type_t<std::string> stringParams; + map_type_t<float> floatParams; + map_type_t<int> intParams; + std::int32_t run_number { -1 }; + std::int32_t event_number { -1 }; + std::int64_t time_stamp { 0 }; + double event_weight { 0e0 }; + }; + std::shared_ptr<header_data> data; + public: + /// Initializing constructor + DataParameters(const std::string& name, Key::mask_type mask); + /// Default constructor + DataParameters() = default; + /// Disable move constructor + DataParameters(DataParameters&& copy) = default; + /// Disable copy constructor + DataParameters(const DataParameters& copy) = default; + /// Default destructor + virtual ~DataParameters() = default; + /// Disable move assignment + DataParameters& operator=(DataParameters&& copy) = default; + /// Disable copy assignment + DataParameters& operator=(const DataParameters& copy) = default; + /// Access data size + std::size_t size() const; + /// Access the event number + std::int32_t getEventNumber() const { + return data->event_number; + } + /// Access the run number + std::int32_t getRunNumber() const { + return data->run_number; + } + /// Access the time stamp + std::uint64_t getTimeStamp() const { + return data->time_stamp; + } + /// Access the event weight + float getWeight() const { + return data->event_weight; + } + /// Set the event number + void setEventNumber(std::int32_t value) { + data->event_number = value; + } + /// Set the run number + void setRunNumber(std::int32_t value) { + data->run_number = value; + } + /// Set the time stamp + void setTimeStamp(std::uint64_t value) { + data->time_stamp = value; + } + /// Set the event weight + void setWeight(float value) { + data->event_weight = value; + } + }; + + /// Initializing constructor + inline DataParameters::DataParameters(const std::string& nam, Key::mask_type msk) + : SegmentEntry(nam, msk, SegmentEntry::HISTORY) + { + this->data = std::make_shared<header_data>(); + } + /// Data segment definition (locked map) /** @@ -1007,8 +1085,9 @@ namespace dd4hep { /// Helper to place data to data segment template <typename KEY, typename DATA> - bool put_data(DataSegment& segment, KEY key, DATA& data) { - return segment.emplace_any(key, std::any(data)); + bool put_data(DataSegment& segment, KEY key, DATA&& value) { + std::any item = std::make_any<DATA>(std::move(value)); + return segment.emplace_any(key, std::move(item)); } /// User event data for DDDigi diff --git a/DDDigi/io/DigiEdm4hepInput.cpp b/DDDigi/io/DigiEdm4hepInput.cpp index 464951b1fc28bd8531bc33fff85ce5fd28b9d440..fed8075e9c4125f768fce8e147451411a9229a11 100644 --- a/DDDigi/io/DigiEdm4hepInput.cpp +++ b/DDDigi/io/DigiEdm4hepInput.cpp @@ -12,104 +12,18 @@ //========================================================================== // Framework include files -#include <DDDigi/DigiInputAction.h> -#include <DDDigi/DigiData.h> +#include "DigiEdm4hepInput.h" #include "DigiIO.h" -/// Forward declarations -namespace podio { class CollectionBase; } - -/// Namespace for the AIDA detector description toolkit -namespace dd4hep { - - /// Namespace for the Digitization part of the AIDA detector description toolkit - namespace digi { - - /// EDM4HEP Digi input reader - /** - * - * \author M.Frank - * \version 1.0 - * \ingroup DD4HEP_DIGITIZATION - */ - class DigiEdm4hepInput : public DigiInputAction { - public: - static constexpr double epsilon = std::numeric_limits<double>::epsilon(); - - /// Forward declarations - class internals_t; - class work_t; - class source_t; - class collection_t; - using podio_coll_t = const podio::CollectionBase; - using descriptor_t = std::pair<const Key, collection_t>; - - /// Reference to internal data - std::unique_ptr<internals_t> internals; - /// Type of tracker hit container - std::string m_trackerHitType { }; - /// Type of calorimenter hit container - std::string m_caloHitType { }; - /// Type of particles container - std::string m_particlesType { }; - - public: - /// Initializing constructor - DigiEdm4hepInput(const DigiKernel& krnl, const std::string& nam); - - /// Generic conversion function for hits - template <typename T, typename COLL> - void from_edm4hep(DigiContext& context, - DataSegment& segment, - Key::mask_type mask, - const std::string& nam, - const COLL* collection) const - { - DepositVector out(nam, mask, SegmentEntry::UNKNOWN); - std::map<CellID, T> hits; - std::size_t len = 0; - const DepositPredicate<EnergyCut> predicate ( { this->epsilon } ); - len = collection->size(); - data_io<edm4hep_input>()._to_digi_if(*collection, hits, predicate); - data_io<edm4hep_input>()._to_digi(Key(nam, segment.id, mask), hits, out); - info("%s+++ %-24s Converted %6ld Edm4hep %-14s to %6ld cell deposits", - context.event->id(), nam.c_str(), len, collection->getValueTypeName().c_str(), out.size()); - put_data(segment, Key(out.name, mask), out); - if ( m_keep_raw ) { - put_data(segment, Key(nam+".edm4hep", mask, segment.id), hits); - } - } - - /// Generic conversion function for MC particles - template <typename COLL> - void from_edm4hep(DigiContext& context, - DataSegment& segment, - int mask, - const std::string& nam, - const COLL* collection) const - { - ParticleMapping particles(nam, mask); - data_io<edm4hep_input>()._to_digi(Key(nam, segment.id, mask), *collection, particles); - debug("%s+++ Converted %ld Edm4hep particles", context.event->id(), particles.size()); - put_data(segment, Key(nam, mask), particles); - } - - /// Callback to handle single branch - virtual void operator()(DigiContext& context, work_t& work) const; - /// Event action callback - virtual void execute(DigiContext& context) const override; - }; - } // End namespace digi -} // End namespace dd4hep - -//#include <podio/Frame.h> +// podio/edm4hep include files #include "DigiFrame.h" +//#include <podio/Frame.h> #include <podio/ROOTFrameReader.h> #include <edm4hep/SimTrackerHit.h> #include <edm4hep/SimCalorimeterHit.h> #include <edm4hep/MCParticleCollection.h> -#include <edm4hep/SimTrackerHitCollection.h> #include <edm4hep/EventHeaderCollection.h> +#include <edm4hep/SimTrackerHitCollection.h> #include <edm4hep/SimCalorimeterHitCollection.h> #include <edm4hep/CaloHitContributionCollection.h> @@ -132,9 +46,10 @@ namespace dd4hep { edm4hep_read_frame_t(podio::Frame&& frm) : frame(std::move(frm)) { } const podio::CollectionBase* get(const std::string& nam) const { return frame.self()->get(nam); } }; + using reader_t = podio::ROOTFrameReader; using frame_t = edm4hep_read_frame_t; - + /// EDM4HEP Digi input reader: Collection descriptor definition /** * @@ -158,10 +73,11 @@ namespace dd4hep { */ class DigiEdm4hepInput::work_t { public: - DigiContext& context; - descriptor_t& descriptor; - DataSegment& segment; - podio_coll_t* collection; + DigiContext& context; + DataSegment& segment; + frame_t& frame; + descriptor_t& descriptor; + podio_coll_t* collection; }; /// EDM4HEP Digi input reader: Input source definition @@ -224,7 +140,7 @@ namespace dd4hep { using input_t = std::unique_ptr<source_t>; /// Reference to the parent object - DigiEdm4hepInput* m_parent { nullptr }; + DigiEdm4hepInput* parent { nullptr }; /// Handle to input source input_t m_source { }; /// Pointer to current input source @@ -232,70 +148,64 @@ namespace dd4hep { public: /// Initializing constructor - internals_t(DigiEdm4hepInput* parent); + internals_t() = default; /// Open the next input source from the input list std::unique_ptr<source_t> open_source(); /// Access the next event from the sequence of input files std::shared_ptr<frame_t> next(); }; - /// Initializing constructor - DigiEdm4hepInput::internals_t::internals_t(DigiEdm4hepInput* parent) - : m_parent(parent) - { - } - /// Open the next input source from the input list std::unique_ptr<DigiEdm4hepInput::source_t> DigiEdm4hepInput::internals_t::open_source() { - const auto& inputs = m_parent->inputs(); + const auto& inputs = parent->inputs(); int len = inputs.size(); if ( inputs.empty() ) m_curr_input = 0; while ( (m_curr_input+1) < len ) { const auto& fname = inputs[++m_curr_input]; auto stream = std::make_unique<reader_t>(); try { - auto sec = m_parent->input_section(); + auto sec = parent->input_section(); stream->openFile(fname); auto source = std::make_unique<source_t>(sec, std::move(stream)); - m_parent->info("+++ Opened EDM4HEP input file %s.", fname.c_str()); - m_parent->onOpenFile(*source); + parent->info("+++ Opened EDM4HEP input file %s.", fname.c_str()); + parent->onOpenFile(*source); return source; } catch (const std::runtime_error& e) { - m_parent->error("OpenInput ++ Failed to open input source %s [%s]", fname.c_str(), e.what()); + parent->error("OpenInput ++ Failed to open input source %s [%s]", fname.c_str(), e.what()); } } - m_parent->except("+++ No open file present. Configuration error?"); + parent->except("+++ No open file present. Configuration error?"); throw std::runtime_error("+++ No open file present"); } /// Access the next event record. If the courrent source is exhausted, open next source std::shared_ptr<frame_t> DigiEdm4hepInput::internals_t::next() { - if ( !m_source || m_source->done() || m_parent->fileLimitReached(*m_source) ) { + if ( !m_source || m_source->done() || parent->fileLimitReached(*m_source) ) { m_source = open_source(); if ( m_source ) { auto frame = m_source->next(); if ( frame ) { auto table = frame->frame.getAvailableCollections(); - int id = 0, mask = m_parent->input_mask(); + int id = 0, mask = parent->input_mask(); for( const auto& nam : table ) { - m_parent->info("+++ Collection id: %04X --> '%s'", id, nam.c_str()); - if ( m_parent->object_loading_is_enabled(nam) ) { + parent->info("+++ Collection id: %04X --> '%s'", id, nam.c_str()); + if ( parent->object_loading_is_enabled(nam) ) { Key key(nam, mask); m_source->collections.emplace( key, collection_t(id, nam) ); } ++id; } - m_parent->onProcessEvent(*m_source, *frame); + parent->onProcessEvent(*m_source, *frame); return frame; } - m_parent->except("+++ No valid frame present in file."); + parent->except("+++ No valid frame present in file."); } - m_parent->except("+++ No open file present. Aborting processing"); + parent->except("+++ No open file present. Aborting processing"); } auto frame = m_source->next(); - m_parent->onProcessEvent(*m_source, *frame); + parent->onProcessEvent(*m_source, *frame); return frame; } @@ -303,16 +213,69 @@ namespace dd4hep { DigiEdm4hepInput::DigiEdm4hepInput(const DigiKernel& krnl, const std::string& nam) : DigiInputAction(krnl, nam) { - internals = std::make_unique<internals_t>(this); - m_trackerHitType = typeName(typeid(edm4hep::SimTrackerHitCollection)); - m_caloHitType = typeName(typeid(edm4hep::SimCalorimeterHitCollection)); - m_particlesType = typeName(typeid(edm4hep::MCParticleCollection)); + internals = std::make_unique<internals_t>(); + internals->parent = this; + m_trackerHitType = typeName(typeid(edm4hep::SimTrackerHitCollection)); + m_caloHitType = typeName(typeid(edm4hep::SimCalorimeterHitCollection)); + m_particlesType = typeName(typeid(edm4hep::MCParticleCollection)); + m_evtHeaderType = typeName(typeid(edm4hep::EventHeaderCollection)); declareProperty("tracker_hits_type", m_trackerHitType); declareProperty("calorimeter_hits_type", m_caloHitType); declareProperty("particles_hits_type", m_particlesType); + declareProperty("event_header_type", m_evtHeaderType); m_input_section = "events"; } + template <typename HIT_TYPE, typename EDM4HEP_COLLECTION_TYPE> + void DigiEdm4hepInput::hits_from_edm4hep(DigiContext& context, + DataSegment& segment, + Key::mask_type mask, + const std::string& nam, + const EDM4HEP_COLLECTION_TYPE* collection) const + { + DepositVector out(nam, mask, SegmentEntry::UNKNOWN); + std::map<CellID, HIT_TYPE> hits; + std::size_t len = 0; + const DepositPredicate<EnergyCut> predicate ( { this->epsilon } ); + len = collection->size(); + data_io<edm4hep_input>()._to_digi_if(*collection, hits, predicate); + data_io<edm4hep_input>()._to_digi(Key(nam, segment.id, mask), hits, out); + info("%s+++ %-24s Converted %6ld Edm4hep %-14s to %6ld cell deposits", + context.event->id(), nam.c_str(), len, collection->getValueTypeName().c_str(), out.size()); + put_data(segment, Key(out.name, mask), std::move(out)); + if ( m_keep_raw ) { + put_data(segment, Key(nam+".edm4hep", mask, segment.id), std::move(hits)); + } + } + + /// Generic conversion function for MC particles + void DigiEdm4hepInput::parts_from_edm4hep(DigiContext& context, + DataSegment& segment, + int mask, + const std::string& nam, + const edm4hep::MCParticleCollection* collection) const + { + ParticleMapping transient(nam, mask); + data_io<edm4hep_input>()._to_digi(Key(nam, segment.id, mask), *collection, transient); + debug("%s+++ Converted %ld Edm4hep transient", context.event->id(), transient.size()); + put_data(segment, Key(nam, mask), std::move(transient)); + } + + /// Generic conversion function for event parameter settings + void DigiEdm4hepInput::params_from_edm4hep(DigiContext& context, + DataSegment& segment, + int mask, + const std::string& nam, + const podio::Frame& frame, + const edm4hep::EventHeaderCollection* collection) const + { + DataParameters parameters(nam, mask); + data_io<edm4hep_input>()._to_digi(Key(nam, segment.id, mask), *collection, parameters); + data_io<edm4hep_input>()._to_digi(Key(nam, segment.id, mask), frame.getGenericParameters(), parameters); + debug("%s+++ Converted %ld Edm4hep transient", context.event->id(), parameters.size()); + put_data(segment, Key(nam, mask), std::move(parameters)); + } + /// Pre-track action callback void DigiEdm4hepInput::execute(DigiContext& context) const { // Lock all ROOT based actions. SEGV otherwise. @@ -325,7 +288,7 @@ namespace dd4hep { const auto& nam = coll.second.name; const podio::CollectionBase* collection = frame->get(nam); if ( collection ) { - work_t work { context, coll, segment, collection }; + work_t work { context, segment, *frame, coll, collection }; (*this)(context, work); continue; } @@ -347,15 +310,16 @@ namespace dd4hep { const auto& typ = col->getTypeName(); if ( typ == m_caloHitType ) - from_edm4hep<edm4hep::SimCalorimeterHit>(context, seg, msk, nam, static_cast<const edm4hep::SimCalorimeterHitCollection*>(col)); + hits_from_edm4hep<edm4hep::SimCalorimeterHit>(context, seg, msk, nam, static_cast<const edm4hep::SimCalorimeterHitCollection*>(col)); else if ( typ == m_trackerHitType ) - from_edm4hep<edm4hep::SimTrackerHit>(context, seg, msk, nam, static_cast<const edm4hep::SimTrackerHitCollection*>(col)); + hits_from_edm4hep<edm4hep::SimTrackerHit>(context, seg, msk, nam, static_cast<const edm4hep::SimTrackerHitCollection*>(col)); else if ( typ == m_particlesType ) - from_edm4hep(context, seg, msk, nam, static_cast<const edm4hep::MCParticleCollection*>(col)); + parts_from_edm4hep(context, seg, msk, nam, static_cast<const edm4hep::MCParticleCollection*>(col)); + else if ( typ == m_evtHeaderType ) + params_from_edm4hep(context, seg, msk, nam, work.frame.frame, static_cast<const edm4hep::EventHeaderCollection*>(col)); else except("Unknown data type encountered in branch: %s", nam.c_str()); } - } // End namespace digi } // End namespace dd4hep diff --git a/DDDigi/io/DigiEdm4hepInput.h b/DDDigi/io/DigiEdm4hepInput.h new file mode 100644 index 0000000000000000000000000000000000000000..e80105cbf43f27674295fc56698c6224ab92a16c --- /dev/null +++ b/DDDigi/io/DigiEdm4hepInput.h @@ -0,0 +1,104 @@ +//========================================================================== +// 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 : M.Frank +// +//========================================================================== +#ifndef DD4HEP_DDDIGI_DIGIEDM4HEPINPUT_H +#define DD4HEP_DDDIGI_DIGIEDM4HEPINPUT_H + +// Framework include files +#include <DDDigi/DigiInputAction.h> +#include <DDDigi/DigiData.h> + +/// Forward declarations +namespace edm4hep { + class EventHeaderCollection; + class MCParticleCollection; +} +namespace podio { + class CollectionBase; + class Frame; +} + +/// Namespace for the AIDA detector description toolkit +namespace dd4hep { + + /// Namespace for the Digitization part of the AIDA detector description toolkit + namespace digi { + + /// Forward declarations + class DataSegment; + class DataContext; + + /// EDM4HEP Digi input reader + /** + * + * \author M.Frank + * \version 1.0 + * \ingroup DD4HEP_DIGITIZATION + */ + class DigiEdm4hepInput : public DigiInputAction { + public: + static constexpr double epsilon = std::numeric_limits<double>::epsilon(); + + /// Forward declarations + class internals_t; + class work_t; + class source_t; + class collection_t; + using podio_coll_t = const podio::CollectionBase; + using descriptor_t = std::pair<const Key, collection_t>; + + /// Reference to internal data + std::unique_ptr<internals_t> internals; + /// Type of tracker hit container + std::string m_trackerHitType { }; + /// Type of calorimenter hit container + std::string m_caloHitType { }; + /// Type of particles container + std::string m_particlesType { }; + /// Type of event header container + std::string m_evtHeaderType { }; + + public: + /// Initializing constructor + DigiEdm4hepInput(const DigiKernel& krnl, const std::string& nam); + + /// Generic conversion function for hits + template <typename HIT_TYPE, typename EDM4HEP_COLLECTION_TYPE> + void hits_from_edm4hep(DigiContext& context, + DataSegment& segment, + Key::mask_type mask, + const std::string& nam, + const EDM4HEP_COLLECTION_TYPE* collection) const; + + /// Generic conversion function for MC particles + void parts_from_edm4hep(DigiContext& context, + DataSegment& segment, + int mask, + const std::string& nam, + const edm4hep::MCParticleCollection* collection) const; + + /// Generic conversion function for event parameter settings + void params_from_edm4hep(DigiContext& context, + DataSegment& segment, + int mask, + const std::string& nam, + const podio::Frame& frame, + const edm4hep::EventHeaderCollection* collection) const; + + /// Callback to handle single branch + virtual void operator()(DigiContext& context, work_t& work) const; + /// Event action callback + virtual void execute(DigiContext& context) const override; + }; + } // End namespace digi +} // End namespace dd4hep +#endif // DD4HEP_DDDIGI_DIGIEDM4HEPINPUT_H diff --git a/DDDigi/io/Digi2edm4hepOutput.cpp b/DDDigi/io/DigiEdm4hepOutput.cpp similarity index 57% rename from DDDigi/io/Digi2edm4hepOutput.cpp rename to DDDigi/io/DigiEdm4hepOutput.cpp index ee42212add4a4df46e6bdfcf1d0da104f99e891b..49575df976649da5e2bc077ec96e88820c99874b 100644 --- a/DDDigi/io/Digi2edm4hepOutput.cpp +++ b/DDDigi/io/DigiEdm4hepOutput.cpp @@ -1,122 +1,3 @@ -//========================================================================== -// 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 : M.Frank -// -//========================================================================== -#ifndef DIGI_DIGI2EDM4HEP_H -#define DIGI_DIGI2EDM4HEP_H - -// Framework include files -#include <DDDigi/DigiOutputAction.h> - -/// C/C++ include files - -namespace edm4hep { - class TrackerHitCollection; - class CalorimeterHitCollection; -} - -/// Namespace for the AIDA detector description toolkit -namespace dd4hep { - - /// Namespace for the Digitization part of the AIDA detector description toolkit - namespace digi { - - /// Event action to support edm4hep output format from DDDigi - /** - * Supported output containers types are: - * - edm4hep::MCParticles aka "MCParticles" - * - edm4hep::CalorimeterHitCollection aka "CalorimeterHits" - * - edm4hep::TrackerHitCollection aka "TracketHits" - * - * \author M.Frank - * \version 1.0 - * \ingroup DD4HEP_DIGITIZATION - */ - class Digi2edm4hepOutput : public DigiOutputAction { - public: - class internals_t; - protected: - /// Reference to internals - std::shared_ptr<internals_t> internals; - - protected: - /// Define standard assignments and constructors - DDDIGI_DEFINE_ACTION_CONSTRUCTORS(Digi2edm4hepOutput); - /// Default destructor - virtual ~Digi2edm4hepOutput(); - - public: - /// Standard constructor - Digi2edm4hepOutput(const kernel_t& kernel, const std::string& nam); - /// Initialization callback - virtual void initialize(); - /// Check for valid output stream - virtual bool have_output() const override final; - /// Open new output stream - virtual void open_output() const override final; - /// Close possible open stream - virtual void close_output() const override final; - /// Commit event data to output stream - virtual void commit_output() const override final; - }; - - /// Actor to save individual data containers to edm4hep - /** Actor to save individual data containers to edm4hep - * - * This is a typical worker action of the Digi2edm4hepOutput - * - * \author M.Frank - * \version 1.0 - * \ingroup DD4HEP_DIGITIZATION - */ - class Digi2edm4hepProcessor : public DigiContainerProcessor { - friend class Digi2edm4hepOutput; - - protected: - /// Reference to the edm4hep engine - std::shared_ptr<Digi2edm4hepOutput::internals_t> internals; - /// Property: RPhi resolution - float m_pointResoutionRPhi = 0.004; - /// Property: Z resolution - float m_pointResoutionZ = 0.004; - /// Hit type for hit processor - int m_hit_type = 0; - - public: - /// Standard constructor - Digi2edm4hepProcessor(const DigiKernel& krnl, const std::string& nam); - - /// Standard destructor - virtual ~Digi2edm4hepProcessor() = default; - - template <typename T> void - convert_depos(const T& cont, const predicate_t& predicate, edm4hep::TrackerHitCollection* collection) const; - - template <typename T> void - convert_depos(const T& cont, const predicate_t& predicate, edm4hep::CalorimeterHitCollection* collection) const; - - template <typename T> void - convert_deposits(DigiContext& context, const T& cont, const predicate_t& predicate) const; - - void convert_history(DigiContext& context, const DepositsHistory& cont, work_t& work, const predicate_t& predicate) const; - - void convert_particles(DigiContext& context, const ParticleMapping& cont) const; - - /// Main functional callback - virtual void execute(DigiContext& context, work_t& work, const predicate_t& predicate) const override final; - }; - } // End namespace digi -} // End namespace dd4hep -#endif // DIGI_DIGI2EDM4HEP_H - //========================================================================== // AIDA Detector description implementation //-------------------------------------------------------------------------- @@ -135,6 +16,7 @@ namespace dd4hep { #include <DDDigi/DigiContext.h> #include <DDDigi/DigiPlugins.h> #include <DDDigi/DigiKernel.h> +#include "DigiEdm4hepOutput.h" #include "DigiIO.h" /// edm4hep include files @@ -161,9 +43,9 @@ namespace dd4hep { * \version 1.0 * \ingroup DD4HEP_DIGITIZATION */ - class Digi2edm4hepOutput::internals_t { + class DigiEdm4hepOutput::internals_t { public: - Digi2edm4hepOutput* m_parent { nullptr }; + DigiEdm4hepOutput* m_parent { nullptr }; /// Reference to podio store std::unique_ptr<podio::EventStore> m_store { }; /// Reference to podio writer @@ -186,7 +68,7 @@ namespace dd4hep { public: /// Default constructor - internals_t(Digi2edm4hepOutput* parent); + internals_t(DigiEdm4hepOutput* parent); /// Default destructor ~internals_t(); @@ -204,18 +86,18 @@ namespace dd4hep { }; /// Default constructor - Digi2edm4hepOutput::internals_t::internals_t(Digi2edm4hepOutput* parent) : m_parent(parent) + DigiEdm4hepOutput::internals_t::internals_t(DigiEdm4hepOutput* parent) : m_parent(parent) { m_store = std::make_unique<podio::EventStore>(); } /// Default destructor - Digi2edm4hepOutput::internals_t::~internals_t() { + DigiEdm4hepOutput::internals_t::~internals_t() { if ( m_file ) close(); m_store.reset(); } - template <typename T> T* Digi2edm4hepOutput::internals_t::register_collection(const std::string& nam, T* coll) { + template <typename T> T* DigiEdm4hepOutput::internals_t::register_collection(const std::string& nam, T* coll) { m_collections.emplace(nam, coll); m_store->registerCollection(nam, coll); m_parent->debug("+++ created collection %s <%s>", nam.c_str(), coll->getTypeName().c_str()); @@ -223,7 +105,7 @@ namespace dd4hep { } /// Create all collections according to the parent setup - void Digi2edm4hepOutput::internals_t::create_collections() { + void DigiEdm4hepOutput::internals_t::create_collections() { if ( nullptr == m_header ) { m_header = register_collection("EventHeader", new edm4hep::EventHeaderCollection()); for( auto& cont : m_parent->m_containers ) { @@ -245,7 +127,7 @@ namespace dd4hep { /// Access named collection: throws exception ifd the collection is not present template <typename T> - podio::CollectionBase* Digi2edm4hepOutput::internals_t::get_collection(const T& cont) { + podio::CollectionBase* DigiEdm4hepOutput::internals_t::get_collection(const T& cont) { auto iter = m_collections.find(cont.name); if ( iter == m_collections.end() ) { m_parent->except("Error"); @@ -254,7 +136,7 @@ namespace dd4hep { } /// Commit data at end of filling procedure - void Digi2edm4hepOutput::internals_t::commit() { + void DigiEdm4hepOutput::internals_t::commit() { if ( m_file ) { m_file->writeEvent(); m_store->clearCollections(); @@ -264,7 +146,7 @@ namespace dd4hep { } /// Open new output stream - void Digi2edm4hepOutput::internals_t::open() { + void DigiEdm4hepOutput::internals_t::open() { if ( m_file ) { close(); } @@ -272,13 +154,13 @@ namespace dd4hep { std::string fname = m_parent->next_stream_name(); m_file = std::make_unique<podio::ROOTWriter>(fname, m_store.get()); m_parent->info("+++ Opened EDM4HEP output file %s", fname.c_str()); - for( const auto& c : m_collections ) { + for( const auto& c : m_collections ) { m_file->registerForWrite(c.first); } } /// Commit data to disk and close output stream - void Digi2edm4hepOutput::internals_t::close() { + void DigiEdm4hepOutput::internals_t::close() { m_parent->info("+++ Closing EDM4HEP output file."); if ( m_file ) { m_file->finish(); @@ -287,7 +169,7 @@ namespace dd4hep { } /// Standard constructor - Digi2edm4hepOutput::Digi2edm4hepOutput(const DigiKernel& krnl, const std::string& nam) + DigiEdm4hepOutput::DigiEdm4hepOutput(const DigiKernel& krnl, const std::string& nam) : DigiOutputAction(krnl, nam) { internals = std::make_shared<internals_t>(this); @@ -295,16 +177,16 @@ namespace dd4hep { } /// Default destructor - Digi2edm4hepOutput::~Digi2edm4hepOutput() { + DigiEdm4hepOutput::~DigiEdm4hepOutput() { internals.reset(); InstanceCount::decrement(this); } /// Initialization callback - void Digi2edm4hepOutput::initialize() { + void DigiEdm4hepOutput::initialize() { this->DigiOutputAction::initialize(); for ( auto& c : m_registered_processors ) { - auto* act = dynamic_cast<Digi2edm4hepProcessor*>(c.second); + auto* act = dynamic_cast<DigiEdm4hepOutputProcessor*>(c.second); if ( act ) { // This is not nice! Need to think about something better. act->internals = this->internals; continue; @@ -316,27 +198,27 @@ namespace dd4hep { } /// Check for valid output stream - bool Digi2edm4hepOutput::have_output() const { + bool DigiEdm4hepOutput::have_output() const { return internals->m_file.get() != nullptr; } /// Open new output stream - void Digi2edm4hepOutput::open_output() const { + void DigiEdm4hepOutput::open_output() const { internals->open(); } /// Close possible open stream - void Digi2edm4hepOutput::close_output() const { + void DigiEdm4hepOutput::close_output() const { internals->close(); } /// Commit event data to output stream - void Digi2edm4hepOutput::commit_output() const { + void DigiEdm4hepOutput::commit_output() const { internals->commit(); } /// Standard constructor - Digi2edm4hepProcessor::Digi2edm4hepProcessor(const DigiKernel& krnl, const std::string& nam) + DigiEdm4hepOutputProcessor::DigiEdm4hepOutputProcessor(const DigiKernel& krnl, const std::string& nam) : DigiContainerProcessor(krnl, nam) { declareProperty("point_resolution_RPhi", m_pointResoutionRPhi); @@ -344,8 +226,8 @@ namespace dd4hep { declareProperty("hit_type", m_hit_type = 0); } - void Digi2edm4hepProcessor::convert_particles(DigiContext& ctxt, - const ParticleMapping& cont) const + void DigiEdm4hepOutputProcessor::convert_particles(DigiContext& ctxt, + const ParticleMapping& cont) const { auto* coll = internals->m_particles; std::size_t start = coll->size(); @@ -357,12 +239,12 @@ namespace dd4hep { } template <typename T> void - Digi2edm4hepProcessor::convert_depos(const T& cont, - const predicate_t& predicate, - edm4hep::TrackerHitCollection* collection) const + DigiEdm4hepOutputProcessor::convert_depos(const T& cont, + const predicate_t& predicate, + edm4hep::TrackerHitCollection* collection) const { std::array<float,6> covMat = {0., 0., m_pointResoutionRPhi*m_pointResoutionRPhi, - 0., 0., m_pointResoutionZ*m_pointResoutionZ + 0., 0., m_pointResoutionZ*m_pointResoutionZ }; for ( const auto& depo : cont ) { if ( predicate(depo) ) { @@ -372,9 +254,9 @@ namespace dd4hep { } template <typename T> void - Digi2edm4hepProcessor::convert_depos(const T& cont, - const predicate_t& predicate, - edm4hep::CalorimeterHitCollection* collection) const + DigiEdm4hepOutputProcessor::convert_depos(const T& cont, + const predicate_t& predicate, + edm4hep::CalorimeterHitCollection* collection) const { for ( const auto& depo : cont ) { if ( predicate(depo) ) { @@ -384,9 +266,9 @@ namespace dd4hep { } template <typename T> void - Digi2edm4hepProcessor::convert_deposits(DigiContext& ctxt, - const T& cont, - const predicate_t& predicate) const + DigiEdm4hepOutputProcessor::convert_deposits(DigiContext& ctxt, + const T& cont, + const predicate_t& predicate) const { podio::CollectionBase* coll = internals->get_collection(cont); std::size_t start = coll->size(); @@ -409,10 +291,10 @@ namespace dd4hep { coll->getTypeName().c_str()); } - void Digi2edm4hepProcessor::convert_history(DigiContext& ctxt, - const DepositsHistory& cont, - work_t& work, - const predicate_t& predicate) const + void DigiEdm4hepOutputProcessor::convert_history(DigiContext& ctxt, + const DepositsHistory& cont, + work_t& work, + const predicate_t& predicate) const { info("%s+++ %-32s Segment: %d Predicate:%s Conversion to edm4hep not implemented!", ctxt.event->id(), cont.name.c_str(), int(work.input.segment->id), @@ -420,7 +302,7 @@ namespace dd4hep { } /// Main functional callback - void Digi2edm4hepProcessor::execute(DigiContext& ctxt, work_t& work, const predicate_t& predicate) const { + void DigiEdm4hepOutputProcessor::execute(DigiContext& ctxt, work_t& work, const predicate_t& predicate) const { if ( const auto* p = work.get_input<ParticleMapping>() ) convert_particles(ctxt, *p); else if ( const auto* m = work.get_input<DepositMapping>() ) @@ -438,5 +320,5 @@ namespace dd4hep { /// Factory instantiation: #include <DDDigi/DigiFactories.h> -DECLARE_DIGIACTION_NS(dd4hep::digi,Digi2edm4hepOutput) -DECLARE_DIGIACTION_NS(dd4hep::digi,Digi2edm4hepProcessor) +DECLARE_DIGIACTION_NS(dd4hep::digi,DigiEdm4hepOutput) +DECLARE_DIGIACTION_NS(dd4hep::digi,DigiEdm4hepOutputProcessor) diff --git a/DDDigi/io/DigiEdm4hepOutput.h b/DDDigi/io/DigiEdm4hepOutput.h new file mode 100644 index 0000000000000000000000000000000000000000..09998b70f4b3b336bd506dd718cd36a4b1429723 --- /dev/null +++ b/DDDigi/io/DigiEdm4hepOutput.h @@ -0,0 +1,127 @@ +//========================================================================== +// 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 : M.Frank +// +//========================================================================== +#ifndef DIGI_DIGIEDM4HEPOUTPUT_H +#define DIGI_DIGIEDM4HEPOUTPUT_H + +// Framework include files +#include <DDDigi/DigiOutputAction.h> + +/// C/C++ include files + +/// Forward declarations from edm4hep +namespace edm4hep { + class TrackerHitCollection; + class CalorimeterHitCollection; +} + +/// Namespace for the AIDA detector description toolkit +namespace dd4hep { + + /// Namespace for the Digitization part of the AIDA detector description toolkit + namespace digi { + + /// Event action to support edm4hep output format from DDDigi + /** + * Supported output containers types are: + * - edm4hep::MCParticles aka "MCParticles" + * - edm4hep::CalorimeterHitCollection aka "CalorimeterHits" + * - edm4hep::TrackerHitCollection aka "TracketHits" + * + * This entity actually is only the work dispatcher: + * It opens files and dumps data into + * + * \author M.Frank + * \version 1.0 + * \ingroup DD4HEP_DIGITIZATION + */ + class DigiEdm4hepOutput : public DigiOutputAction { + public: + class internals_t; + protected: + /// Reference to internals + std::shared_ptr<internals_t> internals; + + protected: + /// Define standard assignments and constructors + DDDIGI_DEFINE_ACTION_CONSTRUCTORS(DigiEdm4hepOutput); + /// Default destructor + virtual ~DigiEdm4hepOutput(); + + public: + /// Standard constructor + DigiEdm4hepOutput(const kernel_t& kernel, const std::string& nam); + /// Initialization callback + virtual void initialize(); + /// Check for valid output stream + virtual bool have_output() const override final; + /// Open new output stream + virtual void open_output() const override final; + /// Close possible open stream + virtual void close_output() const override final; + /// Commit event data to output stream + virtual void commit_output() const override final; + }; + + /// Actor to save individual data containers to edm4hep + /** The processor is the actual unit doing the work. + * + * This is a typical worker action of the DigiEdm4hepOutput + * + * \author M.Frank + * \version 1.0 + * \ingroup DD4HEP_DIGITIZATION + */ + class DigiEdm4hepOutputProcessor : public DigiContainerProcessor { + friend class DigiEdm4hepOutput; + + protected: + /// Reference to the edm4hep engine + std::shared_ptr<DigiEdm4hepOutput::internals_t> internals; + /// Property: RPhi resolution + float m_pointResoutionRPhi = 0.004; + /// Property: Z resolution + float m_pointResoutionZ = 0.004; + /// Hit type for hit processor + int m_hit_type = 0; + + public: + /// Standard constructor + DigiEdm4hepOutputProcessor(const DigiKernel& krnl, const std::string& nam); + + /// Standard destructor + virtual ~DigiEdm4hepOutputProcessor() = default; + + /// Convert tracker hits to edm4hep + template <typename T> void + convert_depos(const T& cont, const predicate_t& predicate, edm4hep::TrackerHitCollection* collection) const; + + /// Convert calorimeter hits to edm4hep + template <typename T> void + convert_depos(const T& cont, const predicate_t& predicate, edm4hep::CalorimeterHitCollection* collection) const; + + /// Dispatcher function to convert any kind of deposits + template <typename T> void + convert_deposits(DigiContext& context, const T& cont, const predicate_t& predicate) const; + + /// Convert history records to edm4hep + void convert_history(DigiContext& context, const DepositsHistory& cont, work_t& work, const predicate_t& predicate) const; + + /// Convert particle record to edm4hep + void convert_particles(DigiContext& context, const ParticleMapping& cont) const; + + /// Main functional callback + virtual void execute(DigiContext& context, work_t& work, const predicate_t& predicate) const override final; + }; + } // End namespace digi +} // End namespace dd4hep +#endif // DIGI_DIGIEDM4HEPOUTPUT_H diff --git a/DDDigi/io/DigiFrame.h b/DDDigi/io/DigiFrame.h index 565c286bdebb1e6bc63715d8ba2a021afec8bd10..a8e8e9c86247fd3ff0a565a6fb2b2dd467477459 100644 --- a/DDDigi/io/DigiFrame.h +++ b/DDDigi/io/DigiFrame.h @@ -234,6 +234,10 @@ public: const podio::GenericParameters& getGenericParametersForWrite() const { return m_self->parameters(); } + /// MSF: Added by me. + const podio::GenericParameters& getGenericParameters() const { + return m_self->parameters(); + } /** * Get a collection for writing (in a prepared and "ready-to-write" state) diff --git a/DDDigi/io/DigiIO.cpp b/DDDigi/io/DigiIO.cpp index be6b3c84ad08dcc05a8963d530efbbac331e7883..13bc66948c7fd81d1af6067394ff2cc47fb2313e 100644 --- a/DDDigi/io/DigiIO.cpp +++ b/DDDigi/io/DigiIO.cpp @@ -32,6 +32,8 @@ #include <edm4hep/SimTrackerHitCollection.h> #include <edm4hep/CalorimeterHitCollection.h> #include <edm4hep/SimCalorimeterHitCollection.h> +#include <edm4hep/EventHeaderCollection.h> +#include <podio/GenericParameters.h> /// Namespace for the AIDA detector description toolkit namespace dd4hep { @@ -301,6 +303,7 @@ namespace dd4hep { } } + /// Import edm4hep SimTrackerHit collections template <> template <> void data_io<edm4hep_input>::_to_digi(Key key, const std::map<CellID, edm4hep::SimTrackerHit>& hits, @@ -325,6 +328,32 @@ namespace dd4hep { } } + /// Import edm4hep EventHeader collections + template <> template <> + void data_io<edm4hep_input>::_to_digi(Key /* key */, + const edm4hep::EventHeaderCollection& headers, + dd4hep::digi::DataParameters& params) { + for( unsigned int i=0, n=headers.size(); i < n; ++i) { + const auto& hdr = headers[i]; + params.setRunNumber(hdr.getRunNumber()); + params.setEventNumber(hdr.getEventNumber()); + params.setTimeStamp(hdr.getTimeStamp()); + params.setWeight(hdr.getWeight()); + break; + } + } + + /// Import parameters from podio frame + template <> template <> + void data_io<edm4hep_input>::_to_digi(Key /* key */, + const podio::GenericParameters& inputparams, + dd4hep::digi::DataParameters& parameters) { + /// Now copy all frame parameters to the data header + parameters.data->stringParams = inputparams.getStringMap(); + parameters.data->floatParams = inputparams.getFloatMap(); + parameters.data->intParams = inputparams.getIntMap(); + } + template <> template <> bool DepositPredicate<EnergyCut>::operator()(edm4hep::SimCalorimeterHit h) const { return h.getEnergy() > data.cutoff; diff --git a/DDDigi/src/DigiData.cpp b/DDDigi/src/DigiData.cpp index fac5b73cf3e64d00806e0552269eaf22795f7e29..6ed37f59cac8a1a2eae440c71b1c3ca3b5bee26a 100644 --- a/DDDigi/src/DigiData.cpp +++ b/DDDigi/src/DigiData.cpp @@ -424,6 +424,12 @@ bool DataSegment::emplace_any(Key key, std::any&& item) { return ret; } +/// Access data size +std::size_t DataParameters::size() const { + return data->stringParams.size()+data->floatParams.size()+data->intParams.size(); +} + +template bool DataSegment::put(Key key, DataParameters&& data); template bool DataSegment::put(Key key, DepositVector&& data); template bool DataSegment::put(Key key, DepositMapping&& data); template bool DataSegment::put(Key key, ParticleMapping&& data);