Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2025-02-25 09:20:29

0001 //==========================================================================
0002 //  AIDA Detector description implementation 
0003 //--------------------------------------------------------------------------
0004 // Copyright (C) Organisation europeenne pour la Recherche nucleaire (CERN)
0005 // All rights reserved.
0006 //
0007 // For the licensing terms see $DD4hepINSTALL/LICENSE.
0008 // For the list of contributors see $DD4hepINSTALL/doc/CREDITS.
0009 //
0010 // Author     : M.Frank
0011 //
0012 //==========================================================================
0013 //
0014 // DDCMS is a detector description convention developed by the CMS experiment.
0015 //
0016 //==========================================================================
0017 
0018 // Framework includes
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 // C/C++ include files
0028 #include <stdexcept>
0029 
0030 using namespace std;
0031 using namespace dd4hep;
0032 using namespace dd4hep::cms;
0033 
0034 /// Create 3D rotation matrix from angles.
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 /// Helper: Convert the name of a placed volume into a subdetector name
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 /// Initializing constructor
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 /// Initializing constructor
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 /// Initializing constructor
0107 Namespace::Namespace(ParsingContext* ctx) : context(ctx)  {
0108   name = context->namespaces.back();
0109 }
0110 
0111 /// Initializing constructor
0112 Namespace::Namespace(ParsingContext& ctx) : context(&ctx)  {
0113   name = context->namespaces.back();
0114 }
0115 
0116 /// Standard destructor (Non virtual!)
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 /// Prepend name with namespace
0126 string Namespace::prepend(const string& n)  const   {
0127   return name + n;
0128 }
0129 
0130 /// Resolve namespace during XML parsing
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 /// Return the namespace name of a component
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 /// Strip off the namespace part of a given name
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 /// Add a new constant to the namespace
0164 void Namespace::addConstant(const string& nam, const string& val, const string& typ)  const  {
0165   addConstantNS(prepend(nam), val, typ);
0166 }
0167 
0168 /// Add a new constant to the namespace indicated by the name
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 /// Access material by its namespace dressed name
0181 Material Namespace::material(const string& nam)  const   {
0182   return context->description->material(real_name(nam));
0183 }
0184 
0185 /// Add rotation matrix to current namespace
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 /// Add rotation matrix to current namespace
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 /// Add rotation matrix to current namespace
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 /// Add solid to current namespace as fully indicated by the name
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 /// Add solid to current namespace
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 /// Access value of rParent child node
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 /// Access value of child'name from the xml element
0317 string AlgoArguments::childName()  const   {
0318   Namespace n(context);
0319   return n.real_name(value<string>("ChildName"));
0320 }
0321 
0322 /// Check the existence of an argument by name
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 /// Access raw argument as a string by name
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 /// Access namespace resolved argument as a string by name
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   /// Access of raw strings as vector by argument name
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 /// Namespace for the AIDA detector description toolkit
0421 namespace dd4hep {
0422 
0423   /// Namespace of DDCMS conversion namespace
0424   namespace cms  {
0425 
0426     /// Access typed argument by name
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     /// Access typed vector<string> argument by name
0438     template<> vector<string> AlgoArguments::value<vector<string> >(const string& nam)  const
0439     {      return raw_vector(this,raw_arg(nam));                     }
0440 
0441     /// Access typed vector<double> argument by name
0442     template<> vector<double> AlgoArguments::value<vector<double> >(const string& nam)  const
0443     {      return __cnvVect<double>(this,"numeric",raw_arg(nam));    }
0444 
0445     /// Access typed vector<float> argument by name
0446     template<> vector<float> AlgoArguments::value<vector<float> >(const string& nam)  const
0447     {      return __cnvVect<float>(this,"numeric",raw_arg(nam));     }
0448 
0449     /// Access typed vector<long> argument by name
0450     template<> vector<long> AlgoArguments::value<vector<long> >(const string& nam)  const
0451     {      return __cnvVect<long>(this,"numeric",raw_arg(nam));      }
0452 
0453     /// Access typed vector<int> argument by name
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 /// Shortcut to access string arguments
0460 string AlgoArguments::str(const string& nam)  const
0461 {  return this->value<string>(nam);                }
0462 
0463 /// Shortcut to access double arguments
0464 double AlgoArguments::dble(const string& nam)  const
0465 {  return this->value<double>(nam);                }
0466 
0467 /// Shortcut to access integer arguments
0468 int AlgoArguments::integer(const string& nam)  const
0469 {  return this->value<int>(nam);                   }
0470 
0471 /// Shortcut to access vector<double> arguments
0472 vector<double> AlgoArguments::vecDble(const string& nam)  const
0473 {  return this->value<vector<double> >(nam);       }
0474 
0475 /// Shortcut to access vector<int> arguments
0476 vector<int> AlgoArguments::vecInt(const string& nam)  const
0477 {  return this->value<vector<int> >(nam);          }
0478 
0479 /// Shortcut to access vector<string> arguments
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 /* set_context */)  {
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 }