ROOTANA
TFancyHistogramCanvas.cxx
Go to the documentation of this file.
2 
3 #include "TMesytecData.hxx"
4 #include "TH2.h"
5 
7 
9  std::string name, int numberChannelsInGroups,
10  bool disableAutoUpdate):
11  TCanvasHandleBase(name),
12  fHistoArray(histoArray){
13 
14  if(histoArray->GetNumberChannelsInGroup() != -1){
15  fNumberChannelsInGroups = histoArray->GetNumberChannelsInGroup();
16  }else if(numberChannelsInGroups > 1)
17  fNumberChannelsInGroups = numberChannelsInGroups;
18  else
19  fNumberChannelsInGroups = -1;
20 
21  fLabelframe = 0;
22  fChannelCounterButton = 0;
23  fLabelChannels = 0;
24  fChannelName = "Histogram";
25  if(histoArray->GetChannelName().compare("")!=0)
26  fChannelName = histoArray->GetChannelName();
27 
28  fGroupCounterButton = 0;
29  fLabelGroup = 0;
30  fGroupName = "Group";
31  if(histoArray->GetGroupName().compare("")!=0)
32  fGroupName = histoArray->GetGroupName();
33 
34  fMultiCanvasButton = 0;
35  fNCanvasButtonGroup =0;
36  fNCanvasButtons[0]=0;
37  fNCanvasButtons[1]=0;
38  fNCanvasButtons[2]=0;
39  fNCanvasButtons[3]=0;
40  fOverlayHistoButton = 0;
41  fNHistoButton = 0;
42  labelNHisto = 0;
43 
44  // Construct the legend here, so that user can modify position immediately.
45  fNHistoLegend = new TLegend(0.6,0.6,0.89,0.8);
46  fNHistoLegend->SetFillColor(10);
47 
48  fDisableAutoUpdate = disableAutoUpdate;
49  if(histoArray->HasAutoUpdate())
50  fDisableAutoUpdate = histoArray->GetDisableAutoUpdate();
51 
52 }
53 
55 
56 }
57 
58 /// This is the complicated part, where we create a bunch of buttons and widgets.
59 void TFancyHistogramCanvas::SetUpCompositeFrame(TGCompositeFrame *compFrame, TRootanaDisplay *display){
60 
61  /// Cached pointer to rootana display; needed so that we can
62  /// create new buttons with correct callbacks.
63  fDisplay = display;
64 
65  // Now create my embedded canvas, along with the various buttons for this canvas.
66  // Sub-frame, to reduce space used
67  fLabelframe = new TGHorizontalFrame(compFrame,200,40);
68  compFrame->AddFrame(fLabelframe, new TGLayoutHints(kLHintsCenterX,2,2,2,2));
69 
70  // ________________________________________________________________________________
71  // Add a button for the groups, if we are using groups
73 
74  TGVerticalFrame *hframe1 = new TGVerticalFrame(fLabelframe, 120, 40, kFixedWidth);
75  fLabelframe->AddFrame(hframe1, new TGLayoutHints(kLHintsLeft,2,2,2,2));
76  int numberGroups = (int)(((double)fHistoArray->size())/((double)fNumberChannelsInGroups));
77 
78  fGroupCounterButton = new TGNumberEntry(hframe1, 0, 9,999, TGNumberFormat::kNESInteger,
79  TGNumberFormat::kNEANonNegative,
80  TGNumberFormat::kNELLimitMinMax,
81  0, numberGroups-1);
82 
83  hframe1->AddFrame(fGroupCounterButton, new TGLayoutHints(kLHintsLeft, 1, 1, 1, 1));
84  // Add call-backs to update plots if widget is used
85  fGroupCounterButton->Connect("ValueSet(Long_t)", "TRootanaDisplay", display, "UpdatePlotsAction()");
86  fGroupCounterButton->GetNumberEntry()->Connect("ReturnPressed()", "TRootanaDisplay", display, "UpdatePlotsAction()");
87 
88  // Add a label for channel selector
89  fLabelGroup = new TGLabel(hframe1, "");
90  hframe1->AddFrame(fLabelGroup, new TGLayoutHints(kLHintsLeft , 1, 1, 1, 1));
92  }
93 
94  // ________________________________________________________________________________
95  // Create the default set of widgets used for all display options: namely a counter
96  // that keeps track of which channel to start from.
97 
98  // Sub-frame, to reduce space used
99  TGVerticalFrame *hframe2 = new TGVerticalFrame(fLabelframe, 120, 40, kFixedWidth);
100  fLabelframe->AddFrame(hframe2, new TGLayoutHints(kLHintsLeft,2,2,2,2));
101  int numberChannels = fHistoArray->size();
102  if(fNumberChannelsInGroups > 1){
103  numberChannels = fNumberChannelsInGroups;
104  }
105  fChannelCounterButton = new TGNumberEntry(hframe2, 0, 9,999, TGNumberFormat::kNESInteger,
106  TGNumberFormat::kNEANonNegative,
107  TGNumberFormat::kNELLimitMinMax,
108  0, numberChannels-1);
109 
110  hframe2->AddFrame(fChannelCounterButton, new TGLayoutHints(kLHintsLeft, 1, 1, 1, 1));
111  // Add call-backs to update plots if widget is used
112  fChannelCounterButton->Connect("ValueSet(Long_t)", "TRootanaDisplay", display, "UpdatePlotsAction()");
113  fChannelCounterButton->GetNumberEntry()->Connect("ReturnPressed()", "TRootanaDisplay", display, "UpdatePlotsAction()");
114 
115  // Add a label for channel selector
116  fLabelChannels = new TGLabel(hframe2, "");
117  hframe2->AddFrame(fLabelChannels, new TGLayoutHints(kLHintsLeft, 5, 5, 5, 5));
119 
120  // ________________________________________________________________________________
121  // Create a button to control whether to use multiple canvases
122  fMultiCanvasButton = new TGCheckButton(fLabelframe, new TGHotString("Multi-Canvas"));
123  fLabelframe->AddFrame(fMultiCanvasButton, new TGLayoutHints(kLHintsTop | kLHintsLeft, 5, 5, 5, 5));
124 
125  // Add call-backs to update plots if button is used; ensure both not all modes are simultaneously active
126  fMultiCanvasButton->Connect("Toggled(Bool_t)", "TFancyHistogramCanvas", this, "ActivateMultiCanvasButton()");
127  fMultiCanvasButton->Connect("Toggled(Bool_t)", "TRootanaDisplay", display, "UpdatePlotsAction()");
128 
129  /// Add the button group to control how many sub-canvases to plot.
130  fNCanvasButtonGroup = new TGHButtonGroup(fLabelframe, "Number of Canvases:");
131  fNCanvasButtons[0] = new TGRadioButton(fNCanvasButtonGroup, new TGHotString("2 | "),1);
132  fNCanvasButtons[1] = new TGRadioButton(fNCanvasButtonGroup, new TGHotString("4 | "),2);
133  fNCanvasButtons[2] = new TGRadioButton(fNCanvasButtonGroup, new TGHotString("8 | "),3);
134  fNCanvasButtons[3] = new TGRadioButton(fNCanvasButtonGroup, new TGHotString("16 | "),4);
135  fNCanvasButtons[0]->SetOn();
136  for(int i = 0; i < 4; i++)
137  fNCanvasButtons[i]->Connect("Toggled(Bool_t)", "TRootanaDisplay", fDisplay, "UpdatePlotsAction()");
138 
139  fNCanvasButtonGroup->SetRadioButtonExclusive(kTRUE);
140 
141  fNCanvasButtonGroup->Show();
142  fLabelframe->AddFrame(fNCanvasButtonGroup, new TGLayoutHints(kLHintsTop | kLHintsLeft, 5, 5, 5, 5));
143  fNCanvasButtonGroup->SetState(false);
144 
145  // ________________________________________________________________________________
146  // Create a button to control whether to overlay histograms in a single canvas
147  fOverlayHistoButton = new TGCheckButton(fLabelframe, new TGHotString("Overlay-Histo"));
148  fLabelframe->AddFrame(fOverlayHistoButton, new TGLayoutHints(kLHintsTop | kLHintsLeft, 5, 5, 5, 5));
149 
150  // Add call-backs to update plots if button is used; ensure both not all modes are simultaneously active
151  fOverlayHistoButton->Connect("Toggled(Bool_t)", "TFancyHistogramCanvas", this, "ActivateOverlayButton()");
152  fOverlayHistoButton->Connect("Toggled(Bool_t)", "TRootanaDisplay", display, "UpdatePlotsAction()");
153 
154  /// Add the button to control how many histograns to plot to plot.
155 
156  // Sub-frame, to reduce space used
157  TGVerticalFrame *hframe3 = new TGVerticalFrame(fLabelframe, 120, 40, kFixedWidth);
158  fLabelframe->AddFrame(hframe3, new TGLayoutHints(kLHintsLeft,2,2,2,2));
159 
160  fNHistoButton = new TGNumberEntry(hframe3, 2, 9,999, TGNumberFormat::kNESInteger,
161  TGNumberFormat::kNEANonNegative,
162  TGNumberFormat::kNELLimitMinMax,
163  2, 20);
164  hframe3->AddFrame(fNHistoButton, new TGLayoutHints(kLHintsLeft, 5, 5, 5, 5));
165  // Add call-backs to update plots if widget is used
166  fNHistoButton->Connect("ValueSet(Long_t)", "TRootanaDisplay", display, "UpdatePlotsAction()");
167  fNHistoButton->GetNumberEntry()->Connect("ReturnPressed()", "TRootanaDisplay", display, "UpdatePlotsAction()");
168  fNHistoButton->SetState(false);
169  // Add a label
170  labelNHisto = new TGLabel(hframe3, "# Histo in Canvas");
171  hframe3->AddFrame(labelNHisto, new TGLayoutHints(kLHintsLeft, 5, 5, 5, 5));
172 
173 }
174 
175 
176 
177 /// Reset the histograms in fHistoArray.
179  for(unsigned int i = 0; i < fHistoArray->size(); i++)
180  (*fHistoArray)[i]->Reset();
181 }
182 
183 /// Update the histograms for this canvas.
185 
186  // If this variable is set, then skip calling the histogram updating;
187  // histogram updating will happen elsewhere.
188  if(fDisableAutoUpdate) return;
189 
190  fHistoArray->UpdateHistograms(dataContainer);
191 }
192 
193 
194 // Helper method to be able to treat TH2 histograms differently
195 void DrawHistogram(TH1* histo, std::string option = std::string("")){
196 
197  if(dynamic_cast<TH2*>(histo)){
198  std::string fulloption = std::string("COLZ") + option;
199  histo->Draw(fulloption.c_str());
200  }else{
201  histo->Draw(option.c_str());
202  }
203 
204 }
205 
206 /// Plot the histograms for this canvas
207 void TFancyHistogramCanvas::PlotCanvas(TDataContainer& dataContainer, TRootEmbeddedCanvas *embedCanvas){
208 
209 
210  TCanvas* c1 = embedCanvas->GetCanvas();
211  c1->Clear();
212 
213  int channel = fChannelCounterButton->GetNumberEntry()->GetIntNumber();
215  channel = fGroupCounterButton->GetNumberEntry()->GetIntNumber() * fNumberChannelsInGroups
216  + fChannelCounterButton->GetNumberEntry()->GetIntNumber();
217 
218  // Choose the display pattern based on which buttons have been pushed.
219 
220  // Multiple canvas option
221  if(fMultiCanvasButton->IsOn()){
222 
223  int ncanvas = 1;
224  if(fNCanvasButtons[0]->IsOn()){
225  c1->Divide(1,2);
226  ncanvas = 2;
227  }
228  if(fNCanvasButtons[1]->IsOn()){
229  c1->Divide(2,2);
230  ncanvas = 4;
231  }
232  if(fNCanvasButtons[2]->IsOn()){
233  c1->Divide(2,4);
234  ncanvas = 8;
235  }
236  if(fNCanvasButtons[3]->IsOn()){
237  c1->Divide(4,4);
238  ncanvas = 16;
239  }
240 
241  for(int i = 0; i < ncanvas; i++){
242  c1->cd(i+1);
243  int index = i + channel;
244  if(index >=0 && index < (int)fHistoArray->size() && (*fHistoArray)[index]){
245  DrawHistogram((*fHistoArray)[index]);
246  (*fHistoArray)[index]->SetLineColor(1);
247  }
248  }
249 
250  }else if(fOverlayHistoButton->IsOn()){ // Show multiple histograms on same canvas.
251 
252  int nhisto = fNHistoButton->GetNumberEntry()->GetIntNumber();
253 
254  // Kind of annoying; need to do two loops through the data in order to check which is
255  // the maximum histogram.
256  int first_channel = channel;
257  int last_channel = channel + nhisto;
258  if(last_channel > (int)fHistoArray->size())
259  last_channel = fHistoArray->size();
260 
261  // find the maximum histogram;
262  TH1 *max_histo = 0;
263  for(int ichan = first_channel; ichan < last_channel; ichan++){
264  if(max_histo == 0)
265  max_histo = (*fHistoArray)[ichan];
266  else if((*fHistoArray)[ichan]->GetMaximum() > max_histo->GetMaximum())
267  max_histo = (*fHistoArray)[ichan];
268 
269  }
270 
271  // New loop again and draw as we go.
272 
273  DrawHistogram(max_histo);
274  fNHistoLegend->Clear();
275  char name[100];
276  for(int ichan = first_channel; ichan < last_channel; ichan++){
277 
278  (*fHistoArray)[ichan]->SetLineColor(ichan-channel+1);
279  sprintf(name,"Histogram # %i",ichan);
280  fNHistoLegend->AddEntry((*fHistoArray)[ichan],(*fHistoArray)[ichan]->GetTitle());
281 
282  if((*fHistoArray)[ichan] == max_histo) continue;
283 
284  DrawHistogram((*fHistoArray)[ichan],"SAME");
285  }
286 
287  fNHistoLegend->Draw("SAME");
288 
289  }else{ // Default: single canvas, single histogram.
290 
291 
292  if(channel >=0 && channel < (int) fHistoArray->size() && (*fHistoArray)[channel]){
293 
294  DrawHistogram((*fHistoArray)[channel]);
295 
296  (*fHistoArray)[channel]->SetLineColor(1);
297  }
298 
299  }
300  c1->Modified();
301  c1->Update();
302 
303 }
304 
305 
306 
307 /// Take actions at begin run
308 void TFancyHistogramCanvas::BeginRun(int transition,int run,int time){
309  fHistoArray->BeginRun(transition, run, time);
310 };
311 
312 /// Take actions at end run
313 void TFancyHistogramCanvas::EndRun(int transition,int run,int time){
314  fHistoArray->EndRun(transition, run, time);
315 };
316 
317 
319  if(fMultiCanvasButton->IsOn()){
320  fOverlayHistoButton->SetDown(false); // Deactivate overlay button
321  fNCanvasButtonGroup->SetState(true); // Enable the set of Ncanvas buttons
322  fNHistoButton->SetState(false);
323  }else{
324  fNCanvasButtonGroup->SetState(false);// Disable the set of Ncanvas buttons
325 
326  }
327 }
329  if(fOverlayHistoButton->IsOn()){
330  fMultiCanvasButton->SetDown(false); // Deactivate multi-canvas button
331  fNCanvasButtonGroup->SetState(false); // Disable the set of Ncanvas buttons
332  fNHistoButton->SetState(true);
333  }else{
334  fNHistoButton->SetState(false);
335  }
336 
337 
338 
339 }
340 
341 
342 void TFancyHistogramCanvas::SetGroupName(std::string groupName){
343 
344  fGroupName = groupName;
345 
346  if(!fLabelGroup) return;
347  int numberGroups = (int)(((double)fHistoArray->size())/((double)fNumberChannelsInGroups));
348  char tlabel[100];
349  sprintf(tlabel,"%s# (0-%i)",groupName.c_str(),(int)numberGroups-1);
350 
351  fLabelGroup->SetText(tlabel);//TGLabel
352 }
353 
354 void TFancyHistogramCanvas::SetChannelName(std::string channelName){
355 
356  fChannelName = channelName;
357 
358  if(!fLabelChannels) return;
359  int numberChannels = fHistoArray->size();
360  if(fNumberChannelsInGroups > 1){
361  numberChannels = fNumberChannelsInGroups;
362  }
363 
364  char tlabel[100];
365  sprintf(tlabel,"%s# (0-%i)",channelName.c_str(),(int)numberChannels-1);
366 
367  fLabelChannels->SetText(tlabel);//TGLabel
368 
369 
370 }
ClassImp(TFancyHistogramCanvas) TFancyHistogramCanvas
void DrawHistogram(TH1 *histo, std::string option=std::string(""))
TGLabel * fLabelChannels
A label for the histogram number button.
TGHorizontalFrame * fLabelframe
Overall frame in which we will add buttons and widgets.
TGHButtonGroup * fNCanvasButtonGroup
Button group to select how many canvases to show.
void UpdateCanvasHistograms(TDataContainer &dataContainer)
Update the histograms for this canvas.
std::string fChannelName
Name for the channel button.
TGNumberEntry * fNHistoButton
Button group to select how many histograms to show.
TGCheckButton * fMultiCanvasButton
This button controls whether to display mutliple sub-canvases.
TGRadioButton * fNCanvasButtons[4]
void BeginRun(int transition, int run, int time)
Take actions at begin run.
void PlotCanvas(TDataContainer &dataContainer, TRootEmbeddedCanvas *embedCanvas)
Plot the histograms for this canvas.
std::string fGroupName
Name for the group button.
TGLabel * fLabelGroup
A label for the group button.
void ResetCanvasHistograms()
Reset the histograms for this canvas.
TGNumberEntry * fChannelCounterButton
Button for the histogram number.
void EndRun(int transition, int run, int time)
Take actions at end run
THistogramArrayBase * fHistoArray
Pointer to the THistogramArrayBase class; memory is not owned by TFancyHistogramCanvas.
void SetChannelName(std::string channelName)
Allow the user to set explicitly the channel name.
void SetGroupName(std::string groupName)
Allow the user to set explicitly the group name.
TGCheckButton * fOverlayHistoButton
This button controls whether to display overlaid histograms.
TGNumberEntry * fGroupCounterButton
Button for the group number.
void SetUpCompositeFrame(TGCompositeFrame *compFrame, TRootanaDisplay *display)
This is the complicated part, where we create a bunch of buttons and widgets.
virtual void BeginRun(int transition, int run, int time)
Take actions at begin run.
const std::string GetChannelName()
const int GetNumberChannelsInGroup()
const std::string GetGroupName()
virtual void UpdateHistograms(TDataContainer &dataContainer)=0
Update the histograms for this canvas.
virtual void EndRun(int transition, int run, int time)
Take actions at end run
const bool GetDisableAutoUpdate()