Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2026-09-26 08:06:28

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/detail/Handle.inl>
0016 #include <DD4hep/detail/DetectorInterna.h>
0017 #include <DD4hep/detail/ConditionsInterna.h>
0018 #include <DD4hep/detail/AlignmentsInterna.h>
0019 #include <DD4hep/InstanceCount.h>
0020 #include <DD4hep/DetectorTools.h>
0021 #include <DD4hep/Printout.h>
0022 
0023 #include <TGeoVolume.h>
0024 #include <TGeoMatrix.h>
0025 #include <TGeoManager.h>
0026 
0027 using namespace dd4hep;
0028 
0029 using PlacementPath = detail::tools::PlacementPath;
0030 using ElementPath   =  detail::tools::ElementPath;
0031 
0032 DD4HEP_INSTANTIATE_HANDLE_NAMED(DetElementObject);
0033 DD4HEP_INSTANTIATE_HANDLE_NAMED(SensitiveDetectorObject);
0034 DD4HEP_INSTANTIATE_HANDLE_NAMED(WorldObject,DetElementObject);
0035 
0036 /// Default constructor
0037 SensitiveDetectorObject::SensitiveDetectorObject()
0038   : NamedObject(), ObjectExtensions(typeid(SensitiveDetectorObject)), magic(magic_word()),
0039     verbose(0), combineHits(0), ecut(0.0), readout(), region(), limits(), hitsCollection()
0040 {
0041   printout(VERBOSE,"SensitiveDetectorObject","+++ Created new anonymous SensitiveDetectorObject()");
0042   InstanceCount::increment(this);
0043 }
0044 
0045 /// Initializing constructor
0046 SensitiveDetectorObject::SensitiveDetectorObject(const std::string& nam)
0047   : NamedObject(), ObjectExtensions(typeid(SensitiveDetectorObject)), magic(magic_word()),
0048     verbose(0), combineHits(0), ecut(0.0), readout(), region(), limits(), hitsCollection()
0049 {
0050   SetName(nam.c_str());
0051   printout(VERBOSE,"SensitiveDetectorObject","+++ Created new SensitiveDetectorObject('%s')",nam.c_str());
0052   InstanceCount::increment(this);
0053 }
0054 
0055 /// Internal object destructor: release extension object(s)
0056 SensitiveDetectorObject::~SensitiveDetectorObject() {
0057   readout.clear();
0058   region.clear();
0059   limits.clear();
0060   ObjectExtensions::clear();
0061   InstanceCount::decrement(this);
0062 }
0063 
0064 /// Default constructor
0065 DetElementObject::DetElementObject()
0066   : NamedObject(), ObjectExtensions(typeid(DetElementObject)), magic(magic_word()),
0067     flag(0), id(0), combineHits(0), typeFlag(0), level(-1), key(0), path(), placementPath(),
0068     idealPlace(), placement(), volumeID(0), parent(), children(),
0069     nominal(), survey()
0070 {
0071   printout(VERBOSE,"DetElementObject","+++ Created new anonymous DetElementObject()");
0072   InstanceCount::increment(this);
0073 }
0074 
0075 /// Initializing constructor
0076 DetElementObject::DetElementObject(const std::string& nam, int ident)
0077   : NamedObject(), ObjectExtensions(typeid(DetElementObject)), magic(magic_word()),
0078     flag(0), id(ident), combineHits(0), typeFlag(0), level(-1), key(0), path(), placementPath(),
0079     idealPlace(), placement(), volumeID(0), parent(), children(),
0080     nominal(), survey()
0081 {
0082   SetName(nam.c_str());
0083   printout(VERBOSE,"DetElementObject","+++ Created new DetElementObject('%s', %d)",nam.c_str(),id);
0084   InstanceCount::increment(this);
0085 }
0086 
0087 /// Internal object destructor: release extension object(s)
0088 DetElementObject::~DetElementObject() {
0089   detail::destroyHandles(children);
0090   detail::destroyHandle (nominal);
0091   detail::destroyHandle (survey);
0092   placement.clear();
0093   idealPlace.clear();
0094   parent.clear();
0095   ObjectExtensions::clear();
0096   InstanceCount::decrement(this);
0097 }
0098 
0099 /// Deep object copy to replicate DetElement trees e.g. for reflection
0100 DetElementObject* DetElementObject::clone(int new_id, int flg) const {
0101   DetElementObject* obj = new DetElementObject();
0102   obj->id          = new_id;
0103   obj->typeFlag    = typeFlag;
0104   obj->flag        = 0;
0105   obj->key         = 0;
0106   obj->level       = -1;
0107   obj->combineHits = combineHits;
0108   obj->nominal     = AlignmentCondition();
0109   obj->survey      = AlignmentCondition();
0110   obj->parent      = DetElement();
0111   if ( (flg & DetElement::COPY_PLACEMENT) == DetElement::COPY_PLACEMENT )  {
0112     obj->placement     = placement;
0113     obj->idealPlace    = idealPlace;
0114     obj->placementPath = "";
0115   }
0116   // This implicitly assumes that the children do not access the parent's extensions!
0117   obj->ObjectExtensions::clear();
0118   obj->ObjectExtensions::copyFrom(extensions, obj);
0119 
0120   obj->children.clear();
0121   for( const auto& i : children )  {
0122     const DetElementObject& d = i.second._data();
0123     int child_id = flg&DetElement::PROPAGATE_PARENT_ID ? obj->id : d.id;
0124     DetElement c = d.clone(child_id, DetElement::COPY_PLACEMENT);
0125     c->SetName( d.GetName() );
0126     c->SetTitle( d.GetTitle() );
0127     bool r = obj->children.emplace(c.name(), c).second;
0128     if ( r ) {
0129       c._data().parent = obj;
0130       continue;
0131     }
0132     except("DetElement",
0133            "+++ DetElement::copy: Element %s is already present [Double-Insert]", c.name());
0134   }
0135   return obj;
0136 }
0137 
0138 /// Reflect all volumes in a DetElement sub-tree and re-attach the placements
0139 std::pair<DetElement,Volume> DetElementObject::reflect(const std::string& new_name, int new_id, SensitiveDetector sd)   {
0140   struct ChildMapper  {
0141     std::map<TGeoNode*,TGeoNode*> nodes;
0142     void match(DetElement de_det, DetElement de_ref)  const  {
0143       auto k = nodes.find(de_det.placement().ptr());
0144       printout(DEBUG,"DetElement","reflect: Match  %s %p  ",de_det.name(), de_det.placement().ptr());
0145       if ( k == nodes.end() )  {
0146         except("DetElement","reflect: Something went wrong when reflecting the source volume!");
0147       }
0148       de_ref.setPlacement((*k).second);
0149       const auto& childrens_det = de_det.children();
0150       const auto& childrens_ref = de_ref.children();
0151       for( auto i=childrens_det.begin(), j=childrens_ref.begin(); i!=childrens_det.end(); ++i, ++j )
0152         match((*i).second, (*j).second);
0153     }
0154     void map(TGeoNode* n1, TGeoNode* n2)   {
0155       if ( nodes.find(n1) == nodes.end() )   {
0156         TGeoVolume* v1 = n1->GetVolume();
0157         TGeoVolume* v2 = n2->GetVolume();
0158         nodes.insert(std::make_pair(n1,n2));
0159         printout(DEBUG,"DetElement","reflect: Map  %p  --- %p ",n1,n2);
0160         for( Int_t i=0; i<v1->GetNdaughters(); ++i )
0161           map(v1->GetNode(i), v2->GetNode(i));
0162       }
0163     }
0164   } mapper;
0165   DetElement  det(this);
0166   DetElement  det_ref   = det.clone(new_name, new_id);
0167   Volume      vol       = det.volume();
0168   TGeoVolume* vol_det   = vol.ptr();
0169   TGeoVolume* vol_ref   = vol.reflect(sd);
0170   const auto& childrens_det = det.children();
0171   const auto& childrens_ref = det_ref.children();
0172 
0173   for( Int_t i=0; i<vol_det->GetNdaughters(); ++i )
0174     mapper.map(vol_det->GetNode(i), vol_ref->GetNode(i));
0175   for( auto i=childrens_det.begin(), j=childrens_ref.begin(); i != childrens_det.end(); ++i, ++j )
0176     mapper.match((*i).second, (*j).second);
0177   return std::make_pair(det_ref,vol_ref);
0178 }
0179 
0180 /// Access to the world object. Only possible once the geometry is closed.
0181 World DetElementObject::i_access_world()   {
0182   if ( !privateWorld.isValid() )  {
0183     DetElementObject* p = parent.ptr();
0184     if ( 0 == p )  {
0185       privateWorld = (WorldObject*)this;
0186       return privateWorld;
0187     }
0188     return p->world();
0189   }
0190   return privateWorld;
0191 }
0192 
0193 /// Revalidate the daughter caches
0194 void DetElementObject::revalidate(bool recurse_down)  {
0195   PlacementPath par_path;
0196   DetElement    det(this);
0197   DetElement    par(det.parent());
0198   DetElement    wrld  = world();
0199   std::string   place = det.placementPath();
0200 
0201   detail::tools::placementPath(par, this, par_path);
0202   PlacedVolume node = detail::tools::findNode(wrld.placement(),place);
0203   if ( !node.isValid() )  {
0204     except("DetElement","The placement %s is not part of the hierarchy.",place.c_str());
0205   }
0206   printout( (idealPlace.ptr() != node.ptr()) ? INFO : DEBUG,
0207             "DetElement","+++ Revalidate DetElement cache of %s -> %s Placement:%p --> %p %s",
0208             det.path().c_str(), detail::tools::placementPath(par_path).c_str(),
0209             placement.ptr(), node.ptr(), (placement.ptr() == node.ptr()) ? "" : "[UPDATE]");
0210   if ( idealPlace.ptr() != node.ptr() && 0 == node->GetUserExtension() )  {
0211     auto ext = idealPlace->GetUserExtension();
0212     node->SetUserExtension(ext);
0213   }
0214   Volume node_vol = node.volume();
0215   Volume plac_vol = idealPlace.volume();
0216   if ( node_vol.ptr() != plac_vol.ptr() && 0 == node_vol->GetUserExtension() )  {
0217     auto ext = plac_vol->GetUserExtension();
0218     node_vol->SetUserExtension(ext);    
0219   }
0220   // Now we can assign the new placement to the object
0221   placement = node;
0222   
0223   /// Now iterate down the children....
0224   if( recurse_down )  {
0225     for(const auto& i : children )  {
0226       i.second->revalidate(recurse_down);
0227     }
0228   }
0229 }
0230 
0231 /// Revalidate the parent caches
0232 void DetElementObject::revalidate_parents()  {
0233   DetElement    det(this);
0234   DetElement    wrld = this->world();
0235   while( det.isValid() && det != wrld )  {
0236     det->revalidate(false);
0237     det = det.parent();
0238   }
0239 }
0240 
0241 /// Remove callback from object
0242 void DetElementObject::removeAtUpdate(unsigned int typ, void* pointer)   {
0243   for( auto i=updateCalls.begin(); i != updateCalls.end(); ++i )  {
0244     if ( (typ&(i->second)) == typ && i->first.par == pointer )  {
0245       updateCalls.erase(i);
0246       return;
0247     }
0248   }
0249 }
0250 
0251 /// Trigger update callbacks
0252 void DetElementObject::update(unsigned int tags, void* param)   {
0253   DetElement det(this);
0254   const void* args[3] = { (void*)((unsigned long)tags), this, param };
0255   if ( (tags&DetElement::PLACEMENT_CHANGED)==DetElement::PLACEMENT_CHANGED &&
0256        (tags&DetElement::PLACEMENT_HIGHEST)==DetElement::PLACEMENT_HIGHEST )  {
0257     printout(INFO,"DetElement",
0258              "++ Need to update local and child caches of %s",
0259              det.path().c_str());
0260     revalidate(true);
0261     revalidate_parents();
0262   }
0263   for ( const auto& i : updateCalls )  {
0264     if ( (tags&i.second) )
0265       i.first.execute(args);
0266   }
0267 }
0268 
0269 /// Initializing constructor
0270 WorldObject::WorldObject(Detector& _description, const std::string& nam) 
0271   : DetElementObject(nam,0), description(&_description)
0272 {
0273 }
0274 
0275 /// Internal object destructor: release extension object(s)
0276 WorldObject::~WorldObject()  {
0277 }