Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2026-09-08 08:22:33

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 <DDAlign/GlobalDetectorAlignment.h>
0016 #include <DD4hep/DetectorTools.h>
0017 #include <DD4hep/InstanceCount.h>
0018 #include <DD4hep/MatrixHelpers.h>
0019 #include <DD4hep/Printout.h>
0020 #include <DD4hep/detail/Handle.inl>
0021 #include <DD4hep/detail/DetectorInterna.h>
0022 
0023 // ROOT include files
0024 #include <TGeoMatrix.h>
0025 #include <TGeoManager.h>
0026 
0027 #ifdef __GNUC__    // Disable some diagnostics.
0028 #pragma GCC diagnostic ignored "-Wunused-function"
0029 #endif
0030 
0031 using LevelElements = std::vector<std::pair<int,dd4hep::DetElement> >;
0032 using namespace dd4hep::align;
0033 using dd4hep::printout;
0034 using dd4hep::INFO;
0035 
0036 /// Namespace for the AIDA detector description toolkit
0037 namespace dd4hep {
0038 
0039   /// Namespace for the alignment part of the AIDA detector description toolkit
0040   namespace align {
0041 
0042     /// Global alignment data container
0043     /**
0044      *   \author  M.Frank
0045      *   \version 1.0
0046      *   \ingroup DD4HEP_DDALIGN
0047      */
0048     class GlobalAlignmentData : public NamedObject  {
0049     public:
0050       GlobalAlignment              global;
0051       std::vector<GlobalAlignment> volume_alignments;
0052       
0053     public:
0054       GlobalAlignmentData(const std::string& path)
0055         : NamedObject(path, "global-alignment")
0056       {
0057         this->global = GlobalAlignment( path );
0058       }
0059       virtual ~GlobalAlignmentData()  {
0060         detail::destroyHandle( this->global );
0061       }
0062     };
0063   }   /* End namespace Aligments               */
0064 }     /* End namespace dd4hep                  */
0065 
0066 DD4HEP_INSTANTIATE_HANDLE_NAMED(GlobalAlignmentData);
0067 
0068 namespace {
0069 
0070   static bool s_GlobalDetectorAlignment_debug = true;
0071 
0072   GlobalAlignment _align(const GlobalAlignment& a, TGeoHMatrix* transform, bool check, double overlap) {
0073     TGeoPhysicalNode* node = a.ptr();
0074     if ( node )  {
0075       TGeoMatrix* mm = node->GetNode()->GetMatrix();
0076       bool dbg = GlobalDetectorAlignment::debug();
0077       if ( dbg )  {
0078         printout( INFO, "Alignment", "DELTA matrix of %s", node->GetName() );
0079         transform->Print();
0080         printout( INFO, "Alignment", "OLD matrix of %s", node->GetName() );
0081         mm->Print();
0082       }
0083       std::vector<dd4hep::PlacedVolume> places;
0084       for( int i = 0; i < node->GetLevel(); ++i )
0085         places.emplace_back( node->GetNode(i+1) );
0086 
0087       transform->MultiplyLeft(mm); // orig * delta
0088       node->Align( transform, 0, check, overlap );
0089       if ( dbg )  {
0090         printout( INFO, "Alignment", "NEW matrix of %s", node->GetName() );
0091         node->GetNode()->GetMatrix()->Print();
0092       }
0093       TGeoVolume* oldm;
0094       dd4hep::PlacedVolume pv = node->GetNode(0);
0095       dd4hep::Volume       v  = pv->GetVolume();
0096       std::string          path = "/";
0097 
0098       dbg = false;
0099       // dbg = true;
0100       path += pv->GetName();
0101       for( int i = 0; i < node->GetLevel(); ++i )  {
0102         /// Attach user extension to placed volume
0103         pv = node->GetNode( i+1 );
0104         if ( nullptr == pv->GetUserExtension() )  {
0105           pv->SetUserExtension( places[i]->GetUserExtension() );
0106         }
0107         oldm = pv->GetMotherVolume();
0108         if( dbg )  {
0109           path += "/";
0110           path += pv->GetName();
0111           if( oldm != v.ptr() )  {
0112             printout(dd4hep::ALWAYS, "GlobalAlignment",
0113                      // "+++ Mother relationship broken after alignment: %s  place: %p volume: %p mother volume: old: %p new: %p",
0114                      "+++ Fix mother relationship after alignment: %s  place: %p volume: %p mother volume: old: %p new: %p",
0115                      path.c_str(), (void*)pv.ptr(), (void*)pv->GetVolume(), (void*)oldm, (void*)v.ptr() );
0116           }
0117         }
0118         pv->SetMotherVolume( v.ptr() );
0119         /// Fix node volumes: attach extensions etc.
0120         v = pv->GetVolume();
0121         /// Fix daughter mother relationship for the nodes in the branches
0122         for( int idau = 0; idau < v->GetNdaughters(); ++idau )  {
0123           TGeoNode* dau = v->GetNode( idau );
0124           if( v.ptr() != dau->GetMotherVolume() )  {
0125             dau->SetMotherVolume( v );
0126             if( dbg )  {
0127               oldm = dau->GetMotherVolume();
0128               if( oldm != v.ptr() )  {
0129                 printout(dd4hep::ALWAYS, "GlobalAlignment",
0130                          // "+++ Mother relationship broken after alignment: %s/%s  place: %p volume: %p mother volume: old: %p --> new: %p",
0131                          "+++ Fix mother relationship after alignment: %s/%s  place: %p volume: %p "
0132                          "mother volume: old: %p --> new: %p",
0133                          path.c_str(), dau->GetName(), (void*)dau, (void*)dau->GetVolume(),
0134                          (void*)oldm, (void*)v.ptr());
0135               }
0136             }
0137           }
0138         }
0139         /// Attach user extension to volume
0140         if ( nullptr == v->GetUserExtension() )  {
0141           v->SetUserExtension( places[i].volume()->GetUserExtension() );
0142         }
0143       }
0144       return GlobalAlignment(node);
0145     }
0146     dd4hep::except("GlobalDetectorAlignment", "Cannot align non existing physical node. [Invalid Handle]");
0147     return { };
0148   }
0149   
0150   GlobalAlignment _alignment(const GlobalDetectorAlignment& det)  {
0151     dd4hep::DetElement::Object& e = det._data();
0152     if ( !e.global_alignment.isValid() )  {
0153       std::string path   = dd4hep::detail::tools::placementPath(det);
0154       e.global_alignment = dd4hep::Ref_t(new GlobalAlignmentData(path));
0155     }
0156     dd4hep::Handle<GlobalAlignmentData> h(e.global_alignment);
0157     if ( h.isValid() && h->global.isValid() )  {
0158       return h->global;
0159     }
0160     dd4hep::except("GlobalDetectorAlignment", "Cannot access global alignment data. [Invalid Handle]");
0161     return { };
0162   }
0163 
0164   void _dumpParentElements(GlobalDetectorAlignment& det, LevelElements& elements)   {
0165     int level = 0;
0166     dd4hep::detail::tools::PlacementPath nodes;
0167     dd4hep::detail::tools::ElementPath   det_nodes;
0168     dd4hep::detail::tools::placementPath(det, nodes);
0169     dd4hep::detail::tools::elementPath(det, det_nodes);
0170     ///    std::cout << "Placement path:";
0171     dd4hep::detail::tools::PlacementPath::const_reverse_iterator j=nodes.rbegin();
0172     dd4hep::detail::tools::ElementPath::const_reverse_iterator   k=det_nodes.rbegin();
0173     for(; j!=nodes.rend(); ++j, ++level)  {
0174       //cout << "(" << level << ") " << (void*)((*j).ptr())
0175       //           << " " << string((*j)->GetName()) << " ";
0176       if ( ::strcmp((*j).ptr()->GetName(), (*k).placement().ptr()->GetName()) )  {
0177         //cout << "[DE]";
0178         elements.emplace_back(level, *k);
0179         ++k;
0180       }
0181       else  {
0182         //elements.emplace_back(level,DetElement());
0183       }
0184       //std::cout << " ";
0185     }
0186     //std::cout << std::endl;
0187   }
0188 }
0189 
0190 /// Initializing constructor
0191 GlobalDetectorAlignment::GlobalDetectorAlignment(DetElement e)
0192   : DetElement(std::move(e))
0193 {
0194 }
0195 
0196 /// Initializing constructor
0197 GlobalDetectorAlignment::GlobalDetectorAlignment(DetElement&& e)
0198   : DetElement(std::move(e))
0199 {
0200 }
0201 
0202 /// Access debugging flag
0203 bool GlobalDetectorAlignment::debug()   {
0204   return s_GlobalDetectorAlignment_debug;
0205 }
0206 
0207 /// Set debugging flag
0208 bool GlobalDetectorAlignment::debug(bool value)   {
0209   bool tmp = s_GlobalDetectorAlignment_debug;
0210   s_GlobalDetectorAlignment_debug = value;
0211   return tmp;
0212 }
0213 
0214 /// Collect all placements from the detector element up to the world volume
0215 void GlobalDetectorAlignment::collectNodes(std::vector<PlacedVolume>& nodes)   {
0216   detail::tools::placementPath(*this, nodes);
0217 }
0218 
0219 /// Access to the alignment block
0220 GlobalAlignment GlobalDetectorAlignment::alignment() const   {
0221   return _alignment(*this);
0222 }
0223 
0224 /// Alignment entries for lower level volumes, which are NOT attached to daughter DetElements
0225 std::vector<GlobalAlignment>& GlobalDetectorAlignment::volumeAlignments()  {
0226   Handle<GlobalAlignmentData> h(_data().global_alignment);
0227   return h->volume_alignments;
0228 }
0229 
0230 /// Alignment entries for lower level volumes, which are NOT attached to daughter DetElements
0231 const std::vector<GlobalAlignment>& GlobalDetectorAlignment::volumeAlignments() const   {
0232   Handle<GlobalAlignmentData> h(_data().global_alignment);
0233   return h->volume_alignments;
0234 }
0235 
0236 /// Align the PhysicalNode of the placement of the detector element (translation only)
0237 GlobalAlignment GlobalDetectorAlignment::align(const Position& pos, bool chk, double overlap) {
0238   return align(detail::matrix::_transform(pos), chk, overlap);
0239 }
0240 
0241 /// Align the PhysicalNode of the placement of the detector element (rotation only)
0242 GlobalAlignment GlobalDetectorAlignment::align(const RotationZYX& rot, bool chk, double overlap) {
0243   return align(detail::matrix::_transform(rot), chk, overlap);
0244 }
0245 
0246 /// Align the PhysicalNode of the placement of the detector element (translation + rotation)
0247 GlobalAlignment GlobalDetectorAlignment::align(const Position& pos, const RotationZYX& rot, bool chk, double overlap) {
0248   return align(detail::matrix::_transform(pos, rot), chk, overlap);
0249 }
0250 
0251 /// Align the physical node according to a generic Transform3D
0252 GlobalAlignment GlobalDetectorAlignment::align(const Transform3D& transform, bool chk, double overlap)  {
0253   return align(detail::matrix::_transform(transform), chk, overlap);
0254 }
0255 
0256 /// Align the physical node according to a generic TGeo matrix
0257 GlobalAlignment GlobalDetectorAlignment::align(TGeoHMatrix* matrix, bool chk, double overlap)  {
0258   return _align(_alignment(*this), matrix, chk, overlap);
0259 }
0260 
0261 /// Align the PhysicalNode of the placement of the detector element (translation only)
0262 GlobalAlignment GlobalDetectorAlignment::align(const std::string& elt_path, const Position& pos, bool chk, double overlap) {
0263   return align(elt_path,detail::matrix::_transform(pos), chk, overlap);
0264 }
0265 
0266 /// Align the PhysicalNode of the placement of the detector element (rotation only)
0267 GlobalAlignment GlobalDetectorAlignment::align(const std::string& elt_path, const RotationZYX& rot, bool chk, double overlap) {
0268   return align(elt_path,detail::matrix::_transform(rot), chk, overlap);
0269 }
0270 
0271 /// Align the PhysicalNode of the placement of the detector element (translation + rotation)
0272 GlobalAlignment 
0273 GlobalDetectorAlignment::align(const std::string& elt_path, const Position& pos, const RotationZYX& rot, bool chk, double overlap) {
0274   return align(elt_path,detail::matrix::_transform(pos, rot), chk, overlap);
0275 }
0276 
0277 /// Align the physical node according to a generic Transform3D
0278 GlobalAlignment GlobalDetectorAlignment::align(const std::string& elt_path, const Transform3D& transform, bool chk, double overlap)  {
0279   return align(elt_path,detail::matrix::_transform(transform), chk, overlap);
0280 }
0281 
0282 /// Align the physical node according to a generic TGeo matrix
0283 GlobalAlignment GlobalDetectorAlignment::align(const std::string& elt_path, TGeoHMatrix* matrix, bool chk, double overlap)  {
0284   if ( elt_path.empty() )
0285     return _align(_alignment(*this), matrix, chk, overlap);
0286   else if ( elt_path == placementPath() )
0287     return _align(_alignment(*this), matrix, chk, overlap);
0288   else if ( elt_path[0] == '/' )   {
0289     GlobalAlignment a(elt_path);
0290     volumeAlignments().emplace_back(a);
0291     return _align(a, matrix, chk, overlap);
0292   }
0293   GlobalAlignment a(placementPath() + '/' + elt_path);
0294   volumeAlignments().emplace_back(a);
0295   return _align(a, matrix, chk, overlap);
0296 }