CMS 3D CMS Logo

DDDefinitions2Objects.cc
Go to the documentation of this file.
1 #include "DD4hep/DetFactoryHelper.h"
2 #include "DD4hep/DetectorHelper.h"
3 #include "DD4hep/DD4hepUnits.h"
4 #include "DD4hep/GeoHandler.h"
5 #include "DD4hep/Printout.h"
6 #include "DD4hep/Plugins.h"
7 #include "DD4hep/detail/SegmentationsInterna.h"
8 #include "DD4hep/detail/DetectorInterna.h"
9 #include "DD4hep/detail/ObjectsInterna.h"
10 #include "DD4hep/MatrixHelpers.h"
11 
12 #include "XML/Utilities.h"
20 
21 #include "TGeoManager.h"
22 #include "TGeoMaterial.h"
23 
24 #include <climits>
25 #include <iostream>
26 #include <iomanip>
27 #include <map>
28 #include <utility>
29 #include "tbb/concurrent_unordered_map.h"
30 #include "tbb/concurrent_vector.h"
31 
32 using namespace std;
33 using namespace dd4hep;
34 using namespace cms;
35 using namespace cms_units::operators;
36 
37 namespace dd4hep {
38 
39  namespace {
40 
41  atomic<UInt_t> unique_mat_id = 0xAFFEFEED;
42 
43  class disabled_algo;
44  class include_constants;
45  class include_load;
46  class include_unload;
47  class print_xml_doc;
48 
49  class ConstantsSection;
50  class DDLConstant;
51 
52  struct DDRegistry {
53  tbb::concurrent_vector<xml::Document> includes;
54  tbb::concurrent_unordered_map<std::string, std::string> unresolvedConst, allConst, originalConst;
55  };
56 
57  class MaterialSection;
60 
61  class RotationSection;
62  class DDLRotation;
63  class DDLReflectionRotation;
64  class DDLRotationSequence;
65  class DDLRotationByAxis;
66  class DDLTransform3D;
67 
68  class PosPartSection;
69  class DDLPosPart;
70  class DDLDivision;
71 
72  class LogicalPartSection;
73  class DDLLogicalPart;
74 
75  class SolidSection;
76  class DDLExtrudedPolygon;
77  class DDLShapeless;
78  class DDLTrapezoid;
79  class DDLEllipticalTube;
80  class DDLPseudoTrap;
81  class DDLPolyhedra;
82  class DDLPolycone;
83  class DDLTorus;
84  class DDLTrd1;
85  class DDLTrd2;
86  class DDLTruncTubs;
87  class DDLCutTubs;
88  class DDLTubs;
89  class DDLBox;
90  class DDLCone;
91  class DDLSphere;
92  class DDLUnionSolid;
93  class DDLIntersectionSolid;
94  class DDLSubtractionSolid;
95 
96  class DDLAlgorithm;
97  class DDLVector;
98 
99  class SpecParSection;
100  class SpecPar;
101  class PartSelector;
102  class Parameter;
103 
104  class vissection;
105  class vis;
106  class debug;
107  } // namespace
108 
109  TGeoCombiTrans* createPlacement(const Rotation3D& iRot, const Position& iTrans) {
110  double elements[9];
111  iRot.GetComponents(elements);
112  TGeoRotation r;
113  r.SetMatrix(elements);
114 
115  TGeoTranslation t(iTrans.x(), iTrans.y(), iTrans.z());
116 
117  return new TGeoCombiTrans(t, r);
118  }
119 
121  template <>
122  void Converter<debug>::operator()(xml_h element) const;
123  template <>
124  void Converter<print_xml_doc>::operator()(xml_h element) const;
125  template <>
126  void Converter<disabled_algo>::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<vissection>::operator()(xml_h element) const;
140  template <>
141  void Converter<vis>::operator()(xml_h element) const;
142 
144  template <>
145  void Converter<MaterialSection>::operator()(xml_h element) const;
146  template <>
147  void Converter<DDLElementaryMaterial>::operator()(xml_h element) const;
148  template <>
149  void Converter<DDLCompositeMaterial>::operator()(xml_h element) const;
150 
152  template <>
153  void Converter<RotationSection>::operator()(xml_h element) const;
155  template <>
156  void Converter<DDLRotation>::operator()(xml_h element) const;
158  template <>
159  void Converter<DDLReflectionRotation>::operator()(xml_h element) const;
161  template <>
162  void Converter<DDLRotationSequence>::operator()(xml_h element) const;
164  template <>
165  void Converter<DDLRotationByAxis>::operator()(xml_h element) const;
166  template <>
167  void Converter<DDLTransform3D>::operator()(xml_h element) const;
168 
170  template <>
171  void Converter<LogicalPartSection>::operator()(xml_h element) const;
172  template <>
173  void Converter<DDLLogicalPart>::operator()(xml_h element) const;
174 
176  template <>
177  void Converter<PosPartSection>::operator()(xml_h element) const;
179  template <>
180  void Converter<DDLPosPart>::operator()(xml_h element) const;
182  template <>
183  void Converter<DDLDivision>::operator()(xml_h element) const;
184 
186  template <>
187  void Converter<SpecParSection>::operator()(xml_h element) const;
188  template <>
189  void Converter<SpecPar>::operator()(xml_h element) const;
190  template <>
191  void Converter<PartSelector>::operator()(xml_h element) const;
192  template <>
193  void Converter<Parameter>::operator()(xml_h element) const;
194 
196  template <>
197  void Converter<SolidSection>::operator()(xml_h element) const;
199  template <>
200  void Converter<DDLUnionSolid>::operator()(xml_h element) const;
202  template <>
203  void Converter<DDLSubtractionSolid>::operator()(xml_h element) const;
205  template <>
206  void Converter<DDLIntersectionSolid>::operator()(xml_h element) const;
208  template <>
209  void Converter<DDLPseudoTrap>::operator()(xml_h element) const;
211  template <>
212  void Converter<DDLExtrudedPolygon>::operator()(xml_h element) const;
214  template <>
215  void Converter<DDLShapeless>::operator()(xml_h element) const;
217  template <>
218  void Converter<DDLTrapezoid>::operator()(xml_h element) const;
220  template <>
221  void Converter<DDLPolycone>::operator()(xml_h element) const;
223  template <>
224  void Converter<DDLPolyhedra>::operator()(xml_h element) const;
226  template <>
227  void Converter<DDLEllipticalTube>::operator()(xml_h element) const;
229  template <>
230  void Converter<DDLTorus>::operator()(xml_h element) const;
232  template <>
233  void Converter<DDLTubs>::operator()(xml_h element) const;
235  template <>
236  void Converter<DDLCutTubs>::operator()(xml_h element) const;
238  template <>
239  void Converter<DDLTruncTubs>::operator()(xml_h element) const;
241  template <>
242  void Converter<DDLSphere>::operator()(xml_h element) const;
244  template <>
245  void Converter<DDLTrd1>::operator()(xml_h element) const;
247  template <>
248  void Converter<DDLTrd2>::operator()(xml_h element) const;
250  template <>
251  void Converter<DDLCone>::operator()(xml_h element) const;
253  template <>
254  void Converter<DDLBox>::operator()(xml_h element) const;
256  template <>
257  void Converter<DDLAlgorithm>::operator()(xml_h element) const;
259  template <>
260  void Converter<DDLVector>::operator()(xml_h element) const;
261 
263  template <>
264  void Converter<include_load>::operator()(xml_h element) const;
266  template <>
267  void Converter<include_unload>::operator()(xml_h element) const;
269  template <>
270  void Converter<include_constants>::operator()(xml_h element) const;
271 } // namespace dd4hep
272 
274 template <>
275 void Converter<ConstantsSection>::operator()(xml_h element) const {
276  cms::DDNamespace ns(_param<cms::DDParsingContext>(), element);
277  cms::DDParsingContext* const context = ns.context();
278  xml_coll_t(element, DD_CMU(Constant)).for_each(Converter<DDLConstant>(description, context, optional));
279  xml_coll_t(element, DD_CMU(Vector)).for_each(Converter<DDLVector>(description, context, optional));
280 }
281 
283 template <>
284 void Converter<vissection>::operator()(xml_h element) const {
285  cms::DDNamespace ns(_param<cms::DDParsingContext>(), element);
286  xml_coll_t(element, DD_CMU(vis)).for_each(Converter<vis>(description, ns.context(), optional));
287 }
288 
290 template <>
291 void Converter<MaterialSection>::operator()(xml_h element) const {
292  cms::DDNamespace ns(_param<cms::DDParsingContext>(), element);
293  xml_coll_t(element, DD_CMU(ElementaryMaterial))
294  .for_each(Converter<DDLElementaryMaterial>(description, ns.context(), optional));
295  xml_coll_t(element, DD_CMU(CompositeMaterial))
296  .for_each(Converter<DDLCompositeMaterial>(description, ns.context(), optional));
297 }
298 
299 template <>
300 void Converter<RotationSection>::operator()(xml_h element) const {
301  cms::DDNamespace ns(_param<cms::DDParsingContext>(), element);
302  xml_coll_t(element, DD_CMU(Rotation)).for_each(Converter<DDLRotation>(description, ns.context(), optional));
303  xml_coll_t(element, DD_CMU(ReflectionRotation))
304  .for_each(Converter<DDLReflectionRotation>(description, ns.context(), optional));
305  xml_coll_t(element, DD_CMU(RotationSequence))
306  .for_each(Converter<DDLRotationSequence>(description, ns.context(), optional));
307  xml_coll_t(element, DD_CMU(RotationByAxis))
308  .for_each(Converter<DDLRotationByAxis>(description, ns.context(), optional));
309 }
310 
311 template <>
312 void Converter<PosPartSection>::operator()(xml_h element) const {
313  cms::DDNamespace ns(_param<cms::DDParsingContext>(), element);
314  xml_coll_t(element, DD_CMU(Division)).for_each(Converter<DDLDivision>(description, ns.context(), optional));
315  xml_coll_t(element, DD_CMU(PosPart)).for_each(Converter<DDLPosPart>(description, ns.context(), optional));
316  xml_coll_t(element, DD_CMU(Algorithm)).for_each(Converter<DDLAlgorithm>(description, ns.context(), optional));
317 }
318 
319 template <>
320 void Converter<SpecParSection>::operator()(xml_h element) const {
321  cms::DDNamespace ns(_param<cms::DDParsingContext>(), element);
322  xml_coll_t(element, DD_CMU(SpecPar)).for_each(Converter<SpecPar>(description, ns.context(), optional));
323 }
324 
325 template <>
326 void Converter<SpecPar>::operator()(xml_h element) const {
327  cms::DDNamespace ns(_param<cms::DDParsingContext>(), element);
328  xml_coll_t(element, DD_CMU(PartSelector)).for_each(Converter<PartSelector>(description, ns.context(), optional));
329  xml_coll_t(element, DD_CMU(Parameter)).for_each(Converter<Parameter>(description, ns.context(), optional));
330 }
331 
333 template <>
334 void Converter<LogicalPartSection>::operator()(xml_h element) const {
335  cms::DDNamespace ns(_param<cms::DDParsingContext>(), element);
336  xml_coll_t(element, DD_CMU(LogicalPart)).for_each(Converter<DDLLogicalPart>(description, ns.context(), optional));
337 }
338 
339 template <>
340 void Converter<disabled_algo>::operator()(xml_h element) const {
341  cms::DDParsingContext* c = _param<cms::DDParsingContext>();
342  c->disabledAlgs.emplace_back(element.attr<string>(_U(name)));
343 }
344 
346 template <>
347 void Converter<SolidSection>::operator()(xml_h element) const {
348  cms::DDNamespace ns(_param<cms::DDParsingContext>(), element);
349  for (xml_coll_t solid(element, _U(star)); solid; ++solid) {
350  string tag = solid.tag();
351  using cms::hash;
352  switch (hash(solid.tag())) {
353  case hash("Box"):
354  Converter<DDLBox>(description, ns.context(), optional)(solid);
355  break;
356  case hash("Polycone"):
357  Converter<DDLPolycone>(description, ns.context(), optional)(solid);
358  break;
359  case hash("Polyhedra"):
360  Converter<DDLPolyhedra>(description, ns.context(), optional)(solid);
361  break;
362  case hash("Tubs"):
363  Converter<DDLTubs>(description, ns.context(), optional)(solid);
364  break;
365  case hash("CutTubs"):
366  Converter<DDLCutTubs>(description, ns.context(), optional)(solid);
367  break;
368  case hash("TruncTubs"):
369  Converter<DDLTruncTubs>(description, ns.context(), optional)(solid);
370  break;
371  case hash("Tube"):
372  Converter<DDLTubs>(description, ns.context(), optional)(solid);
373  break;
374  case hash("Trd1"):
375  Converter<DDLTrd1>(description, ns.context(), optional)(solid);
376  break;
377  case hash("Trd2"):
378  Converter<DDLTrd2>(description, ns.context(), optional)(solid);
379  break;
380  case hash("Cone"):
381  Converter<DDLCone>(description, ns.context(), optional)(solid);
382  break;
383  case hash("Sphere"):
384  Converter<DDLSphere>(description, ns.context(), optional)(solid);
385  break;
386  case hash("EllipticalTube"):
387  Converter<DDLEllipticalTube>(description, ns.context(), optional)(solid);
388  break;
389  case hash("Torus"):
390  Converter<DDLTorus>(description, ns.context(), optional)(solid);
391  break;
392  case hash("PseudoTrap"):
393  Converter<DDLPseudoTrap>(description, ns.context(), optional)(solid);
394  break;
395  case hash("ExtrudedPolygon"):
396  Converter<DDLExtrudedPolygon>(description, ns.context(), optional)(solid);
397  break;
398  case hash("Trapezoid"):
399  Converter<DDLTrapezoid>(description, ns.context(), optional)(solid);
400  break;
401  case hash("UnionSolid"):
402  Converter<DDLUnionSolid>(description, ns.context(), optional)(solid);
403  break;
404  case hash("SubtractionSolid"):
405  Converter<DDLSubtractionSolid>(description, ns.context(), optional)(solid);
406  break;
407  case hash("IntersectionSolid"):
408  Converter<DDLIntersectionSolid>(description, ns.context(), optional)(solid);
409  break;
410  case hash("ShapelessSolid"):
411  Converter<DDLShapeless>(description, ns.context(), optional)(solid);
412  break;
413  default:
414  throw std::runtime_error("Request to process unknown shape '" + xml_dim_t(solid).nameStr() + "' [" + tag + "]");
415  break;
416  }
417  }
418 }
419 
421 template <>
422 void Converter<DDLConstant>::operator()(xml_h element) const {
423  cms::DDNamespace ns(_param<cms::DDParsingContext>());
424  DDRegistry* res = _option<DDRegistry>();
425  xml_dim_t constant = element;
426  xml_dim_t par = constant.parent();
427  bool eval = par.hasAttr(_U(eval)) ? par.attr<bool>(_U(eval)) : false;
428  string val = constant.valueStr();
429  string nam = constant.nameStr();
430  string real = ns.prepend(nam);
431  string typ = eval ? "number" : "string";
432  size_t idx = val.find('[');
433 
434  if (constant.hasAttr(_U(type)))
435  typ = constant.typeStr();
436 
437  if (idx == string::npos || typ == "string") {
438  try {
439  ns.addConstant(nam, val, typ);
440  res->allConst[real] = val;
441  res->originalConst[real] = val;
442  } catch (const exception& e) {
443  printout(INFO,
444  "DD4CMS",
445  "++ Unresolved constant: %s = %s [%s]. Try to resolve later. [%s]",
446  real.c_str(),
447  val.c_str(),
448  typ.c_str(),
449  e.what());
450  }
451  return;
452  }
453  // Setup the resolution mechanism in Converter<resolve>
454  while (idx != string::npos) {
455  ++idx;
456  size_t idp = val.find(':', idx);
457  size_t idq = val.find(']', idx);
458  if (idp == string::npos || idp > idq)
459  val.insert(idx, ns.name());
460  else if (idp != string::npos && idp < idq)
461  val[idp] = NAMESPACE_SEP;
462  idx = val.find('[', idx);
463  }
464  printout(
465  ns.context()->debug_constants ? ALWAYS : DEBUG, "Constant", "Unresolved: %s -> %s", real.c_str(), val.c_str());
466  res->allConst[real] = val;
467  res->originalConst[real] = val;
468  res->unresolvedConst[real] = val;
469 }
470 
479 template <>
480 void Converter<vis>::operator()(xml_h e) const {
481  cms::DDNamespace ns(_param<cms::DDParsingContext>());
482  VisAttr attr(e.attr<string>(_U(name)));
483  float red = e.hasAttr(_U(r)) ? e.attr<float>(_U(r)) : 1.0f;
484  float green = e.hasAttr(_U(g)) ? e.attr<float>(_U(g)) : 1.0f;
485  float blue = e.hasAttr(_U(b)) ? e.attr<float>(_U(b)) : 1.0f;
486 
487  printout(ns.context()->debug_visattr ? ALWAYS : DEBUG,
488  "Compact",
489  "++ Converting VisAttr structure: %-16s. R=%.3f G=%.3f B=%.3f",
490  attr.name(),
491  red,
492  green,
493  blue);
494  attr.setColor(red, green, blue);
495  if (e.hasAttr(_U(alpha)))
496  attr.setAlpha(e.attr<float>(_U(alpha)));
497  if (e.hasAttr(_U(visible)))
498  attr.setVisible(e.attr<bool>(_U(visible)));
499  if (e.hasAttr(_U(lineStyle))) {
500  string ls = e.attr<string>(_U(lineStyle));
501  if (ls == "unbroken")
502  attr.setLineStyle(VisAttr::SOLID);
503  else if (ls == "broken")
504  attr.setLineStyle(VisAttr::DASHED);
505  } else {
506  attr.setLineStyle(VisAttr::SOLID);
507  }
508  if (e.hasAttr(_U(drawingStyle))) {
509  string ds = e.attr<string>(_U(drawingStyle));
510  if (ds == "wireframe")
511  attr.setDrawingStyle(VisAttr::WIREFRAME);
512  else if (ds == "solid")
513  attr.setDrawingStyle(VisAttr::SOLID);
514  } else {
515  attr.setDrawingStyle(VisAttr::SOLID);
516  }
517  if (e.hasAttr(_U(showDaughters)))
518  attr.setShowDaughters(e.attr<bool>(_U(showDaughters)));
519  else
520  attr.setShowDaughters(true);
521  description.addVisAttribute(attr);
522 }
523 
525 template <>
526 void Converter<DDLElementaryMaterial>::operator()(xml_h element) const {
527  cms::DDNamespace ns(_param<cms::DDParsingContext>());
528  xml_dim_t xmat(element);
529  string nam = ns.prepend(xmat.nameStr());
530  TGeoManager& mgr = description.manager();
531  TGeoMaterial* mat = mgr.GetMaterial(nam.c_str());
532  if (nullptr == mat) {
533  const char* matname = nam.c_str();
534  double density = xmat.attr<double>(DD_CMU(density)) / (dd4hep::g / dd4hep::cm3);
535  int atomicNumber = xmat.attr<int>(DD_CMU(atomicNumber));
536  double atomicWeight = xmat.attr<double>(DD_CMU(atomicWeight)) / (dd4hep::g / dd4hep::mole);
537  TGeoElementTable* tab = mgr.GetElementTable();
538  TGeoMixture* mix = new TGeoMixture(nam.c_str(), 1, density);
539  TGeoElement* elt = tab->FindElement(xmat.nameStr().c_str());
540 
541  printout(ns.context()->debug_materials ? ALWAYS : DEBUG,
542  "DD4CMS",
543  "+++ Converting material %-48s Atomic weight %8.3f [g/mol], Atomic number %u, Density: %8.3f [g/cm3] "
544  "ROOT: %8.3f [g/cm3]",
545  ('"' + nam + '"').c_str(),
546  atomicWeight,
547  atomicNumber,
548  density,
549  mix->GetDensity());
550 
551  bool newMatDef = false;
552 
553  if (elt) {
554  // A is Mass of a mole in Geant4 units for atoms with atomic shell
555  printout(ns.context()->debug_materials ? ALWAYS : DEBUG,
556  "DD4CMS",
557  " ROOT definition of %-50s Atomic weight %.3f, Atomic number %u, Number of nucleons %u",
558  elt->GetName(),
559  (elt->A()),
560  elt->Z(),
561  elt->N());
562  if (atomicNumber != elt->Z() || atomicWeight != elt->A())
563  newMatDef = true;
564  }
565 
566  if (!elt || newMatDef) {
567  if (newMatDef)
568  printout(WARNING,
569  "DD4CMS",
570  "+++ Converter<ElementaryMaterial> Different definition of a default element with name:%s [CREATE NEW "
571  "MATERIAL]",
572  matname);
573  else
574  printout(WARNING,
575  "DD4CMS",
576  "+++ Converter<ElementaryMaterial> No default element present with name:%s [CREATE NEW MATERIAL]",
577  matname);
578  elt = new TGeoElement(xmat.nameStr().c_str(), "CMS element", atomicNumber, atomicWeight);
579  }
580 
581  mix->AddElement(elt, 1.0);
582 
584  TGeoMedium* medium = mgr.GetMedium(matname);
585  if (nullptr == medium) {
586  --unique_mat_id;
587  medium = new TGeoMedium(matname, unique_mat_id, mix);
588  medium->SetTitle("material");
589  medium->SetUniqueID(unique_mat_id);
590  }
591  }
592 }
593 
595 template <>
596 void Converter<DDLCompositeMaterial>::operator()(xml_h element) const {
597  cms::DDNamespace ns(_param<cms::DDParsingContext>());
598  xml_dim_t xmat(element);
599  string nam = ns.prepend(xmat.nameStr());
600 
601  TGeoManager& mgr = description.manager();
602  TGeoMaterial* mat = mgr.GetMaterial(nam.c_str());
603  if (nullptr == mat) {
604  const char* matname = nam.c_str();
605  double density = xmat.attr<double>(DD_CMU(density)) / (dd4hep::g / dd4hep::cm3);
606  xml_coll_t composites(xmat, DD_CMU(MaterialFraction));
607  TGeoMixture* mix = new TGeoMixture(nam.c_str(), composites.size(), density);
608 
609  printout(ns.context()->debug_materials ? ALWAYS : DEBUG,
610  "DD4CMS",
611  "++ Converting material %-48s Density: %8.3f [g/cm3] ROOT: %8.3f [g/cm3]",
612  ('"' + nam + '"').c_str(),
613  density,
614  mix->GetDensity());
615 
616  for (composites.reset(); composites; ++composites) {
617  xml_dim_t xfrac(composites);
618  xml_dim_t xfrac_mat(xfrac.child(DD_CMU(rMaterial)));
619  double fraction = xfrac.fraction();
620  string fracname = ns.realName(xfrac_mat.nameStr());
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  printout(WARNING,
631  "DD4CMS",
632  "+++ Composite material \"%s\" [nor \"%s\"] not present! [delay resolution]",
633  fracname.c_str(),
634  ns.prepend(fracname).c_str());
635  ns.context()->unresolvedMaterials[nam].emplace_back(
637  }
638  mix->SetRadLen(0e0);
640  TGeoMedium* medium = mgr.GetMedium(matname);
641  if (nullptr == medium) {
642  --unique_mat_id;
643  medium = new TGeoMedium(matname, unique_mat_id, mix);
644  medium->SetTitle("material");
645  medium->SetUniqueID(unique_mat_id);
646  }
647  }
648 }
649 
651 template <>
652 void Converter<DDLRotation>::operator()(xml_h element) const {
653  cms::DDParsingContext* context = _param<cms::DDParsingContext>();
654  cms::DDNamespace ns(context);
655  xml_dim_t xrot(element);
656  string nam = xrot.nameStr();
657  double thetaX = xrot.hasAttr(DD_CMU(thetaX)) ? ns.attr<double>(xrot, DD_CMU(thetaX)) : 0e0;
658  double phiX = xrot.hasAttr(DD_CMU(phiX)) ? ns.attr<double>(xrot, DD_CMU(phiX)) : 0e0;
659  double thetaY = xrot.hasAttr(DD_CMU(thetaY)) ? ns.attr<double>(xrot, DD_CMU(thetaY)) : 0e0;
660  double phiY = xrot.hasAttr(DD_CMU(phiY)) ? ns.attr<double>(xrot, DD_CMU(phiY)) : 0e0;
661  double thetaZ = xrot.hasAttr(DD_CMU(thetaZ)) ? ns.attr<double>(xrot, DD_CMU(thetaZ)) : 0e0;
662  double phiZ = xrot.hasAttr(DD_CMU(phiZ)) ? ns.attr<double>(xrot, DD_CMU(phiZ)) : 0e0;
663  Rotation3D rot = makeRotation3D(thetaX, phiX, thetaY, phiY, thetaZ, phiZ);
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  ns.addRotation(nam, rot);
675 }
676 
678 template <>
679 void Converter<DDLReflectionRotation>::operator()(xml_h element) const {
680  cms::DDParsingContext* context = _param<cms::DDParsingContext>();
681  cms::DDNamespace ns(context);
682  xml_dim_t xrot(element);
683  string name = xrot.nameStr();
684  double thetaX = xrot.hasAttr(DD_CMU(thetaX)) ? ns.attr<double>(xrot, DD_CMU(thetaX)) : 0e0;
685  double phiX = xrot.hasAttr(DD_CMU(phiX)) ? ns.attr<double>(xrot, DD_CMU(phiX)) : 0e0;
686  double thetaY = xrot.hasAttr(DD_CMU(thetaY)) ? ns.attr<double>(xrot, DD_CMU(thetaY)) : 0e0;
687  double phiY = xrot.hasAttr(DD_CMU(phiY)) ? ns.attr<double>(xrot, DD_CMU(phiY)) : 0e0;
688  double thetaZ = xrot.hasAttr(DD_CMU(thetaZ)) ? ns.attr<double>(xrot, DD_CMU(thetaZ)) : 0e0;
689  double phiZ = xrot.hasAttr(DD_CMU(phiZ)) ? ns.attr<double>(xrot, DD_CMU(phiZ)) : 0e0;
690  printout(context->debug_rotations ? ALWAYS : DEBUG,
691  "DD4CMS",
692  "+++ Adding reflection rotation: %-32s: (theta/phi)[rad] X: %6.3f %6.3f Y: %6.3f %6.3f Z: %6.3f %6.3f",
693  ns.prepend(name).c_str(),
694  thetaX,
695  phiX,
696  thetaY,
697  phiY,
698  thetaZ,
699  phiZ);
700  Rotation3D rot = makeRotReflect(thetaX, phiX, thetaY, phiY, thetaZ, phiZ);
701  ns.addRotation(name, rot);
702 }
703 
705 template <>
706 void Converter<DDLRotationSequence>::operator()(xml_h element) const {
707  cms::DDParsingContext* context = _param<cms::DDParsingContext>();
708  cms::DDNamespace ns(context);
709  xml_dim_t xrot(element);
710  string nam = xrot.nameStr();
711  Rotation3D rot;
712  xml_coll_t rotations(xrot, DD_CMU(RotationByAxis));
713  for (rotations.reset(); rotations; ++rotations) {
714  string axis = ns.attr<string>(rotations, DD_CMU(axis));
715  double angle = ns.attr<double>(rotations, _U(angle));
716  rot = makeRotation3D(rot, axis, angle);
717  printout(context->debug_rotations ? ALWAYS : DEBUG,
718  "DD4CMS",
719  "+ Adding rotation to: %-29s: (axis/angle)[rad] Axis: %s Angle: %6.3f",
720  nam.c_str(),
721  axis.c_str(),
722  angle);
723  }
724  double xx, xy, xz;
725  double yx, yy, yz;
726  double zx, zy, zz;
727  rot.GetComponents(xx, xy, xz, yx, yy, yz, zx, zy, zz);
728  printout(context->debug_rotations ? ALWAYS : DEBUG,
729  "DD4CMS",
730  "+++ Adding rotation sequence: %-23s: %6.3f %6.3f %6.3f, %6.3f %6.3f %6.3f, %6.3f %6.3f %6.3f",
731  ns.prepend(nam).c_str(),
732  xx,
733  xy,
734  xz,
735  yx,
736  yy,
737  yz,
738  zx,
739  zy,
740  zz);
741  ns.addRotation(nam, rot);
742 }
743 
745 template <>
746 void Converter<DDLRotationByAxis>::operator()(xml_h element) const {
747  cms::DDParsingContext* context = _param<cms::DDParsingContext>();
748  cms::DDNamespace ns(context);
749  xml_dim_t xrot(element);
750  xml_dim_t par(xrot.parent());
751  if (xrot.hasAttr(_U(name))) {
752  string nam = xrot.nameStr(); // + string("Rotation"); // xrot.hasAttr(_U(name)) ? xrot.nameStr() : par.nameStr();
753  string axis = ns.attr<string>(xrot, DD_CMU(axis));
754  double angle = ns.attr<double>(xrot, _U(angle));
755  Rotation3D rot;
756  rot = makeRotation3D(rot, axis, angle);
757  printout(context->debug_rotations ? ALWAYS : DEBUG,
758  "DD4CMS",
759  "+++ Adding rotation: %-32s: (axis/angle)[rad] Axis: %s Angle: %6.3f",
760  ns.prepend(nam).c_str(),
761  axis.c_str(),
762  angle);
763  ns.addRotation(nam, rot);
764  }
765 }
766 
768 template <>
769 void Converter<DDLLogicalPart>::operator()(xml_h element) const {
770  cms::DDNamespace ns(_param<cms::DDParsingContext>());
771  xml_dim_t e(element);
772  string sol = e.child(DD_CMU(rSolid)).attr<string>(_U(name));
773  string mat = e.child(DD_CMU(rMaterial)).attr<string>(_U(name));
774  string volName = e.attr<string>(_U(name));
775  Solid solid = ns.solid(sol);
776  Material material = ns.material(mat);
777  Volume volume = ns.addVolume(Volume(volName, solid, material));
778  printout(ns.context()->debug_volumes ? ALWAYS : DEBUG,
779  "DD4CMS",
780  "+++ %s Volume: %-24s [%s] Shape: %-32s [%s] Material: %-40s [%s]",
781  e.tag().c_str(),
782  volName.c_str(),
783  volume.isValid() ? "VALID" : "INVALID",
784  sol.c_str(),
785  solid.isValid() ? "VALID" : "INVALID",
786  mat.c_str(),
787  material.isValid() ? "VALID" : "INVALID");
788 }
789 
791 template <>
792 void Converter<DDLTransform3D>::operator()(xml_h element) const {
793  cms::DDNamespace ns(_param<cms::DDParsingContext>());
794  Transform3D* tr = _option<Transform3D>();
795  xml_dim_t e(element);
796  xml_dim_t translation = e.child(DD_CMU(Translation), false);
797  xml_dim_t rotation = e.child(DD_CMU(Rotation), false);
798  xml_dim_t refRotation = e.child(DD_CMU(rRotation), false);
799  xml_dim_t refReflectionRotation = e.child(DD_CMU(rReflectionRotation), false);
800  Position pos;
801  Rotation3D rot;
802 
803  if (translation.ptr()) {
804  double x = ns.attr<double>(translation, _U(x));
805  double y = ns.attr<double>(translation, _U(y));
806  double z = ns.attr<double>(translation, _U(z));
807  pos = Position(x, y, z);
808  }
809  if (rotation.ptr()) {
810  double x = ns.attr<double>(rotation, _U(x));
811  double y = ns.attr<double>(rotation, _U(y));
812  double z = ns.attr<double>(rotation, _U(z));
813  rot = RotationZYX(z, y, x);
814  } else if (refRotation.ptr()) {
815  string rotName = refRotation.nameStr();
816  if (strchr(rotName.c_str(), NAMESPACE_SEP) == nullptr)
817  rotName = ns.name() + rotName;
818 
819  rot = ns.rotation(rotName);
820  } else if (refReflectionRotation.ptr()) {
821  string rotName = refReflectionRotation.nameStr();
822  if (strchr(rotName.c_str(), NAMESPACE_SEP) == nullptr)
823  rotName = ns.name() + rotName;
824 
825  rot = ns.rotation(rotName);
826  }
827  *tr = Transform3D(rot, pos);
828 }
829 
831 template <>
832 void Converter<DDLPosPart>::operator()(xml_h element) const {
833  cms::DDNamespace ns(_param<cms::DDParsingContext>()); //, element, true );
834  xml_dim_t e(element);
835  int copy = e.attr<int>(DD_CMU(copyNumber));
836  string parentName = ns.attr<string>(e.child(DD_CMU(rParent)), _U(name));
837  string childName = ns.attr<string>(e.child(DD_CMU(rChild)), _U(name));
838  Volume parent = ns.volume(parentName, false);
839  Volume child = ns.volume(childName, false);
840  printout(ns.context()->debug_placements ? ALWAYS : DEBUG,
841  "DD4CMS",
842  "+++ %s Parent: %-24s [%s] Child: %-32s [%s] copy:%d",
843  e.tag().c_str(),
844  parentName.c_str(),
845  parent.isValid() ? "VALID" : "INVALID",
846  childName.c_str(),
847  child.isValid() ? "VALID" : "INVALID",
848  copy);
849 
850  if (!parent.isValid() && strchr(parentName.c_str(), NAMESPACE_SEP) == nullptr)
851  parentName = ns.name() + parentName;
852  parent = ns.volume(parentName);
853 
854  if (!child.isValid() && strchr(childName.c_str(), NAMESPACE_SEP) == nullptr)
855  childName = ns.name() + childName;
856  child = ns.volume(childName, false);
857 
858  printout(ns.context()->debug_placements ? ALWAYS : DEBUG,
859  "DD4CMS",
860  "+++ %s Parent: %-24s [%s] Child: %-32s [%s] copy:%d",
861  e.tag().c_str(),
862  parentName.c_str(),
863  parent.isValid() ? "VALID" : "INVALID",
864  childName.c_str(),
865  child.isValid() ? "VALID" : "INVALID",
866  copy);
867 
869  if (child.isValid()) {
870  Transform3D transform;
871  Converter<DDLTransform3D>(description, param, &transform)(element);
872 
873  // FIXME: workaround for Reflection rotation
874  // copy from DDCore/src/Volumes.cpp to replace
875  // static PlacedVolume _addNode(TGeoVolume* par, TGeoVolume* daughter, int id, TGeoMatrix* transform)
876  if (!parent) {
877  except("dd4hep", "Volume: Attempt to assign daughters to an invalid physical parent volume.");
878  }
879  if (!child) {
880  except("dd4hep", "Volume: Attempt to assign an invalid physical daughter volume.");
881  }
882  TGeoShape* shape = child->GetShape();
883  // Need to fix the daughter's BBox of assemblies, if the BBox was not calculated....
884  if (shape->IsA() == TGeoShapeAssembly::Class()) {
885  TGeoShapeAssembly* as = (TGeoShapeAssembly*)shape;
886  if (std::fabs(as->GetDX()) < numeric_limits<double>::epsilon() &&
887  std::fabs(as->GetDY()) < numeric_limits<double>::epsilon() &&
888  std::fabs(as->GetDZ()) < numeric_limits<double>::epsilon()) {
889  as->NeedsBBoxRecompute();
890  as->ComputeBBox();
891  }
892  }
893  TGeoNode* n;
894  TString nam_id = TString::Format("%s_%d", child->GetName(), copy);
895  n = static_cast<TGeoNode*>(parent->GetNode(nam_id));
896  if (n != nullptr) {
897  printout(ERROR, "PlacedVolume", "++ Attempt to add already exiting node %s", (const char*)nam_id);
898  }
899 
900  Rotation3D rot(transform.Rotation());
901  Translation3D trans(transform.Translation());
902  double x, y, z;
903  trans.GetComponents(x, y, z);
904  Position pos(x, y, z);
905  parent->AddNode(child, copy, createPlacement(rot, pos));
906 
907  n = static_cast<TGeoNode*>(parent->GetNode(nam_id));
908  n->TGeoNode::SetUserExtension(new PlacedVolume::Object());
909  pv = PlacedVolume(n);
910  }
911  if (!pv.isValid()) {
912  printout(ERROR,
913  "DD4CMS",
914  "+++ Placement FAILED! Parent:%s Child:%s Valid:%s",
915  parent.name(),
916  childName.c_str(),
917  yes_no(child.isValid()));
918  }
919 }
920 
922 template <>
923 void Converter<PartSelector>::operator()(xml_h element) const {
924  cms::DDNamespace ns(_param<cms::DDParsingContext>());
925  cms::DDParsingContext* const context = ns.context();
926  DDSpecParRegistry& registry = *context->description.load()->extension<DDSpecParRegistry>();
927  xml_dim_t e(element);
928  xml_dim_t specPar = e.parent();
929  string specParName = specPar.attr<string>(_U(name));
930  string path = e.attr<string>(DD_CMU(path));
931  printout(ns.context()->debug_specpars ? ALWAYS : DEBUG,
932  "DD4CMS",
933  "+++ PartSelector for %s path: %s",
934  specParName.c_str(),
935  path.c_str());
936  registry.specpars[specParName].paths.emplace_back(path);
937 }
938 
940 template <>
941 void Converter<Parameter>::operator()(xml_h element) const {
942  cms::DDNamespace ns(_param<cms::DDParsingContext>());
943  cms::DDParsingContext* const context = ns.context();
944  DDSpecParRegistry& registry = *context->description.load()->extension<DDSpecParRegistry>();
945  xml_dim_t e(element);
946  xml_dim_t specPar = e.parent();
947  xml_dim_t specParSect = specPar.parent();
948  string specParName = specPar.attr<string>(_U(name));
949  string name = e.nameStr();
950  string value = e.attr<string>(DD_CMU(value));
951  bool eval = e.hasAttr(_U(eval)) ? e.attr<bool>(_U(eval))
952  : (specParSect.hasAttr(_U(eval)) ? specParSect.attr<bool>(_U(eval)) : false);
953  string type = eval ? "number" : "string";
954 
955  printout(ns.context()->debug_specpars ? ALWAYS : DEBUG,
956  "DD4CMS",
957  "+++ Parameter for %s: %s value %s is a %s",
958  specParName.c_str(),
959  name.c_str(),
960  value.c_str(),
961  type.c_str());
962 
963  size_t idx = value.find('[');
964  if (idx == string::npos || type == "string") {
965  registry.specpars[specParName].spars[name].emplace_back(value);
966  return;
967  }
968 
969  while (idx != string::npos) {
970  ++idx;
971  size_t idp = value.find(':', idx);
972  size_t idq = value.find(']', idx);
973  if (idp == string::npos || idp > idq)
974  value.insert(idx, ns.name());
975  else if (idp != string::npos && idp < idq)
976  value[idp] = NAMESPACE_SEP;
977  idx = value.find('[', idx);
978  }
979 
980  string rep;
981  string& v = value;
982  size_t idq;
983  for (idx = v.find('[', 0); idx != string::npos; idx = v.find('[', idx + 1)) {
984  idq = v.find(']', idx + 1);
985  rep = v.substr(idx + 1, idq - idx - 1);
986  auto r = ns.context()->description.load()->constants().find(rep);
987  if (r != ns.context()->description.load()->constants().end()) {
988  rep = "(" + r->second->type + ")";
989  v.replace(idx, idq - idx + 1, rep);
990  }
991  }
992  registry.specpars[specParName].numpars[name].emplace_back(_toDouble(value));
993 }
994 
995 template <typename TYPE>
996 static void convert_boolean(cms::DDParsingContext* context, xml_h element) {
997  cms::DDNamespace ns(context);
998  xml_dim_t e(element);
999  string nam = e.nameStr();
1000  string solidName[2];
1001  Solid solids[2];
1002  Solid boolean;
1003  int cnt = 0;
1004  if (e.hasChild(DD_CMU(rSolid))) {
1005  for (xml_coll_t c(element, DD_CMU(rSolid)); cnt < 2 && c; ++c, ++cnt) {
1006  solidName[cnt] = c.attr<string>(_U(name));
1007  solids[cnt] = ns.solid(c.attr<string>(_U(name)));
1008  }
1009  } else {
1010  solidName[0] = e.attr<string>(DD_CMU(firstSolid));
1011  if ((solids[0] = ns.solid(e.attr<string>(DD_CMU(firstSolid)))).isValid())
1012  ++cnt;
1013  solidName[1] = e.attr<string>(DD_CMU(secondSolid));
1014  if ((solids[1] = ns.solid(e.attr<string>(DD_CMU(secondSolid)))).isValid())
1015  ++cnt;
1016  }
1017  if (cnt != 2) {
1018  except("DD4CMS", "+++ Failed to create boolean solid %s. Found only %d parts.", nam.c_str(), cnt);
1019  }
1020 
1021  printout(ns.context()->debug_placements ? ALWAYS : DEBUG,
1022  "DD4CMS",
1023  "+++ BooleanSolid: %s Left: %-32s Right: %-32s",
1024  nam.c_str(),
1025  ((solids[0].ptr() == nullptr) ? solidName[0].c_str() : solids[0]->GetName()),
1026  ((solids[1].ptr() == nullptr) ? solidName[1].c_str() : solids[1]->GetName()));
1027 
1028  if (solids[0].isValid() && solids[1].isValid()) {
1029  Transform3D trafo;
1030  Converter<DDLTransform3D>(*context->description, context, &trafo)(element);
1031  boolean = TYPE(solids[0], solids[1], trafo);
1032  } else {
1033  // Register it for later processing
1034  Transform3D trafo;
1035  Converter<DDLTransform3D>(*context->description, context, &trafo)(element);
1036  ns.context()->unresolvedShapes.emplace(nam,
1037  DDParsingContext::BooleanShape<TYPE>(solidName[0], solidName[1], trafo));
1038  }
1039  if (!boolean.isValid()) {
1040  // Delay processing the shape
1041  ns.context()->shapes.emplace(nam, dd4hep::Solid(nullptr));
1042  } else
1043  ns.addSolid(nam, boolean);
1044 }
1045 
1047 template <>
1048 void Converter<DDLUnionSolid>::operator()(xml_h element) const {
1049  convert_boolean<UnionSolid>(_param<cms::DDParsingContext>(), element);
1050 }
1051 
1053 template <>
1054 void Converter<DDLSubtractionSolid>::operator()(xml_h element) const {
1055  convert_boolean<SubtractionSolid>(_param<cms::DDParsingContext>(), element);
1056 }
1057 
1059 template <>
1060 void Converter<DDLIntersectionSolid>::operator()(xml_h element) const {
1061  convert_boolean<IntersectionSolid>(_param<cms::DDParsingContext>(), element);
1062 }
1063 
1065 template <>
1066 void Converter<DDLPolycone>::operator()(xml_h element) const {
1067  cms::DDNamespace ns(_param<cms::DDParsingContext>());
1068  xml_dim_t e(element);
1069  string nam = e.nameStr();
1070  double startPhi = ns.attr<double>(e, DD_CMU(startPhi));
1071  double deltaPhi = ns.attr<double>(e, DD_CMU(deltaPhi));
1072  vector<double> z, rmin, rmax, r;
1073 
1074  for (xml_coll_t rzpoint(element, DD_CMU(RZPoint)); rzpoint; ++rzpoint) {
1075  z.emplace_back(ns.attr<double>(rzpoint, _U(z)));
1076  r.emplace_back(ns.attr<double>(rzpoint, _U(r)));
1077  }
1078  if (z.empty()) {
1079  for (xml_coll_t zplane(element, DD_CMU(ZSection)); zplane; ++zplane) {
1080  rmin.emplace_back(ns.attr<double>(zplane, DD_CMU(rMin)));
1081  rmax.emplace_back(ns.attr<double>(zplane, DD_CMU(rMax)));
1082  z.emplace_back(ns.attr<double>(zplane, _U(z)));
1083  }
1084  printout(ns.context()->debug_shapes ? ALWAYS : DEBUG,
1085  "DD4CMS",
1086  "+ Polycone: startPhi=%10.3f [rad] deltaPhi=%10.3f [rad] %4ld z-planes",
1087  startPhi,
1088  deltaPhi,
1089  z.size());
1090  ns.addSolid(nam, Polycone(startPhi, deltaPhi, rmin, rmax, z));
1091  } else {
1092  printout(ns.context()->debug_shapes ? ALWAYS : DEBUG,
1093  "DD4CMS",
1094  "+ Polycone: startPhi=%10.3f [rad] deltaPhi=%10.3f [rad] %4ld z-planes and %4ld radii",
1095  startPhi,
1096  deltaPhi,
1097  z.size(),
1098  r.size());
1099  ns.addSolid(nam, Polycone(startPhi, deltaPhi, r, z));
1100  }
1101 }
1102 
1104 template <>
1105 void Converter<DDLExtrudedPolygon>::operator()(xml_h element) const {
1106  cms::DDNamespace ns(_param<cms::DDParsingContext>());
1107  xml_dim_t e(element);
1108  string nam = e.nameStr();
1109  vector<double> pt_x, pt_y, sec_x, sec_y, sec_z, sec_scale;
1110 
1111  for (xml_coll_t sec(element, DD_CMU(ZXYSection)); sec; ++sec) {
1112  sec_z.emplace_back(ns.attr<double>(sec, _U(z)));
1113  sec_x.emplace_back(ns.attr<double>(sec, _U(x)));
1114  sec_y.emplace_back(ns.attr<double>(sec, _U(y)));
1115  sec_scale.emplace_back(ns.attr<double>(sec, DD_CMU(scale), 1.0));
1116  }
1117  for (xml_coll_t pt(element, DD_CMU(XYPoint)); pt; ++pt) {
1118  pt_x.emplace_back(ns.attr<double>(pt, _U(x)));
1119  pt_y.emplace_back(ns.attr<double>(pt, _U(y)));
1120  }
1121  printout(ns.context()->debug_shapes ? ALWAYS : DEBUG,
1122  "DD4CMS",
1123  "+ ExtrudedPolygon: %4ld points %4ld zxy sections",
1124  pt_x.size(),
1125  sec_z.size());
1126  ns.addSolid(nam, ExtrudedPolygon(pt_x, pt_y, sec_z, sec_x, sec_y, sec_scale));
1127 }
1128 
1130 template <>
1131 void Converter<DDLPolyhedra>::operator()(xml_h element) const {
1132  cms::DDNamespace ns(_param<cms::DDParsingContext>());
1133  xml_dim_t e(element);
1134  string nam = e.nameStr();
1135  double numSide = ns.attr<int>(e, DD_CMU(numSide));
1136  double startPhi = ns.attr<double>(e, DD_CMU(startPhi));
1137  double deltaPhi = ns.attr<double>(e, DD_CMU(deltaPhi));
1138  vector<double> z, rmin, rmax;
1139 
1140  for (xml_coll_t zplane(element, DD_CMU(RZPoint)); zplane; ++zplane) {
1141  rmin.emplace_back(0.0);
1142  rmax.emplace_back(ns.attr<double>(zplane, _U(r)));
1143  z.emplace_back(ns.attr<double>(zplane, _U(z)));
1144  }
1145  for (xml_coll_t zplane(element, DD_CMU(ZSection)); zplane; ++zplane) {
1146  rmin.emplace_back(ns.attr<double>(zplane, DD_CMU(rMin)));
1147  rmax.emplace_back(ns.attr<double>(zplane, DD_CMU(rMax)));
1148  z.emplace_back(ns.attr<double>(zplane, _U(z)));
1149  }
1150  printout(ns.context()->debug_shapes ? ALWAYS : DEBUG,
1151  "DD4CMS",
1152  "+ Polyhedra:startPhi=%8.3f [rad] deltaPhi=%8.3f [rad] %4d sides %4ld z-planes",
1153  startPhi,
1154  deltaPhi,
1155  numSide,
1156  z.size());
1157  ns.addSolid(nam, Polyhedra(numSide, startPhi, deltaPhi, z, rmin, rmax));
1158 }
1159 
1161 template <>
1162 void Converter<DDLSphere>::operator()(xml_h element) const {
1163  cms::DDNamespace ns(_param<cms::DDParsingContext>());
1164  xml_dim_t e(element);
1165  string nam = e.nameStr();
1166  double rinner = ns.attr<double>(e, DD_CMU(innerRadius));
1167  double router = ns.attr<double>(e, DD_CMU(outerRadius));
1168  double startPhi = ns.attr<double>(e, DD_CMU(startPhi));
1169  double deltaPhi = ns.attr<double>(e, DD_CMU(deltaPhi));
1170  double startTheta = ns.attr<double>(e, DD_CMU(startTheta));
1171  double deltaTheta = ns.attr<double>(e, DD_CMU(deltaTheta));
1172  printout(ns.context()->debug_shapes ? ALWAYS : DEBUG,
1173  "DD4CMS",
1174  "+ Sphere: r_inner=%8.3f [cm] r_outer=%8.3f [cm]"
1175  " startPhi=%8.3f [rad] deltaPhi=%8.3f startTheta=%8.3f delteTheta=%8.3f [rad]",
1176  rinner,
1177  router,
1178  startPhi,
1179  deltaPhi,
1180  startTheta,
1181  deltaTheta);
1182  ns.addSolid(nam, Sphere(rinner, router, startTheta, deltaTheta, startPhi, deltaPhi));
1183 }
1184 
1186 template <>
1187 void Converter<DDLTorus>::operator()(xml_h element) const {
1188  cms::DDNamespace ns(_param<cms::DDParsingContext>());
1189  xml_dim_t e(element);
1190  string nam = e.nameStr();
1191  double r = ns.attr<double>(e, DD_CMU(torusRadius));
1192  double rinner = ns.attr<double>(e, DD_CMU(innerRadius));
1193  double router = ns.attr<double>(e, DD_CMU(outerRadius));
1194  double startPhi = ns.attr<double>(e, DD_CMU(startPhi));
1195  double deltaPhi = ns.attr<double>(e, DD_CMU(deltaPhi));
1196  printout(ns.context()->debug_shapes ? ALWAYS : DEBUG,
1197  "DD4CMS",
1198  "+ Torus: r=%10.3f [cm] r_inner=%10.3f [cm] r_outer=%10.3f [cm]"
1199  " startPhi=%10.3f [rad] deltaPhi=%10.3f [rad]",
1200  r,
1201  rinner,
1202  router,
1203  startPhi,
1204  deltaPhi);
1205  ns.addSolid(nam, Torus(r, rinner, router, startPhi, deltaPhi));
1206 }
1207 
1209 template <>
1210 void Converter<DDLPseudoTrap>::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 dx1 = ns.attr<double>(e, DD_CMU(dx1));
1215  double dy1 = ns.attr<double>(e, DD_CMU(dy1));
1216  double dx2 = ns.attr<double>(e, DD_CMU(dx2));
1217  double dy2 = ns.attr<double>(e, DD_CMU(dy2));
1218  double dz = ns.attr<double>(e, _U(dz));
1219  double r = ns.attr<double>(e, _U(radius));
1220  bool atMinusZ = ns.attr<bool>(e, DD_CMU(atMinusZ));
1221  printout(ns.context()->debug_shapes ? ALWAYS : DEBUG,
1222  "DD4CMS",
1223  "+ Pseudotrap: dz=%8.3f [cm] dx1:%.3f dy1:%.3f dx2=%.3f dy2=%.3f radius:%.3f atMinusZ:%s",
1224  dz,
1225  dx1,
1226  dy1,
1227  dx2,
1228  dy2,
1229  r,
1230  yes_no(atMinusZ));
1231  ns.addSolid(nam, PseudoTrap(dx1, dx2, dy1, dy2, dz, r, atMinusZ));
1232 }
1233 
1235 template <>
1236 void Converter<DDLTrapezoid>::operator()(xml_h element) const {
1237  cms::DDNamespace ns(_param<cms::DDParsingContext>());
1238  xml_dim_t e(element);
1239  string nam = e.nameStr();
1240  double dz = ns.attr<double>(e, _U(dz));
1241  double alp1 = ns.attr<double>(e, DD_CMU(alp1));
1242  double bl1 = ns.attr<double>(e, DD_CMU(bl1));
1243  double tl1 = ns.attr<double>(e, DD_CMU(tl1));
1244  double h1 = ns.attr<double>(e, DD_CMU(h1));
1245  double alp2 = ns.attr<double>(e, DD_CMU(alp2));
1246  double bl2 = ns.attr<double>(e, DD_CMU(bl2));
1247  double tl2 = ns.attr<double>(e, DD_CMU(tl2));
1248  double h2 = ns.attr<double>(e, DD_CMU(h2));
1249  double phi = ns.attr<double>(e, _U(phi), 0.0);
1250  double theta = ns.attr<double>(e, _U(theta), 0.0);
1251 
1252  printout(ns.context()->debug_shapes ? ALWAYS : DEBUG,
1253  "DD4CMS",
1254  "+ Trapezoid: dz=%10.3f [cm] alp1:%.3f bl1=%.3f tl1=%.3f alp2=%.3f bl2=%.3f tl2=%.3f h2=%.3f phi=%.3f "
1255  "theta=%.3f",
1256  dz,
1257  alp1,
1258  bl1,
1259  tl1,
1260  h1,
1261  alp2,
1262  bl2,
1263  tl2,
1264  h2,
1265  phi,
1266  theta);
1267  ns.addSolid(nam, Trap(dz, theta, phi, h1, bl1, tl1, alp1, h2, bl2, tl2, alp2));
1268 }
1269 
1271 template <>
1272 void Converter<DDLTrd1>::operator()(xml_h element) const {
1273  cms::DDNamespace ns(_param<cms::DDParsingContext>());
1274  xml_dim_t e(element);
1275  string nam = e.nameStr();
1276  double dx1 = ns.attr<double>(e, DD_CMU(dx1));
1277  double dy1 = ns.attr<double>(e, DD_CMU(dy1));
1278  double dx2 = ns.attr<double>(e, DD_CMU(dx2), 0.0);
1279  double dy2 = ns.attr<double>(e, DD_CMU(dy2), dy1);
1280  double dz = ns.attr<double>(e, DD_CMU(dz));
1281  if (dy1 == dy2) {
1282  printout(ns.context()->debug_shapes ? ALWAYS : DEBUG,
1283  "DD4CMS",
1284  "+ Trd1: dz=%8.3f [cm] dx1:%.3f dy1:%.3f dx2:%.3f dy2:%.3f",
1285  dz,
1286  dx1,
1287  dy1,
1288  dx2,
1289  dy2);
1290  ns.addSolid(nam, Trd1(dx1, dx2, dy1, dz));
1291  } else {
1292  printout(ns.context()->debug_shapes ? ALWAYS : DEBUG,
1293  "DD4CMS",
1294  "+ Trd1(which is actually Trd2): dz=%8.3f [cm] dx1:%.3f dy1:%.3f dx2:%.3f dy2:%.3f",
1295  dz,
1296  dx1,
1297  dy1,
1298  dx2,
1299  dy2);
1300  ns.addSolid(nam, Trd2(dx1, dx2, dy1, dy2, dz));
1301  }
1302 }
1303 
1305 template <>
1306 void Converter<DDLTrd2>::operator()(xml_h element) const {
1307  cms::DDNamespace ns(_param<cms::DDParsingContext>());
1308  xml_dim_t e(element);
1309  string nam = e.nameStr();
1310  double dx1 = ns.attr<double>(e, DD_CMU(dx1));
1311  double dy1 = ns.attr<double>(e, DD_CMU(dy1));
1312  double dx2 = ns.attr<double>(e, DD_CMU(dx2), 0.0);
1313  double dy2 = ns.attr<double>(e, DD_CMU(dy2), dy1);
1314  double dz = ns.attr<double>(e, DD_CMU(dz));
1315  printout(ns.context()->debug_shapes ? ALWAYS : DEBUG,
1316  "DD4CMS",
1317  "+ Trd1: dz=%8.3f [cm] dx1:%.3f dy1:%.3f dx2:%.3f dy2:%.3f",
1318  dz,
1319  dx1,
1320  dy1,
1321  dx2,
1322  dy2);
1323  ns.addSolid(nam, Trd2(dx1, dx2, dy1, dy2, dz));
1324 }
1325 
1327 template <>
1328 void Converter<DDLTubs>::operator()(xml_h element) const {
1329  cms::DDNamespace ns(_param<cms::DDParsingContext>());
1330  xml_dim_t e(element);
1331  string nam = e.nameStr();
1332  double dz = ns.attr<double>(e, DD_CMU(dz));
1333  double rmin = ns.attr<double>(e, DD_CMU(rMin));
1334  double rmax = ns.attr<double>(e, DD_CMU(rMax));
1335  double startPhi = ns.attr<double>(e, DD_CMU(startPhi), 0.0);
1336  double deltaPhi = ns.attr<double>(e, DD_CMU(deltaPhi), 2 * M_PI);
1337  printout(ns.context()->debug_shapes ? ALWAYS : DEBUG,
1338  "DD4CMS",
1339  "+ Tubs: dz=%8.3f [cm] rmin=%8.3f [cm] rmax=%8.3f [cm]"
1340  " startPhi=%8.3f [rad] deltaPhi=%8.3f [rad]",
1341  dz,
1342  rmin,
1343  rmax,
1344  startPhi,
1345  deltaPhi);
1346  ns.addSolid(nam, Tube(rmin, rmax, dz, startPhi, startPhi + deltaPhi));
1347 }
1348 
1350 template <>
1351 void Converter<DDLCutTubs>::operator()(xml_h element) const {
1352  cms::DDNamespace ns(_param<cms::DDParsingContext>());
1353  xml_dim_t e(element);
1354  string nam = e.nameStr();
1355  double dz = ns.attr<double>(e, DD_CMU(dz));
1356  double rmin = ns.attr<double>(e, DD_CMU(rMin));
1357  double rmax = ns.attr<double>(e, DD_CMU(rMax));
1358  double startPhi = ns.attr<double>(e, DD_CMU(startPhi));
1359  double deltaPhi = ns.attr<double>(e, DD_CMU(deltaPhi));
1360  double lx = ns.attr<double>(e, DD_CMU(lx));
1361  double ly = ns.attr<double>(e, DD_CMU(ly));
1362  double lz = ns.attr<double>(e, DD_CMU(lz));
1363  double tx = ns.attr<double>(e, DD_CMU(tx));
1364  double ty = ns.attr<double>(e, DD_CMU(ty));
1365  double tz = ns.attr<double>(e, DD_CMU(tz));
1366  printout(ns.context()->debug_shapes ? ALWAYS : DEBUG,
1367  "DD4CMS",
1368  "+ CutTube: dz=%8.3f [cm] rmin=%8.3f [cm] rmax=%8.3f [cm]"
1369  " startPhi=%8.3f [rad] deltaPhi=%8.3f [rad]...",
1370  dz,
1371  rmin,
1372  rmax,
1373  startPhi,
1374  deltaPhi);
1375  ns.addSolid(nam, CutTube(rmin, rmax, dz, startPhi, startPhi + deltaPhi, lx, ly, lz, tx, ty, tz));
1376 }
1377 
1379 template <>
1380 void Converter<DDLTruncTubs>::operator()(xml_h element) const {
1381  cms::DDNamespace ns(_param<cms::DDParsingContext>());
1382  xml_dim_t e(element);
1383  string nam = e.nameStr();
1384  double zhalf = ns.attr<double>(e, DD_CMU(zHalf));
1385  double rmin = ns.attr<double>(e, DD_CMU(rMin));
1386  double rmax = ns.attr<double>(e, DD_CMU(rMax));
1387  double startPhi = ns.attr<double>(e, DD_CMU(startPhi));
1388  double deltaPhi = ns.attr<double>(e, DD_CMU(deltaPhi));
1389  double cutAtStart = ns.attr<double>(e, DD_CMU(cutAtStart));
1390  double cutAtDelta = ns.attr<double>(e, DD_CMU(cutAtDelta));
1391  bool cutInside = ns.attr<bool>(e, DD_CMU(cutInside));
1392  printout(ns.context()->debug_shapes ? ALWAYS : DEBUG,
1393  "DD4CMS",
1394  "+ TruncTube:zHalf=%8.3f [cm] rmin=%8.3f [cm] rmax=%8.3f [cm]"
1395  " startPhi=%8.3f [rad] deltaPhi=%8.3f [rad] atStart=%8.3f [cm] atDelta=%8.3f [cm] inside:%s",
1396  zhalf,
1397  rmin,
1398  rmax,
1399  startPhi,
1400  deltaPhi,
1401  cutAtStart,
1402  cutAtDelta,
1403  yes_no(cutInside));
1404  ns.addSolid(nam, TruncatedTube(zhalf, rmin, rmax, startPhi, deltaPhi, cutAtStart, cutAtDelta, cutInside));
1405 }
1406 
1408 template <>
1409 void Converter<DDLEllipticalTube>::operator()(xml_h element) const {
1410  cms::DDNamespace ns(_param<cms::DDParsingContext>());
1411  xml_dim_t e(element);
1412  string nam = e.nameStr();
1413  double dx = ns.attr<double>(e, DD_CMU(xSemiAxis));
1414  double dy = ns.attr<double>(e, DD_CMU(ySemiAxis));
1415  double dz = ns.attr<double>(e, DD_CMU(zHeight));
1416  printout(ns.context()->debug_shapes ? ALWAYS : DEBUG,
1417  "DD4CMS",
1418  "+ EllipticalTube xSemiAxis=%8.3f [cm] ySemiAxis=%8.3f [cm] zHeight=%8.3f [cm]",
1419  dx,
1420  dy,
1421  dz);
1422  ns.addSolid(nam, EllipticalTube(dx, dy, dz));
1423 }
1424 
1426 template <>
1427 void Converter<DDLCone>::operator()(xml_h element) const {
1428  cms::DDNamespace ns(_param<cms::DDParsingContext>());
1429  xml_dim_t e(element);
1430  string nam = e.nameStr();
1431  double dz = ns.attr<double>(e, DD_CMU(dz));
1432  double rmin1 = ns.attr<double>(e, DD_CMU(rMin1));
1433  double rmin2 = ns.attr<double>(e, DD_CMU(rMin2));
1434  double rmax1 = ns.attr<double>(e, DD_CMU(rMax1));
1435  double rmax2 = ns.attr<double>(e, DD_CMU(rMax2));
1436  double startPhi = ns.attr<double>(e, DD_CMU(startPhi));
1437  double deltaPhi = ns.attr<double>(e, DD_CMU(deltaPhi));
1438  double phi2 = startPhi + deltaPhi;
1439  printout(ns.context()->debug_shapes ? ALWAYS : DEBUG,
1440  "DD4CMS",
1441  "+ Cone: dz=%8.3f [cm]"
1442  " rmin1=%8.3f [cm] rmax1=%8.3f [cm]"
1443  " rmin2=%8.3f [cm] rmax2=%8.3f [cm]"
1444  " startPhi=%8.3f [rad] deltaPhi=%8.3f [rad]",
1445  dz,
1446  rmin1,
1447  rmax1,
1448  rmin2,
1449  rmax2,
1450  startPhi,
1451  deltaPhi);
1452  ns.addSolid(nam, ConeSegment(dz, rmin1, rmax1, rmin2, rmax2, startPhi, phi2));
1453 }
1454 
1456 template <>
1457 void Converter<DDLShapeless>::operator()(xml_h element) const {
1458  cms::DDNamespace ns(_param<cms::DDParsingContext>());
1459  xml_dim_t e(element);
1460  string nam = e.nameStr();
1461  printout(ns.context()->debug_shapes ? ALWAYS : DEBUG,
1462  "DD4CMS",
1463  "+ Shapeless: THIS ONE CAN ONLY BE USED AT THE VOLUME LEVEL -> Assembly%s",
1464  nam.c_str());
1465  ns.addSolid(nam, Box(1, 1, 1));
1466 }
1467 
1469 template <>
1470 void Converter<DDLBox>::operator()(xml_h element) const {
1471  cms::DDNamespace ns(_param<cms::DDParsingContext>());
1472  xml_dim_t e(element);
1473  string nam = e.nameStr();
1474  double dx = ns.attr<double>(e, DD_CMU(dx));
1475  double dy = ns.attr<double>(e, DD_CMU(dy));
1476  double dz = ns.attr<double>(e, DD_CMU(dz));
1477  printout(ns.context()->debug_shapes ? ALWAYS : DEBUG,
1478  "DD4CMS",
1479  "+ Box: dx=%10.3f [cm] dy=%10.3f [cm] dz=%10.3f [cm]",
1480  dx,
1481  dy,
1482  dz);
1483  ns.addSolid(nam, Box(dx, dy, dz));
1484 }
1485 
1487 template <>
1488 void Converter<include_load>::operator()(xml_h element) const {
1489  string fname = element.attr<string>(_U(ref));
1490  edm::FileInPath fp(fname);
1491  xml::Document doc;
1492  doc = xml::DocumentHandler().load(fp.fullPath());
1493  printout(_param<cms::DDParsingContext>()->debug_includes ? ALWAYS : DEBUG,
1494  "DD4CMS",
1495  "+++ Processing the CMS detector description %s",
1496  fname.c_str());
1497  _option<DDRegistry>()->includes.emplace_back(doc);
1498 }
1499 
1501 template <>
1502 void Converter<include_unload>::operator()(xml_h element) const {
1503  string fname = xml::DocumentHandler::system_path(element);
1504  xml::DocumentHolder(xml_elt_t(element).document()).assign(nullptr);
1505  printout(_param<cms::DDParsingContext>()->debug_includes ? ALWAYS : DEBUG,
1506  "DD4CMS",
1507  "+++ Finished processing %s",
1508  fname.c_str());
1509 }
1510 
1512 template <>
1513 void Converter<include_constants>::operator()(xml_h element) const {
1514  xml_coll_t(element, DD_CMU(ConstantsSection)).for_each(Converter<ConstantsSection>(description, param, optional));
1515 }
1516 
1517 namespace {
1518 
1519  // The meaning of the axis index is the following:
1520  // for all volumes having shapes like box, trd1, trd2, trap, gtra or para - 1,2,3 means X,Y,Z;
1521  // for tube, tubs, cone, cons - 1 means Rxy, 2 means phi and 3 means Z;
1522  // for pcon and pgon - 2 means phi and 3 means Z;
1523  // for spheres 1 means R and 2 means phi.
1524 
1525  enum class DDAxes { x = 1, y = 2, z = 3, rho = 1, phi = 2, undefined };
1526  const std::map<std::string, DDAxes> axesmap{{"x", DDAxes::x},
1527  {"y", DDAxes::y},
1528  {"z", DDAxes::z},
1529  {"rho", DDAxes::rho},
1530  {"phi", DDAxes::phi},
1531  {"undefined", DDAxes::undefined}};
1532 } // namespace
1533 
1535 template <>
1536 void Converter<DDLDivision>::operator()(xml_h element) const {
1537  cms::DDNamespace ns(_param<cms::DDParsingContext>(), element);
1538  xml_dim_t e(element);
1539  string childName = e.nameStr();
1540  if (strchr(childName.c_str(), NAMESPACE_SEP) == nullptr)
1541  childName = ns.name() + childName;
1542 
1543  string parentName = ns.attr<string>(e, DD_CMU(parent));
1544  if (strchr(parentName.c_str(), NAMESPACE_SEP) == nullptr)
1545  parentName = ns.name() + parentName;
1546  string axis = ns.attr<string>(e, DD_CMU(axis));
1547 
1548  // If you divide a tube of 360 degrees the offset displaces
1549  // the starting angle, but you still fill the 360 degrees
1550  double offset = e.hasAttr(DD_CMU(offset)) ? ns.attr<double>(e, DD_CMU(offset)) : 0e0;
1551  double width = e.hasAttr(DD_CMU(width)) ? ns.attr<double>(e, DD_CMU(width)) : 0e0;
1552  int nReplicas = e.hasAttr(DD_CMU(nReplicas)) ? ns.attr<int>(e, DD_CMU(nReplicas)) : 0;
1553 
1554  printout(ns.context()->debug_placements ? ALWAYS : DEBUG,
1555  "DD4CMS",
1556  "+++ Start executing Division of %s along %s (%d) with offset %6.3f and %6.3f to produce %s....",
1557  parentName.c_str(),
1558  axis.c_str(),
1559  axesmap.at(axis),
1560  offset,
1561  width,
1562  childName.c_str());
1563 
1564  Volume parent = ns.volume(parentName);
1565 
1566  const TGeoShape* shape = parent.solid();
1567  TClass* cl = shape->IsA();
1568  if (cl == TGeoTubeSeg::Class()) {
1569  const TGeoTubeSeg* sh = (const TGeoTubeSeg*)shape;
1570  double widthInDeg = convertRadToDeg(width);
1571  double startInDeg = convertRadToDeg(offset);
1572  int numCopies = (int)((sh->GetPhi2() - sh->GetPhi1()) / widthInDeg);
1573  printout(ns.context()->debug_placements ? ALWAYS : DEBUG,
1574  "DD4CMS",
1575  "+++ ...divide %s along %s (%d) with offset %6.3f deg and %6.3f deg to produce %d copies",
1576  parent.solid().type(),
1577  axis.c_str(),
1578  axesmap.at(axis),
1579  startInDeg,
1580  widthInDeg,
1581  numCopies);
1582  Volume child = parent.divide(childName, static_cast<int>(axesmap.at(axis)), numCopies, startInDeg, widthInDeg);
1583 
1584  ns.context()->volumes[childName] = child;
1585 
1586  printout(ns.context()->debug_placements ? ALWAYS : DEBUG,
1587  "DD4CMS",
1588  "+++ %s Parent: %-24s [%s] Child: %-32s [%s] is multivolume [%s]",
1589  e.tag().c_str(),
1590  parentName.c_str(),
1591  parent.isValid() ? "VALID" : "INVALID",
1592  child.name(),
1593  child.isValid() ? "VALID" : "INVALID",
1594  child->IsVolumeMulti() ? "YES" : "NO");
1595 
1596  } else if (cl == TGeoTrd1::Class()) {
1597  double dy = static_cast<const TGeoTrd1*>(shape)->GetDy();
1598  printout(ns.context()->debug_placements ? ALWAYS : DEBUG,
1599  "DD4CMS",
1600  "+++ ...divide %s along %s (%d) with offset %6.3f cm and %6.3f cm to produce %d copies in %6.3f",
1601  parent.solid().type(),
1602  axis.c_str(),
1603  axesmap.at(axis),
1604  -dy + offset + width,
1605  width,
1606  nReplicas,
1607  dy);
1608  Volume child = parent.divide(childName, static_cast<int>(axesmap.at(axis)), nReplicas, -dy + offset + width, width);
1609 
1610  ns.context()->volumes[childName] = child;
1611 
1612  printout(ns.context()->debug_placements ? ALWAYS : DEBUG,
1613  "DD4CMS",
1614  "+++ %s Parent: %-24s [%s] Child: %-32s [%s] is multivolume [%s]",
1615  e.tag().c_str(),
1616  parentName.c_str(),
1617  parent.isValid() ? "VALID" : "INVALID",
1618  child.name(),
1619  child.isValid() ? "VALID" : "INVALID",
1620  child->IsVolumeMulti() ? "YES" : "NO");
1621  } else {
1622  printout(ERROR, "DD4CMS", "++ FAILED Division of a %s is not implemented yet!", parent.solid().type());
1623  }
1624 }
1625 
1627 template <>
1628 void Converter<DDLAlgorithm>::operator()(xml_h element) const {
1629  cms::DDNamespace ns(_param<cms::DDParsingContext>());
1630  xml_dim_t e(element);
1631  string name = e.nameStr();
1632  for (auto const& i : ns.context()->disabledAlgs) {
1633  if (name == i) {
1634  // if(ns.context()->disabledAlgs.find( name ) != ns.context()->disabledAlgs.end()) {
1635  printout(INFO, "DD4CMS", "+++ Skip disabled algorithms: %s", name.c_str());
1636  return;
1637  }
1638  }
1639 
1640  size_t idx;
1642  string type = "DDCMS_" + ns.realName(name);
1643  while ((idx = type.find(NAMESPACE_SEP)) != string::npos)
1644  type[idx] = '_';
1645 
1646  // SensitiveDetector and Segmentation currently are undefined. Let's keep it like this
1647  // until we found something better.....
1648  printout(
1649  ns.context()->debug_algorithms ? ALWAYS : DEBUG, "DD4CMS", "+++ Start executing algorithm %s....", type.c_str());
1650 
1651  long ret = PluginService::Create<long>(type, &description, ns.context(), &element, &sd);
1652  if (ret == s_executed) {
1653  printout(ns.context()->debug_algorithms ? ALWAYS : DEBUG,
1654  "DD4CMS",
1655  "+++ Executed algorithm: %08lX = %s",
1656  ret,
1657  name.c_str());
1658  return;
1659  }
1660  printout(ERROR, "DD4CMS", "++ FAILED NOT ADDING SUBDETECTOR %08lX = %s", ret, name.c_str());
1661 }
1662 
1663 template <class InputIt, class ForwardIt, class BinOp>
1664 void for_each_token(InputIt first, InputIt last, ForwardIt s_first, ForwardIt s_last, BinOp binary_op) {
1665  while (first != last) {
1666  const auto pos = std::find_first_of(first, last, s_first, s_last);
1667  binary_op(first, pos);
1668  if (pos == last)
1669  break;
1670  first = std::next(pos);
1671  }
1672 }
1673 
1674 namespace {
1675 
1676  tbb::concurrent_vector<double> splitNumeric(const string& str, const string& delims = ",") {
1677  tbb::concurrent_vector<double> output;
1678 
1679  for_each_token(cbegin(str), cend(str), cbegin(delims), cend(delims), [&output](auto first, auto second) {
1680  if (first != second) {
1681  if (string(first, second).front() == '[' && string(first, second).back() == ']') {
1682  first++;
1683  second--;
1684  }
1685  output.emplace_back(dd4hep::_toDouble(string(first, second)));
1686  }
1687  });
1688  return output;
1689  }
1690 } // namespace
1691 
1694 template <>
1695 void Converter<DDLVector>::operator()(xml_h element) const {
1696  cms::DDNamespace ns(_param<cms::DDParsingContext>());
1697  cms::DDParsingContext* const context = ns.context();
1698  DDVectorsMap* registry = context->description.load()->extension<DDVectorsMap>();
1699  xml_dim_t e(element);
1700  string name = ns.prepend(e.nameStr());
1701  string type = ns.attr<string>(e, _U(type));
1702  string nEntries = ns.attr<string>(e, DD_CMU(nEntries));
1703  string val = e.text();
1704  val.erase(remove_if(val.begin(), val.end(), [](unsigned char x) { return isspace(x); }), val.end());
1705 
1706  printout(ns.context()->debug_constants ? ALWAYS : DEBUG,
1707  "DD4CMS",
1708  "+++ Vector<%s>: %s[%s]: %s",
1709  type.c_str(),
1710  name.c_str(),
1711  nEntries.c_str(),
1712  val.c_str());
1713 
1714  tbb::concurrent_vector<double> results = splitNumeric(val);
1715  registry->insert({name, results});
1716 }
1717 
1718 template <>
1719 void Converter<debug>::operator()(xml_h dbg) const {
1720  cms::DDNamespace ns(_param<cms::DDParsingContext>());
1721  if (dbg.hasChild(DD_CMU(debug_visattr)))
1722  ns.setContext()->debug_visattr = true;
1723  if (dbg.hasChild(DD_CMU(debug_constants)))
1724  ns.setContext()->debug_constants = true;
1725  if (dbg.hasChild(DD_CMU(debug_materials)))
1726  ns.setContext()->debug_materials = true;
1727  if (dbg.hasChild(DD_CMU(debug_rotations)))
1728  ns.setContext()->debug_rotations = true;
1729  if (dbg.hasChild(DD_CMU(debug_shapes)))
1730  ns.setContext()->debug_shapes = true;
1731  if (dbg.hasChild(DD_CMU(debug_volumes)))
1732  ns.setContext()->debug_volumes = true;
1733  if (dbg.hasChild(DD_CMU(debug_placements)))
1734  ns.setContext()->debug_placements = true;
1735  if (dbg.hasChild(DD_CMU(debug_namespaces)))
1736  ns.setContext()->debug_namespaces = true;
1737  if (dbg.hasChild(DD_CMU(debug_includes)))
1738  ns.setContext()->debug_includes = true;
1739  if (dbg.hasChild(DD_CMU(debug_algorithms)))
1740  ns.setContext()->debug_algorithms = true;
1741  if (dbg.hasChild(DD_CMU(debug_specpars)))
1742  ns.setContext()->debug_specpars = true;
1743 }
1744 
1745 template <>
1746 void Converter<DDRegistry>::operator()(xml_h /* element */) const {
1747  cms::DDParsingContext* context = _param<cms::DDParsingContext>();
1748  DDRegistry* res = _option<DDRegistry>();
1749  cms::DDNamespace ns(context);
1750  int count = 0;
1751 
1752  printout(context->debug_constants ? ALWAYS : DEBUG,
1753  "DD4CMS",
1754  "+++ RESOLVING %ld unknown constants.....",
1755  res->unresolvedConst.size());
1756 
1757  while (!res->unresolvedConst.empty()) {
1758  for (auto i : res->unresolvedConst) {
1759  const string& n = i.first;
1760  string rep;
1761  string& v = i.second;
1762  size_t idx, idq;
1763  for (idx = v.find('[', 0); idx != string::npos; idx = v.find('[', idx + 1)) {
1764  idq = v.find(']', idx + 1);
1765  rep = v.substr(idx + 1, idq - idx - 1);
1766  auto r = res->allConst.find(rep);
1767  if (r != res->allConst.end()) {
1768  rep = "(" + (*r).second + ")";
1769  v.replace(idx, idq - idx + 1, rep);
1770  }
1771  }
1772  if (v.find(']') == string::npos) {
1773  if (v.find("-+") != string::npos || v.find("+-") != string::npos) {
1774  while ((idx = v.find("-+")) != string::npos)
1775  v.replace(idx, 2, "-");
1776  while ((idx = v.find("+-")) != string::npos)
1777  v.replace(idx, 2, "-");
1778  }
1779  printout(context->debug_constants ? ALWAYS : DEBUG,
1780  "DD4CMS",
1781  "+++ [%06ld] ---------- %-40s = %s",
1782  res->unresolvedConst.size() - 1,
1783  n.c_str(),
1784  res->originalConst[n].c_str());
1785  ns.addConstantNS(n, v, "number");
1786  res->unresolvedConst.unsafe_erase(n);
1787  break;
1788  }
1789  }
1790  if (++count > 10000)
1791  break;
1792  }
1793  if (!res->unresolvedConst.empty()) {
1794  for (const auto& e : res->unresolvedConst)
1795  printout(ERROR, "DD4CMS", "+++ Unresolved constant: %-40s = %s.", e.first.c_str(), e.second.c_str());
1796  except("DD4CMS", "++ FAILED to resolve %ld constant entries:", res->unresolvedConst.size());
1797  }
1798  res->unresolvedConst.clear();
1799  res->originalConst.clear();
1800  res->allConst.clear();
1801 }
1802 
1803 template <>
1804 void Converter<print_xml_doc>::operator()(xml_h element) const {
1805  string fname = xml::DocumentHandler::system_path(element);
1806  printout(_param<cms::DDParsingContext>()->debug_includes ? ALWAYS : DEBUG,
1807  "DD4CMS",
1808  "+++ Processing data from: %s",
1809  fname.c_str());
1810 }
1811 
1813 static long load_dddefinition(Detector& det, xml_h element) {
1814  cms::DDParsingContext context(&det);
1815  cms::DDNamespace ns(context);
1816  ns.addConstantNS("world_x", "101*m", "number");
1817  ns.addConstantNS("world_y", "101*m", "number");
1818  ns.addConstantNS("world_z", "450*m", "number");
1819  ns.addConstantNS("Air", "materials:Air", "string");
1820  ns.addConstantNS("Vacuum", "materials:Vacuum", "string");
1821  ns.addConstantNS("fm", "1e-12*m", "number");
1822  ns.addConstantNS("mum", "1e-6*m", "number");
1823 
1824  xml_elt_t dddef(element);
1825  string fname = xml::DocumentHandler::system_path(element);
1826  bool open_geometry = dddef.hasChild(DD_CMU(open_geometry)) ? dddef.child(DD_CMU(open_geometry)) : true;
1827  bool close_geometry = dddef.hasChild(DD_CMU(close_geometry)) ? dddef.hasChild(DD_CMU(close_geometry)) : true;
1828 
1829  xml_coll_t(dddef, _U(debug)).for_each(Converter<debug>(det, &context));
1830 
1831  // Here we define the order how XML elements are processed.
1832  // Be aware of dependencies. This can only defined once.
1833  // At the end it is a limitation of DOM....
1834  printout(INFO, "DD4CMS", "+++ Processing the CMS detector description %s", fname.c_str());
1835 
1836  xml::Document doc;
1837  Converter<print_xml_doc> print_doc(det, &context);
1838  try {
1839  DDRegistry res;
1840  print_doc((doc = dddef.document()).root());
1841  xml_coll_t(dddef, DD_CMU(DisabledAlgo)).for_each(Converter<disabled_algo>(det, &context, &res));
1842  xml_coll_t(dddef, DD_CMU(ConstantsSection)).for_each(Converter<ConstantsSection>(det, &context, &res));
1843  xml_coll_t(dddef, DD_CMU(VisSection)).for_each(Converter<vissection>(det, &context));
1844  xml_coll_t(dddef, DD_CMU(RotationSection)).for_each(Converter<RotationSection>(det, &context));
1845  xml_coll_t(dddef, DD_CMU(MaterialSection)).for_each(Converter<MaterialSection>(det, &context));
1846 
1847  xml_coll_t(dddef, DD_CMU(IncludeSection)).for_each(DD_CMU(Include), Converter<include_load>(det, &context, &res));
1848 
1849  for (xml::Document d : res.includes) {
1850  print_doc((doc = d).root());
1851  Converter<include_constants>(det, &context, &res)((doc = d).root());
1852  }
1853  // Before we continue, we have to resolve all constants NOW!
1854  Converter<DDRegistry>(det, &context, &res)(dddef);
1855  // Now we can process the include files one by one.....
1856  for (xml::Document d : res.includes) {
1857  print_doc((doc = d).root());
1858  xml_coll_t(d.root(), DD_CMU(MaterialSection)).for_each(Converter<MaterialSection>(det, &context));
1859  }
1860  {
1861  printout(context.debug_materials ? ALWAYS : DEBUG,
1862  "DD4CMS",
1863  "+++ RESOLVING %ld unknown material constituents.....",
1864  context.unresolvedMaterials.size());
1865 
1866  // Resolve referenced materials (if any)
1867 
1868  while (!context.unresolvedMaterials.empty()) {
1869  for (auto it = context.unresolvedMaterials.begin(); it != context.unresolvedMaterials.end();) {
1870  auto const& name = it->first;
1871  std::vector<bool> valid;
1872 
1873  printout(context.debug_materials ? ALWAYS : DEBUG,
1874  "DD4CMS",
1875  "+++ [%06ld] ---------- %s",
1876  context.unresolvedMaterials.size(),
1877  name.c_str());
1878 
1879  auto mat = ns.material(name);
1880  for (auto& mit : it->second) {
1881  printout(context.debug_materials ? ALWAYS : DEBUG,
1882  "DD4CMS",
1883  "+++ component %-48s Fraction: %.6f",
1884  mit.name.c_str(),
1885  mit.fraction);
1886  auto fmat = ns.material(mit.name);
1887  if (nullptr != fmat.ptr()) {
1888  if (mat.ptr()->GetMaterial()->IsMixture()) {
1889  valid.emplace_back(true);
1890  static_cast<TGeoMixture*>(mat.ptr()->GetMaterial())->AddElement(fmat.ptr()->GetMaterial(), mit.fraction);
1891  }
1892  }
1893  }
1894  // All components are resolved
1895  if (valid.size() == it->second.size())
1896  it = context.unresolvedMaterials.erase(it);
1897  else
1898  ++it;
1899  }
1900  // Do it again if there are unresolved
1901  // materials left after this pass
1902  }
1903  }
1904  if (open_geometry) {
1905  context.geo_inited = true;
1906  det.init();
1907  ns.addVolume(det.worldVolume());
1908  }
1909  for (xml::Document d : res.includes) {
1910  print_doc((doc = d).root());
1911  xml_coll_t(d.root(), DD_CMU(RotationSection)).for_each(Converter<RotationSection>(det, &context));
1912  }
1913  for (xml::Document d : res.includes) {
1914  print_doc((doc = d).root());
1915  xml_coll_t(d.root(), DD_CMU(SolidSection)).for_each(Converter<SolidSection>(det, &context));
1916  }
1917  for (xml::Document d : res.includes) {
1918  print_doc((doc = d).root());
1919  xml_coll_t(d.root(), DD_CMU(LogicalPartSection)).for_each(Converter<LogicalPartSection>(det, &context));
1920  }
1921  for (xml::Document d : res.includes) {
1922  print_doc((doc = d).root());
1923  xml_coll_t(d.root(), DD_CMU(Algorithm)).for_each(Converter<DDLAlgorithm>(det, &context));
1924  }
1925  for (xml::Document d : res.includes) {
1926  print_doc((doc = d).root());
1927  xml_coll_t(d.root(), DD_CMU(PosPartSection)).for_each(Converter<PosPartSection>(det, &context));
1928  }
1929  for (xml::Document d : res.includes) {
1930  print_doc((doc = d).root());
1931  xml_coll_t(d.root(), DD_CMU(SpecParSection)).for_each(Converter<SpecParSection>(det, &context));
1932  }
1933 
1935  for (xml::Document d : res.includes)
1936  Converter<include_unload>(det, &context, &res)(d.root());
1937 
1938  print_doc((doc = dddef.document()).root());
1939  // Now process the actual geometry items
1940  xml_coll_t(dddef, DD_CMU(SolidSection)).for_each(Converter<SolidSection>(det, &context));
1941  {
1942  // Before we continue, we have to resolve all shapes NOW!
1943  // Note: This only happens in a legacy DB payloads where
1944  // boolean shapes can be defined before thier
1945  // component shapes
1946 
1947  while (!context.unresolvedShapes.empty()) {
1948  for (auto it = context.unresolvedShapes.begin(); it != context.unresolvedShapes.end();) {
1949  auto const& name = it->first;
1950  auto const& aname = std::visit([](auto&& arg) -> std::string { return arg.firstSolidName; }, it->second);
1951  auto const& bname = std::visit([](auto&& arg) -> std::string { return arg.secondSolidName; }, it->second);
1952 
1953  auto const& ait = context.shapes.find(aname);
1954  if (ait->second.isValid()) {
1955  auto const& bit = context.shapes.find(bname);
1956  if (bit->second.isValid()) {
1957  dd4hep::Solid shape = std::visit(
1958  [&ait, &bit](auto&& arg) -> dd4hep::Solid { return arg.make(ait->second, bit->second); }, it->second);
1959  context.shapes[name] = shape;
1960  it = context.unresolvedShapes.erase(it);
1961  } else
1962  ++it;
1963  } else
1964  ++it;
1965  }
1966  }
1967  }
1968  xml_coll_t(dddef, DD_CMU(LogicalPartSection)).for_each(Converter<LogicalPartSection>(det, &context));
1969  xml_coll_t(dddef, DD_CMU(Algorithm)).for_each(Converter<DDLAlgorithm>(det, &context));
1970  xml_coll_t(dddef, DD_CMU(PosPartSection)).for_each(Converter<PosPartSection>(det, &context));
1971  xml_coll_t(dddef, DD_CMU(SpecParSection)).for_each(Converter<SpecParSection>(det, &context));
1972  } catch (const exception& e) {
1973  printout(ERROR, "DD4CMS", "Exception while processing xml source:%s", doc.uri().c_str());
1974  printout(ERROR, "DD4CMS", "----> %s", e.what());
1975  throw;
1976  }
1977 
1979  if (close_geometry) {
1980  Volume wv = det.worldVolume();
1981  Volume geomv = ns.volume("cms:OCMS", false);
1982  if (geomv.isValid())
1983  wv.placeVolume(geomv, 1);
1984  Volume mfv = ns.volume("cmsMagneticField:MAGF", false);
1985  if (mfv.isValid())
1986  wv.placeVolume(mfv, 1);
1987  Volume mfv1 = ns.volume("MagneticFieldVolumes:MAGF", false);
1988  if (mfv1.isValid())
1989  wv.placeVolume(mfv1, 1);
1990 
1991  det.endDocument();
1992  }
1993  printout(INFO, "DDDefinition", "+++ Finished processing %s", fname.c_str());
1994  return 1;
1995 }
1996 
1997 // Now declare the factory entry for the plugin mechanism
1998 DECLARE_XML_DOC_READER(DDDefinition, load_dddefinition)
DDLPosPart handles PosPart elements.
Definition: DDLPosPart.h:27
type
Definition: HCALResponse.h:21
#define DEBUG
dd4hep::Volume volume(const std::string &name, bool exc=true) const
Definition: DDNamespace.cc:184
DDLSphere processes all Sphere elements.
Definition: DDLSphere.h:24
tbb::concurrent_vector< xml::Document > includes
tbb::concurrent_unordered_map< std::string, std::string > allConst
DDLDivision processes Division elements.
Definition: DDLDivision.h:27
ROOT::Math::Plane3D::Vector Vector
Definition: EcalHitMaker.cc:29
DDLVector handles Rotation and ReflectionRotation elements.
Definition: DDLVector.h:29
ret
prodAgent to be discontinued
tbb::concurrent_unordered_map< std::string, std::string > originalConst
constexpr NumType convertRadToDeg(NumType radians)
Definition: angle_units.h:21
ROOT::Math::DisplacementVector3D< ROOT::Math::Cartesian3D< double >> Translation
Geom::Theta< T > theta() const
tbb::concurrent_vector< std::string > disabledAlgs
DDLEllipticalTube processes all EllipticalTube elements.
dd4hep::Volume addVolume(dd4hep::Volume vol) const
Add rotation matrix to current namespace.
Definition: DDNamespace.cc:167
TGeoCombiTrans * createPlacement(const Rotation3D &iRot, const Position &iTrans)
dd4hep::Solid solid(const std::string &name) const
Definition: DDNamespace.cc:219
std::map< std::string, std::vector< CompositeMaterial > > unresolvedMaterials
A arg
Definition: Factorize.h:36
std::atomic< dd4hep::Detector * > description
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
Definition: Electron.h:6
dd4hep::Rotation3D makeRotation3D(double thetaX, double phiX, double thetaY, double phiY, double thetaZ, double phiZ)
DDParsingContext *const context() const
Definition: DDNamespace.h:65
std::string_view name() const
Definition: DDNamespace.h:68
U second(std::pair< T, U > const &p)
void addConstantNS(const std::string &name, const std::string &value, const std::string &type) const
Definition: DDNamespace.cc:107
DDLBox processes Box elements.
Definition: DDLBox.h:27
DDLElementaryMaterial processes ElementaryMaterial elements.
std::string realName(const std::string &) const
Definition: DDNamespace.cc:73
static constexpr long s_executed
T attr(xml_elt_t element, const xml_tag_t &name) const
Definition: DDNamespace.h:34
DDLCone processes all Cone elements.
Definition: DDLCone.h:27
dd4hep::PlacedVolume PlacedVolume
dd4hep::Rotation3D makeRotReflect(double thetaX, double phiX, double thetaY, double phiY, double thetaZ, double phiZ)
tbb::concurrent_unordered_map< std::string, tbb::concurrent_vector< double >> DDVectorsMap
Definition: DDNamespace.h:14
def pv(vc)
Definition: MetAnalyzer.py:7
dd4hep::Material material(const std::string &name) const
Definition: DDNamespace.cc:121
double f[11][100]
optional
Definition: Types.py:167
tbb::concurrent_unordered_map< std::string, dd4hep::Volume > volumes
constexpr unsigned int hash(const char *str, int h=0)
Definition: value.py:1
#define DD_CMU(a)
Definition: DDXMLTags.h:189
static void convert_boolean(cms::DDParsingContext *context, xml_h element)
rep
Definition: cuy.py:1190
std::string prepend(const std::string &) const
Definition: DDNamespace.cc:66
dd4hep::Volume Volume
d
Definition: ztail.py:151
#define M_PI
Namespace of DDCMS conversion namespace.
DDLTubs processes Tubs elements.
Definition: DDLTubs.h:21
Polynomial< 0 > Constant
Definition: Constant.h:6
std::map< std::string, std::variant< BooleanShape< dd4hep::UnionSolid >, BooleanShape< dd4hep::SubtractionSolid >, BooleanShape< dd4hep::IntersectionSolid > > > unresolvedShapes
def ls(path, rec=False)
Definition: eostools.py:349
#define debug
Definition: HDRShower.cc:19
dd4hep::Solid addSolid(const std::string &name, dd4hep::Solid solid) const
Definition: DDNamespace.cc:215
DDLLogicalPart processes LogicalPart elements.
tbb::concurrent_unordered_map< std::string, dd4hep::Solid > shapes
double sd
double b
Definition: hdecay.h:118
DDLRotationByAxis handles RotationByAxis elements.
DDLCompositeMaterial processes all CompositeMaterial elements.
const dd4hep::Rotation3D & rotation(const std::string &name) const
Definition: DDNamespace.cc:130
string fname
main script
static long load_dddefinition(Detector &det, xml_h element)
Converter for <DDDefinition> tags.
DDAxes
analagous to geant4/source/global/HEPGeometry/include/geomdefs.hh
Definition: DDAxes.h:11
alpha
zGenParticlesMatch = cms.InputTag(""),
#define str(s)
tbb::concurrent_unordered_map< std::string, std::string > unresolvedConst
DDLRotationSequence handles a set of Rotations.
void addConstant(const std::string &name, const std::string &value, const std::string &type) const
Definition: DDNamespace.cc:103
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:79
T angle(T x1, T y1, T z1, T x2, T y2, T z2)
Definition: angle.h:11
DDParsingContext * setContext()
Definition: DDNamespace.h:66
unsigned transform(const HcalDetId &id, unsigned transformCode)