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

BCTemplateFitter.cxx

Go to the documentation of this file.
00001 #include <iostream>
00002 
00003 #include <TROOT.h>
00004 #include <TH2D.h>
00005 #include <THStack.h>
00006 #include <TCanvas.h>
00007 #include <TLegend.h>
00008 #include <TMath.h>
00009 #include <TRandom3.h>
00010 #include <TGraphAsymmErrors.h>
00011 #include <TPostScript.h>
00012 #include <TPad.h>
00013 #include <TLine.h>
00014 #include <TDirectory.h>
00015 
00016 #include <BAT/BCMath.h>
00017 #include <BAT/BCLog.h>
00018 #include <BAT/BCH1D.h>
00019 
00020 #include "BCTemplateFitter.h"
00021 
00022 // ---------------------------------------------------------
00023 BCTemplateFitter::BCTemplateFitter()
00024    : BCModel()
00025    , fFlagFixNorm(false)
00026    , fFlagPhysicalLimits(true)
00027    , fUncertaintyHistogramExp(0)
00028    , fUncertaintyHistogramObsPosterior(0)
00029    , fNorm(-1)
00030    , fNBins(-1)
00031    , fXmin(1.)
00032    , fXmax(0.)
00033    , fPriorNBins(1000)
00034 {
00035 }
00036 
00037 // ---------------------------------------------------------
00038 BCTemplateFitter::BCTemplateFitter(const char * name)
00039    : BCModel(name)
00040    , fFlagFixNorm(false)
00041    , fFlagPhysicalLimits(true)
00042    , fUncertaintyHistogramExp(0)
00043    , fUncertaintyHistogramObsPosterior(0)
00044    , fNorm(-1)
00045    , fNBins(-1)
00046    , fXmin(1.)
00047    , fXmax(0.)
00048    , fPriorNBins(1000)
00049 {
00050 }
00051 
00052 // ---------------------------------------------------------
00053 BCTemplateFitter::~BCTemplateFitter()
00054 {
00055    if (fUncertaintyHistogramExp)
00056       delete fUncertaintyHistogramExp;
00057 
00058    if (fUncertaintyHistogramObsPosterior)
00059       delete fUncertaintyHistogramObsPosterior;
00060 }
00061 
00062 // ---------------------------------------------------------
00063 double BCTemplateFitter::LogLikelihood(std::vector <double> parameters)
00064 {
00065    double logprob = 0.;
00066 
00067    // get number pf templates
00068    int ntemplates = GetNTemplates();
00069 
00070    // get number of sources of systematic uncertainties
00071    int nsyst = GetNSystErrors();
00072 
00073    // loop over bins
00074    for (int ibin = 1; ibin <= fNBins; ++ibin) {
00075       double nexp = 0;
00076       double ndata = fHistData.GetBinContent(ibin);
00077 
00078       // loop over all templates
00079       for (int itemp = 0; itemp < ntemplates; ++itemp) {
00080          int templateindex = fTemplateParIndexContainer.at(itemp);
00081          int effindex = fEffParIndexContainer.at(itemp);
00082 
00083          // get efficiency for the bin
00084          double efficiency = fEffHistogramContainer.at(itemp).GetBinContent(ibin);
00085 
00086          // modify efficiency by uncertainty
00087          double efferr = fEffErrHistogramContainer.at(itemp).GetBinContent(ibin);
00088 
00089          // check efficiency error
00090          if (efferr > 0)
00091             efficiency += parameters.at(effindex) * efferr;
00092 
00093          // loop over sources of systematic uncertainties
00094          for (int isyst = 0; isyst < nsyst; ++isyst) {
00095             // get parameter index
00096             int systindex = fSystErrorParIndexContainer.at(isyst);
00097 
00098             // add efficiency
00099             double deff = fSystErrorHistogramContainer.at(isyst).at(itemp).GetBinContent(ibin);
00100 
00101             if (deff > 0)
00102                efficiency += deff * parameters.at(systindex);
00103          }
00104 
00105          // make sure efficiency is between 0 and 1
00106          if (efficiency < 0.)
00107             efficiency = 0.;
00108          if (efficiency > 1.)
00109             efficiency = 1.;
00110 
00111          // calculate expectation nvalue
00112          nexp += parameters.at(templateindex)
00113                * efficiency
00114                * fTemplateHistogramContainer.at(itemp).GetBinContent(ibin);
00115       }
00116 
00117       // check that expectation is larger or equal to zero
00118       if (nexp < 0) {
00119          BCLog::OutWarning("BCTemplateFitter::LogLikelihood : Expectation value smaller than 0. Force it to be 0.");
00120          nexp = 0;
00121       }
00122 
00123       // add Poisson term
00124       logprob += BCMath::LogPoisson(ndata, nexp);
00125    }
00126 
00127    // return log likelihood
00128    return logprob;
00129 }
00130 
00131 // ---------------------------------------------------------
00132 double BCTemplateFitter::LogAPrioriProbability(std::vector <double> parameters)
00133 {
00134    double logprob = 0.;
00135 
00136    // get number of templates
00137    int ntemplates = GetNTemplates();
00138 
00139    // loop over templates
00140    for (int i = 0; i < ntemplates; ++i) {
00141 
00142       // prior on process contributions
00143       double par = parameters.at(fTemplateParIndexContainer.at(i));
00144       int bin = fPriorContainer.at(i).FindBin(par);
00145       logprob += log( fPriorContainer.at(i).GetBinContent(bin) );
00146 
00147       // prior on efficiences
00148       par = parameters.at(fEffParIndexContainer.at(i));
00149       logprob += BCMath::LogGaus(par, 0.0, 1.0);
00150    }
00151 
00152    // get number of sources of systematic uncertainties
00153    int nsyst = GetNSystErrors();
00154 
00155    // loop over sources of systematic uncertainties
00156    for (int i = 0; i < nsyst; ++i) {
00157       double par = parameters.at(fSystErrorParIndexContainer.at(i));
00158       if (fSystErrorTypeContainer.at(i) == "gauss")
00159          logprob += BCMath::LogGaus(par, 0.0, 1.0);
00160    }
00161 
00162    // constraints
00163    int nconstraints = int(fConstraintSumIndices.size());
00164    if (nconstraints > 0) {
00165 
00166       // loop over constraints
00167       for (int i = 0; i < nconstraints; ++i) {
00168 
00169          // initialize sum
00170          double sum = 0;
00171 
00172          // get number of summands
00173          int nsummands = int( (fConstraintSumIndices.at(i)).size() );
00174 
00175          // loop over summands and add to sum
00176          for (int j = 0; j < nsummands; ++j) {
00177             int index = fConstraintSumIndices.at(i).at(j);
00178             double par = parameters.at(fTemplateParIndexContainer.at(index));
00179             sum += par;
00180          }
00181 
00182          // add to prior
00183          logprob += BCMath::LogGaus(sum, fConstraintSumMean.at(i), fConstraintSumRMS.at(i));
00184       }
00185    }
00186 
00187    return logprob;
00188 }
00189 
00190 // ---------------------------------------------------------
00191 int BCTemplateFitter::SetData(const TH1D& hist)
00192 {
00193    // create histogram
00194    fNBins = hist.GetNbinsX();
00195    fXmin = (hist.GetXaxis())->GetXmin();
00196    fXmax = (hist.GetXaxis())->GetXmax();
00197    fHistData = TH1D("", "", fNBins, fXmin, fXmax);
00198 
00199    // copy histogram content
00200    for (int i = 1; i <= fNBins; ++i)
00201       fHistData.SetBinContent(i, hist.GetBinContent(i));
00202 
00203    // set histogram style
00204    fHistData.SetXTitle((hist.GetXaxis())->GetTitle());
00205    fHistData.SetYTitle((hist.GetYaxis())->GetTitle());
00206    fHistData.SetMarkerStyle(20);
00207    fHistData.SetMarkerSize(1.1);
00208    fHistData.SetStats(kFALSE);
00209 
00210    // calculate norm
00211    fNorm = hist.Integral();
00212 
00213    // no errors
00214    return 1;
00215 }
00216 
00217 // ---------------------------------------------------------
00218 int BCTemplateFitter::AddTemplate(TH1D hist, const char * name, double Nmin, double Nmax)
00219 {
00220    // check if histogram if filled
00221    if (hist.Integral() <= 0.) {
00222       BCLog::OutError("BCTemplateFitter::AddTemplate : Normalization is zero or less than that.");
00223       return 0;
00224    }
00225 
00226    // compare template properties with data
00227    if (CompareHistogramProperties(fHistData, hist) != 1) {
00228       BCLog::OutError("BCTemplateFitter::AddTemplate : Data and template histogram properties are incompatible.");
00229       return 0;
00230    }
00231 
00232    // check if prior makes sense
00233    if (fFlagPhysicalLimits && Nmin < 0)
00234       Nmin = 0;
00235 
00236    if (Nmin > Nmax) {
00237       BCLog::OutError("BCTemplateFitter::AddTemplate : Lower limit exceeds upper limit.");
00238       return 0;
00239    }
00240 
00241    // get number of templates
00242    int ntemplates = int(fTemplateHistogramContainer.size());
00243 
00244    // set histogram color and style
00245    hist.SetFillColor(2 + ntemplates);
00246    hist.SetFillStyle(1001);
00247    hist.SetStats(kFALSE);
00248 
00249    // scale histogram
00250    hist.Scale(1.0 / hist.Integral());
00251 
00252    // check if template is consistent with other templates
00253    if (ntemplates > 0)
00254       if (!CompareHistogramProperties(fTemplateHistogramContainer.at(0), hist)) {
00255          BCLog::OutError("BCTemplateFitter::AddTemplate : Properties of template histogram is not compatible with older template histograms.");
00256          return 0;
00257       }
00258 
00259    // histograms
00260    TH1D histprior = TH1D("", "", fPriorNBins, Nmin, Nmax);
00261    TH1D histsysterror = TH1D("", "", fNBins, fXmin, fXmax);
00262 
00263    // set style
00264    histprior.SetXTitle(name);
00265 
00266    // fill histograms
00267    for (int i = 1; i <= fPriorNBins; ++i)
00268       histprior.SetBinContent(i, 1.);
00269    for (int i = 1; i <= fNBins; ++i)
00270       histsysterror.SetBinContent(i, 0.);
00271 
00272    // get parameter index
00273    int parindex = GetNParameters();
00274    int partemplateindex = GetNTemplates();
00275 
00276    // add a parameter for the expectation value
00277    AddParameter(Form("N_%i", partemplateindex), Nmin, Nmax);
00278 
00279    // get efficiency parameter index
00280    int effindex = GetNParameters();
00281 
00282    // add a parameter for the efficiency
00283    AddParameter(Form("eff_%i", partemplateindex), -5.0, 5.0);
00284 
00285    // add histogram, name and index to containers
00286    fTemplateHistogramContainer.push_back(hist);
00287    fPriorContainer.push_back(histprior);
00288    fTemplateNameContainer.push_back(name);
00289    fTemplateParIndexContainer.push_back(parindex);
00290    fEffParIndexContainer.push_back(effindex);
00291 
00292    // set efficiency histograms to one without uncertainty
00293    fEffHistogramContainer.push_back(TH1D());
00294    fEffErrHistogramContainer.push_back(TH1D());
00295    SetTemplateEfficiency(name, 1., 0.);
00296 
00297    // add systematic uncertainties
00298    for (int i = 0; i < GetNSystErrors(); ++i) {
00299       std::vector <TH1D> histvector = fSystErrorHistogramContainer.at(i);
00300       histvector.push_back(histsysterror);
00301    }
00302 
00303    // successfully added histogram to container
00304    return 1;
00305 }
00306 
00307 // ---------------------------------------------------------
00308 int BCTemplateFitter::SetTemplatePrior(const char * name, TH1D prior)
00309 {
00310    // get index
00311    int parindex = GetIndexTemplate(name);
00312 
00313    // check parameter index
00314    if (parindex < 0) {
00315       BCLog::OutError("BCTemplateFitter::SetTemplatePrior : Did not find parameter.");
00316       return 0;
00317    }
00318 
00319    // check prior
00320    if (prior.Integral() <= 0) {
00321       BCLog::OutError("BCTemplateFitter::SetTemplatePrior : Integral of prior is equal to zero or less than that.");
00322       return 0;
00323    }
00324 
00325    // normalize prior to unity
00326    prior.Scale(1.0/prior.Integral());
00327 
00328    // replace histogram
00329    fPriorContainer[parindex] = prior;
00330 
00331    // no error
00332    return 1;
00333 }
00334 
00335 // ---------------------------------------------------------
00336 int BCTemplateFitter::SetTemplatePrior(const char * name, double mean, double sigma)
00337 {
00338    // get index
00339    int parindex = GetParIndexTemplate(name);
00340 
00341    // check parameter index
00342    if (parindex < 0) {
00343       BCLog::OutError("BCTemplateFitter::SetTemplatePrior : Did not find parameter.");
00344       return 0;
00345    }
00346 
00347    // get parameter
00348    BCParameter * par = this->GetParameter(parindex);
00349 
00350    // create new histogram
00351    TH1D hist("", "", fPriorNBins, par->GetLowerLimit(), par->GetUpperLimit());
00352 
00353    // loop over bins and fill histogram
00354    for (int i = 1; i < fPriorNBins; ++i) {
00355       double x = hist.GetBinCenter(i);
00356       double fx = TMath::Gaus(x, mean, sigma);
00357       hist.SetBinContent(i, fx);
00358    }
00359 
00360    // set template prior
00361    int err = SetTemplatePrior(name, hist);
00362 
00363    // return error code
00364    return err;
00365 }
00366 
00367 // ---------------------------------------------------------
00368 int BCTemplateFitter::AddSystError(const char * errorname, const char * errtype)
00369 {
00370    // define parameter range
00371    double dx = 1.0;
00372 
00373    // check error type
00374    if (std::string(errtype) == std::string("gauss"))
00375       dx = 5.0;
00376    else if (std::string(errtype) == std::string("flat"))
00377       dx = 1.0;
00378    else {
00379       BCLog::OutError("BCTemplateFitter::AddSystError : Unknown error type.");
00380       return 0;
00381    }
00382 
00383    // add a parameter for the expectation value
00384    AddParameter(Form("systerr_%i", GetNSystErrors()), -dx, dx);
00385 
00386    // add name and index to containers
00387    fSystErrorNameContainer.push_back(errorname);
00388    fSystErrorParIndexContainer.push_back(GetNParameters()-1);
00389 
00390    // create histogram
00391    TH1D hist = TH1D("", "", fNBins, fXmin, fXmax);
00392 
00393    // fill histograms
00394    for (int i = 1; i <= fNBins; ++i)
00395       hist.SetBinContent(i, 0.);
00396 
00397    // get number of templates
00398    int n = GetNTemplates();
00399 
00400    // define vector of histograms
00401    std::vector<TH1D> histvector;
00402 
00403    // add histograms
00404    for (int i = 0; i < n; ++i)
00405       histvector.push_back(hist);
00406 
00407    // add histogram vector
00408    fSystErrorHistogramContainer.push_back(histvector);
00409 
00410    // add error type to container
00411    fSystErrorTypeContainer.push_back(std::string(errtype));
00412 
00413    // no error
00414    return 1;
00415 }
00416 
00417 // ---------------------------------------------------------
00418 int BCTemplateFitter::SetTemplateSystError(const char * errorname, const char * templatename, TH1D parerror)
00419 {
00420    // get error index
00421    int errindex = GetIndexSystError(errorname);
00422 
00423    // check parameter index
00424    if (errindex < 0) {
00425       BCLog::OutError("BCTemplateFitter::SetTemplateSystError : Did not find parameter.");
00426       return 0;
00427    }
00428 
00429    // get template index
00430    int tempindex = GetIndexTemplate(templatename);
00431 
00432    // check index
00433    if (tempindex < 0) {
00434       BCLog::OutError("BCTemplateFitter::SetTemplateSystError : Could not find template.");
00435       return 0;
00436    }
00437 
00438    // set style
00439    parerror.SetStats(kFALSE);
00440 
00441    // set histogram
00442    (fSystErrorHistogramContainer.at(errindex))[tempindex] = parerror;
00443 
00444    // no error
00445    return 1;
00446 }
00447 
00448 // ---------------------------------------------------------
00449 int BCTemplateFitter::Initialize()
00450 {
00451    // check data integral
00452    if (fHistData.Integral() <= 0) {
00453       BCLog::OutError("BCTemplateFitter::Initialize : Normalization of data histogram is zero or less than that.");
00454       return 0;
00455    }
00456 
00457    // create histograms for uncertainty determination
00458    double maximum = 1.5 * fHistData.GetMaximum();
00459 
00460    fUncertaintyHistogramExp = new TH2D(
00461          TString::Format("UncertaintyExp_%i", BCLog::GetHIndex()), "",
00462          fHistData.GetNbinsX(), fHistData.GetXaxis()->GetXmin(), fHistData.GetXaxis()->GetXmax(),
00463          100, 0., maximum);
00464 
00465    fUncertaintyHistogramObsPosterior = new TH2D(
00466          TString::Format("UncertaintyObsPosterior_%i", BCLog::GetHIndex()), "",
00467          fHistData.GetNbinsX(), fHistData.GetXaxis()->GetXmin(), fHistData.GetXaxis()->GetXmax(),
00468          int(maximum) + 1, -0.5, double(int(maximum))+0.5);
00469 
00470    // create histogram containing the normalization
00471    double xmin = 0;
00472    double xmax = 0;
00473    int ntemplates = int(fTemplateParIndexContainer.size());
00474 
00475    // calculate the limits on the norm from the sum of all parameter
00476    // limits
00477    for (int i = 0; i < ntemplates; ++i) {
00478       // get parameter index
00479       int parindex = fTemplateParIndexContainer.at(i);
00480       int effindex = fEffParIndexContainer.at(i);
00481 
00482       // get parameter
00483       BCParameter * par = this->GetParameter(parindex);
00484       BCParameter * eff = this->GetParameter(effindex);
00485 
00486       // increate limits
00487       xmin += par->GetLowerLimit() * eff->GetLowerLimit();
00488       xmax += par->GetUpperLimit() * eff->GetUpperLimit();
00489    }
00490 
00491    // create new histogram for norm
00492    fHistNorm = TH1D("", ";N_{norm};dN/dN_{norm}", 100, xmin, xmax);
00493 
00494    // no error
00495    return 1;
00496 }
00497 
00498 // ---------------------------------------------------------
00499 int BCTemplateFitter::CalculateRatio(int index, std::vector<int> indices, double rmin, double rmax)
00500 {
00501    // get number of templates
00502    int ntemplates = int( fTemplateHistogramContainer.size() );
00503 
00504    // check index
00505    if (index < 0 || index >= ntemplates) {
00506       return 0;
00507    }
00508 
00509    // check indices
00510    for (int i = 0; i < int(indices.size()); ++i) {
00511       if (indices.at(i) < 0 || indices.at(i) >= ntemplates) {
00512          return 0;
00513       }
00514    }
00515 
00516    // create temporary vector
00517    std::vector<int> tempvec;
00518    tempvec.push_back(index);
00519    for (int i = 0; i < int(indices.size()); ++i)
00520       tempvec.push_back(indices.at(i));
00521 
00522    // add ratio
00523    fIndicesRatios1D.push_back(tempvec);
00524 
00525    // get number of ratios
00526    int nratios = int(fHistRatios1D.size());
00527 
00528    // create histogram
00529    double fmin = rmin;
00530    double fmax = rmax;
00531    if (fFlagPhysicalLimits) {
00532       fmin = TMath::Max(rmin, 0.0);
00533       fmax = TMath::Min(1.0, rmax);
00534    }
00535 
00536    TH1D hist_ratio1d(TString::Format("ratio %i", nratios), ";r;p(r|data)", 100, fmin, fmax);
00537    fHistRatios1D.push_back(hist_ratio1d);
00538 
00539    // no error
00540    return 1;
00541 }
00542 
00543 // ---------------------------------------------------------
00544 int BCTemplateFitter::CompareHistogramProperties(TH1D hist1, TH1D hist2)
00545 {
00546    // compare number of bins
00547    if (hist1.GetNbinsX() != hist2.GetNbinsX())
00548       return 0;
00549 
00550    // compare minimum x-values
00551    if (hist1.GetXaxis()->GetXmin() != hist2.GetXaxis()->GetXmin())
00552       return 0;
00553 
00554    // compare maximum x-values
00555    if (hist1.GetXaxis()->GetXmax() != hist2.GetXaxis()->GetXmax())
00556       return 0;
00557 
00558    // conclusion: they have the same properties
00559    return 1;
00560 }
00561 
00562 // ---------------------------------------------------------
00563 void BCTemplateFitter::PrintStack(const char * filename, const char * options)
00564 {
00565    int nbins = fHistData.GetNbinsX();
00566    int ntemplates = int( fTemplateHistogramContainer.size() );
00567 
00568    // check options
00569    bool flag_legend = false;
00570    bool flag_error0 = false; // symm. poisson error for data
00571    bool flag_error1 = false; // symm. poisson error for exp.
00572    bool flag_error2 = false; // asymm. poisson error of expectation value
00573    bool flag_error3 = false; // asymm. poisson error of expected no. of events
00574    bool flag_diff   = false; // plot difference between data and expectation below stack plot
00575 
00576    if (std::string(options).find("L") < std::string(options).size())
00577       flag_legend = true;
00578 
00579    if (std::string(options).find("E0") < std::string(options).size())
00580       flag_error0 = true;
00581 
00582    if (std::string(options).find("E1") < std::string(options).size())
00583       flag_error1 = true;
00584 
00585    if (std::string(options).find("E2") < std::string(options).size())
00586       flag_error2 = true;
00587 
00588    if (std::string(options).find("E3") < std::string(options).size())
00589       flag_error3 = true;
00590 
00591    if (std::string(options).find("D") < std::string(options).size())
00592       flag_diff = true;
00593 
00594    // create canvas
00595    TCanvas* c1 = new TCanvas("", "", 700, 700);
00596    c1->cd();
00597    TPad * pad1;
00598    TPad * pad2;
00599 
00600    double fraction_pads = 0.3;
00601 
00602    if(!flag_diff)
00603       fraction_pads=0.0;
00604 
00605    if (flag_diff) {
00606       pad1 = new TPad("pad1", "", 0.0, fraction_pads, 1.0, 1.0);
00607       pad1->SetTopMargin   (0.13/(1.0-fraction_pads));
00608       pad1->SetBottomMargin(0.0);
00609       pad1->SetLeftMargin  (0.15);
00610       pad1->SetRightMargin (0.13);
00611       pad1->SetFillColor(kWhite);
00612       pad2 = new TPad("pad2", "", 0.0, 0.0, 1.0, fraction_pads);
00613       pad2->SetTopMargin   (0.0);
00614       pad2->SetBottomMargin(0.15 / fraction_pads);
00615       pad2->SetLeftMargin  (0.15);
00616       pad2->SetRightMargin (0.13);
00617       pad2->SetFillColor(kWhite);
00618       pad1->Draw();
00619       pad2->Draw();
00620    }
00621    else {
00622       pad1 = new TPad("pad1", "",0.0, 0.0, 1.0, 1.0);
00623       pad1->SetFillColor(kWhite);
00624       pad2 = new TPad();
00625       pad1->Draw();
00626    }
00627 
00628    pad1->cd();
00629 
00630    // set style and draw data
00631    double ymin = 0.01;
00632    double ymax = 1.1 * (fHistData.GetMaximum() + sqrt(fHistData.GetMaximum()));
00633    fHistData.GetYaxis()->SetRangeUser(ymin, ymax);
00634    fHistData.GetXaxis()->SetNdivisions(505);
00635    if (flag_diff) {
00636       fHistData.GetXaxis()->SetLabelSize(fHistData.GetXaxis()->GetLabelSize()/(1.0-fraction_pads));
00637       fHistData.GetXaxis()->SetLabelOffset(fHistData.GetXaxis()->GetLabelOffset()*(1.0-fraction_pads));
00638       fHistData.GetXaxis()->SetTitleSize(fHistData.GetXaxis()->GetTitleSize()/(1.0-fraction_pads));
00639       fHistData.GetXaxis()->SetTitleOffset(fHistData.GetXaxis()->GetTitleOffset()*(1.0-fraction_pads));
00640       fHistData.GetYaxis()->SetLabelSize(fHistData.GetYaxis()->GetLabelSize()/(1.0-fraction_pads));
00641       fHistData.GetYaxis()->SetLabelOffset(fHistData.GetYaxis()->GetLabelOffset()/(fraction_pads));
00642       fHistData.GetYaxis()->SetTitleSize(fHistData.GetYaxis()->GetTitleSize()/(1.0-fraction_pads));
00643       fHistData.GetYaxis()->SetTitleOffset(fHistData.GetYaxis()->GetTitleOffset()*(1.0-fraction_pads));
00644    }
00645    fHistData.Draw("P");
00646 
00647    // create a histogram with the sum of all contributions
00648    TH1D * histsum = (TH1D*) fHistData.Clone("temp");
00649 
00650    // create stack
00651    THStack stack("histostack","");
00652 
00653    // create legends
00654    TLegend* legend1;
00655    TLegend* legend2;
00656 
00657    if (flag_diff)
00658       legend1 = new TLegend(0.15, (0.88-fraction_pads)/(1-fraction_pads), 0.50, 0.99);
00659    else
00660       legend1 = new TLegend(0.15, 0.88, 0.50, 0.99);
00661    legend1->SetBorderSize(0);
00662    legend1->SetFillColor(kWhite);
00663    legend1->AddEntry(&fHistData, "Data", "LEP");
00664    legend1->AddEntry(&fHistData, "Total expected uncertainty", "LE");
00665 
00666    double y = 0.99;
00667    if (ntemplates > 2 && ntemplates <7)
00668       y -= 0.11 / 4. * double(ntemplates - 2);
00669    legend2 = new TLegend(0.50,(y-fraction_pads)/(1-fraction_pads) , 0.85, 0.99);
00670    legend2->SetBorderSize(0);
00671    legend2->SetFillColor(kWhite);
00672 
00673    // scale histograms and add to stack and legend
00674    for (int itemp = 0; itemp < ntemplates; ++itemp) {
00675       int tempindex = fTemplateParIndexContainer.at(itemp);
00676       int effindex = fEffParIndexContainer.at(itemp);
00677 
00678       // scale histogram
00679       fTemplateHistogramContainer.at(itemp).Scale(
00680             GetBestFitParameter(tempindex)/ fTemplateHistogramContainer.at(itemp).Integral());
00681 
00682       // loop over bins and scale these
00683       for (int ibin = 1; ibin <= fNBins; ++ibin) {
00684          // get efficiency for the bin
00685          double efficiency = fEffHistogramContainer.at(itemp).GetBinContent(ibin);
00686 
00687          // modify efficiency by uncertainty
00688          double efferr = fEffErrHistogramContainer.at(itemp).GetBinContent(ibin);
00689 
00690          // check efficiency error
00691          if (efferr > 0)
00692             efficiency = TMath::Max(0., efficiency + GetBestFitParameter(effindex) * efferr);
00693 
00694          fTemplateHistogramContainer.at(itemp).SetBinContent(
00695                ibin,fTemplateHistogramContainer.at(itemp).GetBinContent(ibin) * efficiency);
00696       }
00697 
00698       // add histogram to stack
00699       stack.Add(&(fTemplateHistogramContainer.at(itemp)));
00700       if (itemp < 2)
00701          legend1->AddEntry(&(fTemplateHistogramContainer.at(itemp)), fTemplateNameContainer.at(itemp).data(), "F");
00702       else if (itemp < 6)
00703          legend2->AddEntry(&(fTemplateHistogramContainer.at(itemp)), fTemplateNameContainer.at(itemp).data(), "F");
00704    }
00705 
00706    // loop over all bins
00707    for (int ibin = 1; ibin <= nbins; ++ibin) {
00708       double bincontent = 0;
00709 
00710       // loop over all templates
00711       for (int itemp = 0; itemp < ntemplates; ++itemp)
00712          bincontent +=fTemplateHistogramContainer.at(itemp).GetBinContent(ibin);
00713 
00714       // set bin content
00715       histsum->SetBinContent(ibin, bincontent);
00716    }
00717 
00718    // define error graph
00719    TGraphAsymmErrors * graph_error_exp = new TGraphAsymmErrors(nbins);
00720    graph_error_exp->SetLineWidth(2);
00721    graph_error_exp->SetMarkerStyle(0);
00722 
00723    TGraphAsymmErrors * graph_error_obs = new TGraphAsymmErrors(nbins);
00724    graph_error_obs->SetMarkerStyle(0);
00725 
00726    // calculate uncertainty
00727    if (flag_error1)
00728       for (int i = 1; i <= nbins; ++i) {
00729          double nexp = histsum->GetBinContent(i);
00730          histsum->SetBinError(i, sqrt(nexp));
00731          histsum->SetMarkerStyle(0);
00732       }
00733 
00734    if (flag_error2)
00735       for (int i = 1; i <= nbins; ++i) {
00736          TH1D * proj = fUncertaintyHistogramExp->ProjectionY("_py", i, i);
00737          if (proj->Integral() > 0)
00738             proj->Scale(1.0 / proj->Integral());
00739          double quantiles[3];
00740          double sums[3] = {0.16, 0.5, 0.84};
00741          proj->GetQuantiles(3, quantiles, sums);
00742          graph_error_exp->SetPoint(i-1, histsum->GetBinCenter(i), quantiles[1]);
00743          graph_error_exp->SetPointError(i-1, 0.0, 0.0, quantiles[1] - quantiles[0], quantiles[2]-quantiles[1]);
00744          delete proj;
00745       }
00746 
00747    if (flag_error3)
00748       for (int i = 1; i <= nbins; ++i) {
00749          TH1D * proj = fUncertaintyHistogramObsPosterior->ProjectionY("_py", i, i);
00750          if (proj->Integral() > 0)
00751             proj->Scale(1.0 / proj->Integral());
00752          double quantiles[3];
00753          double sums[3] = {0.16, 0.5, 0.84};
00754          proj->GetQuantiles(3, quantiles, sums);
00755          graph_error_obs->SetPoint(i-1, histsum->GetBinCenter(i), quantiles[1]);
00756          graph_error_obs->SetPointError(i-1, 0.0, 0.0, quantiles[1] - TMath::Floor(quantiles[0]), TMath::Ceil(quantiles[2])-quantiles[1]);
00757          delete proj;
00758       }
00759 
00760    // create difference histogram
00761    TH1D * hist_diff = 0;
00762 
00763    TGraphAsymmErrors * graph_diff_exp = 0;
00764 
00765    if (flag_diff) {
00766       ymin = 0;
00767       ymax = 0;
00768       hist_diff = new TH1D("hist_diff", "", nbins, histsum->GetXaxis()->GetXmin(), histsum->GetXaxis()->GetXmax() );
00769       hist_diff->GetXaxis()->SetTitle(fHistData.GetXaxis()->GetTitle());
00770       hist_diff->GetYaxis()->SetTitle("#Delta N");
00771       hist_diff->GetXaxis()->SetNdivisions(505);
00772       hist_diff->GetXaxis()->SetLabelSize(hist_diff->GetXaxis()->GetLabelSize()/(fraction_pads));
00773       hist_diff->GetXaxis()->SetLabelOffset(hist_diff->GetXaxis()->GetLabelOffset()/fraction_pads*2.);
00774       hist_diff->GetXaxis()->SetTitleSize(hist_diff->GetXaxis()->GetTitleSize()/(fraction_pads));
00775       hist_diff->GetXaxis()->SetTitleOffset((hist_diff->GetXaxis()->GetTitleOffset()-(1.0-fraction_pads))/(fraction_pads));
00776       hist_diff->GetYaxis()->SetNdivisions(503);
00777       hist_diff->GetYaxis()->SetLabelSize(hist_diff->GetYaxis()->GetLabelSize()/(fraction_pads));
00778       hist_diff->GetYaxis()->SetLabelOffset(hist_diff->GetYaxis()->GetLabelOffset()/(fraction_pads));
00779       hist_diff->GetYaxis()->SetTitleSize(hist_diff->GetYaxis()->GetTitleSize()/(fraction_pads));
00780       hist_diff->GetYaxis()->SetTitleOffset(hist_diff->GetYaxis()->GetTitleOffset()*(fraction_pads));
00781       hist_diff->SetStats(kFALSE);
00782 
00783       graph_diff_exp = new TGraphAsymmErrors(nbins);
00784       graph_diff_exp->SetLineWidth(2);
00785       graph_diff_exp->SetMarkerStyle(0);
00786       graph_diff_exp->SetFillColor(kYellow);
00787       for (int i = 0; i < nbins; ++i) {
00788          hist_diff->SetBinContent(i+1, fHistData.GetBinContent(i+1)-histsum->GetBinContent(i+1));
00789          hist_diff->SetBinError(i+1, fHistData.GetBinError(i+1));
00790          graph_diff_exp->SetPoint(i, (graph_error_exp->GetX())[i], 0.0);
00791          graph_diff_exp->SetPointEXlow(i, 0.0);
00792          graph_diff_exp->SetPointEXhigh(i, 0.0);
00793          graph_diff_exp->SetPointEYlow(i, (graph_error_exp->GetEYlow())[i]);
00794          graph_diff_exp->SetPointEYhigh(i, (graph_error_exp->GetEYhigh())[i]);
00795 
00796          if (-(graph_error_exp->GetEYlow())[i] < ymin)
00797             ymin = -(graph_error_exp->GetEYlow())[i];
00798          if ((graph_error_exp->GetEYhigh())[i] > ymax)
00799             ymax = (graph_error_exp->GetEYhigh())[i];
00800       }
00801       if (ymax < (hist_diff->GetMaximum() + hist_diff->GetBinError(hist_diff->GetMaximumBin())))
00802          ymax = 1.1 * (hist_diff->GetMaximum() + hist_diff->GetBinError(hist_diff->GetMaximumBin()));
00803       if (ymin>(hist_diff->GetMinimum() - hist_diff->GetBinError(hist_diff->GetMaximumBin())))
00804          ymin = 1.1 * (hist_diff->GetMinimum() - hist_diff->GetBinError(hist_diff->GetMaximumBin()));
00805       (hist_diff->GetYaxis())->SetRangeUser(-1.1*TMath::Max(-ymin, ymax), 1.1*TMath::Max(-ymin, ymax));
00806 
00807    }
00808 
00809    // draw histograms
00810    stack.Draw("SAMEA");
00811    stack.GetHistogram() -> SetXTitle("");
00812    stack.GetHistogram() -> SetYTitle("");
00813    stack.GetHistogram() -> GetXaxis() -> SetLabelSize(0);
00814    stack.GetHistogram() -> GetYaxis() -> SetLabelSize(0);
00815    stack.Draw("SAME");
00816    fHistData.Draw("SAMEP");
00817 
00818    if (flag_error0)
00819       fHistData.Draw("SAMEPE");
00820 
00821    if (flag_error1)
00822       histsum->Draw("SAMEE");
00823 
00824    if (flag_error3)
00825       graph_error_obs->Draw("SAMEZ");
00826 
00827    if (flag_error2)
00828       graph_error_exp->Draw("SAME||");
00829 
00830    if (flag_legend) {
00831       legend1->Draw();
00832       if (ntemplates>2)
00833       legend2->Draw();
00834    }
00835 
00836    TLine * line = 0;
00837    if (flag_diff) {
00838       pad2->cd();
00839       hist_diff->Draw("P");
00840       graph_diff_exp->Draw("SAME4");
00841       line = new TLine((hist_diff->GetXaxis())->GetXmin(), 0.0, (hist_diff->GetXaxis())->GetXmax(), 0.0);
00842       line->SetLineWidth(2);
00843       line->SetLineColor(kBlack);
00844       line->Draw("SAME");
00845       hist_diff->Draw("SAMEP");
00846    }
00847 
00848    c1->Print(filename);
00849 
00850    // rescale
00851    for (int i = 0; i < ntemplates; ++i)
00852       fTemplateHistogramContainer.at(i).Scale(1.0 / fTemplateHistogramContainer.at(i).Integral());
00853 
00854    // delete temporary histograms
00855    delete pad1;
00856    delete pad2;
00857    delete c1;
00858    delete legend1;
00859    delete legend2;
00860    delete graph_error_exp;
00861    delete graph_error_obs;
00862    delete histsum;
00863    if (flag_diff) {
00864       delete hist_diff;
00865       delete graph_diff_exp;
00866       delete line;
00867    }
00868 }
00869 
00870 // ---------------------------------------------------------
00871 double BCTemplateFitter::CalculateChi2()
00872 {
00873    int nbins = fHistData.GetNbinsX();
00874    int ntemplates = int(fTemplateHistogramContainer.size());
00875 
00876    std::vector <double> parameters = GetBestFitParameters();
00877 
00878    double chi2 = 0;
00879 
00880    // loop over all bins
00881    for (int ibin = 1; ibin <= nbins; ++ibin) {
00882       double nexp = 0;
00883       double ndata = fHistData.GetBinContent(ibin);
00884 
00885       // loop over all templates
00886       for (int itemp = 0; itemp < ntemplates; ++itemp) {
00887          int tempindex = fTemplateParIndexContainer.at(itemp);
00888          int effindex = fEffParIndexContainer.at(itemp);
00889 
00890          // get efficiency for the bin
00891          double efficiency = fEffHistogramContainer.at(itemp).GetBinContent(ibin);
00892 
00893          // modify efficiency by uncertainty
00894          double efferr = fEffErrHistogramContainer.at(itemp).GetBinContent(ibin);
00895 
00896          // check efficiency error
00897          if (efferr > 0)
00898             efficiency = TMath::Max(0., efficiency + parameters.at(effindex) * efferr);
00899 
00900          // add expectation from bin
00901          nexp += parameters.at(tempindex) * efficiency * fTemplateHistogramContainer.at(itemp).GetBinContent(ibin);
00902       }
00903 
00904       // add to chi2
00905       chi2 += (nexp - ndata) * (nexp - ndata) / nexp;
00906    }
00907 
00908    // return chi2
00909    return chi2;
00910 }
00911 
00912 // ---------------------------------------------------------
00913 double BCTemplateFitter::CalculateChi2Prob()
00914 {
00915    double chi2 = CalculateChi2();
00916    int ndf = GetNDF();
00917 
00918    // return chi2 probability
00919    return TMath::Prob(chi2, ndf);
00920 }
00921 
00922 // ---------------------------------------------------------
00923 double BCTemplateFitter::CalculateMaxLike()
00924 {
00925    // return maximum likelihood
00926    return Eval( GetBestFitParameters() );
00927 }
00928 
00929 // ---------------------------------------------------------
00930 double BCTemplateFitter::CalculateKSProb()
00931 {
00932    // create a histogram with the sum of all contributions
00933    TH1 * histsum = (TH1D*)(fTemplateHistogramContainer.at(0)).Clone("temp");
00934 
00935    int nbins = fHistData.GetNbinsX();
00936    int ntemplates = int(fTemplateHistogramContainer.size());
00937 
00938    std::vector <double> parameters = GetBestFitParameters();
00939 
00940    // loop over all bins
00941    for (int ibin = 1; ibin <= nbins; ++ibin) {
00942       double bincontent = 0;
00943 
00944       // loop over all templates
00945       for (int itemp = 0; itemp < ntemplates; ++itemp) {
00946          int tempindex = fTemplateParIndexContainer.at(itemp);
00947          int effindex = fEffParIndexContainer.at(itemp);
00948 
00949          // get efficiency for the bin
00950          double efficiency = fEffHistogramContainer.at(itemp).GetBinContent(ibin);
00951 
00952          // modify efficiency by uncertainty
00953          double efferr = fEffErrHistogramContainer.at(itemp).GetBinContent(ibin);
00954 
00955          // check efficiency error
00956          if (efferr > 0)
00957             efficiency = TMath::Max(0., efficiency + parameters.at(effindex) * efferr);
00958 
00959          // add expectation from bin
00960          bincontent += parameters.at(tempindex) * efficiency * fTemplateHistogramContainer.at(itemp).GetBinContent(ibin);
00961       }
00962 
00963       // set bin content
00964       histsum->SetBinContent(ibin, bincontent);
00965    }
00966 
00967    // perform KS test
00968    double ksprob = histsum->KolmogorovTest(&fHistData);
00969 
00970    // delete histogram
00971    delete histsum;
00972 
00973    return ksprob;
00974 }
00975 
00976 // ---------------------------------------------------------
00977 double BCTemplateFitter::CalculatePValue()
00978 {
00979    // get best fit parameters
00980    std::vector<double> par = GetBestFitParameters();
00981 
00982    // check size of parameter vector
00983    if (par.size() != GetNParameters()) {
00984       BCLog::OutWarning("BCBCTemplateFitter::CalculatePValueFast : Number of parameters is inconsistent.");
00985       return -1;
00986    }
00987 
00988    // define temporary variables
00989    int nbins = fHistData.GetNbinsX();
00990    int ntemplates = int( fTemplateHistogramContainer.size() );
00991 
00992    std::vector <int> histogram;
00993    std::vector <double> expectation;
00994    histogram.assign(nbins, 0);
00995    expectation.assign(nbins, 0);
00996 
00997    double logp = 0;
00998    double logp_start = 0;
00999    int counter_pvalue = 0;
01000 
01001    // define starting distribution
01002    for (int ibin = 1; ibin <= nbins; ++ibin) {
01003       double nexp = 0;
01004 
01005       // loop over all templates
01006       for (int itemp = 0; itemp < ntemplates; ++itemp) {
01007          int tempindex = fTemplateParIndexContainer.at(itemp);
01008          int effindex = fEffParIndexContainer.at(itemp);
01009 
01010          // get efficiency for the bin
01011          double efficiency = fEffHistogramContainer.at(itemp).GetBinContent(ibin);
01012 
01013          // modify efficiency by uncertainty
01014          double efferr = fEffErrHistogramContainer.at(itemp).GetBinContent(ibin);
01015 
01016          // check efficiency error
01017          if (efferr > 0)
01018             efficiency = TMath::Max(0., efficiency + par.at(effindex) * efferr);
01019 
01020          // add expectation from bin
01021          nexp += par.at(tempindex) * efficiency * fTemplateHistogramContainer.at(itemp).GetBinContent(ibin);
01022       }
01023 
01024       histogram[ibin-1]   = int(nexp);
01025       expectation[ibin-1] = nexp;
01026 
01027       // calculate p;
01028       logp += BCMath::LogPoisson(double(int(nexp)), nexp);
01029       logp_start += BCMath::LogPoisson(fHistData.GetBinContent(ibin), nexp);
01030    }
01031 
01032    int niter = 100000;
01033 
01034    // loop over iterations
01035    for (int iiter = 0; iiter < niter; ++iiter) {
01036       // loop over bins
01037       for (int ibin = 0; ibin < nbins; ++ibin) {
01038          // random step up or down in statistics for this bin
01039          double ptest = fRandom->Rndm() - 0.5;
01040 
01041          // increase statistics by 1
01042          if (ptest > 0) {
01043             // calculate factor of probability
01044             double r = expectation.at(ibin) / double(histogram.at(ibin) + 1);
01045 
01046             // walk, or don't (this is the Metropolis part)
01047             if (fRandom->Rndm() < r) {
01048                histogram[ibin] = histogram.at(ibin) + 1;
01049                logp += log(r);
01050             }
01051          }
01052 
01053          // decrease statistics by 1
01054          else if (ptest <= 0 && histogram[ibin] > 0) {
01055             // calculate factor of probability
01056             double r = double(histogram.at(ibin)) / expectation.at(ibin);
01057 
01058             // walk, or don't (this is the Metropolis part)
01059             if (fRandom->Rndm() < r) {
01060                histogram[ibin] = histogram.at(ibin) - 1;
01061                logp += log(r);
01062             }
01063          }
01064       } // end of looping over bins
01065 
01066       // increase counter
01067       if (logp < logp_start)
01068          counter_pvalue++;
01069 
01070    } // end of looping over iterations
01071 
01072    // calculate p-value
01073    return double(counter_pvalue) / double(niter);
01074 }
01075 
01076 // ---------------------------------------------------------
01077 void BCTemplateFitter::MCMCUserIterationInterface()
01078 {
01079    int nbins      = fHistData.GetNbinsX();
01080    int ntemplates = int(fTemplateHistogramContainer.size());
01081 
01082    // loop over all bins
01083    for (int ibin = 1; ibin <= nbins; ++ibin) {
01084       double bincontent = 0;
01085 
01086       // loop over all templates
01087       for (int itemp = 0; itemp < ntemplates; ++itemp) {
01088          int tempindex = fTemplateParIndexContainer.at(itemp);
01089          int effindex = fEffParIndexContainer.at(itemp);
01090 
01091          // get efficiency for the bin
01092          double efficiency = fEffHistogramContainer.at(itemp).GetBinContent(ibin);
01093 
01094          // modify efficiency by uncertainty
01095          double efferr = fEffErrHistogramContainer.at(itemp).GetBinContent(ibin);
01096 
01097          // check efficiency error
01098          if (efferr > 0)
01099             efficiency = TMath::Max(0., efficiency + fMCMCx.at(effindex) * efferr);
01100 
01101          bincontent += fMCMCx.at(tempindex) * efficiency * fTemplateHistogramContainer.at(itemp).GetBinContent(ibin);
01102       }
01103 
01104       // set bin content
01105       fUncertaintyHistogramExp->Fill(fHistData.GetBinCenter(ibin), bincontent);
01106 
01107       // loop over bins in the other direction
01108       int nbinsy = fUncertaintyHistogramObsPosterior->GetNbinsY();
01109       for (int jbin = 1; jbin <= nbinsy; ++jbin) {
01110          int n = jbin - 1;
01111          if (fabs(n - bincontent) < 2*sqrt(bincontent))
01112             fUncertaintyHistogramObsPosterior->Fill(fHistData.GetBinCenter(ibin), n, TMath::Poisson(bincontent, n));
01113       }
01114    }
01115 
01116    // fill normalization
01117    fHistNorm.Fill(fNorm);
01118 
01119    // fill ratios
01120    int nratios = int( fIndicesRatios1D.size() );
01121 
01122    // loop over fractions to fill
01123    for (int i = 0; i < nratios; ++i) {
01124       int nsum = int( (fIndicesRatios1D.at(i)).size() ) - 1;
01125       double sum = 0;
01126       for (int j = 1; j <= nsum; ++j) {
01127          int indexsum = fIndicesRatios1D.at(i).at(j);
01128          sum += fMCMCx.at(fTemplateParIndexContainer.at(indexsum));
01129       }
01130 
01131       fHistRatios1D.at(i).Fill(fMCMCx.at(fTemplateParIndexContainer.at(fIndicesRatios1D.at(i).at(0)))/sum);
01132    }
01133 
01134 }
01135 
01136 // ---------------------------------------------------------
01137 void BCTemplateFitter::PrintRatios(const char * filename, int options, double ovalue)
01138 {
01139    int nratios = int(fHistRatios1D.size());
01140 
01141    TCanvas * c1 = new TCanvas("");
01142 
01143    TPostScript * ps = new TPostScript(filename, 112);
01144    ps->NewPage();
01145 
01146    c1->cd();
01147    BCH1D * h1temp = new BCH1D(&fHistNorm);
01148    h1temp->Draw();
01149    c1->Update();
01150    ps->NewPage();
01151    for (int i = 0; i < nratios; ++i) {
01152       c1->Update();
01153       ps->NewPage();
01154       c1->cd();
01155       BCH1D* h1temp = new BCH1D(&fHistRatios1D.at(i));
01156       h1temp->Draw(options, ovalue);
01157    }
01158    c1->Update();
01159    ps->Close();
01160 
01161    delete c1;
01162    delete ps;
01163 }
01164 
01165 // ---------------------------------------------------------
01166 int BCTemplateFitter::SetTemplateEfficiency(const char * name, TH1D eff, TH1D efferr)
01167 {
01168    // get index
01169    int index = GetIndexTemplate(name);
01170 
01171    // check index
01172    if (index < 0) {
01173       BCLog::OutError("BCTemplateFitter::SetTemplateEfficiency : Could not find template.");
01174       return 0;
01175    }
01176 
01177    // check efficiency histogram
01178    if (CompareHistogramProperties(fTemplateHistogramContainer.at(index), eff) != 1) {
01179       BCLog::OutError("BCTemplateFitter::SetTemplate efficiency : Template and efficiency histogram properties are incompatible.");
01180       return 0;
01181    }
01182 
01183    // set histogram style
01184    eff.SetXTitle((fHistData.GetXaxis())->GetTitle());
01185    eff.SetYTitle("Efficiency");
01186 
01187    efferr.SetXTitle((fHistData.GetXaxis())->GetTitle());
01188    efferr.SetYTitle("Efficiency uncertainty");
01189 
01190    // set efficiency histogram
01191    fEffHistogramContainer[index] = eff;
01192    fEffErrHistogramContainer[index] = efferr;
01193 
01194    // no error
01195    return 1;
01196 }
01197 
01198 // ---------------------------------------------------------
01199 int BCTemplateFitter::SetTemplateEfficiency(const char * name, double effmean, double effsigma)
01200 {
01201    // get index
01202    int index = GetIndexTemplate(name);
01203 
01204    // check index
01205    if (index < 0) {
01206       BCLog::OutError("BCTemplateFitter::SetTemplateEfficiency : Could not find template.");
01207       return 0;
01208    }
01209 
01210    // create histograms
01211    TH1D histeff = TH1D("", "", fNBins, fXmin, fXmax);
01212    TH1D histefferr = TH1D("", "", fNBins, fXmin, fXmax);
01213 
01214    // fill histograms
01215    for (int i = 1; i <= fNBins; ++i) {
01216       histeff.SetBinContent(i, effmean);
01217       histefferr.SetBinContent(i, effsigma);
01218    }
01219 
01220    // set histograms
01221    int err = SetTemplateEfficiency(name, histeff, histefferr);
01222 
01223    // return error code
01224    return err;
01225 }
01226 
01227 // ---------------------------------------------------------
01228 int BCTemplateFitter::ConstrainSum(std::vector <int> indices, double mean, double rms)
01229 {
01230    // add contraint to container(s)
01231    fConstraintSumIndices.push_back(indices);
01232    fConstraintSumMean.push_back(mean);
01233    fConstraintSumRMS.push_back(rms);
01234 
01235    // no error
01236    return 1;
01237 }
01238 
01239 // ---------------------------------------------------------
01240 void BCTemplateFitter::PrintTemp()
01241 {
01242    TCanvas * c1 = new TCanvas("");
01243 
01244    c1->cd();
01245    fUncertaintyHistogramExp->Draw("COL");
01246    c1->Print("uncertainty_exp.eps");
01247 
01248    c1->cd();
01249    fUncertaintyHistogramObsPosterior->Draw("COL");
01250    c1->Print("uncertainty_obs.eps");
01251 
01252    delete c1;
01253 }
01254 
01255 // ---------------------------------------------------------
01256 int BCTemplateFitter::PrintTemplate(const char * name, const char * filename)
01257 {
01258    // get number of sources of systematic uncertainty
01259    int nsyst = GetNSystErrors();
01260 
01261    // get index
01262    int index = GetIndexTemplate(name);
01263 
01264    // check index
01265    if (index < 0) {
01266       BCLog::OutError("BCTemplateFitter::PrintTemplate : Could not find template.");
01267       return 0;
01268    }
01269 
01270    // remember old directory
01271    TDirectory* dir = gDirectory;
01272 
01273    // create postscript
01274    TPostScript * ps = new TPostScript(filename);
01275 
01276    // create new canvas
01277    TCanvas * c1 = new TCanvas("", "", 700, 700);
01278 
01279    c1->Update();
01280    ps->NewPage();
01281    c1->cd();
01282 
01283    // create legend
01284    TLegend l1(0.18, 0.75, 0.85, 0.85);
01285    l1.SetBorderSize(0);
01286    l1.SetFillColor(kWhite);
01287 
01288    // draw histogram and uncertainties
01289    TH1D hist_template = fTemplateHistogramContainer.at(index);
01290    hist_template.SetFillColor(kWhite);
01291    hist_template.SetFillStyle(0);
01292    hist_template.SetMarkerSize(0);
01293    hist_template.SetLineWidth(0);
01294    l1.AddEntry(&hist_template, name, "L");
01295    TH1D hist_totalerr = CombineUncertainties(name);
01296    TH1D hist_template_totalerr = CreateErrorHist(hist_template, hist_totalerr);
01297    hist_template_totalerr.SetFillColor(kYellow);
01298    hist_template_totalerr.SetFillStyle(1001);
01299    hist_template_totalerr.SetMarkerSize(0);
01300    l1.AddEntry(&hist_template_totalerr, "Systematic uncertainties", "F");
01301    TH1D hist_efferr = fEffErrHistogramContainer.at(index);
01302    TH1D hist_template_efferr = CreateErrorHist(hist_template, hist_efferr);
01303    hist_template_totalerr.SetFillColor(kRed);
01304    hist_template_totalerr.SetFillStyle(1001);
01305    hist_template_efferr.SetMarkerSize(0);
01306    l1.AddEntry(&hist_template_efferr, "Efficiency uncertainties", "F");
01307    int binmax = hist_template.GetMaximumBin();
01308    double ymax = hist_template.GetBinContent(binmax) + 2.0 * hist_template_totalerr.GetBinError(binmax);
01309    hist_template_totalerr.GetYaxis()->SetRangeUser(0.0, 1.25 * ymax);
01310    hist_template_totalerr.Draw("E2");
01311    hist_template_efferr.Draw("SAMEE2");
01312    hist_template.Draw("SAME");
01313 
01314    // draw legend
01315    l1.Draw();
01316 
01317    // update ps
01318    c1->Update();
01319    ps->NewPage();
01320    c1->cd();
01321 
01322    // create legend
01323    TLegend l2(0.18, 0.75, 0.85, 0.85);
01324    l2.SetBorderSize(0);
01325    l2.SetFillColor(kWhite);
01326 
01327    // print uncertainties
01328    c1->cd(2);
01329    hist_efferr = fEffErrHistogramContainer.at(index);
01330    double ymin = hist_efferr.GetMinimum();
01331    ymax = hist_efferr.GetMaximum();
01332    l2.AddEntry(&hist_efferr, "Efficiency", "L");
01333    hist_efferr.SetStats(kFALSE);
01334    hist_efferr.Draw();
01335 
01336    // loop over all uncertainties
01337    for (int i = 0; i < nsyst; ++i) {
01338       TH1D * hist = new TH1D(fSystErrorHistogramContainer.at(i).at(index));
01339       hist->SetLineColor(2 + i);
01340       if (hist->GetMaximum()>ymax)
01341          ymax = hist->GetMaximum();
01342       if (hist->GetMinimum()<ymin)
01343          ymin = hist->GetMinimum();
01344       l2.AddEntry(hist, fSystErrorNameContainer.at(i).c_str(), "L");
01345       hist->Draw("SAME");
01346    }
01347    if (ymin < 0)
01348       ymin = 1.25*ymin;
01349    else
01350       ymin = 0.8*ymin;
01351 
01352    if (ymax > 0)
01353       ymax = 1.25*ymax;
01354    else
01355       ymax = 0.8*ymax;
01356 
01357    hist_efferr.GetYaxis()->SetRangeUser(ymin, ymax);
01358 
01359    // draw legend
01360    l2.Draw();
01361 
01362    // close ps
01363    c1->Update();
01364    ps->Close();
01365 
01366    // change to old directory
01367    dir->cd();
01368 
01369    // free memory
01370    delete c1;
01371    delete ps;
01372 
01373    // no error
01374    return 1;
01375 }
01376 
01377 // ---------------------------------------------------------
01378 TH1D BCTemplateFitter::CreateErrorHist(TH1D hist, TH1D histerr)
01379 {
01380    // check histogram properties
01381    if (CompareHistogramProperties(fHistData, hist) != 1) {
01382       BCLog::OutError("BCTemplateFitter::CreateErrorHist : Histograms are incompatible.");
01383       return hist;
01384    }
01385 
01386    // copy histogram
01387    TH1D h = hist;
01388 
01389    // set style
01390    h.SetStats(kFALSE);
01391    h.SetFillColor(kYellow);
01392    h.SetFillStyle(1001);
01393 
01394    // get number of bins
01395    int nbins = hist.GetNbinsX();
01396 
01397    // loop over bins
01398    for (int i = 1; i <= nbins; ++i)
01399       h.SetBinError(i, histerr.GetBinContent(i) * hist.GetBinContent(i));
01400 
01401    // return histogram
01402    return h;
01403 }
01404 
01405 // ---------------------------------------------------------
01406 TH1D BCTemplateFitter::CombineUncertainties(const char * name)
01407 {
01408    // get number of sources of systematic uncertainty
01409    int nsyst = GetNSystErrors();
01410 
01411    // get template index
01412    int tempindex = GetIndexTemplate(name);
01413 
01414    // create new histogram
01415    TH1D hist = TH1D("", "", fNBins, fXmin, fXmax);
01416 
01417    // fill histogram
01418    for (int ibin = 1; ibin <= fNBins; ++ibin) {
01419 
01420       // define total uncertainty
01421       double err = 0;
01422 
01423       // add efficiency uncertainty squared
01424       double erreff = fEffErrHistogramContainer.at(tempindex).GetBinContent(ibin);
01425       err += erreff * erreff;
01426 
01427       // add systematic uncertainty squared
01428       for (int isyst = 0; isyst < nsyst; ++isyst) {
01429          double errsyst = fSystErrorHistogramContainer.at(isyst).at(tempindex).GetBinContent(ibin);
01430          err += errsyst*errsyst;
01431       }
01432 
01433       // take square root
01434       err = sqrt(err);
01435 
01436       // set bin content
01437       hist.SetBinContent(ibin, err);
01438    }
01439 
01440    // return histogram
01441    return hist;
01442 }
01443 
01444 // ---------------------------------------------------------
01445 int BCTemplateFitter::GetIndexTemplate(const char * name)
01446 {
01447    int index = -1;
01448    int n = GetNTemplates();
01449 
01450    for (int i = 0; i < n; i++)
01451       if (name == fTemplateNameContainer.at(i))
01452          index = i;
01453 
01454    if (index < 0) {
01455       BCLog::OutWarning("BCTemplateFitter::GetIndexTemplate : Template does not exist.");
01456       return 0;
01457    }
01458 
01459    // return index
01460    return index;
01461 }
01462 
01463 // ---------------------------------------------------------
01464 int BCTemplateFitter::GetIndexSystError(const char * name)
01465 {
01466    int index = -1;
01467    int n = GetNSystErrors();
01468 
01469    for (int i = 0; i < n; i++)
01470       if (name == fSystErrorNameContainer.at(i))
01471          index = i;
01472 
01473    if (index < 0) {
01474       BCLog::OutWarning("BCTemplateFitter::GetIndexSystError : Template does not exist.");
01475       return 0;
01476    }
01477 
01478    // return index
01479    return index;
01480 }
01481 
01482 // ---------------------------------------------------------
01483 int BCTemplateFitter::GetParIndexTemplate(const char * name)
01484 {
01485    int index = -1;
01486    int n = GetNTemplates();
01487 
01488    for (int i = 0; i < n; i++)
01489       if (name == fTemplateNameContainer.at(i))
01490          index = fTemplateParIndexContainer.at(i);
01491 
01492    if (index < 0) {
01493       BCLog::OutWarning("BCTemplateFitter::GetParIndexTemplate : Template does not exist.");
01494       return 0;
01495    }
01496 
01497    // return index
01498    return index;
01499 }
01500 
01501 // ---------------------------------------------------------
01502 int BCTemplateFitter::GetParIndexTemplate(int index)
01503 {
01504    // get number of templates
01505    int n = GetNTemplates();
01506 
01507    if (index < 0 || index > n) {
01508       BCLog::OutError("BCTemplateFitter::GetParIndexTemplate : Index out of range.");
01509       return -1;
01510    }
01511 
01512    // return index
01513    return fTemplateParIndexContainer.at(index);
01514 }
01515 
01516 // ---------------------------------------------------------
01517 int BCTemplateFitter::GetParIndexEff(const char * name)
01518 {
01519    int index = -1;
01520    int n = GetNTemplates();
01521 
01522    for (int i = 0; i < n; i++)
01523       if (name == fTemplateNameContainer.at(i))
01524          index = fTemplateParIndexContainer.at(i);
01525 
01526    if (index < 0) {
01527       BCLog::OutWarning("BCTemplateFitter::GetParIndexEff : Template does not exist.");
01528       return 0;
01529    }
01530 
01531    // return index
01532    return index;
01533 }
01534 
01535 // ---------------------------------------------------------
01536 int BCTemplateFitter::GetParIndexSystError(const char * name)
01537 {
01538    int index = -1;
01539    int n = GetNTemplates();
01540 
01541    for (int i = 0; i < n; i++)
01542       if (name == fSystErrorNameContainer.at(i))
01543          index = fSystErrorParIndexContainer.at(i);
01544 
01545    if (index < 0) {
01546       BCLog::OutWarning("BCTemplateFitter::GetParIndexStatError : Systematic error does not exist.");
01547       return 0;
01548    }
01549 
01550    // return index
01551    return index;
01552 }
01553 
01554 // ---------------------------------------------------------
01555 int  BCTemplateFitter::PerformFit()
01556 {
01557    // initialize
01558    if (!Initialize()) {
01559       BCLog::OutError("BCTemplateFitter::PerformFit : Could not initialize template fitter.");
01560       return 0;
01561    }
01562 
01563    // run Markov Chains
01564    MarginalizeAll();
01565 
01566    // find global mode
01567    FindMode();
01568 
01569    // no error
01570    return 1;
01571 }
01572 // ---------------------------------------------------------
01573 

Generated on Mon Aug 30 2010 22:14:54 for Bayesian Analysis Toolkit by  doxygen 1.7.1