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"
21 #include "TGeoManager.h"
22 #include "TGeoMaterial.h"
29 #include <unordered_map>
37 using namespace cms_units::operators;
43 atomic<UInt_t> unique_mat_id = 0xAFFEFEED;
45 class include_constants;
50 class ConstantsSection;
59 class MaterialSection;
63 class RotationSection;
65 class DDLReflectionRotation;
74 class LogicalPartSection;
78 class DDLExtrudedPolygon;
96 class DDLIntersectionSolid;
97 class DDLSubtractionSolid;
102 class SpecParSection;
112 iRot.GetComponents(elements);
114 r.SetMatrix(elements);
116 TGeoTranslation
t(iTrans.x(), iTrans.y(), iTrans.z());
118 return new TGeoCombiTrans(
t, r);
123 void Converter<debug>::operator()(xml_h element)
const;
125 void Converter<print_xml_doc>::operator()(xml_h element)
const;
129 void Converter<ConstantsSection>::operator()(xml_h element)
const;
131 void Converter<DDLConstant>::operator()(xml_h element)
const;
133 void Converter<DDRegistry>::operator()(xml_h element)
const;
137 void Converter<MaterialSection>::operator()(xml_h element)
const;
139 void Converter<DDLElementaryMaterial>::operator()(xml_h element)
const;
141 void Converter<DDLCompositeMaterial>::operator()(xml_h element)
const;
145 void Converter<RotationSection>::operator()(xml_h element)
const;
148 void Converter<DDLRotation>::operator()(xml_h element)
const;
151 void Converter<DDLReflectionRotation>::operator()(xml_h element)
const;
154 void Converter<DDLRotationSequence>::operator()(xml_h element)
const;
157 void Converter<DDLRotationByAxis>::operator()(xml_h element)
const;
159 void Converter<DDLTransform3D>::operator()(xml_h element)
const;
163 void Converter<LogicalPartSection>::operator()(xml_h element)
const;
165 void Converter<DDLLogicalPart>::operator()(xml_h element)
const;
169 void Converter<PosPartSection>::operator()(xml_h element)
const;
172 void Converter<DDLPosPart>::operator()(xml_h element)
const;
175 void Converter<DDLDivision>::operator()(xml_h element)
const;
179 void Converter<SpecParSection>::operator()(xml_h element)
const;
181 void Converter<DDLSpecPar>::operator()(xml_h element)
const;
183 void Converter<PartSelector>::operator()(xml_h element)
const;
185 void Converter<Parameter>::operator()(xml_h element)
const;
189 void Converter<SolidSection>::operator()(xml_h element)
const;
192 void Converter<DDLUnionSolid>::operator()(xml_h element)
const;
195 void Converter<DDLSubtractionSolid>::operator()(xml_h element)
const;
198 void Converter<DDLIntersectionSolid>::operator()(xml_h element)
const;
201 void Converter<DDLPseudoTrap>::operator()(xml_h element)
const;
204 void Converter<DDLExtrudedPolygon>::operator()(xml_h element)
const;
207 void Converter<DDLShapeless>::operator()(xml_h element)
const;
210 void Converter<DDLAssembly>::operator()(xml_h element)
const;
213 void Converter<DDLTrapezoid>::operator()(xml_h element)
const;
216 void Converter<DDLPolycone>::operator()(xml_h element)
const;
219 void Converter<DDLPolyhedra>::operator()(xml_h element)
const;
222 void Converter<DDLEllipticalTube>::operator()(xml_h element)
const;
225 void Converter<DDLTorus>::operator()(xml_h element)
const;
228 void Converter<DDLTubs>::operator()(xml_h element)
const;
231 void Converter<DDLCutTubs>::operator()(xml_h element)
const;
234 void Converter<DDLTruncTubs>::operator()(xml_h element)
const;
237 void Converter<DDLSphere>::operator()(xml_h element)
const;
240 void Converter<DDLTrd1>::operator()(xml_h element)
const;
243 void Converter<DDLTrd2>::operator()(xml_h element)
const;
246 void Converter<DDLCone>::operator()(xml_h element)
const;
249 void Converter<DDLBox>::operator()(xml_h element)
const;
252 void Converter<DDLAlgorithm>::operator()(xml_h element)
const;
255 void Converter<DDLVector>::operator()(xml_h element)
const;
259 void Converter<include_load>::operator()(xml_h element)
const;
262 void Converter<include_unload>::operator()(xml_h element)
const;
265 void Converter<include_constants>::operator()(xml_h element)
const;
270 void Converter<ConstantsSection>::operator()(xml_h element)
const {
279 void Converter<MaterialSection>::operator()(xml_h element)
const {
281 xml_coll_t(element,
DD_CMU(ElementaryMaterial))
283 xml_coll_t(element,
DD_CMU(CompositeMaterial))
288 void Converter<RotationSection>::operator()(xml_h element)
const {
291 xml_coll_t(element,
DD_CMU(ReflectionRotation))
293 xml_coll_t(element,
DD_CMU(RotationSequence))
295 xml_coll_t(element,
DD_CMU(RotationByAxis))
300 void Converter<PosPartSection>::operator()(xml_h element)
const {
308 void Converter<SpecParSection>::operator()(xml_h element)
const {
314 void Converter<DDLSpecPar>::operator()(xml_h element)
const {
322 void Converter<LogicalPartSection>::operator()(xml_h element)
const {
329 void Converter<SolidSection>::operator()(xml_h element)
const {
331 for (xml_coll_t solid(element, _U(star)); solid; ++solid) {
333 switch (
hash(solid.tag())) {
337 case hash(
"Polycone"):
340 case hash(
"Polyhedra"):
346 case hash(
"CutTubs"):
349 case hash(
"TruncTubs"):
367 case hash(
"EllipticalTube"):
373 case hash(
"PseudoTrap"):
376 case hash(
"ExtrudedPolygon"):
379 case hash(
"Trapezoid"):
382 case hash(
"UnionSolid"):
385 case hash(
"SubtractionSolid"):
388 case hash(
"IntersectionSolid"):
391 case hash(
"ShapelessSolid"):
394 case hash(
"Assembly"):
398 throw std::runtime_error(
"Request to process unknown shape '" + xml_dim_t(solid).nameStr() +
"' [" +
407 void Converter<DDLConstant>::operator()(xml_h element)
const {
409 DDRegistry* res = _option<DDRegistry>();
410 xml_dim_t constant = element;
411 xml_dim_t par = constant.parent();
412 bool eval = par.hasAttr(_U(eval)) ? par.attr<
bool>(_U(eval)) :
true;
413 string val = constant.valueStr();
414 string nam = constant.nameStr();
415 string real = ns.prepend(nam);
416 string typ = eval ?
"number" :
"string";
417 size_t idx = val.find(
'[');
419 if (constant.hasAttr(_U(
type)))
420 typ = constant.typeStr();
422 if (idx == string::npos || typ ==
"string") {
424 ns.addConstant(nam, val, typ);
425 res->originalConst[real] =
val;
431 "++ Unresolved constant: %s = %s [%s]. Try to resolve later. [%s]",
441 while (idx != string::npos) {
443 size_t idp = val.find(
':', idx);
444 size_t idq = val.find(
']', idx);
445 if (idp == string::npos || idp > idq)
446 val.insert(idx, ns.name());
447 else if (idp != string::npos && idp < idq)
449 idx = val.find(
'[', idx);
455 ns.context()->debug_constants ? ALWAYS :
DEBUG,
"Constant",
"Unresolved: %s -> %s", real.c_str(), val.c_str());
459 res->originalConst[real] =
val;
460 res->unresolvedConst[real] =
val;
465 void Converter<DDLElementaryMaterial>::operator()(xml_h element)
const {
467 xml_dim_t xmat(element);
468 const string xmatName(xmat.nameStr());
469 string nam = ns.prepend(xmatName);
471 TGeoMaterial* mat = mgr.GetMaterial(nam.c_str());
472 if (
nullptr == mat) {
473 const char* matname = nam.c_str();
474 double density = xmat.attr<
double>(
DD_CMU(density)) / (
dd4hep::g / dd4hep::cm3);
475 int atomicNumber = xmat.attr<
int>(
DD_CMU(atomicNumber));
476 double atomicWeight = xmat.attr<
double>(
DD_CMU(atomicWeight)) / (
dd4hep::g / dd4hep::mole);
477 TGeoElementTable* tab = mgr.GetElementTable();
478 int nElem = tab->GetNelements();
482 printout(ns.context()->debug_materials ? ALWAYS :
DEBUG,
"DD4CMS",
"+++ Element table size = %d", nElem);
487 tab->TGeoElementTable::~TGeoElementTable();
488 new (tab) TGeoElementTable();
489 tab->BuildDefaultElements();
491 TGeoMixture*
mix =
new TGeoMixture(nam.c_str(), 1, density);
492 const char*
const matNameNoNS = xmatName.c_str();
493 TGeoElement* elt = tab->FindElement(matNameNoNS);
497 printout(ns.context()->debug_materials ? ALWAYS :
DEBUG,
499 "+++ Searching for material %-48s elt_ptr = %ld",
503 printout(ns.context()->debug_materials ? ALWAYS :
DEBUG,
505 "+++ Converting material %-48s Atomic weight %8.3f [g/mol], Atomic number %u, Density: %8.3f [g/cm3] "
506 "ROOT: %8.3f [g/cm3]",
507 (
'"' + nam +
'"').c_str(),
515 bool newMatDef =
false;
522 printout(ns.context()->debug_materials ? ALWAYS :
DEBUG,
524 " ROOT definition of %-50s Atomic weight %g, Atomic number %u, Number of nucleons %u",
529 printout(ns.context()->debug_materials ? ALWAYS :
DEBUG,
531 "+++ Compared to XML values: Atomic weight %g, Atomic number %u",
536 static constexpr
double const weightTolerance = 1.0e-6;
537 if (atomicNumber != elt->Z() ||
538 (
std::abs(atomicWeight - elt->A()) > (weightTolerance * (atomicWeight + elt->A()))))
542 if (!elt || newMatDef) {
546 printout(ns.context()->debug_materials ? ALWAYS :
DEBUG,
548 "+++ Converter<ElementaryMaterial> Different definition of a default element with name:%s [CREATE NEW "
557 printout(ns.context()->debug_materials ? ALWAYS :
DEBUG,
559 "+++ Converter<ElementaryMaterial> No default element present with name:%s [CREATE NEW MATERIAL]",
564 elt =
new TGeoElement(matNameNoNS, matNameNoNS, atomicNumber, atomicWeight);
567 mix->AddElement(elt, 1.0);
568 mix->SetTemperature(ns.context()->description.stdConditions().temperature);
569 mix->SetPressure(ns.context()->description.stdConditions().pressure);
572 TGeoMedium* medium = mgr.GetMedium(matname);
573 if (
nullptr == medium) {
575 medium =
new TGeoMedium(matname, unique_mat_id, mix);
576 medium->SetTitle(
"material");
577 medium->SetUniqueID(unique_mat_id);
584 void Converter<DDLCompositeMaterial>::operator()(xml_h element)
const {
586 xml_dim_t xmat(element);
587 string nam = ns.prepend(xmat.nameStr());
590 TGeoMaterial* mat = mgr.GetMaterial(nam.c_str());
591 if (
nullptr == mat) {
592 const char* matname = nam.c_str();
593 double density = xmat.attr<
double>(
DD_CMU(density)) / (
dd4hep::g / dd4hep::cm3);
594 xml_coll_t composites(xmat,
DD_CMU(MaterialFraction));
595 TGeoMixture* mix =
new TGeoMixture(nam.c_str(), composites.size(), density);
599 printout(ns.context()->debug_materials ? ALWAYS :
DEBUG,
601 "++ Converting material %-48s Density: %8.3f [g/cm3] ROOT: %8.3f [g/cm3]",
602 (
'"' + nam +
'"').c_str(),
608 if (ns.context()->makePayload) {
609 ns.context()->compMaterialsVec.emplace_back(std::make_pair(nam, density));
611 for (composites.reset(); composites; ++composites) {
612 xml_dim_t xfrac(composites);
613 xml_dim_t xfrac_mat(xfrac.child(
DD_CMU(rMaterial)));
615 string fracname = ns.realName(xfrac_mat.nameStr());
617 if (ns.context()->makePayload) {
618 ns.context()->compMaterialsRefs[nam].emplace_back(
621 TGeoMaterial* frac_mat = mgr.GetMaterial(fracname.c_str());
622 if (frac_mat ==
nullptr)
623 frac_mat = mgr.GetMaterial(ns.prepend(fracname).c_str());
625 mix->AddElement(frac_mat, fraction);
629 printout(ns.context()->debug_materials ? ALWAYS :
WARNING,
631 "+++ Composite material \"%s\" [nor \"%s\"] not present! [delay resolution]",
633 ns.prepend(fracname).c_str());
635 ns.context()->unresolvedMaterials[nam].emplace_back(
638 mix->SetTemperature(ns.context()->description.stdConditions().temperature);
639 mix->SetPressure(ns.context()->description.stdConditions().pressure);
642 TGeoMedium* medium = mgr.GetMedium(matname);
643 if (
nullptr == medium) {
645 medium =
new TGeoMedium(matname, unique_mat_id, mix);
646 medium->SetTitle(
"material");
647 medium->SetUniqueID(unique_mat_id);
654 void Converter<DDLRotation>::operator()(xml_h element)
const {
657 xml_dim_t xrot(element);
658 string nam = xrot.nameStr();
659 double thetaX = xrot.hasAttr(
DD_CMU(thetaX)) ? ns.attr<
double>(xrot,
DD_CMU(thetaX)) : 0e0;
660 double phiX = xrot.hasAttr(
DD_CMU(phiX)) ? ns.attr<
double>(xrot,
DD_CMU(phiX)) : 0e0;
661 double thetaY = xrot.hasAttr(
DD_CMU(thetaY)) ? ns.attr<
double>(xrot,
DD_CMU(thetaY)) : 0e0;
662 double phiY = xrot.hasAttr(
DD_CMU(phiY)) ? ns.attr<
double>(xrot,
DD_CMU(phiY)) : 0e0;
663 double thetaZ = xrot.hasAttr(
DD_CMU(thetaZ)) ? ns.attr<
double>(xrot,
DD_CMU(thetaZ)) : 0e0;
664 double phiZ = xrot.hasAttr(
DD_CMU(phiZ)) ? ns.attr<
double>(xrot,
DD_CMU(phiZ)) : 0e0;
671 "+++ Adding rotation: %-32s: (theta/phi)[rad] X: %6.3f %6.3f Y: %6.3f %6.3f Z: %6.3f %6.3f",
672 ns.prepend(nam).c_str(),
682 ns.addRotation(nam, rot);
687 void Converter<DDLReflectionRotation>::operator()(xml_h element)
const {
690 xml_dim_t xrot(element);
691 string name = xrot.nameStr();
692 double thetaX = xrot.hasAttr(
DD_CMU(thetaX)) ? ns.attr<
double>(xrot,
DD_CMU(thetaX)) : 0e0;
693 double phiX = xrot.hasAttr(
DD_CMU(phiX)) ? ns.attr<
double>(xrot,
DD_CMU(phiX)) : 0e0;
694 double thetaY = xrot.hasAttr(
DD_CMU(thetaY)) ? ns.attr<
double>(xrot,
DD_CMU(thetaY)) : 0e0;
695 double phiY = xrot.hasAttr(
DD_CMU(phiY)) ? ns.attr<
double>(xrot,
DD_CMU(phiY)) : 0e0;
696 double thetaZ = xrot.hasAttr(
DD_CMU(thetaZ)) ? ns.attr<
double>(xrot,
DD_CMU(thetaZ)) : 0e0;
697 double phiZ = xrot.hasAttr(
DD_CMU(phiZ)) ? ns.attr<
double>(xrot,
DD_CMU(phiZ)) : 0e0;
703 "+++ Adding reflection rotation: %-32s: (theta/phi)[rad] X: %6.3f %6.3f Y: %6.3f %6.3f Z: %6.3f %6.3f",
704 ns.prepend(name).c_str(),
714 Rotation3D rot =
makeRotReflect(thetaX, phiX, thetaY, phiY, thetaZ, phiZ);
715 ns.addRotation(name, rot);
720 void Converter<DDLRotationSequence>::operator()(xml_h element)
const {
723 xml_dim_t xrot(element);
724 string nam = xrot.nameStr();
726 xml_coll_t rotations(xrot,
DD_CMU(RotationByAxis));
727 for (rotations.reset(); rotations; ++rotations) {
728 string axis = ns.attr<
string>(rotations,
DD_CMU(axis));
729 double angle = ns.attr<
double>(rotations, _U(angle));
736 "+ Adding rotation to: %-29s: (axis/angle)[rad] Axis: %s Angle: %6.3f",
746 rot.GetComponents(xx, xy, xz, yx, yy, yz, zx, zy, zz);
752 "+++ Adding rotation sequence: %-23s: %6.3f %6.3f %6.3f, %6.3f %6.3f %6.3f, %6.3f %6.3f %6.3f",
753 ns.prepend(nam).c_str(),
766 ns.addRotation(nam, rot);
771 void Converter<DDLRotationByAxis>::operator()(xml_h element)
const {
774 xml_dim_t xrot(element);
775 xml_dim_t par(xrot.parent());
776 if (xrot.hasAttr(_U(name))) {
777 string nam = xrot.nameStr();
778 string axis = ns.attr<
string>(xrot,
DD_CMU(axis));
779 double angle = ns.attr<
double>(xrot, _U(angle));
787 "+++ Adding rotation: %-32s: (axis/angle)[rad] Axis: %s Angle: %6.3f",
788 ns.prepend(nam).c_str(),
794 ns.addRotation(nam, rot);
800 void Converter<DDLLogicalPart>::operator()(xml_h element)
const {
802 xml_dim_t
e(element);
803 string sol = e.child(
DD_CMU(rSolid)).attr<
string>(_U(name));
804 string mat = e.child(
DD_CMU(rMaterial)).attr<
string>(_U(name));
805 string volName = ns.prepend(e.attr<
string>(_U(name)));
806 Solid solid = ns.solid(sol);
807 Material material = ns.material(mat);
808 if (ns.context()->assemblySolids.count(sol) == 1) {
812 ns.addAssembly(volName,
false);
820 ns.addVolume(
Volume(volName, solid, material));
824 printout(ns.context()->debug_volumes ? ALWAYS :
DEBUG,
826 "+++ %s Volume: %-24s [%s] Shape: %-32s [%s] Material: %-40s [%s]",
829 volume.isValid() ?
"VALID" :
"INVALID",
831 solid.isValid() ?
"VALID" :
"INVALID",
833 material.isValid() ?
"VALID" :
"INVALID");
840 void Converter<DDLTransform3D>::operator()(xml_h element)
const {
842 Transform3D* tr = _option<Transform3D>();
843 xml_dim_t
e(element);
846 xml_dim_t refRotation = e.child(
DD_CMU(rRotation),
false);
847 xml_dim_t refReflectionRotation = e.child(
DD_CMU(rReflectionRotation),
false);
851 if (translation.ptr()) {
852 double x = ns.attr<
double>(translation, _U(x));
853 double y = ns.attr<
double>(translation, _U(y));
854 double z = ns.attr<
double>(translation, _U(z));
857 if (rotation.ptr()) {
858 double x = ns.attr<
double>(
rotation, _U(x));
859 double y = ns.attr<
double>(
rotation, _U(y));
860 double z = ns.attr<
double>(
rotation, _U(z));
861 rot = RotationZYX(z, y, x);
862 }
else if (refRotation.ptr()) {
863 string rotName = ns.prepend(refRotation.nameStr());
864 rot = ns.rotation(rotName);
865 }
else if (refReflectionRotation.ptr()) {
866 string rotName = ns.prepend(refReflectionRotation.nameStr());
867 rot = ns.rotation(rotName);
869 *tr = Transform3D(rot, pos);
873 const string& parentName,
875 const string& childName,
883 "+++ Parent vol: %-24s Child: %-32s, copy:%d",
890 TGeoShape* shape = (*childPtr)->GetShape();
892 if (shape->IsA() == TGeoShapeAssembly::Class()) {
893 TGeoShapeAssembly* as = (TGeoShapeAssembly*)shape;
897 as->NeedsBBoxRecompute();
902 TString nam_id = TString::Format(
"%s_%d", (*childPtr)->GetName(),
copy);
903 n =
static_cast<TGeoNode*
>((*parentPtr)->GetNode(nam_id));
905 printout(
ERROR,
"PlacedVolume",
"++ Attempt to add already existing node %s", (
const char*)nam_id);
910 if ((*childPtr)->IsAssembly()) {
913 pv = parentPtr->placeVolume(*childPtr, copy, transform);
917 printout(
ERROR,
"DD4CMS",
"+++ Placement FAILED! Parent:%s Child:%s", parentName.c_str(), childName.c_str());
923 void Converter<DDLPosPart>::operator()(xml_h element)
const {
925 xml_dim_t
e(element);
927 string parentName = ns.prepend(ns.attr<
string>(e.child(
DD_CMU(rParent)), _U(name)));
928 string childName = ns.prepend(ns.attr<
string>(e.child(
DD_CMU(rChild)), _U(name)));
934 Assembly parAsmb = ns.assembly(parentName,
false);
935 Assembly childAsmb = ns.assembly(childName,
false);
939 printout(ns.context()->debug_placements ? ALWAYS :
DEBUG,
941 "+++ %s Parent: %-24s [%s] Child: %-32s [%s] copy:%d",
944 parent.isValid() ?
"VALID" :
"INVALID",
946 child.isValid() ?
"VALID" :
"INVALID",
951 if (!parent.isValid() && !parAsmb.isValid() && strchr(parentName.c_str(),
NAMESPACE_SEP) ==
nullptr) {
952 parentName = ns.prepend(parentName);
953 parAsmb = ns.assembly(parentName,
false);
954 if (!parAsmb.isValid())
955 parent = ns.volume(parentName);
958 if (!child.isValid() && !childAsmb.isValid() && strchr(childName.c_str(),
NAMESPACE_SEP) ==
nullptr) {
959 childName = ns.prepend(childName);
960 child = ns.volume(childName,
false);
961 childAsmb = ns.assembly(childName,
false);
963 if (parAsmb.isValid() || childAsmb.isValid()) {
964 printout(ns.context()->debug_placements ? ALWAYS :
DEBUG,
966 "***** Placing assembly parent %s, child %s",
969 Volume* parentPtr = parAsmb.isValid() ? &parAsmb : &
parent;
970 Volume* childPtr = childAsmb.isValid() ? &childAsmb : &
child;
971 placeAssembly(parentPtr, parentName, childPtr, childName, copy, transform, ns);
977 printout(ns.context()->debug_placements ? ALWAYS :
DEBUG,
979 "+++ %s Parent: %-24s [%s] Child: %-32s [%s] copy:%d",
982 parent.isValid() ?
"VALID" :
"INVALID",
984 child.isValid() ?
"VALID" :
"INVALID",
990 if (child.isValid()) {
995 except(
"dd4hep",
"Volume: Attempt to assign daughters to an invalid physical parent volume.");
998 except(
"dd4hep",
"Volume: Attempt to assign an invalid physical daughter volume.");
1000 TGeoShape* shape = child->GetShape();
1002 if (shape->IsA() == TGeoShapeAssembly::Class()) {
1003 TGeoShapeAssembly* as = (TGeoShapeAssembly*)shape;
1007 as->NeedsBBoxRecompute();
1012 TString nam_id = TString::Format(
"%s_%d", child->GetName(),
copy);
1013 n =
static_cast<TGeoNode*
>(parent->GetNode(nam_id));
1015 printout(
ERROR,
"PlacedVolume",
"++ Attempt to add already existing node %s", (
const char*)nam_id);
1018 Rotation3D
rot(transform.Rotation());
1019 Translation3D trans(transform.Translation());
1021 trans.GetComponents(x, y, z);
1025 n =
static_cast<TGeoNode*
>(parent->GetNode(nam_id));
1026 n->TGeoNode::SetUserExtension(
new PlacedVolume::Object());
1029 if (!pv.isValid()) {
1032 "+++ Placement FAILED! Parent:%s Child:%s Valid:%s",
1035 yes_no(child.isValid()));
1041 void Converter<PartSelector>::operator()(xml_h element)
const {
1044 dd4hep::SpecParRegistry& registry = *context->
description.extension<dd4hep::SpecParRegistry>();
1045 xml_dim_t
e(element);
1046 xml_dim_t specPar = e.parent();
1047 string specParName = specPar.attr<
string>(_U(name));
1052 printout(ns.context()->debug_specpars ? ALWAYS :
DEBUG,
1054 "+++ PartSelector for %s path: %s",
1055 specParName.c_str(),
1060 size_t pos = std::string::npos;
1061 if ((pos = path.find(
"//.*:")) != std::string::npos) {
1062 path.erase(pos + 2, 3);
1064 registry.specpars[specParName].paths.emplace_back(
std::move(path));
1069 void Converter<Parameter>::operator()(xml_h element)
const {
1072 dd4hep::SpecParRegistry& registry = *context->
description.extension<dd4hep::SpecParRegistry>();
1073 xml_dim_t
e(element);
1074 xml_dim_t specPar = e.parent();
1075 xml_dim_t specParSect = specPar.parent();
1076 string specParName = specPar.attr<
string>(_U(name));
1077 string name = e.nameStr();
1079 bool eval = specParSect.hasAttr(_U(eval)) ? specParSect.attr<
bool>(_U(eval)) :
false;
1080 eval = specPar.hasAttr(_U(eval)) ? specPar.attr<
bool>(_U(eval)) : eval;
1081 eval = e.hasAttr(_U(eval)) ? e.attr<
bool>(_U(eval)) : eval;
1083 string type = eval ?
"number" :
"string";
1087 printout(ns.context()->debug_specpars ? ALWAYS :
DEBUG,
1089 "+++ Parameter for %s: %s value %s is a %s",
1090 specParName.c_str(),
1097 size_t idx = value.find(
'[');
1098 if (idx == string::npos && type ==
"number") {
1099 registry.specpars[specParName].numpars[
name].emplace_back(dd4hep::_toDouble(value));
1102 if (idx == string::npos || type ==
"string") {
1103 registry.specpars[specParName].spars[
name].emplace_back(
std::move(value));
1107 while (idx != string::npos) {
1109 size_t idp = value.find(
':', idx);
1110 size_t idq = value.find(
']', idx);
1111 if (idp == string::npos || idp > idq)
1112 value.insert(idx, ns.name());
1113 else if (idp != string::npos && idp < idq)
1115 idx = value.find(
'[', idx);
1121 for (idx = v.find(
'[', 0); idx != string::npos; idx = v.find(
'[', idx + 1)) {
1122 idq = v.find(
']', idx + 1);
1123 rep = v.substr(idx + 1, idq - idx - 1);
1124 auto r = ns.context()->description.constants().find(rep);
1125 if (
r != ns.context()->description.constants().end()) {
1126 rep =
"(" +
r->second->type +
")";
1127 v.replace(idx, idq - idx + 1, rep);
1130 registry.specpars[specParName].numpars[
name].emplace_back(dd4hep::_toDouble(value));
1133 template <
typename TYPE>
1136 xml_dim_t
e(element);
1137 string nam = e.nameStr();
1138 string solidName[2];
1142 if (e.hasChild(
DD_CMU(rSolid))) {
1143 for (xml_coll_t
c(element,
DD_CMU(rSolid)); cnt < 2 &&
c; ++
c, ++cnt) {
1144 solidName[cnt] = c.attr<
string>(_U(name));
1145 solids[cnt] = ns.
solid(c.attr<
string>(_U(name)));
1148 solidName[0] = e.attr<
string>(
DD_CMU(firstSolid));
1151 solidName[1] = e.attr<
string>(
DD_CMU(secondSolid));
1156 except(
"DD4CMS",
"+++ Failed to create boolean solid %s. Found only %d parts.", nam.c_str(), cnt);
1163 "+++ BooleanSolid: %s Left: %-32s Right: %-32s",
1165 ((solids[0].ptr() ==
nullptr) ? solidName[0].c_str() : solids[0]->GetName()),
1166 ((solids[1].ptr() ==
nullptr) ? solidName[1].c_str() : solids[1]->GetName()));
1173 boolean =
TYPE(solids[0], solids[1], trafo);
1190 void Converter<DDLUnionSolid>::operator()(xml_h element)
const {
1191 convert_boolean<UnionSolid>(_param<cms::DDParsingContext>(), element);
1196 void Converter<DDLSubtractionSolid>::operator()(xml_h element)
const {
1197 convert_boolean<SubtractionSolid>(_param<cms::DDParsingContext>(), element);
1202 void Converter<DDLIntersectionSolid>::operator()(xml_h element)
const {
1203 convert_boolean<IntersectionSolid>(_param<cms::DDParsingContext>(), element);
1208 void Converter<DDLPolycone>::operator()(xml_h element)
const {
1210 xml_dim_t
e(element);
1211 string nam = e.nameStr();
1212 double startPhi = ns.attr<
double>(
e,
DD_CMU(startPhi));
1214 vector<double>
z, rmin, rmax,
r;
1216 for (xml_coll_t rzpoint(element,
DD_CMU(RZPoint)); rzpoint; ++rzpoint) {
1217 z.emplace_back(ns.attr<
double>(rzpoint, _U(z)));
1218 r.emplace_back(ns.attr<
double>(rzpoint, _U(r)));
1221 for (xml_coll_t zplane(element,
DD_CMU(ZSection)); zplane; ++zplane) {
1222 rmin.emplace_back(ns.attr<
double>(zplane,
DD_CMU(rMin)));
1223 rmax.emplace_back(ns.attr<
double>(zplane,
DD_CMU(rMax)));
1224 z.emplace_back(ns.attr<
double>(zplane, _U(z)));
1229 printout(ns.context()->debug_shapes ? ALWAYS :
DEBUG,
1231 "+ Polycone: startPhi=%10.3f [rad] deltaPhi=%10.3f [rad] %4ld z-planes",
1238 ns.addSolid(nam, Polycone(startPhi, deltaPhi, rmin, rmax, z));
1242 printout(ns.context()->debug_shapes ? ALWAYS :
DEBUG,
1244 "+ Polycone: startPhi=%10.3f [rad] deltaPhi=%10.3f [rad] %4ld z-planes and %4ld radii",
1252 ns.addSolid(nam, Polycone(startPhi, deltaPhi, r, z));
1258 void Converter<DDLExtrudedPolygon>::operator()(xml_h element)
const {
1260 xml_dim_t
e(element);
1261 string nam = e.nameStr();
1262 vector<double> pt_x, pt_y, sec_x, sec_y, sec_z, sec_scale;
1264 for (xml_coll_t sec(element,
DD_CMU(ZXYSection)); sec; ++sec) {
1265 sec_z.emplace_back(ns.attr<
double>(sec, _U(z)));
1266 sec_x.emplace_back(ns.attr<
double>(sec, _U(x)));
1267 sec_y.emplace_back(ns.attr<
double>(sec, _U(y)));
1268 sec_scale.emplace_back(ns.attr<
double>(sec,
DD_CMU(
scale), 1.0));
1270 for (xml_coll_t
pt(element,
DD_CMU(XYPoint));
pt; ++
pt) {
1271 pt_x.emplace_back(ns.attr<
double>(
pt, _U(x)));
1272 pt_y.emplace_back(ns.attr<
double>(
pt, _U(y)));
1277 printout(ns.context()->debug_shapes ? ALWAYS :
DEBUG,
1279 "+ ExtrudedPolygon: %4ld points %4ld zxy sections",
1285 ns.addSolid(nam,
ExtrudedPolygon(pt_x, pt_y, sec_z, sec_x, sec_y, sec_scale));
1290 void Converter<DDLPolyhedra>::operator()(xml_h element)
const {
1292 xml_dim_t
e(element);
1293 string nam = e.nameStr();
1294 double numSide = ns.attr<
int>(
e,
DD_CMU(numSide));
1295 double startPhi = ns.attr<
double>(
e,
DD_CMU(startPhi));
1296 double deltaPhi = ns.attr<
double>(
e,
DD_CMU(deltaPhi));
1297 vector<double>
z, rmin, rmax;
1299 for (xml_coll_t zplane(element,
DD_CMU(RZPoint)); zplane; ++zplane) {
1300 rmin.emplace_back(0.0);
1301 rmax.emplace_back(ns.attr<
double>(zplane, _U(r)));
1302 z.emplace_back(ns.attr<
double>(zplane, _U(z)));
1304 for (xml_coll_t zplane(element,
DD_CMU(ZSection)); zplane; ++zplane) {
1305 rmin.emplace_back(ns.attr<
double>(zplane,
DD_CMU(rMin)));
1306 rmax.emplace_back(ns.attr<
double>(zplane,
DD_CMU(rMax)));
1307 z.emplace_back(ns.attr<
double>(zplane, _U(z)));
1312 printout(ns.context()->debug_shapes ? ALWAYS :
DEBUG,
1314 "+ Polyhedra:startPhi=%8.3f [rad] deltaPhi=%8.3f [rad] %4d sides %4ld z-planes",
1322 ns.addSolid(nam,
Polyhedra(numSide, startPhi, deltaPhi, z, rmin, rmax));
1327 void Converter<DDLSphere>::operator()(xml_h element)
const {
1329 xml_dim_t
e(element);
1330 string nam = e.nameStr();
1331 double rinner = ns.attr<
double>(
e,
DD_CMU(innerRadius));
1332 double router = ns.attr<
double>(
e,
DD_CMU(outerRadius));
1333 double startPhi = ns.attr<
double>(
e,
DD_CMU(startPhi));
1334 double deltaPhi = ns.attr<
double>(
e,
DD_CMU(deltaPhi));
1335 double startTheta = ns.attr<
double>(
e,
DD_CMU(startTheta));
1336 double deltaTheta = ns.attr<
double>(
e,
DD_CMU(deltaTheta));
1340 printout(ns.context()->debug_shapes ? ALWAYS :
DEBUG,
1342 "+ Sphere: r_inner=%8.3f [cm] r_outer=%8.3f [cm]"
1343 " startPhi=%8.3f [rad] deltaPhi=%8.3f startTheta=%8.3f delteTheta=%8.3f [rad]",
1344 rinner / dd4hep::cm,
1345 router / dd4hep::cm,
1353 ns.addSolid(nam, Sphere(rinner, router, startTheta, deltaTheta, startPhi, deltaPhi));
1358 void Converter<DDLTorus>::operator()(xml_h element)
const {
1360 xml_dim_t
e(element);
1361 string nam = e.nameStr();
1362 double r = ns.attr<
double>(
e,
DD_CMU(torusRadius));
1363 double rinner = ns.attr<
double>(
e,
DD_CMU(innerRadius));
1364 double router = ns.attr<
double>(
e,
DD_CMU(outerRadius));
1365 double startPhi = ns.attr<
double>(
e,
DD_CMU(startPhi));
1366 double deltaPhi = ns.attr<
double>(
e,
DD_CMU(deltaPhi));
1370 printout(ns.context()->debug_shapes ? ALWAYS :
DEBUG,
1372 "+ Torus: r=%10.3f [cm] r_inner=%10.3f [cm] r_outer=%10.3f [cm]"
1373 " startPhi=%10.3f [rad] deltaPhi=%10.3f [rad]",
1375 rinner / dd4hep::cm,
1376 router / dd4hep::cm,
1382 ns.addSolid(nam, Torus(r, rinner, router, startPhi, deltaPhi));
1387 void Converter<DDLPseudoTrap>::operator()(xml_h element)
const {
1389 xml_dim_t
e(element);
1390 string nam = e.nameStr();
1391 double dx1 = ns.attr<
double>(
e,
DD_CMU(dx1));
1392 double dy1 = ns.attr<
double>(
e,
DD_CMU(dy1));
1393 double dx2 = ns.attr<
double>(
e,
DD_CMU(dx2));
1394 double dy2 = ns.attr<
double>(
e,
DD_CMU(dy2));
1395 double dz = ns.attr<
double>(
e, _U(dz));
1396 double r = ns.attr<
double>(
e, _U(
radius));
1397 bool atMinusZ = ns.attr<
bool>(
e,
DD_CMU(atMinusZ));
1401 printout(ns.context()->debug_shapes ? ALWAYS :
DEBUG,
1403 "+ Pseudotrap: dz=%8.3f [cm] dx1:%.3f dy1:%.3f dx2=%.3f dy2=%.3f radius:%.3f atMinusZ:%s",
1414 ns.addSolid(nam, PseudoTrap(dx1, dx2, dy1, dy2, dz, r, atMinusZ));
1419 void Converter<DDLTrapezoid>::operator()(xml_h element)
const {
1421 xml_dim_t
e(element);
1422 string nam = e.nameStr();
1423 double dz = ns.attr<
double>(
e, _U(dz));
1424 double alp1 = ns.attr<
double>(
e,
DD_CMU(alp1));
1425 double bl1 = ns.attr<
double>(
e,
DD_CMU(bl1));
1426 double tl1 = ns.attr<
double>(
e,
DD_CMU(tl1));
1427 double h1 = ns.attr<
double>(
e,
DD_CMU(h1));
1428 double alp2 = ns.attr<
double>(
e,
DD_CMU(alp2));
1429 double bl2 = ns.attr<
double>(
e,
DD_CMU(bl2));
1430 double tl2 = ns.attr<
double>(
e,
DD_CMU(tl2));
1431 double h2 = ns.attr<
double>(
e,
DD_CMU(h2));
1432 double phi = ns.attr<
double>(
e, _U(phi), 0.0);
1433 double theta = ns.attr<
double>(
e, _U(theta), 0.0);
1437 printout(ns.context()->debug_shapes ? ALWAYS :
DEBUG,
1439 "+ Trapezoid: dz=%10.3f [cm] alp1:%.3f bl1=%.3f tl1=%.3f alp2=%.3f bl2=%.3f tl2=%.3f h2=%.3f phi=%.3f "
1455 ns.addSolid(nam, Trap(dz,
theta, phi, h1, bl1, tl1, alp1, h2, bl2, tl2, alp2));
1460 void Converter<DDLTrd1>::operator()(xml_h element)
const {
1462 xml_dim_t
e(element);
1463 string nam = e.nameStr();
1464 double dx1 = ns.attr<
double>(
e,
DD_CMU(dx1));
1465 double dy1 = ns.attr<
double>(
e,
DD_CMU(dy1));
1466 double dx2 = ns.attr<
double>(
e,
DD_CMU(dx2), 0.0);
1467 double dy2 = ns.attr<
double>(
e,
DD_CMU(dy2), dy1);
1468 double dz = ns.attr<
double>(
e,
DD_CMU(dz));
1472 printout(ns.context()->debug_shapes ? ALWAYS :
DEBUG,
1474 "+ Trd1: dz=%8.3f [cm] dx1:%.3f dy1:%.3f dx2:%.3f dy2:%.3f",
1483 ns.addSolid(nam, Trd1(dx1, dx2, dy1, dz));
1487 printout(ns.context()->debug_shapes ? ALWAYS :
DEBUG,
1489 "+ Trd1(which is actually Trd2): dz=%8.3f [cm] dx1:%.3f dy1:%.3f dx2:%.3f dy2:%.3f",
1498 ns.addSolid(nam, Trd2(dx1, dx2, dy1, dy2, dz));
1504 void Converter<DDLTrd2>::operator()(xml_h element)
const {
1506 xml_dim_t
e(element);
1507 string nam = e.nameStr();
1508 double dx1 = ns.attr<
double>(
e,
DD_CMU(dx1));
1509 double dy1 = ns.attr<
double>(
e,
DD_CMU(dy1));
1510 double dx2 = ns.attr<
double>(
e,
DD_CMU(dx2), 0.0);
1511 double dy2 = ns.attr<
double>(
e,
DD_CMU(dy2), dy1);
1512 double dz = ns.attr<
double>(
e,
DD_CMU(dz));
1516 printout(ns.context()->debug_shapes ? ALWAYS :
DEBUG,
1518 "+ Trd1: dz=%8.3f [cm] dx1:%.3f dy1:%.3f dx2:%.3f dy2:%.3f",
1527 ns.addSolid(nam, Trd2(dx1, dx2, dy1, dy2, dz));
1532 void Converter<DDLTubs>::operator()(xml_h element)
const {
1534 xml_dim_t
e(element);
1535 string nam = e.nameStr();
1536 double dz = ns.attr<
double>(
e,
DD_CMU(dz));
1537 double rmin = ns.attr<
double>(
e,
DD_CMU(rMin));
1538 double rmax = ns.attr<
double>(
e,
DD_CMU(rMax));
1539 double startPhi = ns.attr<
double>(
e,
DD_CMU(startPhi), 0.0);
1540 double deltaPhi = ns.attr<
double>(
e,
DD_CMU(deltaPhi), 2 *
M_PI);
1544 printout(ns.context()->debug_shapes ? ALWAYS :
DEBUG,
1546 "+ Tubs: dz=%8.3f [cm] rmin=%8.3f [cm] rmax=%8.3f [cm]"
1547 " startPhi=%8.3f [rad] deltaPhi=%8.3f [rad]",
1556 ns.addSolid(nam, Tube(rmin, rmax, dz, startPhi, startPhi + deltaPhi));
1561 void Converter<DDLCutTubs>::operator()(xml_h element)
const {
1563 xml_dim_t
e(element);
1564 string nam = e.nameStr();
1565 double dz = ns.attr<
double>(
e,
DD_CMU(dz));
1566 double rmin = ns.attr<
double>(
e,
DD_CMU(rMin));
1567 double rmax = ns.attr<
double>(
e,
DD_CMU(rMax));
1568 double startPhi = ns.attr<
double>(
e,
DD_CMU(startPhi));
1569 double deltaPhi = ns.attr<
double>(
e,
DD_CMU(deltaPhi));
1570 double lx = ns.attr<
double>(
e,
DD_CMU(lx));
1571 double ly = ns.attr<
double>(
e,
DD_CMU(ly));
1572 double lz = ns.attr<
double>(
e,
DD_CMU(lz));
1573 double tx = ns.attr<
double>(
e,
DD_CMU(tx));
1574 double ty = ns.attr<
double>(
e,
DD_CMU(ty));
1575 double tz = ns.attr<
double>(
e,
DD_CMU(tz));
1579 printout(ns.context()->debug_shapes ? ALWAYS :
DEBUG,
1581 "+ CutTube: dz=%8.3f [cm] rmin=%8.3f [cm] rmax=%8.3f [cm]"
1582 " startPhi=%8.3f [rad] deltaPhi=%8.3f [rad]...",
1591 ns.addSolid(nam, CutTube(rmin, rmax, dz, startPhi, startPhi + deltaPhi, lx, ly, lz, tx, ty, tz));
1596 void Converter<DDLTruncTubs>::operator()(xml_h element)
const {
1598 xml_dim_t
e(element);
1599 string nam = e.nameStr();
1600 double zhalf = ns.attr<
double>(
e,
DD_CMU(zHalf));
1601 double rmin = ns.attr<
double>(
e,
DD_CMU(rMin));
1602 double rmax = ns.attr<
double>(
e,
DD_CMU(rMax));
1603 double startPhi = ns.attr<
double>(
e,
DD_CMU(startPhi));
1604 double deltaPhi = ns.attr<
double>(
e,
DD_CMU(deltaPhi));
1605 double cutAtStart = ns.attr<
double>(
e,
DD_CMU(cutAtStart));
1606 double cutAtDelta = ns.attr<
double>(
e,
DD_CMU(cutAtDelta));
1607 bool cutInside = ns.attr<
bool>(
e,
DD_CMU(cutInside));
1611 printout(ns.context()->debug_shapes ? ALWAYS :
DEBUG,
1613 "+ TruncTube:zHalf=%8.3f [cm] rmin=%8.3f [cm] rmax=%8.3f [cm]"
1614 " startPhi=%8.3f [rad] deltaPhi=%8.3f [rad] atStart=%8.3f [cm] atDelta=%8.3f [cm] inside:%s",
1620 cutAtStart / dd4hep::cm,
1621 cutAtDelta / dd4hep::cm,
1626 ns.addSolid(nam, TruncatedTube(zhalf, rmin, rmax, startPhi, deltaPhi, cutAtStart, cutAtDelta, cutInside));
1631 void Converter<DDLEllipticalTube>::operator()(xml_h element)
const {
1633 xml_dim_t
e(element);
1634 string nam = e.nameStr();
1635 double dx = ns.attr<
double>(
e,
DD_CMU(xSemiAxis));
1636 double dy = ns.attr<
double>(
e,
DD_CMU(ySemiAxis));
1637 double dz = ns.attr<
double>(
e,
DD_CMU(zHeight));
1641 printout(ns.context()->debug_shapes ? ALWAYS :
DEBUG,
1643 "+ EllipticalTube xSemiAxis=%8.3f [cm] ySemiAxis=%8.3f [cm] zHeight=%8.3f [cm]",
1650 ns.addSolid(nam, EllipticalTube(dx, dy, dz));
1655 void Converter<DDLCone>::operator()(xml_h element)
const {
1657 xml_dim_t
e(element);
1658 string nam = e.nameStr();
1659 double dz = ns.attr<
double>(
e,
DD_CMU(dz));
1660 double rmin1 = ns.attr<
double>(
e,
DD_CMU(rMin1));
1661 double rmin2 = ns.attr<
double>(
e,
DD_CMU(rMin2));
1662 double rmax1 = ns.attr<
double>(
e,
DD_CMU(rMax1));
1663 double rmax2 = ns.attr<
double>(
e,
DD_CMU(rMax2));
1664 double startPhi = ns.attr<
double>(
e,
DD_CMU(startPhi));
1665 double deltaPhi = ns.attr<
double>(
e,
DD_CMU(deltaPhi));
1670 printout(ns.context()->debug_shapes ? ALWAYS :
DEBUG,
1672 "+ Cone: dz=%8.3f [cm]"
1673 " rmin1=%8.3f [cm] rmax1=%8.3f [cm]"
1674 " rmin2=%8.3f [cm] rmax2=%8.3f [cm]"
1675 " startPhi=%8.3f [rad] deltaPhi=%8.3f [rad]",
1686 ns.addSolid(nam, ConeSegment(dz, rmin1, rmax1, rmin2, rmax2, startPhi, phi2));
1691 void Converter<DDLShapeless>::operator()(xml_h element)
const {
1693 xml_dim_t
e(element);
1694 string nam = e.nameStr();
1698 printout(ns.context()->debug_shapes ? ALWAYS :
DEBUG,
1700 "+ Shapeless: THIS ONE CAN ONLY BE USED AT THE VOLUME LEVEL -> Shapeless: %s",
1705 ns.addSolid(nam, Box(1, 1, 1));
1710 void Converter<DDLAssembly>::operator()(xml_h element)
const {
1712 xml_dim_t
e(element);
1713 string nam = e.nameStr();
1717 ns.context()->debug_shapes ? ALWAYS :
DEBUG,
"DD4CMS",
"+ Assembly: Adding solid -> Assembly: %s", nam.c_str());
1720 ns.addAssemblySolid(nam);
1725 void Converter<DDLBox>::operator()(xml_h element)
const {
1727 xml_dim_t
e(element);
1728 string nam = e.nameStr();
1729 double dx = ns.attr<
double>(
e,
DD_CMU(dx));
1730 double dy = ns.attr<
double>(
e,
DD_CMU(dy));
1731 double dz = ns.attr<
double>(
e,
DD_CMU(dz));
1735 printout(ns.context()->debug_shapes ? ALWAYS :
DEBUG,
1737 "+ Box: dx=%10.3f [cm] dy=%10.3f [cm] dz=%10.3f [cm]",
1744 ns.addSolid(nam, Box(dx, dy, dz));
1749 void Converter<include_load>::operator()(xml_h element)
const {
1750 string fname = element.attr<
string>(_U(ref));
1753 doc = xml::DocumentHandler().load(
fp.fullPath());
1757 printout(_param<cms::DDParsingContext>()->debug_includes ? ALWAYS : DEBUG,
1759 "+++ Processing the CMS detector description %s",
1764 _option<DDRegistry>()->
includes.emplace_back(doc);
1769 void Converter<include_unload>::operator()(xml_h element)
const {
1770 string fname = xml::DocumentHandler::system_path(element);
1771 xml::DocumentHolder(xml_elt_t(element).document()).assign(
nullptr);
1775 printout(_param<cms::DDParsingContext>()->debug_includes ? ALWAYS : DEBUG,
1777 "+++ Finished processing %s",
1784 void Converter<include_constants>::operator()(xml_h element)
const {
1785 xml_coll_t(element,
DD_CMU(ConstantsSection)).for_each(Converter<ConstantsSection>(description, param,
optional));
1797 const std::map<std::string, DDAxes> axesmap{{
"x",
DDAxes::x},
1807 void Converter<DDLDivision>::operator()(xml_h element)
const {
1809 xml_dim_t
e(element);
1810 string childName = e.nameStr();
1812 childName = ns.prepend(childName);
1814 string parentName = ns.attr<
string>(
e,
DD_CMU(parent));
1816 parentName = ns.prepend(parentName);
1817 string axis = ns.attr<
string>(
e,
DD_CMU(axis));
1822 double width = e.hasAttr(
DD_CMU(width)) ? ns.attr<
double>(
e,
DD_CMU(width)) : 0e0;
1823 int nReplicas = e.hasAttr(
DD_CMU(nReplicas)) ? ns.attr<
int>(
e,
DD_CMU(nReplicas)) : 0;
1827 printout(ns.context()->debug_placements ? ALWAYS :
DEBUG,
1829 "+++ Start executing Division of %s along %s (%d) with offset %6.3f and %6.3f to produce %s....",
1839 Volume parent = ns.volume(parentName);
1841 const TGeoShape* shape = parent.solid();
1842 TClass*
cl = shape->IsA();
1843 if (cl == TGeoTubeSeg::Class()) {
1844 const TGeoTubeSeg* sh = (
const TGeoTubeSeg*)shape;
1847 int numCopies = (int)((sh->GetPhi2() - sh->GetPhi1()) / widthInDeg);
1851 printout(ns.context()->debug_placements ? ALWAYS :
DEBUG,
1853 "+++ ...divide %s along %s (%d) with offset %6.3f deg and %6.3f deg to produce %d copies",
1854 parent.solid().type(),
1863 Volume child = parent.divide(childName, static_cast<int>(axesmap.at(axis)), numCopies, startInDeg, widthInDeg);
1865 ns.context()->volumes[childName] =
child;
1869 printout(ns.context()->debug_placements ? ALWAYS :
DEBUG,
1871 "+++ %s Parent: %-24s [%s] Child: %-32s [%s] is multivolume [%s]",
1874 parent.isValid() ?
"VALID" :
"INVALID",
1876 child.isValid() ?
"VALID" :
"INVALID",
1877 child->IsVolumeMulti() ?
"YES" :
"NO");
1880 }
else if (cl == TGeoTrd1::Class()) {
1881 double dy =
static_cast<const TGeoTrd1*
>(shape)->GetDy();
1885 printout(ns.context()->debug_placements ? ALWAYS :
DEBUG,
1887 "+++ ...divide %s along %s (%d) with offset %6.3f cm and %6.3f cm to produce %d copies in %6.3f",
1888 parent.solid().type(),
1891 -dy + offset + width,
1898 Volume child = parent.divide(childName, static_cast<int>(axesmap.at(axis)), nReplicas, -dy + offset + width, width);
1900 ns.context()->volumes[childName] =
child;
1904 printout(ns.context()->debug_placements ? ALWAYS :
DEBUG,
1906 "+++ %s Parent: %-24s [%s] Child: %-32s [%s] is multivolume [%s]",
1909 parent.isValid() ?
"VALID" :
"INVALID",
1911 child.isValid() ?
"VALID" :
"INVALID",
1912 child->IsVolumeMulti() ?
"YES" :
"NO");
1916 printout(
ERROR,
"DD4CMS",
"++ FAILED Division of a %s is not implemented yet!", parent.solid().type());
1922 void Converter<DDLAlgorithm>::operator()(xml_h element)
const {
1924 xml_dim_t
e(element);
1925 string name = e.nameStr();
1927 string type =
"DDCMS_" + ns.realName(name);
1934 ns.context()->debug_algorithms ? ALWAYS :
DEBUG,
"DD4CMS",
"+++ Start executing algorithm %s....", type.c_str());
1942 printout(ns.context()->debug_algorithms ? ALWAYS :
DEBUG,
1945 "+++ Executed algorithm: %08lX = %s",
1952 printout(
ERROR,
"DD4CMS",
"++ FAILED NOT ADDING SUBDETECTOR %08lX = %s", ret, name.c_str());
1955 template <
class InputIt,
class ForwardIt,
class BinOp>
1957 while (first != last) {
1958 const auto pos = std::find_first_of(first, last, s_first, s_last);
1959 binary_op(first, pos);
1968 std::vector<string>
splitString(
const string&
str,
const string& delims =
",") {
1969 std::vector<string>
output;
1983 std::vector<double> splitNumeric(
const string& str,
const string& delims =
",") {
1984 std::vector<double>
output;
1992 output.emplace_back(dd4hep::_toDouble(
string(
first,
second)));
2002 void Converter<DDLVector>::operator()(xml_h element)
const {
2006 xml_dim_t
e(element);
2007 string name = ns.prepend(e.nameStr());
2008 string type = ns.attr<
string>(
e, _U(type));
2009 string nEntries = ns.attr<
string>(
e,
DD_CMU(nEntries));
2010 string val = e.text();
2011 val.erase(remove_if(val.begin(), val.end(), [](
unsigned char x) {
return isspace(x); }), val.end());
2015 printout(ns.context()->debug_constants ? ALWAYS :
DEBUG,
2017 "+++ Vector<%s>: %s[%s]: %s",
2026 std::vector<double>
results = splitNumeric(val);
2035 "++ Unresolved Vector<%s>: %s[%s]: %s. Try to resolve later. [%s]",
2050 void Converter<debug>::operator()(xml_h dbg)
const {
2052 if (dbg.hasChild(
DD_CMU(debug_constants)))
2053 ns.setContext()->debug_constants =
true;
2054 if (dbg.hasChild(
DD_CMU(debug_materials)))
2055 ns.setContext()->debug_materials =
true;
2056 if (dbg.hasChild(
DD_CMU(debug_rotations)))
2057 ns.setContext()->debug_rotations =
true;
2058 if (dbg.hasChild(
DD_CMU(debug_shapes)))
2059 ns.setContext()->debug_shapes =
true;
2060 if (dbg.hasChild(
DD_CMU(debug_volumes)))
2061 ns.setContext()->debug_volumes =
true;
2062 if (dbg.hasChild(
DD_CMU(debug_placements)))
2063 ns.setContext()->debug_placements =
true;
2064 if (dbg.hasChild(
DD_CMU(debug_namespaces)))
2065 ns.setContext()->debug_namespaces =
true;
2066 if (dbg.hasChild(
DD_CMU(debug_includes)))
2067 ns.setContext()->debug_includes =
true;
2068 if (dbg.hasChild(
DD_CMU(debug_algorithms)))
2069 ns.setContext()->debug_algorithms =
true;
2070 if (dbg.hasChild(
DD_CMU(debug_specpars)))
2071 ns.setContext()->debug_specpars =
true;
2075 void Converter<DDRegistry>::operator()(xml_h )
const {
2077 DDRegistry* res = _option<DDRegistry>();
2085 "+++ RESOLVING %ld unknown constants..... (out of %ld)",
2086 res->unresolvedConst.size(),
2087 res->originalConst.size());
2090 while (!res->unresolvedConst.empty()) {
2091 for (
auto&
i : res->unresolvedConst) {
2092 const string& n =
i.first;
2094 string& v =
i.second;
2096 for (idx = v.find(
'[', 0); idx != string::npos; idx = v.find(
'[', idx + 1)) {
2097 idq = v.find(
']', idx + 1);
2098 rep = v.substr(idx + 1, idq - idx - 1);
2099 auto r = res->originalConst.find(rep);
2100 if (r != res->originalConst.end()) {
2101 rep =
"(" + (*r).second +
")";
2102 v.replace(idx, idq - idx + 1, rep);
2105 if (v.find(
']') == string::npos) {
2106 if (v.find(
"-+") != string::npos || v.find(
"+-") != string::npos) {
2107 while ((idx = v.find(
"-+")) != string::npos)
2108 v.replace(idx, 2,
"-");
2109 while ((idx = v.find(
"+-")) != string::npos)
2110 v.replace(idx, 2,
"-");
2117 "+++ [%06ld] ---------- %-40s = %s",
2118 res->unresolvedConst.size() - 1,
2120 res->originalConst[
n].c_str());
2124 ns.addConstantNS(n, v,
"number");
2125 res->unresolvedConst.erase(n);
2129 if (++count > 10000)
2132 if (!res->unresolvedConst.empty()) {
2133 for (
const auto& e : res->unresolvedConst)
2134 printout(
ERROR,
"DD4CMS",
"+++ Unresolved constant: %-40s = %s.", e.first.c_str(), e.second.c_str());
2135 except(
"DD4CMS",
"++ FAILED to resolve %ld constant entries:", res->unresolvedConst.size());
2137 res->unresolvedConst.clear();
2138 res->originalConst.clear();
2142 void Converter<print_xml_doc>::operator()(xml_h element)
const {
2143 string fname = xml::DocumentHandler::system_path(element);
2147 printout(_param<cms::DDParsingContext>()->debug_includes ? ALWAYS : DEBUG,
2149 "+++ Processing data from: %s",
2157 xml_elt_t dddef(element);
2161 ns.addConstantNS(
"world_x",
"101*m",
"number");
2162 ns.addConstantNS(
"world_y",
"101*m",
"number");
2163 ns.addConstantNS(
"world_z",
"450*m",
"number");
2164 ns.addConstantNS(
"Air",
"materials:Air",
"string");
2165 ns.addConstantNS(
"Vacuum",
"materials:Vacuum",
"string");
2167 string fname = xml::DocumentHandler::system_path(element);
2168 bool open_geometry = dddef.hasChild(
DD_CMU(open_geometry)) ? dddef.child(
DD_CMU(open_geometry)) :
true;
2169 bool close_geometry = dddef.hasChild(
DD_CMU(close_geometry)) ? dddef.hasChild(
DD_CMU(close_geometry)) :
true;
2171 xml_coll_t(dddef, _U(
debug)).for_each(Converter<debug>(det, &context));
2176 printout(
INFO,
"DD4CMS",
"+++ Processing the CMS detector description %s", fname.c_str());
2179 Converter<print_xml_doc> print_doc(det, &context);
2182 res.unresolvedConst.reserve(2000);
2183 res.originalConst.reserve(6000);
2184 print_doc((doc = dddef.document()).root());
2185 xml_coll_t(dddef,
DD_CMU(ConstantsSection)).for_each(Converter<ConstantsSection>(det, &context, &res));
2186 xml_coll_t(dddef,
DD_CMU(RotationSection)).for_each(Converter<RotationSection>(det, &context));
2187 xml_coll_t(dddef,
DD_CMU(MaterialSection)).for_each(Converter<MaterialSection>(det, &context));
2189 xml_coll_t(dddef,
DD_CMU(IncludeSection)).for_each(
DD_CMU(Include), Converter<include_load>(det, &context, &res));
2191 for (xml::Document
d : res.includes) {
2192 print_doc((doc = d).root());
2193 Converter<include_constants>(det, &
context, &res)((doc = d).root());
2196 Converter<DDRegistry>(det, &
context, &res)(dddef);
2200 printout(context.debug_constants ? ALWAYS : DEBUG,
2202 "+++ RESOLVING %ld Vectors.....",
2203 context.unresolvedVectors.size());
2205 while (!context.unresolvedVectors.empty()) {
2206 for (
auto it = context.unresolvedVectors.begin(); it != context.unresolvedVectors.end();) {
2207 std::vector<double>
result;
2208 for (
const auto&
i : it->second) {
2209 result.emplace_back(dd4hep::_toDouble(
i));
2211 registry->insert({it->first, result});
2213 it = context.unresolvedVectors.erase(it);
2218 for (xml::Document d : res.includes) {
2219 print_doc((doc = d).root());
2220 xml_coll_t(d.root(),
DD_CMU(MaterialSection)).for_each(Converter<MaterialSection>(det, &context));
2223 PrintLevel printLvl(DEBUG);
2224 if (!context.unresolvedMaterials.empty())
2226 printout(context.debug_materials ? ALWAYS : printLvl,
2228 "+++ RESOLVING %ld unknown material constituents.....",
2229 context.unresolvedMaterials.size());
2233 while (!context.unresolvedMaterials.empty()) {
2234 for (
auto it = context.unresolvedMaterials.begin(); it != context.unresolvedMaterials.end();) {
2235 auto const& name = it->first;
2236 std::vector<bool> valid;
2238 printout(context.debug_materials ? ALWAYS :
WARNING,
2240 "+++ [%06ld] ---------- %s",
2241 context.unresolvedMaterials.size(),
2244 auto mat = ns.material(name);
2245 for (
auto& mit : it->second) {
2246 printout(context.debug_materials ? ALWAYS : WARNING,
2248 "+++ component %-48s Fraction: %.6f",
2251 auto fmat = ns.material(mit.name);
2252 if (
nullptr != fmat.ptr()) {
2253 if (mat.ptr()->GetMaterial()->IsMixture()) {
2254 valid.emplace_back(
true);
2255 static_cast<TGeoMixture*
>(mat.ptr()->GetMaterial())
2256 ->AddElement(fmat.ptr()->GetMaterial(), mit.fraction);
2261 if (valid.size() == it->second.size())
2262 it = context.unresolvedMaterials.erase(it);
2270 if (open_geometry) {
2272 ns.addVolume(det.worldVolume());
2274 for (xml::Document d : res.includes) {
2275 print_doc((doc = d).root());
2276 xml_coll_t(d.root(),
DD_CMU(RotationSection)).for_each(Converter<RotationSection>(det, &context));
2278 for (xml::Document d : res.includes) {
2279 print_doc((doc = d).root());
2280 xml_coll_t(d.root(),
DD_CMU(SolidSection)).for_each(Converter<SolidSection>(det, &context));
2282 for (xml::Document d : res.includes) {
2283 print_doc((doc = d).root());
2284 xml_coll_t(d.root(),
DD_CMU(LogicalPartSection)).for_each(Converter<LogicalPartSection>(det, &context));
2286 for (xml::Document d : res.includes) {
2287 print_doc((doc = d).root());
2288 xml_coll_t(d.root(),
DD_CMU(
Algorithm)).for_each(Converter<DDLAlgorithm>(det, &context));
2290 for (xml::Document d : res.includes) {
2291 print_doc((doc = d).root());
2292 xml_coll_t(d.root(),
DD_CMU(PosPartSection)).for_each(Converter<PosPartSection>(det, &context));
2294 for (xml::Document d : res.includes) {
2295 print_doc((doc = d).root());
2296 xml_coll_t(d.root(),
DD_CMU(SpecParSection)).for_each(Converter<SpecParSection>(det, &context));
2300 for (xml::Document d : res.includes)
2301 Converter<include_unload>(det, &
context, &res)(d.root());
2303 print_doc((doc = dddef.document()).root());
2305 xml_coll_t(dddef,
DD_CMU(SolidSection)).for_each(Converter<SolidSection>(det, &context));
2312 while (!context.unresolvedShapes.empty()) {
2313 for (
auto it = context.unresolvedShapes.begin(); it != context.unresolvedShapes.end();) {
2314 auto const& name = it->first;
2315 auto const& aname = std::visit([](
auto&&
arg) ->
std::string {
return arg.firstSolidName; }, it->second);
2316 auto const& bname = std::visit([](
auto&&
arg) ->
std::string {
return arg.secondSolidName; }, it->second);
2318 auto const& ait = context.shapes.find(aname);
2319 if (ait->second.isValid()) {
2320 auto const& bit = context.shapes.find(bname);
2321 if (bit->second.isValid()) {
2322 dd4hep::Solid shape =
2323 std::visit([&ait, &bit](
auto&&
arg) -> dd4hep::Solid {
return arg.make(ait->second, bit->second); },
2325 context.shapes[
name] = shape;
2326 it = context.unresolvedShapes.erase(it);
2334 xml_coll_t(dddef,
DD_CMU(LogicalPartSection)).for_each(Converter<LogicalPartSection>(det, &context));
2335 xml_coll_t(dddef,
DD_CMU(
Algorithm)).for_each(Converter<DDLAlgorithm>(det, &context));
2336 xml_coll_t(dddef,
DD_CMU(PosPartSection)).for_each(Converter<PosPartSection>(det, &context));
2337 xml_coll_t(dddef,
DD_CMU(SpecParSection)).for_each(Converter<SpecParSection>(det, &context));
2339 printout(
ERROR,
"DD4CMS",
"Exception while processing xml source:%s", doc.uri().c_str());
2340 printout(
ERROR,
"DD4CMS",
"----> %s", e.what());
2345 if (close_geometry) {
2347 Volume geomv = ns.volume(
"cms:OCMS",
false);
2348 if (geomv.isValid())
2349 wv.placeVolume(geomv, 1);
2350 Volume mfv = ns.volume(
"cmsMagneticField:MAGF",
false);
2352 wv.placeVolume(mfv, 1);
2353 Volume mfv1 = ns.volume(
"MagneticFieldVolumes:MAGF",
false);
2355 wv.placeVolume(mfv1, 1);
2358 det.manager().CloseGeometry();
2362 printout(
INFO,
"DDDefinition",
"+++ Finished processing %s", fname.c_str());
2365 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)