• Main Page
  • Namespaces
  • Classes
  • Files
  • File List
  • File Members

BCH1D.cxx

Go to the documentation of this file.
00001 /*
00002  * Copyright (C) 2008-2010, Daniel Kollar and Kevin Kroeninger.
00003  * All rights reserved.
00004  *
00005  * For the licensing terms see doc/COPYING.
00006  */
00007 
00008 // ---------------------------------------------------------
00009 
00010 #include "BAT/BCH1D.h"
00011 
00012 #include "BAT/BCLog.h"
00013 #include "BAT/BCMath.h"
00014 
00015 #include <TH1D.h>
00016 #include <TH2.h>
00017 #include <TLine.h>
00018 #include <TPolyLine.h>
00019 #include <TPaveLabel.h>
00020 #include <TLatex.h>
00021 #include <TError.h>
00022 #include <TCanvas.h>
00023 #include <TMarker.h>
00024 #include <TLegend.h>
00025 #include <TString.h>
00026 
00027 #include <math.h>
00028 
00029 // ---------------------------------------------------------
00030 
00031 BCH1D::BCH1D()
00032 {
00033    fHistogram = 0;
00034    fDefaultCLLimit = 95.; // in percent
00035 
00036    fModeFlag = 0;
00037 }
00038 
00039 // ---------------------------------------------------------
00040 
00041 BCH1D::~BCH1D()
00042 {
00043    if (fHistogram) delete fHistogram;
00044 }
00045 
00046 // ---------------------------------------------------------
00047 
00048 double BCH1D::GetMode()
00049 {
00050    return fHistogram->GetBinCenter(fHistogram->GetMaximumBin());
00051 }
00052 
00053 // ---------------------------------------------------------
00054 
00055 double BCH1D::GetQuantile(double probability)
00056 {
00057    int nquantiles = 1;
00058    double quantiles[1];
00059    double probsum[1];
00060 
00061    probsum[0] = probability;
00062 
00063    // use ROOT function to calculat quantile.
00064    fHistogram->GetQuantiles(nquantiles, quantiles, probsum);
00065 
00066    return quantiles[0];
00067 }
00068 
00069 // ---------------------------------------------------------
00070 
00071 double BCH1D::GetIntegral(double valuemin, double valuemax)
00072 {
00073    double integral = 0;
00074 
00075    int binmin = fHistogram->FindBin(valuemin);
00076    int binmax = fHistogram->FindBin(valuemax);
00077 
00078    // use ROOT function to calculate integral.
00079    integral = fHistogram->Integral(binmin, binmax);
00080 
00081    return integral;
00082 }
00083 
00084 // ---------------------------------------------------------
00085 
00086 double BCH1D::GetPValue(double probability)
00087 {
00088    // use ROOT function to calculate the integral from 0 to "probability".
00089    return fHistogram->Integral(1, fHistogram->FindBin(probability));
00090 }
00091 
00092 // ---------------------------------------------------------
00093 
00094 void BCH1D::SetDefaultCLLimit(double limit)
00095 {
00096    // check if limit is between 68% and 100%. Give a warning if not ...
00097    if(limit>=100. || limit<68.)
00098       BCLog::OutWarning(
00099          Form("BCH1D::SetDefaultCLLimit : Value %.1f out of range. Keeping default %.1f%% CL limit.",limit,fDefaultCLLimit));
00100 
00101    // ... or set value if true.
00102    else
00103       fDefaultCLLimit = limit;
00104 }
00105 
00106 // ---------------------------------------------------------
00107 
00108 void BCH1D::Print(const char * filename, int options, double ovalue, int ww, int wh)
00109 {
00110    char file[256];
00111    int i=0;
00112    while(i<255 && *filename!='\0')
00113       file[i++]=*filename++;
00114    file[i]='\0';
00115 
00116 // temporary
00117    fHistogram->SetLineWidth(1);
00118 
00119    // create temporary canvas
00120    TCanvas * c;
00121    if(ww > 0 && wh > 0)
00122       c = new TCanvas("c","c",ww,wh);
00123    else
00124       c = new TCanvas("c","c");
00125 
00126    c->cd();
00127    Draw(options, ovalue);
00128 
00129    gPad->RedrawAxis();
00130 
00131    // print to file.
00132    c->Print(file);
00133 }
00134 
00135 // ---------------------------------------------------------
00136 
00137 void BCH1D::Draw(int options, double ovalue)
00138 {
00139    double min, max;
00140    double mode;
00141    double thismode = GetMode();
00142 
00143    int nbins = fHistogram->GetNbinsX();
00144 
00145    fHistogram->Scale(1./fHistogram->Integral("width"));
00146 
00147    if(fModeFlag)
00148       mode=fMode;
00149    else
00150       mode=thismode;
00151 
00152    // define temporary line.
00153    TLine * line;
00154 
00155    //control if legend is required
00156    bool flagLegend=false;
00157    char confidenceLabel[25];
00158 
00159    // reset histogram
00160    fHistogram->SetLineColor(kBlack);
00161    fHistogram->SetLineWidth(1);
00162    fHistogram->SetFillStyle(0);
00163 
00164    // check drawing option.
00165    switch(options)
00166    {
00167       // Draw a band between 16% and 84% probability.
00168       // If the mode is outside the band only draw a limit.
00169       case 0:
00170          if (fabs(ovalue) >= 100 || ovalue==0.)
00171          {//default case if no args to Draw() supplied
00172 
00173             min = GetQuantile(.16);
00174             max = GetQuantile(.84);
00175 
00176             //draw a legend later
00177             flagLegend = true;
00178             sprintf(confidenceLabel, "Central 68%%");
00179 
00180 //          if ( thismode > max || fHistogram->FindBin(thismode) == fHistogram->GetNbinsX() )
00181             if ( fHistogram->FindBin(thismode) == fHistogram->GetNbinsX() )
00182             {
00183                min = GetQuantile(1.-(double)fDefaultCLLimit/100.);
00184                max = fHistogram->GetXaxis()->GetXmax();
00185                ovalue = fDefaultCLLimit;
00186                sprintf(confidenceLabel, "%g%% region", fDefaultCLLimit);
00187             }
00188 //          else if (thismode < min || fHistogram->FindBin(thismode)==1)
00189             else if ( fHistogram->FindBin(thismode)==1)
00190             {
00191                min = fHistogram->GetXaxis()->GetXmin();
00192                max = GetQuantile((double)fDefaultCLLimit/100.);
00193                ovalue = -fDefaultCLLimit;
00194                sprintf(confidenceLabel, "%g%% region", fDefaultCLLimit);
00195             }
00196          }
00197 
00198          else if(ovalue < 0)
00199          {
00200             min = fHistogram->GetXaxis()->GetXmin();
00201             max = GetQuantile(-ovalue/100.);
00202          }
00203          else
00204          {
00205             min = GetQuantile(1. - ovalue/100.);
00206             max = fHistogram->GetXaxis()->GetXmax();
00207          }
00208 
00209          // do the drawing
00210          DrawShadedLimits(mode, min, max, ovalue);
00211 
00212          // add legend for the symbols mean, mode, median, confidence band
00213          if(flagLegend)
00214             this ->DrawLegend(confidenceLabel);
00215 
00216 
00217          break;
00218 
00219       // Draw a line at "ovalue".
00220       case 1:
00221 
00222          fHistogram->Draw();
00223          min = fHistogram->GetBinLowEdge(1);
00224          max = fHistogram->GetBinLowEdge(nbins+1);
00225          if(min<=ovalue && ovalue<=max)
00226          {
00227             line = new TLine();
00228             line->SetLineColor(kRed);
00229             line->DrawLine(ovalue, 0., ovalue, 1.05 * fHistogram->GetMaximum());
00230          }
00231 
00232          break;
00233 
00234       // Draw a shaded band at the smallest interval.
00235       case 2:
00236 
00237          if(ovalue<50) // just to ensure there's some sense in the number
00238             ovalue = 68.; // default is 68%
00239 
00240          GetSmallestInterval(min, max, ovalue/100.);
00241          DrawShadedLimits(mode, min, max, 0.);
00242 
00243 //       DrawLegend(TString::Format("Smallest %g%",ovalue));
00244 
00245          break;
00246 
00247       // Draw a shaded band at the smallest intervals
00248       case 3:
00249 
00250          if(ovalue<50) // just to ensure there's some sense in the number
00251             ovalue = 68.; // default is 68%
00252 
00253          DrawSmallest(mode,ovalue);
00254 
00255          break;
00256 
00257       // Sort out bad options and warn.
00258       default:
00259 
00260          BCLog::OutError(Form("BCH1D::Draw : Invalid option %d",options));
00261          break;
00262    }
00263 }
00264 // ---------------------------------------------------------
00265 
00266 void BCH1D::DrawLegend(const char* text)
00267 {
00268    //draw on top right corner
00269 
00270    TLegend* legend = new TLegend(0.73, 0.72, 0.86, 0.85);
00271    legend->SetFillColor(kWhite);
00272    legend->SetBorderSize(1);
00273 
00274    TMarker* triangle = new TMarker(0, 0, 23);
00275    triangle->SetMarkerColor(kRed);
00276    legend->AddEntry(triangle, "Global mode", "P");
00277 
00278    TMarker* diamond = new TMarker(0, 0, 27);
00279    diamond->SetMarkerColor(kBlue);
00280    legend->AddEntry(diamond, "Mean", "P");
00281 
00282    TLine * line;
00283    line = new TLine();
00284    line->SetLineStyle(2);
00285    line->SetLineColor(kGreen + 2);
00286    legend->AddEntry(line, "Median", "l");
00287 
00288    TLegend* band = new TLegend(0, 0, 1, 1);
00289    band->SetFillColor(kYellow);
00290    legend->AddEntry(band, text, "F");
00291 
00292    legend->SetTextAlign(12);
00293 
00294    //fine tuned by hand so text legible even with several plots in a row
00295    legend->SetTextSize(0.016);
00296 
00297    legend->Draw();
00298 }
00299 
00300 // ---------------------------------------------------------
00301 
00302 // TODO Are graphics objects ever deleted from the heap?
00303 
00304 void BCH1D::DrawShadedLimits(double mode, double min, double max, double limit)
00305 {
00306    double maximum = fHistogram->GetMaximum();
00307 
00308    double x0 = mode;
00309    double y0 = fHistogram->GetBinContent( fHistogram->FindBin(mode) );
00310 
00311    double x1 = fHistogram->GetMean();
00312    double y1 = fHistogram->GetBinContent( fHistogram->FindBin(x1) );
00313 
00314    double x2 = GetQuantile(.5); // median
00315    double y2 = fHistogram->GetBinContent( fHistogram->FindBin(x2) );
00316 
00317    double ysize = maximum*1.3;
00318 
00319    double xmin = fHistogram->GetXaxis()->GetXmin();
00320    double xmax = fHistogram->GetXaxis()->GetXmax();
00321 
00322    // draw histogram with axes first
00323    TH2D * hsc = new TH2D(
00324          TString::Format("h2scale_%s_%d",fHistogram->GetName(),BCLog::GetHIndex()),"",
00325          10, xmin, xmax, 10, 0., ysize);
00326    hsc->SetStats(0);
00327    hsc->SetXTitle(fHistogram->GetXaxis()->GetTitle());
00328    hsc->SetYTitle(fHistogram->GetYaxis()->GetTitle());
00329    hsc->Draw();
00330 
00331    // draw histogram
00332    fHistogram->SetLineWidth(1);
00333    fHistogram->Draw("same");
00334 
00335    // draw yellow shaded region between min and max
00336    TH1D * hist_shaded = GetSubHisto(min,max,TString::Format("%s_sub_%d",fHistogram->GetName(),BCLog::GetHIndex()));
00337    hist_shaded->SetFillStyle(1001);
00338    hist_shaded->SetFillColor(kYellow);
00339 
00340    // draw shaded histogram
00341    hist_shaded->Draw("same");
00342 
00343    gPad->RedrawAxis();
00344 
00345    // draw triangle for mode
00346    TPolyLine * tmax;
00347 
00348    double dx = 0.01*(xmax-xmin);
00349    double dy = 0.04*(ysize);
00350    y0+=dy/5.;
00351    double tmax_x[] = {x0, x0 + dx, x0 - dx, x0};
00352    double tmax_y[] = {y0, y0 + dy, y0 + dy, y0};
00353    tmax = new TPolyLine(4,tmax_x,tmax_y);
00354    tmax->SetLineColor(kRed);
00355    tmax->SetLineWidth(1);
00356    tmax->SetFillColor(kRed);
00357    tmax->Draw();
00358    tmax->Draw("f");
00359 
00360    // draw diamond for mean
00361    TPolyLine * tmean;
00362 
00363    y1+=dy/5.;
00364 // double tmean_x[] = {x1, x1 + dx, x1 - dx, x1};
00365 // double tmean_y[] = {y1, y1 + dy, y1 + dy, y1};
00366    double tmean_x[] = {x1, x1 + dx, x1 , x1 - dx, x1};
00367    double tmean_y[] = {y1, y1 + dy/2., y1 + dy, y1 + dy/2., y1};
00368    tmean = new TPolyLine(5,tmean_x,tmean_y);
00369    tmean->SetLineColor(kBlue);
00370 // tmean->SetFillColor(kWhite);
00371    tmean->SetLineWidth(1);
00372 // tmean->SetLineStyle(1);
00373    tmean->Draw();
00374 
00375 /*
00376    // draw arrow for median
00377    TPolyLine * tmed;
00378    TPolyLine * tmed2;
00379 
00380 // y2+=dy/5.;
00381    y2=0.+dy/5.;
00382    double tmed_x[] = {x2 + dx, x2, x2 - dx};
00383    double tmed_y[] = {y2 + dy, y2, y2 + dy};
00384    double tmed2_x[] = {x2, x2};
00385    double tmed2_y[] = {y2, y2 + dy*2.};
00386    tmed = new TPolyLine(3,tmed_x,tmed_y);
00387    tmed2 = new TPolyLine(2,tmed2_x,tmed2_y);
00388    tmed->SetLineColor(kGreen+2);
00389    tmed->SetLineWidth(1);
00390    tmed2->SetLineColor(kGreen+2);
00391    tmed2->SetLineWidth(1);
00392    tmed->Draw();
00393    tmed2->Draw();
00394 */
00395    // draw dashed line for median
00396    TLine * line;
00397    line = new TLine();
00398    line->SetLineStyle(2);
00399    line->SetLineColor(kGreen+2);
00400    line->DrawLine(x2, 0., x2, y2);
00401 
00402 
00403    // write mode location and shaded band
00404 
00405    // format of the number
00406    double delta_max = fmax(fabs(max-x1),fabs(x1-min));
00407 
00408    int sd = 2 + (int)log10(fabs(x1/delta_max));
00409 
00410    if( (int)log10(x1) > (int)log10(delta_max) )
00411       sd++;
00412 
00413    TLatex * tmax_text = new TLatex();
00414    tmax_text->SetTextSize(0.045);
00415    tmax_text->SetTextFont(62);
00416    tmax_text->SetTextAlign(22); // center
00417 // tmax_text->SetTextAlign(13); // top-left
00418 
00419    double xprint=(xmax+xmin)/2.;
00420 // double xprint=xmin+(xmax-xmin)/20.;
00421    double yprint=ysize*(1-1.4*tmax_text->GetTextSize());
00422 
00423    if(fabs(limit)<50) // just to ensure there's some sense in the number
00424       tmax_text->DrawLatex(xprint,yprint,
00425          TString::Format( TString::Format("%%s^{med} = %%.%dg ^{+%%.2g}_{ -%%.2g}",sd),
00426             fHistogram->GetXaxis()->GetTitle(), x2, max-x2, x2-min));
00427 
00428    else if (limit<0)
00429       tmax_text->DrawLatex(xprint,yprint,
00430          TString::Format( TString::Format("%%s (%d%%%% prob.) < %%.4g",-(int)limit),
00431             fHistogram->GetXaxis()->GetTitle(), max));
00432 
00433    else if (limit>0)
00434       tmax_text->DrawLatex(xprint,yprint,
00435          TString::Format( TString::Format("%%s (%d%%%% prob.) > %%.4g",(int)limit),
00436             fHistogram->GetXaxis()->GetTitle(), min));
00437 
00438 /*
00439    TLegend * leg = new TLegend(.61,.7,.9,.88);
00440    leg->SetFillColor(kWhite);
00441    leg->SetFillStyle(0);
00442    leg->SetBorderSize(0);
00443    leg->AddEntry(line,"Median", "l");
00444    TH1D * hh0 = new TH1D("hh0","",10,0,10);
00445    hh0->SetMarkerStyle(23);
00446    hh0->SetMarkerColor(kBlue);
00447    hh0->SetMarkerSize(1);
00448    leg->AddEntry(hh0,"Mean","p");
00449    TH1D * hh1 = new TH1D("hh1","",10,0,10);
00450    hh1->SetMarkerStyle(23);
00451    hh1->SetMarkerColor(kRed);
00452    hh1->SetMarkerSize(1);
00453    leg->AddEntry(hh1,"Mode","p");
00454    leg->AddEntry(hist_shaded, "Central 68%", "f");
00455    leg ->Draw();
00456 */
00457 
00458 }
00459 
00460 // ---------------------------------------------------------
00461 
00462 void BCH1D::DrawSmallest(double mode, double prob, bool drawmean)
00463 {
00464    // prepare triangle for mode
00465    TPolyLine * tmax;
00466 
00467    double x0 = mode;
00468    double y0 = fHistogram->GetBinContent( fHistogram->FindBin(mode) );
00469    double xmin = fHistogram->GetXaxis()->GetXmin();
00470    double xmax = fHistogram->GetXaxis()->GetXmax();
00471    double ysize = 1.3 * fHistogram->GetMaximum();
00472 
00473    double x1 = fHistogram->GetMean();
00474    double y1 = fHistogram->GetBinContent( fHistogram->FindBin(x1) );
00475 
00476    double x2 = GetQuantile(.5); // median
00477    double y2 = fHistogram->GetBinContent( fHistogram->FindBin(x2) );
00478 
00479    double dx = 0.01*(xmax-xmin);
00480    double dy = 0.04*(ysize);
00481    double tmax_x[] = {x0, x0 + dx, x0 - dx, x0};
00482    double tmax_y[] = {y0, y0 + dy, y0 + dy, y0};
00483    tmax = new TPolyLine(4,tmax_x,tmax_y);
00484    tmax->SetLineColor(kRed);
00485    tmax->SetFillColor(kRed);
00486 
00487    // draw histogram with axes first
00488    TH2D * hsc = new TH2D(
00489          TString::Format("h2scale_%s_%d",fHistogram->GetName(),BCLog::GetHIndex()),"",
00490          10, xmin, xmax, 10, 0., ysize);
00491    hsc->SetStats(0);
00492    hsc->SetXTitle(fHistogram->GetXaxis()->GetTitle());
00493    hsc->SetYTitle(fHistogram->GetYaxis()->GetTitle());
00494    hsc->Draw();
00495 
00496    // histogram to be filled with band
00497    TH1D * hist_temp1 = (TH1D*) fHistogram->Clone();
00498    hist_temp1->Scale(1.0/fHistogram->Integral("width"));
00499    hist_temp1->SetFillColor(kYellow);
00500    hist_temp1->SetFillStyle(1001);
00501 
00502    // temporary histogram
00503    TH1D * hist_temp2 = (TH1D*) fHistogram->Clone();
00504    hist_temp2->Scale(1.0/fHistogram->Integral("width"));
00505 
00506    // clear content
00507    hist_temp1->Reset();
00508 
00509    // loop over original histogram and copy bin untils integral equals
00510    // "prob"
00511    prob /= 100.;
00512 
00513    // integral
00514    double sum = 0.0;
00515 
00516    int n=0;
00517    int nbins=fHistogram->GetNbinsX();
00518 
00519    // loop
00520    while (sum < prob && n < nbins)
00521    {
00522       n++;
00523 
00524       // find bin with maximum
00525       int bin = hist_temp2->GetMaximumBin();
00526 
00527       // copy bin to new histogram
00528       double val = hist_temp2->GetBinContent(bin);
00529       hist_temp1->SetBinContent(bin, val);
00530 
00531       // remove maximum from temporary histogram
00532       hist_temp2->SetBinContent(bin, 0.0);
00533 
00534       // integrate by summing
00535       sum += val * hist_temp2->GetBinWidth(bin);
00536    }
00537 
00538    // scale histogram
00539    hist_temp1->Scale(fHistogram->Integral("width"));
00540 
00541    // draw histograms
00542    fHistogram->Draw("same");
00543    hist_temp1->Draw("same");
00544 
00545    // draw triangle for mode
00546    tmax->Draw("f");
00547 
00548    if(drawmean)
00549    {
00550       // draw triangle for mean
00551       // draw diamond for mean
00552       TPolyLine * tmean;
00553 
00554       y1+=dy/5.;
00555 //    double tmean_x[] = {x1, x1 + dx, x1 - dx, x1};
00556 //    double tmean_y[] = {y1, y1 + dy, y1 + dy, y1};
00557       double tmean_x[] = {x1, x1 + dx, x1 , x1 - dx, x1};
00558       double tmean_y[] = {y1, y1 + dy/2., y1 + dy, y1 + dy/2., y1};
00559       tmean = new TPolyLine(5,tmean_x,tmean_y);
00560       tmean->SetLineColor(kBlue);
00561 //    tmean->SetFillColor(kWhite);
00562       tmean->SetLineWidth(1);
00563 //    tmean->SetLineStyle(1);
00564       tmean->Draw();
00565 
00566       // draw dashed line for median
00567       TLine * line;
00568       line = new TLine();
00569       line->SetLineStyle(2);
00570       line->SetLineColor(kGreen+2);
00571       line->DrawLine(x2, 0., x2, y2);
00572    }
00573 
00574    // free memory
00575    delete hist_temp2;
00576 }
00577 
00578 // ---------------------------------------------------------
00579 
00580 double BCH1D::GetSmallestInterval(double & min, double & max, double content)
00581 {
00582    if(content<=0. || content>= 1.)
00583       return 0.;
00584 
00585    int nbins = fHistogram->GetNbinsX();
00586 
00587    double factor = fHistogram->Integral("width");
00588    if(factor==0)
00589       return 0.;
00590 
00591    // normalize if not yet done
00592    fHistogram->Scale(1./factor);
00593 
00594    double xmin = fHistogram->GetXaxis()->GetXmin();
00595    double xmax = fHistogram->GetXaxis()->GetXmax();
00596    double width = xmax - xmin;
00597 
00598    double xdown=xmin;
00599    double xup=xmax;
00600 
00601    int ndiv = 10;
00602 // if(nbins<100)
00603 //    ndiv = 1000;
00604 // if(nbins>1000)
00605 //    ndiv = 10;
00606 
00607    int warn=0;
00608 
00609    double integral_out=0.;
00610 
00611    // loop through the bins
00612    for(int i=1;i<nbins+1;i++)
00613    {
00614       if(fHistogram->Integral(i,nbins,"width") < content)
00615          break;
00616 
00617       // get width of the starting bin
00618       double firstbinwidth = fHistogram->GetBinWidth(i);
00619 
00620       // divide i-th bin in ndiv divisions
00621       // integrate starting at each of these divisions
00622       for(int j=0;j<ndiv;j++)
00623       {
00624          double dxdown = (double)(ndiv-j)/(double)ndiv * firstbinwidth;
00625          xdown = fHistogram->GetBinLowEdge(i) + firstbinwidth - dxdown;
00626          double integral = dxdown * fHistogram->GetBinContent(i);
00627 
00628          if(integral>content)
00629          {
00630             // content fits within one bin
00631             xup = xdown + content / fHistogram->GetBinContent(i);
00632             warn = 1;
00633          }
00634          else
00635             for(int k=i+1;k<nbins+1;k++)
00636             {
00637 
00638                double thisbin = fHistogram->GetBinContent(k) * fHistogram->GetBinWidth(k);
00639 
00640                if(integral+thisbin==content)
00641                {
00642                   xup = fHistogram->GetBinLowEdge(k+1);
00643                   break;
00644                }
00645 
00646                if(integral+thisbin>content)
00647                {
00648                   xup = fHistogram->GetBinLowEdge(k) + (content-integral)/thisbin * fHistogram->GetBinWidth(k);
00649                   integral += thisbin * (xup-fHistogram->GetBinLowEdge(k))/fHistogram->GetBinWidth(k);
00650                   break;
00651                }
00652 
00653                integral += thisbin;
00654             }
00655 
00656          if(integral < content)
00657             continue;
00658 
00659          if(xup - xdown < width)
00660          {
00661             // store necessary information
00662             width = xup - xdown;
00663             xmin  = xdown;
00664             xmax  = xup;
00665             integral_out = integral;
00666          }
00667       }
00668    }
00669 
00670    if(warn)
00671    {
00672       BCLog::OutWarning(
00673             Form("BCH1D::GetSmallestInterval : The requested content of %d%% fits within one bin.",(int)(content*100)));
00674       BCLog::OutWarning("BCH1D::GetSmallestInterval : MAKE FINER BINNING (OR CHANGE RANGE) !!!");
00675    }
00676 
00677    // restore normalization to state before calling this method
00678    fHistogram->Scale(factor);
00679 
00680    min=xmin;
00681    max=xmax;
00682 
00683    return integral_out;
00684 }
00685 
00686 // ---------------------------------------------------------
00687 
00688 double BCH1D::IntegralWidth(double min, double max)
00689 {
00690    int imin = fHistogram->FindBin(min);
00691    int imax = fHistogram->FindBin(max);
00692 
00693    int nbins = fHistogram->GetNbinsX();
00694 
00695    // if outside of histogram range, return -1.
00696    if ( imin<1 || imin>nbins || imax<1 || imax>nbins )
00697       return -1.;
00698 
00699    if ( imin==imax )
00700       return -1.;
00701 
00702    // swap values if necessary
00703    if (imin>imax)
00704    {
00705       int i=imin;
00706       double x=min;
00707       imin=imax, min=max;
00708       imax=i, max=x;
00709    }
00710 
00711    // calculate first bin
00712    double first = ( fHistogram->GetBinLowEdge(imin+1) - min ) * fHistogram->GetBinContent(imin);
00713 
00714    // calculate last bin
00715    double last = ( max - fHistogram->GetBinLowEdge(imax) ) * fHistogram->GetBinContent(imax);
00716 
00717    // calculate inbetween
00718    double inbetween=0.;
00719    if(imax-imin>1)
00720       inbetween = fHistogram->Integral(imin+1, imax-1, "width");
00721 
00722    return first + inbetween + last;
00723 }
00724 
00725 // ---------------------------------------------------------
00726 
00727 TH1D * BCH1D::GetSubHisto(double min, double max, const char * name)
00728 {
00729    if(min>max)
00730    {
00731       double t=min;
00732       min=max;
00733       max=t;
00734    }
00735 
00736    int imin = fHistogram->FindBin(min);
00737    int imax = fHistogram->FindBin(max);
00738 
00739    int nbins = fHistogram->GetNbinsX();
00740    double xmin = fHistogram->GetXaxis()->GetXmin();
00741    double xmax = fHistogram->GetXaxis()->GetXmax();
00742 
00743    if( min==max || (min<=xmin && max>=xmax) )
00744    {
00745       TH1D * h0 = (TH1D*) fHistogram->Clone(name);
00746       return h0;
00747    }
00748 
00749    if (imin<1)
00750    {
00751       imin=1;
00752       min=xmin;
00753    }
00754    if (imax>nbins)
00755    {
00756       imax=nbins;
00757       max=xmax;
00758    }
00759 
00760    double * xb = new double[nbins+3]; // nbins+1 original bin edges + 2 new bins
00761    int n=0; // counter
00762 
00763    int domin=1;
00764    int domax=1;
00765 
00766    for (int i=1;i<nbins+2;i++)
00767    {
00768       double x0 = fHistogram->GetBinLowEdge(i);
00769 
00770       if (min<x0 && domin)
00771       {
00772          xb[n++]=min;
00773          domin=0;
00774       }
00775       else if (min==x0)
00776          domin=0;
00777 
00778       if (max<x0 && domax)
00779       {
00780          xb[n++]=max;
00781          domax=0;
00782       }
00783       else if (max==x0)
00784          domax=0;
00785 
00786       xb[n++]=x0;
00787    }
00788 
00789    // now define the new histogram
00790    TH1D * h0 = new TH1D(name,"",n-1,xb);
00791    for(int i=1;i<n;i++)
00792    {
00793       double x0 = h0->GetBinCenter(i);
00794       if(x0<min || x0>max)
00795          continue;
00796 
00797       int bin=fHistogram->FindBin(x0);
00798       h0->SetBinContent(i, fHistogram->GetBinContent(bin));
00799    }
00800 
00801    return h0;
00802 }
00803 
00804 // ---------------------------------------------------------
00805 
00806 TH1D * BCH1D::GetSmallestIntervalHistogram(double level)
00807 {
00808    // create a new histogram which will be returned and all yellow
00809    TH1D * hist_yellow = (TH1D*) fHistogram->Clone();
00810    hist_yellow->Reset();
00811    hist_yellow->SetFillStyle(1001);
00812    hist_yellow->SetFillColor(kYellow);
00813 
00814    // copy a temporary histogram
00815    TH1D * hist_temp = (TH1D*) fHistogram->Clone(TString::Format("%s_%i",fHistogram->GetName(),BCLog::GetHIndex()));
00816    double factor = hist_temp->Integral("");
00817 
00818    if(factor == 0)
00819       return 0;
00820 
00821    hist_temp->Scale(1. / factor);
00822 
00823    // here's the algorithm:
00824    // 1. find the maximum bin in the temporary histogram and copy it to
00825    // the yellow histogram.
00826    // 2. remove this bin from the temporary histogram.
00827    // 3. repeat this until a total of "level" probability is copied to
00828    // the yellow histogram.
00829 
00830    double sumprob = 0.0;
00831 
00832    while (sumprob < level)
00833    {
00834       // find maximum bin and value
00835       int bin = hist_temp->GetMaximumBin();
00836       double value = hist_temp->GetMaximum();
00837 
00838       // copy "1" into the corresponding bin in the yellow histogram
00839       hist_yellow->SetBinContent(bin, 1.0);
00840 
00841       // set the bin value in the temporary histogram to zero
00842       hist_temp->SetBinContent(bin, 0.0);
00843 
00844       // increase probability sum
00845       sumprob += value;
00846    }
00847 
00848    delete hist_temp;
00849 
00850    return hist_yellow;
00851 }
00852 
00853 // ---------------------------------------------------------
00854 
00855 std::vector <double> BCH1D::GetSmallestIntervals(double content)
00856 {
00857    std::vector <double> v;
00858 
00859    TH1D * hist = GetSmallestIntervalHistogram(content);
00860 
00861    int nbins = hist->GetNbinsX();
00862    int ninter = 0;
00863    int lastbin = -1;
00864 
00865    double max = -1;
00866    double localmax = -1;
00867    double localmaxpos = -1;
00868    double localint = 0;
00869    bool flag = false;
00870 
00871    for (int i = 1; i <= nbins; ++i)
00872    {
00873       // interval starts here
00874       if (!flag && hist->GetBinContent(i) > 0.)
00875       {
00876          flag = true;
00877          v.push_back(hist->GetBinLowEdge(i));
00878 
00879          // remember start position of the interval
00880          lastbin = i;
00881 
00882          // increase number of intervals
00883          ninter++;
00884 
00885          // reset local maximum
00886          localmax = fHistogram->GetBinContent(i);
00887          localmaxpos = hist->GetBinLowEdge(i);
00888 
00889          // reset local integral
00890          localint = 0;
00891       }
00892 
00893       // interval stops here
00894       if ((flag && !(hist->GetBinContent(i) > 0.)) || (flag && i == nbins))
00895       {
00896          flag = false;
00897          v.push_back(hist->GetBinLowEdge(i) + hist->GetBinWidth(i));
00898 
00899          // set right bin to maximum if on edge
00900          if (i == nbins && localmax < fHistogram->GetBinContent(i))
00901             localmaxpos = hist->GetBinCenter(i) + 0.5 * hist->GetBinWidth(i);
00902 
00903          // find the absolute maximum
00904          if (localmax > max)
00905             max = localmax;
00906 
00907          // save local maximum
00908          v.push_back(localmax);
00909          v.push_back(localmaxpos);
00910 
00911          // save local integral
00912          v.push_back(localint);
00913       }
00914 
00915       // find local maximum
00916       if (i < nbins && localmax < fHistogram->GetBinContent(i))
00917       {
00918          localmax = fHistogram->GetBinContent(i);
00919          localmaxpos = hist->GetBinCenter(i);
00920       }
00921 
00922       // increase area
00923       localint += fHistogram->GetBinContent(i) / fHistogram->Integral();
00924    }
00925 
00926    // rescale absolute heights to relative heights
00927    for (int i = 0; i < ninter; ++i)
00928       v[i*5+2] = v.at(i*5+2) / max;
00929 
00930    return v;
00931 }
00932 
00933 // ---------------------------------------------------------

Generated on Fri Nov 19 2010 17:02:52 for Bayesian Analysis Toolkit by  doxygen 1.7.1