// @(#)root/hist:$Id$

//___________________________________
/**
Class HybridPlot
Authors: D. Piparo, G. Schott - Universitaet Karlsruhe

This class provides the plots for the result of a study performed with the 
HybridCalculator class.

An example plot is available here:
   http://www-ekp.physik.uni-karlsruhe.de/~schott/roostats/hybridplot_example.png
*/


#include "assert.h"
#include <cmath>
#include <iostream>
#include <map>

#include "RooStats/HybridPlot.h"
#include "TStyle.h"
#include "TF1.h"
#include "TAxis.h"
#include "TH1.h"
#include "TLine.h"
#include "TLegend.h"
#include "TFile.h"
#include "TVirtualPad.h"

#include <algorithm>

/// To build the THtml documentation
using namespace std;

ClassImp(RooStats::HybridPlot)

using namespace RooStats;

/*----------------------------------------------------------------------------*/

HybridPlot::HybridPlot(const char* name,
                       const  char* title,
                       const std::vector<double> & sb_vals,
                       const std::vector<double> & b_vals,
                       double testStat_data,
                       int n_bins,
                       bool verbosity):
  TNamed(name,title),
  fSb_histo(NULL),
  fSb_histo_shaded(NULL),
  fB_histo(NULL),
  fB_histo_shaded(NULL),
  fData_testStat_line(0),
  fLegend(0),
  fPad(0),
  fVerbose(verbosity)
{
  // HybridPlot constructor

  int nToysSB = sb_vals.size();
  int nToysB = sb_vals.size();
  assert (nToysSB >0);
  assert (nToysB >0);

  // Get the max and the min of the plots
  double min = *std::min_element(sb_vals.begin(), sb_vals.end());
  double max = *std::max_element(sb_vals.begin(), sb_vals.end());

  double min_b = *std::min_element(b_vals.begin(), b_vals.end());
  double max_b = *std::max_element(b_vals.begin(), b_vals.end());
  

  if ( min_b < min) min = min_b; 
  if ( max_b > max) max = max_b; 

  if (testStat_data<min) min = testStat_data;
  if (testStat_data>max) max = testStat_data;

  min *= 1.1;
  max *= 1.1;

  // Build the histos

  fSb_histo = new TH1F ("SB_model",title,n_bins,min,max);
  fSb_histo->SetTitle(fSb_histo->GetTitle());
  fSb_histo->SetLineColor(kBlue);
  fSb_histo->GetXaxis()->SetTitle("test statistics");
  fSb_histo->SetLineWidth(2);

  fB_histo = new TH1F ("B_model",title,n_bins,min,max);
  fB_histo->SetTitle(fB_histo->GetTitle());
  fB_histo->SetLineColor(kRed);
  fB_histo->GetXaxis()->SetTitle("test statistics");
  fB_histo->SetLineWidth(2);

  for (int i=0;i<nToysSB;++i) fSb_histo->Fill(sb_vals[i]);
  for (int i=0;i<nToysB;++i) fB_histo->Fill(b_vals[i]);

  double histos_max_y = fSb_histo->GetMaximum();
  double line_hight = histos_max_y/nToysSB;
  if (histos_max_y<fB_histo->GetMaximum()) histos_max_y = fB_histo->GetMaximum()/nToysB;

  // Build the line of the measured -2lnQ
  fData_testStat_line = new TLine(testStat_data,0,testStat_data,line_hight);
  fData_testStat_line->SetLineWidth(3);
  fData_testStat_line->SetLineColor(kBlack);

  // The legend
  double golden_section = (std::sqrt(5.)-1)/2;

  fLegend = new TLegend(0.75,0.95-0.2*golden_section,0.95,0.95);
  TString title_leg="test statistics distributions ";
  title_leg+=sb_vals.size();
  title_leg+=" toys";
  fLegend->SetName(title_leg.Data());
  fLegend->AddEntry(fSb_histo,"SB toy datasets");
  fLegend->AddEntry(fB_histo,"B toy datasets");
  fLegend->AddEntry((TLine*)fData_testStat_line,"test statistics on data","L");
  fLegend->SetFillColor(0);

}

/*----------------------------------------------------------------------------*/

HybridPlot::~HybridPlot()
{
  // destructor 
  
  if (fSb_histo) delete fSb_histo;
  if (fB_histo) delete fB_histo;
  if (fSb_histo_shaded) delete fSb_histo_shaded;
  if (fB_histo_shaded) delete fB_histo_shaded;
  if (fData_testStat_line) delete fData_testStat_line;
  if (fLegend) delete fLegend;
}

/*----------------------------------------------------------------------------*/

void HybridPlot::Draw(const char* )
{
  // draw the S+B and B histogram in the current canvas


   // We don't want the statistics of the histos
   gStyle->SetOptStat(0);

   // The histos

   if (fSb_histo->GetMaximum()>fB_histo->GetMaximum()){
      fSb_histo->DrawNormalized();
      fB_histo->DrawNormalized("same");
   }
   else{
      fB_histo->DrawNormalized();
      fSb_histo->DrawNormalized("same");
   }

   // Shaded
   fB_histo_shaded = (TH1F*)fB_histo->Clone("b_shaded");
   fB_histo_shaded->SetFillStyle(3005);
   fB_histo_shaded->SetFillColor(kRed);

   fSb_histo_shaded = (TH1F*)fSb_histo->Clone("sb_shaded");
   fSb_histo_shaded->SetFillStyle(3004);
   fSb_histo_shaded->SetFillColor(kBlue);

   // Empty the bins according to the data -2lnQ
   double data_m2lnq= fData_testStat_line->GetX1();
   for (int i=1;i<=fSb_histo->GetNbinsX();++i){
      if (fSb_histo->GetBinCenter(i)<data_m2lnq){
         fSb_histo_shaded->SetBinContent(i,0);
         fB_histo_shaded->SetBinContent(i,fB_histo->GetBinContent(i)/fB_histo->GetSumOfWeights());
      }
      else{
         fB_histo_shaded->SetBinContent(i,0);
         fSb_histo_shaded->SetBinContent(i,fSb_histo->GetBinContent(i)/fSb_histo->GetSumOfWeights());
      }
   }

   // Draw the shaded histos
   fB_histo_shaded->Draw("same");
   fSb_histo_shaded->Draw("same");

   // The line 
   fData_testStat_line->Draw("same");

   // The legend
   fLegend->Draw("same");

   if (gPad) { 
      gPad->SetName(GetName()); 
      gPad->SetTitle(GetTitle() ); 
   }

   fPad = gPad; 

}

/*----------------------------------------------------------------------------*/

void HybridPlot::DumpToFile (const char* RootFileName, const char* options)
{
  // All the objects are written to rootfile

   TFile ofile(RootFileName,options);
   ofile.cd();

   // The histos
   fSb_histo->Write();
   fB_histo->Write();

   // The shaded histos
   if (fB_histo_shaded!=NULL && fSb_histo_shaded!=NULL){
      fB_histo_shaded->Write();
      fSb_histo_shaded->Write();
   }

   // The line 
   fData_testStat_line->Write("Measured test statistics line tag");

   // The legend
   fLegend->Write();

   ofile.Close();

}

void HybridPlot::DumpToImage(const char * filename) { 
   if (!fPad) { 
      Error("HybridPlot","Hybrid plot has not yet been drawn "); 
      return;
   }
   fPad->Print(filename); 
}

/*----------------------------------------------------------------------------*/

// from Rsc.cxx


/**
   Perform 2 times a gaussian fit to fetch the center of the histo.
   To get the second fit range get an interval that tries to keep into account 
   the skewness of the distribution.
**/
double HybridPlot::GetHistoCenter(TH1* histo_orig, double n_rms, bool display_result){
   // Get the center of the histo
   
   TString optfit = "Q0";
   if (display_result) optfit = "Q";

   TH1F* histo = (TH1F*)histo_orig->Clone();

   // get the histo x extremes
   double x_min = histo->GetXaxis()->GetXmin(); 
   double x_max = histo->GetXaxis()->GetXmax();

   // First fit!

   TF1* gaus = new TF1("mygaus", "gaus", x_min, x_max);

   gaus->SetParameter("Constant",histo->GetEntries());
   gaus->SetParameter("Mean",histo->GetMean());
   gaus->SetParameter("Sigma",histo->GetRMS());

   histo->Fit(gaus,optfit);

   // Second fit!
   double sigma = gaus->GetParameter("Sigma");
   double mean = gaus->GetParameter("Mean");

   delete gaus;

   std::cout << "Center is 1st pass = " << mean << std::endl;

   double skewness = histo->GetSkewness();

   x_min = mean - n_rms*sigma - sigma*skewness/2;
   x_max = mean + n_rms*sigma - sigma*skewness/2;;

   TF1* gaus2 = new TF1("mygaus2", "gaus", x_min, x_max);
   gaus2->SetParameter("Mean",mean);

   // second fit : likelihood fit
   optfit += "L";
   histo->Fit(gaus2,optfit,"", x_min, x_max);


   double center = gaus2->GetParameter("Mean");

   if (display_result) { 
      histo->Draw();
      gaus2->Draw("same");
   }
   else { 
      delete histo;
   }
   delete gaus2; 

   return center;


}

/**
   We let an orizzontal bar go down and we stop when we have the integral 
   equal to the desired one.
**/

double* HybridPlot::GetHistoPvals (TH1* histo, double percentage){

   if (percentage>1){
      std::cerr << "Percentage greater or equal to 1!\n";
      return NULL;
   }

   // Get the integral of the histo
   double* h_integral=histo->GetIntegral();

   // Start the iteration
   std::map<int,int> extremes_map;

   for (int i=0;i<histo->GetNbinsX();++i){
      for (int j=0;j<histo->GetNbinsX();++j){
         double integral = h_integral[j]-h_integral[i];
         if (integral>percentage){
            extremes_map[i]=j;
            break;
         }
      }
   }

   // Now select the couple of extremes which have the lower bin content diff
   std::map<int,int>::iterator it;
   int a,b;
   double left_bin_center(0.),right_bin_center(0.);
   double diff=10e40;
   double current_diff;
   for (it = extremes_map.begin();it != extremes_map.end();++it){
      a=it->first;
      b=it->second;
      current_diff=std::fabs(histo->GetBinContent(a)-histo->GetBinContent(b));
      if (current_diff<diff){
         //std::cout << "a=" << a << " b=" << b << std::endl;
         diff=current_diff;
         left_bin_center=histo->GetBinCenter(a);
         right_bin_center=histo->GetBinCenter(b);
      }
   }

   double* d = new double[2];
   d[0]=left_bin_center;
   d[1]=right_bin_center;
   return d;
}

//----------------------------------------------------------------------------//
/**
   Get the median of an histogram.
**/
double HybridPlot::GetMedian(TH1* histo){

   //int xbin_median;
   Double_t* integral = histo->GetIntegral();
   int median_i = 0;
   for (int j=0;j<histo->GetNbinsX(); j++) 
      if (integral[j]<0.5) 
         median_i = j;

   double median_x = 
      histo->GetBinCenter(median_i)+
      (histo->GetBinCenter(median_i+1)-
       histo->GetBinCenter(median_i))*
      (0.5-integral[median_i])/(integral[median_i+1]-integral[median_i]);

   return median_x;
}


 HybridPlot.cxx:1
 HybridPlot.cxx:2
 HybridPlot.cxx:3
 HybridPlot.cxx:4
 HybridPlot.cxx:5
 HybridPlot.cxx:6
 HybridPlot.cxx:7
 HybridPlot.cxx:8
 HybridPlot.cxx:9
 HybridPlot.cxx:10
 HybridPlot.cxx:11
 HybridPlot.cxx:12
 HybridPlot.cxx:13
 HybridPlot.cxx:14
 HybridPlot.cxx:15
 HybridPlot.cxx:16
 HybridPlot.cxx:17
 HybridPlot.cxx:18
 HybridPlot.cxx:19
 HybridPlot.cxx:20
 HybridPlot.cxx:21
 HybridPlot.cxx:22
 HybridPlot.cxx:23
 HybridPlot.cxx:24
 HybridPlot.cxx:25
 HybridPlot.cxx:26
 HybridPlot.cxx:27
 HybridPlot.cxx:28
 HybridPlot.cxx:29
 HybridPlot.cxx:30
 HybridPlot.cxx:31
 HybridPlot.cxx:32
 HybridPlot.cxx:33
 HybridPlot.cxx:34
 HybridPlot.cxx:35
 HybridPlot.cxx:36
 HybridPlot.cxx:37
 HybridPlot.cxx:38
 HybridPlot.cxx:39
 HybridPlot.cxx:40
 HybridPlot.cxx:41
 HybridPlot.cxx:42
 HybridPlot.cxx:43
 HybridPlot.cxx:44
 HybridPlot.cxx:45
 HybridPlot.cxx:46
 HybridPlot.cxx:47
 HybridPlot.cxx:48
 HybridPlot.cxx:49
 HybridPlot.cxx:50
 HybridPlot.cxx:51
 HybridPlot.cxx:52
 HybridPlot.cxx:53
 HybridPlot.cxx:54
 HybridPlot.cxx:55
 HybridPlot.cxx:56
 HybridPlot.cxx:57
 HybridPlot.cxx:58
 HybridPlot.cxx:59
 HybridPlot.cxx:60
 HybridPlot.cxx:61
 HybridPlot.cxx:62
 HybridPlot.cxx:63
 HybridPlot.cxx:64
 HybridPlot.cxx:65
 HybridPlot.cxx:66
 HybridPlot.cxx:67
 HybridPlot.cxx:68
 HybridPlot.cxx:69
 HybridPlot.cxx:70
 HybridPlot.cxx:71
 HybridPlot.cxx:72
 HybridPlot.cxx:73
 HybridPlot.cxx:74
 HybridPlot.cxx:75
 HybridPlot.cxx:76
 HybridPlot.cxx:77
 HybridPlot.cxx:78
 HybridPlot.cxx:79
 HybridPlot.cxx:80
 HybridPlot.cxx:81
 HybridPlot.cxx:82
 HybridPlot.cxx:83
 HybridPlot.cxx:84
 HybridPlot.cxx:85
 HybridPlot.cxx:86
 HybridPlot.cxx:87
 HybridPlot.cxx:88
 HybridPlot.cxx:89
 HybridPlot.cxx:90
 HybridPlot.cxx:91
 HybridPlot.cxx:92
 HybridPlot.cxx:93
 HybridPlot.cxx:94
 HybridPlot.cxx:95
 HybridPlot.cxx:96
 HybridPlot.cxx:97
 HybridPlot.cxx:98
 HybridPlot.cxx:99
 HybridPlot.cxx:100
 HybridPlot.cxx:101
 HybridPlot.cxx:102
 HybridPlot.cxx:103
 HybridPlot.cxx:104
 HybridPlot.cxx:105
 HybridPlot.cxx:106
 HybridPlot.cxx:107
 HybridPlot.cxx:108
 HybridPlot.cxx:109
 HybridPlot.cxx:110
 HybridPlot.cxx:111
 HybridPlot.cxx:112
 HybridPlot.cxx:113
 HybridPlot.cxx:114
 HybridPlot.cxx:115
 HybridPlot.cxx:116
 HybridPlot.cxx:117
 HybridPlot.cxx:118
 HybridPlot.cxx:119
 HybridPlot.cxx:120
 HybridPlot.cxx:121
 HybridPlot.cxx:122
 HybridPlot.cxx:123
 HybridPlot.cxx:124
 HybridPlot.cxx:125
 HybridPlot.cxx:126
 HybridPlot.cxx:127
 HybridPlot.cxx:128
 HybridPlot.cxx:129
 HybridPlot.cxx:130
 HybridPlot.cxx:131
 HybridPlot.cxx:132
 HybridPlot.cxx:133
 HybridPlot.cxx:134
 HybridPlot.cxx:135
 HybridPlot.cxx:136
 HybridPlot.cxx:137
 HybridPlot.cxx:138
 HybridPlot.cxx:139
 HybridPlot.cxx:140
 HybridPlot.cxx:141
 HybridPlot.cxx:142
 HybridPlot.cxx:143
 HybridPlot.cxx:144
 HybridPlot.cxx:145
 HybridPlot.cxx:146
 HybridPlot.cxx:147
 HybridPlot.cxx:148
 HybridPlot.cxx:149
 HybridPlot.cxx:150
 HybridPlot.cxx:151
 HybridPlot.cxx:152
 HybridPlot.cxx:153
 HybridPlot.cxx:154
 HybridPlot.cxx:155
 HybridPlot.cxx:156
 HybridPlot.cxx:157
 HybridPlot.cxx:158
 HybridPlot.cxx:159
 HybridPlot.cxx:160
 HybridPlot.cxx:161
 HybridPlot.cxx:162
 HybridPlot.cxx:163
 HybridPlot.cxx:164
 HybridPlot.cxx:165
 HybridPlot.cxx:166
 HybridPlot.cxx:167
 HybridPlot.cxx:168
 HybridPlot.cxx:169
 HybridPlot.cxx:170
 HybridPlot.cxx:171
 HybridPlot.cxx:172
 HybridPlot.cxx:173
 HybridPlot.cxx:174
 HybridPlot.cxx:175
 HybridPlot.cxx:176
 HybridPlot.cxx:177
 HybridPlot.cxx:178
 HybridPlot.cxx:179
 HybridPlot.cxx:180
 HybridPlot.cxx:181
 HybridPlot.cxx:182
 HybridPlot.cxx:183
 HybridPlot.cxx:184
 HybridPlot.cxx:185
 HybridPlot.cxx:186
 HybridPlot.cxx:187
 HybridPlot.cxx:188
 HybridPlot.cxx:189
 HybridPlot.cxx:190
 HybridPlot.cxx:191
 HybridPlot.cxx:192
 HybridPlot.cxx:193
 HybridPlot.cxx:194
 HybridPlot.cxx:195
 HybridPlot.cxx:196
 HybridPlot.cxx:197
 HybridPlot.cxx:198
 HybridPlot.cxx:199
 HybridPlot.cxx:200
 HybridPlot.cxx:201
 HybridPlot.cxx:202
 HybridPlot.cxx:203
 HybridPlot.cxx:204
 HybridPlot.cxx:205
 HybridPlot.cxx:206
 HybridPlot.cxx:207
 HybridPlot.cxx:208
 HybridPlot.cxx:209
 HybridPlot.cxx:210
 HybridPlot.cxx:211
 HybridPlot.cxx:212
 HybridPlot.cxx:213
 HybridPlot.cxx:214
 HybridPlot.cxx:215
 HybridPlot.cxx:216
 HybridPlot.cxx:217
 HybridPlot.cxx:218
 HybridPlot.cxx:219
 HybridPlot.cxx:220
 HybridPlot.cxx:221
 HybridPlot.cxx:222
 HybridPlot.cxx:223
 HybridPlot.cxx:224
 HybridPlot.cxx:225
 HybridPlot.cxx:226
 HybridPlot.cxx:227
 HybridPlot.cxx:228
 HybridPlot.cxx:229
 HybridPlot.cxx:230
 HybridPlot.cxx:231
 HybridPlot.cxx:232
 HybridPlot.cxx:233
 HybridPlot.cxx:234
 HybridPlot.cxx:235
 HybridPlot.cxx:236
 HybridPlot.cxx:237
 HybridPlot.cxx:238
 HybridPlot.cxx:239
 HybridPlot.cxx:240
 HybridPlot.cxx:241
 HybridPlot.cxx:242
 HybridPlot.cxx:243
 HybridPlot.cxx:244
 HybridPlot.cxx:245
 HybridPlot.cxx:246
 HybridPlot.cxx:247
 HybridPlot.cxx:248
 HybridPlot.cxx:249
 HybridPlot.cxx:250
 HybridPlot.cxx:251
 HybridPlot.cxx:252
 HybridPlot.cxx:253
 HybridPlot.cxx:254
 HybridPlot.cxx:255
 HybridPlot.cxx:256
 HybridPlot.cxx:257
 HybridPlot.cxx:258
 HybridPlot.cxx:259
 HybridPlot.cxx:260
 HybridPlot.cxx:261
 HybridPlot.cxx:262
 HybridPlot.cxx:263
 HybridPlot.cxx:264
 HybridPlot.cxx:265
 HybridPlot.cxx:266
 HybridPlot.cxx:267
 HybridPlot.cxx:268
 HybridPlot.cxx:269
 HybridPlot.cxx:270
 HybridPlot.cxx:271
 HybridPlot.cxx:272
 HybridPlot.cxx:273
 HybridPlot.cxx:274
 HybridPlot.cxx:275
 HybridPlot.cxx:276
 HybridPlot.cxx:277
 HybridPlot.cxx:278
 HybridPlot.cxx:279
 HybridPlot.cxx:280
 HybridPlot.cxx:281
 HybridPlot.cxx:282
 HybridPlot.cxx:283
 HybridPlot.cxx:284
 HybridPlot.cxx:285
 HybridPlot.cxx:286
 HybridPlot.cxx:287
 HybridPlot.cxx:288
 HybridPlot.cxx:289
 HybridPlot.cxx:290
 HybridPlot.cxx:291
 HybridPlot.cxx:292
 HybridPlot.cxx:293
 HybridPlot.cxx:294
 HybridPlot.cxx:295
 HybridPlot.cxx:296
 HybridPlot.cxx:297
 HybridPlot.cxx:298
 HybridPlot.cxx:299
 HybridPlot.cxx:300
 HybridPlot.cxx:301
 HybridPlot.cxx:302
 HybridPlot.cxx:303
 HybridPlot.cxx:304
 HybridPlot.cxx:305
 HybridPlot.cxx:306
 HybridPlot.cxx:307
 HybridPlot.cxx:308
 HybridPlot.cxx:309
 HybridPlot.cxx:310
 HybridPlot.cxx:311
 HybridPlot.cxx:312
 HybridPlot.cxx:313
 HybridPlot.cxx:314
 HybridPlot.cxx:315
 HybridPlot.cxx:316
 HybridPlot.cxx:317
 HybridPlot.cxx:318
 HybridPlot.cxx:319
 HybridPlot.cxx:320
 HybridPlot.cxx:321
 HybridPlot.cxx:322
 HybridPlot.cxx:323
 HybridPlot.cxx:324
 HybridPlot.cxx:325
 HybridPlot.cxx:326
 HybridPlot.cxx:327
 HybridPlot.cxx:328
 HybridPlot.cxx:329
 HybridPlot.cxx:330
 HybridPlot.cxx:331
 HybridPlot.cxx:332
 HybridPlot.cxx:333
 HybridPlot.cxx:334
 HybridPlot.cxx:335
 HybridPlot.cxx:336
 HybridPlot.cxx:337
 HybridPlot.cxx:338
 HybridPlot.cxx:339
 HybridPlot.cxx:340
 HybridPlot.cxx:341
 HybridPlot.cxx:342
 HybridPlot.cxx:343
 HybridPlot.cxx:344
 HybridPlot.cxx:345
 HybridPlot.cxx:346
 HybridPlot.cxx:347
 HybridPlot.cxx:348
 HybridPlot.cxx:349
 HybridPlot.cxx:350
 HybridPlot.cxx:351
 HybridPlot.cxx:352
 HybridPlot.cxx:353
 HybridPlot.cxx:354
 HybridPlot.cxx:355
 HybridPlot.cxx:356
 HybridPlot.cxx:357
 HybridPlot.cxx:358
 HybridPlot.cxx:359
 HybridPlot.cxx:360
 HybridPlot.cxx:361
 HybridPlot.cxx:362
 HybridPlot.cxx:363
 HybridPlot.cxx:364
 HybridPlot.cxx:365
 HybridPlot.cxx:366
 HybridPlot.cxx:367
 HybridPlot.cxx:368
 HybridPlot.cxx:369
 HybridPlot.cxx:370
 HybridPlot.cxx:371
 HybridPlot.cxx:372
 HybridPlot.cxx:373
 HybridPlot.cxx:374
 HybridPlot.cxx:375
 HybridPlot.cxx:376
 HybridPlot.cxx:377
 HybridPlot.cxx:378
 HybridPlot.cxx:379
 HybridPlot.cxx:380