Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2025-01-30 09:17:17

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 <DDEve/View.h>
0016 #include <DDEve/Display.h>
0017 #include <DDEve/ViewMenu.h>
0018 #include <DDEve/DD4hepMenu.h>
0019 #include <DDEve/ElementList.h>
0020 #include <DDEve/GenericEventHandler.h>
0021 #include <DDEve/EveShapeContextMenu.h>
0022 #include <DDEve/EvePgonSetProjectedContextMenu.h>
0023 #include <DDEve/Utilities.h>
0024 #include <DDEve/DDEveEventData.h>
0025 #include <DDEve/HitActors.h>
0026 #include <DDEve/ParticleActors.h>
0027 
0028 #include <DD4hep/Detector.h>
0029 #include <DD4hep/DetectorData.h>
0030 #include <DD4hep/Printout.h>
0031 
0032 // ROOT include files
0033 #include <TROOT.h>
0034 #include <TH2.h>
0035 #include <TFile.h>
0036 #include <TSystem.h>
0037 #include <TGTab.h>
0038 #include <TGMsgBox.h>
0039 #include <TGClient.h>
0040 #include <TGFileDialog.h>
0041 #include <TEveScene.h>
0042 #include <TEveBrowser.h>
0043 #include <TEveManager.h>
0044 #include <TEveCaloData.h>
0045 #include <TEveCalo.h>
0046 #include <TEveViewer.h>
0047 #include <TEveCompound.h>
0048 #include <TEveBoxSet.h>
0049 #include <TEvePointSet.h>
0050 #include <TEveGeoShape.h>
0051 #include <TEveTrackPropagator.h>
0052 #include <TGeoManager.h>
0053 
0054 // C/C++ include files
0055 #include <stdexcept>
0056 #include <climits>
0057 
0058 using namespace dd4hep;
0059 using namespace dd4hep::detail;
0060 
0061 ClassImp(Display)
0062 
0063 namespace dd4hep {
0064   void EveDisplay(const char* xmlConfig = 0, const char* eventFileName = 0)  {
0065     Display* display = new Display(TEveManager::Create(true,"VI"));
0066     if ( xmlConfig != 0 )   {
0067       char text[PATH_MAX];
0068       ::snprintf(text,sizeof(text),"%s%s",strncmp(xmlConfig,"file:",5)==0 ? "file:" : "",xmlConfig);
0069       display->LoadXML(text);
0070     }
0071     else   {
0072       display->MessageBox(INFO,"No DDEve setup given.\nYou need to choose now.....\n"
0073                           "If you need an example, open\n\n"
0074                           "examples/CLIDSid/eve/DDEve.xml\n"
0075                           "and the corresponding event data\n"
0076                           "examples/CLIDSid/eve/CLICSiD_Events.root\n\n\n",
0077                           "Need to choos setup file");
0078       display->ChooseGeometry();
0079       //display->LoadXML("file:../DD4hep/examples/CLICSiD/compact/DDEve.xml");
0080     }
0081     if (eventFileName != 0) {
0082       display->eventHandler().Open(display->getEventHandlerName(),eventFileName);
0083     }
0084   }
0085 }
0086 
0087 /// Standard constructor
0088 Display::Display(TEveManager* eve) 
0089   : m_eve(eve), m_detDesc(0), m_evtHandler(0), m_geoGlobal(0), m_eveGlobal(0),
0090     m_viewMenu(0), m_dd4Menu(0), m_visLevel(7), m_loadLevel(1)
0091 {
0092   TEveBrowser* br = m_eve->GetBrowser();
0093   TGMenuBar*   menu = br->GetMenuBar();
0094   EveShapeContextMenu::install(this);
0095   EvePgonSetProjectedContextMenu::install(this);
0096   ElementListContextMenu::install(this);
0097   m_detDesc = &Detector::getInstance();
0098   TEveGeoShape::GetGeoMangeur()->AddNavigator();
0099   TEveGeoShape::GetGeoMangeur()->SetCurrentNavigator(0);
0100   m_evtHandler = new GenericEventHandler();
0101   m_evtHandler->Subscribe(this);
0102   m_detDesc->addExtension<Display>(this);
0103   br->ShowCloseTab(kFALSE);
0104   m_eve->GetViewers()->SwitchColorSet();
0105   TFile::SetCacheFileDir(".");
0106   BuildMenus(menu);
0107   br->SetTabTitle("Global Scene",TRootBrowser::kRight,0);
0108 }
0109 
0110 /// Default destructor
0111 Display::~Display()   {
0112   TRootBrowser* br = m_eve->GetBrowser();
0113   m_detDesc->removeExtension<Display>(false);
0114   m_viewConfigs.clear();
0115   deletePtr(m_evtHandler);
0116   deletePtr(m_eveGlobal);
0117   deletePtr(m_geoGlobal);
0118   br->CloseTabs();
0119   deletePtr(m_dd4Menu);
0120   deletePtr(m_viewMenu);
0121   deletePtr(m_eve);
0122   //br->ReallyDelete();
0123   DetectorData* data = dynamic_cast<DetectorData*>(m_detDesc);
0124   if ( data ) data->destroyData(false);
0125   deletePtr(m_detDesc);
0126   gGeoManager = 0;
0127   gEve = 0;
0128 }
0129 
0130 /// Load geometry from compact xml file
0131 void Display::LoadXML(const char* xmlFile)     {
0132   TGeoManager& mgr = m_detDesc->manager();
0133   bool has_geo = !m_geoTopics.empty();
0134   m_detDesc->fromXML(xmlFile);
0135   if ( !has_geo )  {
0136     LoadGeoChildren(0,m_loadLevel,false);
0137     mgr.SetVisLevel(m_visLevel);
0138   }
0139   if ( m_dd4Menu && !m_geoTopics.empty() )   {
0140     m_dd4Menu->OnGeometryLoaded();
0141   }
0142 
0143   m_eve->FullRedraw3D(kTRUE); // Reset camera 
0144   BuildMenus(m_eve->GetBrowser()->GetMenuBar());
0145 }
0146 
0147 /// Load geometry from compact xml file
0148 void Display::LoadGeometryRoot(const char* /* rootFile */)     {
0149   throw std::runtime_error("This call is not implemented !");
0150 }
0151 
0152 /// Load geometry with panel
0153 void Display::ChooseGeometry()   {
0154   m_dd4Menu->OnLoadXML(0,0);
0155 }
0156 
0157 /// Access to geometry hub
0158 Detector& Display::detectorDescription() const  {
0159   return *m_detDesc;
0160 }
0161 
0162 /// Access to X-client
0163 TGClient& Display::client() const   {
0164   return *gClient;
0165 }
0166 
0167 /// Access to the event reader
0168 GenericEventHandler& Display::eventHandler() const   {
0169   if ( m_evtHandler )  {
0170     return *m_evtHandler;
0171   }
0172   throw std::runtime_error("Invalid event handler");
0173 }
0174 
0175 /// Add new menu to the main menu bar
0176 void Display::AddMenu(TGMenuBar* menubar, PopupMenu* menu, int hints)  {
0177   m_menus.insert(menu);
0178   menu->Build(menubar, hints);
0179   m_eve->FullRedraw3D(kTRUE); // Reset camera and redraw
0180 }
0181 
0182 /// Import configuration parameters
0183 void Display::ImportConfiguration(const DisplayConfiguration& config)   {
0184   DisplayConfiguration::ViewConfigurations::const_iterator i;
0185   for(i=config.views.begin(); i!=config.views.end(); ++i)  
0186     m_viewConfigs[(*i).name] = *i;
0187 
0188   DisplayConfiguration::Configurations::const_iterator j;
0189   for(j=config.calodata.begin(); j!=config.calodata.end(); ++j)  
0190     m_calodataConfigs[(*j).name] = *j;
0191   for(j=config.collections.begin(); j!=config.collections.end(); ++j)  
0192     m_collectionsConfigs[(*j).name] = *j;
0193 }
0194 
0195 /// Access to calo data histograms by name as defined in the configuration
0196 Display::CalodataContext& Display::GetCaloHistogram(const std::string& nam)   {
0197   Calodata::iterator i = m_calodata.find(nam);
0198   if ( i == m_calodata.end() )  {
0199     DataConfigurations::const_iterator j = m_calodataConfigs.find(nam);
0200     if ( j != m_calodataConfigs.end() )   {
0201       CalodataContext ctx;
0202       ctx.config = (*j).second;
0203       std::string use = ctx.config.use;
0204       std::string hits = ctx.config.hits;
0205       if ( use.empty() )  {
0206         const char* n = nam.c_str();
0207         const DisplayConfiguration::Calodata& cd = (*j).second.data.calodata;
0208         TH2F* h = new TH2F(n,n,cd.n_eta, cd.eta_min, cd.eta_max, cd.n_phi, cd.phi_min, cd.phi_max);
0209         h->SetTitle(hits.c_str());
0210         ctx.eveHist = new TEveCaloDataHist();
0211         ctx.slice = ctx.eveHist->GetNSlices();
0212         ctx.eveHist->AddHistogram(h);
0213         ctx.eveHist->RefSliceInfo(0).Setup(n,cd.threshold,cd.color,101);
0214         ctx.eveHist->GetEtaBins()->SetTitleFont(120);
0215         ctx.eveHist->GetEtaBins()->SetTitle("h");
0216         ctx.eveHist->GetPhiBins()->SetTitleFont(120);
0217         ctx.eveHist->GetPhiBins()->SetTitle("f");
0218         ctx.eveHist->IncDenyDestroy();
0219 
0220         ctx.calo3D = new TEveCalo3D(ctx.eveHist);
0221         ctx.calo3D->SetName(n);
0222         ctx.calo3D->SetBarrelRadius(cd.rmin);
0223         ctx.calo3D->SetEndCapPos(cd.dz);
0224         ctx.calo3D->SetAutoRange(kTRUE);
0225         ctx.calo3D->SetMaxTowerH(cd.towerH);
0226         ImportGeo(ctx.calo3D);
0227         EtaPhiHistogramActor actor(h);
0228         eventHandler().collectionLoop(hits,actor);
0229         ctx.eveHist->DataChanged();
0230       }
0231       else   {
0232         CalodataContext c = GetCaloHistogram(use);
0233         ctx = c;
0234         ctx.config.use  = std::move(use);
0235         ctx.config.hits = std::move(hits);
0236         ctx.config.name = nam;
0237       }
0238       i = m_calodata.emplace(nam, ctx).first;
0239       return (*i).second;      
0240     }
0241     throw std::runtime_error("Cannot access calodata configuration " + nam);
0242   }
0243   return (*i).second;
0244 }
0245 
0246 /// Access a data filter by name. Data filters are used to customize views
0247 const Display::ViewConfig* Display::GetViewConfiguration(const std::string& nam)  const   {
0248   ViewConfigurations::const_iterator i = m_viewConfigs.find(nam);
0249   return (i == m_viewConfigs.end()) ? 0 : &((*i).second);
0250 }
0251 
0252 /// Access a data filter by name. Data filters are used to customize calodatas
0253 const Display::DataConfig* Display::GetCalodataConfiguration(const std::string& nam)  const   {
0254   DataConfigurations::const_iterator i = m_calodataConfigs.find(nam);
0255   return (i == m_calodataConfigs.end()) ? 0 : &((*i).second);
0256 }
0257 
0258 /// Register to the main event scene on new events
0259 void Display::RegisterEvents(View* view)   {
0260   m_eveViews.insert(view);
0261 }
0262 
0263 /// Unregister from the main event scene
0264 void Display::UnregisterEvents(View* view)   {
0265   Views::iterator i = m_eveViews.find(view);
0266   if ( i != m_eveViews.end() )  {
0267     m_eveViews.erase(i);
0268   }
0269 }
0270 
0271 /// Open standard message box
0272 void Display::MessageBox(PrintLevel level, const std::string& text, const std::string& title) const   {
0273   std::string path = TString::Format("%s/", TROOT::GetIconPath().Data()).Data();
0274   const TGPicture* pic = 0;
0275   if ( level == VERBOSE )
0276     pic = client().GetPicture((path+"mb_asterisk_s.xpm").c_str());
0277   else if ( level == DEBUG )
0278     pic = client().GetPicture((path+"mb_asterisk_s.xpm").c_str());
0279   else if ( level == INFO )
0280     pic = client().GetPicture((path+"mb_asterisk_s.xpm").c_str());
0281   else if ( level == WARNING )
0282     pic = client().GetPicture((path+"mb_excalamation_s.xpm").c_str());
0283   else if ( level == ERROR )
0284     pic = client().GetPicture((path+"mb_stop.xpm").c_str());
0285   else if ( level == FATAL )
0286     pic = client().GetPicture((path+"interrupt.xpm").c_str());
0287   new TGMsgBox(gClient->GetRoot(),0,title.c_str(),text.c_str(),pic,
0288                kMBDismiss,0,kVerticalFrame,kTextLeft|kTextCenterY);
0289 }
0290 
0291 /// Popup XML file chooser. returns chosen file name; empty on cancel
0292 std::string Display::OpenXmlFileDialog(const std::string& default_dir)   const {
0293   static const char *evtFiletypes[] = { 
0294     "xml files",    "*.xml",
0295     "XML files",    "*.XML",
0296     "All files",     "*",
0297     0,               0 
0298   };
0299   TGFileInfo fi;
0300   fi.fFileTypes = evtFiletypes;
0301   fi.fIniDir    = StrDup(default_dir.c_str());
0302   fi.fFilename  = 0;
0303   new TGFileDialog(client().GetRoot(), 0, kFDOpen, &fi);
0304   if ( fi.fFilename ) {
0305     std::string ret = fi.fFilename;
0306     if ( ret.find("file:") != 0 ) return "file:"+ret;
0307     return ret;
0308   }
0309   return "";
0310 }
0311 
0312 /// Popup ROOT file chooser. returns chosen file name; empty on cancel
0313 std::string Display::OpenEventFileDialog(const std::string& default_dir)   const {
0314   static const char *evtFiletypes[] = { 
0315     "ROOT files",    "*.root",
0316     "SLCIO files",   "*.slcio",
0317     "LCIO files",    "*.lcio",
0318     "All files",     "*",
0319     0,               0 
0320   };
0321   TGFileInfo fi;
0322   fi.fFileTypes = evtFiletypes;
0323   fi.fIniDir    = StrDup(default_dir.c_str());
0324   fi.fFilename  = 0;
0325   new TGFileDialog(client().GetRoot(), 0, kFDOpen, &fi);
0326   if ( fi.fFilename ) {
0327     return fi.fFilename;
0328   }
0329   return "";
0330 }
0331 
0332 /// Build the DDEve specific menues
0333 void Display::BuildMenus(TGMenuBar* menubar)   {
0334   if ( 0 == menubar ) {
0335     menubar = m_eve->GetBrowser()->GetMenuBar();
0336   }
0337   if ( 0 == m_dd4Menu )  {
0338     m_dd4Menu = new DD4hepMenu(this);
0339     AddMenu(menubar, m_dd4Menu);
0340   }
0341   if ( 0 == m_viewMenu && !m_viewConfigs.empty() )  {
0342     m_viewMenu = new ViewMenu(this,"&Views");
0343     AddMenu(menubar, m_viewMenu, kLHintsRight);
0344   }
0345 }
0346 
0347 /// Open ROOT file
0348 TFile* Display::Open(const char* name) const   {
0349   TFile* f = TFile::Open(name);
0350   if ( f && !f->IsZombie() ) return f;
0351   throw std::runtime_error("+++ Failed to open ROOT file:"+std::string(name));
0352 }
0353 
0354 /// Consumer event data
0355 void Display::OnFileOpen(EventHandler& /* handler */ )   {
0356 }
0357 
0358 /// Consumer event data
0359 void Display::OnNewEvent(EventHandler& handler )   {
0360   typedef EventHandler::TypedEventCollections Types;
0361   typedef std::vector<EventHandler::Collection> Collections;
0362   const Types& types = handler.data();
0363   TEveElement* particles = 0;
0364 
0365   printout(ERROR,"EventHandler","+++ Display new event.....");
0366   manager().GetEventScene()->DestroyElements();
0367   for(Types::const_iterator ityp=types.begin(); ityp!=types.end(); ++ityp)  {
0368     const Collections& colls = (*ityp).second;
0369     for(Collections::const_iterator j=colls.begin(); j!=colls.end(); ++j)   {
0370       std::size_t len = (*j).second;
0371       if ( len > 0 )   {
0372         const char* nam = (*j).first;
0373         DataConfigurations::const_iterator icfg = m_collectionsConfigs.find(nam);
0374         DataConfigurations::const_iterator cfgend = m_collectionsConfigs.end();
0375         EventHandler::CollectionType typ = handler.collectionType(nam);
0376         if ( typ == EventHandler::CALO_HIT_COLLECTION ||
0377              typ == EventHandler::TRACKER_HIT_COLLECTION )  {
0378           if ( icfg != cfgend )  {
0379             const DataConfig& cfg = (*icfg).second;
0380             if ( ::toupper(cfg.use[0]) == 'T' || ::toupper(cfg.use[0]) == 'Y' )  {
0381               if ( cfg.hits == "PointSet" )  {
0382                 PointsetCreator cr(nam,len,cfg);
0383                 handler.collectionLoop((*j).first, cr);
0384                 ImportEvent(cr.element());
0385               }
0386               else if ( cfg.hits == "BoxSet" )  {
0387                 BoxsetCreator cr(nam,len,cfg);
0388                 handler.collectionLoop((*j).first, cr);
0389                 ImportEvent(cr.element());
0390               }
0391               else if ( cfg.hits == "TowerSet" )  {
0392                 TowersetCreator cr(nam,len,cfg);
0393                 handler.collectionLoop((*j).first, cr);
0394                 ImportEvent(cr.element());
0395               }
0396               else {  // Default is point set
0397                 PointsetCreator cr(nam,len);
0398                 handler.collectionLoop((*j).first, cr);
0399                 ImportEvent(cr.element());
0400               }
0401             }
0402           }
0403           else  {
0404             PointsetCreator cr(nam,len);
0405             handler.collectionLoop((*j).first, cr);
0406             ImportEvent(cr.element());
0407           }
0408         }
0409         else if ( typ == EventHandler::PARTICLE_COLLECTION )   {
0410           // We do not have to care about memory leaks here:
0411           // TEveTrackPropagator is reference counted and will be destroyed if the
0412           // last track is gone ie. when we re-initialize the event scene
0413 
0414           // $$$ Do not know exactly what the field parameters mean
0415           if ( (icfg=m_collectionsConfigs.find("StartVertexPoints")) != cfgend )   {
0416             StartVertexCreator cr("StartVertexPoints", len, (*icfg).second);
0417             handler.collectionLoop((*j).first, cr);
0418             printout(INFO,"Display","+++ StartVertexPoints: Filled %d start vertex points.....",cr.count);
0419             ImportEvent(cr.element());
0420           }
0421           if ( (icfg=m_collectionsConfigs.find("MCParticles")) != cfgend )   {
0422             MCParticleCreator cr(new TEveTrackPropagator("","",new TEveMagFieldDuo(350, -3.5, 2.0)),
0423                                  new TEveCompound("MC_Particles","MC_Particles"),
0424                                  icfg == cfgend ? 0 : &((*icfg).second));
0425             handler.collectionLoop((*j).first, cr);
0426             printout(INFO,"Display","+++ StartVertexPoints: Filled %d patricle tracks.....",cr.count);
0427             cr.close();
0428             particles = cr.particles;
0429           }
0430         }
0431       }
0432     }
0433   }
0434   for(Calodata::iterator i = m_calodata.begin(); i != m_calodata.end(); ++i)
0435     (*i).second.eveHist->GetHist(0)->Reset();
0436   for(Calodata::iterator i = m_calodata.begin(); i != m_calodata.end(); ++i)  {
0437     CalodataContext& ctx = (*i).second;
0438     TH2F* h = ctx.eveHist->GetHist(0);
0439     EtaPhiHistogramActor actor(h);
0440     std::size_t n = eventHandler().collectionLoop(ctx.config.hits, actor);
0441     ctx.eveHist->DataChanged();
0442     printout(INFO,"FillEtaPhiHistogram","+++ %s: Filled %ld hits from %s....",
0443              ctx.calo3D->GetName(), n, ctx.config.hits.c_str());
0444   }
0445   /// We absolutely want to import the particles as the last elements, otherwise
0446   /// they end up under the hits and are close to invisible
0447   if ( particles )  {
0448     ImportEvent(particles);
0449   }
0450   for(Views::iterator i = m_eveViews.begin(); i != m_eveViews.end(); ++i)
0451     (*i)->ConfigureEventFromInfo();
0452   manager().Redraw3D();
0453 }
0454 
0455 /// Access / Create global geometry element
0456 TEveElementList& Display::GetGeo()   {
0457   if ( 0 == m_geoGlobal )  {
0458     m_geoGlobal = new ElementList("Geo-Global","Geo-Global", true, true);
0459     manager().AddGlobalElement(m_geoGlobal);
0460   }
0461   return *m_geoGlobal;
0462 }
0463 
0464 /// Access/Create a topic by name
0465 TEveElementList& Display::GetGeoTopic(const std::string& name)    {
0466   Topics::iterator i=m_geoTopics.find(name);
0467   if ( i == m_geoTopics.end() )  {
0468     TEveElementList* topic = new ElementList(name.c_str(), name.c_str(), true, true);
0469     m_geoTopics[name] = topic;
0470     GetGeo().AddElement(topic);
0471     return *topic;
0472   }
0473   return *((*i).second);
0474 }
0475 
0476 /// Access/Create a topic by name. Throws exception if the topic does not exist
0477 TEveElementList& Display::GetGeoTopic(const std::string& name) const   {
0478   Topics::const_iterator i=m_geoTopics.find(name);
0479   if ( i == m_geoTopics.end() )  {
0480     throw std::runtime_error("Display: Attempt to access non-existing geometry topic:"+name);
0481   }
0482   return *((*i).second);
0483 }
0484 
0485 /// Access/Create a topic by name
0486 TEveElementList& Display::GetEveTopic(const std::string& name)    {
0487   Topics::iterator i=m_eveTopics.find(name);
0488   if ( i == m_eveTopics.end() )  {
0489     TEveElementList* topic = new ElementList(name.c_str(), name.c_str(), true, true);
0490     m_eveTopics[name] = topic;
0491     manager().GetEventScene()->AddElement(topic);
0492     return *topic;
0493   }
0494   return *((*i).second);
0495 }
0496 
0497 /// Access/Create a topic by name. Throws exception if the topic does not exist
0498 TEveElementList& Display::GetEveTopic(const std::string& name) const   {
0499   Topics::const_iterator i=m_eveTopics.find(name);
0500   if ( i == m_eveTopics.end() )  {
0501     throw std::runtime_error("Display: Attempt to access non-existing event topic:"+name);
0502   }
0503   return *((*i).second);
0504 }
0505 
0506 /// Call to import geometry elements 
0507 void Display::ImportGeo(TEveElement* el)   {
0508   GetGeo().AddElement(el);
0509 }
0510 
0511 /// Call to import geometry elements by topic
0512 void Display::ImportGeo(const std::string& topic, TEveElement* el)  { 
0513   GetGeoTopic(topic).AddElement(el);
0514 }
0515 
0516 /// Call to import event elements by topic
0517 void Display::ImportEvent(const std::string& topic, TEveElement* el)  { 
0518   GetEveTopic(topic).AddElement(el);
0519 }
0520 
0521 /// Call to import top level event elements 
0522 void Display::ImportEvent(TEveElement* el)  { 
0523   manager().GetEventScene()->AddElement(el);
0524 }
0525 
0526 /// Load 'levels' Children into the geometry scene
0527 void Display::LoadGeoChildren(TEveElement* start, int levels, bool redraw)  {
0528   using namespace dd4hep::detail;
0529   DetElement world = m_detDesc->world();
0530   if ( world.children().size() == 0 )   {
0531     MessageBox(INFO,"It looks like there is no\nGeometry loaded.\nNo event display availible.\n");
0532   }
0533   else if ( levels > 0 )   {
0534     if ( 0 == start )     {
0535       TEveElementList& sens = GetGeoTopic("Sensitive");
0536       TEveElementList& struc = GetGeoTopic("Structure");
0537       const DetElement::Children& c = world.children();
0538       
0539       printout(INFO,"Display","+++ Load children of %s to %d levels", 
0540                world.placement().name(), levels);
0541       for (DetElement::Children::const_iterator i = c.begin(); i != c.end(); ++i) {
0542         DetElement de = (*i).second;
0543         SensitiveDetector sd = m_detDesc->sensitiveDetector(de.name());
0544         TEveElementList& parent = sd.isValid() ? sens : struc;
0545         std::pair<bool,TEveElement*> e = Utilities::LoadDetElement(de,levels,&parent);
0546         if ( e.second && e.first )  {
0547           parent.AddElement(e.second);
0548         }
0549       }
0550     }
0551     else    {
0552       TGeoNode* n = (TGeoNode*)start->GetUserData();
0553       printout(INFO,"Display","+++ Load children of %s to %d levels",Utilities::GetName(start),levels);
0554       if ( 0 != n )   {
0555         TGeoHMatrix mat;
0556         const char* node_name = n->GetName();
0557         int level = Utilities::findNodeWithMatrix(detectorDescription().world().placement().ptr(),n,&mat);
0558         if ( level > 0 )   {
0559           std::pair<bool,TEveElement*> e(false,0);
0560           const DetElement::Children& c = world.children();
0561           for (DetElement::Children::const_iterator i = c.begin(); i != c.end(); ++i) {
0562             DetElement de = (*i).second;
0563             if ( de.placement().ptr() == n )  {
0564               e = Utilities::createEveShape(0, levels, start, n, mat, de.name());
0565               break;
0566             }
0567           }
0568           if ( !e.first && !e.second )  {
0569             e = Utilities::createEveShape(0, levels, start, n, mat, node_name);
0570           }
0571           if ( e.first )  { // newly created
0572             start->AddElement(e.second);
0573           }
0574           printout(INFO,"Display","+++ Import geometry node %s with %d levels.",node_name, levels);
0575         }
0576         else   {
0577           printout(INFO,"Display","+++ FAILED to import geometry node %s with %d levels.",node_name, levels);
0578         }
0579       }
0580       else  {
0581         LoadGeoChildren(0,levels,false);
0582       }
0583     }
0584   }
0585   if ( redraw )   {
0586     manager().Redraw3D();
0587   }
0588 }
0589 
0590 /// Make a set of nodes starting from a top element (in-)visible with a given depth
0591 void Display::MakeNodesVisible(TEveElement* e, bool visible, int level)   {
0592   printout(INFO,"Display","+++ %s element %s with a depth of %d.",
0593            visible ? "Show" : "Hide",Utilities::GetName(e),level);
0594   Utilities::MakeNodesVisible(e, visible, level);
0595   manager().Redraw3D();
0596 }