Skip to content

Commit

Permalink
enable lazy surface map construction
Browse files Browse the repository at this point in the history
  • Loading branch information
Zehvogel committed Jul 31, 2024
1 parent c2cb88c commit 4d97247
Show file tree
Hide file tree
Showing 2 changed files with 151 additions and 41 deletions.
30 changes: 19 additions & 11 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
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,37 @@ 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 :

/// name has to be the name of a single detector! not e.g. tracker or world.
const SurfaceMap& getOrConstruct(const std::string name);

/// TODO: remove
/// initialize all known surface maps
void initialize(const Detector& theDetector) ;

SurfaceMapsMap _map ;
const Detector& m_detector;
const std::set<std::string> m_detectorNames;
const std::set<std::string> m_detectorTypes;
std::map<std::string, std::set<std::string>> m_missingDetectors;
};

} /* namespace rec */
Expand Down
162 changes: 132 additions & 30 deletions DDRec/src/SurfaceManager.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@
#include "DD4hep/Detector.h"

#include <sstream>
#include <ranges>

namespace dd4hep {

Expand All @@ -25,67 +26,168 @@ namespace dd4hep {
namespace rec {


SurfaceManager::SurfaceManager(const Detector& theDetector){
SurfaceManager::SurfaceManager(const Detector& theDetector) :
m_detector(theDetector),
// TODO: clean up after c++23
m_detectorNames(std::views::keys(theDetector.detectors()).begin(), std::views::keys(theDetector.detectors()).end()),
m_detectorTypes(theDetector.detectorTypes().begin(), theDetector.detectorTypes().end())
{

// 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) ;
// 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()) {
std::set<std::string> nameSet{};
for (const DetElement& det : theDetector.detectors(typeName)) {
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 {
const SurfaceMap* SurfaceManager::map( const std::string name ) {

// 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 ;
}

// surface map does not exist or is not completed yet, build it

bool isDetector = m_detectorNames.find(name) != m_detectorNames.end();
bool isDetectorType = m_detectorTypes.find(name) != m_detectorTypes.end();
bool isWorld = name == "world";

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;
}

// 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);
}

return &_map[name].second;
}

if( it != _map.end() ){
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()));
}
}

return & it->second ;
// make a vector of references to all the maps that we need to add to
// urgh I hate c++
// std::vector<std::pair<bool, SurfaceMap>&> maps{};
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);
}
}

return 0 ;
// 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 it = maps.begin(); it != maps.end(); it++) {
for (auto& map : maps) {
map.get().second.emplace(surf->id(), surf);
}
}

// return the map of the detector
return maps[0].get().second;
}

void SurfaceManager::initialize(const Detector& description) {
// TODO: remove
void SurfaceManager::initialize(const Detector& /* description */) {

const std::vector<std::string>& types = description.detectorTypes() ;
// const std::vector<std::string>& types = description.detectorTypes() ;

for(unsigned i=0,N=types.size();i<N;++i){
// for(unsigned i=0,N=types.size();i<N;++i){

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

for(unsigned j=0,M=dets.size();j<M;++j){
// for(unsigned j=0,M=dets.size();j<M;++j){

std::string name = dets[j].name() ;
// std::string name = dets[j].name() ;

SurfaceHelper surfH( dets[j] ) ;
// SurfaceHelper surfH( dets[j] ) ;

const SurfaceList& detSL = surfH.surfaceList() ;
// const SurfaceList& detSL = surfH.surfaceList() ;

// add an empty map for this detector in case there are no surfaces attached
_map.emplace(name , SurfaceMap());
// // add an empty map for this detector in case there are no surfaces attached
// _map.emplace(name , SurfaceMap());

for( SurfaceList::const_iterator it = detSL.begin() ; it != detSL.end() ; ++it ){
ISurface* surf = *it ;
// 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 );
// // enter surface into map for this detector
// _map[ name ].emplace(surf->id(), surf );

// enter surface into map for detector type
_map[ types[i] ].emplace(surf->id(), surf );
// // enter surface into map for detector type
// _map[ types[i] ].emplace(surf->id(), surf );

// enter surface into world map
_map[ "world" ].emplace(surf->id(), surf );
// // enter surface into world map
// _map[ "world" ].emplace(surf->id(), surf );

}
}
}
// }
// }
// }

}

Expand All @@ -97,13 +199,13 @@ namespace dd4hep {

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

0 comments on commit 4d97247

Please sign in to comment.