DD4hep - The AIDA detector description toolkit for high energy physics experiments
DD4hep  Rev:Unversioneddirectory
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
GlobalAlignmentCache.cpp
Go to the documentation of this file.
1 // $Id: $
2 //==========================================================================
3 // AIDA Detector description implementation for LCD
4 //--------------------------------------------------------------------------
5 // Copyright (C) Organisation europeenne pour la Recherche nucleaire (CERN)
6 // All rights reserved.
7 //
8 // For the licensing terms see $DD4hepINSTALL/LICENSE.
9 // For the list of contributors see $DD4hepINSTALL/doc/CREDITS.
10 //
11 // Author : M.Frank
12 //
13 //==========================================================================
14 
15 // Framework include files
16 #include "DD4hep/LCDD.h"
17 #include "DD4hep/Printout.h"
21 
22 // ROOT include files
23 #include "TGeoManager.h"
24 
25 using namespace std;
26 using namespace DD4hep;
27 using namespace DD4hep::Alignments;
28 using namespace DD4hep::Alignments::DDAlign_standard_operations;
30 
32  if ( child.isValid() ) {
33  DetElement p(child.parent());
34  if ( p.isValid() && !p.parent().isValid() )
35  return child;
36  else if ( !p.isValid() ) // World detector element...
37  return child;
38  return _detector(p);
39  }
40  throw runtime_error("DD4hep: DetElement cannot determine detector parent [Invalid handle]");
41 }
42 
44 GlobalAlignmentCache::GlobalAlignmentCache(LCDD& lcdd, const string& sdPath, bool top)
45  : m_lcdd(lcdd), m_sdPath(sdPath), m_sdPathLen(sdPath.length()), m_refCount(1), m_top(top)
46 {
47 }
48 
51  int nentries = (int)m_cache.size();
52  int nsect = (int)m_detectors.size();
54  m_cache.clear();
55  printout(INFO,"GlobalAlignmentCache",
56  "Destroy cache for subdetector %s [%d section(s), %d entrie(s)]",
57  m_sdPath.c_str(),nsect,nentries);
58 }
59 
62  return ++m_refCount;
63 }
64 
67  int value = --m_refCount;
68  if ( value == 0 ) {
69  delete this;
70  }
71  return value;
72 }
73 
76  GlobalAlignmentCache* cache = lcdd.extension<GlobalAlignmentCache>(false);
77  if ( !cache ) {
78  lcdd.addExtension<GlobalAlignmentCache>(new GlobalAlignmentCache(lcdd,"world",true));
79  }
80  return cache;
81 }
82 
85  if ( lcdd.extension<GlobalAlignmentCache>(false) ) {
86  lcdd.removeExtension<GlobalAlignmentCache>(true);
87  }
88 }
89 
92  TGeoPhysicalNode* pn = alignment.ptr();
93  unsigned int index = hash32(pn->GetName()+m_sdPathLen);
94  Cache::const_iterator i = m_cache.find(index);
95  printout(ALWAYS,"GlobalAlignmentCache","Section: %s adding entry: %s",
96  name().c_str(),alignment->GetName());
97  if ( i == m_cache.end() ) {
98  m_cache[index] = pn;
99  return true;
100  }
101  return false;
102 }
103 
105 GlobalAlignmentCache* GlobalAlignmentCache::section(const string& path_name) const {
106  size_t idx, idq;
107  if ( path_name[0] != '/' ) {
108  return section(m_lcdd.world().placementPath()+'/'+path_name);
109  }
110  else if ( (idx=path_name.find('/',1)) == string::npos ) {
111  return (m_sdPath == path_name.c_str()+1) ? (GlobalAlignmentCache*)this : 0;
112  }
113  else if ( m_detectors.empty() ) {
114  return 0;
115  }
116  if ( (idq=path_name.find('/',idx+1)) != string::npos ) --idq;
117  string path = path_name.substr(idx+1,idq-idx);
118  SubdetectorAlignments::const_iterator j = m_detectors.find(path);
119  return (j==m_detectors.end()) ? 0 : (*j).second;
120 }
121 
123 GlobalAlignment GlobalAlignmentCache::get(const string& path_name) const {
124  size_t idx, idq;
125  unsigned int index = hash32(path_name.c_str()+m_sdPathLen);
126  Cache::const_iterator i = m_cache.find(index);
127  if ( i != m_cache.end() ) {
128  return GlobalAlignment((*i).second);
129  }
130  else if ( m_detectors.empty() ) {
131  return GlobalAlignment(0);
132  }
133  else if ( path_name[0] != '/' ) {
134  return get(m_lcdd.world().placementPath()+'/'+path_name);
135  }
136  else if ( (idx=path_name.find('/',1)) == string::npos ) {
137  // Escape: World volume and not found in cache --> not present
138  return GlobalAlignment(0);
139  }
140  if ( (idq=path_name.find('/',idx+1)) != string::npos ) --idq;
141  string path = path_name.substr(idx+1,idq-idx);
142  SubdetectorAlignments::const_iterator j = m_detectors.find(path);
143  if ( j != m_detectors.end() ) return (*j).second->get(path_name);
144  return GlobalAlignment(0);
145 }
146 
148 vector<GlobalAlignment> GlobalAlignmentCache::matches(const string& match, bool exclude_exact) const {
149  vector<GlobalAlignment> result;
150  GlobalAlignmentCache* c = section(match);
151  if ( c ) {
152  size_t len = match.length();
153  result.reserve(c->m_cache.size());
154  for(Cache::const_iterator i=c->m_cache.begin(); i!=c->m_cache.end();++i) {
155  const Cache::value_type& v = *i;
156  const char* n = v.second->GetName();
157  if ( 0 == ::strncmp(n,match.c_str(),len) ) {
158  if ( exclude_exact && len == ::strlen(n) ) continue;
159  result.push_back(GlobalAlignment(v.second));
160  }
161  }
162  }
163  return result;
164 }
165 
168  TGeoManager& mgr = m_lcdd.manager();
169  mgr.UnlockGeometry();
170  apply(stack);
171  mgr.LockGeometry();
172 }
173 
176  SubdetectorAlignments::const_iterator i = m_detectors.find(nam);
177  if ( i == m_detectors.end() ) {
178  GlobalAlignmentCache* ptr = new GlobalAlignmentCache(m_lcdd,nam,false);
179  m_detectors.insert(make_pair(nam,ptr));
180  return ptr;
181  }
182  return (*i).second;
183 }
184 
187  typedef map<string,DetElement> DetElementUpdates;
188  typedef map<DetElement,vector<Entry*> > sd_entries_t;
189  TGeoManager& mgr = m_lcdd.manager();
190  DetElementUpdates detelt_updates;
191  sd_entries_t all;
192 
193  while(stack.size() > 0) {
194  Entry* e = stack.pop().release();
195  DetElement det = _detector(e->detector);
196  all[det].push_back(e);
197  if ( e->hasMatrix() || e->needsReset() || e->resetChildren() ) {
198  detelt_updates.insert(make_pair(e->detector.path(),e->detector));
199  }
200  }
201  for(sd_entries_t::iterator i=all.begin(); i!=all.end(); ++i) {
202  DetElement det((*i).first);
203  GlobalAlignmentCache* sd_cache = subdetectorAlignments(det.placement().name());
204  sd_cache->apply( (*i).second );
205  (*i).second.clear();
206  }
207 
208  printout(INFO,"GlobalAlignmentCache","Alignments were applied. Refreshing physical nodes....");
209  mgr.GetCurrentNavigator()->ResetAll();
210  mgr.GetCurrentNavigator()->BuildCache();
211  mgr.RefreshPhysicalNodes();
212 
213  // Provide update callback for every detector element with a changed placement
214  for(DetElementUpdates::iterator i=detelt_updates.begin(); i!=detelt_updates.end(); ++i) {
215  DetElement elt((*i).second);
216  printout(DEBUG,"GlobalAlignmentCache","+++ Trigger placement update for %s [2]",elt.path().c_str());
218  }
219  // Provide update callback for the highest detector element
220  string last_path = "?????";
221  for(DetElementUpdates::iterator i=detelt_updates.begin(); i!=detelt_updates.end(); ++i) {
222  const string& path = (*i).first;
223  if ( path.find(last_path) == string::npos ) {
224  DetElement elt((*i).second);
225  printout(DEBUG,"GlobalAlignmentCache","+++ Trigger placement update for %s [1]",elt.path().c_str());
227  last_path = (*i).first;
228  }
229  }
230  // Provide update callback at the detector level
231  for(sd_entries_t::iterator i=all.begin(); i!=all.end(); ++i) {
232  DetElement elt((*i).first);
233  printout(DEBUG,"GlobalAlignmentCache","+++ Trigger placement update for %s [0]",elt.path().c_str());
235  }
236 }
237 
239 void GlobalAlignmentCache::apply(const vector<Entry*>& changes) {
240  typedef map<string,pair<TGeoPhysicalNode*,Entry*> > Nodes;
241  Nodes nodes;
242  AlignmentSelector selector(*this,nodes,changes);
243  for_each(m_cache.begin(),m_cache.end(),selector.reset());
244  for_each(nodes.begin(),nodes.end(),AlignmentActor<node_print>(*this,nodes));
245  for_each(nodes.begin(),nodes.end(),AlignmentActor<node_reset>(*this,nodes));
246 
247  for_each(changes.begin(),changes.end(),selector.reset());
248  for_each(nodes.begin(),nodes.end(),AlignmentActor<node_align>(*this,nodes));
249  for_each(nodes.begin(),nodes.end(),AlignmentActor<node_delete>(*this,nodes));
250 }
Act on selected alignment entries.
Cache m_cache
The subdetector specific map of alignments caches.
GlobalAlignmentCache(LCDD &lcdd, const std::string &sdPath, bool top)
Default constructor initializing variables.
const AlignmentSelector & reset() const
bool insert(GlobalAlignment alignment)
Add a new entry to the cache. The key is the placement path.
bool isValid() const
Check the validity of the object held by the handle.
Definition: Handle.h:124
const std::string & name() const
Access the section name.
Main handle class to hold a TGeo alignment object of type TGeoPhysicalNode.
void commit(AlignmentStack &stack)
Close existing transaction stack and apply all alignments.
DetElement detector
Reference to the detector element.
std::vector< GlobalAlignment > matches(const std::string &path_match, bool exclude_exact=false) const
Return all entries matching a given path. Careful: Expensive operaton!
return e
Definition: Volumes.cpp:297
T * ptr() const
Access to the held object.
Definition: Handle.h:149
DD4hep::Geometry::DetElement DetElement
static void uninstall(LCDD &lcdd)
Unregister and delete a tree instance.
GlobalAlignment get(const std::string &path) const
Retrieve an alignment entry by its lacement path.
bool hasMatrix() const
Check if this alignment entry has a non unitary transformation matrix.
size_t size() const
Access size of the alignment stack.
size_t m_sdPathLen
The length of the branch name to optimize lookups....
bool needsReset() const
Check flag if the node location should be reset.
DetElement _detector(DetElement child)
void releaseObjects(M &m)
Definition: Primitives.h:344
int release()
Release object. If reference count goes to NULL, automatic deletion is triggered. ...
void apply(AlignmentStack &stack)
Population entry: Apply a complete stack of ordered alignments to the geometry structure.
DetElement parent() const
Access to the detector elements's parent.
Definition: Detector.cpp:222
virtual ~GlobalAlignmentCache()
Default destructor.
unsigned int hash32(const char *key)
We need it so often: one-at-time 32 bit hash function.
Definition: Primitives.h:39
SubdetectorAlignments m_detectors
Cache of subdetectors.
Class caching all known alignment operations for one LCDD instance.
Handle class describing a detector element.
Definition: Detector.h:172
static GlobalAlignmentCache * install(LCDD &lcdd)
Create and install a new instance tree.
View * v
Definition: MultiView.cpp:30
bool resetChildren() const
Check flag if the node location and all children should be reset.
GlobalAlignmentCache * subdetectorAlignments(const std::string &name)
Retrieve branch cache by name. If not present it will be created.
Stack entry definition.
GlobalAlignmentCache * section(const std::string &path_name) const
Retrieve the cache section corresponding to the path of an entry.
AlignmentStack::StackEntry Entry
int printout(PrintLevel severity, const char *src, const char *fmt,...)
Calls the display action with a given severity level.
Definition: Printout.cpp:111
Alignment Stack object definition.
dd4hep_ptr< StackEntry > pop()
Retrieve an alignment entry of the current stack.
Select alignment operations according to certain criteria.