//========================================================================== // AIDA Detector description implementation //-------------------------------------------------------------------------- // Copyright (C) Organisation europeenne pour la Recherche nucleaire (CERN) // All rights reserved. // // For the licensing terms see $DD4hepINSTALL/LICENSE. // For the list of contributors see $DD4hepINSTALL/doc/CREDITS. // // Author : M.Frank // //========================================================================== // Framework include files #include <DD4hep/Detector.h> #include <DD4hep/Objects.h> #include <DD4hep/Printout.h> #include <DD4hep/InstanceCount.h> #include <DDAlign/GlobalAlignmentStack.h> using namespace dd4hep::align; static dd4hep::dd4hep_ptr<GlobalAlignmentStack>& _stack() { static dd4hep::dd4hep_ptr<GlobalAlignmentStack> s; return s; } static dd4hep::dd4hep_ptr<GlobalAlignmentStack>& _stack(GlobalAlignmentStack* obj) { dd4hep::dd4hep_ptr<GlobalAlignmentStack>& stk = _stack(); stk.adopt(obj); return stk; } /// Constructor with partial initialization GlobalAlignmentStack::StackEntry::StackEntry(DetElement element, const std::string& p, const Delta& del, double ov) : detector(element), delta(del), path(p), overlap(ov) { InstanceCount::increment(this); } /// Copy constructor GlobalAlignmentStack::StackEntry::StackEntry(const StackEntry& e) : detector(e.detector), delta(e.delta), path(e.path), overlap(e.overlap) { InstanceCount::increment(this); } /// Default destructor GlobalAlignmentStack::StackEntry::~StackEntry() { InstanceCount::decrement(this); } #if 0 /// Set flag to reset the entry to its ideal geometrical position GlobalAlignmentStack::StackEntry& GlobalAlignmentStack::StackEntry::setReset(bool new_value) { new_value ? (delta.flags |= RESET_VALUE) : (delta.flags &= ~RESET_VALUE); return *this; } /// Set flag to reset the entry's children to their ideal geometrical position GlobalAlignmentStack::StackEntry& GlobalAlignmentStack::StackEntry::setResetChildren(bool new_value) { new_value ? (delta.flags |= RESET_CHILDREN) : (delta.flags &= ~RESET_CHILDREN); return *this; } /// Set flag to check overlaps GlobalAlignmentStack::StackEntry& GlobalAlignmentStack::StackEntry::setOverlapCheck(bool new_value) { new_value ? (delta.flags |= CHECKOVL_DEFINED) : (delta.flags &= ~CHECKOVL_DEFINED); return *this; } /// Set the precision for the overlap check (otherwise the default is 0.001 cm) GlobalAlignmentStack::StackEntry& GlobalAlignmentStack::StackEntry::setOverlapPrecision(double precision) { delta.flags |= CHECKOVL_DEFINED; delta.flags |= CHECKOVL_VALUE; overlap = precision; return *this; } #endif /// Default constructor GlobalAlignmentStack::GlobalAlignmentStack() { InstanceCount::increment(this); } /// Default destructor GlobalAlignmentStack::~GlobalAlignmentStack() { detail::destroyObjects(m_stack); InstanceCount::decrement(this); } /// Static client accessor GlobalAlignmentStack& GlobalAlignmentStack::get() { if ( _stack().get() ) return *_stack(); except("GlobalAlignmentStack", "Stack not allocated -- may not be retrieved!"); throw std::runtime_error("Stack not allocated"); } /// Create an alignment stack instance. The creation of a second instance will be refused. void GlobalAlignmentStack::create() { if ( _stack().get() ) { except("GlobalAlignmentStack", "Stack already allocated. Multiple copies are not allowed!"); } _stack(new GlobalAlignmentStack()); } /// Check existence of alignment stack bool GlobalAlignmentStack::exists() { return _stack().get() != 0; } /// Clear data content and remove the slignment stack void GlobalAlignmentStack::release() { if ( _stack().get() ) { _stack(0); return; } except("GlobalAlignmentStack", "Attempt to delete non existing stack."); } /// Add a new entry to the cache. The key is the placement path bool GlobalAlignmentStack::insert(const std::string& full_path, dd4hep_ptr<StackEntry>& entry) { if ( entry.get() && !full_path.empty() ) { entry->path = full_path; return add(entry); } except("GlobalAlignmentStack", "Attempt to apply an invalid alignment entry."); return false; } /// Add a new entry to the cache. The key is the placement path bool GlobalAlignmentStack::insert(dd4hep_ptr<StackEntry>& entry) { return add(entry); } /// Add a new entry to the cache. The key is the placement path bool GlobalAlignmentStack::add(dd4hep_ptr<StackEntry>& entry) { if ( entry.get() && !entry->path.empty() ) { Stack::const_iterator i = m_stack.find(entry->path); if ( i == m_stack.end() ) { StackEntry* e = entry.get(); // Need to make some checks BEFORE insertion if ( !e->detector.isValid() ) { except("GlobalAlignmentStack", "Invalid alignment entry [No such detector]"); } printout(INFO,"GlobalAlignmentStack","Add node:%s",e->path.c_str()); m_stack.emplace(e->path,entry.release()); return true; } except("GlobalAlignmentStack", "The entry with path "+entry->path+ " cannot be re-aligned twice in one transaction."); } except("GlobalAlignmentStack", "Attempt to apply an invalid alignment entry."); return false; } /// Retrieve an alignment entry of the current stack dd4hep::dd4hep_ptr<GlobalAlignmentStack::StackEntry> GlobalAlignmentStack::pop() { Stack::iterator i = m_stack.begin(); if ( i != m_stack.end() ) { dd4hep_ptr<StackEntry> e((*i).second); m_stack.erase(i); return e; } except("GlobalAlignmentStack", "Alignment stack is empty. " "Cannot pop entries - check size first!"); return {}; } /// Get all pathes to be aligned std::vector<const GlobalAlignmentStack::StackEntry*> GlobalAlignmentStack::entries() const { std::vector<const StackEntry*> result; result.reserve(m_stack.size()); transform(begin(m_stack),end(m_stack),back_inserter(result),detail::select2nd(m_stack)); return result; }