From 7606f639e6a2de71fe6be9f1bcd69667a58da03f Mon Sep 17 00:00:00 2001 From: Markus Frank <Markus.Frank@cern.ch> Date: Sun, 6 Nov 2022 12:39:24 +0100 Subject: [PATCH] Have consistent callback signatures for container and segmenation callbacks --- DDCore/include/Parsers/Primitives.h | 10 ++ DDCore/src/GrammarTypes.cpp | 4 + DDDigi/include/DDDigi/DigiAttenuator.h | 5 +- .../include/DDDigi/DigiContainerProcessor.h | 50 ++++--- DDDigi/include/DDDigi/DigiData.h | 6 +- DDDigi/include/DDDigi/DigiSegmentProcessor.h | 123 ---------------- DDDigi/include/DDDigi/DigiSegmentSplitter.h | 83 +++++++++-- DDDigi/include/DDDigi/DigiSegmentationTool.h | 20 ++- DDDigi/plugins/Components.cpp | 4 - DDDigi/plugins/DigiCellMultiplicyCounter.cpp | 2 +- DDDigi/plugins/DigiDepositDropKilled.cpp | 91 ++++++++++++ DDDigi/plugins/DigiDepositMapCreator.cpp | 16 ++- DDDigi/plugins/DigiDepositRecalibEnergy.cpp | 119 +++++++++++++++ DDDigi/plugins/DigiDepositSmearEnergy.cpp | 136 ++++++++---------- .../DigiDepositSmearPositionResolution.cpp | 76 +++++----- .../plugins/DigiDepositSmearPositionTrack.cpp | 100 ++++++------- DDDigi/plugins/DigiDepositSmearTime.cpp | 116 +++++++++++++++ .../plugins/DigiDepositWeightedPosition.cpp | 31 ++-- DDDigi/plugins/DigiHitHistoryDrop.cpp | 12 +- DDDigi/plugins/DigiIPMover.cpp | 27 ++-- DDDigi/plugins/DigiResegment.cpp | 57 ++++---- .../plugins/DigiSegmentDepositExtractor.cpp | 32 ++--- DDDigi/plugins/DigiSegmentDepositPrint.cpp | 31 ++-- DDDigi/plugins/DigiSimpleADCResponse.cpp | 46 +++--- DDDigi/python/DDDigiDict.C | 3 - DDDigi/python/dddigi.py | 17 ++- DDDigi/src/DigiAttenuator.cpp | 21 +-- DDDigi/src/DigiContainerProcessor.cpp | 44 ++++-- DDDigi/src/DigiHandle.cpp | 6 - DDDigi/src/DigiSegmentProcessor.cpp | 74 ---------- DDDigi/src/DigiSegmentSplitter.cpp | 82 ++++++++--- DDDigi/src/DigiSegmentationTool.cpp | 31 ++-- .../include/Parsers/spirit/ParsersFactory.h | 18 ++- DDParsers/src/Spirit/ParsersStandardMisc1.cpp | 12 +- .../DDDigi/scripts/TestSegmentationSplit2.py | 50 +++++++ 35 files changed, 968 insertions(+), 587 deletions(-) delete mode 100644 DDDigi/include/DDDigi/DigiSegmentProcessor.h create mode 100644 DDDigi/plugins/DigiDepositDropKilled.cpp create mode 100644 DDDigi/plugins/DigiDepositRecalibEnergy.cpp create mode 100644 DDDigi/plugins/DigiDepositSmearTime.cpp delete mode 100644 DDDigi/src/DigiSegmentProcessor.cpp create mode 100644 examples/DDDigi/scripts/TestSegmentationSplit2.py diff --git a/DDCore/include/Parsers/Primitives.h b/DDCore/include/Parsers/Primitives.h index 77230c610..49dfe4ff6 100644 --- a/DDCore/include/Parsers/Primitives.h +++ b/DDCore/include/Parsers/Primitives.h @@ -213,6 +213,12 @@ namespace dd4hep { /// Definition of the vector type typedef std::vector<value_t> vector_t; + /// Definition of the bool mapped type + typedef std::pair<bool,value_t> bool_pair_t; + /// Definition of the char mapped type + typedef std::pair<char,value_t> char_pair_t; + /// Definition of the unsigned char mapped type + typedef std::pair<unsigned char,value_t> uchar_pair_t; /// Definition of the short integer mapped type typedef std::pair<short,value_t> short_pair_t; /// Definition of the unsigned short integer mapped type @@ -226,6 +232,10 @@ namespace dd4hep { /// Definition of the unsigned long integer mapped type typedef std::pair<unsigned long,value_t> ulong_pair_t; /// Definition of the size_t mapped type + typedef std::pair<float,value_t> float_pair_t; + /// Definition of the size_t mapped type + typedef std::pair<double,value_t> double_pair_t; + /// Definition of the size_t mapped type typedef std::pair<size_t,value_t> size_pair_t; /// Definition of the string mapped type typedef std::pair<std::string,value_t> string_pair_t; diff --git a/DDCore/src/GrammarTypes.cpp b/DDCore/src/GrammarTypes.cpp index 0a7136e49..1aac7af07 100644 --- a/DDCore/src/GrammarTypes.cpp +++ b/DDCore/src/GrammarTypes.cpp @@ -60,3 +60,7 @@ DD4HEP_DEFINE_PARSER_GRAMMAR_CONT(bool,eval_item) DD4HEP_DEFINE_PARSER_GRAMMAR_CONT(float,eval_item) DD4HEP_DEFINE_PARSER_GRAMMAR_CONT(double,eval_item) DD4HEP_DEFINE_PARSER_GRAMMAR_CONT(std::string,eval_item) + +DD4HEP_DEFINE_PARSER_GRAMMAR_SERIAL(__LINE__,1,dd4hep::detail::Primitive<bool>::bool_pair_t,eval_pair) +DD4HEP_DEFINE_PARSER_GRAMMAR_SERIAL(__LINE__,2,dd4hep::detail::Primitive<float>::float_pair_t,eval_pair) +DD4HEP_DEFINE_PARSER_GRAMMAR_SERIAL(__LINE__,5,dd4hep::detail::Primitive<double>::double_pair_t,eval_pair) diff --git a/DDDigi/include/DDDigi/DigiAttenuator.h b/DDDigi/include/DDDigi/DigiAttenuator.h index 4082a7084..b5ed824d6 100644 --- a/DDDigi/include/DDDigi/DigiAttenuator.h +++ b/DDDigi/include/DDDigi/DigiAttenuator.h @@ -58,13 +58,14 @@ namespace dd4hep { /// Default destructor virtual ~DigiAttenuator(); /// Attenuator callback for single container - template <typename T> std::size_t attenuate(T& cont) const; + template <typename DEPOSITS> std::size_t + attenuate(DEPOSITS& cont, const predicate_t& predicate) const; public: /// Standard constructor DigiAttenuator(const DigiKernel& kernel, const std::string& nam); /// Main functional callback adapter - virtual void execute(DigiContext& context, work_t& work) const override; + virtual void execute(DigiContext& context, work_t& work, const predicate_t& predicate) const override; }; /// Default base class for all Digitizer actions and derivates thereof. diff --git a/DDDigi/include/DDDigi/DigiContainerProcessor.h b/DDDigi/include/DDDigi/DigiContainerProcessor.h index 6ac2044b4..621370e94 100644 --- a/DDDigi/include/DDDigi/DigiContainerProcessor.h +++ b/DDDigi/include/DDDigi/DigiContainerProcessor.h @@ -14,6 +14,7 @@ #define DDDIGI_DIGICONTAINERPROCESSOR_H // Framework include files +#include <DD4hep/Callback.h> #include <DDDigi/DigiData.h> #include <DDDigi/DigiEventAction.h> #include <DDDigi/DigiParallelWorker.h> @@ -28,11 +29,12 @@ namespace dd4hep { namespace digi { /// Forward declarations - class DigiContainerProcessor; class DigiContainerSequence; + class DigiContainerProcessor; + class DigiSegmentProcessContext; class DigiContainerSequenceAction; class DigiMultiContainerProcessor; - + /// Worker base class to analyse containers from the input segment in parallel /** * @@ -42,29 +44,45 @@ namespace dd4hep { */ class DigiContainerProcessor : public DigiAction { public: - using segment_t = DataSegment; - using context_t = DigiContext; - using action_t = DigiAction; - using property_t = PropertyManager; + using segment_t = DataSegment; + using context_t = DigiContext; + using action_t = DigiAction; + using property_t = PropertyManager; + using segmentation_t = DigiSegmentProcessContext; + + /// Input definition struct input_t { /// Input data key Key key; /// Input deposits std::any& data; }; + + /// Output handle definition struct output_t { int mask; segment_t& data; }; + + /// Hit processing predicate + struct predicate_t { + Callback callback; + const segmentation_t& segmentation; + predicate_t(const segmentation_t& s) : segmentation(s) {} + predicate_t(const Callback& cb, const segmentation_t& s) : callback(cb), segmentation(s) {} + /// Check if a deposit should be processed + bool operator()(const std::pair<const CellID, EnergyDeposit>& deposit) const; + }; + struct work_t { /// Event processing context - context_t& context; + context_t& context; /// Input data - input_t input; + input_t input; /// Output data - output_t& output; + output_t& output; /// Optional properties - const property_t& properties; + const property_t& properties; /// Basic check if input data are present bool has_input() const { return this->input.data.has_value(); } @@ -84,17 +102,16 @@ namespace dd4hep { /// Define standard assignments and constructors DDDIGI_DEFINE_ACTION_CONSTRUCTORS(DigiContainerProcessor); - private: - /// Main functional callback if specific work is known. - virtual void execute(DigiContext& context, Key key, std::any& data) const; - public: + /// Access to default callback + static const predicate_t& accept_all(); + /// Standard constructor DigiContainerProcessor(const DigiKernel& kernel, const std::string& name); /// Default destructor virtual ~DigiContainerProcessor(); /// Main functional callback adapter - virtual void execute(DigiContext& context, work_t& work) const; + virtual void execute(DigiContext& context, work_t& work, const predicate_t& predicate) const; }; /// Worker class act on containers in an event identified by input masks and container name @@ -114,6 +131,7 @@ namespace dd4hep { friend class DigiParallelWorker<processor_t,work_t>; protected: + /** Member variables */ /// Property to steer parallel processing bool m_parallel { false }; /// Array of sub-workers @@ -136,7 +154,7 @@ namespace dd4hep { /// Adopt new parallel worker virtual void adopt_processor(DigiContainerProcessor* action); /// Main functional callback adapter - virtual void execute(DigiContext& context, work_t& work) const; + virtual void execute(DigiContext& context, work_t& work, const predicate_t& predicate) const; }; /// Worker base class to analyse containers from the input segment in parallel diff --git a/DDDigi/include/DDDigi/DigiData.h b/DDDigi/include/DDDigi/DigiData.h index f31d7715e..2ae18985a 100644 --- a/DDDigi/include/DDDigi/DigiData.h +++ b/DDDigi/include/DDDigi/DigiData.h @@ -469,7 +469,9 @@ namespace dd4hep { enum { KILLED = 1 << 0, ENERGY_SMEARED = 1 << 1, - POSITION_SMEARED = 1 << 2 + POSITION_SMEARED = 1 << 2, + TIME_SMEARED = 1 << 3, + RECALIBRATED = 1 << 4 }; /// Hit position @@ -480,6 +482,8 @@ namespace dd4hep { double length { 0 }; /// Total energy deposit double deposit { 0 }; + /// Proper creation time of the deposit with rescpect to beam crossing + double time { 0 }; /// Optional flag for user masks long flag { 0 }; /// Source mask of this deposit diff --git a/DDDigi/include/DDDigi/DigiSegmentProcessor.h b/DDDigi/include/DDDigi/DigiSegmentProcessor.h deleted file mode 100644 index d768ade55..000000000 --- a/DDDigi/include/DDDigi/DigiSegmentProcessor.h +++ /dev/null @@ -1,123 +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_DIGISEGMENTPROCESSOR_H -#define DDDIGI_DIGISEGMENTPROCESSOR_H - -// Framework include files -#include <DDDigi/DigiData.h> -#include <DDDigi/DigiContainerProcessor.h> -#include <DDDigi/DigiSegmentationTool.h> - -/// 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 DigiSegmentProcessor; - class DigiSegmentSequence; - - /// Default base class to process parts of a subdetector segmentation data - /** - * This is a utility class supporting properties, output and access to - * event and run objects through the context. - * - * Default base class to process parts of a subdetector segmentation data. - * - * \author M.Frank - * \version 1.0 - * \ingroup DD4HEP_DIGITAZATION - */ - class DigiSegmentProcessor : public DigiContainerProcessor { - public: - /// Segmentation split context - 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 - DDDIGI_DEFINE_ACTION_CONSTRUCTORS(DigiSegmentProcessor); - - public: - /// Standard constructor - DigiSegmentProcessor(const DigiKernel& kernel, const std::string& name); - /// Default destructor - virtual ~DigiSegmentProcessor(); - /// Main functional callback if specific work is known - virtual void execute(DigiContext& context, work_t& data) const override; - }; - - /// Sequencer class to process parts of a subdetector segmentation data - /** - * This is a utility class supporting properties, output and access to - * event and run objects through the context. - * - * The sequencer calls all registered processors for the contaiers registered. - * The sequencer manages a set of workers all acting on the same data segment - * being a part of the data of a collection - * - * \author M.Frank - * \version 1.0 - * \ingroup DD4HEP_DIGITIZATION - */ - class DigiSegmentSequence : public DigiSegmentProcessor { - protected: - /// Property to steer parallel processing - bool m_parallel { false }; - - protected: - using self_t = DigiSegmentSequence; - using processor_t = DigiSegmentProcessor; - using worker_t = DigiParallelWorker<processor_t,work_t,VolumeID>; - using workers_t = DigiParallelWorkers<worker_t>; - friend class DigiParallelWorker<processor_t,work_t,VolumeID>; - - /// Array of sub-workers - workers_t m_workers; - - protected: - /// Define standard assignments and constructors - DDDIGI_DEFINE_ACTION_CONSTRUCTORS(DigiSegmentSequence); - /// Default destructor - virtual ~DigiSegmentSequence(); - - public: - /// Standard constructor - DigiSegmentSequence(const DigiKernel& kernel, const std::string& name); - /// Adopt new parallel worker - virtual void adopt_processor(DigiContainerProcessor* action); - /// Main functional callback if specific work is known - virtual void execute(DigiContext& context, work_t& work) const override; - }; - - } // End namespace digi -} // End namespace dd4hep -#endif // DDDIGI_DIGISEGMENTPROCESSOR_H diff --git a/DDDigi/include/DDDigi/DigiSegmentSplitter.h b/DDDigi/include/DDDigi/DigiSegmentSplitter.h index df7201665..901854cc3 100644 --- a/DDDigi/include/DDDigi/DigiSegmentSplitter.h +++ b/DDDigi/include/DDDigi/DigiSegmentSplitter.h @@ -15,7 +15,7 @@ // Framework include files #include <DDDigi/DigiEventAction.h> -#include <DDDigi/DigiSegmentProcessor.h> +#include <DDDigi/DigiContainerProcessor.h> #include <DDDigi/DigiSegmentationTool.h> #include <DDDigi/DigiParallelWorker.h> @@ -25,6 +25,58 @@ namespace dd4hep { /// Namespace for the Digitization part of the AIDA detector description toolkit namespace digi { + /// Segmentation split context + /** + * + * + * + * \author M.Frank + * \version 1.0 + * \ingroup DD4HEP_DIGITIZATION + */ + class DigiSegmentProcessContext : public DigiSegmentContext { + public: + using predicate_t = DigiContainerProcessor::predicate_t; + predicate_t predicate { {}, *this }; + uint32_t id { 0 }; + + public: + /// Default constructor + DigiSegmentProcessContext() = default; + /// Default move constructor + DigiSegmentProcessContext(DigiSegmentProcessContext&& copy) = default; + /// Default copy constructor + DigiSegmentProcessContext(const DigiSegmentContext& copy); + /// Default copy constructor + DigiSegmentProcessContext(const DigiSegmentProcessContext& copy) = default; + /// Default destructor + virtual ~DigiSegmentProcessContext() = default; + /// Default move assignment + DigiSegmentProcessContext& operator=(const DigiSegmentContext& copy); + /// Default move assignment + DigiSegmentProcessContext& operator=(DigiSegmentProcessContext&& copy) = default; + /// Default copy assignment + DigiSegmentProcessContext& operator=(const DigiSegmentProcessContext& copy) = default; + + /// Full identifier (field + id) + std::string identifier() const; + /// Check a given cell id if it matches this selection + bool matches(uint64_t cell) const { + return this->split_id(cell) == this->id; + } + }; + + struct accept_segment_t : public DigiContainerProcessor::predicate_t { + using segmentation_t = DigiSegmentProcessContext; + accept_segment_t(const segmentation_t& s) : predicate_t( { this }, s) { + auto fptr = &accept_segment_t::operator(); + callback.make(fptr); + } + inline bool operator()(const std::pair<const CellID, EnergyDeposit>& depo) const { + return this->segmentation.matches(depo.first); + } + }; + /// Default base class for all Digitizer actions and derivates thereof. /** * This is a utility class supporting properties, output and access to @@ -34,14 +86,19 @@ namespace dd4hep { * \version 1.0 * \ingroup DD4HEP_DIGITIZATION */ - class DigiSegmentSplitter : public DigiContainerSequence { + class DigiSegmentSplitter : public DigiContainerProcessor { protected: using self_t = DigiSegmentSplitter; using split_t = std::pair<DetElement, VolumeID>; using splits_t = std::map<VolumeID, split_t>; - friend class DigiParallelWorker<processor_t, work_t, VolumeID>; - + using segment_t = DigiSegmentProcessContext; + using processor_t = DigiContainerProcessor; + using worker_t = DigiParallelWorker<processor_t,work_t, segment_t>; + using workers_t = DigiParallelWorkers<worker_t>; + friend class DigiParallelWorker<processor_t, work_t, segment_t>; + protected: + /** Object properties */ /// Property: Split element of the ID descriptor std::string m_processor_type; /// Name of the subdetector to be handed @@ -51,7 +108,7 @@ namespace dd4hep { /// Property: Flag if processors should be shared bool m_share_processor { true }; - /** Member variables */ + /** Member variables */ /// Segmentation too instance mutable DigiSegmentationTool m_split_tool; /// Segmentation split context @@ -60,6 +117,12 @@ namespace dd4hep { std::vector<Key> m_keys; /// Split elements used to parallelize the processing splits_t m_splits; + /// Property to steer parallel processing + bool m_parallel { false }; + /// Array of sub-workers + workers_t m_workers; + /// Lock for output merging + mutable std::mutex m_output_lock; protected: /// Default destructor @@ -67,8 +130,12 @@ namespace dd4hep { /// Initialization function void initialize(); - /// Adopt new parallel worker: INHIBITED: will throw exception - virtual void adopt_processor(DigiContainerProcessor* action) override final; + + public: + /// Adopt new parallel worker handling single split identifier + virtual void adopt_segment_processor(DigiContainerProcessor* action, int split_id); + /// Adopt new parallel worker handling multiple split-identifiers + virtual void adopt_segment_processor(DigiContainerProcessor* action, const std::vector<int>& ids); public: /// Standard constructor @@ -76,7 +143,7 @@ namespace dd4hep { /// Access the readout collection keys std::vector<std::string> collection_names() const; /// Main functional callback - virtual void execute(DigiContext& context, work_t& work) const override; + virtual void execute(DigiContext& context, work_t& work, const predicate_t& predicate) const override; }; } // End namespace digi } // End namespace dd4hep diff --git a/DDDigi/include/DDDigi/DigiSegmentationTool.h b/DDDigi/include/DDDigi/DigiSegmentationTool.h index 6dc38300e..6ef34f144 100644 --- a/DDDigi/include/DDDigi/DigiSegmentationTool.h +++ b/DDDigi/include/DDDigi/DigiSegmentationTool.h @@ -48,15 +48,25 @@ namespace dd4hep { int32_t offset { 0 }; int32_t width { 0 }; int32_t max_split { 0 }; - uint32_t id { 0 }; public: + /// Default constructor + DigiSegmentContext() = default; + /// Default move constructor + DigiSegmentContext(DigiSegmentContext&& copy) = default; + /// Default copy constructor + DigiSegmentContext(const DigiSegmentContext& copy) = default; + /// Default destructor + virtual ~DigiSegmentContext() = default; + /// Default move assignment + DigiSegmentContext& operator=(DigiSegmentContext&& copy) = default; + /// Default copy assignment + DigiSegmentContext& operator=(const DigiSegmentContext& copy) = default; + /// Split field name 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 { @@ -70,10 +80,6 @@ namespace dd4hep { uint64_t detector_id(uint64_t cell) const { return (cell & this->det_mask); } - /// Check a given cell id if it matches this selection - bool matches(uint64_t cell) const { - return this->split_id(cell) == this->id; - } }; /// Tool to handle segmentation manipulations diff --git a/DDDigi/plugins/Components.cpp b/DDDigi/plugins/Components.cpp index 3d7c772e1..c37568443 100644 --- a/DDDigi/plugins/Components.cpp +++ b/DDDigi/plugins/Components.cpp @@ -60,10 +60,6 @@ DECLARE_DIGIACTION_NS(dd4hep::digi,DigiContainerCombine) #include <DDDigi/DigiContainerDrop.h> DECLARE_DIGIACTION_NS(dd4hep::digi,DigiContainerDrop) -#include <DDDigi/DigiSegmentProcessor.h> -DECLARE_DIGIACTION_NS(dd4hep::digi,DigiSegmentProcessor) -DECLARE_DIGIACTION_NS(dd4hep::digi,DigiSegmentSequence) - #include <DDDigi/DigiSegmentSplitter.h> DECLARE_DIGIACTION_NS(dd4hep::digi,DigiSegmentSplitter) diff --git a/DDDigi/plugins/DigiCellMultiplicyCounter.cpp b/DDDigi/plugins/DigiCellMultiplicyCounter.cpp index 125c26c5b..ae4635d45 100644 --- a/DDDigi/plugins/DigiCellMultiplicyCounter.cpp +++ b/DDDigi/plugins/DigiCellMultiplicyCounter.cpp @@ -45,7 +45,7 @@ namespace dd4hep { tag, cont.name.c_str(), cont.size(), entries.size()); } /// Main functional callback - virtual void execute(DigiContext& context, work_t& work) const override final { + virtual void execute(DigiContext& context, work_t& work, const predicate_t&) const override final { if ( const auto* m = work.get_input<DepositMapping>() ) count_deposits(context.event->id(), *m); else if ( const auto* v = work.get_input<DepositVector>() ) diff --git a/DDDigi/plugins/DigiDepositDropKilled.cpp b/DDDigi/plugins/DigiDepositDropKilled.cpp new file mode 100644 index 000000000..60ba5b2e6 --- /dev/null +++ b/DDDigi/plugins/DigiDepositDropKilled.cpp @@ -0,0 +1,91 @@ +//========================================================================== +// 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/DigiContainerProcessor.h> +#include <DD4hep/InstanceCount.h> +#include <DD4hep/DD4hepUnits.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 { + + /// Actor to drop energy deposits of a container having the "KILLED" flag + /** + * + * + * \author M.Frank + * \version 1.0 + * \ingroup DD4HEP_DIGITIZATION + */ + class DigiDepositDropKilled : public DigiContainerProcessor { + protected: + /// Property: Flag to update existing container in-place or create a new container + bool m_update_in_place { true }; + + public: + /// Standard constructor + DigiDepositDropKilled(const DigiKernel& krnl, const std::string& nam) + : DigiContainerProcessor(krnl, nam) + { + declareProperty("update_in_place", m_update_in_place = true); + InstanceCount::increment(this); + } + + /// Default destructor + virtual ~DigiDepositDropKilled() { + InstanceCount::decrement(this); + } + template <typename T> std::size_t length(const T* m) const { return m->size(); } + /// Main functional callback + virtual void execute(DigiContext& context, work_t& work, const predicate_t&) const override final { + std::size_t killed = 0, total = 0, i = 0; + if ( auto* v = work.get_input<DepositVector>() ) { + total = length(v); + for( auto iter = v->begin(); iter != v->end(); ++iter, ++i ) { + if ( v->at(i).flag&EnergyDeposit::KILLED ) { + v->remove(iter); + iter = v->begin() + (--i); + } + } + killed = total - length(v); + } + else if ( auto* m = work.get_input<DepositMapping>() ) { + CellID last_cell = ~0x0LL; + total = length(m); + for( auto iter = m->begin(); iter != m->end(); ++iter ) { + if ( iter->second.flag&EnergyDeposit::KILLED ) { + m->remove(iter); + iter = (last_cell != ~0x0LL) ? m->data.find(last_cell) : m->begin(); + continue; + } + last_cell = iter->first; + } + killed = total - length(v); + } + else { + except("Request to handle unknown data type: %s", work.input_type_name().c_str()); + } + info("%s+++ Killed %6ld out of %6ld deposit entries from container: %s",context.event->id(), killed, total); + } + }; + } // End namespace digi +} // End namespace dd4hep + +#include <DDDigi/DigiFactories.h> +DECLARE_DIGIACTION_NS(dd4hep::digi,DigiDepositDropKilled) diff --git a/DDDigi/plugins/DigiDepositMapCreator.cpp b/DDDigi/plugins/DigiDepositMapCreator.cpp index fd637cb98..86765d0e1 100644 --- a/DDDigi/plugins/DigiDepositMapCreator.cpp +++ b/DDDigi/plugins/DigiDepositMapCreator.cpp @@ -35,23 +35,27 @@ namespace dd4hep { /// Standard constructor using DigiContainerProcessor::DigiContainerProcessor; - template <typename T> void create_deposits(const char* tag, const T& cont, work_t& work) const { + template <typename T> void + create_deposits(const char* tag, const T& cont, work_t& work, const predicate_t& predicate) 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()); + for( const auto& dep : cont ) { + if ( predicate(dep) ) { + m.data.emplace(dep.first, EnergyDeposit()); + } + } std::size_t end = m.size(); work.output.data.put(m.key, std::move(m)); 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& context, work_t& work) const override final { + virtual void execute(DigiContext& context, work_t& work, const predicate_t& predicate) const override final { if ( const auto* m = work.get_input<DepositMapping>() ) - create_deposits(context.event->id(), *m, work); + create_deposits(context.event->id(), *m, work, predicate); else if ( const auto* v = work.get_input<DepositVector>() ) - create_deposits(context.event->id(), *v, work); + create_deposits(context.event->id(), *v, work, predicate); else except("Request to handle unknown data type: %s", work.input_type_name().c_str()); } diff --git a/DDDigi/plugins/DigiDepositRecalibEnergy.cpp b/DDDigi/plugins/DigiDepositRecalibEnergy.cpp new file mode 100644 index 000000000..490a23b1f --- /dev/null +++ b/DDDigi/plugins/DigiDepositRecalibEnergy.cpp @@ -0,0 +1,119 @@ +//========================================================================== +// 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/DigiContainerProcessor.h> +#include <DD4hep/InstanceCount.h> +#include <DD4hep/DD4hepUnits.h> + +/// C/C++ include files + +/// Namespace for the AIDA detector description toolkit +namespace dd4hep { + + /// Namespace for the Digitization part of the AIDA detector description toolkit + namespace digi { + + /// Actor to smear timing information of energy deposits + /** + * + * + * \author M.Frank + * \version 1.0 + * \ingroup DD4HEP_DIGITIZATION + */ + class DigiDepositRecalibEnergy : public DigiContainerProcessor { + protected: + /// Property: Polynomial parameters to recalibrate the energy + std::vector<double> m_polynomial { }; + /// Property: Energy base point to compute delta(energy) + double m_e0 { 0e0 }; + /// Property: Flag to update existing container in-place or create a new container + bool m_update_in_place { true }; + + public: + /// Standard constructor + DigiDepositRecalibEnergy(const DigiKernel& krnl, const std::string& nam) + : DigiContainerProcessor(krnl, nam) + { + declareProperty("e0", m_e0); + declareProperty("parameters" , m_polynomial); + InstanceCount::increment(this); + } + + /// Default destructor + virtual ~DigiDepositRecalibEnergy() { + InstanceCount::decrement(this); + } + + /// Create deposit mapping with updates on same cellIDs + template <typename T> void recalibrate_deposit_energy(DigiContext& context, + T& cont, + work_t& work, + const predicate_t& predicate) const { + T output_cont(cont.name, work.output.mask); + std::size_t updated = 0UL; + std::size_t created = 0UL; + std::size_t killed = 0UL; + + info("%s+++ Recalibrarting deposit container: %s %6ld entries", + context.event->id(), cont.name.c_str(), cont.size()); + for( auto& dep : cont ) { + if ( predicate(dep) ) { + double deposit = dep.second.deposit; + double delta_E = deposit - m_e0; + double fac = 1e0; + for( double param : m_polynomial ) { + deposit += param * fac; + fac *= delta_E; + } + if ( m_update_in_place ) { + EnergyDeposit& d = dep.second; + d.deposit = deposit; + d.flag |= EnergyDeposit::RECALIBRATED; + ++updated; + } + else if ( !(dep.second.flag&EnergyDeposit::KILLED) ) { + EnergyDeposit d(dep.second); + d.deposit = deposit; + d.flag |= EnergyDeposit::RECALIBRATED; + output_cont.emplace(dep.first, std::move(d)); + ++created; + } + else { + ++killed; + } + } + } + if ( !m_update_in_place ) { + work.output.data.put(output_cont.key, std::move(output_cont)); + } + info("%s+++ %-32s Smearing: created %6ld updated %6ld killed %6ld entries from mask: %04X", + context.event->id(), cont.name.c_str(), created, updated, killed, cont.key.mask()); + } + + /// Main functional callback + virtual void execute(DigiContext& context, work_t& work, const predicate_t& predicate) const override final { + if ( auto* v = work.get_input<DepositVector>() ) + recalibrate_deposit_energy(context, *v, work, predicate); + else if ( auto* m = work.get_input<DepositMapping>() ) + recalibrate_deposit_energy(context, *m, work, predicate); + else + except("Request to handle unknown data type: %s", work.input_type_name().c_str()); + } + }; + } // End namespace digi +} // End namespace dd4hep + +#include <DDDigi/DigiFactories.h> +DECLARE_DIGIACTION_NS(dd4hep::digi,DigiDepositRecalibEnergy) diff --git a/DDDigi/plugins/DigiDepositSmearEnergy.cpp b/DDDigi/plugins/DigiDepositSmearEnergy.cpp index b76f74530..3aaa47538 100644 --- a/DDDigi/plugins/DigiDepositSmearEnergy.cpp +++ b/DDDigi/plugins/DigiDepositSmearEnergy.cpp @@ -75,8 +75,6 @@ namespace dd4hep { double m_pair_ionization_energy { 0e0 }; /// Property: Flag to use ionization fluctuation smearing (poisson ~ # e-ion-pairs) bool m_ionization_fluctuation { false }; - /// Property: Flag to drop killed entries from the deposits - bool m_drop_killed { false }; /// Property: Flag to update existing container in-place or create a new container bool m_update_in_place { true }; @@ -85,7 +83,6 @@ namespace dd4hep { DigiDepositSmearEnergy(const DigiKernel& krnl, const std::string& nam) : DigiContainerProcessor(krnl, nam) { - declareProperty("drop_killed", m_drop_killed = false); declareProperty("deposit_cutoff", m_deposit_cutoff); declareProperty("intrinsic_fluctuation", m_intrinsic_fluctuation = 0e0); declareProperty("instrumentation_resolution", m_instrumentation_resolution = 0e0); @@ -101,24 +98,9 @@ namespace dd4hep { InstanceCount::decrement(this); } - template <typename T> std::size_t drop_killed_entries(T& cont) const { - //CellID last_cell = 0UL; - std::size_t killed = 0; - for( auto iter = cont.begin(); iter != cont.end(); ++iter ) { - auto& dep = iter->second; - if ( dep.flag&EnergyDeposit::KILLED ) { - cont.remove(iter); - iter = cont.begin(); // (last_cell != 0UL) ? cont.find(last_cell) : cont.begin(); - ++killed; - continue; - } - //last_cell = iter->first; - } - return killed; - } - /// Create deposit mapping with updates on same cellIDs - template <typename T> void smear_deposit_energy(DigiContext& context, T& cont, work_t& work) const { + template <typename T> void + smear(DigiContext& context, T& cont, work_t& work, const predicate_t& predicate) const { auto& random = context.randomGenerator(); T output_cont(cont.name, work.output.mask); std::size_t killed = 0UL; @@ -130,80 +112,76 @@ namespace dd4hep { context.event->id(), cont.name.c_str(), cont.size()); } for( auto& dep : cont ) { - CellID cell = dep.first; - const EnergyDeposit& depo = dep.second; - double deposit = depo.deposit; - if ( deposit >= m_deposit_cutoff ) { - double delta_E = 0e0; - double energy = deposit / dd4hep::GeV; // E in units of GeV - double sigma_E_systematic = m_systematic_resolution * energy; - double sigma_E_intrin_fluct = m_intrinsic_fluctuation * std::sqrt(energy); - double sigma_E_instrument = m_instrumentation_resolution / dd4hep::GeV; - double delta_ion = 0e0, num_pairs = 0e0; - constexpr static double eps = std::numeric_limits<double>::epsilon(); - if ( sigma_E_systematic > eps ) { - delta_E += sigma_E_systematic * random.gaussian(0e0, 1e0); - } - if ( sigma_E_intrin_fluct > eps ) { - delta_E += sigma_E_intrin_fluct * random.gaussian(0e0, 1e0); - } - if ( sigma_E_instrument > eps ) { - delta_E += sigma_E_instrument * random.gaussian(0e0, 1e0); - } - if ( m_ionization_fluctuation ) { - num_pairs = energy / (m_pair_ionization_energy/dd4hep::GeV); - delta_ion = energy * (random.poisson(num_pairs)/num_pairs); - delta_E += delta_ion; - } - if ( dd4hep::isActivePrintLevel(outputLevel()) ) { - print("+++ %016lX [GeV] E:%9.2e [%9.2e %9.2e] intrin_fluct:%9.2e systematic:%9.2e instrument:%9.2e ioni:%9.2e/%.0f %s", - cell, energy, deposit/dd4hep::GeV, delta_E, - sigma_E_intrin_fluct, sigma_E_systematic, sigma_E_instrument, delta_ion, num_pairs, - deposit < m_deposit_cutoff ? "KILLED" : ""); - } - /// delta_E is in GeV - if ( deposit > m_deposit_cutoff ) { - if ( m_update_in_place ) { - EnergyDeposit& d = dep.second; - d.deposit = deposit + (delta_E * dd4hep::GeV); - d.flag |= EnergyDeposit::ENERGY_SMEARED; - ++updated; + if ( predicate(dep) ) { + CellID cell = dep.first; + const EnergyDeposit& depo = dep.second; + double deposit = depo.deposit; + if ( deposit >= m_deposit_cutoff ) { + double delta_E = 0e0; + double energy = deposit / dd4hep::GeV; // E in units of GeV + double sigma_E_systematic = m_systematic_resolution * energy; + double sigma_E_intrin_fluct = m_intrinsic_fluctuation * std::sqrt(energy); + double sigma_E_instrument = m_instrumentation_resolution / dd4hep::GeV; + double delta_ion = 0e0, num_pairs = 0e0; + constexpr static double eps = std::numeric_limits<double>::epsilon(); + if ( sigma_E_systematic > eps ) { + delta_E += sigma_E_systematic * random.gaussian(0e0, 1e0); } - else { - EnergyDeposit d(depo); - d.deposit = deposit + (delta_E * dd4hep::GeV); - d.flag |= EnergyDeposit::ENERGY_SMEARED; - output_cont.emplace(cell, EnergyDeposit(depo)); - ++created; + if ( sigma_E_intrin_fluct > eps ) { + delta_E += sigma_E_intrin_fluct * random.gaussian(0e0, 1e0); + } + if ( sigma_E_instrument > eps ) { + delta_E += sigma_E_instrument * random.gaussian(0e0, 1e0); + } + if ( m_ionization_fluctuation ) { + num_pairs = energy / (m_pair_ionization_energy/dd4hep::GeV); + delta_ion = energy * (random.poisson(num_pairs)/num_pairs); + delta_E += delta_ion; + } + if ( dd4hep::isActivePrintLevel(outputLevel()) ) { + print("+++ %016lX [GeV] E:%9.2e [%9.2e %9.2e] intrin_fluct:%9.2e systematic:%9.2e instrument:%9.2e ioni:%9.2e/%.0f %s", + cell, energy, deposit/dd4hep::GeV, delta_E, + sigma_E_intrin_fluct, sigma_E_systematic, sigma_E_instrument, delta_ion, num_pairs, + deposit < m_deposit_cutoff ? "KILLED" : ""); + } + /// delta_E is in GeV + if ( deposit > m_deposit_cutoff ) { + if ( m_update_in_place ) { + EnergyDeposit& d = dep.second; + d.deposit = deposit + (delta_E * dd4hep::GeV); + d.flag |= EnergyDeposit::ENERGY_SMEARED; + ++updated; + } + else { + EnergyDeposit d(depo); + d.deposit = deposit + (delta_E * dd4hep::GeV); + d.flag |= EnergyDeposit::ENERGY_SMEARED; + output_cont.emplace(cell, EnergyDeposit(depo)); + ++created; + } + continue; } - continue; } - } - else if ( !m_update_in_place ) { - EnergyDeposit& d = dep.second; - d.flag |= EnergyDeposit::KILLED; - ++killed; + else if ( !m_update_in_place ) { + EnergyDeposit& d = dep.second; + d.flag |= EnergyDeposit::KILLED; + ++killed; + } } } - if ( !m_update_in_place ) { work.output.data.put(output_cont.key, std::move(output_cont)); } - - killed = (m_drop_killed && m_update_in_place && killed > 0) - ? drop_killed_entries(cont) - : killed; - info("%s+++ %-32s Smearing: created %6ld updated %6ld killed %6ld entries from mask: %04X", context.event->id(), cont.name.c_str(), created, updated, killed, cont.key.mask()); } /// Main functional callback - virtual void execute(DigiContext& context, work_t& work) const override final { + virtual void execute(DigiContext& context, work_t& work, const predicate_t& predicate) const override final { if ( auto* v = work.get_input<DepositVector>() ) - smear_deposit_energy(context, *v, work); + smear(context, *v, work, predicate); else if ( auto* m = work.get_input<DepositMapping>() ) - smear_deposit_energy(context, *m, work); + smear(context, *m, work, predicate); else except("Request to handle unknown data type: %s", work.input_type_name().c_str()); } diff --git a/DDDigi/plugins/DigiDepositSmearPositionResolution.cpp b/DDDigi/plugins/DigiDepositSmearPositionResolution.cpp index 960d65c26..5c82012e0 100644 --- a/DDDigi/plugins/DigiDepositSmearPositionResolution.cpp +++ b/DDDigi/plugins/DigiDepositSmearPositionResolution.cpp @@ -65,7 +65,8 @@ namespace dd4hep { } /// Create deposit mapping with updates on same cellIDs - template <typename T> void smear_deposit_position(DigiContext& context, T& cont, work_t& work) const { + template <typename T> void + smear(DigiContext& context, T& cont, work_t& work, const predicate_t& predicate) const { T output_cont(cont.name, work.output.mask); auto& random = context.randomGenerator(); std::size_t killed = 0UL; @@ -78,45 +79,46 @@ namespace dd4hep { } VolumeManager volMgr = m_kernel.detectorDescription().volumeManager(); for( auto& dep : cont ) { - CellID cell = dep.first; - const EnergyDeposit& depo = dep.second; - double deposit = depo.deposit; - if ( deposit >= m_deposit_cutoff ) { - auto* ctxt = volMgr.lookupContext(cell); - Position local_pos = ctxt->worldToLocal(depo.position); - double delta_u = m_resolution_u * random.gaussian(); - double delta_v = m_resolution_v * random.gaussian(); - Position delta_pos(delta_u, delta_v, 0e0); - Position oldpos = depo.position; - Position newpos = ctxt->localToWorld(local_pos + delta_pos); + if ( predicate(dep) ) { + CellID cell = dep.first; + const EnergyDeposit& depo = dep.second; + double deposit = depo.deposit; + if ( deposit >= m_deposit_cutoff ) { + auto* ctxt = volMgr.lookupContext(cell); + Position local_pos = ctxt->worldToLocal(depo.position); + double delta_u = m_resolution_u * random.gaussian(); + double delta_v = m_resolution_v * random.gaussian(); + Position delta_pos(delta_u, delta_v, 0e0); + Position oldpos = depo.position; + Position newpos = ctxt->localToWorld(local_pos + delta_pos); - delta_pos = newpos - oldpos; - info("+++ %016lX Smeared position [%9.2e %9.2e %9.2e] by [%9.2e %9.2e %9.2e] to [%9.2e %9.2e %9.2e] [mm]", - oldpos.X(), oldpos.Y(), oldpos.Z(), delta_pos.X(), delta_pos.Y(), delta_pos.Z(), - newpos.X(), newpos.Y(), newpos.Z()); + delta_pos = newpos - oldpos; + info("+++ %016lX Smeared position [%9.2e %9.2e %9.2e] by [%9.2e %9.2e %9.2e] to [%9.2e %9.2e %9.2e] [mm]", + oldpos.X(), oldpos.Y(), oldpos.Z(), delta_pos.X(), delta_pos.Y(), delta_pos.Z(), + newpos.X(), newpos.Y(), newpos.Z()); - /// Update / create deposit with smeared position - if ( m_update_in_place ) { - EnergyDeposit& d = dep.second; - d.position = newpos; - d.flag |= EnergyDeposit::POSITION_SMEARED; - ++updated; + /// Update / create deposit with smeared position + if ( m_update_in_place ) { + EnergyDeposit& d = dep.second; + d.position = newpos; + d.flag |= EnergyDeposit::POSITION_SMEARED; + ++updated; + } + else { + EnergyDeposit d(depo); + d.position = newpos; + d.flag |= EnergyDeposit::POSITION_SMEARED; + output_cont.emplace(cell, std::move(d)); + ++created; + } } - else { - EnergyDeposit d(depo); - d.position = newpos; - d.flag |= EnergyDeposit::POSITION_SMEARED; - output_cont.emplace(cell, std::move(d)); - ++created; + else if ( !m_update_in_place ) { + EnergyDeposit& d = dep.second; + d.flag |= EnergyDeposit::KILLED; + ++killed; } } - else if ( !m_update_in_place ) { - EnergyDeposit& d = dep.second; - d.flag |= EnergyDeposit::KILLED; - ++killed; - } } - if ( !m_update_in_place ) { work.output.data.put(output_cont.key, std::move(output_cont)); } @@ -125,11 +127,11 @@ namespace dd4hep { } /// Main functional callback - virtual void execute(DigiContext& context, work_t& work) const override final { + virtual void execute(DigiContext& context, work_t& work, const predicate_t& predicate) const override final { if ( auto* v = work.get_input<DepositVector>() ) - smear_deposit_position(context, *v, work); + smear(context, *v, work, predicate); else if ( auto* m = work.get_input<DepositMapping>() ) - smear_deposit_position(context, *m, work); + smear(context, *m, work, predicate); else except("Request to handle unknown data type: %s", work.input_type_name().c_str()); } diff --git a/DDDigi/plugins/DigiDepositSmearPositionTrack.cpp b/DDDigi/plugins/DigiDepositSmearPositionTrack.cpp index 652ae28da..25aad28fe 100644 --- a/DDDigi/plugins/DigiDepositSmearPositionTrack.cpp +++ b/DDDigi/plugins/DigiDepositSmearPositionTrack.cpp @@ -65,7 +65,8 @@ namespace dd4hep { } /// Create deposit mapping with updates on same cellIDs - template <typename T> void smear_deposit_position(DigiContext& context, T& cont, work_t& work) const { + template <typename T> void + smear(DigiContext& context, T& cont, work_t& work, const predicate_t& predicate) const { constexpr double eps = detail::numeric_epsilon; T output_cont(cont.name, work.output.mask); auto& random = context.randomGenerator(); @@ -80,55 +81,56 @@ namespace dd4hep { } VolumeManager volMgr = m_kernel.detectorDescription().volumeManager(); for( auto& dep : cont ) { - CellID cell = dep.first; - const EnergyDeposit& depo = dep.second; - double deposit = depo.deposit; - if ( deposit >= m_deposit_cutoff ) { - auto* ctxt = volMgr.lookupContext(cell); - Direction part_momentum = depo.history.average_particle_momentum(ev); - Position local_pos = ctxt->worldToLocal(depo.position); - Position local_dir = ctxt->worldToLocal(part_momentum).unit(); - double cos_u = local_dir.Dot(Position(1,0,0)); - double sin_u = std::sqrt(1e0 - cos_u*cos_u); - double tan_u = sin_u/(std::abs(cos_u)>eps ? cos_u : eps); - double delta_u = tan_u * m_resolution_u * random.gaussian(); - - double cos_v = local_dir.Dot(Position(0,1,0)); - double sin_v = std::sqrt(1e0 - cos_v*cos_v); - double tan_v = sin_v/(std::abs(cos_v)>eps ? cos_v : eps); - double delta_v = tan_v * m_resolution_v * random.gaussian(); - - Position delta_pos(delta_u, delta_v, 0e0); - Position oldpos = depo.position; - Position newpos = ctxt->localToWorld(local_pos + delta_pos); - - delta_pos = newpos - oldpos; - info("+++ %016lX Smeared position [%9.2e %9.2e %9.2e] by [%9.2e %9.2e %9.2e] to [%9.2e %9.2e %9.2e] [mm]", - oldpos.X(), oldpos.Y(), oldpos.Z(), delta_pos.X(), delta_pos.Y(), delta_pos.Z(), - newpos.X(), newpos.Y(), newpos.Z()); - - /// Update / create deposit with smeared position - if ( m_update_in_place ) { - EnergyDeposit& d = dep.second; - d.position = newpos; - d.flag |= EnergyDeposit::POSITION_SMEARED; - ++updated; + if ( predicate(dep) ) { + CellID cell = dep.first; + const EnergyDeposit& depo = dep.second; + double deposit = depo.deposit; + if ( deposit >= m_deposit_cutoff ) { + auto* ctxt = volMgr.lookupContext(cell); + Direction part_momentum = depo.history.average_particle_momentum(ev); + Position local_pos = ctxt->worldToLocal(depo.position); + Position local_dir = ctxt->worldToLocal(part_momentum).unit(); + double cos_u = local_dir.Dot(Position(1,0,0)); + double sin_u = std::sqrt(1e0 - cos_u*cos_u); + double tan_u = sin_u/(std::abs(cos_u)>eps ? cos_u : eps); + double delta_u = tan_u * m_resolution_u * random.gaussian(); + + double cos_v = local_dir.Dot(Position(0,1,0)); + double sin_v = std::sqrt(1e0 - cos_v*cos_v); + double tan_v = sin_v/(std::abs(cos_v)>eps ? cos_v : eps); + double delta_v = tan_v * m_resolution_v * random.gaussian(); + + Position delta_pos(delta_u, delta_v, 0e0); + Position oldpos = depo.position; + Position newpos = ctxt->localToWorld(local_pos + delta_pos); + + delta_pos = newpos - oldpos; + info("+++ %016lX Smeared position [%9.2e %9.2e %9.2e] by [%9.2e %9.2e %9.2e] to [%9.2e %9.2e %9.2e] [mm]", + oldpos.X(), oldpos.Y(), oldpos.Z(), delta_pos.X(), delta_pos.Y(), delta_pos.Z(), + newpos.X(), newpos.Y(), newpos.Z()); + + /// Update / create deposit with smeared position + if ( m_update_in_place ) { + EnergyDeposit& d = dep.second; + d.position = newpos; + d.flag |= EnergyDeposit::POSITION_SMEARED; + ++updated; + } + else { + EnergyDeposit d(depo); + d.position = newpos; + d.flag |= EnergyDeposit::POSITION_SMEARED; + output_cont.emplace(cell, std::move(d)); + ++created; + } } - else { - EnergyDeposit d(depo); - d.position = newpos; - d.flag |= EnergyDeposit::POSITION_SMEARED; - output_cont.emplace(cell, std::move(d)); - ++created; + else if ( !m_update_in_place ) { + EnergyDeposit& d = dep.second; + d.flag |= EnergyDeposit::KILLED; + ++killed; } } - else if ( !m_update_in_place ) { - EnergyDeposit& d = dep.second; - d.flag |= EnergyDeposit::KILLED; - ++killed; - } } - if ( !m_update_in_place ) { work.output.data.put(output_cont.key, std::move(output_cont)); } @@ -137,11 +139,11 @@ namespace dd4hep { } /// Main functional callback - virtual void execute(DigiContext& context, work_t& work) const override final { + virtual void execute(DigiContext& context, work_t& work, const predicate_t& predicate) const override final { if ( auto* v = work.get_input<DepositVector>() ) - smear_deposit_position(context, *v, work); + smear(context, *v, work, predicate); else if ( auto* m = work.get_input<DepositMapping>() ) - smear_deposit_position(context, *m, work); + smear(context, *m, work, predicate); else except("Request to handle unknown data type: %s", work.input_type_name().c_str()); } diff --git a/DDDigi/plugins/DigiDepositSmearTime.cpp b/DDDigi/plugins/DigiDepositSmearTime.cpp new file mode 100644 index 000000000..7925d1f82 --- /dev/null +++ b/DDDigi/plugins/DigiDepositSmearTime.cpp @@ -0,0 +1,116 @@ +//========================================================================== +// 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/DigiContainerProcessor.h> +#include <DD4hep/InstanceCount.h> +#include <DD4hep/DD4hepUnits.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 { + + /// Actor to smear timing information of energy deposits + /** + * + * + * \author M.Frank + * \version 1.0 + * \ingroup DD4HEP_DIGITIZATION + */ + class DigiDepositSmearTime : public DigiContainerProcessor { + protected: + using limit_t = std::numeric_limits<double>; + /// Property: Intrinsic energy resolution constant (gaussian ~ std::sqrt(energy)) + double m_resolution_time { 0e0 }; + /// Property: Time window within the smeared deposits shall be accepted + std::pair<double, double> m_window_time { limit_t::min(), limit_t::max() }; + /// Property: Flag to update existing container in-place or create a new container + bool m_update_in_place { true }; + + public: + /// Standard constructor + DigiDepositSmearTime(const DigiKernel& krnl, const std::string& nam) + : DigiContainerProcessor(krnl, nam) + { + declareProperty("resolution_time", m_resolution_time); + declareProperty("window_time", m_window_time); + InstanceCount::increment(this); + } + + /// Default destructor + virtual ~DigiDepositSmearTime() { + InstanceCount::decrement(this); + } + + /// Create deposit mapping with updates on same cellIDs + template <typename T> void + smear(DigiContext& context, T& cont, work_t& work, const predicate_t& predicate) const { + auto& random = context.randomGenerator(); + T output_cont(cont.name, work.output.mask); + std::size_t killed = 0UL; + std::size_t updated = 0UL; + std::size_t created = 0UL; + + info("%s+++ TIME smearing deposit container: %s %6ld entries", + context.event->id(), cont.name.c_str(), cont.size()); + for( auto& dep : cont ) { + if ( predicate(dep) ) { + int flag = EnergyDeposit::TIME_SMEARED; + double delta_T = m_resolution_time * random.gaussian(); + if ( delta_T < m_window_time.first || delta_T > m_window_time.second ) { + flag |= EnergyDeposit::KILLED; + ++killed; + } + if ( m_update_in_place ) { + EnergyDeposit& d = dep.second; + d.time += delta_T; + d.flag |= flag; + ++updated; + } + else if ( !(flag&EnergyDeposit::KILLED) ) { + EnergyDeposit d(dep.second); + d.time += delta_T; + d.flag |= flag; + output_cont.emplace(dep.first, std::move(d)); + ++created; + } + } + } + if ( !m_update_in_place ) { + work.output.data.put(output_cont.key, std::move(output_cont)); + } + info("%s+++ %-32s Smearing: created %6ld updated %6ld killed %6ld entries from mask: %04X", + context.event->id(), cont.name.c_str(), created, updated, killed, cont.key.mask()); + } + + /// Main functional callback + virtual void execute(DigiContext& context, work_t& work, const predicate_t& predicate) const override final { + if ( auto* v = work.get_input<DepositVector>() ) + smear(context, *v, work, predicate); + else if ( auto* m = work.get_input<DepositMapping>() ) + smear(context, *m, work, predicate); + else + except("Request to handle unknown data type: %s", work.input_type_name().c_str()); + } + }; + } // End namespace digi +} // End namespace dd4hep + +#include <DDDigi/DigiFactories.h> +DECLARE_DIGIACTION_NS(dd4hep::digi,DigiDepositSmearTime) diff --git a/DDDigi/plugins/DigiDepositWeightedPosition.cpp b/DDDigi/plugins/DigiDepositWeightedPosition.cpp index 7de2ee4e7..4bde23c5a 100644 --- a/DDDigi/plugins/DigiDepositWeightedPosition.cpp +++ b/DDDigi/plugins/DigiDepositWeightedPosition.cpp @@ -54,22 +54,25 @@ namespace dd4hep { } /// Create deposit mapping with updates on same cellIDs - template <typename T> void create_deposits(const char* tag, const T& cont, work_t& work) const { + template <typename T> void + create_deposits(const char* tag, const T& cont, work_t& work, const predicate_t& predicate) const { Key key(cont.name, work.output.mask); DepositMapping m(cont.name, work.output.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; + if ( predicate(dep) ) { + 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; } - ++dropped; } info("%s+++ %-32s added %6ld updated %6ld dropped %6ld entries (now: %6ld) from mask: %04X to mask: %04X", tag, cont.name.c_str(), added, updated, dropped, m.size(), cont.key.mask(), m.key.mask()); @@ -77,11 +80,11 @@ namespace dd4hep { } /// Main functional callback - virtual void execute(DigiContext& context, work_t& work) const override final { + virtual void execute(DigiContext& context, work_t& work, const predicate_t& predicate) const override final { if ( const auto* v = work.get_input<DepositVector>() ) - create_deposits(context.event->id(), *v, work); + create_deposits(context.event->id(), *v, work, predicate); else if ( const auto* m = work.get_input<DepositMapping>() ) - create_deposits(context.event->id(), *m, work); + create_deposits(context.event->id(), *m, work, predicate); else except("%s+++ Request to handle unknown data type: %s", context.event->id(), work.input_type_name().c_str()); diff --git a/DDDigi/plugins/DigiHitHistoryDrop.cpp b/DDDigi/plugins/DigiHitHistoryDrop.cpp index 652129098..5b3c663dc 100644 --- a/DDDigi/plugins/DigiHitHistoryDrop.cpp +++ b/DDDigi/plugins/DigiHitHistoryDrop.cpp @@ -63,8 +63,8 @@ namespace dd4hep { std::pair<std::size_t, std::size_t> drop_history(T& cont) const { std::size_t num_drop_hit = 0; std::size_t num_drop_particle = 0; - for( auto& c : cont ) { - auto ret = c.second.history.drop(); + for( auto& dep : cont ) { + auto ret = dep.second.history.drop(); num_drop_hit += ret.first; num_drop_particle += ret.second; } @@ -76,16 +76,16 @@ namespace dd4hep { auto& inputs = context.event->get_segment(m_input); std::size_t num_drop_hit = 0; std::size_t num_drop_particle = 0; - for ( auto& i : inputs ) { + for( auto& i : inputs ) { Key key(i.first); auto im = std::find(m_masks.begin(), m_masks.end(), key.mask()); - if ( im != m_masks.end() ) { - if ( DepositMapping* m = std::any_cast<DepositMapping>(&i.second) ) { + if( im != m_masks.end() ) { + if( DepositMapping* m = std::any_cast<DepositMapping>(&i.second) ) { auto ret = drop_history(*m); num_drop_hit += ret.first; num_drop_particle += ret.second; } - if ( DepositVector* m = std::any_cast<DepositVector>(&i.second) ) { + if( DepositVector* m = std::any_cast<DepositVector>(&i.second) ) { auto ret = drop_history(*m); num_drop_hit += ret.first; num_drop_particle += ret.second; diff --git a/DDDigi/plugins/DigiIPMover.cpp b/DDDigi/plugins/DigiIPMover.cpp index 0aa07c56e..804089bf0 100644 --- a/DDDigi/plugins/DigiIPMover.cpp +++ b/DDDigi/plugins/DigiIPMover.cpp @@ -11,14 +11,16 @@ // //========================================================================== -// Framework include files +/// Framework include files #include <DDDigi/DigiData.h> #include <DDDigi/DigiContainerProcessor.h> +/// C/C++ include files #include <iostream> /// Namespace for the AIDA detector description toolkit namespace dd4hep { + /// Namespace for the Digitization part of the AIDA detector description toolkit namespace digi { @@ -32,21 +34,29 @@ namespace dd4hep { */ class DigiIPMover : public DigiContainerProcessor { public: + /// Standard constructor DigiIPMover(const DigiKernel& krnl, const std::string& nam) : DigiContainerProcessor(krnl, nam) { } + /// Move IP location of deposits - template <typename T> std::size_t move_deposits(const char* tag, T& cont, const Position& delta) const { + template <typename DEPOSITS> std::size_t + move_deposits(const char* tag, DEPOSITS& cont, const Position& delta, const predicate_t& predicate) 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; + for( auto& dep : cont ) { + if( predicate(dep) ) { + dep.second.position += delta; + } + } return cont.size(); } + /// Move IP location of MC particles - template <typename T> std::size_t move_particles(const char* tag, T& cont, const Position& delta) const { + template <typename PARTICLES> std::size_t + move_particles(const char* tag, PARTICLES& 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 ) { @@ -56,14 +66,15 @@ namespace dd4hep { } return cont.size(); } + /// Main functional callback - virtual void execute(DigiContext& context, work_t& work) const override { + virtual void execute(DigiContext& context, work_t& work, const predicate_t& predicate) 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); + move_deposits(tag, *m, delta, predicate); else if ( auto* v = work.get_input<DepositVector>() ) - move_deposits(tag, *v, delta); + move_deposits(tag, *v, delta, predicate); else if ( auto* p = work.get_input<ParticleMapping>() ) move_particles(tag, *p, delta); else diff --git a/DDDigi/plugins/DigiResegment.cpp b/DDDigi/plugins/DigiResegment.cpp index e70ac5eb7..c34298d75 100644 --- a/DDDigi/plugins/DigiResegment.cpp +++ b/DDDigi/plugins/DigiResegment.cpp @@ -103,35 +103,38 @@ namespace dd4hep { info("+++ Successfully initialized resegmentation action."); } - template <typename T> void resegment_deposits(const T& cont, work_t& work) const { + template <typename T> void + resegment_deposits(const T& cont, work_t& work, const predicate_t& predicate) const { Key key(cont.name, work.output.mask); DepositVector m(cont.name, work.output.mask); std::size_t start = m.size(); for( const auto& dep : cont ) { - CellID cell = dep.first; - auto* ctxt = m_volmgr.lookupContext(cell); - if ( !ctxt ) { - error("+++ Cannot locate volume context for cell %016lX", cell); - } - else { - VolumeID volID = m_org_segment.volumeID(cell); - Position org_local = m_org_segment.position(cell); - Position global = ctxt->localToWorld(org_local); - CellID new_cell = m_new_segment.cellID(org_local, global, volID); - Position new_local = m_new_segment.position(new_cell); - if ( m_debug ) { - info("+++ Cell: %016lX -> %016lX DE: %-20s " - "Pos global: %8.2f %8.2f %8.2f local: %8.2f %8.2f %8.2f -> %8.2f %8.2f %8.2f", - cell, new_cell, ctxt->element.name(), - global.X(), global.Y(), global.Z(), - org_local.X(), org_local.Y(), org_local.Z(), - new_local.X(), new_local.Y(), new_local.Z() - ); + if( predicate(dep) ) { + CellID cell = dep.first; + auto* ctxt = m_volmgr.lookupContext(cell); + if ( !ctxt ) { + error("+++ Cannot locate volume context for cell %016lX", cell); + } + else { + VolumeID volID = m_org_segment.volumeID(cell); + Position org_local = m_org_segment.position(cell); + Position global = ctxt->localToWorld(org_local); + CellID new_cell = m_new_segment.cellID(org_local, global, volID); + Position new_local = m_new_segment.position(new_cell); + if ( m_debug ) { + info("+++ Cell: %016lX -> %016lX DE: %-20s " + "Pos global: %8.2f %8.2f %8.2f local: %8.2f %8.2f %8.2f -> %8.2f %8.2f %8.2f", + cell, new_cell, ctxt->element.name(), + global.X(), global.Y(), global.Z(), + org_local.X(), org_local.Y(), org_local.Z(), + new_local.X(), new_local.Y(), new_local.Z() + ); + } + EnergyDeposit d(dep.second); + d.position = global; + d.momentum = dep.second.momentum; + m.emplace(new_cell, std::move(d)); } - EnergyDeposit d(dep.second); - d.position = global; - d.momentum = dep.second.momentum; - m.emplace(new_cell, std::move(d)); } } std::size_t end = m.size(); @@ -141,11 +144,11 @@ namespace dd4hep { } /// Main functional callback - virtual void execute(DigiContext&, work_t& work) const override final { + virtual void execute(DigiContext&, work_t& work, const predicate_t& predicate) const override final { if ( const auto* m = work.get_input<DepositMapping>() ) - resegment_deposits(*m, work); + resegment_deposits(*m, work, predicate); else if ( const auto* v = work.get_input<DepositVector>() ) - resegment_deposits(*v, work); + resegment_deposits(*v, work, predicate); else except("Request to handle unknown data type: %s", work.input_type_name().c_str()); } diff --git a/DDDigi/plugins/DigiSegmentDepositExtractor.cpp b/DDDigi/plugins/DigiSegmentDepositExtractor.cpp index 7ee93ee13..48c81e463 100644 --- a/DDDigi/plugins/DigiSegmentDepositExtractor.cpp +++ b/DDDigi/plugins/DigiSegmentDepositExtractor.cpp @@ -13,7 +13,7 @@ // Framework include files #include <DDDigi/DigiContext.h> -#include <DDDigi/DigiSegmentProcessor.h> +#include <DDDigi/DigiContainerProcessor.h> /// Namespace for the AIDA detector description toolkit namespace dd4hep { @@ -30,31 +30,31 @@ namespace dd4hep { * \version 1.0 * \ingroup DD4HEP_DIGITIZATION */ - class DigiSegmentDepositExtractor : public DigiSegmentProcessor { + class DigiSegmentDepositExtractor : public DigiContainerProcessor { public: /// Standard constructor DigiSegmentDepositExtractor(const DigiKernel& kernel, const std::string& nam) - : DigiSegmentProcessor(kernel, nam) {} + : DigiContainerProcessor(kernel, nam) {} - template <typename T> void copy_deposits(const T& cont, work_t& work) const { + template <typename T> void copy_deposits(const T& cont, work_t& work, const predicate_t& predicate) const { DepositVector deposits(cont.name, work.output.mask); for( const auto& dep : cont ) { - CellID cell = dep.first; - EnergyDeposit depo = dep.second; - deposits.data.emplace_back(cell, std::move(depo)); + if( predicate(dep) ) { + CellID cell = dep.first; + EnergyDeposit depo = dep.second; + deposits.data.emplace_back(cell, std::move(depo)); + } } work.output.data.put(deposits.key, std::move(deposits)); } /// Main functional callback - virtual void execute(DigiContext&, work_t& work) const override final { - if ( segment.matches(work.input.key.value()) ) { - if ( const auto* m = work.get_input<DepositMapping>() ) - copy_deposits(*m, work); - else if ( const auto* v = work.get_input<DepositVector>() ) - copy_deposits(*v, work); - else - except("Request to handle unknown data type: %s", work.input_type_name().c_str()); - } + virtual void execute(DigiContext&, work_t& work, const predicate_t& predicate) const override final { + if ( const auto* m = work.get_input<DepositMapping>() ) + copy_deposits(*m, work, predicate); + else if ( const auto* v = work.get_input<DepositVector>() ) + copy_deposits(*v, work, predicate); + else + except("Request to handle unknown data type: %s", work.input_type_name().c_str()); } }; } // End namespace digi diff --git a/DDDigi/plugins/DigiSegmentDepositPrint.cpp b/DDDigi/plugins/DigiSegmentDepositPrint.cpp index a97281da9..db28f56d0 100644 --- a/DDDigi/plugins/DigiSegmentDepositPrint.cpp +++ b/DDDigi/plugins/DigiSegmentDepositPrint.cpp @@ -13,10 +13,12 @@ // Framework include files #include <DDDigi/DigiContext.h> -#include <DDDigi/DigiSegmentProcessor.h> +#include <DDDigi/DigiSegmentSplitter.h> +#include <DDDigi/DigiContainerProcessor.h> /// Namespace for the AIDA detector description toolkit namespace dd4hep { + /// Namespace for the Digitization part of the AIDA detector description toolkit namespace digi { @@ -27,33 +29,38 @@ namespace dd4hep { * \version 1.0 * \ingroup DD4HEP_SIMULATION */ - class DigiSegmentDepositPrint : public DigiSegmentProcessor { + class DigiSegmentDepositPrint : public DigiContainerProcessor { public: /// Standard constructor DigiSegmentDepositPrint(const DigiKernel& kernel, const std::string& nam) - : DigiSegmentProcessor(kernel, nam) {} + : DigiContainerProcessor(kernel, nam) {} /// Single container printout - template <typename T> void print_deposits(const char* fmt, const T& cont) const { - for(const auto& dep : cont) { - if( this->segment.matches(dep.first) ) { - info(fmt, segment.split_id(dep.first), dep.first, + template <typename T> void + print(const char* fmt, const T& cont, const predicate_t& predicate) const { + for( const auto& dep : cont ) { + if( predicate(dep) ) { + info(fmt, predicate.segmentation.split_id(dep.first), dep.first, dep.second.history.hits.size(), dep.second.history.particles.size(), dep.second.deposit); } } } + /// Main functional callback - virtual void execute(DigiContext& context, work_t& work) const override final { + virtual void execute(DigiContext& context, work_t& work, const predicate_t& predicate) 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", - context.event->id(), segment.idspec.name(), segment.cname(), segment.id, segment.split_mask); + "%s[%s] %s-id: %%d [processor:%d] Cell: %%016lX mask: %016lX " + "hist:%%4ld hits %%4ld parts. entries deposit: %%f", + context.event->id(), + predicate.segmentation.idspec.name(), predicate.segmentation.cname(), + predicate.segmentation.id, predicate.segmentation.split_mask); if ( const auto* m = work.get_input<DepositMapping>() ) - print_deposits(format, *m); + print(format, *m, predicate); else if ( const auto* v = work.get_input<DepositVector>() ) - print_deposits(format, *v); + print(format, *v, predicate); else error("+++ Request to dump an invalid container %s", Key::key_name(work.input.key).c_str()); } diff --git a/DDDigi/plugins/DigiSimpleADCResponse.cpp b/DDDigi/plugins/DigiSimpleADCResponse.cpp index 540901261..5f5c52cec 100644 --- a/DDDigi/plugins/DigiSimpleADCResponse.cpp +++ b/DDDigi/plugins/DigiSimpleADCResponse.cpp @@ -12,7 +12,8 @@ //========================================================================== // Framework include files -#include <DDDigi/DigiSegmentProcessor.h> +#include <DDDigi/DigiContainerProcessor.h> +#include <DDDigi/DigiSegmentSplitter.h> /// C/C++ include files #include <cmath> @@ -23,19 +24,20 @@ namespace dd4hep { /// Namespace for the Digitization part of the AIDA detector description toolkit namespace digi { - class DigiSimpleADCResponse : public DigiSegmentProcessor { - std::string m_response_postfix { ".adc" }; - std::string m_history_postfix { ".hist" }; - double m_use_segmentation { false }; - double m_signal_cutoff { std::numeric_limits<double>::epsilon() }; - double m_signal_saturation { std::numeric_limits<double>::max() }; - double m_adc_offset { 0e0 }; - std::size_t m_adc_resolution { 1024 }; - - public: + class DigiSimpleADCResponse : public DigiContainerProcessor { + using segmentation_t = DigiSegmentProcessContext; + std::string m_response_postfix { ".adc" }; + std::string m_history_postfix { ".hist" }; + double m_use_segmentation { false }; + double m_signal_cutoff { std::numeric_limits<double>::epsilon() }; + double m_signal_saturation { std::numeric_limits<double>::max() }; + double m_adc_offset { 0e0 }; + std::size_t m_adc_resolution { 1024 }; + + public: /// Standard constructor DigiSimpleADCResponse(const DigiKernel& krnl, const std::string& nam) - : DigiSegmentProcessor(krnl, nam) + : DigiContainerProcessor(krnl, nam) { declareProperty("cutoff", m_signal_cutoff); declareProperty("saturation", m_signal_saturation); @@ -46,8 +48,8 @@ namespace dd4hep { /// 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(); + void emulate_adc(const char* tag, const T& input, work_t& work, const P& predicate) const { + std::string postfix = m_use_segmentation ? "."+predicate.segmentation.identifier() : std::string(); std::string history_name = input.name + postfix + m_history_postfix; std::string response_name = input.name + postfix + m_response_postfix; DetectorHistory history (history_name, work.output.mask); @@ -68,24 +70,26 @@ namespace dd4hep { work.output.data.put(response.key, std::move(response)); work.output.data.put(history.key, std::move(history)); } + /// 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 { + void emulate_adc(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); + emulate_adc(tag, *m, work, predicate); else if ( const auto* v = work.get_input<DepositVector>() ) - create_adc_counts(tag, *v, work, predicate); + emulate_adc(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 { + virtual void execute(DigiContext& context, work_t& work, const predicate_t& predicate) const final { if ( !m_use_segmentation ) - create_adc_counts(context, work, accept_all_t()); - else if ( segment.matches(work.input.key.value()) ) - create_adc_counts(context, work, accept_segment_t(segment)); + emulate_adc(context, work, accept_all()); + else if ( predicate.segmentation.matches(work.input.key.value()) ) + emulate_adc(context, work, accept_segment_t(predicate.segmentation)); } }; } // End namespace digi diff --git a/DDDigi/python/DDDigiDict.C b/DDDigi/python/DDDigiDict.C index 7458ef7a9..56b77864a 100644 --- a/DDDigi/python/DDDigiDict.C +++ b/DDDigi/python/DDDigiDict.C @@ -191,7 +191,6 @@ namespace dd4hep { #include <DDDigi/DigiSynchronize.h> #include <DDDigi/DigiInputAction.h> #include <DDDigi/DigiSegmentSplitter.h> -#include <DDDigi/DigiSegmentProcessor.h> #include <DDDigi/DigiActionSequence.h> #include <DDDigi/DigiSignalProcessor.h> @@ -225,8 +224,6 @@ using namespace std; #pragma link C++ class dd4hep::digi::DigiContainerSequenceAction; #pragma link C++ class dd4hep::digi::DigiMultiContainerProcessor; -#pragma link C++ class dd4hep::digi::DigiSegmentProcessor; -#pragma link C++ class dd4hep::digi::DigiSegmentSequence; #pragma link C++ class dd4hep::digi::DigiSegmentSplitter; /// Digi data item wrappers diff --git a/DDDigi/python/dddigi.py b/DDDigi/python/dddigi.py index 87b582e3a..8f7b02eba 100644 --- a/DDDigi/python/dddigi.py +++ b/DDDigi/python/dddigi.py @@ -243,11 +243,19 @@ def _adopt_event_action(self, action): # --------------------------------------------------------------------------- -def _adopt_container_processor(self, action, container): +def _adopt_container_processor(self, action, processor_argument): " Helper to convert DigiActions objects to DigiEventAction " attr = getattr(_get_action(self), 'adopt_processor') proc = Interface.toContainerProcessor(_get_action(action)) - attr(proc, container) + attr(proc, processor_argument) +# --------------------------------------------------------------------------- + + +def _adopt_segment_processor(self, action, processor_argument): + " Helper to convert DigiActions objects to DigiEventAction " + attr = getattr(_get_action(self), '__adopt_segment_processor') + proc = Interface.toContainerProcessor(_get_action(action)) + attr(proc, processor_argument) # --------------------------------------------------------------------------- @@ -301,8 +309,12 @@ def _props(obj, **extensions): cls = getattr(current, obj) for extension in extensions.items(): call = extension[0] + # print('TRY: Overloading: '+str(cls)+' '+call+' to __'+call+' '+str(hasattr(cls, call))) if hasattr(cls, call): + # print('Overloading: '+str(cls)+' '+call+' to __'+call) setattr(cls, '__' + call, getattr(cls, call)) + else: + print('FAILED: Overloading: '+str(cls)+' '+call+' to __'+call+' '+str(hasattr(cls, call))) setattr(cls, call, extension[1]) cls.__getattr__ = _get cls.__setattr__ = _set @@ -333,6 +345,7 @@ _props('DigiParallelActionSequence', adopt_action=_adopt_sequence_action) _props('DigiSequentialActionSequence', adopt_action=_adopt_sequence_action) _props('DigiContainerSequenceAction', adopt_container_processor=_adopt_container_processor) _props('DigiMultiContainerProcessor', adopt_processor=_adopt_processor) +_props('DigiSegmentSplitter', adopt_segment_processor=_adopt_segment_processor) # # Need to import digitize late, since it cross includes dddigi Digitize = None diff --git a/DDDigi/src/DigiAttenuator.cpp b/DDDigi/src/DigiAttenuator.cpp index 42f4746f3..df9c9a12e 100644 --- a/DDDigi/src/DigiAttenuator.cpp +++ b/DDDigi/src/DigiAttenuator.cpp @@ -43,23 +43,26 @@ DigiAttenuator::~DigiAttenuator() { } /// Attenuator callback for single container -template <typename T> std::size_t DigiAttenuator::attenuate(T& cont) const { - for( auto& c : cont ) { - auto& depo = c.second; - depo.deposit *= m_factor; - for( auto& h : depo.history.hits ) h.weight *= m_factor; - for( auto& h : depo.history.particles ) h.weight *= m_factor; +template <typename T> std::size_t +DigiAttenuator::attenuate(T& cont, const predicate_t& predicate) const { + for( auto& dep : cont ) { + if ( predicate(dep) ) { + auto& depo = dep.second; + depo.deposit *= m_factor; + for( auto& h : depo.history.hits ) h.weight *= m_factor; + for( auto& h : depo.history.particles ) h.weight *= m_factor; + } } return cont.size(); } /// Main functional callback adapter -void DigiAttenuator::execute(DigiContext& context, work_t& work) const { +void DigiAttenuator::execute(DigiContext& context, work_t& work, const predicate_t& predicate) const { std::size_t count = 0; if ( auto* m = work.get_input<DepositMapping>() ) - count = this->attenuate(*m); + count = this->attenuate(*m, predicate); else if ( auto* v = work.get_input<DepositVector>() ) - count = this->attenuate(*v); + count = this->attenuate(*v, predicate); Key key { work.input.key }; std::string nam = Key::key_name(key)+":"; info("%s+++ %-32s mask:%04X item: %08X Attenuated %6ld hits by %8.5f", diff --git a/DDDigi/src/DigiContainerProcessor.cpp b/DDDigi/src/DigiContainerProcessor.cpp index df186c91b..040a7731b 100644 --- a/DDDigi/src/DigiContainerProcessor.cpp +++ b/DDDigi/src/DigiContainerProcessor.cpp @@ -17,6 +17,7 @@ #include <DDDigi/DigiKernel.h> #include <DDDigi/DigiContext.h> #include <DDDigi/DigiContainerProcessor.h> +#include <DDDigi/DigiSegmentSplitter.h> /// C/C++ include files #include <sstream> @@ -78,6 +79,25 @@ std::string DigiContainerProcessor::work_t::input_type_name() const { return typeName(input.data.type()); } +/// Access to default callback +const DigiContainerProcessor::predicate_t& DigiContainerProcessor::accept_all() { + struct true_t { + bool use(const std::pair<const CellID, EnergyDeposit>&) const { + return true; + } + }; + static true_t s_y { }; + static segmentation_t s_seg {}; + static predicate_t s_true { Callback(&s_y).make(&true_t::use), s_seg }; + return s_true; +} + +/// Check if a deposit should be processed +bool DigiContainerProcessor::predicate_t::operator()(const std::pair<const CellID, EnergyDeposit>& deposit) const { + const void* args[] = { &deposit }; + return this->callback.execute(args); +} + /// Standard constructor DigiContainerProcessor::DigiContainerProcessor(const DigiKernel& kernel, const std::string& name) : DigiAction(kernel, name) @@ -90,15 +110,10 @@ DigiContainerProcessor::~DigiContainerProcessor() { InstanceCount::decrement(this); } -/// Main functional callback -void DigiContainerProcessor::execute(DigiContext& context, work_t& work) const { - this->execute(context, work.input.key, work.input.data); -} - /// Main functional callback if specific work is known -void DigiContainerProcessor::execute(DigiContext& context, Key key, std::any& /* data */) const { - info("%s+++ %p Using container: %016lX --> %04X %08X %s", - context.event->id(), (void*)this, key.value(), key.mask(), key.item(), Key::key_name(key).c_str()); +void DigiContainerProcessor::execute(DigiContext& /* context */, + work_t& /* work */, + const predicate_t& /* predicate */) const { } /// Standard constructor @@ -124,8 +139,9 @@ 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(context, m_workers.get_group(), m_workers.size(), &work, m_parallel); +void DigiContainerSequence::execute(DigiContext& context, work_t& work, const predicate_t& /* predicate */) const { + auto group = m_workers.get_group(); + m_kernel.submit(context, group, m_workers.size(), &work, m_parallel); } /// Worker adaptor for caller DigiContainerSequence @@ -133,7 +149,7 @@ template <> void DigiParallelWorker<DigiContainerProcessor, DigiContainerSequence::work_t, std::size_t>::execute(void* data) const { calldata_t* args = reinterpret_cast<calldata_t*>(data); - action->execute(args->context, *args); + action->execute(args->context, *args, action->accept_all()); } /// Standard constructor @@ -242,7 +258,7 @@ template <> void DigiParallelWorker<DigiContainerProcessor, calldata_t* args = reinterpret_cast<calldata_t*>(data); auto& item = args->input_items[this->options]; DigiContainerProcessor::work_t work {args->context, {item.key, *item.data}, args->output, args->properties}; - action->execute(args->context, work); + action->execute(args->context, work, action->accept_all()); } /// Standard constructor @@ -373,12 +389,12 @@ template <> void DigiParallelWorker<DigiContainerProcessor, tag = "mask accepted"; if ( keys.empty() ) { DigiContainerProcessor::work_t work {arg->context, {key, *item.second }, arg->output, arg->properties }; - action->execute(work.context, work); + action->execute(work.context, work, action->accept_all()); continue; } else if ( std::find(keys.begin(), keys.end(), key) != keys.end() ) { DigiContainerProcessor::work_t work {arg->context, {key, *item.second }, arg->output, arg->properties }; - action->execute(work.context, work); + action->execute(work.context, work, action->accept_all()); continue; } tag = "no keys matching"; diff --git a/DDDigi/src/DigiHandle.cpp b/DDDigi/src/DigiHandle.cpp index 64aefbab5..1099d011d 100644 --- a/DDDigi/src/DigiHandle.cpp +++ b/DDDigi/src/DigiHandle.cpp @@ -20,7 +20,6 @@ #include <DDDigi/DigiKernel.h> #include <DDDigi/DigiInputAction.h> #include <DDDigi/DigiEventAction.h> -#include <DDDigi/DigiSegmentProcessor.h> #include <DDDigi/DigiSignalProcessor.h> // C/C++ include files @@ -69,10 +68,6 @@ namespace dd4hep { return PluginService::Create<DigiAction*>(t, &kernel, n); } - template <> DigiSegmentProcessor* _raw_create<DigiSegmentProcessor>(const std::string& t, const DigiKernel& kernel, const std::string& n) { - return PluginService::Create<DigiSegmentProcessor*>(t, &kernel, n); - } - template <> DigiSignalProcessor* _raw_create<DigiSignalProcessor>(const std::string& t, const DigiKernel& kernel, const std::string& n) { return PluginService::Create<DigiSignalProcessor*>(t, &kernel, n); } @@ -202,7 +197,6 @@ namespace dd4hep { template class DigiHandle<DigiAction>; template class DigiHandle<DigiInputAction>; template class DigiHandle<DigiEventAction>; - template class DigiHandle<DigiSegmentProcessor>; template class DigiHandle<DigiSynchronize>; template class DigiHandle<DigiActionSequence>; template class DigiHandle<DigiSignalProcessor>; diff --git a/DDDigi/src/DigiSegmentProcessor.cpp b/DDDigi/src/DigiSegmentProcessor.cpp deleted file mode 100644 index 9ce3a2e12..000000000 --- a/DDDigi/src/DigiSegmentProcessor.cpp +++ /dev/null @@ -1,74 +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/DigiKernel.h> -#include <DDDigi/DigiSegmentProcessor.h> - -using namespace dd4hep::digi; - -/// Standard constructor -DigiSegmentProcessor::DigiSegmentProcessor(const DigiKernel& krnl, const std::string& nam) - : DigiContainerProcessor(krnl, nam) -{ - InstanceCount::increment(this); -} - -/// Default destructor -DigiSegmentProcessor::~DigiSegmentProcessor() { - InstanceCount::decrement(this); -} - -/// Main functional callback if specific work is known -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->execute(work->context, *work); -} - -/// Standard constructor -DigiSegmentSequence::DigiSegmentSequence(const DigiKernel& krnl, const std::string& nam) - : DigiSegmentProcessor(krnl, nam) -{ - InstanceCount::increment(this); -} - -/// Default destructor -DigiSegmentSequence::~DigiSegmentSequence() { - InstanceCount::decrement(this); -} - -/// Adopt new parallel worker -void DigiSegmentSequence::adopt_processor(DigiContainerProcessor* action) { - if ( !action ) { - except("+++ FAILED: attempt to add invalid processor!"); - } - auto* proc = dynamic_cast<DigiSegmentProcessor*>(action); - if ( !proc ) { - error("+++ FAILED: Attempt to add processor %s of type %s", - action->c_name(), typeName(typeid(*action)).c_str()); - except("+++ DigiSegmentSplitter do ONLY accept processors of type DigiSegmentProcessor!"); - } - proc->segment = segment; - m_workers.insert(new worker_t(proc, proc->segment.id)); -} - -/// Main functional callback -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 8b22c28c7..4944c8c63 100644 --- a/DDDigi/src/DigiSegmentSplitter.cpp +++ b/DDDigi/src/DigiSegmentSplitter.cpp @@ -21,9 +21,39 @@ using namespace dd4hep::digi; +/// Default copy constructor +DigiSegmentProcessContext::DigiSegmentProcessContext(const DigiSegmentContext& copy) + : DigiSegmentContext(copy) +{ +} + +/// Full identifier (field + id) +std::string DigiSegmentProcessContext::identifier() const { + std::stringstream str; + if ( this->field ) { + str << this->field->name() << "." << this->id; + } + return str.str(); +} + +/// Default move assignment +DigiSegmentProcessContext& +DigiSegmentProcessContext::operator=(const DigiSegmentContext& copy) { + this->DigiSegmentContext::operator=(copy); + return *this; +} + +/// Worker adaptor for caller DigiContainerSequence +template <> void DigiParallelWorker<DigiContainerProcessor, + DigiContainerProcessor::work_t, + DigiSegmentProcessContext>::execute(void* ptr) const { + calldata_t* args = reinterpret_cast<calldata_t*>(ptr); + action->execute(args->context, *args, this->options.predicate); +} + /// Standard constructor DigiSegmentSplitter::DigiSegmentSplitter(const DigiKernel& kernel, const std::string& nam) - : DigiContainerSequence(kernel, nam), + : DigiContainerProcessor(kernel, nam), m_split_tool(kernel.detectorDescription()) { declareProperty("detector", m_detector_name); @@ -70,11 +100,17 @@ void DigiSegmentSplitter::initialize() { for( auto& p : m_splits ) { auto split_id = p.second.second; bool ok = false; - for( const auto* w : workers ) { - if ( VolumeID(w->options) == split_id ) { ok = true; break; } + for( auto* w : workers ) { + if ( w->options.id == split_id ) { + auto& segment = w->options; + segment = m_split_context; + segment.id = p.second.second; + ok = true; + break; + } } if ( !ok ) { - error("+++ Missing processor for plit ID: %08ld", split_id); + error("+++ Missing processor for split ID: %08ld", split_id); bad = true; } } @@ -88,37 +124,43 @@ void DigiSegmentSplitter::initialize() { /// IF NOT: /// 2) Create the processors using the 'processor_type' option for( auto& p : m_splits ) { - ::snprintf(text, sizeof(text), "_%05X", m_split_context.split_id(p.first)); + ::snprintf(text, sizeof(text), "_%05X", + m_split_context.split_id(p.first)); std::string nam = this->name() + text; - auto* proc = createAction<DigiSegmentProcessor>(m_processor_type, m_kernel, nam); + auto* proc = createAction<DigiContainerProcessor>(m_processor_type, m_kernel, nam); if ( !proc ) { - except("+++ Failed to create split worker: %s/%s", m_processor_type.c_str(), nam.c_str()); + except("+++ Failed to create split worker: %s/%s", + m_processor_type.c_str(), nam.c_str()); } - proc->segment = m_split_context; - proc->segment.detector = p.second.first; - proc->segment.id = p.second.second; - m_workers.insert(new worker_t(proc, proc->segment.id)); + auto* w = new worker_t(proc, m_split_context); + auto& segment = w->options; + segment.detector = p.second.first; + segment.id = p.second.second; + m_workers.insert(w); ++count; } info("+++ Detector splitter is now fully initialized!"); } -/// Adopt new parallel worker -void DigiSegmentSplitter::adopt_processor(DigiContainerProcessor* action) { +/// Adopt new parallel worker handling a single split identifier +void DigiSegmentSplitter::adopt_segment_processor(DigiContainerProcessor* action, int split_id) { if ( !action ) { except("+++ FAILED: attempt to add invalid processor!"); } - auto* proc = dynamic_cast<DigiSegmentProcessor*>(action); - if ( !proc ) { - error("+++ FAILED: Attempt to add processor %s of type %s", - action->c_name(), typeName(typeid(*action)).c_str()); - except("+++ DigiSegmentSplitter do ONLY accept processors of type DigiSegmentProcessor!"); + auto* w = new worker_t(action, m_split_context); + w->options.id = split_id; + m_workers.insert(w); +} + +/// Adopt new parallel worker handling multiple split-identifiers +void DigiSegmentSplitter::adopt_segment_processor(DigiContainerProcessor* action, const std::vector<int>& ids) { + for( int split_id : ids ) { + adopt_segment_processor(action, split_id); } - m_workers.insert(new worker_t(proc, m_workers.size())); } /// Main functional callback -void DigiSegmentSplitter::execute(DigiContext& context, work_t& work) const { +void DigiSegmentSplitter::execute(DigiContext& context, work_t& work, const predicate_t& /* predicate */) const { Key key = work.input_key(); Key unmasked_key; unmasked_key.set_item(key.item()); diff --git a/DDDigi/src/DigiSegmentationTool.cpp b/DDDigi/src/DigiSegmentationTool.cpp index a41d92856..2355590da 100644 --- a/DDDigi/src/DigiSegmentationTool.cpp +++ b/DDDigi/src/DigiSegmentationTool.cpp @@ -46,19 +46,15 @@ namespace { /// Split field name const string& DigiSegmentContext::name() const { - return this->field->name(); + if ( this->field ) { + return this->field->name(); + } + throw std::runtime_error("Invalid 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(); + return this->field ? this->field->name().c_str() : ""; } /// Initializing constructor @@ -185,16 +181,25 @@ DigiSegmentationTool::split_segmentation(const string& split_by) const const auto& ids = this->detector.placement().volIDs(); VolumeID vid = this->iddescriptor.encode(ids); VolumeID msk = this->iddescriptor.get_mask(ids); + const auto* fld = this->iddescriptor.field(split_by); const char* det = this->detector.name(); + if ( !fld ) { + except("DigiSegmentationTool","Field discriminator %s does not exist in ID descriptor %s", + split_by.c_str(), this->iddescriptor.name()); + } ::scan_detector(*this, split_by, segmentation_splits, this->detector, vid, msk); printout(INFO,"DigiSegmentationTool", "%-24s has %ld parallel entries when splitting by \"%s\"", det, segmentation_splits.size(), split_by.c_str()); - stringstream str; - for( const auto& id : segmentation_splits ) - str << setw(16) << hex << setfill('0') << id.first << " "; + stringstream str1, str2; + for( const auto& id : segmentation_splits ) { + str1 << setw(16) << hex << setfill('0') << id.first << " "; + str2 << setw(16) << hex << setfill(' ') << ((id.first&fld->mask())>>fld->offset()) << " "; + } printout(INFO,"DigiSegmentationTool","%-24s --> Parallel Entries: %s", - det, str.str().c_str()); + det, str1.str().c_str()); + printout(INFO,"DigiSegmentationTool","%-24s --> %-12s ids: %s", + "", split_by.c_str(), str2.str().c_str()); return segmentation_splits; } diff --git a/DDParsers/include/Parsers/spirit/ParsersFactory.h b/DDParsers/include/Parsers/spirit/ParsersFactory.h index 95830c06e..0e8fb8f9d 100644 --- a/DDParsers/include/Parsers/spirit/ParsersFactory.h +++ b/DDParsers/include/Parsers/spirit/ParsersFactory.h @@ -76,11 +76,19 @@ namespace dd4hep { // ============================================================================ #define PARSERS_DEF_FOR_SINGLE(Type) \ namespace dd4hep { \ - namespace Parsers { \ - template <> int parse(Type& result, const std::string& input) \ - { return parse_(result, input); } \ - template <> std::ostream& toStream(const Type& obj, std::ostream& s) \ - { return toStream_(obj, s); }}} + namespace Parsers { \ + template <> int parse(Type& result, const std::string& input) \ + { return parse_(result, input); } \ + template <> std::ostream& toStream(const Type& obj, std::ostream& s) \ + { return toStream_(obj, s); }}} +// ============================================================================ +#define PARSERS_DEF_FOR_PAIR(First,Second) \ + namespace dd4hep { \ + namespace Parsers { \ + template <> int parse(std::pair<First,Second>& result, const std::string& input) \ + { return parse_(result, input); } \ + template <> std::ostream& toStream(const std::pair<First,Second>& obj, std::ostream& s) \ + { return toStream_(obj, s); }}} // ============================================================================ #endif // PARSERS_SPIRIT_PARSERSFACTORY_H diff --git a/DDParsers/src/Spirit/ParsersStandardMisc1.cpp b/DDParsers/src/Spirit/ParsersStandardMisc1.cpp index 5538fe606..dfbedc6db 100755 --- a/DDParsers/src/Spirit/ParsersStandardMisc1.cpp +++ b/DDParsers/src/Spirit/ParsersStandardMisc1.cpp @@ -10,15 +10,19 @@ //========================================================================== #include "Parsers/spirit/ParsersStandardMiscCommon.h" +PARSERS_DEF_FOR_PAIR(bool,bool) +PARSERS_DEF_FOR_PAIR(float,float) +PARSERS_DEF_FOR_PAIR(double,double) +PARSERS_DEF_FOR_PAIR(double,int) +PARSERS_DEF_FOR_PAIR(double,long) +PARSERS_DEF_FOR_PAIR(double,size_t) + /// Namespace for the AIDA detector description toolkit namespace dd4hep { + /// Namespace for the AIDA detector for utilities using boost::spirit parsers namespace Parsers { - template <> int parse(std::pair<double,double>& result, const std::string& input) { - return parse_(result, input); - } - template <> int parse(std::vector<std::pair<double, double> >& result, const std::string& input) { return parse_(result, input); } diff --git a/examples/DDDigi/scripts/TestSegmentationSplit2.py b/examples/DDDigi/scripts/TestSegmentationSplit2.py new file mode 100644 index 000000000..88d1dc237 --- /dev/null +++ b/examples/DDDigi/scripts/TestSegmentationSplit2.py @@ -0,0 +1,50 @@ +# ========================================================================== +# 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) + digi.load_geo() + input = digi.input_action('DigiParallelActionSequence/READER') + # ======================================================================== + digi.info('Created SIGNAL input') + signal = input.adopt_action('DigiDDG4ROOT/SignalReader', mask=0x0, input=[digi.next_input()]) + digi.check_creation([signal]) + # ======================================================================== + event = digi.event_action('DigiSequentialActionSequence/EventAction') + split_action = event.adopt_action('DigiContainerSequenceAction/SplitSequence', + parallel=True, + input_mask=0x0, + input_segment='inputs', + output_segment='deposits', + output_mask=0xFEED) + splitter = digi.create_action('DigiSegmentSplitter/Splitter', + parallel=True, + split_by='layer', + detector='SiTrackerBarrel') + printer = digi.create_action('DigiSegmentDepositPrint/P1') + splitter.get().adopt_segment_processor(printer, 1) + printer = digi.create_action('DigiSegmentDepositPrint/P2') + splitter.adopt_segment_processor(printer, [2, 3, 4]) + printer = digi.create_action('DigiSegmentDepositPrint/P3') + splitter.adopt_segment_processor(printer, [5]) + split_action.adopt_container_processor(splitter, splitter.collection_names()) + + event.adopt_action('DigiStoreDump/StoreDump') + digi.info('Created event.dump') + # ======================================================================== + digi.run_checked(num_events=1, num_threads=10, parallel=3) + + +if __name__ == '__main__': + run() -- GitLab