diff --git a/DDRec/include/DDRec/SurfaceManager.h b/DDRec/include/DDRec/SurfaceManager.h index eb6d5b210..f12e7d508 100644 --- a/DDRec/include/DDRec/SurfaceManager.h +++ b/DDRec/include/DDRec/SurfaceManager.h @@ -1,5 +1,5 @@ //========================================================================== -// AIDA Detector description implementation +// AIDA Detector description implementation //-------------------------------------------------------------------------- // Copyright (C) Organisation europeenne pour la Recherche nucleaire (CERN) // All rights reserved. @@ -17,24 +17,25 @@ #include "DD4hep/Detector.h" #include #include +#include namespace dd4hep { namespace rec { - /// typedef for surface maps, keyed by the cellID + /// typedef for surface maps, keyed by the cellID typedef std::multimap< unsigned long, ISurface*> SurfaceMap ; - /** Surface manager class that holds maps of surfaces for all known - * sensitive detector types and individual sub detectors. + /** Surface manager class that holds maps of surfaces for all known + * sensitive detector types and individual sub detectors. * Maps can be retrieved via detector name. - * + * * @author F.Gaede, DESY * @date May, 11 2015 * @version $Id$ */ class SurfaceManager { - typedef std::map< std::string, SurfaceMap > SurfaceMapsMap ; + typedef std::map< std::string, std::pair> SurfaceMapsMap; public: /// The constructor @@ -48,30 +49,33 @@ namespace dd4hep { #endif /// No copy constructor SurfaceManager(const SurfaceManager& copy) = delete; - + /// Default destructor ~SurfaceManager(); /// No assignment operator SurfaceManager& operator=(const SurfaceManager& copy) = delete; - + /** Get the maps of all surfaces associated to the given detector or * type of detectors, e.g. map("tracker") returns a map with all surfaces * assigned to tracking detectors. Returns 0 if no map exists. */ - const SurfaceMap* map( const std::string name ) const ; + const SurfaceMap* map( const std::string name ); + - ///create a string with all available maps and their size (number of surfaces) std::string toString() const ; - - protected : + protected : - /// initialize all known surface maps - void initialize(const Detector& theDetector) ; + /// name has to be the name of a single detector! not e.g. tracker or world. + const SurfaceMap& getOrConstruct(const std::string name); SurfaceMapsMap _map ; + const Detector& m_detector; + std::set m_detectorNames; + std::set m_detectorTypes; + std::map> m_missingDetectors; }; } /* namespace rec */ diff --git a/DDRec/src/SurfaceManager.cpp b/DDRec/src/SurfaceManager.cpp index 2576ebb41..563ad2ead 100644 --- a/DDRec/src/SurfaceManager.cpp +++ b/DDRec/src/SurfaceManager.cpp @@ -1,5 +1,5 @@ //========================================================================== -// AIDA Detector description implementation +// AIDA Detector description implementation //-------------------------------------------------------------------------- // Copyright (C) Organisation europeenne pour la Recherche nucleaire (CERN) // All rights reserved. @@ -19,85 +19,142 @@ #include namespace dd4hep { - + using namespace detail ; namespace rec { - - SurfaceManager::SurfaceManager(const Detector& theDetector){ + + SurfaceManager::SurfaceManager(const Detector& theDetector) : + m_detector(theDetector) + { // have to make sure the volume manager is populated once in order to have // the volumeIDs attached to the DetElements VolumeManager::getVolumeManager(theDetector); - initialize(theDetector) ; + std::set worldSet{}; + // collect all detector names that belong to a type e.g.: tracker, calorimeter, passive + for (const std::string& typeName : theDetector.detectorTypes()) { + m_detectorTypes.insert(typeName); + std::set nameSet{}; + for (const DetElement& det : theDetector.detectors(typeName)) { + m_detectorNames.insert(det.name()); + nameSet.insert(det.name()); + } + worldSet.insert(nameSet.begin(), nameSet.end()); + m_missingDetectors.emplace(typeName, std::move(nameSet)); + } + m_missingDetectors.emplace("world", std::move(worldSet)); } - + SurfaceManager::~SurfaceManager(){ // nothing to do } - - - const SurfaceMap* SurfaceManager::map( const std::string name ) const { - SurfaceMapsMap::const_iterator it = _map.find( name ) ; - if( it != _map.end() ){ + const SurfaceMap* SurfaceManager::map( const std::string name ) { - return & it->second ; + // return map if it already exists and is complete + SurfaceMapsMap::const_iterator it = _map.find( name ) ; + if(it != _map.end() && it->second.first) { + return &it->second.second ; } - return 0 ; - } - - void SurfaceManager::initialize(const Detector& description) { - - const std::vector& types = description.detectorTypes() ; + // surface map does not exist or is not completed yet, build it - for(unsigned i=0,N=types.size();i& dets = description.detectors( types[i] ) ; - - for(unsigned j=0,M=dets.size();j invalid + // TODO: maybe do an additional debug printout (not done in original implementation!) + return 0; + } - std::string name = dets[j].name() ; + // if we arrived here we were asked for a type map like tracker or world + // get missing detectors, construct them, look up map again and return it + auto& missingDets = m_missingDetectors[name]; + for (const auto& detName : missingDets) { + getOrConstruct(detName); + } - SurfaceHelper surfH( dets[j] ) ; - - const SurfaceList& detSL = surfH.surfaceList() ; - - // add an empty map for this detector in case there are no surfaces attached - _map.emplace(name , SurfaceMap()); + return &_map[name].second; + } - for( SurfaceList::const_iterator it = detSL.begin() ; it != detSL.end() ; ++it ){ - ISurface* surf = *it ; - - // enter surface into map for this detector - _map[ name ].emplace(surf->id(), surf ); + const SurfaceMap& SurfaceManager::getOrConstruct(const std::string name) { + // check if we already have this map + { + auto it = _map.find(name); + // second condition is always true because we only call this method with name in m_detectorNames + // i.e. no compounds like tracker or world! + if(it != _map.end() /* && it->second.first */){ + return it->second.second ; + } + } // scope to get rid of it variable that is useless after this + + // map does not exist yet, we need to construct it ourselves + // if our detector is also in detectorTypes we construct that + // part of the corresponding surface map also + + std::vector> types; + // we also want to construct a map for the detector itself + // so we just add it first and set it to be valid as we + // will construct it completely + types.push_back(std::make_pair(name, true)); + + // first, check if it is part of any compounds to also add our surfaces to them + // remove the name at the same time as we will construct the map for it now + for (auto& [typeName, nameSet] : m_missingDetectors) { + bool found = nameSet.erase(name); + if (found) { + // we store the typename and if it was the last missing detector of this type + types.push_back(std::make_pair(typeName, nameSet.empty())); + } + } - // enter surface into map for detector type - _map[ types[i] ].emplace(surf->id(), surf ); + // make a vector of references to all the maps that we need to add surfaces to + std::vector>> maps{}; + for (const auto& [typeName, valid] : types) { + auto it = _map.find(typeName); + if (it == _map.end()) { + // need to create a new empty map in the global _map + const auto& res = _map.emplace(typeName, std::make_pair(valid, SurfaceMap())); + maps.push_back(res.first->second); + } else { + maps.push_back(it->second); + } + } - // enter surface into world map - _map[ "world" ].emplace(surf->id(), surf ); + // now get the surfaces and put them into the maps + const DetElement& det = m_detector.detector(name); + SurfaceHelper surfHelper(det); + const SurfaceList& surfList = surfHelper.surfaceList(); - } + for (ISurface* surf : surfList) { + for (auto& map : maps) { + map.get().second.emplace(surf->id(), surf); } } + // return the map of the detector + return maps[0].get().second; } std::string SurfaceManager::toString() const { - + std::stringstream sstr ; - + sstr << "-------- SurfaceManager contains the following maps : --------- " << std::endl ; - + for( SurfaceMapsMap::const_iterator mi = _map.begin() ; mi != _map.end() ; ++mi ) { - - sstr << " key: " << mi->first << " \t number of surfaces : " << mi->second.size() << std::endl ; + + sstr << " key: " << mi->first << " \t number of surfaces : " << mi->second.second.size() << std::endl ; } sstr << "---------------------------------------------------------------- " << std::endl ; @@ -105,5 +162,5 @@ namespace dd4hep { } - } // namespace -}// namespace + } // namespace rec +} // namespace dd4hep