diff --git a/DDDigi/CMakeLists.txt b/DDDigi/CMakeLists.txt index 35e7513a95c2d4fd92920f6ac636998ea60ebeef..8026b13af80b8e269c593e587c4ae9456793bedd 100644 --- a/DDDigi/CMakeLists.txt +++ b/DDDigi/CMakeLists.txt @@ -10,23 +10,16 @@ #========================================================================== SET_PROPERTY(DIRECTORY . PROPERTY PACKAGE_NAME DDDigi) file(GLOB DDDigi_SOURCES ${CMAKE_CURRENT_SOURCE_DIR}/src/*.cpp + ${CMAKE_CURRENT_SOURCE_DIR}/src/noise/*.cpp ${CMAKE_CURRENT_SOURCE_DIR}/src/segmentations/*.cpp) add_library(DDDigi ${DDDigi_SOURCES}) add_library(DD4hep::DDDigi ALIAS DDDigi) -## FIND_PACKAGE(GSL REQUIRED QUIET) -if(GSL_FOUND) - dd4hep_print( "|++> GSL_INCLUDE_DIR --> ${GSL_INCLUDE_DIR}") - dd4hep_print( "|++> GSL_LIBRARY --> ${GSL_LIBRARY}") - dd4hep_print( "|++> GSL found. DDDigi will run multi threaded.") -endif() - target_link_libraries(DDDigi PUBLIC - DD4hep::DDCore Boost::boost ROOT::Core ROOT::Geom ROOT::GenVector ROOT::RIO ${GSL_LIBRARY}) + DD4hep::DDCore Boost::boost ROOT::Core ROOT::Geom ROOT::GenVector ROOT::RIO) target_include_directories(DDDigi PUBLIC - ${GSL_INCLUDE_DIR} $<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/include> $<INSTALL_INTERFACE:include> ) diff --git a/DDDigi/include/DDDigi/DigiData.h b/DDDigi/include/DDDigi/DigiData.h index 1340308930ae59a74a0595816d92fac25b0e2c2e..02c6b4804078a2ac899de672ff84dd400c4e7675 100644 --- a/DDDigi/include/DDDigi/DigiData.h +++ b/DDDigi/include/DDDigi/DigiData.h @@ -218,7 +218,7 @@ namespace dd4hep { /// Merge new deposit map onto existing map (not thread safe!) std::size_t merge(ParticleMapping&& updates); /// Add new entry to the particle mapping (not thread safe!) - void push(Key::key_type key, Particle&& particle); + void push(Key key, Particle&& particle); }; /// Initializing constructor @@ -275,7 +275,7 @@ namespace dd4hep { class DepositMapping : public std::map<CellID, EnergyDeposit> { public: std::string name { }; - Key::mask_type mask { 0x0 }; + Key key { 0x0 }; public: /// Initializing constructor @@ -298,8 +298,8 @@ namespace dd4hep { }; /// Initializing constructor - inline DepositMapping::DepositMapping(const std::string& n, Key::mask_type m) - : name(n), mask(m) + inline DepositMapping::DepositMapping(const std::string& n, Key::mask_type mask) + : name(n), key(mask, n) { } @@ -312,21 +312,20 @@ namespace dd4hep { */ class DataSegment { public: - using key_type = Key::key_type; - using container_map_t = std::map<key_type, std::any>; + using container_map_t = std::map<Key::key_type, std::any>; using iterator = container_map_t::iterator; using const_iterator = container_map_t::const_iterator; private: /// Call on failed any-casts - std::string invalid_cast(key_type key, const std::type_info& type) const; + std::string invalid_cast(Key key, const std::type_info& type) const; /// Call on failed data requests during data requests - std::string invalid_request(key_type key) const; + std::string invalid_request(Key key) const; /// Access data item by key - std::any* get_item(key_type key, bool exc); + std::any* get_item(Key key, bool exc); /// Access data item by key (CONST) - const std::any* get_item(key_type key, bool exc) const; + const std::any* get_item(Key key, bool exc) const; public: container_map_t data; @@ -350,62 +349,64 @@ namespace dd4hep { /** Locked operations */ /// Emplace data item (locked) - bool emplace(key_type key, std::any&& data); + bool emplace(Key key, std::any&& data); /// Remove data item from segment (locked) - bool erase(key_type key); + bool erase(Key key); /// Remove data items from segment (locked) - std::size_t erase(const std::vector<key_type>& keys); + std::size_t erase(const std::vector<Key>& keys); + /// Print segment keys + void print_keys() const; /** Unlocked operations */ /// Access data as reference by key. If not existing, an exception is thrown - template<typename T> T& get(key_type key); + template<typename T> T& get(Key key); /// Access data as reference by key. If not existing, an exception is thrown - template<typename T> const T& get(key_type key) const; + template<typename T> const T& get(Key key) const; /// Access data as pointers by key. If not existing, nullptr is returned - template<typename T> T* pointer(key_type key); + template<typename T> T* pointer(Key key); /// Access data as pointers by key. If not existing, nullptr is returned - template<typename T> const T* pointer(key_type key) const; + template<typename T> const T* pointer(Key key) const; /// Access container size - std::size_t size() const { return this->data.size(); } + std::size_t size() const { return this->data.size(); } /// Check container if empty - bool empty() const { return this->data.empty(); } + bool empty() const { return this->data.empty(); } /// Begin iteration - iterator begin() { return this->data.begin(); } + iterator begin() { return this->data.begin(); } /// End iteration - iterator end() { return this->data.end(); } + iterator end() { return this->data.end(); } /// Find entry by key - iterator find(key_type key) { return this->data.find(key); } + iterator find(Key key) { return this->data.find(key.key); } /// Begin iteration (CONST) - const_iterator begin() const { return this->data.begin(); } + const_iterator begin() const { return this->data.begin(); } /// End iteration (CONST) - const_iterator end() const { return this->data.end(); } + const_iterator end() const { return this->data.end(); } /// Find entry by key - const_iterator find(key_type key) const { return this->data.find(key); } + const_iterator find(Key key) const { return this->data.find(key.key); } }; /// Access data as reference by key. If not existing, an exception is thrown - template<typename T> inline T& DataSegment::get(key_type key) { + template<typename T> inline T& DataSegment::get(Key key) { if ( T* ptr = std::any_cast<T>(this->get_item(key, true)) ) return *ptr; throw std::runtime_error(this->invalid_cast(key, typeid(T))); } /// Access data as reference by key. If not existing, an exception is thrown - template<typename T> inline const T& DataSegment::get(key_type key) const { + template<typename T> inline const T& DataSegment::get(Key key) const { if ( const T* ptr = std::any_cast<T>(this->get_item(key, true)) ) return *ptr; throw std::runtime_error(this->invalid_cast(key, typeid(T))); } /// Access data as pointers by key. If not existing, nullptr is returned - template<typename T> inline T* DataSegment::pointer(key_type key) { + template<typename T> inline T* DataSegment::pointer(Key key) { if ( T* ptr = std::any_cast<T>(this->get_item(key, false)) ) return ptr; return nullptr; } /// Access data as pointers by key. If not existing, nullptr is returned - template<typename T> inline const T* DataSegment::pointer(key_type key) const { + template<typename T> inline const T* DataSegment::pointer(Key key) const { if ( const T* ptr = std::any_cast<T>(this->get_item(key, false)) ) return ptr; return nullptr; diff --git a/DDDigi/include/DDDigi/DigiSegmentationSplitter.h b/DDDigi/include/DDDigi/DigiSegmentationSplitter.h index 163380384c68adc8ee1b4de55006846c47be0114..3c9e72a24d99e145f3bc0e5a530bd6748669eb53 100644 --- a/DDDigi/include/DDDigi/DigiSegmentationSplitter.h +++ b/DDDigi/include/DDDigi/DigiSegmentationSplitter.h @@ -14,52 +14,22 @@ #define DDDIGI_DIGISEGMENTATIONSPLITTER_H // Framework include files -#include <DDDigi/DigiActionSequence.h> #include <DDDigi/DigiData.h> +#include <DDDigi/DigiEventAction.h> +#include <DDDigi/DigiActionSequence.h> +#include <DDDigi/DigiSegmentationTool.h> /// Namespace for the AIDA detector description toolkit namespace dd4hep { - /// DDSegmentation namespace declaration - namespace DDSegmentation { - class BitFieldElement; - } - /// Namespace for the Digitization part of the AIDA detector description toolkit namespace digi { - class DigiSegmentContext; + /// Forward declarations class DigiSegmentAction; + class DigiSegmentContext; class DigiSegmentationSplitter; - class DigiSegmentContext { - public: - DetElement detector { }; - IDDescriptor idspec { }; - const BitFieldElement* field { nullptr }; - uint64_t cell_mask { ~0x0UL }; - uint64_t det_mask { 0UL }; - uint64_t split_mask { 0UL }; - int32_t offset { 0 }; - int32_t width { 0 }; - int32_t max_split { 0 }; - uint32_t id { 0 }; - - public: - uint32_t split_id(uint64_t cell_id) const { - return int( (cell_id & this->split_mask) >> this->offset ); - } - uint64_t cell_id(uint64_t cell_id) const { - return (cell_id & this->cell_mask) >> this->offset; - } - const std::string& name() const { - return this->field->name(); - } - const char* cname() const { - return this->field->name().c_str(); - } - }; - /// Default base class for all Digitizer actions and derivates thereof. /** * This is a utility class supporting properties, output and access to @@ -78,21 +48,19 @@ namespace dd4hep { /// Reference to the implementation std::unique_ptr<internals_t> internals; - /// Main functional callback - virtual void execute(DigiContext& context) const final; - /// Define standard assignments and constructors DDDIGI_DEFINE_ACTION_CONSTRUCTORS(DigiSegmentAction); public: /// Standard constructor DigiSegmentAction(const DigiKernel& kernel, const std::string& name); - /// Default destructor virtual ~DigiSegmentAction(); /// Main functional callback - std::map<Key::key_type, std::any> + virtual void execute(DigiContext& context) const final; + /// Main functional callback + std::vector<std::pair<Key::key_type, std::any> > handleSegment(DigiContext& context, const DigiSegmentContext& segment, const DepositMapping& deposits) const; @@ -108,25 +76,44 @@ namespace dd4hep { * \ingroup DD4HEP_SIMULATION */ class DigiSegmentationSplitter : public DigiActionSequence { + protected: /// Implementation declaration class internals_t; /// Reference to the implementation std::unique_ptr<internals_t> internals; - public: + /// Property: Identifier of the input repository + std::string m_input_id; + /// Property: Split element of the ID descriptor + std::string m_processor_type; + /// Name of the subdetector to be handed + std::string m_detector_name; + /// Splitter field in the segmentation description + std::string m_split_by; + /// Property: Flag if processors should be shared + bool m_share_processor { true }; + /// Property: Input mask in the repository + int m_input_mask; + + /// Segmentation too instance + DigiSegmentationTool m_split_tool; + /// Segmentation split context + DigiSegmentContext m_split_context; + + /// Split elements used to parallelize the processing + std::map<VolumeID, std::pair<DetElement, VolumeID> > m_splits; + /// Input data keys: depend on dd4hep::Readout and the input mask(s) + std::vector<Key> m_data_keys; protected: /// Define standard assignments and constructors DDDIGI_DEFINE_ACTION_CONSTRUCTORS(DigiSegmentationSplitter); - /// Default destructor virtual ~DigiSegmentationSplitter(); - /// Split actions according to the segmentation - //void split_segments(DigiEvent& event, DataSegment& data) const; - - void init_processors(); + /// Initialization function + void initialize(); public: /// Standard constructor diff --git a/DDDigi/include/DDDigi/DigiSegmentationTool.h b/DDDigi/include/DDDigi/DigiSegmentationTool.h new file mode 100644 index 0000000000000000000000000000000000000000..8d1b1ffa74c0c5f1f8dfc7c4f2e4112fa95fea0e --- /dev/null +++ b/DDDigi/include/DDDigi/DigiSegmentationTool.h @@ -0,0 +1,114 @@ +//========================================================================== +// 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_DIGISEGMENTATIONTOOL_H +#define DDDIGI_DIGISEGMENTATIONTOOL_H + +// Framework include files +#include <DD4hep/Detector.h> +#include <DD4hep/DetElement.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 DigiSegmentContext; + class DigiSegmentationTool; + + /// Segmentation split context + /** + * + * + * + * \author M.Frank + * \version 1.0 + * \ingroup DD4HEP_SIMULATION + */ + class DigiSegmentContext { + public: + DetElement detector { }; + IDDescriptor idspec { }; + const BitFieldElement* field { nullptr }; + uint64_t cell_mask { ~0x0UL }; + uint64_t det_mask { 0UL }; + uint64_t split_mask { 0UL }; + int32_t offset { 0 }; + int32_t width { 0 }; + int32_t max_split { 0 }; + uint32_t id { 0 }; + + public: + /// Split field name + const std::string& name() const; + /// Split field name + const char* cname() const; + /// Get the identifier of the cell to be split + uint32_t split_id(uint64_t cell_id) const { + return int( (cell_id & this->split_mask) >> this->offset ); + } + /// The CELL ID part of the identifier + uint64_t cell_id(uint64_t cell_id) const { + return ( (cell_id & this->cell_mask) >> (this->offset + width) ); + } + /// The identifier of the parent detector + uint64_t detector_id(uint64_t cell_id) const { + return (cell_id & this->det_mask); + } + }; + + /// Tool to handle segmentation manipulations + /** + * + * + * + * \author M.Frank + * \version 1.0 + * \ingroup DD4HEP_SIMULATION + */ + class DigiSegmentationTool { + public: + Detector& description; + DetElement detector; + SensitiveDetector sensitive; + IDDescriptor iddescriptor; + + public: + /// Initializing constructor + DigiSegmentationTool(Detector& desc); + /// Default destructor + virtual ~DigiSegmentationTool() = default; + + /// Setup tool to handle a given detector of the geometry + void set_detector(const std::string& det_name); + + /// Access the readout collection keys (mask is empty!) + std::vector<Key> collection_keys() const; + /// Access the readout collection keys with predefined mask + std::vector<Key> collection_keys(Key::mask_type mask) const; + /// Access the collection keys from readout structures of multiple subdetectors + std::vector<Key> collection_keys(const std::vector<std::string>& detectors) const; + /// Access the collection keys from readout structures of multiple subdetectors + std::vector<Key> collection_keys(const std::vector<std::string>& detectors, Key::mask_type mask) const; + + /// Create a split context depending on the segmentation field + DigiSegmentContext split_context(const std::string& split_by) const; + + /// Create full set of detector segments which can be split according to the context + std::map<VolumeID, std::pair<DetElement, VolumeID> > + split_segmentation(const std::string& split_by) const; + }; + } // End namespace digi +} // End namespace dd4hep +#endif // DDDIGI_DIGISEGMENTATIONTOOL_H diff --git a/DDDigi/python/dddigi.py b/DDDigi/python/dddigi.py index 53b97320a26a3f2a196b3f6ad74ea962e845a3fe..94bb896d4f2803b8e28a0f6bc77094b066b0e218 100644 --- a/DDDigi/python/dddigi.py +++ b/DDDigi/python/dddigi.py @@ -210,7 +210,7 @@ def Synchronize(kernel, nam, parallel=False): def _setup(obj): def _adopt(self, action): - self.__adopt(action.get()) + getattr(self,'__adopt')(action.get()) _import_class('digi', obj) cls = getattr(current, obj) setattr(cls, '__adopt', getattr(cls, 'adopt')) diff --git a/DDDigi/src/DigiContainerCombine.cpp b/DDDigi/src/DigiContainerCombine.cpp index 5871265c12f383075589aa8dcc6cd505126bb930..e36d49f3b0bb7dddaad9c8753b887738cff92cb6 100644 --- a/DDDigi/src/DigiContainerCombine.cpp +++ b/DDDigi/src/DigiContainerCombine.cpp @@ -44,6 +44,7 @@ public: std::set<Key::key_type> keys { }; /// Container keys of all containers to be manipulated std::set<Key::key_type> cont_keys { }; + /// Predicate function to select containers for merging std::function<bool(Key::key_type)> container_selector; /// Flag to check the initialization @@ -55,17 +56,6 @@ public: if ( !this->inited ) { this->inited = true; - this->container_selector = [this](Key::key_type k) { - const auto& m = this->masks; - bool use = m.empty() || this->keys.empty(); - if ( !use ) { - use = std::find(m.begin(), m.end(), Key::mask(k)) != m.end(); - if ( !use ) { - return this->cont_keys.find(Key::item(k)) != this->cont_keys.end(); - } - } - return true; - }; for ( const auto& c : this->containers ) { Key key(0x0, c); this->cont_keys.emplace(key.key); @@ -78,6 +68,17 @@ public: this->keys.emplace(key.key); } } + + this->container_selector = [this](Key::key_type k) { + const auto& m = this->masks; + bool use = m.empty() || this->keys.empty(); + if ( !use ) { + if ( !this->cont_keys.empty() ) + return this->cont_keys.find(Key::item(k)) != this->cont_keys.end(); + return std::find(m.begin(), m.end(), Key::mask(k)) != m.end(); + } + return true; + }; } } } @@ -105,7 +106,7 @@ dd4hep::digi::DigiContainerCombine::~DigiContainerCombine() { /// Combine selected containers to one single deposit container template <typename PREDICATE> std::size_t -dd4hep::digi::DigiContainerCombine::combine_containers(DigiEvent& event, +dd4hep::digi::DigiContainerCombine::combine_containers(DigiEvent& event, DataSegment& inputs, DataSegment& outputs, const PREDICATE& predicate) const @@ -113,68 +114,82 @@ dd4hep::digi::DigiContainerCombine::combine_containers(DigiEvent& event, std::size_t cnt_depos = 0; std::size_t cnt_parts = 0; std::size_t cnt_conts = 0; - std::vector<Key::key_type> to_erase; + std::vector<Key> keys; + std::vector<std::any*> work; + std::set<Key::itemkey_type> items; + keys.reserve(inputs.size()); + work.reserve(inputs.size()); for( auto& i : inputs ) { if ( predicate(i.first) ) { - Key depo_key(i.first); - Key input_key(i.first); - DepositMapping* din = std::any_cast<DepositMapping>(&i.second); - if ( din ) { - depo_key.values.mask = internals->deposit_mask; - cnt_depos += din->size(); + keys.emplace_back(i.first); + work.emplace_back(&i.second); + items.insert(Key(i.first).values.item); + } + } + Key depo_key; + depo_key.values.mask = internals->deposit_mask; + for(auto itm : items) { + for( std::size_t i=0; i < keys.size(); ++i ) { + if ( keys[i].values.item != itm ) + continue; + auto* output = work[i]; + depo_key.values.item = itm; + + /// Merge deposit mapping + if ( DepositMapping* depos = std::any_cast<DepositMapping>(output) ) { + if ( !internals->output_name_flag.empty() ) + depos->name = depos->name+"/"+internals->output_name_flag; + cnt_depos += depos->size(); cnt_conts++; - auto iter = outputs.find(depo_key.key); - if ( iter == outputs.end() ) { - this->info("%s+++ %-32s Mask: %06X Input: %06X Merged %6ld deposits", - event.id(), din->name.c_str(), depo_key.values.mask, - input_key.values.mask, din->size()); - if ( !internals->output_name_flag.empty() ) { - din->name = din->name+"/"+internals->output_name_flag; + this->info("%s+++ %-32s Mask: $%04X Input: $%04X Merged %6ld deposits", + event.id(), depos->name.c_str(), depo_key.values.mask, + keys[i].values.mask, depos->size()); + for( std::size_t j=i+1; j < keys.size(); ++j ) { + if ( keys[j].values.item == itm ) { + DepositMapping* next = std::any_cast<DepositMapping>(work[j]); + cnt_depos += next->size(); + cnt_conts++; + std::size_t cnt = depos->merge(std::move(*next)); + this->info("%s+++ %-32s Mask: $%04X Input: $%04X Merged %6ld deposits", + event.id(), depos->name.c_str(), depo_key.values.mask, + keys[j].values.mask, cnt); + cnt_depos += cnt; + cnt_conts++; + work[j]->reset(); } - outputs.emplace(depo_key.key, std::move(i.second)); - to_erase.emplace_back(i.first); - continue; } - DepositMapping* out = std::any_cast<DepositMapping>(&iter->second); - std::size_t cnt = out->merge(std::move(*din)); - this->info("%s+++ %-32s Mask: %06X Input: %06X Merged %6ld deposits", - event.id(), out->name.c_str(), depo_key.values.mask, - input_key.values.mask, cnt); - i.second.reset(); - to_erase.emplace_back(i.first); - continue; + outputs.emplace(depo_key, std::move(*output)); + break; } - ParticleMapping* pin = std::any_cast<ParticleMapping>(&i.second); - if ( pin ) { - depo_key.values.mask = internals->deposit_mask; - cnt_parts += pin->size(); + else if ( ParticleMapping* parts = std::any_cast<ParticleMapping>(output) ) { + if ( !internals->output_name_flag.empty() ) + parts->name = parts->name+"/"+internals->output_name_flag; + cnt_parts += parts->size(); cnt_conts++; - auto iter = outputs.find(depo_key.key); - if ( iter == outputs.end() ) { - this->info("%s+++ %-32s Mask: %06X Input: %06X Merged %6ld particles", - event.id(), pin->name.c_str(), depo_key.values.mask, - input_key.values.mask, pin->size()); - if ( !internals->output_name_flag.empty() ) { - pin->name = pin->name+"/"+internals->output_name_flag; + + this->info("%s+++ %-32s Mask: $%04X Input: $%04X Merged %6ld particles", + event.id(), parts->name.c_str(), depo_key.values.mask, + keys[i].values.mask, parts->size()); + for( std::size_t j=i+1; j < keys.size(); ++j ) { + if ( keys[j].values.item == itm ) { + ParticleMapping* next = std::any_cast<ParticleMapping>(work[j]); + std::size_t cnt = parts->merge(std::move(*next)); + this->info("%s+++ %-32s Mask: $%04X Input: $%04X Merged %6ld particles", + event.id(), parts->name.c_str(), depo_key.values.mask, + keys[j].values.mask, cnt); + cnt_parts += cnt; + cnt_conts++; + work[j]->reset(); } - outputs.emplace(depo_key.key, std::move(i.second)); - to_erase.emplace_back(i.first); - continue; } - ParticleMapping* out = std::any_cast<ParticleMapping>(&iter->second); - std::size_t cnt = out->merge(std::move(*pin)); - this->info("%s+++ %-32s Mask: %06X Input: %06X Merged %6ld particles", - event.id(), out->name.c_str(), depo_key.values.mask, - input_key.values.mask, cnt); - i.second.reset(); - to_erase.emplace_back(i.first); - continue; - } + outputs.emplace(depo_key, std::move(*output)); + break; + } } } if ( this->internals->erase_combined ) { - inputs.erase(to_erase); + inputs.erase(keys); } this->info("%s+++ Merged %ld particles and %ld deposits from %ld containers", event.id(), cnt_parts, cnt_depos, cnt_conts); diff --git a/DDDigi/src/DigiData.cpp b/DDDigi/src/DigiData.cpp index e9ad1a36713291c3090c2564dd8385b704a4a02e..371e219d6009d21f527caf1bff481341a997480a 100644 --- a/DDDigi/src/DigiData.cpp +++ b/DDDigi/src/DigiData.cpp @@ -40,6 +40,7 @@ void Key::set(const std::string& name, int mask) { std::lock_guard<std::mutex> lock(_k.lock); except("DDDigi::Key", "+++ No key name was specified -- this is illegal!"); } + this->key = 0; this->values.mask = (unsigned char)(0xFF&mask); this->values.item = detail::hash32(name); std::lock_guard<std::mutex> lock(_k.lock); @@ -89,16 +90,15 @@ std::size_t ParticleMapping::merge(ParticleMapping&& updates) { return update_size; } -void ParticleMapping::push(Key::key_type k, Particle&& part) { +void ParticleMapping::push(Key key, Particle&& part) { #if defined(__GNUC__) && (__GNUC__ < 10) /// Lower compiler version have a bad implementation of std::any bool ret = false; if ( part.history.has_value() ) {} #else - bool ret = this->emplace(k, std::move(part)).second; + bool ret = this->emplace(key.key, std::move(part)).second; #endif if ( !ret ) { - Key key(k); except("ParticleMapping","Error in particle map. Duplicate ID: mask:%04X Number:%d", key.values.mask, key.values.item); } @@ -110,14 +110,14 @@ DataSegment::DataSegment(std::mutex& l) : lock(l) } /// Remove data item from segment -bool DataSegment::emplace(key_type key, std::any&& item) { +bool DataSegment::emplace(Key key, std::any&& item) { std::lock_guard<std::mutex> l(lock); #if defined(__GNUC__) && (__GNUC__ < 10) /// Lower compiler version have a bad implementation of std::any bool ret = false; if ( item.has_value() ) {} #else - bool ret = data.emplace(key, std::move(item)).second; + bool ret = data.emplace(key.key, std::move(item)).second; #endif if ( !ret ) { Key k(key); @@ -128,9 +128,9 @@ bool DataSegment::emplace(key_type key, std::any&& item) { } /// Remove data item from segment -bool DataSegment::erase(key_type key) { +bool DataSegment::erase(Key key) { std::lock_guard<std::mutex> l(lock); - auto iter = data.find(key); + auto iter = data.find(key.key); if ( iter != data.end() ) { data.erase(iter); return true; @@ -139,11 +139,11 @@ bool DataSegment::erase(key_type key) { } /// Remove data items from segment (locked) -std::size_t DataSegment::erase(const std::vector<key_type>& keys) { +std::size_t DataSegment::erase(const std::vector<Key>& keys) { std::size_t count = 0; std::lock_guard<std::mutex> l(lock); for(auto key : keys) { - auto iter = data.find(key); + auto iter = data.find(key.key); if ( iter != data.end() ) { data.erase(iter); ++count; @@ -152,28 +152,40 @@ std::size_t DataSegment::erase(const std::vector<key_type>& keys) { return count; } +/// Print segment keys +void DataSegment::print_keys() const { + size_t count = 0; + for( const auto& e : this->data ) { + Key k(e.first); + printout(INFO, "DataSegment", "Key No.%4: %16lX <> %16lX -> %04X %10ld", + count, e.first, k.key, k.values.mask, k.values.item, + typeName(e.second.type()).c_str()); + ++count; + } +} + /// Call on failed any-casts during data requests -std::string DataSegment::invalid_cast(key_type key, const std::type_info& type) const { +std::string DataSegment::invalid_cast(Key key, const std::type_info& type) const { return dd4hep::format(0, "Invalid segment data cast. Key:%ld type:%s", key, typeName(type).c_str()); } /// Call on failed data requests during data requests -std::string DataSegment::invalid_request(key_type key) const { +std::string DataSegment::invalid_request(Key key) const { return dd4hep::format(0, "Invalid segment data requested. Key:%ld",key); } /// Access data item by key -std::any* DataSegment::get_item(key_type key, bool exc) { - auto it = this->data.find(key); +std::any* DataSegment::get_item(Key key, bool exc) { + auto it = this->data.find(key.key); if (it != this->data.end()) return &it->second; if ( exc ) throw std::runtime_error(invalid_request(key)); return nullptr; } /// Access data item by key (CONST) -const std::any* DataSegment::get_item(key_type key, bool exc) const { - auto it = this->data.find(key); +const std::any* DataSegment::get_item(Key key, bool exc) const { + auto it = this->data.find(key.key); if (it != this->data.end()) return &it->second; if ( exc ) throw std::runtime_error(invalid_request(key)); return nullptr; diff --git a/DDDigi/src/DigiHitAttenuatorExp.cpp b/DDDigi/src/DigiHitAttenuatorExp.cpp index fb883f524d9eaf7a6d42952d5d845c464668e874..16ae3b2be864ae804e16711f7e05359bd6169697 100644 --- a/DDDigi/src/DigiHitAttenuatorExp.cpp +++ b/DDDigi/src/DigiHitAttenuatorExp.cpp @@ -86,8 +86,9 @@ void dd4hep::digi::DigiHitAttenuatorExp::execute(DigiContext& context) const } count += m->size(); std::string nam = Key::key_name(k.first)+":"; - debug("%s+++ %-32s Mask: %06X Attenuated exponentially %6ld hits by %8.5f", - event.id(), nam.c_str(), m->mask, m->size(), factor); + debug("%s+++ %-32s mask:%04X item: %08X Attenuated exponentially %6ld hits by %8.5f", + event.id(), nam.c_str(), m->key.values.mask, m->key.values.item, + m->size(), factor); continue; } } diff --git a/DDDigi/src/DigiSegmentationSplitter.cpp b/DDDigi/src/DigiSegmentationSplitter.cpp index 560d18f650b77559f0c14d89884f0d67fc7af0d4..f4d1bfb0adbcede22e77e832b574b8e20fe876ee 100644 --- a/DDDigi/src/DigiSegmentationSplitter.cpp +++ b/DDDigi/src/DigiSegmentationSplitter.cpp @@ -13,160 +13,36 @@ // Framework include files #include <DD4hep/Plugins.h> -#include <DD4hep/Detector.h> #include <DD4hep/InstanceCount.h> -#include <DDDigi/DigiData.h> #include <DDDigi/DigiKernel.h> #include <DDDigi/DigiContext.h> #include <DDDigi/DigiSegmentationSplitter.h> -#include <sstream> - using namespace dd4hep::digi; class DigiSegmentAction::internals_t { public: - const DigiSegmentContext* split { nullptr }; - const DepositMapping* input { nullptr }; + DigiSegmentContext split { }; + std::vector<std::pair<Key::key_type, std::any> > output; + const DepositMapping* input { nullptr }; }; class DigiSegmentationSplitter::internals_t { public: - /// Property: Identifier of the input repository - std::string input_id; - /// Property: Subdetector to handle - std::string detector_name; - /// Property: Factory name of the processor type - std::string split_by; - /// Property: Split element of the ID descriptor - std::string processor_type; - /// Property: Flag if processors should be shared - bool share_processor { true }; - /// Property: Input mask in the repository - int input_mask; - - std::vector<Key::key_type> data_keys; - - DigiSegmentContext splitter; - - const DigiKernel& kernel; - Detector& description; - DetElement detector; - SensitiveDetector sensitive; - IDDescriptor iddescriptor; + /// Reference to master DigiSegmentationSplitter* split { nullptr }; - - std::map<uint64_t, DigiSegmentContext> split_processors; - /// Flag to check the initialization bool inited { false }; - - internals_t(const DigiKernel& krnl, DigiSegmentationSplitter* s) - : kernel(krnl), description(kernel.detectorDescription()), split(s) - { - } - - void scan_detector(DetElement de, VolumeID vid, VolumeID mask) { - const auto& new_ids = de.placement().volIDs(); - VolumeID new_vid = vid; - VolumeID new_msk = mask; - if ( !new_ids.empty() ) { - new_vid |= this->iddescriptor.encode(new_ids); - new_msk |= this->iddescriptor.get_mask(new_ids); - for (const auto& id : new_ids) { - if ( id.first == this->split_by ) { - DigiSegmentContext context = this->splitter; - context.detector = de; - context.id = id.second; - this->split_processors.emplace(new_vid, std::move(context)); - return; - } - } - } - for ( const auto& c : de.children() ) - scan_detector(c.second, new_vid, new_msk); - } - - void init_basics() { - const char* det = this->detector_name.c_str(); - this->detector = this->description.detector(det); - if ( !this->detector.isValid() ) { - split->except("FAILED: Cannot access subdetector %s from the detector description.", det); - } - this->sensitive = this->description.sensitiveDetector(det); - if ( !sensitive.isValid() ) { - split->except("FAILED: Cannot access sensitive detector for %s.", det); - } - this->iddescriptor = this->sensitive.idSpec(); - if ( !this->iddescriptor.isValid() ) { - split->except("FAILED: Cannot access ID descriptor for detector %s.", det); - } - Readout rd = this->sensitive.readout(); - auto colls = rd.collectionNames(); - if ( colls.empty() ) colls.emplace_back(rd.name()); - for( const auto& c : colls ) { - this->data_keys.emplace_back(Key(this->input_mask, c).key); - } - } - - void init_splitting() { - const char* det = this->detector_name.c_str(); - /// Setup the splitter - this->splitter.cell_mask = ~0x0UL; - this->splitter.detector = this->detector; - this->splitter.idspec = this->iddescriptor; - for(const auto& f : this->iddescriptor.fields()) { - const BitFieldElement* e = f.second; - if ( e->name() == this->split_by ) { - this->splitter.field = e; - this->splitter.split_mask = e->mask(); - this->splitter.width = e->width(); - this->splitter.offset = e->offset(); - this->splitter.max_split = 1 << e->width(); - } - else { - this->splitter.det_mask |= e->mask(); - } - this->splitter.cell_mask = (splitter.cell_mask << e->width()); - split->info("%-24s %-8s [%3d,%7d] width:%2d offset:%2d mask:%016lX Split:%016lX Det:%016lX Cells:%016lX", - iddescriptor.name(), e->name().c_str(), - e->minValue(), e->maxValue(), e->width(), e->offset(), - e->mask(), this->splitter.split_mask, this->splitter.det_mask, this->splitter.cell_mask); - if ( this->splitter.field ) break; - } - if ( !this->splitter.field ) { - split->except("FAILED: The ID descriptor for detector %s has no field %s.", - det, split_by.c_str()); - } - this->split_processors.clear(); - const auto& ids = this->detector.placement().volIDs(); - VolumeID vid = this->iddescriptor.encode(ids); - VolumeID msk = this->iddescriptor.get_mask(ids); - this->scan_detector(this->detector, vid, msk); - split->info("%-24s has %ld parallel entries in when splitting by \"%s\"", - det, this->split_processors.size(), this->split_by.c_str()); - std::stringstream str; - for( auto id : this->split_processors ) - str << std::setw(16) << std::hex << std::setfill('0') << id.first << " "; - split->info("%-24s --> Parallel Vid: %s", det, str.str().c_str()); - str.str(""); - for( auto id : this->split_processors ) - str << std::setw(16) << std::dec << std::setfill(' ') << this->splitter.split_id(id.first) << " "; - split->info("%-24s --> Parallel ID: %s", det, str.str().c_str()); - } - + /// Default constructor + internals_t(DigiSegmentationSplitter* s) : split(s) {} /// Initializing function: compute values which depend on properties void initialize(DigiContext& context) { if ( !this->inited ) { std::lock_guard<std::mutex> lock(context.initializer_lock()); if ( !this->inited ) { - const std::string det = this->detector_name; + this->split->initialize(); this->inited = true; - this->init_basics(); - this->init_splitting(); - this->split->init_processors(); - split->info("+++ Detector splitter is now fully initialized!"); } } } @@ -174,15 +50,15 @@ public: /// Standard constructor DigiSegmentationSplitter::DigiSegmentationSplitter(const DigiKernel& krnl, const std::string& nam) - : DigiActionSequence(krnl, nam) + : DigiActionSequence(krnl, nam), m_split_tool(krnl.detectorDescription()) { - this->internals = std::make_unique<internals_t>(m_kernel, this); - declareProperty("input", this->internals->input_id = "deposits"); - declareProperty("detector", this->internals->detector_name); - declareProperty("mask", this->internals->input_mask); - declareProperty("split_by", this->internals->split_by); - declareProperty("processor_type", this->internals->processor_type); - declareProperty("share_processor", this->internals->share_processor = true); + this->internals = std::make_unique<internals_t>(this); + declareProperty("detector", this->m_detector_name); + declareProperty("split_by", this->m_split_by); + declareProperty("input", this->m_input_id = "deposits"); + declareProperty("mask", this->m_input_mask); + declareProperty("processor_type", this->m_processor_type); + declareProperty("share_processor", this->m_share_processor = false); InstanceCount::increment(this); } @@ -191,33 +67,38 @@ DigiSegmentationSplitter::~DigiSegmentationSplitter() { InstanceCount::decrement(this); } -void DigiSegmentationSplitter::init_processors() { + +/// Initialization function +void DigiSegmentationSplitter::initialize() { char text[256]; std::size_t count = 0; - auto& imp = *this->internals; - std::string typ = imp.processor_type; - DigiSegmentAction* proc = nullptr; + DigiSegmentAction* proc; + + this->m_split_tool.set_detector(this->m_detector_name); + this->m_split_context = this->m_split_tool.split_context(this->m_split_by); + this->m_data_keys = this->m_split_tool.collection_keys(this->m_input_mask); + this->m_splits = this->m_split_tool.split_segmentation(this->m_split_by); + /// Create the processors: - for( const auto& p : imp.split_processors ) { - auto& split = p.second; - ::snprintf(text, sizeof(text), "_%05X", split.split_id(p.first)); + for( auto& p : this->m_splits ) { + ::snprintf(text, sizeof(text), "_%05X", m_split_context.split_id(p.first)); std::string nam = this->name() + text; - proc = PluginService::Create<DigiSegmentAction*>(typ, &m_kernel, nam); + proc = PluginService::Create<DigiSegmentAction*>(m_processor_type, &m_kernel, nam); proc->internals = std::make_unique<DigiSegmentAction::internals_t>(); - proc->internals->split = &split; + proc->internals->split = this->m_split_context; + proc->internals->split.detector = p.second.first; + proc->internals->split.id = p.second.second; this->DigiActionSequence::adopt(proc); ++count; } + info("+++ Detector splitter is now fully initialized!"); } /// Main functional callback void DigiSegmentationSplitter::execute(DigiContext& context) const { - auto& imp = *this->internals; - auto& event = *context.event; - auto& input = event.get_segment(imp.input_id); - + auto& input = context.event->get_segment(this->m_input_id); this->internals->initialize(context); - for( auto k : imp.data_keys ) { + for( auto k : this->m_data_keys ) { auto* hits = input.pointer<DepositMapping>(k); if ( hits ) { /// prepare processors for execution @@ -245,16 +126,13 @@ DigiSegmentAction::~DigiSegmentAction() { } void DigiSegmentAction::execute(DigiContext& context) const { - auto& input = *this->internals->input; - auto& split = *this->internals->split; - auto ret = this->handleSegment(context, split, input); - if ( !ret.empty() ) { - //auto& segment = context.event->get_segment(); - } + auto& imp = *this->internals; + auto ret = this->handleSegment(context, imp.split, *imp.input); + imp.output = std::move(ret); } /// Main functional callback -std::map<Key::key_type, std::any> +std::vector<std::pair<Key::key_type, std::any> > DigiSegmentAction::handleSegment(DigiContext& context, const DigiSegmentContext& segment, const DepositMapping& deposits) const { diff --git a/DDDigi/src/DigiSegmentationTool.cpp b/DDDigi/src/DigiSegmentationTool.cpp new file mode 100644 index 0000000000000000000000000000000000000000..e2aea1bab5089a2b8f3c0507c99530e8af18e908 --- /dev/null +++ b/DDDigi/src/DigiSegmentationTool.cpp @@ -0,0 +1,185 @@ +//========================================================================== +// 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/Printout.h> +#include <DDDigi/DigiData.h> +#include <DDDigi/DigiSegmentationTool.h> + +#include <sstream> + +using namespace std; +using namespace dd4hep::digi; + +namespace { + void scan_detector(const DigiSegmentationTool& tool, + const string& split_by, + map<dd4hep::VolumeID, pair<dd4hep::DetElement, dd4hep::VolumeID> >& splits, + dd4hep::DetElement de, dd4hep::VolumeID vid, dd4hep::VolumeID mask) { + const auto& new_ids = de.placement().volIDs(); + dd4hep::VolumeID new_vid = vid; + dd4hep::VolumeID new_msk = mask; + if ( !new_ids.empty() ) { + new_vid |= tool.iddescriptor.encode(new_ids); + new_msk |= tool.iddescriptor.get_mask(new_ids); + for (const auto& id : new_ids) { + if ( id.first == split_by ) { + splits.emplace(new_vid, make_pair(de, id.second)); + return; + } + } + } + for ( const auto& c : de.children() ) + scan_detector(tool, split_by, splits, c.second, new_vid, new_msk); + } +} + +/// Split field name +const string& DigiSegmentContext::name() const { + return this->field->name(); +} +/// Split field name +const char* DigiSegmentContext::cname() const { + return this->field->name().c_str(); +} + +/// Initializing constructor +DigiSegmentationTool::DigiSegmentationTool(Detector& desc) + : description(desc) +{ +} + +/// Setup tool to handle a given detector of the geometry +void DigiSegmentationTool::set_detector(const string& det_name) { + const char* det = det_name.c_str(); + this->detector = this->description.detector(det_name); + if ( !this->detector.isValid() ) { + except("DigiSegmentationTool", + "FAILED: Cannot access subdetector %s from the detector description.", det); + } + this->sensitive = this->description.sensitiveDetector(det_name); + if ( !sensitive.isValid() ) { + except("DigiSegmentationTool", + "FAILED: Cannot access sensitive detector for %s.", det); + } + this->iddescriptor = this->sensitive.idSpec(); + if ( !this->iddescriptor.isValid() ) { + except("DigiSegmentationTool", + "FAILED: Cannot access ID descriptor for detector %s.", det); + } +} + +/// Access the readout collection keys +vector<Key> DigiSegmentationTool::collection_keys() const { + return collection_keys(0x0); +} + +/// Access the readout collection keys +vector<Key> DigiSegmentationTool::collection_keys(Key::mask_type mask) const { + vector<Key> keys; + if ( this->sensitive.isValid() ) { + Readout rd = this->sensitive.readout(); + auto colls = rd.collectionNames(); + if ( colls.empty() ) colls.emplace_back(rd.name()); + for( const auto& c : colls ) + keys.emplace_back(Key(mask, c)); + return keys; + } + except("DigiSegmentationTool", + "+++ collection_keys: Readout not valid. Is the proper detector set ?"); + return keys; +} + +/// Access the readout collection keys +vector<Key> +DigiSegmentationTool::collection_keys(const vector<string>& detectors) const { + vector<Key> keys; + for( const auto& det : detectors ) { + DigiSegmentationTool tool(this->description); + tool.set_detector(det); + auto det_keys = tool.collection_keys(0x0); + keys.insert(keys.end(), det_keys.begin(), det_keys.end()); + } + return keys; +} + +/// Access the readout collection keys +vector<Key> +DigiSegmentationTool::collection_keys(const vector<string>& detectors, + Key::mask_type mask) const +{ + vector<Key> keys; + for( const auto& det : detectors ) { + DigiSegmentationTool tool(this->description); + tool.set_detector(det); + auto det_keys = tool.collection_keys(mask); + keys.insert(keys.end(), det_keys.begin(), det_keys.end()); + } + return keys; +} + +/// Create a split context depending on the segmentation field +DigiSegmentContext +DigiSegmentationTool::split_context(const string& split_by) const { + DigiSegmentContext splitter; + splitter.cell_mask = ~0x0UL; + splitter.detector = this->detector; + splitter.idspec = this->iddescriptor; + for(const auto& f : this->iddescriptor.fields()) { + const BitFieldElement* e = f.second; + if ( e->name() == split_by ) { + splitter.field = e; + splitter.split_mask = e->mask(); + splitter.width = e->width(); + splitter.offset = e->offset(); + splitter.max_split = 1 << e->width(); + } + else { + splitter.det_mask |= e->mask(); + } + splitter.cell_mask = (splitter.cell_mask << e->width()); + printout(INFO,"DigiSegmentationTool", + "%-24s %-8s [%3d,%7d] width:%2d offset:%2d mask:%016lX Split:%016lX Det:%016lX Cells:%016lX", + this->iddescriptor.name(), e->name().c_str(), + e->minValue(), e->maxValue(), e->width(), e->offset(), + e->mask(), splitter.split_mask, splitter.det_mask, splitter.cell_mask); + if ( splitter.field ) break; + } + if ( !splitter.field ) { + except("DigiSegmentationTool", + "FAILED: The ID descriptor for detector %s has no field %s.", + this->detector.name(), split_by.c_str()); + } + return splitter; +} + +/// Create full set of detector segments which can be split according to the context +map<dd4hep::VolumeID, pair<dd4hep::DetElement, dd4hep::VolumeID> > +DigiSegmentationTool::split_segmentation(const string& split_by) const +{ + map<VolumeID, pair<DetElement, VolumeID> > segmentation_splits; + const auto& ids = this->detector.placement().volIDs(); + VolumeID vid = this->iddescriptor.encode(ids); + VolumeID msk = this->iddescriptor.get_mask(ids); + const char* det = this->detector.name(); + + ::scan_detector(*this, split_by, segmentation_splits, this->detector, vid, msk); + printout(INFO,"DigiSegmentationTool", + "%-24s has %ld parallel entries in when splitting by \"%s\"", + det, segmentation_splits.size(), split_by.c_str()); + stringstream str; + for( auto id : segmentation_splits ) + str << setw(16) << hex << setfill('0') << id.first << " "; + printout(INFO,"DigiSegmentationTool","%-24s --> Parallel Entries: %s", det, str.str().c_str()); + return segmentation_splits; +} diff --git a/DDDigi/src/noise/DigiSubdetectorSequence.cpp b/DDDigi/src/noise/DigiSubdetectorSequence.cpp index a56e098d06b5bc61137bfa845c0b6e142f3a8f7a..a46bd2a73096fbbc7165042fa19cc6086817b419 100644 --- a/DDDigi/src/noise/DigiSubdetectorSequence.cpp +++ b/DDDigi/src/noise/DigiSubdetectorSequence.cpp @@ -15,6 +15,9 @@ #include <DDDigi/DigiSubdetectorSequence.h> #include <DDDigi/DigiSegmentation.h> #include <DDDigi/DigiKernel.h> +#include <DDDigi/DigiContext.h> +#include <DDDigi/DigiData.h> + #include <DD4hep/InstanceCount.h> #include <DD4hep/Detector.h> #include <DD4hep/IDDescriptor.h> diff --git a/examples/DDDigi/CMakeLists.txt b/examples/DDDigi/CMakeLists.txt index 3e0f6324323daad06cd5dd1ab3193e08af579ab9..91a576cff82b23c1ba0804a107a7c904f532aa02 100644 --- a/examples/DDDigi/CMakeLists.txt +++ b/examples/DDDigi/CMakeLists.txt @@ -52,4 +52,3 @@ dd4hep_add_test_reg(DDDigi_colored_noise REGEX_FAIL "Error;ERROR;Exception" ) # -