Back to home page

Project CMSSW displayed by LXR

 
 

    


File indexing completed on 2021-10-12 08:24:04

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   // Set -0 to 0
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     // Only add it to the dictionary if it is not yet defined
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       // Only set a rotation that is not already in the map
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())         // Protect against seg fault
0210     solidName = s.name();  // If Solid is not valid, s.name() will seg fault.
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())         // Protect against seg fault
0228     solidName = s.name();  // If Solid is not valid, s.name() will seg fault.
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) {  // In algorithms, Assembly solids are not added separately, so add it here
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   // Register a temporary shape
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 }