diff --git a/DDDigi/include/DDDigi/DigiContainerCombine.h b/DDDigi/include/DDDigi/DigiContainerCombine.h index 60393ba2d84c00e15f7262e77dfd7452099a49a8..4351cf9f02b5a3896ca4e996df35679171364373 100644 --- a/DDDigi/include/DDDigi/DigiContainerCombine.h +++ b/DDDigi/include/DDDigi/DigiContainerCombine.h @@ -80,7 +80,8 @@ namespace dd4hep { void have_workers(size_t len) const; /// Combine selected containers to one single deposit container - std::size_t combine_containers(DigiEvent& event, + std::size_t combine_containers(DigiContext& context, + DigiEvent& event, DataSegment& inputs, DataSegment& outputs) const; diff --git a/DDDigi/include/DDDigi/DigiContainerProcessor.h b/DDDigi/include/DDDigi/DigiContainerProcessor.h index 6cfaf3ff1f16b5fe4e82736b3b262c4664f8eb67..c615e70fee9ea1a3abec44add3deeaefae2e40c1 100644 --- a/DDDigi/include/DDDigi/DigiContainerProcessor.h +++ b/DDDigi/include/DDDigi/DigiContainerProcessor.h @@ -171,8 +171,8 @@ namespace dd4hep { }; using worker_t = DigiParallelWorker<processor_t, work_t>; using workers_t = DigiParallelWorkers<worker_t>; - using reg_workers_t = std::map<Key, worker_t*>; - using reg_processors_t = std::map<Key, processor_t*>; + using reg_workers_t = std::map<Key::itemkey_type, worker_t*>; + using reg_processors_t = std::map<Key::itemkey_type, processor_t*>; friend class DigiParallelWorker<processor_t, work_t>; /// Array of sub-workers @@ -204,7 +204,7 @@ namespace dd4hep { virtual void initialize(); /// Get hold of the registered processor for a given container - worker_t* need_registered_worker(Key item_key) const; + worker_t* need_registered_worker(Key item_key, bool exc=true) const; public: /// Standard constructor diff --git a/DDDigi/include/DDDigi/DigiData.h b/DDDigi/include/DDDigi/DigiData.h index 881a489533ea242a530787f54681932428d2deaa..17ae58f52a281a70dcd771587960296101f562f9 100644 --- a/DDDigi/include/DDDigi/DigiData.h +++ b/DDDigi/include/DDDigi/DigiData.h @@ -358,13 +358,17 @@ namespace dd4hep { /// Disable move constructor EnergyDeposit(EnergyDeposit&& copy) = default; /// Disable copy constructor - EnergyDeposit(const EnergyDeposit& copy) = default; + EnergyDeposit(const EnergyDeposit& copy) = default; /// Default destructor virtual ~EnergyDeposit() = default; /// Disable move assignment EnergyDeposit& operator=(EnergyDeposit&& copy) = default; /// Disable copy assignment - EnergyDeposit& operator=(const EnergyDeposit& copy) = default; + EnergyDeposit& operator=(const EnergyDeposit& copy) = default; + /// Update the deposit using deposit weighting + void update_deposit_weighted(EnergyDeposit&& update); + /// Update the deposit using deposit weighting + void update_deposit_weighted(const EnergyDeposit& update); }; @@ -489,12 +493,6 @@ namespace dd4hep { const_iterator begin() const { return this->data.begin(); } /// End iteration (CONST) const_iterator end() const { return this->data.end(); } - - /** Direct element access by key */ - /// Find entry by cell - //iterator find(CellID cell) { return this->data.find(cell); } - /// Find entry by cell - //const_iterator find(CellID cell) const { return this->data.find(cell); } }; /// Initializing constructor @@ -503,6 +501,76 @@ namespace dd4hep { { } + class ADCValue { + public: + using value_t = uint32_t; + using address_t = uint64_t; + public: + value_t value; + address_t address; + }; + + /// Energy deposit vector definition for digitization + /** Energy deposit vector definition for digitization + * + * \author M.Frank + * \version 1.0 + * \ingroup DD4HEP_DIGITIZATION + */ + class DetectorResponse : public SegmentEntry { + public: + using container_t = std::vector<std::pair<CellID, ADCValue> >; + using iterator = container_t::iterator; + using const_iterator = container_t::const_iterator; + + container_t data { }; + + public: + /// Initializing constructor + DetectorResponse(const std::string& name, Key::mask_type mask); + /// Default constructor + DetectorResponse() = default; + /// Disable move constructor + DetectorResponse(DetectorResponse&& copy) = default; + /// Disable copy constructor + DetectorResponse(const DetectorResponse& copy) = default; + /// Default destructor + virtual ~DetectorResponse() = default; + /// Disable move assignment + DetectorResponse& operator=(DetectorResponse&& copy) = default; + /// Disable copy assignment + DetectorResponse& operator=(const DetectorResponse& copy) = default; + /// Emplace entry + void emplace(CellID cell, ADCValue&& value); + + /// Access container size + std::size_t size() const { return this->data.size(); } + /// Check container if empty + bool empty() const { return this->data.empty(); } + + /** Iteration support */ + /// Begin iteration + iterator begin() { return this->data.begin(); } + /// End iteration + iterator end() { return this->data.end(); } + /// Begin iteration (CONST) + const_iterator begin() const { return this->data.begin(); } + /// End iteration (CONST) + const_iterator end() const { return this->data.end(); } + }; + + /// Initializing constructor + inline DetectorResponse::DetectorResponse(const std::string& nam, Key::mask_type msk) + : SegmentEntry(nam, msk) + { + } + + + /// Emplace entry + inline void DetectorResponse::emplace(CellID cell, ADCValue&& value) { + this->data.emplace_back(cell, std::move(value)); + } + /// Data segment definition (locked map) /** * diff --git a/DDDigi/include/DDDigi/DigiKernel.h b/DDDigi/include/DDDigi/DigiKernel.h index e5984b99a8f2a6b07ed9e08acaf15f44f69f7654..041cf245490e80b4b1a3aa9ebe4003bc0a1064c5 100644 --- a/DDDigi/include/DDDigi/DigiKernel.h +++ b/DDDigi/include/DDDigi/DigiKernel.h @@ -164,10 +164,10 @@ namespace dd4hep { DigiActionSequence& outputAction() const; /// Submit a bunch of actions to be executed in parallel - virtual void submit (ParallelCall*const algorithms[], std::size_t count, void* data, bool parallel=true) const; + virtual void submit (DigiContext& context, ParallelCall*const algorithms[], std::size_t count, void* data, bool parallel=true) const; /// Submit a bunch of actions to be executed in parallel - virtual void submit (const std::vector<ParallelCall*>& algorithms, void* data, bool parallel=true) const; + virtual void submit (DigiContext& context, const std::vector<ParallelCall*>& algorithms, void* data, bool parallel=true) const; /// If running multithreaded: wait until the thread-group finished execution virtual void wait(DigiContext& context) const; diff --git a/DDDigi/include/DDDigi/DigiSegmentProcessor.h b/DDDigi/include/DDDigi/DigiSegmentProcessor.h index cde4ceb93553372d9db67fa464c0703f9bd83179..d768ade556bd28996ea050b887661204a5db0da8 100644 --- a/DDDigi/include/DDDigi/DigiSegmentProcessor.h +++ b/DDDigi/include/DDDigi/DigiSegmentProcessor.h @@ -42,7 +42,25 @@ namespace dd4hep { class DigiSegmentProcessor : public DigiContainerProcessor { public: /// Segmentation split context - DigiSegmentContext segment { }; + using segment_t = DigiSegmentContext; + using deposit_cell_t = std::pair<CellID,EnergyDeposit>; + using predicate_t = std::unary_function<deposit_cell_t, bool>; + + struct accept_all_t : public predicate_t { + accept_all_t() = default; + inline bool operator()(const deposit_cell_t& ) const { + return true; + } + }; + struct accept_segment_t : public predicate_t { + const segment_t& segment; + accept_segment_t(const segment_t& s) : segment(s) {} + inline bool operator()(const deposit_cell_t& depo) const { + return this->segment.matches(depo.first); + } + }; + + segment_t segment { }; protected: /// Define standard assignments and constructors @@ -54,7 +72,7 @@ namespace dd4hep { /// Default destructor virtual ~DigiSegmentProcessor(); /// Main functional callback if specific work is known - virtual void handle_segment(DigiContext& context, work_t& data) const; + virtual void execute(DigiContext& context, work_t& data) const override; }; /// Sequencer class to process parts of a subdetector segmentation data @@ -97,7 +115,7 @@ namespace dd4hep { /// Adopt new parallel worker virtual void adopt_processor(DigiContainerProcessor* action); /// Main functional callback if specific work is known - virtual void handle_segment(DigiContext& context, work_t& work) const; + virtual void execute(DigiContext& context, work_t& work) const override; }; } // End namespace digi diff --git a/DDDigi/include/DDDigi/DigiSegmentationTool.h b/DDDigi/include/DDDigi/DigiSegmentationTool.h index 18db270fa71d8e4d19a2382ae56274e75d2ea413..6dc38300e5f824eca783d303f5e0f21bd9d862c4 100644 --- a/DDDigi/include/DDDigi/DigiSegmentationTool.h +++ b/DDDigi/include/DDDigi/DigiSegmentationTool.h @@ -55,6 +55,9 @@ namespace dd4hep { const std::string& name() const; /// Split field name const char* cname() const; + /// Full identifier (field + id) + std::string identifier() const; + /// Get the identifier of the cell to be split uint32_t split_id(uint64_t cell) const { return int( (cell & this->split_mask) >> this->offset ); diff --git a/DDDigi/plugins/DigiCellMultiplicyCounter.cpp b/DDDigi/plugins/DigiCellMultiplicyCounter.cpp index e00d47980bfe1d79fbe9dba89120c2797ba97230..125c26c5b9265ef9d33e67094c09f654cfe9877e 100644 --- a/DDDigi/plugins/DigiCellMultiplicyCounter.cpp +++ b/DDDigi/plugins/DigiCellMultiplicyCounter.cpp @@ -35,21 +35,21 @@ namespace dd4hep { /// Standard constructor using DigiContainerProcessor::DigiContainerProcessor; - template <typename T> void count_deposits(const T& cont) const { + template <typename T> void count_deposits(const char* tag, const T& cont) const { std::map<CellID, std::size_t> entries; for( const auto& dep : cont ) { CellID cell = dep.first; entries[cell] += 1; } - info("+++ %-32s has %6ld entries and %6ld unique cells", - cont.name.c_str(), cont.size(), entries.size()); + info("%s+++ %-32s has %6ld entries and %6ld unique cells", + tag, cont.name.c_str(), cont.size(), entries.size()); } /// Main functional callback - virtual void execute(DigiContext&, work_t& work) const override final { + virtual void execute(DigiContext& context, work_t& work) const override final { if ( const auto* m = work.get_input<DepositMapping>() ) - count_deposits(*m); + count_deposits(context.event->id(), *m); else if ( const auto* v = work.get_input<DepositVector>() ) - count_deposits(*v); + count_deposits(context.event->id(), *v); else except("Request to handle unknown data type: %s", work.input_type_name().c_str()); } diff --git a/DDDigi/plugins/DigiDepositMapCreator.cpp b/DDDigi/plugins/DigiDepositMapCreator.cpp index 233a1f70a58639504acb22edfefcaadd95880bd7..fd637cb98c65e958b1ffd01c59de98bf17d3cb64 100644 --- a/DDDigi/plugins/DigiDepositMapCreator.cpp +++ b/DDDigi/plugins/DigiDepositMapCreator.cpp @@ -17,7 +17,6 @@ /// Namespace for the AIDA detector description toolkit namespace dd4hep { - /// Namespace for the Digitization part of the AIDA detector description toolkit namespace digi { @@ -36,7 +35,7 @@ namespace dd4hep { /// Standard constructor using DigiContainerProcessor::DigiContainerProcessor; - template <typename T> void create_deposits(const T& cont, work_t& work) const { + template <typename T> void create_deposits(const char* tag, const T& cont, work_t& work) const { Key key(cont.name, work.output.mask); DepositMapping m(cont.name, work.output.mask); std::size_t start = m.size(); @@ -44,15 +43,15 @@ namespace dd4hep { m.data.emplace(dep.first, EnergyDeposit()); std::size_t end = m.size(); work.output.data.put(m.key, std::move(m)); - info("+++ %-32s added %6ld entries (now: %6ld) from mask: %04X to mask: %04X", - cont.name.c_str(), end-start, end, cont.key.mask(), m.key.mask()); + info("%s+++ %-32s added %6ld entries (now: %6ld) from mask: %04X to mask: %04X", + tag, cont.name.c_str(), end-start, end, cont.key.mask(), m.key.mask()); } /// Main functional callback - virtual void execute(DigiContext&, work_t& work) const override final { + virtual void execute(DigiContext& context, work_t& work) const override final { if ( const auto* m = work.get_input<DepositMapping>() ) - create_deposits(*m, work); + create_deposits(context.event->id(), *m, work); else if ( const auto* v = work.get_input<DepositVector>() ) - create_deposits(*v, work); + create_deposits(context.event->id(), *v, work); else except("Request to handle unknown data type: %s", work.input_type_name().c_str()); } diff --git a/DDDigi/plugins/DigiDepositWeightedPosition.cpp b/DDDigi/plugins/DigiDepositWeightedPosition.cpp index 512d13bb7d5b604ef04d070efde33f73e61160de..8a5ae36d48ee6f23c4fe65240a55e60f28109bfa 100644 --- a/DDDigi/plugins/DigiDepositWeightedPosition.cpp +++ b/DDDigi/plugins/DigiDepositWeightedPosition.cpp @@ -12,12 +12,13 @@ //========================================================================== // Framework include files -#include <DDDigi/DigiContext.h> #include <DDDigi/DigiContainerProcessor.h> +/// C/C++ include files +#include <limits> + /// Namespace for the AIDA detector description toolkit namespace dd4hep { - /// Namespace for the Digitization part of the AIDA detector description toolkit namespace digi { @@ -25,34 +26,61 @@ namespace dd4hep { /** Actor to select energy deposits according to the supplied segmentation * * The selected deposits are placed in the output container - * supplied by the arguments. + * supplied by the arguments. Multiple CellIDs will be merged to one single + * deposit, where the merge computes the resulting position and + * momentum according to the contribution of the hits. * * \author M.Frank * \version 1.0 * \ingroup DD4HEP_DIGITIZATION */ class DigiDepositWeightedPosition : public DigiContainerProcessor { + protected: + /// Property: Energy cutoff. No hits will be merged with a deposit smaller + double m_cutoff { std::numeric_limits<double>::epsilon() }; + /// Property: register empty containers + bool m_register_empty_containers { true }; + public: /// Standard constructor - using DigiContainerProcessor::DigiContainerProcessor; + DigiDepositWeightedPosition(const DigiKernel& krnl, const std::string& nam) + : DigiContainerProcessor(krnl, nam) + { + declareProperty("deposit_cutoff", m_cutoff); + declareProperty("m_register_empty_containers", m_register_empty_containers); + } + /// Create deposit mapping with updates on same cellIDs template <typename T> void create_deposits(const T& cont, work_t& work) const { Key key(cont.name, work.output.mask); DepositMapping m(cont.name, work.output.mask); - std::size_t start = m.size(); - for( const auto& dep : cont ) - m.data.emplace(dep.first, EnergyDeposit()); - std::size_t end = m.size(); - work.output.data.put(m.key, std::move(m)); - info("+++ %-32s added %6ld entries (now: %6ld) from mask: %04X to mask: %04X", - cont.name.c_str(), end-start, end, cont.key.mask(), m.key.mask()); + std::size_t dropped = 0UL, updated = 0UL, added = 0UL; + for( const auto& dep : cont ) { + const EnergyDeposit& depo = dep.second; + if ( depo.deposit >= m_cutoff ) { + CellID cell = dep.first; + auto iter = m.data.find(cell); + if ( iter == m.data.end() ) + m.data.emplace(dep.first, depo), ++added; + else + iter->second.update_deposit_weighted(depo), ++updated; + continue; + } + ++dropped; + } + if ( m_register_empty_containers ) { + work.output.data.put(m.key, std::move(m)); + } + info("+++ %-32s added %6ld updated %6ld dropped %6ld entries (now: %6ld) from mask: %04X to mask: %04X", + cont.name.c_str(), added, updated, dropped, m.size(), cont.key.mask(), m.key.mask()); } + /// Main functional callback virtual void execute(DigiContext&, work_t& work) const override final { - if ( const auto* m = work.get_input<DepositMapping>() ) - create_deposits(*m, work); - else if ( const auto* v = work.get_input<DepositVector>() ) + if ( const auto* v = work.get_input<DepositVector>() ) create_deposits(*v, work); + else if ( const auto* m = work.get_input<DepositMapping>() ) + create_deposits(*m, work); else except("Request to handle unknown data type: %s", work.input_type_name().c_str()); } diff --git a/DDDigi/plugins/DigiIPMover.cpp b/DDDigi/plugins/DigiIPMover.cpp index 2a3c25836adc28951a4ef877becff0b455cec77f..0aa07c56e22560eed083a7bd3c75fb1f65c108f1 100644 --- a/DDDigi/plugins/DigiIPMover.cpp +++ b/DDDigi/plugins/DigiIPMover.cpp @@ -22,30 +22,33 @@ namespace dd4hep { /// Namespace for the Digitization part of the AIDA detector description toolkit namespace digi { + /// Actor to move the IP of one single container + /** + * Note: in place movement. Not thread safe for the containers! + * + * \author M.Frank + * \version 1.0 + * \ingroup DD4HEP_DIGITIZATION + */ class DigiIPMover : public DigiContainerProcessor { - DigiAction* m_ip_creator { nullptr }; - std::string m_ip_property; - public: /// Standard constructor DigiIPMover(const DigiKernel& krnl, const std::string& nam) : DigiContainerProcessor(krnl, nam) { - declareProperty("ip_property", m_ip_property); - declareProperty("ip_creator", m_ip_creator); } /// Move IP location of deposits - template <typename T> std::size_t move_deposits(T& cont, const Position& delta) const { - info("+++ %-32s [%6ld] IP: x:%7.3f y:%7.3f z:%7.3f", - cont.name.c_str(), cont.size(), delta.X(), delta.Y(), delta.Z()); + template <typename T> std::size_t move_deposits(const char* tag, T& cont, const Position& delta) const { + info("%s+++ %-32s [%6ld] IP: x:%7.3f y:%7.3f z:%7.3f", + tag, cont.name.c_str(), cont.size(), delta.X(), delta.Y(), delta.Z()); for( auto& dep : cont ) dep.second.position += delta; return cont.size(); } /// Move IP location of MC particles - template <typename T> std::size_t move_particles(T& cont, const Position& delta) const { - info("+++ %-32s [%6ld] IP: x:%7.3f y:%7.3f z:%7.3f", - cont.name.c_str(), cont.size(), delta.X(), delta.Y(), delta.Z()); + template <typename T> std::size_t move_particles(const char* tag, T& cont, const Position& delta) const { + info("%s+++ %-32s [%6ld] IP: x:%7.3f y:%7.3f z:%7.3f", + tag, cont.name.c_str(), cont.size(), delta.X(), delta.Y(), delta.Z()); for( auto& p : cont ) { auto& part = p.second; part.end_position += delta; @@ -54,21 +57,18 @@ namespace dd4hep { return cont.size(); } /// Main functional callback - virtual void execute(DigiContext&, work_t& work) const override { - Position delta; - if ( m_ip_creator ) { - m_ip_creator->property(m_ip_property).value(delta); - if ( auto* m = work.get_input<DepositMapping>() ) - move_deposits(*m, delta); - else if ( auto* v = work.get_input<DepositVector>() ) - move_deposits(*v, delta); - else if ( auto* p = work.get_input<ParticleMapping>() ) - move_particles(*p, delta); - else - except("Request to handle unknown data type: %s", work.input_type_name().c_str()); - return; - } - except("+++ No IP creator action known. Did you set the properties: ip_creator and ip_property?"); + virtual void execute(DigiContext& context, work_t& work) const override { + const char* tag = context.event->id(); + Position delta = property("interaction_point").value<Position>(); + if ( auto* m = work.get_input<DepositMapping>() ) + move_deposits(tag, *m, delta); + else if ( auto* v = work.get_input<DepositVector>() ) + move_deposits(tag, *v, delta); + else if ( auto* p = work.get_input<ParticleMapping>() ) + move_particles(tag, *p, delta); + else + except("%s+++ Request to handle unknown data type: %s", tag, work.input_type_name().c_str()); + return; } }; } // End namespace digi diff --git a/DDDigi/plugins/DigiSegmentDepositExtractor.cpp b/DDDigi/plugins/DigiSegmentDepositExtractor.cpp index 3bb3b4e69d37374c5c9b855941e1ce05de2cec21..bb6a5ebc2529fd32304e1625cd4b492493f06ff5 100644 --- a/DDDigi/plugins/DigiSegmentDepositExtractor.cpp +++ b/DDDigi/plugins/DigiSegmentDepositExtractor.cpp @@ -46,7 +46,7 @@ namespace dd4hep { work.output.data.put(deposits.key, std::move(deposits)); } /// Main functional callback - virtual void handle_segment(DigiContext&, work_t& work) const override final { + virtual void execute(DigiContext&, work_t& work) const override final { if ( segment.matches(work.input.key.key) ) { if ( const auto* m = work.get_input<DepositMapping>() ) copy_deposits(*m, work); diff --git a/DDDigi/plugins/DigiSegmentDepositPrint.cpp b/DDDigi/plugins/DigiSegmentDepositPrint.cpp index 9c3007728d6373a478f9fbea3230b6548eee67e5..a8fa3b1a388275d83e3fd8fea5bdaad063d7e25a 100644 --- a/DDDigi/plugins/DigiSegmentDepositPrint.cpp +++ b/DDDigi/plugins/DigiSegmentDepositPrint.cpp @@ -40,7 +40,7 @@ namespace dd4hep { depo.deposit); } /// Main functional callback - virtual void handle_segment(DigiContext& context, work_t& work) const override final { + virtual void execute(DigiContext& context, work_t& work) const override final { char format[256]; ::snprintf(format, sizeof(format), "%s[%s] %s-id: %%d [processor:%d] Cell: %%016lX mask: %016lX hist:%%4ld hits %%4ld parts. entries deposit: %%f", diff --git a/DDDigi/plugins/DigiSimpleADCResponse.cpp b/DDDigi/plugins/DigiSimpleADCResponse.cpp new file mode 100644 index 0000000000000000000000000000000000000000..029f4ebc808c9644b8a0d24d3b77f9c9cc20ade9 --- /dev/null +++ b/DDDigi/plugins/DigiSimpleADCResponse.cpp @@ -0,0 +1,86 @@ +//========================================================================== +// 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 <DDDigi/DigiSegmentProcessor.h> + +/// C/C++ include files +#include <cmath> +#include <limits> + +/// Namespace for the AIDA detector description toolkit +namespace dd4hep { + /// Namespace for the Digitization part of the AIDA detector description toolkit + namespace digi { + + class DigiSimpleADCResponse : public DigiSegmentProcessor { + std::string m_name_postfix { ".adc" }; + double m_use_segmentation { false }; + double m_signal_cutoff { std::numeric_limits<double>::epsilon() }; + double m_signal_saturation { std::numeric_limits<double>::max() }; + std::size_t m_adc_resolution { 1024 }; + + public: + /// Standard constructor + DigiSimpleADCResponse(const DigiKernel& krnl, const std::string& nam) + : DigiSegmentProcessor(krnl, nam) + { + declareProperty("cutoff", m_signal_cutoff); + declareProperty("saturation", m_signal_saturation); + declareProperty("adc_resolution", m_adc_resolution); + declareProperty("name_postfix", m_name_postfix); + } + + /// Create container with ADC counts and register it to the output segment + template <typename T, typename P> + void create_adc_counts(const char* tag, const T& input, work_t& work, const P& predicate) const { + std::string postfix = m_use_segmentation ? "."+segment.identifier() : std::string(); + std::string outname = input.name + postfix + m_name_postfix; + DetectorResponse response(outname, work.output.mask); + for( const auto& dep : input ) { + if ( predicate(dep) ) { + CellID cell = dep.first; + const auto& depo = dep.second; + ADCValue::value_t adc_count = std::round((depo.deposit * m_adc_resolution) / m_signal_saturation); + response.emplace(cell, {adc_count, ADCValue::address_t(cell)}); + } + } + info("%s+++ %-32s %6ld ADC values. Input: %-32s %6ld deposits", tag, + outname.c_str(), response.size(), input.name.c_str(), input.size()); + work.output.data.put(response.key, std::move(response)); + } + /// Create container with ADC counts and register it to the output segment + template <typename P> + void create_adc_counts(DigiContext& context, work_t& work, const P& predicate) const { + const char* tag = context.event->id(); + if ( const auto* m = work.get_input<DepositMapping>() ) + create_adc_counts(tag, *m, work, predicate); + else if ( const auto* v = work.get_input<DepositVector>() ) + create_adc_counts(tag, *v, work, predicate); + else + except("%s+++ Request to handle unknown data type: %s", + tag, work.input_type_name().c_str()); + } + /// Main functional callback + virtual void execute(DigiContext& context, work_t& work) const override final { + if ( !m_use_segmentation ) + create_adc_counts(context, work, accept_all_t()); + else if ( segment.matches(work.input.key.key) ) + create_adc_counts(context, work, accept_segment_t(segment)); + } + }; + } // End namespace digi +} // End namespace dd4hep + +#include <DDDigi/DigiFactories.h> +DECLARE_DIGIACTION_NS(dd4hep::digi,DigiSimpleADCResponse) diff --git a/DDDigi/python/DDDigiDict.C b/DDDigi/python/DDDigiDict.C index 9d39b3223ee120afbb98be209aea0feaf1aed0ad..7458ef7a9bde75795cb21e512ece78c447937c73 100644 --- a/DDDigi/python/DDDigiDict.C +++ b/DDDigi/python/DDDigiDict.C @@ -50,58 +50,106 @@ namespace dd4hep { template <typename VAL> int add_action_property(DigiAction* action, const std::string& name, VAL value); -#define ACTIONHANDLE(x) \ - struct x##Handle { \ - Digi##x* action; \ - explicit x##Handle(Digi##x* a) : action(a) { if ( action ) action->addRef();} \ - x##Handle(const x##Handle& h) : action(h.action) { if ( action ) action->addRef();} \ - ~x##Handle() { if ( action) action->release();} \ - Digi##x* release() { Digi##x* tmp = action; action=0; return tmp; } \ - operator dd4hep::digi::Digi##x* () const { return action; } \ - Digi##x* operator->() const { return action; } \ - Digi##x* get() const { return action; } \ - Digi##x* I_am_a_ROOT_interface_handle() const { return action; } \ - KernelHandle kernel() const { \ - auto* k = const_cast<DigiKernel*>(action->kernel()); \ - return KernelHandle(k); \ - } \ - } - - ACTIONHANDLE(Action); + struct ActionHandle { + DigiAction* action; + explicit ActionHandle(DigiAction* a) : action(a) { + if (action) action->addRef(); + } + ActionHandle(const ActionHandle& h) : action(h.action) { + if (action) action->addRef(); + } + ~ActionHandle() { + if (action) action->release(); + } + ActionHandle& operator=(const ActionHandle& h) { + if ( h.action ) h.action->addRef(); + if ( action ) action->release(); + action = h.action; + return *this; + } + DigiAction* release() { + DigiAction* tmp = action; + action=0; + return tmp; + } + operator dd4hep::digi::DigiAction* () const { return action; } + DigiAction* operator->() const { return action; } + DigiAction* get() const { return action; } + DigiAction* I_am_a_ROOT_interface_handle() const { return action; } + KernelHandle kernel() const { + auto* k = const_cast<DigiKernel*>(action->kernel()); + return KernelHandle(k); + } + }; struct PropertyResult { - std::string data; - int status; - PropertyResult() : status(0) {} - PropertyResult(const std::string& d, int s) : data(d), status(s) {} - PropertyResult(const PropertyResult& c) : data(c.data), status(c.status) {} - ~PropertyResult() {} + public: + std::string data {}; + int status { 0 }; + PropertyResult() = default; + PropertyResult(const std::string& d, int s); + PropertyResult(const PropertyResult& c) = default; + ~PropertyResult() = default; }; + + inline PropertyResult::PropertyResult(const std::string& d, int s) + : data(d), status(s) + { + } struct DigiActionCreation { - template <typename H,typename T> static - H cr(KernelHandle& kernel, const std::string& name_type) { - T action(*kernel.get(),name_type); - H handle(action.get()); - return handle; - } - template <typename T,typename H> static H* cst(T* in) { + template <typename H> static H* cst(DigiAction* in) { auto* out = dynamic_cast<H*>(in); if ( out ) return out; if ( in ) except("DigiAction","Invalid cast of action '%s' [type:%s] to type %s!", - in->c_name(), typeName(typeid(T)).c_str(), typeName(typeid(H)).c_str()); + in->c_name(), typeName(typeid(DigiAction)).c_str(), typeName(typeid(H)).c_str()); except("DigiAction","Invalid cast of NULL [type:%s] to type %s!", - typeName(typeid(T)).c_str(), typeName(typeid(H)).c_str()); + typeName(typeid(DigiAction)).c_str(), typeName(typeid(H)).c_str()); return nullptr; } + static KernelHandle createKernel(DigiAction* action) { + auto* k = const_cast<DigiKernel*>(action->kernel()); + return KernelHandle(k); + } + + static ActionHandle createAction(KernelHandle& kernel, const std::string& name_type) { + DigiHandle<DigiAction> action(*kernel.get(),name_type); + return ActionHandle(action.get()); + } + static DigiAction* toAction(DigiAction* f) { return f; } + static DigiAction* toAction(ActionHandle f) { return f.action; } + + static DigiEventAction* toEventAction(DigiAction* a) { return cst<DigiEventAction>(a); } + static DigiContainerProcessor* toContainerProcessor(DigiAction* a) { return cst<DigiContainerProcessor>(a); } + + /// Access kernel property + static PropertyResult getPropertyKernel(DigiKernel* kernel, const std::string& name) { + if ( kernel->hasProperty(name) ) { + return PropertyResult(kernel->property(name).str(),1); + } + return PropertyResult("",0); + } + + /// Set kernel property + static int setPropertyKernel(DigiKernel* kernel, const std::string& name, const std::string& value) { + if ( kernel->hasProperty(name) ) { + kernel->property(name).str(value); + return 1; + } + return 0; + } + + /// Access DigiAction property static PropertyResult getProperty(DigiAction* action, const std::string& name) { if ( action->hasProperty(name) ) { return PropertyResult(action->property(name).str(),1); } return PropertyResult("",0); } + + /// Set DigiAction property static int setProperty(DigiAction* action, const std::string& name, const std::string& value) { if ( action->hasProperty(name) ) { action->property(name).str(value); @@ -136,74 +184,6 @@ namespace dd4hep { pr.str(value); return add_action_property(action, name, pos); } - //ADD_PROPERTY(PositionProperty,dd4hep::Position) - - static PropertyResult getPropertyKernel(DigiKernel* kernel, const std::string& name) { - if ( kernel->hasProperty(name) ) { - return PropertyResult(kernel->property(name).str(),1); - } - return PropertyResult("",0); - } - static int setPropertyKernel(DigiKernel* kernel, const std::string& name, const std::string& value) { - if ( kernel->hasProperty(name) ) { - kernel->property(name).str(value); - return 1; - } - return 0; - } - - static KernelHandle createKernel(DigiAction* action) { - auto* k = const_cast<DigiKernel*>(action->kernel()); - return KernelHandle(k); - } - static ActionHandle createAction(KernelHandle& kernel, const std::string& name_type) - { return cr<ActionHandle,DigiHandle<DigiAction> >(kernel,name_type); } - static DigiAction* toAction(DigiAction* f) { return f; } - static DigiAction* toAction(ActionHandle f) { return f.action; } - - static DigiEventAction* toEventAction(DigiAction* a) { return cst<DigiAction,DigiEventAction>(a); } - static DigiContainerProcessor* toContainerProcessor(DigiAction* a) { return cst<DigiAction,DigiContainerProcessor>(a); } - -#if 0 - static DigiEventAction* toEventAction(DigiEventAction* a) { return a; } - ACTIONHANDLE(SignalProcessor); - ACTIONHANDLE(EventAction); - ACTIONHANDLE(InputAction); - ACTIONHANDLE(SegmentProcessor); - ACTIONHANDLE(ContainerProcessor); - ACTIONHANDLE(ActionSequence); - ACTIONHANDLE(Synchronize); - - static EventActionHandle createEventAction(KernelHandle& kernel, const std::string& name_type) - { return cr<EventActionHandle,DigiHandle<DigiEventAction> >(kernel,name_type); } - - static InputActionHandle createInputAction(KernelHandle& kernel, const std::string& name_type) - { return cr<InputActionHandle,DigiHandle<DigiInputAction> >(kernel,name_type); } - - static SegmentProcessorHandle createSegmentProcessor(KernelHandle& kernel, const std::string& name_type) - { return cr<SegmentProcessorHandle,DigiHandle<DigiSegmentProcessor> >(kernel,name_type); } - - static ActionSequenceHandle createSequence(KernelHandle& kernel, const std::string& name_type) - { return cr<ActionSequenceHandle,DigiHandle<DigiActionSequence> >(kernel,name_type); } - - static SynchronizeHandle createSync(KernelHandle& kernel, const std::string& name_type) - { return cr<SynchronizeHandle,DigiHandle<DigiSynchronize> >(kernel,name_type); } - - static DigiAction* toAction(DigiEventAction* f) { return f; } - static DigiAction* toAction(DigiInputAction* f) { return f; } - static DigiAction* toAction(DigiSegmentProcessor* f) { return f; } - static DigiAction* toAction(DigiContainerProcessor* f) { return f; } - static DigiAction* toAction(DigiActionSequence* f) { return f; } - static DigiAction* toAction(DigiSynchronize* f) { return f; } - static DigiAction* toAction(DigiSignalProcessor* f) { return f; } - - static DigiAction* toAction(EventActionHandle f) { return f.action; } - static DigiAction* toAction(InputActionHandle f) { return f.action; } - static DigiAction* toAction(SegmentProcessorHandle f) { return f.action; } - static DigiAction* toAction(ActionSequenceHandle f) { return f.action; } - static DigiAction* toAction(SynchronizeHandle f) { return f.action; } - static DigiAction* toAction(SignalProcessorHandle f) { return f.action; } -#endif }; } } @@ -258,11 +238,4 @@ using namespace std; #pragma link C++ class dd4hep::digi::DigiEvent; -//#pragma link C++ class dd4hep::digi::EventActionHandle; -//#pragma link C++ class dd4hep::digi::InputActionHandle; -//#pragma link C++ class dd4hep::digi::SegmentProcessorHandle; -//#pragma link C++ class dd4hep::digi::ActionSequenceHandle; -//#pragma link C++ class dd4hep::digi::SignalProcessorHandle; -//#pragma link C++ class dd4hep::digi::SynchronizeHandle; - #endif diff --git a/DDDigi/python/dddigi.py b/DDDigi/python/dddigi.py index a525ba70aa67dceceacf4385e4f413909c3a4ff5..e36dffcdb2521f8528e8fa5f468b064b9e21703b 100644 --- a/DDDigi/python/dddigi.py +++ b/DDDigi/python/dddigi.py @@ -156,41 +156,50 @@ def _setKernelProperty(self, name, value): return msg = 'DigiKernel::SetProperty [Unhandled]: Cannot set Kernel.' + name + ' = ' + str(value) raise KeyError(msg) +# --------------------------------------------------------------------------- +def _get_action(self): + return Interface.toAction(self) + #if hasattr(self, 'I_am_a_ROOT_interface_handle'): + # return Interface.toAction(self.get()) + #return self # --------------------------------------------------------------------------- + + def _adopt_property(self, action, foreign_name, local_name): - Interface.adoptProperty(self.get(), action, str(foreign_name), str(local_name)) + proc = _get_action(action) + _get_action(self).adopt_property(proc, str(foreign_name), str(local_name)) # --------------------------------------------------------------------------- def _add_property(self, name, value): - Interface.addProperty(self.get(), str(name), value) + Interface.addProperty(_get_action(self), str(name), value) # --------------------------------------------------------------------------- def _add_position_property(self, name, value): - Interface.addPositionProperty(self.get(), str(name), str(value)) + Interface.addPositionProperty(_get_action(self), str(name), str(value)) # --------------------------------------------------------------------------- def _add_set_property(self, name, value): - Interface.addSetProperty(self.get(), str(name), value) + Interface.addSetProperty(_get_action(self), str(name), value) # --------------------------------------------------------------------------- def _add_list_property(self, name, value): - Interface.addListProperty(self.get(), str(name), value) + Interface.addListProperty(_get_action(self), str(name), value) # --------------------------------------------------------------------------- def _add_vector_property(self, name, value): - Interface.addVectorProperty(self.get(), str(name), value) + Interface.addVectorProperty(_get_action(self), str(name), value) # --------------------------------------------------------------------------- def _add_mapped_property(self, name, value): - Interface.addMappedProperty(self.get(), str(name), value) + Interface.addMappedProperty(_get_action(self), str(name), value) # --------------------------------------------------------------------------- @@ -203,47 +212,15 @@ Kernel.__getattr__ = _getKernelProperty Kernel.__setattr__ = _setKernelProperty Kernel.terminate = _kernel_terminate # --------------------------------------------------------------------------- -ActionHandle = digi.ActionHandle -ActionHandle.adopt_property = _adopt_property -ActionHandle.add_property = _add_property -ActionHandle.add_position_property = _add_position_property -ActionHandle.add_set_property = _add_set_property -ActionHandle.add_list_property = _add_list_property -ActionHandle.add_vector_property = _add_vector_property -ActionHandle.add_mapped_property = _add_mapped_property -# --------------------------------------------------------------------------- - - -def _get_action(self): - if hasattr(self, 'I_am_a_ROOT_interface_handle'): - return Interface.toAction(self.get()) - return self -# --------------------------------------------------------------------------- -def _get_container_action(self): +def _get_container_processor(self): if hasattr(self, 'I_am_a_ROOT_interface_handle'): - return Interface.toContainerAction(self.get()) + return Interface.toContainerProcessor(self.get()) return self # --------------------------------------------------------------------------- -def TestAction(kernel, nam, sleep=0): - obj = Interface.createAction(kernel, str('DigiTestAction/' + nam)) - if sleep != 0: - obj.sleep = sleep - return obj -# --------------------------------------------------------------------------- - - -def Action(kernel, nam, **options): - action = Interface.createAction(kernel, str(nam)) - for option in options.items(): - setattr(action, option[0], option[1]) - return action -# --------------------------------------------------------------------------- - - def _default_adopt(self, action): getattr(self, '__adopt')(action.get()) # --------------------------------------------------------------------------- @@ -258,7 +235,7 @@ def _adopt_event_action(self, action): def _adopt_processor_action(self, action, container): " Helper to convert DigiActions objects to DigiEventAction " attr = getattr(self, 'adopt_processor') - proc = _get_container_action(self) + proc = _get_container_processor(action) attr(proc, container) # print('ContainerProcessor succesfully adopted') # --------------------------------------------------------------------------- @@ -298,7 +275,7 @@ def _get(self, name): return getattr(self.action, name) elif a.__class__ != self.__class__ and hasattr(a, name): return getattr(a, name) - msg = 'DDDigiAction::GetProperty [Unhandled]: Cannot access property ' + a.name() + '.' + name + msg = 'DigiAction::GetProperty [Unhandled]: Cannot access property ' + a.name() + '.' + name raise KeyError(msg) # --------------------------------------------------------------------------- @@ -311,7 +288,7 @@ def _set(self, name, value): value = dd4hep.unicode_2_string(value) if Interface.setProperty(a, name, value): return - msg = 'DDDigiAction::SetProperty [Unhandled]: Cannot set ' + a.name() + '.' + name + ' = ' + value + msg = 'DigiAction::SetProperty [Unhandled]: Cannot set ' + a.name() + '.' + name + ' = ' + value raise KeyError(msg) # --------------------------------------------------------------------------- @@ -327,13 +304,19 @@ def _props(obj, **extensions): # --------------------------------------------------------------------------- -def _props2(obj, **extensions): - cls = getattr(current, obj) - for extension in extensions.items(): - setattr(cls, extension[0], extension[1]) - cls.__getattr__ = _get - cls.__setattr__ = _set - return cls +def TestAction(kernel, nam, sleep=0): + obj = Interface.createAction(kernel, str('DigiTestAction/' + nam)) + if sleep != 0: + obj.sleep = sleep + return obj +# --------------------------------------------------------------------------- + + +def Action(kernel, nam, **options): + action = Interface.createAction(kernel, str(nam)) + for option in options.items(): + setattr(action, option[0], option[1]) + return action # --------------------------------------------------------------------------- @@ -345,7 +328,14 @@ _import_class('digi', 'DigiContext') _import_class('digi', 'DigiAction') _import_class('digi', 'DigiEventAction') _import_class('digi', 'DigiInputAction') -_props('ActionHandle') +_props('ActionHandle', + adopt_property=_adopt_property, + add_property=_add_property, + add_position_property=_add_position_property, + add_set_property=_add_set_property, + add_list_property=_add_list_property, + add_vector_property=_add_vector_property, + add_mapped_property=_add_mapped_property) _props('DigiSynchronize', adopt_action=_adopt_sequence_action) _props('DigiActionSequence', adopt_action=_adopt_sequence_action) _props('DigiParallelActionSequence', adopt_action=_adopt_sequence_action) diff --git a/DDDigi/src/DigiContainerCombine.cpp b/DDDigi/src/DigiContainerCombine.cpp index eaa84a2ad65f50628f8add3351a79e5aa2db00a3..2fa76e7eeb614528e74ff62d91e523e0a5a01df8 100644 --- a/DDDigi/src/DigiContainerCombine.cpp +++ b/DDDigi/src/DigiContainerCombine.cpp @@ -209,14 +209,15 @@ bool DigiContainerCombine::use_key(Key key) const { } /// Combine selected containers to one single deposit container -std::size_t DigiContainerCombine::combine_containers(DigiEvent& event, +std::size_t DigiContainerCombine::combine_containers(DigiContext& context, + DigiEvent& event, DataSegment& inputs, DataSegment& outputs) const { work_definition_t def(this, event, inputs, outputs); if ( m_parallel ) { have_workers(def.items.size()); - m_kernel.submit(m_workers.get_group(), def.items.size(), &def); + m_kernel.submit(context, m_workers.get_group(), def.items.size(), &def); } else { def.merge_all(); @@ -234,5 +235,5 @@ void DigiContainerCombine::execute(DigiContext& context) const { auto& event = *context.event; auto& inputs = event.get_segment(m_input); auto& outputs = event.get_segment(m_output); - combine_containers(event, inputs, outputs); + combine_containers(context, event, inputs, outputs); } diff --git a/DDDigi/src/DigiContainerProcessor.cpp b/DDDigi/src/DigiContainerProcessor.cpp index 02b1af906501c3c8035073448af2e5cd27e9a96e..87adb9f3932d4a437e2873ebe83dcbfdacee8efd 100644 --- a/DDDigi/src/DigiContainerProcessor.cpp +++ b/DDDigi/src/DigiContainerProcessor.cpp @@ -124,8 +124,8 @@ void DigiContainerSequence::adopt_processor(DigiContainerProcessor* action) { } /// Main functional callback if specific work is known -void DigiContainerSequence::execute(DigiContext& /* context */, work_t& work) const { - m_kernel.submit(m_workers.get_group(), m_workers.size(), &work, m_parallel); +void DigiContainerSequence::execute(DigiContext& context, work_t& work) const { + m_kernel.submit(context, m_workers.get_group(), m_workers.size(), &work, m_parallel); } /// Worker adaptor for caller DigiContainerSequence @@ -155,12 +155,10 @@ DigiContainerSequenceAction::~DigiContainerSequenceAction() { /// Initialization callback void dd4hep::digi::DigiContainerSequenceAction::initialize() { - size_t count = 0; for( auto& ent : m_registered_processors ) { Key key = ent.first; - key.set_mask(m_input_mask); - worker_t* w = new worker_t(ent.second, count++); - m_registered_workers.emplace(key, w); + worker_t* w = new worker_t(ent.second, m_registered_workers.size()); + m_registered_workers.emplace(key.item(), w); m_workers.insert(w); } } @@ -170,7 +168,7 @@ void DigiContainerSequenceAction::adopt_processor(DigiContainerProcessor* action const std::string& container) { Key key(container, 0x0); - auto it = m_registered_processors.find(key); + auto it = m_registered_processors.find(key.item()); if ( it != m_registered_processors.end() ) { if ( action != it->second ) { except("+++ The action %s was already registered to mask:%04X container:%s!", @@ -183,9 +181,9 @@ void DigiContainerSequenceAction::adopt_processor(DigiContainerProcessor* action return; } action->addRef(); - m_registered_processors.emplace(key, action); - info("+++ Adding processor: %s for container: [%016lX] %s", - action->c_name(), key.key, container.c_str()); + m_registered_processors.emplace(key.item(), action); + info("+++ Adding processor: %s for container: [%08X] %s", + action->c_name(), key.item(), container.c_str()); } /// Adopt new parallel worker acting on multiple containers @@ -200,14 +198,16 @@ void DigiContainerSequenceAction::adopt_processor(DigiContainerProcessor* action /// Get hold of the registered processor for a given container DigiContainerSequenceAction::worker_t* -DigiContainerSequenceAction::need_registered_worker(Key item_key) const { +DigiContainerSequenceAction::need_registered_worker(Key item_key, bool exc) const { Key key; key.set_item(item_key.item()); - auto it = m_registered_workers.find(key.item()); + auto it = m_registered_workers.find(item_key.item()); if ( it != m_registered_workers.end() ) { return it->second; } - except("No worker registered for input: %016lX", key.key); + if ( exc ) { + except("No worker registered for input: %08X", item_key.item()); + } return nullptr; } @@ -225,16 +225,14 @@ void DigiContainerSequenceAction::execute(DigiContext& context) const { for( auto& i : inputs ) { Key key(i.first); if ( key.mask() == m_input_mask ) { - auto it = m_registered_workers.find(key.item()); - if ( it != m_registered_workers.end() ) { - worker_t* w = it->second; + if ( worker_t* w = need_registered_worker(key, false) ) { event_workers.emplace_back(w); - args.input_items[w->options] = { key, &(i.second) }; + args.input_items[w->options] = { key, &i.second }; } } } if ( !event_workers.empty() ) { - m_kernel.submit(&event_workers.at(0), event_workers.size(), &args, m_parallel); + m_kernel.submit(context, &event_workers.at(0), event_workers.size(), &args, m_parallel); } } @@ -308,7 +306,7 @@ void DigiMultiContainerProcessor::execute(DigiContext& context) const { auto& outputs = event.get_segment(m_output_segment); output_t output { m_output_mask, outputs }; work_t args { context, work_items, output, properties(), *this }; - m_kernel.submit(m_workers.get_group(), m_workers.size(), &args, m_parallel); + m_kernel.submit(context, m_workers.get_group(), m_workers.size(), &args, m_parallel); } } diff --git a/DDDigi/src/DigiData.cpp b/DDDigi/src/DigiData.cpp index b0038d7c9695faec00eee855025e14174150b01a..7cdf283b01936d589239b7ff539181122a35ca2b 100644 --- a/DDDigi/src/DigiData.cpp +++ b/DDDigi/src/DigiData.cpp @@ -62,6 +62,30 @@ std::string Key::key_name(const Key& k) { return "UNKNOWN"; } +/// Update the deposit using deposit weighting +void EnergyDeposit::update_deposit_weighted(const EnergyDeposit& upda) { + double sum = deposit + upda.deposit; + Position pos = ((deposit / sum) * position) + ((upda.deposit / sum) * upda.position); + Direction mom = ((deposit / sum) * momentum) + ((upda.deposit / sum) * upda.momentum); + position = pos; + momentum = mom; + deposit = sum; + hit_history.insert(hit_history.end(), upda.hit_history.begin(), upda.hit_history.end()); + particle_history.insert(particle_history.end(), upda.particle_history.begin(), upda.particle_history.end()); +} + +/// Update the deposit using deposit weighting +void EnergyDeposit::update_deposit_weighted(EnergyDeposit&& upda) { + double sum = deposit + upda.deposit; + Position pos = ((deposit / sum) * position) + ((upda.deposit / sum) * upda.position); + Direction mom = ((deposit / sum) * momentum) + ((upda.deposit / sum) * upda.momentum); + position = pos; + momentum = mom; + deposit = sum; + hit_history.insert(hit_history.end(), upda.hit_history.begin(), upda.hit_history.end()); + particle_history.insert(particle_history.end(), upda.particle_history.begin(), upda.particle_history.end()); +} + /// Merge new deposit map onto existing map std::size_t DepositVector::merge(DepositVector&& updates) { std::size_t update_size = updates.size(); @@ -105,23 +129,14 @@ std::size_t DepositVector::insert(const DepositMapping& updates) { /// Merge new deposit map onto existing map std::size_t DepositMapping::merge(DepositVector&& updates) { std::size_t update_size = updates.size(); - for( auto& c : updates ) { - data.emplace(std::move(c)); - CellID cell = c.first; - EnergyDeposit& depo = c.second; - auto iter = data.find(cell); - if ( iter == data.end() ) { - data.emplace(cell, std::move(depo)); - continue; - } - auto& to_update = iter->second; - to_update.deposit += depo.deposit; - to_update.hit_history.insert(to_update.hit_history.end(), - depo.hit_history.begin(), - depo.hit_history.end()); - to_update.particle_history.insert(to_update.particle_history.end(), - depo.particle_history.begin(), - depo.particle_history.end()); + for( auto& dep : updates ) { + EnergyDeposit& depo = dep.second; + CellID cell = dep.first; + auto iter = data.find(cell); + if ( iter == data.end() ) + data.emplace(dep.first, std::move(depo)); + else + iter->second.update_deposit_weighted(std::move(depo)); } return update_size; } @@ -129,25 +144,14 @@ std::size_t DepositMapping::merge(DepositVector&& updates) { /// Merge new deposit map onto existing map std::size_t DepositMapping::merge(DepositMapping&& updates) { std::size_t update_size = updates.size(); - for( auto& c : updates ) { - data.emplace(std::move(c)); -#if 0 - CellID cell = c.first; - EnergyDeposit& depo = c.second; - auto iter = data.find(cell); - if ( iter == data.end() ) { - data.emplace(cell, std::move(depo)); - continue; - } - auto& to_update = iter->second; - to_update.deposit += depo.deposit; - to_update.hit_history.insert(to_update.hit_history.end(), - depo.hit_history.begin(), - depo.hit_history.end()); - to_update.particle_history.insert(to_update.particle_history.end(), - depo.particle_history.begin(), - depo.particle_history.end()); -#endif + for( auto& dep : updates ) { + const EnergyDeposit& depo = dep.second; + CellID cell = dep.first; + auto iter = data.find(cell); + if ( iter == data.end() ) + data.emplace(dep.first, std::move(depo)); + else + iter->second.update_deposit_weighted(std::move(depo)); } return update_size; } @@ -235,6 +239,7 @@ template <typename DATA> bool DataSegment::put(Key key, DATA&& value) { template bool DataSegment::put(Key key, DepositVector&& data); template bool DataSegment::put(Key key, DepositMapping&& data); template bool DataSegment::put(Key key, ParticleMapping&& data); +template bool DataSegment::put(Key key, DetectorResponse&& data); /// Remove data item from segment bool DataSegment::erase(Key key) { diff --git a/DDDigi/src/DigiKernel.cpp b/DDDigi/src/DigiKernel.cpp index 33cd1c5c6aa9b27b087a0c58835f55352170f33e..8afe11f7c2e4d131d00f3c9748485d1d8293820d 100644 --- a/DDDigi/src/DigiKernel.cpp +++ b/DDDigi/src/DigiKernel.cpp @@ -365,26 +365,27 @@ DigiActionSequence& DigiKernel::outputAction() const { } /// Submit a bunch of actions to be executed in parallel -void DigiKernel::submit (ParallelCall*const algorithms[], std::size_t count, void* context, bool parallel) const { +void DigiKernel::submit (DigiContext& context, ParallelCall*const algorithms[], std::size_t count, void* data, bool parallel) const { + const char* tag = context.event->id(); #ifdef DD4HEP_USE_TBB bool para = parallel && (internals->tbb_init && internals->num_threads > 0); if ( para ) { tbb::task_group que; - printout(INFO,"DigiKernel","+++ Executing chunk of %ld execution entries in parallel", count); + printout(INFO,"DigiKernel","%s+++ Executing chunk of %ld execution entries in parallel", tag, count); for( std::size_t i=0; i<count; ++i) - que.run( Wrapper<ParallelCall,void*>(algorithms[i], context) ); + que.run( Wrapper<ParallelCall,void*>(algorithms[i], data) ); que.wait(); return; } #endif - printout(INFO,"DigiKernel","+++ Executing chunk of %ld execution entries sequentially", count); + printout(INFO,"DigiKernel","%s+++ Executing chunk of %ld execution entries sequentially", tag, count); for( std::size_t i=0; i<count; ++i) - algorithms[i]->execute(context); + algorithms[i]->execute(data); } /// Submit a bunch of actions to be executed in parallel -void DigiKernel::submit (const std::vector<ParallelCall*>& algorithms, void* data, bool parallel) const { - this->submit(&algorithms[0], algorithms.size(), data, parallel); +void DigiKernel::submit (DigiContext& context, const std::vector<ParallelCall*>& algorithms, void* data, bool parallel) const { + this->submit(context, &algorithms[0], algorithms.size(), data, parallel); } void DigiKernel::wait(DigiContext& context) const { @@ -418,9 +419,10 @@ void DigiKernel::notify(std::unique_ptr<DigiContext>&& context) { /// Notify kernel that the execution of one single event finished void DigiKernel::notify(std::unique_ptr<DigiContext>&& context, const std::exception& e) { + const char* tag = context->event->id(); internals->stop = true; - printout(ERROR,"DigiKernel","+++ Exception during event processing [Shall stop the event loop]"); - printout(ERROR,"DigiKernel"," -> %s", e.what()); + printout(ERROR,"DigiKernel","%s+++ Exception during event processing [Shall stop the event loop]", tag); + printout(ERROR,"DigiKernel","%s -> %s", tag, e.what()); notify(std::move(context)); } @@ -431,8 +433,7 @@ int DigiKernel::run() { internals->events_finished = 0; internals->events_submitted = 0; internals->events_todo = internals->numEvents; - printout(INFO, - "DigiKernel","+++ Total number of events: %d",internals->numEvents); + printout(INFO,"DigiKernel","+++ Total number of events: %d",internals->numEvents); #ifdef DD4HEP_USE_TBB if ( !internals->tbb_init && internals->num_threads>=0 ) { using ctrl_t = tbb::global_control; diff --git a/DDDigi/src/DigiSegmentProcessor.cpp b/DDDigi/src/DigiSegmentProcessor.cpp index 029753a8c2d1497d7af433a6e4a334e53d1a1387..9ce3a2e120f28bca87700d616d1ced13b52d2848 100644 --- a/DDDigi/src/DigiSegmentProcessor.cpp +++ b/DDDigi/src/DigiSegmentProcessor.cpp @@ -31,14 +31,14 @@ DigiSegmentProcessor::~DigiSegmentProcessor() { } /// Main functional callback if specific work is known -void DigiSegmentProcessor::handle_segment(DigiContext& /* context */, work_t& /* args */) const { +void DigiSegmentProcessor::execute(DigiContext& /* context */, work_t& /* args */) const { } template <> void DigiParallelWorker<DigiSegmentProcessor, DigiSegmentSequence::work_t, dd4hep::VolumeID>::execute(void* args) const { calldata_t* work = reinterpret_cast<calldata_t*>(args); - action->handle_segment(work->context, *work); + action->execute(work->context, *work); } /// Standard constructor @@ -69,6 +69,6 @@ void DigiSegmentSequence::adopt_processor(DigiContainerProcessor* action) { } /// Main functional callback -void DigiSegmentSequence::handle_segment(DigiContext& /* context */, work_t& work) const { - m_kernel.submit(m_workers.get_group(), m_workers.size(), &work, m_parallel); +void DigiSegmentSequence::execute(DigiContext& context, work_t& work) const { + m_kernel.submit(context, m_workers.get_group(), m_workers.size(), &work, m_parallel); } diff --git a/DDDigi/src/DigiSegmentSplitter.cpp b/DDDigi/src/DigiSegmentSplitter.cpp index ab2a1db77e6635712e52399031cb162e8477ea42..b4236d508e26e70f38b9e40e7057fee53572047e 100644 --- a/DDDigi/src/DigiSegmentSplitter.cpp +++ b/DDDigi/src/DigiSegmentSplitter.cpp @@ -118,14 +118,14 @@ void DigiSegmentSplitter::adopt_processor(DigiContainerProcessor* action) { } /// Main functional callback -void DigiSegmentSplitter::execute(DigiContext& /* context */, work_t& work) const { +void DigiSegmentSplitter::execute(DigiContext& context, work_t& work) const { Key key = work.input_key(); Key unmasked_key(key.item()); if ( std::find(m_keys.begin(), m_keys.end(), unmasked_key) != m_keys.end() ) { if ( work.has_input() ) { info("+++ Got hit collection %04X %08X. Prepare processors for %sparallel execution.", key.mask(), key.item(), m_parallel ? "" : "NON-"); - m_kernel.submit(m_workers.get_group(), m_workers.size(), &work, m_parallel); + m_kernel.submit(context, m_workers.get_group(), m_workers.size(), &work, m_parallel); } } } diff --git a/DDDigi/src/DigiSegmentationTool.cpp b/DDDigi/src/DigiSegmentationTool.cpp index be65a2afc2afdcf6ce4524169a56b315e09ef5b9..c6052d5e1f4a6c07cf659f4692df96efb199c951 100644 --- a/DDDigi/src/DigiSegmentationTool.cpp +++ b/DDDigi/src/DigiSegmentationTool.cpp @@ -48,11 +48,19 @@ namespace { const string& DigiSegmentContext::name() const { return this->field->name(); } + /// Split field name const char* DigiSegmentContext::cname() const { return this->field->name().c_str(); } +/// Full identifier (field + id) +string DigiSegmentContext::identifier() const { + std::stringstream str; + str << this->field->name() << "." << this->id; + return str.str(); +} + /// Initializing constructor DigiSegmentationTool::DigiSegmentationTool(Detector& desc) : description(desc) diff --git a/DDDigi/src/DigiStoreDump.cpp b/DDDigi/src/DigiStoreDump.cpp index 1b56b216a0e26bcf82576912dfd2bd9139649156..09c66b52c89ac2cf793dffeb6e957dcdf3d69c21 100644 --- a/DDDigi/src/DigiStoreDump.cpp +++ b/DDDigi/src/DigiStoreDump.cpp @@ -59,20 +59,25 @@ void dd4hep::digi::DigiStoreDump::dump(const std::string& tag, typ = str_replace(str_replace(typ,"std::",""),"dd4hep::",""); typ = str_replace(str_replace(typ,"sim::",""),"digi::",""); if ( const auto* mapping = std::any_cast<DepositMapping>(&data) ) { - str = this->format("%s|---- %4X %08X %-32s: %6ld hits [%s]", + str = this->format("%s|---- %4X %08X %-32s: %6ld deposits [%s]", event.id(), key.values.mask, key.values.item, nam.c_str(), mapping->size(), typ.c_str()); } else if ( const auto* vector = std::any_cast<DepositVector>(&data) ) { - str = this->format("%s|---- %4X %08X %-32s: %6ld hits [%s]", + str = this->format("%s|---- %4X %08X %-32s: %6ld deposits [%s]", event.id(), key.values.mask, key.values.item, nam.c_str(), vector->size(), typ.c_str()); } else if ( const auto* parts = std::any_cast<ParticleMapping>(&data) ) { - str = this->format("%s|---- %4X %08X %-32s: %6ld particles [%s]", + str = this->format("%s|---- %4X %08X %-32s: %6ld particles [%s]", event.id(), key.values.mask, key.values.item, nam.c_str(), parts->size(), typ.c_str()); } + else if ( const auto* adcs = std::any_cast<DetectorResponse>(&data) ) { + str = this->format("%s|---- %4X %08X %-32s: %6ld ADC values [%s]", + event.id(), key.values.mask, key.values.item, + nam.c_str(), adcs->size(), typ.c_str()); + } else { str = this->format("%s|---- %4X %08X %-32s: %s", event.id(), key.values.mask, key.values.item, diff --git a/DDDigi/src/DigiSynchronize.cpp b/DDDigi/src/DigiSynchronize.cpp index 536e0941489d1296f7d97479be4450eba55a9d33..e29262286ab0b3e11f7bbdbfcdad84ba7dff12d6 100644 --- a/DDDigi/src/DigiSynchronize.cpp +++ b/DDDigi/src/DigiSynchronize.cpp @@ -46,11 +46,12 @@ DigiSynchronize::~DigiSynchronize() { void DigiSynchronize::execute(DigiContext& context) const { auto start = chrono::high_resolution_clock::now(); if ( !m_actors.empty() ) { - m_kernel.submit(m_actors.get_group(), m_actors.size(), &context, m_parallel); + m_kernel.submit(context, m_actors.get_group(), m_actors.size(), &context, m_parallel); } chrono::duration<double> secs = chrono::high_resolution_clock::now() - start; - debug("+++ Event: %8d (DigiSynchronize) Parallel: %-4s %3ld actions [%8.3g sec]", - context.event->eventNumber, yes_no(m_parallel), m_actors.size(), + const DigiEvent& ev = *context.event; + debug("%s+++ Event: %8d (DigiSynchronize) Parallel: %-4s %3ld actions [%8.3g sec]", + ev.id(), ev.eventNumber, yes_no(m_parallel), m_actors.size(), secs.count()); } diff --git a/examples/DDDigi/scripts/TestDepositWeighted.py b/examples/DDDigi/scripts/TestDepositWeighted.py new file mode 100644 index 0000000000000000000000000000000000000000..feb01bbfc4715f56908511fd16b6efc146bc32dd --- /dev/null +++ b/examples/DDDigi/scripts/TestDepositWeighted.py @@ -0,0 +1,61 @@ +# ========================================================================== +# 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. +# +# ========================================================================== +from __future__ import absolute_import + + +def run(): + import DigiTest + digi = DigiTest.Test(geometry=None) + + input = digi.input_action('DigiParallelActionSequence/READER') + # ======================================================================================================== + digi.info('Created SIGNAL input') + signal = input.adopt_action('DigiROOTInput/SignalReader', mask=0x0, input=[digi.next_input()]) + digi.check_creation([signal]) + # ======================================================================================================== + digi.info('Creating collision overlays....') + # ======================================================================================================== + overlay = input.adopt_action('DigiSequentialActionSequence/Overlay-1') + evtreader = overlay.adopt_action('DigiROOTInput/Read-1', mask=0x1, input=[digi.next_input()]) + digi.check_creation([overlay, evtreader]) + digi.info('Created input.overlay-1') + # ======================================================================================================== + overlay = input.adopt_action('DigiSequentialActionSequence/Overlay-2') + evtreader = overlay.adopt_action('DigiROOTInput/Read-2', mask=0x2, input=[digi.next_input()]) + digi.check_creation([overlay, evtreader]) + digi.info('Created input.overlay-2') + # ======================================================================================================== + event = digi.event_action('DigiSequentialActionSequence/EventAction') + combine = event.adopt_action('DigiContainerCombine/Combine', + parallel=True, + input_masks=[0x0, 0x1, 0x2, 0x3], + output_mask=0xFEED, + output_segment='deposits', + erase_combined=False) + combine.erase_combined = True + proc = event.adopt_action('DigiContainerSequenceAction/Weight', + parallel=True, + input_mask=0xFEED, + input_segment='deposits', + output_mask=0xBABE, + output_segment='deposits') + count = digi.create_action('DigiDepositWeightedPosition/CellsWeighted') + proc.adopt_container_processor(count, digi.containers()) + + event.adopt_action('DigiStoreDump/StoreDump') + digi.info('Created event.dump') + + # ======================================================================================================== + digi.run_checked(num_events=5, num_threads=5, parallel=3) + + +if __name__ == '__main__': + run() diff --git a/examples/DDDigi/scripts/TestIPMove.py b/examples/DDDigi/scripts/TestIPMove.py index bc629b501358a2d432df878ba714afdaaf3149ac..eecb62c4184bb11d429f3a894dba853cdc45f979 100644 --- a/examples/DDDigi/scripts/TestIPMove.py +++ b/examples/DDDigi/scripts/TestIPMove.py @@ -26,8 +26,7 @@ def run(): move_seq = signal.adopt_action('DigiContainerSequenceAction/MoveSignal', parallel=True, input_mask=0x0, input_segment='inputs') mover = digi.create_action('DigiIPMover/MoveIPSignal') - mover.ip_property = 'interaction_point' - mover.ip_creator = set_ip.get() + mover.adopt_property(set_ip, "interaction_point", "interaction_point"); conts = [c for c in digi.containers()] conts.append('MCParticles') move_seq.adopt_container_processor(mover, conts) diff --git a/examples/DDDigi/scripts/TestResegmentation.py b/examples/DDDigi/scripts/TestResegmentation.py index d29af077595cf29b06293251e6715a6219865893..bbac3cf75760ed39b78c66913724d41117e969ec 100644 --- a/examples/DDDigi/scripts/TestResegmentation.py +++ b/examples/DDDigi/scripts/TestResegmentation.py @@ -35,6 +35,7 @@ def run(): <id>system:8,barrel:3,module:4,layer:6,slice:5,x:32:-16,y:-16</id> </readout> """ + resegment.debug = False seq.adopt_container_processor(resegment, 'EcalBarrelHits') event.adopt_action('DigiStoreDump/StoreDump') diff --git a/examples/DDDigi/scripts/TestSegmentationSplit.py b/examples/DDDigi/scripts/TestSegmentationSplit.py index fde6a62666ffb1463a6c4d2734e8b0fb44026993..9ffb740a63fa3b17b70c0299ec31ee0d58c633fb 100644 --- a/examples/DDDigi/scripts/TestSegmentationSplit.py +++ b/examples/DDDigi/scripts/TestSegmentationSplit.py @@ -22,12 +22,12 @@ def run(): digi.check_creation([signal]) # ======================================================================== event = digi.event_action('DigiSequentialActionSequence/EventAction') - combine = event.adopt_action('DigiContainerCombine/Combine', input_masks=[0x0], deposit_mask=0xFEED) - combine.erase_combined = False # Not thread-safe! only do in SequentialActionSequence split_action = event.adopt_action('DigiContainerSequenceAction/SplitSequence', parallel=True, - input_segment='deposits', - mask=0xFEED) + input_mask=0x0, + input_segment='inputs', + output_segment='deposits', + output_mask=0xFEED) splitter = digi.create_action('DigiSegmentSplitter/Splitter', parallel=True, split_by='layer', @@ -35,11 +35,10 @@ def run(): processor_type='DigiSegmentDepositPrint') split_action.adopt_container_processor(splitter, splitter.collection_names()) - dump = event.adopt_action('DigiStoreDump/StoreDump') - digi.check_creation([combine, dump, splitter]) + event.adopt_action('DigiStoreDump/StoreDump') digi.info('Created event.dump') # ======================================================================== - digi.run_checked(num_events=1, num_threads=5, parallel=3) + digi.run_checked(num_events=1, num_threads=10, parallel=3) if __name__ == '__main__': diff --git a/examples/DDDigi/scripts/TestSimpleADCResponse.py b/examples/DDDigi/scripts/TestSimpleADCResponse.py new file mode 100644 index 0000000000000000000000000000000000000000..6bb327b960bdef0443df205ea5ad730905582f8a --- /dev/null +++ b/examples/DDDigi/scripts/TestSimpleADCResponse.py @@ -0,0 +1,46 @@ +# ========================================================================== +# 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. +# +# ========================================================================== +from __future__ import absolute_import + + +def run(): + import DigiTest + digi = DigiTest.Test(geometry=None) + + # ======================================================================================================== + input = digi.input_action('DigiParallelActionSequence/READER') + input.adopt_action('DigiROOTInput/SignalReader', mask=0x0, input=[digi.next_input()]) + # ======================================================================================================== + event = digi.event_action('DigiSequentialActionSequence/EventAction') + proc = event.adopt_action('DigiContainerCombine/Combine', + parallel=True, + input_masks=[0x0, 0x1, 0x2, 0x3], + output_mask=0xFEED, + output_segment='deposits', + erase_combined=True) + proc = event.adopt_action('DigiContainerSequenceAction/ADCsequence', + parallel=True, + input_mask=0xFEED, + input_segment='deposits', + output_mask=0xBABE, + output_segment='output') + count = digi.create_action('DigiSimpleADCResponse/ADCCreate') + proc.adopt_container_processor(count, digi.containers()) + + event.adopt_action('DigiStoreDump/StoreDump') + digi.info('Created event.dump') + + # ======================================================================================================== + digi.run_checked(num_events=5, num_threads=5, parallel=3) + + +if __name__ == '__main__': + run()