Logo ROOT   6.30.04
Reference Guide
 All Namespaces Files Pages
HybridPlot.cxx
Go to the documentation of this file.
1 // @(#)root/hist:$Id$
2 
3 /** \class RooStats::HybridPlot
4  \ingroup Roostats
5 
6 This class provides the plots for the result of a study performed with the
7 HybridCalculatorOriginal class.
8 
9 Authors: D. Piparo, G. Schott - Universitaet Karlsruhe
10 
11 An example plot is available here:
12 http://www-ekp.physik.uni-karlsruhe.de/~schott/roostats/hybridplot_example.png
13 */
14 
15 #include "assert.h"
16 #include <cmath>
17 #include <iostream>
18 #include <map>
19 
20 #include "RooStats/HybridPlot.h"
21 #include "TStyle.h"
22 #include "TF1.h"
23 #include "TAxis.h"
24 #include "TH1.h"
25 #include "TLine.h"
26 #include "TLegend.h"
27 #include "TFile.h"
28 #include "TVirtualPad.h"
29 
30 #include <algorithm>
31 
32 /// To build the THtml documentation
33 using namespace std;
34 
35 ClassImp(RooStats::HybridPlot);
36 
37 using namespace RooStats;
38 
39 ////////////////////////////////////////////////////////////////////////////////
40 /// HybridPlot constructor
41 
42 HybridPlot::HybridPlot(const char* name,
43  const char* title,
44  const std::vector<double> & sb_vals,
45  const std::vector<double> & b_vals,
46  double testStat_data,
47  int n_bins,
48  bool verbosity):
49  TNamed(name,title),
50  fSb_histo(NULL),
51  fSb_histo_shaded(NULL),
52  fB_histo(NULL),
53  fB_histo_shaded(NULL),
54  fData_testStat_line(0),
55  fLegend(0),
56  fPad(0),
57  fVerbose(verbosity)
58 {
59  int nToysSB = sb_vals.size();
60  int nToysB = sb_vals.size();
61  assert (nToysSB >0);
62  assert (nToysB >0);
63 
64  // Get the max and the min of the plots
65  double min = *std::min_element(sb_vals.begin(), sb_vals.end());
66  double max = *std::max_element(sb_vals.begin(), sb_vals.end());
67 
68  double min_b = *std::min_element(b_vals.begin(), b_vals.end());
69  double max_b = *std::max_element(b_vals.begin(), b_vals.end());
70 
71 
72  if ( min_b < min) min = min_b;
73  if ( max_b > max) max = max_b;
74 
75  if (testStat_data<min) min = testStat_data;
76  if (testStat_data>max) max = testStat_data;
77 
78  min *= 1.1;
79  max *= 1.1;
80 
81  // Build the histos
82 
83  fSb_histo = new TH1F ("SB_model",title,n_bins,min,max);
84  fSb_histo->SetTitle(fSb_histo->GetTitle());
85  fSb_histo->SetLineColor(kBlue);
86  fSb_histo->GetXaxis()->SetTitle("test statistics");
87  fSb_histo->SetLineWidth(2);
88 
89  fB_histo = new TH1F ("B_model",title,n_bins,min,max);
90  fB_histo->SetTitle(fB_histo->GetTitle());
91  fB_histo->SetLineColor(kRed);
92  fB_histo->GetXaxis()->SetTitle("test statistics");
93  fB_histo->SetLineWidth(2);
94 
95  for (int i=0;i<nToysSB;++i) fSb_histo->Fill(sb_vals[i]);
96  for (int i=0;i<nToysB;++i) fB_histo->Fill(b_vals[i]);
97 
98  double histos_max_y = fSb_histo->GetMaximum();
99  double line_hight = histos_max_y/nToysSB;
100  if (histos_max_y<fB_histo->GetMaximum()) histos_max_y = fB_histo->GetMaximum()/nToysB;
101 
102  // Build the line of the measured -2lnQ
103  fData_testStat_line = new TLine(testStat_data,0,testStat_data,line_hight);
104  fData_testStat_line->SetLineWidth(3);
105  fData_testStat_line->SetLineColor(kBlack);
106 
107  // The legend
108  double golden_section = (std::sqrt(5.)-1)/2;
109 
110  fLegend = new TLegend(0.75,0.95-0.2*golden_section,0.95,0.95);
111  TString title_leg="test statistics distributions ";
112  title_leg+=sb_vals.size();
113  title_leg+=" toys";
114  fLegend->SetName(title_leg.Data());
115  fLegend->AddEntry(fSb_histo,"SB toy datasets");
116  fLegend->AddEntry(fB_histo,"B toy datasets");
117  fLegend->AddEntry((TLine*)fData_testStat_line,"test statistics on data","L");
118  fLegend->SetFillColor(0);
119 }
120 
121 ////////////////////////////////////////////////////////////////////////////////
122 /// destructor
123 
124 HybridPlot::~HybridPlot()
125 {
126 
127  if (fSb_histo) delete fSb_histo;
128  if (fB_histo) delete fB_histo;
129  if (fSb_histo_shaded) delete fSb_histo_shaded;
130  if (fB_histo_shaded) delete fB_histo_shaded;
131  if (fData_testStat_line) delete fData_testStat_line;
132  if (fLegend) delete fLegend;
133 }
134 
135 ////////////////////////////////////////////////////////////////////////////////
136 /// draw the S+B and B histogram in the current canvas
137 
138 void HybridPlot::Draw(const char* )
139 {
140  // We don't want the statistics of the histos
141  gStyle->SetOptStat(0);
142 
143  // The histos
144 
145  if (fSb_histo->GetMaximum()>fB_histo->GetMaximum()){
146  fSb_histo->DrawNormalized();
147  fB_histo->DrawNormalized("same");
148  }
149  else{
150  fB_histo->DrawNormalized();
151  fSb_histo->DrawNormalized("same");
152  }
153 
154  // Shaded
155  fB_histo_shaded = (TH1F*)fB_histo->Clone("b_shaded");
156  fB_histo_shaded->SetFillStyle(3005);
157  fB_histo_shaded->SetFillColor(kRed);
158 
159  fSb_histo_shaded = (TH1F*)fSb_histo->Clone("sb_shaded");
160  fSb_histo_shaded->SetFillStyle(3004);
161  fSb_histo_shaded->SetFillColor(kBlue);
162 
163  // Empty the bins according to the data -2lnQ
164  double data_m2lnq= fData_testStat_line->GetX1();
165  for (int i=1;i<=fSb_histo->GetNbinsX();++i){
166  if (fSb_histo->GetBinCenter(i)<data_m2lnq){
167  fSb_histo_shaded->SetBinContent(i,0);
168  fB_histo_shaded->SetBinContent(i,fB_histo->GetBinContent(i)/fB_histo->GetSumOfWeights());
169  }
170  else{
171  fB_histo_shaded->SetBinContent(i,0);
172  fSb_histo_shaded->SetBinContent(i,fSb_histo->GetBinContent(i)/fSb_histo->GetSumOfWeights());
173  }
174  }
175 
176  // Draw the shaded histos
177  fB_histo_shaded->Draw("same");
178  fSb_histo_shaded->Draw("same");
179 
180  // The line
181  fData_testStat_line->Draw("same");
182 
183  // The legend
184  fLegend->Draw("same");
185 
186  if (gPad) {
187  gPad->SetName(GetName());
188  gPad->SetTitle(GetTitle() );
189  }
190 
191  fPad = gPad;
192 
193 }
194 
195 ////////////////////////////////////////////////////////////////////////////////
196 /// All the objects are written to rootfile
197 
198 void HybridPlot::DumpToFile (const char* RootFileName, const char* options)
199 {
200 
201  TFile ofile(RootFileName,options);
202  ofile.cd();
203 
204  // The histos
205  fSb_histo->Write();
206  fB_histo->Write();
207 
208  // The shaded histos
209  if (fB_histo_shaded!=NULL && fSb_histo_shaded!=NULL){
210  fB_histo_shaded->Write();
211  fSb_histo_shaded->Write();
212  }
213 
214  // The line
215  fData_testStat_line->Write("Measured test statistics line tag");
216 
217  // The legend
218  fLegend->Write();
219 
220  ofile.Close();
221 
222 }
223 
224 ////////////////////////////////////////////////////////////////////////////////
225 
226 void HybridPlot::DumpToImage(const char * filename) {
227  if (!fPad) {
228  Error("HybridPlot","Hybrid plot has not yet been drawn ");
229  return;
230  }
231  fPad->Print(filename);
232 }
233 
234 ////////////////////////////////////////////////////////////////////////////////
235 /// Perform 2 times a gaussian fit to fetch the center of the histo.
236 /// To get the second fit range get an interval that tries to keep into account
237 /// the skewness of the distribution.
238 
239 double HybridPlot::GetHistoCenter(TH1* histo_orig, double n_rms, bool display_result){
240  // Get the center of the histo
241 
242  TString optfit = "Q0";
243  if (display_result) optfit = "Q";
244 
245  TH1F* histo = (TH1F*)histo_orig->Clone();
246 
247  // get the histo x extremes
248  double x_min = histo->GetXaxis()->GetXmin();
249  double x_max = histo->GetXaxis()->GetXmax();
250 
251  // First fit!
252 
253  TF1* gaus = new TF1("mygaus", "gaus", x_min, x_max);
254 
255  gaus->SetParameter("Constant",histo->GetEntries());
256  gaus->SetParameter("Mean",histo->GetMean());
257  gaus->SetParameter("Sigma",histo->GetRMS());
258 
259  histo->Fit(gaus,optfit);
260 
261  // Second fit!
262  double sigma = gaus->GetParameter("Sigma");
263  double mean = gaus->GetParameter("Mean");
264 
265  delete gaus;
266 
267  std::cout << "Center is 1st pass = " << mean << std::endl;
268 
269  double skewness = histo->GetSkewness();
270 
271  x_min = mean - n_rms*sigma - sigma*skewness/2;
272  x_max = mean + n_rms*sigma - sigma*skewness/2;;
273 
274  TF1* gaus2 = new TF1("mygaus2", "gaus", x_min, x_max);
275  gaus2->SetParameter("Mean",mean);
276 
277  // second fit : likelihood fit
278  optfit += "L";
279  histo->Fit(gaus2,optfit,"", x_min, x_max);
280 
281 
282  double center = gaus2->GetParameter("Mean");
283 
284  if (display_result) {
285  histo->Draw();
286  gaus2->Draw("same");
287  }
288  else {
289  delete histo;
290  }
291  delete gaus2;
292 
293  return center;
294 
295 
296 }
297 
298 ////////////////////////////////////////////////////////////////////////////////
299 /// We let an horizontal bar go down and we stop when we have the integral
300 /// equal to the desired one.
301 
302 double* HybridPlot::GetHistoPvals (TH1* histo, double percentage){
303 
304  if (percentage>1){
305  std::cerr << "Percentage greater or equal to 1!\n";
306  return NULL;
307  }
308 
309  // Get the integral of the histo
310  double* h_integral=histo->GetIntegral();
311 
312  // Start the iteration
313  std::map<int,int> extremes_map;
314 
315  for (int i=0;i<histo->GetNbinsX();++i){
316  for (int j=0;j<histo->GetNbinsX();++j){
317  double integral = h_integral[j]-h_integral[i];
318  if (integral>percentage){
319  extremes_map[i]=j;
320  break;
321  }
322  }
323  }
324 
325  // Now select the couple of extremes which have the lower bin content diff
326  std::map<int,int>::iterator it;
327  int a,b;
328  double left_bin_center(0.),right_bin_center(0.);
329  double diff=10e40;
330  double current_diff;
331  for (it = extremes_map.begin();it != extremes_map.end();++it){
332  a=it->first;
333  b=it->second;
334  current_diff=std::fabs(histo->GetBinContent(a)-histo->GetBinContent(b));
335  if (current_diff<diff){
336  //std::cout << "a=" << a << " b=" << b << std::endl;
337  diff=current_diff;
338  left_bin_center=histo->GetBinCenter(a);
339  right_bin_center=histo->GetBinCenter(b);
340  }
341  }
342 
343  double* d = new double[2];
344  d[0]=left_bin_center;
345  d[1]=right_bin_center;
346  return d;
347 }
348 
349 ////////////////////////////////////////////////////////////////////////////////
350 /// Get the median of an histogram.
351 
352 double HybridPlot::GetMedian(TH1* histo){
353 
354  //int xbin_median;
355  Double_t* integral = histo->GetIntegral();
356  int median_i = 0;
357  for (int j=0;j<histo->GetNbinsX(); j++)
358  if (integral[j]<0.5)
359  median_i = j;
360 
361  double median_x =
362  histo->GetBinCenter(median_i)+
363  (histo->GetBinCenter(median_i+1)-
364  histo->GetBinCenter(median_i))*
365  (0.5-integral[median_i])/(integral[median_i+1]-integral[median_i]);
366 
367  return median_x;
368 }