////////////////////////////////////////////////////////////
// Author: Gero Flucke <mailto:flucke@mail.desy.de>
//____________________________________
// GFFitHistFrac
// Author: Gero Flucke
// Date: Sept 19th, 2002
// last update: $Date: 2002/10/29 14:59:09 $
// by: $Author: flucke $
//
// This class performs fits to get the best fractions of different
// MC-contributions.
//
// Limitations: Error propagation is not 100% valid in case of more than
// two MC-contributions
//
////////////////////////////////////////////////////////////
#include "TH1.h"
#include "TF1.h"
#include "TObjArray.h"
#include "GFFitHistFrac.h"
ClassImp(GFFitHistFrac)
using namespace std;
TObjArray* GFFitHistFrac::fgMcHists = NULL; // must contain TH1*, with same binning!
Double_t GFFitHistFrac::FitFunc1D(Double_t* x, Double_t* par)
{
// p[0] factor in front of fgMcHists->At(1),
// p[1] factor in front of fgMcHists->At(2) etc.
// (1. - p[1] - p[2] - ...) factor in front of fgMcHists->At(0)
TH1* firstHist = static_cast<TH1*>(fgMcHists->First());
Int_t bin = firstHist->GetXaxis()->FindBin(x[0]);
Int_t numHists = fgMcHists->GetEntriesFast();
Double_t result = 0.;
Double_t fractionFirst = 1.;
for(Int_t i = 1; i < numHists; ++i){ // 0'th hist (=firstHist) to be treated specially!
result +=
par[i-1] * static_cast<TH1*>(fgMcHists->At(i))->GetBinContent(bin);
fractionFirst -= par[i-1];
}
result += fractionFirst * firstHist->GetBinContent(bin);
return result;
}
//____________________________________
GFFitHistFrac::GFFitHistFrac() :
fHistDataNorm(NULL), fHistsMcNorm(NULL),
fScalesMc(0), fFractions(0), fFractionErrors(0)
{
}
//____________________________________
GFFitHistFrac::GFFitHistFrac(const TH1* histData, const TObjArray* histsMc) :
fHistDataNorm(NULL), fHistsMcNorm(NULL),
fScalesMc(0), fFractions(0), fFractionErrors(0)
{
this->SetHistDataMc(histData, histsMc);
}
//____________________________________
GFFitHistFrac::~GFFitHistFrac()
{
delete fHistDataNorm;
if(fHistsMcNorm) fHistsMcNorm->Delete();
delete fHistsMcNorm;
}
//____________________________________
Bool_t GFFitHistFrac::SetHistData(const TH1* hist)
{
if(fHistDataNorm) {
delete fHistDataNorm;
fScaleData = 1.;
}
if(hist){
fHistDataNorm = static_cast<TH1*>(hist->Clone());
fScaleData = fHistDataNorm->Integral();//"width"); ?? //FIXME
if(fScaleData) {
fHistDataNorm->Scale(1./fScaleData);
fHistDataNorm->SetMaximum(fHistDataNorm->GetMaximum()/fScaleData);
}
}
return (Bool_t) hist;
}
//____________________________________
Bool_t GFFitHistFrac::SetHistsMc(const TObjArray* hists)
{
if(fHistsMcNorm) {
fHistsMcNorm->Delete();
}
else fHistsMcNorm = new TObjArray;
Int_t numMc = hists->GetEntries();
fScalesMc.Set(numMc);
TIter next(hists);
Int_t count = 0;
while(TObject* hOrig = next()){
TH1* h = static_cast<TH1*>(hOrig->Clone());
fScalesMc[count] = h->Integral();//"width"); ?? //FIXME:
if(fScalesMc[count]) {
h->Scale(1./fScalesMc[count]);
h->SetMaximum(h->GetMaximum()/fScalesMc[count]);
}
fHistsMcNorm->Add(h);
++count;
}
return (Bool_t) hists;
}
//____________________________________
Bool_t GFFitHistFrac::SetHistDataMc(const TH1* histData, const TObjArray* histsMc)
{
return(this->SetHistData(histData) && this->SetHistsMc(histsMc));
}
//____________________________________
Bool_t GFFitHistFrac::CheckConsistency()
{
// checks whether we have data and MC histograms
// and whether they have the same binning
// check NULL pointers:
if(!fHistDataNorm || !fHistsMcNorm){
this->Error("CheckConsistency", "NULL pointer: dataHist = 0X%X, mcHists = 0X%X",
fHistDataNorm, fHistsMcNorm);
return kFALSE;
}
// enough entries?
Int_t numMc = fHistsMcNorm->GetEntriesFast();
if(numMc < 2) {
this->Error("CheckConsistency", "Only %d histograms to fit fractions!", numMc);
return kFALSE;
}
TIter histMcIter(fHistsMcNorm);
while(TH1* mc = static_cast<TH1*>(histMcIter.Next())){
for(Int_t i = 1; i < fHistDataNorm->GetNbinsX()+1; ++i){ // +1: test also upper edge!
if(fHistDataNorm->GetBinLowEdge(i) != mc->GetBinLowEdge(i)){
this->Error("CheckConsistency", "bin %i has no common lower edge!", i);
return kFALSE;
}
}
}
return kTRUE;
}
//____________________________________
TArrayD GFFitHistFrac::Fit()
{
// performs the fit, returns an array with a fraction for each MC-hist
// each fraction shows how much the MC hist contributes to the shape(!)
// of the data histogram
// clear results:
fFractions.Reset();
fFractionErrors.Reset();
// fit if hists are consistent:
if(this->CheckConsistency()){
// initialise fractions to be equal (summing up to 1.)
// and errors to be zero:
Int_t numFractions = fHistsMcNorm->GetEntriesFast();
fFractions.Set(numFractions);
fFractions.Reset(1./(numFractions));
fFractionErrors.Set(numFractions); // new places in the array are set to 0!
fgMcHists = fHistsMcNorm; // global/static variable used in fitting func.!!!
TF1 mcHistsFunc("mcHistsFunc", GFFitHistFrac::FitFunc1D,
fHistDataNorm->GetXaxis()->GetXmin(),
fHistDataNorm->GetXaxis()->GetXmax(),
numFractions-1);
// initialise with equal 'fractions','+1' is tricky:
mcHistsFunc.SetParameters(fFractions.GetArray()+1);
fHistDataNorm->Fit(&mcHistsFunc, "EMRN");//"0+"
// filling the output arrays:
fFractions[0] = 1.;
Double_t firstErrorSqr = 0;
for(Int_t i = 1; i < numFractions; ++i){ // starting at '1'!
fFractions[i] = mcHistsFunc.GetParameter(i-1);
fFractions[0] -= fFractions[i];
fFractionErrors[i] = mcHistsFunc.GetParError(i-1);
// FIXME: assuming uncorrelated fitting parameters:
// (OK for just 2 MC hists: there is only one parameter!)
firstErrorSqr += fFractionErrors[i] * fFractionErrors[i];
}
fFractionErrors[0] = TMath::Sqrt(firstErrorSqr);// not 100% correct, cf. up
// fgMcHists = NULL; leads to crash: needed by ROOT to draw fitting function
}
return fFractions;
}
//____________________________________
TArrayD GFFitHistFrac::Fit(const TH1* dataHist, const TObjArray* mcHists)
{
// setting histograms and then Fit()
this->SetHistDataMc(dataHist, mcHists);
return this->Fit();
}
//____________________________________
TArrayD GFFitHistFrac::GetFactors() const
{
// after Fit() returning array of factors each MC-histogram has to be
// multiplied with to get the best agreement with data
TArrayD factors(fFractions.GetSize());
for(Int_t i = 0; i < factors.GetSize(); ++i){
factors[i] = fScalesMc.At(i) ?
fFractions.At(i) * fScaleData / fScalesMc.At(i) : 0.;
}
return factors;
}
//____________________________________
TArrayD GFFitHistFrac::GetFactorErrors() const
{
// returns array of errors belonging to array from GetFractions()
// FIXME: assuming fractions of the others were independend!! ???
// (is fine in case of just fitting 2 MC hists to data!)
TArrayD result(fFractionErrors.GetSize());
this->Warning("GetFractionErrors", "Not yet implemented");
return result;
}
ROOT page - Class index - Top of the page
This page has been automatically generated. If you have any comments or suggestions about the page layout send a mail to ROOT support, or contact the developers with any questions or problems regarding ROOT.