diff --git a/DDCore/include/DD4hep/Detector.h b/DDCore/include/DD4hep/Detector.h index a0f841e5457364b42a8cb95120d24b001f49ac79..271c2bdee30e42b4cc66c3c46657a8cbf861e84f 100644 --- a/DDCore/include/DD4hep/Detector.h +++ b/DDCore/include/DD4hep/Detector.h @@ -59,7 +59,7 @@ namespace DD4hep { /// Default constructor Object(); /// Internal object destructor: release extension object(s) - ~Object(); + virtual ~Object(); }; protected: diff --git a/DDCore/include/DD4hep/Fields.h b/DDCore/include/DD4hep/Fields.h index b19014b21e6f6a9bcbb2a2d95eaea23b8de00860..7e2674d2e7b34481f12ce2f35c8453c1437147fe 100644 --- a/DDCore/include/DD4hep/Fields.h +++ b/DDCore/include/DD4hep/Fields.h @@ -55,7 +55,7 @@ namespace DD4hep { /// Default constructor Object(); /// Default destructor - ~Object(); + virtual ~Object(); /// Call to access the field components at a given location virtual void fieldComponents(const double* pos, double* field) = 0; }; @@ -125,7 +125,7 @@ namespace DD4hep { /// Default constructor Object(); /// Default destructor - ~Object(); + virtual ~Object(); }; /// Default constructor diff --git a/DDCore/include/DD4hep/IDDescriptor.h b/DDCore/include/DD4hep/IDDescriptor.h index b2f9e81ce773dcc51cf7ada74cfe329436fb7149..906148cdbd92a1ba70aa0363783e23e48cb0de76 100644 --- a/DDCore/include/DD4hep/IDDescriptor.h +++ b/DDCore/include/DD4hep/IDDescriptor.h @@ -66,7 +66,7 @@ namespace DD4hep { /// Standard constructor Object(); /// Default destructor - ~Object(); + virtual ~Object(); }; public: /// Default constructor diff --git a/DDCore/include/DD4hep/Objects.h b/DDCore/include/DD4hep/Objects.h index 9e69323896ef18c3680d0e334cd6edf9cc4d2211..d75a40708052de361caffda9ab57baff1f02190c 100644 --- a/DDCore/include/DD4hep/Objects.h +++ b/DDCore/include/DD4hep/Objects.h @@ -105,7 +105,7 @@ namespace DD4hep { /// Standard constructor Object(); /// Default destructor - ~Object(); + virtual ~Object(); }; /// Default constructor Header() : Ref_t() {} @@ -270,7 +270,7 @@ namespace DD4hep { /// Standard constructor Object(); /// Default destructor - ~Object(); + virtual ~Object(); }; /// Default constructor VisAttr() : Ref_t() {} @@ -380,7 +380,7 @@ namespace DD4hep { /// Standard constructor Object(); /// Default destructor - ~Object(); + virtual ~Object(); }; /// Constructor to be used when reading the already parsed DOM tree LimitSet() : Ref_t() {} @@ -411,7 +411,7 @@ namespace DD4hep { /// Standard constructor Object(); /// Default destructor - ~Object(); + virtual ~Object(); }; /// Default constructor Region() : Ref_t() {} diff --git a/DDCore/include/DD4hep/Readout.h b/DDCore/include/DD4hep/Readout.h index 690064105b75f6e0dee1eb741f3e9f8b7bb1d3ac..2321408ad5aed8e9df474337646402606bd6cf1f 100644 --- a/DDCore/include/DD4hep/Readout.h +++ b/DDCore/include/DD4hep/Readout.h @@ -49,7 +49,7 @@ namespace DD4hep { /// Standard constructor Object(); /// Default destructor - ~Object(); + virtual ~Object(); }; public: /// Default constructor @@ -76,6 +76,10 @@ namespace DD4hep { struct Alignment : public Ref_t { struct Object : public TNamed { Volume volume; + /// Standard constructor + Object(); + /// Default destructor + virtual ~Object(); }; /// Default constructor Alignment() : Ref_t() {} @@ -94,6 +98,10 @@ namespace DD4hep { */ struct Conditions : public Ref_t { struct Object : public TNamed { + /// Standard constructor + Object(); + /// Default destructor + virtual ~Object(); }; /// Default constructor Conditions() : Ref_t() {} diff --git a/DDCore/include/DD4hep/Segmentations.h b/DDCore/include/DD4hep/Segmentations.h index e8e85295855866addbe355136a2882d457697ff8..6ad3dc724b4b6b40aac62c147ac0d3684775bf31 100644 --- a/DDCore/include/DD4hep/Segmentations.h +++ b/DDCore/include/DD4hep/Segmentations.h @@ -85,7 +85,7 @@ namespace DD4hep { /// Standard constructor Object(); /// Default destructor - ~Object(); + virtual ~Object(); }; protected: diff --git a/DDCore/include/DD4hep/Shapes.h b/DDCore/include/DD4hep/Shapes.h index 9bbf52314c66a354d27612fbfeecc9028119beaf..0450a1029aa9447dac8fe7256959377e242fcd8b 100644 --- a/DDCore/include/DD4hep/Shapes.h +++ b/DDCore/include/DD4hep/Shapes.h @@ -219,7 +219,7 @@ namespace DD4hep { double GetRmin() const { return GetRmin1(); } double GetRmax() const { return GetRmax1(); } }; - struct Tube : public Solid_type<TGeoTubeSeg /* MyConeSeg */> { + struct Tube : public Solid_type< /*TGeoTubeSeg */ MyConeSeg > { protected: void make(const std::string& name,double rmin,double rmax,double z,double startPhi,double deltaPhi); diff --git a/DDCore/include/DD4hep/VolumeManager.h b/DDCore/include/DD4hep/VolumeManager.h index 6efe4fbea6d3731741cb2de403ede32b05ed26c4..50904a21f24b0f9a055574bd44bd8494015e878e 100644 --- a/DDCore/include/DD4hep/VolumeManager.h +++ b/DDCore/include/DD4hep/VolumeManager.h @@ -179,7 +179,7 @@ namespace DD4hep { /// Default constructor Object(); /// Default destructor - ~Object(); + virtual ~Object(); /// Search the locally cached volumes for a matching ID Context* search(const VolIdentifier& id) const; }; diff --git a/DDCore/include/DD4hep/Volumes.h b/DDCore/include/DD4hep/Volumes.h index 2b0178bbf7936118ea7072b8b1d318f61dcc2f1c..3637e11dc5cc7a53fa6f04c523fdebb1127fa893 100644 --- a/DDCore/include/DD4hep/Volumes.h +++ b/DDCore/include/DD4hep/Volumes.h @@ -47,7 +47,7 @@ namespace DD4hep { * @author M.Frank * @version 1.0 */ - struct PlacedVolume : Handle<TGeoNodeMatrix> { + struct PlacedVolume : Handle<TGeoNode> { typedef std::pair<std::string,int> VolID; struct VolIDs : public std::vector<VolID> { typedef std::vector<VolID> Base; @@ -66,18 +66,18 @@ namespace DD4hep { /// Copy constructor Object(const Object& c); /// Default destructor - ~Object(); + virtual ~Object(); /// Assignment operator Object& operator=(const Object& c) { magic=c.magic; volIDs=c.volIDs; return *this; } }; /// Constructor to be used when reading the already parsed DOM tree - PlacedVolume(const TGeoNode* e) : Handle<TGeoNodeMatrix>(e) {} + PlacedVolume(const TGeoNode* e) : Handle<TGeoNode>(e) {} /// Default constructor - PlacedVolume() : Handle<TGeoNodeMatrix>() {} + PlacedVolume() : Handle<TGeoNode>() {} /// Copy assignment - PlacedVolume(const PlacedVolume& e) : Handle<TGeoNodeMatrix>(e) {} + PlacedVolume(const PlacedVolume& e) : Handle<TGeoNode>(e) {} /// Copy assignment from other handle type - template <typename T> PlacedVolume(const Handle<T>& e) : Handle<TGeoNodeMatrix>(e) {} + template <typename T> PlacedVolume(const Handle<T>& e) : Handle<TGeoNode>(e) {} /// Assignment operator (must match copy constructor) PlacedVolume& operator=(const PlacedVolume& v) { m_element=v.m_element; return *this; } @@ -116,7 +116,7 @@ namespace DD4hep { /// Default constructor Object(); /// Default destructor - ~Object(); + virtual ~Object(); void copy(const Object& c) { magic=c.magic; region=c.region; diff --git a/DDCore/src/IDDescriptor.cpp b/DDCore/src/IDDescriptor.cpp index 1fa4668dbc1e58f19714d84090e046800625e5e5..671b2549994aa6f05d037f39e9b4c39af56481a1 100644 --- a/DDCore/src/IDDescriptor.cpp +++ b/DDCore/src/IDDescriptor.cpp @@ -109,7 +109,7 @@ IDDescriptor::Field IDDescriptor::field(const string& field_name) const { const FieldMap& m = fields(); // This already checks the object validity for(FieldMap::const_iterator i=m.begin(); i!=m.end(); ++i) if ( (*i).first == field_name ) return (*i).second; - throw runtime_error(string(name())+": This ID descriptor has now field with the name:"+field_name); + throw runtime_error(string(name())+": This ID descriptor has no field with the name:"+field_name); } /// Get the field descriptor of one field by its identifier @@ -123,5 +123,5 @@ size_t IDDescriptor::fieldID(const string& field_name) const { const FieldIDs& m = ids(); // This already checks the object validity for(FieldIDs::const_iterator i=m.begin(); i!=m.end(); ++i) if ( (*i).second == field_name ) return (*i).first; - throw runtime_error(string(name())+": This ID descriptor has now field with the name:"+field_name); + throw runtime_error(string(name())+": This ID descriptor has no field with the name:"+field_name); } diff --git a/DDCore/src/LCDDImp.cpp b/DDCore/src/LCDDImp.cpp index 22a68501d851a8a32f916cc82e9d34599421c783..5722b5586da341fc3a8fca5e2bf9c7d81bd0fb11 100644 --- a/DDCore/src/LCDDImp.cpp +++ b/DDCore/src/LCDDImp.cpp @@ -61,9 +61,12 @@ LCDDImp::LCDDImp() { InstanceCount::increment(this); m_properties = new Properties(); - //if ( 0 == gGeoManager ) + if ( 0 == gGeoManager ) { - m_manager = gGeoManager = new TGeoManager(); + gGeoManager = new TGeoManager(); + } + { + m_manager = gGeoManager; m_manager->AddNavigator(); m_manager->SetCurrentNavigator(0); //cout << "Navigator:" << (void*)m_manager->GetCurrentNavigator() << endl; @@ -95,14 +98,11 @@ LCDDImp::~LCDDImp() { for_each(m_idDict.begin(), m_idDict.end(), del); for_each(m_limits.begin(), m_limits.end(), del); for_each(m_regions.begin(), m_regions.end(), del); - //for_each(m_detectors.begin(), m_detectors.end(), del); for_each(m_alignments.begin(), m_alignments.end(), del); for_each(m_sensitive.begin(), m_sensitive.end(), del); for_each(m_display.begin(), m_display.end(), del); for_each(m_fields.begin(), m_fields.end(), del); for_each(m_define.begin(), m_define.end(), del); - // for_each(m_materials.begin(), m_materials.end(), del); - //for_each(.begin(), .end(), del); m_trackers.clear(); m_worldVol.clear(); @@ -223,145 +223,8 @@ namespace { } } } - - typedef DetElement::Children _C; - DetElement findElt(DetElement e, PlacedVolume pv) { - const _C& children = e.children(); - if ( e.placement().ptr() == pv.ptr() ) return e; - for(_C::const_iterator i=children.begin(); i!=children.end(); ++i) { - DetElement de = (*i).second; - if ( de.placement().ptr() == pv.ptr() ) return de; - } - for(_C::const_iterator i=children.begin(); i!=children.end(); ++i) { - DetElement de = findElt((*i).second,pv); - if ( de.isValid() ) return de; - } - return DetElement(); - } - - unsigned long long int encode_cell(Readout ro, const PlacedVolume::VolIDs& ids) { - unsigned long long value = ~0x0ull; - const IDDescriptor& en = ro.idSpec(); - for(PlacedVolume::VolIDs::const_iterator i=ids.begin(); i!=ids.end(); ++i) { - const PlacedVolume::VolID& id = (*i); - value &= en.field(id.first).encode(id.second); - } - return value; - } - - typedef void (::ShapePatcher::*Func_t)(DetElement parent, DetElement e,const TGeoNode* n, - const PlacedVolume::VolIDs& ids, - const vector<const TGeoNode*>& nodes, - const vector<const TGeoNode*>& elt_nodes); - - void scanNode(Func_t func, - DetElement parent, DetElement e, PlacedVolume pv, - const PlacedVolume::VolIDs& vol_ids, - vector<const TGeoNode*>& nodes, - vector<const TGeoNode*>& elt_nodes) - { - const TGeoNode* node = dynamic_cast<const TGeoNode*>(pv.ptr()); - if ( node ) { - Int_t ndau = node->GetNdaughters(); - PlacedVolume::VolIDs ids(vol_ids); - const PlacedVolume::VolIDs& ids_node = pv.volIDs(); - - nodes.push_back(node); - elt_nodes.push_back(node); - ids.PlacedVolume::VolIDs::Base::insert(ids.end(),ids_node.begin(),ids_node.end()); - (this->*func)(parent, e, node, ids, nodes, elt_nodes); - for(Int_t idau=0; idau<ndau; ++idau) { - TGeoNode* daughter = node->GetDaughter(idau); - if ( dynamic_cast<const PlacedVolume::Object*>(daughter) ) { - PlacedVolume pv_dau = Ref_t(daughter); - DetElement de_dau = findElt(e,daughter); - if ( de_dau.isValid() ) { - vector<const TGeoNode*> dau_nodes; - scanNode(func, parent, de_dau, pv_dau, ids, nodes, dau_nodes); - } - else { - scanNode(func, parent, e, pv_dau, ids, nodes, elt_nodes); - } - } - } - elt_nodes.pop_back(); - nodes.pop_back(); - } - } - void scanVolumes(Func_t func) { - const _C& children = m_world.children(); - for(_C::const_iterator i=children.begin(); i!=children.end(); ++i) { - DetElement de = (*i).second; - PlacedVolume pv = de.placement(); - if ( pv.isValid() ) { - PlacedVolume::VolIDs ids; - vector<const TGeoNode*> nodes, elt_nodes; - scanNode(func, de, de, pv, ids, nodes, elt_nodes); - continue; - } - cout << "++ Detector element " << de.name() << " has no placement." << endl; - } - } - - void print_node(DetElement parent, DetElement e,const TGeoNode* n, - const PlacedVolume::VolIDs& ids, - const vector<const TGeoNode*>& nodes, - const vector<const TGeoNode*>& elt_nodes); - - GeoScan& printVolumes() { - scanVolumes(&ShapePatcher::print_node); - return *this; - } }; - void ShapePatcher::print_node(DetElement parent, - DetElement e, - const TGeoNode* n, - const PlacedVolume::VolIDs& ids, - const vector<const TGeoNode*>& nodes, - const vector<const TGeoNode*>& elt_nodes) - { - static int s_count = 0; - Volume vol = PlacedVolume(n).volume(); - SensitiveDetector sd = vol.sensitiveDetector(); - Readout ro = sd.readout(); - const IDDescriptor& en = ro.idSpec(); - IDDescriptor::VolumeID volume_id = encode_cell(ro,ids); - PlacedVolume pv = Ref_t(n); - bool sensitive = pv.volume().isSensitive(); - - if ( !sensitive ) return; - ++s_count; - cout << s_count << ": " << e.name() << " de:" << e.ptr() << " ro:" << ro.ptr() - << " pv:" << n->GetName() << " id:" << (void*)volume_id << " : "; - for(PlacedVolume::VolIDs::const_iterator i=ids.begin(); i!=ids.end(); ++i) { - const PlacedVolume::VolID& id = (*i); - IDDescriptor::Field f = ro.idSpec().field(id.first); - int value = en.field(id.first).decode(volume_id); - cout << id.first << "=" << id.second << "," << value - << " [" << f.first << "," << f.second << "] "; - } - cout << " Sensitive:" << (sensitive ? "YES" : "NO"); - if ( sensitive ) { - VolumeManager section = m_volManager.subdetector(volume_id); - VolumeManager::Context* ctxt = section.lookupContext(volume_id|0xDEAD); - if ( ctxt->placement.ptr() != pv.ptr() ) { - cout << " !!!!! No Volume found!" << endl; - } - cout << " Pv:" << pv.ptr() << " <> " << ctxt->placement.ptr(); - } - cout << endl; -#if 0 - cout << s_count << ": " << e.name() << " Detector GeoNodes:"; - for(vector<const TGeoNode*>::const_iterator j=nodes.begin(); j!=nodes.end();++j) - cout << (void*)(*j) << " "; - cout << endl; - cout << s_count << ": " << e.name() << " Element GeoNodes:"; - for(vector<const TGeoNode*>::const_iterator j=elt_nodes.begin(); j!=elt_nodes.end();++j) - cout << (void*)(*j) << " "; - cout << endl; -#endif - } } void LCDDImp::endDocument() { @@ -394,13 +257,9 @@ void LCDDImp::endDocument() { /// Since we allow now for anonymous shapes, /// we will rename them to use the name of the volume they are assigned to mgr->CloseGeometry(); - m_world.setPlacement(PlacedVolume(mgr->GetTopNode())); - m_volManager = VolumeManager("World", m_world, Readout(), VolumeManager::TREE); + m_world.setPlacement(PlacedVolume(mgr->GetTopNode())); ShapePatcher patcher(m_volManager,m_world); patcher.patchShapes(); - //patcher.printVolumes(); - //cout << m_volManager << endl; - cout << "++ Volume manager populated and shaped names successfully updated." << endl; } } @@ -452,15 +311,13 @@ void LCDDImp::fromXML(const string& xmlfile, LCDDBuildType build_type) { } } catch(const XML::XmlException& e) { - cout << "XML-DOM Exception:" << XML::_toString(e.msg) << endl; - throw runtime_error("XML-DOM Exception:\""+XML::_toString(e.msg)+"\" while parsing "+xmlfile); + throw runtime_error("XML-DOM Exception:\n\""+XML::_toString(e.msg)+ + "\"\n while parsing "+xmlfile); } catch(const exception& e) { - cout << "Exception:" << e.what() << endl; - throw runtime_error("Exception:\""+string(e.what())+"\" while parsing "+xmlfile); + throw runtime_error(string(e.what())+"\n while parsing "+xmlfile); } catch(...) { - cout << "UNKNOWN Exception" << endl; throw runtime_error("UNKNOWN exception while parsing "+xmlfile); } #endif diff --git a/DDCore/src/Readout.cpp b/DDCore/src/Readout.cpp index 3b425a5d28abb1a40f189676bc5e7a9bee15c97c..29b0c5cf7de26e178c0acdd2c25b4f1abe80ea03 100644 --- a/DDCore/src/Readout.cpp +++ b/DDCore/src/Readout.cpp @@ -34,7 +34,7 @@ Readout::Readout(const string& nam) void Readout::setIDDescriptor(const Ref_t& new_descriptor) const { if ( isValid() ) { // Remember: segmentation is NOT owned by readout structure! if ( new_descriptor.isValid() ) { // Do NOT delete! - object<Object>().id = new_descriptor; + data<Object>()->id = new_descriptor; return; } } @@ -67,12 +67,32 @@ Segmentation Readout::segmentation() const { return object<Object>().segmentation; } +/// Standard constructor +Alignment::Object::Object() { + InstanceCount::increment(this); +} + +/// Default destructor +Alignment::Object::~Object() { + InstanceCount::decrement(this); +} + /// Initializing constructor to create a new object Alignment::Alignment(const LCDD& /* lcdd */, const string& nam) { assign(new Object(),nam,"alignment"); } +/// Standard constructor +Conditions::Object::Object() { + InstanceCount::increment(this); +} + +/// Default destructor +Conditions::Object::~Object() { + InstanceCount::decrement(this); +} + /// Initializing constructor to create a new object Conditions::Conditions(const LCDD& /* lcdd */, const string& nam) { diff --git a/DDCore/src/Shapes.cpp b/DDCore/src/Shapes.cpp index e447e0692d0507be288ae625568035114bd586c2..15bd7d971c823eca99e6a30af45ad3c15a588426 100644 --- a/DDCore/src/Shapes.cpp +++ b/DDCore/src/Shapes.cpp @@ -178,18 +178,16 @@ ConeSegment& ConeSegment::setDimensions(double dz, double rmin1, double rmax1, d /// Constructor to be used when creating a new object with attribute initialization void Tube::make(const string& name, double rmin, double rmax, double z, double startPhi, double deltaPhi) { - //_assign((TGeoTubeSeg*)new TGeoTube(rmin*MM_2_CM,rmax*MM_2_CM,z*MM_2_CM),name,"tube",true); - _assign(new TGeoTubeSeg(rmin*MM_2_CM,rmax*MM_2_CM,z*MM_2_CM,RAD_2_DEGREE*startPhi,RAD_2_DEGREE*deltaPhi),name,"tube",true); - //MyConeSeg* s = new MyConeSeg(); - //_assign(s,name,"tube",true); - //setDimensions(rmin,rmax,z,startPhi,deltaPhi); + //_assign(new TGeoTubeSeg(rmin*MM_2_CM,rmax*MM_2_CM,z*MM_2_CM,RAD_2_DEGREE*startPhi,RAD_2_DEGREE*deltaPhi),name,"tube",true); + _assign(new MyConeSeg(),name,"tube",true); + setDimensions(rmin,rmax,z,startPhi,deltaPhi); } /// Set the tube dimensions Tube& Tube::setDimensions(double rmin, double rmax, double z, double startPhi, double deltaPhi) { - double params[] = {rmin*MM_2_CM,rmax*MM_2_CM,z*MM_2_CM,RAD_2_DEGREE*startPhi,RAD_2_DEGREE*deltaPhi}; - //double params[] = {z*MM_2_CM,rmin*MM_2_CM,rmax*MM_2_CM,rmin*MM_2_CM,rmax*MM_2_CM,RAD_2_DEGREE*startPhi,RAD_2_DEGREE*deltaPhi}; + //double params[] = {rmin*MM_2_CM,rmax*MM_2_CM,z*MM_2_CM,RAD_2_DEGREE*startPhi,RAD_2_DEGREE*deltaPhi}; + double params[] = {z*MM_2_CM,rmin*MM_2_CM,rmax*MM_2_CM,rmin*MM_2_CM,rmax*MM_2_CM,RAD_2_DEGREE*startPhi,RAD_2_DEGREE*deltaPhi}; _setDimensions(params); return *this; } diff --git a/DDCore/src/VolumeManager.cpp b/DDCore/src/VolumeManager.cpp index 5806159e01225f6294125515a3de965356463a48..a11ae0e1912e7358788e6e96b0c98232260dddee 100644 --- a/DDCore/src/VolumeManager.cpp +++ b/DDCore/src/VolumeManager.cpp @@ -66,6 +66,11 @@ namespace { Volume vol = pv.volume(); node_chain.push_back(node); elt_nodes.push_back(node); +#if 0 + const PlacedVolume::VolIDs::Base& vids = pv.volIDs(); + for(PlacedVolume::VolIDs::Base::const_iterator i=vids.begin(); i!=vids.end(); ++i) + ids.push_back(*i); +#endif ids.PlacedVolume::VolIDs::Base::insert(ids.end(),pv.volIDs().begin(),pv.volIDs().end()); if ( vol.isSensitive() ) { SensitiveDetector sd = vol.sensitiveDetector(); diff --git a/DDCore/src/Volumes.cpp b/DDCore/src/Volumes.cpp index f296a4e7cb2a154531a09b6213e05af4375dea18..e588752ad34073d39d9c2fb9a664e8a0dbb2a1be 100644 --- a/DDCore/src/Volumes.cpp +++ b/DDCore/src/Volumes.cpp @@ -262,9 +262,13 @@ PlacedVolume::VolIDs::insert(const string& name, int value) { return make_pair(i,true); } +static PlacedVolume::Object* _data(const PlacedVolume& v) { + return dynamic_cast<PlacedVolume::Object*>(v.ptr()); +} + /// Add identifier PlacedVolume& PlacedVolume::addPhysVolID(const string& name, int value) { - Object* obj = data<Object>(); + Object* obj = _data(*this); obj->volIDs.push_back(VolID(name,value)); return *this; } @@ -283,12 +287,12 @@ Volume PlacedVolume::motherVol() const /// Access to the volume IDs const PlacedVolume::VolIDs& PlacedVolume::volIDs() const -{ return data<Object>()->volIDs; } +{ return _data(*this)->volIDs; } /// String dump string PlacedVolume::toString() const { stringstream s; - Object* obj = data<Object>(); + Object* obj = _data(*this); s << m_element->GetName() << ": vol='" << m_element->GetVolume()->GetName() << "' mat:'" << m_element->GetMatrix()->GetName() << "' volID[" << obj->volIDs.size() << "] "; for(VolIDs::const_iterator i=obj->volIDs.begin(); i!=obj->volIDs.end();++i) @@ -313,7 +317,7 @@ Volume::Object::~Object() { /// Accessor to the data part of the Volume Volume::Object* _data(const Volume& v) { - if ( v.ptr() && v.ptr()->IsA() == TGeoVolume::Class() ) return v.data<Volume::Object>(); + //if ( v.ptr() && v.ptr()->IsA() == TGeoVolume::Class() ) return v.data<Volume::Object>(); return dynamic_cast<Volume::Object*>(v.ptr()); } @@ -350,7 +354,7 @@ static PlacedVolume _addNode(TGeoVolume* par, TGeoVolume* daughter, TGeoMatrix* transform->SetName(nam.c_str()); } parent->AddNode(daughter,id,transform); - TGeoNodeMatrix* n = dynamic_cast<TGeoNodeMatrix*>(parent->GetNode(id)); + TGeoNode* n = parent->GetNode(id); return PlacedVolume(n); } @@ -513,7 +517,10 @@ void Volume::setSensitiveDetector(const SensitiveDetector& obj) const { /// Access to the handle to the sensitive detector Ref_t Volume::sensitiveDetector() const -{ return _data(*this)->sens_det; } +{ + const Object* o = _data(*this); + return o->sens_det; +} /// Accessor if volume is sensitive (ie. is attached to a sensitive detector) bool Volume::isSensitive() const diff --git a/DDCore/src/plugins/StandardPlugins.cpp b/DDCore/src/plugins/StandardPlugins.cpp index 9c2fcf1c7629a441895365ac33907edde995fd86..d1f3f9c60e82fd236edc0ce966a1bbf704a9a3e9 100644 --- a/DDCore/src/plugins/StandardPlugins.cpp +++ b/DDCore/src/plugins/StandardPlugins.cpp @@ -12,6 +12,7 @@ // Framework include files #include "DD4hep/Factories.h" #include "DD4hep/LCDD.h" +#include "../LCDDImp.h" // ROOT includes #include "TGeoManager.h" @@ -52,3 +53,19 @@ static long load_compact(LCDD& lcdd,int argc,char** argv) { } DECLARE_APPLY(DD4hepCompactLoader,load_compact); +static long load_volmgr(LCDD& lcdd,int,char**) { + try { + LCDDImp* imp = dynamic_cast<LCDDImp*>(&lcdd); + imp->m_volManager = VolumeManager("World", imp->world(), Readout(), VolumeManager::TREE); + cout << "++ Volume manager populated and loaded." << endl; + } + catch(const exception& e) { + throw runtime_error(string(e.what())+"\n" + " while programming VolumeManager. Are your volIDs correct?"); + } + catch(...) { + throw runtime_error("UNKNOWN exception while programming VolumeManager. Are your volIDs correct?"); + } + return 1; +} +DECLARE_APPLY(DD4hepVolumeManager,load_volmgr); diff --git a/DDExamples/ILDExDet/src/compact/ILDExSIT_geo.cpp b/DDExamples/ILDExDet/src/compact/ILDExSIT_geo.cpp index efb9ddf72b0c2cae40d2afd503740e8c358b32dc..3cae843fdb5e1bb5e59b6748c989f3afe3b341ce 100644 --- a/DDExamples/ILDExDet/src/compact/ILDExSIT_geo.cpp +++ b/DDExamples/ILDExDet/src/compact/ILDExSIT_geo.cpp @@ -79,6 +79,7 @@ static Ref_t create_element(LCDD& lcdd, xml_h e, SensitiveDetector sens) { } } pv = lcdd.pickMotherVolume(sit).placeVolume(assembly); + pv.addPhysVolID("system",x_det.id()); sit.setPlacement(pv); return sit; } diff --git a/DDExamples/ILDExDet/src/compact/Tesla_VXD03_geo.cpp b/DDExamples/ILDExDet/src/compact/Tesla_VXD03_geo.cpp index 583a0065206b37060d59beb38cba618a7ad3b2d7..3ac27c4d8e2e6aa1af13d8f56c631f5488ba245e 100644 --- a/DDExamples/ILDExDet/src/compact/Tesla_VXD03_geo.cpp +++ b/DDExamples/ILDExDet/src/compact/Tesla_VXD03_geo.cpp @@ -326,6 +326,7 @@ static Ref_t create_element(LCDD& lcdd, xml_h e, SensitiveDetector sens) { assembly.setVisAttributes(lcdd.visAttributes(x_det.visStr())); PlacedVolume lpv = motherVol.placeVolume(assembly); + lpv.addPhysVolID("system",x_det.id()); vxd.setPlacement(lpv); return vxd; } diff --git a/DDExamples/UtilityApps/src/converter.cpp b/DDExamples/UtilityApps/src/converter.cpp index c306fc1a36ec39bdd30e498b9e5e13b5ab2b6cb0..66ee4b9944b3d3e142af565ff81fc659fd6981b1 100644 --- a/DDExamples/UtilityApps/src/converter.cpp +++ b/DDExamples/UtilityApps/src/converter.cpp @@ -27,6 +27,8 @@ namespace { " [Only valid for -compact2vis] \n" " -destroy [OPTIONAL] Force destruction of the LCDD instance \n" " before exiting the application \n" + " -volmgr [OPTIONAL] Load and populate phys.volume manager to \n" + " check the volume ids for duplicates etc. \n" << endl; exit(EINVAL); } @@ -36,6 +38,7 @@ namespace { //______________________________________________________________________________ int main(int argc,char** argv) { bool ascii = false; + bool volmgr = false; bool destroy = false; bool compact2lcdd = false; bool compact2gdml = false; @@ -61,6 +64,8 @@ int main(int argc,char** argv) { ascii = true; else if ( strncmp(argv[i],"-destroy",2)==0 ) destroy = true; + else if ( strncmp(argv[i],"-volmgr",2)==0 ) + volmgr = true; else usage(); } @@ -84,6 +89,7 @@ int main(int argc,char** argv) { run_plugin(lcdd,"DD4hepGeometry2VISASCII",output,&argv[output]); else if ( compact2vis ) run_plugin(lcdd,"DD4hepGeometry2VIS",output,&argv[output]); + if ( volmgr ) run_plugin(lcdd,"DD4hepVolumeManager",0,0); if ( destroy ) delete &lcdd; return 0; } diff --git a/DDExamples/UtilityApps/src/display.cpp b/DDExamples/UtilityApps/src/display.cpp index 46eaf350bdd205280619f6fbb278fc2f215f54ee..abb2c9cf7dea41f8d3da0df25350fd9889815da9 100644 --- a/DDExamples/UtilityApps/src/display.cpp +++ b/DDExamples/UtilityApps/src/display.cpp @@ -21,6 +21,8 @@ namespace { " starting the dispay. \n" " -destroy [OPTIONAL] Force destruction of the LCDD instance \n" " before exiting the application \n" + " -volmgr [OPTIONAL] Load and populate phys.volume manager to \n" + " check the volume ids for duplicates etc. \n" << endl; exit(EINVAL); } @@ -28,6 +30,7 @@ namespace { //______________________________________________________________________________ int main(int argc,char** argv) { + bool volmgr = false; bool dry_run = false, destroy = false; vector<char*> geo_files; for(int i=1; i<argc;++i) { @@ -38,6 +41,8 @@ int main(int argc,char** argv) { dry_run = true; else if ( strncmp(argv[i],"-destroy",2)==0 ) destroy = true; + else if ( strncmp(argv[i],"-volmgr",2)==0 ) + volmgr = true; else usage(); } @@ -51,6 +56,9 @@ int main(int argc,char** argv) { LCDD& lcdd = dd4hep_instance(); // Load all compact files run_plugin(lcdd,"DD4hepCompactLoader",int(geo_files.size()),&geo_files[0]); + // Create volume manager and populate it required + if ( volmgr ) run_plugin(lcdd,"DD4hepVolumeManager",0,0); + // Create an interactive ROOT application if ( !dry_run ) { pair<int, char**> args(0,0); diff --git a/DDExamples/UtilityApps/src/plugin_runner.cpp b/DDExamples/UtilityApps/src/plugin_runner.cpp index d5787d2584571ea19c87236ab018a75acb34f489..5c98e619c391334b3f65596132ff6f3886e9caf9 100644 --- a/DDExamples/UtilityApps/src/plugin_runner.cpp +++ b/DDExamples/UtilityApps/src/plugin_runner.cpp @@ -18,6 +18,8 @@ namespace { " -input <file> [REQUIRED] Specify input file. \n" " -destroy [OPTIONAL] Force destruction of the LCDD instance \n" " before exiting the application \n" + " -volmgr [OPTIONAL] Load and populate phys.volume manager to \n" + " check the volume ids for duplicates etc. \n" << endl; exit(EINVAL); } @@ -26,6 +28,7 @@ namespace { //______________________________________________________________________________ int main(int argc,char** argv) { string plugin; + bool volmgr = false; bool destroy = false; vector<char*> geo_files; for(int i=1; i<argc;++i) { @@ -36,6 +39,8 @@ int main(int argc,char** argv) { plugin = argv[++i]; else if ( strncmp(argv[i],"-destroy",2)==0 ) destroy = true; + else if ( strncmp(argv[i],"-volmgr",2)==0 ) + volmgr = true; else usage(); } @@ -51,6 +56,7 @@ int main(int argc,char** argv) { run_plugin(lcdd,"DD4hepCompactLoader",int(geo_files.size()),&geo_files[0]); // Execute plugin run_plugin(lcdd,plugin.c_str(),0,0); + if ( volmgr ) run_plugin(lcdd,"DD4hepVolumeManager",0,0); if ( destroy ) delete &lcdd; return 0; } diff --git a/doc/Volumes.cpp b/doc/Volumes.cpp new file mode 100644 index 0000000000000000000000000000000000000000..b5d3d8116e4045a02d2ca08e91add9171b05f282 --- /dev/null +++ b/doc/Volumes.cpp @@ -0,0 +1,395 @@ +// $Id: Volumes.cpp 574 2013-05-17 20:38:31Z markus.frank $ +//==================================================================== +// AIDA Detector description implementation for LCD +//-------------------------------------------------------------------- +// +// Author : M.Frank +// +//==================================================================== + +// Framework include files +#include "DD4hep/LCDD.h" +#include "DD4hep/InstanceCount.h" + +// ROOT include files +#include "TColor.h" +#include "TGeoShape.h" +#include "TGeoVolume.h" +#include "TGeoNode.h" +#include "TGeoMatrix.h" +#include "TGeoMedium.h" +#include "TGeoVoxelFinder.h" +#include "TGeoShapeAssembly.h" + +// C/C++ include files +#include <climits> +#include <iostream> +#include <stdexcept> +#include <sstream> + +using namespace std; +using namespace DD4hep::Geometry; + +/// Default constructor +PlacedVolume::Object::Object() : refCount(0), magic(0), volIDs() { + InstanceCount::increment(this); +} + +/// Copy constructor +PlacedVolume::Object::Object(const Object& c) : refCount(0), magic(c.magic), volIDs(c.volIDs) { + InstanceCount::increment(this); +} + +/// Default destructor +PlacedVolume::Object::~Object() { + InstanceCount::decrement(this); +} + +/// TGeoExtension overload: Method called whenever requiring a pointer to the extension +TGeoExtension* PlacedVolume::Object::Grab() const { + Object* ext = const_cast<Object*>(this); + ++ext->refCount; + return ext; +} + +/// TGeoExtension overload: Method called always when the pointer to the extension is not needed anymore +void PlacedVolume::Object::Release() const { + Object* ext = const_cast<Object*>(this); + --ext->refCount; + if ( 0 == ext->refCount ) delete ext; +} + +/// Lookup volume ID +vector<PlacedVolume::VolID>::const_iterator +PlacedVolume::VolIDs::find(const string& name) const { + for(Base::const_iterator i=this->Base::begin(); i!=this->Base::end(); ++i) + if ( name == (*i).first ) return i; + return this->end(); +} + +/// Insert a new value into the volume ID container +std::pair<vector<PlacedVolume::VolID>::iterator,bool> +PlacedVolume::VolIDs::insert(const string& name, int value) { + Base::iterator i = this->Base::begin(); + for(; i!=this->Base::end(); ++i) + if ( name == (*i).first ) break; + // + if ( i != this->Base::end() ) { + return make_pair(i,false); + } + i = this->Base::insert(this->Base::end(),make_pair(name,value)); + return make_pair(i,true); +} + +/// Accessor to user structure +PlacedVolume::Object& PlacedVolume::data() const { + Object* o = (Object*)(ptr()->GetUserExtension()); + return *o; +} + +/// Add identifier +PlacedVolume& PlacedVolume::addPhysVolID(const string& name, int value) { + data().volIDs.push_back(VolID(name,value)); + return *this; +} + +/// Volume material +Material PlacedVolume::material() const +{ return Material::handle_t(m_element ? m_element->GetMedium() : 0); } + +/// Logical volume of this placement +Volume PlacedVolume::volume() const +{ return Volume::handle_t(m_element ? m_element->GetVolume() : 0); } + +/// Parent volume (envelope) +Volume PlacedVolume::motherVol() const +{ return Volume::handle_t(m_element ? m_element->GetMotherVolume() : 0); } + +/// Access to the volume IDs +const PlacedVolume::VolIDs& PlacedVolume::volIDs() const +{ return data().volIDs; } + +/// String dump +string PlacedVolume::toString() const { + stringstream s; + Object& obj = data(); + s << m_element->GetName() << ": vol='" << m_element->GetVolume()->GetName() + << "' mat:'" << m_element->GetMatrix()->GetName() << "' volID[" << obj.volIDs.size() << "] "; + for(VolIDs::const_iterator i=obj.volIDs.begin(); i!=obj.volIDs.end();++i) + s << (*i).first << "=" << (*i).second << " "; + s << ends; + return s.str(); +} + +/// Default constructor +Volume::Object::Object() : refCount(0), magic(0), region(), limits(), vis(), sens_det() { + InstanceCount::increment(this); +} + +/// Default destructor +Volume::Object::~Object() { + vis.clear(); + region.clear(); + limits.clear(); + sens_det.clear(); + InstanceCount::decrement(this); +} + +/// TGeoExtension overload: Method called whenever requiring a pointer to the extension +TGeoExtension* Volume::Object::Grab() const { + Object* ext = const_cast<Object*>(this); + ++ext->refCount; + return ext; +} + +/// TGeoExtension overload: Method called always when the pointer to the extension is not needed anymore +void Volume::Object::Release() const { + Object* ext = const_cast<Object*>(this); + --ext->refCount; + if ( 0 == ext->refCount ) { + delete ext; + } + else { + cout << "Volume::Object::Release::refCount:" << ext->refCount << endl; + } +} + +/// Constructor to be used when creating a new geometry tree. +Volume::Volume(const string& name) { + m_element = new TGeoVolume(); + m_element->SetName(name.c_str()); + m_element->SetUserExtension(new Object()); +} + +/// Constructor to be used when creating a new geometry tree. Also sets materuial and solid attributes +Volume::Volume(const string& name, const Solid& s, const Material& m) { + m_element = new TGeoVolume(name.c_str(), s.ptr(), m.ptr()); + m_element->SetUserExtension(new Object()); +} + +/// Accessor to user structure +Volume::Object& Volume::data() const { + Object* o = (Object*)(ptr()->GetUserExtension()); + return *o; +} + +/// Set the volume's material +void Volume::setMaterial(const Material& m) const { + if ( m.isValid() ) { + TGeoMedium* medium = m._ptr<TGeoMedium>(); + if ( medium ) { + m_element->SetMedium(medium); + return; + } + throw runtime_error("Volume: Medium "+string(m.name())+" is not registered with geometry manager."); + } + throw runtime_error("Volume: Attempt to assign invalid material."); +} + +static PlacedVolume _addNode(TGeoVolume* par, TGeoVolume* daughter, TGeoMatrix* transform) { + TGeoVolume* parent = par; + TObjArray* a = parent->GetNodes(); + Int_t id = a ? a->GetEntries() : 0; + if ( transform && transform != identityTransform() ) { + string nam = string(daughter->GetName())+"_placement"; + transform->SetName(nam.c_str()); + } + parent->AddNode(daughter,id,transform); + TGeoNodeMatrix* n = dynamic_cast<TGeoNodeMatrix*>(parent->GetNode(id)); + PlacedVolume pv(n); + pv->SetUserExtension(new PlacedVolume::Object()); + return pv; +} + +static TGeoTranslation* _translation(const Position& pos) { + return new TGeoTranslation("",pos.X()*MM_2_CM,pos.Y()*MM_2_CM,pos.Z()*MM_2_CM); +} + +static TGeoRotation* _rotation(const Rotation& rot) { + return new TGeoRotation("",rot.Phi()*RAD_2_DEGREE,rot.Theta()*RAD_2_DEGREE,rot.Psi()*RAD_2_DEGREE); +} + +/// Place daughter volume according to generic Transform3D +PlacedVolume Volume::placeVolume(const Volume& volume, const Transform3D& tr) const { + Rotation rot; + Position pos; + tr.GetDecomposition(rot,pos); + return placeVolume(volume,rot,pos); +} + +/// Place translated and rotated daughter volume +PlacedVolume Volume::placeVolume(const Volume& volume, const Position& pos, const Rotation& rot) const { + if ( volume.isValid() ) { + TGeoCombiTrans* transform = new TGeoCombiTrans("",pos.X()*MM_2_CM,pos.Y()*MM_2_CM,pos.Z()*MM_2_CM,_rotation(rot)); + return _addNode(m_element,volume,transform); + } + throw runtime_error("Volume: Attempt to assign an invalid physical volume."); +} + +/// Place daughter volume in rotated and then translated mother coordinate system +PlacedVolume Volume::placeVolume(const Volume& volume, const Rotation& rot, const Position& pos) const { + if ( volume.isValid() ) { + TGeoHMatrix *trans = new TGeoHMatrix(); + double t[3]; + trans->RotateZ(rot.Phi()*RAD_2_DEGREE); + trans->RotateY(rot.Theta()*RAD_2_DEGREE); + trans->RotateX(rot.Psi()*RAD_2_DEGREE); + pos.GetCoordinates(t); + trans->SetDx(t[0]*MM_2_CM); + trans->SetDy(t[1]*MM_2_CM); + trans->SetDz(t[2]*MM_2_CM); + return _addNode(m_element,volume,trans); + } + throw runtime_error("Volume: Attempt to assign an invalid physical volume."); +} + +/// Place un-rotated daughter volume at the given position. +PlacedVolume Volume::placeVolume(const Volume& volume, const Position& pos) const { + if ( volume.isValid() ) { + return _addNode(m_element,volume,_translation(pos)); + } + throw runtime_error("Volume: Attempt to assign an invalid physical volume."); +} + +/// Place rotated daughter volume. The position is automatically the identity position +PlacedVolume Volume::placeVolume(const Volume& volume, const Rotation& rot) const { + if ( volume.isValid() ) { + return _addNode(m_element,volume,_rotation(rot)); + } + throw runtime_error("Volume: Attempt to assign an invalid physical volume."); +} + +/// Place daughter volume. The position and rotation are the identity +PlacedVolume Volume::placeVolume(const Volume& volume, const IdentityPos& /* pos */) const { + if ( volume.isValid() ) { + return _addNode(m_element,volume,identityTransform()); + } + throw runtime_error("Volume: Attempt to assign an invalid physical volume."); +} + +/// Place daughter volume. The position and rotation are the identity +PlacedVolume Volume::placeVolume(const Volume& volume, const IdentityRot& /* rot */) const { + if ( volume.isValid() ) { + return _addNode(m_element,volume,identityTransform()); + } + throw runtime_error("Volume: Attempt to assign an invalid physical volume."); +} + +/// Set Visualization attributes to the volume +void Volume::setVisAttributes(const VisAttr& attr) const { + if ( attr.isValid() ) { + VisAttr::Object* vis = attr.data<VisAttr::Object>(); + Color_t bright = TColor::GetColorBright(vis->color); + Color_t dark = TColor::GetColorDark(vis->color); + int draw_style = vis->drawingStyle; + int line_style = vis->lineStyle; + m_element->SetLineColor(dark); + if ( draw_style == VisAttr::SOLID ) { + m_element->SetFillColor(bright); + m_element->SetFillStyle(1001); // Root: solid + } + else { + m_element->SetFillColor(0); + m_element->SetFillStyle(0); // Root: hollow + } + if ( line_style == VisAttr::SOLID ) + m_element->SetFillStyle(1); + else if ( line_style == VisAttr::DASHED ) + m_element->SetFillStyle(2); + else + m_element->SetFillStyle(line_style); + + m_element->SetLineWidth(10); + m_element->SetVisibility(vis->visible ? kTRUE : kFALSE); + m_element->SetAttBit(TGeoAtt::kVisContainers,kTRUE); + m_element->SetVisDaughters(vis->showDaughters ? kTRUE : kFALSE); + } + data().vis = attr; +} + +/// Set Visualization attributes to the volume +void Volume::setVisAttributes(const LCDD& lcdd, const string& name) const { + if ( !name.empty() ) { + VisAttr attr = lcdd.visAttributes(name); + data().vis = attr; + setVisAttributes(attr); + } + else { + /* + string tag = this->name(); + if ( ::strstr(tag.c_str(),"_slice") ) // Slices turned off by default + setVisAttributes(lcdd.visAttributes("InvisibleNoDaughters")); + else if ( ::strstr(tag.c_str(),"_layer") ) // Layers turned off, but daughters possibly visible + setVisAttributes(lcdd.visAttributes("InvisibleWithDaughters")); + else if ( ::strstr(tag.c_str(),"_module") ) // Tracker modules similar to layers + setVisAttributes(lcdd.visAttributes("InvisibleWithDaughters")); + else if ( ::strstr(tag.c_str(),"_module_component") ) // Tracker modules similar to layers + setVisAttributes(lcdd.visAttributes("InvisibleNoDaughters")); + */ + } +} + +/// Attach attributes to the volume +void Volume::setAttributes(const LCDD& lcdd, + const string& region, + const string& limits, + const string& vis) const +{ + if ( !region.empty() ) setRegion(lcdd.region(region)); + if ( !limits.empty() ) setLimitSet(lcdd.limitSet(limits)); + setVisAttributes(lcdd,vis); +} + +/// Set the volume's solid shape +void Volume::setSolid(const Solid& solid) const +{ m_element->SetShape(solid); } + +/// Set the regional attributes to the volume +void Volume::setRegion(const Region& obj) const +{ data().region = obj; } + +/// Set the limits to the volume +void Volume::setLimitSet(const LimitSet& obj) const +{ data().limits = obj; } + +/// Assign the sensitive detector structure +void Volume::setSensitiveDetector(const SensitiveDetector& obj) const { + //cout << "Setting sensitive detector '" << obj.name() << "' to volume:" << ptr() << " " << name() << endl; + data().sens_det = obj; +} + +/// Access to the handle to the sensitive detector +Ref_t Volume::sensitiveDetector() const +{ return data().sens_det; } + +/// Accessor if volume is sensitive (ie. is attached to a sensitive detector) +bool Volume::isSensitive() const +{ return data().sens_det.isValid(); } + +/// Access to Solid (Shape) +Solid Volume::solid() const +{ return Solid((*this)->GetShape()); } + +/// Access to the Volume material +Material Volume::material() const +{ return Ref_t(m_element->GetMedium()); } + +/// Access the visualisation attributes +VisAttr Volume::visAttributes() const +{ return data().vis; } + +/// Access to the handle to the region structure +Region Volume::region() const +{ return data().region; } + +/// Access to the limit set +LimitSet Volume::limitSet() const +{ return data().limits; } + +/// Constructor to be used when creating a new geometry tree. +Assembly::Assembly(const string& name) { + Object* ext = new Object(); + m_element = new TGeoVolumeAssembly(name.c_str()); + m_element->SetUserExtension(ext); +} + diff --git a/doc/Volumes.h b/doc/Volumes.h new file mode 100644 index 0000000000000000000000000000000000000000..c6b5ecaf802ce38e03aeaf9916673936d302b494 --- /dev/null +++ b/doc/Volumes.h @@ -0,0 +1,261 @@ +// $Id: Volumes.h 574 2013-05-17 20:38:31Z markus.frank $ +//==================================================================== +// AIDA Detector description implementation for LCD +//-------------------------------------------------------------------- +// +// Author : M.Frank +// +//==================================================================== + +#ifndef DD4hep_GEOMETRY_VOLUMES_H +#define DD4hep_GEOMETRY_VOLUMES_H + +// Framework include files +#include "DD4hep/Handle.h" +#include "DD4hep/Shapes.h" +#include "DD4hep/Objects.h" + +// C/C++ include files +#include <map> + +// ROOT include file (includes TGeoVolume + TGeoShape) +#include "TGeoNode.h" +#include "TGeoExtension.h" +#include "TGeoPatternFinder.h" + +/* + * DD4hep namespace declaration + */ +namespace DD4hep { + + /* + * Geometry namespace declaration + */ + namespace Geometry { + + // Forward declarations + struct LCDD; + struct Region; + struct LimitSet; + struct Material; + struct VisAttr; + struct Volume; + struct PlacedVolume; + struct SensitiveDetector; + + /** @class PlacedVolume Volume.h DD4hep/lcdd/Volume.h + * + * @author M.Frank + * @version 1.0 + */ + struct PlacedVolume : Handle<TGeoNodeMatrix> { + typedef std::pair<std::string,int> VolID; + struct VolIDs : public std::vector<VolID> { + typedef std::vector<VolID> Base; + VolIDs() : Base() {} + ~VolIDs () {} + Base::const_iterator find(const std::string& name) const; + std::pair<Base::iterator,bool> insert(const std::string& name, int value); + }; + struct Object : public TGeoExtension { + /// Reference count on object (used to implement Grab/Release) + long refCount; + /// Magic word + unsigned long magic; + /// ID container + VolIDs volIDs; + /// Default constructor + Object(); + /// Copy constructor + Object(const Object& c); + /// Default destructor + virtual ~Object(); + /// Assignment operator + Object& operator=(const Object& c) { + volIDs = c.volIDs; + magic = c.magic; + return *this; + } + /// TGeoExtension overload: Method called whenever requiring a pointer to the extension + virtual TGeoExtension *Grab() const; + /// TGeoExtension overload: Method called always when the pointer to the extension is not needed anymore + virtual void Release() const; + }; + /// Default constructor + PlacedVolume() : Handle<TGeoNodeMatrix>() {} + /// Constructor to be used when reading the already parsed DOM tree + PlacedVolume(const TGeoNode* e) : Handle<TGeoNodeMatrix>(e) {} + /// Copy assignment + PlacedVolume(const PlacedVolume& e) : Handle<TGeoNodeMatrix>(e) {} + /// Copy assignment from other handle type + template <typename T> PlacedVolume(const Handle<T>& e) : Handle<TGeoNodeMatrix>(e) {} + /// Assignment operator (must match copy constructor) + PlacedVolume& operator=(const PlacedVolume& v) { m_element=v.m_element; return *this; } + + /// Accessor to user structure + Object& data() const; + + /// Add identifier + PlacedVolume& addPhysVolID(const std::string& name, int value); + /// Volume material + Material material() const; + /// Logical volume of this placement + Volume volume() const; + /// Parent volume (envelope) + Volume motherVol() const; + /// Access to the volume IDs + const VolIDs& volIDs() const; + /// String dump + std::string toString() const; + }; + + /** @class Volume Volume.h DD4hep/lcdd/Volume.h + * + * Handle describing a Volume + * + * @author M.Frank + * @version 1.0 + */ + struct Volume : public Handle<TGeoVolume> { + + public: + typedef Handle<TGeoVolume> Base; + struct Object : public TGeoExtension { + /// Reference count on object (used to implement Grab/Release) + long refCount; + /// Magic word + unsigned long magic; + Region region; + LimitSet limits; + VisAttr vis; + Ref_t sens_det; + /// Default constructor + Object(); + /// Default destructor + virtual ~Object(); + /// Object copy + void copy(const Object& c) { + magic = c.magic; + region = c.region; + limits = c.limits; + vis = c.vis; + sens_det = c.sens_det; + } + /// TGeoExtension overload: Method called whenever requiring a pointer to the extension + virtual TGeoExtension *Grab() const; + /// TGeoExtension overload: Method called always when the pointer to the extension is not needed anymore + virtual void Release() const; + }; + + public: + /// Default constructor + Volume() : Base(0) {} + + /// Copy from handle + Volume(const Volume& v) : Base(v) {} + + /// Copy from arbitrary Element + template <typename T> Volume(const Handle<T>& v) : Base(v) {} + + /// Constructor to be used when creating a new geometry tree. + Volume(const std::string& name); + + /// Constructor to be used when creating a new geometry tree. Also sets materuial and solid attributes + Volume(const std::string& name, const Solid& s, const Material& m); + + /// Assignment operator (must match copy constructor) + Volume& operator=(const Volume& a) { m_element=a.m_element; return *this; } + + /// Accessor to user structure + Object& data() const; + + /// Place daughter volume. The position and rotation are the identity + PlacedVolume placeVolume(const Volume& vol) const + { return placeVolume(vol,IdentityPos()); } + /// Place daughter volume according to generic Transform3D + PlacedVolume placeVolume(const Volume& volume, const Transform3D& tr) const; + /// Place un-rotated daughter volume at the given position. + PlacedVolume placeVolume(const Volume& vol, const Position& pos) const; + /// Place rotated daughter volume. The position is automatically the identity position + PlacedVolume placeVolume(const Volume& vol, const Rotation& rot) const; + /// Place rotated and then translated daughter volume + PlacedVolume placeVolume(const Volume& vol, const Position& pos, const Rotation& rot) const; + /// Place daughter volume in rotated and then translated mother coordinate system + PlacedVolume placeVolume(const Volume& vol, const Rotation& rot, const Position& pos) const; + + /// Place daughter volume. The position and rotation are the identity + PlacedVolume placeVolume(const Volume& vol, const IdentityPos& pos) const; + /// Place daughter volume. The position and rotation are the identity + PlacedVolume placeVolume(const Volume& vol, const IdentityRot& pos) const; + + /// Attach attributes to the volume + void setAttributes(const LCDD& lcdd, + const std::string& region, + const std::string& limits, + const std::string& vis) const; + + /// Set the regional attributes to the volume + void setRegion(const Region& obj) const; + /// Access to the handle to the region structure + Region region() const; + + /// Set the limits to the volume + void setLimitSet(const LimitSet& obj) const; + /// Access to the limit set + LimitSet limitSet() const; + + /// Set Visualization attributes to the volume + void setVisAttributes(const VisAttr& obj) const; + /// Set Visualization attributes to the volume + void setVisAttributes(const LCDD& lcdd, const std::string& name) const; + /// Access the visualisation attributes + VisAttr visAttributes() const; + + /// Assign the sensitive detector structure + void setSensitiveDetector(const SensitiveDetector& obj) const; + /// Access to the handle to the sensitive detector + Ref_t sensitiveDetector() const; + /// Accessor if volume is sensitive (ie. is attached to a sensitive detector) + bool isSensitive() const; + + /// Set the volume's solid shape + void setSolid(const Solid& s) const; + /// Access to Solid (Shape) + Solid solid() const; + + /// Set the volume's material + void setMaterial(const Material& m) const; + /// Access to the Volume material + Material material() const; + + /// Auto conversion to underlying ROOT object + operator TGeoVolume*() const { return m_element; } + }; + + /** @class Assembly Volume.h DD4hep/lcdd/Volume.h + * + * Handle describing a volume assembly + * + * @author M.Frank + * @version 1.0 + */ + struct Assembly : public Volume { + /// Default constructor + Assembly() : Volume() {} + + /// Copy from handle + Assembly(const Assembly& v) : Volume(v) {} + + /// Copy from arbitrary Element + template <typename T> Assembly(const Handle<T>& v) : Volume(v) {} + + /// Constructor to be used when creating a new geometry tree. + Assembly(const std::string& name); + + /// Assignment operator (must match copy constructor) + Assembly& operator=(const Assembly& a) { m_element=a.m_element; return *this; } + }; + + } /* End namespace Geometry */ +} /* End namespace DD4hep */ +#endif /* DD4hep_GEOMETRY_VOLUMES_H */ diff --git a/doc/release.notes b/doc/release.notes index 1aca76ff0a17b122a32ebe5eeaca484775d86b3b..f035cb5f29edaf8fa6e9149a8c15c1c66ba268c6 100644 --- a/doc/release.notes +++ b/doc/release.notes @@ -1,6 +1,47 @@ DD4hep ---- Release Notes ================================= +2013/02/06 Markus Frank +-------------------------- + 1) Simplyfy inheritance for common objects from TNamed. + Use direct inheritance of Object from TNamed rather than hidden + using the Value<a,b> construct. + 2) Added physical volume manager to simplyfy the detector element + and sensitive detector lookup from a given physical volume. + This implies: If the volume manager is instantiated, the readout specifiers + MUST be correct. This is in most xml files NOT the case. + The "system" field holding the sibdetector-id is MANDATORY! + Otherwise you will receive messages like this: + + Exception:SITCollection: This ID descriptor has no field with the name:CellID0 + while programming VolumeManager. Are your volIDs correct? + + 3) To check the volume identification, add argument -volmgr to geoConverter, + geoDisplay, etc. + 4) To trace possible memory leaks: + export DD4HEP_TRACE=Yes + then run you converter etc. At the end a table is displayed with a "leakage" + column, showing how many objects were not deleted. + + +----------------------------------------------------------------+ + | I n s t a n c e c o u n t e r s b y T Y P E I N F O | + +----------+---------+-------------------------------------------+ + | Total | Leaking | Type identifier | + +----------+---------+-------------------------------------------+ + | 13| 0|DD4hep::Geometry::DetElement::Object + | 3| 0|DD4hep::Geometry::SensitiveDetector::Object + | 3| 0|DD4hep::Geometry::Readout::Object + | 1| 0|DD4hep::Geometry::OverlayedField::Object + | 1| 0|DD4hep::Geometry::CartesianField::Object + .... + Ideally the second column only has "0"s. Instances of 1 may be OK (singletons). + + Prenotice: + As soon as ROOT v 6.00 is out, we will have to use it! + Andrei kindly agreed to implement a few changes to TGeo, which will make + life much easier and the implementation cleaner and less cumbersome. + + -------- | v00-01 | -------- @@ -8,9 +49,6 @@ DD4hep ---- Release Notes - first beta release... - - - 2013/20/03 Markus Frank -------------------------- 1) Finished the compact->lcdd converter