diff --git a/DDDigi/include/DDDigi/DigiOutputAction.h b/DDDigi/include/DDDigi/DigiOutputAction.h index fb2013ceb0cbba8922d1cfda4564fc9899074826..9931520bb174125479d61a8179a6e9e2ad97f523 100644 --- a/DDDigi/include/DDDigi/DigiOutputAction.h +++ b/DDDigi/include/DDDigi/DigiOutputAction.h @@ -14,7 +14,7 @@ #define DDDIGI_DIGIOUTPUTACTION_H /// Framework include files -#include <DDDigi/DigiEventAction.h> +#include <DDDigi/DigiContainerProcessor.h> /// Namespace for the AIDA detector description toolkit namespace dd4hep { @@ -32,34 +32,68 @@ namespace dd4hep { * \version 1.0 * \ingroup DD4HEP_DIGITIZATION */ - class DigiOutputAction : public DigiEventAction { + class DigiOutputAction : public DigiContainerSequenceAction { public: - enum { OUTPUT_START = -1 }; - enum { NO_MASK = 0x0 }; - protected: - /// Array of data containers to be saved - std::vector<std::string> m_containers { }; + /// Property: Processor type to manage containers + std::string m_processor_type { }; + /// Property: Container / data type mapping + std::map<std::string, std::string> m_containers { }; /// Property: Output data specification - std::string m_output { }; - /// Property: Mask to flag output source items - int m_mask { NO_MASK }; + std::string m_output { }; + /// Property: Create stream names with sequence numbers + bool m_sequence_streams { true }; + + /// Total numbe rof events to be processed + long num_events { -1 }; + /// Running event counter + long event_count { 0 }; + /// Stream sequence counter + long fseq_count { 0 }; protected: /// Define standard assignments and constructors DDDIGI_DEFINE_ACTION_CONSTRUCTORS(DigiOutputAction); + /// Default destructor + virtual ~DigiOutputAction(); + public: /// Standard constructor DigiOutputAction(const kernel_t& kernel, const std::string& nam); - /// Default destructor - virtual ~DigiOutputAction(); + /// Initialization callback + virtual void initialize(); + + /// Finalization callback + virtual void finalize(); + + /// Check for valid output stream + virtual bool have_output() const = 0; + + /// Open new output stream + virtual void open_output() const = 0; + + /// Close current output stream + virtual void close_output() const = 0; + + /// Commit event data to output stream + virtual void commit_output() const = 0; + + /// Create new output stream name + virtual std::string next_stream_name(); + + /// Adopt new parallel worker + virtual void adopt_processor(DigiContainerProcessor* action, + const std::string& container) override; + + /// Adopt new parallel worker acting on multiple containers + virtual void adopt_processor(DigiContainerProcessor* action, + const std::vector<std::string>& containers); /// Callback to read event output virtual void execute(context_t& context) const override; }; - } // End namespace digi } // End namespace dd4hep #endif // DDDIGI_DIGIOUTPUTACTION_H diff --git a/DDDigi/include/DDDigi/DigiROOTOutput.h b/DDDigi/include/DDDigi/DigiROOTOutput.h deleted file mode 100644 index b3a9bdb943b2e30d2f7eccc22c47609cc252dfd0..0000000000000000000000000000000000000000 --- a/DDDigi/include/DDDigi/DigiROOTOutput.h +++ /dev/null @@ -1,79 +0,0 @@ -//========================================================================== -// 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 DDDIGI_DIGIROOTOUTPUT_H -#define DDDIGI_DIGIROOTOUTPUT_H - -/// Framework include files -#include <DDDigi/DigiOutputAction.h> - -/// C/C++ include files -#include <memory> - -/// Forward declarations -class TFile; -class TTree; -class TBranch; - - -/// 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 DigiROOTOutput; - - /// Base class for output actions to the digitization - /** - * - * \author M.Frank - * \version 1.0 - * \ingroup DD4HEP_DIGITIZATION - */ - class DigiROOTOutput : public DigiOutputAction { - - protected: - /// Helper classes - class internals_t; - /// Property: Name of the tree to connect to - std::string m_tree_name { }; - /// Property: Segment name to place output data default: outputs - std::string m_location { }; - /// Property: name of the event tree - std::string m_section { }; - /// Property: File size limit - std::size_t m_max_file_size { std::numeric_limits<std::size_t>::max() }; - /// Property: vector with disabled collections - std::vector<std::string> m_disabledCollections { }; - /// Property: vector with disabled collections - bool m_disableParticles { false }; - - /// Connection parameters to the "current" output source - std::unique_ptr<internals_t> imp; - - protected: - /// Define standard assignments and constructors - DDDIGI_DEFINE_ACTION_CONSTRUCTORS(DigiROOTOutput); - - public: - /// Standard constructor - DigiROOTOutput(const DigiKernel& kernel, const std::string& nam); - /// Default destructor - virtual ~DigiROOTOutput(); - /// Callback to read event output - virtual void execute(DigiContext& context) const override; - }; - } // End namespace digi -} // End namespace dd4hep -#endif // DDDIGI_DIGIROOTOUTPUT_H diff --git a/DDDigi/io/Digi2ROOT.cpp b/DDDigi/io/Digi2ROOT.cpp index 6fadb41e738b6fbe19cb1112b7a1c6453aed8d50..ef0cd7e9f94ff03472719494ac35a8c479a56d92 100644 --- a/DDDigi/io/Digi2ROOT.cpp +++ b/DDDigi/io/Digi2ROOT.cpp @@ -14,7 +14,7 @@ #define DIGI_DIGI2ROOT_H // Framework include files -#include <DDDigi/DigiContainerProcessor.h> +#include <DDDigi/DigiOutputAction.h> #include <DDDigi/DigiData.h> /// Namespace for the AIDA detector description toolkit @@ -26,25 +26,18 @@ namespace dd4hep { /// 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" + * - MCParticles aka "MCParticles" + * - EnergyDeposits * * \author M.Frank * \version 1.0 * \ingroup DD4HEP_DIGITIZATION */ - class Digi2ROOTWriter : public DigiContainerSequenceAction { + class Digi2ROOTWriter : public DigiOutputAction { public: class internals_t; protected: - /// Property: Container names to be loaded - std::string m_output; - /// Property: Processor type to manage containers - std::string m_processor_type; - /// Property: Container / data type mapping - std::map<std::string, std::string> m_containers { }; /// Reference to internals std::shared_ptr<internals_t> internals; @@ -57,32 +50,16 @@ namespace dd4hep { public: /// Standard constructor Digi2ROOTWriter(const kernel_t& kernel, const std::string& nam); - /// Initialization callback virtual void initialize(); - - /// Finalization callback - virtual void finalize(); - - /// Adopt new parallel worker - virtual void adopt_processor(DigiContainerProcessor* action, - const std::string& container) override final; - - /// Adopt new parallel worker acting on multiple containers - virtual void adopt_processor(DigiContainerProcessor* action, - const std::vector<std::string>& containers); - - /// Callback to store the run information - void beginRun(); - - /// Callback to store the run information - void endRun(); - - /// Callback to store the Geant4 run information - void saveRun(); - - /// Main functional callback - virtual void execute(context_t& context) const; + /// 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 @@ -96,7 +73,6 @@ namespace dd4hep { */ class Digi2ROOTProcessor : public DigiContainerProcessor { friend class Digi2ROOTWriter; - protected: /// Reference to the edm4hep engine std::shared_ptr<Digi2ROOTWriter::internals_t> internals; @@ -104,14 +80,13 @@ namespace dd4hep { public: /// Standard constructor Digi2ROOTProcessor(const DigiKernel& krnl, const std::string& nam); - /// Standard destructor virtual ~Digi2ROOTProcessor() = default; - void convert_particles(DigiContext& context, const ParticleMapping& cont) const; - void convert_deposits(DigiContext& context, const DepositVector& cont, const predicate_t& predicate) const; - void convert_deposits(DigiContext& context, const DepositMapping& 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, ParticleMapping& cont) const; + void convert_deposits(DigiContext& context, DepositVector& cont, const predicate_t& predicate) const; + void convert_deposits(DigiContext& context, DepositMapping& cont, const predicate_t& predicate) const; + void convert_history(DigiContext& context, DepositsHistory& cont, work_t& work, const predicate_t& predicate) const; /// Main functional callback virtual void execute(DigiContext& context, work_t& work, const predicate_t& predicate) const override final; @@ -141,9 +116,10 @@ namespace dd4hep { #include "DigiIO.h" /// ROOT include files -#include <TClass.h> #include <TFile.h> #include <TTree.h> +#include <TROOT.h> +#include <TClass.h> #include <TBranch.h> #include <vector> @@ -154,6 +130,9 @@ namespace dd4hep { /// Namespace for the Digitization part of the AIDA detector description toolkit namespace digi { + using persistent_particles_t = std::vector<std::pair<Key::key_type, Particle*> >; + using persistent_deposits_t = std::vector<std::pair<CellID, EnergyDeposit*> >; + /// Helper class to create output in edm4hep format /** Helper class to create output in edm4hep format * @@ -161,35 +140,41 @@ namespace dd4hep { * \version 1.0 * \ingroup DD4HEP_DIGITIZATION */ - class Digi2ROOTWriter::internals_t { + class Digi2ROOTWriter::internals_t final { public: struct BranchWrapper { + TClass* clazz = nullptr; TBranch* branch = nullptr; void* address = nullptr; void (*fcn_clear)(void* addr) = 0; - void clear() { this->fcn_clear(this->address); } - template <typename T> T* get() { return (T*)this->address; } + void (*fcn_del)(void* addr) = 0; + void clear() { this->fcn_clear(this->address); } + void del() { this->fcn_del(this->address); } + template <typename T> T* get() { return (T*)this->address; } + template <typename T> void set(T* ptr); + }; + template <typename O> struct _wrapper_handler { + static void clear(void* ptr) { O* c = (O*)ptr; c->clear(); } + static void del(void* ptr) { O* c = (O*)ptr; delete c; } }; - Digi2ROOTWriter* m_parent { nullptr }; typedef std::map<std::string, BranchWrapper> Collections; - typedef std::map<std::string, TTree*> Sections; - /// Known file sections - Sections m_sections; + + /// Reference to the parent + Digi2ROOTWriter* m_parent { nullptr }; /// Collections in the event tree - Collections m_collections; + Collections m_collections { }; /// Reference to the ROOT file to open - std::unique_ptr<TFile> m_file; + std::unique_ptr<TFile> m_file { }; /// Reference to the event data tree - TTree* m_tree; + TTree* m_tree { nullptr }; + /// Property: name of the event tree - std::string m_section; - /// Property: vector with disabled collections - std::vector<std::string> m_disabledCollections; + std::string m_section { "EVENT" }; - /// Total numbe rof events to be processed - long num_events { -1 }; - /// Running event counter - long event_count { 0 }; + /// Default basket size + Int_t m_basket_size { 32000 }; + /// Default split level + Int_t m_split_level { 99 }; private: /// Helper to register single collection @@ -197,14 +182,16 @@ namespace dd4hep { public: /// Default constructor - internals_t() = default; + internals_t(Digi2ROOTWriter* parent); /// Default destructor - ~internals_t() = default; + ~internals_t(); - /// Commit data at end of filling procedure - void commit(); + /// Open output file + void open(); /// Commit data to disk and close output stream void close(); + /// Commit data at end of filling procedure + void commit(); /// Create all collections according to the parent setup (locked) void create_collections(); @@ -214,11 +201,33 @@ namespace dd4hep { template <typename T> BranchWrapper& get_collection(const T&); }; + template <typename T> void Digi2ROOTWriter::internals_t::BranchWrapper::set(T* ptr) { + clazz = gROOT->GetClass(typeid(*ptr), kTRUE); + branch = nullptr; + address = ptr; + fcn_clear = _wrapper_handler<T>::clear; + fcn_del = _wrapper_handler<T>::del; + } + + /// Default constructor + Digi2ROOTWriter::internals_t::internals_t(Digi2ROOTWriter* parent) : m_parent(parent) + { + } + + /// Default destructor + Digi2ROOTWriter::internals_t::~internals_t() { + m_parent->info("Releasing allocated resources."); + if ( m_file ) close(); + for( auto& coll : m_collections ) { + coll.second.clear(); + coll.second.del(); + } + m_collections.clear(); + } + template <typename T> T* Digi2ROOTWriter::internals_t::register_collection(const std::string& nam, T* coll) { - struct _do_clear { - static void clear(void* ptr) { T* c = (T*)ptr; c->clear(); } - }; - BranchWrapper bw = { nullptr, (void*)coll, _do_clear::clear }; + BranchWrapper bw; + bw.set(coll); m_collections.emplace(nam, bw); m_parent->debug("+++ created collection %s <%s>", nam.c_str(), typeName(typeid(T)).c_str()); return coll; @@ -227,17 +236,16 @@ namespace dd4hep { /// Create all collections according to the parent setup void Digi2ROOTWriter::internals_t::create_collections() { if ( m_collections.empty() ) { - std::string fname = m_parent->m_output; - m_file.reset(new TFile(fname.c_str(), "RECREATE", "DDDigi data")); for( auto& cont : m_parent->m_containers ) { const std::string& nam = cont.first; const std::string& typ = cont.second; - if ( typ == "MCParticles" ) - register_collection(nam, new std::vector<Particle*>()); - else - register_collection(nam, new std::vector<EnergyDeposit*>()); + if ( typ == "MCParticles" ) { + register_collection(nam, new persistent_particles_t()); + } + else { + register_collection(nam, new persistent_deposits_t()); + } } - m_parent->info("+++ Will save %ld events to %s", num_events, m_parent->m_output.c_str()); } } @@ -257,27 +265,38 @@ namespace dd4hep { coll.second.clear(); } - /// Commit data at end of filling procedure - void Digi2ROOTWriter::internals_t::commit() { + /// Open output file + void Digi2ROOTWriter::internals_t::open() { if ( m_file ) { - for( auto& coll : m_collections ) { - coll.second.branch->Write(); - } - clearCollections(); - return; + close(); } - m_parent->except("+++ Failed to write output file. [Stream is not open]"); + std::string fname = m_parent->next_stream_name(); + m_file.reset(TFile::Open(fname.c_str(), "RECREATE", "DDDigi data")); + m_tree = new TTree(m_section.c_str(), "DDDigi data", m_split_level, m_file.get()); + m_parent->info("+++ Opened ROOT output file %s", m_file->GetName()); + for( auto& coll : m_collections ) { + auto& dsc = coll.second; + dsc.branch = m_tree->Branch(coll.first.c_str(), + dsc.clazz->GetName(), + &dsc.address, + m_basket_size, + m_split_level); + dsc.branch->SetAutoDelete(kFALSE); + } + m_parent->info("+++ Will save %ld events to %s", + m_parent->num_events, m_parent->m_output.c_str()); } /// Commit data to disk and close output stream void Digi2ROOTWriter::internals_t::close() { if ( m_file ) { TDirectory::TContext ctxt(m_file.get()); - Sections::iterator i = m_sections.find(m_section); - m_parent->info("+++ Closing ROOT output file %s", m_file->GetName()); - if ( i != m_sections.end() ) - m_sections.erase(i); - m_collections.clear(); + m_parent->info("+++ Closing ROOT output file %s after %ld events and %ld bytes", + m_file->GetName(), m_tree->GetEntries(), m_file->GetBytesWritten()); + for( auto& coll : m_collections ) { + coll.second.branch->ResetAddress(); + coll.second.branch = nullptr; + } m_tree->Write(); m_file->Close(); m_tree = nullptr; @@ -285,168 +304,132 @@ namespace dd4hep { m_file.reset(); } + /// Commit data at end of filling procedure + void Digi2ROOTWriter::internals_t::commit() { + if ( m_tree ) { + m_tree->Fill(); + clearCollections(); + ++m_parent->event_count; + if ( m_parent->m_sequence_streams ) { + if ( 0 == (m_parent->event_count%m_parent->num_events) ) { + close(); + } + } + return; + } + m_parent->except("+++ Failed to write output file. [Stream is not open]"); + } + /// Standard constructor Digi2ROOTWriter::Digi2ROOTWriter(const DigiKernel& krnl, const std::string& nam) - : DigiContainerSequenceAction(krnl, nam) + : DigiOutputAction(krnl, nam) { - internals = std::make_shared<internals_t>(); - declareProperty("output", m_output); - declareProperty("containers", m_containers); - declareProperty("processor_type", m_processor_type = "Digi2ROOTProcessor"); - internals->m_parent = this; + internals = std::make_shared<internals_t>(this); + m_processor_type = "Digi2ROOTProcessor"; + declareProperty("basket_size", internals->m_basket_size); + declareProperty("split_level", internals->m_split_level); InstanceCount::increment(this); } /// Default destructor - Digi2ROOTWriter::~Digi2ROOTWriter() {{ - std::lock_guard<std::mutex> lock(m_kernel.global_io_lock()); - internals->close(); - } + Digi2ROOTWriter::~Digi2ROOTWriter() { internals.reset(); InstanceCount::decrement(this); } /// Initialization callback void Digi2ROOTWriter::initialize() { - if ( m_containers.empty() ) { - warning("+++ No input containers given for attenuation action -- no action taken"); - return; - } - internals->num_events = m_kernel.property("numEvents").value<long>(); - for ( const auto& c : m_containers ) { - Key key(c.first, 0, 0); - auto it = m_registered_processors.find(key); - if ( it == m_registered_processors.end() ) { - std::string nam = name() + ".E4H." + c.first; - auto* conv = createAction<DigiContainerProcessor>(m_processor_type, m_kernel, nam); - if ( !conv ) { - except("+++ Failed to create edm4hep processor: %s of type: %s", - nam.c_str(), m_processor_type.c_str()); - } - conv->property("OutputLevel").set(int(outputLevel())); - adopt_processor(conv, c.first); - conv->release(); // Release processor **after** adoption. - } - } - std::lock_guard<std::mutex> lock(m_kernel.global_io_lock()); - m_parallel = false; - internals->create_collections(); - this->DigiContainerSequenceAction::initialize(); - } - - /// Finalization callback - void Digi2ROOTWriter::finalize() { - internals->close(); - } - - /// Adopt new parallel worker - void Digi2ROOTWriter::adopt_processor(DigiContainerProcessor* action, - const std::string& container) - { - std::size_t idx = container.find('/'); - if ( idx != std::string::npos ) { - std::string nam = container.substr(0, idx); - std::string typ = container.substr(idx+1); - auto* act = dynamic_cast<Digi2ROOTProcessor*>(action); + this->DigiOutputAction::initialize(); + for ( auto& c : m_registered_processors ) { + auto* act = dynamic_cast<Digi2ROOTProcessor*>(c.second); if ( act ) { // This is not nice! Need to think about something better. act->internals = this->internals; + continue; } - this->DigiContainerSequenceAction::adopt_processor(action, nam); - m_containers.emplace(nam, typ); - return; + except("Error: Invalid processor type for ROOT output: %s", c.second->c_name()); } - except("+++ Invalid container specification: %s. %s", - container.c_str(), "Specify container as tuple: \"<name>/<type>\" !"); + m_parallel = false; + internals->create_collections(); } - /// Adopt new parallel worker acting on multiple containers - void Digi2ROOTWriter::adopt_processor(DigiContainerProcessor* action, - const std::vector<std::string>& containers) - { - DigiContainerSequenceAction::adopt_processor(action, containers); + /// Check for valid output stream + bool Digi2ROOTWriter::have_output() const { + return internals->m_file.get() != nullptr; } - /// Main functional callback - void Digi2ROOTWriter::execute(DigiContext& context) const { - std::lock_guard<std::mutex> lock(context.global_io_lock()); - this->DigiContainerSequenceAction::execute(context); - this->internals->commit(); - if ( ++internals->event_count == internals->num_events ) { - internals->close(); - } + /// Open new output stream + void Digi2ROOTWriter::open_output() const { + internals->open(); } - /// Callback to store the run information - void Digi2ROOTWriter::beginRun() { - saveRun(); - } - - /// Callback to store the run information - void Digi2ROOTWriter::endRun() { - // saveRun(run); + /// Close possible open stream + void Digi2ROOTWriter::close_output() const { + internals->close(); } - /// Callback to store the Geant4 run information - void Digi2ROOTWriter::saveRun() { - warning("saveRun(): RunHeader not implemented in EDM4hep, nothing written ..."); + /// Commit event data to output stream + void Digi2ROOTWriter::commit_output() const { + internals->commit(); } - /// Standard constructor Digi2ROOTProcessor::Digi2ROOTProcessor(const DigiKernel& krnl, const std::string& nam) : DigiContainerProcessor(krnl, nam) { } - void Digi2ROOTProcessor::convert_particles(DigiContext& ctxt, - const ParticleMapping& cont) const + void Digi2ROOTProcessor::convert_particles(DigiContext& ctxt, + ParticleMapping& cont) const { auto& coll = internals->get_collection(cont); - auto* vec = coll.get<std::vector<const ParticleMapping::value_type*> >(); + auto* vec = coll.get<persistent_particles_t>(); + vec->clear(); vec->reserve(cont.size()); - for( const auto& p : cont ) { - vec->emplace_back(&p); + for( auto& p : cont ) { + vec->emplace_back(std::make_pair(p.first, &p.second)); } info("%s+++ %-24s added %6ld entries from mask: %04X", ctxt.event->id(), cont.name.c_str(), vec->size(), cont.key.mask()); } - void Digi2ROOTProcessor::convert_deposits(DigiContext& ctxt, - const DepositMapping& cont, - const predicate_t& predicate) const + void Digi2ROOTProcessor::convert_deposits(DigiContext& ctxt, + DepositMapping& cont, + const predicate_t& predicate) const { auto& coll = internals->get_collection(cont); - auto* vec = coll.get<std::vector<const DepositMapping::value_type*> >(); + auto* vec = coll.get<persistent_deposits_t>(); + vec->clear(); vec->reserve(cont.size()); - for ( const auto& depo : cont ) { + for ( auto& depo : cont ) { if ( predicate(depo) ) { - vec->emplace_back(&depo); + vec->emplace_back(std::make_pair(depo.first, &depo.second)); } } info("%s+++ %-24s added %6ld entries from mask: %04X", ctxt.event->id(), cont.name.c_str(), vec->size(), cont.key.mask()); } - void Digi2ROOTProcessor::convert_deposits(DigiContext& ctxt, - const DepositVector& cont, - const predicate_t& predicate) const + void Digi2ROOTProcessor::convert_deposits(DigiContext& ctxt, + DepositVector& cont, + const predicate_t& predicate) const { auto& coll = internals->get_collection(cont); - auto* vec = coll.get<std::vector<const DepositVector::value_type*> >(); + auto* vec = coll.get<persistent_deposits_t>(); + vec->clear(); vec->reserve(cont.size()); - for ( const auto& depo : cont ) { + for ( auto& depo : cont ) { if ( predicate(depo) ) { - vec->emplace_back(&depo); + vec->emplace_back(std::make_pair(depo.first, &depo.second)); } } info("%s+++ %-24s added %6ld entries from mask: %04X", ctxt.event->id(), cont.name.c_str(), vec->size(), cont.key.mask()); } - void Digi2ROOTProcessor::convert_history(DigiContext& ctxt, - const DepositsHistory& cont, - work_t& work, - const predicate_t& predicate) const + void Digi2ROOTProcessor::convert_history(DigiContext& ctxt, + 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), @@ -455,13 +438,13 @@ namespace dd4hep { /// Main functional callback void Digi2ROOTProcessor::execute(DigiContext& ctxt, work_t& work, const predicate_t& predicate) const { - if ( const auto* p = work.get_input<ParticleMapping>() ) + if ( auto* p = work.get_input<ParticleMapping>() ) convert_particles(ctxt, *p); - else if ( const auto* m = work.get_input<DepositMapping>() ) + else if ( auto* m = work.get_input<DepositMapping>() ) convert_deposits(ctxt, *m, predicate); - else if ( const auto* v = work.get_input<DepositVector>() ) + else if ( auto* v = work.get_input<DepositVector>() ) convert_deposits(ctxt, *v, predicate); - else if ( const auto* h = work.get_input<DepositsHistory>() ) + else if ( auto* h = work.get_input<DepositsHistory>() ) convert_history(ctxt, *h, work, predicate); else except("Request to handle unknown data type: %s", work.input_type_name().c_str()); diff --git a/DDDigi/io/Digi2edm4hep.cpp b/DDDigi/io/Digi2edm4hep.cpp index 745f6b5c36ac6e732db8e820175c25d8c9c153a6..677dc51e53bfbfb8301d47b00bb361775977a648 100644 --- a/DDDigi/io/Digi2edm4hep.cpp +++ b/DDDigi/io/Digi2edm4hep.cpp @@ -14,7 +14,7 @@ #define DIGI_DIGI2EDM4HEP_H // Framework include files -#include <DDDigi/DigiContainerProcessor.h> +#include <DDDigi/DigiOutputAction.h> /// C/C++ include files @@ -40,17 +40,10 @@ namespace dd4hep { * \version 1.0 * \ingroup DD4HEP_DIGITIZATION */ - class Digi2edm4hepWriter : public DigiContainerSequenceAction { + class Digi2edm4hepWriter : public DigiOutputAction { public: class internals_t; - protected: - /// Property: Container names to be loaded - std::string m_output; - /// Property: Processor type to manage containers - std::string m_processor_type; - /// Property: Container / data type mapping - std::map<std::string, std::string> m_containers { }; /// Reference to internals std::shared_ptr<internals_t> internals; @@ -63,32 +56,16 @@ namespace dd4hep { public: /// Standard constructor Digi2edm4hepWriter(const kernel_t& kernel, const std::string& nam); - /// Initialization callback virtual void initialize(); - - /// Finalization callback - virtual void finalize(); - - /// Adopt new parallel worker - virtual void adopt_processor(DigiContainerProcessor* action, - const std::string& container) override final; - - /// Adopt new parallel worker acting on multiple containers - virtual void adopt_processor(DigiContainerProcessor* action, - const std::vector<std::string>& containers); - - /// Callback to store the run information - void beginRun(); - - /// Callback to store the run information - void endRun(); - - /// Callback to store the Geant4 run information - void saveRun(); - - /// Main functional callback - virtual void execute(context_t& context) const; + /// 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 @@ -209,12 +186,14 @@ namespace dd4hep { public: /// Default constructor - internals_t() = default; + internals_t(Digi2edm4hepWriter* parent); /// Default destructor - ~internals_t() = default; + ~internals_t(); /// Commit data at end of filling procedure void commit(); + /// Open new output stream + void open(); /// Commit data to disk and close output stream void close(); @@ -224,10 +203,21 @@ namespace dd4hep { template <typename T> podio::CollectionBase* get_collection(const T&); }; + /// Default constructor + Digi2edm4hepWriter::internals_t::internals_t(Digi2edm4hepWriter* parent) : m_parent(parent) + { + m_store = std::make_unique<podio::EventStore>(); + } + + /// Default destructor + Digi2edm4hepWriter::internals_t::~internals_t() { + if ( m_file ) close(); + m_store.reset(); + } + template <typename T> T* Digi2edm4hepWriter::internals_t::register_collection(const std::string& nam, T* coll) { m_collections.emplace(nam, coll); m_store->registerCollection(nam, coll); - m_file->registerForWrite(nam); m_parent->debug("+++ created collection %s <%s>", nam.c_str(), coll->getTypeName().c_str()); return coll; } @@ -235,9 +225,6 @@ namespace dd4hep { /// Create all collections according to the parent setup void Digi2edm4hepWriter::internals_t::create_collections() { if ( nullptr == m_header ) { - std::string fname = m_parent->m_output; - m_store = std::make_unique<podio::EventStore>(); - m_file = std::make_unique<podio::ROOTWriter>(fname, m_store.get()); m_header = register_collection("EventHeader", new edm4hep::EventHeaderCollection()); for( auto& cont : m_parent->m_containers ) { const std::string& nam = cont.first; @@ -276,122 +263,78 @@ namespace dd4hep { m_parent->except("+++ Failed to write output file. [Stream is not open]"); } + /// Open new output stream + void Digi2edm4hepWriter::internals_t::open() { + if ( m_file ) { + close(); + } + m_file.reset(); + 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 ) { + m_file->registerForWrite(c.first); + } + } + /// Commit data to disk and close output stream void Digi2edm4hepWriter::internals_t::close() { + m_parent->info("+++ Closing EDM4HEP output file."); if ( m_file ) { m_file->finish(); } m_file.reset(); - m_store.reset(); } /// Standard constructor Digi2edm4hepWriter::Digi2edm4hepWriter(const DigiKernel& krnl, const std::string& nam) - : DigiContainerSequenceAction(krnl, nam) + : DigiOutputAction(krnl, nam) { - internals = std::make_shared<internals_t>(); - declareProperty("output", m_output); - declareProperty("containers", m_containers); - declareProperty("processor_type", m_processor_type = "Digi2edm4hepProcessor"); - internals->m_parent = this; + internals = std::make_shared<internals_t>(this); InstanceCount::increment(this); } /// Default destructor - Digi2edm4hepWriter::~Digi2edm4hepWriter() {{ - std::lock_guard<std::mutex> lock(m_kernel.global_io_lock()); - internals->close(); - } + Digi2edm4hepWriter::~Digi2edm4hepWriter() { internals.reset(); InstanceCount::decrement(this); } /// Initialization callback void Digi2edm4hepWriter::initialize() { - if ( m_containers.empty() ) { - warning("+++ No input containers given for attenuation action -- no action taken"); - return; - } - internals->num_events = m_kernel.property("numEvents").value<long>(); - for ( const auto& c : m_containers ) { - Key key(c.first, 0, 0); - auto it = m_registered_processors.find(key); - if ( it == m_registered_processors.end() ) { - std::string nam = name() + ".E4H." + c.first; - auto* conv = createAction<DigiContainerProcessor>(m_processor_type, m_kernel, nam); - if ( !conv ) { - except("+++ Failed to create edm4hep processor: %s of type: %s", - nam.c_str(), m_processor_type.c_str()); - } - conv->property("OutputLevel").set(int(outputLevel())); - adopt_processor(conv, c.first); - conv->release(); // Release processor **after** adoption. - } - } - std::lock_guard<std::mutex> lock(m_kernel.global_io_lock()); - m_parallel = false; - internals->create_collections(); - this->DigiContainerSequenceAction::initialize(); - } - - /// Finalization callback - void Digi2edm4hepWriter::finalize() { - internals->close(); - } - - /// Adopt new parallel worker - void Digi2edm4hepWriter::adopt_processor(DigiContainerProcessor* action, - const std::string& container) - { - std::size_t idx = container.find('/'); - if ( idx != std::string::npos ) { - std::string nam = container.substr(0, idx); - std::string typ = container.substr(idx+1); - auto* act = dynamic_cast<Digi2edm4hepProcessor*>(action); + this->DigiOutputAction::initialize(); + for ( auto& c : m_registered_processors ) { + auto* act = dynamic_cast<Digi2edm4hepProcessor*>(c.second); if ( act ) { // This is not nice! Need to think about something better. act->internals = this->internals; + continue; } - this->DigiContainerSequenceAction::adopt_processor(action, nam); - m_containers.emplace(nam, typ); - return; + except("Error: Invalid processor type for EDM4HEP output: %s", c.second->c_name()); } - except("+++ Invalid container specification: %s. %s", - container.c_str(), "Specify container as tuple: \"<name>/<type>\" !"); - } - - /// Adopt new parallel worker acting on multiple containers - void Digi2edm4hepWriter::adopt_processor(DigiContainerProcessor* action, - const std::vector<std::string>& containers) - { - DigiContainerSequenceAction::adopt_processor(action, containers); + m_parallel = false; + internals->create_collections(); } - /// Main functional callback - void Digi2edm4hepWriter::execute(DigiContext& context) const { - std::lock_guard<std::mutex> lock(context.global_io_lock()); - this->DigiContainerSequenceAction::execute(context); - this->internals->commit(); - if ( ++internals->event_count == internals->num_events ) { - internals->close(); - } + /// Check for valid output stream + bool Digi2edm4hepWriter::have_output() const { + return internals->m_file.get() != nullptr; } - /// Callback to store the run information - void Digi2edm4hepWriter::beginRun() { - saveRun(); + /// Open new output stream + void Digi2edm4hepWriter::open_output() const { + internals->open(); } - /// Callback to store the run information - void Digi2edm4hepWriter::endRun() { - // saveRun(run); + /// Close possible open stream + void Digi2edm4hepWriter::close_output() const { + internals->close(); } - /// Callback to store the Geant4 run information - void Digi2edm4hepWriter::saveRun() { - warning("saveRun(): RunHeader not implemented in EDM4hep, nothing written ..."); + /// Commit event data to output stream + void Digi2edm4hepWriter::commit_output() const { + internals->commit(); } - /// Standard constructor Digi2edm4hepProcessor::Digi2edm4hepProcessor(const DigiKernel& krnl, const std::string& nam) : DigiContainerProcessor(krnl, nam) diff --git a/DDDigi/io/DigiIO.cpp b/DDDigi/io/DigiIO.cpp index b70cadfb22b9c6bc9a333c3562f51ba101e20187..c06a998294e9a4447e07ee4e1ef187068c86f09a 100644 --- a/DDDigi/io/DigiIO.cpp +++ b/DDDigi/io/DigiIO.cpp @@ -233,7 +233,7 @@ namespace dd4hep { hit.setCellID( dep.first ); hit.setEDep( de.deposit ); hit.setEDepError( dep_error ); - hit.setEdx( de.deposit/de.length ); + //hit.setEdx( de.deposit/de.length ); hit.setPosition( _toVectorD(de.position) ); } diff --git a/DDDigi/plugins/Components.cpp b/DDDigi/plugins/Components.cpp index c976ba968796a886bbcded903e4045214a3e9094..a6fce560ad35d411595e57f945275c9b40a82856 100644 --- a/DDDigi/plugins/Components.cpp +++ b/DDDigi/plugins/Components.cpp @@ -24,12 +24,6 @@ #include <DDDigi/DigiInputAction.h> DECLARE_DIGIACTION_NS(dd4hep::digi,DigiInputAction) -#include <DDDigi/DigiOutputAction.h> -DECLARE_DIGIACTION_NS(dd4hep::digi,DigiOutputAction) - -#include <DDDigi/DigiROOTOutput.h> -DECLARE_DIGIACTION_NS(dd4hep::digi,DigiROOTOutput) - #include <DDDigi/DigiSynchronize.h> DECLARE_DIGIACTION_NS(dd4hep::digi,DigiSynchronize) diff --git a/DDDigi/python/DDDigiDict.C b/DDDigi/python/DDDigiDict.C index 5346ef08c00133274c53902c30348375656ce12a..108ff020aa01beb6acde8ab690e08a8e98765a35 100644 --- a/DDDigi/python/DDDigiDict.C +++ b/DDDigi/python/DDDigiDict.C @@ -200,15 +200,16 @@ namespace dd4hep { //#pragma link C++ class dd4hep::digi::Key; #pragma link C++ class std::pair<dd4hep::digi::Key::key_type, dd4hep::digi::Particle>+; #pragma link C++ class std::map<dd4hep::digi::Key::key_type, dd4hep::digi::Particle>+; +#pragma link C++ class std::map<dd4hep::digi::Key::key_type, dd4hep::digi::Particle*>+; #pragma link C++ class std::vector<std::pair<dd4hep::digi::Key::key_type, dd4hep::digi::Particle> >+; - -#pragma link C++ class std::pair<dd4hep::digi::Key::key_type, dd4hep::digi::Particle>; -#pragma link C++ class std::map<dd4hep::digi::Key::key_type, dd4hep::digi::Particle>; -#pragma link C++ class std::vector<std::pair<dd4hep::digi::Key::key_type, dd4hep::digi::Particle> >; +#pragma link C++ class std::vector<std::pair<dd4hep::digi::Key::key_type, dd4hep::digi::Particle*> >+; #pragma link C++ class std::pair<dd4hep::CellID, dd4hep::digi::EnergyDeposit>+; +#pragma link C++ class std::pair<dd4hep::CellID, dd4hep::digi::EnergyDeposit*>+; #pragma link C++ class std::map<dd4hep::CellID, dd4hep::digi::EnergyDeposit>+; +#pragma link C++ class std::map<dd4hep::CellID, dd4hep::digi::EnergyDeposit*>+; #pragma link C++ class std::vector<std::pair<dd4hep::CellID, dd4hep::digi::EnergyDeposit> >+; +#pragma link C++ class std::vector<std::pair<dd4hep::CellID, dd4hep::digi::EnergyDeposit*> >+; #pragma link C++ class dd4hep::digi::History+; #pragma link C++ class dd4hep::digi::Particle+; diff --git a/DDDigi/src/DigiOutputAction.cpp b/DDDigi/src/DigiOutputAction.cpp index ad23ac4b6df3abd809160c1dcf4366ebbb494c12..81b12ed7a7c0b7a520685979e2b00544af71c545 100644 --- a/DDDigi/src/DigiOutputAction.cpp +++ b/DDDigi/src/DigiOutputAction.cpp @@ -14,21 +14,23 @@ // Framework include files #include <DD4hep/InstanceCount.h> #include <DDDigi/DigiOutputAction.h> +#include <DDDigi/DigiContext.h> +#include <DDDigi/DigiPlugins.h> +#include <DDDigi/DigiKernel.h> // C/C++ include files #include <stdexcept> -#include <unistd.h> -using namespace std; using namespace dd4hep::digi; /// Standard constructor -DigiOutputAction::DigiOutputAction(const DigiKernel& kernel, const string& nam) - : DigiEventAction(kernel, nam) +DigiOutputAction::DigiOutputAction(const DigiKernel& kernel, const std::string& nam) + : DigiContainerSequenceAction(kernel, nam) { - declareProperty("containers", m_containers); - declareProperty("output", m_output); - declareProperty("mask", m_mask); + declareProperty("sequence_streams", m_sequence_streams); + declareProperty("processor_type", m_processor_type); + declareProperty("containers", m_containers); + declareProperty("output", m_output); InstanceCount::increment(this); } @@ -37,8 +39,85 @@ DigiOutputAction::~DigiOutputAction() { InstanceCount::decrement(this); } +/// Create new output stream name +std::string DigiOutputAction::next_stream_name() { + if ( m_sequence_streams ) { + std::size_t idx = m_output.rfind("."); + std::stringstream str; + if ( idx != std::string::npos ) { + std::string fname = m_output.substr(0, idx); + std::string ftype = m_output.substr(idx+1); + str << fname << '_' << std::dec << std::setfill('0') << std::setw(8) << fseq_count << "." << ftype; + return str.str(); + } + str << m_output << '_' << std::dec << std::setfill('0') << std::setw(8) << fseq_count; + return str.str(); + } + return m_output; +} +/// Initialization callback +void DigiOutputAction::initialize() { + if ( m_containers.empty() ) { + warning("+++ No input containers given for attenuation action -- no action taken"); + return; + } + num_events = m_kernel.property("numEvents").value<long>(); + for ( const auto& c : m_containers ) { + Key key(c.first, 0, 0); + auto it = m_registered_processors.find(key); + if ( it == m_registered_processors.end() ) { + std::string nam = name() + ".E4H." + c.first; + auto* conv = createAction<DigiContainerProcessor>(m_processor_type, m_kernel, nam); + if ( !conv ) { + except("+++ Failed to create edm4hep processor: %s of type: %s", + nam.c_str(), m_processor_type.c_str()); + } + conv->property("OutputLevel").set(int(outputLevel())); + adopt_processor(conv, c.first); + conv->release(); // Release processor **after** adoption. + } + } + std::lock_guard<std::mutex> lock(m_kernel.global_io_lock()); + this->DigiContainerSequenceAction::initialize(); +} + +/// Finalization callback +void DigiOutputAction::finalize() { + close_output(); + this->DigiContainerSequenceAction::finalize(); +} + +/// Adopt new parallel worker +void DigiOutputAction::adopt_processor(DigiContainerProcessor* action, + const std::string& container) +{ + std::size_t idx = container.find('/'); + if ( idx != std::string::npos ) { + std::string nam = container.substr(0, idx); + std::string typ = container.substr(idx+1); + this->DigiContainerSequenceAction::adopt_processor(action, nam); + m_containers.emplace(nam, typ); + return; + } + except("+++ Invalid container specification: %s. %s", + container.c_str(), "Specify container as tuple: \"<name>/<type>\" !"); +} + +/// Adopt new parallel worker acting on multiple containers +void DigiOutputAction::adopt_processor(DigiContainerProcessor* action, + const std::vector<std::string>& containers) +{ + DigiContainerSequenceAction::adopt_processor(action, containers); +} + /// Pre-track action callback -void DigiOutputAction::execute(DigiContext& /* context */) const { - info("+++ Virtual method execute() --- Should not be called"); - ::sleep(1); +void DigiOutputAction::execute(DigiContext& context) const { + std::lock_guard<std::mutex> lock(context.global_io_lock()); + /// Check for valid output stream. If not: open new stream + if ( !have_output() ) { + open_output(); + } + this->DigiContainerSequenceAction::execute(context); + /// Commit data. Close stream if necessary + commit_output(); } diff --git a/DDDigi/src/DigiROOTOutput.cpp b/DDDigi/src/DigiROOTOutput.cpp deleted file mode 100644 index 3929794e72888167caacd64ea2e8ee2f34f68297..0000000000000000000000000000000000000000 --- a/DDDigi/src/DigiROOTOutput.cpp +++ /dev/null @@ -1,237 +0,0 @@ -//========================================================================== -// 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 -// -//========================================================================== - -/// Framework include files -#include <DD4hep/InstanceCount.h> -#include <DDDigi/DigiROOTOutput.h> - -/// ROOT include files -#include <TFile.h> -#include <TTree.h> -#include <TBranch.h> - -/// C/C++ include files -#include <stdexcept> -#include <unistd.h> - -using namespace std; -using namespace dd4hep::digi; - -class DigiROOTOutput::internals_t { -public: - typedef std::map<std::string, TBranch*> Branches; - typedef std::map<std::string, TTree*> Sections; - /// Reference to the ROOT file to open - TFile* m_file { nullptr }; - /// Reference to the event data tree - TTree* m_tree { nullptr }; - /// Known file sections - Sections m_sections; - /// Branches in the event tree - Branches m_branches; - DigiROOTOutput* output { nullptr }; - -public: - internals_t(DigiROOTOutput* o) - : output(o) - { - } - ~internals_t() { - if (m_file) { - TDirectory::TContext ctxt(m_file); - m_tree->Write(); - m_file->Close(); - m_tree = 0; - detail::deletePtr (m_file); - } - } - /// Create/access tree by name for non collection user data - TTree* section(const std::string& nam) { - auto i = m_sections.find(nam); - if ( i == m_sections.end() ) { - TDirectory::TContext ctxt(m_file); - TTree* t = new TTree(nam.c_str(), ("Digitization " + nam + " information").c_str()); - m_sections.emplace(nam, t); - return t; - } - return i->second; - } - /// Commit data at end of filling procedure - void commit() { - if ( m_file ) { - TObjArray* a = m_tree->GetListOfBranches(); - Long64_t evt = m_tree->GetEntries() + 1; - Int_t nb = a->GetEntriesFast(); - /// Fill NULL pointers to all branches, which have less entries than the Event branch - for (Int_t i = 0; i < nb; ++i) { - TBranch* br_ptr = (TBranch*) a->UncheckedAt(i); - Long64_t br_evt = br_ptr->GetEntries(); - if (br_evt < evt) { - Long64_t num = evt - br_evt; - br_ptr->SetAddress(0); - while (num > 0) { - br_ptr->Fill(); - --num; - } - } - } - m_tree->SetEntries(evt); - } - } - /// Fill single EVENT branch entry (Geant4 collection data) - int fill(const string& nam, const std::type_info& type, void* ptr) { - if (m_file) { - TBranch* b = 0; - auto i = m_branches.find(nam); - if (i == m_branches.end()) { - TClass* cl = TBuffer::GetClass(type); - if (cl) { - b = m_tree->Branch(nam.c_str(), cl->GetName(), (void*) 0); - b->SetAutoDelete(false); - m_branches.emplace(nam, b); - } - else { - throw runtime_error("No ROOT TClass object availible for object type:" + typeName(type)); - } - } - else { - b = (*i).second; - } - Long64_t evt = b->GetEntries(), nevt = b->GetTree()->GetEntries(), num = nevt - evt; - if (nevt > evt) { - b->SetAddress(0); - while (num > 0) { - b->Fill(); - --num; - } - } - b->SetAddress(&ptr); - int nbytes = b->Fill(); - if (nbytes < 0) { - throw runtime_error("Failed to write ROOT collection:" + nam + "!"); - } - return nbytes; - } - return 0; - } - /// Callback to store the Geant4 event - void saveEvent(DigiContext& /* ctxt */) { - if ( !output->m_disableParticles ) { -#if 0 - Geant4ParticleMap* parts = context()->event().extension<Geant4ParticleMap>(); - if ( parts ) { - typedef Geant4HitWrapper::HitManipulator Manip; - typedef Geant4ParticleMap::ParticleMap ParticleMap; - Manip* manipulator = Geant4HitWrapper::manipulator<Geant4Particle>(); - const ParticleMap& pm = parts->particles(); - vector<void*> particles; - particles.reserve(pm.size()); - for ( const auto& i : pm ) { - particles.emplace_back((ParticleMap::mapped_type*)i.second); - } - fill("MCParticles",manipulator->vec_type,&particles); - } -#endif - } - } -}; - -/// Standard constructor -DigiROOTOutput::DigiROOTOutput(const DigiKernel& kernel, const std::string& nam) - : DigiOutputAction(kernel, nam) -{ - imp = std::make_unique<internals_t>(this); - declareProperty("section", m_section = "EVENT"); - declareProperty("max_file_size", m_max_file_size); - declareProperty("disabled_collections", m_disabledCollections); - declareProperty("disable_particles", m_disableParticles); - InstanceCount::increment(this); -} - -/// Default destructor -DigiROOTOutput::~DigiROOTOutput() { - imp.reset(); - InstanceCount::decrement(this); -} - -/// Pre-track action callback -void DigiROOTOutput::execute(DigiContext& context) const { - imp->saveEvent(context); -#if 0 - for (int i = 0; i < nCol; ++i) { - G4VHitsCollection* hc = hce->GetHC(i); - saveCollection(ctxt, hc); - } -#endif -} - -#if 0 -/// Callback to store the Geant4 run information -void DigiROOTOutput::beginRun(const G4Run* run) { - if (!m_file && !m_output.empty()) { - TDirectory::TContext ctxt(TDirectory::CurrentDirectory()); - m_file = TFile::Open(m_output.c_str(), "RECREATE", "DD4hep digitization data"); - if (m_file->IsZombie()) { - detail::deletePtr (m_file); - except("+++ Failed to open ROOT output file:'" + m_output + "'"); - } - m_tree = section("EVENT"); - } - Geant4OutputAction::beginRun(run); -} - - - -/// Callback to store each Geant4 hit collection -void DigiROOTOutput::saveCollection(DigiContext& /* ctxt */, G4VHitsCollection* collection) { - Geant4HitCollection* coll = dynamic_cast<Geant4HitCollection*>(collection); - string hc_nam = collection->GetName(); - for(const auto& n : m_disabledCollections) { - if ( n == hc_nam ) { - return; - } - } - if (coll) { - vector<void*> hits; - coll->getHitsUnchecked(hits); - size_t nhits = coll->GetSize(); - if ( m_handleMCTruth && m_truth && nhits > 0 ) { - hits.reserve(nhits); - try { - for(size_t i=0; i<nhits; ++i) { - Geant4HitData* h = coll->hit(i); - Geant4Tracker::Hit* trk_hit = dynamic_cast<Geant4Tracker::Hit*>(h); - if ( 0 != trk_hit ) { - Geant4HitData::Contribution& t = trk_hit->truth; - int trackID = t.trackID; - t.trackID = m_truth->particleID(trackID); - } - Geant4Calorimeter::Hit* cal_hit = dynamic_cast<Geant4Calorimeter::Hit*>(h); - if ( 0 != cal_hit ) { - Geant4HitData::Contributions& c = cal_hit->truth; - for(Geant4HitData::Contributions::iterator j=c.begin(); j!=c.end(); ++j) { - Geant4HitData::Contribution& t = *j; - int trackID = t.trackID; - t.trackID = m_truth->particleID(trackID); - } - } - } - } - catch(...) { - printout(ERROR,name(),"+++ Exception while saving collection %s.",hc_nam.c_str()); - } - } - fill(hc_nam, coll->vector_type(), &hits); - } -} -#endif diff --git a/examples/DDDigi/CMakeLists.txt b/examples/DDDigi/CMakeLists.txt index 7d3028138e2897aa7bfb673e1c77621d93308d33..392d557afb2b31928105581c961875114bf8f8fc 100644 --- a/examples/DDDigi/CMakeLists.txt +++ b/examples/DDDigi/CMakeLists.txt @@ -207,6 +207,15 @@ if (DD4HEP_USE_GEANT4) REGEX_FAIL "Error;ERROR;Exception" ) # + # Test raw digi write + dd4hep_add_test_reg(DDDigi_test_digi_root_write + COMMAND "${CMAKE_INSTALL_PREFIX}/bin/run_test_DDDigi.sh" + EXEC_ARGS ${Python_EXECUTABLE} ${CMAKE_INSTALL_PREFIX}/examples/DDDigi/scripts/TestWriteDigi.py + DEPENDS DDDigi_generate_data + REGEX_PASS "\\+\\+\\+ Closing ROOT output file dddigi_write_digi_00000000.root after 5 events" + REGEX_FAIL "Error;ERROR;Exception" + ) + # if (DD4HEP_USE_EDM4HEP) # Test edm4hep write (needs to be expanded) dd4hep_add_test_reg(DDDigi_test_edm4hep_write diff --git a/examples/DDDigi/scripts/TestWriteDigi.py b/examples/DDDigi/scripts/TestWriteDigi.py index 4f764a32d595c1c2c7239f7a20c512594e733f64..1aa5bb4d0a6c565c962b1feb5a70e79d253431ea 100644 --- a/examples/DDDigi/scripts/TestWriteDigi.py +++ b/examples/DDDigi/scripts/TestWriteDigi.py @@ -30,7 +30,7 @@ def run(): writ.adopt_container_processor(proc, cont) writ.adopt_container_processor(proc, 'MCParticles/MCParticles') digi.check_creation([read, dump]) - digi.run_checked(num_events=10, num_threads=10, parallel=3) + digi.run_checked(num_events=5, num_threads=10, parallel=5) # ---------------------------------------------------------------------------