Back to home page

Project CMSSW displayed by LXR

 
 

    


File indexing completed on 2024-04-06 12:05:29

0001 #include "DetectorDescription/DDCMS/interface/DDAlgoArguments.h"
0002 #include <DD4hep/Path.h>
0003 #include <DD4hep/Printout.h>
0004 #include <DD4hep/Detector.h>
0005 #include <DD4hep/Filter.h>
0006 #include <DD4hep/Grammar.h>
0007 
0008 #include <TClass.h>
0009 
0010 #include <algorithm>
0011 #include <stdexcept>
0012 
0013 using namespace std;
0014 using namespace cms;
0015 using namespace dd4hep;
0016 
0017 //
0018 // Helpers to create 3D rotation matrix from angles
0019 //
0020 dd4hep::Rotation3D cms::makeRotation3D(
0021     double thetaX, double phiX, double thetaY, double phiY, double thetaZ, double phiZ) {
0022   dd4hep::Position posX(sin(thetaX) * cos(phiX), sin(thetaX) * sin(phiX), cos(thetaX));
0023   dd4hep::Position posY(sin(thetaY) * cos(phiY), sin(thetaY) * sin(phiY), cos(thetaY));
0024   dd4hep::Position posZ(sin(thetaZ) * cos(phiZ), sin(thetaZ) * sin(phiZ), cos(thetaZ));
0025   dd4hep::Rotation3D rotation(posX, posY, posZ);
0026 
0027   return rotation;
0028 }
0029 
0030 // makes sure that the RotationMatrix built is
0031 // LEFT-handed coordinate system (i.e. reflected)
0032 dd4hep::Rotation3D cms::makeRotReflect(
0033     double thetaX, double phiX, double thetaY, double phiY, double thetaZ, double phiZ) {
0034   // define 3 unit std::vectors forming the new left-handed axes
0035   DD3Vector x(cos(phiX) * sin(thetaX), sin(phiX) * sin(thetaX), cos(thetaX));
0036   DD3Vector y(cos(phiY) * sin(thetaY), sin(phiY) * sin(thetaY), cos(thetaY));
0037   DD3Vector z(cos(phiZ) * sin(thetaZ), sin(phiZ) * sin(thetaZ), cos(thetaZ));
0038 
0039   constexpr double tol = 1.0e-3;       // Geant4 compatible
0040   double check = (x.Cross(y)).Dot(z);  // in case of a LEFT-handed orthogonal system this must be -1
0041   if (abs(1. + check) > tol) {
0042     except("DD4CMS", "+++ FAILED to construct Rotation is not LEFT-handed!");
0043   }
0044 
0045   dd4hep::Rotation3D rotation(x.x(), y.x(), z.x(), x.y(), y.y(), z.y(), x.z(), y.z(), z.z());
0046 
0047   return rotation;
0048 }
0049 
0050 dd4hep::Rotation3D cms::makeRotation3D(dd4hep::Rotation3D rotation, const std::string& axis, double angle) {
0051   switch (hash(axis)) {
0052     case hash("x"):
0053       rotation = dd4hep::RotationX(angle);
0054       break;
0055     case hash("y"):
0056       rotation = dd4hep::RotationY(angle);
0057       break;
0058     case hash("z"):
0059       rotation = dd4hep::RotationZ(angle);
0060       break;
0061     default:
0062       throw std::runtime_error("Axis is not valid.");
0063   }
0064   return rotation;
0065 }
0066 
0067 namespace {
0068 
0069   std::string& ltrim(std::string& str, const std::string& chars = "\t\n\v\f\r ") {
0070     str.erase(0, str.find_first_not_of(chars));
0071     return str;
0072   }
0073 
0074   std::string& rtrim(std::string& str, const std::string& chars = "\t\n\v\f\r ") {
0075     str.erase(str.find_last_not_of(chars) + 1);
0076     return str;
0077   }
0078 
0079   std::string& trimWhitespace(std::string& str, const std::string& chars = "\t\n\v\f\r ") {
0080     return ltrim(rtrim(str, chars), chars);
0081   }
0082 
0083   std::string trimSVecWhitespace(std::string& str) {
0084     std::string res;
0085 
0086     vector<string_view> v = dd::split(str, ",");
0087     for (auto& n : v) {
0088       std::string ts{n.data(), n.size()};
0089       trimWhitespace(ts);
0090       res.append(ts).append(",");
0091     };
0092 
0093     res.erase(res.find_last_of(','));
0094 
0095     return res;
0096   }
0097 }  // namespace
0098 
0099 DDAlgoArguments::DDAlgoArguments(cms::DDParsingContext& ctxt, xml_h elt) : context(ctxt), element(elt) {
0100   name = xml_dim_t(element).nameStr();
0101 }
0102 
0103 /// Access value of rParent child node
0104 string DDAlgoArguments::parentName() const {
0105   cms::DDNamespace n(context);
0106   xml_dim_t e(element);
0107   string val = n.realName(xml_dim_t(e.child(DD_CMU(rParent))).nameStr());
0108   return val;
0109 }
0110 
0111 /// Access value of child'name from the xml element
0112 string DDAlgoArguments::childName() const {
0113   cms::DDNamespace n(context);
0114   return n.realName(value<string>("ChildName"));
0115 }
0116 
0117 /// Check the existence of an argument by name
0118 bool DDAlgoArguments::find(const string& nam) const {
0119   for (xml_coll_t p(element, _U(star)); p; ++p) {
0120     string n = p.attr<string>(_U(name));
0121     if (n == nam) {
0122       return true;
0123     }
0124   }
0125   return false;
0126 }
0127 
0128 /// Access raw argument as a string by name
0129 xml_h DDAlgoArguments::rawArgument(const string& nam) const {
0130   for (xml_coll_t p(element, _U(star)); p; ++p) {
0131     string n = p.attr<string>(_U(name));
0132     if (n == nam) {
0133       return p;
0134     }
0135   }
0136   except("DD4CMS", "+++ Attempt to access non-existing algorithm option %s[%s]", name.c_str(), nam.c_str());
0137   throw runtime_error("DDCMS: Attempt to access non-existing algorithm option.");
0138 }
0139 
0140 /// Access namespace resolved argument as a string by name
0141 string DDAlgoArguments::resolved_scalar_arg(const string& nam) const {
0142   cms::DDNamespace ns(context);
0143   xml_h arg = rawArgument(nam);
0144   string val = arg.attr<string>(_U(value));
0145   return ns.realName(val);
0146 }
0147 
0148 string DDAlgoArguments::resolveValue(const std::string& aValue) const {
0149   cms::DDNamespace ns(context);
0150   string value(aValue);
0151   size_t idx = value.find('[');
0152   if (idx == string::npos) {
0153     return value;
0154   }
0155 
0156   while (idx != string::npos) {
0157     ++idx;
0158     size_t idp = value.find(':', idx);
0159     size_t idq = value.find(']', idx);
0160     if (idp == string::npos || idp > idq)
0161       value.insert(idx, ns.name());
0162     else if (idp != string::npos && idp < idq)
0163       value[idp] = NAMESPACE_SEP;
0164     idx = value.find('[', idx);
0165   }
0166 
0167   string rep;
0168   string& v = value;
0169   size_t idq;
0170   for (idx = v.find('[', 0); idx != string::npos; idx = v.find('[', idx + 1)) {
0171     idq = v.find(']', idx + 1);
0172     rep = v.substr(idx + 1, idq - idx - 1);
0173     auto r = ns.context()->description.constants().find(rep);
0174     if (r != ns.context()->description.constants().end()) {
0175       rep = "(" + r->second->type + ")";
0176       v.replace(idx, idq - idx + 1, rep);
0177     }
0178   }
0179   return value;
0180 }
0181 
0182 namespace {
0183 
0184   /// Access of raw strings as vector by argument name
0185   vector<string> raw_vector(const DDAlgoArguments* a, xml_h arg) {
0186     xml_dim_t xp(arg);
0187     vector<string> data;
0188     cms::DDNamespace ns(a->context);
0189     string val = xp.text();
0190     string nam = xp.nameStr();
0191     string typ = xp.typeStr();
0192     string numValue = xp.attr<string>(DD_CMU(nEntries));
0193     int num = _toDouble(numValue);
0194     const BasicGrammar& gr = BasicGrammar::instance<vector<string> >();
0195 
0196     val = trimSVecWhitespace(val);
0197     val = '[' + ns.realName(val) + ']';
0198     int res = gr.fromString(&data, val);
0199     if (!res) {
0200       except(
0201           "DD4CMS", "+++ VectorParam<%s>: %s -> %s [Invalid conversion:%d]", typ.c_str(), nam.c_str(), val.c_str(), res);
0202     } else if (num != (int)data.size()) {
0203       except("DD4CMS",
0204              "+++ VectorParam<%s>: %s -> %s [Invalid entry count: %d <> %ld]",
0205              typ.c_str(),
0206              nam.c_str(),
0207              val.c_str(),
0208              num,
0209              data.size());
0210     }
0211     printout(a->context.debug_algorithms ? ALWAYS : DEBUG,
0212              "DD4CMS",
0213              "+++ VectorParam<%s>: ret=%d %s -> %s",
0214              typ.c_str(),
0215              res,
0216              nam.c_str(),
0217              gr.str(&data).c_str());
0218     return data;
0219   }
0220 
0221   template <typename T>
0222   T __cnv(const string&) {
0223     return 0;
0224   }
0225   template <>
0226   double __cnv<double>(const string& arg) {
0227     return _toDouble(arg);
0228   }
0229   template <>
0230   float __cnv<float>(const string& arg) {
0231     return _toFloat(arg);
0232   }
0233   template <>
0234   long __cnv<long>(const string& arg) {
0235     return _toLong(arg);
0236   }
0237   template <>
0238   int __cnv<int>(const string& arg) {
0239     return _toInt(arg);
0240   }
0241   template <>
0242   string __cnv<string>(const string& arg) {
0243     return arg;
0244   }
0245 
0246   template <typename T>
0247   vector<T> __cnvVect(const DDAlgoArguments* a, const char* req_typ, xml_h xp) {
0248     cms::DDNamespace ns(a->context);
0249     string piece;
0250     string nam = xp.attr<string>(_U(name));
0251     string typ = xp.hasAttr(_U(type)) ? xp.attr<string>(_U(type)) : "numeric";
0252     string val = xp.text();
0253     string nValues = a->resolveValue(xp.attr<string>(DD_CMU(nEntries)));
0254     int num = _toInt(nValues);
0255     if (typ != req_typ) {
0256       except("DD4CMS",
0257              "+++ VectorParam<%s | %s>: %s -> <%s> %s [Incompatible vector-type]",
0258              req_typ,
0259              typ.c_str(),
0260              nam.c_str(),
0261              typeName(typeid(T)).c_str(),
0262              val.c_str());
0263     }
0264     vector<T> data;
0265     val = remove_whitespace(val);
0266 
0267     if (!val.empty())
0268       val += ',';
0269     for (size_t idx = 0, idq = val.find(',', idx); idx != string::npos && idq != string::npos;
0270          idx = ++idq, idq = val.find(',', idx)) {
0271       piece = ns.realName(val.substr(idx, idq - idx));
0272       T d = __cnv<T>(piece);
0273       data.push_back(d);
0274     }
0275     printout(a->context.debug_algorithms ? ALWAYS : DEBUG,
0276              "DD4CMS",
0277              "+++ VectorParam<%s>: %s[%d] -> %s",
0278              typ.c_str(),
0279              nam.c_str(),
0280              num,
0281              val.c_str());
0282     return data;
0283   }
0284 }  // namespace
0285 
0286 /// Namespace of DDCMS conversion namespace
0287 namespace cms {
0288 
0289   /// Access typed argument by name
0290   template <typename T>
0291   T DDAlgoArguments::value(const string& nam) const {
0292     return __cnv<T>(resolved_scalar_arg(nam));
0293   }
0294 
0295   template double DDAlgoArguments::value<double>(const string& nam) const;
0296   template float DDAlgoArguments::value<float>(const string& nam) const;
0297   template long DDAlgoArguments::value<long>(const string& nam) const;
0298   template int DDAlgoArguments::value<int>(const string& nam) const;
0299   template string DDAlgoArguments::value<string>(const string& nam) const;
0300 
0301   /// Access typed vector<string> argument by name
0302   template <>
0303   vector<string> DDAlgoArguments::value<vector<string> >(const string& nam) const {
0304     return raw_vector(this, rawArgument(nam));
0305   }
0306 
0307   /// Access typed vector<double> argument by name
0308   template <>
0309   vector<double> DDAlgoArguments::value<vector<double> >(const string& nam) const {
0310     return __cnvVect<double>(this, "numeric", rawArgument(nam));
0311   }
0312 
0313   /// Access typed vector<float> argument by name
0314   template <>
0315   vector<float> DDAlgoArguments::value<vector<float> >(const string& nam) const {
0316     return __cnvVect<float>(this, "numeric", rawArgument(nam));
0317   }
0318 
0319   /// Access typed vector<long> argument by name
0320   template <>
0321   vector<long> DDAlgoArguments::value<vector<long> >(const string& nam) const {
0322     return __cnvVect<long>(this, "numeric", rawArgument(nam));
0323   }
0324 
0325   /// Access typed vector<int> argument by name
0326   template <>
0327   vector<int> DDAlgoArguments::value<vector<int> >(const string& nam) const {
0328     return __cnvVect<int>(this, "numeric", rawArgument(nam));
0329   }
0330 }  // namespace cms
0331 
0332 /// Shortcut to access string arguments
0333 string DDAlgoArguments::str(const string& nam) const { return this->value<string>(nam); }
0334 
0335 /// Shortcut to access double arguments
0336 double DDAlgoArguments::dble(const string& nam) const { return this->value<double>(resolveValue(nam)); }
0337 
0338 /// Shortcut to access integer arguments
0339 int DDAlgoArguments::integer(const string& nam) const { return this->value<int>(nam); }
0340 
0341 /// Shortcut to access vector<double> arguments
0342 vector<double> DDAlgoArguments::vecDble(const string& nam) const { return this->value<vector<double> >(nam); }
0343 
0344 /// Shortcut to access vector<float> arguments
0345 vector<float> DDAlgoArguments::vecFloat(const string& nam) const { return this->value<vector<float> >(nam); }
0346 
0347 /// Shortcut to access vector<int> arguments
0348 vector<int> DDAlgoArguments::vecInt(const string& nam) const { return this->value<vector<int> >(nam); }
0349 
0350 /// Shortcut to access vector<string> arguments
0351 vector<string> DDAlgoArguments::vecStr(const string& nam) const { return this->value<vector<string> >(nam); }