Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2025-01-30 09:16:25

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 // Framework include files
0015 #include <DD4hep/Detector.h>
0016 #include <DD4hep/Printout.h>
0017 #include <DDAlign/GlobalAlignmentCache.h>
0018 #include <DDAlign/GlobalAlignmentOperators.h>
0019 #include <DD4hep/detail/DetectorInterna.h>
0020 
0021 // ROOT include files
0022 #include <TGeoManager.h>
0023 
0024 using namespace dd4hep::align;
0025 using Entry = GlobalAlignmentStack::StackEntry;
0026 
0027 dd4hep::DetElement _detector(dd4hep::DetElement child)   {
0028   if ( child.isValid() )   {
0029     dd4hep::DetElement p(child.parent());
0030     if ( p.isValid() && !p.parent().isValid() )
0031       return child;
0032     else if ( !p.isValid() )  // World detector element...
0033       return child;
0034     return _detector(p);
0035   }
0036   dd4hep::except("GlobalAlignmentCache", "DetElement cannot determine detector parent [Invalid handle]");
0037   return {};
0038 }
0039 
0040 /// Default constructor
0041 GlobalAlignmentCache::GlobalAlignmentCache(Detector& description, const std::string& sdPath, bool top)
0042   : m_detDesc(description), m_sdPath(sdPath), m_sdPathLen(sdPath.length()), m_refCount(1), m_top(top)
0043 {
0044 }
0045 
0046 /// Default destructor
0047 GlobalAlignmentCache::~GlobalAlignmentCache()   {
0048   int nentries = (int)m_cache.size();
0049   int nsect    = (int)m_detectors.size();
0050   detail::releaseObjects(m_detectors);
0051   m_cache.clear();
0052   printout(INFO,"GlobalAlignmentCache",
0053            "Destroy cache for subdetector %s [%d section(s), %d entrie(s)]",
0054            m_sdPath.c_str(),nsect,nentries);
0055 }
0056 
0057 /// Add reference count
0058 int GlobalAlignmentCache::addRef()   {
0059   return ++m_refCount;
0060 }
0061 
0062 /// Release object. If reference count goes to NULL, automatic deletion is triggered.
0063 int GlobalAlignmentCache::release()   {
0064   int value = --m_refCount;
0065   if ( value == 0 )  {
0066     delete this;
0067   }
0068   return value;
0069 }
0070 
0071 /// Create and install a new instance tree
0072 GlobalAlignmentCache* GlobalAlignmentCache::install(Detector& description)   {
0073   GlobalAlignmentCache* cache = description.extension<GlobalAlignmentCache>(false);
0074   if ( !cache )  {
0075     cache = new GlobalAlignmentCache(description,"world",true);
0076     ExtensionEntry* e = new detail::DeleteExtension<GlobalAlignmentCache,GlobalAlignmentCache>(cache);
0077     description.addUserExtension(detail::typeHash64<GlobalAlignmentCache>(),e);
0078   }
0079   return cache;
0080 }
0081 
0082 /// Unregister and delete a tree instance
0083 void GlobalAlignmentCache::uninstall(Detector& description)   {
0084   if ( description.extension<GlobalAlignmentCache>(false) )  {
0085     description.removeExtension<GlobalAlignmentCache>(true);
0086   }
0087 }
0088 
0089 /// Add a new entry to the cache. The key is the placement path
0090 bool GlobalAlignmentCache::insert(GlobalAlignment alignment)  {
0091   TGeoPhysicalNode* pn = alignment.ptr();
0092   unsigned int index = detail::hash32(pn->GetName()+m_sdPathLen);
0093   Cache::const_iterator i = m_cache.find(index);
0094   printout(ALWAYS,"GlobalAlignmentCache","Section: %s adding entry: %s",
0095            name().c_str(),alignment->GetName());
0096   if ( i == m_cache.end() )   {
0097     m_cache[index] = pn;
0098     return true;
0099   }
0100   return false;
0101 }
0102 
0103 /// Retrieve the cache section corresponding to the path of an entry.
0104 GlobalAlignmentCache* GlobalAlignmentCache::section(const std::string& path_name) const   {
0105   std::size_t idx, idq;
0106   if ( path_name[0] != '/' )   {
0107     return section(m_detDesc.world().placementPath()+'/'+path_name);
0108   }
0109   else if ( (idx=path_name.find('/',1)) == std::string::npos )  {
0110     return (m_sdPath == path_name.c_str()+1) ? (GlobalAlignmentCache*)this : 0;
0111   }
0112   else if ( m_detectors.empty() )  {
0113     return 0;
0114   }
0115   if ( (idq=path_name.find('/',idx+1)) != std::string::npos ) --idq;
0116   std::string path = path_name.substr(idx+1,idq-idx);
0117   SubdetectorAlignments::const_iterator j = m_detectors.find(path);
0118   return (j==m_detectors.end()) ? 0 : (*j).second;
0119 }
0120 
0121 /// Retrieve an alignment entry by its placement path
0122 GlobalAlignment GlobalAlignmentCache::get(const std::string& path_name) const   {
0123   std::size_t idx, idq;
0124   unsigned int index = detail::hash32(path_name.c_str()+m_sdPathLen);
0125   Cache::const_iterator i = m_cache.find(index);
0126   if ( i != m_cache.end() )  {
0127     return GlobalAlignment((*i).second);
0128   }
0129   else if ( m_detectors.empty() )  {
0130     return GlobalAlignment(0);
0131   }
0132   else if ( path_name[0] != '/' )   {
0133     return get(m_detDesc.world().placementPath()+'/'+path_name);
0134   }
0135   else if ( (idx=path_name.find('/',1)) == std::string::npos )  {
0136     // Escape: World volume and not found in cache --> not present
0137     return GlobalAlignment(0);
0138   }
0139   if ( (idq=path_name.find('/',idx+1)) != std::string::npos ) --idq;
0140   std::string path = path_name.substr(idx+1, idq-idx);
0141   SubdetectorAlignments::const_iterator j = m_detectors.find(path);
0142   if ( j != m_detectors.end() ) return (*j).second->get(path_name);
0143   return GlobalAlignment(0);
0144 }
0145 
0146 /// Return all entries matching a given path.
0147 std::vector<GlobalAlignment>
0148 GlobalAlignmentCache::matches(const std::string& match, bool exclude_exact) const   {
0149   std::vector<GlobalAlignment> result;
0150   GlobalAlignmentCache* c = section(match);
0151   if ( c )  {
0152     std::size_t len = match.length();
0153     result.reserve(c->m_cache.size());
0154     for(Cache::const_iterator i=c->m_cache.begin(); i!=c->m_cache.end();++i)  {
0155       const Cache::value_type& v = *i;
0156       const char* n = v.second->GetName();
0157       if ( 0 == ::strncmp(n,match.c_str(),len) )   {
0158         if ( exclude_exact && len == ::strlen(n) ) continue;
0159         result.emplace_back(GlobalAlignment(v.second));
0160       }
0161     }
0162   }
0163   return result;
0164 }
0165 
0166 /// Close existing transaction stack and apply all alignments
0167 void GlobalAlignmentCache::commit(GlobalAlignmentStack& stack)   {
0168   TGeoManager& mgr = m_detDesc.manager();
0169   mgr.UnlockGeometry();
0170   apply(stack);
0171   mgr.LockGeometry();
0172 }
0173 
0174 /// Retrieve branch cache by name. If not present it will be created
0175 GlobalAlignmentCache* GlobalAlignmentCache::subdetectorAlignments(const std::string& nam)    {
0176   SubdetectorAlignments::const_iterator i = m_detectors.find(nam);
0177   if ( i == m_detectors.end() )   {
0178     GlobalAlignmentCache* ptr = new GlobalAlignmentCache(m_detDesc,nam,false);
0179     m_detectors.emplace(nam,ptr);
0180     return ptr;
0181   }
0182   return (*i).second;
0183 }
0184 
0185 /// Apply a complete stack of ordered alignments to the geometry structure
0186 void GlobalAlignmentCache::apply(GlobalAlignmentStack& stack)    {
0187   typedef std::map<std::string,DetElement> DetElementUpdates;
0188   typedef std::map<DetElement,std::vector<Entry*> > sd_entries_t;
0189   TGeoManager& mgr = m_detDesc.manager();
0190   DetElementUpdates detelt_updates;
0191   sd_entries_t all;
0192 
0193   while(stack.size() > 0)    {
0194     Entry* e = stack.pop().release();
0195     DetElement det = _detector(e->detector);
0196     all[det].emplace_back(e);
0197     if ( stack.hasMatrix(*e) || stack.needsReset(*e) || stack.resetChildren(*e) )  {
0198       detelt_updates.emplace(e->detector.path(),e->detector);
0199     }
0200   }
0201   for(sd_entries_t::iterator i=all.begin(); i!=all.end(); ++i)  {
0202     DetElement det((*i).first);
0203     GlobalAlignmentCache* sd_cache = subdetectorAlignments(det.placement().name());
0204     sd_cache->apply( (*i).second );
0205     (*i).second.clear();
0206   }
0207 
0208   printout(INFO,"GlobalAlignmentCache","Alignments were applied. Refreshing physical nodes....");
0209   mgr.GetCurrentNavigator()->ResetAll();
0210   mgr.GetCurrentNavigator()->BuildCache();
0211   mgr.RefreshPhysicalNodes();
0212 
0213   // Provide update callback for every detector element with a changed placement
0214   for(DetElementUpdates::iterator i=detelt_updates.begin(); i!=detelt_updates.end(); ++i)  {
0215     DetElement elt((*i).second);
0216     printout(DEBUG,"GlobalAlignmentCache","+++ Trigger placement update for %s [2]",elt.path().c_str());
0217     elt->update(DetElement::PLACEMENT_CHANGED|DetElement::PLACEMENT_ELEMENT,elt.ptr());
0218   }
0219   // Provide update callback for the highest detector element
0220   std::string last_path = "?????";
0221   for(DetElementUpdates::iterator i=detelt_updates.begin(); i!=detelt_updates.end(); ++i)  {
0222     const std::string& path = (*i).first;
0223     if ( path.find(last_path) == std::string::npos )  {
0224       DetElement elt((*i).second);
0225       printout(DEBUG,"GlobalAlignmentCache","+++ Trigger placement update for %s [1]",elt.path().c_str());
0226       elt->update(DetElement::PLACEMENT_CHANGED|DetElement::PLACEMENT_HIGHEST,elt.ptr());
0227       last_path = (*i).first;
0228     }
0229   }
0230   // Provide update callback at the detector level
0231   for(sd_entries_t::iterator i=all.begin(); i!=all.end(); ++i)  {
0232     DetElement elt((*i).first);
0233     printout(DEBUG,"GlobalAlignmentCache","+++ Trigger placement update for %s [0]",elt.path().c_str());
0234     elt->update(DetElement::PLACEMENT_CHANGED|DetElement::PLACEMENT_DETECTOR,elt.ptr());
0235   }
0236 }
0237 
0238 /// Apply a vector of SD entries of ordered alignments to the geometry structure
0239 void GlobalAlignmentCache::apply(const std::vector<Entry*>& changes)   {
0240   std::map<std::string,std::pair<TGeoPhysicalNode*,Entry*> > nodes;
0241   namespace ops = dd4hep::align::DDAlign_standard_operations;
0242   GlobalAlignmentSelector selector(*this,nodes,changes);
0243 
0244   for_each(m_cache.begin(),m_cache.end(),selector.reset());
0245   for_each(nodes.begin(),nodes.end(),GlobalAlignmentActor<ops::node_print>(*this,nodes));
0246   for_each(nodes.begin(),nodes.end(),GlobalAlignmentActor<ops::node_reset>(*this,nodes));
0247 
0248   for_each(changes.begin(),changes.end(),selector.reset());
0249   for_each(nodes.begin(),nodes.end(),GlobalAlignmentActor<ops::node_align>(*this,nodes));
0250   for_each(nodes.begin(),nodes.end(),GlobalAlignmentActor<ops::node_delete>(*this,nodes));
0251 }