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
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
0031
0032 dd4hep::Rotation3D cms::makeRotReflect(
0033 double thetaX, double phiX, double thetaY, double phiY, double thetaZ, double phiZ) {
0034
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;
0040 double check = (x.Cross(y)).Dot(z);
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 }
0098
0099 DDAlgoArguments::DDAlgoArguments(cms::DDParsingContext& ctxt, xml_h elt) : context(ctxt), element(elt) {
0100 name = xml_dim_t(element).nameStr();
0101 }
0102
0103
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
0112 string DDAlgoArguments::childName() const {
0113 cms::DDNamespace n(context);
0114 return n.realName(value<string>("ChildName"));
0115 }
0116
0117
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
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
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
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 }
0285
0286
0287 namespace cms {
0288
0289
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
0302 template <>
0303 vector<string> DDAlgoArguments::value<vector<string> >(const string& nam) const {
0304 return raw_vector(this, rawArgument(nam));
0305 }
0306
0307
0308 template <>
0309 vector<double> DDAlgoArguments::value<vector<double> >(const string& nam) const {
0310 return __cnvVect<double>(this, "numeric", rawArgument(nam));
0311 }
0312
0313
0314 template <>
0315 vector<float> DDAlgoArguments::value<vector<float> >(const string& nam) const {
0316 return __cnvVect<float>(this, "numeric", rawArgument(nam));
0317 }
0318
0319
0320 template <>
0321 vector<long> DDAlgoArguments::value<vector<long> >(const string& nam) const {
0322 return __cnvVect<long>(this, "numeric", rawArgument(nam));
0323 }
0324
0325
0326 template <>
0327 vector<int> DDAlgoArguments::value<vector<int> >(const string& nam) const {
0328 return __cnvVect<int>(this, "numeric", rawArgument(nam));
0329 }
0330 }
0331
0332
0333 string DDAlgoArguments::str(const string& nam) const { return this->value<string>(nam); }
0334
0335
0336 double DDAlgoArguments::dble(const string& nam) const { return this->value<double>(resolveValue(nam)); }
0337
0338
0339 int DDAlgoArguments::integer(const string& nam) const { return this->value<int>(nam); }
0340
0341
0342 vector<double> DDAlgoArguments::vecDble(const string& nam) const { return this->value<vector<double> >(nam); }
0343
0344
0345 vector<float> DDAlgoArguments::vecFloat(const string& nam) const { return this->value<vector<float> >(nam); }
0346
0347
0348 vector<int> DDAlgoArguments::vecInt(const string& nam) const { return this->value<vector<int> >(nam); }
0349
0350
0351 vector<string> DDAlgoArguments::vecStr(const string& nam) const { return this->value<vector<string> >(nam); }