File indexing completed on 2023-03-17 10:51:43
0001 #include "DD4hep/DetFactoryHelper.h"
0002 #include "DD4hep/DetectorHelper.h"
0003 #include "DD4hep/DD4hepUnits.h"
0004 #include "DD4hep/GeoHandler.h"
0005 #include "DD4hep/Printout.h"
0006 #include "DD4hep/Plugins.h"
0007 #include "DD4hep/detail/SegmentationsInterna.h"
0008 #include "DD4hep/detail/DetectorInterna.h"
0009 #include "DD4hep/detail/ObjectsInterna.h"
0010 #include "DD4hep/MatrixHelpers.h"
0011
0012 #include "XML/Utilities.h"
0013 #include "FWCore/ParameterSet/interface/FileInPath.h"
0014 #include "FWCore/Utilities/interface/Exception.h"
0015 #include "FWCore/Utilities/interface/thread_safety_macros.h"
0016 #include "DataFormats/Math/interface/CMSUnits.h"
0017 #include "DetectorDescription/DDCMS/interface/DDAlgoArguments.h"
0018 #include "DetectorDescription/DDCMS/interface/DDNamespace.h"
0019 #include "DetectorDescription/DDCMS/interface/DDParsingContext.h"
0020 #include "DetectorDescription/DDCMS/interface/DDDetector.h"
0021
0022 #include "TGeoManager.h"
0023 #include "TGeoMaterial.h"
0024
0025 #include <climits>
0026 #include <iostream>
0027 #include <iomanip>
0028 #include <map>
0029 #include <vector>
0030 #include <unordered_map>
0031 #include <utility>
0032
0033
0034
0035 using namespace std;
0036 using namespace dd4hep;
0037 using namespace cms;
0038 using namespace cms_units::operators;
0039
0040 namespace dd4hep {
0041
0042 namespace {
0043
0044 atomic<UInt_t> unique_mat_id = 0xAFFEFEED;
0045
0046 class include_constants;
0047 class include_load;
0048 class include_unload;
0049 class print_xml_doc;
0050
0051 class ConstantsSection;
0052 class DDLConstant;
0053
0054 struct DDRegistry {
0055 std::vector<xml::Document> includes;
0056 std::unordered_map<std::string, std::string> unresolvedConst;
0057 std::unordered_map<std::string, std::string> originalConst;
0058 };
0059
0060 class MaterialSection;
0061 class DDLElementaryMaterial;
0062 class DDLCompositeMaterial;
0063
0064 class RotationSection;
0065 class DDLRotation;
0066 class DDLReflectionRotation;
0067 class DDLRotationSequence;
0068 class DDLRotationByAxis;
0069 class DDLTransform3D;
0070
0071 class PosPartSection;
0072 class DDLPosPart;
0073 class DDLDivision;
0074
0075 class LogicalPartSection;
0076 class DDLLogicalPart;
0077
0078 class SolidSection;
0079 class DDLExtrudedPolygon;
0080 class DDLShapeless;
0081 class DDLAssembly;
0082 class DDLTrapezoid;
0083 class DDLEllipticalTube;
0084 class DDLPseudoTrap;
0085 class DDLPolyhedra;
0086 class DDLPolycone;
0087 class DDLTorus;
0088 class DDLTrd1;
0089 class DDLTrd2;
0090 class DDLTruncTubs;
0091 class DDLCutTubs;
0092 class DDLTubs;
0093 class DDLBox;
0094 class DDLCone;
0095 class DDLSphere;
0096 class DDLUnionSolid;
0097 class DDLIntersectionSolid;
0098 class DDLSubtractionSolid;
0099
0100 class DDLAlgorithm;
0101 class DDLVector;
0102
0103 class SpecParSection;
0104 class DDLSpecPar;
0105 class PartSelector;
0106 class Parameter;
0107
0108 class debug;
0109 }
0110
0111 TGeoCombiTrans* createPlacement(const Rotation3D& iRot, const Position& iTrans) {
0112 double elements[9];
0113 iRot.GetComponents(elements);
0114 TGeoRotation r;
0115 r.SetMatrix(elements);
0116
0117 TGeoTranslation t(iTrans.x(), iTrans.y(), iTrans.z());
0118
0119 return new TGeoCombiTrans(t, r);
0120 }
0121
0122
0123 template <>
0124 void Converter<debug>::operator()(xml_h element) const;
0125 template <>
0126 void Converter<print_xml_doc>::operator()(xml_h element) const;
0127
0128
0129 template <>
0130 void Converter<ConstantsSection>::operator()(xml_h element) const;
0131 template <>
0132 void Converter<DDLConstant>::operator()(xml_h element) const;
0133 template <>
0134 void Converter<DDRegistry>::operator()(xml_h element) const;
0135
0136
0137 template <>
0138 void Converter<MaterialSection>::operator()(xml_h element) const;
0139 template <>
0140 void Converter<DDLElementaryMaterial>::operator()(xml_h element) const;
0141 template <>
0142 void Converter<DDLCompositeMaterial>::operator()(xml_h element) const;
0143
0144
0145 template <>
0146 void Converter<RotationSection>::operator()(xml_h element) const;
0147
0148 template <>
0149 void Converter<DDLRotation>::operator()(xml_h element) const;
0150
0151 template <>
0152 void Converter<DDLReflectionRotation>::operator()(xml_h element) const;
0153
0154 template <>
0155 void Converter<DDLRotationSequence>::operator()(xml_h element) const;
0156
0157 template <>
0158 void Converter<DDLRotationByAxis>::operator()(xml_h element) const;
0159 template <>
0160 void Converter<DDLTransform3D>::operator()(xml_h element) const;
0161
0162
0163 template <>
0164 void Converter<LogicalPartSection>::operator()(xml_h element) const;
0165 template <>
0166 void Converter<DDLLogicalPart>::operator()(xml_h element) const;
0167
0168
0169 template <>
0170 void Converter<PosPartSection>::operator()(xml_h element) const;
0171
0172 template <>
0173 void Converter<DDLPosPart>::operator()(xml_h element) const;
0174
0175 template <>
0176 void Converter<DDLDivision>::operator()(xml_h element) const;
0177
0178
0179 template <>
0180 void Converter<SpecParSection>::operator()(xml_h element) const;
0181 template <>
0182 void Converter<DDLSpecPar>::operator()(xml_h element) const;
0183 template <>
0184 void Converter<PartSelector>::operator()(xml_h element) const;
0185 template <>
0186 void Converter<Parameter>::operator()(xml_h element) const;
0187
0188
0189 template <>
0190 void Converter<SolidSection>::operator()(xml_h element) const;
0191
0192 template <>
0193 void Converter<DDLUnionSolid>::operator()(xml_h element) const;
0194
0195 template <>
0196 void Converter<DDLSubtractionSolid>::operator()(xml_h element) const;
0197
0198 template <>
0199 void Converter<DDLIntersectionSolid>::operator()(xml_h element) const;
0200
0201 template <>
0202 void Converter<DDLPseudoTrap>::operator()(xml_h element) const;
0203
0204 template <>
0205 void Converter<DDLExtrudedPolygon>::operator()(xml_h element) const;
0206
0207 template <>
0208 void Converter<DDLShapeless>::operator()(xml_h element) const;
0209
0210 template <>
0211 void Converter<DDLAssembly>::operator()(xml_h element) const;
0212
0213 template <>
0214 void Converter<DDLTrapezoid>::operator()(xml_h element) const;
0215
0216 template <>
0217 void Converter<DDLPolycone>::operator()(xml_h element) const;
0218
0219 template <>
0220 void Converter<DDLPolyhedra>::operator()(xml_h element) const;
0221
0222 template <>
0223 void Converter<DDLEllipticalTube>::operator()(xml_h element) const;
0224
0225 template <>
0226 void Converter<DDLTorus>::operator()(xml_h element) const;
0227
0228 template <>
0229 void Converter<DDLTubs>::operator()(xml_h element) const;
0230
0231 template <>
0232 void Converter<DDLCutTubs>::operator()(xml_h element) const;
0233
0234 template <>
0235 void Converter<DDLTruncTubs>::operator()(xml_h element) const;
0236
0237 template <>
0238 void Converter<DDLSphere>::operator()(xml_h element) const;
0239
0240 template <>
0241 void Converter<DDLTrd1>::operator()(xml_h element) const;
0242
0243 template <>
0244 void Converter<DDLTrd2>::operator()(xml_h element) const;
0245
0246 template <>
0247 void Converter<DDLCone>::operator()(xml_h element) const;
0248
0249 template <>
0250 void Converter<DDLBox>::operator()(xml_h element) const;
0251
0252 template <>
0253 void Converter<DDLAlgorithm>::operator()(xml_h element) const;
0254
0255 template <>
0256 void Converter<DDLVector>::operator()(xml_h element) const;
0257
0258
0259 template <>
0260 void Converter<include_load>::operator()(xml_h element) const;
0261
0262 template <>
0263 void Converter<include_unload>::operator()(xml_h element) const;
0264
0265 template <>
0266 void Converter<include_constants>::operator()(xml_h element) const;
0267 }
0268
0269
0270 template <>
0271 void Converter<ConstantsSection>::operator()(xml_h element) const {
0272 cms::DDNamespace ns(_param<cms::DDParsingContext>(), element);
0273 cms::DDParsingContext* const context = ns.context();
0274 xml_coll_t(element, DD_CMU(Constant)).for_each(Converter<DDLConstant>(description, context, optional));
0275 xml_coll_t(element, DD_CMU(Vector)).for_each(Converter<DDLVector>(description, context, optional));
0276 }
0277
0278
0279 template <>
0280 void Converter<MaterialSection>::operator()(xml_h element) const {
0281 cms::DDNamespace ns(_param<cms::DDParsingContext>(), element);
0282 xml_coll_t(element, DD_CMU(ElementaryMaterial))
0283 .for_each(Converter<DDLElementaryMaterial>(description, ns.context(), optional));
0284 xml_coll_t(element, DD_CMU(CompositeMaterial))
0285 .for_each(Converter<DDLCompositeMaterial>(description, ns.context(), optional));
0286 }
0287
0288 template <>
0289 void Converter<RotationSection>::operator()(xml_h element) const {
0290 cms::DDNamespace ns(_param<cms::DDParsingContext>(), element);
0291 xml_coll_t(element, DD_CMU(Rotation)).for_each(Converter<DDLRotation>(description, ns.context(), optional));
0292 xml_coll_t(element, DD_CMU(ReflectionRotation))
0293 .for_each(Converter<DDLReflectionRotation>(description, ns.context(), optional));
0294 xml_coll_t(element, DD_CMU(RotationSequence))
0295 .for_each(Converter<DDLRotationSequence>(description, ns.context(), optional));
0296 xml_coll_t(element, DD_CMU(RotationByAxis))
0297 .for_each(Converter<DDLRotationByAxis>(description, ns.context(), optional));
0298 }
0299
0300 template <>
0301 void Converter<PosPartSection>::operator()(xml_h element) const {
0302 cms::DDNamespace ns(_param<cms::DDParsingContext>(), element);
0303 xml_coll_t(element, DD_CMU(Division)).for_each(Converter<DDLDivision>(description, ns.context(), optional));
0304 xml_coll_t(element, DD_CMU(PosPart)).for_each(Converter<DDLPosPart>(description, ns.context(), optional));
0305 xml_coll_t(element, DD_CMU(Algorithm)).for_each(Converter<DDLAlgorithm>(description, ns.context(), optional));
0306 }
0307
0308 template <>
0309 void Converter<SpecParSection>::operator()(xml_h element) const {
0310 cms::DDNamespace ns(_param<cms::DDParsingContext>(), element);
0311 xml_coll_t(element, DD_CMU(SpecPar)).for_each(Converter<DDLSpecPar>(description, ns.context(), optional));
0312 }
0313
0314 template <>
0315 void Converter<DDLSpecPar>::operator()(xml_h element) const {
0316 cms::DDNamespace ns(_param<cms::DDParsingContext>(), element);
0317 xml_coll_t(element, DD_CMU(PartSelector)).for_each(Converter<PartSelector>(description, ns.context(), optional));
0318 xml_coll_t(element, DD_CMU(Parameter)).for_each(Converter<Parameter>(description, ns.context(), optional));
0319 }
0320
0321
0322 template <>
0323 void Converter<LogicalPartSection>::operator()(xml_h element) const {
0324 cms::DDNamespace ns(_param<cms::DDParsingContext>(), element);
0325 xml_coll_t(element, DD_CMU(LogicalPart)).for_each(Converter<DDLLogicalPart>(description, ns.context(), optional));
0326 }
0327
0328
0329 template <>
0330 void Converter<SolidSection>::operator()(xml_h element) const {
0331 cms::DDNamespace ns(_param<cms::DDParsingContext>(), element);
0332 for (xml_coll_t solid(element, _U(star)); solid; ++solid) {
0333 using cms::hash;
0334 switch (hash(solid.tag())) {
0335 case hash("Box"):
0336 Converter<DDLBox>(description, ns.context(), optional)(solid);
0337 break;
0338 case hash("Polycone"):
0339 Converter<DDLPolycone>(description, ns.context(), optional)(solid);
0340 break;
0341 case hash("Polyhedra"):
0342 Converter<DDLPolyhedra>(description, ns.context(), optional)(solid);
0343 break;
0344 case hash("Tubs"):
0345 Converter<DDLTubs>(description, ns.context(), optional)(solid);
0346 break;
0347 case hash("CutTubs"):
0348 Converter<DDLCutTubs>(description, ns.context(), optional)(solid);
0349 break;
0350 case hash("TruncTubs"):
0351 Converter<DDLTruncTubs>(description, ns.context(), optional)(solid);
0352 break;
0353 case hash("Tube"):
0354 Converter<DDLTubs>(description, ns.context(), optional)(solid);
0355 break;
0356 case hash("Trd1"):
0357 Converter<DDLTrd1>(description, ns.context(), optional)(solid);
0358 break;
0359 case hash("Trd2"):
0360 Converter<DDLTrd2>(description, ns.context(), optional)(solid);
0361 break;
0362 case hash("Cone"):
0363 Converter<DDLCone>(description, ns.context(), optional)(solid);
0364 break;
0365 case hash("Sphere"):
0366 Converter<DDLSphere>(description, ns.context(), optional)(solid);
0367 break;
0368 case hash("EllipticalTube"):
0369 Converter<DDLEllipticalTube>(description, ns.context(), optional)(solid);
0370 break;
0371 case hash("Torus"):
0372 Converter<DDLTorus>(description, ns.context(), optional)(solid);
0373 break;
0374 case hash("PseudoTrap"):
0375 Converter<DDLPseudoTrap>(description, ns.context(), optional)(solid);
0376 break;
0377 case hash("ExtrudedPolygon"):
0378 Converter<DDLExtrudedPolygon>(description, ns.context(), optional)(solid);
0379 break;
0380 case hash("Trapezoid"):
0381 Converter<DDLTrapezoid>(description, ns.context(), optional)(solid);
0382 break;
0383 case hash("UnionSolid"):
0384 Converter<DDLUnionSolid>(description, ns.context(), optional)(solid);
0385 break;
0386 case hash("SubtractionSolid"):
0387 Converter<DDLSubtractionSolid>(description, ns.context(), optional)(solid);
0388 break;
0389 case hash("IntersectionSolid"):
0390 Converter<DDLIntersectionSolid>(description, ns.context(), optional)(solid);
0391 break;
0392 case hash("ShapelessSolid"):
0393 Converter<DDLShapeless>(description, ns.context(), optional)(solid);
0394 break;
0395 case hash("Assembly"):
0396 Converter<DDLAssembly>(description, ns.context(), optional)(solid);
0397 break;
0398 default:
0399 throw std::runtime_error("Request to process unknown shape '" + xml_dim_t(solid).nameStr() + "' [" +
0400 solid.tag() + "]");
0401 break;
0402 }
0403 }
0404 }
0405
0406
0407 template <>
0408 void Converter<DDLConstant>::operator()(xml_h element) const {
0409 cms::DDNamespace ns(_param<cms::DDParsingContext>());
0410 DDRegistry* res = _option<DDRegistry>();
0411 xml_dim_t constant = element;
0412 xml_dim_t par = constant.parent();
0413 bool eval = par.hasAttr(_U(eval)) ? par.attr<bool>(_U(eval)) : true;
0414 string val = constant.valueStr();
0415 string nam = constant.nameStr();
0416 string real = ns.prepend(nam);
0417 string typ = eval ? "number" : "string";
0418 size_t idx = val.find('[');
0419
0420 if (constant.hasAttr(_U(type)))
0421 typ = constant.typeStr();
0422
0423 if (idx == string::npos || typ == "string") {
0424 try {
0425 ns.addConstant(nam, val, typ);
0426 res->originalConst[real] = val;
0427 } catch (const exception& e) {
0428 #ifdef EDM_ML_DEBUG
0429
0430 printout(INFO,
0431 "DD4CMS",
0432 "++ Unresolved constant: %s = %s [%s]. Try to resolve later. [%s]",
0433 real.c_str(),
0434 val.c_str(),
0435 typ.c_str(),
0436 e.what());
0437 #endif
0438 }
0439 return;
0440 }
0441
0442 while (idx != string::npos) {
0443 ++idx;
0444 size_t idp = val.find(':', idx);
0445 size_t idq = val.find(']', idx);
0446 if (idp == string::npos || idp > idq)
0447 val.insert(idx, ns.name());
0448 else if (idp != string::npos && idp < idq)
0449 val[idp] = NAMESPACE_SEP;
0450 idx = val.find('[', idx);
0451 }
0452
0453 #ifdef EDM_ML_DEBUG
0454
0455 printout(
0456 ns.context()->debug_constants ? ALWAYS : DEBUG, "Constant", "Unresolved: %s -> %s", real.c_str(), val.c_str());
0457
0458 #endif
0459
0460 res->originalConst[real] = val;
0461 res->unresolvedConst[real] = val;
0462 }
0463
0464
0465 template <>
0466 void Converter<DDLElementaryMaterial>::operator()(xml_h element) const {
0467 cms::DDNamespace ns(_param<cms::DDParsingContext>());
0468 xml_dim_t xmat(element);
0469 const string xmatName(xmat.nameStr());
0470 string nam = ns.prepend(xmatName);
0471 TGeoManager& mgr = description.manager();
0472 TGeoMaterial* mat = mgr.GetMaterial(nam.c_str());
0473 if (nullptr == mat) {
0474 const char* matname = nam.c_str();
0475 double density = xmat.attr<double>(DD_CMU(density)) / (dd4hep::g / dd4hep::cm3);
0476 int atomicNumber = xmat.attr<int>(DD_CMU(atomicNumber));
0477 double atomicWeight = xmat.attr<double>(DD_CMU(atomicWeight)) / (dd4hep::g / dd4hep::mole);
0478 TGeoElementTable* tab = mgr.GetElementTable();
0479 int nElem = tab->GetNelements();
0480
0481 #ifdef EDM_ML_DEBUG
0482
0483 printout(ns.context()->debug_materials ? ALWAYS : DEBUG, "DD4CMS", "+++ Element table size = %d", nElem);
0484
0485 #endif
0486
0487 if (nElem <= 1) {
0488 tab->TGeoElementTable::~TGeoElementTable();
0489 new (tab) TGeoElementTable();
0490 tab->BuildDefaultElements();
0491 }
0492 TGeoMixture* mix = new TGeoMixture(nam.c_str(), 1, density);
0493 const char* const matNameNoNS = xmatName.c_str();
0494 TGeoElement* elt = tab->FindElement(matNameNoNS);
0495
0496 #ifdef EDM_ML_DEBUG
0497
0498 printout(ns.context()->debug_materials ? ALWAYS : DEBUG,
0499 "DD4CMS",
0500 "+++ Searching for material %-48s elt_ptr = %ld",
0501 matNameNoNS,
0502 elt);
0503
0504 printout(ns.context()->debug_materials ? ALWAYS : DEBUG,
0505 "DD4CMS",
0506 "+++ Converting material %-48s Atomic weight %8.3f [g/mol], Atomic number %u, Density: %8.3f [g/cm3] "
0507 "ROOT: %8.3f [g/cm3]",
0508 ('"' + nam + '"').c_str(),
0509 atomicWeight,
0510 atomicNumber,
0511 density,
0512 mix->GetDensity());
0513
0514 #endif
0515
0516 bool newMatDef = false;
0517
0518 if (elt) {
0519
0520
0521 #ifdef EDM_ML_DEBUG
0522
0523 printout(ns.context()->debug_materials ? ALWAYS : DEBUG,
0524 "DD4CMS",
0525 " ROOT definition of %-50s Atomic weight %g, Atomic number %u, Number of nucleons %u",
0526 elt->GetName(),
0527 elt->A(),
0528 elt->Z(),
0529 elt->N());
0530 printout(ns.context()->debug_materials ? ALWAYS : DEBUG,
0531 "DD4CMS",
0532 "+++ Compared to XML values: Atomic weight %g, Atomic number %u",
0533 atomicWeight,
0534 atomicNumber);
0535 #endif
0536
0537 static constexpr double const weightTolerance = 1.0e-6;
0538 if (atomicNumber != elt->Z() ||
0539 (std::abs(atomicWeight - elt->A()) > (weightTolerance * (atomicWeight + elt->A()))))
0540 newMatDef = true;
0541 }
0542
0543 if (!elt || newMatDef) {
0544 if (newMatDef) {
0545 #ifdef EDM_ML_DEBUG
0546
0547 printout(ns.context()->debug_materials ? ALWAYS : DEBUG,
0548 "DD4CMS Warning",
0549 "+++ Converter<ElementaryMaterial> Different definition of a default element with name:%s [CREATE NEW "
0550 "MATERIAL]",
0551 matname);
0552
0553 #endif
0554
0555 } else {
0556 #ifdef EDM_ML_DEBUG
0557
0558 printout(ns.context()->debug_materials ? ALWAYS : DEBUG,
0559 "DD4CMS Warning",
0560 "+++ Converter<ElementaryMaterial> No default element present with name:%s [CREATE NEW MATERIAL]",
0561 matname);
0562
0563 #endif
0564 }
0565 elt = new TGeoElement(matNameNoNS, matNameNoNS, atomicNumber, atomicWeight);
0566 }
0567
0568 mix->AddElement(elt, 1.0);
0569 mix->SetTemperature(ns.context()->description.stdConditions().temperature);
0570 mix->SetPressure(ns.context()->description.stdConditions().pressure);
0571
0572
0573 TGeoMedium* medium = mgr.GetMedium(matname);
0574 if (nullptr == medium) {
0575 --unique_mat_id;
0576 medium = new TGeoMedium(matname, unique_mat_id, mix);
0577 medium->SetTitle("material");
0578 medium->SetUniqueID(unique_mat_id);
0579 }
0580 }
0581 }
0582
0583
0584 template <>
0585 void Converter<DDLCompositeMaterial>::operator()(xml_h element) const {
0586 cms::DDNamespace ns(_param<cms::DDParsingContext>());
0587 xml_dim_t xmat(element);
0588 string nam = ns.prepend(xmat.nameStr());
0589
0590 TGeoManager& mgr = description.manager();
0591 TGeoMaterial* mat = mgr.GetMaterial(nam.c_str());
0592 if (nullptr == mat) {
0593 const char* matname = nam.c_str();
0594 double density = xmat.attr<double>(DD_CMU(density)) / (dd4hep::g / dd4hep::cm3);
0595 xml_coll_t composites(xmat, DD_CMU(MaterialFraction));
0596 TGeoMixture* mix = new TGeoMixture(nam.c_str(), composites.size(), density);
0597
0598 #ifdef EDM_ML_DEBUG
0599
0600 printout(ns.context()->debug_materials ? ALWAYS : DEBUG,
0601 "DD4CMS",
0602 "++ Converting material %-48s Density: %8.3f [g/cm3] ROOT: %8.3f [g/cm3]",
0603 ('"' + nam + '"').c_str(),
0604 density,
0605 mix->GetDensity());
0606
0607 #endif
0608
0609 if (ns.context()->makePayload) {
0610 ns.context()->compMaterialsVec.emplace_back(std::make_pair(nam, density));
0611 }
0612 for (composites.reset(); composites; ++composites) {
0613 xml_dim_t xfrac(composites);
0614 xml_dim_t xfrac_mat(xfrac.child(DD_CMU(rMaterial)));
0615 double fraction = xfrac.fraction();
0616 string fracname = ns.realName(xfrac_mat.nameStr());
0617
0618 if (ns.context()->makePayload) {
0619 ns.context()->compMaterialsRefs[nam].emplace_back(
0620 cms::DDParsingContext::CompositeMaterial(ns.prepend(fracname), fraction));
0621 }
0622 TGeoMaterial* frac_mat = mgr.GetMaterial(fracname.c_str());
0623 if (frac_mat == nullptr)
0624 frac_mat = mgr.GetMaterial(ns.prepend(fracname).c_str());
0625 if (frac_mat) {
0626 mix->AddElement(frac_mat, fraction);
0627 continue;
0628 }
0629
0630 throw cms::Exception("DD4CMS") << "Composite material \"" + fracname + "\" or \"" + ns.prepend(fracname) +
0631 "\" not yet defined.";
0632 }
0633 mix->SetTemperature(ns.context()->description.stdConditions().temperature);
0634 mix->SetPressure(ns.context()->description.stdConditions().pressure);
0635 mix->SetRadLen(0e0);
0636
0637 TGeoMedium* medium = mgr.GetMedium(matname);
0638 if (nullptr == medium) {
0639 --unique_mat_id;
0640 medium = new TGeoMedium(matname, unique_mat_id, mix);
0641 medium->SetTitle("material");
0642 medium->SetUniqueID(unique_mat_id);
0643 }
0644 }
0645 }
0646
0647
0648 template <>
0649 void Converter<DDLRotation>::operator()(xml_h element) const {
0650 cms::DDParsingContext* context = _param<cms::DDParsingContext>();
0651 cms::DDNamespace ns(context);
0652 xml_dim_t xrot(element);
0653 string nam = xrot.nameStr();
0654 double thetaX = xrot.hasAttr(DD_CMU(thetaX)) ? ns.attr<double>(xrot, DD_CMU(thetaX)) : 0e0;
0655 double phiX = xrot.hasAttr(DD_CMU(phiX)) ? ns.attr<double>(xrot, DD_CMU(phiX)) : 0e0;
0656 double thetaY = xrot.hasAttr(DD_CMU(thetaY)) ? ns.attr<double>(xrot, DD_CMU(thetaY)) : 0e0;
0657 double phiY = xrot.hasAttr(DD_CMU(phiY)) ? ns.attr<double>(xrot, DD_CMU(phiY)) : 0e0;
0658 double thetaZ = xrot.hasAttr(DD_CMU(thetaZ)) ? ns.attr<double>(xrot, DD_CMU(thetaZ)) : 0e0;
0659 double phiZ = xrot.hasAttr(DD_CMU(phiZ)) ? ns.attr<double>(xrot, DD_CMU(phiZ)) : 0e0;
0660 Rotation3D rot = makeRotation3D(thetaX, phiX, thetaY, phiY, thetaZ, phiZ);
0661
0662 #ifdef EDM_ML_DEBUG
0663
0664 printout(context->debug_rotations ? ALWAYS : DEBUG,
0665 "DD4CMS",
0666 "+++ Adding rotation: %-32s: (theta/phi)[rad] X: %6.3f %6.3f Y: %6.3f %6.3f Z: %6.3f %6.3f",
0667 ns.prepend(nam).c_str(),
0668 thetaX,
0669 phiX,
0670 thetaY,
0671 phiY,
0672 thetaZ,
0673 phiZ);
0674
0675 #endif
0676
0677 ns.addRotation(nam, rot);
0678 }
0679
0680
0681 template <>
0682 void Converter<DDLReflectionRotation>::operator()(xml_h element) const {
0683 cms::DDParsingContext* context = _param<cms::DDParsingContext>();
0684 cms::DDNamespace ns(context);
0685 xml_dim_t xrot(element);
0686 string name = xrot.nameStr();
0687 double thetaX = xrot.hasAttr(DD_CMU(thetaX)) ? ns.attr<double>(xrot, DD_CMU(thetaX)) : 0e0;
0688 double phiX = xrot.hasAttr(DD_CMU(phiX)) ? ns.attr<double>(xrot, DD_CMU(phiX)) : 0e0;
0689 double thetaY = xrot.hasAttr(DD_CMU(thetaY)) ? ns.attr<double>(xrot, DD_CMU(thetaY)) : 0e0;
0690 double phiY = xrot.hasAttr(DD_CMU(phiY)) ? ns.attr<double>(xrot, DD_CMU(phiY)) : 0e0;
0691 double thetaZ = xrot.hasAttr(DD_CMU(thetaZ)) ? ns.attr<double>(xrot, DD_CMU(thetaZ)) : 0e0;
0692 double phiZ = xrot.hasAttr(DD_CMU(phiZ)) ? ns.attr<double>(xrot, DD_CMU(phiZ)) : 0e0;
0693
0694 #ifdef EDM_ML_DEBUG
0695
0696 printout(context->debug_rotations ? ALWAYS : DEBUG,
0697 "DD4CMS",
0698 "+++ Adding reflection rotation: %-32s: (theta/phi)[rad] X: %6.3f %6.3f Y: %6.3f %6.3f Z: %6.3f %6.3f",
0699 ns.prepend(name).c_str(),
0700 thetaX,
0701 phiX,
0702 thetaY,
0703 phiY,
0704 thetaZ,
0705 phiZ);
0706
0707 #endif
0708
0709 Rotation3D rot = makeRotReflect(thetaX, phiX, thetaY, phiY, thetaZ, phiZ);
0710 ns.addRotation(name, rot);
0711 }
0712
0713
0714 template <>
0715 void Converter<DDLRotationSequence>::operator()(xml_h element) const {
0716 cms::DDParsingContext* context = _param<cms::DDParsingContext>();
0717 cms::DDNamespace ns(context);
0718 xml_dim_t xrot(element);
0719 string nam = xrot.nameStr();
0720 Rotation3D rot;
0721 xml_coll_t rotations(xrot, DD_CMU(RotationByAxis));
0722 for (rotations.reset(); rotations; ++rotations) {
0723 string axis = ns.attr<string>(rotations, DD_CMU(axis));
0724 double angle = ns.attr<double>(rotations, _U(angle));
0725 rot = makeRotation3D(rot, axis, angle);
0726
0727 #ifdef EDM_ML_DEBUG
0728
0729 printout(context->debug_rotations ? ALWAYS : DEBUG,
0730 "DD4CMS",
0731 "+ Adding rotation to: %-29s: (axis/angle)[rad] Axis: %s Angle: %6.3f",
0732 nam.c_str(),
0733 axis.c_str(),
0734 angle);
0735
0736 #endif
0737 }
0738 double xx, xy, xz;
0739 double yx, yy, yz;
0740 double zx, zy, zz;
0741 rot.GetComponents(xx, xy, xz, yx, yy, yz, zx, zy, zz);
0742
0743 #ifdef EDM_ML_DEBUG
0744
0745 printout(context->debug_rotations ? ALWAYS : DEBUG,
0746 "DD4CMS",
0747 "+++ Adding rotation sequence: %-23s: %6.3f %6.3f %6.3f, %6.3f %6.3f %6.3f, %6.3f %6.3f %6.3f",
0748 ns.prepend(nam).c_str(),
0749 xx,
0750 xy,
0751 xz,
0752 yx,
0753 yy,
0754 yz,
0755 zx,
0756 zy,
0757 zz);
0758
0759 #endif
0760
0761 ns.addRotation(nam, rot);
0762 }
0763
0764
0765 template <>
0766 void Converter<DDLRotationByAxis>::operator()(xml_h element) const {
0767 cms::DDParsingContext* context = _param<cms::DDParsingContext>();
0768 cms::DDNamespace ns(context);
0769 xml_dim_t xrot(element);
0770 xml_dim_t par(xrot.parent());
0771 if (xrot.hasAttr(_U(name))) {
0772 string nam = xrot.nameStr();
0773 string axis = ns.attr<string>(xrot, DD_CMU(axis));
0774 double angle = ns.attr<double>(xrot, _U(angle));
0775 Rotation3D rot;
0776 rot = makeRotation3D(rot, axis, angle);
0777
0778 #ifdef EDM_ML_DEBUG
0779
0780 printout(context->debug_rotations ? ALWAYS : DEBUG,
0781 "DD4CMS",
0782 "+++ Adding rotation: %-32s: (axis/angle)[rad] Axis: %s Angle: %6.3f",
0783 ns.prepend(nam).c_str(),
0784 axis.c_str(),
0785 angle);
0786
0787 #endif
0788
0789 ns.addRotation(nam, rot);
0790 }
0791 }
0792
0793
0794 template <>
0795 void Converter<DDLLogicalPart>::operator()(xml_h element) const {
0796 cms::DDNamespace ns(_param<cms::DDParsingContext>());
0797 xml_dim_t e(element);
0798 string sol = e.child(DD_CMU(rSolid)).attr<string>(_U(name));
0799 string mat = e.child(DD_CMU(rMaterial)).attr<string>(_U(name));
0800 string volName = ns.prepend(e.attr<string>(_U(name)));
0801 Solid solid = ns.solid(sol);
0802 Material material = ns.material(mat);
0803 if (ns.context()->assemblySolids.count(sol) == 1) {
0804
0805
0806
0807 ns.addAssembly(volName, false);
0808 return;
0809 }
0810
0811 #ifdef EDM_ML_DEBUG
0812 Volume volume =
0813 #endif
0814
0815 ns.addVolume(Volume(volName, solid, material));
0816
0817 #ifdef EDM_ML_DEBUG
0818
0819 printout(ns.context()->debug_volumes ? ALWAYS : DEBUG,
0820 "DD4CMS",
0821 "+++ %s Volume: %-24s [%s] Shape: %-32s [%s] Material: %-40s [%s]",
0822 e.tag().c_str(),
0823 volName.c_str(),
0824 volume.isValid() ? "VALID" : "INVALID",
0825 sol.c_str(),
0826 solid.isValid() ? "VALID" : "INVALID",
0827 mat.c_str(),
0828 material.isValid() ? "VALID" : "INVALID");
0829
0830 #endif
0831 }
0832
0833
0834 template <>
0835 void Converter<DDLTransform3D>::operator()(xml_h element) const {
0836 cms::DDNamespace ns(_param<cms::DDParsingContext>());
0837 Transform3D* tr = _option<Transform3D>();
0838 xml_dim_t e(element);
0839 xml_dim_t translation = e.child(DD_CMU(Translation), false);
0840 xml_dim_t rotation = e.child(DD_CMU(Rotation), false);
0841 xml_dim_t refRotation = e.child(DD_CMU(rRotation), false);
0842 xml_dim_t refReflectionRotation = e.child(DD_CMU(rReflectionRotation), false);
0843 Position pos;
0844 Rotation3D rot;
0845
0846 if (translation.ptr()) {
0847 double x = ns.attr<double>(translation, _U(x));
0848 double y = ns.attr<double>(translation, _U(y));
0849 double z = ns.attr<double>(translation, _U(z));
0850 pos = Position(x, y, z);
0851 }
0852 if (rotation.ptr()) {
0853 double x = ns.attr<double>(rotation, _U(x));
0854 double y = ns.attr<double>(rotation, _U(y));
0855 double z = ns.attr<double>(rotation, _U(z));
0856 rot = RotationZYX(z, y, x);
0857 } else if (refRotation.ptr()) {
0858 string rotName = ns.prepend(refRotation.nameStr());
0859 rot = ns.rotation(rotName);
0860 } else if (refReflectionRotation.ptr()) {
0861 string rotName = ns.prepend(refReflectionRotation.nameStr());
0862 rot = ns.rotation(rotName);
0863 }
0864 *tr = Transform3D(rot, pos);
0865 }
0866
0867 static void placeAssembly(Volume* parentPtr,
0868 const string& parentName,
0869 Volume* childPtr,
0870 const string& childName,
0871 int copy,
0872 const Transform3D& transform,
0873 cms::DDNamespace& ns) {
0874 #ifdef EDM_ML_DEBUG
0875
0876 printout(ns.context()->debug_placements ? ALWAYS : DEBUG,
0877 "DD4CMS",
0878 "+++ Parent vol: %-24s Child: %-32s, copy:%d",
0879 parentName.c_str(),
0880 childName.c_str(),
0881 copy);
0882
0883 #endif
0884
0885 TGeoShape* shape = (*childPtr)->GetShape();
0886
0887 if (shape->IsA() == TGeoShapeAssembly::Class()) {
0888 TGeoShapeAssembly* as = (TGeoShapeAssembly*)shape;
0889 if (std::fabs(as->GetDX()) < numeric_limits<double>::epsilon() &&
0890 std::fabs(as->GetDY()) < numeric_limits<double>::epsilon() &&
0891 std::fabs(as->GetDZ()) < numeric_limits<double>::epsilon()) {
0892 as->NeedsBBoxRecompute();
0893 as->ComputeBBox();
0894 }
0895 }
0896 if (ns.context()->validate) {
0897 TGeoNode* n;
0898 TString nam_id = TString::Format("%s_%d", (*childPtr)->GetName(), copy);
0899 n = static_cast<TGeoNode*>((*parentPtr)->GetNode(nam_id));
0900 if (n != nullptr) {
0901 printout(ERROR, "PlacedVolume", "++ Attempt to add already existing node %s", (const char*)nam_id);
0902 return;
0903 }
0904 }
0905
0906 PlacedVolume pv;
0907 if ((*childPtr)->IsAssembly()) {
0908 pv = parentPtr->placeVolume(ns.assembly(childName), copy, transform);
0909 } else {
0910 pv = parentPtr->placeVolume(*childPtr, copy, transform);
0911 }
0912
0913 if (!pv.isValid()) {
0914 printout(ERROR, "DD4CMS", "+++ Placement FAILED! Parent:%s Child:%s", parentName.c_str(), childName.c_str());
0915 }
0916 }
0917
0918
0919 template <>
0920 void Converter<DDLPosPart>::operator()(xml_h element) const {
0921 cms::DDNamespace ns(_param<cms::DDParsingContext>());
0922 xml_dim_t e(element);
0923 int copy = e.attr<int>(DD_CMU(copyNumber));
0924 string parentName = ns.prepend(ns.attr<string>(e.child(DD_CMU(rParent)), _U(name)));
0925 string childName = ns.prepend(ns.attr<string>(e.child(DD_CMU(rChild)), _U(name)));
0926 Transform3D transform;
0927 Converter<DDLTransform3D>(description, param, &transform)(element);
0928
0929 Volume parent = ns.volume(parentName, false);
0930 Volume child = ns.volume(childName, false);
0931 Assembly parAsmb = ns.assembly(parentName, false);
0932 Assembly childAsmb = ns.assembly(childName, false);
0933
0934 #ifdef EDM_ML_DEBUG
0935
0936 printout(ns.context()->debug_placements ? ALWAYS : DEBUG,
0937 "DD4CMS",
0938 "+++ %s Parent: %-24s [%s] Child: %-32s [%s] copy:%d",
0939 e.tag().c_str(),
0940 parentName.c_str(),
0941 parent.isValid() ? "VALID" : "INVALID",
0942 childName.c_str(),
0943 child.isValid() ? "VALID" : "INVALID",
0944 copy);
0945
0946 #endif
0947
0948 if (!parent.isValid() && !parAsmb.isValid() && strchr(parentName.c_str(), NAMESPACE_SEP) == nullptr) {
0949 parentName = ns.prepend(parentName);
0950 parAsmb = ns.assembly(parentName, false);
0951 if (!parAsmb.isValid())
0952 parent = ns.volume(parentName);
0953 }
0954
0955 if (!child.isValid() && !childAsmb.isValid() && strchr(childName.c_str(), NAMESPACE_SEP) == nullptr) {
0956 childName = ns.prepend(childName);
0957 child = ns.volume(childName, false);
0958 childAsmb = ns.assembly(childName, false);
0959 }
0960 if (parAsmb.isValid() || childAsmb.isValid()) {
0961 printout(ns.context()->debug_placements ? ALWAYS : DEBUG,
0962 "DD4CMS",
0963 "***** Placing assembly parent %s, child %s",
0964 parentName.c_str(),
0965 childName.c_str());
0966 Volume* parentPtr = parAsmb.isValid() ? &parAsmb : &parent;
0967 Volume* childPtr = childAsmb.isValid() ? &childAsmb : &child;
0968 placeAssembly(parentPtr, parentName, childPtr, childName, copy, transform, ns);
0969 return;
0970 }
0971
0972 #ifdef EDM_ML_DEBUG
0973
0974 printout(ns.context()->debug_placements ? ALWAYS : DEBUG,
0975 "DD4CMS",
0976 "+++ %s Parent: %-24s [%s] Child: %-32s [%s] copy:%d",
0977 e.tag().c_str(),
0978 parentName.c_str(),
0979 parent.isValid() ? "VALID" : "INVALID",
0980 childName.c_str(),
0981 child.isValid() ? "VALID" : "INVALID",
0982 copy);
0983
0984 #endif
0985
0986 PlacedVolume pv;
0987 if (child.isValid()) {
0988
0989
0990
0991 if (!parent) {
0992 except("dd4hep", "Volume: Attempt to assign daughters to an invalid physical parent volume.");
0993 }
0994 if (!child) {
0995 except("dd4hep", "Volume: Attempt to assign an invalid physical daughter volume.");
0996 }
0997 TGeoShape* shape = child->GetShape();
0998
0999 if (shape->IsA() == TGeoShapeAssembly::Class()) {
1000 TGeoShapeAssembly* as = (TGeoShapeAssembly*)shape;
1001 if (std::fabs(as->GetDX()) < numeric_limits<double>::epsilon() &&
1002 std::fabs(as->GetDY()) < numeric_limits<double>::epsilon() &&
1003 std::fabs(as->GetDZ()) < numeric_limits<double>::epsilon()) {
1004 as->NeedsBBoxRecompute();
1005 as->ComputeBBox();
1006 }
1007 }
1008 TGeoNode* n;
1009 TString nam_id = TString::Format("%s_%d", child->GetName(), copy);
1010 if (ns.context()->validate) {
1011 n = static_cast<TGeoNode*>(parent->GetNode(nam_id));
1012 if (n != nullptr) {
1013 printout(ERROR, "PlacedVolume", "++ Attempt to add already existing node %s", (const char*)nam_id);
1014 }
1015 }
1016
1017 Rotation3D rot(transform.Rotation());
1018 Translation3D trans(transform.Translation());
1019 double x, y, z;
1020 trans.GetComponents(x, y, z);
1021 Position pos(x, y, z);
1022 parent->AddNode(child, copy, createPlacement(rot, pos));
1023
1024 n = static_cast<TGeoNode*>(parent->GetNodes()->Last());
1025 assert(n->GetName() == nam_id);
1026 n->TGeoNode::SetUserExtension(new PlacedVolume::Object());
1027 pv = PlacedVolume(n);
1028 }
1029 if (!pv.isValid()) {
1030 printout(ERROR,
1031 "DD4CMS",
1032 "+++ Placement FAILED! Parent:%s Child:%s Valid:%s",
1033 parent.name(),
1034 childName.c_str(),
1035 yes_no(child.isValid()));
1036 }
1037 }
1038
1039
1040 template <>
1041 void Converter<PartSelector>::operator()(xml_h element) const {
1042 cms::DDNamespace ns(_param<cms::DDParsingContext>());
1043 cms::DDParsingContext* const context = ns.context();
1044 dd4hep::SpecParRegistry& registry = *context->description.extension<dd4hep::SpecParRegistry>();
1045 xml_dim_t e(element);
1046 xml_dim_t specPar = e.parent();
1047 string specParName = specPar.attr<string>(_U(name));
1048 string path = e.attr<string>(DD_CMU(path));
1049
1050 #ifdef EDM_ML_DEBUG
1051
1052 printout(ns.context()->debug_specpars ? ALWAYS : DEBUG,
1053 "DD4CMS",
1054 "+++ PartSelector for %s path: %s",
1055 specParName.c_str(),
1056 path.c_str());
1057
1058 #endif
1059
1060 size_t pos = std::string::npos;
1061 if ((pos = path.find("//.*:")) != std::string::npos) {
1062 path.erase(pos + 2, 3);
1063 }
1064 registry.specpars[specParName].paths.emplace_back(std::move(path));
1065 }
1066
1067
1068 template <>
1069 void Converter<Parameter>::operator()(xml_h element) const {
1070 cms::DDNamespace ns(_param<cms::DDParsingContext>());
1071 cms::DDParsingContext* const context = ns.context();
1072 dd4hep::SpecParRegistry& registry = *context->description.extension<dd4hep::SpecParRegistry>();
1073 xml_dim_t e(element);
1074 xml_dim_t specPar = e.parent();
1075 xml_dim_t specParSect = specPar.parent();
1076 string specParName = specPar.attr<string>(_U(name));
1077 string name = e.nameStr();
1078 string value = e.attr<string>(DD_CMU(value));
1079 bool eval = specParSect.hasAttr(_U(eval)) ? specParSect.attr<bool>(_U(eval)) : false;
1080 eval = specPar.hasAttr(_U(eval)) ? specPar.attr<bool>(_U(eval)) : eval;
1081 eval = e.hasAttr(_U(eval)) ? e.attr<bool>(_U(eval)) : eval;
1082
1083 string type = eval ? "number" : "string";
1084
1085 #ifdef EDM_ML_DEBUG
1086
1087 printout(ns.context()->debug_specpars ? ALWAYS : DEBUG,
1088 "DD4CMS",
1089 "+++ Parameter for %s: %s value %s is a %s",
1090 specParName.c_str(),
1091 name.c_str(),
1092 value.c_str(),
1093 type.c_str());
1094
1095 #endif
1096
1097 size_t idx = value.find('[');
1098 if (idx == string::npos && type == "number") {
1099 registry.specpars[specParName].numpars[name].emplace_back(dd4hep::_toDouble(value));
1100 return;
1101 }
1102 if (idx == string::npos || type == "string") {
1103 registry.specpars[specParName].spars[name].emplace_back(std::move(value));
1104 return;
1105 }
1106
1107 while (idx != string::npos) {
1108 ++idx;
1109 size_t idp = value.find(':', idx);
1110 size_t idq = value.find(']', idx);
1111 if (idp == string::npos || idp > idq)
1112 value.insert(idx, ns.name());
1113 else if (idp != string::npos && idp < idq)
1114 value[idp] = NAMESPACE_SEP;
1115 idx = value.find('[', idx);
1116 }
1117
1118 string rep;
1119 string& v = value;
1120 size_t idq;
1121 for (idx = v.find('[', 0); idx != string::npos; idx = v.find('[', idx + 1)) {
1122 idq = v.find(']', idx + 1);
1123 rep = v.substr(idx + 1, idq - idx - 1);
1124 auto r = ns.context()->description.constants().find(rep);
1125 if (r != ns.context()->description.constants().end()) {
1126 rep = "(" + r->second->type + ")";
1127 v.replace(idx, idq - idx + 1, rep);
1128 }
1129 }
1130 registry.specpars[specParName].numpars[name].emplace_back(dd4hep::_toDouble(value));
1131 }
1132
1133 template <typename TYPE>
1134 static void convert_boolean(cms::DDParsingContext* context, xml_h element) {
1135 cms::DDNamespace ns(context);
1136 xml_dim_t e(element);
1137 string nam = e.nameStr();
1138 string solidName[2];
1139 Solid solids[2];
1140 Solid boolean;
1141 int cnt = 0;
1142 if (e.hasChild(DD_CMU(rSolid))) {
1143 for (xml_coll_t c(element, DD_CMU(rSolid)); cnt < 2 && c; ++c, ++cnt) {
1144 solidName[cnt] = c.attr<string>(_U(name));
1145 solids[cnt] = ns.solid(c.attr<string>(_U(name)));
1146 }
1147 } else {
1148 solidName[0] = e.attr<string>(DD_CMU(firstSolid));
1149 if ((solids[0] = ns.solid(e.attr<string>(DD_CMU(firstSolid)))).isValid())
1150 ++cnt;
1151 solidName[1] = e.attr<string>(DD_CMU(secondSolid));
1152 if ((solids[1] = ns.solid(e.attr<string>(DD_CMU(secondSolid)))).isValid())
1153 ++cnt;
1154 }
1155 if (cnt != 2) {
1156 except("DD4CMS", "+++ Failed to create boolean solid %s. Found only %d parts.", nam.c_str(), cnt);
1157 }
1158
1159 #ifdef EDM_ML_DEBUG
1160
1161 printout(ns.context()->debug_placements ? ALWAYS : DEBUG,
1162 "DD4CMS",
1163 "+++ BooleanSolid: %s Left: %-32s Right: %-32s",
1164 nam.c_str(),
1165 ((solids[0].ptr() == nullptr) ? solidName[0].c_str() : solids[0]->GetName()),
1166 ((solids[1].ptr() == nullptr) ? solidName[1].c_str() : solids[1]->GetName()));
1167
1168 #endif
1169
1170 if (solids[0].isValid() && solids[1].isValid()) {
1171 Transform3D trafo;
1172 Converter<DDLTransform3D>(context->description, context, &trafo)(element);
1173 boolean = TYPE(solids[0], solids[1], trafo);
1174 } else {
1175
1176 Transform3D trafo;
1177 Converter<DDLTransform3D>(context->description, context, &trafo)(element);
1178 ns.context()->unresolvedShapes.emplace(nam,
1179 DDParsingContext::BooleanShape<TYPE>(solidName[0], solidName[1], trafo));
1180 if (solids[0].isValid() == false) {
1181 printout(ERROR, "DD4CMS", "++ Solid not defined yet: %s", solidName[0].c_str());
1182 }
1183 if (solids[1].isValid() == false) {
1184 printout(ERROR, "DD4CMS", "++ Solid not defined yet: %s", solidName[1].c_str());
1185 }
1186 printout(ERROR, "DD4CMS", "++ Re-order XML files to prevent references to undefined solids");
1187 }
1188 if (!boolean.isValid()) {
1189
1190 ns.context()->shapes.emplace(nam, dd4hep::Solid(nullptr));
1191 } else
1192 ns.addSolid(nam, boolean);
1193 }
1194
1195
1196 template <>
1197 void Converter<DDLUnionSolid>::operator()(xml_h element) const {
1198 convert_boolean<UnionSolid>(_param<cms::DDParsingContext>(), element);
1199 }
1200
1201
1202 template <>
1203 void Converter<DDLSubtractionSolid>::operator()(xml_h element) const {
1204 convert_boolean<SubtractionSolid>(_param<cms::DDParsingContext>(), element);
1205 }
1206
1207
1208 template <>
1209 void Converter<DDLIntersectionSolid>::operator()(xml_h element) const {
1210 convert_boolean<IntersectionSolid>(_param<cms::DDParsingContext>(), element);
1211 }
1212
1213
1214 template <>
1215 void Converter<DDLPolycone>::operator()(xml_h element) const {
1216 cms::DDNamespace ns(_param<cms::DDParsingContext>());
1217 xml_dim_t e(element);
1218 string nam = e.nameStr();
1219 double startPhi = ns.attr<double>(e, DD_CMU(startPhi));
1220 double deltaPhi = ns.attr<double>(e, DD_CMU(deltaPhi));
1221 vector<double> z, rmin, rmax, r;
1222
1223 for (xml_coll_t rzpoint(element, DD_CMU(RZPoint)); rzpoint; ++rzpoint) {
1224 z.emplace_back(ns.attr<double>(rzpoint, _U(z)));
1225 r.emplace_back(ns.attr<double>(rzpoint, _U(r)));
1226 }
1227 if (z.empty()) {
1228 for (xml_coll_t zplane(element, DD_CMU(ZSection)); zplane; ++zplane) {
1229 rmin.emplace_back(ns.attr<double>(zplane, DD_CMU(rMin)));
1230 rmax.emplace_back(ns.attr<double>(zplane, DD_CMU(rMax)));
1231 z.emplace_back(ns.attr<double>(zplane, _U(z)));
1232 }
1233
1234 #ifdef EDM_ML_DEBUG
1235
1236 printout(ns.context()->debug_shapes ? ALWAYS : DEBUG,
1237 "DD4CMS",
1238 "+ Polycone: startPhi=%10.3f [rad] deltaPhi=%10.3f [rad] %4ld z-planes",
1239 startPhi,
1240 deltaPhi,
1241 z.size());
1242
1243 #endif
1244
1245 ns.addSolid(nam, Polycone(startPhi, deltaPhi, rmin, rmax, z));
1246 } else {
1247 #ifdef EDM_ML_DEBUG
1248
1249 printout(ns.context()->debug_shapes ? ALWAYS : DEBUG,
1250 "DD4CMS",
1251 "+ Polycone: startPhi=%10.3f [rad] deltaPhi=%10.3f [rad] %4ld z-planes and %4ld radii",
1252 startPhi,
1253 deltaPhi,
1254 z.size(),
1255 r.size());
1256
1257 #endif
1258
1259 ns.addSolid(nam, Polycone(startPhi, deltaPhi, r, z));
1260 }
1261 }
1262
1263
1264 template <>
1265 void Converter<DDLExtrudedPolygon>::operator()(xml_h element) const {
1266 cms::DDNamespace ns(_param<cms::DDParsingContext>());
1267 xml_dim_t e(element);
1268 string nam = e.nameStr();
1269 vector<double> pt_x, pt_y, sec_x, sec_y, sec_z, sec_scale;
1270
1271 for (xml_coll_t sec(element, DD_CMU(ZXYSection)); sec; ++sec) {
1272 sec_z.emplace_back(ns.attr<double>(sec, _U(z)));
1273 sec_x.emplace_back(ns.attr<double>(sec, _U(x)));
1274 sec_y.emplace_back(ns.attr<double>(sec, _U(y)));
1275 sec_scale.emplace_back(ns.attr<double>(sec, DD_CMU(scale), 1.0));
1276 }
1277 for (xml_coll_t pt(element, DD_CMU(XYPoint)); pt; ++pt) {
1278 pt_x.emplace_back(ns.attr<double>(pt, _U(x)));
1279 pt_y.emplace_back(ns.attr<double>(pt, _U(y)));
1280 }
1281
1282 #ifdef EDM_ML_DEBUG
1283
1284 printout(ns.context()->debug_shapes ? ALWAYS : DEBUG,
1285 "DD4CMS",
1286 "+ ExtrudedPolygon: %4ld points %4ld zxy sections",
1287 pt_x.size(),
1288 sec_z.size());
1289
1290 #endif
1291
1292 ns.addSolid(nam, ExtrudedPolygon(pt_x, pt_y, sec_z, sec_x, sec_y, sec_scale));
1293 }
1294
1295
1296 template <>
1297 void Converter<DDLPolyhedra>::operator()(xml_h element) const {
1298 cms::DDNamespace ns(_param<cms::DDParsingContext>());
1299 xml_dim_t e(element);
1300 string nam = e.nameStr();
1301 double numSide = ns.attr<int>(e, DD_CMU(numSide));
1302 double startPhi = ns.attr<double>(e, DD_CMU(startPhi));
1303 double deltaPhi = ns.attr<double>(e, DD_CMU(deltaPhi));
1304 vector<double> z, rmin, rmax;
1305
1306 for (xml_coll_t zplane(element, DD_CMU(RZPoint)); zplane; ++zplane) {
1307 rmin.emplace_back(0.0);
1308 rmax.emplace_back(ns.attr<double>(zplane, _U(r)));
1309 z.emplace_back(ns.attr<double>(zplane, _U(z)));
1310 }
1311 for (xml_coll_t zplane(element, DD_CMU(ZSection)); zplane; ++zplane) {
1312 rmin.emplace_back(ns.attr<double>(zplane, DD_CMU(rMin)));
1313 rmax.emplace_back(ns.attr<double>(zplane, DD_CMU(rMax)));
1314 z.emplace_back(ns.attr<double>(zplane, _U(z)));
1315 }
1316
1317 #ifdef EDM_ML_DEBUG
1318
1319 printout(ns.context()->debug_shapes ? ALWAYS : DEBUG,
1320 "DD4CMS",
1321 "+ Polyhedra:startPhi=%8.3f [rad] deltaPhi=%8.3f [rad] %4d sides %4ld z-planes",
1322 startPhi,
1323 deltaPhi,
1324 numSide,
1325 z.size());
1326
1327 #endif
1328
1329 ns.addSolid(nam, Polyhedra(numSide, startPhi, deltaPhi, z, rmin, rmax));
1330 }
1331
1332
1333 template <>
1334 void Converter<DDLSphere>::operator()(xml_h element) const {
1335 cms::DDNamespace ns(_param<cms::DDParsingContext>());
1336 xml_dim_t e(element);
1337 string nam = e.nameStr();
1338 double rinner = ns.attr<double>(e, DD_CMU(innerRadius));
1339 double router = ns.attr<double>(e, DD_CMU(outerRadius));
1340 double startPhi = ns.attr<double>(e, DD_CMU(startPhi));
1341 double deltaPhi = ns.attr<double>(e, DD_CMU(deltaPhi));
1342 double startTheta = ns.attr<double>(e, DD_CMU(startTheta));
1343 double deltaTheta = ns.attr<double>(e, DD_CMU(deltaTheta));
1344
1345 #ifdef EDM_ML_DEBUG
1346
1347 printout(ns.context()->debug_shapes ? ALWAYS : DEBUG,
1348 "DD4CMS",
1349 "+ Sphere: r_inner=%8.3f [cm] r_outer=%8.3f [cm]"
1350 " startPhi=%8.3f [rad] deltaPhi=%8.3f startTheta=%8.3f delteTheta=%8.3f [rad]",
1351 rinner / dd4hep::cm,
1352 router / dd4hep::cm,
1353 startPhi,
1354 deltaPhi,
1355 startTheta,
1356 deltaTheta);
1357
1358 #endif
1359
1360 ns.addSolid(nam, Sphere(rinner, router, startTheta, deltaTheta, startPhi, deltaPhi));
1361 }
1362
1363
1364 template <>
1365 void Converter<DDLTorus>::operator()(xml_h element) const {
1366 cms::DDNamespace ns(_param<cms::DDParsingContext>());
1367 xml_dim_t e(element);
1368 string nam = e.nameStr();
1369 double r = ns.attr<double>(e, DD_CMU(torusRadius));
1370 double rinner = ns.attr<double>(e, DD_CMU(innerRadius));
1371 double router = ns.attr<double>(e, DD_CMU(outerRadius));
1372 double startPhi = ns.attr<double>(e, DD_CMU(startPhi));
1373 double deltaPhi = ns.attr<double>(e, DD_CMU(deltaPhi));
1374
1375 #ifdef EDM_ML_DEBUG
1376
1377 printout(ns.context()->debug_shapes ? ALWAYS : DEBUG,
1378 "DD4CMS",
1379 "+ Torus: r=%10.3f [cm] r_inner=%10.3f [cm] r_outer=%10.3f [cm]"
1380 " startPhi=%10.3f [rad] deltaPhi=%10.3f [rad]",
1381 r / dd4hep::cm,
1382 rinner / dd4hep::cm,
1383 router / dd4hep::cm,
1384 startPhi,
1385 deltaPhi);
1386
1387 #endif
1388
1389 ns.addSolid(nam, Torus(r, rinner, router, startPhi, deltaPhi));
1390 }
1391
1392
1393 template <>
1394 void Converter<DDLPseudoTrap>::operator()(xml_h element) const {
1395 cms::DDNamespace ns(_param<cms::DDParsingContext>());
1396 xml_dim_t e(element);
1397 string nam = e.nameStr();
1398 double dx1 = ns.attr<double>(e, DD_CMU(dx1));
1399 double dy1 = ns.attr<double>(e, DD_CMU(dy1));
1400 double dx2 = ns.attr<double>(e, DD_CMU(dx2));
1401 double dy2 = ns.attr<double>(e, DD_CMU(dy2));
1402 double dz = ns.attr<double>(e, _U(dz));
1403 double r = ns.attr<double>(e, _U(radius));
1404 bool atMinusZ = ns.attr<bool>(e, DD_CMU(atMinusZ));
1405
1406 #ifdef EDM_ML_DEBUG
1407
1408 printout(ns.context()->debug_shapes ? ALWAYS : DEBUG,
1409 "DD4CMS",
1410 "+ Pseudotrap: dz=%8.3f [cm] dx1:%.3f dy1:%.3f dx2=%.3f dy2=%.3f radius:%.3f atMinusZ:%s",
1411 dz / dd4hep::cm,
1412 dx1 / dd4hep::cm,
1413 dy1 / dd4hep::cm,
1414 dx2 / dd4hep::cm,
1415 dy2 / dd4hep::cm,
1416 r / dd4hep::cm,
1417 yes_no(atMinusZ));
1418
1419 #endif
1420
1421 ns.addSolid(nam, PseudoTrap(dx1, dx2, dy1, dy2, dz, r, atMinusZ));
1422 }
1423
1424
1425 template <>
1426 void Converter<DDLTrapezoid>::operator()(xml_h element) const {
1427 cms::DDNamespace ns(_param<cms::DDParsingContext>());
1428 xml_dim_t e(element);
1429 string nam = e.nameStr();
1430 double dz = ns.attr<double>(e, _U(dz));
1431 double alp1 = ns.attr<double>(e, DD_CMU(alp1));
1432 double bl1 = ns.attr<double>(e, DD_CMU(bl1));
1433 double tl1 = ns.attr<double>(e, DD_CMU(tl1));
1434 double h1 = ns.attr<double>(e, DD_CMU(h1));
1435 double alp2 = ns.attr<double>(e, DD_CMU(alp2));
1436 double bl2 = ns.attr<double>(e, DD_CMU(bl2));
1437 double tl2 = ns.attr<double>(e, DD_CMU(tl2));
1438 double h2 = ns.attr<double>(e, DD_CMU(h2));
1439 double phi = ns.attr<double>(e, _U(phi), 0.0);
1440 double theta = ns.attr<double>(e, _U(theta), 0.0);
1441
1442 #ifdef EDM_ML_DEBUG
1443
1444 printout(ns.context()->debug_shapes ? ALWAYS : DEBUG,
1445 "DD4CMS",
1446 "+ Trapezoid: dz=%10.3f [cm] alp1:%.3f bl1=%.3f tl1=%.3f alp2=%.3f bl2=%.3f tl2=%.3f h2=%.3f phi=%.3f "
1447 "theta=%.3f",
1448 dz / dd4hep::cm,
1449 alp1,
1450 bl1 / dd4hep::cm,
1451 tl1 / dd4hep::cm,
1452 h1 / dd4hep::cm,
1453 alp2,
1454 bl2 / dd4hep::cm,
1455 tl2 / dd4hep::cm,
1456 h2 / dd4hep::cm,
1457 phi,
1458 theta);
1459
1460 #endif
1461
1462 ns.addSolid(nam, Trap(dz, theta, phi, h1, bl1, tl1, alp1, h2, bl2, tl2, alp2));
1463 }
1464
1465
1466 template <>
1467 void Converter<DDLTrd1>::operator()(xml_h element) const {
1468 cms::DDNamespace ns(_param<cms::DDParsingContext>());
1469 xml_dim_t e(element);
1470 string nam = e.nameStr();
1471 double dx1 = ns.attr<double>(e, DD_CMU(dx1));
1472 double dy1 = ns.attr<double>(e, DD_CMU(dy1));
1473 double dx2 = ns.attr<double>(e, DD_CMU(dx2), 0.0);
1474 double dy2 = ns.attr<double>(e, DD_CMU(dy2), dy1);
1475 double dz = ns.attr<double>(e, DD_CMU(dz));
1476 if (dy1 == dy2) {
1477 #ifdef EDM_ML_DEBUG
1478
1479 printout(ns.context()->debug_shapes ? ALWAYS : DEBUG,
1480 "DD4CMS",
1481 "+ Trd1: dz=%8.3f [cm] dx1:%.3f dy1:%.3f dx2:%.3f dy2:%.3f",
1482 dz / dd4hep::cm,
1483 dx1 / dd4hep::cm,
1484 dy1 / dd4hep::cm,
1485 dx2 / dd4hep::cm,
1486 dy2 / dd4hep::cm);
1487
1488 #endif
1489
1490 ns.addSolid(nam, Trd1(dx1, dx2, dy1, dz));
1491 } else {
1492 #ifdef EDM_ML_DEBUG
1493
1494 printout(ns.context()->debug_shapes ? ALWAYS : DEBUG,
1495 "DD4CMS",
1496 "+ Trd1(which is actually Trd2): dz=%8.3f [cm] dx1:%.3f dy1:%.3f dx2:%.3f dy2:%.3f",
1497 dz / dd4hep::cm,
1498 dx1 / dd4hep::cm,
1499 dy1 / dd4hep::cm,
1500 dx2 / dd4hep::cm,
1501 dy2 / dd4hep::cm);
1502
1503 #endif
1504
1505 ns.addSolid(nam, Trd2(dx1, dx2, dy1, dy2, dz));
1506 }
1507 }
1508
1509
1510 template <>
1511 void Converter<DDLTrd2>::operator()(xml_h element) const {
1512 cms::DDNamespace ns(_param<cms::DDParsingContext>());
1513 xml_dim_t e(element);
1514 string nam = e.nameStr();
1515 double dx1 = ns.attr<double>(e, DD_CMU(dx1));
1516 double dy1 = ns.attr<double>(e, DD_CMU(dy1));
1517 double dx2 = ns.attr<double>(e, DD_CMU(dx2), 0.0);
1518 double dy2 = ns.attr<double>(e, DD_CMU(dy2), dy1);
1519 double dz = ns.attr<double>(e, DD_CMU(dz));
1520
1521 #ifdef EDM_ML_DEBUG
1522
1523 printout(ns.context()->debug_shapes ? ALWAYS : DEBUG,
1524 "DD4CMS",
1525 "+ Trd1: dz=%8.3f [cm] dx1:%.3f dy1:%.3f dx2:%.3f dy2:%.3f",
1526 dz / dd4hep::cm,
1527 dx1 / dd4hep::cm,
1528 dy1 / dd4hep::cm,
1529 dx2 / dd4hep::cm,
1530 dy2 / dd4hep::cm);
1531
1532 #endif
1533
1534 ns.addSolid(nam, Trd2(dx1, dx2, dy1, dy2, dz));
1535 }
1536
1537
1538 template <>
1539 void Converter<DDLTubs>::operator()(xml_h element) const {
1540 cms::DDNamespace ns(_param<cms::DDParsingContext>());
1541 xml_dim_t e(element);
1542 string nam = e.nameStr();
1543 double dz = ns.attr<double>(e, DD_CMU(dz));
1544 double rmin = ns.attr<double>(e, DD_CMU(rMin));
1545 double rmax = ns.attr<double>(e, DD_CMU(rMax));
1546 double startPhi = ns.attr<double>(e, DD_CMU(startPhi), 0.0);
1547 double deltaPhi = ns.attr<double>(e, DD_CMU(deltaPhi), 2 * M_PI);
1548
1549 #ifdef EDM_ML_DEBUG
1550
1551 printout(ns.context()->debug_shapes ? ALWAYS : DEBUG,
1552 "DD4CMS",
1553 "+ Tubs: dz=%8.3f [cm] rmin=%8.3f [cm] rmax=%8.3f [cm]"
1554 " startPhi=%8.3f [rad] deltaPhi=%8.3f [rad]",
1555 dz / dd4hep::cm,
1556 rmin / dd4hep::cm,
1557 rmax / dd4hep::cm,
1558 startPhi,
1559 deltaPhi);
1560
1561 #endif
1562
1563 ns.addSolid(nam, Tube(rmin, rmax, dz, startPhi, startPhi + deltaPhi));
1564 }
1565
1566
1567 template <>
1568 void Converter<DDLCutTubs>::operator()(xml_h element) const {
1569 cms::DDNamespace ns(_param<cms::DDParsingContext>());
1570 xml_dim_t e(element);
1571 string nam = e.nameStr();
1572 double dz = ns.attr<double>(e, DD_CMU(dz));
1573 double rmin = ns.attr<double>(e, DD_CMU(rMin));
1574 double rmax = ns.attr<double>(e, DD_CMU(rMax));
1575 double startPhi = ns.attr<double>(e, DD_CMU(startPhi));
1576 double deltaPhi = ns.attr<double>(e, DD_CMU(deltaPhi));
1577 double lx = ns.attr<double>(e, DD_CMU(lx));
1578 double ly = ns.attr<double>(e, DD_CMU(ly));
1579 double lz = ns.attr<double>(e, DD_CMU(lz));
1580 double tx = ns.attr<double>(e, DD_CMU(tx));
1581 double ty = ns.attr<double>(e, DD_CMU(ty));
1582 double tz = ns.attr<double>(e, DD_CMU(tz));
1583
1584 #ifdef EDM_ML_DEBUG
1585
1586 printout(ns.context()->debug_shapes ? ALWAYS : DEBUG,
1587 "DD4CMS",
1588 "+ CutTube: dz=%8.3f [cm] rmin=%8.3f [cm] rmax=%8.3f [cm]"
1589 " startPhi=%8.3f [rad] deltaPhi=%8.3f [rad]...",
1590 dz / dd4hep::cm,
1591 rmin / dd4hep::cm,
1592 rmax / dd4hep::cm,
1593 startPhi,
1594 deltaPhi);
1595
1596 #endif
1597
1598 ns.addSolid(nam, CutTube(rmin, rmax, dz, startPhi, startPhi + deltaPhi, lx, ly, lz, tx, ty, tz));
1599 }
1600
1601
1602 template <>
1603 void Converter<DDLTruncTubs>::operator()(xml_h element) const {
1604 cms::DDNamespace ns(_param<cms::DDParsingContext>());
1605 xml_dim_t e(element);
1606 string nam = e.nameStr();
1607 double zhalf = ns.attr<double>(e, DD_CMU(zHalf));
1608 double rmin = ns.attr<double>(e, DD_CMU(rMin));
1609 double rmax = ns.attr<double>(e, DD_CMU(rMax));
1610 double startPhi = ns.attr<double>(e, DD_CMU(startPhi));
1611 double deltaPhi = ns.attr<double>(e, DD_CMU(deltaPhi));
1612 double cutAtStart = ns.attr<double>(e, DD_CMU(cutAtStart));
1613 double cutAtDelta = ns.attr<double>(e, DD_CMU(cutAtDelta));
1614 bool cutInside = ns.attr<bool>(e, DD_CMU(cutInside));
1615
1616 #ifdef EDM_ML_DEBUG
1617
1618 printout(ns.context()->debug_shapes ? ALWAYS : DEBUG,
1619 "DD4CMS",
1620 "+ TruncTube:zHalf=%8.3f [cm] rmin=%8.3f [cm] rmax=%8.3f [cm]"
1621 " startPhi=%8.3f [rad] deltaPhi=%8.3f [rad] atStart=%8.3f [cm] atDelta=%8.3f [cm] inside:%s",
1622 zhalf / dd4hep::cm,
1623 rmin / dd4hep::cm,
1624 rmax / dd4hep::cm,
1625 startPhi,
1626 deltaPhi,
1627 cutAtStart / dd4hep::cm,
1628 cutAtDelta / dd4hep::cm,
1629 yes_no(cutInside));
1630
1631 #endif
1632
1633 ns.addSolid(nam, TruncatedTube(zhalf, rmin, rmax, startPhi, deltaPhi, cutAtStart, cutAtDelta, cutInside));
1634 }
1635
1636
1637 template <>
1638 void Converter<DDLEllipticalTube>::operator()(xml_h element) const {
1639 cms::DDNamespace ns(_param<cms::DDParsingContext>());
1640 xml_dim_t e(element);
1641 string nam = e.nameStr();
1642 double dx = ns.attr<double>(e, DD_CMU(xSemiAxis));
1643 double dy = ns.attr<double>(e, DD_CMU(ySemiAxis));
1644 double dz = ns.attr<double>(e, DD_CMU(zHeight));
1645
1646 #ifdef EDM_ML_DEBUG
1647
1648 printout(ns.context()->debug_shapes ? ALWAYS : DEBUG,
1649 "DD4CMS",
1650 "+ EllipticalTube xSemiAxis=%8.3f [cm] ySemiAxis=%8.3f [cm] zHeight=%8.3f [cm]",
1651 dx / dd4hep::cm,
1652 dy / dd4hep::cm,
1653 dz / dd4hep::cm);
1654
1655 #endif
1656
1657 ns.addSolid(nam, EllipticalTube(dx, dy, dz));
1658 }
1659
1660
1661 template <>
1662 void Converter<DDLCone>::operator()(xml_h element) const {
1663 cms::DDNamespace ns(_param<cms::DDParsingContext>());
1664 xml_dim_t e(element);
1665 string nam = e.nameStr();
1666 double dz = ns.attr<double>(e, DD_CMU(dz));
1667 double rmin1 = ns.attr<double>(e, DD_CMU(rMin1));
1668 double rmin2 = ns.attr<double>(e, DD_CMU(rMin2));
1669 double rmax1 = ns.attr<double>(e, DD_CMU(rMax1));
1670 double rmax2 = ns.attr<double>(e, DD_CMU(rMax2));
1671 double startPhi = ns.attr<double>(e, DD_CMU(startPhi));
1672 double deltaPhi = ns.attr<double>(e, DD_CMU(deltaPhi));
1673 double phi2 = startPhi + deltaPhi;
1674
1675 #ifdef EDM_ML_DEBUG
1676
1677 printout(ns.context()->debug_shapes ? ALWAYS : DEBUG,
1678 "DD4CMS",
1679 "+ Cone: dz=%8.3f [cm]"
1680 " rmin1=%8.3f [cm] rmax1=%8.3f [cm]"
1681 " rmin2=%8.3f [cm] rmax2=%8.3f [cm]"
1682 " startPhi=%8.3f [rad] deltaPhi=%8.3f [rad]",
1683 dz / dd4hep::cm,
1684 rmin1 / dd4hep::cm,
1685 rmax1 / dd4hep::cm,
1686 rmin2 / dd4hep::cm,
1687 rmax2 / dd4hep::cm,
1688 startPhi,
1689 deltaPhi);
1690
1691 #endif
1692
1693 ns.addSolid(nam, ConeSegment(dz, rmin1, rmax1, rmin2, rmax2, startPhi, phi2));
1694 }
1695
1696
1697 template <>
1698 void Converter<DDLShapeless>::operator()(xml_h element) const {
1699 cms::DDNamespace ns(_param<cms::DDParsingContext>());
1700 xml_dim_t e(element);
1701 string nam = e.nameStr();
1702
1703 #ifdef EDM_ML_DEBUG
1704
1705 printout(ns.context()->debug_shapes ? ALWAYS : DEBUG,
1706 "DD4CMS",
1707 "+ Shapeless: THIS ONE CAN ONLY BE USED AT THE VOLUME LEVEL -> Shapeless: %s",
1708 nam.c_str());
1709
1710 #endif
1711
1712 ns.addSolid(nam, Box(1, 1, 1));
1713 }
1714
1715
1716 template <>
1717 void Converter<DDLAssembly>::operator()(xml_h element) const {
1718 cms::DDNamespace ns(_param<cms::DDParsingContext>());
1719 xml_dim_t e(element);
1720 string nam = e.nameStr();
1721
1722 #ifdef EDM_ML_DEBUG
1723 printout(
1724 ns.context()->debug_shapes ? ALWAYS : DEBUG, "DD4CMS", "+ Assembly: Adding solid -> Assembly: %s", nam.c_str());
1725 #endif
1726
1727 ns.addAssemblySolid(nam);
1728 }
1729
1730
1731 template <>
1732 void Converter<DDLBox>::operator()(xml_h element) const {
1733 cms::DDNamespace ns(_param<cms::DDParsingContext>());
1734 xml_dim_t e(element);
1735 string nam = e.nameStr();
1736 double dx = ns.attr<double>(e, DD_CMU(dx));
1737 double dy = ns.attr<double>(e, DD_CMU(dy));
1738 double dz = ns.attr<double>(e, DD_CMU(dz));
1739
1740 #ifdef EDM_ML_DEBUG
1741
1742 printout(ns.context()->debug_shapes ? ALWAYS : DEBUG,
1743 "DD4CMS",
1744 "+ Box: dx=%10.3f [cm] dy=%10.3f [cm] dz=%10.3f [cm]",
1745 dx / dd4hep::cm,
1746 dy / dd4hep::cm,
1747 dz / dd4hep::cm);
1748
1749 #endif
1750
1751 ns.addSolid(nam, Box(dx, dy, dz));
1752 }
1753
1754
1755 template <>
1756 void Converter<include_load>::operator()(xml_h element) const {
1757 string fname = element.attr<string>(_U(ref));
1758 edm::FileInPath fp(fname);
1759 xml::Document doc;
1760 doc = xml::DocumentHandler().load(fp.fullPath());
1761
1762 #ifdef EDM_ML_DEBUG
1763
1764 printout(_param<cms::DDParsingContext>()->debug_includes ? ALWAYS : DEBUG,
1765 "DD4CMS",
1766 "+++ Processing the CMS detector description %s",
1767 fname.c_str());
1768
1769 #endif
1770
1771 _option<DDRegistry>()->includes.emplace_back(doc);
1772 }
1773
1774
1775 template <>
1776 void Converter<include_unload>::operator()(xml_h element) const {
1777 string fname = xml::DocumentHandler::system_path(element);
1778 xml::DocumentHolder(xml_elt_t(element).document()).assign(nullptr);
1779
1780 #ifdef EDM_ML_DEBUG
1781
1782 printout(_param<cms::DDParsingContext>()->debug_includes ? ALWAYS : DEBUG,
1783 "DD4CMS",
1784 "+++ Finished processing %s",
1785 fname.c_str());
1786 #endif
1787 }
1788
1789
1790 template <>
1791 void Converter<include_constants>::operator()(xml_h element) const {
1792 xml_coll_t(element, DD_CMU(ConstantsSection)).for_each(Converter<ConstantsSection>(description, param, optional));
1793 }
1794
1795 namespace {
1796
1797
1798
1799
1800
1801
1802
1803 enum class DDAxes { x = 1, y = 2, z = 3, rho = 1, phi = 2, undefined };
1804 const std::map<std::string, DDAxes> axesmap{{"x", DDAxes::x},
1805 {"y", DDAxes::y},
1806 {"z", DDAxes::z},
1807 {"rho", DDAxes::rho},
1808 {"phi", DDAxes::phi},
1809 {"undefined", DDAxes::undefined}};
1810 }
1811
1812
1813 template <>
1814 void Converter<DDLDivision>::operator()(xml_h element) const {
1815 cms::DDNamespace ns(_param<cms::DDParsingContext>(), element);
1816 xml_dim_t e(element);
1817 string childName = e.nameStr();
1818 if (strchr(childName.c_str(), NAMESPACE_SEP) == nullptr)
1819 childName = ns.prepend(childName);
1820
1821 string parentName = ns.attr<string>(e, DD_CMU(parent));
1822 if (strchr(parentName.c_str(), NAMESPACE_SEP) == nullptr)
1823 parentName = ns.prepend(parentName);
1824 string axis = ns.attr<string>(e, DD_CMU(axis));
1825
1826
1827
1828 double offset = e.hasAttr(DD_CMU(offset)) ? ns.attr<double>(e, DD_CMU(offset)) : 0e0;
1829 double width = e.hasAttr(DD_CMU(width)) ? ns.attr<double>(e, DD_CMU(width)) : 0e0;
1830 int nReplicas = e.hasAttr(DD_CMU(nReplicas)) ? ns.attr<int>(e, DD_CMU(nReplicas)) : 0;
1831
1832 #ifdef EDM_ML_DEBUG
1833
1834 printout(ns.context()->debug_placements ? ALWAYS : DEBUG,
1835 "DD4CMS",
1836 "+++ Start executing Division of %s along %s (%d) with offset %6.3f and %6.3f to produce %s....",
1837 parentName.c_str(),
1838 axis.c_str(),
1839 axesmap.at(axis),
1840 offset,
1841 width,
1842 childName.c_str());
1843
1844 #endif
1845
1846 Volume parent = ns.volume(parentName);
1847
1848 const TGeoShape* shape = parent.solid();
1849 TClass* cl = shape->IsA();
1850 if (cl == TGeoTubeSeg::Class()) {
1851 const TGeoTubeSeg* sh = (const TGeoTubeSeg*)shape;
1852 double widthInDeg = convertRadToDeg(width);
1853 double startInDeg = convertRadToDeg(offset);
1854 int numCopies = (int)((sh->GetPhi2() - sh->GetPhi1()) / widthInDeg);
1855
1856 #ifdef EDM_ML_DEBUG
1857
1858 printout(ns.context()->debug_placements ? ALWAYS : DEBUG,
1859 "DD4CMS",
1860 "+++ ...divide %s along %s (%d) with offset %6.3f deg and %6.3f deg to produce %d copies",
1861 parent.solid().type(),
1862 axis.c_str(),
1863 axesmap.at(axis),
1864 startInDeg,
1865 widthInDeg,
1866 numCopies);
1867
1868 #endif
1869
1870 Volume child = parent.divide(childName, static_cast<int>(axesmap.at(axis)), numCopies, startInDeg, widthInDeg);
1871
1872 ns.context()->volumes[childName] = child;
1873
1874 #ifdef EDM_ML_DEBUG
1875
1876 printout(ns.context()->debug_placements ? ALWAYS : DEBUG,
1877 "DD4CMS",
1878 "+++ %s Parent: %-24s [%s] Child: %-32s [%s] is multivolume [%s]",
1879 e.tag().c_str(),
1880 parentName.c_str(),
1881 parent.isValid() ? "VALID" : "INVALID",
1882 child.name(),
1883 child.isValid() ? "VALID" : "INVALID",
1884 child->IsVolumeMulti() ? "YES" : "NO");
1885 #endif
1886
1887 } else if (cl == TGeoTrd1::Class()) {
1888 double dy = static_cast<const TGeoTrd1*>(shape)->GetDy();
1889
1890 #ifdef EDM_ML_DEBUG
1891
1892 printout(ns.context()->debug_placements ? ALWAYS : DEBUG,
1893 "DD4CMS",
1894 "+++ ...divide %s along %s (%d) with offset %6.3f cm and %6.3f cm to produce %d copies in %6.3f",
1895 parent.solid().type(),
1896 axis.c_str(),
1897 axesmap.at(axis),
1898 -dy + offset + width,
1899 width,
1900 nReplicas,
1901 dy);
1902
1903 #endif
1904
1905 Volume child = parent.divide(childName, static_cast<int>(axesmap.at(axis)), nReplicas, -dy + offset + width, width);
1906
1907 ns.context()->volumes[childName] = child;
1908
1909 #ifdef EDM_ML_DEBUG
1910
1911 printout(ns.context()->debug_placements ? ALWAYS : DEBUG,
1912 "DD4CMS",
1913 "+++ %s Parent: %-24s [%s] Child: %-32s [%s] is multivolume [%s]",
1914 e.tag().c_str(),
1915 parentName.c_str(),
1916 parent.isValid() ? "VALID" : "INVALID",
1917 child.name(),
1918 child.isValid() ? "VALID" : "INVALID",
1919 child->IsVolumeMulti() ? "YES" : "NO");
1920
1921 #endif
1922 } else {
1923 printout(ERROR, "DD4CMS", "++ FAILED Division of a %s is not implemented yet!", parent.solid().type());
1924 }
1925 }
1926
1927
1928 template <>
1929 void Converter<DDLAlgorithm>::operator()(xml_h element) const {
1930 cms::DDNamespace ns(_param<cms::DDParsingContext>());
1931 xml_dim_t e(element);
1932 string name = e.nameStr();
1933 size_t idx;
1934 string type = "DDCMS_" + ns.realName(name);
1935 while ((idx = type.find(NAMESPACE_SEP)) != string::npos)
1936 type[idx] = '_';
1937
1938 #ifdef EDM_ML_DEBUG
1939
1940 printout(
1941 ns.context()->debug_algorithms ? ALWAYS : DEBUG, "DD4CMS", "+++ Start executing algorithm %s....", type.c_str());
1942
1943 #endif
1944
1945 long ret = PluginService::Create<long>(type, &description, ns.context(), &element);
1946 if (ret == s_executed) {
1947 #ifdef EDM_ML_DEBUG
1948
1949 printout(ns.context()->debug_algorithms ? ALWAYS : DEBUG,
1950
1951 "DD4CMS",
1952 "+++ Executed algorithm: %08lX = %s",
1953 ret,
1954 name.c_str());
1955
1956 #endif
1957 return;
1958 }
1959 printout(ERROR, "DD4CMS", "++ FAILED NOT ADDING SUBDETECTOR %08lX = %s", ret, name.c_str());
1960 }
1961
1962 template <class InputIt, class ForwardIt, class BinOp>
1963 void for_each_token(InputIt first, InputIt last, ForwardIt s_first, ForwardIt s_last, BinOp binary_op) {
1964 while (first != last) {
1965 const auto pos = std::find_first_of(first, last, s_first, s_last);
1966 binary_op(first, pos);
1967 if (pos == last)
1968 break;
1969 first = std::next(pos);
1970 }
1971 }
1972
1973 namespace {
1974
1975 std::vector<string> splitString(const string& str, const string& delims = ",") {
1976 std::vector<string> output;
1977
1978 for_each_token(cbegin(str), cend(str), cbegin(delims), cend(delims), [&output](auto first, auto second) {
1979 if (first != second) {
1980 if (string(first, second).front() == '[' && string(first, second).back() == ']') {
1981 first++;
1982 second--;
1983 }
1984 output.emplace_back(string(first, second));
1985 }
1986 });
1987 return output;
1988 }
1989
1990 std::vector<double> splitNumeric(const string& str, const string& delims = ",") {
1991 std::vector<double> output;
1992
1993 for_each_token(cbegin(str), cend(str), cbegin(delims), cend(delims), [&output](auto first, auto second) {
1994 if (first != second) {
1995 if (string(first, second).front() == '[' && string(first, second).back() == ']') {
1996 first++;
1997 second--;
1998 }
1999 output.emplace_back(dd4hep::_toDouble(string(first, second)));
2000 }
2001 });
2002 return output;
2003 }
2004 }
2005
2006
2007
2008 template <>
2009 void Converter<DDLVector>::operator()(xml_h element) const {
2010 cms::DDNamespace ns(_param<cms::DDParsingContext>());
2011 cms::DDParsingContext* const context = ns.context();
2012 DDVectorsMap* registry = context->description.extension<DDVectorsMap>();
2013 xml_dim_t e(element);
2014 string name = ns.prepend(e.nameStr());
2015 string type = ns.attr<string>(e, _U(type));
2016 string nEntries = ns.attr<string>(e, DD_CMU(nEntries));
2017 string val = e.text();
2018 val.erase(remove_if(val.begin(), val.end(), [](unsigned char x) { return isspace(x); }), val.end());
2019
2020 #ifdef EDM_ML_DEBUG
2021
2022 printout(ns.context()->debug_constants ? ALWAYS : DEBUG,
2023 "DD4CMS",
2024 "+++ Vector<%s>: %s[%s]: %s",
2025 type.c_str(),
2026 name.c_str(),
2027 nEntries.c_str(),
2028 val.c_str());
2029
2030 #endif
2031
2032 try {
2033 std::vector<double> results = splitNumeric(val);
2034 registry->insert(
2035 {name,
2036 results});
2037 } catch (const exception& e) {
2038 #ifdef EDM_ML_DEBUG
2039
2040 printout(INFO,
2041 "DD4CMS",
2042 "++ Unresolved Vector<%s>: %s[%s]: %s. Try to resolve later. [%s]",
2043 type.c_str(),
2044 name.c_str(),
2045 nEntries.c_str(),
2046 val.c_str(),
2047 e.what());
2048
2049 #endif
2050
2051 std::vector<string> results = splitString(val);
2052 context->unresolvedVectors.insert({name, results});
2053 }
2054 }
2055
2056 template <>
2057 void Converter<debug>::operator()(xml_h dbg) const {
2058 cms::DDNamespace ns(_param<cms::DDParsingContext>());
2059 if (dbg.hasChild(DD_CMU(debug_constants)))
2060 ns.setContext()->debug_constants = true;
2061 if (dbg.hasChild(DD_CMU(debug_materials)))
2062 ns.setContext()->debug_materials = true;
2063 if (dbg.hasChild(DD_CMU(debug_rotations)))
2064 ns.setContext()->debug_rotations = true;
2065 if (dbg.hasChild(DD_CMU(debug_shapes)))
2066 ns.setContext()->debug_shapes = true;
2067 if (dbg.hasChild(DD_CMU(debug_volumes)))
2068 ns.setContext()->debug_volumes = true;
2069 if (dbg.hasChild(DD_CMU(debug_placements)))
2070 ns.setContext()->debug_placements = true;
2071 if (dbg.hasChild(DD_CMU(debug_namespaces)))
2072 ns.setContext()->debug_namespaces = true;
2073 if (dbg.hasChild(DD_CMU(debug_includes)))
2074 ns.setContext()->debug_includes = true;
2075 if (dbg.hasChild(DD_CMU(debug_algorithms)))
2076 ns.setContext()->debug_algorithms = true;
2077 if (dbg.hasChild(DD_CMU(debug_specpars)))
2078 ns.setContext()->debug_specpars = true;
2079 }
2080
2081 template <>
2082 void Converter<DDRegistry>::operator()(xml_h ) const {
2083 cms::DDParsingContext* context = _param<cms::DDParsingContext>();
2084 DDRegistry* res = _option<DDRegistry>();
2085 cms::DDNamespace ns(context);
2086 int count = 0;
2087
2088 #ifdef EDM_ML_DEBUG
2089
2090 printout(context->debug_constants ? ALWAYS : DEBUG,
2091 "DD4CMS",
2092 "+++ RESOLVING %ld unknown constants..... (out of %ld)",
2093 res->unresolvedConst.size(),
2094 res->originalConst.size());
2095 #endif
2096
2097 while (!res->unresolvedConst.empty()) {
2098 for (auto& i : res->unresolvedConst) {
2099 const string& n = i.first;
2100 string rep;
2101 string& v = i.second;
2102 size_t idx, idq;
2103 for (idx = v.find('[', 0); idx != string::npos; idx = v.find('[', idx + 1)) {
2104 idq = v.find(']', idx + 1);
2105 rep = v.substr(idx + 1, idq - idx - 1);
2106 auto r = res->originalConst.find(rep);
2107 if (r != res->originalConst.end()) {
2108 rep = "(" + (*r).second + ")";
2109 v.replace(idx, idq - idx + 1, rep);
2110 }
2111 }
2112 if (v.find(']') == string::npos) {
2113 if (v.find("-+") != string::npos || v.find("+-") != string::npos) {
2114 while ((idx = v.find("-+")) != string::npos)
2115 v.replace(idx, 2, "-");
2116 while ((idx = v.find("+-")) != string::npos)
2117 v.replace(idx, 2, "-");
2118 }
2119
2120 #ifdef EDM_ML_DEBUG
2121
2122 printout(context->debug_constants ? ALWAYS : DEBUG,
2123 "DD4CMS",
2124 "+++ [%06ld] ---------- %-40s = %s",
2125 res->unresolvedConst.size() - 1,
2126 n.c_str(),
2127 res->originalConst[n].c_str());
2128
2129 #endif
2130
2131 ns.addConstantNS(n, v, "number");
2132 res->unresolvedConst.erase(n);
2133 break;
2134 }
2135 }
2136 if (++count > 10000)
2137 break;
2138 }
2139 if (!res->unresolvedConst.empty()) {
2140 for (const auto& e : res->unresolvedConst)
2141 printout(ERROR, "DD4CMS", "+++ Unresolved constant: %-40s = %s.", e.first.c_str(), e.second.c_str());
2142 except("DD4CMS", "++ FAILED to resolve %ld constant entries:", res->unresolvedConst.size());
2143 }
2144 res->unresolvedConst.clear();
2145 res->originalConst.clear();
2146 }
2147
2148 template <>
2149 void Converter<print_xml_doc>::operator()(xml_h element) const {
2150 string fname = xml::DocumentHandler::system_path(element);
2151
2152 #ifdef EDM_ML_DEBUG
2153
2154 printout(_param<cms::DDParsingContext>()->debug_includes ? ALWAYS : DEBUG,
2155 "DD4CMS",
2156 "+++ Processing data from: %s",
2157 fname.c_str());
2158
2159 #endif
2160 }
2161
2162
2163 static long load_dddefinition(Detector& det, xml_h element) {
2164 xml_elt_t dddef(element);
2165 if (dddef) {
2166 cms::DDParsingContext& context = *det.extension<DDParsingContext>();
2167 cms::DDNamespace ns(context);
2168 ns.addConstantNS("world_x", "101*m", "number");
2169 ns.addConstantNS("world_y", "101*m", "number");
2170 ns.addConstantNS("world_z", "450*m", "number");
2171 ns.addConstantNS("Air", "materials:Air", "string");
2172 ns.addConstantNS("Vacuum", "materials:Vacuum", "string");
2173
2174 string fname = xml::DocumentHandler::system_path(element);
2175 bool open_geometry = dddef.hasChild(DD_CMU(open_geometry)) ? dddef.child(DD_CMU(open_geometry)) : true;
2176 bool close_geometry = dddef.hasChild(DD_CMU(close_geometry)) ? dddef.hasChild(DD_CMU(close_geometry)) : true;
2177
2178 xml_coll_t(dddef, _U(debug)).for_each(Converter<debug>(det, &context));
2179
2180
2181
2182
2183 printout(INFO, "DD4CMS", "+++ Processing the CMS detector description %s", fname.c_str());
2184
2185 xml::Document doc;
2186 Converter<print_xml_doc> print_doc(det, &context);
2187 try {
2188 DDRegistry res;
2189 res.unresolvedConst.reserve(2000);
2190 res.originalConst.reserve(6000);
2191 print_doc((doc = dddef.document()).root());
2192 xml_coll_t(dddef, DD_CMU(ConstantsSection)).for_each(Converter<ConstantsSection>(det, &context, &res));
2193 xml_coll_t(dddef, DD_CMU(RotationSection)).for_each(Converter<RotationSection>(det, &context));
2194 xml_coll_t(dddef, DD_CMU(MaterialSection)).for_each(Converter<MaterialSection>(det, &context));
2195
2196 xml_coll_t(dddef, DD_CMU(IncludeSection)).for_each(DD_CMU(Include), Converter<include_load>(det, &context, &res));
2197
2198 for (xml::Document d : res.includes) {
2199 print_doc((doc = d).root());
2200 Converter<include_constants>(det, &context, &res)((doc = d).root());
2201 }
2202
2203 Converter<DDRegistry>(det, &context, &res)(dddef);
2204 {
2205 DDVectorsMap* registry = context.description.extension<DDVectorsMap>();
2206
2207 printout(context.debug_constants ? ALWAYS : DEBUG,
2208 "DD4CMS",
2209 "+++ RESOLVING %ld Vectors.....",
2210 context.unresolvedVectors.size());
2211
2212 while (!context.unresolvedVectors.empty()) {
2213 for (auto it = context.unresolvedVectors.begin(); it != context.unresolvedVectors.end();) {
2214 std::vector<double> result;
2215 for (const auto& i : it->second) {
2216 result.emplace_back(dd4hep::_toDouble(i));
2217 }
2218 registry->insert({it->first, result});
2219
2220 it = context.unresolvedVectors.erase(it);
2221 }
2222 }
2223 }
2224
2225 for (xml::Document d : res.includes) {
2226 print_doc((doc = d).root());
2227 xml_coll_t(d.root(), DD_CMU(MaterialSection)).for_each(Converter<MaterialSection>(det, &context));
2228 }
2229 if (open_geometry) {
2230 det.init();
2231 ns.addVolume(det.worldVolume());
2232 }
2233 for (xml::Document d : res.includes) {
2234 print_doc((doc = d).root());
2235 xml_coll_t(d.root(), DD_CMU(RotationSection)).for_each(Converter<RotationSection>(det, &context));
2236 }
2237 for (xml::Document d : res.includes) {
2238 print_doc((doc = d).root());
2239 xml_coll_t(d.root(), DD_CMU(SolidSection)).for_each(Converter<SolidSection>(det, &context));
2240 }
2241 for (xml::Document d : res.includes) {
2242 print_doc((doc = d).root());
2243 xml_coll_t(d.root(), DD_CMU(LogicalPartSection)).for_each(Converter<LogicalPartSection>(det, &context));
2244 }
2245 for (xml::Document d : res.includes) {
2246 print_doc((doc = d).root());
2247 xml_coll_t(d.root(), DD_CMU(Algorithm)).for_each(Converter<DDLAlgorithm>(det, &context));
2248 }
2249 for (xml::Document d : res.includes) {
2250 print_doc((doc = d).root());
2251 xml_coll_t(d.root(), DD_CMU(PosPartSection)).for_each(Converter<PosPartSection>(det, &context));
2252 }
2253 for (xml::Document d : res.includes) {
2254 print_doc((doc = d).root());
2255 xml_coll_t(d.root(), DD_CMU(SpecParSection)).for_each(Converter<SpecParSection>(det, &context));
2256 }
2257
2258
2259 for (xml::Document d : res.includes)
2260 Converter<include_unload>(det, &context, &res)(d.root());
2261
2262 print_doc((doc = dddef.document()).root());
2263
2264 xml_coll_t(dddef, DD_CMU(SolidSection)).for_each(Converter<SolidSection>(det, &context));
2265 {
2266
2267
2268
2269
2270
2271 while (!context.unresolvedShapes.empty()) {
2272 for (auto it = context.unresolvedShapes.begin(); it != context.unresolvedShapes.end();) {
2273 auto const& name = it->first;
2274 auto const& aname = std::visit([](auto&& arg) -> std::string { return arg.firstSolidName; }, it->second);
2275 auto const& bname = std::visit([](auto&& arg) -> std::string { return arg.secondSolidName; }, it->second);
2276
2277 auto const& ait = context.shapes.find(aname);
2278 if (ait->second.isValid()) {
2279 auto const& bit = context.shapes.find(bname);
2280 if (bit->second.isValid()) {
2281 dd4hep::Solid shape =
2282 std::visit([&ait, &bit](auto&& arg) -> dd4hep::Solid { return arg.make(ait->second, bit->second); },
2283 it->second);
2284 context.shapes[name] = shape;
2285 it = context.unresolvedShapes.erase(it);
2286 } else
2287 ++it;
2288 } else
2289 ++it;
2290 }
2291 }
2292 }
2293 xml_coll_t(dddef, DD_CMU(LogicalPartSection)).for_each(Converter<LogicalPartSection>(det, &context));
2294 xml_coll_t(dddef, DD_CMU(Algorithm)).for_each(Converter<DDLAlgorithm>(det, &context));
2295 xml_coll_t(dddef, DD_CMU(PosPartSection)).for_each(Converter<PosPartSection>(det, &context));
2296 xml_coll_t(dddef, DD_CMU(SpecParSection)).for_each(Converter<SpecParSection>(det, &context));
2297 } catch (const exception& e) {
2298 printout(ERROR, "DD4CMS", "Exception while processing xml source:%s", doc.uri().c_str());
2299 printout(ERROR, "DD4CMS", "----> %s", e.what());
2300 throw;
2301 }
2302
2303
2304 if (close_geometry) {
2305 Volume wv = det.worldVolume();
2306 Volume geomv = ns.volume("cms:OCMS", false);
2307 if (geomv.isValid())
2308 wv.placeVolume(geomv, 1);
2309 Volume mfv = ns.volume("cmsMagneticField:MAGF", false);
2310 if (mfv.isValid())
2311 wv.placeVolume(mfv, 1);
2312 Volume mfv1 = ns.volume("MagneticFieldVolumes:MAGF", false);
2313 if (mfv1.isValid())
2314 wv.placeVolume(mfv1, 1);
2315
2316
2317 det.manager().CloseGeometry();
2318
2319 det.endDocument();
2320 }
2321 printout(INFO, "DDDefinition", "+++ Finished processing %s", fname.c_str());
2322 return 1;
2323 }
2324 except("DDDefinition", "+++ FAILED to process unknown DOM tree [Invalid Handle]");
2325 return 0;
2326 }
2327
2328
2329 DECLARE_XML_DOC_READER(DDDefinition, load_dddefinition)