File indexing completed on 2025-01-30 09:17:17
0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013
0014
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
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
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
0080 }
0081 if (eventFileName != 0) {
0082 display->eventHandler().Open(display->getEventHandlerName(),eventFileName);
0083 }
0084 }
0085 }
0086
0087
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
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
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
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);
0144 BuildMenus(m_eve->GetBrowser()->GetMenuBar());
0145 }
0146
0147
0148 void Display::LoadGeometryRoot(const char* ) {
0149 throw std::runtime_error("This call is not implemented !");
0150 }
0151
0152
0153 void Display::ChooseGeometry() {
0154 m_dd4Menu->OnLoadXML(0,0);
0155 }
0156
0157
0158 Detector& Display::detectorDescription() const {
0159 return *m_detDesc;
0160 }
0161
0162
0163 TGClient& Display::client() const {
0164 return *gClient;
0165 }
0166
0167
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
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);
0180 }
0181
0182
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
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
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
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
0259 void Display::RegisterEvents(View* view) {
0260 m_eveViews.insert(view);
0261 }
0262
0263
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
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
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
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
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
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
0355 void Display::OnFileOpen(EventHandler& ) {
0356 }
0357
0358
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 {
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
0411
0412
0413
0414
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
0446
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
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
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
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
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
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
0507 void Display::ImportGeo(TEveElement* el) {
0508 GetGeo().AddElement(el);
0509 }
0510
0511
0512 void Display::ImportGeo(const std::string& topic, TEveElement* el) {
0513 GetGeoTopic(topic).AddElement(el);
0514 }
0515
0516
0517 void Display::ImportEvent(const std::string& topic, TEveElement* el) {
0518 GetEveTopic(topic).AddElement(el);
0519 }
0520
0521
0522 void Display::ImportEvent(TEveElement* el) {
0523 manager().GetEventScene()->AddElement(el);
0524 }
0525
0526
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 ) {
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
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 }