File indexing completed on 2024-09-27 04:54:48
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 double density = xmat.attr<double>(DD_CMU(density)) / (dd4hep::g / dd4hep::cm3);
0594 xml_coll_t composites(xmat, DD_CMU(MaterialFraction));
0595 TGeoMixture* mix = new TGeoMixture(nam.c_str(), composites.size(), density);
0596
0597 #ifdef EDM_ML_DEBUG
0598
0599 printout(ns.context()->debug_materials ? ALWAYS : DEBUG,
0600 "DD4CMS",
0601 "++ Converting material %-48s Density: %8.3f [g/cm3] ROOT: %8.3f [g/cm3]",
0602 ('"' + nam + '"').c_str(),
0603 density,
0604 mix->GetDensity());
0605
0606 #endif
0607
0608 if (ns.context()->makePayload) {
0609 ns.context()->compMaterialsVec.emplace_back(std::make_pair(nam, density));
0610 }
0611 for (composites.reset(); composites; ++composites) {
0612 xml_dim_t xfrac(composites);
0613 xml_dim_t xfrac_mat(xfrac.child(DD_CMU(rMaterial)));
0614 double fraction = xfrac.fraction();
0615 string fracname = ns.realName(xfrac_mat.nameStr());
0616
0617 if (ns.context()->makePayload) {
0618 ns.context()->compMaterialsRefs[nam].emplace_back(
0619 cms::DDParsingContext::CompositeMaterial(ns.prepend(fracname), fraction));
0620 }
0621 TGeoMaterial* frac_mat = mgr.GetMaterial(fracname.c_str());
0622 if (frac_mat == nullptr)
0623 frac_mat = mgr.GetMaterial(ns.prepend(fracname).c_str());
0624 if (frac_mat) {
0625 mix->AddElement(frac_mat, fraction);
0626 continue;
0627 }
0628
0629 throw cms::Exception("DD4CMS") << "Composite material \"" + fracname + "\" or \"" + ns.prepend(fracname) +
0630 "\" not yet defined.";
0631 }
0632 mix->SetTemperature(ns.context()->description.stdConditions().temperature);
0633 mix->SetPressure(ns.context()->description.stdConditions().pressure);
0634 mix->SetRadLen(0e0);
0635
0636 TGeoMedium* medium = mgr.GetMedium(nam.c_str());
0637 if (nullptr == medium) {
0638 --unique_mat_id;
0639 medium = new TGeoMedium(nam.c_str(), unique_mat_id, mix);
0640 medium->SetTitle("material");
0641 medium->SetUniqueID(unique_mat_id);
0642 }
0643 }
0644 }
0645
0646
0647 template <>
0648 void Converter<DDLRotation>::operator()(xml_h element) const {
0649 cms::DDParsingContext* context = _param<cms::DDParsingContext>();
0650 cms::DDNamespace ns(context);
0651 xml_dim_t xrot(element);
0652 string nam = xrot.nameStr();
0653 double thetaX = xrot.hasAttr(DD_CMU(thetaX)) ? ns.attr<double>(xrot, DD_CMU(thetaX)) : 0e0;
0654 double phiX = xrot.hasAttr(DD_CMU(phiX)) ? ns.attr<double>(xrot, DD_CMU(phiX)) : 0e0;
0655 double thetaY = xrot.hasAttr(DD_CMU(thetaY)) ? ns.attr<double>(xrot, DD_CMU(thetaY)) : 0e0;
0656 double phiY = xrot.hasAttr(DD_CMU(phiY)) ? ns.attr<double>(xrot, DD_CMU(phiY)) : 0e0;
0657 double thetaZ = xrot.hasAttr(DD_CMU(thetaZ)) ? ns.attr<double>(xrot, DD_CMU(thetaZ)) : 0e0;
0658 double phiZ = xrot.hasAttr(DD_CMU(phiZ)) ? ns.attr<double>(xrot, DD_CMU(phiZ)) : 0e0;
0659 Rotation3D rot = makeRotation3D(thetaX, phiX, thetaY, phiY, thetaZ, phiZ);
0660
0661 #ifdef EDM_ML_DEBUG
0662
0663 printout(context->debug_rotations ? ALWAYS : DEBUG,
0664 "DD4CMS",
0665 "+++ Adding rotation: %-32s: (theta/phi)[rad] X: %6.3f %6.3f Y: %6.3f %6.3f Z: %6.3f %6.3f",
0666 ns.prepend(nam).c_str(),
0667 thetaX,
0668 phiX,
0669 thetaY,
0670 phiY,
0671 thetaZ,
0672 phiZ);
0673
0674 #endif
0675
0676 ns.addRotation(nam, rot);
0677 }
0678
0679
0680 template <>
0681 void Converter<DDLReflectionRotation>::operator()(xml_h element) const {
0682 cms::DDParsingContext* context = _param<cms::DDParsingContext>();
0683 cms::DDNamespace ns(context);
0684 xml_dim_t xrot(element);
0685 string name = xrot.nameStr();
0686 double thetaX = xrot.hasAttr(DD_CMU(thetaX)) ? ns.attr<double>(xrot, DD_CMU(thetaX)) : 0e0;
0687 double phiX = xrot.hasAttr(DD_CMU(phiX)) ? ns.attr<double>(xrot, DD_CMU(phiX)) : 0e0;
0688 double thetaY = xrot.hasAttr(DD_CMU(thetaY)) ? ns.attr<double>(xrot, DD_CMU(thetaY)) : 0e0;
0689 double phiY = xrot.hasAttr(DD_CMU(phiY)) ? ns.attr<double>(xrot, DD_CMU(phiY)) : 0e0;
0690 double thetaZ = xrot.hasAttr(DD_CMU(thetaZ)) ? ns.attr<double>(xrot, DD_CMU(thetaZ)) : 0e0;
0691 double phiZ = xrot.hasAttr(DD_CMU(phiZ)) ? ns.attr<double>(xrot, DD_CMU(phiZ)) : 0e0;
0692
0693 #ifdef EDM_ML_DEBUG
0694
0695 printout(context->debug_rotations ? ALWAYS : DEBUG,
0696 "DD4CMS",
0697 "+++ Adding reflection rotation: %-32s: (theta/phi)[rad] X: %6.3f %6.3f Y: %6.3f %6.3f Z: %6.3f %6.3f",
0698 ns.prepend(name).c_str(),
0699 thetaX,
0700 phiX,
0701 thetaY,
0702 phiY,
0703 thetaZ,
0704 phiZ);
0705
0706 #endif
0707
0708 Rotation3D rot = makeRotReflect(thetaX, phiX, thetaY, phiY, thetaZ, phiZ);
0709 ns.addRotation(name, rot);
0710 }
0711
0712
0713 template <>
0714 void Converter<DDLRotationSequence>::operator()(xml_h element) const {
0715 cms::DDParsingContext* context = _param<cms::DDParsingContext>();
0716 cms::DDNamespace ns(context);
0717 xml_dim_t xrot(element);
0718 string nam = xrot.nameStr();
0719 Rotation3D rot;
0720 xml_coll_t rotations(xrot, DD_CMU(RotationByAxis));
0721 for (rotations.reset(); rotations; ++rotations) {
0722 string axis = ns.attr<string>(rotations, DD_CMU(axis));
0723 double angle = ns.attr<double>(rotations, _U(angle));
0724 rot = makeRotation3D(rot, axis, angle);
0725
0726 #ifdef EDM_ML_DEBUG
0727
0728 printout(context->debug_rotations ? ALWAYS : DEBUG,
0729 "DD4CMS",
0730 "+ Adding rotation to: %-29s: (axis/angle)[rad] Axis: %s Angle: %6.3f",
0731 nam.c_str(),
0732 axis.c_str(),
0733 angle);
0734
0735 #endif
0736 }
0737 double xx, xy, xz;
0738 double yx, yy, yz;
0739 double zx, zy, zz;
0740 rot.GetComponents(xx, xy, xz, yx, yy, yz, zx, zy, zz);
0741
0742 #ifdef EDM_ML_DEBUG
0743
0744 printout(context->debug_rotations ? ALWAYS : DEBUG,
0745 "DD4CMS",
0746 "+++ Adding rotation sequence: %-23s: %6.3f %6.3f %6.3f, %6.3f %6.3f %6.3f, %6.3f %6.3f %6.3f",
0747 ns.prepend(nam).c_str(),
0748 xx,
0749 xy,
0750 xz,
0751 yx,
0752 yy,
0753 yz,
0754 zx,
0755 zy,
0756 zz);
0757
0758 #endif
0759
0760 ns.addRotation(nam, rot);
0761 }
0762
0763
0764 template <>
0765 void Converter<DDLRotationByAxis>::operator()(xml_h element) const {
0766 cms::DDParsingContext* context = _param<cms::DDParsingContext>();
0767 cms::DDNamespace ns(context);
0768 xml_dim_t xrot(element);
0769 xml_dim_t par(xrot.parent());
0770 if (xrot.hasAttr(_U(name))) {
0771 string nam = xrot.nameStr();
0772 string axis = ns.attr<string>(xrot, DD_CMU(axis));
0773 double angle = ns.attr<double>(xrot, _U(angle));
0774 Rotation3D rot;
0775 rot = makeRotation3D(rot, axis, angle);
0776
0777 #ifdef EDM_ML_DEBUG
0778
0779 printout(context->debug_rotations ? ALWAYS : DEBUG,
0780 "DD4CMS",
0781 "+++ Adding rotation: %-32s: (axis/angle)[rad] Axis: %s Angle: %6.3f",
0782 ns.prepend(nam).c_str(),
0783 axis.c_str(),
0784 angle);
0785
0786 #endif
0787
0788 ns.addRotation(nam, rot);
0789 }
0790 }
0791
0792
0793 template <>
0794 void Converter<DDLLogicalPart>::operator()(xml_h element) const {
0795 cms::DDNamespace ns(_param<cms::DDParsingContext>());
0796 xml_dim_t e(element);
0797 string sol = e.child(DD_CMU(rSolid)).attr<string>(_U(name));
0798 string mat = e.child(DD_CMU(rMaterial)).attr<string>(_U(name));
0799 string volName = ns.prepend(e.attr<string>(_U(name)));
0800 Solid solid = ns.solid(sol);
0801 Material material = ns.material(mat);
0802 if (ns.context()->assemblySolids.count(sol) == 1) {
0803
0804
0805
0806 ns.addAssembly(volName, false);
0807 return;
0808 }
0809
0810 #ifdef EDM_ML_DEBUG
0811 Volume volume =
0812 #endif
0813
0814 ns.addVolume(Volume(volName, solid, material));
0815
0816 #ifdef EDM_ML_DEBUG
0817
0818 printout(ns.context()->debug_volumes ? ALWAYS : DEBUG,
0819 "DD4CMS",
0820 "+++ %s Volume: %-24s [%s] Shape: %-32s [%s] Material: %-40s [%s]",
0821 e.tag().c_str(),
0822 volName.c_str(),
0823 volume.isValid() ? "VALID" : "INVALID",
0824 sol.c_str(),
0825 solid.isValid() ? "VALID" : "INVALID",
0826 mat.c_str(),
0827 material.isValid() ? "VALID" : "INVALID");
0828
0829 #endif
0830 }
0831
0832
0833 template <>
0834 void Converter<DDLTransform3D>::operator()(xml_h element) const {
0835 cms::DDNamespace ns(_param<cms::DDParsingContext>());
0836 Transform3D* tr = _option<Transform3D>();
0837 xml_dim_t e(element);
0838 xml_dim_t translation = e.child(DD_CMU(Translation), false);
0839 xml_dim_t rotation = e.child(DD_CMU(Rotation), false);
0840 xml_dim_t refRotation = e.child(DD_CMU(rRotation), false);
0841 xml_dim_t refReflectionRotation = e.child(DD_CMU(rReflectionRotation), false);
0842 Position pos;
0843 Rotation3D rot;
0844
0845 if (translation.ptr()) {
0846 double x = ns.attr<double>(translation, _U(x));
0847 double y = ns.attr<double>(translation, _U(y));
0848 double z = ns.attr<double>(translation, _U(z));
0849 pos = Position(x, y, z);
0850 }
0851 if (rotation.ptr()) {
0852 double x = ns.attr<double>(rotation, _U(x));
0853 double y = ns.attr<double>(rotation, _U(y));
0854 double z = ns.attr<double>(rotation, _U(z));
0855 rot = RotationZYX(z, y, x);
0856 } else if (refRotation.ptr()) {
0857 string rotName = ns.prepend(refRotation.nameStr());
0858 rot = ns.rotation(rotName);
0859 } else if (refReflectionRotation.ptr()) {
0860 string rotName = ns.prepend(refReflectionRotation.nameStr());
0861 rot = ns.rotation(rotName);
0862 }
0863 *tr = Transform3D(rot, pos);
0864 }
0865
0866 static void placeAssembly(Volume* parentPtr,
0867 const string& parentName,
0868 Volume* childPtr,
0869 const string& childName,
0870 int copy,
0871 const Transform3D& transform,
0872 cms::DDNamespace& ns) {
0873 #ifdef EDM_ML_DEBUG
0874
0875 printout(ns.context()->debug_placements ? ALWAYS : DEBUG,
0876 "DD4CMS",
0877 "+++ Parent vol: %-24s Child: %-32s, copy:%d",
0878 parentName.c_str(),
0879 childName.c_str(),
0880 copy);
0881
0882 #endif
0883
0884 TGeoShape* shape = (*childPtr)->GetShape();
0885
0886 if (shape->IsA() == TGeoShapeAssembly::Class()) {
0887 TGeoShapeAssembly* as = (TGeoShapeAssembly*)shape;
0888 if (std::fabs(as->GetDX()) < numeric_limits<double>::epsilon() &&
0889 std::fabs(as->GetDY()) < numeric_limits<double>::epsilon() &&
0890 std::fabs(as->GetDZ()) < numeric_limits<double>::epsilon()) {
0891 as->NeedsBBoxRecompute();
0892 as->ComputeBBox();
0893 }
0894 }
0895 if (ns.context()->validate) {
0896 TGeoNode* n;
0897 TString nam_id = TString::Format("%s_%d", (*childPtr)->GetName(), copy);
0898 n = static_cast<TGeoNode*>((*parentPtr)->GetNode(nam_id));
0899 if (n != nullptr) {
0900 printout(ERROR, "PlacedVolume", "++ Attempt to add already existing node %s", (const char*)nam_id);
0901 return;
0902 }
0903 }
0904
0905 PlacedVolume pv;
0906 if ((*childPtr)->IsAssembly()) {
0907 pv = parentPtr->placeVolume(ns.assembly(childName), copy, transform);
0908 } else {
0909 pv = parentPtr->placeVolume(*childPtr, copy, transform);
0910 }
0911
0912 if (!pv.isValid()) {
0913 printout(ERROR, "DD4CMS", "+++ Placement FAILED! Parent:%s Child:%s", parentName.c_str(), childName.c_str());
0914 }
0915 }
0916
0917
0918 template <>
0919 void Converter<DDLPosPart>::operator()(xml_h element) const {
0920 cms::DDNamespace ns(_param<cms::DDParsingContext>());
0921 xml_dim_t e(element);
0922 int copy = e.attr<int>(DD_CMU(copyNumber));
0923 string parentName = ns.prepend(ns.attr<string>(e.child(DD_CMU(rParent)), _U(name)));
0924 string childName = ns.prepend(ns.attr<string>(e.child(DD_CMU(rChild)), _U(name)));
0925 Transform3D transform;
0926 Converter<DDLTransform3D>(description, param, &transform)(element);
0927
0928 Volume parent = ns.volume(parentName, false);
0929 Volume child = ns.volume(childName, false);
0930 Assembly parAsmb = ns.assembly(parentName, false);
0931 Assembly childAsmb = ns.assembly(childName, false);
0932
0933 #ifdef EDM_ML_DEBUG
0934
0935 printout(ns.context()->debug_placements ? ALWAYS : DEBUG,
0936 "DD4CMS",
0937 "+++ %s Parent: %-24s [%s] Child: %-32s [%s] copy:%d",
0938 e.tag().c_str(),
0939 parentName.c_str(),
0940 parent.isValid() ? "VALID" : "INVALID",
0941 childName.c_str(),
0942 child.isValid() ? "VALID" : "INVALID",
0943 copy);
0944
0945 #endif
0946
0947 if (!parent.isValid() && !parAsmb.isValid() && strchr(parentName.c_str(), NAMESPACE_SEP) == nullptr) {
0948 parentName = ns.prepend(parentName);
0949 parAsmb = ns.assembly(parentName, false);
0950 if (!parAsmb.isValid())
0951 parent = ns.volume(parentName);
0952 }
0953
0954 if (!child.isValid() && !childAsmb.isValid() && strchr(childName.c_str(), NAMESPACE_SEP) == nullptr) {
0955 childName = ns.prepend(childName);
0956 child = ns.volume(childName, false);
0957 childAsmb = ns.assembly(childName, false);
0958 }
0959 if (parAsmb.isValid() || childAsmb.isValid()) {
0960 printout(ns.context()->debug_placements ? ALWAYS : DEBUG,
0961 "DD4CMS",
0962 "***** Placing assembly parent %s, child %s",
0963 parentName.c_str(),
0964 childName.c_str());
0965 Volume* parentPtr = parAsmb.isValid() ? &parAsmb : &parent;
0966 Volume* childPtr = childAsmb.isValid() ? &childAsmb : &child;
0967 placeAssembly(parentPtr, parentName, childPtr, childName, copy, transform, ns);
0968 return;
0969 }
0970
0971 #ifdef EDM_ML_DEBUG
0972
0973 printout(ns.context()->debug_placements ? ALWAYS : DEBUG,
0974 "DD4CMS",
0975 "+++ %s Parent: %-24s [%s] Child: %-32s [%s] copy:%d",
0976 e.tag().c_str(),
0977 parentName.c_str(),
0978 parent.isValid() ? "VALID" : "INVALID",
0979 childName.c_str(),
0980 child.isValid() ? "VALID" : "INVALID",
0981 copy);
0982
0983 #endif
0984
0985 PlacedVolume pv;
0986 if (child.isValid()) {
0987
0988
0989
0990 if (!parent) {
0991 except("dd4hep", "Volume: Attempt to assign daughters to an invalid physical parent volume.");
0992 }
0993 if (!child) {
0994 except("dd4hep", "Volume: Attempt to assign an invalid physical daughter volume.");
0995 }
0996 TGeoShape* shape = child->GetShape();
0997
0998 if (shape->IsA() == TGeoShapeAssembly::Class()) {
0999 TGeoShapeAssembly* as = (TGeoShapeAssembly*)shape;
1000 if (std::fabs(as->GetDX()) < numeric_limits<double>::epsilon() &&
1001 std::fabs(as->GetDY()) < numeric_limits<double>::epsilon() &&
1002 std::fabs(as->GetDZ()) < numeric_limits<double>::epsilon()) {
1003 as->NeedsBBoxRecompute();
1004 as->ComputeBBox();
1005 }
1006 }
1007 TGeoNode* n;
1008 TString nam_id = TString::Format("%s_%d", child->GetName(), copy);
1009 if (ns.context()->validate) {
1010 n = static_cast<TGeoNode*>(parent->GetNode(nam_id));
1011 if (n != nullptr) {
1012 printout(ERROR, "PlacedVolume", "++ Attempt to add already existing node %s", (const char*)nam_id);
1013 }
1014 }
1015
1016 Rotation3D rot(transform.Rotation());
1017 Translation3D trans(transform.Translation());
1018 double x, y, z;
1019 trans.GetComponents(x, y, z);
1020 Position pos(x, y, z);
1021 parent->AddNode(child, copy, createPlacement(rot, pos));
1022
1023 n = static_cast<TGeoNode*>(parent->GetNodes()->Last());
1024 assert(n->GetName() == nam_id);
1025 n->TGeoNode::SetUserExtension(new PlacedVolume::Object());
1026 pv = PlacedVolume(n);
1027 }
1028 if (!pv.isValid()) {
1029 printout(ERROR,
1030 "DD4CMS",
1031 "+++ Placement FAILED! Parent:%s Child:%s Valid:%s",
1032 parent.name(),
1033 childName.c_str(),
1034 yes_no(child.isValid()));
1035 }
1036 }
1037
1038
1039 template <>
1040 void Converter<PartSelector>::operator()(xml_h element) const {
1041 cms::DDNamespace ns(_param<cms::DDParsingContext>());
1042 cms::DDParsingContext* const context = ns.context();
1043 dd4hep::SpecParRegistry& registry = *context->description.extension<dd4hep::SpecParRegistry>();
1044 xml_dim_t e(element);
1045 xml_dim_t specPar = e.parent();
1046 string specParName = specPar.attr<string>(_U(name));
1047 string path = e.attr<string>(DD_CMU(path));
1048
1049 #ifdef EDM_ML_DEBUG
1050
1051 printout(ns.context()->debug_specpars ? ALWAYS : DEBUG,
1052 "DD4CMS",
1053 "+++ PartSelector for %s path: %s",
1054 specParName.c_str(),
1055 path.c_str());
1056
1057 #endif
1058
1059 size_t pos = std::string::npos;
1060 if ((pos = path.find("//.*:")) != std::string::npos) {
1061 path.erase(pos + 2, 3);
1062 }
1063 registry.specpars[specParName].paths.emplace_back(std::move(path));
1064 }
1065
1066
1067 template <>
1068 void Converter<Parameter>::operator()(xml_h element) const {
1069 cms::DDNamespace ns(_param<cms::DDParsingContext>());
1070 cms::DDParsingContext* const context = ns.context();
1071 dd4hep::SpecParRegistry& registry = *context->description.extension<dd4hep::SpecParRegistry>();
1072 xml_dim_t e(element);
1073 xml_dim_t specPar = e.parent();
1074 xml_dim_t specParSect = specPar.parent();
1075 string specParName = specPar.attr<string>(_U(name));
1076 string name = e.nameStr();
1077 string value = e.attr<string>(DD_CMU(value));
1078 bool eval = specParSect.hasAttr(_U(eval)) ? specParSect.attr<bool>(_U(eval)) : false;
1079 eval = specPar.hasAttr(_U(eval)) ? specPar.attr<bool>(_U(eval)) : eval;
1080 eval = e.hasAttr(_U(eval)) ? e.attr<bool>(_U(eval)) : eval;
1081
1082 string type = eval ? "number" : "string";
1083
1084 #ifdef EDM_ML_DEBUG
1085
1086 printout(ns.context()->debug_specpars ? ALWAYS : DEBUG,
1087 "DD4CMS",
1088 "+++ Parameter for %s: %s value %s is a %s",
1089 specParName.c_str(),
1090 name.c_str(),
1091 value.c_str(),
1092 type.c_str());
1093
1094 #endif
1095
1096 size_t idx = value.find('[');
1097 if (idx == string::npos && type == "number") {
1098 registry.specpars[specParName].numpars[name].emplace_back(dd4hep::_toDouble(value));
1099 return;
1100 }
1101 if (idx == string::npos || type == "string") {
1102 registry.specpars[specParName].spars[name].emplace_back(std::move(value));
1103 return;
1104 }
1105
1106 while (idx != string::npos) {
1107 ++idx;
1108 size_t idp = value.find(':', idx);
1109 size_t idq = value.find(']', idx);
1110 if (idp == string::npos || idp > idq)
1111 value.insert(idx, ns.name());
1112 else if (idp != string::npos && idp < idq)
1113 value[idp] = NAMESPACE_SEP;
1114 idx = value.find('[', idx);
1115 }
1116
1117 string rep;
1118 string& v = value;
1119 size_t idq;
1120 for (idx = v.find('[', 0); idx != string::npos; idx = v.find('[', idx + 1)) {
1121 idq = v.find(']', idx + 1);
1122 rep = v.substr(idx + 1, idq - idx - 1);
1123 auto r = ns.context()->description.constants().find(rep);
1124 if (r != ns.context()->description.constants().end()) {
1125 rep = "(" + r->second->type + ")";
1126 v.replace(idx, idq - idx + 1, rep);
1127 }
1128 }
1129 registry.specpars[specParName].numpars[name].emplace_back(dd4hep::_toDouble(value));
1130 }
1131
1132 template <typename TYPE>
1133 static void convert_boolean(cms::DDParsingContext* context, xml_h element) {
1134 cms::DDNamespace ns(context);
1135 xml_dim_t e(element);
1136 string nam = e.nameStr();
1137 string solidName[2];
1138 Solid solids[2];
1139 Solid boolean;
1140 int cnt = 0;
1141 if (e.hasChild(DD_CMU(rSolid))) {
1142 for (xml_coll_t c(element, DD_CMU(rSolid)); cnt < 2 && c; ++c, ++cnt) {
1143 solidName[cnt] = c.attr<string>(_U(name));
1144 solids[cnt] = ns.solid(c.attr<string>(_U(name)));
1145 }
1146 } else {
1147 solidName[0] = e.attr<string>(DD_CMU(firstSolid));
1148 if ((solids[0] = ns.solid(e.attr<string>(DD_CMU(firstSolid)))).isValid())
1149 ++cnt;
1150 solidName[1] = e.attr<string>(DD_CMU(secondSolid));
1151 if ((solids[1] = ns.solid(e.attr<string>(DD_CMU(secondSolid)))).isValid())
1152 ++cnt;
1153 }
1154 if (cnt != 2) {
1155 except("DD4CMS", "+++ Failed to create boolean solid %s. Found only %d parts.", nam.c_str(), cnt);
1156 }
1157
1158 #ifdef EDM_ML_DEBUG
1159
1160 printout(ns.context()->debug_placements ? ALWAYS : DEBUG,
1161 "DD4CMS",
1162 "+++ BooleanSolid: %s Left: %-32s Right: %-32s",
1163 nam.c_str(),
1164 ((solids[0].ptr() == nullptr) ? solidName[0].c_str() : solids[0]->GetName()),
1165 ((solids[1].ptr() == nullptr) ? solidName[1].c_str() : solids[1]->GetName()));
1166
1167 #endif
1168
1169 if (solids[0].isValid() && solids[1].isValid()) {
1170 Transform3D trafo;
1171 Converter<DDLTransform3D>(context->description, context, &trafo)(element);
1172 boolean = TYPE(solids[0], solids[1], trafo);
1173 } else {
1174
1175 Transform3D trafo;
1176 Converter<DDLTransform3D>(context->description, context, &trafo)(element);
1177 ns.context()->unresolvedShapes.emplace(nam,
1178 DDParsingContext::BooleanShape<TYPE>(solidName[0], solidName[1], trafo));
1179 if (solids[0].isValid() == false) {
1180 printout(ERROR, "DD4CMS", "++ Solid not defined yet: %s", solidName[0].c_str());
1181 }
1182 if (solids[1].isValid() == false) {
1183 printout(ERROR, "DD4CMS", "++ Solid not defined yet: %s", solidName[1].c_str());
1184 }
1185 printout(ERROR, "DD4CMS", "++ Re-order XML files to prevent references to undefined solids");
1186 }
1187 if (!boolean.isValid()) {
1188
1189 ns.context()->shapes.emplace(nam, dd4hep::Solid(nullptr));
1190 } else
1191 ns.addSolid(nam, boolean);
1192 }
1193
1194
1195 template <>
1196 void Converter<DDLUnionSolid>::operator()(xml_h element) const {
1197 convert_boolean<UnionSolid>(_param<cms::DDParsingContext>(), element);
1198 }
1199
1200
1201 template <>
1202 void Converter<DDLSubtractionSolid>::operator()(xml_h element) const {
1203 convert_boolean<SubtractionSolid>(_param<cms::DDParsingContext>(), element);
1204 }
1205
1206
1207 template <>
1208 void Converter<DDLIntersectionSolid>::operator()(xml_h element) const {
1209 convert_boolean<IntersectionSolid>(_param<cms::DDParsingContext>(), element);
1210 }
1211
1212
1213 template <>
1214 void Converter<DDLPolycone>::operator()(xml_h element) const {
1215 cms::DDNamespace ns(_param<cms::DDParsingContext>());
1216 xml_dim_t e(element);
1217 string nam = e.nameStr();
1218 double startPhi = ns.attr<double>(e, DD_CMU(startPhi));
1219 double deltaPhi = ns.attr<double>(e, DD_CMU(deltaPhi));
1220 vector<double> z, rmin, rmax, r;
1221
1222 for (xml_coll_t rzpoint(element, DD_CMU(RZPoint)); rzpoint; ++rzpoint) {
1223 z.emplace_back(ns.attr<double>(rzpoint, _U(z)));
1224 r.emplace_back(ns.attr<double>(rzpoint, _U(r)));
1225 }
1226 if (z.empty()) {
1227 for (xml_coll_t zplane(element, DD_CMU(ZSection)); zplane; ++zplane) {
1228 rmin.emplace_back(ns.attr<double>(zplane, DD_CMU(rMin)));
1229 rmax.emplace_back(ns.attr<double>(zplane, DD_CMU(rMax)));
1230 z.emplace_back(ns.attr<double>(zplane, _U(z)));
1231 }
1232
1233 #ifdef EDM_ML_DEBUG
1234
1235 printout(ns.context()->debug_shapes ? ALWAYS : DEBUG,
1236 "DD4CMS",
1237 "+ Polycone: startPhi=%10.3f [rad] deltaPhi=%10.3f [rad] %4ld z-planes",
1238 startPhi,
1239 deltaPhi,
1240 z.size());
1241
1242 #endif
1243
1244 ns.addSolid(nam, Polycone(startPhi, deltaPhi, rmin, rmax, z));
1245 } else {
1246 #ifdef EDM_ML_DEBUG
1247
1248 printout(ns.context()->debug_shapes ? ALWAYS : DEBUG,
1249 "DD4CMS",
1250 "+ Polycone: startPhi=%10.3f [rad] deltaPhi=%10.3f [rad] %4ld z-planes and %4ld radii",
1251 startPhi,
1252 deltaPhi,
1253 z.size(),
1254 r.size());
1255
1256 #endif
1257
1258 ns.addSolid(nam, Polycone(startPhi, deltaPhi, r, z));
1259 }
1260 }
1261
1262
1263 template <>
1264 void Converter<DDLExtrudedPolygon>::operator()(xml_h element) const {
1265 cms::DDNamespace ns(_param<cms::DDParsingContext>());
1266 xml_dim_t e(element);
1267 string nam = e.nameStr();
1268 vector<double> pt_x, pt_y, sec_x, sec_y, sec_z, sec_scale;
1269
1270 for (xml_coll_t sec(element, DD_CMU(ZXYSection)); sec; ++sec) {
1271 sec_z.emplace_back(ns.attr<double>(sec, _U(z)));
1272 sec_x.emplace_back(ns.attr<double>(sec, _U(x)));
1273 sec_y.emplace_back(ns.attr<double>(sec, _U(y)));
1274 sec_scale.emplace_back(ns.attr<double>(sec, DD_CMU(scale), 1.0));
1275 }
1276 for (xml_coll_t pt(element, DD_CMU(XYPoint)); pt; ++pt) {
1277 pt_x.emplace_back(ns.attr<double>(pt, _U(x)));
1278 pt_y.emplace_back(ns.attr<double>(pt, _U(y)));
1279 }
1280
1281 #ifdef EDM_ML_DEBUG
1282
1283 printout(ns.context()->debug_shapes ? ALWAYS : DEBUG,
1284 "DD4CMS",
1285 "+ ExtrudedPolygon: %4ld points %4ld zxy sections",
1286 pt_x.size(),
1287 sec_z.size());
1288
1289 #endif
1290
1291 ns.addSolid(nam, ExtrudedPolygon(pt_x, pt_y, sec_z, sec_x, sec_y, sec_scale));
1292 }
1293
1294
1295 template <>
1296 void Converter<DDLPolyhedra>::operator()(xml_h element) const {
1297 cms::DDNamespace ns(_param<cms::DDParsingContext>());
1298 xml_dim_t e(element);
1299 string nam = e.nameStr();
1300 double numSide = ns.attr<int>(e, DD_CMU(numSide));
1301 double startPhi = ns.attr<double>(e, DD_CMU(startPhi));
1302 double deltaPhi = ns.attr<double>(e, DD_CMU(deltaPhi));
1303 vector<double> z, rmin, rmax;
1304
1305 for (xml_coll_t zplane(element, DD_CMU(RZPoint)); zplane; ++zplane) {
1306 rmin.emplace_back(0.0);
1307 rmax.emplace_back(ns.attr<double>(zplane, _U(r)));
1308 z.emplace_back(ns.attr<double>(zplane, _U(z)));
1309 }
1310 for (xml_coll_t zplane(element, DD_CMU(ZSection)); zplane; ++zplane) {
1311 rmin.emplace_back(ns.attr<double>(zplane, DD_CMU(rMin)));
1312 rmax.emplace_back(ns.attr<double>(zplane, DD_CMU(rMax)));
1313 z.emplace_back(ns.attr<double>(zplane, _U(z)));
1314 }
1315
1316 #ifdef EDM_ML_DEBUG
1317
1318 printout(ns.context()->debug_shapes ? ALWAYS : DEBUG,
1319 "DD4CMS",
1320 "+ Polyhedra:startPhi=%8.3f [rad] deltaPhi=%8.3f [rad] %4d sides %4ld z-planes",
1321 startPhi,
1322 deltaPhi,
1323 numSide,
1324 z.size());
1325
1326 #endif
1327
1328 ns.addSolid(nam, Polyhedra(numSide, startPhi, deltaPhi, z, rmin, rmax));
1329 }
1330
1331
1332 template <>
1333 void Converter<DDLSphere>::operator()(xml_h element) const {
1334 cms::DDNamespace ns(_param<cms::DDParsingContext>());
1335 xml_dim_t e(element);
1336 string nam = e.nameStr();
1337 double rinner = ns.attr<double>(e, DD_CMU(innerRadius));
1338 double router = ns.attr<double>(e, DD_CMU(outerRadius));
1339 double startPhi = ns.attr<double>(e, DD_CMU(startPhi));
1340 double deltaPhi = ns.attr<double>(e, DD_CMU(deltaPhi));
1341 double startTheta = ns.attr<double>(e, DD_CMU(startTheta));
1342 double deltaTheta = ns.attr<double>(e, DD_CMU(deltaTheta));
1343
1344 #ifdef EDM_ML_DEBUG
1345
1346 printout(ns.context()->debug_shapes ? ALWAYS : DEBUG,
1347 "DD4CMS",
1348 "+ Sphere: r_inner=%8.3f [cm] r_outer=%8.3f [cm]"
1349 " startPhi=%8.3f [rad] deltaPhi=%8.3f startTheta=%8.3f delteTheta=%8.3f [rad]",
1350 rinner / dd4hep::cm,
1351 router / dd4hep::cm,
1352 startPhi,
1353 deltaPhi,
1354 startTheta,
1355 deltaTheta);
1356
1357 #endif
1358
1359 ns.addSolid(nam, Sphere(rinner, router, startTheta, deltaTheta, startPhi, deltaPhi));
1360 }
1361
1362
1363 template <>
1364 void Converter<DDLTorus>::operator()(xml_h element) const {
1365 cms::DDNamespace ns(_param<cms::DDParsingContext>());
1366 xml_dim_t e(element);
1367 string nam = e.nameStr();
1368 double r = ns.attr<double>(e, DD_CMU(torusRadius));
1369 double rinner = ns.attr<double>(e, DD_CMU(innerRadius));
1370 double router = ns.attr<double>(e, DD_CMU(outerRadius));
1371 double startPhi = ns.attr<double>(e, DD_CMU(startPhi));
1372 double deltaPhi = ns.attr<double>(e, DD_CMU(deltaPhi));
1373
1374 #ifdef EDM_ML_DEBUG
1375
1376 printout(ns.context()->debug_shapes ? ALWAYS : DEBUG,
1377 "DD4CMS",
1378 "+ Torus: r=%10.3f [cm] r_inner=%10.3f [cm] r_outer=%10.3f [cm]"
1379 " startPhi=%10.3f [rad] deltaPhi=%10.3f [rad]",
1380 r / dd4hep::cm,
1381 rinner / dd4hep::cm,
1382 router / dd4hep::cm,
1383 startPhi,
1384 deltaPhi);
1385
1386 #endif
1387
1388 ns.addSolid(nam, Torus(r, rinner, router, startPhi, deltaPhi));
1389 }
1390
1391
1392 template <>
1393 void Converter<DDLPseudoTrap>::operator()(xml_h element) const {
1394 cms::DDNamespace ns(_param<cms::DDParsingContext>());
1395 xml_dim_t e(element);
1396 string nam = e.nameStr();
1397 double dx1 = ns.attr<double>(e, DD_CMU(dx1));
1398 double dy1 = ns.attr<double>(e, DD_CMU(dy1));
1399 double dx2 = ns.attr<double>(e, DD_CMU(dx2));
1400 double dy2 = ns.attr<double>(e, DD_CMU(dy2));
1401 double dz = ns.attr<double>(e, _U(dz));
1402 double r = ns.attr<double>(e, _U(radius));
1403 bool atMinusZ = ns.attr<bool>(e, DD_CMU(atMinusZ));
1404
1405 #ifdef EDM_ML_DEBUG
1406
1407 printout(ns.context()->debug_shapes ? ALWAYS : DEBUG,
1408 "DD4CMS",
1409 "+ Pseudotrap: dz=%8.3f [cm] dx1:%.3f dy1:%.3f dx2=%.3f dy2=%.3f radius:%.3f atMinusZ:%s",
1410 dz / dd4hep::cm,
1411 dx1 / dd4hep::cm,
1412 dy1 / dd4hep::cm,
1413 dx2 / dd4hep::cm,
1414 dy2 / dd4hep::cm,
1415 r / dd4hep::cm,
1416 yes_no(atMinusZ));
1417
1418 #endif
1419
1420 ns.addSolid(nam, PseudoTrap(dx1, dx2, dy1, dy2, dz, r, atMinusZ));
1421 }
1422
1423
1424 template <>
1425 void Converter<DDLTrapezoid>::operator()(xml_h element) const {
1426 cms::DDNamespace ns(_param<cms::DDParsingContext>());
1427 xml_dim_t e(element);
1428 string nam = e.nameStr();
1429 double dz = ns.attr<double>(e, _U(dz));
1430 double alp1 = ns.attr<double>(e, DD_CMU(alp1));
1431 double bl1 = ns.attr<double>(e, DD_CMU(bl1));
1432 double tl1 = ns.attr<double>(e, DD_CMU(tl1));
1433 double h1 = ns.attr<double>(e, DD_CMU(h1));
1434 double alp2 = ns.attr<double>(e, DD_CMU(alp2));
1435 double bl2 = ns.attr<double>(e, DD_CMU(bl2));
1436 double tl2 = ns.attr<double>(e, DD_CMU(tl2));
1437 double h2 = ns.attr<double>(e, DD_CMU(h2));
1438 double phi = ns.attr<double>(e, _U(phi), 0.0);
1439 double theta = ns.attr<double>(e, _U(theta), 0.0);
1440
1441 #ifdef EDM_ML_DEBUG
1442
1443 printout(ns.context()->debug_shapes ? ALWAYS : DEBUG,
1444 "DD4CMS",
1445 "+ Trapezoid: dz=%10.3f [cm] alp1:%.3f bl1=%.3f tl1=%.3f alp2=%.3f bl2=%.3f tl2=%.3f h2=%.3f phi=%.3f "
1446 "theta=%.3f",
1447 dz / dd4hep::cm,
1448 alp1,
1449 bl1 / dd4hep::cm,
1450 tl1 / dd4hep::cm,
1451 h1 / dd4hep::cm,
1452 alp2,
1453 bl2 / dd4hep::cm,
1454 tl2 / dd4hep::cm,
1455 h2 / dd4hep::cm,
1456 phi,
1457 theta);
1458
1459 #endif
1460
1461 ns.addSolid(nam, Trap(dz, theta, phi, h1, bl1, tl1, alp1, h2, bl2, tl2, alp2));
1462 }
1463
1464
1465 template <>
1466 void Converter<DDLTrd1>::operator()(xml_h element) const {
1467 cms::DDNamespace ns(_param<cms::DDParsingContext>());
1468 xml_dim_t e(element);
1469 string nam = e.nameStr();
1470 double dx1 = ns.attr<double>(e, DD_CMU(dx1));
1471 double dy1 = ns.attr<double>(e, DD_CMU(dy1));
1472 double dx2 = ns.attr<double>(e, DD_CMU(dx2), 0.0);
1473 double dy2 = ns.attr<double>(e, DD_CMU(dy2), dy1);
1474 double dz = ns.attr<double>(e, DD_CMU(dz));
1475 if (dy1 == dy2) {
1476 #ifdef EDM_ML_DEBUG
1477
1478 printout(ns.context()->debug_shapes ? ALWAYS : DEBUG,
1479 "DD4CMS",
1480 "+ Trd1: dz=%8.3f [cm] dx1:%.3f dy1:%.3f dx2:%.3f dy2:%.3f",
1481 dz / dd4hep::cm,
1482 dx1 / dd4hep::cm,
1483 dy1 / dd4hep::cm,
1484 dx2 / dd4hep::cm,
1485 dy2 / dd4hep::cm);
1486
1487 #endif
1488
1489 ns.addSolid(nam, Trd1(dx1, dx2, dy1, dz));
1490 } else {
1491 #ifdef EDM_ML_DEBUG
1492
1493 printout(ns.context()->debug_shapes ? ALWAYS : DEBUG,
1494 "DD4CMS",
1495 "+ Trd1(which is actually Trd2): dz=%8.3f [cm] dx1:%.3f dy1:%.3f dx2:%.3f dy2:%.3f",
1496 dz / dd4hep::cm,
1497 dx1 / dd4hep::cm,
1498 dy1 / dd4hep::cm,
1499 dx2 / dd4hep::cm,
1500 dy2 / dd4hep::cm);
1501
1502 #endif
1503
1504 ns.addSolid(nam, Trd2(dx1, dx2, dy1, dy2, dz));
1505 }
1506 }
1507
1508
1509 template <>
1510 void Converter<DDLTrd2>::operator()(xml_h element) const {
1511 cms::DDNamespace ns(_param<cms::DDParsingContext>());
1512 xml_dim_t e(element);
1513 string nam = e.nameStr();
1514 double dx1 = ns.attr<double>(e, DD_CMU(dx1));
1515 double dy1 = ns.attr<double>(e, DD_CMU(dy1));
1516 double dx2 = ns.attr<double>(e, DD_CMU(dx2), 0.0);
1517 double dy2 = ns.attr<double>(e, DD_CMU(dy2), dy1);
1518 double dz = ns.attr<double>(e, DD_CMU(dz));
1519
1520 #ifdef EDM_ML_DEBUG
1521
1522 printout(ns.context()->debug_shapes ? ALWAYS : DEBUG,
1523 "DD4CMS",
1524 "+ Trd1: dz=%8.3f [cm] dx1:%.3f dy1:%.3f dx2:%.3f dy2:%.3f",
1525 dz / dd4hep::cm,
1526 dx1 / dd4hep::cm,
1527 dy1 / dd4hep::cm,
1528 dx2 / dd4hep::cm,
1529 dy2 / dd4hep::cm);
1530
1531 #endif
1532
1533 ns.addSolid(nam, Trd2(dx1, dx2, dy1, dy2, dz));
1534 }
1535
1536
1537 template <>
1538 void Converter<DDLTubs>::operator()(xml_h element) const {
1539 cms::DDNamespace ns(_param<cms::DDParsingContext>());
1540 xml_dim_t e(element);
1541 string nam = e.nameStr();
1542 double dz = ns.attr<double>(e, DD_CMU(dz));
1543 double rmin = ns.attr<double>(e, DD_CMU(rMin));
1544 double rmax = ns.attr<double>(e, DD_CMU(rMax));
1545 double startPhi = ns.attr<double>(e, DD_CMU(startPhi), 0.0);
1546 double deltaPhi = ns.attr<double>(e, DD_CMU(deltaPhi), 2 * M_PI);
1547
1548 #ifdef EDM_ML_DEBUG
1549
1550 printout(ns.context()->debug_shapes ? ALWAYS : DEBUG,
1551 "DD4CMS",
1552 "+ Tubs: dz=%8.3f [cm] rmin=%8.3f [cm] rmax=%8.3f [cm]"
1553 " startPhi=%8.3f [rad] deltaPhi=%8.3f [rad]",
1554 dz / dd4hep::cm,
1555 rmin / dd4hep::cm,
1556 rmax / dd4hep::cm,
1557 startPhi,
1558 deltaPhi);
1559
1560 #endif
1561
1562 ns.addSolid(nam, Tube(rmin, rmax, dz, startPhi, startPhi + deltaPhi));
1563 }
1564
1565
1566 template <>
1567 void Converter<DDLCutTubs>::operator()(xml_h element) const {
1568 cms::DDNamespace ns(_param<cms::DDParsingContext>());
1569 xml_dim_t e(element);
1570 string nam = e.nameStr();
1571 double dz = ns.attr<double>(e, DD_CMU(dz));
1572 double rmin = ns.attr<double>(e, DD_CMU(rMin));
1573 double rmax = ns.attr<double>(e, DD_CMU(rMax));
1574 double startPhi = ns.attr<double>(e, DD_CMU(startPhi));
1575 double deltaPhi = ns.attr<double>(e, DD_CMU(deltaPhi));
1576 double lx = ns.attr<double>(e, DD_CMU(lx));
1577 double ly = ns.attr<double>(e, DD_CMU(ly));
1578 double lz = ns.attr<double>(e, DD_CMU(lz));
1579 double tx = ns.attr<double>(e, DD_CMU(tx));
1580 double ty = ns.attr<double>(e, DD_CMU(ty));
1581 double tz = ns.attr<double>(e, DD_CMU(tz));
1582
1583 #ifdef EDM_ML_DEBUG
1584
1585 printout(ns.context()->debug_shapes ? ALWAYS : DEBUG,
1586 "DD4CMS",
1587 "+ CutTube: dz=%8.3f [cm] rmin=%8.3f [cm] rmax=%8.3f [cm]"
1588 " startPhi=%8.3f [rad] deltaPhi=%8.3f [rad]...",
1589 dz / dd4hep::cm,
1590 rmin / dd4hep::cm,
1591 rmax / dd4hep::cm,
1592 startPhi,
1593 deltaPhi);
1594
1595 #endif
1596
1597 ns.addSolid(nam, CutTube(rmin, rmax, dz, startPhi, startPhi + deltaPhi, lx, ly, lz, tx, ty, tz));
1598 }
1599
1600
1601 template <>
1602 void Converter<DDLTruncTubs>::operator()(xml_h element) const {
1603 cms::DDNamespace ns(_param<cms::DDParsingContext>());
1604 xml_dim_t e(element);
1605 string nam = e.nameStr();
1606 double zhalf = ns.attr<double>(e, DD_CMU(zHalf));
1607 double rmin = ns.attr<double>(e, DD_CMU(rMin));
1608 double rmax = ns.attr<double>(e, DD_CMU(rMax));
1609 double startPhi = ns.attr<double>(e, DD_CMU(startPhi));
1610 double deltaPhi = ns.attr<double>(e, DD_CMU(deltaPhi));
1611 double cutAtStart = ns.attr<double>(e, DD_CMU(cutAtStart));
1612 double cutAtDelta = ns.attr<double>(e, DD_CMU(cutAtDelta));
1613 bool cutInside = ns.attr<bool>(e, DD_CMU(cutInside));
1614
1615 #ifdef EDM_ML_DEBUG
1616
1617 printout(ns.context()->debug_shapes ? ALWAYS : DEBUG,
1618 "DD4CMS",
1619 "+ TruncTube:zHalf=%8.3f [cm] rmin=%8.3f [cm] rmax=%8.3f [cm]"
1620 " startPhi=%8.3f [rad] deltaPhi=%8.3f [rad] atStart=%8.3f [cm] atDelta=%8.3f [cm] inside:%s",
1621 zhalf / dd4hep::cm,
1622 rmin / dd4hep::cm,
1623 rmax / dd4hep::cm,
1624 startPhi,
1625 deltaPhi,
1626 cutAtStart / dd4hep::cm,
1627 cutAtDelta / dd4hep::cm,
1628 yes_no(cutInside));
1629
1630 #endif
1631
1632 ns.addSolid(nam, TruncatedTube(zhalf, rmin, rmax, startPhi, deltaPhi, cutAtStart, cutAtDelta, cutInside));
1633 }
1634
1635
1636 template <>
1637 void Converter<DDLEllipticalTube>::operator()(xml_h element) const {
1638 cms::DDNamespace ns(_param<cms::DDParsingContext>());
1639 xml_dim_t e(element);
1640 string nam = e.nameStr();
1641 double dx = ns.attr<double>(e, DD_CMU(xSemiAxis));
1642 double dy = ns.attr<double>(e, DD_CMU(ySemiAxis));
1643 double dz = ns.attr<double>(e, DD_CMU(zHeight));
1644
1645 #ifdef EDM_ML_DEBUG
1646
1647 printout(ns.context()->debug_shapes ? ALWAYS : DEBUG,
1648 "DD4CMS",
1649 "+ EllipticalTube xSemiAxis=%8.3f [cm] ySemiAxis=%8.3f [cm] zHeight=%8.3f [cm]",
1650 dx / dd4hep::cm,
1651 dy / dd4hep::cm,
1652 dz / dd4hep::cm);
1653
1654 #endif
1655
1656 ns.addSolid(nam, EllipticalTube(dx, dy, dz));
1657 }
1658
1659
1660 template <>
1661 void Converter<DDLCone>::operator()(xml_h element) const {
1662 cms::DDNamespace ns(_param<cms::DDParsingContext>());
1663 xml_dim_t e(element);
1664 string nam = e.nameStr();
1665 double dz = ns.attr<double>(e, DD_CMU(dz));
1666 double rmin1 = ns.attr<double>(e, DD_CMU(rMin1));
1667 double rmin2 = ns.attr<double>(e, DD_CMU(rMin2));
1668 double rmax1 = ns.attr<double>(e, DD_CMU(rMax1));
1669 double rmax2 = ns.attr<double>(e, DD_CMU(rMax2));
1670 double startPhi = ns.attr<double>(e, DD_CMU(startPhi));
1671 double deltaPhi = ns.attr<double>(e, DD_CMU(deltaPhi));
1672 double phi2 = startPhi + deltaPhi;
1673
1674 #ifdef EDM_ML_DEBUG
1675
1676 printout(ns.context()->debug_shapes ? ALWAYS : DEBUG,
1677 "DD4CMS",
1678 "+ Cone: dz=%8.3f [cm]"
1679 " rmin1=%8.3f [cm] rmax1=%8.3f [cm]"
1680 " rmin2=%8.3f [cm] rmax2=%8.3f [cm]"
1681 " startPhi=%8.3f [rad] deltaPhi=%8.3f [rad]",
1682 dz / dd4hep::cm,
1683 rmin1 / dd4hep::cm,
1684 rmax1 / dd4hep::cm,
1685 rmin2 / dd4hep::cm,
1686 rmax2 / dd4hep::cm,
1687 startPhi,
1688 deltaPhi);
1689
1690 #endif
1691
1692 ns.addSolid(nam, ConeSegment(dz, rmin1, rmax1, rmin2, rmax2, startPhi, phi2));
1693 }
1694
1695
1696 template <>
1697 void Converter<DDLShapeless>::operator()(xml_h element) const {
1698 cms::DDNamespace ns(_param<cms::DDParsingContext>());
1699 xml_dim_t e(element);
1700 string nam = e.nameStr();
1701
1702 #ifdef EDM_ML_DEBUG
1703
1704 printout(ns.context()->debug_shapes ? ALWAYS : DEBUG,
1705 "DD4CMS",
1706 "+ Shapeless: THIS ONE CAN ONLY BE USED AT THE VOLUME LEVEL -> Shapeless: %s",
1707 nam.c_str());
1708
1709 #endif
1710
1711 ns.addSolid(nam, Box(1, 1, 1));
1712 }
1713
1714
1715 template <>
1716 void Converter<DDLAssembly>::operator()(xml_h element) const {
1717 cms::DDNamespace ns(_param<cms::DDParsingContext>());
1718 xml_dim_t e(element);
1719 string nam = e.nameStr();
1720
1721 #ifdef EDM_ML_DEBUG
1722 printout(
1723 ns.context()->debug_shapes ? ALWAYS : DEBUG, "DD4CMS", "+ Assembly: Adding solid -> Assembly: %s", nam.c_str());
1724 #endif
1725
1726 ns.addAssemblySolid(nam);
1727 }
1728
1729
1730 template <>
1731 void Converter<DDLBox>::operator()(xml_h element) const {
1732 cms::DDNamespace ns(_param<cms::DDParsingContext>());
1733 xml_dim_t e(element);
1734 string nam = e.nameStr();
1735 double dx = ns.attr<double>(e, DD_CMU(dx));
1736 double dy = ns.attr<double>(e, DD_CMU(dy));
1737 double dz = ns.attr<double>(e, DD_CMU(dz));
1738
1739 #ifdef EDM_ML_DEBUG
1740
1741 printout(ns.context()->debug_shapes ? ALWAYS : DEBUG,
1742 "DD4CMS",
1743 "+ Box: dx=%10.3f [cm] dy=%10.3f [cm] dz=%10.3f [cm]",
1744 dx / dd4hep::cm,
1745 dy / dd4hep::cm,
1746 dz / dd4hep::cm);
1747
1748 #endif
1749
1750 ns.addSolid(nam, Box(dx, dy, dz));
1751 }
1752
1753
1754 template <>
1755 void Converter<include_load>::operator()(xml_h element) const {
1756 string fname = element.attr<string>(_U(ref));
1757 edm::FileInPath fp(fname);
1758 xml::Document doc;
1759 doc = xml::DocumentHandler().load(fp.fullPath());
1760
1761 #ifdef EDM_ML_DEBUG
1762
1763 printout(_param<cms::DDParsingContext>()->debug_includes ? ALWAYS : DEBUG,
1764 "DD4CMS",
1765 "+++ Processing the CMS detector description %s",
1766 fname.c_str());
1767
1768 #endif
1769
1770 _option<DDRegistry>()->includes.emplace_back(doc);
1771 }
1772
1773
1774 template <>
1775 void Converter<include_unload>::operator()(xml_h element) const {
1776 string fname = xml::DocumentHandler::system_path(element);
1777 xml::DocumentHolder(xml_elt_t(element).document()).assign(nullptr);
1778
1779 #ifdef EDM_ML_DEBUG
1780
1781 printout(_param<cms::DDParsingContext>()->debug_includes ? ALWAYS : DEBUG,
1782 "DD4CMS",
1783 "+++ Finished processing %s",
1784 fname.c_str());
1785 #endif
1786 }
1787
1788
1789 template <>
1790 void Converter<include_constants>::operator()(xml_h element) const {
1791 xml_coll_t(element, DD_CMU(ConstantsSection)).for_each(Converter<ConstantsSection>(description, param, optional));
1792 }
1793
1794 namespace {
1795
1796
1797
1798
1799
1800
1801
1802 enum class DDAxes { x = 1, y = 2, z = 3, rho = 1, phi = 2, undefined };
1803 const std::map<std::string, DDAxes> axesmap{{"x", DDAxes::x},
1804 {"y", DDAxes::y},
1805 {"z", DDAxes::z},
1806 {"rho", DDAxes::rho},
1807 {"phi", DDAxes::phi},
1808 {"undefined", DDAxes::undefined}};
1809 }
1810
1811
1812 template <>
1813 void Converter<DDLDivision>::operator()(xml_h element) const {
1814 cms::DDNamespace ns(_param<cms::DDParsingContext>(), element);
1815 xml_dim_t e(element);
1816 string childName = e.nameStr();
1817 if (strchr(childName.c_str(), NAMESPACE_SEP) == nullptr)
1818 childName = ns.prepend(childName);
1819
1820 string parentName = ns.attr<string>(e, DD_CMU(parent));
1821 if (strchr(parentName.c_str(), NAMESPACE_SEP) == nullptr)
1822 parentName = ns.prepend(parentName);
1823 string axis = ns.attr<string>(e, DD_CMU(axis));
1824
1825
1826
1827 double offset = e.hasAttr(DD_CMU(offset)) ? ns.attr<double>(e, DD_CMU(offset)) : 0e0;
1828 double width = e.hasAttr(DD_CMU(width)) ? ns.attr<double>(e, DD_CMU(width)) : 0e0;
1829 int nReplicas = e.hasAttr(DD_CMU(nReplicas)) ? ns.attr<int>(e, DD_CMU(nReplicas)) : 0;
1830
1831 #ifdef EDM_ML_DEBUG
1832
1833 printout(ns.context()->debug_placements ? ALWAYS : DEBUG,
1834 "DD4CMS",
1835 "+++ Start executing Division of %s along %s (%d) with offset %6.3f and %6.3f to produce %s....",
1836 parentName.c_str(),
1837 axis.c_str(),
1838 axesmap.at(axis),
1839 offset,
1840 width,
1841 childName.c_str());
1842
1843 #endif
1844
1845 Volume parent = ns.volume(parentName);
1846
1847 const TGeoShape* shape = parent.solid();
1848 TClass* cl = shape->IsA();
1849 if (cl == TGeoTubeSeg::Class()) {
1850 const TGeoTubeSeg* sh = (const TGeoTubeSeg*)shape;
1851 double widthInDeg = convertRadToDeg(width);
1852 double startInDeg = convertRadToDeg(offset);
1853 int numCopies = (int)((sh->GetPhi2() - sh->GetPhi1()) / widthInDeg);
1854
1855 #ifdef EDM_ML_DEBUG
1856
1857 printout(ns.context()->debug_placements ? ALWAYS : DEBUG,
1858 "DD4CMS",
1859 "+++ ...divide %s along %s (%d) with offset %6.3f deg and %6.3f deg to produce %d copies",
1860 parent.solid().type(),
1861 axis.c_str(),
1862 axesmap.at(axis),
1863 startInDeg,
1864 widthInDeg,
1865 numCopies);
1866
1867 #endif
1868
1869 Volume child = parent.divide(childName, static_cast<int>(axesmap.at(axis)), numCopies, startInDeg, widthInDeg);
1870
1871 ns.context()->volumes[childName] = child;
1872
1873 #ifdef EDM_ML_DEBUG
1874
1875 printout(ns.context()->debug_placements ? ALWAYS : DEBUG,
1876 "DD4CMS",
1877 "+++ %s Parent: %-24s [%s] Child: %-32s [%s] is multivolume [%s]",
1878 e.tag().c_str(),
1879 parentName.c_str(),
1880 parent.isValid() ? "VALID" : "INVALID",
1881 child.name(),
1882 child.isValid() ? "VALID" : "INVALID",
1883 child->IsVolumeMulti() ? "YES" : "NO");
1884 #endif
1885
1886 } else if (cl == TGeoTrd1::Class()) {
1887 double dy = static_cast<const TGeoTrd1*>(shape)->GetDy();
1888
1889 #ifdef EDM_ML_DEBUG
1890
1891 printout(ns.context()->debug_placements ? ALWAYS : DEBUG,
1892 "DD4CMS",
1893 "+++ ...divide %s along %s (%d) with offset %6.3f cm and %6.3f cm to produce %d copies in %6.3f",
1894 parent.solid().type(),
1895 axis.c_str(),
1896 axesmap.at(axis),
1897 -dy + offset + width,
1898 width,
1899 nReplicas,
1900 dy);
1901
1902 #endif
1903
1904 Volume child = parent.divide(childName, static_cast<int>(axesmap.at(axis)), nReplicas, -dy + offset + width, width);
1905
1906 ns.context()->volumes[childName] = child;
1907
1908 #ifdef EDM_ML_DEBUG
1909
1910 printout(ns.context()->debug_placements ? ALWAYS : DEBUG,
1911 "DD4CMS",
1912 "+++ %s Parent: %-24s [%s] Child: %-32s [%s] is multivolume [%s]",
1913 e.tag().c_str(),
1914 parentName.c_str(),
1915 parent.isValid() ? "VALID" : "INVALID",
1916 child.name(),
1917 child.isValid() ? "VALID" : "INVALID",
1918 child->IsVolumeMulti() ? "YES" : "NO");
1919
1920 #endif
1921 } else {
1922 printout(ERROR, "DD4CMS", "++ FAILED Division of a %s is not implemented yet!", parent.solid().type());
1923 }
1924 }
1925
1926
1927 template <>
1928 void Converter<DDLAlgorithm>::operator()(xml_h element) const {
1929 cms::DDNamespace ns(_param<cms::DDParsingContext>());
1930 xml_dim_t e(element);
1931 string name = e.nameStr();
1932 size_t idx;
1933 string type = "DDCMS_" + ns.realName(name);
1934 while ((idx = type.find(NAMESPACE_SEP)) != string::npos)
1935 type[idx] = '_';
1936
1937 #ifdef EDM_ML_DEBUG
1938
1939 printout(
1940 ns.context()->debug_algorithms ? ALWAYS : DEBUG, "DD4CMS", "+++ Start executing algorithm %s....", type.c_str());
1941
1942 #endif
1943
1944 long ret = PluginService::Create<long>(type, &description, ns.context(), &element);
1945 if (ret == s_executed) {
1946 #ifdef EDM_ML_DEBUG
1947
1948 printout(ns.context()->debug_algorithms ? ALWAYS : DEBUG,
1949
1950 "DD4CMS",
1951 "+++ Executed algorithm: %08lX = %s",
1952 ret,
1953 name.c_str());
1954
1955 #endif
1956 return;
1957 }
1958 printout(ERROR, "DD4CMS", "++ FAILED NOT ADDING SUBDETECTOR %08lX = %s", ret, name.c_str());
1959 }
1960
1961 template <class InputIt, class ForwardIt, class BinOp>
1962 void for_each_token(InputIt first, InputIt last, ForwardIt s_first, ForwardIt s_last, BinOp binary_op) {
1963 while (first != last) {
1964 const auto pos = std::find_first_of(first, last, s_first, s_last);
1965 binary_op(first, pos);
1966 if (pos == last)
1967 break;
1968 first = std::next(pos);
1969 }
1970 }
1971
1972 namespace {
1973
1974 std::vector<string> splitString(const string& str, const string& delims = ",") {
1975 std::vector<string> output;
1976
1977 for_each_token(cbegin(str), cend(str), cbegin(delims), cend(delims), [&output](auto first, auto second) {
1978 if (first != second) {
1979 if (string(first, second).front() == '[' && string(first, second).back() == ']') {
1980 first++;
1981 second--;
1982 }
1983 output.emplace_back(string(first, second));
1984 }
1985 });
1986 return output;
1987 }
1988
1989 std::vector<double> splitNumeric(const string& str, const string& delims = ",") {
1990 std::vector<double> output;
1991
1992 for_each_token(cbegin(str), cend(str), cbegin(delims), cend(delims), [&output](auto first, auto second) {
1993 if (first != second) {
1994 if (string(first, second).front() == '[' && string(first, second).back() == ']') {
1995 first++;
1996 second--;
1997 }
1998 output.emplace_back(dd4hep::_toDouble(string(first, second)));
1999 }
2000 });
2001 return output;
2002 }
2003 }
2004
2005
2006
2007 template <>
2008 void Converter<DDLVector>::operator()(xml_h element) const {
2009 cms::DDNamespace ns(_param<cms::DDParsingContext>());
2010 cms::DDParsingContext* const context = ns.context();
2011 DDVectorsMap* registry = context->description.extension<DDVectorsMap>();
2012 xml_dim_t e(element);
2013 string name = ns.prepend(e.nameStr());
2014 string type = ns.attr<string>(e, _U(type));
2015 string nEntries = ns.attr<string>(e, DD_CMU(nEntries));
2016 string val = e.text();
2017 val.erase(remove_if(val.begin(), val.end(), [](unsigned char x) { return isspace(x); }), val.end());
2018
2019 #ifdef EDM_ML_DEBUG
2020
2021 printout(ns.context()->debug_constants ? ALWAYS : DEBUG,
2022 "DD4CMS",
2023 "+++ Vector<%s>: %s[%s]: %s",
2024 type.c_str(),
2025 name.c_str(),
2026 nEntries.c_str(),
2027 val.c_str());
2028
2029 #endif
2030
2031 try {
2032 std::vector<double> results = splitNumeric(val);
2033 registry->insert(
2034 {name,
2035 results});
2036 } catch (const exception& e) {
2037 #ifdef EDM_ML_DEBUG
2038
2039 printout(INFO,
2040 "DD4CMS",
2041 "++ Unresolved Vector<%s>: %s[%s]: %s. Try to resolve later. [%s]",
2042 type.c_str(),
2043 name.c_str(),
2044 nEntries.c_str(),
2045 val.c_str(),
2046 e.what());
2047
2048 #endif
2049
2050 std::vector<string> results = splitString(val);
2051 context->unresolvedVectors.insert({name, results});
2052 }
2053 }
2054
2055 template <>
2056 void Converter<debug>::operator()(xml_h dbg) const {
2057 cms::DDNamespace ns(_param<cms::DDParsingContext>());
2058 if (dbg.hasChild(DD_CMU(debug_constants)))
2059 ns.setContext()->debug_constants = true;
2060 if (dbg.hasChild(DD_CMU(debug_materials)))
2061 ns.setContext()->debug_materials = true;
2062 if (dbg.hasChild(DD_CMU(debug_rotations)))
2063 ns.setContext()->debug_rotations = true;
2064 if (dbg.hasChild(DD_CMU(debug_shapes)))
2065 ns.setContext()->debug_shapes = true;
2066 if (dbg.hasChild(DD_CMU(debug_volumes)))
2067 ns.setContext()->debug_volumes = true;
2068 if (dbg.hasChild(DD_CMU(debug_placements)))
2069 ns.setContext()->debug_placements = true;
2070 if (dbg.hasChild(DD_CMU(debug_namespaces)))
2071 ns.setContext()->debug_namespaces = true;
2072 if (dbg.hasChild(DD_CMU(debug_includes)))
2073 ns.setContext()->debug_includes = true;
2074 if (dbg.hasChild(DD_CMU(debug_algorithms)))
2075 ns.setContext()->debug_algorithms = true;
2076 if (dbg.hasChild(DD_CMU(debug_specpars)))
2077 ns.setContext()->debug_specpars = true;
2078 }
2079
2080 template <>
2081 void Converter<DDRegistry>::operator()(xml_h ) const {
2082 cms::DDParsingContext* context = _param<cms::DDParsingContext>();
2083 DDRegistry* res = _option<DDRegistry>();
2084 cms::DDNamespace ns(context);
2085 int count = 0;
2086
2087 #ifdef EDM_ML_DEBUG
2088
2089 printout(context->debug_constants ? ALWAYS : DEBUG,
2090 "DD4CMS",
2091 "+++ RESOLVING %ld unknown constants..... (out of %ld)",
2092 res->unresolvedConst.size(),
2093 res->originalConst.size());
2094 #endif
2095
2096 while (!res->unresolvedConst.empty()) {
2097 for (auto& i : res->unresolvedConst) {
2098 const string& n = i.first;
2099 string rep;
2100 string& v = i.second;
2101 size_t idx, idq;
2102 for (idx = v.find('[', 0); idx != string::npos; idx = v.find('[', idx + 1)) {
2103 idq = v.find(']', idx + 1);
2104 rep = v.substr(idx + 1, idq - idx - 1);
2105 auto r = res->originalConst.find(rep);
2106 if (r != res->originalConst.end()) {
2107 rep = "(" + (*r).second + ")";
2108 v.replace(idx, idq - idx + 1, rep);
2109 }
2110 }
2111 if (v.find(']') == string::npos) {
2112 if (v.find("-+") != string::npos || v.find("+-") != string::npos) {
2113 while ((idx = v.find("-+")) != string::npos)
2114 v.replace(idx, 2, "-");
2115 while ((idx = v.find("+-")) != string::npos)
2116 v.replace(idx, 2, "-");
2117 }
2118
2119 #ifdef EDM_ML_DEBUG
2120
2121 printout(context->debug_constants ? ALWAYS : DEBUG,
2122 "DD4CMS",
2123 "+++ [%06ld] ---------- %-40s = %s",
2124 res->unresolvedConst.size() - 1,
2125 n.c_str(),
2126 res->originalConst[n].c_str());
2127
2128 #endif
2129
2130 ns.addConstantNS(n, v, "number");
2131 res->unresolvedConst.erase(n);
2132 break;
2133 }
2134 }
2135 if (++count > 10000)
2136 break;
2137 }
2138 if (!res->unresolvedConst.empty()) {
2139 for (const auto& e : res->unresolvedConst)
2140 printout(ERROR, "DD4CMS", "+++ Unresolved constant: %-40s = %s.", e.first.c_str(), e.second.c_str());
2141 except("DD4CMS", "++ FAILED to resolve %ld constant entries:", res->unresolvedConst.size());
2142 }
2143 res->unresolvedConst.clear();
2144 res->originalConst.clear();
2145 }
2146
2147 template <>
2148 void Converter<print_xml_doc>::operator()(xml_h element) const {
2149 string fname = xml::DocumentHandler::system_path(element);
2150
2151 #ifdef EDM_ML_DEBUG
2152
2153 printout(_param<cms::DDParsingContext>()->debug_includes ? ALWAYS : DEBUG,
2154 "DD4CMS",
2155 "+++ Processing data from: %s",
2156 fname.c_str());
2157
2158 #endif
2159 }
2160
2161
2162 static long load_dddefinition(Detector& det, xml_h element) {
2163 xml_elt_t dddef(element);
2164 if (dddef) {
2165 cms::DDParsingContext& context = *det.extension<DDParsingContext>();
2166 cms::DDNamespace ns(context);
2167 ns.addConstantNS("world_x", "101*m", "number");
2168 ns.addConstantNS("world_y", "101*m", "number");
2169 ns.addConstantNS("world_z", "450*m", "number");
2170 ns.addConstantNS("Air", "materials:Air", "string");
2171 ns.addConstantNS("Vacuum", "materials:Vacuum", "string");
2172
2173 string fname = xml::DocumentHandler::system_path(element);
2174 bool open_geometry = dddef.hasChild(DD_CMU(open_geometry)) ? dddef.child(DD_CMU(open_geometry)) : true;
2175 bool close_geometry = dddef.hasChild(DD_CMU(close_geometry)) ? dddef.hasChild(DD_CMU(close_geometry)) : true;
2176
2177 xml_coll_t(dddef, _U(debug)).for_each(Converter<debug>(det, &context));
2178
2179
2180
2181
2182 printout(INFO, "DD4CMS", "+++ Processing the CMS detector description %s", fname.c_str());
2183
2184 xml::Document doc;
2185 Converter<print_xml_doc> print_doc(det, &context);
2186 try {
2187 DDRegistry res;
2188 res.unresolvedConst.reserve(2000);
2189 res.originalConst.reserve(6000);
2190 print_doc((doc = dddef.document()).root());
2191 xml_coll_t(dddef, DD_CMU(ConstantsSection)).for_each(Converter<ConstantsSection>(det, &context, &res));
2192 xml_coll_t(dddef, DD_CMU(RotationSection)).for_each(Converter<RotationSection>(det, &context));
2193 xml_coll_t(dddef, DD_CMU(MaterialSection)).for_each(Converter<MaterialSection>(det, &context));
2194
2195 xml_coll_t(dddef, DD_CMU(IncludeSection)).for_each(DD_CMU(Include), Converter<include_load>(det, &context, &res));
2196
2197 for (xml::Document d : res.includes) {
2198 print_doc((doc = d).root());
2199 Converter<include_constants>(det, &context, &res)((doc = d).root());
2200 }
2201
2202 Converter<DDRegistry>(det, &context, &res)(dddef);
2203 {
2204 DDVectorsMap* registry = context.description.extension<DDVectorsMap>();
2205
2206 printout(context.debug_constants ? ALWAYS : DEBUG,
2207 "DD4CMS",
2208 "+++ RESOLVING %ld Vectors.....",
2209 context.unresolvedVectors.size());
2210
2211 while (!context.unresolvedVectors.empty()) {
2212 for (auto it = context.unresolvedVectors.begin(); it != context.unresolvedVectors.end();) {
2213 std::vector<double> result;
2214 for (const auto& i : it->second) {
2215 result.emplace_back(dd4hep::_toDouble(i));
2216 }
2217 registry->insert({it->first, result});
2218
2219 it = context.unresolvedVectors.erase(it);
2220 }
2221 }
2222 }
2223
2224 for (xml::Document d : res.includes) {
2225 print_doc((doc = d).root());
2226 xml_coll_t(d.root(), DD_CMU(MaterialSection)).for_each(Converter<MaterialSection>(det, &context));
2227 }
2228 if (open_geometry) {
2229 det.init();
2230 ns.addVolume(det.worldVolume());
2231 }
2232 for (xml::Document d : res.includes) {
2233 print_doc((doc = d).root());
2234 xml_coll_t(d.root(), DD_CMU(RotationSection)).for_each(Converter<RotationSection>(det, &context));
2235 }
2236 for (xml::Document d : res.includes) {
2237 print_doc((doc = d).root());
2238 xml_coll_t(d.root(), DD_CMU(SolidSection)).for_each(Converter<SolidSection>(det, &context));
2239 }
2240 for (xml::Document d : res.includes) {
2241 print_doc((doc = d).root());
2242 xml_coll_t(d.root(), DD_CMU(LogicalPartSection)).for_each(Converter<LogicalPartSection>(det, &context));
2243 }
2244 for (xml::Document d : res.includes) {
2245 print_doc((doc = d).root());
2246 xml_coll_t(d.root(), DD_CMU(Algorithm)).for_each(Converter<DDLAlgorithm>(det, &context));
2247 }
2248 for (xml::Document d : res.includes) {
2249 print_doc((doc = d).root());
2250 xml_coll_t(d.root(), DD_CMU(PosPartSection)).for_each(Converter<PosPartSection>(det, &context));
2251 }
2252 for (xml::Document d : res.includes) {
2253 print_doc((doc = d).root());
2254 xml_coll_t(d.root(), DD_CMU(SpecParSection)).for_each(Converter<SpecParSection>(det, &context));
2255 }
2256
2257
2258 for (xml::Document d : res.includes)
2259 Converter<include_unload>(det, &context, &res)(d.root());
2260
2261 print_doc((doc = dddef.document()).root());
2262
2263 xml_coll_t(dddef, DD_CMU(SolidSection)).for_each(Converter<SolidSection>(det, &context));
2264 {
2265
2266
2267
2268
2269
2270 while (!context.unresolvedShapes.empty()) {
2271 for (auto it = context.unresolvedShapes.begin(); it != context.unresolvedShapes.end();) {
2272 auto const& name = it->first;
2273 auto const& aname = std::visit([](auto&& arg) -> std::string { return arg.firstSolidName; }, it->second);
2274 auto const& bname = std::visit([](auto&& arg) -> std::string { return arg.secondSolidName; }, it->second);
2275
2276 auto const& ait = context.shapes.find(aname);
2277 if (ait->second.isValid()) {
2278 auto const& bit = context.shapes.find(bname);
2279 if (bit->second.isValid()) {
2280 dd4hep::Solid shape =
2281 std::visit([&ait, &bit](auto&& arg) -> dd4hep::Solid { return arg.make(ait->second, bit->second); },
2282 it->second);
2283 context.shapes[name] = shape;
2284 it = context.unresolvedShapes.erase(it);
2285 } else
2286 ++it;
2287 } else
2288 ++it;
2289 }
2290 }
2291 }
2292 xml_coll_t(dddef, DD_CMU(LogicalPartSection)).for_each(Converter<LogicalPartSection>(det, &context));
2293 xml_coll_t(dddef, DD_CMU(Algorithm)).for_each(Converter<DDLAlgorithm>(det, &context));
2294 xml_coll_t(dddef, DD_CMU(PosPartSection)).for_each(Converter<PosPartSection>(det, &context));
2295 xml_coll_t(dddef, DD_CMU(SpecParSection)).for_each(Converter<SpecParSection>(det, &context));
2296 } catch (const exception& e) {
2297 printout(ERROR, "DD4CMS", "Exception while processing xml source:%s", doc.uri().c_str());
2298 printout(ERROR, "DD4CMS", "----> %s", e.what());
2299 throw;
2300 }
2301
2302
2303 if (close_geometry) {
2304 Volume wv = det.worldVolume();
2305 Volume geomv = ns.volume("cms:OCMS", false);
2306 if (geomv.isValid())
2307 wv.placeVolume(geomv, 1);
2308 Volume mfv = ns.volume("cmsMagneticField:MAGF", false);
2309 if (mfv.isValid())
2310 wv.placeVolume(mfv, 1);
2311 Volume mfv1 = ns.volume("MagneticFieldVolumes:MAGF", false);
2312 if (mfv1.isValid())
2313 wv.placeVolume(mfv1, 1);
2314
2315
2316 det.manager().CloseGeometry("nv");
2317
2318 det.endDocument();
2319 }
2320 printout(INFO, "DDDefinition", "+++ Finished processing %s", fname.c_str());
2321 return 1;
2322 }
2323 except("DDDefinition", "+++ FAILED to process unknown DOM tree [Invalid Handle]");
2324 return 0;
2325 }
2326
2327
2328 DECLARE_XML_DOC_READER(DDDefinition, load_dddefinition)