diff --git a/DDCore/CMakeLists.txt b/DDCore/CMakeLists.txt index 7c6db6a1b154c7e23ea4dc2ec5cddb46ad2abae7..99481f63ae8da1f5d73ca7e153f8c14331b9e715 100644 --- a/DDCore/CMakeLists.txt +++ b/DDCore/CMakeLists.txt @@ -26,6 +26,7 @@ endif() add_library(DD4hepCore SHARED ${sources}) target_link_libraries(DD4hepCore ${ROOT_LIBRARIES} ${XERCESC_LIBRARIES} Geom Reflex ${libraries}) + #---Rootmap generation-------------------------------------------------------------- dd4hep_generate_rootmap(DD4hepCore) diff --git a/DDCore/include/XML/LCDDConverter.h b/DDCore/include/XML/LCDDConverter.h index 29796227d30a450259435eb80b70ab386c34e891..12405ea1af86c062a379ddf4e244c40e2a3c70d2 100644 --- a/DDCore/include/XML/LCDDConverter.h +++ b/DDCore/include/XML/LCDDConverter.h @@ -25,6 +25,8 @@ class TGeoElement; class TGeoShape; class TGeoMedium; class TGeoNode; +class TGeoMatrix; + /* * DD4hep namespace declaration @@ -56,6 +58,7 @@ namespace DD4hep { typedef std::map<const TGeoVolume*, XmlElement*> VolumeMap; typedef std::map<const TGeoShape*, XmlElement*> SolidMap; typedef std::map<const TNamed*, XmlElement*> VisMap; + typedef std::map<const TNamed*, XmlElement*> FieldMap; typedef std::map<const TNamed*, XmlElement*> IdSpecMap; typedef std::map<const TGeoMatrix*, XmlElement*> TrafoMap; struct GeometryInfo : public Geometry::GeoHandler::GeometryInfo { @@ -71,10 +74,23 @@ namespace DD4hep { SensDetMap xmlSensDets; TrafoMap xmlPositions; TrafoMap xmlRotations; - + FieldMap xmlFields; ObjectSet sensitives; ObjectSet regions; ObjectSet limits; + // These we need for redundancy and checking the data integrity + typedef std::map<std::string,const TNamed*> CheckIter; + struct _checks { + std::map<std::string,const TNamed*> positions, rotations, volumes, solids, materials; + }; + mutable _checks checks; + void check(const std::string& name,const TNamed* n,std::map<std::string,const TNamed*>& array) const; + void checkPosition(const std::string& name,const TNamed* n) const { check(name,n,checks.positions); } + void checkRotation(const std::string& name,const TNamed* n) const { check(name,n,checks.rotations); } + void checkVolume (const std::string& name,const TNamed* n) const { check(name,n,checks.volumes); } + void checkShape (const std::string& name,const TNamed* n) const { check(name,n,checks.solids); } + void checkMaterial(const std::string& name,const TNamed* n) const { check(name,n,checks.materials); } + Document doc; Element doc_root, doc_header, doc_idDict, doc_detectors, doc_limits, doc_regions, doc_display, doc_gdml, doc_fields, doc_define, doc_materials, doc_solids, doc_structure, doc_setup; @@ -117,7 +133,7 @@ namespace DD4hep { /// Convert the geometry type logical volume into the corresponding Xml object(s). virtual Handle_t handleVolume(const std::string& name, const TGeoVolume* volume) const; - virtual void collectVolume(const std::string& name, const TGeoVolume* volume) const; + virtual void collectVolume(const std::string& name, const TGeoVolume* volume) const; /// Convert the geometry type volume placement into the corresponding Xml object(s). virtual Handle_t handlePlacement(const std::string& name, const TGeoNode* node) const; @@ -146,6 +162,9 @@ namespace DD4hep { /// Convert the Rotation into the corresponding Xml object(s). virtual Handle_t handleRotation(const std::string& name, const TGeoMatrix* trafo) const; + /// Convert the electric or magnetic fields into the corresponding Xml object(s). + virtual Handle_t handleField(const std::string& name, const TNamed* field) const; + /// Handle the geant 4 specific properties void handleProperties(LCDD::Properties& prp) const; }; diff --git a/DDCore/include/XML/XMLElements.h b/DDCore/include/XML/XMLElements.h index ade10e8f620a6635c282546be935bc23f18bfdd1..84544b6b80b885e7631259912f520cda0dc8ef10 100644 --- a/DDCore/include/XML/XMLElements.h +++ b/DDCore/include/XML/XMLElements.h @@ -410,7 +410,7 @@ namespace DD4hep { { return attr_value(tag); } template<> INLINE bool Handle_t::attr<bool>(const XmlChar* tag) const - { return _toBool(attr_value_nothrow(tag)); } + { return _toBool(attr_value(tag)); } template<> INLINE int Handle_t::attr<int>(const XmlChar* tag) const { return _toInt(attr_value(tag)); } @@ -422,7 +422,7 @@ namespace DD4hep { { return _toDouble(attr_value(tag)); } template<> INLINE std::string Handle_t::attr<std::string>(const XmlChar* tag) const - { return _toString(attr_nothrow(tag)); } + { return _toString(attr_value(tag)); } #if 0 template<> INLINE bool Handle_t::attr<bool>(const Attribute tag) const { return _toBool(attr_value(tag)); } diff --git a/DDCore/src/XML/LCDDConverter.cpp b/DDCore/src/XML/LCDDConverter.cpp index cfccc02deda34ff1bf027fbdc47b6017d7ea80f0..a051deff3e30f1d9bf1477df8340cee58d1a2ffc 100644 --- a/DDCore/src/XML/LCDDConverter.cpp +++ b/DDCore/src/XML/LCDDConverter.cpp @@ -8,6 +8,7 @@ //==================================================================== #include "DD4hep/Volumes.h" +#include "DD4hep/FieldTypes.h" #include "DD4hep/DetFactoryHelper.h" #include "XML/DocumentHandler.h" #include "XML/LCDDConverter.h" @@ -93,6 +94,17 @@ namespace { } } + +void LCDDConverter::GeometryInfo::check(const string& name, const TNamed* n,map<string,const TNamed*>& m) const { + map<string,const TNamed*>::const_iterator i=m.find(name); + if ( i != m.end() ) { + const char* isa = n ? n->IsA()->GetName() : (*i).second ? (*i).second->IsA()->GetName() : "Unknown"; + cout << isa << "(position): duplicate entry with name:" << name + << " " << (void*)n << " " << (void*)(*i).second << endl; + } + m.insert(make_pair(name,n)); +} + /// Initializing Constructor LCDDConverter::LCDDConverter( LCDD& lcdd ) : m_lcdd(lcdd) { m_checkOverlaps = true; @@ -132,6 +144,8 @@ Handle_t LCDDConverter::handleMaterial(const string& name, const TGeoMedium* med obj.setAttr(_A(unit),"g/cm3"); obj.setAttr(_A(type),"density"); + geo.checkMaterial(name,medium); + if ( m->IsMixture() ) { TGeoMixture* mix=(TGeoMixture*)m; const double *wmix = mix->GetWmixt(); @@ -171,6 +185,7 @@ Handle_t LCDDConverter::handleSolid(const string& name, const TGeoShape* shape) Handle_t solid(geo.xmlSolids[shape]); if ( !solid && shape ) { Handle_t zplane(0); + geo.checkShape(name,shape); if ( shape->IsA() == TGeoBBox::Class() ) { const TGeoBBox* s = (const TGeoBBox*)shape; geo.doc_solids.append(solid = Element(geo.doc,_X(box))); @@ -448,6 +463,7 @@ Handle_t LCDDConverter::handlePosition(const std::string& name, const TGeoMatrix static Handle_t identity; const double* tr = trafo->GetTranslation(); if ( tr[0] != 0 || tr[1] != 0 || tr[2] != 0 ) { + geo.checkPosition(name,trafo); geo.doc_define.append(pos=Element(geo.doc,_X(position))); pos.setAttr(_A(name),name); pos.setAttr(_A(x),tr[0]); @@ -464,6 +480,7 @@ Handle_t LCDDConverter::handlePosition(const std::string& name, const TGeoMatrix identity.setAttr(_A(y),0); identity.setAttr(_A(z),0); pos = identity; + geo.checkPosition("identity_pos",0); } geo.xmlPositions[trafo] = pos; } @@ -478,6 +495,7 @@ Handle_t LCDDConverter::handleRotation(const std::string& name, const TGeoMatrix static Handle_t identity; XYZRotation r = getXYZangles(trafo->Inverse().GetRotationMatrix()); if ( r.X() != 0 || r.Y() != 0 || r.Z() != 0 ) { + geo.checkRotation(name,trafo); geo.doc_define.append(rot=Element(geo.doc,_X(rotation))); rot.setAttr(_A(name),name); rot.setAttr(_A(x),r.X()); @@ -494,6 +512,7 @@ Handle_t LCDDConverter::handleRotation(const std::string& name, const TGeoMatrix identity.setAttr(_A(y),0); identity.setAttr(_A(z),0); rot = identity; + geo.checkRotation("identity_rot",0); } geo.xmlRotations[trafo] = rot; } @@ -517,6 +536,7 @@ Handle_t LCDDConverter::handleVolume(const string& name, const TGeoVolume* volum else if ( !m && v->IsA() != TGeoVolumeAssembly::Class() ) throw runtime_error("G4Converter: No Geant4 material present for volume:"+n); + geo.checkVolume(name,volume); geo.doc_structure.append(vol=Element(geo.doc,_X(volume))); vol.setAttr(_A(name),n); vol.setRef(_X(solidref),sol.name()); @@ -577,13 +597,13 @@ void LCDDConverter::checkVolumes(const string& name, const TGeoVolume* volume) c SensitiveDetector s = v.sensitiveDetector(); VisAttr vis = v.visAttributes(); if ( s.isValid() ) { - cout << "of " << s.name(); + cout << "of " << s.name() << " "; } else if ( vis.isValid() ) { - cout << "with VisAttrs " << vis.name(); + cout << "with VisAttrs " << vis.name() << " "; } } - cout << " has duplicate entries." << endl; + cout << "has duplicate entries." << endl; return; } m_checkNames.insert(name); @@ -591,7 +611,7 @@ void LCDDConverter::checkVolumes(const string& name, const TGeoVolume* volume) c /// Dump volume placement in GDML format to output stream Handle_t LCDDConverter::handlePlacement(const string& name, const TGeoNode* node) const { - GeometryInfo& geo = data(); + GeometryInfo& geo = data(); Handle_t place = geo.xmlPlacements[node]; if ( !place ) { TGeoMatrix* t = node->GetMatrix(); @@ -604,9 +624,12 @@ Handle_t LCDDConverter::handlePlacement(const string& name, const TGeoNode* node mot.append(place); } place.setRef(_X(volumeref),vol.name()); - if ( t ) { - RefElement pos = handlePosition(name+"_pos",t); - RefElement rot = handleRotation(name+"_rot",t); + if ( t ) { + char text[32]; + ::sprintf(text,"_%p_pos",node); + RefElement pos = handlePosition(name+text,t); + ::sprintf(text,"_%p_rot",node); + RefElement rot = handleRotation(name+text,t); place.setRef(_X(positionref),pos.name()); place.setRef(_X(rotationref),rot.name()); } @@ -749,6 +772,32 @@ Handle_t LCDDConverter::handleVis(const string& name, const TNamed* v) const { return vis; } +/// Convert the electric or magnetic fields into the corresponding Xml object(s). +Handle_t LCDDConverter::handleField(const std::string& name, const TNamed* f) const { + GeometryInfo& geo = data(); + Handle_t field = geo.xmlFields[f]; + if ( !field ) { + string typ = f->GetTitle(); + geo.doc_fields.append(field=Element(geo.doc,_X(field))); + field.setAttr(_A(name),f->GetName()); + field.setAttr(_A(type),typ); + if ( typ == "SolenoidMagnet" ) { + double tesla = 0.001; + Geometry::SolenoidField* s = Ref_t(f).data<Geometry::SolenoidField>(); + field.setAttr(_A(lunit),"mm"); + field.setAttr(_A(funit),"tesla"); + field.setAttr(_A(x),m_lcdd.constant<string>("world_side")); + field.setAttr(_A(outer_radius),s->outerRadius); + field.setAttr(_A(inner_radius),s->innerRadius); + field.setAttr(_A(inner_field),s->innerField/tesla); + field.setAttr(_A(outer_field),s->outerField/tesla); + field.setAttr(_A(zmin),s->minZ); + field.setAttr(_A(zmax),s->maxZ); + } + } + return field; +} + /// Handle the geant 4 specific properties void LCDDConverter::handleProperties(LCDD::Properties& prp) const { map<string,string> processors; @@ -809,7 +858,8 @@ void LCDDConverter::handleHeader() const { template <typename O, typename C, typename F> 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); + string n = (*i)->GetName(); + (o->*pmf)(n,*i); } } @@ -849,6 +899,7 @@ void LCDDConverter::create(Geometry::DetElement top) { "</lcdd>\0\0"; DocumentHandler docH; + Element elt(0); geo.doc = docH.parse(empty_lcdd,sizeof(empty_lcdd)); //doc->setXmlStandalone(true); //doc->setStrictErrorChecking(true); @@ -863,18 +914,27 @@ void LCDDConverter::create(Geometry::DetElement top) { geo.doc_root.append(geo.doc_display = Element(geo.doc,_X(display))); geo.doc_root.append(geo.doc_gdml = Element(geo.doc,_X(gdml))); geo.doc_root.append(geo.doc_fields = Element(geo.doc,_X(fields))); - + //elt = Element(); + geo.doc_gdml.append(geo.doc_define = Element(geo.doc,_X(define))); geo.doc_gdml.append(geo.doc_materials = Element(geo.doc,_X(materials))); geo.doc_gdml.append(geo.doc_solids = Element(geo.doc,_X(solids))); geo.doc_gdml.append(geo.doc_structure = Element(geo.doc,_X(structure))); geo.doc_gdml.append(geo.doc_setup = Element(geo.doc,_X(setup))); + elt = Element(geo.doc,_X(world)); + elt.setAttr(_A(ref),lcdd.worldVolume().name()); + geo.doc_setup.append(elt); + // Ensure that all required materials are present in the Geant4 material table const LCDD::HandleMap& mat = lcdd.materials(); for(LCDD::HandleMap::const_iterator i=mat.begin(); i!=mat.end(); ++i) geo.materials.insert(dynamic_cast<TGeoMedium*>((*i).second.ptr())); + const LCDD::HandleMap& fld = lcdd.fields(); + for(LCDD::HandleMap::const_iterator i=fld.begin(); i!=fld.end(); ++i) + geo.fields.insert((*i).second.ptr()); + handleHeader(); // Start creating the objects for materials, solids and log volumes. handle(this, geo.materials, &LCDDConverter::handleMaterial); @@ -901,13 +961,15 @@ void LCDDConverter::create(Geometry::DetElement top) { handle(this, geo.volumes, &LCDDConverter::handleVolume); cout << "++ Handled " << geo.volumes.size() << " volumes." << endl; + handle(this, geo.fields, &LCDDConverter::handleField); + cout << "++ Handled " << geo.fields.size() << " fields." << endl; + // Now place all this stuff appropriately handleRMap(this, *m_data, &LCDDConverter::handlePlacement); m_checkNames.clear(); handle(this, geo.volumes, &LCDDConverter::checkVolumes); - #if 0 //==================== Fields handleProperties(m_lcdd.properties()); diff --git a/DDCore/src/compact/Compact2Objects.cpp b/DDCore/src/compact/Compact2Objects.cpp index a5711d60f4afce9332ee58cc608586f1363efa5f..626dae8f3296e953f0b063f950beb3fed2fecc0a 100644 --- a/DDCore/src/compact/Compact2Objects.cpp +++ b/DDCore/src/compact/Compact2Objects.cpp @@ -131,15 +131,18 @@ static Ref_t create_ConstantField(lcdd_t& /* lcdd */, const xml_h& e) { DECLARE_XMLELEMENT(ConstantField,create_ConstantField); -static Ref_t create_SolenoidField(lcdd_t& /* lcdd */, const xml_h& e) { +static Ref_t create_SolenoidField(lcdd_t& lcdd, const xml_h& e) { xml_comp_t c(e); CartesianField obj; Value<TNamed,SolenoidField>* ptr = new Value<TNamed,SolenoidField>(); if ( c.hasAttr(_A(inner_radius)) ) ptr->innerRadius = c.attr<double>(_A(inner_radius)); + else ptr->innerRadius = 0.0; if ( c.hasAttr(_A(outer_radius)) ) ptr->outerRadius = c.attr<double>(_A(outer_radius)); + else ptr->outerRadius = lcdd.constant<double>("world_side"); if ( c.hasAttr(_A(inner_field)) ) ptr->innerField = c.attr<double>(_A(inner_field)); if ( c.hasAttr(_A(outer_field)) ) ptr->outerField = c.attr<double>(_A(outer_field)); if ( c.hasAttr(_A(zmax)) ) ptr->maxZ = c.attr<double>(_A(zmax)); + else ptr->maxZ = lcdd.constant<double>("world_side"); if ( c.hasAttr(_A(zmin)) ) ptr->minZ = c.attr<double>(_A(zmin)); else ptr->minZ = - ptr->maxZ; obj.assign(ptr,c.nameStr(),c.typeStr());