File indexing completed on 2025-02-25 09:20:29
0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013
0014
0015
0016
0017
0018
0019 #include "DD4hep/Path.h"
0020 #include "DD4hep/Printout.h"
0021 #include "DD4hep/Detector.h"
0022 #include "DD4hep/Grammar.h"
0023 #include "DDCMS/DDCMS.h"
0024
0025 #include <TClass.h>
0026
0027
0028 #include <stdexcept>
0029
0030 using namespace std;
0031 using namespace dd4hep;
0032 using namespace dd4hep::cms;
0033
0034
0035 Rotation3D dd4hep::cms::make_rotation3D(double thetaX, double phiX,
0036 double thetaY, double phiY,
0037 double thetaZ, double phiZ) {
0038 Position posX(sin(thetaX) * cos(phiX), sin(thetaX) * sin(phiX), cos(thetaX));
0039 Position posY(sin(thetaY) * cos(phiY), sin(thetaY) * sin(phiY), cos(thetaY));
0040 Position posZ(sin(thetaZ) * cos(phiZ), sin(thetaZ) * sin(phiZ), cos(thetaZ));
0041 Rotation3D rot(posX,posY,posZ);
0042 return rot;
0043 }
0044
0045
0046 string dd4hep::cms::detElementName(PlacedVolume pv) {
0047 if ( pv.isValid() ) {
0048 string nam = pv.name();
0049 string nnam = nam.substr(nam.find(NAMESPACE_SEP)+1);
0050 return nnam;
0051 }
0052 except("DDCMS","++ Cannot deduce name from invalid PlacedVolume handle!");
0053 return string();
0054 }
0055
0056
0057 Namespace::Namespace(ParsingContext* ctx, xml_h element) : context(ctx) {
0058 xml_dim_t elt(element);
0059 bool has_label = elt.hasAttr(_U(label));
0060 name = has_label ? elt.labelStr() : "";
0061 if ( !has_label ) {
0062 if ( !context->namespaces.empty() ) {
0063 name = context->namespaces.back();
0064 }
0065 printout(context->debug.namespaces ? ALWAYS : DEBUG,
0066 "DDCMS","+++ Current namespace is now: %s",name.c_str());
0067 return;
0068 }
0069 if ( has_label ) {
0070 size_t idx = name.find('.');
0071 name = name.substr(0,idx);
0072 }
0073 else {
0074 Path path(xml::DocumentHandler::system_path(element));
0075 name = path.filename().substr(0,path.filename().rfind('.'));
0076 }
0077 if ( !name.empty() ) name += NAMESPACE_SEP;
0078 context->namespaces.push_back(name);
0079 pop = true;
0080 printout(context->debug.namespaces ? ALWAYS : DEBUG,
0081 "DDCMS","+++ Current namespace is now: %s",name.c_str());
0082 return;
0083 }
0084
0085
0086 Namespace::Namespace(ParsingContext& ctx, xml_h element, bool ) : context(&ctx) {
0087 xml_dim_t elt(element);
0088 bool has_label = elt.hasAttr(_U(label));
0089 name = has_label ? elt.labelStr() : "";
0090 if ( has_label ) {
0091 size_t idx = name.find('.');
0092 name = name.substr(0,idx);
0093 }
0094 else {
0095 Path path(xml::DocumentHandler::system_path(element));
0096 name = path.filename().substr(0,path.filename().rfind('.'));
0097 }
0098 if ( !name.empty() ) name += NAMESPACE_SEP;
0099 context->namespaces.push_back(name);
0100 pop = true;
0101 printout(context->debug.namespaces ? ALWAYS : DEBUG,
0102 "DDCMS","+++ Current namespace is now: %s",name.c_str());
0103 return;
0104 }
0105
0106
0107 Namespace::Namespace(ParsingContext* ctx) : context(ctx) {
0108 name = context->namespaces.back();
0109 }
0110
0111
0112 Namespace::Namespace(ParsingContext& ctx) : context(&ctx) {
0113 name = context->namespaces.back();
0114 }
0115
0116
0117 Namespace::~Namespace() {
0118 if ( pop ) {
0119 context->namespaces.pop_back();
0120 printout(context->debug.namespaces ? ALWAYS : DEBUG,
0121 "DDCMS","+++ Current namespace is now: %s",context->ns().c_str());
0122 }
0123 }
0124
0125
0126 string Namespace::prepend(const string& n) const {
0127 return name + n;
0128 }
0129
0130
0131 string Namespace::real_name(const string& v) const {
0132 size_t idx, idq, idp;
0133 string val = v;
0134 while ( (idx=val.find('[')) != string::npos ) {
0135 val.erase(idx,1);
0136 idp = val.find(NAMESPACE_SEP,idx);
0137 idq = val.find(']',idx);
0138 val.erase(idq,1);
0139 if ( idp == string::npos || idp > idq )
0140 val.insert(idx,name);
0141 else if ( idp != string::npos && idp < idq )
0142 val[idp] = NAMESPACE_SEP;
0143 }
0144 return val;
0145 }
0146
0147
0148 string Namespace::ns_name(const string& nam) {
0149 size_t idx;
0150 if ( (idx=nam.find(NAMESPACE_SEP)) != string::npos )
0151 return nam.substr(0,idx);
0152 return "";
0153 }
0154
0155
0156 string Namespace::obj_name(const string& nam) {
0157 size_t idx;
0158 if ( (idx=nam.find(NAMESPACE_SEP)) != string::npos )
0159 return nam.substr(idx+1);
0160 return "";
0161 }
0162
0163
0164 void Namespace::addConstant(const string& nam, const string& val, const string& typ) const {
0165 addConstantNS(prepend(nam), val, typ);
0166 }
0167
0168
0169 void Namespace::addConstantNS(const string& nam, const string& val, const string& typ) const {
0170 const string& v = val;
0171 const string& n = nam;
0172 printout(context->debug.constants ? ALWAYS : DEBUG,
0173 "DDCMS","+++ Add constant object: %-40s = %s [type:%s]",
0174 n.c_str(), v.c_str(), typ.c_str());
0175 _toDictionary(n, v, typ);
0176 Constant c(n, v, typ);
0177 context->description->addConstant(c);
0178 }
0179
0180
0181 Material Namespace::material(const string& nam) const {
0182 return context->description->material(real_name(nam));
0183 }
0184
0185
0186 void Namespace::addRotation(const string& nam,const Rotation3D& rot) const {
0187 string n = prepend(nam);
0188 Position x, y, z;
0189 rot.GetComponents(x,y,z);
0190 double det = (x.Cross(y)).Dot(z);
0191 printout(DEBUG, "DDCMS","+++ Add rotation: %s %s-handed",
0192 nam.c_str(), (det>=0) ? "RIGHT" : "LEFT");
0193 context->rotations[n] = rot;
0194 }
0195
0196 const Rotation3D& Namespace::rotation(const string& nam) const {
0197 static Rotation3D s_null;
0198 size_t idx;
0199 auto i = context->rotations.find(nam);
0200 if ( i != context->rotations.end() )
0201 return (*i).second;
0202 else if ( nam == "NULL" )
0203 return s_null;
0204 else if ( nam.find(":NULL") == nam.length()-5 )
0205 return s_null;
0206
0207 string n = this->name + nam;
0208 i = context->rotations.find(n);
0209 if ( i != context->rotations.end() )
0210 return (*i).second;
0211
0212 n = nam;
0213 if ( (idx=nam.find(NAMESPACE_SEP)) != string::npos ) {
0214 n[idx] = NAMESPACE_SEP;
0215 i = context->rotations.find(n);
0216 if ( i != context->rotations.end() )
0217 return (*i).second;
0218 }
0219 printout(ERROR,"Namespace","[%s] Cannot find rotation identifier: '%s'",this->name.c_str(), nam.c_str());
0220 for (const auto& r : context->rotations ) {
0221 printout(ERROR,"Namespace","[%s] Known rotation: '%s'",this->name.c_str(), r.first.c_str());
0222 }
0223 throw runtime_error("Unknown rotation identifier: '"+nam+"'");
0224 }
0225
0226
0227 Volume Namespace::addVolumeNS(Volume vol) const {
0228 string nam = vol.name();
0229 Solid sol = vol.solid();
0230 Material mat = vol.material();
0231 vol->SetName(nam.c_str());
0232 context->volumes[nam] = vol;
0233 printout(context->debug.volumes ? ALWAYS : DEBUG, "DDCMS",
0234 "+++ Add volume:%-38s Solid:%-26s[%-16s] Material:%s",
0235 vol.name(), sol.name(), sol.type(), mat.name());
0236 return vol;
0237 }
0238
0239
0240 Volume Namespace::addVolume(Volume vol) const {
0241 string nam = prepend(vol.name());
0242 Solid sol = vol.solid();
0243 Material mat = vol.material();
0244 vol->SetName(nam.c_str());
0245 context->volumes[nam] = vol;
0246 printout(context->debug.volumes ? ALWAYS : DEBUG, "DDCMS",
0247 "+++ Add volume:%-38s Solid:%-26s[%-16s] Material:%s",
0248 vol.name(), sol.name(), sol.type(), mat.name());
0249 return vol;
0250 }
0251
0252 Volume Namespace::volume(const string& nam, bool exc) const {
0253 size_t idx;
0254 auto i = context->volumes.find(nam);
0255 if ( i != context->volumes.end() ) {
0256 return (*i).second;
0257 }
0258 if ( (idx=nam.find(NAMESPACE_SEP)) != string::npos ) {
0259 string n = nam;
0260 n[idx] = NAMESPACE_SEP;
0261 i = context->volumes.find(n);
0262 if ( i != context->volumes.end() )
0263 return (*i).second;
0264 }
0265 if ( exc ) {
0266 throw runtime_error("Unknown volume identifier:"+nam);
0267 }
0268 return 0;
0269 }
0270
0271
0272 Solid Namespace::addSolidNS(const string& nam,Solid sol) const {
0273 printout(context->debug.shapes ? ALWAYS : DEBUG, "DDCMS",
0274 "+++ Add shape of type %s : %s",sol->IsA()->GetName(), nam.c_str());
0275 context->shapes[nam] = sol.setName(nam);
0276 return sol;
0277 }
0278
0279
0280 Solid Namespace::addSolid(const string& nam, Solid sol) const {
0281 return addSolidNS(prepend(nam), sol);
0282 }
0283
0284 Solid Namespace::solid(const string& nam) const {
0285 size_t idx;
0286 string n = context->namespaces.back() + nam;
0287 auto i = context->shapes.find(n);
0288 if ( i != context->shapes.end() )
0289 return (*i).second;
0290 if ( (idx=nam.find(NAMESPACE_SEP)) != string::npos ) {
0291 n = real_name(nam);
0292 n[idx] = NAMESPACE_SEP;
0293 i = context->shapes.find(n);
0294 if ( i != context->shapes.end() )
0295 return (*i).second;
0296 }
0297 i = context->shapes.find(nam);
0298 if ( i != context->shapes.end() ) return (*i).second;
0299 throw runtime_error("Unknown shape identifier:"+nam);
0300 }
0301
0302 AlgoArguments::AlgoArguments(ParsingContext& ctxt, xml_h elt)
0303 : context(ctxt), element(elt)
0304 {
0305 name = xml_dim_t(element).nameStr();
0306 }
0307
0308
0309 string AlgoArguments::parentName() const {
0310 Namespace n(context);
0311 xml_dim_t e(element);
0312 string val = n.real_name(xml_dim_t(e.child(_CMU(rParent))).nameStr());
0313 return val;
0314 }
0315
0316
0317 string AlgoArguments::childName() const {
0318 Namespace n(context);
0319 return n.real_name(value<string>("ChildName"));
0320 }
0321
0322
0323 bool AlgoArguments::find(const string& nam) const {
0324 for(xml_coll_t p(element,_U(star)); p; ++p) {
0325 string n = p.attr<string>(_U(name));
0326 if ( n == nam ) {
0327 return true;
0328 }
0329 }
0330 return false;
0331 }
0332
0333
0334 xml_h AlgoArguments::raw_arg(const string& nam) const {
0335 for(xml_coll_t p(element,_U(star)); p; ++p) {
0336 string n = p.attr<string>(_U(name));
0337 if ( n == nam ) {
0338 return p;
0339 }
0340 }
0341 except("DDCMS","+++ Attempt to access non-existing algorithm option %s[%s]",name.c_str(),nam.c_str());
0342 throw runtime_error("DDCMS: Attempt to access non-existing algorithm option.");
0343 }
0344
0345
0346 string AlgoArguments::resolved_scalar_arg(const string& nam) const {
0347 Namespace name_space(context);
0348 xml_h arg = raw_arg(nam);
0349 string val = arg.attr<string>(_U(value));
0350 return name_space.real_name(val);
0351 }
0352
0353 namespace {
0354
0355
0356 vector<string> raw_vector(const AlgoArguments* a, xml_h arg) {
0357 xml_dim_t xp(arg);
0358 vector<string> data;
0359 Namespace name_space(a->context);
0360 string val = xp.text();
0361 string nam = xp.nameStr();
0362 string typ = xp.typeStr();
0363 int num = xp.attr<int>(_CMU(nEntries));
0364 const BasicGrammar& gr = BasicGrammar::instance<vector<string> >();
0365
0366 val = '['+name_space.real_name(val)+']';
0367 val = remove_whitespace(val);
0368 int res = gr.fromString(&data,val);
0369 if ( !res ) {
0370 except("DDCMS","+++ VectorParam<%s>: %s -> %s [Invalid conversion:%d]",
0371 typ.c_str(), nam.c_str(), val.c_str(), res);
0372 }
0373 else if ( num != (int)data.size() ) {
0374 except("DDCMS","+++ VectorParam<%s>: %s -> %s [Invalid entry count: %d <> %ld]",
0375 typ.c_str(), nam.c_str(), val.c_str(), num, data.size());
0376 }
0377 printout(DEBUG,"DDCMS","+++ VectorParam<%s>: ret=%d %s -> %s",
0378 typ.c_str(), res, nam.c_str(), gr.str(&data).c_str());
0379 return data;
0380 }
0381
0382
0383 template <typename T> T __cnv(const string&) { return 0;}
0384 template <> double __cnv<double>(const string& arg) { return _toDouble(arg); }
0385 template <> float __cnv<float> (const string& arg) { return _toFloat(arg); }
0386 template <> long __cnv<long> (const string& arg) { return _toLong(arg); }
0387 template <> int __cnv<int> (const string& arg) { return _toInt(arg); }
0388 template <> string __cnv<string>(const string& arg) { return arg; }
0389
0390 template <typename T> vector<T> __cnvVect(const AlgoArguments* a, const char* req_typ, xml_h xp) {
0391 Namespace ns(a->context);
0392 string piece;
0393 string nam = xp.attr<string>(_U(name));
0394 string typ = xp.attr<string>(_U(type));
0395 string val = xp.text();
0396 int num = xp.attr<int>(_CMU(nEntries));
0397 if ( typ != req_typ ) {
0398 except("DDCMS",
0399 "+++ VectorParam<%s | %s>: %s -> <%s> %s [Incompatible vector-type]",
0400 req_typ, typ.c_str(), nam.c_str(), typeName(typeid(T)).c_str(),
0401 val.c_str());
0402 }
0403 vector<T> data;
0404 val = remove_whitespace(val);
0405 if ( !val.empty() ) val += ',';
0406 for(size_t idx=0, idq=val.find(',',idx);
0407 idx != string::npos && idq != string::npos;
0408 idx=++idq, idq=val.find(',',idx))
0409 {
0410 piece = ns.real_name(val.substr(idx,idq-idx));
0411 T d = __cnv<T>(piece);
0412 data.push_back(d);
0413 }
0414 printout(DEBUG,"DDCMS","+++ VectorParam<%s>: %s[%d] -> %s",
0415 typ.c_str(), nam.c_str(), num, val.c_str());
0416 return data;
0417 }
0418 }
0419
0420
0421 namespace dd4hep {
0422
0423
0424 namespace cms {
0425
0426
0427 template<typename T> T AlgoArguments::value(const string& nam) const {
0428 return __cnv<T>(resolved_scalar_arg(nam));
0429 }
0430
0431 template double AlgoArguments::value<double>(const string& nam) const;
0432 template float AlgoArguments::value<float>(const string& nam) const;
0433 template long AlgoArguments::value<long>(const string& nam) const;
0434 template int AlgoArguments::value<int>(const string& nam) const;
0435 template string AlgoArguments::value<string>(const string& nam) const;
0436
0437
0438 template<> vector<string> AlgoArguments::value<vector<string> >(const string& nam) const
0439 { return raw_vector(this,raw_arg(nam)); }
0440
0441
0442 template<> vector<double> AlgoArguments::value<vector<double> >(const string& nam) const
0443 { return __cnvVect<double>(this,"numeric",raw_arg(nam)); }
0444
0445
0446 template<> vector<float> AlgoArguments::value<vector<float> >(const string& nam) const
0447 { return __cnvVect<float>(this,"numeric",raw_arg(nam)); }
0448
0449
0450 template<> vector<long> AlgoArguments::value<vector<long> >(const string& nam) const
0451 { return __cnvVect<long>(this,"numeric",raw_arg(nam)); }
0452
0453
0454 template<> vector<int> AlgoArguments::value<vector<int> >(const string& nam) const
0455 { return __cnvVect<int>(this,"numeric",raw_arg(nam)); }
0456 }
0457 }
0458
0459
0460 string AlgoArguments::str(const string& nam) const
0461 { return this->value<string>(nam); }
0462
0463
0464 double AlgoArguments::dble(const string& nam) const
0465 { return this->value<double>(nam); }
0466
0467
0468 int AlgoArguments::integer(const string& nam) const
0469 { return this->value<int>(nam); }
0470
0471
0472 vector<double> AlgoArguments::vecDble(const string& nam) const
0473 { return this->value<vector<double> >(nam); }
0474
0475
0476 vector<int> AlgoArguments::vecInt(const string& nam) const
0477 { return this->value<vector<int> >(nam); }
0478
0479
0480 vector<string> AlgoArguments::vecStr(const string& nam) const
0481 { return this->value<vector<string> >(nam); }
0482
0483 namespace {
0484 bool s_debug_algorithms = false;
0485 vector<string> s_algorithms;
0486 const std::string currentAlg() {
0487 static std::string s_none = "??????";
0488 if ( !s_algorithms.empty() ) return s_algorithms.back();
0489 return s_none;
0490 }
0491 }
0492
0493 LogDebug::LogDebug(const std::string& tag_value, bool ) {
0494 level = s_debug_algorithms ? ALWAYS : DEBUG;
0495 s_algorithms.push_back(tag_value);
0496 pop = true;
0497 }
0498
0499 LogDebug::LogDebug(const std::string& t) : stringstream(), tag(t) {
0500 level = s_debug_algorithms ? ALWAYS : DEBUG;
0501 }
0502
0503 LogDebug::~LogDebug() {
0504 if ( pop ) {
0505 s_algorithms.pop_back();
0506 return;
0507 }
0508 if ( this->str().empty() ) return;
0509 printout(PrintLevel(level),
0510 currentAlg(),"%s: %s",
0511 tag.c_str(),this->str().c_str());
0512 }
0513
0514 void LogDebug::setDebugAlgorithms(bool value) {
0515 s_debug_algorithms = value;
0516 }
0517
0518 LogWarn::LogWarn(const std::string& t) : LogDebug(t) {
0519 level = WARNING;
0520 }