From 28406391a25efe8e81cf4cf5bb62375dcbf79189 Mon Sep 17 00:00:00 2001 From: Markus Frank <markus.frank@cern.ch> Date: Thu, 9 Aug 2012 14:29:50 +0000 Subject: [PATCH] Support for user defined Segmentation objects --- DDCore/include/DD4hep/DetFactoryHelper.h | 1 + DDCore/include/DD4hep/Detector.h | 69 ++++-- DDCore/include/DD4hep/Factories.h | 26 +-- DDCore/include/DD4hep/GeoHandler.h | 27 +-- DDCore/include/DD4hep/Handle.h | 6 + DDCore/include/DD4hep/Objects.h | 109 +++++++-- DDCore/include/DD4hep/Readout.h | 2 +- DDCore/include/DD4hep/Segmentations.h | 76 +++++-- DDCore/include/DD4hep/Volumes.h | 1 + DDCore/include/XML/XMLElements.h | 55 +++-- DDCore/src/Detector.cpp | 113 ++++++---- DDCore/src/GeoHandler.cpp | 7 + DDCore/src/Handle.cpp | 16 ++ DDCore/src/LCDDImp.cpp | 102 +++++---- DDCore/src/Objects.cpp | 74 +++++-- DDCore/src/Readout.cpp | 2 +- DDCore/src/Segementations.cpp | 42 ++++ DDCore/src/Volumes.cpp | 21 +- DDCore/src/XML/DocumentHandler.cpp | 6 +- DDCore/src/XML/XMLDetector.cpp | 4 +- DDCore/src/XML/XMLElements.cpp | 4 + DDCore/src/compact/Compact2Objects.cpp | 269 +++++++++++++---------- 22 files changed, 676 insertions(+), 356 deletions(-) diff --git a/DDCore/include/DD4hep/DetFactoryHelper.h b/DDCore/include/DD4hep/DetFactoryHelper.h index c8b0c1469..b38dd17c4 100644 --- a/DDCore/include/DD4hep/DetFactoryHelper.h +++ b/DDCore/include/DD4hep/DetFactoryHelper.h @@ -18,6 +18,7 @@ #define _A(a) DD4hep::XML::Attr_##a // Shortcuts to elements of the XML namespace +typedef DD4hep::XML::Attribute xml_attr_t; typedef DD4hep::XML::Collection_t xml_coll_t; typedef DD4hep::XML::Handle_t xml_h; typedef DD4hep::XML::RefElement xml_ref_t; diff --git a/DDCore/include/DD4hep/Detector.h b/DDCore/include/DD4hep/Detector.h index 38bdb3688..dffeca72a 100644 --- a/DDCore/include/DD4hep/Detector.h +++ b/DDCore/include/DD4hep/Detector.h @@ -48,13 +48,12 @@ namespace DD4hep { struct Object { unsigned int magic; int verbose; - int combine_hits; + int combineHits; double ecut; - std::string eunit; - std::string hits_collection; + std::string hitsCollection; Readout readout; Extensions extensions; - Object() : magic(magic_word()), verbose(0), readout(), extensions() {} + Object() : magic(magic_word()), verbose(0), combineHits(0), ecut(0.0), hitsCollection(), readout(), extensions() {} }; protected: @@ -72,12 +71,15 @@ namespace DD4hep { /// Default constructor SensitiveDetector() : Ref_t() {} + /// Copy from handle + SensitiveDetector(const SensitiveDetector& sd) : Ref_t(sd) {} + /// Templated constructor for handle conversions template <typename Q> SensitiveDetector(const Handle<Q>& e) : Ref_t(e) {} /// Constructor for a new sensitive detector element - SensitiveDetector(const std::string& type, const std::string& name); + SensitiveDetector(const std::string& name, const std::string& type); /// Additional data accessor Object& _data() const { return *data<Object>(); } @@ -85,18 +87,39 @@ namespace DD4hep { /// Access the type of the sensitive detector std::string type() const; + /// Set detector type (structure, tracker, calorimeter, etc.). + SensitiveDetector& setType(const std::string& typ); + + /// Set flag to handle hits collection + SensitiveDetector& setVerbose(bool value); + + /// Access flag to combine hist + bool verbose() const; + /// Set flag to handle hits collection SensitiveDetector& setCombineHits(bool value); + /// Access flag to combine hist + bool combineHits() const; + /// Assign the name of the hits collection SensitiveDetector& setHitsCollection(const std::string& spec); + /// Access the hits collection name + const std::string& hitsCollection() const; + /// Assign the IDDescriptor reference SensitiveDetector& setReadout(Readout readout); /// Access readout structure of the sensitive detector Readout readout() const; + /// Set energy cut off + SensitiveDetector& setEnergyCutoff(double value); + + /// Access energy cut off + double energyCutoff() const; + /// Extend the sensitive detector element with an arbitrary structure accessible by the type template<typename IFACE, typename CONCRETE> IFACE* addExtension(CONCRETE* c) { return (IFACE*)i_addExtension(dynamic_cast<IFACE*>(c),typeid(IFACE),_delete<IFACE>); } @@ -108,13 +131,9 @@ namespace DD4hep { /** @class SubDetector Detector.h DD4hep/lcdd/Detector.h * - * Please note: - * Though nowhere enforced, it is obvious that only placements - * of the **SAME** logical volume should be added. - * - * We explicitly rely here on the common sense of the user - * of this class. People without a brain can always screw - * things completely - nothing one can do about! + * The basic object type to access all information of a given + * Subdetector including it's hierarchical structure with + * other dependending DetElement daughters. * * @author M.Frank * @version 1.0 @@ -122,7 +141,6 @@ namespace DD4hep { struct DetElement : public Ref_t { typedef Ref_t Parent; typedef std::map<std::string,DetElement> Children; - typedef std::vector<PlacedVolume> Placements; typedef std::map<const std::type_info*,void*> Extensions; enum { @@ -135,14 +153,14 @@ namespace DD4hep { struct Object { unsigned int magic; int id; + /// Full path to this detector element. May be invalid std::string path; - int combine_hits; + int combineHits; Volume volume; Readout readout; Alignment alignment; Conditions conditions; PlacedVolume placement; - Placements placements; Parent parent; Parent reference; Children children; @@ -229,15 +247,24 @@ namespace DD4hep { template <class T> T* extension() const { return (T*)i_extension(typeid(T)); } - DetElement& setCombineHits(bool value, SensitiveDetector& sens); + /// Set the detector identifier int id() const; + /// Setter: Combine hits attribite + DetElement& setCombineHits(bool value, SensitiveDetector& sens); + /// Getter: Combine hits attribite + bool combineHits() const; + + /// Access detector type (structure, tracker, calorimeter, etc.). + /** Required for determination of G4 sensitive detector. + */ std::string type() const; + /// Set detector type (structure, tracker, calorimeter, etc.). + DetElement& setType(const std::string& typ); + + /// Path of the detector element (not necessarily identical to placement path!) std::string path() const; /// Access to the full path to the placed object std::string placementPath() const; - bool isTracker() const; - bool isCalorimeter() const; - bool combineHits() const; /// Set all attributes in one go DetElement& setAttributes(const LCDD& lcdd, const Volume& volume, @@ -257,10 +284,8 @@ namespace DD4hep { /// Assign readout definition DetElement& setReadout(const Readout& readout); - /// Access to the logical volume of the placements (all daughters have the same!) + /// Access to the logical volume of the daughter placement Volume volume() const; - /// Set the logical volume of the placements (all daughters have the same!) - //void setVolume(Volume vol); /// Access to the physical volume of this detector element PlacedVolume placement() const; diff --git a/DDCore/include/DD4hep/Factories.h b/DDCore/include/DD4hep/Factories.h index 4a4761538..e2fac36a7 100644 --- a/DDCore/include/DD4hep/Factories.h +++ b/DDCore/include/DD4hep/Factories.h @@ -6,8 +6,8 @@ // Author : M.Frank // //==================================================================== -#ifndef DD4hep_FACTORIES_H -#define DD4hep_FACTORIES_H +#ifndef DD4HEP_FACTORIES_H +#define DD4HEP_FACTORIES_H #ifndef __CINT__ #include "Reflex/PluginService.h" @@ -132,20 +132,20 @@ namespace { PLUGINSVC_FACTORY_WITH_ID(x,std::string(#x),TNamed*(DD4hep::Geometry::LCDD*,const DD4hep::XML::Handle_t*,DD4hep::Geometry::SensitiveDetector*)) #define DECLARE_TRANSLATION(name,func) \ - namespace DD4hep { namespace Geometry { namespace { struct name {}; } \ - template <> Ref_t TranslationFactory<name>::create(LCDD& lcdd) {return func(lcdd);} }} \ + namespace DD4hep { namespace Geometry { namespace { struct name {}; } \ + template <> Ref_t TranslationFactory<name>::create(LCDD& l) {return func(l);} }} \ DECLARE_NAMED_TRANSLATION_FACTORY(DD4hep::Geometry,name) #define DECLARE_XMLELEMENT(name,func) \ - namespace DD4hep { namespace Geometry { namespace { struct name {}; } \ - template <> Ref_t XMLElementFactory<name>::create(LCDD& lcdd, const XML::Handle_t& e) \ - { return func(lcdd,e);} }} \ - DECLARE_NAMED_XMLELEMENT_FACTORY(DD4hep::Geometry,name) + namespace DD4hep { namespace Geometry { namespace { struct xml_element_##name {}; } \ + using DD4hep::Geometry::xml_element_##name; \ + template <> Ref_t XMLElementFactory<xml_element_##name>::create(LCDD& l,const XML::Handle_t& e) {return func(l,e);} }}\ + PLUGINSVC_FACTORY_WITH_ID(xml_element_##name,std::string(#name),TNamed*(DD4hep::Geometry::LCDD*,const DD4hep::XML::Handle_t*)) #define DECLARE_DETELEMENT(name,func) \ - namespace DD4hep { namespace Geometry { namespace { struct name {}; } \ - template <> Ref_t DetElementFactory<name>::create(LCDD& lcdd, const XML::Handle_t& e, SensitiveDetector& s) \ - { return func(lcdd,e,s);} }} \ - DECLARE_NAMED_DETELEMENT_FACTORY(DD4hep::Geometry,name) + namespace DD4hep { namespace Geometry { namespace { struct det_element_##name {}; } \ + using DD4hep::Geometry::det_element_##name; \ + template <> Ref_t DetElementFactory<det_element_##name>::create(LCDD& l,const XML::Handle_t& e,SensitiveDetector& s){return func(l,e,s);}}}\ + PLUGINSVC_FACTORY_WITH_ID(det_element_##name,std::string(#name),TNamed*(DD4hep::Geometry::LCDD*,const DD4hep::XML::Handle_t*,DD4hep::Geometry::SensitiveDetector*)) -#endif // DD4hep_FACTORIES_H +#endif // DD4HEP_FACTORIES_H diff --git a/DDCore/include/DD4hep/GeoHandler.h b/DDCore/include/DD4hep/GeoHandler.h index 02fe51519..a53c3f993 100644 --- a/DDCore/include/DD4hep/GeoHandler.h +++ b/DDCore/include/DD4hep/GeoHandler.h @@ -42,16 +42,28 @@ namespace DD4hep { typedef std::vector<std::pair<std::string, TGeoMatrix*> > TransformSet; typedef std::set<TGeoShape*> SolidSet; typedef std::set<TGeoMedium*> MaterialSet; + typedef std::map<TNamed*,std::set<const TGeoVolume*> > SensitiveVolumes; + typedef std::map<TNamed*,std::set<const TGeoVolume*> > RegionVolumes; + typedef std::map<TNamed*,std::set<const TGeoVolume*> > LimitVolumes; typedef std::map<int, std::set<const TGeoNode*> > Data; typedef std::set<TNamed*> VisRefs; typedef LCDD::HandleMap DefinitionSet; + typedef Geometry::LCDD LCDD; + typedef Geometry::Volume Volume; + typedef Geometry::PlacedVolume PlacedVolume; + typedef Geometry::DetElement DetElement; + typedef Geometry::SensitiveDetector SensitiveDetector; + struct GeometryInfo { SolidSet solids; VolumeSet volumes; TransformSet trafos; VisRefs vis; MaterialSet materials; + // SensitiveVolumes sensitives; + // RegionVolumes regions; + // LimitVolumes limits; std::set<TGeoMedium*> media; std::set<TGeoElement*> elements; }; @@ -74,21 +86,6 @@ namespace DD4hep { GeoHandler& collect(DetElement top, GeometryInfo& info); /// Access to collected node list Data* release(); -#if 0 - template <typename C, typename F> static void _handle(const O* ptr, const C& c, F pmf) { - for(typename C::const_iterator i=c.begin(); i != c.end(); ++i) { - (ptr->*pmf)((*i).first, (*i).second); - } - } -#endif - template <typename O, typename C, typename F> static void handle(const O* o, const C& c, F pmf) { - for(typename C::const_iterator i=c.begin(); i != c.end(); ++i) - (o->*pmf)((*i)->GetName(),*i); - } - template <typename O, typename C, typename F> static void handle(O* o, const C& c, F pmf) { - for(typename C::const_iterator i=c.begin(); i != c.end(); ++i) - (o->*pmf)((*i)->GetName(),*i); - } }; struct GeoScan { diff --git a/DDCore/include/DD4hep/Handle.h b/DDCore/include/DD4hep/Handle.h index 58157c6c9..0441804bd 100644 --- a/DDCore/include/DD4hep/Handle.h +++ b/DDCore/include/DD4hep/Handle.h @@ -63,6 +63,12 @@ namespace DD4hep { inline int _toInt(int value) { return value; } inline float _toFloat(float value) { return value; } inline double _toDouble(double value) { return value; } + + template<class T> T _multiply(const std::string& left, const std::string& right); + template <> int _multiply<int>(const std::string& left, const std::string& right); + template <> long _multiply<long>(const std::string& left, const std::string& right); + template <> float _multiply<float>(const std::string& left, const std::string& right); + template <> double _multiply<double>(const std::string& left, const std::string& right); void _toDictionary(const std::string& name, const std::string& value); diff --git a/DDCore/include/DD4hep/Objects.h b/DDCore/include/DD4hep/Objects.h index e879bde4e..51b380ddb 100644 --- a/DDCore/include/DD4hep/Objects.h +++ b/DDCore/include/DD4hep/Objects.h @@ -22,6 +22,8 @@ class TGeoPhysicalNode; #include "TGeoPhysicalNode.h" // C/C++ include files +#include <set> + #define _USE_MATH_DEFINES #include <cmath> #ifndef M_PI @@ -112,18 +114,55 @@ namespace DD4hep { /// Default constructor Position() : x(0), y(0), z(0) {} /// Initializing constructor - Position(double xval, double yval, double zval) : x(xval), y(yval), z(zval) { } + Position(double xval, double yval, double zval) : x(xval), y(yval), z(zval) { } /// Is it a identity rotation ? - bool isNull() const { return x==0 && y==0 && z==0; } + bool isNull() const { return x==0 && y==0 && z==0; } + /// Ceck 2 positions for equality + bool operator==(const Position& c) const { return x==c.x && y==c.y && z==c.z; } + /// Ceck 2 positions for in-equality + bool operator!=(const Position& c) const { return x!=c.x || y!=c.y || x!=c.z; } + /// Negation of the direction + Position operator - () const { return Position(-x,-y,-z); } + /// Scalar multiplication + Position& operator *=(double a) { x *= a;y *= a;z *= a;return *this; } + /// Addition operator + Position& operator +=(const Position& p) { x+=p.x;y+=p.y;z+=p.z;return *this; } + /// Subtraction operator + Position& operator -= (const Position& p) { x-=p.x;y-=p.y;z-=p.z;return *this; } + + /// Position length + double length() const { return sqrt(x*x + y*y + z*z); } /// Access to array like coordinates - const double* coordinates() const { return &x; } + const double* coordinates() const { return &x; } /// Initializer for all member variables - Position& set(double xv, double yv, double zv) { x=xv; y=yv; z=zv; return *this; } + Position& set(double xv, double yv, double zv) { x=xv; y=yv; z=zv; return *this; } }; #ifdef _WIN32 #pragma pack(pop,DD4Hep_Objects_Position) #pragma pack(push,DD4Hep_Objects_Rotation,1) #endif + /// Addition of 2 positions + inline Position operator + (const Position& l, const Position& r) + { return Position(l.x+r.x,l.y+r.y,l.z+r.z); } + /// Subtraction of to positions + inline Position operator - (const Position& l, const Position& r) + { return Position(l.x-r.x,l.y-r.y,l.z-r.z); } + /// Dot product of 3-vectors. + inline double operator * (const Position& l, const Position& r) + { return sqrt(l.x*r.x + l.y*r.y + l.z*r.z); } + /// Positions scaling from left + inline Position operator * (double l, const Position& r) + { return Position(r.x*l,r.y*l,r.z*l); } + /// Positions scaling from right + inline Position operator * (const Position& l, double r) + { return Position(l.x*r,l.y*r,l.z*r); } + /// Positions scaling from right + inline Position operator / (const Position& l, double r) + { return Position(l.x/r,l.y/r,l.z/r); } + + typedef Position Direction; + typedef Position Momentum; + /** @class Rotation Objects.h * * @author M.Frank @@ -136,11 +175,15 @@ namespace DD4hep { /// Initializing constructor Rotation(double thetaval, double phival, double psival) : theta(thetaval), phi(phival), psi(psival) {} /// Is it a identity rotation ? - bool isNull() const { return theta==0 && phi==0 && psi==0; } + bool isNull() const { return theta==0 && phi==0 && psi==0; } + /// Ceck 2 rotations for equality + bool operator==(const Rotation& c) const { return theta==c.theta && phi==c.phi && psi==c.psi;} + /// Ceck 2 rotations for in-equality + bool operator!=(const Rotation& c) const { return theta!=c.theta || phi!=c.phi || psi!=c.psi;} /// Access to array like coordinates - const double* angles() const { return θ } + const double* angles() const { return θ } /// Initializer for all member variables - Rotation& set(double th, double ph, double ps) { theta=th; phi=ph; psi=ps;return *this; } + Rotation& set(double th, double ph, double ps) { theta=th; phi=ph; psi=ps;return *this; } }; #ifdef _WIN32 @@ -324,20 +367,29 @@ namespace DD4hep { /** @class Limit Objects.h - * + * Small object describing a limit structure + * * @author M.Frank * @version 1.0 */ - struct Limit : public Ref_t { - typedef std::pair<std::string,double> Object; - - /// Constructor to be used when creating a new limit object - Limit(LCDD& doc, const std::string& name); - /// Additional data accessor - Object& _data() const { return *data<Object>(); } - void setParticles(const std::string& particleNames); - void setValue(double value); - void setUnit(const std::string& unit); + struct Limit { + std::string particles; + std::string name; + std::string unit; + std::string content; + double value; + /// Default constructor + Limit() : particles(), name(), unit(), content(), value(0.0) {} + /// Copy constructor + Limit(const Limit& c) : particles(c.particles), name(c.name), unit(c.unit), content(c.content), value(c.value) {} + /// Assignment operator + Limit& operator=(const Limit& c); + /// Equality operator + bool operator==(const Limit& c) const; + /// operator less + bool operator< (const Limit& c) const; + /// Conversion to a string representation + std::string toString() const; }; /** @class LimitSet Objects.h @@ -346,15 +398,18 @@ namespace DD4hep { * @version 1.0 */ struct LimitSet : public Ref_t { - typedef TMap Object; + typedef std::set<Limit> Object; /// Constructor to be used when reading the already parsed DOM tree LimitSet() : Ref_t() {} /// Constructor to be used when reading the already parsed DOM tree template <typename Q> LimitSet(const Handle<Q>& e) : Ref_t(e) {} /// Constructor to be used when creating a new DOM tree - LimitSet(LCDD& doc, const std::string& name); - void addLimit(const Ref_t& limit); + LimitSet(const std::string& name); + /// Add new limit. Returns true if the new limit was added, false if it already existed. + bool addLimit(const Limit& limit); + /// Accessor to limits container + const Object& limits() const; }; /** @class Region Objects.h @@ -369,6 +424,7 @@ namespace DD4hep { double cut; bool store_secondaries; std::string lunit, eunit; + std::vector<std::string> user_limits; }; /// Default constructor Region() : Ref_t() {} @@ -376,7 +432,7 @@ namespace DD4hep { template <typename Q> Region(const Handle<Q>& e) : Ref_t(e) {} /// Constructor to be used when creating a new DOM tree - Region(LCDD& doc, const std::string& name); + Region(const std::string& name); /// Additional data accessor Object& _data() const { return *data<Object>(); } @@ -385,6 +441,15 @@ namespace DD4hep { Region& setCut(double value); Region& setLengthUnit(const std::string& unit); Region& setEnergyUnit(const std::string& unit); + /// Access references to user limits + std::vector<std::string>& limits() const; + + /// Access cut value + double cut() const; + /// Access production threshold + double threshold() const; + /// Access secondaries flag + bool storeSecondaries() const; }; /** @class IDSpec Objects.h diff --git a/DDCore/include/DD4hep/Readout.h b/DDCore/include/DD4hep/Readout.h index 4bce185d1..d4a9e9b5f 100644 --- a/DDCore/include/DD4hep/Readout.h +++ b/DDCore/include/DD4hep/Readout.h @@ -49,7 +49,7 @@ namespace DD4hep { /// Constructor to be used when reading the already parsed object template <typename Q> Readout(const Handle<Q>& e) : Ref_t(e) {} /// Initializing constructor - Readout(const LCDD& doc, const std::string& name); + Readout(const std::string& name); /// Assign IDDescription to readout structure void setIDDescriptor(const Ref_t& spec) const; /// Access IDDescription structure diff --git a/DDCore/include/DD4hep/Segmentations.h b/DDCore/include/DD4hep/Segmentations.h index 80d07864a..86292f90e 100644 --- a/DDCore/include/DD4hep/Segmentations.h +++ b/DDCore/include/DD4hep/Segmentations.h @@ -7,12 +7,15 @@ // //==================================================================== -#ifndef DD4hep_GEOMETRY_SEGMENTATIONS_H -#define DD4hep_GEOMETRY_SEGMENTATIONS_H +#ifndef DD4HEP_GEOMETRY_SEGMENTATIONS_H +#define DD4HEP_GEOMETRY_SEGMENTATIONS_H // Framework include files #include "DD4hep/Handle.h" +// C/C++ include files +#include <cmath> + /* * DD4hep namespace declaration */ @@ -29,38 +32,64 @@ namespace DD4hep { * @version 1.0 */ struct Segmentation : public Ref_t { + public: + enum { REGULAR=0, EXTENDED=1 }; + struct Object { + /// Magic word to check object integrity unsigned long magic; + /// Segmentation type (REGULAR or EXTENDED) + unsigned char type; + /// Flag to use segmentation for hit positioning unsigned char useForHitPosition; - union { - double values[10]; - struct { + /// Spares to start 16 byte Byte aligned + unsigned char _spare[6]; + + union Data { + /// Maximal size and data buffer for specialized user segentations + double values[32]; + /// Extension buffer for specialized user segentations, where above values are insufficient + struct Extension { + const std::type_info* info; + void (*destructor)(void*); + void* ptr; + } extension; + /// No the regular structures for default segmentations + struct Cartesian { int nx; int ny; int nz; } cartesian; - struct { + struct CartesianGrid { double grid_size_x; double grid_size_y; double grid_size_z; } cartesian_grid; - struct { + struct CylindricalBinning { int nphi; int ntheta; int nz; } cylindrical_binning; - struct { + struct CylindricalGrid { double grid_size_phi; double grid_size_theta; double grid_size_z; - } cylindrical_grid; + } cylindrical_grid; + } data; - Object() : useForHitPosition(0) { - data.cartesian_grid.grid_size_x = 0; - data.cartesian_grid.grid_size_y = 0; - data.cartesian_grid.grid_size_z = 0; - } + Object(); + ~Object(); }; + + protected: + /// Templated destructor function + template <typename T> static void _delete(void* ptr) { delete (T*)(ptr); } + /// Add an extension object to the detector element + void* i_setExtension(void* ptr, const std::type_info& info, void (*destruct)(void*)); + /// Access an existing extension object from the detector element + void* i_extension(const std::type_info& info) const; + + public: /// Default constructor Segmentation() : Handle<Implementation>() {} /// Constructor to be used when reading the already parsed object @@ -69,11 +98,23 @@ namespace DD4hep { /// Constructor to create a new segmentation object (to be called by super class only) Segmentation(const std::string& type); /// Accessor to ata structure - Object& _data() const { return *data<Object>(); } + Object& _data() const { return *data<Object>(); } /// Access flag for hit positioning bool useForHitPosition() const; /// Segmentation type const std::string type() const; + /// Extend the segmentation object with an arbitrary structure accessible by the type + template<typename IFACE, typename CONCRETE> IFACE* setExtension(CONCRETE* c) + { return (IFACE*)i_addExtension(dynamic_cast<IFACE*>(c),typeid(IFACE),_delete<IFACE>); } + /// Access extension element by the type + template <class T> T* extension() const { return (T*)i_extension(typeid(T)); } + /// Access extension element by the type + template <class T> T* extensionUnchecked() const { return (T*)_data().data.extension.ptr;} + + /// Compute the coordinate in one dimension given a eauidistant bin value. + static double binCenter(int bin, double width) { return (double(bin) + .5) * width; } + /// Compute the equidistant bin given a coordinate in one dimension. + static int bin(double value, double width) { return int(floor(value/width)); } }; /** @class ProjectiveCylinder Segmentations.h DD4hep/lcdd/Segmentations.h @@ -200,6 +241,7 @@ namespace DD4hep { GlobalGridXY() : GridXY("global_grid_xy") {} }; - } /* End namespace Geometry */ + + } /* End namespace Geometry */ } /* End namespace DD4hep */ -#endif /* DD4hep_GEOMETRY_SEGMENTATIONS_H */ +#endif /* DD4HEP_GEOMETRY_SEGMENTATIONS_H */ diff --git a/DDCore/include/DD4hep/Volumes.h b/DDCore/include/DD4hep/Volumes.h index 222c819db..42eda251f 100644 --- a/DDCore/include/DD4hep/Volumes.h +++ b/DDCore/include/DD4hep/Volumes.h @@ -104,6 +104,7 @@ namespace DD4hep { Ref_t sens_det; int referenced; Object() : region(), limits(), vis(), sens_det(), referenced(0) {} + void copy(const Object& c) { region=c.region; limits=c.limits; vis=c.vis; sens_det=c.sens_det; referenced=c.referenced; } }; /// Default constructor Volume() : Base(0) {} diff --git a/DDCore/include/XML/XMLElements.h b/DDCore/include/XML/XMLElements.h index 875e2eddf..8c376b688 100644 --- a/DDCore/include/XML/XMLElements.h +++ b/DDCore/include/XML/XMLElements.h @@ -103,6 +103,7 @@ namespace DD4hep { Handle_t clone(xercesc::DOMDocument* new_doc, bool deep) const; bool hasAttr(const XMLCh* t) const { return 0 != m_node->getAttributeNode(t); } bool hasAttr(const char* t) const { return 0 != m_node->getAttributeNode(Strng_t(t));} + template <class T> T attr(const Attribute a) const; template <class T> T attr(const XMLCh* t) const; template <class T> T attr(const char* t) const { return this->attr<T>(Strng_t(t)); } void setAttrs(Handle_t e) const; @@ -130,40 +131,50 @@ namespace DD4hep { void removeChildren(const XMLCh* tag) const; void append(xercesc::DOMElement* e) const { m_node->appendChild(e); } const XMLCh* attr_value(const XMLCh* attr) const; + const XMLCh* attr_value(const Attribute attr) const; + const XMLCh* attr_value_nothrow(const XMLCh* attr) const; + Attribute attr_ptr(const XMLCh* attr) const; Attribute attr_nothrow(const XMLCh* tag) const { return m_node->getAttributeNode(tag); } - const XMLCh* attr_value_nothrow(const XMLCh* attr) const; }; #define INLINE inline - template <> INLINE Attribute Handle_t::attr<Attribute>(const XMLCh* tag) const { - return attr_ptr(tag); - } + template <> INLINE Attribute Handle_t::attr<Attribute>(const XMLCh* tag) const + { return attr_ptr(tag); } typedef const XMLCh* cpXMLCh; - template<> INLINE cpXMLCh Handle_t::attr<cpXMLCh>(const XMLCh* tag) const { - return attr_value(tag); - } + template<> INLINE cpXMLCh Handle_t::attr<cpXMLCh>(const XMLCh* tag) const + { return attr_value(tag); } + + template<> INLINE bool Handle_t::attr<bool>(const XMLCh* tag) const + { return _toBool(attr_value_nothrow(tag)); } + + template<> INLINE int Handle_t::attr<int>(const XMLCh* tag) const + { return _toInt(attr_value(tag)); } + + template<> INLINE float Handle_t::attr<float>(const XMLCh* tag) const + { return _toFloat(attr_value(tag)); } + + template<> INLINE double Handle_t::attr<double>(const XMLCh* tag) const + { return _toDouble(attr_value(tag)); } + + template<> INLINE std::string Handle_t::attr<std::string>(const XMLCh* tag) const + { return _toString(attr_nothrow(tag)); } - template<> INLINE bool Handle_t::attr<bool>(const XMLCh* tag) const { - return _toBool(attr_value_nothrow(tag)); - } + template<> INLINE bool Handle_t::attr<bool>(const Attribute tag) const + { return _toBool(attr_value(tag)); } - template<> INLINE int Handle_t::attr<int>(const XMLCh* tag) const { - return _toInt(attr_value(tag)); - } + template<> INLINE int Handle_t::attr<int>(const Attribute tag) const + { return _toInt(attr_value(tag)); } - template<> INLINE float Handle_t::attr<float>(const XMLCh* tag) const { - return _toFloat(attr_value(tag)); - } + template<> INLINE float Handle_t::attr<float>(const Attribute tag) const + { return _toFloat(attr_value(tag)); } - template<> INLINE double Handle_t::attr<double>(const XMLCh* tag) const { - return _toDouble(attr_value(tag)); - } + template<> INLINE double Handle_t::attr<double>(const Attribute tag) const + { return _toDouble(attr_value(tag)); } - template<> INLINE std::string Handle_t::attr<std::string>(const XMLCh* tag) const { - return _toString(attr_nothrow(tag)); - } + template<> INLINE std::string Handle_t::attr<std::string>(const Attribute tag) const + { return _toString(attr_value(tag)); } struct Collection_t : public Handle_t { mutable XMLSize_t m_index; diff --git a/DDCore/src/Detector.cpp b/DDCore/src/Detector.cpp index 622e82940..f5be04f41 100644 --- a/DDCore/src/Detector.cpp +++ b/DDCore/src/Detector.cpp @@ -123,8 +123,8 @@ static DetElement _par(DetElement o, DetElement top, vector<TGeoNode*>& det_node /// Default constructor DetElement::Object::Object() - : magic(magic_word()), id(0), combine_hits(0), readout(), - alignment(), placement(), placements(), parent(), children(), + : magic(magic_word()), id(0), combineHits(0), readout(), + alignment(), placement(), parent(), children(), worldTrafo(0), parentTrafo(0), referenceTrafo(0) { } @@ -135,14 +135,13 @@ Value<TNamed,DetElement::Object>* DetElement::Object::clone(int new_id, int flag const ExtensionMap& m = detelement_extensions(); Ref_t det(obj); obj->id = new_id; - obj->combine_hits = combine_hits; + obj->combineHits = combineHits; obj->readout = readout; obj->volume = volume; obj->alignment = Alignment(); obj->conditions = Conditions(); obj->parent = DetElement(); obj->placement = ((flag©_PLACEMENT) == COPY_PLACEMENT) ? placement : PlacedVolume(); - obj->placements = ((flag©_PLACEMENT) == COPY_PLACEMENT) ? placements : Placements(); // This implicitly assumes that the children do not access the parent's extensions! obj->extensions.clear(); @@ -244,7 +243,7 @@ DetElement::DetElement(const string& name, int id) { /// Constructor for a new subdetector element DetElement::DetElement(DetElement parent, const string& name, int id) { - assign(new Value<TNamed,Object>(),name,""); + assign(new Value<TNamed,Object>(),name,parent.type()); _data().id = id; parent.add(*this); } @@ -308,6 +307,15 @@ string DetElement::type() const { return m_element ? m_element->GetTitle() : ""; } +/// Set the type of the sensitive detector +DetElement& DetElement::setType(const std::string& typ) { + if ( isValid() ) { + m_element->SetTitle(typ.c_str()); + return *this; + } + throw runtime_error("DetElement::setType: Self is not defined [Invalid Handle]"); +} + string DetElement::path() const { if ( m_element ) { Object& o = _data(); @@ -325,7 +333,13 @@ int DetElement::id() const { } bool DetElement::combineHits() const { - return _data().combine_hits != 0; + return _data().combineHits != 0; +} + +DetElement& DetElement::setCombineHits(bool value, SensitiveDetector& sens) { + _data().combineHits = value; + if ( sens.isValid() ) sens.setCombineHits(value); + return *this; } Readout DetElement::readout() const { @@ -423,15 +437,7 @@ Volume DetElement::volume() const { } throw runtime_error("DetElement::volume: Self is not defined [Invalid Handle]"); } -#if 0 -/// Set the logical volume of the placements (all daughters have the same!) -void DetElement::setVolume(Volume vol) { - if ( isValid() ) { - _data().volume = vol; - } - throw runtime_error("DetElement::setVolume: Self is not defined [Invalid Handle]"); -} -#endif + DetElement& DetElement::setVisAttributes(const LCDD& lcdd, const string& name, const Volume& volume) { if ( isValid() ) { volume.setVisAttributes(lcdd,name); @@ -468,34 +474,6 @@ DetElement& DetElement::setAttributes(const LCDD& lcdd, const Volume& volume, return setRegion(lcdd,region,volume).setLimitSet(lcdd,limits,volume).setVisAttributes(lcdd,vis,volume); } -DetElement& DetElement::setCombineHits(bool value, SensitiveDetector& sens) { - if ( isTracker() ) { - _data().combine_hits = value; - sens.setCombineHits(value); - } - return *this; -} - -bool DetElement::isTracker() const { - if ( isValid() ) { - string typ = type(); - if ( typ.find("Tracker") != string::npos && _data().readout.isValid() ) { - return true; - } - } - return false; -} - -bool DetElement::isCalorimeter() const { - if ( isValid() ) { - string typ = type(); - if ( typ.find("Calorimeter") != string::npos && _data().readout.isValid() ) { - return true; - } - } - return false; -} - /// Set detector element for reference transformations. Will delete existing reference trafo. DetElement& DetElement::setReference(DetElement reference) { Object& o = _data(); @@ -552,7 +530,7 @@ bool DetElement::referenceToLocal(const Position& global, Position& local) cons } /// Constructor -SensitiveDetector::SensitiveDetector(const std::string& type, const std::string& name) { +SensitiveDetector::SensitiveDetector(const std::string& name, const std::string& type) { /* <calorimeter ecut="0" eunit="MeV" hits_collection="EcalEndcapHits" name="EcalEndcap" verbose="0"> <global_grid_xy grid_size_x="3.5" grid_size_y="3.5"/> @@ -561,10 +539,18 @@ SensitiveDetector::SensitiveDetector(const std::string& type, const std::string& */ assign(new Value<TNamed,Object>(),name,type); _data().ecut = 0e0; - _data().eunit = "MeV"; _data().verbose = 0; } +/// Set the type of the sensitive detector +SensitiveDetector& SensitiveDetector::setType(const std::string& typ) { + if ( isValid() ) { + m_element->SetTitle(typ.c_str()); + return *this; + } + throw runtime_error("SensitiveDetector::setType: Self is not defined [Invalid Handle]"); +} + /// Access the type of the sensitive detector string SensitiveDetector::type() const { return m_element ? m_element->GetTitle() : ""; @@ -581,19 +567,52 @@ Readout SensitiveDetector::readout() const { return _data().readout; } +/// Set energy cut off +SensitiveDetector& SensitiveDetector::setEnergyCutoff(double value) { + _data().ecut = value; + return *this; +} + +/// Access energy cut off +double SensitiveDetector::energyCutoff() const { + return _data().ecut; +} + /// Assign the name of the hits collection SensitiveDetector& SensitiveDetector::setHitsCollection(const string& collection) { - _data().hits_collection = collection; + _data().hitsCollection = collection; return *this; } +/// Access the hits collection name +const string& SensitiveDetector::hitsCollection() const { + return _data().hitsCollection; +} + +/// Assign the name of the hits collection +SensitiveDetector& SensitiveDetector::setVerbose(bool value) { + int v = value ? 1 : 0; + _data().verbose = v; + return *this; +} + +/// Access flag to combine hist +bool SensitiveDetector::verbose() const { + return _data().verbose == 1; +} + /// Assign the name of the hits collection SensitiveDetector& SensitiveDetector::setCombineHits(bool value) { int v = value ? 1 : 0; - _data().combine_hits = v; + _data().combineHits = v; return *this; } +/// Access flag to combine hist +bool SensitiveDetector::combineHits() const { + return _data().combineHits == 1; +} + /// Add an extension object to the detector element void* SensitiveDetector::i_addExtension(void* ptr, const std::type_info& info, void (*destruct)(void*)) { Object& o = _data(); diff --git a/DDCore/src/GeoHandler.cpp b/DDCore/src/GeoHandler.cpp index f84421f56..49ecdcac5 100644 --- a/DDCore/src/GeoHandler.cpp +++ b/DDCore/src/GeoHandler.cpp @@ -73,10 +73,17 @@ GeoHandler& GeoHandler::collect(DetElement element, GeometryInfo& info) { TGeoMedium* m = v->GetMedium(); Volume vol = Handle<>(v); VisAttr vis = vol.visAttributes(); + //Region reg = vol.region(); + //LimitSet lim = vol.limitSet(); + //SensitiveDetector det = vol.sensitiveDetector(); info.volumes.insert(v); info.materials.insert(m); if ( vis.isValid() ) info.vis.insert(vis.ptr()); + //if ( lim.isValid() ) info.limits[lim.ptr()].insert(v); + //if ( reg.isValid() ) info.regions[reg.ptr()].insert(v); + //if ( det.isValid() ) info.sensitives[det.ptr()].insert(v); + collectSolid(info,v->GetName(),n->GetName(),v->GetShape(),n->GetMatrix()); } } diff --git a/DDCore/src/Handle.cpp b/DDCore/src/Handle.cpp index f11a672d6..a898f94ae 100644 --- a/DDCore/src/Handle.cpp +++ b/DDCore/src/Handle.cpp @@ -61,6 +61,22 @@ double DD4hep::Geometry::_toDouble(const string& value) { return result; } +template <> int _multiply<int>(const std::string& left, const std::string& right) { + return (int)_toDouble(left+"*"+right); +} + +template <> long _multiply<long>(const std::string& left, const std::string& right) { + return (long)_toDouble(left+"*"+right); +} + +template <> float _multiply<float>(const std::string& left, const std::string& right) { + return _toFloat(left+"*"+right); +} + +template <> double _multiply<double>(const std::string& left, const std::string& right) { + return _toDouble(left+"*"+right); +} + void DD4hep::Geometry::_toDictionary(const string& name, const string& value) { string n=name, v=value; size_t idx = v.find("(int)"); diff --git a/DDCore/src/LCDDImp.cpp b/DDCore/src/LCDDImp.cpp index 694cb00bf..fa24ab0a3 100644 --- a/DDCore/src/LCDDImp.cpp +++ b/DDCore/src/LCDDImp.cpp @@ -35,7 +35,7 @@ using namespace DD4hep; using namespace std; namespace { struct TopDetElement : public DetElement { - TopDetElement(const std::string& nam, Volume vol) : DetElement(nam,0) { _data().volume = vol; } + TopDetElement(const std::string& nam, Volume vol) : DetElement(nam,/* "structure", */0) { _data().volume = vol; } }; } @@ -120,64 +120,70 @@ namespace { } void LCDDImp::endDocument() { - LCDD& lcdd = *this; - Material air = material("Air"); - - m_worldVol.setMaterial(air); - m_trackingVol.setMaterial(air); - - Region trackingRegion(lcdd,"TrackingRegion"); - trackingRegion.setThreshold(1); - trackingRegion.setStoreSecondaries(true); - add(trackingRegion); - m_trackingVol.setRegion(trackingRegion); + TGeoManager* mgr = gGeoManager; + if ( !mgr->IsClosed() ) { + LCDD& lcdd = *this; + Material air = material("Air"); + + m_worldVol.setMaterial(air); + m_trackingVol.setMaterial(air); + + Region trackingRegion("TrackingRegion"); + trackingRegion.setThreshold(1); + trackingRegion.setStoreSecondaries(true); + add(trackingRegion); + m_trackingVol.setRegion(trackingRegion); - // Set the world volume to invisible. - VisAttr worldVis(lcdd,"WorldVis"); - worldVis.setVisible(false); - m_worldVol.setVisAttributes(worldVis); - add(worldVis); + // Set the world volume to invisible. + VisAttr worldVis(lcdd,"WorldVis"); + worldVis.setVisible(false); + m_worldVol.setVisAttributes(worldVis); + add(worldVis); - // Set the tracking volume to invisible. - VisAttr trackingVis(lcdd,"TrackingVis"); - trackingVis.setVisible(false); - m_trackingVol.setVisAttributes(trackingVis); - add(trackingVis); - - /// Since we allow now for anonymous shapes, - /// we will rename them to use the name of the volume they are assigned to - TGeoManager* mgr = gGeoManager; - gGeoManager->SetTopVolume(m_worldVol); - mgr->CloseGeometry(); - m_world.setPlacement(PlacedVolume(mgr->GetTopNode())); - ShapePatcher(m_world)(); + // Set the tracking volume to invisible. + VisAttr trackingVis(lcdd,"TrackingVis"); + trackingVis.setVisible(false); + m_trackingVol.setVisAttributes(trackingVis); + add(trackingVis); + + /// Since we allow now for anonymous shapes, + /// we will rename them to use the name of the volume they are assigned to + gGeoManager->SetTopVolume(m_worldVol); + mgr->CloseGeometry(); + m_world.setPlacement(PlacedVolume(mgr->GetTopNode())); + ShapePatcher(m_world)(); + } } void LCDDImp::create() { - gGeoManager = new TGeoManager(); + if ( 0 == gGeoManager ) { + gGeoManager = new TGeoManager(); + } } void LCDDImp::init() { - LCDD& lcdd = *this; - Box worldSolid("world_box","world_x","world_y","world_z"); - Material vacuum = material("Vacuum"); - Volume world("world_volume",worldSolid,vacuum); - Tube trackingSolid("tracking_cylinder", - 0., - _toDouble("tracking_region_radius"), - _toDouble("2*tracking_region_zmax"),2*M_PI); - Volume tracking("tracking_volume",trackingSolid, vacuum); - m_world = TopDetElement("world",world); - m_trackers = TopDetElement("tracking",tracking); - m_worldVol = world; - m_trackingVol = tracking; - m_materialAir = material("Air"); - m_materialVacuum = material("Vacuum"); - m_detectors.append(m_world); - m_world.add(m_trackers); + if ( !m_world.isValid() ) { + Box worldSolid("world_box","world_x","world_y","world_z"); + Material vacuum = material("Vacuum"); + Volume world("world_volume",worldSolid,vacuum); + Tube trackingSolid("tracking_cylinder", + 0., + _toDouble("tracking_region_radius"), + _toDouble("2*tracking_region_zmax"),2*M_PI); + Volume tracking("tracking_volume",trackingSolid, vacuum); + m_world = TopDetElement("world",world); + m_trackers = TopDetElement("tracking",tracking); + m_worldVol = world; + m_trackingVol = tracking; + m_materialAir = material("Air"); + m_materialVacuum = material("Vacuum"); + m_detectors.append(m_world); + m_world.add(m_trackers); + } } void LCDDImp::fromCompact(const std::string& xmlfile) { + create(); #if DD4HEP_USE_PYROOT string cmd; TPython::Exec("import lcdd"); diff --git a/DDCore/src/Objects.cpp b/DDCore/src/Objects.cpp index b879c72d9..e1f839927 100644 --- a/DDCore/src/Objects.cpp +++ b/DDCore/src/Objects.cpp @@ -245,37 +245,56 @@ int AlignmentEntry::align(const Position& pos, const Rotation& rot, bool check, throw std::runtime_error("Callot align non existing physical node."); } -/// Constructor to be used when creating a limit object -Limit::Limit(LCDD& /* lcdd */, const string& name) { - Value<TNamed,Object>* obj = new Value<TNamed,Object>(); - assign(obj,name,"*"); - obj->first = "mm"; - obj->second = 1.0; + +/// Assignment operator +Limit& Limit::operator=(const Limit& c) { + particles = c.particles; + name = c.name; + unit = c.unit; + value = c.value; + content = c.content; + return *this; } -void Limit::setParticles(const string& particleNames) { - m_element->SetTitle(particleNames.c_str()); +/// Equality operator +bool Limit::operator==(const Limit& c) const { + return value==c.value && name==c.name && particles == c.particles; } -void Limit::setValue(double value) { - _data().second = value; +/// operator less +bool Limit::operator< (const Limit& c) const { + if ( value < c.value ) return true; + if ( name < c.name ) return true; + if ( particles < c.particles ) return true; + return false; } -void Limit::setUnit(const string& value) { - _data().first = value; +/// Conversion to a string representation +std::string Limit::toString() const { + string res = name + " = " + content; + if ( !unit.empty() ) res += unit + " "; + res + " (" + particles + ")"; + return res; } /// Constructor to be used when creating a new DOM tree -LimitSet::LimitSet(LCDD& /* lcdd */, const string& name) { - assign(new Value<TNamed,TMap>(),name,"limitset"); +LimitSet::LimitSet(const string& name) { + assign(new Value<TNamed,Object>(),name,"limitset"); } -void LimitSet::addLimit(const Ref_t& limit) { - data<TMap>()->Add(limit.ptr(),limit.ptr()); +/// Add new limit. Returns true if the new limit was added, false if it already existed. +bool LimitSet::addLimit(const Limit& limit) { + pair<Object::iterator,bool> ret = data<Object>()->insert(limit); + return ret.second; +} + +/// Accessor to limits container +const LimitSet::Object& LimitSet::limits() const { + return *(data<Object>()); } /// Constructor to be used when creating a new DOM tree -Region::Region(LCDD& /* lcdd */, const string& name) { +Region::Region(const string& name) { Value<TNamed,Object>* p = new Value<TNamed,Object>(); assign(p, name, "region"); p->magic = magic_word(); @@ -310,6 +329,27 @@ Region& Region::setEnergyUnit(const string& unit) { _data().eunit = unit; return *this; } + +/// Access references to user limits +vector<string>& Region::limits() const { + return _data().user_limits; +} + +/// Access cut value +double Region::cut() const { + return _data().cut; +} + +/// Access production threshold +double Region::threshold() const { + return _data().threshold; +} + +/// Access secondaries flag +bool Region::storeSecondaries() const { + return _data().store_secondaries; +} + #undef setAttr #if 0 diff --git a/DDCore/src/Readout.cpp b/DDCore/src/Readout.cpp index 2a389e138..61723b317 100644 --- a/DDCore/src/Readout.cpp +++ b/DDCore/src/Readout.cpp @@ -13,7 +13,7 @@ using namespace std; using namespace DD4hep::Geometry; /// Initializing constructor to create a new object -Readout::Readout(const LCDD& /* lcdd */, const string& nam) +Readout::Readout(const string& nam) { assign(new Value<TNamed,Object>(),nam,"readout"); } diff --git a/DDCore/src/Segementations.cpp b/DDCore/src/Segementations.cpp index 929f1f6ed..d72706489 100644 --- a/DDCore/src/Segementations.cpp +++ b/DDCore/src/Segementations.cpp @@ -13,6 +13,21 @@ using namespace std; using namespace DD4hep::Geometry; +Segmentation::Object::Object() : magic(magic_word()), type(REGULAR), useForHitPosition(0) { + ::memset(data.values,0,sizeof(data.values)); +} + +Segmentation::Object::~Object() { + if ( type == EXTENDED && data.extension.ptr != 0 ) { + if ( data.extension.destructor ) { + (*data.extension.destructor)(data.extension.ptr); + data.extension.destructor = 0; + data.extension.info = 0; + data.extension.ptr = 0; + } + } +} + Segmentation::Segmentation(const string& type) { assign(new Value<TNamed,Segmentation::Object>(),"segmentation",type); } @@ -25,6 +40,33 @@ const string Segmentation::type() const { return m_element->GetTitle(); } +/// Add an extension object to the detector element +void* Segmentation::i_setExtension(void* ptr, const std::type_info& info, void (*destruct)(void*)) { + Object& o = _data(); + o.type = EXTENDED; + o.data.extension.ptr = ptr; + o.data.extension.info = &info; + o.data.extension.destructor = destruct; + return ptr; +} + +/// Access an existing extension object from the detector element +void* Segmentation::i_extension(const std::type_info& info) const { + if ( isValid() ) { + Object::Data::Extension& o = _data().data.extension; + if ( o.ptr ) { + if ( &info == o.info ) { + return o.ptr; + } + throw runtime_error("extension: The segmentation object "+string(type())+ + " has the wrong type!"); + } + throw runtime_error("extension: The segmentation object "+string(type())+ + " has no extension defined."); + } + throw runtime_error("extension: The segmentation object is not valid!"); +} + ProjectiveCylinder::ProjectiveCylinder() : Segmentation("projective_cylinder") {} diff --git a/DDCore/src/Volumes.cpp b/DDCore/src/Volumes.cpp index 5fef0ee9e..e87aa741b 100644 --- a/DDCore/src/Volumes.cpp +++ b/DDCore/src/Volumes.cpp @@ -100,16 +100,23 @@ namespace DD4hep { namespace Geometry { template <> _VolWrap<TGeoVolume>::_VolWrap(const char* name, TGeoShape* s, TGeoMedium* m) : TGeoVolume(name,s,m) {} - template <> _VolWrap<TGeoVolumeAssembly>::_VolWrap(const char* name, TGeoShape* s, TGeoMedium* m) + template <> _VolWrap<TGeoVolumeAssembly>::_VolWrap(const char* name, TGeoShape* /* s */, TGeoMedium* /* m */) : TGeoVolumeAssembly(name) {} template <> struct Value<TGeoVolume,Volume::Object> : public _VolWrap<TGeoVolume>, public Volume::Object { - Value(const char* name, TGeoShape* s=0, TGeoMedium* m=0) : _VolWrap<TGeoVolume>(name,s,m) {magic = magic_word();} + Value(const char* name, TGeoShape* s=0, TGeoMedium* m=0) + : _VolWrap<TGeoVolume>(name,s,m) {magic = magic_word();} virtual ~Value() {} + TGeoVolume *_copyVol(TGeoShape *newshape) const { + typedef Value<TGeoVolume,Volume::Object> _Vol; + _Vol *vol = new _Vol(GetName(), newshape, fMedium); + vol->copy(*this); + return vol; + } virtual TGeoVolume* MakeCopyVolume(TGeoShape *newshape) { // make a copy of this volume. build a volume with same name, shape and medium - TGeoVolume *vol = new Value<TGeoVolume,Volume::Object>(GetName(), newshape, fMedium); + TGeoVolume *vol = _copyVol(newshape); vol->SetVisibility(IsVisible()); vol->SetLineColor(GetLineColor()); vol->SetLineStyle(GetLineStyle()); @@ -123,7 +130,7 @@ namespace DD4hep { namespace Geometry { return vol; } virtual TGeoVolume* CloneVolume() const { - TGeoVolume *vol = new Value<TGeoVolume,Volume::Object>(GetName(), fShape, fMedium); + TGeoVolume *vol = _copyVol(fShape); Int_t i; // copy volume attributes vol->SetLineColor(GetLineColor()); @@ -383,8 +390,10 @@ void Volume::setLimitSet(const LimitSet& obj) const { data<Object>()->limits = obj; } /// Assign the sensitive detector structure -void Volume::setSensitiveDetector(const SensitiveDetector& obj) const -{ data<Object>()->sens_det = obj; } +void Volume::setSensitiveDetector(const SensitiveDetector& obj) const { + //cout << "Setting sensitive detector '" << obj.name() << "' to volume:" << ptr() << " " << name() << endl; + data<Object>()->sens_det = obj; +} /// Access to the handle to the sensitive detector Ref_t Volume::sensitiveDetector() const diff --git a/DDCore/src/XML/DocumentHandler.cpp b/DDCore/src/XML/DocumentHandler.cpp index f05a43700..e8de01f71 100644 --- a/DDCore/src/XML/DocumentHandler.cpp +++ b/DDCore/src/XML/DocumentHandler.cpp @@ -118,13 +118,13 @@ XercesDOMParser* DocumentHandler::makeParser(xercesc::ErrorHandler* err_handler) } Document DocumentHandler::load(const string& fname) const { + cout << "Loading document URI:" << fname << endl; XMLURL xerurl = (const XMLCh*)Strng_t(fname); string path = _toString(xerurl.getPath()); string proto = _toString(xerurl.getProtocolName()); auto_ptr<XercesDOMParser> parser(makeParser()); - cout << "Loading document :" << path << endl - << " protocol:" << proto << endl - << " URI:" << fname << endl; + cout << " protocol:" << proto << endl + << " path:" << path << endl; try { parser->parse(path.c_str()); } diff --git a/DDCore/src/XML/XMLDetector.cpp b/DDCore/src/XML/XMLDetector.cpp index 55b98b138..90cf63613 100644 --- a/DDCore/src/XML/XMLDetector.cpp +++ b/DDCore/src/XML/XMLDetector.cpp @@ -284,7 +284,9 @@ double DetElement::Component::thickness() const { } bool DetElement::Component::isSensitive() const { - return m_element.hasAttr(Attr_sensitive) && m_element.attr<bool>(Attr_sensitive); + char val = m_element.hasAttr(Attr_sensitive) ? m_element.attr<string>(Attr_sensitive)[0] : 'f'; + val = ::toupper(val); + return val == 'T' || val == 'Y'; } string DetElement::Component::visStr() const { diff --git a/DDCore/src/XML/XMLElements.cpp b/DDCore/src/XML/XMLElements.cpp index 9ddbca10a..568694b47 100644 --- a/DDCore/src/XML/XMLElements.cpp +++ b/DDCore/src/XML/XMLElements.cpp @@ -323,6 +323,10 @@ const XMLCh* Handle_t::attr_value(const XMLCh* attr) const { return attr_ptr(attr)->getValue(); } +const XMLCh* Handle_t::attr_value(const Attribute attr) const { + return attr->getValue(); +} + const XMLCh* Handle_t::attr_value_nothrow(const XMLCh* attr) const { Attribute a = attr_nothrow(attr); //Attribute a = attr_ptr(attr); diff --git a/DDCore/src/compact/Compact2Objects.cpp b/DDCore/src/compact/Compact2Objects.cpp index 1f5f0d2f6..256f99596 100644 --- a/DDCore/src/compact/Compact2Objects.cpp +++ b/DDCore/src/compact/Compact2Objects.cpp @@ -29,6 +29,61 @@ namespace { static UInt_t unique_mat_id = 0xAFFEFEED; } +static Ref_t create_GridXYZ(lcdd_t& /* lcdd */, const xml_h& e) { + GridXYZ obj; + if ( e.hasAttr(_A(gridSizeX)) ) obj.setGridSizeX(e.attr<float>(_A(gridSizeX))); + if ( e.hasAttr(_A(gridSizeY)) ) obj.setGridSizeY(e.attr<float>(_A(gridSizeY))); + if ( e.hasAttr(_A(gridSizeZ)) ) obj.setGridSizeZ(e.attr<float>(_A(gridSizeZ))); + return obj; +} +DECLARE_XMLELEMENT(GridXYZ,create_GridXYZ); + +namespace DD4hep { namespace Geometry { typedef GridXYZ RegularNgonCartesianGridXY; }} +DECLARE_XMLELEMENT(RegularNgonCartesianGridXY,create_GridXYZ); + +static Ref_t create_GlobalGridXY(lcdd_t& /* lcdd */, const xml_h& e) { + GlobalGridXY obj; + if ( e.hasAttr(_A(gridSizeX)) ) obj.setGridSizeX(e.attr<float>(_A(gridSizeX))); + if ( e.hasAttr(_A(gridSizeY)) ) obj.setGridSizeY(e.attr<float>(_A(gridSizeY))); + return obj; +} +DECLARE_XMLELEMENT(GlobalGridXY,create_GlobalGridXY); + +static Ref_t create_CartesianGridXY(lcdd_t& /* lcdd */, const xml_h& e) { + CartesianGridXY obj; + if ( e.hasAttr(_A(gridSizeX)) ) obj.setGridSizeX(e.attr<double>(_A(gridSizeX))); + if ( e.hasAttr(_A(gridSizeY)) ) obj.setGridSizeY(e.attr<double>(_A(gridSizeY))); + return obj; +} +DECLARE_XMLELEMENT(CartesianGridXY,create_CartesianGridXY); + +namespace DD4hep { namespace Geometry { typedef CartesianGridXY EcalBarrelCartesianGridXY; }} +DECLARE_XMLELEMENT(EcalBarrelCartesianGridXY,create_CartesianGridXY); + +static Ref_t create_ProjectiveCylinder(lcdd_t& /* lcdd */, const xml_h& e) { + ProjectiveCylinder obj; + if ( e.hasAttr(_A(phiBins)) ) obj.setPhiBins(e.attr<int>(_A(phiBins))); + if ( e.hasAttr(_A(thetaBins)) ) obj.setThetaBins(e.attr<int>(_A(thetaBins))); + return obj; +} +DECLARE_XMLELEMENT(ProjectiveCylinder,create_ProjectiveCylinder); + +static Ref_t create_NonProjectiveCylinder(lcdd_t& /* lcdd */, const xml_h& e) { + NonProjectiveCylinder obj; + if ( e.hasAttr(_A(gridSizePhi)) ) obj.setThetaBinSize(e.attr<double>(_A(gridSizePhi))); + if ( e.hasAttr(_A(gridSizeZ)) ) obj.setPhiBinSize(e.attr<double>(_A(gridSizeZ))); + return obj; +} +DECLARE_XMLELEMENT(NonProjectiveCylinder,create_NonProjectiveCylinder); + +static Ref_t create_ProjectiveZPlane(lcdd_t& /* lcdd */, const xml_h& e) { + ProjectiveZPlane obj; + if ( e.hasAttr(_A(phiBins)) ) obj.setThetaBins(e.attr<int>(_A(phiBins))); + if ( e.hasAttr(_A(thetaBins)) ) obj.setPhiBins(e.attr<int>(_A(thetaBins))); + return obj; +} +DECLARE_XMLELEMENT(ProjectiveZPlane,create_ProjectiveZPlane); + namespace DD4hep { namespace Geometry { struct Compact; struct Includes; @@ -152,22 +207,21 @@ namespace DD4hep { namespace Geometry { return Ref_t(id); } - template <> Ref_t toRefObject<Limit>(lcdd_t& lcdd, const xml_h& e) { - /* <limit name="step_length_max" particles="*" value="5.0" unit="mm" /> - */ - Limit limit(lcdd,e.attr<string>(_A(name))); - limit.setParticles(e.attr<string>(_A(particles))); - limit.setValue(e.attr<double>(_A(value))); - limit.setUnit(e.attr<string>(_A(unit))); - return limit; - } - template <> Ref_t toRefObject<LimitSet>(lcdd_t& lcdd, const xml_h& e) { - /* <limitset name="...."> ... </limitset> + /* <limitset name="...."> + * <limit name="step_length_max" particles="*" value="5.0" unit="mm" /> + * ... </limitset> */ - LimitSet ls(lcdd,XML::Tag_t(e.attr<string>(_A(name)))); - for (xml_coll_t c(e,XML::Tag_limit); c; ++c) - ls.addLimit(toRefObject<Limit>(lcdd,c)); + LimitSet ls(e.attr<string>(_A(name))); + for (xml_coll_t c(e,XML::Tag_limit); c; ++c) { + Limit limit; + limit.particles = c.attr<string>(_A(particles)); + limit.name = c.attr<string>(_A(name)); + limit.content = c.attr<string>(_A(value)); + limit.unit = c.attr<string>(_A(unit)); + limit.value = _multiply<double>(limit.content,limit.unit); + ls.addLimit(limit); + } return ls; } @@ -200,86 +254,25 @@ namespace DD4hep { namespace Geometry { if ( e.hasAttr(_A(showDaughters)) ) attr.setShowDaughters(e.attr<bool>(_A(showDaughters))); return attr; } - - template <> Elt_t toObject<GridXYZ>(lcdd_t& /* lcdd */, const xml_h& e) { - GridXYZ obj; - if ( e.hasAttr(_A(gridSizeX)) ) obj.setGridSizeX(e.attr<float>(_A(gridSizeX))); - if ( e.hasAttr(_A(gridSizeY)) ) obj.setGridSizeY(e.attr<float>(_A(gridSizeY))); - if ( e.hasAttr(_A(gridSizeZ)) ) obj.setGridSizeZ(e.attr<float>(_A(gridSizeZ))); - return obj; - } - template <> Elt_t toObject<GlobalGridXY>(lcdd_t& /* lcdd */, const xml_h& e) { - GlobalGridXY obj; - if ( e.hasAttr(_A(gridSizeX)) ) obj.setGridSizeX(e.attr<float>(_A(gridSizeX))); - if ( e.hasAttr(_A(gridSizeY)) ) obj.setGridSizeY(e.attr<float>(_A(gridSizeY))); - return obj; - } - - template <> Elt_t toObject<CartesianGridXY>(lcdd_t& /* lcdd */, const xml_h& e) { - CartesianGridXY obj; - if ( e.hasAttr(_A(gridSizeX)) ) obj.setGridSizeX(e.attr<double>(_A(gridSizeX))); - if ( e.hasAttr(_A(gridSizeY)) ) obj.setGridSizeY(e.attr<double>(_A(gridSizeY))); - return obj; - } - - template <> Elt_t toObject<ProjectiveCylinder>(lcdd_t& /* lcdd */, const xml_h& e) { - ProjectiveCylinder obj; - if ( e.hasAttr(_A(phiBins)) ) obj.setPhiBins(e.attr<int>(_A(phiBins))); - if ( e.hasAttr(_A(thetaBins)) ) obj.setThetaBins(e.attr<int>(_A(thetaBins))); - return obj; - } - - template <> Elt_t toObject<NonProjectiveCylinder>(lcdd_t& /* lcdd */, const xml_h& e) { - NonProjectiveCylinder obj; - if ( e.hasAttr(_A(gridSizePhi)) ) obj.setThetaBinSize(e.attr<double>(_A(gridSizePhi))); - if ( e.hasAttr(_A(gridSizeZ)) ) obj.setPhiBinSize(e.attr<double>(_A(gridSizeZ))); - return obj; - } - - template <> Elt_t toObject<ProjectiveZPlane>(lcdd_t& /* lcdd */, const xml_h& e) { - ProjectiveZPlane obj; - if ( e.hasAttr(_A(phiBins)) ) obj.setThetaBins(e.attr<int>(_A(phiBins))); - if ( e.hasAttr(_A(thetaBins)) ) obj.setPhiBins(e.attr<int>(_A(thetaBins))); - return obj; - } - - template <> Elt_t toObject<Segmentation>(lcdd_t& lcdd, const xml_h& e) { - string seg_typ = e.attr<string>(_A(type)); - if ( seg_typ == "GridXYZ" ) - return toObject<GridXYZ>(lcdd,e); - else if ( seg_typ == "GlobalGridXY" ) - return toObject<GlobalGridXY>(lcdd,e); - else if ( seg_typ == "CartesianGridXY" ) - return toObject<CartesianGridXY>(lcdd,e); - else if ( seg_typ == "RegularNgonCartesianGridXY" ) - return toObject<GridXYZ>(lcdd,e); - else if ( seg_typ == "EcalBarrelCartesianGridXY" ) - return toObject<CartesianGridXY>(lcdd,e); - else if ( seg_typ == "ProjectiveCylinder" ) - return toObject<ProjectiveCylinder>(lcdd,e); - else if ( seg_typ == "NonProjectiveCylinder" ) - return toObject<NonProjectiveCylinder>(lcdd,e); - else if ( seg_typ == "ProjectiveZPlane" ) - return toObject<ProjectiveZPlane>(lcdd,e); - else - cout << "Request to create UNKNOWN segmentation of type:" << seg_typ << endl; - return Elt_t(0); - } - + template <> Ref_t toRefObject<Readout>(lcdd_t& lcdd, const xml_h& e) { /* <readout name="HcalBarrelHits"> <segmentation type="RegularNgonCartesianGridXY" gridSizeX="3.0*cm" gridSizeY="3.0*cm" /> <id>system:6,barrel:3,module:4,layer:8,slice:5,x:32:-16,y:-16</id> </readout> */ - xml_h id, seg; + const xml_h id = e.child(_X(id)); + const xml_h seg = e.child(_X(segmentation),false); string name = e.attr<string>(_A(name)); - Readout ro(lcdd,name); - if ( (seg=e.child(_X(segmentation),false)) ) { // Segmentation is not mandatory! - string seg_typ = seg.attr<string>(_A(type)); - ro.setSegmentation(toObject<Segmentation>(lcdd,seg)); + Readout ro(name); + + if ( seg ) { // Segmentation is not mandatory! + string type = seg.attr<string>(_A(type)); + Ref_t segment(ROOT::Reflex::PluginService::Create<TNamed*>(type,&lcdd,&seg)); + if ( !segment.isValid() ) throw runtime_error("FAILED to create segmentation:"+type); + ro.setSegmentation(segment); } - if ( (id=e.child(_X(id))) ) { + if ( id ) { Ref_t idSpec = toRefObject<IDDescriptor>(lcdd,id); idSpec->SetName(ro.name()); ro.setIDDescriptor(idSpec); @@ -326,28 +319,19 @@ namespace DD4hep { namespace Geometry { { return toRefObject<T>(lcdd,xml,sens); } } - template <> Ref_t toRefObject<SensitiveDetector>(lcdd_t& lcdd, const xml_h& e) { - string nam = e.attr<string>(_A(name)); - string typ = e.attr<string>(_A(type)); - - if ( e.hasAttr("calorimeterType") ) typ = "calorimeter"; - else if ( typ.find("Tracker") != string::npos ) typ = "tracker"; - else if ( nam.find("Tracker") != string::npos ) typ = "tracker"; - - if ( e.hasAttr(_A(readout)) ) { - Readout ro = lcdd.readout(e.attr<string>(_A(readout))); - SensitiveDetector sd = SensitiveDetector(typ,nam); - sd.setReadout(ro); - sd.setHitsCollection(ro.name()); - lcdd.addSensitiveDetector(sd); - return sd; - } - return SensitiveDetector(); - } - template <> Ref_t toRefObject<Region>(lcdd_t& /* lcdd */, const xml_h& e) { - xml_ref_t compact(e); - return Ref_t(0); + Region region(e.attr<string>(_A(name))); + vector<string>& limits = region.limits(); + string ene = e.attr<string>(_A(eunit)), len = e.attr<string>(_A(lunit)); + + region.setEnergyUnit(ene); + region.setLengthUnit(len); + region.setCut(_multiply<double>(e.attr<string>(_A(cut)),len)); + region.setThreshold(_multiply<double>(e.attr<string>(_A(threshold)),ene)); + region.setStoreSecondaries(e.attr<bool>(_A(store_secondaries))); + for(xml_coll_t user_limits(e,_X(limitsetref)); user_limits; ++user_limits) + limits.push_back(user_limits.attr<string>(_A(name))); + return region; } template <> void Converter<Constant>::operator()(const xml_h& element) const { @@ -357,7 +341,6 @@ namespace DD4hep { namespace Geometry { lcdd.addMaterial(toRefObject<to_type>(lcdd,element)); } template <> void Converter<Atom>::operator()(const xml_h& element) const { - // lcdd.addMaterial(toRefObject<to_type>(lcdd,element)); toRefObject<to_type>(lcdd,element); } template <> void Converter<VisAttr>::operator()(const xml_h& element) const { @@ -386,6 +369,51 @@ namespace DD4hep { namespace Geometry { } for_each(children.begin(),children.end(),setChildTitles); } + + template <> void Converter<SensitiveDetector>::operator()(const xml_h& element) const { + string type = element.attr<string>(_A(type)); + string name = element.attr<string>(_A(name)); + try { + DetElement det = lcdd.detector(name); + SensitiveDetector sd = lcdd.sensitiveDetector(name); + + xml_attr_t type = element.attr_nothrow(_A(type)); + if ( type ) { + sd.setType(element.attr<string>(type)); + } + xml_attr_t verbose = element.attr_nothrow(_A(verbose)); + if ( verbose ) { + sd.setVerbose(element.attr<bool>(verbose)); + } + xml_attr_t combine = element.attr_nothrow(_A(combine_hits)); + if ( combine ) { + sd.setCombineHits(element.attr<bool>(combine)); + } + xml_attr_t hits = element.attr_nothrow(_A(hits_collection)); + if ( hits ) { + sd.setHitsCollection(element.attr<string>(hits)); + } + xml_attr_t ecut = element.attr_nothrow(_A(ecut)); + xml_attr_t eunit = element.attr_nothrow(_A(eunit)); + if ( ecut && eunit ) { + double value = _multiply<double>(_toString(ecut),_toString(eunit)); + sd.setEnergyCutoff(value); + } + else if ( ecut ) { // If no unit is given , we assume the correct Geant4 unit is used! + sd.setEnergyCutoff(element.attr<double>(ecut)); + } + + cout << " sensitive detector:" << name << " of type " << type << endl; + //lcdd.addDetector(det); + } + catch(const exception& e) { + cout << "FAILED to convert subdetector:" << name << " of type " << type << ": " << e.what() << endl; + } + catch(...) { + cout << "FAILED to convert subdetector:" << name << " of type " << type << ": UNKNONW Exception" << endl; + } + } + template <> void Converter<DetElement>::operator()(const xml_h& element) const { static const char* req_dets = ::getenv("REQUIRED_DETECTORS"); static const char* req_typs = ::getenv("REQUIRED_DETECTOR_TYPES"); @@ -400,26 +428,26 @@ namespace DD4hep { namespace Geometry { if ( ign_dets && strstr(ign_dets,name_match.c_str()) ) return; if ( ign_typs && strstr(ign_typs,type_match.c_str()) ) return; try { + bool has_ro = element.hasAttr(_A(readout)); + Readout ro = has_ro ? lcdd.readout(element.attr<string>(_A(readout))) : Readout(); SensitiveDetector sd; - if ( element.hasAttr(_A(sensitive_detector)) ) { - string sensitive_type = element.attr<string>(_A(sensitive_detector)); - sd = lcdd.sensitiveDetector(sensitive_type); - // Ref_t(ROOT::Reflex::PluginService::Create<TNamed*>(sensitive_type,&lcdd,&element)); - } - if ( !sd.isValid() ) { - sd = toRefObject<SensitiveDetector>(lcdd,element); + if ( has_ro ) { + sd = SensitiveDetector(name,"structure"); + sd.setHitsCollection(ro.name()); + sd.setReadout(ro); + lcdd.addSensitiveDetector(sd); } - DetElement det(Ref_t(ROOT::Reflex::PluginService::Create<TNamed*>(type,&lcdd,&element,&sd))); if ( det.isValid() ) { setChildTitles(make_pair(name,det)); if ( element.hasAttr(_A(readout)) ) { - string rdo = element.attr<string>(_A(readout)); - det.setReadout(lcdd.readout(rdo)); + det.setReadout(ro); } } cout << (det.isValid() ? "Converted" : "FAILED ") - << " subdetector:" << name << " of type " << type << endl; + << " subdetector:" << name << " of type " << type; + if ( det.isValid() ) cout << " [" << sd.type() << "]"; + cout << endl; lcdd.addDetector(det); } catch(const exception& e) { @@ -449,13 +477,11 @@ namespace DD4hep { namespace Geometry { template <> void Converter<Compact>::operator()(const xml_h& element) const { XML::Element compact(element); - lcdd.create(); xml_coll_t(compact,_X(includes) ).for_each(_X(gdmlFile), Converter<GdmlFile>(lcdd)); //Header(lcdd.header()).fromCompact(doc,compact.child(Tag_info),Strng_t("In memory")); xml_coll_t(compact,_X(define) ).for_each(_X(constant), Converter<Constant>(lcdd)); xml_coll_t(compact,_X(materials) ).for_each(_X(element), Converter<Atom>(lcdd)); xml_coll_t(compact,_X(materials) ).for_each(_X(material), Converter<Material>(lcdd)); - lcdd.init(); xml_coll_t(compact,_X(limits) ).for_each(_X(limitset), Converter<LimitSet>(lcdd)); xml_coll_t(compact,_X(display) ).for_each(_X(vis), Converter<VisAttr>(lcdd)); @@ -463,6 +489,7 @@ namespace DD4hep { namespace Geometry { xml_coll_t(compact,_X(detectors) ).for_each(_X(detector), Converter<DetElement>(lcdd)); xml_coll_t(compact,_X(includes) ).for_each(_X(alignment),Converter<AlignmentFile>(lcdd)); xml_coll_t(compact,_X(alignments)).for_each(_X(alignment),Converter<AlignmentEntry>(lcdd)); + xml_coll_t(compact,_X(sensitive_detectors)).for_each(_X(detector),Converter<SensitiveDetector>(lcdd)); lcdd.endDocument(); } }} -- GitLab