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"
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  const string xmatName(xmat.nameStr());
469  string nam = ns.prepend(xmatName);
470  TGeoManager& mgr = description.manager();
471  TGeoMaterial* mat = mgr.GetMaterial(nam.c_str());
472  if (nullptr == mat) {
473  const char* matname = nam.c_str();
474  double density = xmat.attr<double>(DD_CMU(density)) / (dd4hep::g / dd4hep::cm3);
475  int atomicNumber = xmat.attr<int>(DD_CMU(atomicNumber));
476  double atomicWeight = xmat.attr<double>(DD_CMU(atomicWeight)) / (dd4hep::g / dd4hep::mole);
477  TGeoElementTable* tab = mgr.GetElementTable();
478  int nElem = tab->GetNelements();
479 
480 #ifdef EDM_ML_DEBUG
481 
482  printout(ns.context()->debug_materials ? ALWAYS : DEBUG, "DD4CMS", "+++ Element table size = %d", nElem);
483 
484 #endif
485 
486  if (nElem <= 1) { // Restore the element table DD4hep destroyed.
487  tab->TGeoElementTable::~TGeoElementTable();
488  new (tab) TGeoElementTable();
489  tab->BuildDefaultElements();
490  }
491  TGeoMixture* mix = new TGeoMixture(nam.c_str(), 1, density);
492  const char* const matNameNoNS = xmatName.c_str();
493  TGeoElement* elt = tab->FindElement(matNameNoNS);
494 
495 #ifdef EDM_ML_DEBUG
496 
497  printout(ns.context()->debug_materials ? ALWAYS : DEBUG,
498  "DD4CMS",
499  "+++ Searching for material %-48s elt_ptr = %ld",
500  matNameNoNS,
501  elt);
502 
503  printout(ns.context()->debug_materials ? ALWAYS : DEBUG,
504  "DD4CMS",
505  "+++ Converting material %-48s Atomic weight %8.3f [g/mol], Atomic number %u, Density: %8.3f [g/cm3] "
506  "ROOT: %8.3f [g/cm3]",
507  ('"' + nam + '"').c_str(),
508  atomicWeight,
509  atomicNumber,
510  density,
511  mix->GetDensity());
512 
513 #endif
514 
515  bool newMatDef = false;
516 
517  if (elt) {
518  // A is Mass of a mole in Geant4 units for atoms with atomic shell
519 
520 #ifdef EDM_ML_DEBUG
521 
522  printout(ns.context()->debug_materials ? ALWAYS : DEBUG,
523  "DD4CMS",
524  " ROOT definition of %-50s Atomic weight %g, Atomic number %u, Number of nucleons %u",
525  elt->GetName(),
526  elt->A(),
527  elt->Z(),
528  elt->N());
529  printout(ns.context()->debug_materials ? ALWAYS : DEBUG,
530  "DD4CMS",
531  "+++ Compared to XML values: Atomic weight %g, Atomic number %u",
532  atomicWeight,
533  atomicNumber);
534 #endif
535 
536  static constexpr double const weightTolerance = 1.0e-6;
537  if (atomicNumber != elt->Z() ||
538  (std::abs(atomicWeight - elt->A()) > (weightTolerance * (atomicWeight + elt->A()))))
539  newMatDef = true;
540  }
541 
542  if (!elt || newMatDef) {
543  if (newMatDef) {
544 #ifdef EDM_ML_DEBUG
545 
546  printout(ns.context()->debug_materials ? ALWAYS : DEBUG,
547  "DD4CMS Warning",
548  "+++ Converter<ElementaryMaterial> Different definition of a default element with name:%s [CREATE NEW "
549  "MATERIAL]",
550  matname);
551 
552 #endif
553 
554  } else {
555 #ifdef EDM_ML_DEBUG
556 
557  printout(ns.context()->debug_materials ? ALWAYS : DEBUG,
558  "DD4CMS Warning",
559  "+++ Converter<ElementaryMaterial> No default element present with name:%s [CREATE NEW MATERIAL]",
560  matname);
561 
562 #endif
563  }
564  elt = new TGeoElement(matNameNoNS, matNameNoNS, atomicNumber, atomicWeight);
565  }
566 
567  mix->AddElement(elt, 1.0);
568  mix->SetTemperature(ns.context()->description.stdConditions().temperature);
569  mix->SetPressure(ns.context()->description.stdConditions().pressure);
570 
572  TGeoMedium* medium = mgr.GetMedium(matname);
573  if (nullptr == medium) {
574  --unique_mat_id;
575  medium = new TGeoMedium(matname, unique_mat_id, mix);
576  medium->SetTitle("material");
577  medium->SetUniqueID(unique_mat_id);
578  }
579  }
580 }
581 
583 template <>
584 void Converter<DDLCompositeMaterial>::operator()(xml_h element) const {
585  cms::DDNamespace ns(_param<cms::DDParsingContext>());
586  xml_dim_t xmat(element);
587  string nam = ns.prepend(xmat.nameStr());
588 
589  TGeoManager& mgr = description.manager();
590  TGeoMaterial* mat = mgr.GetMaterial(nam.c_str());
591  if (nullptr == mat) {
592  const char* matname = nam.c_str();
593  double density = xmat.attr<double>(DD_CMU(density)) / (dd4hep::g / dd4hep::cm3);
594  xml_coll_t composites(xmat, DD_CMU(MaterialFraction));
595  TGeoMixture* mix = new TGeoMixture(nam.c_str(), composites.size(), density);
596 
597 #ifdef EDM_ML_DEBUG
598 
599  printout(ns.context()->debug_materials ? ALWAYS : DEBUG,
600  "DD4CMS",
601  "++ Converting material %-48s Density: %8.3f [g/cm3] ROOT: %8.3f [g/cm3]",
602  ('"' + nam + '"').c_str(),
603  density,
604  mix->GetDensity());
605 
606 #endif
607 
608  if (ns.context()->makePayload) {
609  ns.context()->compMaterialsVec.emplace_back(std::make_pair(nam, density));
610  }
611  for (composites.reset(); composites; ++composites) {
612  xml_dim_t xfrac(composites);
613  xml_dim_t xfrac_mat(xfrac.child(DD_CMU(rMaterial)));
614  double fraction = xfrac.fraction();
615  string fracname = ns.realName(xfrac_mat.nameStr());
616 
617  if (ns.context()->makePayload) {
618  ns.context()->compMaterialsRefs[nam].emplace_back(
619  cms::DDParsingContext::CompositeMaterial(ns.prepend(fracname), fraction));
620  }
621  TGeoMaterial* frac_mat = mgr.GetMaterial(fracname.c_str());
622  if (frac_mat == nullptr) // Try to find it within this namespace
623  frac_mat = mgr.GetMaterial(ns.prepend(fracname).c_str());
624  if (frac_mat) {
625  mix->AddElement(frac_mat, fraction);
626  continue;
627  }
628 
629  printout(ns.context()->debug_materials ? ALWAYS : WARNING,
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  ns.context()->unresolvedMaterials[nam].emplace_back(
636  cms::DDParsingContext::CompositeMaterial(ns.prepend(fracname), fraction));
637  }
638  mix->SetTemperature(ns.context()->description.stdConditions().temperature);
639  mix->SetPressure(ns.context()->description.stdConditions().pressure);
640  mix->SetRadLen(0e0);
642  TGeoMedium* medium = mgr.GetMedium(matname);
643  if (nullptr == medium) {
644  --unique_mat_id;
645  medium = new TGeoMedium(matname, unique_mat_id, mix);
646  medium->SetTitle("material");
647  medium->SetUniqueID(unique_mat_id);
648  }
649  }
650 }
651 
653 template <>
654 void Converter<DDLRotation>::operator()(xml_h element) const {
655  cms::DDParsingContext* context = _param<cms::DDParsingContext>();
656  cms::DDNamespace ns(context);
657  xml_dim_t xrot(element);
658  string nam = xrot.nameStr();
659  double thetaX = xrot.hasAttr(DD_CMU(thetaX)) ? ns.attr<double>(xrot, DD_CMU(thetaX)) : 0e0;
660  double phiX = xrot.hasAttr(DD_CMU(phiX)) ? ns.attr<double>(xrot, DD_CMU(phiX)) : 0e0;
661  double thetaY = xrot.hasAttr(DD_CMU(thetaY)) ? ns.attr<double>(xrot, DD_CMU(thetaY)) : 0e0;
662  double phiY = xrot.hasAttr(DD_CMU(phiY)) ? ns.attr<double>(xrot, DD_CMU(phiY)) : 0e0;
663  double thetaZ = xrot.hasAttr(DD_CMU(thetaZ)) ? ns.attr<double>(xrot, DD_CMU(thetaZ)) : 0e0;
664  double phiZ = xrot.hasAttr(DD_CMU(phiZ)) ? ns.attr<double>(xrot, DD_CMU(phiZ)) : 0e0;
665  Rotation3D rot = makeRotation3D(thetaX, phiX, thetaY, phiY, thetaZ, phiZ);
666 
667 #ifdef EDM_ML_DEBUG
668 
669  printout(context->debug_rotations ? ALWAYS : DEBUG,
670  "DD4CMS",
671  "+++ Adding rotation: %-32s: (theta/phi)[rad] X: %6.3f %6.3f Y: %6.3f %6.3f Z: %6.3f %6.3f",
672  ns.prepend(nam).c_str(),
673  thetaX,
674  phiX,
675  thetaY,
676  phiY,
677  thetaZ,
678  phiZ);
679 
680 #endif
681 
682  ns.addRotation(nam, rot);
683 }
684 
686 template <>
687 void Converter<DDLReflectionRotation>::operator()(xml_h element) const {
688  cms::DDParsingContext* context = _param<cms::DDParsingContext>();
689  cms::DDNamespace ns(context);
690  xml_dim_t xrot(element);
691  string name = xrot.nameStr();
692  double thetaX = xrot.hasAttr(DD_CMU(thetaX)) ? ns.attr<double>(xrot, DD_CMU(thetaX)) : 0e0;
693  double phiX = xrot.hasAttr(DD_CMU(phiX)) ? ns.attr<double>(xrot, DD_CMU(phiX)) : 0e0;
694  double thetaY = xrot.hasAttr(DD_CMU(thetaY)) ? ns.attr<double>(xrot, DD_CMU(thetaY)) : 0e0;
695  double phiY = xrot.hasAttr(DD_CMU(phiY)) ? ns.attr<double>(xrot, DD_CMU(phiY)) : 0e0;
696  double thetaZ = xrot.hasAttr(DD_CMU(thetaZ)) ? ns.attr<double>(xrot, DD_CMU(thetaZ)) : 0e0;
697  double phiZ = xrot.hasAttr(DD_CMU(phiZ)) ? ns.attr<double>(xrot, DD_CMU(phiZ)) : 0e0;
698 
699 #ifdef EDM_ML_DEBUG
700 
701  printout(context->debug_rotations ? ALWAYS : DEBUG,
702  "DD4CMS",
703  "+++ Adding reflection rotation: %-32s: (theta/phi)[rad] X: %6.3f %6.3f Y: %6.3f %6.3f Z: %6.3f %6.3f",
704  ns.prepend(name).c_str(),
705  thetaX,
706  phiX,
707  thetaY,
708  phiY,
709  thetaZ,
710  phiZ);
711 
712 #endif
713 
714  Rotation3D rot = makeRotReflect(thetaX, phiX, thetaY, phiY, thetaZ, phiZ);
715  ns.addRotation(name, rot);
716 }
717 
719 template <>
720 void Converter<DDLRotationSequence>::operator()(xml_h element) const {
721  cms::DDParsingContext* context = _param<cms::DDParsingContext>();
722  cms::DDNamespace ns(context);
723  xml_dim_t xrot(element);
724  string nam = xrot.nameStr();
725  Rotation3D rot;
726  xml_coll_t rotations(xrot, DD_CMU(RotationByAxis));
727  for (rotations.reset(); rotations; ++rotations) {
728  string axis = ns.attr<string>(rotations, DD_CMU(axis));
729  double angle = ns.attr<double>(rotations, _U(angle));
730  rot = makeRotation3D(rot, axis, angle);
731 
732 #ifdef EDM_ML_DEBUG
733 
734  printout(context->debug_rotations ? ALWAYS : DEBUG,
735  "DD4CMS",
736  "+ Adding rotation to: %-29s: (axis/angle)[rad] Axis: %s Angle: %6.3f",
737  nam.c_str(),
738  axis.c_str(),
739  angle);
740 
741 #endif
742  }
743  double xx, xy, xz;
744  double yx, yy, yz;
745  double zx, zy, zz;
746  rot.GetComponents(xx, xy, xz, yx, yy, yz, zx, zy, zz);
747 
748 #ifdef EDM_ML_DEBUG
749 
750  printout(context->debug_rotations ? ALWAYS : DEBUG,
751  "DD4CMS",
752  "+++ Adding rotation sequence: %-23s: %6.3f %6.3f %6.3f, %6.3f %6.3f %6.3f, %6.3f %6.3f %6.3f",
753  ns.prepend(nam).c_str(),
754  xx,
755  xy,
756  xz,
757  yx,
758  yy,
759  yz,
760  zx,
761  zy,
762  zz);
763 
764 #endif
765 
766  ns.addRotation(nam, rot);
767 }
768 
770 template <>
771 void Converter<DDLRotationByAxis>::operator()(xml_h element) const {
772  cms::DDParsingContext* context = _param<cms::DDParsingContext>();
773  cms::DDNamespace ns(context);
774  xml_dim_t xrot(element);
775  xml_dim_t par(xrot.parent());
776  if (xrot.hasAttr(_U(name))) {
777  string nam = xrot.nameStr();
778  string axis = ns.attr<string>(xrot, DD_CMU(axis));
779  double angle = ns.attr<double>(xrot, _U(angle));
780  Rotation3D rot;
781  rot = makeRotation3D(rot, axis, angle);
782 
783 #ifdef EDM_ML_DEBUG
784 
785  printout(context->debug_rotations ? ALWAYS : DEBUG,
786  "DD4CMS",
787  "+++ Adding rotation: %-32s: (axis/angle)[rad] Axis: %s Angle: %6.3f",
788  ns.prepend(nam).c_str(),
789  axis.c_str(),
790  angle);
791 
792 #endif
793 
794  ns.addRotation(nam, rot);
795  }
796 }
797 
799 template <>
800 void Converter<DDLLogicalPart>::operator()(xml_h element) const {
801  cms::DDNamespace ns(_param<cms::DDParsingContext>());
802  xml_dim_t e(element);
803  string sol = e.child(DD_CMU(rSolid)).attr<string>(_U(name));
804  string mat = e.child(DD_CMU(rMaterial)).attr<string>(_U(name));
805  string volName = ns.prepend(e.attr<string>(_U(name)));
806  Solid solid = ns.solid(sol);
807  Material material = ns.material(mat);
808  if (ns.context()->assemblySolids.count(sol) == 1) {
809  // To match the general paradigm, an assembly starts as a solid,
810  // and then a logical part is made of the solid. However, the
811  // solid is just a dummy whose names tags it as an assembly.
812  ns.addAssembly(volName, false);
813  return;
814  }
815 
816 #ifdef EDM_ML_DEBUG
817  Volume volume =
818 #endif
819 
820  ns.addVolume(Volume(volName, solid, material));
821 
822 #ifdef EDM_ML_DEBUG
823 
824  printout(ns.context()->debug_volumes ? ALWAYS : DEBUG,
825  "DD4CMS",
826  "+++ %s Volume: %-24s [%s] Shape: %-32s [%s] Material: %-40s [%s]",
827  e.tag().c_str(),
828  volName.c_str(),
829  volume.isValid() ? "VALID" : "INVALID",
830  sol.c_str(),
831  solid.isValid() ? "VALID" : "INVALID",
832  mat.c_str(),
833  material.isValid() ? "VALID" : "INVALID");
834 
835 #endif
836 }
837 
839 template <>
840 void Converter<DDLTransform3D>::operator()(xml_h element) const {
841  cms::DDNamespace ns(_param<cms::DDParsingContext>());
842  Transform3D* tr = _option<Transform3D>();
843  xml_dim_t e(element);
844  xml_dim_t translation = e.child(DD_CMU(Translation), false);
845  xml_dim_t rotation = e.child(DD_CMU(Rotation), false);
846  xml_dim_t refRotation = e.child(DD_CMU(rRotation), false);
847  xml_dim_t refReflectionRotation = e.child(DD_CMU(rReflectionRotation), false);
848  Position pos;
849  Rotation3D rot;
850 
851  if (translation.ptr()) {
852  double x = ns.attr<double>(translation, _U(x));
853  double y = ns.attr<double>(translation, _U(y));
854  double z = ns.attr<double>(translation, _U(z));
855  pos = Position(x, y, z);
856  }
857  if (rotation.ptr()) {
858  double x = ns.attr<double>(rotation, _U(x));
859  double y = ns.attr<double>(rotation, _U(y));
860  double z = ns.attr<double>(rotation, _U(z));
861  rot = RotationZYX(z, y, x);
862  } else if (refRotation.ptr()) {
863  string rotName = ns.prepend(refRotation.nameStr());
864  rot = ns.rotation(rotName);
865  } else if (refReflectionRotation.ptr()) {
866  string rotName = ns.prepend(refReflectionRotation.nameStr());
867  rot = ns.rotation(rotName);
868  }
869  *tr = Transform3D(rot, pos);
870 }
871 
872 static void placeAssembly(Volume* parentPtr,
873  const string& parentName,
874  Volume* childPtr,
875  const string& childName,
876  int copy,
877  const Transform3D& transform,
878  cms::DDNamespace& ns) {
879 #ifdef EDM_ML_DEBUG
880 
881  printout(ns.context()->debug_placements ? ALWAYS : DEBUG,
882  "DD4CMS",
883  "+++ Parent vol: %-24s Child: %-32s, copy:%d",
884  parentName.c_str(),
885  childName.c_str(),
886  copy);
887 
888 #endif
889 
890  TGeoShape* shape = (*childPtr)->GetShape();
891  // Need to fix the daughter's BBox of assemblies, if the BBox was not calculated....
892  if (shape->IsA() == TGeoShapeAssembly::Class()) {
893  TGeoShapeAssembly* as = (TGeoShapeAssembly*)shape;
894  if (std::fabs(as->GetDX()) < numeric_limits<double>::epsilon() &&
895  std::fabs(as->GetDY()) < numeric_limits<double>::epsilon() &&
896  std::fabs(as->GetDZ()) < numeric_limits<double>::epsilon()) {
897  as->NeedsBBoxRecompute();
898  as->ComputeBBox();
899  }
900  }
901  TGeoNode* n;
902  TString nam_id = TString::Format("%s_%d", (*childPtr)->GetName(), copy);
903  n = static_cast<TGeoNode*>((*parentPtr)->GetNode(nam_id));
904  if (n != nullptr) {
905  printout(ERROR, "PlacedVolume", "++ Attempt to add already existing node %s", (const char*)nam_id);
906  return;
907  }
908 
910  if ((*childPtr)->IsAssembly()) {
911  pv = parentPtr->placeVolume(ns.assembly(childName), copy, transform);
912  } else {
913  pv = parentPtr->placeVolume(*childPtr, copy, transform);
914  }
915 
916  if (!pv.isValid()) {
917  printout(ERROR, "DD4CMS", "+++ Placement FAILED! Parent:%s Child:%s", parentName.c_str(), childName.c_str());
918  }
919 }
920 
922 template <>
923 void Converter<DDLPosPart>::operator()(xml_h element) const {
924  cms::DDNamespace ns(_param<cms::DDParsingContext>()); //, element, true );
925  xml_dim_t e(element);
926  int copy = e.attr<int>(DD_CMU(copyNumber));
927  string parentName = ns.prepend(ns.attr<string>(e.child(DD_CMU(rParent)), _U(name)));
928  string childName = ns.prepend(ns.attr<string>(e.child(DD_CMU(rChild)), _U(name)));
929  Transform3D transform;
930  Converter<DDLTransform3D>(description, param, &transform)(element);
931 
932  Volume parent = ns.volume(parentName, false);
933  Volume child = ns.volume(childName, false);
934  Assembly parAsmb = ns.assembly(parentName, false);
935  Assembly childAsmb = ns.assembly(childName, false);
936 
937 #ifdef EDM_ML_DEBUG
938 
939  printout(ns.context()->debug_placements ? ALWAYS : DEBUG,
940  "DD4CMS",
941  "+++ %s Parent: %-24s [%s] Child: %-32s [%s] copy:%d",
942  e.tag().c_str(),
943  parentName.c_str(),
944  parent.isValid() ? "VALID" : "INVALID",
945  childName.c_str(),
946  child.isValid() ? "VALID" : "INVALID",
947  copy);
948 
949 #endif
950 
951  if (!parent.isValid() && !parAsmb.isValid() && strchr(parentName.c_str(), NAMESPACE_SEP) == nullptr) {
952  parentName = ns.prepend(parentName);
953  parAsmb = ns.assembly(parentName, false);
954  if (!parAsmb.isValid())
955  parent = ns.volume(parentName);
956  }
957 
958  if (!child.isValid() && !childAsmb.isValid() && strchr(childName.c_str(), NAMESPACE_SEP) == nullptr) {
959  childName = ns.prepend(childName);
960  child = ns.volume(childName, false);
961  childAsmb = ns.assembly(childName, false);
962  }
963  if (parAsmb.isValid() || childAsmb.isValid()) {
964  printout(ns.context()->debug_placements ? ALWAYS : DEBUG,
965  "DD4CMS",
966  "***** Placing assembly parent %s, child %s",
967  parentName.c_str(),
968  childName.c_str());
969  Volume* parentPtr = parAsmb.isValid() ? &parAsmb : &parent;
970  Volume* childPtr = childAsmb.isValid() ? &childAsmb : &child;
971  placeAssembly(parentPtr, parentName, childPtr, childName, copy, transform, ns);
972  return;
973  }
974 
975 #ifdef EDM_ML_DEBUG
976 
977  printout(ns.context()->debug_placements ? ALWAYS : DEBUG,
978  "DD4CMS",
979  "+++ %s Parent: %-24s [%s] Child: %-32s [%s] copy:%d",
980  e.tag().c_str(),
981  parentName.c_str(),
982  parent.isValid() ? "VALID" : "INVALID",
983  childName.c_str(),
984  child.isValid() ? "VALID" : "INVALID",
985  copy);
986 
987 #endif
988 
990  if (child.isValid()) {
991  // FIXME: workaround for Reflection rotation
992  // copy from DDCore/src/Volumes.cpp to replace
993  // static PlacedVolume _addNode(TGeoVolume* par, TGeoVolume* daughter, int id, TGeoMatrix* transform)
994  if (!parent) {
995  except("dd4hep", "Volume: Attempt to assign daughters to an invalid physical parent volume.");
996  }
997  if (!child) {
998  except("dd4hep", "Volume: Attempt to assign an invalid physical daughter volume.");
999  }
1000  TGeoShape* shape = child->GetShape();
1001  // Need to fix the daughter's BBox of assemblies, if the BBox was not calculated....
1002  if (shape->IsA() == TGeoShapeAssembly::Class()) {
1003  TGeoShapeAssembly* as = (TGeoShapeAssembly*)shape;
1004  if (std::fabs(as->GetDX()) < numeric_limits<double>::epsilon() &&
1005  std::fabs(as->GetDY()) < numeric_limits<double>::epsilon() &&
1006  std::fabs(as->GetDZ()) < numeric_limits<double>::epsilon()) {
1007  as->NeedsBBoxRecompute();
1008  as->ComputeBBox();
1009  }
1010  }
1011  TGeoNode* n;
1012  TString nam_id = TString::Format("%s_%d", child->GetName(), copy);
1013  n = static_cast<TGeoNode*>(parent->GetNode(nam_id));
1014  if (n != nullptr) {
1015  printout(ERROR, "PlacedVolume", "++ Attempt to add already existing node %s", (const char*)nam_id);
1016  }
1017 
1018  Rotation3D rot(transform.Rotation());
1019  Translation3D trans(transform.Translation());
1020  double x, y, z;
1021  trans.GetComponents(x, y, z);
1022  Position pos(x, y, z);
1023  parent->AddNode(child, copy, createPlacement(rot, pos));
1024 
1025  n = static_cast<TGeoNode*>(parent->GetNode(nam_id));
1026  n->TGeoNode::SetUserExtension(new PlacedVolume::Object());
1027  pv = PlacedVolume(n);
1028  }
1029  if (!pv.isValid()) {
1030  printout(ERROR,
1031  "DD4CMS",
1032  "+++ Placement FAILED! Parent:%s Child:%s Valid:%s",
1033  parent.name(),
1034  childName.c_str(),
1035  yes_no(child.isValid()));
1036  }
1037 }
1038 
1040 template <>
1041 void Converter<PartSelector>::operator()(xml_h element) const {
1042  cms::DDNamespace ns(_param<cms::DDParsingContext>());
1043  cms::DDParsingContext* const context = ns.context();
1044  dd4hep::SpecParRegistry& registry = *context->description.extension<dd4hep::SpecParRegistry>();
1045  xml_dim_t e(element);
1046  xml_dim_t specPar = e.parent();
1047  string specParName = specPar.attr<string>(_U(name));
1048  string path = e.attr<string>(DD_CMU(path));
1049 
1050 #ifdef EDM_ML_DEBUG
1051 
1052  printout(ns.context()->debug_specpars ? ALWAYS : DEBUG,
1053  "DD4CMS",
1054  "+++ PartSelector for %s path: %s",
1055  specParName.c_str(),
1056  path.c_str());
1057 
1058 #endif
1059 
1060  size_t pos = std::string::npos;
1061  if ((pos = path.find("//.*:")) != std::string::npos) {
1062  path.erase(pos + 2, 3);
1063  }
1064  registry.specpars[specParName].paths.emplace_back(std::move(path));
1065 }
1066 
1068 template <>
1069 void Converter<Parameter>::operator()(xml_h element) const {
1070  cms::DDNamespace ns(_param<cms::DDParsingContext>());
1071  cms::DDParsingContext* const context = ns.context();
1072  dd4hep::SpecParRegistry& registry = *context->description.extension<dd4hep::SpecParRegistry>();
1073  xml_dim_t e(element);
1074  xml_dim_t specPar = e.parent();
1075  xml_dim_t specParSect = specPar.parent();
1076  string specParName = specPar.attr<string>(_U(name));
1077  string name = e.nameStr();
1078  string value = e.attr<string>(DD_CMU(value));
1079  bool eval = specParSect.hasAttr(_U(eval)) ? specParSect.attr<bool>(_U(eval)) : false;
1080  eval = specPar.hasAttr(_U(eval)) ? specPar.attr<bool>(_U(eval)) : eval;
1081  eval = e.hasAttr(_U(eval)) ? e.attr<bool>(_U(eval)) : eval;
1082 
1083  string type = eval ? "number" : "string";
1084 
1085 #ifdef EDM_ML_DEBUG
1086 
1087  printout(ns.context()->debug_specpars ? ALWAYS : DEBUG,
1088  "DD4CMS",
1089  "+++ Parameter for %s: %s value %s is a %s",
1090  specParName.c_str(),
1091  name.c_str(),
1092  value.c_str(),
1093  type.c_str());
1094 
1095 #endif
1096 
1097  size_t idx = value.find('[');
1098  if (idx == string::npos && type == "number") {
1099  registry.specpars[specParName].numpars[name].emplace_back(dd4hep::_toDouble(value));
1100  return;
1101  }
1102  if (idx == string::npos || type == "string") {
1103  registry.specpars[specParName].spars[name].emplace_back(std::move(value));
1104  return;
1105  }
1106 
1107  while (idx != string::npos) {
1108  ++idx;
1109  size_t idp = value.find(':', idx);
1110  size_t idq = value.find(']', idx);
1111  if (idp == string::npos || idp > idq)
1112  value.insert(idx, ns.name());
1113  else if (idp != string::npos && idp < idq)
1114  value[idp] = NAMESPACE_SEP;
1115  idx = value.find('[', idx);
1116  }
1117 
1118  string rep;
1119  string& v = value;
1120  size_t idq;
1121  for (idx = v.find('[', 0); idx != string::npos; idx = v.find('[', idx + 1)) {
1122  idq = v.find(']', idx + 1);
1123  rep = v.substr(idx + 1, idq - idx - 1);
1124  auto r = ns.context()->description.constants().find(rep);
1125  if (r != ns.context()->description.constants().end()) {
1126  rep = "(" + r->second->type + ")";
1127  v.replace(idx, idq - idx + 1, rep);
1128  }
1129  }
1130  registry.specpars[specParName].numpars[name].emplace_back(dd4hep::_toDouble(value));
1131 }
1132 
1133 template <typename TYPE>
1134 static void convert_boolean(cms::DDParsingContext* context, xml_h element) {
1135  cms::DDNamespace ns(context);
1136  xml_dim_t e(element);
1137  string nam = e.nameStr();
1138  string solidName[2];
1139  Solid solids[2];
1140  Solid boolean;
1141  int cnt = 0;
1142  if (e.hasChild(DD_CMU(rSolid))) {
1143  for (xml_coll_t c(element, DD_CMU(rSolid)); cnt < 2 && c; ++c, ++cnt) {
1144  solidName[cnt] = c.attr<string>(_U(name));
1145  solids[cnt] = ns.solid(c.attr<string>(_U(name)));
1146  }
1147  } else {
1148  solidName[0] = e.attr<string>(DD_CMU(firstSolid));
1149  if ((solids[0] = ns.solid(e.attr<string>(DD_CMU(firstSolid)))).isValid())
1150  ++cnt;
1151  solidName[1] = e.attr<string>(DD_CMU(secondSolid));
1152  if ((solids[1] = ns.solid(e.attr<string>(DD_CMU(secondSolid)))).isValid())
1153  ++cnt;
1154  }
1155  if (cnt != 2) {
1156  except("DD4CMS", "+++ Failed to create boolean solid %s. Found only %d parts.", nam.c_str(), cnt);
1157  }
1158 
1159 #ifdef EDM_ML_DEBUG
1160 
1161  printout(ns.context()->debug_placements ? ALWAYS : DEBUG,
1162  "DD4CMS",
1163  "+++ BooleanSolid: %s Left: %-32s Right: %-32s",
1164  nam.c_str(),
1165  ((solids[0].ptr() == nullptr) ? solidName[0].c_str() : solids[0]->GetName()),
1166  ((solids[1].ptr() == nullptr) ? solidName[1].c_str() : solids[1]->GetName()));
1167 
1168 #endif
1169 
1170  if (solids[0].isValid() && solids[1].isValid()) {
1171  Transform3D trafo;
1172  Converter<DDLTransform3D>(context->description, context, &trafo)(element);
1173  boolean = TYPE(solids[0], solids[1], trafo);
1174  } else {
1175  // Register it for later processing
1176  Transform3D trafo;
1177  Converter<DDLTransform3D>(context->description, context, &trafo)(element);
1178  ns.context()->unresolvedShapes.emplace(nam,
1179  DDParsingContext::BooleanShape<TYPE>(solidName[0], solidName[1], trafo));
1180  }
1181  if (!boolean.isValid()) {
1182  // Delay processing the shape
1183  ns.context()->shapes.emplace(nam, dd4hep::Solid(nullptr));
1184  } else
1185  ns.addSolid(nam, boolean);
1186 }
1187 
1189 template <>
1190 void Converter<DDLUnionSolid>::operator()(xml_h element) const {
1191  convert_boolean<UnionSolid>(_param<cms::DDParsingContext>(), element);
1192 }
1193 
1195 template <>
1196 void Converter<DDLSubtractionSolid>::operator()(xml_h element) const {
1197  convert_boolean<SubtractionSolid>(_param<cms::DDParsingContext>(), element);
1198 }
1199 
1201 template <>
1202 void Converter<DDLIntersectionSolid>::operator()(xml_h element) const {
1203  convert_boolean<IntersectionSolid>(_param<cms::DDParsingContext>(), element);
1204 }
1205 
1207 template <>
1208 void Converter<DDLPolycone>::operator()(xml_h element) const {
1209  cms::DDNamespace ns(_param<cms::DDParsingContext>());
1210  xml_dim_t e(element);
1211  string nam = e.nameStr();
1212  double startPhi = ns.attr<double>(e, DD_CMU(startPhi));
1213  double deltaPhi = ns.attr<double>(e, DD_CMU(deltaPhi));
1214  vector<double> z, rmin, rmax, r;
1215 
1216  for (xml_coll_t rzpoint(element, DD_CMU(RZPoint)); rzpoint; ++rzpoint) {
1217  z.emplace_back(ns.attr<double>(rzpoint, _U(z)));
1218  r.emplace_back(ns.attr<double>(rzpoint, _U(r)));
1219  }
1220  if (z.empty()) {
1221  for (xml_coll_t zplane(element, DD_CMU(ZSection)); zplane; ++zplane) {
1222  rmin.emplace_back(ns.attr<double>(zplane, DD_CMU(rMin)));
1223  rmax.emplace_back(ns.attr<double>(zplane, DD_CMU(rMax)));
1224  z.emplace_back(ns.attr<double>(zplane, _U(z)));
1225  }
1226 
1227 #ifdef EDM_ML_DEBUG
1228 
1229  printout(ns.context()->debug_shapes ? ALWAYS : DEBUG,
1230  "DD4CMS",
1231  "+ Polycone: startPhi=%10.3f [rad] deltaPhi=%10.3f [rad] %4ld z-planes",
1232  startPhi,
1233  deltaPhi,
1234  z.size());
1235 
1236 #endif
1237 
1238  ns.addSolid(nam, Polycone(startPhi, deltaPhi, rmin, rmax, z));
1239  } else {
1240 #ifdef EDM_ML_DEBUG
1241 
1242  printout(ns.context()->debug_shapes ? ALWAYS : DEBUG,
1243  "DD4CMS",
1244  "+ Polycone: startPhi=%10.3f [rad] deltaPhi=%10.3f [rad] %4ld z-planes and %4ld radii",
1245  startPhi,
1246  deltaPhi,
1247  z.size(),
1248  r.size());
1249 
1250 #endif
1251 
1252  ns.addSolid(nam, Polycone(startPhi, deltaPhi, r, z));
1253  }
1254 }
1255 
1257 template <>
1258 void Converter<DDLExtrudedPolygon>::operator()(xml_h element) const {
1259  cms::DDNamespace ns(_param<cms::DDParsingContext>());
1260  xml_dim_t e(element);
1261  string nam = e.nameStr();
1262  vector<double> pt_x, pt_y, sec_x, sec_y, sec_z, sec_scale;
1263 
1264  for (xml_coll_t sec(element, DD_CMU(ZXYSection)); sec; ++sec) {
1265  sec_z.emplace_back(ns.attr<double>(sec, _U(z)));
1266  sec_x.emplace_back(ns.attr<double>(sec, _U(x)));
1267  sec_y.emplace_back(ns.attr<double>(sec, _U(y)));
1268  sec_scale.emplace_back(ns.attr<double>(sec, DD_CMU(scale), 1.0));
1269  }
1270  for (xml_coll_t pt(element, DD_CMU(XYPoint)); pt; ++pt) {
1271  pt_x.emplace_back(ns.attr<double>(pt, _U(x)));
1272  pt_y.emplace_back(ns.attr<double>(pt, _U(y)));
1273  }
1274 
1275 #ifdef EDM_ML_DEBUG
1276 
1277  printout(ns.context()->debug_shapes ? ALWAYS : DEBUG,
1278  "DD4CMS",
1279  "+ ExtrudedPolygon: %4ld points %4ld zxy sections",
1280  pt_x.size(),
1281  sec_z.size());
1282 
1283 #endif
1284 
1285  ns.addSolid(nam, ExtrudedPolygon(pt_x, pt_y, sec_z, sec_x, sec_y, sec_scale));
1286 }
1287 
1289 template <>
1290 void Converter<DDLPolyhedra>::operator()(xml_h element) const {
1291  cms::DDNamespace ns(_param<cms::DDParsingContext>());
1292  xml_dim_t e(element);
1293  string nam = e.nameStr();
1294  double numSide = ns.attr<int>(e, DD_CMU(numSide));
1295  double startPhi = ns.attr<double>(e, DD_CMU(startPhi));
1296  double deltaPhi = ns.attr<double>(e, DD_CMU(deltaPhi));
1297  vector<double> z, rmin, rmax;
1298 
1299  for (xml_coll_t zplane(element, DD_CMU(RZPoint)); zplane; ++zplane) {
1300  rmin.emplace_back(0.0);
1301  rmax.emplace_back(ns.attr<double>(zplane, _U(r)));
1302  z.emplace_back(ns.attr<double>(zplane, _U(z)));
1303  }
1304  for (xml_coll_t zplane(element, DD_CMU(ZSection)); zplane; ++zplane) {
1305  rmin.emplace_back(ns.attr<double>(zplane, DD_CMU(rMin)));
1306  rmax.emplace_back(ns.attr<double>(zplane, DD_CMU(rMax)));
1307  z.emplace_back(ns.attr<double>(zplane, _U(z)));
1308  }
1309 
1310 #ifdef EDM_ML_DEBUG
1311 
1312  printout(ns.context()->debug_shapes ? ALWAYS : DEBUG,
1313  "DD4CMS",
1314  "+ Polyhedra:startPhi=%8.3f [rad] deltaPhi=%8.3f [rad] %4d sides %4ld z-planes",
1315  startPhi,
1316  deltaPhi,
1317  numSide,
1318  z.size());
1319 
1320 #endif
1321 
1322  ns.addSolid(nam, Polyhedra(numSide, startPhi, deltaPhi, z, rmin, rmax));
1323 }
1324 
1326 template <>
1327 void Converter<DDLSphere>::operator()(xml_h element) const {
1328  cms::DDNamespace ns(_param<cms::DDParsingContext>());
1329  xml_dim_t e(element);
1330  string nam = e.nameStr();
1331  double rinner = ns.attr<double>(e, DD_CMU(innerRadius));
1332  double router = ns.attr<double>(e, DD_CMU(outerRadius));
1333  double startPhi = ns.attr<double>(e, DD_CMU(startPhi));
1334  double deltaPhi = ns.attr<double>(e, DD_CMU(deltaPhi));
1335  double startTheta = ns.attr<double>(e, DD_CMU(startTheta));
1336  double deltaTheta = ns.attr<double>(e, DD_CMU(deltaTheta));
1337 
1338 #ifdef EDM_ML_DEBUG
1339 
1340  printout(ns.context()->debug_shapes ? ALWAYS : DEBUG,
1341  "DD4CMS",
1342  "+ Sphere: r_inner=%8.3f [cm] r_outer=%8.3f [cm]"
1343  " startPhi=%8.3f [rad] deltaPhi=%8.3f startTheta=%8.3f delteTheta=%8.3f [rad]",
1344  rinner / dd4hep::cm,
1345  router / dd4hep::cm,
1346  startPhi,
1347  deltaPhi,
1348  startTheta,
1349  deltaTheta);
1350 
1351 #endif
1352 
1353  ns.addSolid(nam, Sphere(rinner, router, startTheta, deltaTheta, startPhi, deltaPhi));
1354 }
1355 
1357 template <>
1358 void Converter<DDLTorus>::operator()(xml_h element) const {
1359  cms::DDNamespace ns(_param<cms::DDParsingContext>());
1360  xml_dim_t e(element);
1361  string nam = e.nameStr();
1362  double r = ns.attr<double>(e, DD_CMU(torusRadius));
1363  double rinner = ns.attr<double>(e, DD_CMU(innerRadius));
1364  double router = ns.attr<double>(e, DD_CMU(outerRadius));
1365  double startPhi = ns.attr<double>(e, DD_CMU(startPhi));
1366  double deltaPhi = ns.attr<double>(e, DD_CMU(deltaPhi));
1367 
1368 #ifdef EDM_ML_DEBUG
1369 
1370  printout(ns.context()->debug_shapes ? ALWAYS : DEBUG,
1371  "DD4CMS",
1372  "+ Torus: r=%10.3f [cm] r_inner=%10.3f [cm] r_outer=%10.3f [cm]"
1373  " startPhi=%10.3f [rad] deltaPhi=%10.3f [rad]",
1374  r / dd4hep::cm,
1375  rinner / dd4hep::cm,
1376  router / dd4hep::cm,
1377  startPhi,
1378  deltaPhi);
1379 
1380 #endif
1381 
1382  ns.addSolid(nam, Torus(r, rinner, router, startPhi, deltaPhi));
1383 }
1384 
1386 template <>
1387 void Converter<DDLPseudoTrap>::operator()(xml_h element) const {
1388  cms::DDNamespace ns(_param<cms::DDParsingContext>());
1389  xml_dim_t e(element);
1390  string nam = e.nameStr();
1391  double dx1 = ns.attr<double>(e, DD_CMU(dx1));
1392  double dy1 = ns.attr<double>(e, DD_CMU(dy1));
1393  double dx2 = ns.attr<double>(e, DD_CMU(dx2));
1394  double dy2 = ns.attr<double>(e, DD_CMU(dy2));
1395  double dz = ns.attr<double>(e, _U(dz));
1396  double r = ns.attr<double>(e, _U(radius));
1397  bool atMinusZ = ns.attr<bool>(e, DD_CMU(atMinusZ));
1398 
1399 #ifdef EDM_ML_DEBUG
1400 
1401  printout(ns.context()->debug_shapes ? ALWAYS : DEBUG,
1402  "DD4CMS",
1403  "+ Pseudotrap: dz=%8.3f [cm] dx1:%.3f dy1:%.3f dx2=%.3f dy2=%.3f radius:%.3f atMinusZ:%s",
1404  dz / dd4hep::cm,
1405  dx1 / dd4hep::cm,
1406  dy1 / dd4hep::cm,
1407  dx2 / dd4hep::cm,
1408  dy2 / dd4hep::cm,
1409  r / dd4hep::cm,
1410  yes_no(atMinusZ));
1411 
1412 #endif
1413 
1414  ns.addSolid(nam, PseudoTrap(dx1, dx2, dy1, dy2, dz, r, atMinusZ));
1415 }
1416 
1418 template <>
1419 void Converter<DDLTrapezoid>::operator()(xml_h element) const {
1420  cms::DDNamespace ns(_param<cms::DDParsingContext>());
1421  xml_dim_t e(element);
1422  string nam = e.nameStr();
1423  double dz = ns.attr<double>(e, _U(dz));
1424  double alp1 = ns.attr<double>(e, DD_CMU(alp1));
1425  double bl1 = ns.attr<double>(e, DD_CMU(bl1));
1426  double tl1 = ns.attr<double>(e, DD_CMU(tl1));
1427  double h1 = ns.attr<double>(e, DD_CMU(h1));
1428  double alp2 = ns.attr<double>(e, DD_CMU(alp2));
1429  double bl2 = ns.attr<double>(e, DD_CMU(bl2));
1430  double tl2 = ns.attr<double>(e, DD_CMU(tl2));
1431  double h2 = ns.attr<double>(e, DD_CMU(h2));
1432  double phi = ns.attr<double>(e, _U(phi), 0.0);
1433  double theta = ns.attr<double>(e, _U(theta), 0.0);
1434 
1435 #ifdef EDM_ML_DEBUG
1436 
1437  printout(ns.context()->debug_shapes ? ALWAYS : DEBUG,
1438  "DD4CMS",
1439  "+ Trapezoid: dz=%10.3f [cm] alp1:%.3f bl1=%.3f tl1=%.3f alp2=%.3f bl2=%.3f tl2=%.3f h2=%.3f phi=%.3f "
1440  "theta=%.3f",
1441  dz / dd4hep::cm,
1442  alp1,
1443  bl1 / dd4hep::cm,
1444  tl1 / dd4hep::cm,
1445  h1 / dd4hep::cm,
1446  alp2,
1447  bl2 / dd4hep::cm,
1448  tl2 / dd4hep::cm,
1449  h2 / dd4hep::cm,
1450  phi,
1451  theta);
1452 
1453 #endif
1454 
1455  ns.addSolid(nam, Trap(dz, theta, phi, h1, bl1, tl1, alp1, h2, bl2, tl2, alp2));
1456 }
1457 
1459 template <>
1460 void Converter<DDLTrd1>::operator()(xml_h element) const {
1461  cms::DDNamespace ns(_param<cms::DDParsingContext>());
1462  xml_dim_t e(element);
1463  string nam = e.nameStr();
1464  double dx1 = ns.attr<double>(e, DD_CMU(dx1));
1465  double dy1 = ns.attr<double>(e, DD_CMU(dy1));
1466  double dx2 = ns.attr<double>(e, DD_CMU(dx2), 0.0);
1467  double dy2 = ns.attr<double>(e, DD_CMU(dy2), dy1);
1468  double dz = ns.attr<double>(e, DD_CMU(dz));
1469  if (dy1 == dy2) {
1470 #ifdef EDM_ML_DEBUG
1471 
1472  printout(ns.context()->debug_shapes ? ALWAYS : DEBUG,
1473  "DD4CMS",
1474  "+ Trd1: dz=%8.3f [cm] dx1:%.3f dy1:%.3f dx2:%.3f dy2:%.3f",
1475  dz / dd4hep::cm,
1476  dx1 / dd4hep::cm,
1477  dy1 / dd4hep::cm,
1478  dx2 / dd4hep::cm,
1479  dy2 / dd4hep::cm);
1480 
1481 #endif
1482 
1483  ns.addSolid(nam, Trd1(dx1, dx2, dy1, dz));
1484  } else {
1485 #ifdef EDM_ML_DEBUG
1486 
1487  printout(ns.context()->debug_shapes ? ALWAYS : DEBUG,
1488  "DD4CMS",
1489  "+ Trd1(which is actually Trd2): dz=%8.3f [cm] dx1:%.3f dy1:%.3f dx2:%.3f dy2:%.3f",
1490  dz / dd4hep::cm,
1491  dx1 / dd4hep::cm,
1492  dy1 / dd4hep::cm,
1493  dx2 / dd4hep::cm,
1494  dy2 / dd4hep::cm);
1495 
1496 #endif
1497 
1498  ns.addSolid(nam, Trd2(dx1, dx2, dy1, dy2, dz));
1499  }
1500 }
1501 
1503 template <>
1504 void Converter<DDLTrd2>::operator()(xml_h element) const {
1505  cms::DDNamespace ns(_param<cms::DDParsingContext>());
1506  xml_dim_t e(element);
1507  string nam = e.nameStr();
1508  double dx1 = ns.attr<double>(e, DD_CMU(dx1));
1509  double dy1 = ns.attr<double>(e, DD_CMU(dy1));
1510  double dx2 = ns.attr<double>(e, DD_CMU(dx2), 0.0);
1511  double dy2 = ns.attr<double>(e, DD_CMU(dy2), dy1);
1512  double dz = ns.attr<double>(e, DD_CMU(dz));
1513 
1514 #ifdef EDM_ML_DEBUG
1515 
1516  printout(ns.context()->debug_shapes ? ALWAYS : DEBUG,
1517  "DD4CMS",
1518  "+ Trd1: dz=%8.3f [cm] dx1:%.3f dy1:%.3f dx2:%.3f dy2:%.3f",
1519  dz / dd4hep::cm,
1520  dx1 / dd4hep::cm,
1521  dy1 / dd4hep::cm,
1522  dx2 / dd4hep::cm,
1523  dy2 / dd4hep::cm);
1524 
1525 #endif
1526 
1527  ns.addSolid(nam, Trd2(dx1, dx2, dy1, dy2, dz));
1528 }
1529 
1531 template <>
1532 void Converter<DDLTubs>::operator()(xml_h element) const {
1533  cms::DDNamespace ns(_param<cms::DDParsingContext>());
1534  xml_dim_t e(element);
1535  string nam = e.nameStr();
1536  double dz = ns.attr<double>(e, DD_CMU(dz));
1537  double rmin = ns.attr<double>(e, DD_CMU(rMin));
1538  double rmax = ns.attr<double>(e, DD_CMU(rMax));
1539  double startPhi = ns.attr<double>(e, DD_CMU(startPhi), 0.0);
1540  double deltaPhi = ns.attr<double>(e, DD_CMU(deltaPhi), 2 * M_PI);
1541 
1542 #ifdef EDM_ML_DEBUG
1543 
1544  printout(ns.context()->debug_shapes ? ALWAYS : DEBUG,
1545  "DD4CMS",
1546  "+ Tubs: dz=%8.3f [cm] rmin=%8.3f [cm] rmax=%8.3f [cm]"
1547  " startPhi=%8.3f [rad] deltaPhi=%8.3f [rad]",
1548  dz / dd4hep::cm,
1549  rmin / dd4hep::cm,
1550  rmax / dd4hep::cm,
1551  startPhi,
1552  deltaPhi);
1553 
1554 #endif
1555 
1556  ns.addSolid(nam, Tube(rmin, rmax, dz, startPhi, startPhi + deltaPhi));
1557 }
1558 
1560 template <>
1561 void Converter<DDLCutTubs>::operator()(xml_h element) const {
1562  cms::DDNamespace ns(_param<cms::DDParsingContext>());
1563  xml_dim_t e(element);
1564  string nam = e.nameStr();
1565  double dz = ns.attr<double>(e, DD_CMU(dz));
1566  double rmin = ns.attr<double>(e, DD_CMU(rMin));
1567  double rmax = ns.attr<double>(e, DD_CMU(rMax));
1568  double startPhi = ns.attr<double>(e, DD_CMU(startPhi));
1569  double deltaPhi = ns.attr<double>(e, DD_CMU(deltaPhi));
1570  double lx = ns.attr<double>(e, DD_CMU(lx));
1571  double ly = ns.attr<double>(e, DD_CMU(ly));
1572  double lz = ns.attr<double>(e, DD_CMU(lz));
1573  double tx = ns.attr<double>(e, DD_CMU(tx));
1574  double ty = ns.attr<double>(e, DD_CMU(ty));
1575  double tz = ns.attr<double>(e, DD_CMU(tz));
1576 
1577 #ifdef EDM_ML_DEBUG
1578 
1579  printout(ns.context()->debug_shapes ? ALWAYS : DEBUG,
1580  "DD4CMS",
1581  "+ CutTube: dz=%8.3f [cm] rmin=%8.3f [cm] rmax=%8.3f [cm]"
1582  " startPhi=%8.3f [rad] deltaPhi=%8.3f [rad]...",
1583  dz / dd4hep::cm,
1584  rmin / dd4hep::cm,
1585  rmax / dd4hep::cm,
1586  startPhi,
1587  deltaPhi);
1588 
1589 #endif
1590 
1591  ns.addSolid(nam, CutTube(rmin, rmax, dz, startPhi, startPhi + deltaPhi, lx, ly, lz, tx, ty, tz));
1592 }
1593 
1595 template <>
1596 void Converter<DDLTruncTubs>::operator()(xml_h element) const {
1597  cms::DDNamespace ns(_param<cms::DDParsingContext>());
1598  xml_dim_t e(element);
1599  string nam = e.nameStr();
1600  double zhalf = ns.attr<double>(e, DD_CMU(zHalf));
1601  double rmin = ns.attr<double>(e, DD_CMU(rMin));
1602  double rmax = ns.attr<double>(e, DD_CMU(rMax));
1603  double startPhi = ns.attr<double>(e, DD_CMU(startPhi));
1604  double deltaPhi = ns.attr<double>(e, DD_CMU(deltaPhi));
1605  double cutAtStart = ns.attr<double>(e, DD_CMU(cutAtStart));
1606  double cutAtDelta = ns.attr<double>(e, DD_CMU(cutAtDelta));
1607  bool cutInside = ns.attr<bool>(e, DD_CMU(cutInside));
1608 
1609 #ifdef EDM_ML_DEBUG
1610 
1611  printout(ns.context()->debug_shapes ? ALWAYS : DEBUG,
1612  "DD4CMS",
1613  "+ TruncTube:zHalf=%8.3f [cm] rmin=%8.3f [cm] rmax=%8.3f [cm]"
1614  " startPhi=%8.3f [rad] deltaPhi=%8.3f [rad] atStart=%8.3f [cm] atDelta=%8.3f [cm] inside:%s",
1615  zhalf / dd4hep::cm,
1616  rmin / dd4hep::cm,
1617  rmax / dd4hep::cm,
1618  startPhi,
1619  deltaPhi,
1620  cutAtStart / dd4hep::cm,
1621  cutAtDelta / dd4hep::cm,
1622  yes_no(cutInside));
1623 
1624 #endif
1625 
1626  ns.addSolid(nam, TruncatedTube(zhalf, rmin, rmax, startPhi, deltaPhi, cutAtStart, cutAtDelta, cutInside));
1627 }
1628 
1630 template <>
1631 void Converter<DDLEllipticalTube>::operator()(xml_h element) const {
1632  cms::DDNamespace ns(_param<cms::DDParsingContext>());
1633  xml_dim_t e(element);
1634  string nam = e.nameStr();
1635  double dx = ns.attr<double>(e, DD_CMU(xSemiAxis));
1636  double dy = ns.attr<double>(e, DD_CMU(ySemiAxis));
1637  double dz = ns.attr<double>(e, DD_CMU(zHeight));
1638 
1639 #ifdef EDM_ML_DEBUG
1640 
1641  printout(ns.context()->debug_shapes ? ALWAYS : DEBUG,
1642  "DD4CMS",
1643  "+ EllipticalTube xSemiAxis=%8.3f [cm] ySemiAxis=%8.3f [cm] zHeight=%8.3f [cm]",
1644  dx / dd4hep::cm,
1645  dy / dd4hep::cm,
1646  dz / dd4hep::cm);
1647 
1648 #endif
1649 
1650  ns.addSolid(nam, EllipticalTube(dx, dy, dz));
1651 }
1652 
1654 template <>
1655 void Converter<DDLCone>::operator()(xml_h element) const {
1656  cms::DDNamespace ns(_param<cms::DDParsingContext>());
1657  xml_dim_t e(element);
1658  string nam = e.nameStr();
1659  double dz = ns.attr<double>(e, DD_CMU(dz));
1660  double rmin1 = ns.attr<double>(e, DD_CMU(rMin1));
1661  double rmin2 = ns.attr<double>(e, DD_CMU(rMin2));
1662  double rmax1 = ns.attr<double>(e, DD_CMU(rMax1));
1663  double rmax2 = ns.attr<double>(e, DD_CMU(rMax2));
1664  double startPhi = ns.attr<double>(e, DD_CMU(startPhi));
1665  double deltaPhi = ns.attr<double>(e, DD_CMU(deltaPhi));
1666  double phi2 = startPhi + deltaPhi;
1667 
1668 #ifdef EDM_ML_DEBUG
1669 
1670  printout(ns.context()->debug_shapes ? ALWAYS : DEBUG,
1671  "DD4CMS",
1672  "+ Cone: dz=%8.3f [cm]"
1673  " rmin1=%8.3f [cm] rmax1=%8.3f [cm]"
1674  " rmin2=%8.3f [cm] rmax2=%8.3f [cm]"
1675  " startPhi=%8.3f [rad] deltaPhi=%8.3f [rad]",
1676  dz / dd4hep::cm,
1677  rmin1 / dd4hep::cm,
1678  rmax1 / dd4hep::cm,
1679  rmin2 / dd4hep::cm,
1680  rmax2 / dd4hep::cm,
1681  startPhi,
1682  deltaPhi);
1683 
1684 #endif
1685 
1686  ns.addSolid(nam, ConeSegment(dz, rmin1, rmax1, rmin2, rmax2, startPhi, phi2));
1687 }
1688 
1690 template <>
1691 void Converter<DDLShapeless>::operator()(xml_h element) const {
1692  cms::DDNamespace ns(_param<cms::DDParsingContext>());
1693  xml_dim_t e(element);
1694  string nam = e.nameStr();
1695 
1696 #ifdef EDM_ML_DEBUG
1697 
1698  printout(ns.context()->debug_shapes ? ALWAYS : DEBUG,
1699  "DD4CMS",
1700  "+ Shapeless: THIS ONE CAN ONLY BE USED AT THE VOLUME LEVEL -> Shapeless: %s",
1701  nam.c_str());
1702 
1703 #endif
1704 
1705  ns.addSolid(nam, Box(1, 1, 1));
1706 }
1707 
1709 template <>
1710 void Converter<DDLAssembly>::operator()(xml_h element) const {
1711  cms::DDNamespace ns(_param<cms::DDParsingContext>());
1712  xml_dim_t e(element);
1713  string nam = e.nameStr();
1714 
1715 #ifdef EDM_ML_DEBUG
1716  printout(
1717  ns.context()->debug_shapes ? ALWAYS : DEBUG, "DD4CMS", "+ Assembly: Adding solid -> Assembly: %s", nam.c_str());
1718 #endif
1719 
1720  ns.addAssemblySolid(nam);
1721 }
1722 
1724 template <>
1725 void Converter<DDLBox>::operator()(xml_h element) const {
1726  cms::DDNamespace ns(_param<cms::DDParsingContext>());
1727  xml_dim_t e(element);
1728  string nam = e.nameStr();
1729  double dx = ns.attr<double>(e, DD_CMU(dx));
1730  double dy = ns.attr<double>(e, DD_CMU(dy));
1731  double dz = ns.attr<double>(e, DD_CMU(dz));
1732 
1733 #ifdef EDM_ML_DEBUG
1734 
1735  printout(ns.context()->debug_shapes ? ALWAYS : DEBUG,
1736  "DD4CMS",
1737  "+ Box: dx=%10.3f [cm] dy=%10.3f [cm] dz=%10.3f [cm]",
1738  dx / dd4hep::cm,
1739  dy / dd4hep::cm,
1740  dz / dd4hep::cm);
1741 
1742 #endif
1743 
1744  ns.addSolid(nam, Box(dx, dy, dz));
1745 }
1746 
1748 template <>
1749 void Converter<include_load>::operator()(xml_h element) const {
1750  string fname = element.attr<string>(_U(ref));
1751  edm::FileInPath fp(fname);
1752  xml::Document doc;
1753  doc = xml::DocumentHandler().load(fp.fullPath());
1754 
1755 #ifdef EDM_ML_DEBUG
1756 
1757  printout(_param<cms::DDParsingContext>()->debug_includes ? ALWAYS : DEBUG,
1758  "DD4CMS",
1759  "+++ Processing the CMS detector description %s",
1760  fname.c_str());
1761 
1762 #endif
1763 
1764  _option<DDRegistry>()->includes.emplace_back(doc);
1765 }
1766 
1768 template <>
1769 void Converter<include_unload>::operator()(xml_h element) const {
1770  string fname = xml::DocumentHandler::system_path(element);
1771  xml::DocumentHolder(xml_elt_t(element).document()).assign(nullptr);
1772 
1773 #ifdef EDM_ML_DEBUG
1774 
1775  printout(_param<cms::DDParsingContext>()->debug_includes ? ALWAYS : DEBUG,
1776  "DD4CMS",
1777  "+++ Finished processing %s",
1778  fname.c_str());
1779 #endif
1780 }
1781 
1783 template <>
1784 void Converter<include_constants>::operator()(xml_h element) const {
1785  xml_coll_t(element, DD_CMU(ConstantsSection)).for_each(Converter<ConstantsSection>(description, param, optional));
1786 }
1787 
1788 namespace {
1789 
1790  // The meaning of the axis index is the following:
1791  // for all volumes having shapes like box, trd1, trd2, trap, gtra or para - 1,2,3 means X,Y,Z;
1792  // for tube, tubs, cone, cons - 1 means Rxy, 2 means phi and 3 means Z;
1793  // for pcon and pgon - 2 means phi and 3 means Z;
1794  // for spheres 1 means R and 2 means phi.
1795 
1796  enum class DDAxes { x = 1, y = 2, z = 3, rho = 1, phi = 2, undefined };
1797  const std::map<std::string, DDAxes> axesmap{{"x", DDAxes::x},
1798  {"y", DDAxes::y},
1799  {"z", DDAxes::z},
1800  {"rho", DDAxes::rho},
1801  {"phi", DDAxes::phi},
1802  {"undefined", DDAxes::undefined}};
1803 } // namespace
1804 
1806 template <>
1807 void Converter<DDLDivision>::operator()(xml_h element) const {
1808  cms::DDNamespace ns(_param<cms::DDParsingContext>(), element);
1809  xml_dim_t e(element);
1810  string childName = e.nameStr();
1811  if (strchr(childName.c_str(), NAMESPACE_SEP) == nullptr)
1812  childName = ns.prepend(childName);
1813 
1814  string parentName = ns.attr<string>(e, DD_CMU(parent));
1815  if (strchr(parentName.c_str(), NAMESPACE_SEP) == nullptr)
1816  parentName = ns.prepend(parentName);
1817  string axis = ns.attr<string>(e, DD_CMU(axis));
1818 
1819  // If you divide a tube of 360 degrees the offset displaces
1820  // the starting angle, but you still fill the 360 degrees
1821  double offset = e.hasAttr(DD_CMU(offset)) ? ns.attr<double>(e, DD_CMU(offset)) : 0e0;
1822  double width = e.hasAttr(DD_CMU(width)) ? ns.attr<double>(e, DD_CMU(width)) : 0e0;
1823  int nReplicas = e.hasAttr(DD_CMU(nReplicas)) ? ns.attr<int>(e, DD_CMU(nReplicas)) : 0;
1824 
1825 #ifdef EDM_ML_DEBUG
1826 
1827  printout(ns.context()->debug_placements ? ALWAYS : DEBUG,
1828  "DD4CMS",
1829  "+++ Start executing Division of %s along %s (%d) with offset %6.3f and %6.3f to produce %s....",
1830  parentName.c_str(),
1831  axis.c_str(),
1832  axesmap.at(axis),
1833  offset,
1834  width,
1835  childName.c_str());
1836 
1837 #endif
1838 
1839  Volume parent = ns.volume(parentName);
1840 
1841  const TGeoShape* shape = parent.solid();
1842  TClass* cl = shape->IsA();
1843  if (cl == TGeoTubeSeg::Class()) {
1844  const TGeoTubeSeg* sh = (const TGeoTubeSeg*)shape;
1845  double widthInDeg = convertRadToDeg(width);
1846  double startInDeg = convertRadToDeg(offset);
1847  int numCopies = (int)((sh->GetPhi2() - sh->GetPhi1()) / widthInDeg);
1848 
1849 #ifdef EDM_ML_DEBUG
1850 
1851  printout(ns.context()->debug_placements ? ALWAYS : DEBUG,
1852  "DD4CMS",
1853  "+++ ...divide %s along %s (%d) with offset %6.3f deg and %6.3f deg to produce %d copies",
1854  parent.solid().type(),
1855  axis.c_str(),
1856  axesmap.at(axis),
1857  startInDeg,
1858  widthInDeg,
1859  numCopies);
1860 
1861 #endif
1862 
1863  Volume child = parent.divide(childName, static_cast<int>(axesmap.at(axis)), numCopies, startInDeg, widthInDeg);
1864 
1865  ns.context()->volumes[childName] = child;
1866 
1867 #ifdef EDM_ML_DEBUG
1868 
1869  printout(ns.context()->debug_placements ? ALWAYS : DEBUG,
1870  "DD4CMS",
1871  "+++ %s Parent: %-24s [%s] Child: %-32s [%s] is multivolume [%s]",
1872  e.tag().c_str(),
1873  parentName.c_str(),
1874  parent.isValid() ? "VALID" : "INVALID",
1875  child.name(),
1876  child.isValid() ? "VALID" : "INVALID",
1877  child->IsVolumeMulti() ? "YES" : "NO");
1878 #endif
1879 
1880  } else if (cl == TGeoTrd1::Class()) {
1881  double dy = static_cast<const TGeoTrd1*>(shape)->GetDy();
1882 
1883 #ifdef EDM_ML_DEBUG
1884 
1885  printout(ns.context()->debug_placements ? ALWAYS : DEBUG,
1886  "DD4CMS",
1887  "+++ ...divide %s along %s (%d) with offset %6.3f cm and %6.3f cm to produce %d copies in %6.3f",
1888  parent.solid().type(),
1889  axis.c_str(),
1890  axesmap.at(axis),
1891  -dy + offset + width,
1892  width,
1893  nReplicas,
1894  dy);
1895 
1896 #endif
1897 
1898  Volume child = parent.divide(childName, static_cast<int>(axesmap.at(axis)), nReplicas, -dy + offset + width, width);
1899 
1900  ns.context()->volumes[childName] = child;
1901 
1902 #ifdef EDM_ML_DEBUG
1903 
1904  printout(ns.context()->debug_placements ? ALWAYS : DEBUG,
1905  "DD4CMS",
1906  "+++ %s Parent: %-24s [%s] Child: %-32s [%s] is multivolume [%s]",
1907  e.tag().c_str(),
1908  parentName.c_str(),
1909  parent.isValid() ? "VALID" : "INVALID",
1910  child.name(),
1911  child.isValid() ? "VALID" : "INVALID",
1912  child->IsVolumeMulti() ? "YES" : "NO");
1913 
1914 #endif
1915  } else {
1916  printout(ERROR, "DD4CMS", "++ FAILED Division of a %s is not implemented yet!", parent.solid().type());
1917  }
1918 }
1919 
1921 template <>
1922 void Converter<DDLAlgorithm>::operator()(xml_h element) const {
1923  cms::DDNamespace ns(_param<cms::DDParsingContext>());
1924  xml_dim_t e(element);
1925  string name = e.nameStr();
1926  size_t idx;
1927  string type = "DDCMS_" + ns.realName(name);
1928  while ((idx = type.find(NAMESPACE_SEP)) != string::npos)
1929  type[idx] = '_';
1930 
1931 #ifdef EDM_ML_DEBUG
1932 
1933  printout(
1934  ns.context()->debug_algorithms ? ALWAYS : DEBUG, "DD4CMS", "+++ Start executing algorithm %s....", type.c_str());
1935 
1936 #endif
1937 
1938  long ret = PluginService::Create<long>(type, &description, ns.context(), &element);
1939  if (ret == s_executed) {
1940 #ifdef EDM_ML_DEBUG
1941 
1942  printout(ns.context()->debug_algorithms ? ALWAYS : DEBUG,
1943 
1944  "DD4CMS",
1945  "+++ Executed algorithm: %08lX = %s",
1946  ret,
1947  name.c_str());
1948 
1949 #endif
1950  return;
1951  }
1952  printout(ERROR, "DD4CMS", "++ FAILED NOT ADDING SUBDETECTOR %08lX = %s", ret, name.c_str());
1953 }
1954 
1955 template <class InputIt, class ForwardIt, class BinOp>
1956 void for_each_token(InputIt first, InputIt last, ForwardIt s_first, ForwardIt s_last, BinOp binary_op) {
1957  while (first != last) {
1958  const auto pos = std::find_first_of(first, last, s_first, s_last);
1959  binary_op(first, pos);
1960  if (pos == last)
1961  break;
1962  first = std::next(pos);
1963  }
1964 }
1965 
1966 namespace {
1967 
1968  std::vector<string> splitString(const string& str, const string& delims = ",") {
1969  std::vector<string> output;
1970 
1971  for_each_token(cbegin(str), cend(str), cbegin(delims), cend(delims), [&output](auto first, auto second) {
1972  if (first != second) {
1973  if (string(first, second).front() == '[' && string(first, second).back() == ']') {
1974  first++;
1975  second--;
1976  }
1977  output.emplace_back(string(first, second));
1978  }
1979  });
1980  return output;
1981  }
1982 
1983  std::vector<double> splitNumeric(const string& str, const string& delims = ",") {
1984  std::vector<double> output;
1985 
1986  for_each_token(cbegin(str), cend(str), cbegin(delims), cend(delims), [&output](auto first, auto second) {
1987  if (first != second) {
1988  if (string(first, second).front() == '[' && string(first, second).back() == ']') {
1989  first++;
1990  second--;
1991  }
1992  output.emplace_back(dd4hep::_toDouble(string(first, second)));
1993  }
1994  });
1995  return output;
1996  }
1997 } // namespace
1998 
2001 template <>
2002 void Converter<DDLVector>::operator()(xml_h element) const {
2003  cms::DDNamespace ns(_param<cms::DDParsingContext>());
2004  cms::DDParsingContext* const context = ns.context();
2005  DDVectorsMap* registry = context->description.extension<DDVectorsMap>();
2006  xml_dim_t e(element);
2007  string name = ns.prepend(e.nameStr());
2008  string type = ns.attr<string>(e, _U(type));
2009  string nEntries = ns.attr<string>(e, DD_CMU(nEntries));
2010  string val = e.text();
2011  val.erase(remove_if(val.begin(), val.end(), [](unsigned char x) { return isspace(x); }), val.end());
2012 
2013 #ifdef EDM_ML_DEBUG
2014 
2015  printout(ns.context()->debug_constants ? ALWAYS : DEBUG,
2016  "DD4CMS",
2017  "+++ Vector<%s>: %s[%s]: %s",
2018  type.c_str(),
2019  name.c_str(),
2020  nEntries.c_str(),
2021  val.c_str());
2022 
2023 #endif
2024 
2025  try {
2026  std::vector<double> results = splitNumeric(val);
2027  registry->insert(
2028  {name,
2029  results}); //tbb::concurrent_vector<double, tbb::cache_aligned_allocator<double>>(results.begin(), results.end())});
2030  } catch (const exception& e) {
2031 #ifdef EDM_ML_DEBUG
2032 
2033  printout(INFO,
2034  "DD4CMS",
2035  "++ Unresolved Vector<%s>: %s[%s]: %s. Try to resolve later. [%s]",
2036  type.c_str(),
2037  name.c_str(),
2038  nEntries.c_str(),
2039  val.c_str(),
2040  e.what());
2041 
2042 #endif
2043 
2044  std::vector<string> results = splitString(val);
2045  context->unresolvedVectors.insert({name, results});
2046  }
2047 }
2048 
2049 template <>
2050 void Converter<debug>::operator()(xml_h dbg) const {
2051  cms::DDNamespace ns(_param<cms::DDParsingContext>());
2052  if (dbg.hasChild(DD_CMU(debug_constants)))
2053  ns.setContext()->debug_constants = true;
2054  if (dbg.hasChild(DD_CMU(debug_materials)))
2055  ns.setContext()->debug_materials = true;
2056  if (dbg.hasChild(DD_CMU(debug_rotations)))
2057  ns.setContext()->debug_rotations = true;
2058  if (dbg.hasChild(DD_CMU(debug_shapes)))
2059  ns.setContext()->debug_shapes = true;
2060  if (dbg.hasChild(DD_CMU(debug_volumes)))
2061  ns.setContext()->debug_volumes = true;
2062  if (dbg.hasChild(DD_CMU(debug_placements)))
2063  ns.setContext()->debug_placements = true;
2064  if (dbg.hasChild(DD_CMU(debug_namespaces)))
2065  ns.setContext()->debug_namespaces = true;
2066  if (dbg.hasChild(DD_CMU(debug_includes)))
2067  ns.setContext()->debug_includes = true;
2068  if (dbg.hasChild(DD_CMU(debug_algorithms)))
2069  ns.setContext()->debug_algorithms = true;
2070  if (dbg.hasChild(DD_CMU(debug_specpars)))
2071  ns.setContext()->debug_specpars = true;
2072 }
2073 
2074 template <>
2075 void Converter<DDRegistry>::operator()(xml_h /* element */) const {
2076  cms::DDParsingContext* context = _param<cms::DDParsingContext>();
2077  DDRegistry* res = _option<DDRegistry>();
2078  cms::DDNamespace ns(context);
2079  int count = 0;
2080 
2081 #ifdef EDM_ML_DEBUG
2082 
2083  printout(context->debug_constants ? ALWAYS : DEBUG,
2084  "DD4CMS",
2085  "+++ RESOLVING %ld unknown constants..... (out of %ld)",
2086  res->unresolvedConst.size(),
2087  res->originalConst.size());
2088 #endif
2089 
2090  while (!res->unresolvedConst.empty()) {
2091  for (auto& i : res->unresolvedConst) {
2092  const string& n = i.first;
2093  string rep;
2094  string& v = i.second;
2095  size_t idx, idq;
2096  for (idx = v.find('[', 0); idx != string::npos; idx = v.find('[', idx + 1)) {
2097  idq = v.find(']', idx + 1);
2098  rep = v.substr(idx + 1, idq - idx - 1);
2099  auto r = res->originalConst.find(rep);
2100  if (r != res->originalConst.end()) {
2101  rep = "(" + (*r).second + ")";
2102  v.replace(idx, idq - idx + 1, rep);
2103  }
2104  }
2105  if (v.find(']') == string::npos) {
2106  if (v.find("-+") != string::npos || v.find("+-") != string::npos) {
2107  while ((idx = v.find("-+")) != string::npos)
2108  v.replace(idx, 2, "-");
2109  while ((idx = v.find("+-")) != string::npos)
2110  v.replace(idx, 2, "-");
2111  }
2112 
2113 #ifdef EDM_ML_DEBUG
2114 
2115  printout(context->debug_constants ? ALWAYS : DEBUG,
2116  "DD4CMS",
2117  "+++ [%06ld] ---------- %-40s = %s",
2118  res->unresolvedConst.size() - 1,
2119  n.c_str(),
2120  res->originalConst[n].c_str());
2121 
2122 #endif
2123 
2124  ns.addConstantNS(n, v, "number");
2125  res->unresolvedConst.erase(n);
2126  break;
2127  }
2128  }
2129  if (++count > 10000)
2130  break;
2131  }
2132  if (!res->unresolvedConst.empty()) {
2133  for (const auto& e : res->unresolvedConst)
2134  printout(ERROR, "DD4CMS", "+++ Unresolved constant: %-40s = %s.", e.first.c_str(), e.second.c_str());
2135  except("DD4CMS", "++ FAILED to resolve %ld constant entries:", res->unresolvedConst.size());
2136  }
2137  res->unresolvedConst.clear();
2138  res->originalConst.clear();
2139 }
2140 
2141 template <>
2142 void Converter<print_xml_doc>::operator()(xml_h element) const {
2143  string fname = xml::DocumentHandler::system_path(element);
2144 
2145 #ifdef EDM_ML_DEBUG
2146 
2147  printout(_param<cms::DDParsingContext>()->debug_includes ? ALWAYS : DEBUG,
2148  "DD4CMS",
2149  "+++ Processing data from: %s",
2150  fname.c_str());
2151 
2152 #endif
2153 }
2154 
2156 static long load_dddefinition(Detector& det, xml_h element) {
2157  xml_elt_t dddef(element);
2158  if (dddef) {
2159  cms::DDParsingContext& context = *det.extension<DDParsingContext>();
2160  cms::DDNamespace ns(context);
2161  ns.addConstantNS("world_x", "101*m", "number");
2162  ns.addConstantNS("world_y", "101*m", "number");
2163  ns.addConstantNS("world_z", "450*m", "number");
2164  ns.addConstantNS("Air", "materials:Air", "string");
2165  ns.addConstantNS("Vacuum", "materials:Vacuum", "string");
2166 
2167  string fname = xml::DocumentHandler::system_path(element);
2168  bool open_geometry = dddef.hasChild(DD_CMU(open_geometry)) ? dddef.child(DD_CMU(open_geometry)) : true;
2169  bool close_geometry = dddef.hasChild(DD_CMU(close_geometry)) ? dddef.hasChild(DD_CMU(close_geometry)) : true;
2170 
2171  xml_coll_t(dddef, _U(debug)).for_each(Converter<debug>(det, &context));
2172 
2173  // Here we define the order how XML elements are processed.
2174  // Be aware of dependencies. This can only defined once.
2175  // At the end it is a limitation of DOM....
2176  printout(INFO, "DD4CMS", "+++ Processing the CMS detector description %s", fname.c_str());
2177 
2178  xml::Document doc;
2179  Converter<print_xml_doc> print_doc(det, &context);
2180  try {
2181  DDRegistry res;
2182  res.unresolvedConst.reserve(2000);
2183  res.originalConst.reserve(6000);
2184  print_doc((doc = dddef.document()).root());
2185  xml_coll_t(dddef, DD_CMU(ConstantsSection)).for_each(Converter<ConstantsSection>(det, &context, &res));
2186  xml_coll_t(dddef, DD_CMU(RotationSection)).for_each(Converter<RotationSection>(det, &context));
2187  xml_coll_t(dddef, DD_CMU(MaterialSection)).for_each(Converter<MaterialSection>(det, &context));
2188 
2189  xml_coll_t(dddef, DD_CMU(IncludeSection)).for_each(DD_CMU(Include), Converter<include_load>(det, &context, &res));
2190 
2191  for (xml::Document d : res.includes) {
2192  print_doc((doc = d).root());
2193  Converter<include_constants>(det, &context, &res)((doc = d).root());
2194  }
2195  // Before we continue, we have to resolve all constants NOW!
2196  Converter<DDRegistry>(det, &context, &res)(dddef);
2197  {
2198  DDVectorsMap* registry = context.description.extension<DDVectorsMap>();
2199 
2200  printout(context.debug_constants ? ALWAYS : DEBUG,
2201  "DD4CMS",
2202  "+++ RESOLVING %ld Vectors.....",
2203  context.unresolvedVectors.size());
2204 
2205  while (!context.unresolvedVectors.empty()) {
2206  for (auto it = context.unresolvedVectors.begin(); it != context.unresolvedVectors.end();) {
2207  std::vector<double> result;
2208  for (const auto& i : it->second) {
2209  result.emplace_back(dd4hep::_toDouble(i));
2210  }
2211  registry->insert({it->first, result});
2212  // All components are resolved
2213  it = context.unresolvedVectors.erase(it);
2214  }
2215  }
2216  }
2217  // Now we can process the include files one by one.....
2218  for (xml::Document d : res.includes) {
2219  print_doc((doc = d).root());
2220  xml_coll_t(d.root(), DD_CMU(MaterialSection)).for_each(Converter<MaterialSection>(det, &context));
2221  }
2222  {
2223  PrintLevel printLvl(DEBUG);
2224  if (!context.unresolvedMaterials.empty())
2225  printLvl = WARNING;
2226  printout(context.debug_materials ? ALWAYS : printLvl,
2227  "DD4CMS",
2228  "+++ RESOLVING %ld unknown material constituents.....",
2229  context.unresolvedMaterials.size());
2230 
2231  // Resolve referenced materials (if any)
2232 
2233  while (!context.unresolvedMaterials.empty()) {
2234  for (auto it = context.unresolvedMaterials.begin(); it != context.unresolvedMaterials.end();) {
2235  auto const& name = it->first;
2236  std::vector<bool> valid;
2237 
2238  printout(context.debug_materials ? ALWAYS : WARNING,
2239  "DD4CMS",
2240  "+++ [%06ld] ---------- %s",
2241  context.unresolvedMaterials.size(),
2242  name.c_str());
2243 
2244  auto mat = ns.material(name);
2245  for (auto& mit : it->second) {
2246  printout(context.debug_materials ? ALWAYS : WARNING,
2247  "DD4CMS",
2248  "+++ component %-48s Fraction: %.6f",
2249  mit.name.c_str(),
2250  mit.fraction);
2251  auto fmat = ns.material(mit.name);
2252  if (nullptr != fmat.ptr()) {
2253  if (mat.ptr()->GetMaterial()->IsMixture()) {
2254  valid.emplace_back(true);
2255  static_cast<TGeoMixture*>(mat.ptr()->GetMaterial())
2256  ->AddElement(fmat.ptr()->GetMaterial(), mit.fraction);
2257  }
2258  }
2259  }
2260  // All components are resolved
2261  if (valid.size() == it->second.size())
2262  it = context.unresolvedMaterials.erase(it);
2263  else
2264  ++it;
2265  }
2266  // Do it again if there are unresolved
2267  // materials left after this pass
2268  }
2269  }
2270  if (open_geometry) {
2271  det.init();
2272  ns.addVolume(det.worldVolume());
2273  }
2274  for (xml::Document d : res.includes) {
2275  print_doc((doc = d).root());
2276  xml_coll_t(d.root(), DD_CMU(RotationSection)).for_each(Converter<RotationSection>(det, &context));
2277  }
2278  for (xml::Document d : res.includes) {
2279  print_doc((doc = d).root());
2280  xml_coll_t(d.root(), DD_CMU(SolidSection)).for_each(Converter<SolidSection>(det, &context));
2281  }
2282  for (xml::Document d : res.includes) {
2283  print_doc((doc = d).root());
2284  xml_coll_t(d.root(), DD_CMU(LogicalPartSection)).for_each(Converter<LogicalPartSection>(det, &context));
2285  }
2286  for (xml::Document d : res.includes) {
2287  print_doc((doc = d).root());
2288  xml_coll_t(d.root(), DD_CMU(Algorithm)).for_each(Converter<DDLAlgorithm>(det, &context));
2289  }
2290  for (xml::Document d : res.includes) {
2291  print_doc((doc = d).root());
2292  xml_coll_t(d.root(), DD_CMU(PosPartSection)).for_each(Converter<PosPartSection>(det, &context));
2293  }
2294  for (xml::Document d : res.includes) {
2295  print_doc((doc = d).root());
2296  xml_coll_t(d.root(), DD_CMU(SpecParSection)).for_each(Converter<SpecParSection>(det, &context));
2297  }
2298 
2300  for (xml::Document d : res.includes)
2301  Converter<include_unload>(det, &context, &res)(d.root());
2302 
2303  print_doc((doc = dddef.document()).root());
2304  // Now process the actual geometry items
2305  xml_coll_t(dddef, DD_CMU(SolidSection)).for_each(Converter<SolidSection>(det, &context));
2306  {
2307  // Before we continue, we have to resolve all shapes NOW!
2308  // Note: This only happens in a legacy DB payloads where
2309  // boolean shapes can be defined before thier
2310  // component shapes
2311 
2312  while (!context.unresolvedShapes.empty()) {
2313  for (auto it = context.unresolvedShapes.begin(); it != context.unresolvedShapes.end();) {
2314  auto const& name = it->first;
2315  auto const& aname = std::visit([](auto&& arg) -> std::string { return arg.firstSolidName; }, it->second);
2316  auto const& bname = std::visit([](auto&& arg) -> std::string { return arg.secondSolidName; }, it->second);
2317 
2318  auto const& ait = context.shapes.find(aname);
2319  if (ait->second.isValid()) {
2320  auto const& bit = context.shapes.find(bname);
2321  if (bit->second.isValid()) {
2322  dd4hep::Solid shape =
2323  std::visit([&ait, &bit](auto&& arg) -> dd4hep::Solid { return arg.make(ait->second, bit->second); },
2324  it->second);
2325  context.shapes[name] = shape;
2326  it = context.unresolvedShapes.erase(it);
2327  } else
2328  ++it;
2329  } else
2330  ++it;
2331  }
2332  }
2333  }
2334  xml_coll_t(dddef, DD_CMU(LogicalPartSection)).for_each(Converter<LogicalPartSection>(det, &context));
2335  xml_coll_t(dddef, DD_CMU(Algorithm)).for_each(Converter<DDLAlgorithm>(det, &context));
2336  xml_coll_t(dddef, DD_CMU(PosPartSection)).for_each(Converter<PosPartSection>(det, &context));
2337  xml_coll_t(dddef, DD_CMU(SpecParSection)).for_each(Converter<SpecParSection>(det, &context));
2338  } catch (const exception& e) {
2339  printout(ERROR, "DD4CMS", "Exception while processing xml source:%s", doc.uri().c_str());
2340  printout(ERROR, "DD4CMS", "----> %s", e.what());
2341  throw;
2342  }
2343 
2345  if (close_geometry) {
2346  Volume wv = det.worldVolume();
2347  Volume geomv = ns.volume("cms:OCMS", false);
2348  if (geomv.isValid())
2349  wv.placeVolume(geomv, 1);
2350  Volume mfv = ns.volume("cmsMagneticField:MAGF", false);
2351  if (mfv.isValid())
2352  wv.placeVolume(mfv, 1);
2353  Volume mfv1 = ns.volume("MagneticFieldVolumes:MAGF", false);
2354  if (mfv1.isValid())
2355  wv.placeVolume(mfv1, 1);
2356 
2357  // Can not deal with reflections without closed geometry
2358  det.manager().CloseGeometry();
2359 
2360  det.endDocument();
2361  }
2362  printout(INFO, "DDDefinition", "+++ Finished processing %s", fname.c_str());
2363  return 1;
2364  }
2365  except("DDDefinition", "+++ FAILED to process unknown DOM tree [Invalid Handle]");
2366  return 0;
2367 }
2368 
2369 // Now declare the factory entry for the plugin mechanism
2370 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
static const int WARNING
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
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)