ROOTANA
TRootanaDisplay.cxx
Go to the documentation of this file.
1 #include "TRootanaDisplay.hxx"
2 #include "TPad.h"
3 #include "TSystem.h"
4 #include <stdlib.h>
5 #include "math.h"
6 
7 #ifndef NO_CINT
9 #endif
10 
12 {
15  fNumberProcessed = 0;
18  fLastUpdateTime = 0.0;
19 
20  SetDisplayName("Rootana Display");
21  waitingForNextButton = true;
23 
24  fUpdatingBasedSeconds = false;
25  fQuitPushed = false;
26 
27  // Don't create second main window.
29 
30  // Don't create output ROOT files;
31  // Output ROOT files will kill histograms.
32  DisableRootOutput(true);
33 
34 }
35 
37 
38  for(unsigned int i = 0; i < fCanvasHandlers.size(); i++)
39  delete fCanvasHandlers[i].second;
40 
41 };
42 
43 
44 #ifdef OS_DARWIN
45 static int gMainDisplayDefaultWidth = 1100;
46 static int gMainDisplayDefaultHeight = 580;
47 #else
48 static int gMainDisplayDefaultWidth = 1200;
49 static int gMainDisplayDefaultHeight = 800;
50 #endif
51 
53 
56 
57  // Link the a bunch of buttons in TMainWindowDisplay to functions in TRootanaDisplay.
58  // This bit of ROOT magic requires that the TRootanaDisplay class get rootcint-ed.
59  // It also requires that TRootanaDisplay methods be public (protected doesn't work).
60 
61  // The reset button
62  fMainWindow->GetResetButton()->Connect("Clicked()", "TRootanaDisplay", this, "Reset()");
63 
64  // The tab buttons
65  fMainWindow->GetTab()->Connect("Selected(Int_t)", "TRootanaDisplay", this, "UpdatePlotsAction()");
66 
67  // The quit button
68  fMainWindow->GetQuitButton()->Connect("Clicked()", "TRootanaDisplay", this, "QuitButtonAction()");
69 
70  // The next button
71  fMainWindow->GetNextButton()->Connect("Clicked()", "TRootanaDisplay", this, "NextButtonPushed()");
72 
73  // The next interesting button
74  if(iem_t::instance()->IsEnabled())
75  fMainWindow->GetNextInterestingButton()->Connect("Clicked()", "TRootanaDisplay", this, "NextInterestingButtonPushed()");
76 
77  // The event skip counter
78  if(IsOnline()){
79  TGNumberEntry *skipButton = fMainWindow->GetSkipEventButton();
80  skipButton->Connect("ValueSet(Long_t)", "TRootanaDisplay",this, "EventSkipButtonPushed()");
81  skipButton->GetNumberEntry()->Connect("ReturnPressed()", "TRootanaDisplay", this, "EventSkipButtonPushed()");
82  // set the initial value of this field
84  skipButton->GetNumberEntry()->SetIntNumber((int)fSecondsBeforeUpdating);
85  }else{
86  skipButton->GetNumberEntry()->SetIntNumber(fNumberSkipEventsOnline);
87  }
88  }
89 
90  // Let the user add all the canvases they want.
92 
93  // Check: make sure we have at least one canvas.
94  if(GetDisplayWindow()->GetTab()->GetNumberOfTabs() <= 0){
95  std::cerr << "Error in TRootanaDisplay: you have not created any canvases; you must create at least one canvas. Exiting. " << std::endl;
96  exit(0);
97 
98  }
99  // Now map out window.
101 
102 
103 }
104 
105 
106 void TRootanaDisplay::AddSingleCanvas(TCanvasHandleBase* handleClass, std::string subtab_name){
107 
108  std::pair<int,int> index = GetDisplayWindow()->AddCanvas(handleClass->GetTabName(),subtab_name);
109 
110  std::pair< std::pair<int,int>, TCanvasHandleBase*> tmp(index,handleClass);
111 
112  fCanvasHandlers.push_back(tmp);
113  // Now set up the embedded canvas, if user so desires.
114  TGCompositeFrame* embed = GetDisplayWindow()->GetCompositeFrame(index);//ssGetTab()->GetTabContainer(tab_index);
115  handleClass->SetUpCompositeFrame(embed,this);
116 
117  // If we just created a new sub-tab, grab the tab and add
118  // call-back to UpdatePlot
119  if(index.second == 0){
120  TGTab* tab = GetDisplayWindow()->GetSubTab(index.first);
121  tab->Connect("Selected(Int_t)", "TRootanaDisplay", this, "UpdatePlotsAction()");
122  }
123 
124 
125 }
126 
127 
128 /// Make separate treatment of online and offline data, since both are quite different
130 
132 
133  iem_t::instance()->Reset(); // Reset the interesting event manager each event.
134 
135  if(IsOnline()){
136  return ProcessMidasEventOnline(dataContainer);
137  }else{
138  return ProcessMidasEventOffline(dataContainer);
139  }
140 
141 
142 }
143 
144 
145 /// Handle online processing of MIDAS events.
147 
148  // If processing is not paused or the next button was previously pressed, then update plots.
150  SetCachedDataContainer(dataContainer);
151 
152  // Perform any histogram updating from user code.
154  for(unsigned int i = 0; i < fCanvasHandlers.size(); i++)
155  fCanvasHandlers[i].second->UpdateCanvasHistograms(*fCachedDataContainer);
156 
157  }
158 
159  // If processing is not paused, then just update plot and return
161  SetCachedDataContainer(dataContainer);
162  // Do canvas updating from user code;
163  // we have two modes; we can either update after X seconds or X events
165  struct timeval nowTime;
166  gettimeofday(&nowTime, NULL);
167 
168  double dnowtime = nowTime.tv_sec + (nowTime.tv_usec)/1000000.0;
169  double diffTime = dnowtime - fLastUpdateTime;
170  if(diffTime > fSecondsBeforeUpdating){
172  fLastUpdateTime = dnowtime;
173  }
174 
175  }else{
176  // only do plot if we have processed enough events
179  }
180  }
181 
182  return true;
183  }
184 
187 
188  // If we pressed the next interesting button, then check if this event was
189  // interesting; if yes, then update plot and let user look at it.
190  // If no, then just return (and check again for next event).
192  if(iem_t::instance()->IsInteresting()){
193  std::cout << "Found next interesting event " << std::endl;
195  }else{
196  return true;
197  }
198  }
199 
200  // If online and paused, then keep looping till the free-flowing button or
201  // next button is pushed.
202  waitingForNextButton = true;
204  while(1){
205 
206  // Add some sleeps; otherwise program takes 100% of CPU...
207  usleep(10000);
208 
209  // Break out if no longer in paused state.
210  if(!fMainWindow->IsDisplayPaused()) break;
211 
212  // Break out if next button or next interesting button pressed.
214 
215  // Check if quit button has been pushed. See QuitButtonAction() for details
216  if(fQuitPushed) break;
217 
218  // Resize windows, if needed.
220 
221  // handle GUI events
222  gSystem->ProcessEvents();
223 
224  }
225  return true;
226 
227 }
228 
229 
230 
232 
233 
234  SetCachedDataContainer(dataContainer);
235 
236  // Perform any histogram updating from user code.
238  for(unsigned int i = 0; i < fCanvasHandlers.size(); i++)
239  fCanvasHandlers[i].second->UpdateCanvasHistograms(*fCachedDataContainer);
240 
241  // Keep skipping if we haven't processed enough
243  return true;
244  }
245 
246  // If we pressed the next interesting button, then check if this event was
247  // interesting; if yes, then update plot and let user look at it.
248  // If no, then just return (and check again for next event).
250  if(!iem_t::instance()->IsInteresting()){
251  return true;
252  }else{
253  std::cout << "Found next interesting event " << std::endl;
254  }
255  }
256 
258 
259  // Reset clock for next time 'FreeRunning' is pushed.
260  double firstFreeRunningTime = 0.0;
261 
262  // If offline, then keep looping till the next event button is pushed.
263  waitingForNextButton = true;
265  while(1){
266 
267  // Add some sleeps; otherwise program takes 100% of CPU...
268  usleep(10000);
269 
270  // Break out if next button or next interesting button pressed.
272 
273  // In offline free-running mode, go to next event after a couple seconds.
275  struct timeval nowTime;
276  gettimeofday(&nowTime, NULL);
277 
278  double dnowtime = nowTime.tv_sec + (nowTime.tv_usec)/1000000.0;
279  if(fabs(firstFreeRunningTime) < 0.00000001){ // first event of free-running...
280  firstFreeRunningTime = dnowtime; // ... so, start the clock
281  }else{ // otherwise, check if enough seconds elapsed.
282  double diffTime = dnowtime - firstFreeRunningTime;
283  if(diffTime > fSecondsBeforeUpdating){
284  firstFreeRunningTime = 0.0;
285  break;
286  }
287  }
288  }else{
289  firstFreeRunningTime = 0.0;
290  }
291 
292 
293  // Resize windows, if needed.
295 
296  // handle GUI events
297  gSystem->ProcessEvents();
298 
299  }
300  return true;
301 
302 }
303 
304 void TRootanaDisplay::BeginRunRAD(int transition,int run,int time){
305 
306  std::cout << "Begin of run " << run << " at time " << time << std::endl;
307  for(unsigned int i = 0; i < fCanvasHandlers.size(); i++)
308  fCanvasHandlers[i].second->BeginRun(transition,run,time);
310 }
311 
312 void TRootanaDisplay::EndRunRAD(int transition,int run,int time){
313 
314  std::cout << "End of run " << run << " at time " << time << std::endl;
315  for(unsigned int i = 0; i < fCanvasHandlers.size(); i++)
316  fCanvasHandlers[i].second->EndRun(transition,run,time);
318 
319  if(fNumberSkipEventsOffline == -1){
320  // Pause the display
321  while(1){
322  usleep(10000);
323 
324  // Break out if next button or next interesting button pressed.
326 
327  // Resize windows, if needed.
329 
330  // handle GUI events
331  gSystem->ProcessEvents();
332  }
333  }
334 }
335 
336 
337 
339 
341  char displayTitle[200];
342  sprintf(displayTitle,"%s (): run %i (no events yet)",
343  GetDisplayName().c_str(),GetCurrentRunNumber());
344  GetDisplayWindow()->GetMain()->SetWindowName(displayTitle);
345  return;
346  }
347 
348  // Execute the plotting actions from user event loop.
350 
351  // See if we find a user class that describes this tab.
352  std::pair<int,int> tabdex = GetDisplayWindow()->GetCurrentTabIndex();
353  for(unsigned int i = 0; i < fCanvasHandlers.size(); i++){
354  if(tabdex == fCanvasHandlers[i].first){
355  TRootEmbeddedCanvas* embed = GetDisplayWindow()->GetCurrentEmbeddedCanvas();
356  fCanvasHandlers[i].second->PlotCanvas(*fCachedDataContainer,embed);
357  }
358  }
359 
360 
361  // Set the display title
362  char displayTitle[200];
363  if(IsOnline())
364  sprintf(displayTitle,"%s (online): run %i event %i",
367  else
368  sprintf(displayTitle,"%s (offline): run %i event %i",
371 
372  GetDisplayWindow()->GetMain()->SetWindowName(displayTitle);
373 
374 
375  // Update canvas and window sizes
377 
378 }
379 
381  // Call the reset functions defined in user event loop.
382  ResetHistograms();
383  // Call the user defined canvas classes.
384  for(unsigned int i = 0; i < fCanvasHandlers.size(); i++)
385  fCanvasHandlers[i].second->ResetCanvasHistograms();
387 }
388 
389 
391 {
392  // If we are offline, then we close the ROOT file here.
393  // If we are online then the control will return to TRootanaEventLoop::ProcessMidasOnline
394  // which will take care of closing the file.
395 
396  if(!IsOnline()){
398  CloseRootFile();
399  }
400 
401  // Set a flag so that we can breakout of loop if
402  // we are ONLINE and PAUSED.
403  // It is odd that gApplication->Terminate(0) doesn't
404  // finish, but somehow it seems to wait for the the
405  // RootanaDisplay::ProcessMidasEvent() to finish.
406  fQuitPushed = true;
407  gApplication->Terminate(0);
408 
409  // Hmm, don't quite understand this.
410  // If we opened a TBrowser, we need to delete it before
411  // we close the ROOT file... hmm, ROOT...
413 
414 }
static int gMainDisplayDefaultWidth
ClassImp(TRootanaDisplay) TRootanaDisplay
static int gMainDisplayDefaultHeight
std::string GetTabName()
virtual void SetUpCompositeFrame(TGCompositeFrame *, TRootanaDisplay *display)
TMidasEvent & GetMidasData() const
Get the MIDAS data for this event, in TMidasEvent format.
void Reset()
Reset state of manager = set to not interesting event.
static TInterestingEventManager * instance()
std::pair< int, int > GetCurrentTabIndex()
Return an pair<int> index for current tab/sub-tab;.
std::pair< int, int > AddCanvas(std::string subtabname, std::string tabname=std::string(""))
TGTab * GetSubTab(int index)
TGTab * GetTab(std::pair< int, int > tabindex)
TGTextButton * GetQuitButton()
TGTextButton * GetResetButton()
TGTextButton * GetNextButton()
TGTextButton * GetNextInterestingButton()
TRootEmbeddedCanvas * GetCurrentEmbeddedCanvas()
Return the current embedded canvas.
TGCompositeFrame * GetCompositeFrame(std::pair< int, int > index)
TGNumberEntry * GetSkipEventButton()
uint32_t GetSerialNumber() const
return the serial number
void AddSingleCanvas(std::string name, std::string subtab_name=std::string(""))
Add a new canvas; user will interactively fill it.
virtual void ResetHistograms()
This method can be implemented by users to plotting of current canvas.
std::string GetDisplayName()
Get Display name.
bool fQuitPushed
Flag to keep track of if quite button has been pushed.
TMainDisplayWindow * fMainWindow
The pointer to our display window.
virtual ~TRootanaDisplay()
void QuitButtonAction()
Method to call when 'quit' button is pressed.
void SetDisplayName(std::string name)
Set Display name.
void EndRunRAD(int transition, int run, int time)
virtual void PlotCanvas(TDataContainer &dataContainer)
This method can be implemented by users to plotting of current canvas.
virtual void UpdateHistograms(TDataContainer &dataContainer)
This method can be implemented by users to update user histograms.
bool ProcessMidasEvent(TDataContainer &dataContainer)
Process each midas event.
virtual void AddAllCanvases()=0
User must.
TMainDisplayWindow * GetDisplayWindow()
void SetCachedDataContainer(TDataContainer &dataContainer)
std::vector< std::pair< std::pair< int, int >,TCanvasHandleBase * > > fCanvasHandlers
void InitializeMainWindow()
Method to initialize the Main display window.
bool ProcessMidasEventOnline(TDataContainer &dataContainer)
Process each online midas event.
bool waitingForNextInterestingButton
bool ProcessMidasEventOffline(TDataContainer &dataContainer)
Process each offline midas event.
void BeginRunRAD(int transition, int run, int time)
TDataContainer * fCachedDataContainer
We keep a cached copy of the midas event (so that it can used for callback).
void DisableAutoMainWindow()
Disable automatic creation of MainWindow.
void DisableRootOutput(bool disable=true)
int GetCurrentRunNumber() const
Current Run Number.
void CloseRootFile()
Cloe output ROOT file.
virtual void EndRun(int transition, int run, int time)
bool IsOffline() const
Are we processing offline data?
bool IsOnline() const
Are we processing online data?