diff --git a/DDCore/CMakeLists.txt b/DDCore/CMakeLists.txt index c6519b47f032e09b10aecbb8deed41f20a97554b..990199c939f181949604429c5c91ebe55437cdc4 100644 --- a/DDCore/CMakeLists.txt +++ b/DDCore/CMakeLists.txt @@ -24,6 +24,7 @@ list(REMOVE_ITEM headers ${CMAKE_CURRENT_SOURCE_DIR}/include/DD4hep/DetFactoryHe ${CMAKE_CURRENT_SOURCE_DIR}/include/DD4hep/Factories.h ${CMAKE_CURRENT_SOURCE_DIR}/include/DD4hep/Plugins.h ${CMAKE_CURRENT_SOURCE_DIR}/include/DD4hep/IoStreams.h + ${CMAKE_CURRENT_SOURCE_DIR}/include/DD4hep/SurfaceInstaller.h ) root_generate_dictionary( G__DD4hep ${headers} ${internal_headers} LINKDEF include/ROOT/LinkDef.h) list(APPEND sources G__DD4hep.cxx) diff --git a/DDCore/include/DD4hep/Handle.h b/DDCore/include/DD4hep/Handle.h index 7fc02ee25b9814d563af52ed763520dcc59b57d9..579a8281cc15fafc54efc0918001fd678c938a97 100644 --- a/DDCore/include/DD4hep/Handle.h +++ b/DDCore/include/DD4hep/Handle.h @@ -49,11 +49,16 @@ namespace DD4hep { /// String conversions: boolean value to string \ingroup DD4HEP_GEOMETRY std::string _toString(bool value); /// String conversions: integer value to string \ingroup DD4HEP_GEOMETRY - std::string _toString(int value); + std::string _toString(int value, const char* fmt = "%d"); /// String conversions: float value to string \ingroup DD4HEP_GEOMETRY - std::string _toString(float value); + std::string _toString(float value, const char* fmt = "%f"); /// String conversions: double value to string \ingroup DD4HEP_GEOMETRY - std::string _toString(double value); + std::string _toString(double value, const char* fmt = "%f"); + /// Pointer to text conversion + std::string _ptrToString(const void* p, const char* fmt = "%p"); + /// Format any pointer (64 bits) to string \ingroup DD4HEP_XML + template <typename T> std::string _toString(const T* p, const char* fmt = "%p") + { return _ptrToString((void*)p, fmt); } /// String conversions: string to boolean value \ingroup DD4HEP_GEOMETRY bool _toBool(const std::string& value); diff --git a/DDCore/include/DD4hep/Plugins.h b/DDCore/include/DD4hep/Plugins.h index 24b01e9e505bb7d215e2f8190f32ad3573767834..54df4f3372f2281045a280106af2fe5ad50622bc 100644 --- a/DDCore/include/DD4hep/Plugins.h +++ b/DDCore/include/DD4hep/Plugins.h @@ -24,8 +24,9 @@ namespace DD4hep { * for a limited code scope. Automatically back-adjusts the debug * level at object destruction. * - * @author M.Frank - * @version 1.0 + * \author M.Frank + * \version 1.0 + * \ingroup DD4HEP */ struct PluginDebug { int m_debug; diff --git a/DDCore/include/DD4hep/Shapes.h b/DDCore/include/DD4hep/Shapes.h index 70c26f9c7abf7557e017614fe64d9c2c1370342d..7659b4e94c0d34013426058b3ea641667760bacb 100644 --- a/DDCore/include/DD4hep/Shapes.h +++ b/DDCore/include/DD4hep/Shapes.h @@ -108,9 +108,13 @@ namespace DD4hep { void make(const std::string& name, double x, double y, double z); public: - /// Constructor to be used when reading the already parsed box object - template <typename Q> - Box(const Handle<Q>& e) + /// Constructor to be used with an existing object + template <typename Q> Box(const Q* p) + : Solid_type<TGeoBBox>(p) { + } + + /// Constructor to be used with an existing object + template <typename Q> Box(const Handle<Q>& e) : Solid_type<TGeoBBox>(e) { } @@ -158,6 +162,11 @@ namespace DD4hep { */ class Polycone: public Solid_type<TGeoPcon> { public: + /// Constructor to be used with an existing object + template <typename Q> Polycone(const Q* p) + : Solid_type<TGeoPcon>(p) { + } + /// Constructor to be used when reading the already parsed polycone object template <typename Q> Polycone(const Handle<Q>& e) : Solid_type<TGeoPcon>(e) { @@ -188,6 +197,11 @@ namespace DD4hep { */ class ConeSegment: public Solid_type<TGeoConeSeg> { public: + /// Constructor to be used with an existing object + template <typename Q> ConeSegment(const Q* p) + : Solid_type<TGeoConeSeg>(p) { + } + /// Constructor to be used when reading the already parsed ConeSegment object template <typename Q> ConeSegment(const Handle<Q>& e) : Solid_type<TGeoConeSeg>(e) { @@ -236,6 +250,10 @@ namespace DD4hep { void make(const std::string& name, double rmin, double rmax, double z, double startPhi, double deltaPhi); public: + /// Constructor to be used with an existing object + template <typename Q> Tube(const Q* p) : Solid_type<MyConeSeg>(p) { + } + /// Constructor to assign an object template <typename Q> Tube(const Handle<Q>& e) : Solid_type<MyConeSeg>(e) { @@ -291,6 +309,10 @@ namespace DD4hep { void make(const std::string& name, double z, double rmin1, double rmax1, double rmin2, double rmax2); public: + /// Constructor to be used with an existing object + template <typename Q> Cone(const Q* p) + : Solid_type<TGeoCone>(p) { + } /// Constructor to be used when passing an already created object template <typename Q> Cone(const Handle<Q>& e) @@ -324,7 +346,13 @@ namespace DD4hep { private: /// Internal helper method to support object construction void make(double pz, double py, double px, double pLTX); + public: + /// Constructor to be used with an existing object + template <typename Q> Trap(const Q* p) + : Solid_type<TGeoTrap>(p) { + } + /// Constructor to be used when passing an already created object Trap(const Trap& e) : Solid_type<TGeoTrap>(e) { @@ -364,21 +392,31 @@ namespace DD4hep { private: /// Internal helper method to support object construction void make(double x1, double x2, double y1, double y2, double z); + public: + /// Constructor to be used with an existing object + template <typename Q> Trapezoid(const Q* p) + : Solid_type<TGeoTrd2>(p) { + } + /// Constructor to be used when passing an already created object Trapezoid(const Trapezoid& e) : Solid_type<TGeoTrd2>(e) { } + /// Constructor to be used when passing an already created object template <typename Q> Trapezoid(const Handle<Q>& e) : Solid_type<TGeoTrd2>(e) { } + /// Constructor to create a new anonymous object with attribute initialization Trapezoid(double x1, double x2, double y1, double y2, double z); + /// Constructor to create a new anonymous object with attribute initialization template <typename X1,typename X2,typename Y1,typename Y2,typename Z> Trapezoid(X1 x1, X2 x2, Y1 y1, Y2 y2, Z z) { make(_toDouble(x1),_toDouble(x2),_toDouble(y1),_toDouble(y2),_toDouble(z)); } + /// Set the Trapezoid dimensions Trapezoid& setDimensions(double x1, double x2, double y1, double y2, double z); }; @@ -397,21 +435,30 @@ namespace DD4hep { /// Internal helper method to support object construction void make(double r, double rmin, double rmax, double phi, double delta_phi); public: + /// Constructor to be used with an existing object + template <typename Q> Torus(const Q* p) + : Solid_type<TGeoTorus>(p) { + } + /// Constructor to be used when passing an already created object Torus(const Torus& e) : Solid_type<TGeoTorus>(e) { } + /// Constructor to be used when passing an already created object template <typename Q> Torus(const Handle<Q>& e) : Solid_type<TGeoTorus>(e) { } + /// Constructor to create a new anonymous object with attribute initialization template<typename R, typename RMIN, typename RMAX, typename PHI, typename DELTA_PHI> Torus(R r, RMIN rmin, RMAX rmax, PHI phi=M_PI, DELTA_PHI delta_phi = 2.*M_PI) { make(_toDouble(r),_toDouble(rmin),_toDouble(rmax),_toDouble(phi),_toDouble(delta_phi)); } + /// Constructor to create a new anonymous object with attribute initialization Torus(double r, double rmin, double rmax, double phi=M_PI, double delta_phi = 2.*M_PI) { make(r,rmin,rmax,phi,delta_phi); } + /// Set the Torus dimensions Torus& setDimensions(double r, double rmin, double rmax, double phi, double delta_phi); }; @@ -428,17 +475,25 @@ namespace DD4hep { */ class Sphere: public Solid_type<TGeoSphere> { public: + /// Constructor to be used with an existing object + template <typename Q> Sphere(const Q* p) + : Solid_type<TGeoSphere>(p) { + } + /// Constructor to be used when passing an already created object Sphere(const Sphere& e) : Solid_type<TGeoSphere>(e) { } + /// Constructor to be used when passing an already created object template <typename Q> Sphere(const Handle<Q>& e) : Solid_type<TGeoSphere>(e) { } + /// Constructor to create a new anonymous object with attribute initialization Sphere(double rmin, double rmax, double theta = 0., double delta_theta = M_PI, double phi = 0.0, double delta_phi = 2. * M_PI); + /// Set the Sphere dimensions Sphere& setDimensions(double rmin, double rmax, double theta, double delta_theta, double phi, double delta_phi); }; @@ -453,17 +508,26 @@ namespace DD4hep { * \version 1.0 * \ingroup DD4HEP_GEOMETRY */ - struct Paraboloid: public Solid_type<TGeoParaboloid> { + class Paraboloid: public Solid_type<TGeoParaboloid> { + public: + /// Constructor to be used with an existing object + template <typename Q> Paraboloid(const Q* p) + : Solid_type<TGeoParaboloid>(p) { + } + /// Constructor to be used when passing an already created object Paraboloid(const Paraboloid& e) : Solid_type<TGeoParaboloid>(e) { } + /// Constructor to be used when passing an already created object template <typename Q> Paraboloid(const Handle<Q>& e) : Solid_type<TGeoParaboloid>(e) { } + /// Constructor to create a new anonymous object with attribute initialization Paraboloid(double r_low, double r_high, double delta_z); + /// Set the Paraboloid dimensions Paraboloid& setDimensions(double r_low, double r_high, double delta_z); }; @@ -483,10 +547,16 @@ namespace DD4hep { void _create(const std::string& name, int nsides, double rmin, double rmax, double zpos, double zneg, double start, double delta); public: + /// Constructor to be used with an existing object + template <typename Q> PolyhedraRegular(const Q* p) + : Solid_type<TGeoPgon>(p) { + } + /// Constructor to be used when passing an already created object PolyhedraRegular(const PolyhedraRegular& e) : Solid_type<TGeoPgon>(e) { } + /// Constructor to be used when passing an already created object template <typename Q> PolyhedraRegular(const Handle<Q>& e) @@ -514,15 +584,23 @@ namespace DD4hep { private: /// Internal helper method to support object construction void make(double dz, const double* vtx); + public: + /// Constructor to be used with an existing object + template <typename Q> EightPointSolid(const Q* p) + : Solid_type<TGeoArb8>(p) { + } + /// Constructor to be used when passing an already created object EightPointSolid(const EightPointSolid& e) : Solid_type<TGeoArb8>(e) { } + /// Constructor to be used when passing an already created object template <typename Q> EightPointSolid(const Handle<Q>& e) : Solid_type<TGeoArb8>(e) { } + /// Constructor to create a new anonymous object with attribute initialization EightPointSolid(double dz, const double* vertices) { make(dz,vertices); } }; diff --git a/DDCore/include/DD4hep/SurfaceInstaller.h b/DDCore/include/DD4hep/SurfaceInstaller.h new file mode 100644 index 0000000000000000000000000000000000000000..b0af1ddcc8ccc115be3da19f1250a50c1140bea2 --- /dev/null +++ b/DDCore/include/DD4hep/SurfaceInstaller.h @@ -0,0 +1,179 @@ +// $Id: SiTrackerBarrel_geo.cpp 1360 2014-10-27 16:32:06Z Nikiforos.Nikiforou@cern.ch $ +//==================================================================== +// AIDA Detector description implementation for LCD +//-------------------------------------------------------------------- +// +// Author : M.Frank +// +//==================================================================== +#ifndef DD4HEP_DDREC_SURFACEINSTALLER_H +#define DD4HEP_DDREC_SURFACEINSTALLER_H 1 + +// Framework include files +#include "DD4hep/LCDD.h" +#include "DD4hep/DetectorTools.h" +#include "DD4hep/DetFactoryHelper.h" + +// C/C++ include files +#include <map> +#include <algorithm> + +/// Namespace for the tracking surfaces of the AIDA detector description toolkit +namespace DDSurfaces { + /// Class describing the surface types + class SurfaceType; +} + +/// Namespace for the AIDA detector description toolkit +namespace DD4hep { + + /// Namespace for the reconstruction part of the AIDA detector description toolkit + namespace DDRec { + /// Class describing surface data + class SurfaceData; + } + + /** Base class to implement surface installers for known detector patterns + * + * The class scans the geometry of a subdetector and gives callbacks + * to user classes, which then should install in the proper callback + * routines the surface instances to the detector elements. + * + * \author M.Frank + * \version 1.0 + * \ingroup DD4HEP + */ + class SurfaceInstaller { + protected: + typedef Geometry::LCDD LCDD; + typedef Geometry::DetElement DetElement; + typedef Geometry::Volume Volume; + typedef Geometry::PlacedVolume PlacedVolume; + typedef Geometry::DetectorTools::ElementPath ElementPath; + typedef Geometry::DetectorTools::PlacementPath PlacementPath; + typedef DDRec::SurfaceData SurfaceData; + typedef DDSurfaces::SurfaceType SurfaceType; + + typedef std::map<TGeoVolume*, SurfaceData* > Surfaces; + /// Reference to the LCDD instance + LCDD& m_lcdd; + /// Reference to the detector element of the subdetector + DetElement m_det; + /// Map of surface instances keyed by the logical volume + Surfaces m_surfaces; + + /// Scan through tree of detector elements + void scan(DetElement de); + + public: + /// Initializing constructor + SurfaceInstaller(LCDD& lcdd, const std::string& det_name); + /// Default destructor + virtual ~SurfaceInstaller() {} + /// Indicate error message and throw exception + void invalidInstaller(const std::string& msg) const; + /// Scan through tree of detector elements + void scan(); + /// Install volume information. Default implementation only prints! + virtual void install(DetElement e, PlacedVolume pv); + /// Executor + template <typename T> static long run(LCDD& lcdd,int argc,char** argv); + }; + + /// Action routine to execute the test + template <typename T> inline long SurfaceInstaller::run(Geometry::LCDD& lcdd,int argc,char** argv) + { + for(; argc>0; --argc) { + std::string name = argv[argc-1]; + T installer(lcdd,name); + installer.scan(); + } + return 1; + } + +#define DECLARE_SURFACE_INSTALLER(name,class) \ + namespace DD4hep { \ + template long SurfaceInstaller::run< class >(Geometry::LCDD& lcdd,int argc,char** argv); \ + } \ + DECLARE_APPLY(name,SurfaceInstaller::run< class >) + +} // End namespace DD4hep + + +#ifdef DD4HEP_USE_SURFACEINSTALL_HELPER + +#include "DDRec/Surface.h" +#include "DDRec/DetectorData.h" + +/** If you want to save yourself some typing when creating surface installers, + * set the compile macro DD4HEP_USE_SURFACEINSTALL_HELPER LOCALLY ! + * This will then enable the code below and the only thing you will have to + * type is the installer member function to create a measurement surface for + * a given volume. + * + * \author M.Frank + * \version 1.0 + * \ingroup DD4HEP + */ +namespace { + + /** Install class template to create surface installer plugins + * + * See the base class SurfaceInstaller for further details. + * + * \author M.Frank + * \version 1.0 + * \ingroup DD4HEP + */ + class Installer : public DD4hep::SurfaceInstaller { + public: + typedef DD4hep::DDRec::Vector3D Vector3D; + typedef DD4hep::DDRec::VolSurface VolSurface; + typedef DD4hep::DDRec::VolPlane VolPlane; + typedef DDSurfaces::SurfaceType Type; + public: + /// Initializing constructor + Installer(LCDD& lcdd, const std::string& nam) : DD4hep::SurfaceInstaller(lcdd, nam) {} + /// Default destructor + virtual ~Installer() {} + /// Install volume information. Default implementation only prints! + virtual void install(DetElement component, PlacedVolume pv); + /// Try to handle surface using the surface cache + bool handleUsingCache(DetElement comp, Volume vol) const { + Surfaces::const_iterator is = m_surfaces.find(vol.ptr()); + if ( is != m_surfaces.end() ) { + VolSurface surf((*is).second); + DD4hep::DDRec::volSurfaceList(comp)->push_back(surf); + return true; + } + return false; + } + Volume parentVolume(DetElement component) const { + DetElement module = component.parent(); + if ( module.isValid() ) { + return module.placement().volume(); + } + return Volume(); + } + const double* placementTranslation(DetElement component) const { + TGeoMatrix* mat = component.placement()->GetMatrix(); + const double* trans = mat->GetTranslation(); + return trans; + } + void addSurface(DetElement component, const DD4hep::DDRec::VolSurface& surf) { + m_surfaces.insert(std::make_pair(surf.volume().ptr(),surf.ptr())); + DD4hep::DDRec::volSurfaceList(component)->push_back(surf); + } + template <typename T> bool checkShape(const T& shape) const { + if ( shape.isValid() ) return true; + invalidInstaller("Shape is not of the required type:"+DD4hep::typeName(typeid(T))); + return false; + } + }; +} + +DECLARE_SURFACE_INSTALLER(DD4HEP_USE_SURFACEINSTALL_HELPER,Installer) + +#endif /* DD4HEP_USE_SURFACEINSTALL_HELPER */ + +#endif /* DD4HEP_DDREC_SURFACEINSTALLER_H */ diff --git a/DDCore/include/XML/UnicodeValues.h b/DDCore/include/XML/UnicodeValues.h index 372159baed4b30bc03639a85235130c863834680..1ba1fa22a90f382cc358071c1df7a8fb7ef91b39 100644 --- a/DDCore/include/XML/UnicodeValues.h +++ b/DDCore/include/XML/UnicodeValues.h @@ -33,6 +33,8 @@ namespace DD4hep { UNICODE (alpha3); UNICODE (alpha4); UNICODE (arb8); + UNICODE (arg); + UNICODE (argument); UNICODE (assembly); UNICODE (atom); UNICODE (attributes); @@ -264,6 +266,8 @@ namespace DD4hep { UNICODE (phi_size_max); UNICODE (physvol); UNICODE (physvolid); + UNICODE (plugin); + UNICODE (plugins); UNICODE (polyhedra); UNICODE (polycone); UNICODE (position); diff --git a/DDCore/include/XML/XMLElements.h b/DDCore/include/XML/XMLElements.h index d922a7584f67d6f40efa66e4a24248dfc2b437e5..3ac19a1da94f466eca44ac5ba074fe81f7fb58a4 100644 --- a/DDCore/include/XML/XMLElements.h +++ b/DDCore/include/XML/XMLElements.h @@ -109,6 +109,11 @@ namespace DD4hep { std::string _toString(float d, const char* fmt = "%f"); /// Format double procision float number (64 bits) to string with atrbitrary format \ingroup DD4HEP_XML std::string _toString(double d, const char* fmt = "%f"); + /// Format void pointer (64 bits) to string with atrbitrary format \ingroup DD4HEP_XML + std::string _ptrToString(const void* p, const char* fmt = "%p"); + /// Format void pointer (64 bits) to string with atrbitrary format \ingroup DD4HEP_XML + template <typename T> std::string _toString(const T* p, const char* fmt = "%p") + { return _ptrToString((void*)p,fmt); } /// Helper function to populate the evaluator dictionary \ingroup DD4HEP_XML void _toDictionary(const XmlChar* name, const XmlChar* value); diff --git a/DDCore/src/Handle.cpp b/DDCore/src/Handle.cpp index 9b331b1300c15feb0fc0ae29a1b826072fb76aba..1fc3ea21ae0af93a81c57109a22e60170e73b7ca 100644 --- a/DDCore/src/Handle.cpp +++ b/DDCore/src/Handle.cpp @@ -122,29 +122,32 @@ void DD4hep::Geometry::_toDictionary(const string& name, const string& value) { eval.setVariable(n.c_str(), result); } -string DD4hep::Geometry::_toString(bool value) { - char text[32]; - ::snprintf(text, sizeof(text), "%s", value ? "true" : "false"); +template <typename T> static inline string __to_string(T value, const char* fmt) { + char text[128]; + ::snprintf(text, sizeof(text), fmt, value); return text; } -string DD4hep::Geometry::_toString(int value) { - char text[32]; - ::snprintf(text, sizeof(text), "%d", value); - return text; +string DD4hep::Geometry::_toString(bool value) { + return value ? "true" : "false"; } -string DD4hep::Geometry::_toString(float value) { - char text[32]; - ::snprintf(text, sizeof(text), "%f", value); - return text; +string DD4hep::Geometry::_toString(int value, const char* fmt) { + return __to_string(value, fmt); } -string DD4hep::Geometry::_toString(double value) { - char text[32]; - ::snprintf(text, sizeof(text), "%f", value); - return text; +string DD4hep::Geometry::_toString(float value, const char* fmt) { + return __to_string(value, fmt); } + +string DD4hep::Geometry::_toString(double value, const char* fmt) { + return __to_string(value, fmt); +} + +string DD4hep::Geometry::_ptrToString(const void* value, const char* fmt) { + return __to_string(value, fmt); +} + namespace DD4hep { namespace Geometry { static long s_numVerifies = 0; diff --git a/DDCore/src/LCDDImp.cpp b/DDCore/src/LCDDImp.cpp index 24f13ef5868055ecf53d1900c55f5ac9a6fb2153..4cbad73a5f30a86d4d4dc6ca055351e15b53feb5 100644 --- a/DDCore/src/LCDDImp.cpp +++ b/DDCore/src/LCDDImp.cpp @@ -229,6 +229,7 @@ namespace { } void patchShapes() { GeoHandler::Data& data = *m_data; + char text[32]; string nam; printout(INFO,"LCDD","+++ Patching names of anonymous shapes...."); for (GeoHandler::Data::const_reverse_iterator i = data.rbegin(); i != data.rend(); ++i) { @@ -238,20 +239,21 @@ namespace { TGeoVolume* v = n->GetVolume(); TGeoShape* s = v->GetShape(); const char* sn = s->GetName(); + ::snprintf(text,sizeof(text),"_shape_%p",(void*)s); if (0 == sn || 0 == ::strlen(sn)) { nam = v->GetName(); - nam += "_shape"; + nam += text; s->SetName(nam.c_str()); } else if (0 == ::strcmp(sn, s->IsA()->GetName())) { nam = v->GetName(); - nam += "_shape"; + nam += text; s->SetName(nam.c_str()); } else { nam = sn; if (nam.find("_shape") == string::npos) - nam += "_shape"; + nam += text; s->SetName(nam.c_str()); } if (s->IsA() == TGeoCompositeShape::Class()) { diff --git a/DDCore/src/SurfaceInstaller.cpp b/DDCore/src/SurfaceInstaller.cpp new file mode 100644 index 0000000000000000000000000000000000000000..e94670f1aaaae6ce3f2413d7ea8445830fe8d91d --- /dev/null +++ b/DDCore/src/SurfaceInstaller.cpp @@ -0,0 +1,102 @@ +// $Id: SiTrackerBarrel_geo.cpp 1360 2014-10-27 16:32:06Z Nikiforos.Nikiforou@cern.ch $ +//==================================================================== +// AIDA Detector description implementation for LCD +//-------------------------------------------------------------------- +// +// Author : M.Frank +// +//==================================================================== +#include "DD4hep/Printout.h" +#include "DD4hep/SurfaceInstaller.h" + +// C/C++ include files +#include <stdexcept> +#include "TClass.h" + +using namespace std; +using namespace DD4hep; +using namespace DD4hep::Geometry; + +typedef DetElement::Children _C; + +/// Initializing constructor +SurfaceInstaller::SurfaceInstaller(LCDD& lcdd, const std::string& det_name) + : m_lcdd(lcdd), m_det() +{ + string n = det_name[0] == '-' ? det_name.substr(1) : det_name; + m_det = lcdd.detector(n); + if ( !m_det.isValid() ) { + stringstream err; + err << "The subdetector " << det_name << " is not known to the geometry."; + printout(INFO,"SurfaceInstaller",err.str().c_str()); + throw runtime_error(err.str()); + } + printout(INFO,m_det.name(),"+++ Processing SurfaceInstaller for subdetector: '%s'",m_det.name()); +} + +/// Indicate error message and throw exception +void SurfaceInstaller::invalidInstaller(const std::string& msg) const { + const char* det = m_det.isValid() ? m_det.name() : "<UNKNOWN>"; + const char* typ = m_det.isValid() ? m_det.type().c_str() : "<UNKNOWN>"; + printout(FATAL,"SurfaceInstaller","+++ Surfaces for: %s",det); + printout(FATAL,"SurfaceInstaller","+++ %s.",msg.c_str()); + printout(FATAL,"SurfaceInstaller","+++ You sure you apply the correct plugin to generate"); + printout(FATAL,"SurfaceInstaller","+++ surfaces for a detector of type %s",typ); + throw std::runtime_error("+++ Failed to install Surfaces to detector "+string(det)); +} + +/// Printout volume information +void SurfaceInstaller::install(DetElement component, PlacedVolume pv) { + if ( pv.volume().isSensitive() ) { + stringstream log; + PlacementPath all_nodes; + ElementPath det_elts; + DetectorTools::elementPath(component,det_elts); + DetectorTools::placementPath(component,all_nodes); + string elt_path = DetectorTools::elementPath(det_elts); + string node_path = DetectorTools::placementPath(all_nodes); + + log << "Lookup " << " Detector[" << det_elts.size() << "]: " << elt_path; + printout(INFO,m_det.name(),log.str()); + log.str(""); + log << " " << " Places[" << all_nodes.size() << "]: " << node_path; + printout(INFO,m_det.name(),log.str()); + log.str(""); + log << " " << " Matrices[" << all_nodes.size() << "]: "; + log << pv->GetVolume()->GetShape()->IsA()->GetName() << " "; + for(PlacementPath::const_reverse_iterator i=all_nodes.rbegin(); i!=all_nodes.rend(); ++i) { + log << (void*)((*i)->GetMatrix()) << " "; + if ( i+1 == all_nodes.rend() ) log << "( -> " << (*i)->GetName() << ")"; + } + // Get the module element: + TClass* cl = pv->GetVolume()->GetShape()->IsA(); + printout(INFO,m_det.name(),log.str()); + log.str(""); + log << " " + << " Sensitive:" << (pv.volume().isSensitive() ? "YES" : "NO ") + << " Shape: " << cl->GetName(); + TGeoBBox* box = (TGeoBBox*)pv.volume()->GetShape(); + if ( cl == TGeoBBox::Class() ) { + log << " [" << (void*)box << "]" + << " x:" << box->GetDX() + << " y:" << box->GetDY() + << " z:" << box->GetDZ(); + } + } +} + +/// Scan through tree of volume placements +void SurfaceInstaller::scan(DetElement e) { + const _C& children = e.children(); + install(e,e.placement()); + for (_C::const_iterator i=children.begin(); i!=children.end(); ++i) + scan((*i).second); +} + +/// Scan through tree of volume placements +void SurfaceInstaller::scan() { + scan(m_det); +} + +typedef DD4hep::SurfaceInstaller TestSurfacesPlugin; +DECLARE_SURFACE_INSTALLER(TestSurfaces,TestSurfacesPlugin) diff --git a/DDCore/src/XML/XMLElements.cpp b/DDCore/src/XML/XMLElements.cpp index 441d1485372e13313ca56ebb0ea13d464f3e51e0..681d3ba3b0e8493a9ac53596f1fef757bec8023f 100644 --- a/DDCore/src/XML/XMLElements.cpp +++ b/DDCore/src/XML/XMLElements.cpp @@ -229,6 +229,11 @@ string DD4hep::XML::_toString(double v, const char* fmt) { return __to_string(v, fmt); } +/// Format pointer to string with atrbitrary format +string DD4hep::XML::_ptrToString(const void* v, const char* fmt) { + return __to_string(v, fmt); +} + int DD4hep::XML::_toInt(const XmlChar* value) { if (value) { string s = _toString(value); diff --git a/DDCore/src/plugins/Compact2Objects.cpp b/DDCore/src/plugins/Compact2Objects.cpp index 009f81a9e129392b58bc5348f0e9458be7350203..86e467395c79c82f33e035130d5f94e66697aa5b 100644 --- a/DDCore/src/plugins/Compact2Objects.cpp +++ b/DDCore/src/plugins/Compact2Objects.cpp @@ -35,6 +35,7 @@ using namespace DD4hep::Geometry; namespace DD4hep { namespace Geometry { + struct Plugin; struct Compact; struct Includes; struct GdmlFile; @@ -43,6 +44,7 @@ namespace DD4hep { struct AlignmentFile; struct DetElementInclude {}; } + template <> void Converter<Plugin>::operator()(xml_h e) const; template <> void Converter<Constant>::operator()(xml_h e) const; template <> void Converter<Material>::operator()(xml_h e) const; template <> void Converter<Atom>::operator()(xml_h e) const; @@ -217,6 +219,28 @@ static long create_Compact(lcdd_t& lcdd, xml_h element) { } DECLARE_XML_DOC_READER(lccdd,create_Compact) +/** Convert/execute plugin objects from the xml (plugins) + * + * + */ +template <> void Converter<Plugin>::operator()(xml_h e) const { + xml_comp_t plugin(e); + vector<char*> argv; + vector<string> arguments; + string name = plugin.nameStr(); + for (xml_coll_t coll(e, _U(arg)); coll; ++coll) { + string val = coll.attr<string>(_U(value)); + arguments.push_back(val); + } + for (xml_coll_t coll(e, _U(argument)); coll; ++coll) { + string val = coll.attr<string>(_U(value)); + arguments.push_back(val); + } + for(std::vector<string>::iterator i=arguments.begin(); i!=arguments.end(); ++i) + argv.push_back(&((*i)[0])); + lcdd.apply(name.c_str(),int(argv.size()), &argv[0]); +} + /** Convert compact constant objects (defines) * * @@ -228,7 +252,6 @@ template <> void Converter<Constant>::operator()(xml_h e) const { _toDictionary(obj->GetName(), obj->GetTitle()); lcdd.addConstant(cons); } - /** Convert compact constant objects (defines) * * @@ -870,6 +893,7 @@ template <> void Converter<Compact>::operator()(xml_h element) const { xml_coll_t(compact, _U(alignments)).for_each(_U(alignment), Converter < AlignmentEntry > (lcdd)); xml_coll_t(compact, _U(fields)).for_each(_U(field), Converter < CartesianField > (lcdd)); xml_coll_t(compact, _U(sensitive_detectors)).for_each(_U(sd), Converter < SensitiveDetector > (lcdd)); + xml_coll_t(compact, _U(plugins)).for_each(_U(plugin), Converter < Plugin > (lcdd)); ::snprintf(text, sizeof(text), "%u", xml_h(element).checksum(0)); lcdd.addConstant(Constant("compact_checksum", text)); if ( --num_calls == 0 ) { diff --git a/DDCore/src/plugins/GeometryWalk.cpp b/DDCore/src/plugins/GeometryWalk.cpp index fc314ec2477b23910410d79775051236c39502bc..2db01ff64df802e72a8859e41bf0ce4692e79bbb 100644 --- a/DDCore/src/plugins/GeometryWalk.cpp +++ b/DDCore/src/plugins/GeometryWalk.cpp @@ -57,7 +57,6 @@ namespace { void print(DetElement e, PlacedVolume pv, const VolIDs& child_ids) const; /// Action routine to execute the test static long run(LCDD& lcdd,int argc,char** argv); - void dumpPathes(DetElement e, PlacedVolume pv) const; }; } @@ -130,6 +129,7 @@ long GeometryWalk::run(LCDD& lcdd,int argc,char** argv) { return 1; } + namespace DD4hep { namespace Geometry { using ::GeometryWalk; diff --git a/DDCore/src/plugins/LCDDConverter.cpp b/DDCore/src/plugins/LCDDConverter.cpp index e511dc7ced3a23bec0a09c931aa3bccbb4a9f1ce..6bf092795019499c0acd8b9c8c221fd0def0bd68 100644 --- a/DDCore/src/plugins/LCDDConverter.cpp +++ b/DDCore/src/plugins/LCDDConverter.cpp @@ -600,18 +600,18 @@ xml_h LCDDConverter::handleRotation(const std::string& name, const TGeoMatrix* t } /// Dump logical volume in GDML format to output stream -xml_h LCDDConverter::handleVolume(const string& name, Volume volume) const { +xml_h LCDDConverter::handleVolume(const string& /* name */, Volume volume) const { GeometryInfo& geo = data(); xml_h vol = geo.xmlVolumes[volume]; if (!vol) { const TGeoVolume* v = volume; Volume _v = Ref_t(v); - string n = v->GetName(); + string n = v->GetName()+_toString(v,"_%p"); TGeoMedium* m = v->GetMedium(); TGeoShape* s = v->GetShape(); xml_ref_t sol = handleSolid(s->GetName(), s); - geo.checkVolume(name, volume); + geo.checkVolume(n, volume); if (v->IsAssembly()) { vol = xml_elt_t(geo.doc, _U(assembly)); vol.setAttr(_U(name), n); @@ -707,10 +707,11 @@ void LCDDConverter::collectVolume(const string& /* name */, const TGeoVolume* vo } } -void LCDDConverter::checkVolumes(const string& name, Volume v) const { - NameSet::const_iterator i = m_checkNames.find(name); +void LCDDConverter::checkVolumes(const string& /* name */, Volume v) const { + string n = v.name()+_toString(v.ptr(),"_%p"); + NameSet::const_iterator i = m_checkNames.find(n); if (i != m_checkNames.end()) { - cout << "checkVolumes: Volume " << name << " "; + cout << "checkVolumes: Volume " << n << " "; if (is_volume(v.ptr())) { SensitiveDetector s = v.sensitiveDetector(); VisAttr vis = v.visAttributes(); @@ -724,7 +725,7 @@ void LCDDConverter::checkVolumes(const string& name, Volume v) const { cout << "has duplicate entries." << endl; return; } - m_checkNames.insert(name); + m_checkNames.insert(n); } /// Dump volume placement in GDML format to output stream diff --git a/DDDetectors/CMakeLists.txt b/DDDetectors/CMakeLists.txt index 7fb544c08072f309887b09a79345b652b74cdf69..4b0b7a4e76d1d3ba4c93881e2b09feed0c3d21c7 100644 --- a/DDDetectors/CMakeLists.txt +++ b/DDDetectors/CMakeLists.txt @@ -12,6 +12,7 @@ find_package( ROOT REQUIRED COMPONENTS Geom Reflex ) #---Includedirs--------------------------------------------------------------------- include_directories(${CMAKE_SOURCE_DIR}/DDCore/include ${CMAKE_SOURCE_DIR}/DDRec/include + ${CMAKE_SOURCE_DIR}/DDSurfaces/include ${CMAKE_SOURCE_DIR}/DDSegmentation/include ${ROOT_INCLUDE_DIR} ) # diff --git a/DDDetectors/compact/SiD/SiD_Tracker.xml b/DDDetectors/compact/SiD/SiD_Tracker.xml index 00d6b2becc1b479b90e0de5643042a768e8968c7..9b828cbd1243c05910c9aa7e9785f19819d5fe84 100644 --- a/DDDetectors/compact/SiD/SiD_Tracker.xml +++ b/DDDetectors/compact/SiD/SiD_Tracker.xml @@ -43,9 +43,10 @@ </readouts> <!-- Includes for sensitives and support --> +<!-- <include ref="SiD_TrackerEndcap.xml"/> <include ref="SiD_TrackerBarrel.xml"/> <include ref="SiD_TrackerForward.xml"/> <include ref="SiD_TrackerSupport.xml"/> - +--> </lccdd> diff --git a/DDDetectors/src/SiTrackerBarrel_geo.cpp b/DDDetectors/src/SiTrackerBarrel_geo.cpp index 4a64bdab60fe81f2a20b70ded1e50db437f3eb89..dceead3356f4eb7f0b8deae33c2c9d3fb953fa2f 100644 --- a/DDDetectors/src/SiTrackerBarrel_geo.cpp +++ b/DDDetectors/src/SiTrackerBarrel_geo.cpp @@ -14,13 +14,15 @@ using namespace DD4hep; using namespace DD4hep::Geometry; static Ref_t create_detector(LCDD& lcdd, xml_h e, SensitiveDetector sens) { + typedef vector<PlacedVolume> Placements; xml_det_t x_det = e; Material air = lcdd.air(); int det_id = x_det.id(); string det_name = x_det.nameStr(); DetElement sdet (det_name,det_id); - Assembly assembly (det_name+"_assembly"); + Assembly assembly (det_name); map<string, Volume> volumes; + map<string, Placements> sensitives; PlacedVolume pv; sens.setType("tracker"); @@ -28,7 +30,7 @@ static Ref_t create_detector(LCDD& lcdd, xml_h e, SensitiveDetector sens) { xml_comp_t x_mod = mi; xml_comp_t m_env = x_mod.child(_U(module_envelope)); string m_nam = x_mod.nameStr(); - Volume m_vol(det_name+"_"+m_nam,Box(m_env.width()/2,m_env.length()/2,m_env.thickness()/2),air); + Volume m_vol(m_nam,Box(m_env.width()/2,m_env.length()/2,m_env.thickness()/2),air); int ncomponents = 0, sensor_number = 1; if ( volumes.find(m_nam) != volumes.end() ) { @@ -36,37 +38,38 @@ static Ref_t create_detector(LCDD& lcdd, xml_h e, SensitiveDetector sens) { throw runtime_error("Logics error in building modules."); } volumes[m_nam] = m_vol; + m_vol.setVisAttributes(lcdd.visAttributes(x_mod.visStr())); for(xml_coll_t ci(x_mod,_U(module_component)); ci; ++ci, ++ncomponents) { xml_comp_t x_comp = ci; xml_comp_t x_pos = x_comp.position(false); - xml_comp_t x_rot = x_comp.rotation(false); - string c_nam = det_name+"_"+m_nam+_toString(ncomponents,"_component%d"); + xml_comp_t x_rot = x_comp.rotation(false); + string c_nam = _toString(ncomponents,"component%d"); Box c_box(x_comp.width()/2,x_comp.length()/2,x_comp.thickness()/2); Volume c_vol(c_nam,c_box,lcdd.material(x_comp.materialStr())); if ( x_pos && x_rot ) { - Position c_pos(x_pos.x(0),x_pos.y(0),x_pos.z(0)); - RotationZYX c_rot(x_rot.z(0),x_rot.y(0),x_rot.x(0)); - pv = m_vol.placeVolume(c_vol, Transform3D(c_rot,c_pos)); + Position c_pos(x_pos.x(0),x_pos.y(0),x_pos.z(0)); + RotationZYX c_rot(x_rot.z(0),x_rot.y(0),x_rot.x(0)); + pv = m_vol.placeVolume(c_vol, Transform3D(c_rot,c_pos)); } else if ( x_rot ) { - pv = m_vol.placeVolume(c_vol,RotationZYX(x_rot.z(0),x_rot.y(0),x_rot.x(0))); + pv = m_vol.placeVolume(c_vol,RotationZYX(x_rot.z(0),x_rot.y(0),x_rot.x(0))); } else if ( x_pos ) { - pv = m_vol.placeVolume(c_vol,Position(x_pos.x(0),x_pos.y(0),x_pos.z(0))); + pv = m_vol.placeVolume(c_vol,Position(x_pos.x(0),x_pos.y(0),x_pos.z(0))); } else { - pv = m_vol.placeVolume(c_vol); + pv = m_vol.placeVolume(c_vol); } c_vol.setRegion(lcdd, x_comp.regionStr()); c_vol.setLimitSet(lcdd, x_comp.limitsStr()); c_vol.setVisAttributes(lcdd, x_comp.visStr()); if ( x_comp.isSensitive() ) { - pv.addPhysVolID(_U(sensor),sensor_number++); - c_vol.setSensitiveDetector(sens); + pv.addPhysVolID(_U(sensor),sensor_number++); + c_vol.setSensitiveDetector(sens); + sensitives[m_nam].push_back(pv); } } - m_vol.setVisAttributes(lcdd.visAttributes(x_mod.visStr())); } for(xml_coll_t li(x_det,_U(layer)); li; ++li) { xml_comp_t x_layer = li; @@ -75,8 +78,7 @@ static Ref_t create_detector(LCDD& lcdd, xml_h e, SensitiveDetector sens) { xml_comp_t z_layout = x_layer.child(_U(z_layout)); // Get the <z_layout> element. int lay_id = x_layer.id(); string m_nam = x_layer.moduleStr(); - Volume m_env = volumes[m_nam]; - string lay_nam = det_name+"_"+m_nam+_toString(x_layer.id(),"_layer%d"); + string lay_nam = _toString(x_layer.id(),"layer%d"); Tube lay_tub (x_barrel.inner_r(),x_barrel.outer_r(),x_barrel.z_length()/2); Volume lay_vol (lay_nam,lay_tub,air); // Create the layer envelope volume. double phi0 = x_layout.phi0(); // Starting phi of first module. @@ -89,6 +91,9 @@ static Ref_t create_detector(LCDD& lcdd, xml_h e, SensitiveDetector sens) { double z0 = z_layout.z0(); // Z position of first module in phi. double nz = z_layout.nz(); // Number of modules to place in z. double z_dr = z_layout.dr(); // Radial displacement parameter, of every other module. + Volume m_env = volumes[m_nam]; + DetElement lay_elt(sdet,_toString(x_layer.id(),"layer%d"),lay_id); + Placements& sensVols = sensitives[m_nam]; // Z increment for module placement along Z axis. // Adjust for z0 at center of module rather than @@ -99,28 +104,40 @@ static Ref_t create_detector(LCDD& lcdd, xml_h e, SensitiveDetector sens) { int module = 1; // Loop over the number of modules in phi. - for (int ii = 0; ii < nphi; ii++) { - double dx = z_dr * std::cos(phic + phi_tilt); // Delta x of module position. - double dy = z_dr * std::sin(phic + phi_tilt); // Delta y of module position. - double x = rc * std::cos(phic); // Basic x module position. - double y = rc * std::sin(phic); // Basic y module position. - + for (int ii = 0; ii < nphi; ii++) { + double dx = z_dr * std::cos(phic + phi_tilt); // Delta x of module position. + double dy = z_dr * std::sin(phic + phi_tilt); // Delta y of module position. + double x = rc * std::cos(phic); // Basic x module position. + double y = rc * std::sin(phic); // Basic y module position. + // Loop over the number of modules in z. - for (int j = 0; j < nz; j++) { - // Module PhysicalVolume. - // Transform3D tr(RotationZYX(0,-((M_PI/2)-phic-phi_tilt),M_PI/2),Position(x,y,module_z)); - //NOTE (Nikiforos, 26/08 Rotations needed to be fixed so that component1 (silicon) is on the outside - Transform3D tr(RotationZYX(0,((M_PI/2)-phic-phi_tilt),-M_PI/2),Position(x,y,module_z)); - pv = lay_vol.placeVolume(m_env,tr); - pv.addPhysVolID("module", module++); - // Adjust the x and y coordinates of the module. - x += dx; - y += dy; - // Flip sign of x and y adjustments. - dx *= -1; - dy *= -1; - // Add z increment to get next z placement pos. - module_z += z_incr; + for (int j = 0; j < nz; j++) { + string module_name = _toString(module,"module%d"); + DetElement mod_elt(lay_elt,module_name,module); + // Module PhysicalVolume. + // Transform3D tr(RotationZYX(0,-((M_PI/2)-phic-phi_tilt),M_PI/2),Position(x,y,module_z)); + //NOTE (Nikiforos, 26/08 Rotations needed to be fixed so that component1 (silicon) is on the outside + Transform3D tr(RotationZYX(0,((M_PI/2)-phic-phi_tilt),-M_PI/2),Position(x,y,module_z)); + + pv = lay_vol.placeVolume(m_env,tr); + pv.addPhysVolID("module", module); + mod_elt.setPlacement(pv); + for(size_t ic=0; ic<sensVols.size(); ++ic) { + PlacedVolume sens_pv = sensVols[ic]; + DetElement comp_elt(mod_elt,sens_pv.volume().name(),module); + comp_elt.setPlacement(sens_pv); + } + + /// Increase counters etc. + module++; + // Adjust the x and y coordinates of the module. + x += dx; + y += dy; + // Flip sign of x and y adjustments. + dx *= -1; + dy *= -1; + // Add z increment to get next z placement pos. + module_z += z_incr; } phic += phi_incr; // Increment the phi placement of module. rc += rphi_dr; // Increment the center radius according to dr parameter. @@ -128,14 +145,13 @@ static Ref_t create_detector(LCDD& lcdd, xml_h e, SensitiveDetector sens) { module_z = -z0; // Reset the Z placement parameter for module. } // Create the PhysicalVolume for the layer. - assembly.setVisAttributes(lcdd.invisible()); pv = assembly.placeVolume(lay_vol); // Place layer in mother pv.addPhysVolID("layer", lay_id); // Set the layer ID. - DetElement m_elt(sdet,lay_nam,lay_id); - m_elt.setAttributes(lcdd,lay_vol,x_layer.regionStr(),x_layer.limitsStr(),x_layer.visStr()); - m_elt.setPlacement(pv); + lay_elt.setAttributes(lcdd,lay_vol,x_layer.regionStr(),x_layer.limitsStr(),x_layer.visStr()); + lay_elt.setPlacement(pv); } sdet.setAttributes(lcdd,assembly,x_det.regionStr(),x_det.limitsStr(),x_det.visStr()); + assembly.setVisAttributes(lcdd.invisible()); pv = lcdd.pickMotherVolume(sdet).placeVolume(assembly); pv.addPhysVolID("system", det_id); // Set the subdetector system ID. pv.addPhysVolID("barrel", 0); // Flag this as a barrel subdetector. diff --git a/DDDetectors/src/SiTrackerBarrel_surfaces.cpp b/DDDetectors/src/SiTrackerBarrel_surfaces.cpp new file mode 100644 index 0000000000000000000000000000000000000000..6d88ea2296774585cf257c233fcf545ea1e97684 --- /dev/null +++ b/DDDetectors/src/SiTrackerBarrel_surfaces.cpp @@ -0,0 +1,36 @@ +// $Id: SiTrackerBarrel_geo.cpp 1360 2014-10-27 16:32:06Z Nikiforos.Nikiforou@cern.ch $ +//==================================================================== +// AIDA Detector description implementation for LCD +//-------------------------------------------------------------------- +// +// Author : M.Frank +// +//==================================================================== +// Framework include files +#define DD4HEP_USE_SURFACEINSTALL_HELPER DD4hep_SiTrackerBarrel_Surfaces +#include "DD4hep/SurfaceInstaller.h" + +/// Install volume information. Default implementation only prints! +void Installer::install(DetElement component, PlacedVolume pv) { + Volume comp_vol = pv.volume(); + if ( comp_vol.isSensitive() ) { + Volume mod_vol = parentVolume(component); + DD4hep::Geometry::Box mod_shape(mod_vol.solid()), comp_shape(comp_vol.solid()); + + if ( !comp_shape.isValid() || !mod_shape.isValid() ) { + invalidInstaller("Components and/or modules are not boxes -- invalid shapes"); + } + else if ( !handleUsingCache(component,comp_vol) ) { + const double* trans = placementTranslation(component); + double half_module_thickness = mod_shape->GetDZ(); + double sensitive_z_position = trans[2]; + double outer_thickness = half_module_thickness + sensitive_z_position; + double inner_thickness = half_module_thickness - sensitive_z_position; + Vector3D u(1.,0.,0.), v(0.,1.,0.), n(0.,0.,1.), o(0.,0.,sensitive_z_position); + + VolPlane surf(comp_vol,Type(Type::Sensitive,Type::Measurement1D), + inner_thickness, outer_thickness, u, v, n, o); + addSurface(component,surf); + } + } +} diff --git a/DDDetectors/src/SiTrackerEndcap2_geo.cpp b/DDDetectors/src/SiTrackerEndcap2_geo.cpp index 4dbf5f38c9a02052f9407724da15c01c89cee4f6..68ced8f8251ca566105ce76992b3295b0e7efe85 100644 --- a/DDDetectors/src/SiTrackerEndcap2_geo.cpp +++ b/DDDetectors/src/SiTrackerEndcap2_geo.cpp @@ -15,17 +15,19 @@ using namespace DD4hep; using namespace DD4hep::Geometry; static Ref_t create_detector(LCDD& lcdd, xml_h e, SensitiveDetector sens) { + typedef vector<PlacedVolume> Placements; xml_det_t x_det = e; Material vacuum = lcdd.vacuum(); int det_id = x_det.id(); string det_name = x_det.nameStr(); bool reflect = x_det.reflect(false); DetElement sdet (det_name,det_id); - Assembly assembly (det_name+"_assembly"); - //Volume assembly (det_name+"_assembly",Box(10000,10000,10000),vacuum); + Assembly assembly (det_name); + //Volume assembly (det_name,Box(10000,10000,10000),vacuum); Volume motherVol = lcdd.pickMotherVolume(sdet); int m_id=0, c_id=0, n_sensor=0; map<string,Volume> modules; + map<string, Placements> sensitives; PlacedVolume pv; assembly.setVisAttributes(lcdd.invisible()); @@ -45,23 +47,23 @@ static Ref_t create_detector(LCDD& lcdd, xml_h e, SensitiveDetector sens) { total_thickness += xml_comp_t(ci).thickness(); y1 = y2 = total_thickness / 2; - Volume m_volume(det_name+"_"+m_nam, Trapezoid(x1, x2, y1, y2, z), vacuum); + Volume m_volume(m_nam, Trapezoid(x1, x2, y1, y2, z), vacuum); m_volume.setVisAttributes(lcdd.visAttributes(x_mod.visStr())); for(ci.reset(), n_sensor=1, c_id=0, posY=-y1; ci; ++ci, ++c_id) { xml_comp_t c = ci; double c_thick = c.thickness(); Material c_mat = lcdd.material(c.materialStr()); - string c_name = m_volume.name() + _toString(c_id,"_component%d"); + string c_name = _toString(c_id,"component%d"); Volume c_vol(c_name, Trapezoid(x1,x2,c_thick/2e0,c_thick/2e0,z), c_mat); c_vol.setVisAttributes(lcdd.visAttributes(c.visStr())); pv = m_volume.placeVolume(c_vol,Position(0,posY+c_thick/2,0)); - //pv.addPhysVolID("component",c_id); if ( c.isSensitive() ) { sdet.check(n_sensor > 2,"SiTrackerEndcap2::fromCompact: "+c_name+" Max of 2 modules allowed!"); pv.addPhysVolID("sensor",n_sensor); c_vol.setSensitiveDetector(sens); + sensitives[m_nam].push_back(pv); ++n_sensor; } posY += c_thick; @@ -84,6 +86,7 @@ static Ref_t create_detector(LCDD& lcdd, xml_h e, SensitiveDetector sens) { Volume m_vol = modules[m_nam]; double iphi = 2*M_PI/nmodules; double phi = phi0; + Placements& sensVols = sensitives[m_nam]; for(int k=0; k<nmodules; ++k) { string m_base = _toString(l_id,"layer%d") + _toString(mod_num,"_module%d"); @@ -93,11 +96,22 @@ static Ref_t create_detector(LCDD& lcdd, xml_h e, SensitiveDetector sens) { pv = assembly.placeVolume(m_vol,Transform3D(RotationZYX(0,-M_PI/2-phi,-M_PI/2),Position(x,y,zstart+dz))); pv.addPhysVolID("barrel",1).addPhysVolID("layer", l_id).addPhysVolID("module",mod_num); module.setPlacement(pv); + for(size_t ic=0; ic<sensVols.size(); ++ic) { + PlacedVolume sens_pv = sensVols[ic]; + DetElement comp_elt(module,sens_pv.volume().name(),mod_num); + comp_elt.setPlacement(sens_pv); + } + if ( reflect ) { pv = assembly.placeVolume(m_vol,Transform3D(RotationZYX(M_PI,-M_PI/2-phi,-M_PI/2),Position(x,y,-zstart-dz))); pv.addPhysVolID("barrel",2).addPhysVolID("layer",l_id).addPhysVolID("module",mod_num); DetElement r_module(sdet,m_base+"_neg",det_id); r_module.setPlacement(pv); + for(size_t ic=0; ic<sensVols.size(); ++ic) { + PlacedVolume sens_pv = sensVols[ic]; + DetElement comp_elt(r_module,sens_pv.volume().name(),mod_num); + comp_elt.setPlacement(sens_pv); + } } dz = -dz; phi += iphi; diff --git a/DDDetectors/src/SiTrackerEndcap_surfaces.cpp b/DDDetectors/src/SiTrackerEndcap_surfaces.cpp new file mode 100644 index 0000000000000000000000000000000000000000..297a54e5701df4b432333c9a026143a2f3791d1e --- /dev/null +++ b/DDDetectors/src/SiTrackerEndcap_surfaces.cpp @@ -0,0 +1,36 @@ +// $Id: $ +//==================================================================== +// AIDA Detector description implementation for LCD +//-------------------------------------------------------------------- +// +// Author : M.Frank +// +//==================================================================== +// Framework include files +#define DD4HEP_USE_SURFACEINSTALL_HELPER DD4hep_SiTrackerEndcap_Surfaces +#include "DD4hep/SurfaceInstaller.h" + +void Installer::install(DetElement component, PlacedVolume pv) { + Volume comp_vol = pv.volume(); + if ( comp_vol.isSensitive() ) { + Volume mod_vol = parentVolume(component); + DD4hep::Geometry::Trapezoid comp_shape(comp_vol.solid()), mod_shape(mod_vol.solid()); + + if ( !comp_shape.isValid() || !mod_shape.isValid() ) { + invalidInstaller("Components and/or modules are not Trapezoid -- invalid shapes"); + } + else if ( !handleUsingCache(component,comp_vol) ) { + const double* trans = placementTranslation(component); + double half_mod_thickness = mod_shape->GetDy1(); + double half_comp_thickness = comp_shape->GetDy1(); + double si_position = trans[1]; + double outer_thickness = half_mod_thickness + si_position; + double inner_thickness = half_mod_thickness - si_position; + Vector3D u(0.,0.,-1.), v(-1.,0.,0.), n(0.,-1.,0.), o(0.,0.,0.); + + VolPlane surf(comp_vol,Type(Type::Sensitive,Type::Measurement1D), + inner_thickness, outer_thickness, u, v, n, o); + addSurface(component,surf); + } + } +} diff --git a/DDG4/examples/CLICSidSimuMarkus.py b/DDG4/examples/CLICSidSimuMarkus.py index b5dea3f23e7c73090e7341fa7e0c38180bdca4ac..750bca4481ffec21cbff74a211ee6c29ffd630a0 100644 --- a/DDG4/examples/CLICSidSimuMarkus.py +++ b/DDG4/examples/CLICSidSimuMarkus.py @@ -18,7 +18,7 @@ def run(): lcdd = kernel.lcdd() install_dir = os.environ['DD4hepINSTALL'] example_dir = install_dir+'/examples/DDG4/examples'; - kernel.loadGeometry("file:"+install_dir+"/DDDetectors/compact/SiD.xml") + kernel.loadGeometry("file:"+install_dir+"/DDDetectors/compact/SiD_Markus.xml") kernel.loadXML("file:"+example_dir+"/DDG4_field.xml") DDG4.importConstants(lcdd,debug=False) simple = DDG4.Simple(kernel,tracker='Geant4TrackerCombineAction') @@ -43,7 +43,7 @@ def run(): # Configure I/O ##evt_lcio = simple.setupLCIOOutput('LcioOutput','CLICSiD_'+time.strftime('%Y-%m-%d_%H-%M')) ##evt_lcio.OutputLevel = generator_output_level - ##evt_root = simple.setupROOTOutput('RootOutput','CLICSiD_'+time.strftime('%Y-%m-%d_%H-%M')) + evt_root = simple.setupROOTOutput('RootOutput','CLICSiD_'+time.strftime('%Y-%m-%d_%H-%M')) gen = DDG4.GeneratorAction(kernel,"Geant4GeneratorActionInit/GenerationInit") gen.OutputLevel = generator_output_level @@ -111,7 +111,7 @@ def run(): kernel.generatorAction().adopt(rdr) """ - seq,act = simple.setupTracker('SiTrackerBarrel') + seq,act = simple.setupTracker('SiVertexBarrel') """ # First the tracking detectors seq,act = simple.setupTracker('SiVertexBarrel') diff --git a/DDG4/plugins/Geant4SDActions.cpp b/DDG4/plugins/Geant4SDActions.cpp index 7fed4852fca4a8fe9e53a1252f9fc669df732340..16434403c610e31f3257c5ad52593b2b411f99a6 100644 --- a/DDG4/plugins/Geant4SDActions.cpp +++ b/DDG4/plugins/Geant4SDActions.cpp @@ -66,7 +66,7 @@ namespace DD4hep { mark(h.track); if ( 0 == hit->cellID ) { hit->cellID = volumeID( step ) ; - throw runtime_error("Invalid CELL ID for hit!"); + except("+++ Invalid CELL ID for hit!"); } print("Geant4Tracker","%s> Hit with deposit:%f Pos:%f %f %f ID=%016X", c_name(),step->GetTotalEnergyDeposit(),position.X(),position.Y(),position.Z(), @@ -75,7 +75,8 @@ namespace DD4hep { print("Geant4Tracker","%s> Geant4 path:%s",c_name(),handler.path().c_str()); return true; } - throw runtime_error("new() failed: Cannot allocate hit object"); + except("new() failed: Cannot allocate hit object"); + return false; } typedef Geant4SensitiveAction<Geant4Tracker> Geant4TrackerAction; @@ -110,7 +111,7 @@ namespace DD4hep { c_name(),contrib.deposit,pos.X,pos.Y,pos.Z,handler.path().c_str()); if ( 0 == hit->cellID ) { // for debugging only! hit->cellID = cellID(step); - throw runtime_error("Invalid CELL ID for hit!"); + except("+++ Invalid CELL ID for hit!"); } } hit->truth.push_back(contrib); @@ -160,7 +161,7 @@ namespace DD4hep { coll->add(hit); if ( 0 == hit->cellID ) { hit->cellID = volumeID(step); - throw runtime_error("Invalid CELL ID for hit!"); + except("+++ Invalid CELL ID for hit!"); } } hit->energyDeposit += contrib.deposit; @@ -189,8 +190,9 @@ namespace DD4hep { double e_cut; int current; int combined; + long long int cell; - TrackerCombine() : pre(), post(), sensitive(0), e_cut(0.0), current(-1), combined(0) { + TrackerCombine() : pre(), post(), sensitive(0), e_cut(0.0), current(-1), combined(0), cell(0) { } /// Start a new hit @@ -201,12 +203,20 @@ namespace DD4hep { sensitive->mark(step->GetTrack()); post = pre; combined = 0; + cell = 0; } /// Update energy and track information during hit info accumulation void update(G4Step* step) { post.storePoint(step,step->GetPostStepPoint()); pre.truth.deposit += post.truth.deposit; + if ( 0 == cell ) { + cell = sensitive->cellID(step); + if ( 0 == cell ) { + cell = sensitive->volumeID(step) ; + sensitive->except("+++ Invalid CELL ID for hit!"); + } + } ++combined; } @@ -216,6 +226,7 @@ namespace DD4hep { pre.clear(); current = -1; combined = 0; + cell = 0; } bool mustSaveTrack(const G4Track* tr) const { @@ -236,7 +247,8 @@ namespace DD4hep { deposit,time); hit->position = pos; hit->momentum = mom; - hit->length = path_len; + hit->length = path_len; + hit->cellID = cell; collection->add(hit); sensitive->printM2("+++ TrackID:%6d [%s] CREATE hit combination with %2d deposit(s):" " %e MeV Pos:%8.2f %8.2f %8.2f", diff --git a/DDG4/src/Geant4ParticleGun.cpp b/DDG4/src/Geant4ParticleGun.cpp index 9a2f4893a6e521598490690bc6a7a5b9d1d4a8ce..f10ed36ab431b9e7a61a5d77307e537b82c07f72 100644 --- a/DDG4/src/Geant4ParticleGun.cpp +++ b/DDG4/src/Geant4ParticleGun.cpp @@ -91,6 +91,9 @@ void Geant4ParticleGun::operator()(G4Event* event) { inter->vertices.insert(make_pair(m_mask,vtx)); prim->add(m_mask, inter); + vtx->x = m_position.X(); + vtx->y = m_position.Y(); + vtx->z = m_position.Z(); for(int i=0; i<m_multiplicity; ++i) { Geant4ParticleHandle p = new Geant4Particle(i); p->reason = 0; @@ -100,12 +103,12 @@ void Geant4ParticleGun::operator()(G4Event* event) { p->psz = m_direction.Z()*m_energy; p->time = 0; p->properTime = 0; - p->vsx = m_position.X(); - p->vsy = m_position.Y(); - p->vsz = m_position.Z(); - p->vex = m_position.X(); - p->vey = m_position.Y(); - p->vez = m_position.Z(); + p->vsx = vtx->x; + p->vsy = vtx->y; + p->vsz = vtx->z; + p->vex = vtx->x; + p->vey = vtx->y; + p->vez = vtx->z; //p->definition = m_particle; //p->process = 0; p->spin[0] = 0;