diff --git a/DetectorDescription/DDCMS/data/testLogicalParts.xml b/DetectorDescription/DDCMS/data/testLogicalParts.xml index e8133e05ff5bf..4429013c67077 100644 --- a/DetectorDescription/DDCMS/data/testLogicalParts.xml +++ b/DetectorDescription/DDCMS/data/testLogicalParts.xml @@ -126,7 +126,14 @@ - + + + + + + + + diff --git a/DetectorDescription/DDCMS/data/testPosParts.xml b/DetectorDescription/DDCMS/data/testPosParts.xml index 1b97f9814c6ee..26b4e63122198 100644 --- a/DetectorDescription/DDCMS/data/testPosParts.xml +++ b/DetectorDescription/DDCMS/data/testPosParts.xml @@ -184,5 +184,40 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/DetectorDescription/DDCMS/data/testSolids.xml b/DetectorDescription/DDCMS/data/testSolids.xml index 4813d6bc8cabd..6511a25c7104d 100644 --- a/DetectorDescription/DDCMS/data/testSolids.xml +++ b/DetectorDescription/DDCMS/data/testSolids.xml @@ -57,6 +57,8 @@ + + diff --git a/DetectorDescription/DDCMS/interface/DDDetector.h b/DetectorDescription/DDCMS/interface/DDDetector.h index b1b8ec26125c7..8d6f49e8ed543 100644 --- a/DetectorDescription/DDCMS/interface/DDDetector.h +++ b/DetectorDescription/DDCMS/interface/DDDetector.h @@ -2,6 +2,7 @@ #define DetectorDescription_DDCMS_DDDetector_h #include "DetectorDescription/DDCMS/interface/DDVectorRegistry.h" +#include "DetectorDescription/DDCMS/interface/DDParsingContext.h" #include #include #include @@ -11,7 +12,7 @@ class TGeoManager; namespace cms { class DDDetector { public: - explicit DDDetector(const std::string&, const std::string&, bool bigXML = false); + explicit DDDetector(const std::string&, const std::string&, bool bigXML = false, bool makePayload = false); DDDetector() = delete; cms::DDVectorsMap const& vectors() const { return m_vectors; } @@ -34,6 +35,8 @@ namespace cms { dd4hep::Detector const* description() const { return m_description; } + DDParsingContext* m_context; + private: void process(const std::string&); void processXML(const std::string&); diff --git a/DetectorDescription/DDCMS/interface/DDNamespace.h b/DetectorDescription/DDCMS/interface/DDNamespace.h index ddadd38665444..8dadbefa6bf36 100644 --- a/DetectorDescription/DDCMS/interface/DDNamespace.h +++ b/DetectorDescription/DDCMS/interface/DDNamespace.h @@ -10,6 +10,12 @@ namespace cms { + namespace rotation_utils { + std::string rotHash(const Double_t* rot); + std::string rotHash(const dd4hep::Rotation3D& rot); + double roundBinary(double value); + } // namespace rotation_utils + class DDParsingContext; using DDVectorsMap = std::unordered_map>; @@ -57,9 +63,11 @@ namespace cms { dd4hep::Solid addSolidNS(const std::string& name, dd4hep::Solid solid) const; dd4hep::Assembly assembly(const std::string& name) const; - dd4hep::Assembly addAssembly(dd4hep::Assembly asmb) const; + dd4hep::Assembly addAssembly(dd4hep::Assembly asmb, bool addSolid = true) const; + dd4hep::Assembly addAssemblySolid(dd4hep::Assembly assembly) const; dd4hep::Volume volume(const std::string& name, bool exc = true) const; + dd4hep::Volume* getVolPtr(const std::string& name) const; dd4hep::Volume addVolume(dd4hep::Volume vol) const; dd4hep::Volume addVolumeNS(dd4hep::Volume vol) const; diff --git a/DetectorDescription/DDCMS/interface/DDParsingContext.h b/DetectorDescription/DDCMS/interface/DDParsingContext.h index d885a9efe36cd..ca95d16507f8b 100644 --- a/DetectorDescription/DDCMS/interface/DDParsingContext.h +++ b/DetectorDescription/DDCMS/interface/DDParsingContext.h @@ -6,22 +6,30 @@ #include #include #include +#include #include namespace cms { class DDParsingContext { public: - DDParsingContext(dd4hep::Detector& det) : description(det) { + DDParsingContext(dd4hep::Detector& det, bool makePayloadArg = false) + : makePayload(makePayloadArg), description(det) { assemblies.reserve(100); + assemblySolids.reserve(100); rotations.reserve(3000); shapes.reserve(4000); volumes.reserve(3000); + volPtrs.reserve(3000); unresolvedMaterials.reserve(300); unresolvedVectors.reserve(300); unresolvedShapes.reserve(1000); namespaces.emplace_back(""); + if (makePayload) { + rotRevMap.reserve(3000); + allCompMaterials.reserve(400); + } } DDParsingContext() = delete; @@ -64,16 +72,21 @@ namespace cms { bool debug_namespaces = false; bool debug_algorithms = false; bool debug_specpars = false; + bool makePayload = false; dd4hep::Detector& description; std::unordered_map assemblies; + std::unordered_set assemblySolids; std::unordered_map rotations; + std::unordered_map rotRevMap; std::unordered_map shapes; std::unordered_map volumes; + std::unordered_map volPtrs; std::vector namespaces; std::unordered_map> unresolvedMaterials; + std::unordered_map>> allCompMaterials; std::unordered_map> unresolvedVectors; std::unordered_map, diff --git a/DetectorDescription/DDCMS/interface/DDSolidShapes.h b/DetectorDescription/DDCMS/interface/DDSolidShapes.h index b101c795e7ab4..9db8af26f1d63 100644 --- a/DetectorDescription/DDCMS/interface/DDSolidShapes.h +++ b/DetectorDescription/DDCMS/interface/DDSolidShapes.h @@ -92,9 +92,11 @@ namespace cms { ddcuttubs = 18, ddextrudedpolygon = 19, ddtrd1 = 20, + ddtrd2 = 21, + ddassembly = 22 }; - const std::array, 19> DDSolidShapeMap{ + const std::array, 21> DDSolidShapeMap{ {{DDSolidShape::dd_not_init, "Solid not initialized"}, {DDSolidShape::ddbox, "Box"}, {DDSolidShape::ddtubs, "Tube"}, @@ -113,9 +115,11 @@ namespace cms { {DDSolidShape::ddellipticaltube, "EllipticalTube"}, {DDSolidShape::ddcuttubs, "CutTube"}, {DDSolidShape::ddextrudedpolygon, "ExtrudedPolygon"}, - {DDSolidShape::ddtrd1, "Trd1"}}}; + {DDSolidShape::ddtrd1, "Trd1"}, + {DDSolidShape::ddtrd2, "Trd2"}, + {DDSolidShape::ddassembly, "Assembly"}}}; - const std::array, 20> LegacySolidShapeMap{ + const std::array, 21> LegacySolidShapeMap{ {{LegacySolidShape::dd_not_init, cms::DDSolidShape::dd_not_init}, {LegacySolidShape::ddbox, cms::DDSolidShape::ddbox}, {LegacySolidShape::ddtubs, cms::DDSolidShape::ddtubs}, @@ -135,7 +139,8 @@ namespace cms { {LegacySolidShape::ddsphere, cms::DDSolidShape::ddsphere}, {LegacySolidShape::ddellipticaltube, cms::DDSolidShape::ddellipticaltube}, {LegacySolidShape::ddcuttubs, cms::DDSolidShape::ddcuttubs}, - {LegacySolidShape::ddextrudedpolygon, cms::DDSolidShape::ddextrudedpolygon}}}; + {LegacySolidShape::ddextrudedpolygon, cms::DDSolidShape::ddextrudedpolygon}, + {LegacySolidShape::ddassembly, cms::DDSolidShape::ddassembly}}}; } // namespace cms diff --git a/DetectorDescription/DDCMS/plugins/DDDetectorESProducer.cc b/DetectorDescription/DDCMS/plugins/DDDetectorESProducer.cc index a127205940127..9fff129717e2c 100644 --- a/DetectorDescription/DDCMS/plugins/DDDetectorESProducer.cc +++ b/DetectorDescription/DDCMS/plugins/DDDetectorESProducer.cc @@ -59,6 +59,7 @@ class DDDetectorESProducer : public ESProducer, public EventSetupRecordIntervalF const string confGeomXMLFiles_; const string rootDDName_; const string label_; + const bool makePayload_; edm::ESGetToken mfToken_; edm::ESGetToken geomToken_; }; @@ -68,7 +69,8 @@ DDDetectorESProducer::DDDetectorESProducer(const ParameterSet& iConfig) appendToDataLabel_(iConfig.getParameter("appendToDataLabel")), confGeomXMLFiles_(fromDB_ ? "none" : iConfig.getParameter("confGeomXMLFiles").fullPath()), rootDDName_(iConfig.getParameter("rootDDName")), - label_(iConfig.getParameter("label")) { + label_(iConfig.getParameter("label")), + makePayload_(iConfig.getParameter("makePayload")) { usesResources({edm::ESSharedResourceNames::kDD4Hep}); if (rootDDName_ == "MagneticFieldVolumes:MAGF" || rootDDName_ == "cmsMagneticField:MAGF") { auto c = setWhatProduced(this, @@ -96,12 +98,14 @@ void DDDetectorESProducer::fillDescriptions(ConfigurationDescriptions& descripti desc.add("rootDDName", "cms:OCMS"); desc.add("label", ""); desc.add("fromDB", false); + desc.add("makePayload", false); descriptions.add("DDDetectorESProducer", desc); edm::ParameterSetDescription descDB; descDB.add("rootDDName", "cms:OCMS"); descDB.add("label", "Extended"); descDB.add("fromDB", true); + descDB.add("makePayload", false); descriptions.add("DDDetectorESProducerFromDB", descDB); } @@ -131,13 +135,13 @@ DDDetectorESProducer::ReturnType DDDetectorESProducer::produceGeom(const IdealGe return make_unique(label_, string(tb->begin(), tb->end()), true); } else { - return make_unique(appendToDataLabel_, confGeomXMLFiles_); + return make_unique(appendToDataLabel_, confGeomXMLFiles_, false, makePayload_); } } DDDetectorESProducer::ReturnType DDDetectorESProducer::produce() { LogVerbatim("Geometry") << "DDDetectorESProducer::Produce " << appendToDataLabel_; - return make_unique(appendToDataLabel_, confGeomXMLFiles_); + return make_unique(appendToDataLabel_, confGeomXMLFiles_, false, makePayload_); } DEFINE_FWK_EVENTSETUP_SOURCE(DDDetectorESProducer); diff --git a/DetectorDescription/DDCMS/plugins/dd4hep/DDDefinitions2Objects.cc b/DetectorDescription/DDCMS/plugins/dd4hep/DDDefinitions2Objects.cc index fadc63983d531..fa3403c9b3923 100644 --- a/DetectorDescription/DDCMS/plugins/dd4hep/DDDefinitions2Objects.cc +++ b/DetectorDescription/DDCMS/plugins/dd4hep/DDDefinitions2Objects.cc @@ -29,6 +29,8 @@ #include #include +// #define EDM_ML_DEBUG 1 + using namespace std; using namespace dd4hep; using namespace cms; @@ -75,6 +77,7 @@ namespace dd4hep { class SolidSection; class DDLExtrudedPolygon; class DDLShapeless; + class DDLAssembly; class DDLTrapezoid; class DDLEllipticalTube; class DDLPseudoTrap; @@ -202,6 +205,9 @@ namespace dd4hep { /// Converter for tags template <> void Converter::operator()(xml_h element) const; + /// Converter for tags + template <> + void Converter::operator()(xml_h element) const; /// Converter for tags template <> void Converter::operator()(xml_h element) const; @@ -385,6 +391,9 @@ void Converter::operator()(xml_h element) const { case hash("ShapelessSolid"): Converter(description, ns.context(), optional)(solid); break; + case hash("Assembly"): + Converter(description, ns.context(), optional)(solid); + break; default: throw std::runtime_error("Request to process unknown shape '" + xml_dim_t(solid).nameStr() + "' [" + solid.tag() + "]"); @@ -600,6 +609,11 @@ void Converter::operator()(xml_h element) const { double fraction = xfrac.fraction(); string fracname = ns.realName(xfrac_mat.nameStr()); + if (ns.context()->makePayload) { + ns.context()->allCompMaterials[nam].first = density; + ns.context()->allCompMaterials[nam].second.emplace_back( + cms::DDParsingContext::CompositeMaterial(ns.prepend(fracname), fraction)); + } TGeoMaterial* frac_mat = mgr.GetMaterial(fracname.c_str()); if (frac_mat == nullptr) // Try to find it within this namespace frac_mat = mgr.GetMaterial(ns.prepend(fracname).c_str()); @@ -791,6 +805,13 @@ void Converter::operator()(xml_h element) const { string volName = ns.prepend(e.attr(_U(name))); Solid solid = ns.solid(sol); Material material = ns.material(mat); + if (ns.context()->assemblySolids.count(sol) == 1) { + // To match the general paradigm, an assembly starts as a solid, + // and then a logical part is made of the solid. However, the + // solid is just a dummy whose names tags it as an assembly. + ns.addAssembly(volName, false); + return; + } #ifdef EDM_ML_DEBUG Volume volume = @@ -848,6 +869,55 @@ void Converter::operator()(xml_h element) const { *tr = Transform3D(rot, pos); } +static void placeAssembly(Volume* parentPtr, + const string& parentName, + Volume* childPtr, + const string& childName, + int copy, + const Transform3D& transform, + cms::DDNamespace& ns) { +#ifdef EDM_ML_DEBUG + + printout(ns.context()->debug_placements ? ALWAYS : DEBUG, + "DD4CMS", + "+++ Parent vol: %-24s Child: %-32s, copy:%d", + parentName.c_str(), + childName.c_str(), + copy); + +#endif + + TGeoShape* shape = (*childPtr)->GetShape(); + // Need to fix the daughter's BBox of assemblies, if the BBox was not calculated.... + if (shape->IsA() == TGeoShapeAssembly::Class()) { + TGeoShapeAssembly* as = (TGeoShapeAssembly*)shape; + if (std::fabs(as->GetDX()) < numeric_limits::epsilon() && + std::fabs(as->GetDY()) < numeric_limits::epsilon() && + std::fabs(as->GetDZ()) < numeric_limits::epsilon()) { + as->NeedsBBoxRecompute(); + as->ComputeBBox(); + } + } + TGeoNode* n; + TString nam_id = TString::Format("%s_%d", (*childPtr)->GetName(), copy); + n = static_cast((*parentPtr)->GetNode(nam_id)); + if (n != nullptr) { + printout(ERROR, "PlacedVolume", "++ Attempt to add already existing node %s", (const char*)nam_id); + return; + } + + PlacedVolume pv; + if ((*childPtr)->IsAssembly()) { + pv = parentPtr->placeVolume(ns.assembly(childName), copy, transform); + } else { + pv = parentPtr->placeVolume(*childPtr, copy, transform); + } + + if (!pv.isValid()) { + printout(ERROR, "DD4CMS", "+++ Placement FAILED! Parent:%s Child:%s", parentName.c_str(), childName.c_str()); + } +} + /// Converter for tags template <> void Converter::operator()(xml_h element) const { @@ -856,8 +926,13 @@ void Converter::operator()(xml_h element) const { int copy = e.attr(DD_CMU(copyNumber)); string parentName = ns.prepend(ns.attr(e.child(DD_CMU(rParent)), _U(name))); string childName = ns.prepend(ns.attr(e.child(DD_CMU(rChild)), _U(name))); + Transform3D transform; + Converter(description, param, &transform)(element); + Volume parent = ns.volume(parentName, false); Volume child = ns.volume(childName, false); + Volume* parentPtr = ns.getVolPtr(parentName); + Volume* childPtr = ns.getVolPtr(childName); #ifdef EDM_ML_DEBUG @@ -875,11 +950,26 @@ void Converter::operator()(xml_h element) const { if (!parent.isValid() && strchr(parentName.c_str(), NAMESPACE_SEP) == nullptr) parentName = ns.prepend(parentName); - parent = ns.volume(parentName); + parent = ns.volume(parentName, false); + if (parentPtr == nullptr) + parentPtr = ns.getVolPtr(parentName); + if (!parent.isValid() && parentPtr == nullptr) + throw runtime_error("Unknown volume identifier:" + parentName); if (!child.isValid() && strchr(childName.c_str(), NAMESPACE_SEP) == nullptr) childName = ns.prepend(childName); child = ns.volume(childName, false); + if (childPtr == nullptr) + childPtr = ns.getVolPtr(childName); + if (childPtr != nullptr && parentPtr != nullptr && ((*parentPtr)->IsAssembly() || (*childPtr)->IsAssembly())) { + printout(ns.context()->debug_placements ? ALWAYS : DEBUG, + "DD4CMS", + "***** Placing assembly parent %s, child %s", + parentName.c_str(), + childName.c_str()); + placeAssembly(parentPtr, parentName, childPtr, childName, copy, transform, ns); + return; + } #ifdef EDM_ML_DEBUG @@ -897,9 +987,6 @@ void Converter::operator()(xml_h element) const { PlacedVolume pv; if (child.isValid()) { - Transform3D transform; - Converter(description, param, &transform)(element); - // FIXME: workaround for Reflection rotation // copy from DDCore/src/Volumes.cpp to replace // static PlacedVolume _addNode(TGeoVolume* par, TGeoVolume* daughter, int id, TGeoMatrix* transform) @@ -924,7 +1011,7 @@ void Converter::operator()(xml_h element) const { TString nam_id = TString::Format("%s_%d", child->GetName(), copy); n = static_cast(parent->GetNode(nam_id)); if (n != nullptr) { - printout(ERROR, "PlacedVolume", "++ Attempt to add already exiting node %s", (const char*)nam_id); + printout(ERROR, "PlacedVolume", "++ Attempt to add already existing node %s", (const char*)nam_id); } Rotation3D rot(transform.Rotation()); @@ -1609,7 +1696,7 @@ void Converter::operator()(xml_h element) const { printout(ns.context()->debug_shapes ? ALWAYS : DEBUG, "DD4CMS", - "+ Shapeless: THIS ONE CAN ONLY BE USED AT THE VOLUME LEVEL -> Assembly%s", + "+ Shapeless: THIS ONE CAN ONLY BE USED AT THE VOLUME LEVEL -> Shapeless: %s", nam.c_str()); #endif @@ -1617,6 +1704,22 @@ void Converter::operator()(xml_h element) const { ns.addSolid(nam, Box(1, 1, 1)); } +/// Converter for tags +template <> +void Converter::operator()(xml_h element) const { + cms::DDNamespace ns(_param()); + xml_dim_t e(element); + string nam = e.nameStr(); + +#ifdef EDM_ML_DEBUG + printout( + ns.context()->debug_shapes ? ALWAYS : DEBUG, "DD4CMS", "+ Assembly: Adding solid -> Assembly: %s", nam.c_str()); +#endif + + ns.addSolid(nam, Box(nam, 1, 1, 1)); // Add a dummy solid to allow assembly to be treated like other volumes + ns.addAssemblySolid(nam); +} + /// Converter for tags template <> void Converter::operator()(xml_h element) const { @@ -1760,6 +1863,9 @@ void Converter::operator()(xml_h element) const { Volume child = parent.divide(childName, static_cast(axesmap.at(axis)), numCopies, startInDeg, widthInDeg); ns.context()->volumes[childName] = child; + // ns.context()->volPtrs[childName] = &(ns.context()->volumes[childName]); + // TGeoVolumeMulti objects not needed in volPtrs list, and they cause + // crash when IsAssembly() method is called on them. #ifdef EDM_ML_DEBUG @@ -1795,6 +1901,7 @@ void Converter::operator()(xml_h element) const { Volume child = parent.divide(childName, static_cast(axesmap.at(axis)), nReplicas, -dy + offset + width, width); ns.context()->volumes[childName] = child; + // ns.context()->volPtrs[childName] = &(ns.context()->volumes[childName]); #ifdef EDM_ML_DEBUG @@ -1809,7 +1916,6 @@ void Converter::operator()(xml_h element) const { child->IsVolumeMulti() ? "YES" : "NO"); #endif - } else { printout(ERROR, "DD4CMS", "++ FAILED Division of a %s is not implemented yet!", parent.solid().type()); } @@ -2054,7 +2160,7 @@ void Converter::operator()(xml_h element) const { static long load_dddefinition(Detector& det, xml_h element) { xml_elt_t dddef(element); if (dddef) { - cms::DDParsingContext context(det); + cms::DDParsingContext& context = *det.extension(); cms::DDNamespace ns(context); ns.addConstantNS("world_x", "101*m", "number"); ns.addConstantNS("world_y", "101*m", "number"); diff --git a/DetectorDescription/DDCMS/src/DDDetector.cc b/DetectorDescription/DDCMS/src/DDDetector.cc index f9f97890e50bf..159f081d868cf 100644 --- a/DetectorDescription/DDCMS/src/DDDetector.cc +++ b/DetectorDescription/DDCMS/src/DDDetector.cc @@ -10,7 +10,8 @@ namespace cms { - DDDetector::DDDetector(const std::string& tag, const std::string& fileName, bool bigXML) : m_tag(tag) { + DDDetector::DDDetector(const std::string& tag, const std::string& fileName, bool bigXML, bool makePayload) + : m_tag(tag) { //We do not want to use any previously created TGeoManager but we do want to reset after we are done. auto oldGeoManager = gGeoManager; gGeoManager = nullptr; @@ -19,6 +20,8 @@ namespace cms { m_description = &dd4hep::Detector::getInstance(tag); m_description->addExtension(&m_vectors); + m_context = new cms::DDParsingContext(*m_description, makePayload); + m_description->addExtension(m_context); m_description->addExtension(&m_partsels); m_description->addExtension(&m_specpars); m_description->setStdConditions("NTP"); @@ -27,6 +30,8 @@ namespace cms { processXML(fileName); else process(fileName); + if (makePayload == false) // context no longer needed if not making payloads + m_description->removeExtension(); } void DDDetector::process(const std::string& fileName) { @@ -38,6 +43,7 @@ namespace cms { void DDDetector::processXML(const std::string& xml) { edm::LogVerbatim("Geometry") << "DDDetector::processXML process string size " << xml.size() << " with max_size " << xml.max_size(); + edm::LogVerbatim("Geometry") << "DDDetector::processXML XML string contents = " << xml.substr(0, 800); std::string name("DD4hep_XMLProcessor"); dd4hep::xml::DocumentHolder doc(dd4hep::xml::DocumentHandler().parse(xml.c_str(), xml.length())); diff --git a/DetectorDescription/DDCMS/src/DDFilteredView.cc b/DetectorDescription/DDCMS/src/DDFilteredView.cc index d3b1726d9b37c..dcb2a0938f1ba 100644 --- a/DetectorDescription/DDCMS/src/DDFilteredView.cc +++ b/DetectorDescription/DDCMS/src/DDFilteredView.cc @@ -552,6 +552,9 @@ const std::vector DDFilteredView::parameters() const { const cms::DDSolidShape DDFilteredView::shape() const { assert(node_); + if ((volume().volume())->IsAssembly()) { + return (cms::DDSolidShape::ddbox); // Return dummy box + } return cms::dd::value(cms::DDSolidShapeMap, std::string(node_->GetVolume()->GetShape()->GetTitle())); } @@ -859,7 +862,13 @@ std::string_view DDFilteredView::fullName() const { return (node_ == nullptr ? std::string_view() : (volume().volume().name())); } -dd4hep::Solid DDFilteredView::solid() const { return (volume().volume().solid()); } +dd4hep::Solid DDFilteredView::solid() const { + if ((volume().volume())->IsAssembly()) { + std::string solName(name()); + return (dd4hep::Box(solName, 1., 1., 1.)); + } + return (volume().volume().solid()); +} unsigned short DDFilteredView::copyNum() const { return (volume().copyNumber()); } diff --git a/DetectorDescription/DDCMS/src/DDNamespace.cc b/DetectorDescription/DDCMS/src/DDNamespace.cc index 4628633f94895..a780974126d20 100644 --- a/DetectorDescription/DDCMS/src/DDNamespace.cc +++ b/DetectorDescription/DDCMS/src/DDNamespace.cc @@ -1,5 +1,6 @@ #include "DetectorDescription/DDCMS/interface/DDNamespace.h" #include "DetectorDescription/DDCMS/interface/DDParsingContext.h" +#include "DataFormats/Math/interface/Rounding.h" #include "DD4hep/Path.h" #include "DD4hep/Printout.h" #include "XML/XML.h" @@ -11,6 +12,35 @@ using namespace std; using namespace cms; +double cms::rotation_utils::roundBinary(double value) { + value = cms_rounding::roundIfNear0(value); + static constexpr double roundingVal = 1 << 14; + value = (round(value * roundingVal) / roundingVal); + // Set -0 to 0 + return (cms_rounding::roundIfNear0(value)); +} + +std::string cms::rotation_utils::rotHash(const Double_t* rot) { + std::string hashVal; + for (int row = 0; row <= 2; ++row) { + for (int col = 0; col <= 2; ++col) { + hashVal += std::to_string(roundBinary(rot[(3 * row) + col])); + } + } + return (hashVal); +} + +std::string cms::rotation_utils::rotHash(const dd4hep::Rotation3D& rot) { + std::string hashVal; + std::vector matrix; + matrix.assign(9, 0.); + rot.GetComponents(matrix.begin()); + for (double val : matrix) { + hashVal += std::to_string(roundBinary(val)); + } + return (hashVal); +} + DDNamespace::DDNamespace(DDParsingContext* context, xml_h element) : m_context(context) { dd4hep::Path path(xml_handler_t::system_path(element)); m_name = path.filename().substr(0, path.filename().rfind('.')); @@ -120,6 +150,10 @@ dd4hep::Material DDNamespace::material(const string& name) const { void DDNamespace::addRotation(const string& name, const dd4hep::Rotation3D& rot) const { string n = prepend(name); m_context->rotations[n] = rot; + if (m_context->makePayload) { + string hashVal = cms::rotation_utils::rotHash(rot); + m_context->rotRevMap[hashVal] = n; + } } const dd4hep::Rotation3D& DDNamespace::rotation(const string& name) const { @@ -148,6 +182,7 @@ dd4hep::Volume DDNamespace::addVolumeNS(dd4hep::Volume vol) const { dd4hep::Material m = vol.material(); vol->SetName(n.c_str()); m_context->volumes[n] = vol; + m_context->volPtrs[n] = &(m_context->volumes[n]); const char* solidName = "Invalid solid"; if (s.isValid()) // Protect against seg fault solidName = s.name(); // If Solid is not valid, s.name() will seg fault. @@ -161,12 +196,12 @@ dd4hep::Volume DDNamespace::addVolumeNS(dd4hep::Volume vol) const { return vol; } -/// Add rotation matrix to current namespace dd4hep::Volume DDNamespace::addVolume(dd4hep::Volume vol) const { string n = prepend(vol.name()); dd4hep::Solid s = vol.solid(); dd4hep::Material m = vol.material(); m_context->volumes[n] = vol; + m_context->volPtrs[n] = &(m_context->volumes[n]); const char* solidName = "Invalid solid"; if (s.isValid()) // Protect against seg fault solidName = s.name(); // If Solid is not valid, s.name() will seg fault. @@ -181,11 +216,23 @@ dd4hep::Volume DDNamespace::addVolume(dd4hep::Volume vol) const { return vol; } -dd4hep::Assembly DDNamespace::addAssembly(dd4hep::Assembly assembly) const { +dd4hep::Assembly DDNamespace::addAssembly(dd4hep::Assembly assembly, bool addSolid) const { string n = assembly.name(); m_context->assemblies[n] = assembly; + m_context->volPtrs[n] = &(m_context->assemblies[n]); + if (addSolid) { // In algorithms, Assembly solids are not added separately, so add it here + m_context->assemblySolids.emplace(n); + } + dd4hep::printout( + m_context->debug_volumes ? dd4hep::ALWAYS : dd4hep::DEBUG, "DD4CMS", "+++ Add assembly: %-38s", n.c_str()); + return assembly; +} + +dd4hep::Assembly DDNamespace::addAssemblySolid(dd4hep::Assembly assembly) const { + string n = prepend(assembly.name()); + m_context->assemblySolids.emplace(n); dd4hep::printout( - m_context->debug_volumes ? dd4hep::ALWAYS : dd4hep::DEBUG, "DD4CMS", "+++ Add assembly:%-38s", assembly.name()); + m_context->debug_volumes ? dd4hep::ALWAYS : dd4hep::DEBUG, "DD4CMS", "+++ Add assembly solid: %-38s", n.c_str()); return assembly; } @@ -218,6 +265,19 @@ dd4hep::Volume DDNamespace::volume(const string& name, bool exc) const { return nullptr; } +dd4hep::Volume* DDNamespace::getVolPtr(const string& name) const { + auto i = m_context->volPtrs.find(name); + if (i != m_context->volPtrs.end()) { + return (*i).second; + } + if (name.front() == NAMESPACE_SEP) { + i = m_context->volPtrs.find(name.substr(1, name.size())); + if (i != m_context->volPtrs.end()) + return (*i).second; + } + return nullptr; +} + dd4hep::Solid DDNamespace::addSolidNS(const string& name, dd4hep::Solid solid) const { dd4hep::printout(m_context->debug_shapes ? dd4hep::ALWAYS : dd4hep::DEBUG, "DD4CMS", diff --git a/DetectorDescription/DDCMS/test/DDSolidLegacyShapes.cppunit.cc b/DetectorDescription/DDCMS/test/DDSolidLegacyShapes.cppunit.cc index 636f8e462d39b..dcfaca7b4fbfe 100644 --- a/DetectorDescription/DDCMS/test/DDSolidLegacyShapes.cppunit.cc +++ b/DetectorDescription/DDCMS/test/DDSolidLegacyShapes.cppunit.cc @@ -77,6 +77,9 @@ void testDDSolidLegacyShapes::checkDDSolidLegacyShapes() { LegacySolidShape legacyShapeless = cms::dd::value(cms::LegacySolidShapeMap, cms::DDSolidShape::ddshapeless); CPPUNIT_ASSERT(legacyShapeless == LegacySolidShape::ddshapeless); + LegacySolidShape legacyAssembly = cms::dd::value(cms::LegacySolidShapeMap, cms::DDSolidShape::ddassembly); + CPPUNIT_ASSERT(legacyAssembly == LegacySolidShape::ddassembly); + LegacySolidShape legacyPseudotrap = cms::dd::value(cms::LegacySolidShapeMap, cms::DDSolidShape::ddpseudotrap); CPPUNIT_ASSERT(legacyPseudotrap == LegacySolidShape::ddpseudotrap); @@ -96,8 +99,8 @@ void testDDSolidLegacyShapes::checkDDSolidLegacyShapes() { cms::dd::value(cms::LegacySolidShapeMap, cms::DDSolidShape::ddextrudedpolygon); CPPUNIT_ASSERT(legacyExtrudedpolygon == LegacySolidShape::ddextrudedpolygon); - int ids[] = {0, 0, 1, 1, 2, 2, 3, 3, 4, 4, 5, 5, 7, 5, 6, 6, 8, 6, 9, 9, - 10, 10, 11, 11, 12, 12, 13, 13, 14, 14, 15, 15, 16, 16, 17, 17, 18, 18, 19, 19}; + int ids[] = {0, 0, 1, 1, 2, 2, 3, 3, 4, 4, 5, 5, 7, 5, 6, 6, 8, 6, 9, 9, 10, + 10, 11, 11, 12, 12, 13, 13, 14, 14, 15, 15, 16, 16, 17, 17, 18, 18, 19, 19, 20, 22}; int i = 0; for (const auto it : LegacySolidShapeMap) { CPPUNIT_ASSERT(static_cast(it.value) == ids[i++]);