diff --git a/DDCore/include/XML/UnicodeValues.h b/DDCore/include/XML/UnicodeValues.h index 8f311e564960e0453e238b9b3923aeed86cf60e8..91e02862d8209235630cf2311376f06b2f62e45a 100644 --- a/DDCore/include/XML/UnicodeValues.h +++ b/DDCore/include/XML/UnicodeValues.h @@ -338,6 +338,7 @@ UNICODE (physvolid); UNICODE (pitch); UNICODE (pivot); UNICODE (pivot_point); +UNICODE (placement); UNICODE (plane); UNICODE (plugin); UNICODE (plugins); diff --git a/DDCore/include/XML/VolumeBuilder.h b/DDCore/include/XML/VolumeBuilder.h index 8b3826cb952ad10e7575303695f34bacb7ec1aac..63759cbd0b91e861230e971f264554fb915049c3 100644 --- a/DDCore/include/XML/VolumeBuilder.h +++ b/DDCore/include/XML/VolumeBuilder.h @@ -145,6 +145,7 @@ namespace dd4hep { Detector& description; Handle_t x_det; int id = -1; + std::string name; DetElement detector; SensitiveDetector sensitive; DetectorBuildType buildType; diff --git a/DDCore/src/XML/Utilities.cpp b/DDCore/src/XML/Utilities.cpp index 0203c4badb90b24a0223af2bcc6d95aa7af1b89c..37a39ac10dbf1acf335c24a9a23a1c2cca03f9af 100644 --- a/DDCore/src/XML/Utilities.cpp +++ b/DDCore/src/XML/Utilities.cpp @@ -98,6 +98,17 @@ Volume dd4hep::xml::createVolume(Detector& description, xml::Element element) vol.setAttributes(description,e.regionStr(),e.limitsStr(),e.visStr()); return vol; } + xml_h h = e; + xml_attr_t a = h.attr_nothrow(_U(type)); + if ( a ) { + string typ = h.attr<string>(a); + if ( typ.substr(1) == "ssembly" ) { + Assembly vol("assembly"); + if ( e.hasAttr(_U(name)) ) vol->SetName(e.attr<string>(_U(name)).c_str()); + vol.setAttributes(description,e.regionStr(),e.limitsStr(),e.visStr()); + return vol; + } + } except("xml::createVolume","Failed to create volume. No material specified!"); return Volume(); } diff --git a/DDCore/src/XML/VolumeBuilder.cpp b/DDCore/src/XML/VolumeBuilder.cpp index a458f7d670c1209ec594c4a2c851d5ad68ae3d65..f7f354111f5b9211ed4cc7de94df5136cb6d95b0 100644 --- a/DDCore/src/XML/VolumeBuilder.cpp +++ b/DDCore/src/XML/VolumeBuilder.cpp @@ -34,8 +34,8 @@ VolumeBuilder::VolumeBuilder(Detector& dsc, xml_h x_parent, SensitiveDetector sd { if ( x_det ) { xml_det_t c(x_det); - string name = c.nameStr(); - id = c.id(); + name = c.nameStr(); + id = c.id(); detector = DetElement(name, id); } buildType = description.buildType(); @@ -176,8 +176,8 @@ size_t VolumeBuilder::buildShapes(xml_h handle) { } } string type = x.attr<string>(_U(type)); - Solid solid = xml::createShape(description, type,c); - if ( solid.isValid() ) { + Solid solid = xml::createShape(description, type, c); + if ( !solid.isValid() ) { except("VolumeBuilder","+++ Failed to create shape %s of type: %s", nam.c_str(), type.c_str()); } @@ -235,6 +235,7 @@ size_t VolumeBuilder::buildVolumes(xml_h handle) { if ( debug ) { printout(ALWAYS,"VolumeBuilder","+++ Building volume from XML: %s",nam.c_str()); } + buildVolumes(c); continue; } bool is_assembly = true; @@ -245,6 +246,7 @@ size_t VolumeBuilder::buildVolumes(xml_h handle) { placeDaughters(detector, vol, x); vol.setAttributes(description,x.regionStr(),x.limitsStr(),x.visStr()); volumes.insert(make_pair(nam,make_pair(c,vol))); + buildVolumes(c); continue; } except("VolumeBuilder","+++ Failed to create volume %s. " @@ -256,15 +258,21 @@ size_t VolumeBuilder::buildVolumes(xml_h handle) { /// Build all <physvol/> identifiers as PlaceVolume daughters. Ignores structure VolumeBuilder& VolumeBuilder::placeDaughters(Volume vol, xml_h handle) { for( xml_coll_t c(handle,_U(physvol)); c; ++c ) { - xml_comp_t x_comp = c; - string nam = x_comp.attr<string>(_U(logvol)); + xml_attr_t attr = c.attr_nothrow(_U(logvol)); + if ( !attr ) { + attr = c.attr_nothrow(_U(volume)); + } + if ( !attr ) { + except("VolumeBuilder","+++ The xml volume element has no 'logvol' or 'volume' attribute!"); + } + string nam = c.attr<string>(attr); if ( vol_veto.find(nam) == vol_veto.end() ) { auto iv = volumes.find(nam); if ( iv == volumes.end() ) { except("VolumeBuilder","+++ Failed to locate volume %s. [typo somewhere in the XML?]", nam.c_str()); } - xml_attr_t attr = c.attr_nothrow(_U(transformation)); + attr = c.attr_nothrow(_U(transformation)); if ( attr ) { string tr_nam = c.attr<string>(attr); auto it = transformations.find(tr_nam); @@ -276,10 +284,12 @@ VolumeBuilder& VolumeBuilder::placeDaughters(Volume vol, xml_h handle) { } const Transform3D& tr = (*it).second.second; vol.placeVolume((*iv).second.second, tr); + placeDaughters(vol, c); } else { Transform3D tr = xml::createTransformation(c); vol.placeVolume((*iv).second.second, tr); + placeDaughters(vol, c); } } } @@ -290,8 +300,14 @@ VolumeBuilder& VolumeBuilder::placeDaughters(Volume vol, xml_h handle) { VolumeBuilder& VolumeBuilder::placeDaughters(DetElement parent, Volume vol, xml_h handle) { for( xml_coll_t c(handle,_U(physvol)); c; ++c ) { - xml_comp_t x_comp = c; - string nam = x_comp.attr<string>(_U(logvol)); + xml_attr_t attr = c.attr_nothrow(_U(logvol)); + if ( !attr ) { + attr = c.attr_nothrow(_U(volume)); + } + if ( !attr ) { + except("VolumeBuilder","+++ The xml volume element has no 'logvol' or 'volume' attribute!"); + } + string nam = c.attr<string>(attr); if ( vol_veto.find(nam) == vol_veto.end() ) { auto iv = volumes.find(nam); if ( iv == volumes.end() ) { @@ -300,7 +316,7 @@ VolumeBuilder& VolumeBuilder::placeDaughters(DetElement parent, Volume vol, xml_ nam.c_str()); } PlacedVolume pv; - xml_attr_t attr = c.attr_nothrow(_U(transformation)); + attr = c.attr_nothrow(_U(transformation)); if ( attr ) { string tr_nam = c.attr<string>(attr); auto it = transformations.find(tr_nam); @@ -327,6 +343,10 @@ VolumeBuilder& VolumeBuilder::placeDaughters(DetElement parent, Volume vol, xml_ } DetElement de(parent,elt,parent_id); de.setPlacement(pv); + placeDaughters(de, vol, c); + } + else { + placeDaughters(parent, vol, c); } } } diff --git a/DDCore/src/plugins/Compact2Objects.cpp b/DDCore/src/plugins/Compact2Objects.cpp index 8bdded2dc80469905cf66123e902f1e47ada05a2..6dc66594b9cee2e74aa3acbe3a729bd5b2b02240 100644 --- a/DDCore/src/plugins/Compact2Objects.cpp +++ b/DDCore/src/plugins/Compact2Objects.cpp @@ -236,6 +236,7 @@ static long load_Compact(Detector& description, xml_h element) { return 1; } DECLARE_XML_DOC_READER(lccdd,load_Compact) +DECLARE_XML_DOC_READER(compact,load_Compact) /** Convert parser debug flags. */ diff --git a/DDDetectors/src/VolumeAssembly_geo.cpp b/DDDetectors/src/VolumeAssembly_geo.cpp index 1f3850dea2dd619148ecf10a77d43de399264bcf..e430d7a79141dad43878436db46ca53c867763ac 100644 --- a/DDDetectors/src/VolumeAssembly_geo.cpp +++ b/DDDetectors/src/VolumeAssembly_geo.cpp @@ -15,156 +15,72 @@ // //========================================================================== #include "DD4hep/DetFactoryHelper.h" -#include "DD4hep/DetectorTools.h" #include "DD4hep/Printout.h" +#include "XML/VolumeBuilder.h" #include "XML/Utilities.h" using namespace std; using namespace dd4hep; using namespace dd4hep::detail; +static Ref_t create_element(Detector& description, xml_h e, SensitiveDetector sens) { + //Builder b(description); + //return b.create(e, sens); + xml_comp_t x_det(e); + xml_comp_t x_env = e.child(_U(envelope)); + xml_comp_t x_shp = x_env.child(_U(shape),false); + xml_h x_dbg = e.child(_U(debug),false); + xml_h x_pos, x_rot, x_tr; + Volume assembly; + xml::tools::VolumeBuilder builder(description, e, sens); -namespace { - /// Helper to create the volume assembly - struct Builder { - /// Created volumes - map<string, Volume> volumes; - Detector& description; - /// Default constructor - Builder(Detector& dsc) : description(dsc) {} - - /// Default destructor - ~Builder() {} - - /// Place single volume in mother - PlacedVolume placeVolume(DetElement parent, Volume mother, xml_h c) { - xml_dim_t x_vol = c; - string vnam = x_vol.attr<string>(_U(volume)); - string name = x_vol.hasAttr(_U(name)) ? x_vol.nameStr() : string(""); - xml_dim_t x_tr = x_vol.child(_U(transformation),false); - xml_dim_t x_pos = x_vol.child(_U(position),false); - xml_dim_t x_rot = x_vol.child(_U(rotation),false); - PlacedVolume pv; - - auto iv = volumes.find(vnam); - if ( iv == volumes.end() ) { - except("VolumeAssembly","+++ Failed to attach unknown volume: %s",vnam.c_str()); - } - Volume vol = (*iv).second; - for(xml_coll_t coll(c,_U(physvol)); coll; ++coll) { - if ( coll.hasAttr(_U(element)) ) { - DetElement de(parent, coll.attr<string>(_U(element)), parent.id()); - pv = placeVolume(de, vol, coll); - de.setType("compound"); - de.setPlacement(pv); - continue; - } - placeVolume(parent, vol, coll); - } - - if ( x_tr ) { - Transform3D tr = xml::createTransformation(x_tr); - pv = mother.placeVolume(vol, tr); - } - else if ( x_rot && x_pos ) { - Position pos(x_pos.x(0.0),x_pos.y(0.0),x_pos.z(0.0)); - RotationZYX rot(x_rot.z(0.0),x_rot.y(0.0),x_rot.x(0.0)); - pv = mother.placeVolume(vol, Transform3D(rot, pos)); - } - else if ( x_rot ) { - RotationZYX rot(x_rot.z(0.0),x_rot.y(0.0),x_rot.x(0.0)); - pv = mother.placeVolume(vol, rot); - } - else if ( x_pos ) { - Position pos(x_pos.x(0.0),x_pos.y(0.0),x_pos.z(0.0)); - pv = mother.placeVolume(vol, pos); - } - else { - pv = mother.placeVolume(vol); - } - return pv; - } - - Ref_t create(xml_h e, SensitiveDetector sens) { - xml_det_t x_det(e); - xml_comp_t x_env = x_det.child(_U(envelope)); - xml_comp_t x_envshape = x_env.child(_U(shape),false); - string det_name = x_det.nameStr(); - DetElement sdet(det_name, x_det.id()); - Volume assembly; - PlacedVolume pv; - - if ( !x_envshape ) x_envshape = x_env; - if ( x_envshape.typeStr() == "Assembly" ) { - assembly = Assembly("lv"+det_name); - } - else { - Material mat = description.material(x_env.materialStr()); - Solid solid = xml::createShape(description, x_envshape.typeStr(), x_envshape); - assembly = Volume("lv"+det_name, solid, mat); - } - /// Set generic associations - assembly.setAttributes(description,x_det.regionStr(),x_det.limitsStr(),x_det.visStr()); - /// If specified more direct: use these ones. - if ( x_env.hasAttr(_U(vis)) ) { - assembly.setVisAttributes(description, x_env.visStr()); - } - if ( x_det.hasAttr(_U(sensitive)) ) { - sens.setType(x_det.attr<string>(_U(sensitive))); - } - if ( x_env.hasAttr(_U(name)) ) { - assembly->SetName(x_env.nameStr().c_str()); - } - - for(xml_coll_t coll(e,_U(volume)); coll; ++coll) { - xml_comp_t x_vol = coll; - Volume vol = xml::createVolume(description,x_vol); - if ( x_vol.isSensitive() ) { - vol.setSensitiveDetector(sens); - } - volumes.insert(make_pair(vol.name(), vol)); - } - for(xml_coll_t coll(e,_U(physvol)); coll; ++coll) { - if ( coll.hasAttr(_U(element)) ) { - string de_name = coll.attr<string>(_U(element)); - DetElement de(sdet, de_name, x_det.id()); - pv = placeVolume(de, assembly, coll); - de.setType("compound"); - de.setPlacement(pv); - continue; - } - placeVolume(sdet, assembly, coll); - } + builder.debug = x_dbg != 0; + builder.buildShapes(x_det); + builder.buildShapes(x_env); + builder.buildVolumes(x_det); + builder.buildVolumes(x_env); - xml_dim_t x_tr = x_det.child(_U(transformation),false); - xml_dim_t x_pos = x_det.child(_U(position),false); - xml_dim_t x_rot = x_det.child(_U(rotation),false); - Volume mother = description.pickMotherVolume(sdet); - if ( x_tr ) { - Transform3D tr = xml::createTransformation(x_tr); - pv = mother.placeVolume(assembly, tr); - } - else if( x_rot && x_pos ){ - Position pos(x_pos.x(0.0),x_pos.y(0.0),x_pos.z(0.0)); - RotationZYX rot(x_rot.z(0.0),x_rot.y(0.0),x_rot.x(0.0)); - pv = mother.placeVolume(assembly, Transform3D(rot, pos)); - } else if( x_rot ){ - RotationZYX rot(x_rot.z(0.0),x_rot.y(0.0),x_rot.x(0.0)); - pv = mother.placeVolume(assembly, rot); - } else if( x_pos ){ - Position pos(x_pos.x(0.0),x_pos.y(0.0),x_pos.z(0.0)); - pv = mother.placeVolume(assembly, pos); - } else { - pv = mother.placeVolume(assembly); - } - sdet.setPlacement(pv); - return sdet; - } - }; -} - -static Ref_t create_element(Detector& description, xml_h e, SensitiveDetector sens) { - Builder b(description); - return b.create(e, sens); + // Need to keep these alive as long as the volumebuilder lives + map<string, xml::DocumentHolder*> docs; + for( xml_coll_t c(x_det,_U(include)); c; ++c ) { + string ref = c.attr<string>(_U(ref)); + docs[ref] = new xml::DocumentHolder(xml::DocumentHandler().load(e, c.attr_value(_U(ref)))); + xml_h vols = docs[ref]->root(); + builder.buildShapes(vols); + builder.buildVolumes(vols); + } + for(auto& d : docs) delete d.second; + + // Now we build the envelope + if ( !x_shp ) x_shp = x_env; + if ( x_shp.typeStr() == "Assembly" ) { + assembly = Assembly("lv"+builder.name); + } + else { + Material mat = description.material(x_env.materialStr()); + Solid solid = xml::createShape(description, x_shp.typeStr(), x_shp); + assembly = Volume("lv"+builder.name, solid, mat); + } + /// Set generic associations + assembly.setAttributes(description,x_det.regionStr(),x_det.limitsStr(),x_det.visStr()); + /// If specified more direct: use these ones. + if ( x_env.hasAttr(_U(vis)) ) { + assembly.setVisAttributes(description, x_env.visStr()); + } + if ( x_det.hasAttr(_U(sensitive)) ) { + sens.setType(x_det.attr<string>(_U(sensitive))); + } + if ( x_env.hasAttr(_U(name)) ) { + assembly->SetName(x_env.nameStr().c_str()); + } + builder.placeDaughters(builder.detector, assembly, x_env); + builder.placeDaughters(builder.detector, assembly, x_det); + x_pos = x_env.child(_U(position),false); + x_rot = x_env.child(_U(rotation),false); + x_tr = x_env.child(_U(transformation),false); + builder.placeDetector(assembly, (x_pos || x_rot || x_tr) ? x_env : x_det); + printout(builder.debug ? ALWAYS : DEBUG, "VolumeBuilder", + "+++ Created subdetector instance %s",builder.name.c_str()); + return builder.detector; } DECLARE_DETELEMENT(DD4hep_VolumeAssembly,create_element) diff --git a/examples/DDCodex/eve/DDEve.xml b/examples/DDCodex/eve/DDEve.xml index 328cf05f0caf866dcbf44793c922d51083e185e7..260cbd67699982013ebad7d1e686c1af7edcc5b3 100644 --- a/examples/DDCodex/eve/DDEve.xml +++ b/examples/DDCodex/eve/DDEve.xml @@ -12,7 +12,7 @@ --> <display visLevel="12" loadLevel="12"/> - <collection name="CodexHits" hits="PointSet" color="kRed" size="0.8" type="20"/> + <collection name="CodexHits" hits="PointSet" color="kRed" size="1.4" type="20"/> <collection name="MC_Particles" hits="Particles" size="0.6" width="1" type="kCircle"/> <view name="3D Trackers" type="View3D">