21 #include <TGraphAsymmErrors.h>
23 #include "../../BAT/BCMath.h"
24 #include "../../BAT/BCLog.h"
36 :
BCModel(
"Multi-template Fitter")
40 , fFlagEfficiencyConstraint(false)
49 , fFlagEfficiencyConstraint(false)
69 if (!channel->
GetName().compare(name))
86 if (!process->
GetName().compare(name))
103 if (!systematic->
GetName().compare(name))
112 int BCMTF::SetTemplate(
const char * channelname,
const char * processname, TH1D hist,
double efficiency,
double norm)
118 if (channelindex < 0) {
119 BCLog::OutWarning(
"BCMultitemplateFitter::SetTemplate() : Channel does not exist.");
127 if (processindex < 0) {
128 BCLog::OutWarning(
"BCMultitemplateFitter::SetTemplate() : Process does not exist.");
139 hist.SetStats(kFALSE);
143 color = 2 + processindex;
152 hist.SetFillColor(color);
153 hist.SetFillStyle(fillstyle);
154 hist.SetLineStyle(linestyle);
157 TH1D * temphist =
new TH1D(hist);
170 int BCMTF::SetTemplate(
const char * channelname,
const char * processname, std::vector<TF1 *> * funccont,
int nbins,
double efficiency)
176 if (channelindex < 0) {
177 BCLog::OutWarning(
"BCMultitemplateFitter::SetTemplate() : Channel does not exist.");
185 if (processindex < 0) {
186 BCLog::OutWarning(
"BCMultitemplateFitter::SetTemplate() : Process does not exist.");
207 int BCMTF::SetData(
const char * channelname, TH1D hist,
double minimum,
double maximum)
212 if (channelindex < 0) {
213 BCLog::OutWarning(
"BCMultitemplateFitter::SetTemplate() : Channel does not exist.");
224 hist.SetStats(kFALSE);
227 hist.SetMarkerStyle(20);
228 hist.SetMarkerSize(1.1);
231 hist.SetNdivisions(509);
254 maximum = ceil(hist.GetMaximum() + 5.*sqrt(hist.GetMaximum()));
256 std::vector<double> a(hist.GetNbinsX()+1);
257 for (
int i = 0; i < hist.GetNbinsX()+1; ++i) {
258 a[i] = hist.GetXaxis()->GetBinLowEdge(i+1);
261 TH2D* hist_uncbandexp =
new TH2D(TString::Format(
"UncertaintyBandExpectation_%i",
BCLog::GetHIndex()),
"",
262 hist.GetNbinsX(), &a[0], 1000, minimum, maximum);
263 hist_uncbandexp->SetStats(kFALSE);
265 TH2D* hist_uncbandpoisson =
new TH2D(TString::Format(
"UncertaintyBandPoisson_%i",
BCLog::GetHIndex()),
"",
266 hist.GetNbinsX(), &a[0], int(maximum-minimum), minimum, maximum);
267 hist_uncbandpoisson->SetStats(kFALSE);
288 BCLog::OutWarning(
"BCMultitemplateFitter::AddChannel() : Channel with this name exists already.");
337 int BCMTF::AddProcess(
const char * name,
double nmin,
double nmax,
int color,
int fillstyle,
int linestyle)
343 BCLog::OutWarning(
"BCMultitemplateFitter::AddProcess() : Process with this name exists already.");
401 BCLog::OutWarning(
"BCMultitemplateFitter::AddSystematic() : Systematic with this name exists already.");
442 int BCMTF::SetSystematicVariation(
const char * channelname,
const char * processname,
const char * systematicname,
double variation_up,
double variation_down)
449 if (channelindex < 0) {
450 BCLog::OutWarning(
"BCMultitemplateFitter::SetTemplate() : Channel does not exist.");
458 if (processindex < 0) {
459 BCLog::OutWarning(
"BCMultitemplateFitter::SetTemplate() : Process does not exist.");
467 if (systematicindex < 0) {
468 BCLog::OutWarning(
"BCMultitemplateFitter::SetTemplate() : Systematic does not exist.");
479 TH1D hist_up = TH1D(*hist_template);
480 TH1D hist_down = TH1D(*hist_template);
482 int nbins = hist_up.GetNbinsX();
485 for (
int ibin = 1; ibin <= nbins; ++ibin) {
486 hist_up.SetBinContent(ibin, variation_up);
487 hist_down.SetBinContent(ibin, variation_down);
494 variation->
SetHistograms(processindex,
new TH1D(hist_up),
new TH1D(hist_down));
507 if (channelindex < 0) {
508 BCLog::OutWarning(
"BCMultitemplateFitter::SetTemplate() : Channel does not exist.");
516 if (processindex < 0) {
517 BCLog::OutWarning(
"BCMultitemplateFitter::SetTemplate() : Process does not exist.");
525 if (systematicindex < 0) {
526 BCLog::OutWarning(
"BCMultitemplateFitter::SetTemplate() : Systematic does not exist.");
537 variation->
SetHistograms(processindex,
new TH1D(hist_up),
new TH1D(hist_down));
547 int nbins = hist.GetNbinsX();
549 TH1D * hist_up_rel =
new TH1D(hist);
550 TH1D * hist_down_rel =
new TH1D(hist);
553 for (
int ibin = 1; ibin <= nbins; ++ibin) {
554 hist_up_rel->SetBinContent(ibin, (hist_up.GetBinContent(ibin) - hist.GetBinContent(ibin)) / hist.GetBinContent(ibin));
555 hist_down_rel->SetBinContent(ibin, (hist.GetBinContent(ibin) - hist_down.GetBinContent(ibin)) / hist.GetBinContent(ibin));
566 std::ofstream ofi(filename);
571 BCLog::OutWarning(Form(
"BCMultitemplateFitter::PrintSummary() : Could not open file %s", filename));
576 <<
" Multi template fitter summary " << std::endl
577 <<
" ----------------------------- " << std::endl
579 <<
" Number of channels : " <<
fNChannels << std::endl
580 <<
" Number of processes : " <<
fNProcesses << std::endl
585 <<
" Channels :" << std::endl;
596 <<
" Processes :" << std::endl;
608 <<
" Systematics :" << std::endl;
620 <<
" - none - " << std::endl;
623 <<
" Goodness-of-fit: " << std::endl;
644 double expectation = 0.;
649 double efficiency =
Efficiency(channelindex, i, binindex, parameters);
652 double probability =
Probability(channelindex, i, binindex, parameters);
674 std::vector<TF1 *> * funccont =
fChannelContainer[channelindex]->GetTemplate(processindex)->GetFunctionContainer();
676 if (funccont->size()>0)
680 return parameters[parindex];
684 return func->Eval(parameters[parindex]);
689 double BCMTF::Efficiency(
int channelindex,
int processindex,
int binindex,
const std::vector<double> & parameters)
696 double defficiency = 1.;
709 if (parameters[parindex] > 0)
719 defficiency += parameters[parindex] * hist->GetBinContent(binindex);
723 efficiency *= defficiency;
737 double BCMTF::Probability(
int channelindex,
int processindex,
int binindex,
const std::vector<double> & parameters)
740 TH1D * hist =
fChannelContainer[channelindex]->GetTemplate(processindex)->GetHistogram();
743 std::vector<TF1 *> * funccont =
fChannelContainer[channelindex]->GetTemplate(processindex)->GetFunctionContainer();
746 if (!hist && !(funccont->size()>0))
750 return hist->GetBinContent(binindex);
753 return funccont->at(binindex-1)->Eval(parameters[parindex]);
758 int BCMTF::PrintStack(
const char * channelname,
const std::vector<double> & parameters,
const char * filename,
const char * options)
762 return PrintStack(index, parameters, filename, options);
766 int BCMTF::PrintStack(
int channelindex,
const std::vector<double> & parameters,
const char * filename,
const char * options)
773 if (!parameters.size())
777 bool flag_logx =
false;
778 bool flag_logy =
false;
779 bool flag_bw =
false;
781 bool flag_sum =
false;
782 bool flag_stack =
false;
784 bool flag_e0 =
false;
785 bool flag_e1 =
false;
787 bool flag_b0 =
false;
788 bool flag_b1 =
false;
790 if (std::string(options).find(
"logx") < std::string(options).size())
793 if (std::string(options).find(
"logy") < std::string(options).size())
796 if (std::string(options).find(
"bw") < std::string(options).size())
799 if (std::string(options).find(
"sum") < std::string(options).size())
802 if (std::string(options).find(
"stack") < std::string(options).size())
805 if (std::string(options).find(
"e0") < std::string(options).size())
808 if (std::string(options).find(
"e1") < std::string(options).size())
811 if (std::string(options).find(
"b0") < std::string(options).size())
814 if (std::string(options).find(
"b1") < std::string(options).size())
824 BCLog::OutWarning(
"BCMTF::PrintStack : Did not run MCMC. Error bands are not available.");
831 TCanvas * c1 =
new TCanvas();
845 int nbins = hist_data->GetNbinsX();
848 TH1D* hist_sum =
new TH1D(*hist_data);
849 hist_sum->SetLineColor(kBlack);
850 for (
int i = 1; i <= nbins; ++i)
851 hist_sum->SetBinContent(i, 0);
854 TH1D* hist_error_band =
new TH1D(*hist_data);
855 hist_error_band->SetFillColor(kBlack);
856 hist_error_band->SetFillStyle(3005);
857 hist_error_band->SetLineWidth(1);
858 hist_error_band->SetStats(kFALSE);
859 hist_error_band->SetMarkerSize(0);
861 TGraphAsymmErrors * graph_error_exp =
new TGraphAsymmErrors(nbins);
863 graph_error_exp->SetMarkerStyle(0);
864 graph_error_exp->SetFillColor(kBlack);
865 graph_error_exp->SetFillStyle(3005);
872 for (
int i = 1; i <= nbins; ++i) {
873 TH1D * proj = hist_uncbandexp->ProjectionY(
"_py", i, i);
874 if (proj->Integral() > 0)
875 proj->Scale(1.0 / proj->Integral());
877 double sums[3] = {0.16, 0.5, 0.84};
878 proj->GetQuantiles(3, quantiles, sums);
879 graph_error_exp->SetPoint(i-1, hist_data->GetBinCenter(i), quantiles[1]);
880 graph_error_exp->SetPointError(i-1, 0.0, 0.0, quantiles[1] - quantiles[0], quantiles[2]-quantiles[1]);
881 hist_error_band->SetBinContent(i, 0.5*(quantiles[2]+quantiles[0]));
882 hist_error_band->SetBinError(i, 0, 0.5*(quantiles[2]-quantiles[0]));
888 THStack * stack =
new THStack(
"",
"");
891 std::vector<TH1D *> histcontainer;
897 for (
unsigned int i = 0; i < ntemplates; ++i) {
909 hist =
new TH1D( *(temphist) );
927 hist->SetFillColor(color);
928 hist->SetFillStyle(fillstyle);
929 hist->SetLineStyle(linestyle);
932 hist->SetFillColor(0);
936 for (
int ibin = 1; ibin <= nbins; ++ibin) {
939 double efficiency =
Efficiency(channelindex, i, ibin, parameters);
942 double probability =
Probability(channelindex, i, ibin, parameters);
948 double expectation = parameters[parindex] * efficiency * probability;
951 hist->SetBinContent(ibin, expectation);
954 hist_sum->SetBinContent(ibin, hist_sum->GetBinContent(ibin) + expectation);
958 histcontainer.push_back(hist);
965 hist_data->Draw(
"P0");
971 ymax = hist_data->GetMaximum() + sqrt(hist_data->GetMaximum());
973 ymax = hist_data->GetMaximum();
980 stack->Draw(
"SAMEHIST");
981 if (stack->GetMaximum() > ymax)
982 ymax = stack->GetMaximum();
989 hist_temp->Draw(
"SAMEE2");
994 int ymaxbin = hist_temp->GetMaximumBin();
996 if (hist_temp->GetBinContent(ymaxbin)+hist_temp->GetBinError(ymaxbin)> ymax)
997 ymax = hist_temp->GetBinContent(ymaxbin)+hist_temp->GetBinError(ymaxbin);
1002 hist_error_band->Draw(
"SAMEE2");
1006 hist_sum->Draw(
"SAME");
1010 hist_data->Draw(
"SAMEP0");
1013 hist_data->Draw(
"SAMEP0E");
1015 hist_data->GetYaxis()->SetRangeUser(0., 1.1* ymax);
1021 c1->Print(filename);
1024 for (
unsigned int i = 0; i < histcontainer.size(); ++i) {
1025 TH1D * hist = histcontainer.at(i);
1030 delete graph_error_exp;
1031 delete hist_error_band;
1041 if (parameters.size() == 0)
1058 int nbins = hist->GetNbinsX();
1061 for (
int ibin = 1; ibin <= nbins; ++ibin) {
1063 double expectation =
Expectation(channelindex, ibin, parameters);
1066 double observation = hist->GetBinContent(ibin);
1069 chi2 += (expectation - observation) * (expectation - observation) / expectation;
1080 if (parameters.size() == 0)
1089 for (
int i = 0; i < nchannels; ++i) {
1100 if (parameters.size() == 0)
1117 int nbins = hist->GetNbinsX();
1120 for (
int ibin = 1; ibin <= nbins; ++ibin) {
1122 double expectation =
Expectation(channelindex, ibin, parameters);
1125 double observation = hist->GetBinContent(ibin);
1128 cash += 2. * (expectation - observation);
1131 if (observation > 0)
1132 cash += 2. * observation * log (observation/expectation);
1144 if (parameters.size() == 0)
1153 for (
int i = 0; i < nchannels; ++i) {
1176 int nbins = hist->GetNbinsX();
1179 std::vector<unsigned> observation(nbins);
1180 std::vector<double> expectation(nbins);
1183 for (
int ibin = 0; ibin < nbins; ++ibin) {
1185 expectation[ibin] =
Expectation(channelindex, ibin + 1, parameters);
1188 observation[ibin]= unsigned(hist->GetBinContent(ibin + 1));
1192 static const unsigned nIterations = unsigned (1e5);
1201 std::vector<unsigned> observation;
1202 std::vector<double> expectation;
1205 for (
int ichannel = 0; ichannel <
fNChannels; ++ichannel) {
1223 int nbins = hist->GetNbinsX();
1226 for (
int ibin = 0; ibin < nbins; ++ibin) {
1228 expectation.push_back(
Expectation(ichannel, ibin + 1, parameters));
1231 observation.push_back(
unsigned(hist->GetBinContent(ibin + 1)));
1236 static const unsigned nIterations = unsigned(1e5);
1246 double logprob = 0.;
1249 for (
int ichannel = 0; ichannel <
fNChannels; ++ichannel) {
1272 for (
int ibin = 1; ibin <= nbins; ++ibin) {
1275 double expectation =
Expectation(ichannel, ibin, parameters);
1278 double observation = hist->GetBinContent(ibin);
1292 for (
int ichannel = 0; ichannel <
fNChannels; ++ichannel) {
1315 if (!hist_uncbandexp)
1319 int nbins = hist_data->GetNbinsX();
1322 for (
int ibin = 1; ibin <= nbins; ++ibin) {
1328 hist_uncbandexp->Fill(hist_data->GetBinCenter(ibin), expectation);