CMS 3D CMS Logo

DDDefinitions2Objects.cc
Go to the documentation of this file.
1 #include "DD4hep/DetFactoryHelper.h"
2 #include "DD4hep/DetectorHelper.h"
3 #include "DD4hep/DD4hepUnits.h"
4 #include "DD4hep/GeoHandler.h"
5 #include "DD4hep/Printout.h"
6 #include "DD4hep/Plugins.h"
7 #include "DD4hep/detail/SegmentationsInterna.h"
8 #include "DD4hep/detail/DetectorInterna.h"
9 #include "DD4hep/detail/ObjectsInterna.h"
10 #include "DD4hep/MatrixHelpers.h"
11 
12 #include "XML/Utilities.h"
20 
21 #include "TGeoManager.h"
22 #include "TGeoMaterial.h"
23 
24 #include <climits>
25 #include <iostream>
26 #include <iomanip>
27 #include <map>
28 #include <vector>
29 #include <unordered_map>
30 #include <utility>
31 
32 // #define EDM_ML_DEBUG 1
33 
34 using namespace std;
35 using namespace dd4hep;
36 using namespace cms;
37 using namespace cms_units::operators;
38 
39 namespace dd4hep {
40 
41  namespace {
42 
43  atomic<UInt_t> unique_mat_id = 0xAFFEFEED;
44 
45  class include_constants;
46  class include_load;
47  class include_unload;
48  class print_xml_doc;
49 
50  class ConstantsSection;
51  class DDLConstant;
52 
53  struct DDRegistry {
54  std::vector<xml::Document> includes;
55  std::unordered_map<std::string, std::string> unresolvedConst;
56  std::unordered_map<std::string, std::string> originalConst;
57  };
58 
59  class MaterialSection;
62 
63  class RotationSection;
64  class DDLRotation;
65  class DDLReflectionRotation;
66  class DDLRotationSequence;
67  class DDLRotationByAxis;
68  class DDLTransform3D;
69 
70  class PosPartSection;
71  class DDLPosPart;
72  class DDLDivision;
73 
74  class LogicalPartSection;
75  class DDLLogicalPart;
76 
77  class SolidSection;
78  class DDLExtrudedPolygon;
79  class DDLShapeless;
80  class DDLAssembly;
81  class DDLTrapezoid;
82  class DDLEllipticalTube;
83  class DDLPseudoTrap;
84  class DDLPolyhedra;
85  class DDLPolycone;
86  class DDLTorus;
87  class DDLTrd1;
88  class DDLTrd2;
89  class DDLTruncTubs;
90  class DDLCutTubs;
91  class DDLTubs;
92  class DDLBox;
93  class DDLCone;
94  class DDLSphere;
95  class DDLUnionSolid;
96  class DDLIntersectionSolid;
97  class DDLSubtractionSolid;
98 
99  class DDLAlgorithm;
100  class DDLVector;
101 
102  class SpecParSection;
103  class DDLSpecPar;
104  class PartSelector;
105  class Parameter;
106 
107  class debug;
108  } // namespace
109 
110  TGeoCombiTrans* createPlacement(const Rotation3D& iRot, const Position& iTrans) {
111  double elements[9];
112  iRot.GetComponents(elements);
113  TGeoRotation r;
114  r.SetMatrix(elements);
115 
116  TGeoTranslation t(iTrans.x(), iTrans.y(), iTrans.z());
117 
118  return new TGeoCombiTrans(t, r);
119  }
120 
122  template <>
123  void Converter<debug>::operator()(xml_h element) const;
124  template <>
125  void Converter<print_xml_doc>::operator()(xml_h element) const;
126 
128  template <>
129  void Converter<ConstantsSection>::operator()(xml_h element) const;
130  template <>
131  void Converter<DDLConstant>::operator()(xml_h element) const;
132  template <>
133  void Converter<DDRegistry>::operator()(xml_h element) const;
134 
136  template <>
137  void Converter<MaterialSection>::operator()(xml_h element) const;
138  template <>
139  void Converter<DDLElementaryMaterial>::operator()(xml_h element) const;
140  template <>
141  void Converter<DDLCompositeMaterial>::operator()(xml_h element) const;
142 
144  template <>
145  void Converter<RotationSection>::operator()(xml_h element) const;
147  template <>
148  void Converter<DDLRotation>::operator()(xml_h element) const;
150  template <>
151  void Converter<DDLReflectionRotation>::operator()(xml_h element) const;
153  template <>
154  void Converter<DDLRotationSequence>::operator()(xml_h element) const;
156  template <>
157  void Converter<DDLRotationByAxis>::operator()(xml_h element) const;
158  template <>
159  void Converter<DDLTransform3D>::operator()(xml_h element) const;
160 
162  template <>
163  void Converter<LogicalPartSection>::operator()(xml_h element) const;
164  template <>
165  void Converter<DDLLogicalPart>::operator()(xml_h element) const;
166 
168  template <>
169  void Converter<PosPartSection>::operator()(xml_h element) const;
171  template <>
172  void Converter<DDLPosPart>::operator()(xml_h element) const;
174  template <>
175  void Converter<DDLDivision>::operator()(xml_h element) const;
176 
178  template <>
179  void Converter<SpecParSection>::operator()(xml_h element) const;
180  template <>
181  void Converter<DDLSpecPar>::operator()(xml_h element) const;
182  template <>
183  void Converter<PartSelector>::operator()(xml_h element) const;
184  template <>
185  void Converter<Parameter>::operator()(xml_h element) const;
186 
188  template <>
189  void Converter<SolidSection>::operator()(xml_h element) const;
191  template <>
192  void Converter<DDLUnionSolid>::operator()(xml_h element) const;
194  template <>
195  void Converter<DDLSubtractionSolid>::operator()(xml_h element) const;
197  template <>
198  void Converter<DDLIntersectionSolid>::operator()(xml_h element) const;
200  template <>
201  void Converter<DDLPseudoTrap>::operator()(xml_h element) const;
203  template <>
204  void Converter<DDLExtrudedPolygon>::operator()(xml_h element) const;
206  template <>
207  void Converter<DDLShapeless>::operator()(xml_h element) const;
209  template <>
210  void Converter<DDLAssembly>::operator()(xml_h element) const;
212  template <>
213  void Converter<DDLTrapezoid>::operator()(xml_h element) const;
215  template <>
216  void Converter<DDLPolycone>::operator()(xml_h element) const;
218  template <>
219  void Converter<DDLPolyhedra>::operator()(xml_h element) const;
221  template <>
222  void Converter<DDLEllipticalTube>::operator()(xml_h element) const;
224  template <>
225  void Converter<DDLTorus>::operator()(xml_h element) const;
227  template <>
228  void Converter<DDLTubs>::operator()(xml_h element) const;
230  template <>
231  void Converter<DDLCutTubs>::operator()(xml_h element) const;
233  template <>
234  void Converter<DDLTruncTubs>::operator()(xml_h element) const;
236  template <>
237  void Converter<DDLSphere>::operator()(xml_h element) const;
239  template <>
240  void Converter<DDLTrd1>::operator()(xml_h element) const;
242  template <>
243  void Converter<DDLTrd2>::operator()(xml_h element) const;
245  template <>
246  void Converter<DDLCone>::operator()(xml_h element) const;
248  template <>
249  void Converter<DDLBox>::operator()(xml_h element) const;
251  template <>
252  void Converter<DDLAlgorithm>::operator()(xml_h element) const;
254  template <>
255  void Converter<DDLVector>::operator()(xml_h element) const;
256 
258  template <>
259  void Converter<include_load>::operator()(xml_h element) const;
261  template <>
262  void Converter<include_unload>::operator()(xml_h element) const;
264  template <>
265  void Converter<include_constants>::operator()(xml_h element) const;
266 } // namespace dd4hep
267 
269 template <>
270 void Converter<ConstantsSection>::operator()(xml_h element) const {
271  cms::DDNamespace ns(_param<cms::DDParsingContext>(), element);
272  cms::DDParsingContext* const context = ns.context();
273  xml_coll_t(element, DD_CMU(Constant)).for_each(Converter<DDLConstant>(description, context, optional));
274  xml_coll_t(element, DD_CMU(Vector)).for_each(Converter<DDLVector>(description, context, optional));
275 }
276 
278 template <>
279 void Converter<MaterialSection>::operator()(xml_h element) const {
280  cms::DDNamespace ns(_param<cms::DDParsingContext>(), element);
281  xml_coll_t(element, DD_CMU(ElementaryMaterial))
282  .for_each(Converter<DDLElementaryMaterial>(description, ns.context(), optional));
283  xml_coll_t(element, DD_CMU(CompositeMaterial))
284  .for_each(Converter<DDLCompositeMaterial>(description, ns.context(), optional));
285 }
286 
287 template <>
288 void Converter<RotationSection>::operator()(xml_h element) const {
289  cms::DDNamespace ns(_param<cms::DDParsingContext>(), element);
290  xml_coll_t(element, DD_CMU(Rotation)).for_each(Converter<DDLRotation>(description, ns.context(), optional));
291  xml_coll_t(element, DD_CMU(ReflectionRotation))
292  .for_each(Converter<DDLReflectionRotation>(description, ns.context(), optional));
293  xml_coll_t(element, DD_CMU(RotationSequence))
294  .for_each(Converter<DDLRotationSequence>(description, ns.context(), optional));
295  xml_coll_t(element, DD_CMU(RotationByAxis))
296  .for_each(Converter<DDLRotationByAxis>(description, ns.context(), optional));
297 }
298 
299 template <>
300 void Converter<PosPartSection>::operator()(xml_h element) const {
301  cms::DDNamespace ns(_param<cms::DDParsingContext>(), element);
302  xml_coll_t(element, DD_CMU(Division)).for_each(Converter<DDLDivision>(description, ns.context(), optional));
303  xml_coll_t(element, DD_CMU(PosPart)).for_each(Converter<DDLPosPart>(description, ns.context(), optional));
304  xml_coll_t(element, DD_CMU(Algorithm)).for_each(Converter<DDLAlgorithm>(description, ns.context(), optional));
305 }
306 
307 template <>
308 void Converter<SpecParSection>::operator()(xml_h element) const {
309  cms::DDNamespace ns(_param<cms::DDParsingContext>(), element);
310  xml_coll_t(element, DD_CMU(SpecPar)).for_each(Converter<DDLSpecPar>(description, ns.context(), optional));
311 }
312 
313 template <>
314 void Converter<DDLSpecPar>::operator()(xml_h element) const {
315  cms::DDNamespace ns(_param<cms::DDParsingContext>(), element);
316  xml_coll_t(element, DD_CMU(PartSelector)).for_each(Converter<PartSelector>(description, ns.context(), optional));
317  xml_coll_t(element, DD_CMU(Parameter)).for_each(Converter<Parameter>(description, ns.context(), optional));
318 }
319 
321 template <>
322 void Converter<LogicalPartSection>::operator()(xml_h element) const {
323  cms::DDNamespace ns(_param<cms::DDParsingContext>(), element);
324  xml_coll_t(element, DD_CMU(LogicalPart)).for_each(Converter<DDLLogicalPart>(description, ns.context(), optional));
325 }
326 
328 template <>
329 void Converter<SolidSection>::operator()(xml_h element) const {
330  cms::DDNamespace ns(_param<cms::DDParsingContext>(), element);
331  for (xml_coll_t solid(element, _U(star)); solid; ++solid) {
332  using cms::hash;
333  switch (hash(solid.tag())) {
334  case hash("Box"):
335  Converter<DDLBox>(description, ns.context(), optional)(solid);
336  break;
337  case hash("Polycone"):
338  Converter<DDLPolycone>(description, ns.context(), optional)(solid);
339  break;
340  case hash("Polyhedra"):
341  Converter<DDLPolyhedra>(description, ns.context(), optional)(solid);
342  break;
343  case hash("Tubs"):
344  Converter<DDLTubs>(description, ns.context(), optional)(solid);
345  break;
346  case hash("CutTubs"):
347  Converter<DDLCutTubs>(description, ns.context(), optional)(solid);
348  break;
349  case hash("TruncTubs"):
350  Converter<DDLTruncTubs>(description, ns.context(), optional)(solid);
351  break;
352  case hash("Tube"):
353  Converter<DDLTubs>(description, ns.context(), optional)(solid);
354  break;
355  case hash("Trd1"):
356  Converter<DDLTrd1>(description, ns.context(), optional)(solid);
357  break;
358  case hash("Trd2"):
359  Converter<DDLTrd2>(description, ns.context(), optional)(solid);
360  break;
361  case hash("Cone"):
362  Converter<DDLCone>(description, ns.context(), optional)(solid);
363  break;
364  case hash("Sphere"):
365  Converter<DDLSphere>(description, ns.context(), optional)(solid);
366  break;
367  case hash("EllipticalTube"):
368  Converter<DDLEllipticalTube>(description, ns.context(), optional)(solid);
369  break;
370  case hash("Torus"):
371  Converter<DDLTorus>(description, ns.context(), optional)(solid);
372  break;
373  case hash("PseudoTrap"):
374  Converter<DDLPseudoTrap>(description, ns.context(), optional)(solid);
375  break;
376  case hash("ExtrudedPolygon"):
377  Converter<DDLExtrudedPolygon>(description, ns.context(), optional)(solid);
378  break;
379  case hash("Trapezoid"):
380  Converter<DDLTrapezoid>(description, ns.context(), optional)(solid);
381  break;
382  case hash("UnionSolid"):
383  Converter<DDLUnionSolid>(description, ns.context(), optional)(solid);
384  break;
385  case hash("SubtractionSolid"):
386  Converter<DDLSubtractionSolid>(description, ns.context(), optional)(solid);
387  break;
388  case hash("IntersectionSolid"):
389  Converter<DDLIntersectionSolid>(description, ns.context(), optional)(solid);
390  break;
391  case hash("ShapelessSolid"):
392  Converter<DDLShapeless>(description, ns.context(), optional)(solid);
393  break;
394  case hash("Assembly"):
395  Converter<DDLAssembly>(description, ns.context(), optional)(solid);
396  break;
397  default:
398  throw std::runtime_error("Request to process unknown shape '" + xml_dim_t(solid).nameStr() + "' [" +
399  solid.tag() + "]");
400  break;
401  }
402  }
403 }
404 
406 template <>
407 void Converter<DDLConstant>::operator()(xml_h element) const {
408  cms::DDNamespace ns(_param<cms::DDParsingContext>());
409  DDRegistry* res = _option<DDRegistry>();
410  xml_dim_t constant = element;
411  xml_dim_t par = constant.parent();
412  bool eval = par.hasAttr(_U(eval)) ? par.attr<bool>(_U(eval)) : true;
413  string val = constant.valueStr();
414  string nam = constant.nameStr();
415  string real = ns.prepend(nam);
416  string typ = eval ? "number" : "string";
417  size_t idx = val.find('[');
418 
419  if (constant.hasAttr(_U(type)))
420  typ = constant.typeStr();
421 
422  if (idx == string::npos || typ == "string") {
423  try {
424  ns.addConstant(nam, val, typ);
425  res->originalConst[real] = val;
426  } catch (const exception& e) {
427 #ifdef EDM_ML_DEBUG
428 
429  printout(INFO,
430  "DD4CMS",
431  "++ Unresolved constant: %s = %s [%s]. Try to resolve later. [%s]",
432  real.c_str(),
433  val.c_str(),
434  typ.c_str(),
435  e.what());
436 #endif
437  }
438  return;
439  }
440  // Setup the resolution mechanism in Converter<resolve>
441  while (idx != string::npos) {
442  ++idx;
443  size_t idp = val.find(':', idx);
444  size_t idq = val.find(']', idx);
445  if (idp == string::npos || idp > idq)
446  val.insert(idx, ns.name());
447  else if (idp != string::npos && idp < idq)
448  val[idp] = NAMESPACE_SEP;
449  idx = val.find('[', idx);
450  }
451 
452 #ifdef EDM_ML_DEBUG
453 
454  printout(
455  ns.context()->debug_constants ? ALWAYS : DEBUG, "Constant", "Unresolved: %s -> %s", real.c_str(), val.c_str());
456 
457 #endif
458 
459  res->originalConst[real] = val;
460  res->unresolvedConst[real] = val;
461 }
462 
464 template <>
465 void Converter<DDLElementaryMaterial>::operator()(xml_h element) const {
466  cms::DDNamespace ns(_param<cms::DDParsingContext>());
467  xml_dim_t xmat(element);
468  string nam = ns.prepend(xmat.nameStr());
469  TGeoManager& mgr = description.manager();
470  TGeoMaterial* mat = mgr.GetMaterial(nam.c_str());
471  if (nullptr == mat) {
472  const char* matname = nam.c_str();
473  double density = xmat.attr<double>(DD_CMU(density)) / (dd4hep::g / dd4hep::cm3);
474  int atomicNumber = xmat.attr<int>(DD_CMU(atomicNumber));
475  double atomicWeight = xmat.attr<double>(DD_CMU(atomicWeight)) / (dd4hep::g / dd4hep::mole);
476  TGeoElementTable* tab = mgr.GetElementTable();
477  int nElem = tab->GetNelements();
478 
479 #ifdef EDM_ML_DEBUG
480 
481  printout(ns.context()->debug_materials ? ALWAYS : DEBUG, "DD4CMS", "+++ Element table size = %d", nElem);
482 
483 #endif
484 
485  if (nElem <= 1) { // Restore the element table DD4hep destroyed.
486  tab->TGeoElementTable::~TGeoElementTable();
487  new (tab) TGeoElementTable();
488  tab->BuildDefaultElements();
489  }
490  TGeoMixture* mix = new TGeoMixture(nam.c_str(), 1, density);
491  TGeoElement* elt = tab->FindElement(xmat.nameStr().c_str());
492 
493 #ifdef EDM_ML_DEBUG
494 
495  printout(ns.context()->debug_materials ? ALWAYS : DEBUG,
496  "DD4CMS",
497  "+++ Searching for material %-48s elt_ptr = %ld",
498  xmat.nameStr().c_str(),
499  elt);
500 
501  printout(ns.context()->debug_materials ? ALWAYS : DEBUG,
502  "DD4CMS",
503  "+++ Converting material %-48s Atomic weight %8.3f [g/mol], Atomic number %u, Density: %8.3f [g/cm3] "
504  "ROOT: %8.3f [g/cm3]",
505  ('"' + nam + '"').c_str(),
506  atomicWeight,
507  atomicNumber,
508  density,
509  mix->GetDensity());
510 
511 #endif
512 
513  bool newMatDef = false;
514 
515  if (elt) {
516  // A is Mass of a mole in Geant4 units for atoms with atomic shell
517 
518 #ifdef EDM_ML_DEBUG
519 
520  printout(ns.context()->debug_materials ? ALWAYS : DEBUG,
521  "DD4CMS",
522  " ROOT definition of %-50s Atomic weight %g, Atomic number %u, Number of nucleons %u",
523  elt->GetName(),
524  elt->A(),
525  elt->Z(),
526  elt->N());
527  printout(ns.context()->debug_materials ? ALWAYS : DEBUG,
528  "DD4CMS",
529  "+++ Compared to XML values: Atomic weight %g, Atomic number %u",
530  atomicWeight,
531  atomicNumber);
532 #endif
533 
534  static constexpr double const weightTolerance = 1.0e-6;
535  if (atomicNumber != elt->Z() ||
536  (std::abs(atomicWeight - elt->A()) > (weightTolerance * (atomicWeight + elt->A()))))
537  newMatDef = true;
538  }
539 
540  if (!elt || newMatDef) {
541  if (newMatDef) {
542 #ifdef EDM_ML_DEBUG
543 
544  printout(ns.context()->debug_materials ? ALWAYS : DEBUG,
545  "DD4CMS Warning",
546  "+++ Converter<ElementaryMaterial> Different definition of a default element with name:%s [CREATE NEW "
547  "MATERIAL]",
548  matname);
549 
550 #endif
551 
552  } else {
553 #ifdef EDM_ML_DEBUG
554 
555  printout(ns.context()->debug_materials ? ALWAYS : DEBUG,
556  "DD4CMS Warning",
557  "+++ Converter<ElementaryMaterial> No default element present with name:%s [CREATE NEW MATERIAL]",
558  matname);
559 
560 #endif
561  }
562  elt = new TGeoElement(xmat.nameStr().c_str(), "CMS element", atomicNumber, atomicWeight);
563  }
564 
565  mix->AddElement(elt, 1.0);
566  mix->SetTemperature(ns.context()->description.stdConditions().temperature);
567  mix->SetPressure(ns.context()->description.stdConditions().pressure);
568 
570  TGeoMedium* medium = mgr.GetMedium(matname);
571  if (nullptr == medium) {
572  --unique_mat_id;
573  medium = new TGeoMedium(matname, unique_mat_id, mix);
574  medium->SetTitle("material");
575  medium->SetUniqueID(unique_mat_id);
576  }
577  }
578 }
579 
581 template <>
582 void Converter<DDLCompositeMaterial>::operator()(xml_h element) const {
583  cms::DDNamespace ns(_param<cms::DDParsingContext>());
584  xml_dim_t xmat(element);
585  string nam = ns.prepend(xmat.nameStr());
586 
587  TGeoManager& mgr = description.manager();
588  TGeoMaterial* mat = mgr.GetMaterial(nam.c_str());
589  if (nullptr == mat) {
590  const char* matname = nam.c_str();
591  double density = xmat.attr<double>(DD_CMU(density)) / (dd4hep::g / dd4hep::cm3);
592  xml_coll_t composites(xmat, DD_CMU(MaterialFraction));
593  TGeoMixture* mix = new TGeoMixture(nam.c_str(), composites.size(), density);
594 
595 #ifdef EDM_ML_DEBUG
596 
597  printout(ns.context()->debug_materials ? ALWAYS : DEBUG,
598  "DD4CMS",
599  "++ Converting material %-48s Density: %8.3f [g/cm3] ROOT: %8.3f [g/cm3]",
600  ('"' + nam + '"').c_str(),
601  density,
602  mix->GetDensity());
603 
604 #endif
605 
606  if (ns.context()->makePayload) {
607  ns.context()->compMaterialsVec.emplace_back(std::make_pair(nam, density));
608  }
609  for (composites.reset(); composites; ++composites) {
610  xml_dim_t xfrac(composites);
611  xml_dim_t xfrac_mat(xfrac.child(DD_CMU(rMaterial)));
612  double fraction = xfrac.fraction();
613  string fracname = ns.realName(xfrac_mat.nameStr());
614 
615  if (ns.context()->makePayload) {
616  ns.context()->compMaterialsRefs[nam].emplace_back(
617  cms::DDParsingContext::CompositeMaterial(ns.prepend(fracname), fraction));
618  }
619  TGeoMaterial* frac_mat = mgr.GetMaterial(fracname.c_str());
620  if (frac_mat == nullptr) // Try to find it within this namespace
621  frac_mat = mgr.GetMaterial(ns.prepend(fracname).c_str());
622  if (frac_mat) {
623  mix->AddElement(frac_mat, fraction);
624  continue;
625  }
626 
627 #ifdef EDM_ML_DEBUG
628 
629  printout(ns.context()->debug_materials ? ALWAYS : DEBUG,
630  "DD4CMS Warning",
631  "+++ Composite material \"%s\" [nor \"%s\"] not present! [delay resolution]",
632  fracname.c_str(),
633  ns.prepend(fracname).c_str());
634 
635 #endif
636 
637  ns.context()->unresolvedMaterials[nam].emplace_back(
638  cms::DDParsingContext::CompositeMaterial(ns.prepend(fracname), fraction));
639  }
640  mix->SetTemperature(ns.context()->description.stdConditions().temperature);
641  mix->SetPressure(ns.context()->description.stdConditions().pressure);
642  mix->SetRadLen(0e0);
644  TGeoMedium* medium = mgr.GetMedium(matname);
645  if (nullptr == medium) {
646  --unique_mat_id;
647  medium = new TGeoMedium(matname, unique_mat_id, mix);
648  medium->SetTitle("material");
649  medium->SetUniqueID(unique_mat_id);
650  }
651  }
652 }
653 
655 template <>
656 void Converter<DDLRotation>::operator()(xml_h element) const {
657  cms::DDParsingContext* context = _param<cms::DDParsingContext>();
659  xml_dim_t xrot(element);
660  string nam = xrot.nameStr();
661  double thetaX = xrot.hasAttr(DD_CMU(thetaX)) ? ns.attr<double>(xrot, DD_CMU(thetaX)) : 0e0;
662  double phiX = xrot.hasAttr(DD_CMU(phiX)) ? ns.attr<double>(xrot, DD_CMU(phiX)) : 0e0;
663  double thetaY = xrot.hasAttr(DD_CMU(thetaY)) ? ns.attr<double>(xrot, DD_CMU(thetaY)) : 0e0;
664  double phiY = xrot.hasAttr(DD_CMU(phiY)) ? ns.attr<double>(xrot, DD_CMU(phiY)) : 0e0;
665  double thetaZ = xrot.hasAttr(DD_CMU(thetaZ)) ? ns.attr<double>(xrot, DD_CMU(thetaZ)) : 0e0;
666  double phiZ = xrot.hasAttr(DD_CMU(phiZ)) ? ns.attr<double>(xrot, DD_CMU(phiZ)) : 0e0;
667  Rotation3D rot = makeRotation3D(thetaX, phiX, thetaY, phiY, thetaZ, phiZ);
668 
669 #ifdef EDM_ML_DEBUG
670 
671  printout(context->debug_rotations ? ALWAYS : DEBUG,
672  "DD4CMS",
673  "+++ Adding rotation: %-32s: (theta/phi)[rad] X: %6.3f %6.3f Y: %6.3f %6.3f Z: %6.3f %6.3f",
674  ns.prepend(nam).c_str(),
675  thetaX,
676  phiX,
677  thetaY,
678  phiY,
679  thetaZ,
680  phiZ);
681 
682 #endif
683 
684  ns.addRotation(nam, rot);
685 }
686 
688 template <>
689 void Converter<DDLReflectionRotation>::operator()(xml_h element) const {
690  cms::DDParsingContext* context = _param<cms::DDParsingContext>();
692  xml_dim_t xrot(element);
693  string name = xrot.nameStr();
694  double thetaX = xrot.hasAttr(DD_CMU(thetaX)) ? ns.attr<double>(xrot, DD_CMU(thetaX)) : 0e0;
695  double phiX = xrot.hasAttr(DD_CMU(phiX)) ? ns.attr<double>(xrot, DD_CMU(phiX)) : 0e0;
696  double thetaY = xrot.hasAttr(DD_CMU(thetaY)) ? ns.attr<double>(xrot, DD_CMU(thetaY)) : 0e0;
697  double phiY = xrot.hasAttr(DD_CMU(phiY)) ? ns.attr<double>(xrot, DD_CMU(phiY)) : 0e0;
698  double thetaZ = xrot.hasAttr(DD_CMU(thetaZ)) ? ns.attr<double>(xrot, DD_CMU(thetaZ)) : 0e0;
699  double phiZ = xrot.hasAttr(DD_CMU(phiZ)) ? ns.attr<double>(xrot, DD_CMU(phiZ)) : 0e0;
700 
701 #ifdef EDM_ML_DEBUG
702 
703  printout(context->debug_rotations ? ALWAYS : DEBUG,
704  "DD4CMS",
705  "+++ Adding reflection rotation: %-32s: (theta/phi)[rad] X: %6.3f %6.3f Y: %6.3f %6.3f Z: %6.3f %6.3f",
706  ns.prepend(name).c_str(),
707  thetaX,
708  phiX,
709  thetaY,
710  phiY,
711  thetaZ,
712  phiZ);
713 
714 #endif
715 
716  Rotation3D rot = makeRotReflect(thetaX, phiX, thetaY, phiY, thetaZ, phiZ);
717  ns.addRotation(name, rot);
718 }
719 
721 template <>
722 void Converter<DDLRotationSequence>::operator()(xml_h element) const {
723  cms::DDParsingContext* context = _param<cms::DDParsingContext>();
725  xml_dim_t xrot(element);
726  string nam = xrot.nameStr();
727  Rotation3D rot;
728  xml_coll_t rotations(xrot, DD_CMU(RotationByAxis));
729  for (rotations.reset(); rotations; ++rotations) {
730  string axis = ns.attr<string>(rotations, DD_CMU(axis));
731  double angle = ns.attr<double>(rotations, _U(angle));
732  rot = makeRotation3D(rot, axis, angle);
733 
734 #ifdef EDM_ML_DEBUG
735 
736  printout(context->debug_rotations ? ALWAYS : DEBUG,
737  "DD4CMS",
738  "+ Adding rotation to: %-29s: (axis/angle)[rad] Axis: %s Angle: %6.3f",
739  nam.c_str(),
740  axis.c_str(),
741  angle);
742 
743 #endif
744  }
745  double xx, xy, xz;
746  double yx, yy, yz;
747  double zx, zy, zz;
748  rot.GetComponents(xx, xy, xz, yx, yy, yz, zx, zy, zz);
749 
750 #ifdef EDM_ML_DEBUG
751 
752  printout(context->debug_rotations ? ALWAYS : DEBUG,
753  "DD4CMS",
754  "+++ Adding rotation sequence: %-23s: %6.3f %6.3f %6.3f, %6.3f %6.3f %6.3f, %6.3f %6.3f %6.3f",
755  ns.prepend(nam).c_str(),
756  xx,
757  xy,
758  xz,
759  yx,
760  yy,
761  yz,
762  zx,
763  zy,
764  zz);
765 
766 #endif
767 
768  ns.addRotation(nam, rot);
769 }
770 
772 template <>
773 void Converter<DDLRotationByAxis>::operator()(xml_h element) const {
774  cms::DDParsingContext* context = _param<cms::DDParsingContext>();
776  xml_dim_t xrot(element);
777  xml_dim_t par(xrot.parent());
778  if (xrot.hasAttr(_U(name))) {
779  string nam = xrot.nameStr();
780  string axis = ns.attr<string>(xrot, DD_CMU(axis));
781  double angle = ns.attr<double>(xrot, _U(angle));
782  Rotation3D rot;
783  rot = makeRotation3D(rot, axis, angle);
784 
785 #ifdef EDM_ML_DEBUG
786 
787  printout(context->debug_rotations ? ALWAYS : DEBUG,
788  "DD4CMS",
789  "+++ Adding rotation: %-32s: (axis/angle)[rad] Axis: %s Angle: %6.3f",
790  ns.prepend(nam).c_str(),
791  axis.c_str(),
792  angle);
793 
794 #endif
795 
796  ns.addRotation(nam, rot);
797  }
798 }
799 
801 template <>
802 void Converter<DDLLogicalPart>::operator()(xml_h element) const {
803  cms::DDNamespace ns(_param<cms::DDParsingContext>());
804  xml_dim_t e(element);
805  string sol = e.child(DD_CMU(rSolid)).attr<string>(_U(name));
806  string mat = e.child(DD_CMU(rMaterial)).attr<string>(_U(name));
807  string volName = ns.prepend(e.attr<string>(_U(name)));
808  Solid solid = ns.solid(sol);
809  Material material = ns.material(mat);
810  if (ns.context()->assemblySolids.count(sol) == 1) {
811  // To match the general paradigm, an assembly starts as a solid,
812  // and then a logical part is made of the solid. However, the
813  // solid is just a dummy whose names tags it as an assembly.
814  ns.addAssembly(volName, false);
815  return;
816  }
817 
818 #ifdef EDM_ML_DEBUG
819  Volume volume =
820 #endif
821 
822  ns.addVolume(Volume(volName, solid, material));
823 
824 #ifdef EDM_ML_DEBUG
825 
826  printout(ns.context()->debug_volumes ? ALWAYS : DEBUG,
827  "DD4CMS",
828  "+++ %s Volume: %-24s [%s] Shape: %-32s [%s] Material: %-40s [%s]",
829  e.tag().c_str(),
830  volName.c_str(),
831  volume.isValid() ? "VALID" : "INVALID",
832  sol.c_str(),
833  solid.isValid() ? "VALID" : "INVALID",
834  mat.c_str(),
835  material.isValid() ? "VALID" : "INVALID");
836 
837 #endif
838 }
839 
841 template <>
842 void Converter<DDLTransform3D>::operator()(xml_h element) const {
843  cms::DDNamespace ns(_param<cms::DDParsingContext>());
844  Transform3D* tr = _option<Transform3D>();
845  xml_dim_t e(element);
846  xml_dim_t translation = e.child(DD_CMU(Translation), false);
847  xml_dim_t rotation = e.child(DD_CMU(Rotation), false);
848  xml_dim_t refRotation = e.child(DD_CMU(rRotation), false);
849  xml_dim_t refReflectionRotation = e.child(DD_CMU(rReflectionRotation), false);
850  Position pos;
851  Rotation3D rot;
852 
853  if (translation.ptr()) {
854  double x = ns.attr<double>(translation, _U(x));
855  double y = ns.attr<double>(translation, _U(y));
856  double z = ns.attr<double>(translation, _U(z));
857  pos = Position(x, y, z);
858  }
859  if (rotation.ptr()) {
860  double x = ns.attr<double>(rotation, _U(x));
861  double y = ns.attr<double>(rotation, _U(y));
862  double z = ns.attr<double>(rotation, _U(z));
863  rot = RotationZYX(z, y, x);
864  } else if (refRotation.ptr()) {
865  string rotName = ns.prepend(refRotation.nameStr());
866  rot = ns.rotation(rotName);
867  } else if (refReflectionRotation.ptr()) {
868  string rotName = ns.prepend(refReflectionRotation.nameStr());
869  rot = ns.rotation(rotName);
870  }
871  *tr = Transform3D(rot, pos);
872 }
873 
874 static void placeAssembly(Volume* parentPtr,
875  const string& parentName,
876  Volume* childPtr,
877  const string& childName,
878  int copy,
879  const Transform3D& transform,
880  cms::DDNamespace& ns) {
881 #ifdef EDM_ML_DEBUG
882 
883  printout(ns.context()->debug_placements ? ALWAYS : DEBUG,
884  "DD4CMS",
885  "+++ Parent vol: %-24s Child: %-32s, copy:%d",
886  parentName.c_str(),
887  childName.c_str(),
888  copy);
889 
890 #endif
891 
892  TGeoShape* shape = (*childPtr)->GetShape();
893  // Need to fix the daughter's BBox of assemblies, if the BBox was not calculated....
894  if (shape->IsA() == TGeoShapeAssembly::Class()) {
895  TGeoShapeAssembly* as = (TGeoShapeAssembly*)shape;
896  if (std::fabs(as->GetDX()) < numeric_limits<double>::epsilon() &&
897  std::fabs(as->GetDY()) < numeric_limits<double>::epsilon() &&
898  std::fabs(as->GetDZ()) < numeric_limits<double>::epsilon()) {
899  as->NeedsBBoxRecompute();
900  as->ComputeBBox();
901  }
902  }
903  TGeoNode* n;
904  TString nam_id = TString::Format("%s_%d", (*childPtr)->GetName(), copy);
905  n = static_cast<TGeoNode*>((*parentPtr)->GetNode(nam_id));
906  if (n != nullptr) {
907  printout(ERROR, "PlacedVolume", "++ Attempt to add already existing node %s", (const char*)nam_id);
908  return;
909  }
910 
912  if ((*childPtr)->IsAssembly()) {
913  pv = parentPtr->placeVolume(ns.assembly(childName), copy, transform);
914  } else {
915  pv = parentPtr->placeVolume(*childPtr, copy, transform);
916  }
917 
918  if (!pv.isValid()) {
919  printout(ERROR, "DD4CMS", "+++ Placement FAILED! Parent:%s Child:%s", parentName.c_str(), childName.c_str());
920  }
921 }
922 
924 template <>
925 void Converter<DDLPosPart>::operator()(xml_h element) const {
926  cms::DDNamespace ns(_param<cms::DDParsingContext>()); //, element, true );
927  xml_dim_t e(element);
928  int copy = e.attr<int>(DD_CMU(copyNumber));
929  string parentName = ns.prepend(ns.attr<string>(e.child(DD_CMU(rParent)), _U(name)));
930  string childName = ns.prepend(ns.attr<string>(e.child(DD_CMU(rChild)), _U(name)));
931  Transform3D transform;
932  Converter<DDLTransform3D>(description, param, &transform)(element);
933 
934  Volume parent = ns.volume(parentName, false);
935  Volume child = ns.volume(childName, false);
936  Assembly parAsmb = ns.assembly(parentName, false);
937  Assembly childAsmb = ns.assembly(childName, false);
938 
939 #ifdef EDM_ML_DEBUG
940 
941  printout(ns.context()->debug_placements ? ALWAYS : DEBUG,
942  "DD4CMS",
943  "+++ %s Parent: %-24s [%s] Child: %-32s [%s] copy:%d",
944  e.tag().c_str(),
945  parentName.c_str(),
946  parent.isValid() ? "VALID" : "INVALID",
947  childName.c_str(),
948  child.isValid() ? "VALID" : "INVALID",
949  copy);
950 
951 #endif
952 
953  if (!parent.isValid() && !parAsmb.isValid() && strchr(parentName.c_str(), NAMESPACE_SEP) == nullptr) {
954  parentName = ns.prepend(parentName);
955  parAsmb = ns.assembly(parentName, false);
956  if (!parAsmb.isValid())
957  parent = ns.volume(parentName);
958  }
959 
960  if (!child.isValid() && !childAsmb.isValid() && strchr(childName.c_str(), NAMESPACE_SEP) == nullptr) {
961  childName = ns.prepend(childName);
962  child = ns.volume(childName, false);
963  childAsmb = ns.assembly(childName, false);
964  }
965  if (parAsmb.isValid() || childAsmb.isValid()) {
966  printout(ns.context()->debug_placements ? ALWAYS : DEBUG,
967  "DD4CMS",
968  "***** Placing assembly parent %s, child %s",
969  parentName.c_str(),
970  childName.c_str());
971  Volume* parentPtr = parAsmb.isValid() ? &parAsmb : &parent;
972  Volume* childPtr = childAsmb.isValid() ? &childAsmb : &child;
973  placeAssembly(parentPtr, parentName, childPtr, childName, copy, transform, ns);
974  return;
975  }
976 
977 #ifdef EDM_ML_DEBUG
978 
979  printout(ns.context()->debug_placements ? ALWAYS : DEBUG,
980  "DD4CMS",
981  "+++ %s Parent: %-24s [%s] Child: %-32s [%s] copy:%d",
982  e.tag().c_str(),
983  parentName.c_str(),
984  parent.isValid() ? "VALID" : "INVALID",
985  childName.c_str(),
986  child.isValid() ? "VALID" : "INVALID",
987  copy);
988 
989 #endif
990 
992  if (child.isValid()) {
993  // FIXME: workaround for Reflection rotation
994  // copy from DDCore/src/Volumes.cpp to replace
995  // static PlacedVolume _addNode(TGeoVolume* par, TGeoVolume* daughter, int id, TGeoMatrix* transform)
996  if (!parent) {
997  except("dd4hep", "Volume: Attempt to assign daughters to an invalid physical parent volume.");
998  }
999  if (!child) {
1000  except("dd4hep", "Volume: Attempt to assign an invalid physical daughter volume.");
1001  }
1002  TGeoShape* shape = child->GetShape();
1003  // Need to fix the daughter's BBox of assemblies, if the BBox was not calculated....
1004  if (shape->IsA() == TGeoShapeAssembly::Class()) {
1005  TGeoShapeAssembly* as = (TGeoShapeAssembly*)shape;
1006  if (std::fabs(as->GetDX()) < numeric_limits<double>::epsilon() &&
1007  std::fabs(as->GetDY()) < numeric_limits<double>::epsilon() &&
1008  std::fabs(as->GetDZ()) < numeric_limits<double>::epsilon()) {
1009  as->NeedsBBoxRecompute();
1010  as->ComputeBBox();
1011  }
1012  }
1013  TGeoNode* n;
1014  TString nam_id = TString::Format("%s_%d", child->GetName(), copy);
1015  n = static_cast<TGeoNode*>(parent->GetNode(nam_id));
1016  if (n != nullptr) {
1017  printout(ERROR, "PlacedVolume", "++ Attempt to add already existing node %s", (const char*)nam_id);
1018  }
1019 
1020  Rotation3D rot(transform.Rotation());
1021  Translation3D trans(transform.Translation());
1022  double x, y, z;
1023  trans.GetComponents(x, y, z);
1024  Position pos(x, y, z);
1025  parent->AddNode(child, copy, createPlacement(rot, pos));
1026 
1027  n = static_cast<TGeoNode*>(parent->GetNode(nam_id));
1028  n->TGeoNode::SetUserExtension(new PlacedVolume::Object());
1029  pv = PlacedVolume(n);
1030  }
1031  if (!pv.isValid()) {
1032  printout(ERROR,
1033  "DD4CMS",
1034  "+++ Placement FAILED! Parent:%s Child:%s Valid:%s",
1035  parent.name(),
1036  childName.c_str(),
1037  yes_no(child.isValid()));
1038  }
1039 }
1040 
1042 template <>
1043 void Converter<PartSelector>::operator()(xml_h element) const {
1044  cms::DDNamespace ns(_param<cms::DDParsingContext>());
1045  cms::DDParsingContext* const context = ns.context();
1046  dd4hep::SpecParRegistry& registry = *context->description.extension<dd4hep::SpecParRegistry>();
1047  xml_dim_t e(element);
1048  xml_dim_t specPar = e.parent();
1049  string specParName = specPar.attr<string>(_U(name));
1050  string path = e.attr<string>(DD_CMU(path));
1051 
1052 #ifdef EDM_ML_DEBUG
1053 
1054  printout(ns.context()->debug_specpars ? ALWAYS : DEBUG,
1055  "DD4CMS",
1056  "+++ PartSelector for %s path: %s",
1057  specParName.c_str(),
1058  path.c_str());
1059 
1060 #endif
1061 
1062  size_t pos = std::string::npos;
1063  if ((pos = path.find("//.*:")) != std::string::npos) {
1064  path.erase(pos + 2, 3);
1065  }
1066  registry.specpars[specParName].paths.emplace_back(std::move(path));
1067 }
1068 
1070 template <>
1071 void Converter<Parameter>::operator()(xml_h element) const {
1072  cms::DDNamespace ns(_param<cms::DDParsingContext>());
1073  cms::DDParsingContext* const context = ns.context();
1074  dd4hep::SpecParRegistry& registry = *context->description.extension<dd4hep::SpecParRegistry>();
1075  xml_dim_t e(element);
1076  xml_dim_t specPar = e.parent();
1077  xml_dim_t specParSect = specPar.parent();
1078  string specParName = specPar.attr<string>(_U(name));
1079  string name = e.nameStr();
1080  string value = e.attr<string>(DD_CMU(value));
1081  bool eval = specParSect.hasAttr(_U(eval)) ? specParSect.attr<bool>(_U(eval)) : false;
1082  eval = specPar.hasAttr(_U(eval)) ? specPar.attr<bool>(_U(eval)) : eval;
1083  eval = e.hasAttr(_U(eval)) ? e.attr<bool>(_U(eval)) : eval;
1084 
1085  string type = eval ? "number" : "string";
1086 
1087 #ifdef EDM_ML_DEBUG
1088 
1089  printout(ns.context()->debug_specpars ? ALWAYS : DEBUG,
1090  "DD4CMS",
1091  "+++ Parameter for %s: %s value %s is a %s",
1092  specParName.c_str(),
1093  name.c_str(),
1094  value.c_str(),
1095  type.c_str());
1096 
1097 #endif
1098 
1099  size_t idx = value.find('[');
1100  if (idx == string::npos && type == "number") {
1101  registry.specpars[specParName].numpars[name].emplace_back(dd4hep::_toDouble(value));
1102  return;
1103  }
1104  if (idx == string::npos || type == "string") {
1105  registry.specpars[specParName].spars[name].emplace_back(std::move(value));
1106  return;
1107  }
1108 
1109  while (idx != string::npos) {
1110  ++idx;
1111  size_t idp = value.find(':', idx);
1112  size_t idq = value.find(']', idx);
1113  if (idp == string::npos || idp > idq)
1114  value.insert(idx, ns.name());
1115  else if (idp != string::npos && idp < idq)
1116  value[idp] = NAMESPACE_SEP;
1117  idx = value.find('[', idx);
1118  }
1119 
1120  string rep;
1121  string& v = value;
1122  size_t idq;
1123  for (idx = v.find('[', 0); idx != string::npos; idx = v.find('[', idx + 1)) {
1124  idq = v.find(']', idx + 1);
1125  rep = v.substr(idx + 1, idq - idx - 1);
1126  auto r = ns.context()->description.constants().find(rep);
1127  if (r != ns.context()->description.constants().end()) {
1128  rep = "(" + r->second->type + ")";
1129  v.replace(idx, idq - idx + 1, rep);
1130  }
1131  }
1132  registry.specpars[specParName].numpars[name].emplace_back(dd4hep::_toDouble(value));
1133 }
1134 
1135 template <typename TYPE>
1136 static void convert_boolean(cms::DDParsingContext* context, xml_h element) {
1138  xml_dim_t e(element);
1139  string nam = e.nameStr();
1140  string solidName[2];
1141  Solid solids[2];
1142  Solid boolean;
1143  int cnt = 0;
1144  if (e.hasChild(DD_CMU(rSolid))) {
1145  for (xml_coll_t c(element, DD_CMU(rSolid)); cnt < 2 && c; ++c, ++cnt) {
1146  solidName[cnt] = c.attr<string>(_U(name));
1147  solids[cnt] = ns.solid(c.attr<string>(_U(name)));
1148  }
1149  } else {
1150  solidName[0] = e.attr<string>(DD_CMU(firstSolid));
1151  if ((solids[0] = ns.solid(e.attr<string>(DD_CMU(firstSolid)))).isValid())
1152  ++cnt;
1153  solidName[1] = e.attr<string>(DD_CMU(secondSolid));
1154  if ((solids[1] = ns.solid(e.attr<string>(DD_CMU(secondSolid)))).isValid())
1155  ++cnt;
1156  }
1157  if (cnt != 2) {
1158  except("DD4CMS", "+++ Failed to create boolean solid %s. Found only %d parts.", nam.c_str(), cnt);
1159  }
1160 
1161 #ifdef EDM_ML_DEBUG
1162 
1163  printout(ns.context()->debug_placements ? ALWAYS : DEBUG,
1164  "DD4CMS",
1165  "+++ BooleanSolid: %s Left: %-32s Right: %-32s",
1166  nam.c_str(),
1167  ((solids[0].ptr() == nullptr) ? solidName[0].c_str() : solids[0]->GetName()),
1168  ((solids[1].ptr() == nullptr) ? solidName[1].c_str() : solids[1]->GetName()));
1169 
1170 #endif
1171 
1172  if (solids[0].isValid() && solids[1].isValid()) {
1173  Transform3D trafo;
1174  Converter<DDLTransform3D>(context->description, context, &trafo)(element);
1175  boolean = TYPE(solids[0], solids[1], trafo);
1176  } else {
1177  // Register it for later processing
1178  Transform3D trafo;
1179  Converter<DDLTransform3D>(context->description, context, &trafo)(element);
1180  ns.context()->unresolvedShapes.emplace(nam,
1181  DDParsingContext::BooleanShape<TYPE>(solidName[0], solidName[1], trafo));
1182  }
1183  if (!boolean.isValid()) {
1184  // Delay processing the shape
1185  ns.context()->shapes.emplace(nam, dd4hep::Solid(nullptr));
1186  } else
1187  ns.addSolid(nam, boolean);
1188 }
1189 
1191 template <>
1192 void Converter<DDLUnionSolid>::operator()(xml_h element) const {
1193  convert_boolean<UnionSolid>(_param<cms::DDParsingContext>(), element);
1194 }
1195 
1197 template <>
1198 void Converter<DDLSubtractionSolid>::operator()(xml_h element) const {
1199  convert_boolean<SubtractionSolid>(_param<cms::DDParsingContext>(), element);
1200 }
1201 
1203 template <>
1204 void Converter<DDLIntersectionSolid>::operator()(xml_h element) const {
1205  convert_boolean<IntersectionSolid>(_param<cms::DDParsingContext>(), element);
1206 }
1207 
1209 template <>
1210 void Converter<DDLPolycone>::operator()(xml_h element) const {
1211  cms::DDNamespace ns(_param<cms::DDParsingContext>());
1212  xml_dim_t e(element);
1213  string nam = e.nameStr();
1214  double startPhi = ns.attr<double>(e, DD_CMU(startPhi));
1215  double deltaPhi = ns.attr<double>(e, DD_CMU(deltaPhi));
1216  vector<double> z, rmin, rmax, r;
1217 
1218  for (xml_coll_t rzpoint(element, DD_CMU(RZPoint)); rzpoint; ++rzpoint) {
1219  z.emplace_back(ns.attr<double>(rzpoint, _U(z)));
1220  r.emplace_back(ns.attr<double>(rzpoint, _U(r)));
1221  }
1222  if (z.empty()) {
1223  for (xml_coll_t zplane(element, DD_CMU(ZSection)); zplane; ++zplane) {
1224  rmin.emplace_back(ns.attr<double>(zplane, DD_CMU(rMin)));
1225  rmax.emplace_back(ns.attr<double>(zplane, DD_CMU(rMax)));
1226  z.emplace_back(ns.attr<double>(zplane, _U(z)));
1227  }
1228 
1229 #ifdef EDM_ML_DEBUG
1230 
1231  printout(ns.context()->debug_shapes ? ALWAYS : DEBUG,
1232  "DD4CMS",
1233  "+ Polycone: startPhi=%10.3f [rad] deltaPhi=%10.3f [rad] %4ld z-planes",
1234  startPhi,
1235  deltaPhi,
1236  z.size());
1237 
1238 #endif
1239 
1240  ns.addSolid(nam, Polycone(startPhi, deltaPhi, rmin, rmax, z));
1241  } else {
1242 #ifdef EDM_ML_DEBUG
1243 
1244  printout(ns.context()->debug_shapes ? ALWAYS : DEBUG,
1245  "DD4CMS",
1246  "+ Polycone: startPhi=%10.3f [rad] deltaPhi=%10.3f [rad] %4ld z-planes and %4ld radii",
1247  startPhi,
1248  deltaPhi,
1249  z.size(),
1250  r.size());
1251 
1252 #endif
1253 
1254  ns.addSolid(nam, Polycone(startPhi, deltaPhi, r, z));
1255  }
1256 }
1257 
1259 template <>
1260 void Converter<DDLExtrudedPolygon>::operator()(xml_h element) const {
1261  cms::DDNamespace ns(_param<cms::DDParsingContext>());
1262  xml_dim_t e(element);
1263  string nam = e.nameStr();
1264  vector<double> pt_x, pt_y, sec_x, sec_y, sec_z, sec_scale;
1265 
1266  for (xml_coll_t sec(element, DD_CMU(ZXYSection)); sec; ++sec) {
1267  sec_z.emplace_back(ns.attr<double>(sec, _U(z)));
1268  sec_x.emplace_back(ns.attr<double>(sec, _U(x)));
1269  sec_y.emplace_back(ns.attr<double>(sec, _U(y)));
1270  sec_scale.emplace_back(ns.attr<double>(sec, DD_CMU(scale), 1.0));
1271  }
1272  for (xml_coll_t pt(element, DD_CMU(XYPoint)); pt; ++pt) {
1273  pt_x.emplace_back(ns.attr<double>(pt, _U(x)));
1274  pt_y.emplace_back(ns.attr<double>(pt, _U(y)));
1275  }
1276 
1277 #ifdef EDM_ML_DEBUG
1278 
1279  printout(ns.context()->debug_shapes ? ALWAYS : DEBUG,
1280  "DD4CMS",
1281  "+ ExtrudedPolygon: %4ld points %4ld zxy sections",
1282  pt_x.size(),
1283  sec_z.size());
1284 
1285 #endif
1286 
1287  ns.addSolid(nam, ExtrudedPolygon(pt_x, pt_y, sec_z, sec_x, sec_y, sec_scale));
1288 }
1289 
1291 template <>
1292 void Converter<DDLPolyhedra>::operator()(xml_h element) const {
1293  cms::DDNamespace ns(_param<cms::DDParsingContext>());
1294  xml_dim_t e(element);
1295  string nam = e.nameStr();
1296  double numSide = ns.attr<int>(e, DD_CMU(numSide));
1297  double startPhi = ns.attr<double>(e, DD_CMU(startPhi));
1298  double deltaPhi = ns.attr<double>(e, DD_CMU(deltaPhi));
1299  vector<double> z, rmin, rmax;
1300 
1301  for (xml_coll_t zplane(element, DD_CMU(RZPoint)); zplane; ++zplane) {
1302  rmin.emplace_back(0.0);
1303  rmax.emplace_back(ns.attr<double>(zplane, _U(r)));
1304  z.emplace_back(ns.attr<double>(zplane, _U(z)));
1305  }
1306  for (xml_coll_t zplane(element, DD_CMU(ZSection)); zplane; ++zplane) {
1307  rmin.emplace_back(ns.attr<double>(zplane, DD_CMU(rMin)));
1308  rmax.emplace_back(ns.attr<double>(zplane, DD_CMU(rMax)));
1309  z.emplace_back(ns.attr<double>(zplane, _U(z)));
1310  }
1311 
1312 #ifdef EDM_ML_DEBUG
1313 
1314  printout(ns.context()->debug_shapes ? ALWAYS : DEBUG,
1315  "DD4CMS",
1316  "+ Polyhedra:startPhi=%8.3f [rad] deltaPhi=%8.3f [rad] %4d sides %4ld z-planes",
1317  startPhi,
1318  deltaPhi,
1319  numSide,
1320  z.size());
1321 
1322 #endif
1323 
1324  ns.addSolid(nam, Polyhedra(numSide, startPhi, deltaPhi, z, rmin, rmax));
1325 }
1326 
1328 template <>
1329 void Converter<DDLSphere>::operator()(xml_h element) const {
1330  cms::DDNamespace ns(_param<cms::DDParsingContext>());
1331  xml_dim_t e(element);
1332  string nam = e.nameStr();
1333  double rinner = ns.attr<double>(e, DD_CMU(innerRadius));
1334  double router = ns.attr<double>(e, DD_CMU(outerRadius));
1335  double startPhi = ns.attr<double>(e, DD_CMU(startPhi));
1336  double deltaPhi = ns.attr<double>(e, DD_CMU(deltaPhi));
1337  double startTheta = ns.attr<double>(e, DD_CMU(startTheta));
1338  double deltaTheta = ns.attr<double>(e, DD_CMU(deltaTheta));
1339 
1340 #ifdef EDM_ML_DEBUG
1341 
1342  printout(ns.context()->debug_shapes ? ALWAYS : DEBUG,
1343  "DD4CMS",
1344  "+ Sphere: r_inner=%8.3f [cm] r_outer=%8.3f [cm]"
1345  " startPhi=%8.3f [rad] deltaPhi=%8.3f startTheta=%8.3f delteTheta=%8.3f [rad]",
1346  rinner / dd4hep::cm,
1347  router / dd4hep::cm,
1348  startPhi,
1349  deltaPhi,
1350  startTheta,
1351  deltaTheta);
1352 
1353 #endif
1354 
1355  ns.addSolid(nam, Sphere(rinner, router, startTheta, deltaTheta, startPhi, deltaPhi));
1356 }
1357 
1359 template <>
1360 void Converter<DDLTorus>::operator()(xml_h element) const {
1361  cms::DDNamespace ns(_param<cms::DDParsingContext>());
1362  xml_dim_t e(element);
1363  string nam = e.nameStr();
1364  double r = ns.attr<double>(e, DD_CMU(torusRadius));
1365  double rinner = ns.attr<double>(e, DD_CMU(innerRadius));
1366  double router = ns.attr<double>(e, DD_CMU(outerRadius));
1367  double startPhi = ns.attr<double>(e, DD_CMU(startPhi));
1368  double deltaPhi = ns.attr<double>(e, DD_CMU(deltaPhi));
1369 
1370 #ifdef EDM_ML_DEBUG
1371 
1372  printout(ns.context()->debug_shapes ? ALWAYS : DEBUG,
1373  "DD4CMS",
1374  "+ Torus: r=%10.3f [cm] r_inner=%10.3f [cm] r_outer=%10.3f [cm]"
1375  " startPhi=%10.3f [rad] deltaPhi=%10.3f [rad]",
1376  r / dd4hep::cm,
1377  rinner / dd4hep::cm,
1378  router / dd4hep::cm,
1379  startPhi,
1380  deltaPhi);
1381 
1382 #endif
1383 
1384  ns.addSolid(nam, Torus(r, rinner, router, startPhi, deltaPhi));
1385 }
1386 
1388 template <>
1389 void Converter<DDLPseudoTrap>::operator()(xml_h element) const {
1390  cms::DDNamespace ns(_param<cms::DDParsingContext>());
1391  xml_dim_t e(element);
1392  string nam = e.nameStr();
1393  double dx1 = ns.attr<double>(e, DD_CMU(dx1));
1394  double dy1 = ns.attr<double>(e, DD_CMU(dy1));
1395  double dx2 = ns.attr<double>(e, DD_CMU(dx2));
1396  double dy2 = ns.attr<double>(e, DD_CMU(dy2));
1397  double dz = ns.attr<double>(e, _U(dz));
1398  double r = ns.attr<double>(e, _U(radius));
1399  bool atMinusZ = ns.attr<bool>(e, DD_CMU(atMinusZ));
1400 
1401 #ifdef EDM_ML_DEBUG
1402 
1403  printout(ns.context()->debug_shapes ? ALWAYS : DEBUG,
1404  "DD4CMS",
1405  "+ Pseudotrap: dz=%8.3f [cm] dx1:%.3f dy1:%.3f dx2=%.3f dy2=%.3f radius:%.3f atMinusZ:%s",
1406  dz / dd4hep::cm,
1407  dx1 / dd4hep::cm,
1408  dy1 / dd4hep::cm,
1409  dx2 / dd4hep::cm,
1410  dy2 / dd4hep::cm,
1411  r / dd4hep::cm,
1412  yes_no(atMinusZ));
1413 
1414 #endif
1415 
1416  ns.addSolid(nam, PseudoTrap(dx1, dx2, dy1, dy2, dz, r, atMinusZ));
1417 }
1418 
1420 template <>
1421 void Converter<DDLTrapezoid>::operator()(xml_h element) const {
1422  cms::DDNamespace ns(_param<cms::DDParsingContext>());
1423  xml_dim_t e(element);
1424  string nam = e.nameStr();
1425  double dz = ns.attr<double>(e, _U(dz));
1426  double alp1 = ns.attr<double>(e, DD_CMU(alp1));
1427  double bl1 = ns.attr<double>(e, DD_CMU(bl1));
1428  double tl1 = ns.attr<double>(e, DD_CMU(tl1));
1429  double h1 = ns.attr<double>(e, DD_CMU(h1));
1430  double alp2 = ns.attr<double>(e, DD_CMU(alp2));
1431  double bl2 = ns.attr<double>(e, DD_CMU(bl2));
1432  double tl2 = ns.attr<double>(e, DD_CMU(tl2));
1433  double h2 = ns.attr<double>(e, DD_CMU(h2));
1434  double phi = ns.attr<double>(e, _U(phi), 0.0);
1435  double theta = ns.attr<double>(e, _U(theta), 0.0);
1436 
1437 #ifdef EDM_ML_DEBUG
1438 
1439  printout(ns.context()->debug_shapes ? ALWAYS : DEBUG,
1440  "DD4CMS",
1441  "+ Trapezoid: dz=%10.3f [cm] alp1:%.3f bl1=%.3f tl1=%.3f alp2=%.3f bl2=%.3f tl2=%.3f h2=%.3f phi=%.3f "
1442  "theta=%.3f",
1443  dz / dd4hep::cm,
1444  alp1,
1445  bl1 / dd4hep::cm,
1446  tl1 / dd4hep::cm,
1447  h1 / dd4hep::cm,
1448  alp2,
1449  bl2 / dd4hep::cm,
1450  tl2 / dd4hep::cm,
1451  h2 / dd4hep::cm,
1452  phi,
1453  theta);
1454 
1455 #endif
1456 
1457  ns.addSolid(nam, Trap(dz, theta, phi, h1, bl1, tl1, alp1, h2, bl2, tl2, alp2));
1458 }
1459 
1461 template <>
1462 void Converter<DDLTrd1>::operator()(xml_h element) const {
1463  cms::DDNamespace ns(_param<cms::DDParsingContext>());
1464  xml_dim_t e(element);
1465  string nam = e.nameStr();
1466  double dx1 = ns.attr<double>(e, DD_CMU(dx1));
1467  double dy1 = ns.attr<double>(e, DD_CMU(dy1));
1468  double dx2 = ns.attr<double>(e, DD_CMU(dx2), 0.0);
1469  double dy2 = ns.attr<double>(e, DD_CMU(dy2), dy1);
1470  double dz = ns.attr<double>(e, DD_CMU(dz));
1471  if (dy1 == dy2) {
1472 #ifdef EDM_ML_DEBUG
1473 
1474  printout(ns.context()->debug_shapes ? ALWAYS : DEBUG,
1475  "DD4CMS",
1476  "+ Trd1: dz=%8.3f [cm] dx1:%.3f dy1:%.3f dx2:%.3f dy2:%.3f",
1477  dz / dd4hep::cm,
1478  dx1 / dd4hep::cm,
1479  dy1 / dd4hep::cm,
1480  dx2 / dd4hep::cm,
1481  dy2 / dd4hep::cm);
1482 
1483 #endif
1484 
1485  ns.addSolid(nam, Trd1(dx1, dx2, dy1, dz));
1486  } else {
1487 #ifdef EDM_ML_DEBUG
1488 
1489  printout(ns.context()->debug_shapes ? ALWAYS : DEBUG,
1490  "DD4CMS",
1491  "+ Trd1(which is actually Trd2): dz=%8.3f [cm] dx1:%.3f dy1:%.3f dx2:%.3f dy2:%.3f",
1492  dz / dd4hep::cm,
1493  dx1 / dd4hep::cm,
1494  dy1 / dd4hep::cm,
1495  dx2 / dd4hep::cm,
1496  dy2 / dd4hep::cm);
1497 
1498 #endif
1499 
1500  ns.addSolid(nam, Trd2(dx1, dx2, dy1, dy2, dz));
1501  }
1502 }
1503 
1505 template <>
1506 void Converter<DDLTrd2>::operator()(xml_h element) const {
1507  cms::DDNamespace ns(_param<cms::DDParsingContext>());
1508  xml_dim_t e(element);
1509  string nam = e.nameStr();
1510  double dx1 = ns.attr<double>(e, DD_CMU(dx1));
1511  double dy1 = ns.attr<double>(e, DD_CMU(dy1));
1512  double dx2 = ns.attr<double>(e, DD_CMU(dx2), 0.0);
1513  double dy2 = ns.attr<double>(e, DD_CMU(dy2), dy1);
1514  double dz = ns.attr<double>(e, DD_CMU(dz));
1515 
1516 #ifdef EDM_ML_DEBUG
1517 
1518  printout(ns.context()->debug_shapes ? ALWAYS : DEBUG,
1519  "DD4CMS",
1520  "+ Trd1: dz=%8.3f [cm] dx1:%.3f dy1:%.3f dx2:%.3f dy2:%.3f",
1521  dz / dd4hep::cm,
1522  dx1 / dd4hep::cm,
1523  dy1 / dd4hep::cm,
1524  dx2 / dd4hep::cm,
1525  dy2 / dd4hep::cm);
1526 
1527 #endif
1528 
1529  ns.addSolid(nam, Trd2(dx1, dx2, dy1, dy2, dz));
1530 }
1531 
1533 template <>
1534 void Converter<DDLTubs>::operator()(xml_h element) const {
1535  cms::DDNamespace ns(_param<cms::DDParsingContext>());
1536  xml_dim_t e(element);
1537  string nam = e.nameStr();
1538  double dz = ns.attr<double>(e, DD_CMU(dz));
1539  double rmin = ns.attr<double>(e, DD_CMU(rMin));
1540  double rmax = ns.attr<double>(e, DD_CMU(rMax));
1541  double startPhi = ns.attr<double>(e, DD_CMU(startPhi), 0.0);
1542  double deltaPhi = ns.attr<double>(e, DD_CMU(deltaPhi), 2 * M_PI);
1543 
1544 #ifdef EDM_ML_DEBUG
1545 
1546  printout(ns.context()->debug_shapes ? ALWAYS : DEBUG,
1547  "DD4CMS",
1548  "+ Tubs: dz=%8.3f [cm] rmin=%8.3f [cm] rmax=%8.3f [cm]"
1549  " startPhi=%8.3f [rad] deltaPhi=%8.3f [rad]",
1550  dz / dd4hep::cm,
1551  rmin / dd4hep::cm,
1552  rmax / dd4hep::cm,
1553  startPhi,
1554  deltaPhi);
1555 
1556 #endif
1557 
1558  ns.addSolid(nam, Tube(rmin, rmax, dz, startPhi, startPhi + deltaPhi));
1559 }
1560 
1562 template <>
1563 void Converter<DDLCutTubs>::operator()(xml_h element) const {
1564  cms::DDNamespace ns(_param<cms::DDParsingContext>());
1565  xml_dim_t e(element);
1566  string nam = e.nameStr();
1567  double dz = ns.attr<double>(e, DD_CMU(dz));
1568  double rmin = ns.attr<double>(e, DD_CMU(rMin));
1569  double rmax = ns.attr<double>(e, DD_CMU(rMax));
1570  double startPhi = ns.attr<double>(e, DD_CMU(startPhi));
1571  double deltaPhi = ns.attr<double>(e, DD_CMU(deltaPhi));
1572  double lx = ns.attr<double>(e, DD_CMU(lx));
1573  double ly = ns.attr<double>(e, DD_CMU(ly));
1574  double lz = ns.attr<double>(e, DD_CMU(lz));
1575  double tx = ns.attr<double>(e, DD_CMU(tx));
1576  double ty = ns.attr<double>(e, DD_CMU(ty));
1577  double tz = ns.attr<double>(e, DD_CMU(tz));
1578 
1579 #ifdef EDM_ML_DEBUG
1580 
1581  printout(ns.context()->debug_shapes ? ALWAYS : DEBUG,
1582  "DD4CMS",
1583  "+ CutTube: dz=%8.3f [cm] rmin=%8.3f [cm] rmax=%8.3f [cm]"
1584  " startPhi=%8.3f [rad] deltaPhi=%8.3f [rad]...",
1585  dz / dd4hep::cm,
1586  rmin / dd4hep::cm,
1587  rmax / dd4hep::cm,
1588  startPhi,
1589  deltaPhi);
1590 
1591 #endif
1592 
1593  ns.addSolid(nam, CutTube(rmin, rmax, dz, startPhi, startPhi + deltaPhi, lx, ly, lz, tx, ty, tz));
1594 }
1595 
1597 template <>
1598 void Converter<DDLTruncTubs>::operator()(xml_h element) const {
1599  cms::DDNamespace ns(_param<cms::DDParsingContext>());
1600  xml_dim_t e(element);
1601  string nam = e.nameStr();
1602  double zhalf = ns.attr<double>(e, DD_CMU(zHalf));
1603  double rmin = ns.attr<double>(e, DD_CMU(rMin));
1604  double rmax = ns.attr<double>(e, DD_CMU(rMax));
1605  double startPhi = ns.attr<double>(e, DD_CMU(startPhi));
1606  double deltaPhi = ns.attr<double>(e, DD_CMU(deltaPhi));
1607  double cutAtStart = ns.attr<double>(e, DD_CMU(cutAtStart));
1608  double cutAtDelta = ns.attr<double>(e, DD_CMU(cutAtDelta));
1609  bool cutInside = ns.attr<bool>(e, DD_CMU(cutInside));
1610 
1611 #ifdef EDM_ML_DEBUG
1612 
1613  printout(ns.context()->debug_shapes ? ALWAYS : DEBUG,
1614  "DD4CMS",
1615  "+ TruncTube:zHalf=%8.3f [cm] rmin=%8.3f [cm] rmax=%8.3f [cm]"
1616  " startPhi=%8.3f [rad] deltaPhi=%8.3f [rad] atStart=%8.3f [cm] atDelta=%8.3f [cm] inside:%s",
1617  zhalf / dd4hep::cm,
1618  rmin / dd4hep::cm,
1619  rmax / dd4hep::cm,
1620  startPhi,
1621  deltaPhi,
1622  cutAtStart / dd4hep::cm,
1623  cutAtDelta / dd4hep::cm,
1624  yes_no(cutInside));
1625 
1626 #endif
1627 
1628  ns.addSolid(nam, TruncatedTube(zhalf, rmin, rmax, startPhi, deltaPhi, cutAtStart, cutAtDelta, cutInside));
1629 }
1630 
1632 template <>
1633 void Converter<DDLEllipticalTube>::operator()(xml_h element) const {
1634  cms::DDNamespace ns(_param<cms::DDParsingContext>());
1635  xml_dim_t e(element);
1636  string nam = e.nameStr();
1637  double dx = ns.attr<double>(e, DD_CMU(xSemiAxis));
1638  double dy = ns.attr<double>(e, DD_CMU(ySemiAxis));
1639  double dz = ns.attr<double>(e, DD_CMU(zHeight));
1640 
1641 #ifdef EDM_ML_DEBUG
1642 
1643  printout(ns.context()->debug_shapes ? ALWAYS : DEBUG,
1644  "DD4CMS",
1645  "+ EllipticalTube xSemiAxis=%8.3f [cm] ySemiAxis=%8.3f [cm] zHeight=%8.3f [cm]",
1646  dx / dd4hep::cm,
1647  dy / dd4hep::cm,
1648  dz / dd4hep::cm);
1649 
1650 #endif
1651 
1652  ns.addSolid(nam, EllipticalTube(dx, dy, dz));
1653 }
1654 
1656 template <>
1657 void Converter<DDLCone>::operator()(xml_h element) const {
1658  cms::DDNamespace ns(_param<cms::DDParsingContext>());
1659  xml_dim_t e(element);
1660  string nam = e.nameStr();
1661  double dz = ns.attr<double>(e, DD_CMU(dz));
1662  double rmin1 = ns.attr<double>(e, DD_CMU(rMin1));
1663  double rmin2 = ns.attr<double>(e, DD_CMU(rMin2));
1664  double rmax1 = ns.attr<double>(e, DD_CMU(rMax1));
1665  double rmax2 = ns.attr<double>(e, DD_CMU(rMax2));
1666  double startPhi = ns.attr<double>(e, DD_CMU(startPhi));
1667  double deltaPhi = ns.attr<double>(e, DD_CMU(deltaPhi));
1668  double phi2 = startPhi + deltaPhi;
1669 
1670 #ifdef EDM_ML_DEBUG
1671 
1672  printout(ns.context()->debug_shapes ? ALWAYS : DEBUG,
1673  "DD4CMS",
1674  "+ Cone: dz=%8.3f [cm]"
1675  " rmin1=%8.3f [cm] rmax1=%8.3f [cm]"
1676  " rmin2=%8.3f [cm] rmax2=%8.3f [cm]"
1677  " startPhi=%8.3f [rad] deltaPhi=%8.3f [rad]",
1678  dz / dd4hep::cm,
1679  rmin1 / dd4hep::cm,
1680  rmax1 / dd4hep::cm,
1681  rmin2 / dd4hep::cm,
1682  rmax2 / dd4hep::cm,
1683  startPhi,
1684  deltaPhi);
1685 
1686 #endif
1687 
1688  ns.addSolid(nam, ConeSegment(dz, rmin1, rmax1, rmin2, rmax2, startPhi, phi2));
1689 }
1690 
1692 template <>
1693 void Converter<DDLShapeless>::operator()(xml_h element) const {
1694  cms::DDNamespace ns(_param<cms::DDParsingContext>());
1695  xml_dim_t e(element);
1696  string nam = e.nameStr();
1697 
1698 #ifdef EDM_ML_DEBUG
1699 
1700  printout(ns.context()->debug_shapes ? ALWAYS : DEBUG,
1701  "DD4CMS",
1702  "+ Shapeless: THIS ONE CAN ONLY BE USED AT THE VOLUME LEVEL -> Shapeless: %s",
1703  nam.c_str());
1704 
1705 #endif
1706 
1707  ns.addSolid(nam, Box(1, 1, 1));
1708 }
1709 
1711 template <>
1712 void Converter<DDLAssembly>::operator()(xml_h element) const {
1713  cms::DDNamespace ns(_param<cms::DDParsingContext>());
1714  xml_dim_t e(element);
1715  string nam = e.nameStr();
1716 
1717 #ifdef EDM_ML_DEBUG
1718  printout(
1719  ns.context()->debug_shapes ? ALWAYS : DEBUG, "DD4CMS", "+ Assembly: Adding solid -> Assembly: %s", nam.c_str());
1720 #endif
1721 
1722  ns.addAssemblySolid(nam);
1723 }
1724 
1726 template <>
1727 void Converter<DDLBox>::operator()(xml_h element) const {
1728  cms::DDNamespace ns(_param<cms::DDParsingContext>());
1729  xml_dim_t e(element);
1730  string nam = e.nameStr();
1731  double dx = ns.attr<double>(e, DD_CMU(dx));
1732  double dy = ns.attr<double>(e, DD_CMU(dy));
1733  double dz = ns.attr<double>(e, DD_CMU(dz));
1734 
1735 #ifdef EDM_ML_DEBUG
1736 
1737  printout(ns.context()->debug_shapes ? ALWAYS : DEBUG,
1738  "DD4CMS",
1739  "+ Box: dx=%10.3f [cm] dy=%10.3f [cm] dz=%10.3f [cm]",
1740  dx / dd4hep::cm,
1741  dy / dd4hep::cm,
1742  dz / dd4hep::cm);
1743 
1744 #endif
1745 
1746  ns.addSolid(nam, Box(dx, dy, dz));
1747 }
1748 
1750 template <>
1751 void Converter<include_load>::operator()(xml_h element) const {
1752  string fname = element.attr<string>(_U(ref));
1754  xml::Document doc;
1755  doc = xml::DocumentHandler().load(fp.fullPath());
1756 
1757 #ifdef EDM_ML_DEBUG
1758 
1759  printout(_param<cms::DDParsingContext>()->debug_includes ? ALWAYS : DEBUG,
1760  "DD4CMS",
1761  "+++ Processing the CMS detector description %s",
1762  fname.c_str());
1763 
1764 #endif
1765 
1766  _option<DDRegistry>()->includes.emplace_back(doc);
1767 }
1768 
1770 template <>
1771 void Converter<include_unload>::operator()(xml_h element) const {
1772  string fname = xml::DocumentHandler::system_path(element);
1773  xml::DocumentHolder(xml_elt_t(element).document()).assign(nullptr);
1774 
1775 #ifdef EDM_ML_DEBUG
1776 
1777  printout(_param<cms::DDParsingContext>()->debug_includes ? ALWAYS : DEBUG,
1778  "DD4CMS",
1779  "+++ Finished processing %s",
1780  fname.c_str());
1781 #endif
1782 }
1783 
1785 template <>
1786 void Converter<include_constants>::operator()(xml_h element) const {
1787  xml_coll_t(element, DD_CMU(ConstantsSection)).for_each(Converter<ConstantsSection>(description, param, optional));
1788 }
1789 
1790 namespace {
1791 
1792  // The meaning of the axis index is the following:
1793  // for all volumes having shapes like box, trd1, trd2, trap, gtra or para - 1,2,3 means X,Y,Z;
1794  // for tube, tubs, cone, cons - 1 means Rxy, 2 means phi and 3 means Z;
1795  // for pcon and pgon - 2 means phi and 3 means Z;
1796  // for spheres 1 means R and 2 means phi.
1797 
1798  enum class DDAxes { x = 1, y = 2, z = 3, rho = 1, phi = 2, undefined };
1799  const std::map<std::string, DDAxes> axesmap{{"x", DDAxes::x},
1800  {"y", DDAxes::y},
1801  {"z", DDAxes::z},
1802  {"rho", DDAxes::rho},
1803  {"phi", DDAxes::phi},
1804  {"undefined", DDAxes::undefined}};
1805 } // namespace
1806 
1808 template <>
1809 void Converter<DDLDivision>::operator()(xml_h element) const {
1810  cms::DDNamespace ns(_param<cms::DDParsingContext>(), element);
1811  xml_dim_t e(element);
1812  string childName = e.nameStr();
1813  if (strchr(childName.c_str(), NAMESPACE_SEP) == nullptr)
1814  childName = ns.prepend(childName);
1815 
1816  string parentName = ns.attr<string>(e, DD_CMU(parent));
1817  if (strchr(parentName.c_str(), NAMESPACE_SEP) == nullptr)
1818  parentName = ns.prepend(parentName);
1819  string axis = ns.attr<string>(e, DD_CMU(axis));
1820 
1821  // If you divide a tube of 360 degrees the offset displaces
1822  // the starting angle, but you still fill the 360 degrees
1823  double offset = e.hasAttr(DD_CMU(offset)) ? ns.attr<double>(e, DD_CMU(offset)) : 0e0;
1824  double width = e.hasAttr(DD_CMU(width)) ? ns.attr<double>(e, DD_CMU(width)) : 0e0;
1825  int nReplicas = e.hasAttr(DD_CMU(nReplicas)) ? ns.attr<int>(e, DD_CMU(nReplicas)) : 0;
1826 
1827 #ifdef EDM_ML_DEBUG
1828 
1829  printout(ns.context()->debug_placements ? ALWAYS : DEBUG,
1830  "DD4CMS",
1831  "+++ Start executing Division of %s along %s (%d) with offset %6.3f and %6.3f to produce %s....",
1832  parentName.c_str(),
1833  axis.c_str(),
1834  axesmap.at(axis),
1835  offset,
1836  width,
1837  childName.c_str());
1838 
1839 #endif
1840 
1841  Volume parent = ns.volume(parentName);
1842 
1843  const TGeoShape* shape = parent.solid();
1844  TClass* cl = shape->IsA();
1845  if (cl == TGeoTubeSeg::Class()) {
1846  const TGeoTubeSeg* sh = (const TGeoTubeSeg*)shape;
1847  double widthInDeg = convertRadToDeg(width);
1848  double startInDeg = convertRadToDeg(offset);
1849  int numCopies = (int)((sh->GetPhi2() - sh->GetPhi1()) / widthInDeg);
1850 
1851 #ifdef EDM_ML_DEBUG
1852 
1853  printout(ns.context()->debug_placements ? ALWAYS : DEBUG,
1854  "DD4CMS",
1855  "+++ ...divide %s along %s (%d) with offset %6.3f deg and %6.3f deg to produce %d copies",
1856  parent.solid().type(),
1857  axis.c_str(),
1858  axesmap.at(axis),
1859  startInDeg,
1860  widthInDeg,
1861  numCopies);
1862 
1863 #endif
1864 
1865  Volume child = parent.divide(childName, static_cast<int>(axesmap.at(axis)), numCopies, startInDeg, widthInDeg);
1866 
1867  ns.context()->volumes[childName] = child;
1868 
1869 #ifdef EDM_ML_DEBUG
1870 
1871  printout(ns.context()->debug_placements ? ALWAYS : DEBUG,
1872  "DD4CMS",
1873  "+++ %s Parent: %-24s [%s] Child: %-32s [%s] is multivolume [%s]",
1874  e.tag().c_str(),
1875  parentName.c_str(),
1876  parent.isValid() ? "VALID" : "INVALID",
1877  child.name(),
1878  child.isValid() ? "VALID" : "INVALID",
1879  child->IsVolumeMulti() ? "YES" : "NO");
1880 #endif
1881 
1882  } else if (cl == TGeoTrd1::Class()) {
1883  double dy = static_cast<const TGeoTrd1*>(shape)->GetDy();
1884 
1885 #ifdef EDM_ML_DEBUG
1886 
1887  printout(ns.context()->debug_placements ? ALWAYS : DEBUG,
1888  "DD4CMS",
1889  "+++ ...divide %s along %s (%d) with offset %6.3f cm and %6.3f cm to produce %d copies in %6.3f",
1890  parent.solid().type(),
1891  axis.c_str(),
1892  axesmap.at(axis),
1893  -dy + offset + width,
1894  width,
1895  nReplicas,
1896  dy);
1897 
1898 #endif
1899 
1900  Volume child = parent.divide(childName, static_cast<int>(axesmap.at(axis)), nReplicas, -dy + offset + width, width);
1901 
1902  ns.context()->volumes[childName] = child;
1903 
1904 #ifdef EDM_ML_DEBUG
1905 
1906  printout(ns.context()->debug_placements ? ALWAYS : DEBUG,
1907  "DD4CMS",
1908  "+++ %s Parent: %-24s [%s] Child: %-32s [%s] is multivolume [%s]",
1909  e.tag().c_str(),
1910  parentName.c_str(),
1911  parent.isValid() ? "VALID" : "INVALID",
1912  child.name(),
1913  child.isValid() ? "VALID" : "INVALID",
1914  child->IsVolumeMulti() ? "YES" : "NO");
1915 
1916 #endif
1917  } else {
1918  printout(ERROR, "DD4CMS", "++ FAILED Division of a %s is not implemented yet!", parent.solid().type());
1919  }
1920 }
1921 
1923 template <>
1924 void Converter<DDLAlgorithm>::operator()(xml_h element) const {
1925  cms::DDNamespace ns(_param<cms::DDParsingContext>());
1926  xml_dim_t e(element);
1927  string name = e.nameStr();
1928  size_t idx;
1929  string type = "DDCMS_" + ns.realName(name);
1930  while ((idx = type.find(NAMESPACE_SEP)) != string::npos)
1931  type[idx] = '_';
1932 
1933 #ifdef EDM_ML_DEBUG
1934 
1935  printout(
1936  ns.context()->debug_algorithms ? ALWAYS : DEBUG, "DD4CMS", "+++ Start executing algorithm %s....", type.c_str());
1937 
1938 #endif
1939 
1940  long ret = PluginService::Create<long>(type, &description, ns.context(), &element);
1941  if (ret == s_executed) {
1942 #ifdef EDM_ML_DEBUG
1943 
1944  printout(ns.context()->debug_algorithms ? ALWAYS : DEBUG,
1945 
1946  "DD4CMS",
1947  "+++ Executed algorithm: %08lX = %s",
1948  ret,
1949  name.c_str());
1950 
1951 #endif
1952  return;
1953  }
1954  printout(ERROR, "DD4CMS", "++ FAILED NOT ADDING SUBDETECTOR %08lX = %s", ret, name.c_str());
1955 }
1956 
1957 template <class InputIt, class ForwardIt, class BinOp>
1958 void for_each_token(InputIt first, InputIt last, ForwardIt s_first, ForwardIt s_last, BinOp binary_op) {
1959  while (first != last) {
1960  const auto pos = std::find_first_of(first, last, s_first, s_last);
1961  binary_op(first, pos);
1962  if (pos == last)
1963  break;
1964  first = std::next(pos);
1965  }
1966 }
1967 
1968 namespace {
1969 
1970  std::vector<string> splitString(const string& str, const string& delims = ",") {
1971  std::vector<string> output;
1972 
1973  for_each_token(cbegin(str), cend(str), cbegin(delims), cend(delims), [&output](auto first, auto second) {
1974  if (first != second) {
1975  if (string(first, second).front() == '[' && string(first, second).back() == ']') {
1976  first++;
1977  second--;
1978  }
1979  output.emplace_back(string(first, second));
1980  }
1981  });
1982  return output;
1983  }
1984 
1985  std::vector<double> splitNumeric(const string& str, const string& delims = ",") {
1986  std::vector<double> output;
1987 
1988  for_each_token(cbegin(str), cend(str), cbegin(delims), cend(delims), [&output](auto first, auto second) {
1989  if (first != second) {
1990  if (string(first, second).front() == '[' && string(first, second).back() == ']') {
1991  first++;
1992  second--;
1993  }
1994  output.emplace_back(dd4hep::_toDouble(string(first, second)));
1995  }
1996  });
1997  return output;
1998  }
1999 } // namespace
2000 
2003 template <>
2004 void Converter<DDLVector>::operator()(xml_h element) const {
2005  cms::DDNamespace ns(_param<cms::DDParsingContext>());
2006  cms::DDParsingContext* const context = ns.context();
2007  DDVectorsMap* registry = context->description.extension<DDVectorsMap>();
2008  xml_dim_t e(element);
2009  string name = ns.prepend(e.nameStr());
2010  string type = ns.attr<string>(e, _U(type));
2011  string nEntries = ns.attr<string>(e, DD_CMU(nEntries));
2012  string val = e.text();
2013  val.erase(remove_if(val.begin(), val.end(), [](unsigned char x) { return isspace(x); }), val.end());
2014 
2015 #ifdef EDM_ML_DEBUG
2016 
2017  printout(ns.context()->debug_constants ? ALWAYS : DEBUG,
2018  "DD4CMS",
2019  "+++ Vector<%s>: %s[%s]: %s",
2020  type.c_str(),
2021  name.c_str(),
2022  nEntries.c_str(),
2023  val.c_str());
2024 
2025 #endif
2026 
2027  try {
2028  std::vector<double> results = splitNumeric(val);
2029  registry->insert(
2030  {name,
2031  results}); //tbb::concurrent_vector<double, tbb::cache_aligned_allocator<double>>(results.begin(), results.end())});
2032  } catch (const exception& e) {
2033 #ifdef EDM_ML_DEBUG
2034 
2035  printout(INFO,
2036  "DD4CMS",
2037  "++ Unresolved Vector<%s>: %s[%s]: %s. Try to resolve later. [%s]",
2038  type.c_str(),
2039  name.c_str(),
2040  nEntries.c_str(),
2041  val.c_str(),
2042  e.what());
2043 
2044 #endif
2045 
2046  std::vector<string> results = splitString(val);
2047  context->unresolvedVectors.insert({name, results});
2048  }
2049 }
2050 
2051 template <>
2052 void Converter<debug>::operator()(xml_h dbg) const {
2053  cms::DDNamespace ns(_param<cms::DDParsingContext>());
2054  if (dbg.hasChild(DD_CMU(debug_constants)))
2055  ns.setContext()->debug_constants = true;
2056  if (dbg.hasChild(DD_CMU(debug_materials)))
2057  ns.setContext()->debug_materials = true;
2058  if (dbg.hasChild(DD_CMU(debug_rotations)))
2059  ns.setContext()->debug_rotations = true;
2060  if (dbg.hasChild(DD_CMU(debug_shapes)))
2061  ns.setContext()->debug_shapes = true;
2062  if (dbg.hasChild(DD_CMU(debug_volumes)))
2063  ns.setContext()->debug_volumes = true;
2064  if (dbg.hasChild(DD_CMU(debug_placements)))
2065  ns.setContext()->debug_placements = true;
2066  if (dbg.hasChild(DD_CMU(debug_namespaces)))
2067  ns.setContext()->debug_namespaces = true;
2068  if (dbg.hasChild(DD_CMU(debug_includes)))
2069  ns.setContext()->debug_includes = true;
2070  if (dbg.hasChild(DD_CMU(debug_algorithms)))
2071  ns.setContext()->debug_algorithms = true;
2072  if (dbg.hasChild(DD_CMU(debug_specpars)))
2073  ns.setContext()->debug_specpars = true;
2074 }
2075 
2076 template <>
2077 void Converter<DDRegistry>::operator()(xml_h /* element */) const {
2078  cms::DDParsingContext* context = _param<cms::DDParsingContext>();
2079  DDRegistry* res = _option<DDRegistry>();
2081  int count = 0;
2082 
2083 #ifdef EDM_ML_DEBUG
2084 
2085  printout(context->debug_constants ? ALWAYS : DEBUG,
2086  "DD4CMS",
2087  "+++ RESOLVING %ld unknown constants..... (out of %ld)",
2088  res->unresolvedConst.size(),
2089  res->originalConst.size());
2090 #endif
2091 
2092  while (!res->unresolvedConst.empty()) {
2093  for (auto& i : res->unresolvedConst) {
2094  const string& n = i.first;
2095  string rep;
2096  string& v = i.second;
2097  size_t idx, idq;
2098  for (idx = v.find('[', 0); idx != string::npos; idx = v.find('[', idx + 1)) {
2099  idq = v.find(']', idx + 1);
2100  rep = v.substr(idx + 1, idq - idx - 1);
2101  auto r = res->originalConst.find(rep);
2102  if (r != res->originalConst.end()) {
2103  rep = "(" + (*r).second + ")";
2104  v.replace(idx, idq - idx + 1, rep);
2105  }
2106  }
2107  if (v.find(']') == string::npos) {
2108  if (v.find("-+") != string::npos || v.find("+-") != string::npos) {
2109  while ((idx = v.find("-+")) != string::npos)
2110  v.replace(idx, 2, "-");
2111  while ((idx = v.find("+-")) != string::npos)
2112  v.replace(idx, 2, "-");
2113  }
2114 
2115 #ifdef EDM_ML_DEBUG
2116 
2117  printout(context->debug_constants ? ALWAYS : DEBUG,
2118  "DD4CMS",
2119  "+++ [%06ld] ---------- %-40s = %s",
2120  res->unresolvedConst.size() - 1,
2121  n.c_str(),
2122  res->originalConst[n].c_str());
2123 
2124 #endif
2125 
2126  ns.addConstantNS(n, v, "number");
2127  res->unresolvedConst.erase(n);
2128  break;
2129  }
2130  }
2131  if (++count > 10000)
2132  break;
2133  }
2134  if (!res->unresolvedConst.empty()) {
2135  for (const auto& e : res->unresolvedConst)
2136  printout(ERROR, "DD4CMS", "+++ Unresolved constant: %-40s = %s.", e.first.c_str(), e.second.c_str());
2137  except("DD4CMS", "++ FAILED to resolve %ld constant entries:", res->unresolvedConst.size());
2138  }
2139  res->unresolvedConst.clear();
2140  res->originalConst.clear();
2141 }
2142 
2143 template <>
2144 void Converter<print_xml_doc>::operator()(xml_h element) const {
2145  string fname = xml::DocumentHandler::system_path(element);
2146 
2147 #ifdef EDM_ML_DEBUG
2148 
2149  printout(_param<cms::DDParsingContext>()->debug_includes ? ALWAYS : DEBUG,
2150  "DD4CMS",
2151  "+++ Processing data from: %s",
2152  fname.c_str());
2153 
2154 #endif
2155 }
2156 
2158 static long load_dddefinition(Detector& det, xml_h element) {
2159  xml_elt_t dddef(element);
2160  if (dddef) {
2161  cms::DDParsingContext& context = *det.extension<DDParsingContext>();
2163  ns.addConstantNS("world_x", "101*m", "number");
2164  ns.addConstantNS("world_y", "101*m", "number");
2165  ns.addConstantNS("world_z", "450*m", "number");
2166  ns.addConstantNS("Air", "materials:Air", "string");
2167  ns.addConstantNS("Vacuum", "materials:Vacuum", "string");
2168 
2169  string fname = xml::DocumentHandler::system_path(element);
2170  bool open_geometry = dddef.hasChild(DD_CMU(open_geometry)) ? dddef.child(DD_CMU(open_geometry)) : true;
2171  bool close_geometry = dddef.hasChild(DD_CMU(close_geometry)) ? dddef.hasChild(DD_CMU(close_geometry)) : true;
2172 
2173  xml_coll_t(dddef, _U(debug)).for_each(Converter<debug>(det, &context));
2174 
2175  // Here we define the order how XML elements are processed.
2176  // Be aware of dependencies. This can only defined once.
2177  // At the end it is a limitation of DOM....
2178  printout(INFO, "DD4CMS", "+++ Processing the CMS detector description %s", fname.c_str());
2179 
2180  xml::Document doc;
2181  Converter<print_xml_doc> print_doc(det, &context);
2182  try {
2183  DDRegistry res;
2184  res.unresolvedConst.reserve(2000);
2185  res.originalConst.reserve(6000);
2186  print_doc((doc = dddef.document()).root());
2187  xml_coll_t(dddef, DD_CMU(ConstantsSection)).for_each(Converter<ConstantsSection>(det, &context, &res));
2188  xml_coll_t(dddef, DD_CMU(RotationSection)).for_each(Converter<RotationSection>(det, &context));
2189  xml_coll_t(dddef, DD_CMU(MaterialSection)).for_each(Converter<MaterialSection>(det, &context));
2190 
2191  xml_coll_t(dddef, DD_CMU(IncludeSection)).for_each(DD_CMU(Include), Converter<include_load>(det, &context, &res));
2192 
2193  for (xml::Document d : res.includes) {
2194  print_doc((doc = d).root());
2195  Converter<include_constants>(det, &context, &res)((doc = d).root());
2196  }
2197  // Before we continue, we have to resolve all constants NOW!
2198  Converter<DDRegistry>(det, &context, &res)(dddef);
2199  {
2200  DDVectorsMap* registry = context.description.extension<DDVectorsMap>();
2201 
2202  printout(context.debug_constants ? ALWAYS : DEBUG,
2203  "DD4CMS",
2204  "+++ RESOLVING %ld Vectors.....",
2205  context.unresolvedVectors.size());
2206 
2207  while (!context.unresolvedVectors.empty()) {
2208  for (auto it = context.unresolvedVectors.begin(); it != context.unresolvedVectors.end();) {
2209  std::vector<double> result;
2210  for (const auto& i : it->second) {
2211  result.emplace_back(dd4hep::_toDouble(i));
2212  }
2213  registry->insert({it->first, result});
2214  // All components are resolved
2215  it = context.unresolvedVectors.erase(it);
2216  }
2217  }
2218  }
2219  // Now we can process the include files one by one.....
2220  for (xml::Document d : res.includes) {
2221  print_doc((doc = d).root());
2222  xml_coll_t(d.root(), DD_CMU(MaterialSection)).for_each(Converter<MaterialSection>(det, &context));
2223  }
2224  {
2225  printout(context.debug_materials ? ALWAYS : DEBUG,
2226  "DD4CMS",
2227  "+++ RESOLVING %ld unknown material constituents.....",
2228  context.unresolvedMaterials.size());
2229 
2230  // Resolve referenced materials (if any)
2231 
2232  while (!context.unresolvedMaterials.empty()) {
2233  for (auto it = context.unresolvedMaterials.begin(); it != context.unresolvedMaterials.end();) {
2234  auto const& name = it->first;
2235  std::vector<bool> valid;
2236 
2237  printout(context.debug_materials ? ALWAYS : DEBUG,
2238  "DD4CMS",
2239  "+++ [%06ld] ---------- %s",
2240  context.unresolvedMaterials.size(),
2241  name.c_str());
2242 
2243  auto mat = ns.material(name);
2244  for (auto& mit : it->second) {
2245  printout(context.debug_materials ? ALWAYS : DEBUG,
2246  "DD4CMS",
2247  "+++ component %-48s Fraction: %.6f",
2248  mit.name.c_str(),
2249  mit.fraction);
2250  auto fmat = ns.material(mit.name);
2251  if (nullptr != fmat.ptr()) {
2252  if (mat.ptr()->GetMaterial()->IsMixture()) {
2253  valid.emplace_back(true);
2254  static_cast<TGeoMixture*>(mat.ptr()->GetMaterial())
2255  ->AddElement(fmat.ptr()->GetMaterial(), mit.fraction);
2256  }
2257  }
2258  }
2259  // All components are resolved
2260  if (valid.size() == it->second.size())
2261  it = context.unresolvedMaterials.erase(it);
2262  else
2263  ++it;
2264  }
2265  // Do it again if there are unresolved
2266  // materials left after this pass
2267  }
2268  }
2269  if (open_geometry) {
2270  det.init();
2271  ns.addVolume(det.worldVolume());
2272  }
2273  for (xml::Document d : res.includes) {
2274  print_doc((doc = d).root());
2275  xml_coll_t(d.root(), DD_CMU(RotationSection)).for_each(Converter<RotationSection>(det, &context));
2276  }
2277  for (xml::Document d : res.includes) {
2278  print_doc((doc = d).root());
2279  xml_coll_t(d.root(), DD_CMU(SolidSection)).for_each(Converter<SolidSection>(det, &context));
2280  }
2281  for (xml::Document d : res.includes) {
2282  print_doc((doc = d).root());
2283  xml_coll_t(d.root(), DD_CMU(LogicalPartSection)).for_each(Converter<LogicalPartSection>(det, &context));
2284  }
2285  for (xml::Document d : res.includes) {
2286  print_doc((doc = d).root());
2287  xml_coll_t(d.root(), DD_CMU(Algorithm)).for_each(Converter<DDLAlgorithm>(det, &context));
2288  }
2289  for (xml::Document d : res.includes) {
2290  print_doc((doc = d).root());
2291  xml_coll_t(d.root(), DD_CMU(PosPartSection)).for_each(Converter<PosPartSection>(det, &context));
2292  }
2293  for (xml::Document d : res.includes) {
2294  print_doc((doc = d).root());
2295  xml_coll_t(d.root(), DD_CMU(SpecParSection)).for_each(Converter<SpecParSection>(det, &context));
2296  }
2297 
2299  for (xml::Document d : res.includes)
2300  Converter<include_unload>(det, &context, &res)(d.root());
2301 
2302  print_doc((doc = dddef.document()).root());
2303  // Now process the actual geometry items
2304  xml_coll_t(dddef, DD_CMU(SolidSection)).for_each(Converter<SolidSection>(det, &context));
2305  {
2306  // Before we continue, we have to resolve all shapes NOW!
2307  // Note: This only happens in a legacy DB payloads where
2308  // boolean shapes can be defined before thier
2309  // component shapes
2310 
2311  while (!context.unresolvedShapes.empty()) {
2312  for (auto it = context.unresolvedShapes.begin(); it != context.unresolvedShapes.end();) {
2313  auto const& name = it->first;
2314  auto const& aname = std::visit([](auto&& arg) -> std::string { return arg.firstSolidName; }, it->second);
2315  auto const& bname = std::visit([](auto&& arg) -> std::string { return arg.secondSolidName; }, it->second);
2316 
2317  auto const& ait = context.shapes.find(aname);
2318  if (ait->second.isValid()) {
2319  auto const& bit = context.shapes.find(bname);
2320  if (bit->second.isValid()) {
2321  dd4hep::Solid shape =
2322  std::visit([&ait, &bit](auto&& arg) -> dd4hep::Solid { return arg.make(ait->second, bit->second); },
2323  it->second);
2324  context.shapes[name] = shape;
2325  it = context.unresolvedShapes.erase(it);
2326  } else
2327  ++it;
2328  } else
2329  ++it;
2330  }
2331  }
2332  }
2333  xml_coll_t(dddef, DD_CMU(LogicalPartSection)).for_each(Converter<LogicalPartSection>(det, &context));
2334  xml_coll_t(dddef, DD_CMU(Algorithm)).for_each(Converter<DDLAlgorithm>(det, &context));
2335  xml_coll_t(dddef, DD_CMU(PosPartSection)).for_each(Converter<PosPartSection>(det, &context));
2336  xml_coll_t(dddef, DD_CMU(SpecParSection)).for_each(Converter<SpecParSection>(det, &context));
2337  } catch (const exception& e) {
2338  printout(ERROR, "DD4CMS", "Exception while processing xml source:%s", doc.uri().c_str());
2339  printout(ERROR, "DD4CMS", "----> %s", e.what());
2340  throw;
2341  }
2342 
2344  if (close_geometry) {
2345  Volume wv = det.worldVolume();
2346  Volume geomv = ns.volume("cms:OCMS", false);
2347  if (geomv.isValid())
2348  wv.placeVolume(geomv, 1);
2349  Volume mfv = ns.volume("cmsMagneticField:MAGF", false);
2350  if (mfv.isValid())
2351  wv.placeVolume(mfv, 1);
2352  Volume mfv1 = ns.volume("MagneticFieldVolumes:MAGF", false);
2353  if (mfv1.isValid())
2354  wv.placeVolume(mfv1, 1);
2355 
2356  // Can not deal with reflections without closed geometry
2357  det.manager().CloseGeometry();
2358 
2359  det.endDocument();
2360  }
2361  printout(INFO, "DDDefinition", "+++ Finished processing %s", fname.c_str());
2362  return 1;
2363  }
2364  except("DDDefinition", "+++ FAILED to process unknown DOM tree [Invalid Handle]");
2365  return 0;
2366 }
2367 
2368 // Now declare the factory entry for the plugin mechanism
2369 DECLARE_XML_DOC_READER(DDDefinition, load_dddefinition)
DDLVector
DDLVector handles Rotation and ReflectionRotation elements.
Definition: DDLVector.h:29
runTheMatrix.ret
ret
prodAgent to be discontinued
Definition: runTheMatrix.py:543
originalConst
std::unordered_map< std::string, std::string > originalConst
Definition: DDDefinitions2Objects.cc:56
cms::DDNamespace::assembly
dd4hep::Assembly assembly(const std::string &name, bool exception=true) const
Definition: DDNamespace.cc:247
DDAxes::y
photonAnalyzer_cfi.rMax
rMax
Definition: photonAnalyzer_cfi.py:91
ApeEstimator_cff.width
width
Definition: ApeEstimator_cff.py:24
pixelCPEforGPU::Rotation
SOARotation< float > Rotation
Definition: pixelCPEforGPU.h:19
mps_fire.i
i
Definition: mps_fire.py:428
cms_units::operators
Definition: CMSUnits.h:13
geometryCSVtoXML.zz
zz
Definition: geometryCSVtoXML.py:19
geometryCSVtoXML.yz
yz
Definition: geometryCSVtoXML.py:19
g4SimHits_cfi.Material
Material
Definition: g4SimHits_cfi.py:594
dqmiodumpmetadata.n
n
Definition: dqmiodumpmetadata.py:28
funct::Constant
Polynomial< 0 > Constant
Definition: Constant.h:6
for_each_token
void for_each_token(InputIt first, InputIt last, ForwardIt s_first, ForwardIt s_last, BinOp binary_op)
Definition: DDDefinitions2Objects.cc:1958
cms::DDNamespace::solid
dd4hep::Solid solid(const std::string &name) const
Definition: DDNamespace.cc:299
HLT_FULL_cff.Class
Class
Definition: HLT_FULL_cff.py:8399
L1EGammaCrystalsEmulatorProducer_cfi.scale
scale
Definition: L1EGammaCrystalsEmulatorProducer_cfi.py:10
cms::hash
constexpr unsigned int hash(const char *str, int h=0)
Definition: DDAlgoArguments.h:18
DDLSpecPar
DDLSpecPar processes SpecPar elements.
Definition: DDLSpecPar.h:26
placeAssembly
static void placeAssembly(Volume *parentPtr, const string &parentName, Volume *childPtr, const string &childName, int copy, const Transform3D &transform, cms::DDNamespace &ns)
Definition: DDDefinitions2Objects.cc:874
filterCSVwithJSON.copy
copy
Definition: filterCSVwithJSON.py:36
DDLSphere
DDLSphere processes all Sphere elements.
Definition: DDLSphere.h:24
DDParsingContext.h
boostedTaus_cff.doc
doc
Definition: boostedTaus_cff.py:20
DiDispStaMuonMonitor_cfi.pt
pt
Definition: DiDispStaMuonMonitor_cfi.py:39
convertSQLitetoXML_cfg.output
output
Definition: convertSQLitetoXML_cfg.py:72
DDLTubs
DDLTubs processes Tubs elements.
Definition: DDLTubs.h:21
cond::hash
Definition: Time.h:19
cms::DDParsingContext
Definition: DDParsingContext.h:14
angle_units::operators::convertRadToDeg
constexpr NumType convertRadToDeg(NumType radians)
Definition: angle_units.h:21
cms::DDNamespace
Definition: DDNamespace.h:22
edmLumisInFiles.description
description
Definition: edmLumisInFiles.py:11
pos
Definition: PixelAliasList.h:18
cms::DDParsingContext::debug_placements
bool debug_placements
Definition: DDParsingContext.h:71
interestingEgammaIsoDetIdsSequence_cff.outerRadius
outerRadius
Definition: interestingEgammaIsoDetIdsSequence_cff.py:14
Types.optional
optional
Definition: Types.py:198
cms::makeRotation3D
DDRotationMatrix makeRotation3D(double thetaX, double phiX, double thetaY, double phiY, double thetaZ, double phiZ)
Definition: DDAlgoArguments.cc:20
edm::second
U second(std::pair< T, U > const &p)
Definition: ParameterSet.cc:222
bookConverter.results
results
Definition: bookConverter.py:144
splitString
std::vector< std::string > splitString(const std::string &fLine)
Definition: HcalDbASCIIIO.cc:55
DDLPseudoTrap
Definition: DDLPseudoTrap.h:23
personalPlayback.fp
fp
Definition: personalPlayback.py:523
DDLLogicalPart
DDLLogicalPart processes LogicalPart elements.
Definition: DDLLogicalPart.h:34
cms::DDParsingContext::CompositeMaterial
Definition: DDParsingContext.h:57
DDAxes::x
gpuVertexFinder::wv
float *__restrict__ wv
Definition: gpuFitVertices.h:27
cms::PlacedVolume
dd4hep::PlacedVolume PlacedVolume
Definition: DDFilteredView.h:48
findQualityFiles.v
v
Definition: findQualityFiles.py:179
DDLElementaryMaterial
DDLElementaryMaterial processes ElementaryMaterial elements.
Definition: DDLElementaryMaterial.h:28
DDDetector.h
l1tVertexFinder::Algorithm
Algorithm
Definition: AlgoSettings.h:12
DDLCompositeMaterial
DDLCompositeMaterial processes all CompositeMaterial elements.
Definition: DDLCompositeMaterial.h:31
geometryDiff.epsilon
int epsilon
Definition: geometryDiff.py:26
heavyIonCSV_trainingSettings.idx
idx
Definition: heavyIonCSV_trainingSettings.py:5
Vector
ROOT::Math::Plane3D::Vector Vector
Definition: EcalHitMaker.cc:29
visDQMUpload.context
context
Definition: visDQMUpload.py:37
DDLCone
DDLCone processes all Cone elements.
Definition: DDLCone.h:27
GetRecoTauVFromDQM_MC_cff.cl
cl
Definition: GetRecoTauVFromDQM_MC_cff.py:38
edm::FileInPath
Definition: FileInPath.h:61
unresolvedConst
std::unordered_map< std::string, std::string > unresolvedConst
Definition: DDDefinitions2Objects.cc:55
dqmdumpme.last
last
Definition: dqmdumpme.py:56
debug
#define debug
Definition: HDRShower.cc:19
convert_boolean
static void convert_boolean(cms::DDParsingContext *context, xml_h element)
Definition: DDDefinitions2Objects.cc:1136
DDAxes::undefined
DDLEllipticalTube
DDLEllipticalTube processes all EllipticalTube elements.
Definition: DDLEllipticalTube.h:24
SiPixelRawToDigiRegional_cfi.deltaPhi
deltaPhi
Definition: SiPixelRawToDigiRegional_cfi.py:9
HLT_FULL_cff.fraction
fraction
Definition: HLT_FULL_cff.py:52823
DDLBox
DDLBox processes Box elements.
Definition: DDLBox.h:27
DDAxes::z
str
#define str(s)
Definition: TestProcessor.cc:53
DDLRotationByAxis
DDLRotationByAxis handles RotationByAxis elements.
Definition: DDLRotationByAxis.h:25
submitPVResolutionJobs.count
count
Definition: submitPVResolutionJobs.py:352
theta
Geom::Theta< T > theta() const
Definition: Basic3DVectorLD.h:150
HcalDetIdTransform::transform
unsigned transform(const HcalDetId &id, unsigned transformCode)
Definition: HcalDetIdTransform.cc:7
PixelTestBeamValidation_cfi.Position
Position
Definition: PixelTestBeamValidation_cfi.py:83
DDLTorus
Definition: DDLTorus.h:23
DDLAlgorithm
DDLAlgorithm processes Algorithm elements.
Definition: DDLAlgorithm.h:25
sistrip::SpyUtilities::isValid
const bool isValid(const Frame &aFrame, const FrameQuality &aQuality, const uint16_t aExpectedPos)
Definition: SiStripSpyUtilities.cc:124
first
auto first
Definition: CAHitNtupletGeneratorKernelsImpl.h:125
DDLPosPart
DDLPosPart handles PosPart elements.
Definition: DDLPosPart.h:27
geometryCSVtoXML.xy
xy
Definition: geometryCSVtoXML.py:19
DDAlgoArguments.h
DDAxes::rho
FileInPath.h
cms::DDParsingContext::shapes
std::unordered_map< std::string, dd4hep::Solid > shapes
Definition: DDParsingContext.h:83
unpackBuffers-CaloStage2.INFO
INFO
Definition: unpackBuffers-CaloStage2.py:169
cppFunctionSkipper.exception
exception
Definition: cppFunctionSkipper.py:10
cms::Volume
dd4hep::Volume Volume
Definition: DDFilteredView.h:47
idealTransformation.rotation
dictionary rotation
Definition: idealTransformation.py:1
geometryCSVtoXML.yy
yy
Definition: geometryCSVtoXML.py:19
cms::DDParsingContext::BooleanShape
Definition: DDParsingContext.h:44
DDAxes
DDAxes
analagous to geant4/source/global/HEPGeometry/include/geomdefs.hh
Definition: DDAxes.h:11
type
type
Definition: SiPixelVCal_PayloadInspector.cc:39
geometryCSVtoXML.xz
xz
Definition: geometryCSVtoXML.py:19
thread_safety_macros.h
interestingEgammaIsoDetIdsSequence_cff.innerRadius
innerRadius
Definition: interestingEgammaIsoDetIdsSequence_cff.py:15
includes
std::vector< xml::Document > includes
Definition: DDDefinitions2Objects.cc:54
createfilelist.int
int
Definition: createfilelist.py:10
MetAnalyzer.pv
def pv(vc)
Definition: MetAnalyzer.py:7
load_dddefinition
static long load_dddefinition(Detector &det, xml_h element)
Converter for <DDDefinition> tags.
Definition: DDDefinitions2Objects.cc:2158
value
Definition: value.py:1
cuy.rep
rep
Definition: cuy.py:1189
root
Definition: RooFitFunction.h:10
M_PI
#define M_PI
Definition: BXVectorInputProducer.cc:49
DDLRotationSequence
DDLRotationSequence handles a set of Rotations.
Definition: DDLRotationSequence.h:24
Translation
ROOT::Math::DisplacementVector3D< ROOT::Math::Cartesian3D< double > > Translation
Definition: PGeometricDetBuilder.cc:21
cms::DDNamespace::addSolid
dd4hep::Solid addSolid(const std::string &name, dd4hep::Solid solid) const
Definition: DDNamespace.cc:295
PVValHelper::dy
Definition: PVValidationHelpers.h:50
DOFs::thetaY
Definition: AlignPCLThresholdsWriter.cc:37
DDLTrapezoid
Definition: DDLTrapezoid.h:23
res
Definition: Electron.h:6
AlCaHLTBitMon_QueryRunRegistry.string
string string
Definition: AlCaHLTBitMon_QueryRunRegistry.py:256
fileinputsource_cfi.sec
sec
Definition: fileinputsource_cfi.py:94
cms::s_executed
static constexpr long s_executed
Definition: DDAlgoArguments.h:16
alignCSCRings.r
r
Definition: alignCSCRings.py:93
DDAxes::phi
alignmentValidation.fname
string fname
main script
Definition: alignmentValidation.py:959
DOFs::thetaX
Definition: AlignPCLThresholdsWriter.cc:37
align::Detector
Definition: StructureType.h:92
bookConverter.elements
elements
Definition: bookConverter.py:147
heppy_batch.val
val
Definition: heppy_batch.py:351
eostools.move
def move(src, dest)
Definition: eostools.py:511
std
Definition: JetResolutionObject.h:76
submitPVValidationJobs.child
child
Definition: submitPVValidationJobs.py:119
cms::rotation_utils::rotName
static const std::string & rotName(const T &rot, const cms::DDParsingContext &context)
Definition: DDCoreToDDXMLOutput.cc:81
DDLDivision
DDLDivision processes Division elements.
Definition: DDLDivision.h:27
PVValHelper::dz
Definition: PVValidationHelpers.h:51
cms::DDNamespace::context
DDParsingContext *const context() const
Definition: DDNamespace.h:76
DOFs::thetaZ
Definition: AlignPCLThresholdsWriter.cc:37
HGCalGeometryMode::Polyhedra
Definition: HGCalGeometryMode.h:37
relativeConstraints.value
value
Definition: relativeConstraints.py:53
dd4hep
Definition: DDPlugins.h:8
runonSM.TYPE
TYPE
Definition: runonSM.py:21
cms::DDVectorsMap
std::unordered_map< std::string, std::vector< double > > DDVectorsMap
Definition: DDNamespace.h:20
genVertex_cff.x
x
Definition: genVertex_cff.py:13
DD_CMU
#define DD_CMU(a)
Definition: DDXMLTags.h:183
makeMuonMisalignmentScenario.rot
rot
Definition: makeMuonMisalignmentScenario.py:322
CosmicsPD_Skims.radius
radius
Definition: CosmicsPD_Skims.py:135
HGCalGeometryMode::ExtrudedPolygon
Definition: HGCalGeometryMode.h:37
angle
T angle(T x1, T y1, T z1, T x2, T y2, T z2)
Definition: angle.h:11
Skims_PA_cff.name
name
Definition: Skims_PA_cff.py:17
DEBUG
#define DEBUG
Definition: DMRChecker.cc:119
CMSUnits.h
DDNamespace.h
NAMESPACE_SEP
#define NAMESPACE_SEP
Definition: DDNamespace.h:92
photonAnalyzer_cfi.rMin
rMin
Definition: photonAnalyzer_cfi.py:90
funct::arg
A arg
Definition: Factorize.h:31
ztail.d
d
Definition: ztail.py:151
mps_fire.result
result
Definition: mps_fire.py:311
castor_dqm_sourceclient_file_cfg.path
path
Definition: castor_dqm_sourceclient_file_cfg.py:37
funct::abs
Abs< T >::type abs(const T &t)
Definition: Abs.h:22
RunInfoPI::valid
Definition: RunInfoPayloadInspectoHelper.h:16
c
auto & c
Definition: CAHitNtupletGeneratorKernelsImpl.h:56
hltrates_dqm_sourceclient-live_cfg.offset
offset
Definition: hltrates_dqm_sourceclient-live_cfg.py:82
child
Definition: simpleInheritance.h:11
dqm::qstatus::ERROR
static const int ERROR
Definition: MonitorElement.h:54
submitPVValidationJobs.t
string t
Definition: submitPVValidationJobs.py:644
GeneratorMix_cff.mix
mix
Definition: GeneratorMix_cff.py:6
dd4hep::createPlacement
TGeoCombiTrans * createPlacement(const Rotation3D &iRot, const Position &iTrans)
Definition: DDDefinitions2Objects.cc:110
DDLAssembly
DDLAssembly processes Assembly elements.
Definition: DDLAssembly.h:21
cms::DDParsingContext::unresolvedShapes
std::unordered_map< std::string, std::variant< BooleanShape< dd4hep::UnionSolid >, BooleanShape< dd4hep::SubtractionSolid >, BooleanShape< dd4hep::IntersectionSolid > > > unresolvedShapes
Definition: DDParsingContext.h:95
class-composition.parent
parent
Definition: class-composition.py:98
PVValHelper::dx
Definition: PVValidationHelpers.h:49
geometryCSVtoXML.xx
xx
Definition: geometryCSVtoXML.py:19
g
The Signals That Services Can Subscribe To This is based on ActivityRegistry and is current per Services can connect to the signals distributed by the ActivityRegistry in order to monitor the activity of the application Each possible callback has some defined which we here list in angle e g
Definition: Activities.doc:4
fastSimProducer_cff.density
density
Definition: fastSimProducer_cff.py:61
GetRecoTauVFromDQM_MC_cff.next
next
Definition: GetRecoTauVFromDQM_MC_cff.py:31
cms
Namespace of DDCMS conversion namespace.
Definition: ProducerAnalyzer.cc:21
MillePedeFileConverter_cfg.e
e
Definition: MillePedeFileConverter_cfg.py:37
cms::makeRotReflect
DDRotationMatrix makeRotReflect(double thetaX, double phiX, double thetaY, double phiY, double thetaZ, double phiZ)
Definition: DDAlgoArguments.cc:32