#ifndef ROOSTATS_MCMCIntervalPlot
#include "RooStats/MCMCIntervalPlot.h"
#endif
#include <iostream>
#ifndef ROOT_TROOT
#include "TROOT.h"
#endif
#ifndef ROOT_TMath
#include "TMath.h"
#endif
#ifndef ROOT_TLine
#include "TLine.h"
#endif
#ifndef ROOT_TObjArray
#include "TObjArray.h"
#endif
#ifndef ROOT_TList
#include "TList.h"
#endif
#ifndef ROOT_TGraph
#include "TGraph.h"
#endif
#ifndef ROOT_TPad
#include "TPad.h"
#endif
#ifndef ROO_REAL_VAR
#include "RooRealVar.h"
#endif
#ifndef ROO_PLOT
#include "RooPlot.h"
#endif
#ifndef ROOT_TH2
#include "TH2.h"
#endif
#ifndef ROOT_TH1F
#include "TH1F.h"
#endif
#ifndef ROO_ARG_LIST
#include "RooArgList.h"
#endif
#ifndef ROOT_TAxis
#include "TAxis.h"
#endif
#ifndef ROO_GLOBAL_FUNC
#include "RooGlobalFunc.h"
#endif
ClassImp(RooStats::MCMCIntervalPlot);
using namespace std;
using namespace RooStats;
MCMCIntervalPlot::MCMCIntervalPlot()
{
fInterval = NULL;
fParameters = NULL;
fPosteriorHist = NULL;
fPosteriorKeysPdf = NULL;
fPosteriorKeysProduct = NULL;
fDimension = 0;
fLineColor = kBlack;
fShadeColor = kGray;
fLineWidth = 1;
fShowBurnIn = kTRUE;
fWalk = NULL;
fBurnIn = NULL;
fFirst = NULL;
fParamGraph = NULL;
fNLLGraph = NULL;
fNLLHist = NULL;
fWeightHist = NULL;
fPosteriorHistHistCopy = NULL;
fPosteriorHistTFCopy = NULL;
}
MCMCIntervalPlot::MCMCIntervalPlot(MCMCInterval& interval)
{
SetMCMCInterval(interval);
fPosteriorHist = NULL;
fPosteriorKeysPdf = NULL;
fPosteriorKeysProduct = NULL;
fLineColor = kBlack;
fShadeColor = kGray;
fLineWidth = 1;
fShowBurnIn = kTRUE;
fWalk = NULL;
fBurnIn = NULL;
fFirst = NULL;
fParamGraph = NULL;
fNLLGraph = NULL;
fNLLHist = NULL;
fWeightHist = NULL;
fPosteriorHistHistCopy = NULL;
fPosteriorHistTFCopy = NULL;
}
MCMCIntervalPlot::~MCMCIntervalPlot()
{
delete fParameters;
delete fPosteriorKeysPdf;
delete fPosteriorKeysProduct;
delete fWalk;
delete fBurnIn;
delete fFirst;
delete fParamGraph;
delete fNLLGraph;
}
void MCMCIntervalPlot::SetMCMCInterval(MCMCInterval& interval)
{
fInterval = &interval;
fDimension = fInterval->GetDimension();
fParameters = fInterval->GetParameters();
}
void MCMCIntervalPlot::Draw(const Option_t* options)
{
DrawInterval(options);
}
void MCMCIntervalPlot::DrawPosterior(const Option_t* options)
{
if (fInterval->GetUseKeys())
DrawPosteriorKeysPdf(options);
else
DrawPosteriorHist(options);
}
void* MCMCIntervalPlot::DrawPosteriorHist(const Option_t* ,
const char* title, Bool_t scale)
{
if (fPosteriorHist == NULL)
fPosteriorHist = fInterval->GetPosteriorHist();
if (fPosteriorHist == NULL) {
coutE(InputArguments) << "MCMCIntervalPlot::DrawPosteriorHist: "
<< "Couldn't get posterior histogram." << endl;
return NULL;
}
if (scale)
fPosteriorHist->Scale(1/fPosteriorHist->GetBinContent(
fPosteriorHist->GetMaximumBin()));
TString ourTitle(GetTitle());
if (ourTitle.CompareTo("") == 0) {
if (title)
fPosteriorHist->SetTitle(title);
} else
fPosteriorHist->SetTitle(GetTitle());
return (void*)fPosteriorHist;
}
void* MCMCIntervalPlot::DrawPosteriorKeysPdf(const Option_t* options)
{
if (fPosteriorKeysPdf == NULL)
fPosteriorKeysPdf = fInterval->GetPosteriorKeysPdf();
if (fPosteriorKeysPdf == NULL) {
coutE(InputArguments) << "MCMCIntervalPlot::DrawPosteriorKeysPdf: "
<< "Couldn't get posterior Keys PDF." << endl;
return NULL;
}
TString title(GetTitle());
Bool_t isEmpty = (title.CompareTo("") == 0);
if (fDimension == 1) {
RooRealVar* v = (RooRealVar*)fParameters->first();
RooPlot* frame = v->frame();
if (frame == NULL) {
coutE(InputArguments) << "MCMCIntervalPlot::DrawPosteriorKeysPdf: "
<< "Invalid parameter" << endl;
return NULL;
}
if (isEmpty)
frame->SetTitle(Form("Posterior Keys PDF for %s", v->GetName()));
else
frame->SetTitle(GetTitle());
return (void*)frame;
} else if (fDimension == 2) {
RooArgList* axes = fInterval->GetAxes();
RooRealVar* xVar = (RooRealVar*)axes->at(0);
RooRealVar* yVar = (RooRealVar*)axes->at(1);
TH2F* keysHist = (TH2F*)fPosteriorKeysPdf->createHistogram(
"keysPlot2D", *xVar, RooFit::YVar(*yVar), RooFit::Scaling(kFALSE));
if (isEmpty)
keysHist->SetTitle(
Form("MCMC histogram of posterior Keys PDF for %s, %s",
axes->at(0)->GetName(), axes->at(1)->GetName()));
else
keysHist->SetTitle(GetTitle());
keysHist->Draw(options);
delete axes;
return NULL;
}
return NULL;
}
void MCMCIntervalPlot::DrawInterval(const Option_t* options)
{
switch (fInterval->GetIntervalType()) {
case MCMCInterval::kShortest:
DrawShortestInterval(options);
break;
case MCMCInterval::kTailFraction:
DrawTailFractionInterval(options);
break;
default:
coutE(InputArguments) << "MCMCIntervalPlot::DrawInterval(): " <<
"Interval type not supported" << endl;
break;
}
}
void MCMCIntervalPlot::DrawShortestInterval(const Option_t* options)
{
if (fInterval->GetUseKeys())
DrawKeysPdfInterval(options);
else
DrawHistInterval(options);
}
void MCMCIntervalPlot::DrawKeysPdfInterval(const Option_t* options)
{
TString title(GetTitle());
Bool_t isEmpty = (title.CompareTo("") == 0);
if (fDimension == 1) {
RooPlot* frame = (RooPlot*)DrawPosteriorKeysPdf(options);
Double_t height = fInterval->GetKeysMax();
RooRealVar* p = (RooRealVar*)fParameters->first();
Double_t ul = fInterval->UpperLimitByKeys(*p);
Double_t ll = fInterval->LowerLimitByKeys(*p);
if (frame != NULL && fPosteriorKeysPdf != NULL) {
if (isEmpty)
frame->SetTitle(NULL);
else
frame->SetTitle(GetTitle());
frame->GetYaxis()->SetTitle(Form("Posterior for parameter %s",
p->GetName()));
fPosteriorKeysPdf->plotOn(frame,
RooFit::Normalization(1, RooAbsReal::Raw),
RooFit::Range(ll, ul, kFALSE),
RooFit::VLines(),
RooFit::DrawOption("F"),
RooFit::MoveToBack(),
RooFit::FillColor(fShadeColor));
fPosteriorKeysPdf->plotOn(frame,
RooFit::Normalization(1, RooAbsReal::Raw));
}
if (frame) {
frame->Draw(options);
}
TLine* llLine = new TLine(ll, 0, ll, height);
TLine* ulLine = new TLine(ul, 0, ul, height);
llLine->SetLineColor(fLineColor);
ulLine->SetLineColor(fLineColor);
llLine->SetLineWidth(fLineWidth);
ulLine->SetLineWidth(fLineWidth);
llLine->Draw(options);
ulLine->Draw(options);
} else if (fDimension == 2) {
if (fPosteriorKeysPdf == NULL)
fPosteriorKeysPdf = fInterval->GetPosteriorKeysPdf();
if (fPosteriorKeysPdf == NULL) {
coutE(InputArguments) << "MCMCIntervalPlot::DrawKeysPdfInterval: "
<< "Couldn't get posterior Keys PDF." << endl;
return;
}
RooArgList* axes = fInterval->GetAxes();
RooRealVar* xVar = (RooRealVar*)axes->at(0);
RooRealVar* yVar = (RooRealVar*)axes->at(1);
TH2F* contHist = (TH2F*)fPosteriorKeysPdf->createHistogram(
"keysContour2D", *xVar, RooFit::YVar(*yVar), RooFit::Scaling(kFALSE));
if (!isEmpty)
contHist->SetTitle(GetTitle());
else
contHist->SetTitle(NULL);
contHist->SetStats(kFALSE);
TString tmpOpt(options);
if (!tmpOpt.Contains("CONT2")) tmpOpt.Append("CONT2");
Double_t cutoff = fInterval->GetKeysPdfCutoff();
contHist->SetContour(1, &cutoff);
contHist->SetLineColor(fLineColor);
contHist->SetLineWidth(fLineWidth);
contHist->Draw(tmpOpt.Data());
delete axes;
} else {
coutE(InputArguments) << "MCMCIntervalPlot::DrawKeysPdfInterval: "
<< " Sorry: " << fDimension << "-D plots not currently supported" << endl;
}
}
void MCMCIntervalPlot::DrawHistInterval(const Option_t* options)
{
TString title(GetTitle());
Bool_t isEmpty = (title.CompareTo("") == 0);
if (fDimension == 1) {
RooRealVar* p = (RooRealVar*)fParameters->first();
Double_t ul = fInterval->UpperLimitByHist(*p);
Double_t ll = fInterval->LowerLimitByHist(*p);
TH1F* hist = (TH1F*)DrawPosteriorHist(options, NULL, false);
if (hist == NULL) return;
if (isEmpty)
hist->SetTitle(NULL);
else
hist->SetTitle(GetTitle());
hist->GetYaxis()->SetTitle(Form("Posterior for parameter %s",
p->GetName()));
hist->SetStats(kFALSE);
TH1F* copy = (TH1F*)hist->Clone(Form("%s_copy", hist->GetTitle()));
Double_t histCutoff = fInterval->GetHistCutoff();
Int_t i;
Int_t nBins = copy->GetNbinsX();
Double_t height;
for (i = 1; i <= nBins; i++) {
height = copy->GetBinContent(i);
if (height < histCutoff)
copy->SetBinContent(i, 0);
}
hist->Scale(1/hist->GetBinContent(hist->GetMaximumBin()));
copy->Scale(1/copy->GetBinContent(hist->GetMaximumBin()));
copy->SetFillStyle(1001);
copy->SetFillColor(fShadeColor);
hist->Draw(options);
copy->Draw("same");
fPosteriorHistHistCopy = copy;
TLine* llLine = new TLine(ll, 0, ll, 1);
TLine* ulLine = new TLine(ul, 0, ul, 1);
llLine->SetLineColor(fLineColor);
ulLine->SetLineColor(fLineColor);
llLine->SetLineWidth(fLineWidth);
ulLine->SetLineWidth(fLineWidth);
llLine->Draw(options);
ulLine->Draw(options);
} else if (fDimension == 2) {
if (fPosteriorHist == NULL)
fPosteriorHist = fInterval->GetPosteriorHist();
if (fPosteriorHist == NULL) {
coutE(InputArguments) << "MCMCIntervalPlot::DrawHistInterval: "
<< "Couldn't get posterior histogram." << endl;
return;
}
RooArgList* axes = fInterval->GetAxes();
if (!isEmpty)
fPosteriorHist->SetTitle(GetTitle());
else
fPosteriorHist->SetTitle(NULL);
delete axes;
fPosteriorHist->SetStats(kFALSE);
TString tmpOpt(options);
if (!tmpOpt.Contains("CONT2")) tmpOpt.Append("CONT2");
Double_t cutoff = fInterval->GetHistCutoff();
fPosteriorHist->SetContour(1, &cutoff);
fPosteriorHist->SetLineColor(fLineColor);
fPosteriorHist->SetLineWidth(fLineWidth);
fPosteriorHist->Draw(tmpOpt.Data());
} else {
coutE(InputArguments) << "MCMCIntervalPlot::DrawHistInterval: "
<< " Sorry: " << fDimension << "-D plots not currently supported" << endl;
}
}
void MCMCIntervalPlot::DrawTailFractionInterval(const Option_t* options)
{
TString title(GetTitle());
Bool_t isEmpty = (title.CompareTo("") == 0);
if (fDimension == 1) {
RooRealVar* p = (RooRealVar*)fParameters->first();
Double_t ul = fInterval->UpperLimitTailFraction(*p);
Double_t ll = fInterval->LowerLimitTailFraction(*p);
TH1F* hist = (TH1F*)DrawPosteriorHist(options, NULL, false);
if (hist == NULL) return;
if (isEmpty)
hist->SetTitle(NULL);
else
hist->SetTitle(GetTitle());
hist->GetYaxis()->SetTitle(Form("Posterior for parameter %s",
p->GetName()));
hist->SetStats(kFALSE);
TH1F* copy = (TH1F*)hist->Clone(Form("%s_copy", hist->GetTitle()));
Int_t i;
Int_t nBins = copy->GetNbinsX();
Double_t center;
for (i = 1; i <= nBins; i++) {
center = copy->GetBinCenter(i);
if (center < ll || center > ul)
copy->SetBinContent(i, 0);
}
hist->Scale(1/hist->GetBinContent(hist->GetMaximumBin()));
copy->Scale(1/copy->GetBinContent(hist->GetMaximumBin()));
copy->SetFillStyle(1001);
copy->SetFillColor(fShadeColor);
hist->Draw(options);
copy->Draw("same");
TLine* llLine = new TLine(ll, 0, ll, 1);
TLine* ulLine = new TLine(ul, 0, ul, 1);
llLine->SetLineColor(fLineColor);
ulLine->SetLineColor(fLineColor);
llLine->SetLineWidth(fLineWidth);
ulLine->SetLineWidth(fLineWidth);
llLine->Draw(options);
ulLine->Draw(options);
} else {
coutE(InputArguments) << "MCMCIntervalPlot::DrawTailFractionInterval: "
<< " Sorry: " << fDimension << "-D plots not currently supported"
<< endl;
}
}
void* MCMCIntervalPlot::DrawPosteriorKeysProduct(const Option_t* options)
{
if (fPosteriorKeysProduct == NULL)
fPosteriorKeysProduct = fInterval->GetPosteriorKeysProduct();
if (fPosteriorKeysProduct == NULL) {
coutE(InputArguments) << "MCMCIntervalPlot::DrawPosteriorKeysProduct: "
<< "Couldn't get posterior Keys product." << endl;
return NULL;
}
RooArgList* axes = fInterval->GetAxes();
TString title(GetTitle());
Bool_t isEmpty = (title.CompareTo("") == 0);
if (fDimension == 1) {
RooPlot* frame = ((RooRealVar*)fParameters->first())->frame();
if (!frame) return NULL;
if (isEmpty)
frame->SetTitle(Form("Posterior Keys PDF * Heaviside product for %s",
axes->at(0)->GetName()));
else
frame->SetTitle(GetTitle());
fPosteriorKeysProduct->plotOn(frame,
RooFit::Normalization(1, RooAbsReal::Raw));
frame->Draw(options);
return (void*)frame;
} else if (fDimension == 2) {
RooRealVar* xVar = (RooRealVar*)axes->at(0);
RooRealVar* yVar = (RooRealVar*)axes->at(1);
TH2F* productHist = (TH2F*)fPosteriorKeysProduct->createHistogram(
"prodPlot2D", *xVar, RooFit::YVar(*yVar), RooFit::Scaling(kFALSE));
if (isEmpty)
productHist->SetTitle(
Form("MCMC Posterior Keys Product Hist. for %s, %s",
axes->at(0)->GetName(), axes->at(1)->GetName()));
else
productHist->SetTitle(GetTitle());
productHist->Draw(options);
return NULL;
}
delete axes;
return NULL;
}
void MCMCIntervalPlot::DrawChainScatter(RooRealVar& xVar, RooRealVar& yVar)
{
const MarkovChain* markovChain = fInterval->GetChain();
Int_t size = markovChain->Size();
Int_t burnInSteps;
if (fShowBurnIn)
burnInSteps = fInterval->GetNumBurnInSteps();
else
burnInSteps = 0;
Double_t* x = new Double_t[size - burnInSteps];
Double_t* y = new Double_t[size - burnInSteps];
Double_t* burnInX = NULL;
Double_t* burnInY = NULL;
if (burnInSteps > 0) {
burnInX = new Double_t[burnInSteps];
burnInY = new Double_t[burnInSteps];
}
Double_t firstX;
Double_t firstY;
for (Int_t i = burnInSteps; i < size; i++) {
x[i - burnInSteps] = markovChain->Get(i)->getRealValue(xVar.GetName());
y[i - burnInSteps] = markovChain->Get(i)->getRealValue(yVar.GetName());
}
for (Int_t i = 0; i < burnInSteps; i++) {
burnInX[i] = markovChain->Get(i)->getRealValue(xVar.GetName());
burnInY[i] = markovChain->Get(i)->getRealValue(yVar.GetName());
}
firstX = markovChain->Get(0)->getRealValue(xVar.GetName());
firstY = markovChain->Get(0)->getRealValue(yVar.GetName());
TString title(GetTitle());
Bool_t isEmpty = (title.CompareTo("") == 0);
TGraph* walk = new TGraph(size - burnInSteps, x, y);
if (isEmpty)
walk->SetTitle(Form("2-D Scatter Plot of Markov chain for %s, %s",
xVar.GetName(), yVar.GetName()));
else
walk->SetTitle(GetTitle());
walk->GetXaxis()->Set(xVar.numBins(), xVar.getMin(), xVar.getMax());
walk->GetXaxis()->SetTitle(xVar.GetName());
walk->GetYaxis()->Set(yVar.numBins(), yVar.getMin(), yVar.getMax());
walk->GetYaxis()->SetTitle(yVar.GetName());
walk->SetLineColor(kGray);
walk->SetMarkerStyle(6);
walk->SetMarkerColor(kViolet);
walk->Draw("A,L,P,same");
TGraph* burnIn = NULL;
if (burnInX != NULL && burnInY != NULL) {
burnIn = new TGraph(burnInSteps - 1, burnInX, burnInY);
burnIn->SetLineColor(kPink);
burnIn->SetMarkerStyle(6);
burnIn->SetMarkerColor(kPink);
burnIn->Draw("L,P,same");
}
TGraph* first = new TGraph(1, &firstX, &firstY);
first->SetLineColor(kGreen);
first->SetMarkerStyle(3);
first->SetMarkerSize(2);
first->SetMarkerColor(kGreen);
first->Draw("L,P,same");
delete [] x;
delete [] y;
if (burnInX != NULL) delete [] burnInX;
if (burnInY != NULL) delete [] burnInY;
}
void MCMCIntervalPlot::DrawParameterVsTime(RooRealVar& param)
{
const MarkovChain* markovChain = fInterval->GetChain();
Int_t size = markovChain->Size();
Int_t numEntries = 2 * size;
Double_t* value = new Double_t[numEntries];
Double_t* time = new Double_t[numEntries];
Double_t val;
Int_t weight;
Int_t t = 0;
for (Int_t i = 0; i < size; i++) {
val = markovChain->Get(i)->getRealValue(param.GetName());
weight = (Int_t)markovChain->Weight();
value[2*i] = val;
value[2*i + 1] = val;
time[2*i] = t;
t += weight;
time[2*i + 1] = t;
}
TString title(GetTitle());
Bool_t isEmpty = (title.CompareTo("") == 0);
TGraph* paramGraph = new TGraph(numEntries, time, value);
if (isEmpty)
paramGraph->SetTitle(Form("%s vs. time in Markov chain",param.GetName()));
else
paramGraph->SetTitle(GetTitle());
paramGraph->GetXaxis()->SetTitle("Time (discrete steps)");
paramGraph->GetYaxis()->SetTitle(param.GetName());
paramGraph->Draw("A,L,same");
delete [] value;
delete [] time;
}
void MCMCIntervalPlot::DrawNLLVsTime()
{
const MarkovChain* markovChain = fInterval->GetChain();
Int_t size = markovChain->Size();
Int_t numEntries = 2 * size;
Double_t* nllValue = new Double_t[numEntries];
Double_t* time = new Double_t[numEntries];
Double_t nll;
Int_t weight;
Int_t t = 0;
for (Int_t i = 0; i < size; i++) {
nll = markovChain->NLL(i);
weight = (Int_t)markovChain->Weight();
nllValue[2*i] = nll;
nllValue[2*i + 1] = nll;
time[2*i] = t;
t += weight;
time[2*i + 1] = t;
}
TString title(GetTitle());
Bool_t isEmpty = (title.CompareTo("") == 0);
TGraph* nllGraph = new TGraph(numEntries, time, nllValue);
if (isEmpty)
nllGraph->SetTitle("NLL value vs. time in Markov chain");
else
nllGraph->SetTitle(GetTitle());
nllGraph->GetXaxis()->SetTitle("Time (discrete steps)");
nllGraph->GetYaxis()->SetTitle("NLL (-log(likelihood))");
nllGraph->Draw("A,L,same");
delete [] nllValue;
delete [] time;
}
void MCMCIntervalPlot::DrawNLLHist(const Option_t* options)
{
if (fNLLHist == NULL) {
const MarkovChain* markovChain = fInterval->GetChain();
Double_t maxNLL = 0;
Int_t size = markovChain->Size();
for (Int_t i = 0; i < size; i++)
if (markovChain->NLL(i) > maxNLL)
maxNLL = markovChain->NLL(i);
RooRealVar* nllVar = fInterval->GetNLLVar();
fNLLHist = new TH1F("mcmc_nll_hist", "MCMC NLL Histogram",
nllVar->getBins(), 0, maxNLL);
TString title(GetTitle());
Bool_t isEmpty = (title.CompareTo("") == 0);
if (!isEmpty)
fNLLHist->SetTitle(GetTitle());
fNLLHist->GetXaxis()->SetTitle("-log(likelihood)");
for (Int_t i = 0; i < size; i++)
fNLLHist->Fill(markovChain->NLL(i), markovChain->Weight());
}
fNLLHist->Draw(options);
}
void MCMCIntervalPlot::DrawWeightHist(const Option_t* options)
{
if (fWeightHist == NULL) {
const MarkovChain* markovChain = fInterval->GetChain();
Double_t maxWeight = 0;
Int_t size = markovChain->Size();
for (Int_t i = 0; i < size; i++)
if (markovChain->Weight(i) > maxWeight)
maxWeight = markovChain->Weight(i);
fWeightHist = new TH1F("mcmc_weight_hist", "MCMC Weight Histogram",
(Int_t)(maxWeight + 1), 0, maxWeight * 1.02);
for (Int_t i = 0; i < size; i++)
fWeightHist->Fill(markovChain->Weight(i));
}
fWeightHist->Draw(options);
}