File indexing completed on 2025-03-14 08:15:02
0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013 #ifndef DD4HEP_NONE
0014
0015
0016 #include <XML/Utilities.h>
0017 #include <DD4hep/Plugins.h>
0018 #include <DD4hep/Detector.h>
0019 #include <DD4hep/Printout.h>
0020 #include <DD4hep/DetFactoryHelper.h>
0021 #include <Math/Polar2D.h>
0022
0023
0024 class TObject;
0025
0026 using namespace dd4hep::xml::tools;
0027 using dd4hep::printout;
0028
0029 namespace {
0030 static constexpr const char* TAG_LIMITSETREF = "limitsetref";
0031 static constexpr const char* TAG_REGIONREF = "regionref";
0032 static constexpr const char* TAG_VISREF = "visref";
0033
0034 static constexpr const char* TAG_COMBINE_HITS = "combine_hits";
0035 static constexpr const char* TAG_VERBOSE = "verbose";
0036 static constexpr const char* TAG_TYPE = "type";
0037 static constexpr const char* TAG_ECUT = "ecut";
0038 static constexpr const char* TAG_HITS_COLLECTION = "hits_collection";
0039 }
0040
0041
0042 dd4hep::Transform3D dd4hep::xml::createTransformation(xml::Element e) {
0043 int flag = 0;
0044 Transform3D position, rotation, result;
0045 for( xml_coll_t c(e,_U(star)); c; ++c ) {
0046 std::string tag = c.tag();
0047 xml_dim_t x_elt = c;
0048 if ( tag == "positionRPhiZ" ) {
0049 if ( flag == 1 ) result = position * result;
0050 else if ( flag == 2 ) result = (position * rotation) * result;
0051 PositionRhoZPhi pos(x_elt.r(0), x_elt.z(0), x_elt.phi(0));
0052 position = Transform3D(pos);
0053 rotation = Transform3D();
0054 flag = 1;
0055 }
0056 else if ( tag == "position" ) {
0057 if ( flag == 1 ) result = position * result;
0058 else if ( flag == 2 ) result = (position * rotation) * result;
0059 Position pos(x_elt.x(0), x_elt.y(0), x_elt.z(0));
0060 position = Transform3D(pos);
0061 rotation = Transform3D();
0062 flag = 1;
0063 }
0064 else if ( tag == "transformation" ) {
0065 if ( flag == 1 ) result = position * result;
0066 else if ( flag == 2 ) result = (position * rotation) * result;
0067 Transform3D trafo = createTransformation(c);
0068 result = trafo * result;
0069 position = Transform3D();
0070 rotation = Transform3D();
0071 flag = 0;
0072 }
0073 else if ( tag == "rotation" ) {
0074 rotation = Transform3D(RotationZYX(x_elt.z(0), x_elt.y(0), x_elt.x(0)));
0075 flag = 2;
0076 }
0077 }
0078 if ( flag == 1 ) result = position * result;
0079 else if ( flag == 2 ) result = (position * rotation) * result;
0080 return result;
0081 }
0082
0083
0084 dd4hep::Solid dd4hep::xml::createShape(Detector& description,
0085 const std::string& shape_type,
0086 xml::Element element) {
0087 std::string fac = shape_type + "__shape_constructor";
0088 xml::Handle_t solid_elt = element;
0089 Solid solid = Solid(PluginService::Create<TObject*>(fac, &description, &solid_elt));
0090 if ( !solid.isValid() ) {
0091 PluginDebug dbg;
0092 PluginService::Create<TObject*>(fac, &description, &solid_elt);
0093 dd4hep::except("xml::createShape","Failed to create solid of type %s [%s]",
0094 shape_type.c_str(),dbg.missingFactory(shape_type).c_str());
0095 }
0096 return solid;
0097 }
0098
0099
0100 dd4hep::Volume dd4hep::xml::createStdVolume(Detector& description, xml::Element element) {
0101 Volume vol;
0102 xml_dim_t elt(element);
0103 std::string typ, tag = elt.tag();
0104 PrintLevel lvl = ALWAYS;
0105
0106
0107 printout(lvl, "xml::createStdVolume", "++ Processing tag: %-12s", tag.c_str());
0108 if ( elt.hasAttr(_U(material)) ) {
0109 xml_dim_t x_s = elt.child(_U(shape));
0110 Solid sol = createShape(description, x_s.typeStr(), x_s);
0111 Material mat = description.material(elt.attr<std::string>(_U(material)));
0112 vol = Volume("volume", sol, mat);
0113 if ( elt.hasAttr(_U(name)) ) vol->SetName(elt.nameStr().c_str());
0114 vol.setAttributes(description,elt.regionStr(),elt.limitsStr(),elt.visStr());
0115 printout(lvl, "xml::createStdVolume", "++ --> name: %s vis: %s region: %s limits: %s",
0116 vol.name(),
0117 elt.visStr("").c_str(),
0118 elt.regionStr("").c_str(),
0119 elt.limitsStr("").c_str());
0120 elt = std::move(x_s);
0121 }
0122 else if ( elt.hasAttr(_U(type)) ) {
0123 typ = elt.typeStr();
0124 if ( typ == "CAD_Assembly" || typ == "CAD_MultiVolume" || typ == "GenVolume" )
0125 vol = xml::createVolume(description, typ, elt);
0126 else if ( typ.substr(1) == "ssembly" )
0127 vol = Assembly("assembly");
0128 if ( elt.hasAttr(_U(name)) ) vol->SetName(elt.nameStr().c_str());
0129 vol.setAttributes(description,elt.regionStr(),elt.limitsStr(),elt.visStr());
0130 printout(lvl, "xml::createStdVolume", "++ --> name: %s vis: %s region: %s limits: %s",
0131 vol.name(),
0132 elt.visStr("").c_str(),
0133 elt.regionStr("").c_str(),
0134 elt.limitsStr("").c_str());
0135 }
0136 if ( vol.isValid() ) {
0137 for( xml_coll_t xv(elt, _U(volume)); xv; ++xv ) {
0138 xml_dim_t xvol = xv;
0139 xml_dim_t xshap = xv.child(_U(shape), false);
0140
0141
0142
0143
0144
0145
0146
0147
0148
0149
0150
0151
0152
0153
0154
0155 if ( xvol && ((xvol.hasAttr(_U(material)) && xshap) || xvol.hasAttr(_U(type))) ) {
0156 RotationZYX rot;
0157 Position pos;
0158 xml_comp_t x_rot = xvol.child( _U(rotation), false );
0159 xml_comp_t x_pos = xvol.child( _U(position), false );
0160 Volume child = xml::createStdVolume( description, xvol );
0161 if ( x_rot ) rot = RotationZYX( x_rot.z(0),x_rot.y(0),x_rot.x(0) );
0162 if ( x_pos ) pos = Position( x_pos.x(0),x_pos.y(0),x_pos.z(0) );
0163 Transform3D trafo(Rotation3D(rot), pos);
0164 vol.placeVolume( child, trafo );
0165 }
0166 }
0167 for( xml_coll_t xs(elt, _U(shape)); xs; ++xs ) {
0168 xml_dim_t xshap = xs;
0169
0170
0171
0172
0173
0174
0175
0176
0177
0178 if ( xshap && xshap.hasAttr(_U(type)) ) {
0179 RotationZYX rot;
0180 Position pos;
0181 xml_comp_t x_rot = xshap.child( _U(rotation), false );
0182 xml_comp_t x_pos = xshap.child( _U(position), false );
0183 Volume child = xml::createStdVolume( description, xshap );
0184 if ( x_rot ) rot = RotationZYX( x_rot.z(0),x_rot.y(0),x_rot.x(0) );
0185 if ( x_pos ) pos = Position( x_pos.x(0),x_pos.y(0),x_pos.z(0) );
0186 Transform3D trafo(Rotation3D(rot), pos);
0187 vol.placeVolume( child, trafo );
0188 }
0189 }
0190 return vol;
0191 }
0192 dd4hep::except("xml::createStdVolume","Failed to create volume. No material specified!");
0193 return Volume();
0194 }
0195
0196
0197 dd4hep::Volume dd4hep::xml::createVolume(Detector& description,
0198 const std::string& typ,
0199 xml::Element element) {
0200 if ( !typ.empty() ) {
0201 xml_dim_t e(element);
0202 std::string fac = typ + "__volume_constructor";
0203 xml::Handle_t elt = element;
0204 TObject* obj = PluginService::Create<TObject*>(fac, &description, &elt);
0205 Volume vol = Volume(dynamic_cast<TGeoVolume*>(obj));
0206 if ( !vol.isValid() ) {
0207 PluginDebug dbg;
0208 PluginService::Create<TObject*>(fac, &description, &elt);
0209 except("xml::createShape","Failed to create volume of type %s [%s]",
0210 typ.c_str(),dbg.missingFactory(typ).c_str());
0211 }
0212 if ( e.hasAttr(_U(name)) ) vol->SetName(e.attr<std::string>(_U(name)).c_str());
0213 vol.setAttributes(description,e.regionStr(),e.limitsStr(),e.visStr());
0214 return vol;
0215 }
0216 dd4hep::except("xml::createVolume","Failed to create volume. No materiaWNo type specified!");
0217 return Volume();
0218 }
0219
0220 dd4hep::Volume dd4hep::xml::createPlacedEnvelope( dd4hep::Detector& description,
0221 dd4hep::xml::Handle_t e,
0222 dd4hep::DetElement sdet)
0223 {
0224 xml_det_t x_det = e;
0225 std::string det_name = x_det.nameStr();
0226
0227 xml_comp_t x_env = x_det.child( dd4hep::xml::Strng_t("envelope") );
0228 xml_comp_t x_shape = x_env.child( _U(shape) );
0229
0230 bool useRot = false;
0231 bool usePos = false;
0232 Position pos;
0233 RotationZYX rot;
0234
0235 if( x_env.hasChild( _U(position) ) ) {
0236 usePos = true;
0237 xml_comp_t env_pos = x_env.position();
0238 pos = Position( env_pos.x(),env_pos.y(),env_pos.z() );
0239 }
0240 if( x_env.hasChild( _U(rotation) ) ) {
0241 useRot = true;
0242 xml_comp_t env_rot = x_env.rotation();
0243 rot = RotationZYX( env_rot.z(),env_rot.y(),env_rot.x() );
0244 }
0245
0246 Volume envelope;
0247 if( x_shape.typeStr() == "Assembly" ){
0248 envelope = Assembly( det_name+"_assembly" );
0249 } else {
0250
0251 Box env_solid = xml_comp_t( x_shape ).createShape();
0252
0253 if( !env_solid.isValid() ){
0254 dd4hep::except("createPlacedEnvelope",
0255 "Cannot create envelope volume : %s for detector %s.",
0256 x_shape.typeStr().c_str(), det_name.c_str());
0257 }
0258 Material env_mat = description.material( x_shape.materialStr() );
0259 envelope = Volume( det_name+"_envelope", env_solid, env_mat );
0260 }
0261 PlacedVolume env_pv;
0262 Volume mother = description.pickMotherVolume(sdet);
0263
0264
0265
0266
0267 if( useRot && usePos ){
0268 env_pv = mother.placeVolume( envelope , Transform3D( rot, pos ) );
0269 } else if( useRot ){
0270 env_pv = mother.placeVolume( envelope , rot );
0271 } else if( usePos ){
0272 env_pv = mother.placeVolume( envelope , pos );
0273 } else {
0274 env_pv = mother.placeVolume( envelope );
0275 }
0276
0277
0278 env_pv.addPhysVolID("system", sdet.id());
0279 sdet.setPlacement( env_pv );
0280 envelope.setAttributes( description,x_det.regionStr(),x_det.limitsStr(),x_env.visStr());
0281 return envelope;
0282 }
0283
0284 void dd4hep::xml::setDetectorTypeFlag( dd4hep::xml::Handle_t e, dd4hep::DetElement sdet ) {
0285 xml_det_t x_det = e;
0286 std::string det_name = x_det.nameStr();
0287
0288 try{
0289 xml_comp_t x_dettype = x_det.child( dd4hep::xml::Strng_t("type_flags") );
0290 unsigned int typeFlag = x_dettype.type();
0291 printout(DEBUG,"Utilities","+++ setDetectorTypeFlags for detector: %s set to 0x%x", det_name.c_str(), typeFlag );
0292 sdet.setTypeFlag( typeFlag );
0293 }
0294 catch(const std::runtime_error& err) {
0295 printout(INFO,"Utilities",
0296 "+++ setDetectorTypeFlags for detector: %s not set.",
0297 det_name.c_str() );
0298 printout(DEBUG, "Utilities",
0299 "+++ setDetectorTypeFlags encountered an error:\n%s", err.what());
0300 }
0301 }
0302
0303 namespace {
0304 template <typename TYPE>
0305 std::size_t _propagate(bool debug,
0306 bool apply_to_children,
0307 dd4hep::Volume vol,
0308 TYPE item,
0309 const dd4hep::Volume& (dd4hep::Volume::*apply)(const TYPE&) const) {
0310 std::size_t count = 0;
0311 if ( !vol->IsAssembly() ) {
0312 printout(debug ? dd4hep::ALWAYS : dd4hep::DEBUG,"VolumeConfig", "++ Volume: %s apply setting %s", vol.name(), item.name());
0313 (vol.*apply)(item);
0314 ++count;
0315 }
0316 if ( apply_to_children ) {
0317 std::set<dd4hep::Volume> handled;
0318 for (Int_t idau = 0, ndau = vol->GetNdaughters(); idau < ndau; ++idau) {
0319 dd4hep::Volume v = vol->GetNode(idau)->GetVolume();
0320 if ( handled.find(v) == handled.end() ) {
0321 handled.insert(v);
0322 count += _propagate(debug, apply_to_children, v, item, apply);
0323 }
0324 }
0325 }
0326 return count;
0327 }
0328 }
0329
0330
0331 std::size_t dd4hep::xml::configVolume( dd4hep::Detector& detector,
0332 dd4hep::xml::Handle_t element,
0333 dd4hep::Volume vol,
0334 bool propagate,
0335 bool ignore_unknown)
0336 {
0337 std::size_t count = 0;
0338 if ( element ) {
0339 xml::Attribute x_dbg = element.attr_nothrow(_U(debug));
0340 bool debug = x_dbg ? element.attr<bool>(x_dbg) : false;
0341 PrintLevel lvl = debug ? ALWAYS : DEBUG;
0342 for( xml_coll_t coll(element, "*"); coll; coll++ ) {
0343 xml_dim_t itm = coll;
0344 std::string nam = itm.nameStr("UN-NAMED");
0345
0346 if ( itm.tag() == TAG_REGIONREF ) {
0347 Region region = detector.region(nam);
0348 count += _propagate(debug, propagate, vol.ptr(), region, &Volume::setRegion);
0349 printout(lvl, "VolumeConfig", "++ %-12s: %-10s REGIONs named '%s'",
0350 vol.name(), region.isValid() ? "Set" : "Invalidate", nam.c_str());
0351 }
0352 else if ( itm.tag() == TAG_LIMITSETREF ) {
0353 LimitSet limitset = detector.limitSet(nam);
0354 count += _propagate(debug, propagate, vol.ptr(), limitset, &Volume::setLimitSet);
0355 printout(lvl, "VolumeConfig", "++ %-12s: %-10s LIMITSETs named '%s'",
0356 vol.name(), limitset.isValid() ? "Set" : "Invalidate", nam.c_str());
0357 }
0358 else if ( itm.tag() == TAG_VISREF ) {
0359 VisAttr attrs = detector.visAttributes(nam);
0360 count += _propagate(debug, propagate, vol.ptr(), attrs, &Volume::setVisAttributes);
0361 printout(lvl, "VolumeConfig", "++ %-12s: %-10s VISATTRs named '%s'",
0362 vol.name(), attrs.isValid() ? "Set" : "Invalidate", nam.c_str());
0363 }
0364 else if ( !ignore_unknown ) {
0365 except("VolumeConfig", "++ Unknown Volume property: %s [Ignored]", itm.tag().c_str());
0366 }
0367 else {
0368 printout(DEBUG, "VolumeConfig", "++ Unknown Volume property: %s [Ignored]", itm.tag().c_str());
0369 }
0370 }
0371 return count;
0372 }
0373 except("VolumeConfig","++ Invalid XML handle to configure DetElement!");
0374 return count;
0375 }
0376
0377
0378 std::size_t dd4hep::xml::configSensitiveDetector( dd4hep::Detector& ,
0379 dd4hep::SensitiveDetector sensitive,
0380 dd4hep::xml::Handle_t element)
0381 {
0382 std::size_t count = 0;
0383 if ( sensitive.isValid() && element ) {
0384 xml::Attribute x_dbg = element.attr_nothrow(_U(debug));
0385 bool debug = x_dbg ? element.attr<bool>(x_dbg) : false;
0386 PrintLevel lvl = debug ? ALWAYS : DEBUG;
0387
0388 for( xml_coll_t coll(element, "*"); coll; coll++ ) {
0389 xml_dim_t itm = coll;
0390 if ( itm.tag() == TAG_COMBINE_HITS ) {
0391 bool value = itm.attr<bool>(_U(value));
0392 sensitive.setCombineHits(value);
0393 ++count;
0394 printout(lvl, "SensDetConfig", "++ %s Set property 'combine_hits' to %s",
0395 sensitive.name(), true_false(value));
0396 }
0397 else if ( itm.tag() == TAG_VERBOSE ) {
0398 bool value = itm.attr<bool>(_U(value));
0399 sensitive.setVerbose(value);
0400 ++count;
0401 printout(lvl, "SensDetConfig", "++ %s Set property 'verbose' to %s",
0402 sensitive.name(), true_false(value));
0403 }
0404 else if ( itm.tag() == TAG_TYPE ) {
0405 std::string value = itm.valueStr();
0406 sensitive.setType(value);
0407 ++count;
0408 printout(lvl, "SensDetConfig", "++ %s Set property 'type' to %s",
0409 sensitive.name(), value.c_str());
0410 }
0411 else if ( itm.tag() == TAG_ECUT ) {
0412 double value = itm.attr<double>(_U(value));
0413 sensitive.setEnergyCutoff(value);
0414 ++count;
0415 printout(lvl, "SensDetConfig", "++ %s Set property 'ecut' to %f",
0416 sensitive.name(), value);
0417 }
0418 else if ( itm.tag() == TAG_HITS_COLLECTION ) {
0419 sensitive.setHitsCollection(itm.valueStr());
0420 ++count;
0421 printout(lvl, "SensDetConfig", "++ %s Set property 'hits_collection' to %s",
0422 sensitive.name(), itm.valueStr().c_str());
0423 }
0424 else {
0425 except("SensDetConfig",
0426 "++ Unknown Sensitive Detector property: %s [Failure]",
0427 itm.tag().c_str());
0428 }
0429 }
0430 return count;
0431 }
0432 except("SensDetConfig",
0433 "FAILED: No valid sensitive detector. Configuration could not be applied!");
0434 return count;
0435 }
0436
0437 #endif