Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

SurfaceManager: lazily construct surface maps on demand #1304

Draft
wants to merge 3 commits into
base: master
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
32 changes: 18 additions & 14 deletions DDRec/include/DDRec/SurfaceManager.h
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
//==========================================================================
// AIDA Detector description implementation
// AIDA Detector description implementation
//--------------------------------------------------------------------------
// Copyright (C) Organisation europeenne pour la Recherche nucleaire (CERN)
// All rights reserved.
Expand All @@ -17,24 +17,25 @@
#include "DD4hep/Detector.h"
#include <string>
#include <map>
#include <set>

namespace dd4hep {
namespace rec {

/// typedef for surface maps, keyed by the cellID
/// typedef for surface maps, keyed by the cellID
Zehvogel marked this conversation as resolved.
Show resolved Hide resolved
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<bool, SurfaceMap>> SurfaceMapsMap;

public:
/// The constructor
Expand All @@ -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<std::string> m_detectorNames;
std::set<std::string> m_detectorTypes;
std::map<std::string, std::set<std::string>> m_missingDetectors;
};

} /* namespace rec */
Expand Down
149 changes: 103 additions & 46 deletions DDRec/src/SurfaceManager.cpp
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
//==========================================================================
// AIDA Detector description implementation
// AIDA Detector description implementation
//--------------------------------------------------------------------------
// Copyright (C) Organisation europeenne pour la Recherche nucleaire (CERN)
// All rights reserved.
Expand All @@ -19,91 +19,148 @@
#include <sstream>

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<std::string> 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<std::string> 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<std::string>& types = description.detectorTypes() ;
// surface map does not exist or is not completed yet, build it

for(unsigned i=0,N=types.size();i<N;++i){
bool isDetector = m_detectorNames.find(name) != m_detectorNames.end();
bool isDetectorType = m_detectorTypes.find(name) != m_detectorTypes.end();
bool isWorld = name == "world";

const std::vector<DetElement>& dets = description.detectors( types[i] ) ;

for(unsigned j=0,M=dets.size();j<M;++j){
if (isDetector) {
// name is a detector: easiest case
return &getOrConstruct(name);
} else if (!isDetectorType && !isWorld) {
// neither a type name nor world -> 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<std::pair<std::string, bool>> 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<std::reference_wrapper<std::pair<bool, SurfaceMap>>> 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 ;

return sstr.str() ;
}


} // namespace
}// namespace
} // namespace rec
} // namespace dd4hep
Loading