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"
12 #include "XML/Utilities.h"
22 #include "TGeoManager.h"
23 #include "TGeoMaterial.h"
30 #include <unordered_map>
38 using namespace cms_units::operators;
44 atomic<UInt_t> unique_mat_id = 0xAFFEFEED;
46 class include_constants;
51 class ConstantsSection;
60 class MaterialSection;
64 class RotationSection;
66 class DDLReflectionRotation;
75 class LogicalPartSection;
79 class DDLExtrudedPolygon;
97 class DDLIntersectionSolid;
98 class DDLSubtractionSolid;
103 class SpecParSection;
113 iRot.GetComponents(elements);
115 r.SetMatrix(elements);
117 TGeoTranslation
t(iTrans.x(), iTrans.y(), iTrans.z());
119 return new TGeoCombiTrans(
t, r);
124 void Converter<debug>::operator()(xml_h element)
const;
126 void Converter<print_xml_doc>::operator()(xml_h element)
const;
130 void Converter<ConstantsSection>::operator()(xml_h element)
const;
132 void Converter<DDLConstant>::operator()(xml_h element)
const;
134 void Converter<DDRegistry>::operator()(xml_h element)
const;
138 void Converter<MaterialSection>::operator()(xml_h element)
const;
140 void Converter<DDLElementaryMaterial>::operator()(xml_h element)
const;
142 void Converter<DDLCompositeMaterial>::operator()(xml_h element)
const;
146 void Converter<RotationSection>::operator()(xml_h element)
const;
149 void Converter<DDLRotation>::operator()(xml_h element)
const;
152 void Converter<DDLReflectionRotation>::operator()(xml_h element)
const;
155 void Converter<DDLRotationSequence>::operator()(xml_h element)
const;
158 void Converter<DDLRotationByAxis>::operator()(xml_h element)
const;
160 void Converter<DDLTransform3D>::operator()(xml_h element)
const;
164 void Converter<LogicalPartSection>::operator()(xml_h element)
const;
166 void Converter<DDLLogicalPart>::operator()(xml_h element)
const;
170 void Converter<PosPartSection>::operator()(xml_h element)
const;
173 void Converter<DDLPosPart>::operator()(xml_h element)
const;
176 void Converter<DDLDivision>::operator()(xml_h element)
const;
180 void Converter<SpecParSection>::operator()(xml_h element)
const;
182 void Converter<DDLSpecPar>::operator()(xml_h element)
const;
184 void Converter<PartSelector>::operator()(xml_h element)
const;
186 void Converter<Parameter>::operator()(xml_h element)
const;
190 void Converter<SolidSection>::operator()(xml_h element)
const;
193 void Converter<DDLUnionSolid>::operator()(xml_h element)
const;
196 void Converter<DDLSubtractionSolid>::operator()(xml_h element)
const;
199 void Converter<DDLIntersectionSolid>::operator()(xml_h element)
const;
202 void Converter<DDLPseudoTrap>::operator()(xml_h element)
const;
205 void Converter<DDLExtrudedPolygon>::operator()(xml_h element)
const;
208 void Converter<DDLShapeless>::operator()(xml_h element)
const;
211 void Converter<DDLAssembly>::operator()(xml_h element)
const;
214 void Converter<DDLTrapezoid>::operator()(xml_h element)
const;
217 void Converter<DDLPolycone>::operator()(xml_h element)
const;
220 void Converter<DDLPolyhedra>::operator()(xml_h element)
const;
223 void Converter<DDLEllipticalTube>::operator()(xml_h element)
const;
226 void Converter<DDLTorus>::operator()(xml_h element)
const;
229 void Converter<DDLTubs>::operator()(xml_h element)
const;
232 void Converter<DDLCutTubs>::operator()(xml_h element)
const;
235 void Converter<DDLTruncTubs>::operator()(xml_h element)
const;
238 void Converter<DDLSphere>::operator()(xml_h element)
const;
241 void Converter<DDLTrd1>::operator()(xml_h element)
const;
244 void Converter<DDLTrd2>::operator()(xml_h element)
const;
247 void Converter<DDLCone>::operator()(xml_h element)
const;
250 void Converter<DDLBox>::operator()(xml_h element)
const;
253 void Converter<DDLAlgorithm>::operator()(xml_h element)
const;
256 void Converter<DDLVector>::operator()(xml_h element)
const;
260 void Converter<include_load>::operator()(xml_h element)
const;
263 void Converter<include_unload>::operator()(xml_h element)
const;
266 void Converter<include_constants>::operator()(xml_h element)
const;
271 void Converter<ConstantsSection>::operator()(xml_h element)
const {
280 void Converter<MaterialSection>::operator()(xml_h element)
const {
282 xml_coll_t(element,
DD_CMU(ElementaryMaterial))
284 xml_coll_t(element,
DD_CMU(CompositeMaterial))
289 void Converter<RotationSection>::operator()(xml_h element)
const {
292 xml_coll_t(element,
DD_CMU(ReflectionRotation))
294 xml_coll_t(element,
DD_CMU(RotationSequence))
296 xml_coll_t(element,
DD_CMU(RotationByAxis))
301 void Converter<PosPartSection>::operator()(xml_h element)
const {
309 void Converter<SpecParSection>::operator()(xml_h element)
const {
315 void Converter<DDLSpecPar>::operator()(xml_h element)
const {
323 void Converter<LogicalPartSection>::operator()(xml_h element)
const {
330 void Converter<SolidSection>::operator()(xml_h element)
const {
332 for (xml_coll_t solid(element, _U(star)); solid; ++solid) {
334 switch (
hash(solid.tag())) {
338 case hash(
"Polycone"):
341 case hash(
"Polyhedra"):
347 case hash(
"CutTubs"):
350 case hash(
"TruncTubs"):
368 case hash(
"EllipticalTube"):
374 case hash(
"PseudoTrap"):
377 case hash(
"ExtrudedPolygon"):
380 case hash(
"Trapezoid"):
383 case hash(
"UnionSolid"):
386 case hash(
"SubtractionSolid"):
389 case hash(
"IntersectionSolid"):
392 case hash(
"ShapelessSolid"):
395 case hash(
"Assembly"):
399 throw std::runtime_error(
"Request to process unknown shape '" + xml_dim_t(solid).nameStr() +
"' [" +
408 void Converter<DDLConstant>::operator()(xml_h element)
const {
410 DDRegistry* res = _option<DDRegistry>();
411 xml_dim_t constant = element;
412 xml_dim_t par = constant.parent();
413 bool eval = par.hasAttr(_U(eval)) ? par.attr<
bool>(_U(eval)) :
true;
414 string val = constant.valueStr();
415 string nam = constant.nameStr();
416 string real = ns.prepend(nam);
417 string typ = eval ?
"number" :
"string";
418 size_t idx = val.find(
'[');
420 if (constant.hasAttr(_U(
type)))
421 typ = constant.typeStr();
423 if (idx == string::npos || typ ==
"string") {
425 ns.addConstant(nam, val, typ);
426 res->originalConst[real] =
val;
432 "++ Unresolved constant: %s = %s [%s]. Try to resolve later. [%s]",
442 while (idx != string::npos) {
444 size_t idp = val.find(
':', idx);
445 size_t idq = val.find(
']', idx);
446 if (idp == string::npos || idp > idq)
447 val.insert(idx, ns.name());
448 else if (idp != string::npos && idp < idq)
450 idx = val.find(
'[', idx);
456 ns.context()->debug_constants ? ALWAYS :
DEBUG,
"Constant",
"Unresolved: %s -> %s", real.c_str(), val.c_str());
460 res->originalConst[real] =
val;
461 res->unresolvedConst[real] =
val;
466 void Converter<DDLElementaryMaterial>::operator()(xml_h element)
const {
468 xml_dim_t xmat(element);
469 const string xmatName(xmat.nameStr());
470 string nam = ns.prepend(xmatName);
472 TGeoMaterial* mat = mgr.GetMaterial(nam.c_str());
473 if (
nullptr == mat) {
474 const char* matname = nam.c_str();
475 double density = xmat.attr<
double>(
DD_CMU(density)) / (
dd4hep::g / dd4hep::cm3);
476 int atomicNumber = xmat.attr<
int>(
DD_CMU(atomicNumber));
477 double atomicWeight = xmat.attr<
double>(
DD_CMU(atomicWeight)) / (
dd4hep::g / dd4hep::mole);
478 TGeoElementTable* tab = mgr.GetElementTable();
479 int nElem = tab->GetNelements();
483 printout(ns.context()->debug_materials ? ALWAYS :
DEBUG,
"DD4CMS",
"+++ Element table size = %d", nElem);
488 tab->TGeoElementTable::~TGeoElementTable();
489 new (tab) TGeoElementTable();
490 tab->BuildDefaultElements();
492 TGeoMixture*
mix =
new TGeoMixture(nam.c_str(), 1, density);
493 const char*
const matNameNoNS = xmatName.c_str();
494 TGeoElement* elt = tab->FindElement(matNameNoNS);
498 printout(ns.context()->debug_materials ? ALWAYS :
DEBUG,
500 "+++ Searching for material %-48s elt_ptr = %ld",
504 printout(ns.context()->debug_materials ? ALWAYS :
DEBUG,
506 "+++ Converting material %-48s Atomic weight %8.3f [g/mol], Atomic number %u, Density: %8.3f [g/cm3] "
507 "ROOT: %8.3f [g/cm3]",
508 (
'"' + nam +
'"').c_str(),
516 bool newMatDef =
false;
523 printout(ns.context()->debug_materials ? ALWAYS :
DEBUG,
525 " ROOT definition of %-50s Atomic weight %g, Atomic number %u, Number of nucleons %u",
530 printout(ns.context()->debug_materials ? ALWAYS :
DEBUG,
532 "+++ Compared to XML values: Atomic weight %g, Atomic number %u",
537 static constexpr
double const weightTolerance = 1.0e-6;
538 if (atomicNumber != elt->Z() ||
539 (
std::abs(atomicWeight - elt->A()) > (weightTolerance * (atomicWeight + elt->A()))))
543 if (!elt || newMatDef) {
547 printout(ns.context()->debug_materials ? ALWAYS :
DEBUG,
549 "+++ Converter<ElementaryMaterial> Different definition of a default element with name:%s [CREATE NEW "
558 printout(ns.context()->debug_materials ? ALWAYS :
DEBUG,
560 "+++ Converter<ElementaryMaterial> No default element present with name:%s [CREATE NEW MATERIAL]",
565 elt =
new TGeoElement(matNameNoNS, matNameNoNS, atomicNumber, atomicWeight);
568 mix->AddElement(elt, 1.0);
569 mix->SetTemperature(ns.context()->description.stdConditions().temperature);
570 mix->SetPressure(ns.context()->description.stdConditions().pressure);
573 TGeoMedium* medium = mgr.GetMedium(matname);
574 if (
nullptr == medium) {
576 medium =
new TGeoMedium(matname, unique_mat_id, mix);
577 medium->SetTitle(
"material");
578 medium->SetUniqueID(unique_mat_id);
585 void Converter<DDLCompositeMaterial>::operator()(xml_h element)
const {
587 xml_dim_t xmat(element);
588 string nam = ns.prepend(xmat.nameStr());
591 TGeoMaterial* mat = mgr.GetMaterial(nam.c_str());
592 if (
nullptr == mat) {
593 const char* matname = nam.c_str();
594 double density = xmat.attr<
double>(
DD_CMU(density)) / (
dd4hep::g / dd4hep::cm3);
595 xml_coll_t composites(xmat,
DD_CMU(MaterialFraction));
596 TGeoMixture* mix =
new TGeoMixture(nam.c_str(), composites.size(), density);
600 printout(ns.context()->debug_materials ? ALWAYS :
DEBUG,
602 "++ Converting material %-48s Density: %8.3f [g/cm3] ROOT: %8.3f [g/cm3]",
603 (
'"' + nam +
'"').c_str(),
609 if (ns.context()->makePayload) {
610 ns.context()->compMaterialsVec.emplace_back(std::make_pair(nam, density));
612 for (composites.reset(); composites; ++composites) {
613 xml_dim_t xfrac(composites);
614 xml_dim_t xfrac_mat(xfrac.child(
DD_CMU(rMaterial)));
616 string fracname = ns.realName(xfrac_mat.nameStr());
618 if (ns.context()->makePayload) {
619 ns.context()->compMaterialsRefs[nam].emplace_back(
622 TGeoMaterial* frac_mat = mgr.GetMaterial(fracname.c_str());
623 if (frac_mat ==
nullptr)
624 frac_mat = mgr.GetMaterial(ns.prepend(fracname).c_str());
626 mix->AddElement(frac_mat, fraction);
630 throw cms::Exception(
"DD4CMS") <<
"Composite material \"" + fracname +
"\" or \"" + ns.prepend(fracname) +
631 "\" not yet defined.";
633 mix->SetTemperature(ns.context()->description.stdConditions().temperature);
634 mix->SetPressure(ns.context()->description.stdConditions().pressure);
637 TGeoMedium* medium = mgr.GetMedium(matname);
638 if (
nullptr == medium) {
640 medium =
new TGeoMedium(matname, unique_mat_id, mix);
641 medium->SetTitle(
"material");
642 medium->SetUniqueID(unique_mat_id);
649 void Converter<DDLRotation>::operator()(xml_h element)
const {
652 xml_dim_t xrot(element);
653 string nam = xrot.nameStr();
654 double thetaX = xrot.hasAttr(
DD_CMU(thetaX)) ? ns.attr<
double>(xrot,
DD_CMU(thetaX)) : 0e0;
655 double phiX = xrot.hasAttr(
DD_CMU(phiX)) ? ns.attr<
double>(xrot,
DD_CMU(phiX)) : 0e0;
656 double thetaY = xrot.hasAttr(
DD_CMU(thetaY)) ? ns.attr<
double>(xrot,
DD_CMU(thetaY)) : 0e0;
657 double phiY = xrot.hasAttr(
DD_CMU(phiY)) ? ns.attr<
double>(xrot,
DD_CMU(phiY)) : 0e0;
658 double thetaZ = xrot.hasAttr(
DD_CMU(thetaZ)) ? ns.attr<
double>(xrot,
DD_CMU(thetaZ)) : 0e0;
659 double phiZ = xrot.hasAttr(
DD_CMU(phiZ)) ? ns.attr<
double>(xrot,
DD_CMU(phiZ)) : 0e0;
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(),
677 ns.addRotation(nam, rot);
682 void Converter<DDLReflectionRotation>::operator()(xml_h element)
const {
685 xml_dim_t xrot(element);
686 string name = xrot.nameStr();
687 double thetaX = xrot.hasAttr(
DD_CMU(thetaX)) ? ns.attr<
double>(xrot,
DD_CMU(thetaX)) : 0e0;
688 double phiX = xrot.hasAttr(
DD_CMU(phiX)) ? ns.attr<
double>(xrot,
DD_CMU(phiX)) : 0e0;
689 double thetaY = xrot.hasAttr(
DD_CMU(thetaY)) ? ns.attr<
double>(xrot,
DD_CMU(thetaY)) : 0e0;
690 double phiY = xrot.hasAttr(
DD_CMU(phiY)) ? ns.attr<
double>(xrot,
DD_CMU(phiY)) : 0e0;
691 double thetaZ = xrot.hasAttr(
DD_CMU(thetaZ)) ? ns.attr<
double>(xrot,
DD_CMU(thetaZ)) : 0e0;
692 double phiZ = xrot.hasAttr(
DD_CMU(phiZ)) ? ns.attr<
double>(xrot,
DD_CMU(phiZ)) : 0e0;
698 "+++ Adding reflection rotation: %-32s: (theta/phi)[rad] X: %6.3f %6.3f Y: %6.3f %6.3f Z: %6.3f %6.3f",
699 ns.prepend(name).c_str(),
709 Rotation3D rot =
makeRotReflect(thetaX, phiX, thetaY, phiY, thetaZ, phiZ);
710 ns.addRotation(name, rot);
715 void Converter<DDLRotationSequence>::operator()(xml_h element)
const {
718 xml_dim_t xrot(element);
719 string nam = xrot.nameStr();
721 xml_coll_t rotations(xrot,
DD_CMU(RotationByAxis));
722 for (rotations.reset(); rotations; ++rotations) {
723 string axis = ns.attr<
string>(rotations,
DD_CMU(axis));
724 double angle = ns.attr<
double>(rotations, _U(angle));
731 "+ Adding rotation to: %-29s: (axis/angle)[rad] Axis: %s Angle: %6.3f",
741 rot.GetComponents(xx, xy, xz, yx, yy, yz, zx, zy, zz);
747 "+++ Adding rotation sequence: %-23s: %6.3f %6.3f %6.3f, %6.3f %6.3f %6.3f, %6.3f %6.3f %6.3f",
748 ns.prepend(nam).c_str(),
761 ns.addRotation(nam, rot);
766 void Converter<DDLRotationByAxis>::operator()(xml_h element)
const {
769 xml_dim_t xrot(element);
770 xml_dim_t par(xrot.parent());
771 if (xrot.hasAttr(_U(name))) {
772 string nam = xrot.nameStr();
773 string axis = ns.attr<
string>(xrot,
DD_CMU(axis));
774 double angle = ns.attr<
double>(xrot, _U(angle));
782 "+++ Adding rotation: %-32s: (axis/angle)[rad] Axis: %s Angle: %6.3f",
783 ns.prepend(nam).c_str(),
789 ns.addRotation(nam, rot);
795 void Converter<DDLLogicalPart>::operator()(xml_h element)
const {
797 xml_dim_t
e(element);
798 string sol = e.child(
DD_CMU(rSolid)).attr<
string>(_U(name));
799 string mat = e.child(
DD_CMU(rMaterial)).attr<
string>(_U(name));
800 string volName = ns.prepend(e.attr<
string>(_U(name)));
801 Solid solid = ns.solid(sol);
802 Material material = ns.material(mat);
803 if (ns.context()->assemblySolids.count(sol) == 1) {
807 ns.addAssembly(volName,
false);
815 ns.addVolume(
Volume(volName, solid, material));
819 printout(ns.context()->debug_volumes ? ALWAYS :
DEBUG,
821 "+++ %s Volume: %-24s [%s] Shape: %-32s [%s] Material: %-40s [%s]",
824 volume.isValid() ?
"VALID" :
"INVALID",
826 solid.isValid() ?
"VALID" :
"INVALID",
828 material.isValid() ?
"VALID" :
"INVALID");
835 void Converter<DDLTransform3D>::operator()(xml_h element)
const {
837 Transform3D* tr = _option<Transform3D>();
838 xml_dim_t
e(element);
841 xml_dim_t refRotation = e.child(
DD_CMU(rRotation),
false);
842 xml_dim_t refReflectionRotation = e.child(
DD_CMU(rReflectionRotation),
false);
846 if (translation.ptr()) {
847 double x = ns.attr<
double>(translation, _U(x));
848 double y = ns.attr<
double>(translation, _U(y));
849 double z = ns.attr<
double>(translation, _U(z));
852 if (rotation.ptr()) {
853 double x = ns.attr<
double>(
rotation, _U(x));
854 double y = ns.attr<
double>(
rotation, _U(y));
855 double z = ns.attr<
double>(
rotation, _U(z));
856 rot = RotationZYX(z, y, x);
857 }
else if (refRotation.ptr()) {
858 string rotName = ns.prepend(refRotation.nameStr());
859 rot = ns.rotation(rotName);
860 }
else if (refReflectionRotation.ptr()) {
861 string rotName = ns.prepend(refReflectionRotation.nameStr());
862 rot = ns.rotation(rotName);
864 *tr = Transform3D(rot, pos);
868 const string& parentName,
870 const string& childName,
878 "+++ Parent vol: %-24s Child: %-32s, copy:%d",
885 TGeoShape* shape = (*childPtr)->GetShape();
887 if (shape->IsA() == TGeoShapeAssembly::Class()) {
888 TGeoShapeAssembly* as = (TGeoShapeAssembly*)shape;
892 as->NeedsBBoxRecompute();
897 TString nam_id = TString::Format(
"%s_%d", (*childPtr)->GetName(),
copy);
898 n =
static_cast<TGeoNode*
>((*parentPtr)->GetNode(nam_id));
900 printout(
ERROR,
"PlacedVolume",
"++ Attempt to add already existing node %s", (
const char*)nam_id);
905 if ((*childPtr)->IsAssembly()) {
908 pv = parentPtr->placeVolume(*childPtr, copy, transform);
912 printout(
ERROR,
"DD4CMS",
"+++ Placement FAILED! Parent:%s Child:%s", parentName.c_str(), childName.c_str());
918 void Converter<DDLPosPart>::operator()(xml_h element)
const {
920 xml_dim_t
e(element);
922 string parentName = ns.prepend(ns.attr<
string>(e.child(
DD_CMU(rParent)), _U(name)));
923 string childName = ns.prepend(ns.attr<
string>(e.child(
DD_CMU(rChild)), _U(name)));
929 Assembly parAsmb = ns.assembly(parentName,
false);
930 Assembly childAsmb = ns.assembly(childName,
false);
934 printout(ns.context()->debug_placements ? ALWAYS :
DEBUG,
936 "+++ %s Parent: %-24s [%s] Child: %-32s [%s] copy:%d",
939 parent.isValid() ?
"VALID" :
"INVALID",
941 child.isValid() ?
"VALID" :
"INVALID",
946 if (!parent.isValid() && !parAsmb.isValid() && strchr(parentName.c_str(),
NAMESPACE_SEP) ==
nullptr) {
947 parentName = ns.prepend(parentName);
948 parAsmb = ns.assembly(parentName,
false);
949 if (!parAsmb.isValid())
950 parent = ns.volume(parentName);
953 if (!child.isValid() && !childAsmb.isValid() && strchr(childName.c_str(),
NAMESPACE_SEP) ==
nullptr) {
954 childName = ns.prepend(childName);
955 child = ns.volume(childName,
false);
956 childAsmb = ns.assembly(childName,
false);
958 if (parAsmb.isValid() || childAsmb.isValid()) {
959 printout(ns.context()->debug_placements ? ALWAYS :
DEBUG,
961 "***** Placing assembly parent %s, child %s",
964 Volume* parentPtr = parAsmb.isValid() ? &parAsmb : &
parent;
965 Volume* childPtr = childAsmb.isValid() ? &childAsmb : &
child;
966 placeAssembly(parentPtr, parentName, childPtr, childName, copy, transform, ns);
972 printout(ns.context()->debug_placements ? ALWAYS :
DEBUG,
974 "+++ %s Parent: %-24s [%s] Child: %-32s [%s] copy:%d",
977 parent.isValid() ?
"VALID" :
"INVALID",
979 child.isValid() ?
"VALID" :
"INVALID",
985 if (child.isValid()) {
990 except(
"dd4hep",
"Volume: Attempt to assign daughters to an invalid physical parent volume.");
993 except(
"dd4hep",
"Volume: Attempt to assign an invalid physical daughter volume.");
995 TGeoShape* shape = child->GetShape();
997 if (shape->IsA() == TGeoShapeAssembly::Class()) {
998 TGeoShapeAssembly* as = (TGeoShapeAssembly*)shape;
1002 as->NeedsBBoxRecompute();
1007 TString nam_id = TString::Format(
"%s_%d", child->GetName(),
copy);
1008 n =
static_cast<TGeoNode*
>(parent->GetNode(nam_id));
1010 printout(
ERROR,
"PlacedVolume",
"++ Attempt to add already existing node %s", (
const char*)nam_id);
1013 Rotation3D
rot(transform.Rotation());
1014 Translation3D trans(transform.Translation());
1016 trans.GetComponents(x, y, z);
1020 n =
static_cast<TGeoNode*
>(parent->GetNode(nam_id));
1021 n->TGeoNode::SetUserExtension(
new PlacedVolume::Object());
1024 if (!pv.isValid()) {
1027 "+++ Placement FAILED! Parent:%s Child:%s Valid:%s",
1030 yes_no(child.isValid()));
1036 void Converter<PartSelector>::operator()(xml_h element)
const {
1039 dd4hep::SpecParRegistry& registry = *context->
description.extension<dd4hep::SpecParRegistry>();
1040 xml_dim_t
e(element);
1041 xml_dim_t specPar = e.parent();
1042 string specParName = specPar.attr<
string>(_U(name));
1047 printout(ns.context()->debug_specpars ? ALWAYS :
DEBUG,
1049 "+++ PartSelector for %s path: %s",
1050 specParName.c_str(),
1055 size_t pos = std::string::npos;
1056 if ((pos = path.find(
"//.*:")) != std::string::npos) {
1057 path.erase(pos + 2, 3);
1059 registry.specpars[specParName].paths.emplace_back(
std::move(path));
1064 void Converter<Parameter>::operator()(xml_h element)
const {
1067 dd4hep::SpecParRegistry& registry = *context->
description.extension<dd4hep::SpecParRegistry>();
1068 xml_dim_t
e(element);
1069 xml_dim_t specPar = e.parent();
1070 xml_dim_t specParSect = specPar.parent();
1071 string specParName = specPar.attr<
string>(_U(name));
1072 string name = e.nameStr();
1074 bool eval = specParSect.hasAttr(_U(eval)) ? specParSect.attr<
bool>(_U(eval)) :
false;
1075 eval = specPar.hasAttr(_U(eval)) ? specPar.attr<
bool>(_U(eval)) : eval;
1076 eval = e.hasAttr(_U(eval)) ? e.attr<
bool>(_U(eval)) : eval;
1078 string type = eval ?
"number" :
"string";
1082 printout(ns.context()->debug_specpars ? ALWAYS :
DEBUG,
1084 "+++ Parameter for %s: %s value %s is a %s",
1085 specParName.c_str(),
1092 size_t idx = value.find(
'[');
1093 if (idx == string::npos && type ==
"number") {
1094 registry.specpars[specParName].numpars[
name].emplace_back(dd4hep::_toDouble(value));
1097 if (idx == string::npos || type ==
"string") {
1098 registry.specpars[specParName].spars[
name].emplace_back(
std::move(value));
1102 while (idx != string::npos) {
1104 size_t idp = value.find(
':', idx);
1105 size_t idq = value.find(
']', idx);
1106 if (idp == string::npos || idp > idq)
1107 value.insert(idx, ns.name());
1108 else if (idp != string::npos && idp < idq)
1110 idx = value.find(
'[', idx);
1116 for (idx = v.find(
'[', 0); idx != string::npos; idx = v.find(
'[', idx + 1)) {
1117 idq = v.find(
']', idx + 1);
1118 rep = v.substr(idx + 1, idq - idx - 1);
1119 auto r = ns.context()->description.constants().find(rep);
1120 if (
r != ns.context()->description.constants().end()) {
1121 rep =
"(" +
r->second->type +
")";
1122 v.replace(idx, idq - idx + 1, rep);
1125 registry.specpars[specParName].numpars[
name].emplace_back(dd4hep::_toDouble(value));
1128 template <
typename TYPE>
1131 xml_dim_t
e(element);
1132 string nam = e.nameStr();
1133 string solidName[2];
1137 if (e.hasChild(
DD_CMU(rSolid))) {
1138 for (xml_coll_t
c(element,
DD_CMU(rSolid)); cnt < 2 &&
c; ++
c, ++cnt) {
1139 solidName[cnt] = c.attr<
string>(_U(name));
1140 solids[cnt] = ns.
solid(c.attr<
string>(_U(name)));
1143 solidName[0] = e.attr<
string>(
DD_CMU(firstSolid));
1146 solidName[1] = e.attr<
string>(
DD_CMU(secondSolid));
1151 except(
"DD4CMS",
"+++ Failed to create boolean solid %s. Found only %d parts.", nam.c_str(), cnt);
1158 "+++ BooleanSolid: %s Left: %-32s Right: %-32s",
1160 ((solids[0].ptr() ==
nullptr) ? solidName[0].c_str() : solids[0]->GetName()),
1161 ((solids[1].ptr() ==
nullptr) ? solidName[1].c_str() : solids[1]->GetName()));
1168 boolean =
TYPE(solids[0], solids[1], trafo);
1175 if (solids[0].
isValid() ==
false) {
1176 printout(
ERROR,
"DD4CMS",
"++ Solid not defined yet: %s", solidName[0].c_str());
1178 if (solids[1].
isValid() ==
false) {
1179 printout(
ERROR,
"DD4CMS",
"++ Solid not defined yet: %s", solidName[1].c_str());
1181 printout(
ERROR,
"DD4CMS",
"++ Re-order XML files to prevent references to undefined solids");
1192 void Converter<DDLUnionSolid>::operator()(xml_h element)
const {
1193 convert_boolean<UnionSolid>(_param<cms::DDParsingContext>(), element);
1198 void Converter<DDLSubtractionSolid>::operator()(xml_h element)
const {
1199 convert_boolean<SubtractionSolid>(_param<cms::DDParsingContext>(), element);
1204 void Converter<DDLIntersectionSolid>::operator()(xml_h element)
const {
1205 convert_boolean<IntersectionSolid>(_param<cms::DDParsingContext>(), element);
1210 void Converter<DDLPolycone>::operator()(xml_h element)
const {
1212 xml_dim_t
e(element);
1213 string nam = e.nameStr();
1214 double startPhi = ns.attr<
double>(
e,
DD_CMU(startPhi));
1216 vector<double>
z, rmin, rmax,
r;
1218 for (xml_coll_t rzpoint(element,
DD_CMU(RZPoint)); rzpoint; ++rzpoint) {
1219 z.emplace_back(ns.attr<
double>(rzpoint, _U(z)));
1220 r.emplace_back(ns.attr<
double>(rzpoint, _U(r)));
1223 for (xml_coll_t zplane(element,
DD_CMU(ZSection)); zplane; ++zplane) {
1224 rmin.emplace_back(ns.attr<
double>(zplane,
DD_CMU(rMin)));
1225 rmax.emplace_back(ns.attr<
double>(zplane,
DD_CMU(rMax)));
1226 z.emplace_back(ns.attr<
double>(zplane, _U(z)));
1231 printout(ns.context()->debug_shapes ? ALWAYS :
DEBUG,
1233 "+ Polycone: startPhi=%10.3f [rad] deltaPhi=%10.3f [rad] %4ld z-planes",
1240 ns.addSolid(nam, Polycone(startPhi, deltaPhi, rmin, rmax, z));
1244 printout(ns.context()->debug_shapes ? ALWAYS :
DEBUG,
1246 "+ Polycone: startPhi=%10.3f [rad] deltaPhi=%10.3f [rad] %4ld z-planes and %4ld radii",
1254 ns.addSolid(nam, Polycone(startPhi, deltaPhi, r, z));
1260 void Converter<DDLExtrudedPolygon>::operator()(xml_h element)
const {
1262 xml_dim_t
e(element);
1263 string nam = e.nameStr();
1264 vector<double> pt_x, pt_y, sec_x, sec_y, sec_z, sec_scale;
1266 for (xml_coll_t sec(element,
DD_CMU(ZXYSection)); sec; ++sec) {
1267 sec_z.emplace_back(ns.attr<
double>(sec, _U(z)));
1268 sec_x.emplace_back(ns.attr<
double>(sec, _U(x)));
1269 sec_y.emplace_back(ns.attr<
double>(sec, _U(y)));
1270 sec_scale.emplace_back(ns.attr<
double>(sec,
DD_CMU(
scale), 1.0));
1272 for (xml_coll_t
pt(element,
DD_CMU(XYPoint));
pt; ++
pt) {
1273 pt_x.emplace_back(ns.attr<
double>(
pt, _U(x)));
1274 pt_y.emplace_back(ns.attr<
double>(
pt, _U(y)));
1279 printout(ns.context()->debug_shapes ? ALWAYS :
DEBUG,
1281 "+ ExtrudedPolygon: %4ld points %4ld zxy sections",
1287 ns.addSolid(nam,
ExtrudedPolygon(pt_x, pt_y, sec_z, sec_x, sec_y, sec_scale));
1292 void Converter<DDLPolyhedra>::operator()(xml_h element)
const {
1294 xml_dim_t
e(element);
1295 string nam = e.nameStr();
1296 double numSide = ns.attr<
int>(
e,
DD_CMU(numSide));
1297 double startPhi = ns.attr<
double>(
e,
DD_CMU(startPhi));
1298 double deltaPhi = ns.attr<
double>(
e,
DD_CMU(deltaPhi));
1299 vector<double>
z, rmin, rmax;
1301 for (xml_coll_t zplane(element,
DD_CMU(RZPoint)); zplane; ++zplane) {
1302 rmin.emplace_back(0.0);
1303 rmax.emplace_back(ns.attr<
double>(zplane, _U(r)));
1304 z.emplace_back(ns.attr<
double>(zplane, _U(z)));
1306 for (xml_coll_t zplane(element,
DD_CMU(ZSection)); zplane; ++zplane) {
1307 rmin.emplace_back(ns.attr<
double>(zplane,
DD_CMU(rMin)));
1308 rmax.emplace_back(ns.attr<
double>(zplane,
DD_CMU(rMax)));
1309 z.emplace_back(ns.attr<
double>(zplane, _U(z)));
1314 printout(ns.context()->debug_shapes ? ALWAYS :
DEBUG,
1316 "+ Polyhedra:startPhi=%8.3f [rad] deltaPhi=%8.3f [rad] %4d sides %4ld z-planes",
1324 ns.addSolid(nam,
Polyhedra(numSide, startPhi, deltaPhi, z, rmin, rmax));
1329 void Converter<DDLSphere>::operator()(xml_h element)
const {
1331 xml_dim_t
e(element);
1332 string nam = e.nameStr();
1333 double rinner = ns.attr<
double>(
e,
DD_CMU(innerRadius));
1334 double router = ns.attr<
double>(
e,
DD_CMU(outerRadius));
1335 double startPhi = ns.attr<
double>(
e,
DD_CMU(startPhi));
1336 double deltaPhi = ns.attr<
double>(
e,
DD_CMU(deltaPhi));
1337 double startTheta = ns.attr<
double>(
e,
DD_CMU(startTheta));
1338 double deltaTheta = ns.attr<
double>(
e,
DD_CMU(deltaTheta));
1342 printout(ns.context()->debug_shapes ? ALWAYS :
DEBUG,
1344 "+ Sphere: r_inner=%8.3f [cm] r_outer=%8.3f [cm]"
1345 " startPhi=%8.3f [rad] deltaPhi=%8.3f startTheta=%8.3f delteTheta=%8.3f [rad]",
1346 rinner / dd4hep::cm,
1347 router / dd4hep::cm,
1355 ns.addSolid(nam, Sphere(rinner, router, startTheta, deltaTheta, startPhi, deltaPhi));
1360 void Converter<DDLTorus>::operator()(xml_h element)
const {
1362 xml_dim_t
e(element);
1363 string nam = e.nameStr();
1364 double r = ns.attr<
double>(
e,
DD_CMU(torusRadius));
1365 double rinner = ns.attr<
double>(
e,
DD_CMU(innerRadius));
1366 double router = ns.attr<
double>(
e,
DD_CMU(outerRadius));
1367 double startPhi = ns.attr<
double>(
e,
DD_CMU(startPhi));
1368 double deltaPhi = ns.attr<
double>(
e,
DD_CMU(deltaPhi));
1372 printout(ns.context()->debug_shapes ? ALWAYS :
DEBUG,
1374 "+ Torus: r=%10.3f [cm] r_inner=%10.3f [cm] r_outer=%10.3f [cm]"
1375 " startPhi=%10.3f [rad] deltaPhi=%10.3f [rad]",
1377 rinner / dd4hep::cm,
1378 router / dd4hep::cm,
1384 ns.addSolid(nam, Torus(r, rinner, router, startPhi, deltaPhi));
1389 void Converter<DDLPseudoTrap>::operator()(xml_h element)
const {
1391 xml_dim_t
e(element);
1392 string nam = e.nameStr();
1393 double dx1 = ns.attr<
double>(
e,
DD_CMU(dx1));
1394 double dy1 = ns.attr<
double>(
e,
DD_CMU(dy1));
1395 double dx2 = ns.attr<
double>(
e,
DD_CMU(dx2));
1396 double dy2 = ns.attr<
double>(
e,
DD_CMU(dy2));
1397 double dz = ns.attr<
double>(
e, _U(dz));
1398 double r = ns.attr<
double>(
e, _U(
radius));
1399 bool atMinusZ = ns.attr<
bool>(
e,
DD_CMU(atMinusZ));
1403 printout(ns.context()->debug_shapes ? ALWAYS :
DEBUG,
1405 "+ Pseudotrap: dz=%8.3f [cm] dx1:%.3f dy1:%.3f dx2=%.3f dy2=%.3f radius:%.3f atMinusZ:%s",
1416 ns.addSolid(nam, PseudoTrap(dx1, dx2, dy1, dy2, dz, r, atMinusZ));
1421 void Converter<DDLTrapezoid>::operator()(xml_h element)
const {
1423 xml_dim_t
e(element);
1424 string nam = e.nameStr();
1425 double dz = ns.attr<
double>(
e, _U(dz));
1426 double alp1 = ns.attr<
double>(
e,
DD_CMU(alp1));
1427 double bl1 = ns.attr<
double>(
e,
DD_CMU(bl1));
1428 double tl1 = ns.attr<
double>(
e,
DD_CMU(tl1));
1429 double h1 = ns.attr<
double>(
e,
DD_CMU(h1));
1430 double alp2 = ns.attr<
double>(
e,
DD_CMU(alp2));
1431 double bl2 = ns.attr<
double>(
e,
DD_CMU(bl2));
1432 double tl2 = ns.attr<
double>(
e,
DD_CMU(tl2));
1433 double h2 = ns.attr<
double>(
e,
DD_CMU(h2));
1434 double phi = ns.attr<
double>(
e, _U(phi), 0.0);
1435 double theta = ns.attr<
double>(
e, _U(theta), 0.0);
1439 printout(ns.context()->debug_shapes ? ALWAYS :
DEBUG,
1441 "+ Trapezoid: dz=%10.3f [cm] alp1:%.3f bl1=%.3f tl1=%.3f alp2=%.3f bl2=%.3f tl2=%.3f h2=%.3f phi=%.3f "
1457 ns.addSolid(nam, Trap(dz,
theta, phi, h1, bl1, tl1, alp1, h2, bl2, tl2, alp2));
1462 void Converter<DDLTrd1>::operator()(xml_h element)
const {
1464 xml_dim_t
e(element);
1465 string nam = e.nameStr();
1466 double dx1 = ns.attr<
double>(
e,
DD_CMU(dx1));
1467 double dy1 = ns.attr<
double>(
e,
DD_CMU(dy1));
1468 double dx2 = ns.attr<
double>(
e,
DD_CMU(dx2), 0.0);
1469 double dy2 = ns.attr<
double>(
e,
DD_CMU(dy2), dy1);
1470 double dz = ns.attr<
double>(
e,
DD_CMU(dz));
1474 printout(ns.context()->debug_shapes ? ALWAYS :
DEBUG,
1476 "+ Trd1: dz=%8.3f [cm] dx1:%.3f dy1:%.3f dx2:%.3f dy2:%.3f",
1485 ns.addSolid(nam, Trd1(dx1, dx2, dy1, dz));
1489 printout(ns.context()->debug_shapes ? ALWAYS :
DEBUG,
1491 "+ Trd1(which is actually Trd2): dz=%8.3f [cm] dx1:%.3f dy1:%.3f dx2:%.3f dy2:%.3f",
1500 ns.addSolid(nam, Trd2(dx1, dx2, dy1, dy2, dz));
1506 void Converter<DDLTrd2>::operator()(xml_h element)
const {
1508 xml_dim_t
e(element);
1509 string nam = e.nameStr();
1510 double dx1 = ns.attr<
double>(
e,
DD_CMU(dx1));
1511 double dy1 = ns.attr<
double>(
e,
DD_CMU(dy1));
1512 double dx2 = ns.attr<
double>(
e,
DD_CMU(dx2), 0.0);
1513 double dy2 = ns.attr<
double>(
e,
DD_CMU(dy2), dy1);
1514 double dz = ns.attr<
double>(
e,
DD_CMU(dz));
1518 printout(ns.context()->debug_shapes ? ALWAYS :
DEBUG,
1520 "+ Trd1: dz=%8.3f [cm] dx1:%.3f dy1:%.3f dx2:%.3f dy2:%.3f",
1529 ns.addSolid(nam, Trd2(dx1, dx2, dy1, dy2, dz));
1534 void Converter<DDLTubs>::operator()(xml_h element)
const {
1536 xml_dim_t
e(element);
1537 string nam = e.nameStr();
1538 double dz = ns.attr<
double>(
e,
DD_CMU(dz));
1539 double rmin = ns.attr<
double>(
e,
DD_CMU(rMin));
1540 double rmax = ns.attr<
double>(
e,
DD_CMU(rMax));
1541 double startPhi = ns.attr<
double>(
e,
DD_CMU(startPhi), 0.0);
1542 double deltaPhi = ns.attr<
double>(
e,
DD_CMU(deltaPhi), 2 *
M_PI);
1546 printout(ns.context()->debug_shapes ? ALWAYS :
DEBUG,
1548 "+ Tubs: dz=%8.3f [cm] rmin=%8.3f [cm] rmax=%8.3f [cm]"
1549 " startPhi=%8.3f [rad] deltaPhi=%8.3f [rad]",
1558 ns.addSolid(nam, Tube(rmin, rmax, dz, startPhi, startPhi + deltaPhi));
1563 void Converter<DDLCutTubs>::operator()(xml_h element)
const {
1565 xml_dim_t
e(element);
1566 string nam = e.nameStr();
1567 double dz = ns.attr<
double>(
e,
DD_CMU(dz));
1568 double rmin = ns.attr<
double>(
e,
DD_CMU(rMin));
1569 double rmax = ns.attr<
double>(
e,
DD_CMU(rMax));
1570 double startPhi = ns.attr<
double>(
e,
DD_CMU(startPhi));
1571 double deltaPhi = ns.attr<
double>(
e,
DD_CMU(deltaPhi));
1572 double lx = ns.attr<
double>(
e,
DD_CMU(lx));
1573 double ly = ns.attr<
double>(
e,
DD_CMU(ly));
1574 double lz = ns.attr<
double>(
e,
DD_CMU(lz));
1575 double tx = ns.attr<
double>(
e,
DD_CMU(tx));
1576 double ty = ns.attr<
double>(
e,
DD_CMU(ty));
1577 double tz = ns.attr<
double>(
e,
DD_CMU(tz));
1581 printout(ns.context()->debug_shapes ? ALWAYS :
DEBUG,
1583 "+ CutTube: dz=%8.3f [cm] rmin=%8.3f [cm] rmax=%8.3f [cm]"
1584 " startPhi=%8.3f [rad] deltaPhi=%8.3f [rad]...",
1593 ns.addSolid(nam, CutTube(rmin, rmax, dz, startPhi, startPhi + deltaPhi, lx, ly, lz, tx, ty, tz));
1598 void Converter<DDLTruncTubs>::operator()(xml_h element)
const {
1600 xml_dim_t
e(element);
1601 string nam = e.nameStr();
1602 double zhalf = ns.attr<
double>(
e,
DD_CMU(zHalf));
1603 double rmin = ns.attr<
double>(
e,
DD_CMU(rMin));
1604 double rmax = ns.attr<
double>(
e,
DD_CMU(rMax));
1605 double startPhi = ns.attr<
double>(
e,
DD_CMU(startPhi));
1606 double deltaPhi = ns.attr<
double>(
e,
DD_CMU(deltaPhi));
1607 double cutAtStart = ns.attr<
double>(
e,
DD_CMU(cutAtStart));
1608 double cutAtDelta = ns.attr<
double>(
e,
DD_CMU(cutAtDelta));
1609 bool cutInside = ns.attr<
bool>(
e,
DD_CMU(cutInside));
1613 printout(ns.context()->debug_shapes ? ALWAYS :
DEBUG,
1615 "+ TruncTube:zHalf=%8.3f [cm] rmin=%8.3f [cm] rmax=%8.3f [cm]"
1616 " startPhi=%8.3f [rad] deltaPhi=%8.3f [rad] atStart=%8.3f [cm] atDelta=%8.3f [cm] inside:%s",
1622 cutAtStart / dd4hep::cm,
1623 cutAtDelta / dd4hep::cm,
1628 ns.addSolid(nam, TruncatedTube(zhalf, rmin, rmax, startPhi, deltaPhi, cutAtStart, cutAtDelta, cutInside));
1633 void Converter<DDLEllipticalTube>::operator()(xml_h element)
const {
1635 xml_dim_t
e(element);
1636 string nam = e.nameStr();
1637 double dx = ns.attr<
double>(
e,
DD_CMU(xSemiAxis));
1638 double dy = ns.attr<
double>(
e,
DD_CMU(ySemiAxis));
1639 double dz = ns.attr<
double>(
e,
DD_CMU(zHeight));
1643 printout(ns.context()->debug_shapes ? ALWAYS :
DEBUG,
1645 "+ EllipticalTube xSemiAxis=%8.3f [cm] ySemiAxis=%8.3f [cm] zHeight=%8.3f [cm]",
1652 ns.addSolid(nam, EllipticalTube(dx, dy, dz));
1657 void Converter<DDLCone>::operator()(xml_h element)
const {
1659 xml_dim_t
e(element);
1660 string nam = e.nameStr();
1661 double dz = ns.attr<
double>(
e,
DD_CMU(dz));
1662 double rmin1 = ns.attr<
double>(
e,
DD_CMU(rMin1));
1663 double rmin2 = ns.attr<
double>(
e,
DD_CMU(rMin2));
1664 double rmax1 = ns.attr<
double>(
e,
DD_CMU(rMax1));
1665 double rmax2 = ns.attr<
double>(
e,
DD_CMU(rMax2));
1666 double startPhi = ns.attr<
double>(
e,
DD_CMU(startPhi));
1667 double deltaPhi = ns.attr<
double>(
e,
DD_CMU(deltaPhi));
1672 printout(ns.context()->debug_shapes ? ALWAYS :
DEBUG,
1674 "+ Cone: dz=%8.3f [cm]"
1675 " rmin1=%8.3f [cm] rmax1=%8.3f [cm]"
1676 " rmin2=%8.3f [cm] rmax2=%8.3f [cm]"
1677 " startPhi=%8.3f [rad] deltaPhi=%8.3f [rad]",
1688 ns.addSolid(nam, ConeSegment(dz, rmin1, rmax1, rmin2, rmax2, startPhi, phi2));
1693 void Converter<DDLShapeless>::operator()(xml_h element)
const {
1695 xml_dim_t
e(element);
1696 string nam = e.nameStr();
1700 printout(ns.context()->debug_shapes ? ALWAYS :
DEBUG,
1702 "+ Shapeless: THIS ONE CAN ONLY BE USED AT THE VOLUME LEVEL -> Shapeless: %s",
1707 ns.addSolid(nam, Box(1, 1, 1));
1712 void Converter<DDLAssembly>::operator()(xml_h element)
const {
1714 xml_dim_t
e(element);
1715 string nam = e.nameStr();
1719 ns.context()->debug_shapes ? ALWAYS :
DEBUG,
"DD4CMS",
"+ Assembly: Adding solid -> Assembly: %s", nam.c_str());
1722 ns.addAssemblySolid(nam);
1727 void Converter<DDLBox>::operator()(xml_h element)
const {
1729 xml_dim_t
e(element);
1730 string nam = e.nameStr();
1731 double dx = ns.attr<
double>(
e,
DD_CMU(dx));
1732 double dy = ns.attr<
double>(
e,
DD_CMU(dy));
1733 double dz = ns.attr<
double>(
e,
DD_CMU(dz));
1737 printout(ns.context()->debug_shapes ? ALWAYS :
DEBUG,
1739 "+ Box: dx=%10.3f [cm] dy=%10.3f [cm] dz=%10.3f [cm]",
1746 ns.addSolid(nam, Box(dx, dy, dz));
1751 void Converter<include_load>::operator()(xml_h element)
const {
1752 string fname = element.attr<
string>(_U(ref));
1755 doc = xml::DocumentHandler().load(
fp.fullPath());
1759 printout(_param<cms::DDParsingContext>()->debug_includes ? ALWAYS : DEBUG,
1761 "+++ Processing the CMS detector description %s",
1766 _option<DDRegistry>()->
includes.emplace_back(doc);
1771 void Converter<include_unload>::operator()(xml_h element)
const {
1772 string fname = xml::DocumentHandler::system_path(element);
1773 xml::DocumentHolder(xml_elt_t(element).document()).assign(
nullptr);
1777 printout(_param<cms::DDParsingContext>()->debug_includes ? ALWAYS : DEBUG,
1779 "+++ Finished processing %s",
1786 void Converter<include_constants>::operator()(xml_h element)
const {
1787 xml_coll_t(element,
DD_CMU(ConstantsSection)).for_each(Converter<ConstantsSection>(description, param,
optional));
1799 const std::map<std::string, DDAxes> axesmap{{
"x",
DDAxes::x},
1809 void Converter<DDLDivision>::operator()(xml_h element)
const {
1811 xml_dim_t
e(element);
1812 string childName = e.nameStr();
1814 childName = ns.prepend(childName);
1816 string parentName = ns.attr<
string>(
e,
DD_CMU(parent));
1818 parentName = ns.prepend(parentName);
1819 string axis = ns.attr<
string>(
e,
DD_CMU(axis));
1824 double width = e.hasAttr(
DD_CMU(width)) ? ns.attr<
double>(
e,
DD_CMU(width)) : 0e0;
1825 int nReplicas = e.hasAttr(
DD_CMU(nReplicas)) ? ns.attr<
int>(
e,
DD_CMU(nReplicas)) : 0;
1829 printout(ns.context()->debug_placements ? ALWAYS :
DEBUG,
1831 "+++ Start executing Division of %s along %s (%d) with offset %6.3f and %6.3f to produce %s....",
1841 Volume parent = ns.volume(parentName);
1843 const TGeoShape* shape = parent.solid();
1844 TClass*
cl = shape->IsA();
1845 if (cl == TGeoTubeSeg::Class()) {
1846 const TGeoTubeSeg* sh = (
const TGeoTubeSeg*)shape;
1849 int numCopies = (int)((sh->GetPhi2() - sh->GetPhi1()) / widthInDeg);
1853 printout(ns.context()->debug_placements ? ALWAYS :
DEBUG,
1855 "+++ ...divide %s along %s (%d) with offset %6.3f deg and %6.3f deg to produce %d copies",
1856 parent.solid().type(),
1865 Volume child = parent.divide(childName, static_cast<int>(axesmap.at(axis)), numCopies, startInDeg, widthInDeg);
1867 ns.context()->volumes[childName] =
child;
1871 printout(ns.context()->debug_placements ? ALWAYS :
DEBUG,
1873 "+++ %s Parent: %-24s [%s] Child: %-32s [%s] is multivolume [%s]",
1876 parent.isValid() ?
"VALID" :
"INVALID",
1878 child.isValid() ?
"VALID" :
"INVALID",
1879 child->IsVolumeMulti() ?
"YES" :
"NO");
1882 }
else if (cl == TGeoTrd1::Class()) {
1883 double dy =
static_cast<const TGeoTrd1*
>(shape)->GetDy();
1887 printout(ns.context()->debug_placements ? ALWAYS :
DEBUG,
1889 "+++ ...divide %s along %s (%d) with offset %6.3f cm and %6.3f cm to produce %d copies in %6.3f",
1890 parent.solid().type(),
1893 -dy + offset + width,
1900 Volume child = parent.divide(childName, static_cast<int>(axesmap.at(axis)), nReplicas, -dy + offset + width, width);
1902 ns.context()->volumes[childName] =
child;
1906 printout(ns.context()->debug_placements ? ALWAYS :
DEBUG,
1908 "+++ %s Parent: %-24s [%s] Child: %-32s [%s] is multivolume [%s]",
1911 parent.isValid() ?
"VALID" :
"INVALID",
1913 child.isValid() ?
"VALID" :
"INVALID",
1914 child->IsVolumeMulti() ?
"YES" :
"NO");
1918 printout(
ERROR,
"DD4CMS",
"++ FAILED Division of a %s is not implemented yet!", parent.solid().type());
1924 void Converter<DDLAlgorithm>::operator()(xml_h element)
const {
1926 xml_dim_t
e(element);
1927 string name = e.nameStr();
1929 string type =
"DDCMS_" + ns.realName(name);
1936 ns.context()->debug_algorithms ? ALWAYS :
DEBUG,
"DD4CMS",
"+++ Start executing algorithm %s....", type.c_str());
1944 printout(ns.context()->debug_algorithms ? ALWAYS :
DEBUG,
1947 "+++ Executed algorithm: %08lX = %s",
1954 printout(
ERROR,
"DD4CMS",
"++ FAILED NOT ADDING SUBDETECTOR %08lX = %s", ret, name.c_str());
1957 template <
class InputIt,
class ForwardIt,
class BinOp>
1959 while (first != last) {
1960 const auto pos = std::find_first_of(first, last, s_first, s_last);
1961 binary_op(first, pos);
1970 std::vector<string>
splitString(
const string&
str,
const string& delims =
",") {
1971 std::vector<string>
output;
1985 std::vector<double> splitNumeric(
const string& str,
const string& delims =
",") {
1986 std::vector<double>
output;
1994 output.emplace_back(dd4hep::_toDouble(
string(
first,
second)));
2004 void Converter<DDLVector>::operator()(xml_h element)
const {
2008 xml_dim_t
e(element);
2009 string name = ns.prepend(e.nameStr());
2010 string type = ns.attr<
string>(
e, _U(type));
2011 string nEntries = ns.attr<
string>(
e,
DD_CMU(nEntries));
2012 string val = e.text();
2013 val.erase(remove_if(val.begin(), val.end(), [](
unsigned char x) {
return isspace(x); }), val.end());
2017 printout(ns.context()->debug_constants ? ALWAYS :
DEBUG,
2019 "+++ Vector<%s>: %s[%s]: %s",
2028 std::vector<double>
results = splitNumeric(val);
2037 "++ Unresolved Vector<%s>: %s[%s]: %s. Try to resolve later. [%s]",
2052 void Converter<debug>::operator()(xml_h dbg)
const {
2054 if (dbg.hasChild(
DD_CMU(debug_constants)))
2055 ns.setContext()->debug_constants =
true;
2056 if (dbg.hasChild(
DD_CMU(debug_materials)))
2057 ns.setContext()->debug_materials =
true;
2058 if (dbg.hasChild(
DD_CMU(debug_rotations)))
2059 ns.setContext()->debug_rotations =
true;
2060 if (dbg.hasChild(
DD_CMU(debug_shapes)))
2061 ns.setContext()->debug_shapes =
true;
2062 if (dbg.hasChild(
DD_CMU(debug_volumes)))
2063 ns.setContext()->debug_volumes =
true;
2064 if (dbg.hasChild(
DD_CMU(debug_placements)))
2065 ns.setContext()->debug_placements =
true;
2066 if (dbg.hasChild(
DD_CMU(debug_namespaces)))
2067 ns.setContext()->debug_namespaces =
true;
2068 if (dbg.hasChild(
DD_CMU(debug_includes)))
2069 ns.setContext()->debug_includes =
true;
2070 if (dbg.hasChild(
DD_CMU(debug_algorithms)))
2071 ns.setContext()->debug_algorithms =
true;
2072 if (dbg.hasChild(
DD_CMU(debug_specpars)))
2073 ns.setContext()->debug_specpars =
true;
2077 void Converter<DDRegistry>::operator()(xml_h )
const {
2079 DDRegistry* res = _option<DDRegistry>();
2087 "+++ RESOLVING %ld unknown constants..... (out of %ld)",
2088 res->unresolvedConst.size(),
2089 res->originalConst.size());
2092 while (!res->unresolvedConst.empty()) {
2093 for (
auto&
i : res->unresolvedConst) {
2094 const string& n =
i.first;
2096 string& v =
i.second;
2098 for (idx = v.find(
'[', 0); idx != string::npos; idx = v.find(
'[', idx + 1)) {
2099 idq = v.find(
']', idx + 1);
2100 rep = v.substr(idx + 1, idq - idx - 1);
2101 auto r = res->originalConst.find(rep);
2102 if (r != res->originalConst.end()) {
2103 rep =
"(" + (*r).second +
")";
2104 v.replace(idx, idq - idx + 1, rep);
2107 if (v.find(
']') == string::npos) {
2108 if (v.find(
"-+") != string::npos || v.find(
"+-") != string::npos) {
2109 while ((idx = v.find(
"-+")) != string::npos)
2110 v.replace(idx, 2,
"-");
2111 while ((idx = v.find(
"+-")) != string::npos)
2112 v.replace(idx, 2,
"-");
2119 "+++ [%06ld] ---------- %-40s = %s",
2120 res->unresolvedConst.size() - 1,
2122 res->originalConst[
n].c_str());
2126 ns.addConstantNS(n, v,
"number");
2127 res->unresolvedConst.erase(n);
2131 if (++count > 10000)
2134 if (!res->unresolvedConst.empty()) {
2135 for (
const auto& e : res->unresolvedConst)
2136 printout(
ERROR,
"DD4CMS",
"+++ Unresolved constant: %-40s = %s.", e.first.c_str(), e.second.c_str());
2137 except(
"DD4CMS",
"++ FAILED to resolve %ld constant entries:", res->unresolvedConst.size());
2139 res->unresolvedConst.clear();
2140 res->originalConst.clear();
2144 void Converter<print_xml_doc>::operator()(xml_h element)
const {
2145 string fname = xml::DocumentHandler::system_path(element);
2149 printout(_param<cms::DDParsingContext>()->debug_includes ? ALWAYS : DEBUG,
2151 "+++ Processing data from: %s",
2159 xml_elt_t dddef(element);
2163 ns.addConstantNS(
"world_x",
"101*m",
"number");
2164 ns.addConstantNS(
"world_y",
"101*m",
"number");
2165 ns.addConstantNS(
"world_z",
"450*m",
"number");
2166 ns.addConstantNS(
"Air",
"materials:Air",
"string");
2167 ns.addConstantNS(
"Vacuum",
"materials:Vacuum",
"string");
2169 string fname = xml::DocumentHandler::system_path(element);
2170 bool open_geometry = dddef.hasChild(
DD_CMU(open_geometry)) ? dddef.child(
DD_CMU(open_geometry)) :
true;
2171 bool close_geometry = dddef.hasChild(
DD_CMU(close_geometry)) ? dddef.hasChild(
DD_CMU(close_geometry)) :
true;
2173 xml_coll_t(dddef, _U(
debug)).for_each(Converter<debug>(det, &context));
2178 printout(
INFO,
"DD4CMS",
"+++ Processing the CMS detector description %s", fname.c_str());
2181 Converter<print_xml_doc> print_doc(det, &context);
2184 res.unresolvedConst.reserve(2000);
2185 res.originalConst.reserve(6000);
2186 print_doc((doc = dddef.document()).root());
2187 xml_coll_t(dddef,
DD_CMU(ConstantsSection)).for_each(Converter<ConstantsSection>(det, &context, &res));
2188 xml_coll_t(dddef,
DD_CMU(RotationSection)).for_each(Converter<RotationSection>(det, &context));
2189 xml_coll_t(dddef,
DD_CMU(MaterialSection)).for_each(Converter<MaterialSection>(det, &context));
2191 xml_coll_t(dddef,
DD_CMU(IncludeSection)).for_each(
DD_CMU(Include), Converter<include_load>(det, &context, &res));
2193 for (xml::Document
d : res.includes) {
2194 print_doc((doc = d).root());
2195 Converter<include_constants>(det, &
context, &res)((doc = d).root());
2198 Converter<DDRegistry>(det, &
context, &res)(dddef);
2202 printout(context.debug_constants ? ALWAYS : DEBUG,
2204 "+++ RESOLVING %ld Vectors.....",
2205 context.unresolvedVectors.size());
2207 while (!context.unresolvedVectors.empty()) {
2208 for (
auto it = context.unresolvedVectors.begin(); it != context.unresolvedVectors.end();) {
2209 std::vector<double>
result;
2210 for (
const auto&
i : it->second) {
2211 result.emplace_back(dd4hep::_toDouble(
i));
2213 registry->insert({it->first, result});
2215 it = context.unresolvedVectors.erase(it);
2220 for (xml::Document d : res.includes) {
2221 print_doc((doc = d).root());
2222 xml_coll_t(d.root(),
DD_CMU(MaterialSection)).for_each(Converter<MaterialSection>(det, &context));
2224 if (open_geometry) {
2226 ns.addVolume(det.worldVolume());
2228 for (xml::Document d : res.includes) {
2229 print_doc((doc = d).root());
2230 xml_coll_t(d.root(),
DD_CMU(RotationSection)).for_each(Converter<RotationSection>(det, &context));
2232 for (xml::Document d : res.includes) {
2233 print_doc((doc = d).root());
2234 xml_coll_t(d.root(),
DD_CMU(SolidSection)).for_each(Converter<SolidSection>(det, &context));
2236 for (xml::Document d : res.includes) {
2237 print_doc((doc = d).root());
2238 xml_coll_t(d.root(),
DD_CMU(LogicalPartSection)).for_each(Converter<LogicalPartSection>(det, &context));
2240 for (xml::Document d : res.includes) {
2241 print_doc((doc = d).root());
2242 xml_coll_t(d.root(),
DD_CMU(
Algorithm)).for_each(Converter<DDLAlgorithm>(det, &context));
2244 for (xml::Document d : res.includes) {
2245 print_doc((doc = d).root());
2246 xml_coll_t(d.root(),
DD_CMU(PosPartSection)).for_each(Converter<PosPartSection>(det, &context));
2248 for (xml::Document d : res.includes) {
2249 print_doc((doc = d).root());
2250 xml_coll_t(d.root(),
DD_CMU(SpecParSection)).for_each(Converter<SpecParSection>(det, &context));
2254 for (xml::Document d : res.includes)
2255 Converter<include_unload>(det, &
context, &res)(d.root());
2257 print_doc((doc = dddef.document()).root());
2259 xml_coll_t(dddef,
DD_CMU(SolidSection)).for_each(Converter<SolidSection>(det, &context));
2266 while (!context.unresolvedShapes.empty()) {
2267 for (
auto it = context.unresolvedShapes.begin(); it != context.unresolvedShapes.end();) {
2268 auto const& name = it->first;
2269 auto const& aname = std::visit([](
auto&&
arg) ->
std::string {
return arg.firstSolidName; }, it->second);
2270 auto const& bname = std::visit([](
auto&&
arg) ->
std::string {
return arg.secondSolidName; }, it->second);
2272 auto const& ait = context.shapes.find(aname);
2273 if (ait->second.isValid()) {
2274 auto const& bit = context.shapes.find(bname);
2275 if (bit->second.isValid()) {
2276 dd4hep::Solid shape =
2277 std::visit([&ait, &bit](
auto&&
arg) -> dd4hep::Solid {
return arg.make(ait->second, bit->second); },
2279 context.shapes[
name] = shape;
2280 it = context.unresolvedShapes.erase(it);
2288 xml_coll_t(dddef,
DD_CMU(LogicalPartSection)).for_each(Converter<LogicalPartSection>(det, &context));
2289 xml_coll_t(dddef,
DD_CMU(
Algorithm)).for_each(Converter<DDLAlgorithm>(det, &context));
2290 xml_coll_t(dddef,
DD_CMU(PosPartSection)).for_each(Converter<PosPartSection>(det, &context));
2291 xml_coll_t(dddef,
DD_CMU(SpecParSection)).for_each(Converter<SpecParSection>(det, &context));
2293 printout(
ERROR,
"DD4CMS",
"Exception while processing xml source:%s", doc.uri().c_str());
2294 printout(
ERROR,
"DD4CMS",
"----> %s", e.what());
2299 if (close_geometry) {
2301 Volume geomv = ns.volume(
"cms:OCMS",
false);
2302 if (geomv.isValid())
2303 wv.placeVolume(geomv, 1);
2304 Volume mfv = ns.volume(
"cmsMagneticField:MAGF",
false);
2306 wv.placeVolume(mfv, 1);
2307 Volume mfv1 = ns.volume(
"MagneticFieldVolumes:MAGF",
false);
2309 wv.placeVolume(mfv1, 1);
2312 det.manager().CloseGeometry();
2316 printout(
INFO,
"DDDefinition",
"+++ Finished processing %s", fname.c_str());
2319 except(
"DDDefinition",
"+++ FAILED to process unknown DOM tree [Invalid Handle]");
DDLPosPart handles PosPart elements.
std::unordered_map< std::string, std::vector< double >> DDVectorsMap
tuple ret
prodAgent to be discontinued
DDLSphere processes all Sphere elements.
const edm::EventSetup & c
DDLDivision processes Division elements.
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
DDLVector handles Rotation and ReflectionRotation elements.
constexpr NumType convertRadToDeg(NumType radians)
Geom::Theta< T > theta() const
DDLSpecPar processes SpecPar elements.
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
DDLAlgorithm processes Algorithm elements.
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
DDRotationMatrix makeRotation3D(double thetaX, double phiX, double thetaY, double phiY, double thetaZ, double phiZ)
std::unordered_map< std::string, std::string > unresolvedConst
DDParsingContext *const context() const
static const std::string & rotName(const T &rot, const cms::DDParsingContext &context)
U second(std::pair< T, U > const &p)
DDLBox processes Box elements.
DDLElementaryMaterial processes ElementaryMaterial elements.
DDLAssembly processes Assembly elements.
static constexpr long s_executed
DDLCone processes all Cone elements.
dd4hep::PlacedVolume PlacedVolume
DDRotationMatrix makeRotReflect(double thetaX, double phiX, double thetaY, double phiY, double thetaZ, double phiZ)
Abs< T >::type abs(const T &t)
constexpr unsigned int hash(const char *str, int h=0)
std::unordered_map< std::string, dd4hep::Solid > shapes
static void convert_boolean(cms::DDParsingContext *context, xml_h element)
DDLTubs processes Tubs elements.
Basic2DVector< T > xy() const
dd4hep::Solid addSolid(const std::string &name, dd4hep::Solid solid) const
DDLLogicalPart processes LogicalPart elements.
SOARotation< float > Rotation
DDLRotationByAxis handles RotationByAxis elements.
DDLCompositeMaterial processes all CompositeMaterial elements.
std::vector< xml::Document > includes
static long load_dddefinition(Detector &det, xml_h element)
Converter for <DDDefinition> tags.
dd4hep::Detector & description
DDAxes
analagous to geant4/source/global/HEPGeometry/include/geomdefs.hh
std::unordered_map< std::string, std::string > originalConst
dd4hep::Assembly assembly(const std::string &name, bool exception=true) const
DDLRotationSequence handles a set of Rotations.
void for_each_token(InputIt first, InputIt last, ForwardIt s_first, ForwardIt s_last, BinOp binary_op)
ROOT::Math::DisplacementVector3D< ROOT::Math::Cartesian3D< double >> Translation
T angle(T x1, T y1, T z1, T x2, T y2, T z2)