File indexing completed on 2023-03-17 10:51:45
0001 #include "DetectorDescription/DDCMS/interface/DDNamespace.h"
0002 #include "DetectorDescription/DDCMS/interface/DDParsingContext.h"
0003 #include "DataFormats/Math/interface/Rounding.h"
0004 #include "DD4hep/Path.h"
0005 #include "DD4hep/Printout.h"
0006 #include "Evaluator/Evaluator.h"
0007 #include "XML/XML.h"
0008
0009 #include <TClass.h>
0010 #include <iomanip>
0011 #include <sstream>
0012 #include <unordered_map>
0013 #include <vector>
0014
0015 using namespace std;
0016 using namespace cms;
0017
0018 double cms::rotation_utils::roundBinary(double value) {
0019 value = cms_rounding::roundIfNear0(value);
0020 static constexpr double roundingVal = 1 << 24;
0021 value = (round(value * roundingVal) / roundingVal);
0022
0023 return (cms_rounding::roundIfNear0(value));
0024 }
0025
0026 std::string cms::rotation_utils::rotHash(const Double_t* rot) {
0027 std::string hashVal;
0028 for (int row = 0; row <= 2; ++row) {
0029 for (int col = 0; col <= 2; ++col) {
0030 std::ostringstream numStream;
0031 numStream << std::fixed << std::setprecision(7);
0032 numStream << roundBinary(rot[(3 * row) + col]);
0033 hashVal += numStream.str();
0034 }
0035 }
0036 return (hashVal);
0037 }
0038
0039 std::string cms::rotation_utils::rotHash(const dd4hep::Rotation3D& rot) {
0040 std::string hashVal;
0041 std::vector<double> matrix;
0042 matrix.assign(9, 0.);
0043 rot.GetComponents(matrix.begin());
0044 for (double val : matrix) {
0045 std::ostringstream numStream;
0046 numStream << std::fixed << std::setprecision(7);
0047 numStream << roundBinary(val);
0048 hashVal += numStream.str();
0049 }
0050 return (hashVal);
0051 }
0052
0053 DDNamespace::DDNamespace(DDParsingContext* context, xml_h element) : m_context(context) {
0054 dd4hep::Path path(xml_handler_t::system_path(element));
0055 m_name = path.filename().substr(0, path.filename().rfind('.'));
0056 if (!m_name.empty())
0057 m_name += NAMESPACE_SEP;
0058 m_context->namespaces.emplace_back(m_name);
0059 m_pop = true;
0060 dd4hep::printout(m_context->debug_namespaces ? dd4hep::ALWAYS : dd4hep::DEBUG,
0061 "DD4CMS",
0062 "+++ Current namespace is now: %s",
0063 m_name.c_str());
0064 }
0065
0066 DDNamespace::DDNamespace(DDParsingContext& ctx, xml_h element, bool) : m_context(&ctx) {
0067 dd4hep::Path path(xml_handler_t::system_path(element));
0068 m_name = path.filename().substr(0, path.filename().rfind('.'));
0069 if (!m_name.empty())
0070 m_name += NAMESPACE_SEP;
0071 m_context->namespaces.emplace_back(m_name);
0072 m_pop = true;
0073 dd4hep::printout(m_context->debug_namespaces ? dd4hep::ALWAYS : dd4hep::DEBUG,
0074 "DD4CMS",
0075 "+++ Current namespace is now: %s",
0076 m_name.c_str());
0077 }
0078
0079 DDNamespace::DDNamespace(DDParsingContext* ctx) : m_context(ctx) {
0080 if (!m_context->namespaces.empty())
0081 m_name = m_context->namespaces.back();
0082 }
0083
0084 DDNamespace::DDNamespace(DDParsingContext& ctx) : m_context(&ctx) {
0085 if (!m_context->namespaces.empty())
0086 m_name = m_context->namespaces.back();
0087 }
0088
0089 DDNamespace::~DDNamespace() {
0090 if (m_pop) {
0091 m_context->namespaces.pop_back();
0092 dd4hep::printout(m_context->debug_namespaces ? dd4hep::ALWAYS : dd4hep::DEBUG,
0093 "DD4CMS",
0094 "+++ Current namespace is now: %s",
0095 m_context->ns().c_str());
0096 }
0097 }
0098
0099 string DDNamespace::prepend(const string& n) const {
0100 if (strchr(n.c_str(), NAMESPACE_SEP) == nullptr)
0101 return m_name + n;
0102 else
0103 return n;
0104 }
0105
0106 string DDNamespace::realName(const string& v) const {
0107 size_t idx, idq, idp;
0108 string val = v;
0109 while ((idx = val.find('[')) != string::npos) {
0110 val.erase(idx, 1);
0111 idp = val.find(NAMESPACE_SEP, idx);
0112 idq = val.find(']', idx);
0113 val.erase(idq, 1);
0114 if (idp == string::npos || idp > idq)
0115 val.insert(idx, m_name);
0116 else if (idp != string::npos && idp < idq)
0117 val[idp] = NAMESPACE_SEP;
0118 }
0119 return val;
0120 }
0121
0122 string DDNamespace::nsName(const string& name) {
0123 size_t idx;
0124 if ((idx = name.find(NAMESPACE_SEP)) != string::npos)
0125 return name.substr(0, idx);
0126 return "";
0127 }
0128
0129 string DDNamespace::objName(const string& name) {
0130 size_t idx;
0131 if ((idx = name.find(NAMESPACE_SEP)) != string::npos)
0132 return name.substr(idx + 1);
0133 return "";
0134 }
0135
0136 void DDNamespace::addConstant(const string& name, const string& val, const string& type) const {
0137 addConstantNS(prepend(name), val, type);
0138 }
0139
0140 namespace dd4hep {
0141 dd4hep::tools::Evaluator& evaluator();
0142 }
0143
0144 void DDNamespace::addConstantNS(const string& name, const string& val, const string& type) const {
0145 const string& v = val;
0146 const string& n = name;
0147 dd4hep::printout(m_context->debug_constants ? dd4hep::ALWAYS : dd4hep::DEBUG,
0148 "DD4CMS",
0149 "+++ Add constant object: %-40s = %s [type:%s]",
0150 n.c_str(),
0151 v.c_str(),
0152 type.c_str());
0153 const dd4hep::tools::Evaluator& eval(dd4hep::evaluator());
0154 bool constExists = eval.findVariable(n);
0155 dd4hep::printout(
0156 m_context->debug_constants ? dd4hep::ALWAYS : dd4hep::DEBUG, "DD4CMS", "findVariable result = %d", constExists);
0157 if (constExists == false) {
0158
0159 dd4hep::_toDictionary(n, v, type);
0160 }
0161 dd4hep::Constant c(n, v, type);
0162
0163 m_context->description.addConstant(c);
0164 }
0165
0166 dd4hep::Material DDNamespace::material(const string& name) const {
0167 return m_context->description.material(realName(name));
0168 }
0169
0170 void DDNamespace::addRotation(const string& name, const dd4hep::Rotation3D& rot) const {
0171 string n = prepend(name);
0172 m_context->rotations[n] = rot;
0173 if (m_context->makePayload) {
0174 string hashVal = cms::rotation_utils::rotHash(rot);
0175 if (m_context->rotRevMap.find(hashVal) == m_context->rotRevMap.end()) {
0176
0177 m_context->rotRevMap[hashVal] = n;
0178 }
0179 }
0180 }
0181
0182 const dd4hep::Rotation3D& DDNamespace::rotation(const string& name) const {
0183 static const dd4hep::Rotation3D s_null;
0184 size_t idx;
0185 auto i = m_context->rotations.find(name);
0186 if (i != m_context->rotations.end())
0187 return (*i).second;
0188 else if (name == "NULL")
0189 return s_null;
0190 else if (name.find(":NULL") == name.length() - 5)
0191 return s_null;
0192 string n = name;
0193 if ((idx = name.find(NAMESPACE_SEP)) != string::npos) {
0194 n[idx] = NAMESPACE_SEP;
0195 i = m_context->rotations.find(n);
0196 if (i != m_context->rotations.end())
0197 return (*i).second;
0198 }
0199 throw runtime_error("Unknown rotation identifier:" + name);
0200 }
0201
0202 dd4hep::Volume DDNamespace::addVolumeNS(dd4hep::Volume vol) const {
0203 string n = prepend(vol.name());
0204 dd4hep::Solid s = vol.solid();
0205 dd4hep::Material m = vol.material();
0206 vol->SetName(n.c_str());
0207 m_context->volumes[n] = vol;
0208 const char* solidName = "Invalid solid";
0209 if (s.isValid())
0210 solidName = s.name();
0211 dd4hep::printout(m_context->debug_volumes ? dd4hep::ALWAYS : dd4hep::DEBUG,
0212 "DD4CMS",
0213 "+++ Add volumeNS:%-38s Solid:%-26s[%-16s] Material:%s",
0214 vol.name(),
0215 solidName,
0216 s.type(),
0217 m.name());
0218 return vol;
0219 }
0220
0221 dd4hep::Volume DDNamespace::addVolume(dd4hep::Volume vol) const {
0222 string n = prepend(vol.name());
0223 dd4hep::Solid s = vol.solid();
0224 dd4hep::Material m = vol.material();
0225 m_context->volumes[n] = vol;
0226 const char* solidName = "Invalid solid";
0227 if (s.isValid())
0228 solidName = s.name();
0229 dd4hep::printout(m_context->debug_volumes ? dd4hep::ALWAYS : dd4hep::DEBUG,
0230 "DD4CMS",
0231 "+++ Add volume:%-38s as [%s] Solid:%-26s[%-16s] Material:%s",
0232 vol.name(),
0233 n.c_str(),
0234 solidName,
0235 s.type(),
0236 m.name());
0237 return vol;
0238 }
0239
0240 dd4hep::Assembly DDNamespace::addAssembly(dd4hep::Assembly assembly, bool addSolid) const {
0241 string n = assembly.name();
0242 m_context->assemblies[n] = assembly;
0243 if (addSolid) {
0244 m_context->assemblySolids.emplace(n);
0245 }
0246 dd4hep::printout(
0247 m_context->debug_volumes ? dd4hep::ALWAYS : dd4hep::DEBUG, "DD4CMS", "+++ Add assembly: %-38s", n.c_str());
0248 return assembly;
0249 }
0250
0251 dd4hep::Assembly DDNamespace::addAssemblySolid(dd4hep::Assembly assembly) const {
0252 string n = prepend(assembly.name());
0253 m_context->assemblySolids.emplace(n);
0254 dd4hep::printout(
0255 m_context->debug_volumes ? dd4hep::ALWAYS : dd4hep::DEBUG, "DD4CMS", "+++ Add assembly solid: %-38s", n.c_str());
0256 return assembly;
0257 }
0258
0259 dd4hep::Assembly DDNamespace::assembly(const std::string& name, bool exception) const {
0260 auto i = m_context->assemblies.find(name);
0261 if (i != m_context->assemblies.end()) {
0262 return (*i).second;
0263 }
0264 if (name.front() == NAMESPACE_SEP) {
0265 i = m_context->assemblies.find(name.substr(1, name.size()));
0266 if (i != m_context->assemblies.end())
0267 return (*i).second;
0268 }
0269 if (exception) {
0270 throw runtime_error("Unknown assembly identifier: " + name);
0271 }
0272 dd4hep::Volume nullVol(nullptr);
0273 return nullVol;
0274 }
0275
0276 dd4hep::Volume DDNamespace::volume(const string& name, bool exc) const {
0277 auto i = m_context->volumes.find(name);
0278 if (i != m_context->volumes.end()) {
0279 return (*i).second;
0280 }
0281 if (name.front() == NAMESPACE_SEP) {
0282 i = m_context->volumes.find(name.substr(1, name.size()));
0283 if (i != m_context->volumes.end())
0284 return (*i).second;
0285 }
0286 if (exc) {
0287 throw runtime_error("Unknown volume identifier:" + name);
0288 }
0289 return nullptr;
0290 }
0291
0292 dd4hep::Solid DDNamespace::addSolidNS(const string& name, dd4hep::Solid solid) const {
0293 dd4hep::printout(m_context->debug_shapes ? dd4hep::ALWAYS : dd4hep::DEBUG,
0294 "DD4CMS",
0295 "+++ Add shape of type %s : %s",
0296 solid->IsA()->GetName(),
0297 name.c_str());
0298
0299 auto shape = m_context->shapes.emplace(name, solid.setName(name));
0300 if (!shape.second) {
0301 m_context->shapes[name] = solid.setName(name);
0302 }
0303
0304 return solid;
0305 }
0306
0307 dd4hep::Solid DDNamespace::addSolid(const string& name, dd4hep::Solid sol) const {
0308 return addSolidNS(prepend(name), sol);
0309 }
0310
0311 dd4hep::Solid DDNamespace::solid(const string& nam) const {
0312 size_t idx;
0313 string n = m_name + nam;
0314 auto i = m_context->shapes.find(n);
0315 if (i != m_context->shapes.end())
0316 return (*i).second;
0317 if ((idx = nam.find(NAMESPACE_SEP)) != string::npos) {
0318 n = realName(nam);
0319 n[idx] = NAMESPACE_SEP;
0320 i = m_context->shapes.find(n);
0321 if (i != m_context->shapes.end())
0322 return (*i).second;
0323 }
0324 i = m_context->shapes.find(nam);
0325 if (i != m_context->shapes.end())
0326 return (*i).second;
0327
0328 auto tmpShape = m_context->shapes.emplace(nam, dd4hep::Solid(nullptr));
0329 return (*tmpShape.first).second;
0330 }
0331
0332 std::vector<double> DDNamespace::vecDbl(const std::string& name) const {
0333 cms::DDVectorsMap* registry = m_context->description.extension<cms::DDVectorsMap>();
0334 auto it = registry->find(name);
0335 if (it != registry->end()) {
0336 return {begin(it->second), end(it->second)};
0337 } else
0338 return std::vector<double>();
0339 }
0340
0341 std::vector<float> DDNamespace::vecFloat(const std::string& name) const {
0342 cms::DDVectorsMap* registry = m_context->description.extension<cms::DDVectorsMap>();
0343 auto it = registry->find(name);
0344 if (it != registry->end()) {
0345 std::vector<float> result;
0346 std::transform(
0347 begin(it->second), end(it->second), std::back_inserter(result), [](double i) -> float { return (float)i; });
0348 return result;
0349 } else
0350 return std::vector<float>();
0351 }
0352
0353 std::string DDNamespace::noNamespace(const std::string& fullName) const {
0354 std::string result(fullName);
0355 auto n = result.find(':');
0356 if (n == std::string::npos) {
0357 return result;
0358 } else {
0359 return result.substr(n + 1);
0360 }
0361 }