Fork me on GitHub

source: git/display/DelphesEventDisplay.cc@ 83e77ee

Last change on this file since 83e77ee was 341014c, checked in by Pavel Demin <pavel-demin@…>, 6 years ago

apply .clang-format to all .h, .cc and .cpp files

  • Property mode set to 100644
File size: 17.6 KB
Line 
1/*
2 * Delphes: a framework for fast simulation of a generic collider experiment
3 * Copyright (C) 2012-2014 Universite catholique de Louvain (UCL), Belgium
4 *
5 * This program is free software: you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation, either version 3 of the License, or
8 * (at your option) any later version.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with this program. If not, see <http://www.gnu.org/licenses/>.
17 */
18
19#include <algorithm>
20#include <cassert>
21#include <iostream>
22#include <utility>
23
24#include "TAxis.h"
25#include "TCanvas.h"
26#include "TChain.h"
27#include "TClonesArray.h"
28#include "TEveArrow.h"
29#include "TEveBrowser.h"
30#include "TEveCalo.h"
31#include "TEveElement.h"
32#include "TEveEventManager.h"
33#include "TEveGeoNode.h"
34#include "TEveJetCone.h"
35#include "TEveManager.h"
36#include "TEveTrack.h"
37#include "TEveTrackPropagator.h"
38#include "TEveTrans.h"
39#include "TEveViewer.h"
40#include "TGButton.h"
41#include "TGHtml.h"
42#include "TGNumberEntry.h"
43#include "TGProgressBar.h"
44#include "TGStatusBar.h"
45#include "TGTextEntry.h"
46#include "TGeoManager.h"
47#include "TGeoVolume.h"
48#include "TH1F.h"
49#include "TMath.h"
50#include "TRootBrowser.h"
51#include "TRootEmbeddedCanvas.h"
52#include "TSystem.h"
53
54#include "display/Delphes3DGeometry.h"
55#include "display/DelphesBranchElement.h"
56#include "display/DelphesCaloData.h"
57#include "display/DelphesDisplay.h"
58#include "display/DelphesEventDisplay.h"
59#include "display/DelphesHtmlSummary.h"
60#include "display/DelphesPlotSummary.h"
61
62#include "classes/DelphesClasses.h"
63#include "external/ExRootAnalysis/ExRootConfReader.h"
64#include "external/ExRootAnalysis/ExRootTreeReader.h"
65
66DelphesEventDisplay::DelphesEventDisplay()
67{
68 event_id_ = 0;
69 tkRadius_ = 1.29;
70 totRadius_ = 2.0;
71 tkHalfLength_ = 3.0;
72 muHalfLength_ = 6.0;
73 bz_ = 3.8;
74 chain_ = new TChain("Delphes");
75 treeReader_ = 0;
76 delphesDisplay_ = 0;
77 etaAxis_ = 0;
78 phiAxis_ = 0;
79}
80
81DelphesEventDisplay::~DelphesEventDisplay()
82{
83 delete chain_;
84}
85
86void DelphesEventDisplay::EventChanged(Int_t e)
87{
88 if(e != event_id_)
89 {
90 event_id_ = e;
91 Emit("EventChanged(Int_t)", e);
92 load_event();
93 }
94}
95
96DelphesEventDisplay::DelphesEventDisplay(const char *configFile, const char *inputFile, Delphes3DGeometry &det3D)
97{
98 event_id_ = 0;
99 tkRadius_ = 1.29;
100 totRadius_ = 2.0;
101 tkHalfLength_ = 3.0;
102 bz_ = 3.8;
103 chain_ = new TChain("Delphes");
104 treeReader_ = 0;
105 delphesDisplay_ = 0;
106
107 // initialize the application
108 TEveManager::Create(kTRUE, "IV");
109 fStatusBar_ = gEve->GetBrowser()->GetStatusBar();
110 TGeoManager *geom = gGeoManager;
111
112 // build the detector
113 tkRadius_ = det3D.getTrackerRadius();
114 totRadius_ = det3D.getDetectorRadius();
115 tkHalfLength_ = det3D.getTrackerHalfLength();
116 muHalfLength_ = det3D.getDetectorHalfLength();
117 bz_ = det3D.getBField();
118 etaAxis_ = det3D.getCaloAxes().first;
119 phiAxis_ = det3D.getCaloAxes().second;
120 TGeoVolume *top = det3D.getDetector(false);
121 geom->SetTopVolume(top);
122 TEveElementList *geometry = new TEveElementList("Geometry");
123 TObjArray *nodes = top->GetNodes();
124 TIter itNodes(nodes);
125 TGeoNode *nodeobj;
126 TEveGeoTopNode *node;
127 while((nodeobj = (TGeoNode *)itNodes.Next()))
128 {
129 node = new TEveGeoTopNode(gGeoManager, nodeobj);
130 node->UseNodeTrans();
131 geometry->AddElement(node);
132 }
133
134 // Create chain of root trees
135 chain_->Add(inputFile);
136
137 // Create object of class ExRootTreeReader
138 fStatusBar_->SetText("Opening Delphes data file", 1);
139 gSystem->ProcessEvents();
140 treeReader_ = new ExRootTreeReader(chain_);
141
142 // prepare data collections
143 readConfig(configFile, elements_);
144 for(std::vector<DelphesBranchBase *>::iterator element = elements_.begin(); element < elements_.end(); ++element)
145 {
146 DelphesBranchElement<TEveTrackList> *item_v1 = dynamic_cast<DelphesBranchElement<TEveTrackList> *>(*element);
147 DelphesBranchElement<TEveElementList> *item_v2 = dynamic_cast<DelphesBranchElement<TEveElementList> *>(*element);
148 if(item_v1) gEve->AddElement(item_v1->GetContainer());
149 if(item_v2) gEve->AddElement(item_v2->GetContainer());
150 }
151
152 // viewers and scenes
153 delphesDisplay_ = new DelphesDisplay;
154 gEve->AddGlobalElement(geometry);
155 delphesDisplay_->ImportGeomRPhi(geometry);
156 delphesDisplay_->ImportGeomRhoZ(geometry);
157 // find the first calo data and use that to initialize the calo display
158 for(std::vector<DelphesBranchBase *>::iterator data = elements_.begin(); data < elements_.end(); ++data)
159 {
160 if(TString((*data)->GetType()) == "Tower")
161 { // we could also use GetClassName()=="DelphesCaloData"
162 DelphesCaloData *container = dynamic_cast<DelphesBranchElement<DelphesCaloData> *>((*data))->GetContainer();
163 assert(container);
164 TEveCalo3D *calo3d = new TEveCalo3D(container);
165 calo3d->SetBarrelRadius(tkRadius_);
166 calo3d->SetEndCapPos(tkHalfLength_);
167 gEve->AddGlobalElement(calo3d);
168 delphesDisplay_->ImportCaloRPhi(calo3d);
169 delphesDisplay_->ImportCaloRhoZ(calo3d);
170 TEveCaloLego *lego = new TEveCaloLego(container);
171 lego->InitMainTrans();
172 // lego->RefMainTrans().SetScale(TMath::TwoPi(), TMath::TwoPi(), TMath::Pi());
173 lego->RefMainTrans().SetScale(100, 100, TMath::Pi());
174 lego->SetAutoRebin(kFALSE);
175 lego->Set2DMode(TEveCaloLego::kValSizeOutline);
176 delphesDisplay_->ImportCaloLego(lego);
177 break;
178 }
179 }
180
181 // the GUI: control panel, summary tab
182 make_gui();
183
184 //ready...
185 fStatusBar_->SetText("Ready.", 1);
186 gSystem->ProcessEvents();
187 load_event();
188 gEve->Redraw3D(kTRUE);
189}
190
191// function that parses the config to extract the branches of interest and prepare containers
192void DelphesEventDisplay::readConfig(const char *configFile, std::vector<DelphesBranchBase *> &elements)
193{
194 ExRootConfReader *confReader = new ExRootConfReader;
195 confReader->ReadFile(configFile);
196 ExRootConfParam branches = confReader->GetParam("TreeWriter::Branch");
197 Int_t nBranches = branches.GetSize() / 3;
198 DelphesBranchElement<TEveTrackList> *tlist;
199 DelphesBranchElement<DelphesCaloData> *clist;
200 DelphesBranchElement<TEveElementList> *elist;
201 // first loop with all but tracks
202 for(Int_t b = 0; b < nBranches; ++b)
203 {
204 TString input = branches[b * 3].GetString();
205 TString name = branches[b * 3 + 1].GetString();
206 TString className = branches[b * 3 + 2].GetString();
207 if(className == "Tower")
208 {
209 if(input.Contains("eflow", TString::kIgnoreCase) || name.Contains("eflow", TString::kIgnoreCase)) continue; //no eflow
210 clist = new DelphesBranchElement<DelphesCaloData>(name, treeReader_->UseBranch(name), kBlack);
211 clist->GetContainer()->SetEtaBins(etaAxis_);
212 clist->GetContainer()->SetPhiBins(phiAxis_);
213 elements.push_back(clist);
214 }
215 else if(className == "Jet")
216 {
217 if(input.Contains("GenJetFinder"))
218 {
219 elist = new DelphesBranchElement<TEveElementList>(name, treeReader_->UseBranch(name), kCyan);
220 elist->GetContainer()->SetRnrSelf(false);
221 elist->GetContainer()->SetRnrChildren(false);
222 elist->SetTrackingVolume(tkRadius_, tkHalfLength_, bz_);
223 elements.push_back(elist);
224 }
225 else
226 {
227 elist = new DelphesBranchElement<TEveElementList>(name, treeReader_->UseBranch(name), kYellow);
228 elist->SetTrackingVolume(tkRadius_, tkHalfLength_, bz_);
229 elements.push_back(elist);
230 }
231 }
232 else if(className == "Electron")
233 {
234 tlist = new DelphesBranchElement<TEveTrackList>(name, treeReader_->UseBranch(name), kRed);
235 tlist->SetTrackingVolume(tkRadius_, tkHalfLength_, bz_);
236 elements.push_back(tlist);
237 }
238 else if(className == "Photon")
239 {
240 tlist = new DelphesBranchElement<TEveTrackList>(name, treeReader_->UseBranch(name), kYellow);
241 tlist->SetTrackingVolume(tkRadius_, tkHalfLength_, bz_);
242 elements.push_back(tlist);
243 }
244 else if(className == "Muon")
245 {
246 tlist = new DelphesBranchElement<TEveTrackList>(name, treeReader_->UseBranch(name), kGreen);
247 tlist->SetTrackingVolume(totRadius_, muHalfLength_, bz_);
248 elements.push_back(tlist);
249 }
250 else if(className == "MissingET")
251 {
252 elist = new DelphesBranchElement<TEveElementList>(name, treeReader_->UseBranch(name), kViolet);
253 elist->SetTrackingVolume(tkRadius_, tkHalfLength_, bz_);
254 elements.push_back(elist);
255 }
256 else if(className == "GenParticle")
257 {
258 tlist = new DelphesBranchElement<TEveTrackList>(name, treeReader_->UseBranch(name), kCyan);
259 tlist->SetTrackingVolume(tkRadius_, tkHalfLength_, bz_);
260 tlist->GetContainer()->SetRnrSelf(false);
261 tlist->GetContainer()->SetRnrChildren(false);
262 elements.push_back(tlist);
263 }
264 else
265 {
266 continue;
267 }
268 }
269 // second loop for tracks
270 for(Int_t b = 0; b < nBranches; ++b)
271 {
272 TString input = branches[b * 3].GetString();
273 TString name = branches[b * 3 + 1].GetString();
274 TString className = branches[b * 3 + 2].GetString();
275 if(className == "Track")
276 {
277 if(input.Contains("eflow", TString::kIgnoreCase) || name.Contains("eflow", TString::kIgnoreCase)) continue; //no eflow
278 tlist = new DelphesBranchElement<TEveTrackList>(name, treeReader_->UseBranch(name), kBlue);
279 tlist->SetTrackingVolume(tkRadius_, tkHalfLength_, bz_);
280 elements.push_back(tlist);
281 }
282 }
283}
284
285void DelphesEventDisplay::load_event()
286{
287 // Load event specified in global event_id_.
288 // The contents of previous event are removed.
289
290 // safety
291 if(event_id_ >= treeReader_->GetEntries() || event_id_ < 0) return;
292
293 // message
294 fStatusBar_->SetText(Form("Loading event %d.", event_id_), 1);
295 gSystem->ProcessEvents();
296
297 // clear the previous event
298 gEve->GetViewers()->DeleteAnnotations();
299 for(std::vector<DelphesBranchBase *>::iterator data = elements_.begin(); data < elements_.end(); ++data)
300 {
301 (*data)->Reset();
302 }
303
304 // Load selected branches with data from specified event
305 treeReader_->ReadEntry(event_id_);
306 for(std::vector<DelphesBranchBase *>::iterator data = elements_.begin(); data < elements_.end(); ++data)
307 {
308 (*data)->ReadBranch();
309 }
310
311 // update display
312 TEveElement *top = (TEveElement *)gEve->GetCurrentEvent();
313 delphesDisplay_->DestroyEventRPhi();
314 delphesDisplay_->ImportEventRPhi(top);
315 delphesDisplay_->DestroyEventRhoZ();
316 delphesDisplay_->ImportEventRhoZ(top);
317 update_html_summary();
318 plotSummary_->FillEvent();
319 plotSummary_->Draw();
320
321 gEve->Redraw3D(kFALSE, kTRUE);
322 fStatusBar_->SetText(Form("Loaded event %d.", event_id_), 1);
323 gSystem->ProcessEvents();
324}
325
326void DelphesEventDisplay::update_html_summary()
327{
328 // Update summary of current event.
329
330 TEveElement::List_i i;
331 TEveElement::List_i j;
332 Int_t k;
333 TEveElement *el;
334 DelphesHtmlObjTable *table;
335 TEveEventManager *mgr = gEve ? gEve->GetCurrentEvent() : 0;
336 if(mgr)
337 {
338 htmlSummary_->Clear("D");
339 for(i = mgr->BeginChildren(); i != mgr->EndChildren(); ++i)
340 {
341 el = ((TEveElement *)(*i));
342 if(el->IsA() == TEvePointSet::Class())
343 {
344 TEvePointSet *ps = (TEvePointSet *)el;
345 TString ename = ps->GetElementName();
346 TString etitle = ps->GetElementTitle();
347 if(ename.First('\'') != kNPOS)
348 ename.Remove(ename.First('\''));
349 etitle.Remove(0, 2);
350 Int_t nel = atoi(etitle.Data());
351 table = htmlSummary_->AddTable(ename, 0, nel);
352 }
353 else if(el->IsA() == TEveTrackList::Class())
354 {
355 TEveTrackList *tracks = (TEveTrackList *)el;
356 TString ename = tracks->GetElementName();
357 if(ename.First('\'') != kNPOS)
358 ename.Remove(ename.First('\''));
359 table = htmlSummary_->AddTable(ename.Data(), 5,
360 tracks->NumChildren(), kTRUE, "first");
361 table->SetLabel(0, "Momentum");
362 table->SetLabel(1, "P_t");
363 table->SetLabel(2, "Phi");
364 table->SetLabel(3, "Theta");
365 table->SetLabel(4, "Eta");
366 k = 0;
367 for(j = tracks->BeginChildren(); j != tracks->EndChildren(); ++j)
368 {
369 Float_t p = ((TEveTrack *)(*j))->GetMomentum().Mag();
370 table->SetValue(0, k, p);
371 Float_t pt = ((TEveTrack *)(*j))->GetMomentum().Perp();
372 table->SetValue(1, k, pt);
373 Float_t phi = ((TEveTrack *)(*j))->GetMomentum().Phi();
374 table->SetValue(2, k, phi);
375 Float_t theta = ((TEveTrack *)(*j))->GetMomentum().Theta();
376 table->SetValue(3, k, theta);
377 Float_t eta = theta > 0.0005 && theta < 3.1413 ? ((TEveTrack *)(*j))->GetMomentum().Eta() : 1e10;
378 table->SetValue(4, k, eta);
379 ++k;
380 }
381 }
382 }
383 htmlSummary_->Build();
384 gHtml_->Clear();
385 gHtml_->ParseText((char *)htmlSummary_->Html().Data());
386 gHtml_->Layout();
387 }
388}
389
390/******************************************************************************/
391// GUI
392/******************************************************************************/
393
394void DelphesEventDisplay::make_gui()
395{
396 // Create minimal GUI for event navigation.
397
398 // add a tab on the left
399 TEveBrowser *browser = gEve->GetBrowser();
400 browser->SetWindowName("Delphes Event Display");
401 browser->StartEmbedding(TRootBrowser::kLeft);
402
403 // set the main title
404 TGMainFrame *frmMain = new TGMainFrame(gClient->GetRoot(), 1000, 600);
405 frmMain->SetWindowName("Delphes Event Display");
406 frmMain->SetCleanup(kDeepCleanup);
407
408 // build the navigation menu
409 TString icondir;
410 if(gSystem->Getenv("ROOTSYS"))
411 icondir = Form("%s/icons/", gSystem->Getenv("ROOTSYS"));
412 if(!gSystem->OpenDirectory(icondir))
413 icondir = Form("%s/icons/", (const char *)gSystem->GetFromPipe("root-config --etcdir"));
414 TGGroupFrame *vf = new TGGroupFrame(frmMain, "Event navigation", kVerticalFrame | kFitWidth);
415 {
416 TGHorizontalFrame *hf = new TGHorizontalFrame(frmMain);
417 {
418 TGPictureButton *b = 0;
419
420 b = new TGPictureButton(hf, gClient->GetPicture(icondir + "GoBack.gif"));
421 hf->AddFrame(b, new TGLayoutHints(kLHintsLeft | kLHintsCenterY, 10, 2, 10, 10));
422 b->Connect("Clicked()", "DelphesEventDisplay", this, "Bck()");
423
424 TGNumberEntry *numberEntry = new TGNumberEntry(hf, 0, 9, -1, TGNumberFormat::kNESInteger, TGNumberFormat::kNEANonNegative, TGNumberFormat::kNELLimitMinMax, 0, treeReader_->GetEntries());
425 hf->AddFrame(numberEntry, new TGLayoutHints(kLHintsCenterX | kLHintsCenterY, 2, 0, 10, 10));
426 this->Connect("EventChanged(Int_t)", "TGNumberEntry", numberEntry, "SetIntNumber(Long_t)");
427 numberEntry->GetNumberEntry()->Connect("TextChanged(char*)", "DelphesEventDisplay", this, "PreSetEv(char*)");
428 numberEntry->GetNumberEntry()->Connect("ReturnPressed()", "DelphesEventDisplay", this, "GoTo()");
429
430 b = new TGPictureButton(hf, gClient->GetPicture(icondir + "GoForward.gif"));
431 hf->AddFrame(b, new TGLayoutHints(kLHintsRight | kLHintsCenterY, 2, 10, 10, 10));
432 b->Connect("Clicked()", "DelphesEventDisplay", this, "Fwd()");
433 }
434 vf->AddFrame(hf, new TGLayoutHints(kLHintsExpandX, 2, 2, 2, 2));
435
436 TGHProgressBar *progress = new TGHProgressBar(frmMain, TGProgressBar::kFancy, 100);
437 progress->SetMax(treeReader_->GetEntries());
438 progress->ShowPosition(kTRUE, kFALSE, "Event %.0f");
439 progress->SetBarColor("green");
440 vf->AddFrame(progress, new TGLayoutHints(kLHintsExpandX, 10, 10, 5, 5));
441 this->Connect("EventChanged(Int_t)", "TGHProgressBar", progress, "SetPosition(Float_t)");
442 }
443 frmMain->AddFrame(vf, new TGLayoutHints(kLHintsExpandX, 5, 5, 5, 5));
444 vf = new TGGroupFrame(frmMain, "Batch operations", kVerticalFrame | kFitWidth);
445 {
446 TGTextButton *b = new TGTextButton(vf, "Initialize Summary Plots");
447 vf->AddFrame(b, new TGLayoutHints(kLHintsCenterX | kLHintsCenterY | kLHintsExpandX, 10, 10, 10, 10));
448 b->Connect("Clicked()", "DelphesEventDisplay", this, "InitSummaryPlots()");
449 }
450 frmMain->AddFrame(vf, new TGLayoutHints(kLHintsExpandX, 5, 5, 5, 5));
451
452 frmMain->MapSubwindows();
453 frmMain->Resize();
454 frmMain->MapWindow();
455 browser->StopEmbedding();
456 browser->SetTabTitle("Event Control", 0);
457
458 // the summary tab
459 htmlSummary_ = new DelphesHtmlSummary("Delphes Event Display Summary Table");
460 TEveWindowSlot *slot = TEveWindow::CreateWindowInTab(gEve->GetBrowser()->GetTabRight());
461 gHtml_ = new TGHtml(0, 100, 100);
462 TEveWindowFrame *wf = slot->MakeFrame(gHtml_);
463 gHtml_->MapSubwindows();
464 wf->SetElementName("Summary tables");
465
466 // plot tab
467 slot = TEveWindow::CreateWindowInTab(gEve->GetBrowser()->GetTabRight());
468 TEveWindowTab *tab = slot->MakeTab();
469 tab->SetElementName("Summary plots");
470 tab->SetShowTitleBar(kFALSE);
471 plotSummary_ = new DelphesPlotSummary(tab);
472 plotSummary_->Init(elements_);
473 plotSummary_->Connect("Progress(Int_t)", "DelphesEventDisplay", this, "DisplayProgress(Int_t)");
474}
475
476void DelphesEventDisplay::Fwd()
477{
478 if(event_id_ < treeReader_->GetEntries() - 2)
479 {
480 EventChanged(event_id_ + 1);
481 }
482 else
483 {
484 printf("Already at last event.\n");
485 }
486}
487
488void DelphesEventDisplay::Bck()
489{
490 if(event_id_ > 0)
491 {
492 EventChanged(event_id_ - 1);
493 }
494 else
495 {
496 printf("Already at first event.\n");
497 }
498}
499
500void DelphesEventDisplay::PreSetEv(char *ev)
501{
502 event_id_tmp_ = Int_t(atoi(ev));
503}
504
505void DelphesEventDisplay::GoTo()
506{
507 if(event_id_tmp_ >= 0 && event_id_tmp_ < treeReader_->GetEntries() - 1)
508 {
509 EventChanged(event_id_tmp_);
510 }
511 else
512 {
513 printf("Error: no such event.\n");
514 }
515}
516
517void DelphesEventDisplay::InitSummaryPlots()
518{
519 plotSummary_->FillSample(treeReader_, event_id_);
520 plotSummary_->FillEvent();
521 plotSummary_->Draw();
522}
523
524void DelphesEventDisplay::DisplayProgress(Int_t p)
525{
526 fStatusBar_->SetText(Form("Processing... %d %%", p), 1);
527 gSystem->ProcessEvents();
528}
Note: See TracBrowser for help on using the repository browser.