BAT  0.9.4
The Bayesian analysis toolkit
 All Classes Namespaces Functions Variables Enumerations
BCMTF.cxx
1 /*
2  * Copyright (C) 2007-2014, the BAT core developer team
3  * All rights reserved.
4  *
5  * For the licensing terms see doc/COPYING.
6  * For documentation see http://mpp.mpg.de/bat
7  */
8 
9 // ---------------------------------------------------------
10 
11 #include <iostream>
12 #include <fstream>
13 
14 #include <TCanvas.h>
15 #include <THStack.h>
16 #include <TH1D.h>
17 #include <TH2D.h>
18 #include <TAxis.h>
19 #include <TF1.h>
20 #include <TMath.h>
21 #include <TGraphAsymmErrors.h>
22 
23 #include "../../BAT/BCMath.h"
24 #include "../../BAT/BCLog.h"
25 
26 #include "BCMTFChannel.h"
27 #include "BCMTFProcess.h"
28 #include "BCMTFTemplate.h"
29 #include "BCMTFSystematic.h"
30 #include "BCMTFSystematicVariation.h"
31 
32 #include "BCMTF.h"
33 
34 // ---------------------------------------------------------
36  : BCModel("Multi-template Fitter")
37  , fNChannels(0)
38  , fNProcesses(0)
39  , fNSystematics(0)
40  , fFlagEfficiencyConstraint(false)
41 {}
42 
43 // ---------------------------------------------------------
44 BCMTF::BCMTF(const char * name)
45  : BCModel(name)
46  , fNChannels(0)
47  , fNProcesses(0)
48  , fNSystematics(0)
49  , fFlagEfficiencyConstraint(false)
50 {}
51 
52 // ---------------------------------------------------------
54 // default destructor
55 {
56  for (int i = 0; i < fNChannels; ++i)
57  delete fChannelContainer.at(i);
58 }
59 
60 // ---------------------------------------------------------
61 int BCMTF::GetChannelIndex(const char * name)
62 {
63  // loop over all channels and compare names
64  for (int i = 0; i < fNChannels; ++i) {
65  // get channel
66  BCMTFChannel * channel = GetChannel(i);
67 
68  // compare names
69  if (!channel->GetName().compare(name))
70  return i;
71  }
72 
73  // if channel does not exist, return -1
74  return -1;
75 }
76 
77 // ---------------------------------------------------------
78 int BCMTF::GetProcessIndex(const char * name)
79 {
80  // loop over all processs and compare names
81  for (int i = 0; i < fNProcesses; ++i) {
82  // get process
83  BCMTFProcess * process = GetProcess(i);
84 
85  // compare names
86  if (!process->GetName().compare(name))
87  return i;
88  }
89 
90  // if process does not exist, return -1
91  return -1;
92 }
93 
94 // ---------------------------------------------------------
95 int BCMTF::GetSystematicIndex(const char * name)
96 {
97  // loop over all systematics and compare names
98  for (int i = 0; i < fNSystematics; ++i) {
99  // get systematic
100  BCMTFSystematic * systematic = GetSystematic(i);
101 
102  // compare names
103  if (!systematic->GetName().compare(name))
104  return i;
105  }
106 
107  // if process does not exist, return -1
108  return -1;
109 }
110 
111 // ---------------------------------------------------------
112 int BCMTF::SetTemplate(const char * channelname, const char * processname, TH1D hist, double efficiency, double norm)
113 {
114  // get channel index
115  int channelindex = GetChannelIndex(channelname);
116 
117  // check if channel exists
118  if (channelindex < 0) {
119  BCLog::OutWarning("BCMultitemplateFitter::SetTemplate() : Channel does not exist.");
120  return -1;
121  }
122 
123  // get process index
124  int processindex = GetProcessIndex(processname);
125 
126  // check if process exists
127  if (processindex < 0) {
128  BCLog::OutWarning("BCMultitemplateFitter::SetTemplate() : Process does not exist.");
129  return -1;
130  }
131 
132  // get channel
133  BCMTFChannel * channel = GetChannel(channelindex);
134 
135  // get template
136  BCMTFTemplate * bctemplate = channel->GetTemplate(processindex);
137 
138  // remove statistics box
139  hist.SetStats(kFALSE);
140 
141  int color = GetProcess(processindex)->GetHistogramColor();
142  if (color < 0)
143  color = 2 + processindex;
144  int fillstyle = GetProcess(processindex)->GetHistogramFillStyle();
145  if (fillstyle < 0)
146  fillstyle = 1001;
147  int linestyle = GetProcess(processindex)->GetHistogramLineStyle();
148  if (linestyle < 0)
149  linestyle = 1;
150 
151  // set color and fill style
152  hist.SetFillColor(color);
153  hist.SetFillStyle(fillstyle);
154  hist.SetLineStyle(linestyle);
155 
156  // create new histogram
157  TH1D * temphist = new TH1D(hist);
158 
159  // set histogram
160  bctemplate->SetHistogram(temphist, norm);
161 
162  // set efficiency
163  bctemplate->SetEfficiency(efficiency);
164 
165  // no error
166  return 1;
167 }
168 
169 // ---------------------------------------------------------
170 int BCMTF::SetTemplate(const char * channelname, const char * processname, std::vector<TF1 *> * funccont, int nbins, double efficiency)
171 {
172  // get channel index
173  int channelindex = GetChannelIndex(channelname);
174 
175  // check if channel exists
176  if (channelindex < 0) {
177  BCLog::OutWarning("BCMultitemplateFitter::SetTemplate() : Channel does not exist.");
178  return -1;
179  }
180 
181  // get process index
182  int processindex = GetProcessIndex(processname);
183 
184  // check if process exists
185  if (processindex < 0) {
186  BCLog::OutWarning("BCMultitemplateFitter::SetTemplate() : Process does not exist.");
187  return -1;
188  }
189 
190  // get channel
191  BCMTFChannel * channel = GetChannel(channelindex);
192 
193  // get template
194  BCMTFTemplate * bctemplate = channel->GetTemplate(processindex);
195 
196  // set histogram
197  bctemplate->SetFunctionContainer(funccont, nbins);
198 
199  // set efficiency
200  bctemplate->SetEfficiency(efficiency);
201 
202  // no error
203  return 1;
204 }
205 
206 // ---------------------------------------------------------
207 int BCMTF::SetData(const char * channelname, TH1D hist, double minimum, double maximum)
208 {
209  int channelindex = GetChannelIndex(channelname);
210 
211  // check if channel exists
212  if (channelindex < 0) {
213  BCLog::OutWarning("BCMultitemplateFitter::SetTemplate() : Channel does not exist.");
214  return -1;
215  }
216 
217  // get channel
218  BCMTFChannel * channel = GetChannel(channelindex);
219 
220  // get template
221  BCMTFTemplate * data = channel->GetData();
222 
223  // remove statistics box
224  hist.SetStats(kFALSE);
225 
226  // set marker
227  hist.SetMarkerStyle(20);
228  hist.SetMarkerSize(1.1);
229 
230  // set divisions
231  hist.SetNdivisions(509);
232 
233  // remove old data set if it exists
234  if (data->GetHistogram()) {
235  delete data->GetHistogram();
236  data->SetHistogram(0);
237  }
238 
239  // remove old uncertainty histograms if they exist
240  if (channel->GetHistUncertaintyBandExpectation()) {
241  delete channel->GetHistUncertaintyBandExpectation();
243  }
244  if (channel->GetHistUncertaintyBandPoisson()) {
245  delete channel->GetHistUncertaintyBandPoisson();
246  channel->SetHistUncertaintyBandPoisson(0);
247  }
248 
249  // create new histograms for uncertainty bands
250  // double minimum = floor(TMath::Max(0., hist.GetMinimum() - 7.*sqrt(hist.GetMinimum())));
251  if (minimum==-1)
252  minimum = 0;
253  if (maximum==-1)
254  maximum = ceil(hist.GetMaximum() + 5.*sqrt(hist.GetMaximum()));
255 
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);
259  }
260 
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);
264 
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);
268 
269  // set histograms
270  data->SetHistogram(new TH1D(hist), hist.Integral());
271  channel->SetHistUncertaintyBandExpectation(hist_uncbandexp);
272  channel->SetHistUncertaintyBandPoisson(hist_uncbandpoisson);
273 
274  // set y-range for printing
275  channel->SetRangeY(minimum, maximum);
276 
277  // no error
278  return 1;
279 }
280 
281 // ---------------------------------------------------------
282 int BCMTF::AddChannel(const char * name)
283 {
284  // check if channel exists
285  for (int i = 0; i < fNChannels; ++i) {
286  // compare names
287  if (GetChannelIndex(name) >= 0) {
288  BCLog::OutWarning("BCMultitemplateFitter::AddChannel() : Channel with this name exists already.");
289  return -1;
290  }
291  }
292 
293  // create new channel
294  BCMTFChannel * channel = new BCMTFChannel(name);
295 
296  // create new data
297  BCMTFTemplate * bctemplate = new BCMTFTemplate(channel->GetName().c_str(), "data");
298 
299  // add data
300  channel->SetData(bctemplate);
301 
302  // add process templates
303  for (int i = 0; i < fNProcesses; ++i) {
304  // get process
305  BCMTFProcess * process = GetProcess(i);
306 
307  // create new template
308  BCMTFTemplate * bctemplate = new BCMTFTemplate(name, process->GetName().c_str());
309 
310  // add template
311  channel->AddTemplate(bctemplate);
312  }
313 
314  // loop over all systematics
315  for (int i = 0; i < fNSystematics; ++i) {
316  // get systematic
317  BCMTFSystematic * systematic = GetSystematic(i);
318 
319  // create new systematic variation
320  BCMTFSystematicVariation * variation = new BCMTFSystematicVariation(name, systematic->GetName().c_str(), fNProcesses);
321 
322  // add systematic variation
323  channel->AddSystematicVariation(variation);
324  }
325 
326  // add channel
327  fChannelContainer.push_back(channel);
328 
329  // increase number of channels
330  fNChannels++;
331 
332  // no error
333  return 1;
334 }
335 
336 // ---------------------------------------------------------
337 int BCMTF::AddProcess(const char * name, double nmin, double nmax, int color, int fillstyle, int linestyle)
338 {
339  // check if process exists
340  for (int i = 0; i < fNProcesses; ++i) {
341  // compare names
342  if (GetProcessIndex(name) >= 0) {
343  BCLog::OutWarning("BCMultitemplateFitter::AddProcess() : Process with this name exists already.");
344  return -1;
345  }
346  }
347 
348  // create new process
349  BCMTFProcess * process = new BCMTFProcess(name);
350  process->SetHistogramColor(color);
351  process->SetHistogramFillStyle(fillstyle);
352  process->SetHistogramLineStyle(linestyle);
353 
354  // add process
355  fProcessContainer.push_back(process);
356 
357  // add process templates
358  for (int i = 0; i < fNChannels; ++i) {
359  // get channel
360  BCMTFChannel * channel = GetChannel(i);
361 
362  // create new template
363  BCMTFTemplate * bctemplate = new BCMTFTemplate(channel->GetName().c_str(), name);
364 
365  // add template
366  channel->AddTemplate(bctemplate);
367 
368  // loop over all systematic
369  for (int j = 0; j < fNSystematics; ++j) {
370  // get systematic variation
371  BCMTFSystematicVariation * variation = channel->GetSystematicVariation(j);
372 
373  // add histogram
374  variation->AddHistograms(0, 0);
375  }
376  }
377 
378  // increase number of processes
379  fNProcesses++;
380 
381  // add parameter index to container
382  fProcessParIndexContainer.push_back(GetNParameters());
383 
384  // add parameter
385  AddParameter(name, nmin, nmax);
386 
387  // add a functional form for the expectation
388  fExpectationFunctionContainer.push_back(0);
389 
390  // no error
391  return 1;
392 }
393 
394 // ---------------------------------------------------------
395 int BCMTF::AddSystematic(const char * name, double min, double max)
396 {
397  // check if systematic exists
398  for (int i = 0; i < fNSystematics; ++i) {
399  // compare names
400  if (GetSystematicIndex(name) >= 0) {
401  BCLog::OutWarning("BCMultitemplateFitter::AddSystematic() : Systematic with this name exists already.");
402  return -1;
403  }
404  }
405 
406  // create new systematic
407  BCMTFSystematic * systematic = new BCMTFSystematic(name);
408 
409  // add systematic
410  fSystematicContainer.push_back(systematic);
411 
412  // add systematic variations
413  for (int i = 0; i < fNChannels; ++i) {
414  // get channel
415  BCMTFChannel * channel = GetChannel(i);
416 
417  // create new systematic variation
418  BCMTFSystematicVariation * variation = new BCMTFSystematicVariation(channel->GetName().c_str(), name, fNProcesses);
419 
420  // add systematic variation
421  channel->AddSystematicVariation(variation);
422  }
423  // ...
424 
425  // increase number of systematices
426  fNSystematics++;
427 
428  // add parameter index to container
429  fSystematicParIndexContainer.push_back(GetNParameters());
430 
431  // add parameter
432  AddParameter(name, min, max);
433 
434  // add a functional form for the expectation
435  fExpectationFunctionContainer.push_back(0);
436 
437  // no error
438  return 1;
439 }
440 
441 // ---------------------------------------------------------
442 int BCMTF::SetSystematicVariation(const char * channelname, const char * processname, const char * systematicname, double variation_up, double variation_down)
443 {
444 
445  // get channel index
446  int channelindex = GetChannelIndex(channelname);
447 
448  // check if channel exists
449  if (channelindex < 0) {
450  BCLog::OutWarning("BCMultitemplateFitter::SetTemplate() : Channel does not exist.");
451  return -1;
452  }
453 
454  // get process index
455  int processindex = GetProcessIndex(processname);
456 
457  // check if process exists
458  if (processindex < 0) {
459  BCLog::OutWarning("BCMultitemplateFitter::SetTemplate() : Process does not exist.");
460  return -1;
461  }
462 
463  // get systematic index
464  int systematicindex = GetSystematicIndex(systematicname);
465 
466  // check if systematic exists
467  if (systematicindex < 0) {
468  BCLog::OutWarning("BCMultitemplateFitter::SetTemplate() : Systematic does not exist.");
469  return -1;
470  }
471 
472  // get channel
473  BCMTFChannel * channel = GetChannel(channelindex);
474 
475  BCMTFTemplate * bctemplate = channel->GetTemplate(processindex);
476 
477  TH1D * hist_template = bctemplate->GetHistogram();
478 
479  TH1D hist_up = TH1D(*hist_template);
480  TH1D hist_down = TH1D(*hist_template);
481 
482  int nbins = hist_up.GetNbinsX();
483 
484  // loop over all bins
485  for (int ibin = 1; ibin <= nbins; ++ibin) {
486  hist_up.SetBinContent(ibin, variation_up);
487  hist_down.SetBinContent(ibin, variation_down);
488  }
489 
490  // get systematic variation
491  BCMTFSystematicVariation * variation = channel->GetSystematicVariation(systematicindex);
492 
493  // set histogram
494  variation->SetHistograms(processindex, new TH1D(hist_up), new TH1D(hist_down));
495 
496  // no error
497  return 1;
498 }
499 
500 // ---------------------------------------------------------
501 int BCMTF::SetSystematicVariation(const char * channelname, const char * processname, const char * systematicname, TH1D hist_up, TH1D hist_down)
502 {
503  // get channel index
504  int channelindex = GetChannelIndex(channelname);
505 
506  // check if channel exists
507  if (channelindex < 0) {
508  BCLog::OutWarning("BCMultitemplateFitter::SetTemplate() : Channel does not exist.");
509  return -1;
510  }
511 
512  // get process index
513  int processindex = GetProcessIndex(processname);
514 
515  // check if process exists
516  if (processindex < 0) {
517  BCLog::OutWarning("BCMultitemplateFitter::SetTemplate() : Process does not exist.");
518  return -1;
519  }
520 
521  // get systematic index
522  int systematicindex = GetSystematicIndex(systematicname);
523 
524  // check if systematic exists
525  if (systematicindex < 0) {
526  BCLog::OutWarning("BCMultitemplateFitter::SetTemplate() : Systematic does not exist.");
527  return -1;
528  }
529 
530  // get channel
531  BCMTFChannel * channel = GetChannel(channelindex);
532 
533  // get systematic variation
534  BCMTFSystematicVariation * variation = channel->GetSystematicVariation(systematicindex);
535 
536  // set histogram
537  variation->SetHistograms(processindex, new TH1D(hist_up), new TH1D(hist_down));
538 
539  // no error
540  return 1;
541 }
542 
543 // ---------------------------------------------------------
544 int BCMTF::SetSystematicVariation(const char * channelname, const char * processname, const char * systematicname, TH1D hist, TH1D hist_up, TH1D hist_down)
545 {
546  // get number of bins
547  int nbins = hist.GetNbinsX();
548 
549  TH1D * hist_up_rel = new TH1D(hist);
550  TH1D * hist_down_rel = new TH1D(hist);
551 
552  // loop over all bins
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));
556  }
557 
558  // set the systematic variation
559  return SetSystematicVariation(channelname, processname, systematicname, *hist_up_rel, *hist_down_rel);
560 }
561 
562 // ---------------------------------------------------------
563 int BCMTF::PrintSummary(const char * filename)
564 {
565  // open file
566  std::ofstream ofi(filename);
567  ofi.precision(3);
568 
569  // check if file is open
570  if(!ofi.is_open()) {
571  BCLog::OutWarning(Form("BCMultitemplateFitter::PrintSummary() : Could not open file %s", filename));
572  return 0;
573  }
574 
575  ofi
576  << " Multi template fitter summary " << std::endl
577  << " ----------------------------- " << std::endl
578  << std::endl
579  << " Number of channels : " << fNChannels << std::endl
580  << " Number of processes : " << fNProcesses << std::endl
581  << " Number of systematics : " << fNSystematics << std::endl
582  << std::endl;
583 
584  ofi
585  << " Channels :" << std::endl;
586  for (int i = 0; i < GetNChannels(); ++i) {
587  ofi
588  << " " << i
589  << " : \"" << GetChannel(i)->GetName().c_str() << "\""
590  << std::endl;
591  }
592  ofi
593  << std::endl;
594 
595  ofi
596  << " Processes :" << std::endl;
597  for (int i = 0; i < GetNProcesses(); ++i) {
598  ofi
599  << " " << i
600  << " : \"" << GetProcess(i)->GetName().c_str() << "\""
601  << " (par index " << GetParIndexProcess(i) << ")"
602  << std::endl;
603  }
604  ofi
605  << std::endl;
606 
607  ofi
608  << " Systematics :" << std::endl;
609  for (int i = 0; i < GetNSystematics(); ++i) {
610  ofi
611  << " " << i
612  << " : \"" << GetSystematic(i)->GetName().c_str() << "\""
613  << " (par index " << GetParIndexSystematic(i) << ")"
614  << std::endl;
615  }
616  ofi
617  << std::endl;
618  if (GetNSystematics() == 0)
619  ofi
620  << " - none - " << std::endl;
621 
622  ofi
623  << " Goodness-of-fit: " << std::endl;
624  for (int i = 0; i < GetNChannels(); ++i) {
625  ofi
626  << " i : \"" << GetChannel(i)->GetName().c_str() << "\" : chi2 = "
627  << CalculateChi2( i, GetBestFitParameters() )
628  << std::endl;
629  }
630  ofi
631  << std::endl;
632 
633 
634  // close file
635  ofi.close();
636 
637  // no error
638  return 1;
639 }
640 
641 // ---------------------------------------------------------
642 double BCMTF::Expectation(int channelindex, int binindex, const std::vector<double> & parameters)
643 {
644  double expectation = 0.;
645 
646  // loop over all processes
647  for (int i = 0; i < fNProcesses; ++i) {
648  // get efficiency
649  double efficiency = Efficiency(channelindex, i, binindex, parameters);
650 
651  // get probability
652  double probability = Probability(channelindex, i, binindex, parameters);
653 
654  // get parameter index
655  int parindex = fProcessParIndexContainer[i];
656 
657  // add to expectation
658  expectation += ExpectationFunction(parindex, channelindex, i, parameters)
659  * efficiency
660  * probability;
661  }
662 
663  // check if expectation is positive
664  if (expectation < 0)
665  expectation = 0.;
666 
667  return expectation;
668 }
669 
670 // ---------------------------------------------------------
671 double BCMTF::ExpectationFunction(int parindex, int channelindex, int processindex, const std::vector<double> & parameters)
672 {
673  // get function container
674  std::vector<TF1 *> * funccont = fChannelContainer[channelindex]->GetTemplate(processindex)->GetFunctionContainer();
675 
676  if (funccont->size()>0)
677  return 1.;
678 
679  else if (!fExpectationFunctionContainer[parindex])
680  return parameters[parindex];
681 
682  else {
683  TF1 * func = fExpectationFunctionContainer[parindex];
684  return func->Eval(parameters[parindex]);
685  }
686 }
687 
688 // ---------------------------------------------------------
689 double BCMTF::Efficiency(int channelindex, int processindex, int binindex, const std::vector<double> & parameters)
690 {
691  // get channel
692  BCMTFChannel * channel = fChannelContainer[channelindex];
693 
694  double efficiency = channel->GetTemplate(processindex)->GetEfficiency();
695 
696  double defficiency = 1.;
697 
698  // loop over all systematics
699  for (int i = 0; i < fNSystematics; ++i) {
700  if (!(fSystematicContainer[i]->GetFlagSystematicActive()))
701  continue;
702 
703  // get parameter index
704  int parindex = fSystematicParIndexContainer[i];
705 
706  // get histogram
707  TH1D * hist = 0;
708 
709  if (parameters[parindex] > 0)
710  hist = channel->GetSystematicVariation(i)->GetHistogramUp(processindex);
711  else
712  hist = channel->GetSystematicVariation(i)->GetHistogramDown(processindex);
713 
714  // check if histogram exists
715  if (!hist)
716  continue;
717 
718  // multiply efficiency
719  defficiency += parameters[parindex] * hist->GetBinContent(binindex);
720  }
721 
722  // calculate efficiency
723  efficiency *= defficiency;
724 
725  // make sure efficiency is between 0 and 1
726  if (fFlagEfficiencyConstraint) {
727  if (efficiency < 0.)
728  efficiency = 0.;
729  if (efficiency > 1.)
730  efficiency = 1.;
731  }
732 
733  return efficiency;
734 }
735 
736 // ---------------------------------------------------------
737 double BCMTF::Probability(int channelindex, int processindex, int binindex, const std::vector<double> & parameters)
738 {
739  // get histogram
740  TH1D * hist = fChannelContainer[channelindex]->GetTemplate(processindex)->GetHistogram();
741 
742  // get function container
743  std::vector<TF1 *> * funccont = fChannelContainer[channelindex]->GetTemplate(processindex)->GetFunctionContainer();
744 
745  // this needs to be fast
746  if (!hist && !(funccont->size()>0))
747  return 0.;
748 
749  if (hist)
750  return hist->GetBinContent(binindex);
751  else {
752  int parindex = fProcessParIndexContainer[processindex];
753  return funccont->at(binindex-1)->Eval(parameters[parindex]);
754  }
755 }
756 
757 // ---------------------------------------------------------
758 int BCMTF::PrintStack(const char * channelname, const std::vector<double> & parameters, const char * filename, const char * options)
759 {
760  int index = GetChannelIndex(channelname);
761 
762  return PrintStack(index, parameters, filename, options);
763 }
764 
765 // ---------------------------------------------------------
766 int BCMTF::PrintStack(int channelindex, const std::vector<double> & parameters, const char * filename, const char * options)
767 {
768  // todo:
769  // - add difference/ratio/significance plot below
770  // - check for b0/1 if the mcmc was run
771 
772  // check if parameters are filled
773  if (!parameters.size())
774  return -1;
775 
776  // check options
777  bool flag_logx = false; // plot x-axis in log-scale
778  bool flag_logy = false; // plot y-axis in log-scale
779  bool flag_bw = false; // plot in black and white
780 
781  bool flag_sum = false; // plot sum of all templates
782  bool flag_stack = false; // plot stack of templates
783 
784  bool flag_e0 = false; // do not draw error bars on data
785  bool flag_e1 = false; // draw sqrt(N) error bars on data
786 
787  bool flag_b0 = false; // draw an error band on the expectation
788  bool flag_b1 = false; // draw an error band on the number of events
789 
790  if (std::string(options).find("logx") < std::string(options).size())
791  flag_logx = true;
792 
793  if (std::string(options).find("logy") < std::string(options).size())
794  flag_logy = true;
795 
796  if (std::string(options).find("bw") < std::string(options).size())
797  flag_bw = true;
798 
799  if (std::string(options).find("sum") < std::string(options).size())
800  flag_sum = true;
801 
802  if (std::string(options).find("stack") < std::string(options).size())
803  flag_stack = true;
804 
805  if (std::string(options).find("e0") < std::string(options).size())
806  flag_e0 = true;
807 
808  if (std::string(options).find("e1") < std::string(options).size())
809  flag_e1 = true;
810 
811  if (std::string(options).find("b0") < std::string(options).size())
812  flag_b0 = true;
813 
814  if (std::string(options).find("b1") < std::string(options).size())
815  flag_b1 = true;
816 
817  if (!flag_e0)
818  flag_e1=true;
819 
820  // check if MCMC ran
821  if (!(GetMarginalizationMethod() == BCIntegrate::kMargMetropolis)) {
822  flag_b0 = false;
823  flag_b1 = false;
824  BCLog::OutWarning("BCMTF::PrintStack : Did not run MCMC. Error bands are not available.");
825  }
826 
827  // get channel
828  BCMTFChannel * channel = GetChannel(channelindex);
829 
830  // create canvas
831  TCanvas * c1 = new TCanvas();
832  c1->cd();
833 
834  // set log or linear scale
835  if (flag_logx)
836  c1->SetLogx();
837 
838  if (flag_logy)
839  c1->SetLogy();
840 
841  // get data histogram
842  TH1D* hist_data = channel->GetData()->GetHistogram();
843 
844  // get number of bins
845  int nbins = hist_data->GetNbinsX();
846 
847  // define sum of templates
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);
852 
853  // define error band
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);
860 
861  TGraphAsymmErrors * graph_error_exp = new TGraphAsymmErrors(nbins);
862  // graph_error_exp->SetLineWidth(2);
863  graph_error_exp->SetMarkerStyle(0);
864  graph_error_exp->SetFillColor(kBlack);
865  graph_error_exp->SetFillStyle(3005);
866 
867  // get histogram for uncertainty band
868  TH2D* hist_uncbandexp = channel->GetHistUncertaintyBandExpectation();
869 
870  // fill error band
871  if (flag_b0) {
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());
876  double quantiles[3];
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]));
883  delete proj;
884  }
885  }
886 
887  // create stack
888  THStack * stack = new THStack("", "");
889 
890  // create a container of temporary histograms
891  std::vector<TH1D *> histcontainer;
892 
893  // get number of templates
894  unsigned int ntemplates = GetNProcesses();
895 
896  // loop over all templates
897  for (unsigned int i = 0; i < ntemplates; ++i) {
898 
899  // get histogram
900  TH1D * temphist = channel->GetTemplate(i)->GetHistogram();
901 
902  // get function container
903  std::vector<TF1 *> * funccont = channel->GetTemplate(i)->GetFunctionContainer();
904 
905  // create new histogram
906  TH1D * hist(0);
907 
908  if (temphist)
909  hist = new TH1D( *(temphist) );
910  else if (funccont)
911  hist = new TH1D( *(channel->GetData()->GetHistogram()));
912  else
913  continue;
914 
915  // set histogram style
916  int color = GetProcess(i)->GetHistogramColor();
917  if (color < 0)
918  color = 2 + i;
919  int fillstyle = GetProcess(i)->GetHistogramFillStyle();
920  if (fillstyle < 0)
921  fillstyle = 1001;
922  int linestyle = GetProcess(i)->GetHistogramLineStyle();
923  if (linestyle < 0)
924  linestyle = 1;
925 
926  // set color and fill style
927  hist->SetFillColor(color);
928  hist->SetFillStyle(fillstyle);
929  hist->SetLineStyle(linestyle);
930 
931  if (flag_bw) {
932  hist->SetFillColor(0);
933  }
934 
935  // scale histogram
936  for (int ibin = 1; ibin <= nbins; ++ibin) {
937 
938  // get efficiency
939  double efficiency = Efficiency(channelindex, i, ibin, parameters);
940 
941  // get probability
942  double probability = Probability(channelindex, i, ibin, parameters);
943 
944  // get parameter index
945  int parindex = GetParIndexProcess(i);
946 
947  // add to expectation
948  double expectation = parameters[parindex] * efficiency * probability;
949 
950  // set bin content
951  hist->SetBinContent(ibin, expectation);
952 
953  // add bin content
954  hist_sum->SetBinContent(ibin, hist_sum->GetBinContent(ibin) + expectation);
955  }
956 
957  // add histogram to container (for memory management)
958  histcontainer.push_back(hist);
959 
960  // add histogram to stack
961  stack->Add(hist);
962  }
963 
964  //draw data
965  hist_data->Draw("P0");
966 
967  // define variable for maximum in y-direction
968  double ymax = 0;;
969 
970  if (flag_e1)
971  ymax = hist_data->GetMaximum() + sqrt(hist_data->GetMaximum());
972  else
973  ymax = hist_data->GetMaximum();
974 
975  // set range user
976  hist_data->GetYaxis()->SetRangeUser(channel->GetRangeYMin(), channel->GetRangeYMax());
977 
978  // draw stack
979  if (flag_stack) {
980  stack->Draw("SAMEHIST");
981  if (stack->GetMaximum() > ymax)
982  ymax = stack->GetMaximum();
983  }
984 
985  // draw error band on number of observed events
986  if (flag_b1) {
988  TH1D* hist_temp = channel->CalculateUncertaintyBandPoisson(0.001, 0.999, kRed);
989  hist_temp->Draw("SAMEE2");
990  channel->CalculateUncertaintyBandPoisson(0.023, 0.977, kOrange)->Draw("SAMEE2");
991  channel->CalculateUncertaintyBandPoisson(0.159, 0.841, kGreen)->Draw("SAMEE2");
992 
993  // get bin with maximum
994  int ymaxbin = hist_temp->GetMaximumBin();
995 
996  if (hist_temp->GetBinContent(ymaxbin)+hist_temp->GetBinError(ymaxbin)> ymax)
997  ymax = hist_temp->GetBinContent(ymaxbin)+hist_temp->GetBinError(ymaxbin);
998  }
999 
1000  // draw error band on expectation
1001  if (flag_b0) {
1002  hist_error_band->Draw("SAMEE2");
1003  }
1004 
1005  if (flag_sum)
1006  hist_sum->Draw("SAME");
1007 
1008  //draw data again
1009  if (flag_e0)
1010  hist_data->Draw("SAMEP0");
1011 
1012  if (flag_e1)
1013  hist_data->Draw("SAMEP0E");
1014 
1015  hist_data->GetYaxis()->SetRangeUser(0., 1.1* ymax);
1016 
1017  // redraw the axes
1018  gPad->RedrawAxis();
1019 
1020  // print
1021  c1->Print(filename);
1022 
1023  // free memory
1024  for (unsigned int i = 0; i < histcontainer.size(); ++i) {
1025  TH1D * hist = histcontainer.at(i);
1026  delete hist;
1027  }
1028  delete stack;
1029  delete c1;
1030  delete graph_error_exp;
1031  delete hist_error_band;
1032  delete hist_sum;
1033 
1034  // no error
1035  return 1;
1036 }
1037 
1038 // ---------------------------------------------------------
1039 double BCMTF::CalculateChi2(int channelindex, const std::vector<double> & parameters)
1040 {
1041  if (parameters.size() == 0)
1042  return -1;
1043 
1044  double chi2 = 0;
1045 
1046  // get channel
1047  BCMTFChannel * channel = GetChannel(channelindex);
1048 
1049  // get data
1050  BCMTFTemplate * data = channel->GetData();
1051 
1052  // get histogram
1053  TH1D * hist = data->GetHistogram();
1054 
1055  // check if histogram exists
1056  if (hist) {
1057  // get number of bins in data
1058  int nbins = hist->GetNbinsX();
1059 
1060  // loop over all bins
1061  for (int ibin = 1; ibin <= nbins; ++ibin) {
1062  // get expectation value
1063  double expectation = Expectation(channelindex, ibin, parameters);
1064 
1065  // get observation
1066  double observation = hist->GetBinContent(ibin);
1067 
1068  // add Poisson term
1069  chi2 += (expectation - observation) * (expectation - observation) / expectation;
1070  }
1071  }
1072 
1073  // return chi2;
1074  return chi2;
1075 }
1076 
1077 // ---------------------------------------------------------
1078 double BCMTF::CalculateChi2(const std::vector<double> & parameters)
1079 {
1080  if (parameters.size() == 0)
1081  return -1;
1082 
1083  double chi2 = 0;
1084 
1085  // get number of channels
1086  int nchannels = GetNChannels();
1087 
1088  // loop over all channels
1089  for (int i = 0; i < nchannels; ++i) {
1090  chi2 += CalculateChi2(i, parameters);
1091  }
1092 
1093  // return chi2
1094  return chi2;
1095 }
1096 
1097 // ---------------------------------------------------------
1098 double BCMTF::CalculateCash(int channelindex, const std::vector<double> & parameters)
1099 {
1100  if (parameters.size() == 0)
1101  return -1;
1102 
1103  double cash = 0;
1104 
1105  // get channel
1106  BCMTFChannel * channel = GetChannel(channelindex);
1107 
1108  // get data
1109  BCMTFTemplate * data = channel->GetData();
1110 
1111  // get histogram
1112  TH1D * hist = data->GetHistogram();
1113 
1114  // check if histogram exists
1115  if (hist) {
1116  // get number of bins in data
1117  int nbins = hist->GetNbinsX();
1118 
1119  // loop over all bins
1120  for (int ibin = 1; ibin <= nbins; ++ibin) {
1121  // get expectation value
1122  double expectation = Expectation(channelindex, ibin, parameters);
1123 
1124  // get observation
1125  double observation = hist->GetBinContent(ibin);
1126 
1127  // calculate Cash statistic
1128  cash += 2. * (expectation - observation);
1129 
1130  // check negative log
1131  if (observation > 0)
1132  cash += 2. * observation * log (observation/expectation);
1133  }
1134  }
1135 
1136  // return cash;
1137  return cash;
1138 
1139 }
1140 
1141 // ---------------------------------------------------------
1142 double BCMTF::CalculateCash(const std::vector<double> & parameters)
1143 {
1144  if (parameters.size() == 0)
1145  return -1;
1146 
1147  double cash = 0;
1148 
1149  // get number of channels
1150  int nchannels = GetNChannels();
1151 
1152  // loop over all channels
1153  for (int i = 0; i < nchannels; ++i) {
1154  cash += CalculateCash(i, parameters);
1155  }
1156 
1157  // return cash
1158  return cash;
1159 }
1160 
1161 // ---------------------------------------------------------
1162 double BCMTF::CalculatePValue(int channelindex, const std::vector<double> & parameters)
1163 {
1164  // get channel
1165  BCMTFChannel * channel = GetChannel(channelindex);
1166 
1167  // get data histogram
1168  TH1D * hist = channel->GetData()->GetHistogram();
1169 
1170  // check if histogram exists
1171  if (!hist) {
1172  return -1;
1173  }
1174 
1175  // get number of bins in data
1176  int nbins = hist->GetNbinsX();
1177 
1178  // copy observed and expected values
1179  std::vector<unsigned> observation(nbins);
1180  std::vector<double> expectation(nbins);
1181 
1182  // loop over all bins
1183  for (int ibin = 0; ibin < nbins; ++ibin) {
1184  // get expectation value
1185  expectation[ibin] = Expectation(channelindex, ibin + 1, parameters);
1186 
1187  // get observation
1188  observation[ibin]= unsigned(hist->GetBinContent(ibin + 1));
1189  }
1190 
1191  // create pseudo experiments
1192  static const unsigned nIterations = unsigned (1e5);
1193  return BCMath::FastPValue(observation, expectation, nIterations, fRandom->GetSeed());
1194 }
1195 
1196 // ---------------------------------------------------------
1197 double BCMTF::CalculatePValue(const std::vector<double> & parameters)
1198 {
1199 
1200  // copy observed and expected values
1201  std::vector<unsigned> observation;
1202  std::vector<double> expectation;
1203 
1204  // loop over all channels
1205  for (int ichannel = 0; ichannel < fNChannels; ++ichannel) {
1206 
1207  // get channel
1208  BCMTFChannel * channel = fChannelContainer[ichannel];
1209 
1210  // check if channel is active
1211  if (!(channel->GetFlagChannelActive()))
1212  continue;
1213 
1214  // get data histogram
1215  TH1D * hist = channel->GetData()->GetHistogram();
1216 
1217  // check if histogram exists
1218  if (!hist) {
1219  return -1;
1220  }
1221 
1222  // get number of bins in data
1223  int nbins = hist->GetNbinsX();
1224 
1225  // loop over all bins
1226  for (int ibin = 0; ibin < nbins; ++ibin) {
1227  // get expectation value
1228  expectation.push_back(Expectation(ichannel, ibin + 1, parameters));
1229 
1230  // get observation
1231  observation.push_back(unsigned(hist->GetBinContent(ibin + 1)));
1232  }
1233  }
1234 
1235  // create pseudo experiments
1236  static const unsigned nIterations = unsigned(1e5);
1237  fPValue = BCMath::FastPValue(observation, expectation, nIterations, fRandom->GetSeed());
1238  fPValueNDoF = BCMath::CorrectPValue(fPValue, parameters.size(), observation.size());
1239 
1240  return fPValue;
1241 }
1242 
1243 // ---------------------------------------------------------
1244 double BCMTF::LogLikelihood(const std::vector<double> & parameters)
1245 {
1246  double logprob = 0.;
1247 
1248  // loop over all channels
1249  for (int ichannel = 0; ichannel < fNChannels; ++ichannel) {
1250 
1251  // get channel
1252  BCMTFChannel * channel = fChannelContainer[ichannel];
1253 
1254  // check if channel is active
1255  if (!(channel->GetFlagChannelActive()))
1256  continue;
1257 
1258  // get data
1259  BCMTFTemplate * data = channel->GetData();
1260 
1261  // get histogram
1262  TH1D * hist = data->GetHistogram();
1263 
1264  // check if histogram exists
1265  if (!hist)
1266  continue;
1267 
1268  // get number of bins in data
1269  int nbins = data->GetNBins();
1270 
1271  // loop over all bins
1272  for (int ibin = 1; ibin <= nbins; ++ibin) {
1273 
1274  // get expectation value
1275  double expectation = Expectation(ichannel, ibin, parameters);
1276 
1277  // get observation
1278  double observation = hist->GetBinContent(ibin);
1279 
1280  // add Poisson term
1281  logprob += BCMath::LogPoisson(observation, expectation);
1282  }
1283  }
1284 
1285  return logprob;
1286 }
1287 
1288 // ---------------------------------------------------------
1290 {
1291  // loop over all channels
1292  for (int ichannel = 0; ichannel < fNChannels; ++ichannel) {
1293 
1294  // get channel
1295  BCMTFChannel * channel = fChannelContainer[ichannel];
1296 
1297  // check if channel is active
1298  if (!(channel->GetFlagChannelActive()))
1299  continue;
1300 
1301  // get data
1302  BCMTFTemplate * data = channel->GetData();
1303 
1304  // get histogram
1305  TH1D * hist_data = data->GetHistogram();
1306 
1307  // check if histogram exists
1308  if (!hist_data)
1309  continue;
1310 
1311  // get histogram for uncertainty band
1312  TH2D* hist_uncbandexp = channel->GetHistUncertaintyBandExpectation();
1313 
1314  // check if histogram exists
1315  if (!hist_uncbandexp)
1316  continue;
1317 
1318  // get number of bins in data
1319  int nbins = hist_data->GetNbinsX();
1320 
1321  // loop over all bins
1322  for (int ibin = 1; ibin <= nbins; ++ibin) {
1323 
1324  // get expectation value
1325  double expectation = Expectation(ichannel, ibin, fMCMCx);
1326 
1327  // fill uncertainty band on expectation
1328  hist_uncbandexp->Fill(hist_data->GetBinCenter(ibin), expectation);
1329  }
1330  }
1331 
1332 }
1333 
1334 // ---------------------------------------------------------
int SetSystematicVariation(const char *channelname, const char *processname, const char *systematicname, double variation_up, double variation_down)
Definition: BCMTF.cxx:442
int GetHistogramLineStyle()
Definition: BCMTFProcess.h:64
int AddChannel(const char *name)
Definition: BCMTF.cxx:282
void SetFunctionContainer(std::vector< TF1 * > *funccont, int nbins)
int SetData(const char *channelname, TH1D hist, double minimum=-1, double maximum=-1)
Definition: BCMTF.cxx:207
TH1D * CalculateUncertaintyBandPoisson(double minimum, double maximumm, int color)
A class describing a template.
Definition: BCMTFTemplate.h:32
double CalculatePValue(int channelindex, const std::vector< double > &parameters)
Definition: BCMTF.cxx:1162
void AddTemplate(BCMTFTemplate *bctemplate)
Definition: BCMTFChannel.h:156
bool GetFlagChannelActive()
Definition: BCMTFChannel.h:80
void SetHistUncertaintyBandExpectation(TH2D *hist)
Definition: BCMTFChannel.h:126
int GetNChannels()
Definition: BCMTF.h:65
double FastPValue(const std::vector< unsigned > &observed, const std::vector< double > &expected, unsigned nIterations, unsigned seed)
Definition: BCMath.cxx:690
int SetTemplate(const char *channelname, const char *processname, TH1D hist, double efficiency=1., double norm=1.)
Definition: BCMTF.cxx:112
int GetProcessIndex(const char *name)
Definition: BCMTF.cxx:78
double ExpectationFunction(int parindex, int channelindex, int processindex, const std::vector< double > &parameters)
Definition: BCMTF.cxx:671
double GetEfficiency()
Definition: BCMTFTemplate.h:66
The base class for all user-defined models.
Definition: BCModel.h:50
int AddSystematic(const char *name, double min=-5., double max=5.)
Definition: BCMTF.cxx:395
void SetHistogram(TH1D *hist, double norm=1)
~BCMTF()
Definition: BCMTF.cxx:53
double GetRangeYMin()
Definition: BCMTFChannel.h:98
void AddSystematicVariation(BCMTFSystematicVariation *variation)
Definition: BCMTFChannel.h:162
int GetChannelIndex(const char *name)
Definition: BCMTF.cxx:61
BCMTFTemplate * GetTemplate(int index)
Definition: BCMTFChannel.h:68
void MCMCUserIterationInterface()
Definition: BCMTF.cxx:1289
double CorrectPValue(const double &pvalue, const unsigned &npar, const unsigned &nobservations)
Definition: BCMath.cxx:665
BCMTFSystematicVariation * GetSystematicVariation(int index)
Definition: BCMTFChannel.h:75
double Expectation(int channelindex, int binindex, const std::vector< double > &parameters)
Definition: BCMTF.cxx:642
int GetSystematicIndex(const char *name)
Definition: BCMTF.cxx:95
static int GetHIndex()
Definition: BCLog.h:164
int GetNSystematics()
Definition: BCMTF.h:75
double Efficiency(int channelindex, int processindex, int binindex, const std::vector< double > &parameters)
Definition: BCMTF.cxx:689
A class describing a process.
Definition: BCMTFProcess.h:27
void SetEfficiency(double eff)
void AddHistograms(TH1D *hist_up, TH1D *hist_down)
TH2D * GetHistUncertaintyBandExpectation()
Definition: BCMTFChannel.h:87
void SetRangeY(double min, double max)
Definition: BCMTFChannel.h:145
double Probability(int channelindex, int processindex, int binindex, const std::vector< double > &parameters)
Definition: BCMTF.cxx:737
int PrintStack(int channelindex, const std::vector< double > &parameters, const char *filename="stack.pdf", const char *options="e1b0stack")
Definition: BCMTF.cxx:766
TH2D * GetHistUncertaintyBandPoisson()
Definition: BCMTFChannel.h:93
TH1D * GetHistogram()
Definition: BCMTFTemplate.h:71
double CalculateCash(int channelindex, const std::vector< double > &parameters)
Definition: BCMTF.cxx:1098
std::string GetName()
Definition: BCMTFProcess.h:49
virtual int AddParameter(BCParameter *parameter)
Definition: BCModel.cxx:225
int GetNProcesses()
Definition: BCMTF.h:70
std::string GetName()
Definition: BCMTFChannel.h:56
std::vector< TF1 * > * GetFunctionContainer()
Definition: BCMTFTemplate.h:97
A class describing a physics channel.
Definition: BCMTFChannel.h:33
void SetHistograms(int index, TH1D *hist_up, TH1D *hist_down)
void PrintSummary()
Definition: BCModel.cxx:772
int AddProcess(const char *name, double nmin=0., double nmax=1., int color=-1, int fillstyle=-1, int linestyle=-1)
Definition: BCMTF.cxx:337
double GetRangeYMax()
Definition: BCMTFChannel.h:103
int GetParIndexSystematic(int index)
Definition: BCMTF.h:102
void CalculateHistUncertaintyBandPoisson()
BCMTFTemplate * GetData()
Definition: BCMTFChannel.h:61
BCMTF()
Definition: BCMTF.cxx:35
void SetHistogramColor(int color)
Definition: BCMTFProcess.h:81
BCMTFSystematic * GetSystematic(int index)
Definition: BCMTF.h:120
int GetParIndexProcess(int index)
Definition: BCMTF.h:96
BCMTFChannel * GetChannel(int index)
Definition: BCMTF.h:108
void SetData(BCMTFTemplate *bctemplate)
Definition: BCMTFChannel.h:119
BCMTFProcess * GetProcess(int index)
Definition: BCMTF.h:114
std::string GetName()
double LogPoisson(double x, double par)
Definition: BCMath.cxx:57
int GetHistogramColor()
Definition: BCMTFProcess.h:54
void SetHistogramLineStyle(int style)
Definition: BCMTFProcess.h:93
double fPValue
Definition: BCModel.h:536
int GetHistogramFillStyle()
Definition: BCMTFProcess.h:59
double CalculateChi2(int channelindex, const std::vector< double > &parameters)
Definition: BCMTF.cxx:1039
void SetHistUncertaintyBandPoisson(TH2D *hist)
Definition: BCMTFChannel.h:132
double LogLikelihood(const std::vector< double > &parameters)
Definition: BCMTF.cxx:1244
void SetHistogramFillStyle(int style)
Definition: BCMTFProcess.h:87
A class desribing a systematic uncertainty.
A class describing a systematic variation.