diff --git a/DDCore/include/DD4hep/OpticalSurfaceManager.h b/DDCore/include/DD4hep/OpticalSurfaceManager.h index ddb4c316feb3b996a1f4be99e1aee47d2a9ca88d..ccefe96de58cfd180764d39a25aadcd652a57dfc 100644 --- a/DDCore/include/DD4hep/OpticalSurfaceManager.h +++ b/DDCore/include/DD4hep/OpticalSurfaceManager.h @@ -22,6 +22,11 @@ /// Namespace for the AIDA detector description toolkit namespace dd4hep { + /// Namespace for implementation details of the AIDA detector description toolkit + namespace detail { + class OpticalSurfaceManagerObject; + } + /// Class to support the handling of optical surfaces. /** * @@ -29,9 +34,9 @@ namespace dd4hep { * \version 1.0 * \ingroup DD4HEP_CORE */ - class OpticalSurfaceManager: public Handle<TGeoManager> { + class OpticalSurfaceManager: public Handle<detail::OpticalSurfaceManagerObject> { public: - typedef TGeoManager Object; + typedef detail::OpticalSurfaceManagerObject Object; public: /// Default constructor @@ -59,13 +64,16 @@ namespace dd4hep { /// Access border surface by its identifier BorderSurface getBorderSurface(DetElement de, const std::string& nam) const; /// Access optical surface data by its identifier - OpticalSurface getSurface(DetElement de, const std::string& nam) const; + OpticalSurface getOpticalSurface(DetElement de, const std::string& nam) const; /// Add skin surface to manager - void addSkinSurface(SkinSurface surf) const; + void addSkinSurface(DetElement de, SkinSurface surf) const; /// Add border surface to manager - void addBorderSurface(BorderSurface surf) const; + void addBorderSurface(DetElement de, BorderSurface surf) const; /// Add optical surface data to manager - void addSurface(OpticalSurface surf) const; + void addOpticalSurface(OpticalSurface surf) const; + + /// Register the temporary surface objects with the TGeoManager + void registerSurfaces(DetElement subdetector); #endif }; } /* End namespace dd4hep */ diff --git a/DDCore/include/DD4hep/OpticalSurfaces.h b/DDCore/include/DD4hep/OpticalSurfaces.h index 556fb2406d942fed649d977be5a58ca0829f4499..31eb6f4fae1389123781988b41a72ecbe5d42ef6 100644 --- a/DDCore/include/DD4hep/OpticalSurfaces.h +++ b/DDCore/include/DD4hep/OpticalSurfaces.h @@ -90,7 +90,11 @@ namespace dd4hep { template <typename Q> SkinSurface(const Handle<Q>& e) : Handle<Object>(e) { } /// Initializing constructor. - SkinSurface(DetElement de, const std::string& nam, OpticalSurface surf, Volume vol); + SkinSurface(Detector& description, + DetElement de, + const std::string& nam, + OpticalSurface surf, + Volume vol); /// Assignment operator SkinSurface& operator=(const SkinSurface& m) = default; @@ -125,7 +129,12 @@ namespace dd4hep { template <typename Q> BorderSurface(const Handle<Q>& e) : Handle<Object>(e) { } /// Initializing constructor: Creates the object and registers it to the manager - BorderSurface(DetElement de, const std::string& nam, OpticalSurface surf, PlacedVolume left, PlacedVolume right); + BorderSurface(Detector& description, + DetElement de, + const std::string& nam, + OpticalSurface surf, + PlacedVolume left, + PlacedVolume right); /// Assignment operator BorderSurface& operator=(const BorderSurface& m) = default; diff --git a/DDCore/include/DD4hep/detail/OpticalSurfaceManagerInterna.h b/DDCore/include/DD4hep/detail/OpticalSurfaceManagerInterna.h new file mode 100644 index 0000000000000000000000000000000000000000..9d882653193b0d12f93d91a1499ad64494d47b6d --- /dev/null +++ b/DDCore/include/DD4hep/detail/OpticalSurfaceManagerInterna.h @@ -0,0 +1,74 @@ +//========================================================================== +// 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 +// +//========================================================================== +// +// NOTE: +// +// This is an internal include file. It should only be included to +// instantiate code. Otherwise the Opticalsurfacemanager include file should be +// sufficient for all practical purposes. +// +//========================================================================== +#ifndef DD4HEP_DDCORE_OPTICALSURFACEMANAGERINTERNA_H +#define DD4HEP_DDCORE_OPTICALSURFACEMANAGERINTERNA_H + +/// Framework include files +#include "DD4hep/Detector.h" + +/// C/C++ include files +#include <map> + +/// Namespace for the AIDA detector description toolkit +namespace dd4hep { + + /// Namespace for implementation details of the AIDA detector description toolkit + namespace detail { + + /// This structure describes the internal data of the volume manager object + /** + * + * \author M.Frank + * \version 1.0 + * \ingroup DD4HEP_CORE + */ + class OpticalSurfaceManagerObject: public NamedObject { + public: + typedef std::pair<DetElement, std::string> LocalKey; + + /// Reference to the main detector description object + Detector& detector; +#if ROOT_VERSION_CODE > ROOT_VERSION(6,16,0) + std::map<LocalKey, SkinSurface> skinSurfaces; + std::map<LocalKey, BorderSurface> borderSurfaces; + std::map<std::string, OpticalSurface> opticalSurfaces; +#endif + + public: + /// Default constructor + OpticalSurfaceManagerObject() = delete; + /// No move constructor + OpticalSurfaceManagerObject(OpticalSurfaceManagerObject&& copy) = delete; + /// No copy constructor + OpticalSurfaceManagerObject(const OpticalSurfaceManagerObject& copy) = default; + /// Initializing constructor + OpticalSurfaceManagerObject(Detector& det) : detector(det) {} + /// Default destructor + virtual ~OpticalSurfaceManagerObject(); + /// No move assignment + OpticalSurfaceManagerObject& operator=(OpticalSurfaceManagerObject&& copy) = default; + /// No copy assignment + OpticalSurfaceManagerObject& operator=(const OpticalSurfaceManagerObject& copy) = delete; + }; + + } /* End namespace detail */ +} /* End namespace dd4hep */ +#endif /* DD4HEP_DDCORE_OPTICALSURFACEMANAGERINTERNA_H */ diff --git a/DDCore/src/DetectorImp.cpp b/DDCore/src/DetectorImp.cpp index 59c9df81081bfe6bd88b7eae9d9b98f1ca1cec15..2a43619e2c0c0b36f739d8c580966a231c12d2bc 100644 --- a/DDCore/src/DetectorImp.cpp +++ b/DDCore/src/DetectorImp.cpp @@ -22,6 +22,7 @@ #include "DD4hep/detail/ObjectsInterna.h" #include "DD4hep/detail/DetectorInterna.h" #include "DD4hep/detail/VolumeManagerInterna.h" +#include "DD4hep/detail/OpticalSurfaceManagerInterna.h" #include "DetectorImp.h" // C/C++ include files @@ -173,6 +174,8 @@ DetectorImp::DetectorImp(const string& name) { gGeoIdentity = new TGeoIdentity(); } + m_surfaceManager = new detail::OpticalSurfaceManagerObject(*this); + VisAttr attr("invisible"); attr.setColor(0.5, 0.5, 0.5); attr.setAlpha(1); @@ -194,6 +197,7 @@ DetectorImp::~DetectorImp() { s_instances.remove(m_manager->GetName()); } } + deletePtr(m_surfaceManager); destroyData(true); m_extensions.clear(); InstanceCount::decrement(this); diff --git a/DDCore/src/DetectorImp.h b/DDCore/src/DetectorImp.h index 9d2dd46723de6355e5591f9126b25f4237549dfe..be947b8ddf4402f0fe3d9087ec0e2faae5e6a582 100644 --- a/DDCore/src/DetectorImp.h +++ b/DDCore/src/DetectorImp.h @@ -28,6 +28,11 @@ class TGeoManager; /// Namespace for the AIDA detector description toolkit namespace dd4hep { + /// Namespace for implementation details of the AIDA detector description toolkit + namespace detail { + class OpticalSurfaceManagerObject; + } + /// Concrete implementation class of the Detector interface /** The main entry point to the DD4hep detector description * @@ -49,6 +54,9 @@ namespace dd4hep { /// VolumeManager m_volManager; DetectorBuildType m_buildType; + /// Optical surface manager + detail::OpticalSurfaceManagerObject* m_surfaceManager = 0; //! not persistent + private: /// Disable move constructor DetectorImp(DetectorImp&& copy) = delete; @@ -179,7 +187,7 @@ namespace dd4hep { } /// Access the optical surface manager virtual OpticalSurfaceManager surfaceManager() const override { - return OpticalSurfaceManager(m_manager); + return OpticalSurfaceManager(m_surfaceManager); } /// Return handle to the combined electromagentic field description. diff --git a/DDCore/src/OpticalSurfaceManager.cpp b/DDCore/src/OpticalSurfaceManager.cpp index 3473c16456a88e9c5f82d0aa29c59a37fce6746a..43a97ac49f0517cb7a7cdab4f0c4cd0bb8855119 100644 --- a/DDCore/src/OpticalSurfaceManager.cpp +++ b/DDCore/src/OpticalSurfaceManager.cpp @@ -13,16 +13,15 @@ // Framework include files #include "DD4hep/OpticalSurfaceManager.h" +#include "DD4hep/detail/OpticalSurfaceManagerInterna.h" +#include "DD4hep/ExtensionEntry.h" #include "DD4hep/Detector.h" #include "DD4hep/Printout.h" -#include "DD4hep/detail/Handle.inl" // C/C++ includes #include <sstream> #include <iomanip> -DD4HEP_INSTANTIATE_HANDLE(TGeoManager); - using namespace std; using namespace dd4hep; @@ -36,8 +35,13 @@ OpticalSurfaceManager OpticalSurfaceManager::getOpticalSurfaceManager(Detector& /// Access skin surface by its identifier SkinSurface OpticalSurfaceManager::getSkinSurface(DetElement de, const string& nam) const { if ( de.isValid() ) { - string n = de.path() + '#' + nam; - return access()->GetSkinSurface(n.c_str()); + Object* o = access(); + string n = de.path() + '#' + nam; + TGeoSkinSurface* surf = o->detector.manager().GetSkinSurface(n.c_str()); + if ( surf ) return surf; + auto i = o->skinSurfaces.find(Object::LocalKey(de, nam)); + if ( i != o->skinSurfaces.end() ) return (*i).second; + return 0; } except("SkinSurface", "++ Cannot access SkinSurface %s without valid detector element!",nam.c_str()); @@ -47,8 +51,13 @@ SkinSurface OpticalSurfaceManager::getSkinSurface(DetElement de, const string& /// Access border surface by its identifier BorderSurface OpticalSurfaceManager::getBorderSurface(DetElement de, const string& nam) const { if ( de.isValid() ) { - string n = de.path() + '#' + nam; - return access()->GetBorderSurface(n.c_str()); + Object* o = access(); + string n = de.path() + '#' + nam; + TGeoBorderSurface* surf = o->detector.manager().GetBorderSurface(n.c_str()); + if ( surf ) return surf; + auto i = o->borderSurfaces.find(Object::LocalKey(de, nam)); + if ( i != o->borderSurfaces.end() ) return (*i).second; + return 0; } except("BorderSurface", "++ Cannot access BorderSurface %s without valid detector element!",nam.c_str()); @@ -56,10 +65,15 @@ BorderSurface OpticalSurfaceManager::getBorderSurface(DetElement de, const stri } /// Access optical surface data by its identifier -OpticalSurface OpticalSurfaceManager::getSurface(DetElement de, const string& nam) const { +OpticalSurface OpticalSurfaceManager::getOpticalSurface(DetElement de, const string& nam) const { if ( de.isValid() ) { - string n = de.path() + '#' + nam; - return access()->GetOpticalSurface(n.c_str()); + Object* o = access(); + string n = de.path() + '#' + nam; + TGeoOpticalSurface* surf = o->detector.manager().GetOpticalSurface(n.c_str()); + if ( surf ) return surf; + auto i = o->opticalSurfaces.find(n); + if ( i != o->opticalSurfaces.end() ) return (*i).second; + return 0; } except("OpticalSurface", "++ Cannot access OpticalSurface %s without valid detector element!",nam.c_str()); @@ -67,17 +81,62 @@ OpticalSurface OpticalSurfaceManager::getSurface(DetElement de, const string& na } /// Add skin surface to manager -void OpticalSurfaceManager::addSkinSurface(SkinSurface surf) const { - access()->AddSkinSurface(surf.ptr()); +void OpticalSurfaceManager::addSkinSurface(DetElement de, SkinSurface surf) const { + if ( access()->skinSurfaces.insert(make_pair(make_pair(de,surf->GetName()), surf)).second ) + return; + except("OpticalSurfaceManager","++ Skin surface %s already present for DE:%s.", + surf->GetName(), de.name()); } /// Add border surface to manager -void OpticalSurfaceManager::addBorderSurface(BorderSurface surf) const { - access()->AddBorderSurface(surf.ptr()); +void OpticalSurfaceManager::addBorderSurface(DetElement de, BorderSurface surf) const { + if ( access()->borderSurfaces.insert(make_pair(make_pair(de,surf->GetName()), surf)).second ) + return; + except("OpticalSurfaceManager","++ Border surface %s already present for DE:%s.", + surf->GetName(), de.name()); } /// Add optical surface data to manager -void OpticalSurfaceManager::addSurface(OpticalSurface surf) const { - access()->AddOpticalSurface(surf.ptr()); +void OpticalSurfaceManager::addOpticalSurface(OpticalSurface surf) const { + if ( access()->opticalSurfaces.insert(make_pair(surf->GetName(), surf)).second ) + return; + except("OpticalSurfaceManager","++ Optical surface %s already present.", + surf->GetName()); +} + +/// Register the temporary surface objects with the TGeoManager +void OpticalSurfaceManager::registerSurfaces(DetElement subdetector) { + Object* o = access(); + unique_ptr<Object> extension(new Object(o->detector)); + for(auto& s : o->opticalSurfaces) { + //string n = s.first.first.path() + '#' + s.first.second; + //s.second->SetName(n.c_str()); + o->detector.manager().AddOpticalSurface(s.second.ptr()); + extension->opticalSurfaces.insert(s); + } + o->opticalSurfaces.clear(); + + for(auto& s : o->skinSurfaces) { + string n = s.first.first.path() + '#' + s.first.second; + s.second->SetName(n.c_str()); + o->detector.manager().AddSkinSurface(s.second.ptr()); + extension->skinSurfaces.insert(s); + } + o->skinSurfaces.clear(); + + for(auto& s : o->borderSurfaces) { + string n = s.first.first.path() + '#' + s.first.second; + s.second->SetName(n.c_str()); + o->detector.manager().AddBorderSurface(s.second.ptr()); + extension->borderSurfaces.insert(s); + } + o->borderSurfaces.clear(); + + if ( extension->opticalSurfaces.empty() && + extension->borderSurfaces.empty() && + extension->skinSurfaces.empty() ) { + return; + } + subdetector.addExtension(new detail::DeleteExtension<Object,Object>(extension.release())); } #endif diff --git a/DDCore/src/OpticalSurfaceManagerInterna.cpp b/DDCore/src/OpticalSurfaceManagerInterna.cpp new file mode 100644 index 0000000000000000000000000000000000000000..2da6cb6dc4a12341384a7c93191738e711ba66e9 --- /dev/null +++ b/DDCore/src/OpticalSurfaceManagerInterna.cpp @@ -0,0 +1,30 @@ +//========================================================================== +// 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/detail/OpticalSurfaceManagerInterna.h" +#include "DD4hep/detail/Handle.inl" + +// C/C++ includes +#include <sstream> +#include <iomanip> + +using namespace std; +using namespace dd4hep; + +using detail::OpticalSurfaceManagerObject; +DD4HEP_INSTANTIATE_HANDLE(OpticalSurfaceManagerObject); + +/// Default destructor +detail::OpticalSurfaceManagerObject::~OpticalSurfaceManagerObject() { +} diff --git a/DDCore/src/OpticalSurfaces.cpp b/DDCore/src/OpticalSurfaces.cpp index 3d6dfa9adb871a37d5d485c467e218af46dc4716..8979412ec60dee96b0ecd5bdc3b1db6f2efeaeab 100644 --- a/DDCore/src/OpticalSurfaces.cpp +++ b/DDCore/src/OpticalSurfaces.cpp @@ -35,31 +35,29 @@ DD4HEP_INSTANTIATE_HANDLE(TGeoOpticalSurface); /// Initializing constructor. OpticalSurface::OpticalSurface(Detector& description, - const string& nam, + const string& full_name, EModel model, EFinish finish, EType type, double value) { - unique_ptr<Object> s(new Object(nam.c_str(), model, finish, type, value)); - description.manager().AddOpticalSurface(m_element=s.release()); + unique_ptr<Object> s(new Object(full_name.c_str(), model, finish, type, value)); + description.surfaceManager().addOpticalSurface(m_element=s.release()); } /// Initializing constructor: Creates the object and registers it to the manager -SkinSurface::SkinSurface(DetElement de, const string& nam, OpticalSurface surf, Volume vol) +SkinSurface::SkinSurface(Detector& description, DetElement de, const string& nam, OpticalSurface surf, Volume vol) { if ( de.isValid() ) { - string n = de.path() + '#' + nam; if ( vol.isValid() ) { - if ( surf.isValid() ) { - World wrld = de.world(); - unique_ptr<Object> s(new Object(n.c_str(), surf->GetName(), surf.ptr(), vol.ptr())); - wrld.detectorDescription().manager().AddSkinSurface(m_element=s.release()); + if ( surf.isValid() ) { + unique_ptr<Object> s(new Object(nam.c_str(), surf->GetName(), surf.ptr(), vol.ptr())); + description.surfaceManager().addSkinSurface(de, m_element=s.release()); return; } - except("SkinSurface","++ Cannot create SkinSurface %s without valid optical surface!",n.c_str()); + except("SkinSurface","++ Cannot create SkinSurface %s without valid optical surface!",nam.c_str()); } - except("SkinSurface","++ Cannot create SkinSurface %s without valid volume!",n.c_str()); + except("SkinSurface","++ Cannot create SkinSurface %s without valid volume!",nam.c_str()); } except("SkinSurface", "++ Cannot create SkinSurface %s which is not connected to a valid detector element!",nam.c_str()); @@ -76,20 +74,23 @@ Volume SkinSurface::volume() const { } /// Initializing constructor: Creates the object and registers it to the manager -BorderSurface::BorderSurface(DetElement de, const string& nam, OpticalSurface surf, PlacedVolume lft, PlacedVolume rht) +BorderSurface::BorderSurface(Detector& description, + DetElement de, + const string& nam, + OpticalSurface surf, + PlacedVolume lft, + PlacedVolume rht) { if ( de.isValid() ) { - string n = de.path() + '#' + nam; if ( lft.isValid() && rht.isValid() ) { if ( surf.isValid() ) { - World wrld = de.world(); - unique_ptr<Object> s(new Object(n.c_str(), surf->GetName(), surf.ptr(), lft.ptr(), rht.ptr())); - wrld.detectorDescription().manager().AddBorderSurface(m_element=s.release()); + unique_ptr<Object> s(new Object(nam.c_str(), surf->GetName(), surf.ptr(), lft.ptr(), rht.ptr())); + description.surfaceManager().addBorderSurface(de, m_element=s.release()); return; } - except("BorderSurface","++ Cannot create BorderSurface %s without valid optical surface!",n.c_str()); + except("BorderSurface","++ Cannot create BorderSurface %s without valid optical surface!",nam.c_str()); } - except("BorderSurface","++ Cannot create BorderSurface %s without valid placements!",n.c_str()); + except("BorderSurface","++ Cannot create BorderSurface %s without valid placements!",nam.c_str()); } except("BorderSurface", "++ Cannot create BorderSurface %s which is not connected to a valid detector element!",nam.c_str()); diff --git a/DDCore/src/plugins/Compact2Objects.cpp b/DDCore/src/plugins/Compact2Objects.cpp index 037d7a54a2f00ec028f27c936f4ad6cd233dcbf4..e9f5057330dc55fd497b1eb8a4ad671b07b9cd25 100644 --- a/DDCore/src/plugins/Compact2Objects.cpp +++ b/DDCore/src/plugins/Compact2Objects.cpp @@ -1144,6 +1144,7 @@ template <> void Converter<DetElement>::operator()(xml_h element) const { throw runtime_error("Failed to execute subdetector creation plugin. " + dbg.missingFactory(type)); } description.addDetector(det); + description.surfaceManager().registerSurfaces(det); return; } catch (const exception& e) { diff --git a/DDG4/src/Geant4Converter.cpp b/DDG4/src/Geant4Converter.cpp index 66ebe6342932c3475985d9da0d4891911f431d56..aefa7494298bb7b27fe4eb9c362d1ed93f49d50b 100644 --- a/DDG4/src/Geant4Converter.cpp +++ b/DDG4/src/Geant4Converter.cpp @@ -414,6 +414,10 @@ void* Geant4Converter::handleMaterial(const string& name, Material medium) const } Geant4GeometryInfo::PropertyVector* v = (Geant4GeometryInfo::PropertyVector*)handleMaterialProperties(matrix); + if ( 0 == v ) { + except("Geant4Converter", "++ FAILED to create G4 material %s [Cannot convert property:%s]", + material->GetName(), n->GetName()); + } G4MaterialPropertyVector* vec = new G4MaterialPropertyVector(&v->bins[0], &v->values[0], v->bins.size()); tab->AddProperty(n->GetName(), vec);