CMS 3D CMS Logo

 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Friends Macros Groups Pages
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"
21 
22 #include "TGeoManager.h"
23 #include "TGeoMaterial.h"
24 
25 #include <climits>
26 #include <iostream>
27 #include <iomanip>
28 #include <map>
29 #include <vector>
30 #include <unordered_map>
31 #include <utility>
32 
33 // #define EDM_ML_DEBUG 1
34 
35 using namespace std;
36 using namespace dd4hep;
37 using namespace cms;
38 using namespace cms_units::operators;
39 
40 namespace dd4hep {
41 
42  namespace {
43 
44  atomic<UInt_t> unique_mat_id = 0xAFFEFEED;
45 
46  class include_constants;
47  class include_load;
48  class include_unload;
49  class print_xml_doc;
50 
51  class ConstantsSection;
52  class DDLConstant;
53 
54  struct DDRegistry {
55  std::vector<xml::Document> includes;
56  std::unordered_map<std::string, std::string> unresolvedConst;
57  std::unordered_map<std::string, std::string> originalConst;
58  };
59 
60  class MaterialSection;
63 
64  class RotationSection;
65  class DDLRotation;
66  class DDLReflectionRotation;
67  class DDLRotationSequence;
68  class DDLRotationByAxis;
69  class DDLTransform3D;
70 
71  class PosPartSection;
72  class DDLPosPart;
73  class DDLDivision;
74 
75  class LogicalPartSection;
76  class DDLLogicalPart;
77 
78  class SolidSection;
79  class DDLExtrudedPolygon;
80  class DDLShapeless;
81  class DDLAssembly;
82  class DDLTrapezoid;
83  class DDLEllipticalTube;
84  class DDLPseudoTrap;
85  class DDLPolyhedra;
86  class DDLPolycone;
87  class DDLTorus;
88  class DDLTrd1;
89  class DDLTrd2;
90  class DDLTruncTubs;
91  class DDLCutTubs;
92  class DDLTubs;
93  class DDLBox;
94  class DDLCone;
95  class DDLSphere;
96  class DDLUnionSolid;
97  class DDLIntersectionSolid;
98  class DDLSubtractionSolid;
99 
100  class DDLAlgorithm;
101  class DDLVector;
102 
103  class SpecParSection;
104  class DDLSpecPar;
105  class PartSelector;
106  class Parameter;
107 
108  class debug;
109  } // namespace
110 
111  TGeoCombiTrans* createPlacement(const Rotation3D& iRot, const Position& iTrans) {
112  double elements[9];
113  iRot.GetComponents(elements);
114  TGeoRotation r;
115  r.SetMatrix(elements);
116 
117  TGeoTranslation t(iTrans.x(), iTrans.y(), iTrans.z());
118 
119  return new TGeoCombiTrans(t, r);
120  }
121 
123  template <>
124  void Converter<debug>::operator()(xml_h element) const;
125  template <>
126  void Converter<print_xml_doc>::operator()(xml_h element) const;
127 
129  template <>
130  void Converter<ConstantsSection>::operator()(xml_h element) const;
131  template <>
132  void Converter<DDLConstant>::operator()(xml_h element) const;
133  template <>
134  void Converter<DDRegistry>::operator()(xml_h element) const;
135 
137  template <>
138  void Converter<MaterialSection>::operator()(xml_h element) const;
139  template <>
140  void Converter<DDLElementaryMaterial>::operator()(xml_h element) const;
141  template <>
142  void Converter<DDLCompositeMaterial>::operator()(xml_h element) const;
143 
145  template <>
146  void Converter<RotationSection>::operator()(xml_h element) const;
148  template <>
149  void Converter<DDLRotation>::operator()(xml_h element) const;
151  template <>
152  void Converter<DDLReflectionRotation>::operator()(xml_h element) const;
154  template <>
155  void Converter<DDLRotationSequence>::operator()(xml_h element) const;
157  template <>
158  void Converter<DDLRotationByAxis>::operator()(xml_h element) const;
159  template <>
160  void Converter<DDLTransform3D>::operator()(xml_h element) const;
161 
163  template <>
164  void Converter<LogicalPartSection>::operator()(xml_h element) const;
165  template <>
166  void Converter<DDLLogicalPart>::operator()(xml_h element) const;
167 
169  template <>
170  void Converter<PosPartSection>::operator()(xml_h element) const;
172  template <>
173  void Converter<DDLPosPart>::operator()(xml_h element) const;
175  template <>
176  void Converter<DDLDivision>::operator()(xml_h element) const;
177 
179  template <>
180  void Converter<SpecParSection>::operator()(xml_h element) const;
181  template <>
182  void Converter<DDLSpecPar>::operator()(xml_h element) const;
183  template <>
184  void Converter<PartSelector>::operator()(xml_h element) const;
185  template <>
186  void Converter<Parameter>::operator()(xml_h element) const;
187 
189  template <>
190  void Converter<SolidSection>::operator()(xml_h element) const;
192  template <>
193  void Converter<DDLUnionSolid>::operator()(xml_h element) const;
195  template <>
196  void Converter<DDLSubtractionSolid>::operator()(xml_h element) const;
198  template <>
199  void Converter<DDLIntersectionSolid>::operator()(xml_h element) const;
201  template <>
202  void Converter<DDLPseudoTrap>::operator()(xml_h element) const;
204  template <>
205  void Converter<DDLExtrudedPolygon>::operator()(xml_h element) const;
207  template <>
208  void Converter<DDLShapeless>::operator()(xml_h element) const;
210  template <>
211  void Converter<DDLAssembly>::operator()(xml_h element) const;
213  template <>
214  void Converter<DDLTrapezoid>::operator()(xml_h element) const;
216  template <>
217  void Converter<DDLPolycone>::operator()(xml_h element) const;
219  template <>
220  void Converter<DDLPolyhedra>::operator()(xml_h element) const;
222  template <>
223  void Converter<DDLEllipticalTube>::operator()(xml_h element) const;
225  template <>
226  void Converter<DDLTorus>::operator()(xml_h element) const;
228  template <>
229  void Converter<DDLTubs>::operator()(xml_h element) const;
231  template <>
232  void Converter<DDLCutTubs>::operator()(xml_h element) const;
234  template <>
235  void Converter<DDLTruncTubs>::operator()(xml_h element) const;
237  template <>
238  void Converter<DDLSphere>::operator()(xml_h element) const;
240  template <>
241  void Converter<DDLTrd1>::operator()(xml_h element) const;
243  template <>
244  void Converter<DDLTrd2>::operator()(xml_h element) const;
246  template <>
247  void Converter<DDLCone>::operator()(xml_h element) const;
249  template <>
250  void Converter<DDLBox>::operator()(xml_h element) const;
252  template <>
253  void Converter<DDLAlgorithm>::operator()(xml_h element) const;
255  template <>
256  void Converter<DDLVector>::operator()(xml_h element) const;
257 
259  template <>
260  void Converter<include_load>::operator()(xml_h element) const;
262  template <>
263  void Converter<include_unload>::operator()(xml_h element) const;
265  template <>
266  void Converter<include_constants>::operator()(xml_h element) const;
267 } // namespace dd4hep
268 
270 template <>
271 void Converter<ConstantsSection>::operator()(xml_h element) const {
272  cms::DDNamespace ns(_param<cms::DDParsingContext>(), element);
273  cms::DDParsingContext* const context = ns.context();
274  xml_coll_t(element, DD_CMU(Constant)).for_each(Converter<DDLConstant>(description, context, optional));
275  xml_coll_t(element, DD_CMU(Vector)).for_each(Converter<DDLVector>(description, context, optional));
276 }
277 
279 template <>
280 void Converter<MaterialSection>::operator()(xml_h element) const {
281  cms::DDNamespace ns(_param<cms::DDParsingContext>(), element);
282  xml_coll_t(element, DD_CMU(ElementaryMaterial))
283  .for_each(Converter<DDLElementaryMaterial>(description, ns.context(), optional));
284  xml_coll_t(element, DD_CMU(CompositeMaterial))
285  .for_each(Converter<DDLCompositeMaterial>(description, ns.context(), optional));
286 }
287 
288 template <>
289 void Converter<RotationSection>::operator()(xml_h element) const {
290  cms::DDNamespace ns(_param<cms::DDParsingContext>(), element);
291  xml_coll_t(element, DD_CMU(Rotation)).for_each(Converter<DDLRotation>(description, ns.context(), optional));
292  xml_coll_t(element, DD_CMU(ReflectionRotation))
293  .for_each(Converter<DDLReflectionRotation>(description, ns.context(), optional));
294  xml_coll_t(element, DD_CMU(RotationSequence))
295  .for_each(Converter<DDLRotationSequence>(description, ns.context(), optional));
296  xml_coll_t(element, DD_CMU(RotationByAxis))
297  .for_each(Converter<DDLRotationByAxis>(description, ns.context(), optional));
298 }
299 
300 template <>
301 void Converter<PosPartSection>::operator()(xml_h element) const {
302  cms::DDNamespace ns(_param<cms::DDParsingContext>(), element);
303  xml_coll_t(element, DD_CMU(Division)).for_each(Converter<DDLDivision>(description, ns.context(), optional));
304  xml_coll_t(element, DD_CMU(PosPart)).for_each(Converter<DDLPosPart>(description, ns.context(), optional));
305  xml_coll_t(element, DD_CMU(Algorithm)).for_each(Converter<DDLAlgorithm>(description, ns.context(), optional));
306 }
307 
308 template <>
309 void Converter<SpecParSection>::operator()(xml_h element) const {
310  cms::DDNamespace ns(_param<cms::DDParsingContext>(), element);
311  xml_coll_t(element, DD_CMU(SpecPar)).for_each(Converter<DDLSpecPar>(description, ns.context(), optional));
312 }
313 
314 template <>
315 void Converter<DDLSpecPar>::operator()(xml_h element) const {
316  cms::DDNamespace ns(_param<cms::DDParsingContext>(), element);
317  xml_coll_t(element, DD_CMU(PartSelector)).for_each(Converter<PartSelector>(description, ns.context(), optional));
318  xml_coll_t(element, DD_CMU(Parameter)).for_each(Converter<Parameter>(description, ns.context(), optional));
319 }
320 
322 template <>
323 void Converter<LogicalPartSection>::operator()(xml_h element) const {
324  cms::DDNamespace ns(_param<cms::DDParsingContext>(), element);
325  xml_coll_t(element, DD_CMU(LogicalPart)).for_each(Converter<DDLLogicalPart>(description, ns.context(), optional));
326 }
327 
329 template <>
330 void Converter<SolidSection>::operator()(xml_h element) const {
331  cms::DDNamespace ns(_param<cms::DDParsingContext>(), element);
332  for (xml_coll_t solid(element, _U(star)); solid; ++solid) {
333  using cms::hash;
334  switch (hash(solid.tag())) {
335  case hash("Box"):
336  Converter<DDLBox>(description, ns.context(), optional)(solid);
337  break;
338  case hash("Polycone"):
339  Converter<DDLPolycone>(description, ns.context(), optional)(solid);
340  break;
341  case hash("Polyhedra"):
342  Converter<DDLPolyhedra>(description, ns.context(), optional)(solid);
343  break;
344  case hash("Tubs"):
345  Converter<DDLTubs>(description, ns.context(), optional)(solid);
346  break;
347  case hash("CutTubs"):
348  Converter<DDLCutTubs>(description, ns.context(), optional)(solid);
349  break;
350  case hash("TruncTubs"):
351  Converter<DDLTruncTubs>(description, ns.context(), optional)(solid);
352  break;
353  case hash("Tube"):
354  Converter<DDLTubs>(description, ns.context(), optional)(solid);
355  break;
356  case hash("Trd1"):
357  Converter<DDLTrd1>(description, ns.context(), optional)(solid);
358  break;
359  case hash("Trd2"):
360  Converter<DDLTrd2>(description, ns.context(), optional)(solid);
361  break;
362  case hash("Cone"):
363  Converter<DDLCone>(description, ns.context(), optional)(solid);
364  break;
365  case hash("Sphere"):
366  Converter<DDLSphere>(description, ns.context(), optional)(solid);
367  break;
368  case hash("EllipticalTube"):
369  Converter<DDLEllipticalTube>(description, ns.context(), optional)(solid);
370  break;
371  case hash("Torus"):
372  Converter<DDLTorus>(description, ns.context(), optional)(solid);
373  break;
374  case hash("PseudoTrap"):
375  Converter<DDLPseudoTrap>(description, ns.context(), optional)(solid);
376  break;
377  case hash("ExtrudedPolygon"):
378  Converter<DDLExtrudedPolygon>(description, ns.context(), optional)(solid);
379  break;
380  case hash("Trapezoid"):
381  Converter<DDLTrapezoid>(description, ns.context(), optional)(solid);
382  break;
383  case hash("UnionSolid"):
384  Converter<DDLUnionSolid>(description, ns.context(), optional)(solid);
385  break;
386  case hash("SubtractionSolid"):
387  Converter<DDLSubtractionSolid>(description, ns.context(), optional)(solid);
388  break;
389  case hash("IntersectionSolid"):
390  Converter<DDLIntersectionSolid>(description, ns.context(), optional)(solid);
391  break;
392  case hash("ShapelessSolid"):
393  Converter<DDLShapeless>(description, ns.context(), optional)(solid);
394  break;
395  case hash("Assembly"):
396  Converter<DDLAssembly>(description, ns.context(), optional)(solid);
397  break;
398  default:
399  throw std::runtime_error("Request to process unknown shape '" + xml_dim_t(solid).nameStr() + "' [" +
400  solid.tag() + "]");
401  break;
402  }
403  }
404 }
405 
407 template <>
408 void Converter<DDLConstant>::operator()(xml_h element) const {
409  cms::DDNamespace ns(_param<cms::DDParsingContext>());
410  DDRegistry* res = _option<DDRegistry>();
411  xml_dim_t constant = element;
412  xml_dim_t par = constant.parent();
413  bool eval = par.hasAttr(_U(eval)) ? par.attr<bool>(_U(eval)) : true;
414  string val = constant.valueStr();
415  string nam = constant.nameStr();
416  string real = ns.prepend(nam);
417  string typ = eval ? "number" : "string";
418  size_t idx = val.find('[');
419 
420  if (constant.hasAttr(_U(type)))
421  typ = constant.typeStr();
422 
423  if (idx == string::npos || typ == "string") {
424  try {
425  ns.addConstant(nam, val, typ);
426  res->originalConst[real] = val;
427  } catch (const exception& e) {
428 #ifdef EDM_ML_DEBUG
429 
430  printout(INFO,
431  "DD4CMS",
432  "++ Unresolved constant: %s = %s [%s]. Try to resolve later. [%s]",
433  real.c_str(),
434  val.c_str(),
435  typ.c_str(),
436  e.what());
437 #endif
438  }
439  return;
440  }
441  // Setup the resolution mechanism in Converter<resolve>
442  while (idx != string::npos) {
443  ++idx;
444  size_t idp = val.find(':', idx);
445  size_t idq = val.find(']', idx);
446  if (idp == string::npos || idp > idq)
447  val.insert(idx, ns.name());
448  else if (idp != string::npos && idp < idq)
449  val[idp] = NAMESPACE_SEP;
450  idx = val.find('[', idx);
451  }
452 
453 #ifdef EDM_ML_DEBUG
454 
455  printout(
456  ns.context()->debug_constants ? ALWAYS : DEBUG, "Constant", "Unresolved: %s -> %s", real.c_str(), val.c_str());
457 
458 #endif
459 
460  res->originalConst[real] = val;
461  res->unresolvedConst[real] = val;
462 }
463 
465 template <>
466 void Converter<DDLElementaryMaterial>::operator()(xml_h element) const {
467  cms::DDNamespace ns(_param<cms::DDParsingContext>());
468  xml_dim_t xmat(element);
469  const string xmatName(xmat.nameStr());
470  string nam = ns.prepend(xmatName);
471  TGeoManager& mgr = description.manager();
472  TGeoMaterial* mat = mgr.GetMaterial(nam.c_str());
473  if (nullptr == mat) {
474  const char* matname = nam.c_str();
475  double density = xmat.attr<double>(DD_CMU(density)) / (dd4hep::g / dd4hep::cm3);
476  int atomicNumber = xmat.attr<int>(DD_CMU(atomicNumber));
477  double atomicWeight = xmat.attr<double>(DD_CMU(atomicWeight)) / (dd4hep::g / dd4hep::mole);
478  TGeoElementTable* tab = mgr.GetElementTable();
479  int nElem = tab->GetNelements();
480 
481 #ifdef EDM_ML_DEBUG
482 
483  printout(ns.context()->debug_materials ? ALWAYS : DEBUG, "DD4CMS", "+++ Element table size = %d", nElem);
484 
485 #endif
486 
487  if (nElem <= 1) { // Restore the element table DD4hep destroyed.
488  tab->TGeoElementTable::~TGeoElementTable();
489  new (tab) TGeoElementTable();
490  tab->BuildDefaultElements();
491  }
492  TGeoMixture* mix = new TGeoMixture(nam.c_str(), 1, density);
493  const char* const matNameNoNS = xmatName.c_str();
494  TGeoElement* elt = tab->FindElement(matNameNoNS);
495 
496 #ifdef EDM_ML_DEBUG
497 
498  printout(ns.context()->debug_materials ? ALWAYS : DEBUG,
499  "DD4CMS",
500  "+++ Searching for material %-48s elt_ptr = %ld",
501  matNameNoNS,
502  elt);
503 
504  printout(ns.context()->debug_materials ? ALWAYS : DEBUG,
505  "DD4CMS",
506  "+++ Converting material %-48s Atomic weight %8.3f [g/mol], Atomic number %u, Density: %8.3f [g/cm3] "
507  "ROOT: %8.3f [g/cm3]",
508  ('"' + nam + '"').c_str(),
509  atomicWeight,
510  atomicNumber,
511  density,
512  mix->GetDensity());
513 
514 #endif
515 
516  bool newMatDef = false;
517 
518  if (elt) {
519  // A is Mass of a mole in Geant4 units for atoms with atomic shell
520 
521 #ifdef EDM_ML_DEBUG
522 
523  printout(ns.context()->debug_materials ? ALWAYS : DEBUG,
524  "DD4CMS",
525  " ROOT definition of %-50s Atomic weight %g, Atomic number %u, Number of nucleons %u",
526  elt->GetName(),
527  elt->A(),
528  elt->Z(),
529  elt->N());
530  printout(ns.context()->debug_materials ? ALWAYS : DEBUG,
531  "DD4CMS",
532  "+++ Compared to XML values: Atomic weight %g, Atomic number %u",
533  atomicWeight,
534  atomicNumber);
535 #endif
536 
537  static constexpr double const weightTolerance = 1.0e-6;
538  if (atomicNumber != elt->Z() ||
539  (std::abs(atomicWeight - elt->A()) > (weightTolerance * (atomicWeight + elt->A()))))
540  newMatDef = true;
541  }
542 
543  if (!elt || newMatDef) {
544  if (newMatDef) {
545 #ifdef EDM_ML_DEBUG
546 
547  printout(ns.context()->debug_materials ? ALWAYS : DEBUG,
548  "DD4CMS Warning",
549  "+++ Converter<ElementaryMaterial> Different definition of a default element with name:%s [CREATE NEW "
550  "MATERIAL]",
551  matname);
552 
553 #endif
554 
555  } else {
556 #ifdef EDM_ML_DEBUG
557 
558  printout(ns.context()->debug_materials ? ALWAYS : DEBUG,
559  "DD4CMS Warning",
560  "+++ Converter<ElementaryMaterial> No default element present with name:%s [CREATE NEW MATERIAL]",
561  matname);
562 
563 #endif
564  }
565  elt = new TGeoElement(matNameNoNS, matNameNoNS, atomicNumber, atomicWeight);
566  }
567 
568  mix->AddElement(elt, 1.0);
569  mix->SetTemperature(ns.context()->description.stdConditions().temperature);
570  mix->SetPressure(ns.context()->description.stdConditions().pressure);
571 
573  TGeoMedium* medium = mgr.GetMedium(matname);
574  if (nullptr == medium) {
575  --unique_mat_id;
576  medium = new TGeoMedium(matname, unique_mat_id, mix);
577  medium->SetTitle("material");
578  medium->SetUniqueID(unique_mat_id);
579  }
580  }
581 }
582 
584 template <>
585 void Converter<DDLCompositeMaterial>::operator()(xml_h element) const {
586  cms::DDNamespace ns(_param<cms::DDParsingContext>());
587  xml_dim_t xmat(element);
588  string nam = ns.prepend(xmat.nameStr());
589 
590  TGeoManager& mgr = description.manager();
591  TGeoMaterial* mat = mgr.GetMaterial(nam.c_str());
592  if (nullptr == mat) {
593  const char* matname = nam.c_str();
594  double density = xmat.attr<double>(DD_CMU(density)) / (dd4hep::g / dd4hep::cm3);
595  xml_coll_t composites(xmat, DD_CMU(MaterialFraction));
596  TGeoMixture* mix = new TGeoMixture(nam.c_str(), composites.size(), density);
597 
598 #ifdef EDM_ML_DEBUG
599 
600  printout(ns.context()->debug_materials ? ALWAYS : DEBUG,
601  "DD4CMS",
602  "++ Converting material %-48s Density: %8.3f [g/cm3] ROOT: %8.3f [g/cm3]",
603  ('"' + nam + '"').c_str(),
604  density,
605  mix->GetDensity());
606 
607 #endif
608 
609  if (ns.context()->makePayload) {
610  ns.context()->compMaterialsVec.emplace_back(std::make_pair(nam, density));
611  }
612  for (composites.reset(); composites; ++composites) {
613  xml_dim_t xfrac(composites);
614  xml_dim_t xfrac_mat(xfrac.child(DD_CMU(rMaterial)));
615  double fraction = xfrac.fraction();
616  string fracname = ns.realName(xfrac_mat.nameStr());
617 
618  if (ns.context()->makePayload) {
619  ns.context()->compMaterialsRefs[nam].emplace_back(
620  cms::DDParsingContext::CompositeMaterial(ns.prepend(fracname), fraction));
621  }
622  TGeoMaterial* frac_mat = mgr.GetMaterial(fracname.c_str());
623  if (frac_mat == nullptr) // Try to find it within this namespace
624  frac_mat = mgr.GetMaterial(ns.prepend(fracname).c_str());
625  if (frac_mat) {
626  mix->AddElement(frac_mat, fraction);
627  continue;
628  }
629 
630  throw cms::Exception("DD4CMS") << "Composite material \"" + fracname + "\" or \"" + ns.prepend(fracname) +
631  "\" not yet defined.";
632  }
633  mix->SetTemperature(ns.context()->description.stdConditions().temperature);
634  mix->SetPressure(ns.context()->description.stdConditions().pressure);
635  mix->SetRadLen(0e0);
637  TGeoMedium* medium = mgr.GetMedium(matname);
638  if (nullptr == medium) {
639  --unique_mat_id;
640  medium = new TGeoMedium(matname, unique_mat_id, mix);
641  medium->SetTitle("material");
642  medium->SetUniqueID(unique_mat_id);
643  }
644  }
645 }
646 
648 template <>
649 void Converter<DDLRotation>::operator()(xml_h element) const {
650  cms::DDParsingContext* context = _param<cms::DDParsingContext>();
651  cms::DDNamespace ns(context);
652  xml_dim_t xrot(element);
653  string nam = xrot.nameStr();
654  double thetaX = xrot.hasAttr(DD_CMU(thetaX)) ? ns.attr<double>(xrot, DD_CMU(thetaX)) : 0e0;
655  double phiX = xrot.hasAttr(DD_CMU(phiX)) ? ns.attr<double>(xrot, DD_CMU(phiX)) : 0e0;
656  double thetaY = xrot.hasAttr(DD_CMU(thetaY)) ? ns.attr<double>(xrot, DD_CMU(thetaY)) : 0e0;
657  double phiY = xrot.hasAttr(DD_CMU(phiY)) ? ns.attr<double>(xrot, DD_CMU(phiY)) : 0e0;
658  double thetaZ = xrot.hasAttr(DD_CMU(thetaZ)) ? ns.attr<double>(xrot, DD_CMU(thetaZ)) : 0e0;
659  double phiZ = xrot.hasAttr(DD_CMU(phiZ)) ? ns.attr<double>(xrot, DD_CMU(phiZ)) : 0e0;
660  Rotation3D rot = makeRotation3D(thetaX, phiX, thetaY, phiY, thetaZ, phiZ);
661 
662 #ifdef EDM_ML_DEBUG
663 
664  printout(context->debug_rotations ? ALWAYS : DEBUG,
665  "DD4CMS",
666  "+++ Adding rotation: %-32s: (theta/phi)[rad] X: %6.3f %6.3f Y: %6.3f %6.3f Z: %6.3f %6.3f",
667  ns.prepend(nam).c_str(),
668  thetaX,
669  phiX,
670  thetaY,
671  phiY,
672  thetaZ,
673  phiZ);
674 
675 #endif
676 
677  ns.addRotation(nam, rot);
678 }
679 
681 template <>
682 void Converter<DDLReflectionRotation>::operator()(xml_h element) const {
683  cms::DDParsingContext* context = _param<cms::DDParsingContext>();
684  cms::DDNamespace ns(context);
685  xml_dim_t xrot(element);
686  string name = xrot.nameStr();
687  double thetaX = xrot.hasAttr(DD_CMU(thetaX)) ? ns.attr<double>(xrot, DD_CMU(thetaX)) : 0e0;
688  double phiX = xrot.hasAttr(DD_CMU(phiX)) ? ns.attr<double>(xrot, DD_CMU(phiX)) : 0e0;
689  double thetaY = xrot.hasAttr(DD_CMU(thetaY)) ? ns.attr<double>(xrot, DD_CMU(thetaY)) : 0e0;
690  double phiY = xrot.hasAttr(DD_CMU(phiY)) ? ns.attr<double>(xrot, DD_CMU(phiY)) : 0e0;
691  double thetaZ = xrot.hasAttr(DD_CMU(thetaZ)) ? ns.attr<double>(xrot, DD_CMU(thetaZ)) : 0e0;
692  double phiZ = xrot.hasAttr(DD_CMU(phiZ)) ? ns.attr<double>(xrot, DD_CMU(phiZ)) : 0e0;
693 
694 #ifdef EDM_ML_DEBUG
695 
696  printout(context->debug_rotations ? ALWAYS : DEBUG,
697  "DD4CMS",
698  "+++ Adding reflection rotation: %-32s: (theta/phi)[rad] X: %6.3f %6.3f Y: %6.3f %6.3f Z: %6.3f %6.3f",
699  ns.prepend(name).c_str(),
700  thetaX,
701  phiX,
702  thetaY,
703  phiY,
704  thetaZ,
705  phiZ);
706 
707 #endif
708 
709  Rotation3D rot = makeRotReflect(thetaX, phiX, thetaY, phiY, thetaZ, phiZ);
710  ns.addRotation(name, rot);
711 }
712 
714 template <>
715 void Converter<DDLRotationSequence>::operator()(xml_h element) const {
716  cms::DDParsingContext* context = _param<cms::DDParsingContext>();
717  cms::DDNamespace ns(context);
718  xml_dim_t xrot(element);
719  string nam = xrot.nameStr();
720  Rotation3D rot;
721  xml_coll_t rotations(xrot, DD_CMU(RotationByAxis));
722  for (rotations.reset(); rotations; ++rotations) {
723  string axis = ns.attr<string>(rotations, DD_CMU(axis));
724  double angle = ns.attr<double>(rotations, _U(angle));
725  rot = makeRotation3D(rot, axis, angle);
726 
727 #ifdef EDM_ML_DEBUG
728 
729  printout(context->debug_rotations ? ALWAYS : DEBUG,
730  "DD4CMS",
731  "+ Adding rotation to: %-29s: (axis/angle)[rad] Axis: %s Angle: %6.3f",
732  nam.c_str(),
733  axis.c_str(),
734  angle);
735 
736 #endif
737  }
738  double xx, xy, xz;
739  double yx, yy, yz;
740  double zx, zy, zz;
741  rot.GetComponents(xx, xy, xz, yx, yy, yz, zx, zy, zz);
742 
743 #ifdef EDM_ML_DEBUG
744 
745  printout(context->debug_rotations ? ALWAYS : DEBUG,
746  "DD4CMS",
747  "+++ Adding rotation sequence: %-23s: %6.3f %6.3f %6.3f, %6.3f %6.3f %6.3f, %6.3f %6.3f %6.3f",
748  ns.prepend(nam).c_str(),
749  xx,
750  xy,
751  xz,
752  yx,
753  yy,
754  yz,
755  zx,
756  zy,
757  zz);
758 
759 #endif
760 
761  ns.addRotation(nam, rot);
762 }
763 
765 template <>
766 void Converter<DDLRotationByAxis>::operator()(xml_h element) const {
767  cms::DDParsingContext* context = _param<cms::DDParsingContext>();
768  cms::DDNamespace ns(context);
769  xml_dim_t xrot(element);
770  xml_dim_t par(xrot.parent());
771  if (xrot.hasAttr(_U(name))) {
772  string nam = xrot.nameStr();
773  string axis = ns.attr<string>(xrot, DD_CMU(axis));
774  double angle = ns.attr<double>(xrot, _U(angle));
775  Rotation3D rot;
776  rot = makeRotation3D(rot, axis, angle);
777 
778 #ifdef EDM_ML_DEBUG
779 
780  printout(context->debug_rotations ? ALWAYS : DEBUG,
781  "DD4CMS",
782  "+++ Adding rotation: %-32s: (axis/angle)[rad] Axis: %s Angle: %6.3f",
783  ns.prepend(nam).c_str(),
784  axis.c_str(),
785  angle);
786 
787 #endif
788 
789  ns.addRotation(nam, rot);
790  }
791 }
792 
794 template <>
795 void Converter<DDLLogicalPart>::operator()(xml_h element) const {
796  cms::DDNamespace ns(_param<cms::DDParsingContext>());
797  xml_dim_t e(element);
798  string sol = e.child(DD_CMU(rSolid)).attr<string>(_U(name));
799  string mat = e.child(DD_CMU(rMaterial)).attr<string>(_U(name));
800  string volName = ns.prepend(e.attr<string>(_U(name)));
801  Solid solid = ns.solid(sol);
802  Material material = ns.material(mat);
803  if (ns.context()->assemblySolids.count(sol) == 1) {
804  // To match the general paradigm, an assembly starts as a solid,
805  // and then a logical part is made of the solid. However, the
806  // solid is just a dummy whose names tags it as an assembly.
807  ns.addAssembly(volName, false);
808  return;
809  }
810 
811 #ifdef EDM_ML_DEBUG
812  Volume volume =
813 #endif
814 
815  ns.addVolume(Volume(volName, solid, material));
816 
817 #ifdef EDM_ML_DEBUG
818 
819  printout(ns.context()->debug_volumes ? ALWAYS : DEBUG,
820  "DD4CMS",
821  "+++ %s Volume: %-24s [%s] Shape: %-32s [%s] Material: %-40s [%s]",
822  e.tag().c_str(),
823  volName.c_str(),
824  volume.isValid() ? "VALID" : "INVALID",
825  sol.c_str(),
826  solid.isValid() ? "VALID" : "INVALID",
827  mat.c_str(),
828  material.isValid() ? "VALID" : "INVALID");
829 
830 #endif
831 }
832 
834 template <>
835 void Converter<DDLTransform3D>::operator()(xml_h element) const {
836  cms::DDNamespace ns(_param<cms::DDParsingContext>());
837  Transform3D* tr = _option<Transform3D>();
838  xml_dim_t e(element);
839  xml_dim_t translation = e.child(DD_CMU(Translation), false);
840  xml_dim_t rotation = e.child(DD_CMU(Rotation), false);
841  xml_dim_t refRotation = e.child(DD_CMU(rRotation), false);
842  xml_dim_t refReflectionRotation = e.child(DD_CMU(rReflectionRotation), false);
843  Position pos;
844  Rotation3D rot;
845 
846  if (translation.ptr()) {
847  double x = ns.attr<double>(translation, _U(x));
848  double y = ns.attr<double>(translation, _U(y));
849  double z = ns.attr<double>(translation, _U(z));
850  pos = Position(x, y, z);
851  }
852  if (rotation.ptr()) {
853  double x = ns.attr<double>(rotation, _U(x));
854  double y = ns.attr<double>(rotation, _U(y));
855  double z = ns.attr<double>(rotation, _U(z));
856  rot = RotationZYX(z, y, x);
857  } else if (refRotation.ptr()) {
858  string rotName = ns.prepend(refRotation.nameStr());
859  rot = ns.rotation(rotName);
860  } else if (refReflectionRotation.ptr()) {
861  string rotName = ns.prepend(refReflectionRotation.nameStr());
862  rot = ns.rotation(rotName);
863  }
864  *tr = Transform3D(rot, pos);
865 }
866 
867 static void placeAssembly(Volume* parentPtr,
868  const string& parentName,
869  Volume* childPtr,
870  const string& childName,
871  int copy,
872  const Transform3D& transform,
873  cms::DDNamespace& ns) {
874 #ifdef EDM_ML_DEBUG
875 
876  printout(ns.context()->debug_placements ? ALWAYS : DEBUG,
877  "DD4CMS",
878  "+++ Parent vol: %-24s Child: %-32s, copy:%d",
879  parentName.c_str(),
880  childName.c_str(),
881  copy);
882 
883 #endif
884 
885  TGeoShape* shape = (*childPtr)->GetShape();
886  // Need to fix the daughter's BBox of assemblies, if the BBox was not calculated....
887  if (shape->IsA() == TGeoShapeAssembly::Class()) {
888  TGeoShapeAssembly* as = (TGeoShapeAssembly*)shape;
889  if (std::fabs(as->GetDX()) < numeric_limits<double>::epsilon() &&
890  std::fabs(as->GetDY()) < numeric_limits<double>::epsilon() &&
891  std::fabs(as->GetDZ()) < numeric_limits<double>::epsilon()) {
892  as->NeedsBBoxRecompute();
893  as->ComputeBBox();
894  }
895  }
896  TGeoNode* n;
897  TString nam_id = TString::Format("%s_%d", (*childPtr)->GetName(), copy);
898  n = static_cast<TGeoNode*>((*parentPtr)->GetNode(nam_id));
899  if (n != nullptr) {
900  printout(ERROR, "PlacedVolume", "++ Attempt to add already existing node %s", (const char*)nam_id);
901  return;
902  }
903 
905  if ((*childPtr)->IsAssembly()) {
906  pv = parentPtr->placeVolume(ns.assembly(childName), copy, transform);
907  } else {
908  pv = parentPtr->placeVolume(*childPtr, copy, transform);
909  }
910 
911  if (!pv.isValid()) {
912  printout(ERROR, "DD4CMS", "+++ Placement FAILED! Parent:%s Child:%s", parentName.c_str(), childName.c_str());
913  }
914 }
915 
917 template <>
918 void Converter<DDLPosPart>::operator()(xml_h element) const {
919  cms::DDNamespace ns(_param<cms::DDParsingContext>()); //, element, true );
920  xml_dim_t e(element);
921  int copy = e.attr<int>(DD_CMU(copyNumber));
922  string parentName = ns.prepend(ns.attr<string>(e.child(DD_CMU(rParent)), _U(name)));
923  string childName = ns.prepend(ns.attr<string>(e.child(DD_CMU(rChild)), _U(name)));
924  Transform3D transform;
925  Converter<DDLTransform3D>(description, param, &transform)(element);
926 
927  Volume parent = ns.volume(parentName, false);
928  Volume child = ns.volume(childName, false);
929  Assembly parAsmb = ns.assembly(parentName, false);
930  Assembly childAsmb = ns.assembly(childName, false);
931 
932 #ifdef EDM_ML_DEBUG
933 
934  printout(ns.context()->debug_placements ? ALWAYS : DEBUG,
935  "DD4CMS",
936  "+++ %s Parent: %-24s [%s] Child: %-32s [%s] copy:%d",
937  e.tag().c_str(),
938  parentName.c_str(),
939  parent.isValid() ? "VALID" : "INVALID",
940  childName.c_str(),
941  child.isValid() ? "VALID" : "INVALID",
942  copy);
943 
944 #endif
945 
946  if (!parent.isValid() && !parAsmb.isValid() && strchr(parentName.c_str(), NAMESPACE_SEP) == nullptr) {
947  parentName = ns.prepend(parentName);
948  parAsmb = ns.assembly(parentName, false);
949  if (!parAsmb.isValid())
950  parent = ns.volume(parentName);
951  }
952 
953  if (!child.isValid() && !childAsmb.isValid() && strchr(childName.c_str(), NAMESPACE_SEP) == nullptr) {
954  childName = ns.prepend(childName);
955  child = ns.volume(childName, false);
956  childAsmb = ns.assembly(childName, false);
957  }
958  if (parAsmb.isValid() || childAsmb.isValid()) {
959  printout(ns.context()->debug_placements ? ALWAYS : DEBUG,
960  "DD4CMS",
961  "***** Placing assembly parent %s, child %s",
962  parentName.c_str(),
963  childName.c_str());
964  Volume* parentPtr = parAsmb.isValid() ? &parAsmb : &parent;
965  Volume* childPtr = childAsmb.isValid() ? &childAsmb : &child;
966  placeAssembly(parentPtr, parentName, childPtr, childName, copy, transform, ns);
967  return;
968  }
969 
970 #ifdef EDM_ML_DEBUG
971 
972  printout(ns.context()->debug_placements ? ALWAYS : DEBUG,
973  "DD4CMS",
974  "+++ %s Parent: %-24s [%s] Child: %-32s [%s] copy:%d",
975  e.tag().c_str(),
976  parentName.c_str(),
977  parent.isValid() ? "VALID" : "INVALID",
978  childName.c_str(),
979  child.isValid() ? "VALID" : "INVALID",
980  copy);
981 
982 #endif
983 
985  if (child.isValid()) {
986  // FIXME: workaround for Reflection rotation
987  // copy from DDCore/src/Volumes.cpp to replace
988  // static PlacedVolume _addNode(TGeoVolume* par, TGeoVolume* daughter, int id, TGeoMatrix* transform)
989  if (!parent) {
990  except("dd4hep", "Volume: Attempt to assign daughters to an invalid physical parent volume.");
991  }
992  if (!child) {
993  except("dd4hep", "Volume: Attempt to assign an invalid physical daughter volume.");
994  }
995  TGeoShape* shape = child->GetShape();
996  // Need to fix the daughter's BBox of assemblies, if the BBox was not calculated....
997  if (shape->IsA() == TGeoShapeAssembly::Class()) {
998  TGeoShapeAssembly* as = (TGeoShapeAssembly*)shape;
999  if (std::fabs(as->GetDX()) < numeric_limits<double>::epsilon() &&
1000  std::fabs(as->GetDY()) < numeric_limits<double>::epsilon() &&
1001  std::fabs(as->GetDZ()) < numeric_limits<double>::epsilon()) {
1002  as->NeedsBBoxRecompute();
1003  as->ComputeBBox();
1004  }
1005  }
1006  TGeoNode* n;
1007  TString nam_id = TString::Format("%s_%d", child->GetName(), copy);
1008  n = static_cast<TGeoNode*>(parent->GetNode(nam_id));
1009  if (n != nullptr) {
1010  printout(ERROR, "PlacedVolume", "++ Attempt to add already existing node %s", (const char*)nam_id);
1011  }
1012 
1013  Rotation3D rot(transform.Rotation());
1014  Translation3D trans(transform.Translation());
1015  double x, y, z;
1016  trans.GetComponents(x, y, z);
1017  Position pos(x, y, z);
1018  parent->AddNode(child, copy, createPlacement(rot, pos));
1019 
1020  n = static_cast<TGeoNode*>(parent->GetNode(nam_id));
1021  n->TGeoNode::SetUserExtension(new PlacedVolume::Object());
1022  pv = PlacedVolume(n);
1023  }
1024  if (!pv.isValid()) {
1025  printout(ERROR,
1026  "DD4CMS",
1027  "+++ Placement FAILED! Parent:%s Child:%s Valid:%s",
1028  parent.name(),
1029  childName.c_str(),
1030  yes_no(child.isValid()));
1031  }
1032 }
1033 
1035 template <>
1036 void Converter<PartSelector>::operator()(xml_h element) const {
1037  cms::DDNamespace ns(_param<cms::DDParsingContext>());
1038  cms::DDParsingContext* const context = ns.context();
1039  dd4hep::SpecParRegistry& registry = *context->description.extension<dd4hep::SpecParRegistry>();
1040  xml_dim_t e(element);
1041  xml_dim_t specPar = e.parent();
1042  string specParName = specPar.attr<string>(_U(name));
1043  string path = e.attr<string>(DD_CMU(path));
1044 
1045 #ifdef EDM_ML_DEBUG
1046 
1047  printout(ns.context()->debug_specpars ? ALWAYS : DEBUG,
1048  "DD4CMS",
1049  "+++ PartSelector for %s path: %s",
1050  specParName.c_str(),
1051  path.c_str());
1052 
1053 #endif
1054 
1055  size_t pos = std::string::npos;
1056  if ((pos = path.find("//.*:")) != std::string::npos) {
1057  path.erase(pos + 2, 3);
1058  }
1059  registry.specpars[specParName].paths.emplace_back(std::move(path));
1060 }
1061 
1063 template <>
1064 void Converter<Parameter>::operator()(xml_h element) const {
1065  cms::DDNamespace ns(_param<cms::DDParsingContext>());
1066  cms::DDParsingContext* const context = ns.context();
1067  dd4hep::SpecParRegistry& registry = *context->description.extension<dd4hep::SpecParRegistry>();
1068  xml_dim_t e(element);
1069  xml_dim_t specPar = e.parent();
1070  xml_dim_t specParSect = specPar.parent();
1071  string specParName = specPar.attr<string>(_U(name));
1072  string name = e.nameStr();
1073  string value = e.attr<string>(DD_CMU(value));
1074  bool eval = specParSect.hasAttr(_U(eval)) ? specParSect.attr<bool>(_U(eval)) : false;
1075  eval = specPar.hasAttr(_U(eval)) ? specPar.attr<bool>(_U(eval)) : eval;
1076  eval = e.hasAttr(_U(eval)) ? e.attr<bool>(_U(eval)) : eval;
1077 
1078  string type = eval ? "number" : "string";
1079 
1080 #ifdef EDM_ML_DEBUG
1081 
1082  printout(ns.context()->debug_specpars ? ALWAYS : DEBUG,
1083  "DD4CMS",
1084  "+++ Parameter for %s: %s value %s is a %s",
1085  specParName.c_str(),
1086  name.c_str(),
1087  value.c_str(),
1088  type.c_str());
1089 
1090 #endif
1091 
1092  size_t idx = value.find('[');
1093  if (idx == string::npos && type == "number") {
1094  registry.specpars[specParName].numpars[name].emplace_back(dd4hep::_toDouble(value));
1095  return;
1096  }
1097  if (idx == string::npos || type == "string") {
1098  registry.specpars[specParName].spars[name].emplace_back(std::move(value));
1099  return;
1100  }
1101 
1102  while (idx != string::npos) {
1103  ++idx;
1104  size_t idp = value.find(':', idx);
1105  size_t idq = value.find(']', idx);
1106  if (idp == string::npos || idp > idq)
1107  value.insert(idx, ns.name());
1108  else if (idp != string::npos && idp < idq)
1109  value[idp] = NAMESPACE_SEP;
1110  idx = value.find('[', idx);
1111  }
1112 
1113  string rep;
1114  string& v = value;
1115  size_t idq;
1116  for (idx = v.find('[', 0); idx != string::npos; idx = v.find('[', idx + 1)) {
1117  idq = v.find(']', idx + 1);
1118  rep = v.substr(idx + 1, idq - idx - 1);
1119  auto r = ns.context()->description.constants().find(rep);
1120  if (r != ns.context()->description.constants().end()) {
1121  rep = "(" + r->second->type + ")";
1122  v.replace(idx, idq - idx + 1, rep);
1123  }
1124  }
1125  registry.specpars[specParName].numpars[name].emplace_back(dd4hep::_toDouble(value));
1126 }
1127 
1128 template <typename TYPE>
1129 static void convert_boolean(cms::DDParsingContext* context, xml_h element) {
1130  cms::DDNamespace ns(context);
1131  xml_dim_t e(element);
1132  string nam = e.nameStr();
1133  string solidName[2];
1134  Solid solids[2];
1135  Solid boolean;
1136  int cnt = 0;
1137  if (e.hasChild(DD_CMU(rSolid))) {
1138  for (xml_coll_t c(element, DD_CMU(rSolid)); cnt < 2 && c; ++c, ++cnt) {
1139  solidName[cnt] = c.attr<string>(_U(name));
1140  solids[cnt] = ns.solid(c.attr<string>(_U(name)));
1141  }
1142  } else {
1143  solidName[0] = e.attr<string>(DD_CMU(firstSolid));
1144  if ((solids[0] = ns.solid(e.attr<string>(DD_CMU(firstSolid)))).isValid())
1145  ++cnt;
1146  solidName[1] = e.attr<string>(DD_CMU(secondSolid));
1147  if ((solids[1] = ns.solid(e.attr<string>(DD_CMU(secondSolid)))).isValid())
1148  ++cnt;
1149  }
1150  if (cnt != 2) {
1151  except("DD4CMS", "+++ Failed to create boolean solid %s. Found only %d parts.", nam.c_str(), cnt);
1152  }
1153 
1154 #ifdef EDM_ML_DEBUG
1155 
1156  printout(ns.context()->debug_placements ? ALWAYS : DEBUG,
1157  "DD4CMS",
1158  "+++ BooleanSolid: %s Left: %-32s Right: %-32s",
1159  nam.c_str(),
1160  ((solids[0].ptr() == nullptr) ? solidName[0].c_str() : solids[0]->GetName()),
1161  ((solids[1].ptr() == nullptr) ? solidName[1].c_str() : solids[1]->GetName()));
1162 
1163 #endif
1164 
1165  if (solids[0].isValid() && solids[1].isValid()) {
1166  Transform3D trafo;
1167  Converter<DDLTransform3D>(context->description, context, &trafo)(element);
1168  boolean = TYPE(solids[0], solids[1], trafo);
1169  } else {
1170  // Register it for later processing
1171  Transform3D trafo;
1172  Converter<DDLTransform3D>(context->description, context, &trafo)(element);
1173  ns.context()->unresolvedShapes.emplace(nam,
1174  DDParsingContext::BooleanShape<TYPE>(solidName[0], solidName[1], trafo));
1175  if (solids[0].isValid() == false) {
1176  printout(ERROR, "DD4CMS", "++ Solid not defined yet: %s", solidName[0].c_str());
1177  }
1178  if (solids[1].isValid() == false) {
1179  printout(ERROR, "DD4CMS", "++ Solid not defined yet: %s", solidName[1].c_str());
1180  }
1181  printout(ERROR, "DD4CMS", "++ Re-order XML files to prevent references to undefined solids");
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));
1753  edm::FileInPath fp(fname);
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>();
2080  cms::DDNamespace ns(context);
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>();
2162  cms::DDNamespace ns(context);
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  if (open_geometry) {
2225  det.init();
2226  ns.addVolume(det.worldVolume());
2227  }
2228  for (xml::Document d : res.includes) {
2229  print_doc((doc = d).root());
2230  xml_coll_t(d.root(), DD_CMU(RotationSection)).for_each(Converter<RotationSection>(det, &context));
2231  }
2232  for (xml::Document d : res.includes) {
2233  print_doc((doc = d).root());
2234  xml_coll_t(d.root(), DD_CMU(SolidSection)).for_each(Converter<SolidSection>(det, &context));
2235  }
2236  for (xml::Document d : res.includes) {
2237  print_doc((doc = d).root());
2238  xml_coll_t(d.root(), DD_CMU(LogicalPartSection)).for_each(Converter<LogicalPartSection>(det, &context));
2239  }
2240  for (xml::Document d : res.includes) {
2241  print_doc((doc = d).root());
2242  xml_coll_t(d.root(), DD_CMU(Algorithm)).for_each(Converter<DDLAlgorithm>(det, &context));
2243  }
2244  for (xml::Document d : res.includes) {
2245  print_doc((doc = d).root());
2246  xml_coll_t(d.root(), DD_CMU(PosPartSection)).for_each(Converter<PosPartSection>(det, &context));
2247  }
2248  for (xml::Document d : res.includes) {
2249  print_doc((doc = d).root());
2250  xml_coll_t(d.root(), DD_CMU(SpecParSection)).for_each(Converter<SpecParSection>(det, &context));
2251  }
2252 
2254  for (xml::Document d : res.includes)
2255  Converter<include_unload>(det, &context, &res)(d.root());
2256 
2257  print_doc((doc = dddef.document()).root());
2258  // Now process the actual geometry items
2259  xml_coll_t(dddef, DD_CMU(SolidSection)).for_each(Converter<SolidSection>(det, &context));
2260  {
2261  // Before we continue, we have to resolve all shapes NOW!
2262  // Note: This only happens in a legacy DB payloads where
2263  // boolean shapes can be defined before thier
2264  // component shapes
2265 
2266  while (!context.unresolvedShapes.empty()) {
2267  for (auto it = context.unresolvedShapes.begin(); it != context.unresolvedShapes.end();) {
2268  auto const& name = it->first;
2269  auto const& aname = std::visit([](auto&& arg) -> std::string { return arg.firstSolidName; }, it->second);
2270  auto const& bname = std::visit([](auto&& arg) -> std::string { return arg.secondSolidName; }, it->second);
2271 
2272  auto const& ait = context.shapes.find(aname);
2273  if (ait->second.isValid()) {
2274  auto const& bit = context.shapes.find(bname);
2275  if (bit->second.isValid()) {
2276  dd4hep::Solid shape =
2277  std::visit([&ait, &bit](auto&& arg) -> dd4hep::Solid { return arg.make(ait->second, bit->second); },
2278  it->second);
2279  context.shapes[name] = shape;
2280  it = context.unresolvedShapes.erase(it);
2281  } else
2282  ++it;
2283  } else
2284  ++it;
2285  }
2286  }
2287  }
2288  xml_coll_t(dddef, DD_CMU(LogicalPartSection)).for_each(Converter<LogicalPartSection>(det, &context));
2289  xml_coll_t(dddef, DD_CMU(Algorithm)).for_each(Converter<DDLAlgorithm>(det, &context));
2290  xml_coll_t(dddef, DD_CMU(PosPartSection)).for_each(Converter<PosPartSection>(det, &context));
2291  xml_coll_t(dddef, DD_CMU(SpecParSection)).for_each(Converter<SpecParSection>(det, &context));
2292  } catch (const exception& e) {
2293  printout(ERROR, "DD4CMS", "Exception while processing xml source:%s", doc.uri().c_str());
2294  printout(ERROR, "DD4CMS", "----> %s", e.what());
2295  throw;
2296  }
2297 
2299  if (close_geometry) {
2300  Volume wv = det.worldVolume();
2301  Volume geomv = ns.volume("cms:OCMS", false);
2302  if (geomv.isValid())
2303  wv.placeVolume(geomv, 1);
2304  Volume mfv = ns.volume("cmsMagneticField:MAGF", false);
2305  if (mfv.isValid())
2306  wv.placeVolume(mfv, 1);
2307  Volume mfv1 = ns.volume("MagneticFieldVolumes:MAGF", false);
2308  if (mfv1.isValid())
2309  wv.placeVolume(mfv1, 1);
2310 
2311  // Can not deal with reflections without closed geometry
2312  det.manager().CloseGeometry();
2313 
2314  det.endDocument();
2315  }
2316  printout(INFO, "DDDefinition", "+++ Finished processing %s", fname.c_str());
2317  return 1;
2318  }
2319  except("DDDefinition", "+++ FAILED to process unknown DOM tree [Invalid Handle]");
2320  return 0;
2321 }
2322 
2323 // Now declare the factory entry for the plugin mechanism
2324 DECLARE_XML_DOC_READER(DDDefinition, load_dddefinition)
DDLPosPart handles PosPart elements.
Definition: DDLPosPart.h:27
std::unordered_map< std::string, std::vector< double >> DDVectorsMap
Definition: DDNamespace.h:20
tuple optional
Definition: Types.py:198
string rep
Definition: cuy.py:1189
tuple ret
prodAgent to be discontinued
DDLSphere processes all Sphere elements.
Definition: DDLSphere.h:24
const edm::EventSetup & c
list TYPE
Definition: runonSM.py:21
DDLDivision processes Division elements.
Definition: DDLDivision.h:27
std::unordered_map< std::string, std::variant< BooleanShape< dd4hep::UnionSolid >, BooleanShape< dd4hep::SubtractionSolid >, BooleanShape< dd4hep::IntersectionSolid > > > unresolvedShapes
std::unordered_map< std::string, std::vector< std::string > > unresolvedVectors
const bool isValid(const Frame &aFrame, const FrameQuality &aQuality, const uint16_t aExpectedPos)
static void placeAssembly(Volume *parentPtr, const string &parentName, Volume *childPtr, const string &childName, int copy, const Transform3D &transform, cms::DDNamespace &ns)
ROOT::Math::Plane3D::Vector Vector
Definition: EcalHitMaker.cc:29
DDLVector handles Rotation and ReflectionRotation elements.
Definition: DDLVector.h:29
constexpr NumType convertRadToDeg(NumType radians)
Definition: angle_units.h:21
dictionary results
float *__restrict__ wv
Geom::Theta< T > theta() const
DDLSpecPar processes SpecPar elements.
Definition: DDLSpecPar.h:26
DDLEllipticalTube processes all EllipticalTube elements.
TGeoCombiTrans * createPlacement(const Rotation3D &iRot, const Position &iTrans)
std::vector< std::string > splitString(const std::string &fLine)
dd4hep::Solid solid(const std::string &name) const
Definition: DDNamespace.cc:311
A arg
Definition: Factorize.h:31
DDLAlgorithm processes Algorithm elements.
Definition: DDLAlgorithm.h:25
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
DDRotationMatrix makeRotation3D(double thetaX, double phiX, double thetaY, double phiY, double thetaZ, double phiZ)
tuple cl
Definition: haddnano.py:49
std::unordered_map< std::string, std::string > unresolvedConst
DDParsingContext *const context() const
Definition: DDNamespace.h:76
tuple result
Definition: mps_fire.py:311
dictionary elements
static const std::string & rotName(const T &rot, const cms::DDParsingContext &context)
U second(std::pair< T, U > const &p)
tuple d
Definition: ztail.py:151
DDLBox processes Box elements.
Definition: DDLBox.h:27
tuple dd4hep
Definition: dd4hep_cff.py:3
DDLElementaryMaterial processes ElementaryMaterial elements.
DDLAssembly processes Assembly elements.
Definition: DDLAssembly.h:21
static constexpr long s_executed
DDLCone processes all Cone elements.
Definition: DDLCone.h:27
dd4hep::PlacedVolume PlacedVolume
DDRotationMatrix makeRotReflect(double thetaX, double phiX, double thetaY, double phiY, double thetaZ, double phiZ)
def move
Definition: eostools.py:511
Abs< T >::type abs(const T &t)
Definition: Abs.h:22
constexpr unsigned int hash(const char *str, int h=0)
std::unordered_map< std::string, dd4hep::Solid > shapes
#define DD_CMU(a)
Definition: DDXMLTags.h:183
static void convert_boolean(cms::DDParsingContext *context, xml_h element)
dd4hep::Volume Volume
#define M_PI
DDLTubs processes Tubs elements.
Definition: DDLTubs.h:21
Polynomial< 0 > Constant
Definition: Constant.h:6
Basic2DVector< T > xy() const
#define debug
Definition: HDRShower.cc:19
constexpr float sol
Definition: Config.h:48
dd4hep::Solid addSolid(const std::string &name, dd4hep::Solid solid) const
Definition: DDNamespace.cc:307
DDLLogicalPart processes LogicalPart elements.
SOARotation< float > Rotation
DDLRotationByAxis handles RotationByAxis elements.
DDLCompositeMaterial processes all CompositeMaterial elements.
string fname
main script
#define DEBUG
Definition: DMRChecker.cc:120
std::vector< xml::Document > includes
static long load_dddefinition(Detector &det, xml_h element)
Converter for &lt;DDDefinition&gt; tags.
dd4hep::Detector & description
DDAxes
analagous to geant4/source/global/HEPGeometry/include/geomdefs.hh
Definition: DDAxes.h:11
std::unordered_map< std::string, std::string > originalConst
tuple last
Definition: dqmdumpme.py:56
#define str(s)
dd4hep::Assembly assembly(const std::string &name, bool exception=true) const
Definition: DDNamespace.cc:259
DDLRotationSequence handles a set of Rotations.
void for_each_token(InputIt first, InputIt last, ForwardIt s_first, ForwardIt s_last, BinOp binary_op)
static const int ERROR
#define NAMESPACE_SEP
Definition: DDNamespace.h:92
ROOT::Math::DisplacementVector3D< ROOT::Math::Cartesian3D< double >> Translation
T angle(T x1, T y1, T z1, T x2, T y2, T z2)
Definition: angle.h:11
unsigned transform(const HcalDetId &id, unsigned transformCode)