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
AlignmentsManager.cpp
Go to the documentation of this file.
1 //==========================================================================
2 // AIDA Detector description implementation for LCD
3 //--------------------------------------------------------------------------
4 // Copyright (C) Organisation europeenne pour la Recherche nucleaire (CERN)
5 // All rights reserved.
6 //
7 // For the licensing terms see $DD4hepINSTALL/LICENSE.
8 // For the list of contributors see $DD4hepINSTALL/doc/CREDITS.
9 //
10 // Author : M.Frank
11 //
12 //==========================================================================
13 
14 // Framework include files
15 #include "DD4hep/LCDD.h"
16 #include "DD4hep/Handle.inl"
17 #include "DD4hep/Printout.h"
18 #include "DD4hep/InstanceCount.h"
19 #include "DD4hep/MatrixHelpers.h"
20 #include "DDCond/ConditionsPool.h"
22 
23 using namespace DD4hep;
24 using namespace DD4hep::Alignments;
25 
27 namespace DD4hep {
28 
30  namespace Alignments {
31 
33 
34  class AlignContext {
35  public:
36  struct Entry {
37  const Dependency* dep;
40  unsigned int key, top, valid;
41  };
42  struct PathOrdering {
43  bool operator()(const DetElement& a, const DetElement& b) const
44  { return a.path() < b.path(); }
45  };
46  typedef std::map<DetElement,size_t,PathOrdering> DetectorMap;
47  typedef std::map<unsigned int,size_t> Keys;
48  typedef std::vector<Entry> Entries;
49 
53  unsigned long long int magic;
54  AlignContext() : magic(magic_word()) {
56  }
59  }
61  if ( det.isValid() ) {
62  Entry entry;
63  unsigned int key = det.key();
64  entry.valid = 0;
65  entry.top = 0;
66  entry.cond = con;
67  entry.dep = dep;
68  entry.det = det.ptr();
69  entry.key = key;
70  detectors.insert(std::make_pair(det, entries.size()));
71  keys.insert(std::make_pair(key, entries.size()));
72  entries.insert(entries.end(), entry);
73  }
74  }
75  };
76 
78  template <> AlignmentsManager AlignmentsManager::from<LCDD>(LCDD& host) {
79  Object* obj = host.extension<Object>();
80  if ( obj ) return AlignmentsManager(obj);
81  except("AlignmentsManager","+++ Failed to access manager from LCDD.");
82  return AlignmentsManager();
83  }
84 
85  } /* End namespace Alignments */
86 } /* End namespace DD4hep */
87 
88 
91 
96  dependencies = new Dependencies();
97 }
98 
101  dependencies->clear();
105 }
106 
108  UserPool& pool,
109  DetElement det,
110  TGeoHMatrix& delta_to_world) const
111 {
112  using Conditions::Condition;
113  DetElement par = det.parent();
114  while( par.isValid() ) {
115  // If we find that the parent also got updated, directly take this transformation.
116  // Since we compute top-down, it is already valid!
117  AlignContext::Keys::const_iterator i = new_alignments.keys.find(par.key());
118  if ( i != new_alignments.keys.end() ) {
119  const AlignContext::Entry& e = new_alignments.entries[(*i).second];
120  // The parent entry is (not yet) valid. need to compute it first
121  if ( 0 == e.valid ) {
122  compute(new_alignments, pool, par);
123  }
124  AlignmentCondition cond(e.cond);
125  AlignmentData& align = cond.data();
126  if ( s_PRINT <= INFO ) {
127  printf("Multiply-left ALIGNMENT %s:", det.path().c_str()); delta_to_world.Print();
128  printf(" with ALIGN(world) %s :", par.path().c_str());
129  align.worldDelta.Print();
130  }
131  delta_to_world.MultiplyLeft(&align.worldDelta);
132  if ( s_PRINT <= INFO ) {
133  printf(" Result :"); delta_to_world.Print();
134  }
135  return;
136  }
137  // The parent did not get updated: We have to search the conditions pool if
138  // there is a still valid condition, which we can use to build the world transformation
139  // The parent's alignment condition by defintiion must be present in the pool,
140  // since it got updated in the past!
141  i = all_alignments->keys.find(par.key());
142  if ( i != all_alignments->keys.end() ) {
143  const AlignContext::Entry& e = all_alignments->entries[(*i).second];
144  Condition::key_type key = e.dep->target.hash;
145  AlignmentCondition cond = pool.get(key);
146  AlignmentData& align = cond.data();
147  if ( s_PRINT <= INFO ) {
148  printf("Multiply-left ALIGNMENT %s:", det.path().c_str()); delta_to_world.Print();
149  printf(" with ALIGN(world) %s :", par.path().c_str());
150  align.worldDelta.Print();
151  }
152  delta_to_world.MultiplyLeft(&align.worldDelta);
153  if ( s_PRINT <= INFO ) {
154  printf(" Result :"); delta_to_world.Print();
155  }
156  return;
157  }
158  // There is no special alignment for this detector element.
159  // Hence to nominal (relative) transformation to the parent is valid
160  if ( s_PRINT <= INFO ) {
161  printf("Multiply-left ALIGNMENT %s:", det.path().c_str()); delta_to_world.Print();
162  printf(" with NOMINAL(det) %s :", par.path().c_str());
163  par.nominal().detectorTransformation().Print();
164  }
165  delta_to_world.MultiplyLeft(&par.nominal().detectorTransformation());
166  if ( s_PRINT <= INFO ) {
167  printf(" Result :"); delta_to_world.Print();
168  }
169  par = par.parent();
170  }
171 }
172 
174 void AlignmentsManagerObject::compute(UserPool& user_pool) const {
175  compute(user_pool, *dependencies);
176 }
177 
179 void AlignmentsManagerObject::compute(UserPool& pool, const Dependencies& deps) const {
180  AlignContext new_alignments;
181  new_alignments.entries.reserve(deps.size());
182  pool.compute(deps, &new_alignments);
183  for(auto i=new_alignments.entries.begin(); i != new_alignments.entries.end(); ++i)
184  compute(new_alignments, pool, (*i).det);
185  for(auto i=new_alignments.entries.begin(); i != new_alignments.entries.end(); ++i)
186  compute(new_alignments, pool, (*i).det);
187 #if 0
188  std::string prev = "-----";
189  for(auto i=new_alignments.detectors.begin(); i!=new_alignments.detectors.end(); ++i) {
190  AlignContext::Entry& e = new_alignments.entries[(*i).second];
191  DetElement det = e.det;
192  const std::string& p = det.path();
193  size_t idx = p.find(prev);
194  if ( idx == 0 ) {
195  continue;
196  }
197  prev = p;
198  printout(s_PRINT,"Alignment","Update top Node: Lvl:%d Key:%08X: %s", det.level(), det.key(), p.c_str());
199  e.top = 1;
200  }
201  // We got now the top nodes of the new_alignments. From the top nodes we have to
202  // recursively calculate all changes downwards the lower levels!
203  // Note: The upper levels are already correct and do not need to be updated!
204  printout(INFO,"Alignment","Working down the tree....");
205  for(auto i=new_alignments.detectors.begin(); i != new_alignments.detectors.end(); ++i) {
206  AlignContext::Entry& e = new_alignments.entries[(*i).second];
207  if ( e.top ) {
208  compute(new_alignments, pool, e.det);
209  }
210  }
211 #endif
212 }
213 
215 static void computeDelta(AlignmentCondition cond, TGeoHMatrix& tr_delta) {
216  const AlignmentData& align = cond.data();
217  const Delta& delta = align.delta;
218  const Position& pos = delta.translation;
219  const Translation3D& piv = delta.pivot;
220  const RotationZYX& rot = delta.rotation;
221 
222  switch(delta.flags) {
224  Geometry::_transform(tr_delta, Transform3D(Translation3D(pos)*piv*rot*(piv.Inverse())));
225  break;
227  Geometry::_transform(tr_delta, Transform3D(rot,pos));
228  break;
230  Geometry::_transform(tr_delta, Transform3D(piv*rot*(piv.Inverse())));
231  break;
233  Geometry::_transform(tr_delta, rot);
234  break;
236  Geometry::_transform(tr_delta, pos);
237  break;
238  default:
239  break;
240  }
241 }
242 
244 void AlignmentsManagerObject::compute(AlignContext& new_alignments, UserPool& pool, DetElement det) const {
245  auto k=new_alignments.keys.find(det.key());
246  bool has_cond = (k != new_alignments.keys.end());
247  AlignContext::Entry* ent = has_cond ? &new_alignments.entries[(*k).second] : 0;
248 
249  if ( ent && ent->valid == 1 ) {
250  printout(DEBUG,"ComputeAlignment","================ IGNORE %s (already valid)",det.path().c_str());
251  return;
252  }
253  if ( ent && ent->valid == 0 ) {
254  TGeoHMatrix tr_delta;
255  AlignmentCondition cond = ent->cond;
256  AlignmentData& align = cond.data();
257  if ( s_PRINT <= INFO ) {
258  printout(INFO,"ComputeAlignment",
259  "============================== Compute transformation of %s ============================== ",
260  det.path().c_str());
261  }
262  ent->valid = 1;
263  computeDelta(cond, tr_delta);
264  align.worldDelta = tr_delta;
265  to_world(new_alignments, pool, det, align.worldDelta);
266  align.worldTrafo = det.nominal().worldTransformation()*align.worldDelta;
267  align.detectorTrafo = det.nominal().detectorTransformation()*tr_delta;
268  align.trToWorld = Geometry::_transform(&align.worldDelta);
269  if ( s_PRINT <= INFO ) {
270  printout(INFO,"ComputeAlignment","Level:%d Path:%s DetKey:%08X: Cond:%s key:%08X IOV:%s",
271  det.level(), det.path().c_str(), det.key(),
272  yes_no(has_cond), cond.key(), cond.iov().str().c_str());
273  }
274  if ( s_PRINT <= DEBUG ) {
275  printf("DetectorTrafo: '%s' -> '%s' ",det.path().c_str(), det.parent().path().c_str());
276  det.nominal().detectorTransformation().Print();
277  printf("Delta: '%s' ",det.path().c_str()); tr_delta.Print();
278  printf("World-Delta: '%s' ",det.path().c_str()); align.worldDelta.Print();
279  printf("Nominal: '%s' ",det.path().c_str()); det.nominal().worldTransformation().Print();
280  printf("Result: '%s' ",det.path().c_str()); align.worldTrafo.Print();
281  }
282  }
283  else {
284  // DetElement 'det' has no specific alignment. If any of the children has one
285  // and any of the parents, 'to_world' should pick up all the proper components
286  // to build the proper world-transformation of the child.
287  // Hence, we do not have to recompute it's value.
288  // We just continue to trickle down to the children.
289  //
290  // Alternatively we could inject 'special' alignment conditions, which would depend
291  // on the parent...
292  // Under circumstances, this might be cheaper to re-compute.
293  //
294  // NOT HANDLED HERE!
295  // Solution uses derived conditions to generate AlignmentCondition
296  // objects with an empty Delta.
297  //
298  // Handled in the alignment plugin: DDAlign_AlignmentForward,
299  // to be executed AFTER DDAlign_AlignmentRegister.
300  // This plugin will inject the relevant dependency calls.
301  //
302  }
303  const DetElement::Children& children = det.children();
304  for(auto c=children.begin(); c!=children.end(); ++c) {
305  DetElement child = (*c).second;
306  compute(new_alignments, pool, child);
307  }
308 }
309 
311 AlignmentsManager::AlignmentsManager(const std::string& nam) {
312  assign(new AlignmentsManagerObject(), nam, "alignmentmanager");
313 }
314 
317  assign(new AlignmentsManagerObject(), nam ? nam : "", "alignmentmanager");
318 }
319 
323 }
324 
327  Object* o = access();
328  auto res = o->dependencies->insert(dependency);
329  if ( res.second ) {
330  o->all_alignments->newEntry(dependency->detector, dependency, 0);
331  return res.second;
332  }
333  return false;
334 }
335 
338  return *(access()->dependencies);
339 }
340 
343  Object* o = access();
344  o->compute(*user_pool, *(o->dependencies));
345 }
346 
348 void AlignmentsManager::compute(dd4hep_ptr<UserPool>& user_pool, const Dependencies& deps) const {
349  access()->compute(*user_pool, deps);
350 }
351 
354  DetElement& det,
355  const Dependency* dep,
356  AlignmentCondition& con) {
357  // It must be ensured this is a valid object! Check magic word
358  AlignContext* o = static_cast<AlignContext*>(context.parameter);
359  if ( o && o->magic == magic_word() ) {
360  o->newEntry(det, dep, con.ptr());
361  return;
362  }
363 }
unsigned int top
Data & data()
Data accessor for the use of decorators.
Definition: Alignments.cpp:86
key_type key() const
Access the hash identifier.
Definition: Alignments.cpp:81
void destroy()
Delete the manager. Be careful: this affects all referencing handles!
The data class behind an alignments handle.
TGeoHMatrix detectorTrafo
Intermediate buffer to store the transformation to the parent detector element.
void deletePtr(T *&p)
Helper to delete objects from heap and reset the pointer. Saves many many lines of code...
Definition: Primitives.h:234
void clear()
Clear the dependency container. Destroys the contained stuff.
void newEntry(DetElement det, const Dependency *dep, AlignmentCondition::Object *con)
TGeoHMatrix worldDelta
Delta transformation to the world coordination system.
std::pair< iterator, bool > insert(const Dependencies::value_type &entry)
Mini-container interface: insert element by key.
AlignmentCondition::Object * cond
static void decrement(T *)
Decrement count according to type information.
const char * yes_no(bool value)
Helper function to print booleans in format YES/NO.
Definition: Printout.h:295
Main condition object handle.
Definition: Conditions.h:70
virtual ~AlignmentsManagerObject()
Default destructor.
DD4HEP_INSTANTIATE_HANDLE_NAMED(AlignmentsManagerObject)
Out version of the std auto_ptr implementation base either on auto_ptr or unique_ptr.
Definition: Memory.h:43
return e
Definition: Volumes.cpp:297
bool adoptDependency(Dependency *dependency) const
Adopy alignment dependency for later recalculation.
int except(const std::string &src, const std::string &fmt,...)
Calls the display action with ERROR and throws an std::runtime_error exception.
Definition: Printout.cpp:217
const Dependencies & knownDependencies() const
Access all known dependencies.
PrintLevel
Definition: Printout.h:47
T * ptr() const
Access to the held object.
Definition: Handle.h:149
DD4hep::Geometry::DetElement DetElement
Condition dependency definition.
Alignment manager instance to handle alignment dependencies.
Implementation of a named object.
Definition: NamedObject.h:31
bool operator()(const DetElement &a, const DetElement &b) const
unsigned int valid
ROOT::Math::RotationZYX RotationZYX
Definition: Objects.h:98
Delta delta
Alignment changes.
AlignmentsManager::Dependencies Dependencies
TGeoHMatrix * _transform(const Geometry::Transform3D &trans)
Convert a Transform3D object to a TGeoHMatrix
ConditionUpdateContext class used by the derived conditions calculation mechanism.
static PrintLevel s_PRINT
void assign(Implementation *n, const std::string &nam, const std::string &title)
Assign a new named object. Note: object references must be managed by the user.
unsigned int key
Dependencies * dependencies
Full list of alignment dependencies.
AlignmentsManagerObject * access() const
Checked object access. Throws invalid handle runtime exception.
void compute(AlignContext &new_alignments, UserPool &pool, DetElement child) const
Compute all alignment conditions of the lower levels.
AlignmentsManagerObject()
Initializing constructor.
Class describing an condition to re-adjust an alignment.
Definition: AlignmentData.h:49
ROOT::Math::XYZVector Position
Definition: Objects.h:75
DetElement::Object * det
static void newEntry(const Context &parameter, DetElement &det, const Dependency *dep, AlignmentCondition &con)
Register new updated derived alignment during the computation step.
void compute(dd4hep_ptr< UserPool > &user_pool) const
Compute all alignment conditions of the internal dependency list.
DetElement detector
Reference to the target's detector element.
const iov_type & iov() const
Access the IOV block.
Definition: Alignments.cpp:76
DetElement parent() const
Access to the detector elements's parent.
Definition: Detector.cpp:222
static void increment(T *)
Increment count according to type information.
Definition: InstanceCount.h:98
AlignmentsManager()=default
Default constructor.
ROOT::Math::Translation3D Translation3D
Definition: Objects.h:112
size_t size() const
Mini-container interface: number of entries.
key_type hash
Hashed key representation.
Definition: Conditions.h:281
Main handle class to hold an alignment conditions object.
Definition: Alignments.h:142
Transform3D trToWorld
Transformation from volume to the world.
std::map< std::string, DetElement > Children
Definition: Detector.h:202
AlignmentsManagerObject * m_element
Single and only data member: Reference to the actual element.
Definition: Handle.h:96
Data class with properties of a detector element.
ConditionKey target
Key to the condition to be updated.
int printout(PrintLevel severity, const char *src, const char *fmt,...)
Calls the display action with a given severity level.
Definition: Printout.cpp:111
ROOT::Math::Transform3D Transform3D
Definition: Objects.h:110
AlignContext * all_alignments
References to all alignment possibilities known.
const Dependency * dep
void to_world(AlignContext &new_alignments, UserPool &pool, DetElement det, TGeoHMatrix &mat) const
Compute the transformation from the closest detector element of the alignment to the world system...
Derived condition data-object definition.
std::string path
Full path to this detector element. May be invalid.
static void computeDelta(AlignmentCondition cond, TGeoHMatrix &tr_delta)
Compute the alignment delta for one detector element and it's alignment condition.
unsigned long long int magic_word()
Access to the magic word, which is protecting some objects against memory corruptions.
Definition: Handle.h:55
Conditions::ConditionDependency Dependency
std::map< DetElement, size_t, PathOrdering > DetectorMap
TGeoHMatrix worldTrafo
Intermediate buffer to store the transformation to the world coordination system. ...
std::map< unsigned int, size_t > Keys
std::string str() const
Create string representation of the IOV.
Definition: IOV.cpp:126