diff --git a/CMakeLists.txt b/CMakeLists.txt index 66d7f0c26eae34dcf63989bf9f3ecca5d40844de..4ec365bb6986b52b53f05bf7c36d482d431f91bc 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -49,6 +49,7 @@ include(DD4hep) add_subdirectory(DDCore) if(DD4HEP_WITH_GEANT4) add_subdirectory(DDG4) +### add_subdirectory(DDSense) endif() #---Examples------------------------------------------------------------------------ diff --git a/DDG4/CMakeLists.txt b/DDG4/CMakeLists.txt index e8a71875046d38637b315ec47289799235abc70a..43bae55053d72791bb7d5faa95a4e085edc22a3e 100644 --- a/DDG4/CMakeLists.txt +++ b/DDG4/CMakeLists.txt @@ -13,6 +13,7 @@ include(DD4hep_XML_setup) #---Includedirs------------------------------------------------------------------- include_directories(${CMAKE_SOURCE_DIR}/DDCore/include + ${CMAKE_SOURCE_DIR}/DDSense/include ${CMAKE_CURRENT_SOURCE_DIR}/include ${ROOT_INCLUDE_DIR} ${CLHEP_INCLUDE_DIR} @@ -24,7 +25,7 @@ if(NOT DD4HEP_USE_XERCESC) list(REMOVE_ITEM sources ${CMAKE_CURRENT_SOURCE_DIR}/src/Geant4XML.cpp) endif() add_library(DD4hepG4 SHARED ${sources}) -target_link_libraries(DD4hepG4 DD4hepCore ${ROOT_LIBRARIES} Reflex ${Geant4_LIBRARIES}) +target_link_libraries(DD4hepG4 DD4hepCore DD4hepSense ${ROOT_LIBRARIES} Reflex ${Geant4_LIBRARIES}) SET_TARGET_PROPERTIES( DD4hepG4 PROPERTIES VERSION ${DD4hep_VERSION} SOVERSION ${DD4hep_SOVERSION}) diff --git a/DDSense/CMakeLists.txt b/DDSense/CMakeLists.txt new file mode 100644 index 0000000000000000000000000000000000000000..440a61852866d9dc9e4f6be7ec64a6892d64afe5 --- /dev/null +++ b/DDSense/CMakeLists.txt @@ -0,0 +1,59 @@ +#---Find Geant4------------------------------------------------------------------- + +find_package(Geant4 REQUIRED ) #gdml ui_all vis_all) +#if(NOT Geant4_clhep_FOUND) +# find_package(CLHEP REQUIRED) +# set(Geant4_INCLUDE_DIRS ${Geant4_INCLUDE_DIRS} ${CLHEP_INCLUDE_DIRS}) +# set(Geant4_LIBRARIES ${Geant4_LIBRARIES} ${CLHEP_LIBRARIES}) +#endif() +INCLUDE(${Geant4_USE_FILE}) # this also takes care of geant 4 definitions and include dirs + + +# --- needed ? +# include(DD4hep_XML_setup) + +#---Includedirs------------------------------------------------------------------- +include_directories( ${CMAKE_SOURCE_DIR}/DDCore/include + ${CMAKE_CURRENT_SOURCE_DIR}/include + #${CLHEP_INCLUDE_DIR} + ${Geant4_INCLUDE_DIRS} + ) + +#---Add Library------------------------------------------------------------------- +file(GLOB sources src/*.cpp) +#if(NOT DD4HEP_USE_XERCESC) +# list(REMOVE_ITEM sources ${CMAKE_CURRENT_SOURCE_DIR}/src/Geant4XML.cpp) +#endif() + +add_library(DD4hepSense SHARED ${sources}) + +#target_link_libraries(DDSense ${Geant4_LIBRARIES}) + +SET_TARGET_PROPERTIES( DD4hepSense PROPERTIES VERSION ${DD4hep_VERSION} SOVERSION ${DD4hep_SOVERSION}) + +#-------------------------------------------------- +# trivial example library +file(GLOB exsrc example/*.cpp) +#if(NOT DD4HEP_USE_XERCESC) +# list(REMOVE_ITEM sources ${CMAKE_CURRENT_SOURCE_DIR}/src/Geant4XML.cpp) +#endif() +add_library(DD4hepSenseExample SHARED ${exsrc} ) +target_link_libraries(DD4hepSenseExample DD4hepSense ${Geant4_LIBRARIES}) + +#----------------------------------------------------------------------------------- +add_executable(ddsense_example example/ddsense_example.cpp ) +target_link_libraries(ddsense_example DD4hepSense) + + +#--- install target------------------------------------- +install(DIRECTORY include/DDSense + DESTINATION include + PATTERN ".svn" EXCLUDE ) + +#install(TARGETS DD4hepG4 g4gdmlDisplay +# RUNTIME DESTINATION bin +# LIBRARY DESTINATION lib +# ) + +# to do: add corresponding uninstall... +#------------------------------------------------------- diff --git a/DDSense/Readme b/DDSense/Readme new file mode 100644 index 0000000000000000000000000000000000000000..007c04949b42496d2a5b3f49f9885f69e1834220 --- /dev/null +++ b/DDSense/Readme @@ -0,0 +1,27 @@ + ********************** + * DDSense + * + * @author F.Gaede + * 08 2013 + ********************** + + First shot at a sensitive detector subpackage with a + plugin mechanism. + + classes: G4SensitiveDetector, DDSensitiveManager + G4ExampleTrackingSD + + see: ./example/ddsense_example.cpp + + + * To build uncomment in $DD4hep/CMakeLists.txt: + ## add_subdirectory(DDSense) + + * to run test: + + export DD4hep_SD_DLL=./lib/libDD4hepSenseExample.dylib + + ./bin/ddsense_example + + + diff --git a/DDSense/example/G4ExampleTrackingSD.cpp b/DDSense/example/G4ExampleTrackingSD.cpp new file mode 100644 index 0000000000000000000000000000000000000000..8e7f309e6242d3290a5f9281f82c0dd37d245023 --- /dev/null +++ b/DDSense/example/G4ExampleTrackingSD.cpp @@ -0,0 +1,38 @@ +#include "G4ExampleTrackingSD.h" + + +/** DD4hep namespace declaration */ +namespace DD4hep { + /** DDSense namespace declaration */ + namespace Simulation { + + + // global instance + G4ExampleTrackingSD _theG4ExampleTrackingSD ; + + + G4ExampleTrackingSD::G4ExampleTrackingSD() : G4SensitiveDetector("G4ExampleTrackingSD" ), + G4VSensitiveDetector("G4ExampleTrackingSD") {} + + + G4bool G4ExampleTrackingSD::ProcessHits(G4Step*aStep, G4TouchableHistory*ROhist) { + + std::cout << "G4ExampleTrackingSD::ProcessHits " << std::endl ; + + } + + G4SensitiveDetector* G4ExampleTrackingSD::newInstance() const { return new G4ExampleTrackingSD ; } + + /** Implementation classes can overwrite this to initialize from named parameters + */ + void G4ExampleTrackingSD::init( const ParameterMap& parameters ) { + + G4SensitiveDetector::init( parameters ) ; + + // do sth. with parameters ... + } + + + } //namespace +} //namespace + diff --git a/DDSense/example/G4ExampleTrackingSD.h b/DDSense/example/G4ExampleTrackingSD.h new file mode 100644 index 0000000000000000000000000000000000000000..d6f6c88278a9b07daf540488399317fd2008949f --- /dev/null +++ b/DDSense/example/G4ExampleTrackingSD.h @@ -0,0 +1,50 @@ +// $Id:$ +//==================================================================== +// AIDA Detector description implementation for LCD +//-------------------------------------------------------------------- +// +// @Author : F.Gaede, DESY +// +//==================================================================== + +#ifndef DD4hep_Simulation_G4ExampleTrackingSD_h +#define DD4hep_Simulation_G4ExampleTrackingSD_h + +#include "DDSense/G4SensitiveDetector.h" + +#include "G4VSensitiveDetector.hh" + +/** DD4hep namespace declaration */ +namespace DD4hep { + /** DDSense namespace declaration */ + namespace Simulation { + + + /** Trivial example SD thatn does not do anything - just for testing plugin mechanism... + */ + class G4ExampleTrackingSD : public G4SensitiveDetector, G4VSensitiveDetector { + + public: + + /** c'tor */ + G4ExampleTrackingSD() ; + + virtual G4SensitiveDetector* newInstance() const ; + + /** Implementation classes can overwrite this to initialize from named parameters + */ + virtual void init( const ParameterMap& parameters ) ; + + virtual G4bool ProcessHits(G4Step*aStep, G4TouchableHistory*ROhist) ; + + /** d'tor */ + virtual ~G4ExampleTrackingSD() {} + + private: + + } ; + + } // namespace +} // namespace + +#endif diff --git a/DDSense/example/ddsense_example.cpp b/DDSense/example/ddsense_example.cpp new file mode 100644 index 0000000000000000000000000000000000000000..9c46686f2530cbf0b871d5ce21171e1053e268dd --- /dev/null +++ b/DDSense/example/ddsense_example.cpp @@ -0,0 +1,74 @@ +// $Id:$ +//==================================================================== +// AIDA Detector description implementation for LCD +//-------------------------------------------------------------------- +// +// @Author : F.Gaede, DESY +//==================================================================== + +#include "DDSense/DDSensitiveManager.h" +#include "DDSense/G4SensitiveDetector.h" + +#include <iostream> + + +/** Simple test and demonstration program for simple plugin mechanism for SensitiveDetector classes. + */ +int main(){ + + + DD4hep::Simulation::DDSensitiveManager* mgr = DD4hep::Simulation::DDSensitiveManager::instance() ; + + + std::cout << " loading plugins as specified in env variable " + << DD4hep::Simulation::DDSensitiveManager::DLL + << std::endl ; + + mgr->loadLibraries() ; + + std::cout << " get G4SensitiveDetectors types: " << std::endl ; + + std::vector<std::string> sdt = mgr->getSDTypes() ; + + + for(unsigned i=0,N=sdt.size() ; i<N ; ++i){ + std::cout << " " << sdt[i] << std::endl ; + } + + + if( sdt.size() ) { + + std::cout << " get instance for type " << sdt[0] << std::endl ; + + + DD4hep::Simulation::G4SensitiveDetector* sd = mgr->getSD( sdt[0] ) ; + + + if( sd ){ + + std::cout << " and create a new instance and configure it ..." << std::endl ; + + + DD4hep::Simulation::G4SensitiveDetector* sd_1 = sd->newInstance() ; + + DD4hep::Simulation::G4SensitiveDetector::ParameterMap params; + + params["Readout"] = "GridXYZ" ; + params["EnergyCut"] = "0.1*keV" ; + + sd_1->init( params ) ; + + + std::cout << sd_1->toString() << std::endl ; + + + delete sd_1 ; + + } + + } else { + + std::cout << " no SDs loaded - make sure you set " << DD4hep::Simulation::DDSensitiveManager::DLL << " correctly ...." << std::endl ; + + } +} diff --git a/DDSense/include/DDSense/DDSensitiveManager.h b/DDSense/include/DDSense/DDSensitiveManager.h new file mode 100644 index 0000000000000000000000000000000000000000..9ce32d7072b327fe05dab907cc6aa31d8ccea024 --- /dev/null +++ b/DDSense/include/DDSense/DDSensitiveManager.h @@ -0,0 +1,82 @@ +// $Id:$ +//==================================================================== +// AIDA Detector description implementation for LCD +//-------------------------------------------------------------------- +// +// @Author : F.Gaede, DESY +// +//==================================================================== + +#ifndef DD4hep_Simulation_DDSensitiveManager_h +#define DD4hep_Simulation_DDSensitiveManager_h + +// C/C++ include files +#include <string> +#include <map> +#include <vector> + +/** DD4hep namespace declaration */ +namespace DD4hep { + /** DDSense namespace declaration */ + namespace Simulation { + + class G4SensitiveDetector ; + + /**Singleton class that holds all known plugins of DDSensitiveDetector objects ... + */ + class DDSensitiveManager{ + + public: + + typedef std::map< std::string, G4SensitiveDetector*> SDMap ; + + // name of the env variable + static const std::string DLL ; + + /** Return the instance of this manager. + */ + static DDSensitiveManager* instance() ; + + /** d'tor + */ + virtual ~DDSensitiveManager() ; + + + /** register a G4SensitiveDetector */ + void registerSD( G4SensitiveDetector* ) ; + + + /** Load libraries with plugins from files specified in environment variable 'DD4hep_SD_DLL' */ + void loadLibraries() ; + + + /** Return a list of registered G4SensitiveDetector types */ + std::vector<std::string> getSDTypes() ; + + + /** Get a pointer to the stored SD - 0 if type hast not been registered */ + inline G4SensitiveDetector* getSD( const std::string& typeName ){ + + SDMap::iterator i = _map.find( typeName ) ; + + return ( i != _map.end() ? i->second : 0 ) ; + } + + + + private: + /** private c'tor */ + DDSensitiveManager() ; + + + + SDMap _map ; + + static DDSensitiveManager* _me ; + } ; + + + } // namespace +} // namespace + +#endif diff --git a/DDSense/include/DDSense/G4SensitiveDetector.h b/DDSense/include/DDSense/G4SensitiveDetector.h new file mode 100644 index 0000000000000000000000000000000000000000..1d67d17e59de941e8852a46ccc0adaade85d3069 --- /dev/null +++ b/DDSense/include/DDSense/G4SensitiveDetector.h @@ -0,0 +1,73 @@ +// $Id:$ +//==================================================================== +// AIDA Detector description implementation for LCD +//-------------------------------------------------------------------- +// +// @Author : F.Gaede, DESY +// +//==================================================================== + +#ifndef DD4hep_Simulation_G4SensitiveDetector_h +#define DD4hep_Simulation_G4SensitiveDetector_h + +// C/C++ include files +#include <string> +#include <map> + +/** DD4hep namespace declaration */ +namespace DD4hep { + /** DDSense namespace declaration */ + namespace Simulation { + + class DDSensitiveManager ; + + + /** Base class for G4VSensitiveDetectors used with DD4Hep. + */ + class G4SensitiveDetector{ + + protected : + /** c'tor */ + G4SensitiveDetector() ; + + public: + + typedef std::map< std::string, std::string > ParameterMap ; + + /**only public c'tor - initialize with unique tpe name */ + G4SensitiveDetector( const std::string& typeName) ; + + /** Return unique type name (typically the class name) + */ + inline const std::string& typeName() const { return _typeName ; } + + + /**Implementation classes need to provide a factory method: + */ + virtual G4SensitiveDetector* newInstance() const =0 ; + + /** Implementation classes can overwrite this to initialize from named parameters + */ + virtual void init( const ParameterMap& parameters ) ; + + /** d'tor */ + virtual ~G4SensitiveDetector() ; + + + /** Create String with parameters + */ + std::string toString() ; + + protected: + + ParameterMap _params ; + + private: + std::string _typeName ; + + } ; + + } // namespace +} // namespace + +#endif diff --git a/DDSense/src/DDSensitiveManager.cpp b/DDSense/src/DDSensitiveManager.cpp new file mode 100644 index 0000000000000000000000000000000000000000..e9d904429ba7ac473249772c33a1eeb1f04e7f5b --- /dev/null +++ b/DDSense/src/DDSensitiveManager.cpp @@ -0,0 +1,145 @@ +#include "DDSense/DDSensitiveManager.h" +#include "DDSense/G4SensitiveDetector.h" + +#include "DD4hep/BitField64.h" // provides StringTokenizer + +#include <dlfcn.h> +#include <iostream> +#include <cstdlib> +#include <string> +#include <vector> +#include <set> + + +/** DD4hep namespace declaration */ +namespace DD4hep { + /** DDSense namespace declaration */ + namespace Simulation { + + const std::string DDSensitiveManager::DLL = "DD4hep_SD_DLL" ; + + typedef std::vector<std::string> StringVec ; + + DDSensitiveManager* DDSensitiveManager::_me = 0 ; + + DDSensitiveManager* DDSensitiveManager::instance(){ + if( !_me){ + _me = new DDSensitiveManager ; + + // now load all plugins defined in DD4HepSD_DLL: + // _me->loadLibraries() ; + } + return _me ; + } + + DDSensitiveManager::DDSensitiveManager(){ + } + + + DDSensitiveManager::~DDSensitiveManager(){ + } + + void DDSensitiveManager::registerSD( G4SensitiveDetector*s ){ + + // std::cout << " DDSensitiveManager::registerSD( " << s->typeName() << ")" << std::endl ; + + SDMap::iterator it = _map.find( s->typeName() ) ; + if( it == _map.end() ) + _map.insert( std::make_pair( s->typeName() , s ) ) ; + } + + + + std::vector<std::string> DDSensitiveManager::getSDTypes() { + + std::vector< std::string> sdtypes ; + for( SDMap:: iterator it = _map.begin() ; it != _map.end() ; ++it ){ + + sdtypes.push_back( it->first ) ; + } + + return sdtypes ; + } + + + void DDSensitiveManager::loadLibraries(){ + + StringVec libs ; + StringTokenizer t( libs, ':' ) ; + + std::string sds("") ; + + char* var = std::getenv( DLL.c_str() ) ; + if( var != 0 ) { + sds = var ; + } else { + std::cout << std::endl << "******** You have no " << DLL << " variable in your environment " + " - so no G4SensitiveDetectors will be loaded. ! ******* " << std::endl << std::endl ; + } + + std::for_each( sds.begin(), sds.end(), t ) ; + + bool loadError=false; + + std::set<std::string> checkDuplicateLibs; + + + for( unsigned i=0,N=libs.size() ; i<N ; ++i){ + + const std::string& libName = libs[i] ; + + size_t idx; + idx = libName.find_last_of("/"); + // the library basename, i.e. /path/to/libBlah.so --> libBlah.so + std::string libBaseName( libName.substr( idx + 1 ) ); + + char *real_path = realpath(libName.c_str(), NULL); + + if( real_path != NULL ){ + std::cout << " Loading shared library : " << real_path << " ("<< libBaseName << ") " << std::endl ; + + // use real_path + free(real_path); + } + else{ + std::cout << "Loading shared library : " << libName << " ("<< libBaseName << ") " << std::endl ; + } + + if( checkDuplicateLibs.find( libBaseName ) == checkDuplicateLibs.end() ){ + checkDuplicateLibs.insert( libBaseName ) ; + } + else{ + std::cout << std::endl << " ERROR loading shared library : " << libName << std::endl + << " -> Trying to load DUPLICATE library " << std::endl << std::endl ; + loadError=true; + } + + + if( ! loadError ){ + + //void* libPointer = dlopen( libName.c_str() , RTLD_NOW) ; + //void* libPointer = dlopen( libName.c_str() , RTLD_LAZY ) ; + //void* libPointer = dlopen( libName.c_str() , RTLD_NOW | RTLD_GLOBAL) ; + void* libPointer = dlopen( libName.c_str() , RTLD_LAZY | RTLD_GLOBAL) ; + + if( libPointer == 0 ){ + std::cout << std::endl << " ERROR loading shared library : " << libName << std::endl + << " -> " << dlerror() << std::endl << std::endl ; + loadError=true; + } + // else{ + // libs.push_back( libPointer ) ; + // } + } + + + }// loop over libs + + } + //-------------------------------------- + + + + } //namespace +} //namespace + diff --git a/DDSense/src/G4SensitiveDetector.cpp b/DDSense/src/G4SensitiveDetector.cpp new file mode 100644 index 0000000000000000000000000000000000000000..206d257a09823931dd3af35ec2bdc3e52366af09 --- /dev/null +++ b/DDSense/src/G4SensitiveDetector.cpp @@ -0,0 +1,46 @@ +#include "DDSense/G4SensitiveDetector.h" +#include "DDSense/DDSensitiveManager.h" + +#include <sstream> + +/** DD4hep namespace declaration */ +namespace DD4hep { + /** DDSense namespace declaration */ + namespace Simulation { + + + G4SensitiveDetector::G4SensitiveDetector(const std::string& typeName) : _typeName( typeName ) { + + DDSensitiveManager::instance()->registerSD( this ) ; + } + + + void G4SensitiveDetector::init( const ParameterMap& parameters ){ + + _params = parameters ; // copy parameter map + } + + + G4SensitiveDetector::~G4SensitiveDetector(){ + } + + + std::string G4SensitiveDetector::toString(){ + + std::stringstream s ; + + s << "---- G4SensitiveDetector - type " << typeName() << std::endl ; + + for( ParameterMap::iterator it = _params.begin() ; it != _params.end() ; ++it ){ + + s << " " << it->first << ": " << it->second << std::endl ; + } + s << "----" << std::endl ; + + return s.str() ; + } + + + } //namespace +} //namespace +