// @(#)root/tmva $Id: TMVA_MethodLikelihood.cxx,v 1.3 2006/05/10 07:36:12 brun Exp $
// Author: Andreas Hoecker, Helge Voss, Kai Voss
/**********************************************************************************
* Project: TMVA - a Root-integrated toolkit for multivariate Data analysis *
* Package: TMVA *
* Class : TMVA_MethodLikelihood *
* *
* Description: *
* Implementation (see header for description) *
* *
* Authors (alphabetical): *
* Andreas Hoecker <Andreas.Hocker@cern.ch> - CERN, Switzerland *
* Xavier Prudent <prudent@lapp.in2p3.fr> - LAPP, France *
* Helge Voss <Helge.Voss@cern.ch> - MPI-KP Heidelberg, Germany *
* Kai Voss <Kai.Voss@cern.ch> - U. of Victoria, Canada *
* *
* Copyright (c) 2005: *
* CERN, Switzerland, *
* U. of Victoria, Canada, *
* MPI-KP Heidelberg, Germany, *
* LAPP, Annecy, France *
* *
* Redistribution and use in source and binary forms, with or without *
* modification, are permitted according to the terms listed in LICENSE *
* (http://mva.sourceforge.net/license.txt) *
* *
**********************************************************************************/
//_______________________________________________________________________
//
// Likelihood analysis ("non-parametric approach")
// Also implemented is a "diagonalized likelihood approach",
// which improves over the uncorrelated likelihood ansatz by
// transforming linearly the input variables into a diagonal space,
// using the square-root of the covariance matrix
//
//_______________________________________________________________________
#include "TMVA_MethodLikelihood.h"
#include "TMVA_Tools.h"
#include "TMatrixD.h"
#include "TVector.h"
#include "TObjString.h"
#include "TFile.h"
#include "TKey.h"
#define DEBUG_TMVA_MethodLikelihood kFALSE
#define Transform_Likelihood_Output_ kTRUE
#define NmaxVar 200
ClassImp(TMVA_MethodLikelihood)
//_______________________________________________________________________
TMVA_MethodLikelihood::TMVA_MethodLikelihood( TString jobName, vector<TString>* theVariables,
TTree* theTree, TString theOption,
TDirectory* theTargetDir )
: TMVA_MethodBase( jobName, theVariables, theTree, theOption, theTargetDir )
{
InitLik();
if (fOptions.Sizeof()<2) {
fOptions="Spline2:0:25";
cout << "--- " << GetName() << ": using default options: " << fOptions << endl;
}
// initialize
fNsmooth = 5;
// sanity check
if (fNvar > TMVA_MethodLikelihood_max_nvar__) {
cout << "--- " << GetName() << ": too many input variables ==> abort" << endl;
exit(1);
}
// default settings (should be defined in fOptions string)
TList* list = TMVA_Tools::ParseFormatLine( fOptions );
// format and syntax of option string: "Spline2:0:25:Decorr"
//
// where:
// Splinei [i=1,2,3,5] - which spline is used for smoothing the pdfs
// 0 - how often the input histos are smoothed
// 25 - average num of events per PDF bin to trigger warning
// NoDecorr - do NOT use square-root-matrix to decorrelate variable space
if (list->GetSize() > 0) {
TString s = ((TObjString*)list->At(0))->GetString();
if (s.Contains("Spline2")) fSmoothMethod = TMVA_PDF::kSpline2;
else if (s.Contains("Spline3")) fSmoothMethod = TMVA_PDF::kSpline3;
else if (s.Contains("Spline5")) fSmoothMethod = TMVA_PDF::kSpline3;
else {
cout << "--- " << GetName() << ": WARNING unknown Spline type! Choose Spline2" << endl;
fSmoothMethod = TMVA_PDF::kSpline2;
}
}
if (list->GetSize() > 1)
fNsmooth = atoi( ((TObjString*)list->At(1))->GetString() ) ;
else
fNsmooth = 0;
if (list->GetSize() > 2) {
fAverageEvtPerBin = atoi( ((TObjString*)list->At(2))->GetString() ) ;
if (fAverageEvtPerBin < 1) fAverageEvtPerBin = 25;
}
else
fAverageEvtPerBin = 25;
fDecorrVarSpace = kFALSE;
if (list->GetSize() > 3) {
TString s = ((TObjString*)list->At(3))->GetString();
s.ToUpper();
if (s == "D" ) {
fMethodName += "D";
fTestvar = fTestvarPrefix+GetMethodName();
cout << "--- " << GetName() << ": decorrelate variable space" << endl;
fDecorrVarSpace = kTRUE;
}
}
cout << "--- " << GetName() << ": smooth input histos "<<fNsmooth<<" times; ";
if (fSmoothMethod == TMVA_PDF::kSpline2) cout << "Spline2";
if (fSmoothMethod == TMVA_PDF::kSpline3) cout << "Spline3";
if (fSmoothMethod == TMVA_PDF::kSpline5) cout << "Spline5";
cout << " for smoothing; <events> per bin " << fAverageEvtPerBin << endl;
//--------------------------------------------------------------
// note that one variable is type
if (0 != fTrainingTree) {
// trainingTree should only contain those variables that are used in the MVA
if (fTrainingTree->GetListOfBranches()->GetEntries() - 1 != fNvar) {
cout << "--- " << GetName() << ": Error: mismatch in number of variables"
<< " --> abort" << endl;
exit(1);
}
// count number of signal and background events
fNevt = fTrainingTree->GetEntries();
fNsig = 0;
fNbgd = 0;
for (Int_t ievt = 0; ievt < fNevt; ievt++) {
if ((Int_t)TMVA_Tools::GetValue( fTrainingTree, ievt, "type" ) == 1)
++fNsig;
else
++fNbgd;
}
// numbers of events should match
if (fNsig + fNbgd != fNevt) {
cout << "--- " << GetName() << ": Error: mismatch in number of events"
<< " --> abort" << endl;
exit(1);
}
if (Verbose())
cout << "--- " << GetName() << " <verbose>: num of events for training (signal, background): "
<< " (" << fNsig << ", " << fNbgd << ")" << endl;
// Likelihood wants same number of events in each species
if (fNsig != fNbgd) {
cout << "--- " << GetName() << ":\t--------------------------------------------------"
<< endl;
cout << "--- " << GetName() << ":\tWarning: different number of signal and background\n"
<< "--- " << GetName() << " \tevents: Likelihood training will not be optimal :-("
<< endl;
cout << "--- " << GetName() << ":\t--------------------------------------------------"
<< endl;
}
}
else {
fNevt = 0;
fNsig = 0;
fNbgd = 0;
}
}
//_______________________________________________________________________
TMVA_MethodLikelihood::TMVA_MethodLikelihood( vector<TString> *theVariables,
TString theWeightFile,
TDirectory* theTargetDir )
: TMVA_MethodBase( theVariables, theWeightFile, theTargetDir )
{
InitLik();
}
//_______________________________________________________________________
void TMVA_MethodLikelihood::InitLik( void )
{
fFin = NULL;
fSqS = NULL;
fSqB = NULL;
fHistSig = NULL;
fHistBgd = NULL;
fHistSig_smooth = NULL;
fHistBgd_smooth = NULL;
fPDFSig = NULL;
fPDFBgd = NULL;
fMethodName = "Likelihood";
fMethod = TMVA_Types::Likelihood;
fTestvar = fTestvarPrefix+GetMethodName();
fEpsilon = 1e-5;
fBgdPDFHist = new TList();
fSigPDFHist = new TList();
fNevt = 0;
fNsig = 0;
fNbgd = 0;
fHistSig = new vector<TH1*> ( fNvar );
fHistBgd = new vector<TH1*> ( fNvar );
fHistSig_smooth = new vector<TH1*> ( fNvar );
fHistBgd_smooth = new vector<TH1*> ( fNvar );
fPDFSig = new vector<TMVA_PDF*>( fNvar );
fPDFBgd = new vector<TMVA_PDF*>( fNvar );
}
//_______________________________________________________________________
TMVA_MethodLikelihood::~TMVA_MethodLikelihood( void )
{
if (NULL != fSqS) delete fSqS;
if (NULL != fSqB) delete fSqB;
if (NULL != fHistSig) delete fHistSig;
if (NULL != fHistBgd) delete fHistBgd;
if (NULL != fHistSig_smooth) delete fHistSig_smooth;
if (NULL != fHistBgd_smooth) delete fHistBgd_smooth;
if (NULL != fPDFSig) delete fPDFSig;
if (NULL != fPDFBgd) delete fPDFBgd;
// delete histos
if (NULL != fFin) { fFin->Close(); fFin->Delete(); }
if (NULL != fFin) { fFin->Close(); fFin->Delete(); }
delete fBgdPDFHist;
delete fSigPDFHist;
}
//_______________________________________________________________________
void TMVA_MethodLikelihood::Train( void )
{
//--------------------------------------------------------------
// default sanity checks
if (!CheckSanity()) {
cout << "--- " << GetName() << ": Error: sanity check failed" << endl;
exit(1);
}
// build square-root matrices for signal and background
if (fDecorrVarSpace) {
this->GetSQRMats();
if (Verbose()) {
cout << "--- " << GetName()
<< " <verbose>: SQRT covariance matrix for signal: " << endl;
fSqS->Print();
cout << "--- " << GetName()
<< " <verbose>: SQRT covariance matrix for background: " << endl;
fSqB->Print();
}
}
// create reference histograms
fNbins = (Int_t)(TMath::Min(fNsig,fNbgd)/fAverageEvtPerBin);
TString histTitle, histName;
TVectorT<float>* vmin = new TVectorT<float>( fNvar );
TVectorT<float>* vmax = new TVectorT<float>( fNvar );
TVectorT<float>* vs = new TVectorT<float>( fNvar );
TVectorT<float>* vb = new TVectorT<float>( fNvar );
for (Int_t ivar=0; ivar<fNvar; ivar++) { (*vmin)(ivar) = 1e15; (*vmax)(ivar) = -1e15; }
// search for kinematic borders
for (Int_t ievt=0; ievt<fTrainingTree->GetEntries(); ievt++) {
for (Int_t ivar=0; ivar<fNvar; ivar++) {
Double_t x = TMVA_Tools::GetValue( fTrainingTree, ievt, (*fInputVars)[ivar] );
(*vs)(ivar) = __N__( x, GetXminNorm( ivar ), GetXmaxNorm( ivar ) );
(*vb)(ivar) = (*vs)(ivar);
}
// the minima and maxima will change after the diagonalization
if (fDecorrVarSpace) { (*vs) *= (*fSqS); (*vb) *= (*fSqB); }
for (Int_t ivar=0; ivar<fNvar; ivar++) {
if ((*vs)(ivar) < (*vmin)(ivar)) (*vmin)(ivar) = (*vs)(ivar);
if ((*vb)(ivar) < (*vmin)(ivar)) (*vmin)(ivar) = (*vb)(ivar);
if ((*vs)(ivar) > (*vmax)(ivar)) (*vmax)(ivar) = (*vs)(ivar);
if ((*vb)(ivar) > (*vmax)(ivar)) (*vmax)(ivar) = (*vb)(ivar);
}
}
if (Verbose()) {
cout << "--- " << GetName() << " <verbose>: variable minima and maxima: " << endl;
vmin->Print();
vmax->Print();
}
for (Int_t ivar=0; ivar<fNvar; ivar++) {
// for signal events
histTitle = (*fInputVars)[ivar] + " signal training";
histName = (*fInputVars)[ivar] + "_sig";
TH1F *htemp = new TH1F( histName, histTitle, fNbins, (*vmin)(ivar), (*vmax)(ivar) );
(*fHistSig)[ivar] = htemp;
// for background events
histTitle = (*fInputVars)[ivar] + " background training";
histName = (*fInputVars)[ivar] + "_bgd";
TH1F *htemp2 = new TH1F( histName, histTitle, fNbins, (*vmin)(ivar), (*vmax)(ivar) );
(*fHistBgd)[ivar] = htemp2;
}
delete vmin;
delete vmax;
delete vs;
delete vb;
// ----- fill the reference histograms
// event loop
TVectorT<float>* v = new TVectorT<float>( fNvar );
for (Int_t ievt=0; ievt<fTrainingTree->GetEntries(); ievt++) {
// fill variable vector
for (Int_t ivar=0; ivar<fNvar; ivar++) {
Double_t x = TMVA_Tools::GetValue( fTrainingTree, ievt, (*fInputVars)[ivar] );
(*v)(ivar) = __N__( x, GetXminNorm( ivar ), GetXmaxNorm( ivar ) );
}
// compute diagonalized vector
if ((Int_t)TMVA_Tools::GetValue( fTrainingTree, ievt, "type") == 1) {
if (fDecorrVarSpace) (*v) *= (*fSqS);
for (Int_t ivar=0; ivar<fNvar; ivar++) (*fHistSig)[ivar]->Fill( (Float_t)(*v)(ivar) );
}
else {
if (fDecorrVarSpace) (*v) *= (*fSqB);
for (Int_t ivar=0; ivar<fNvar; ivar++) (*fHistBgd)[ivar]->Fill( (Float_t)(*v)(ivar) );
}
}
delete v;
// apply smoothing, and create PDFs
for (Int_t ivar=0; ivar<fNvar; ivar++) {
// signal
(*fHistSig_smooth)[ivar] = (TH1D*)(*fHistSig)[ivar]->Clone();
histTitle = (*fInputVars)[ivar] + " signal training smoothed ";
histTitle += fNsmooth;
histTitle += " times";
histName = (*fInputVars)[ivar] + "_sig_smooth";
(*fHistSig_smooth)[ivar]->SetName(histName);
(*fHistSig_smooth)[ivar]->SetTitle(histTitle);
if (((*fHistSig_smooth)[ivar]->GetNbinsX() >2 ) && (fNsmooth >0) ){
(*fHistSig_smooth)[ivar]->Smooth(fNsmooth);
}else{
if (((*fHistSig_smooth)[ivar]->GetNbinsX() <=2 ) )
cout << "--- " << GetName() << ": WARNING histogram "<< (*fHistSig_smooth)[ivar]->GetName()
<<" has not enough ("<<(*fHistSig_smooth)[ivar]->GetNbinsX()
<<") bins for for smoothing "<<endl;
}
(*fPDFSig)[ivar] = new TMVA_PDF( (*fHistSig_smooth)[ivar], fSmoothMethod );
// background
(*fHistBgd_smooth)[ivar] = (TH1D*)(*fHistBgd)[ivar]->Clone();
histTitle = (*fInputVars)[ivar] + " background training smoothed ";
histTitle += fNsmooth;
histTitle += " times";
histName = (*fInputVars)[ivar] + "_bgd_smooth";
(*fHistBgd_smooth)[ivar]->SetName(histName);
(*fHistBgd_smooth)[ivar]->SetTitle(histTitle);
if (((*fHistBgd_smooth)[ivar]->GetNbinsX() >2) && (fNsmooth >0) ){
(*fHistBgd_smooth)[ivar]->Smooth(fNsmooth);
}
else{
if (((*fHistBgd_smooth)[ivar]->GetNbinsX() <=2 ) )
cout << "--- " << GetName() << ": WARNING histogram "<< (*fHistBgd_smooth)[ivar]->GetName()
<<" has not enough ("<<(*fHistBgd_smooth)[ivar]->GetNbinsX()
<<") bins for for smoothing "<<endl;
}
(*fPDFBgd)[ivar] = new TMVA_PDF( (*fHistBgd_smooth)[ivar], fSmoothMethod );
}
// write weights to file
WriteWeightsToFile();
// the reference histograms to file
WriteHistosToFile();
}
//_______________________________________________________________________
Double_t TMVA_MethodLikelihood::GetMvaValue( TMVA_Event *e )
{
// fill a new Likelihood branch into the testTree
Int_t ivar;
Double_t myMVA;
TH1D *hist;
Double_t ps = 1;
Double_t pb = 1;
// retrieve variables, and transform, if required
TVectorT<float> vs( fNvar );
TVectorT<float> vb( fNvar );
for (ivar=0; ivar<fNvar; ivar++) {
vs(ivar) = __N__( e->GetData(ivar), GetXminNorm( ivar ), GetXmaxNorm( ivar ) );
vb(ivar) = vs(ivar);
}
if (fDecorrVarSpace) { vs *= (*fSqS); vb *= (*fSqB); }
// compute the likelihood (signal)
TIter next1(fSigPDFHist);
for (ivar=0; ivar<fNvar; ivar++) {
Double_t x = vs(ivar);
next1.Reset();
while ((hist = (TH1D*)next1())) {
TString varname;
for (Int_t i=0; i<(((TString)hist->GetName()).Index("_sig_")); i++)
varname.Append( ( (TString)hist->GetName())(i) );
if (varname == (*fInputVars)[ivar]) break;
}
// interpolate linearly between adjacent bins
Int_t bin = hist->FindBin(x);
Int_t nextbin = bin;
if ((x > hist->GetBinCenter(bin) && bin != hist->GetNbinsX()) || bin == 1)
nextbin++;
else
nextbin--;
Double_t dx = hist->GetBinCenter(bin) - hist->GetBinCenter(nextbin);
Double_t dy = hist->GetBinContent(bin) - hist->GetBinContent(nextbin);
Double_t like = hist->GetBinContent(bin) + (x - hist->GetBinCenter(bin)) * dy/dx;
ps *= max(like, fEpsilon);
}
// compute the likelihood (background)
TIter next2(fBgdPDFHist);
for (ivar=0; ivar<fNvar; ivar++) {
Double_t x = vb(ivar);
next2.Reset();
while ((hist = (TH1D*)next2())) {
TString varname;
for (Int_t i=0; i<(((TString)hist->GetName()).Index("_bgd_")); i++)
varname.Append( ( (TString)hist->GetName())(i) );
if (varname == (*fInputVars)[ivar]) break;
}
// interpolate linearly between adjacent bins
Int_t bin = hist->FindBin(x);
Int_t nextbin = bin;
if ((x > hist->GetBinCenter(bin) && bin != hist->GetNbinsX()) || bin == 1)
nextbin++;
else
nextbin--;
Double_t dx = hist->GetBinCenter(bin) - hist->GetBinCenter(nextbin);
Double_t dy = hist->GetBinContent(bin) - hist->GetBinContent(nextbin);
Double_t like = hist->GetBinContent(bin) + (x - hist->GetBinCenter(bin)) * dy/dx;
pb *= max(like, fEpsilon);
}
// the likelihood
if (Transform_Likelihood_Output_) {
// inverse Fermi function
Double_t r = ps/(pb+ps);
Double_t tau = 15.0;
myMVA = - log(1.0/r - 1.0)/tau;
}
else myMVA = ps/(pb+ps);
return myMVA;
}
//_______________________________________________________________________
void TMVA_MethodLikelihood::GetSQRMats( void )
{
if (NULL != fSqS) { delete fSqS; fSqS = 0; }
if (NULL != fSqB) { delete fSqB; fSqB = 0; }
TMatrixTSym<double> *covMatS = new TMatrixTSym<double>( fNvar );
TMatrixTSym<double> *covMatB = new TMatrixTSym<double>( fNvar );
fSqS = new TMatrixT<double> ( fNvar, fNvar );
fSqB = new TMatrixT<double> ( fNvar, fNvar );
TMVA_Tools::GetCovarianceMatrix( fTrainingTree, covMatS, fInputVars, 1, kTRUE );
TMVA_Tools::GetCovarianceMatrix( fTrainingTree, covMatB, fInputVars, 0, kTRUE );
TMVA_Tools::GetSQRootMatrix( covMatS, fSqS );
TMVA_Tools::GetSQRootMatrix( covMatB, fSqB );
delete covMatS;
delete covMatB;
}
//_______________________________________________________________________
void TMVA_MethodLikelihood::WriteWeightsToFile( void )
{
// write coefficients to file
TString fname = GetWeightFileName() + ".root";
cout << "--- " << GetName() << ": creating weight file: " << fname << endl;
TFile *fout = new TFile( fname, "RECREATE" );
// build TList of input variables, and TVectors for min/max
// NOTE: the latter values are mandatory for the normalisation
// in the reader application !!!
TList lvar;
TVectorT<double> vmin( fNvar ), vmax( fNvar );
for (Int_t ivar=0; ivar<fNvar; ivar++) {
lvar.Add( new TNamed( (*fInputVars)[ivar], TString() ) );
vmin[ivar] = this->GetXminNorm( ivar );
vmax[ivar] = this->GetXmaxNorm( ivar );
}
// write to file
lvar.Write();
vmin.Write( "vmin" );
vmax.Write( "vmax" );
lvar.Delete();
// save configuration options
// (best would be to use a TMap here, but found implementation really complicated)
TVectorT<double> likelOptions( 4 );
likelOptions(0) = (Double_t)fSmoothMethod;
likelOptions(1) = (Double_t)fNsmooth;
likelOptions(2) = (Double_t)fAverageEvtPerBin;
likelOptions(3) = (Double_t)fDecorrVarSpace;
likelOptions.Write( "LikelihoodOptions" );
// write out SQRT matrices if diagonalization option is set
if (fDecorrVarSpace) {
fSqS->Write( "sqS" );
fSqB->Write( "sqB" );
}
// now write the histograms
for(Int_t ivar=0; ivar<fNvar; ivar++){
(*fPDFSig)[ivar]->GetPDFHist()->Write();
(*fPDFBgd)[ivar]->GetPDFHist()->Write();
}
fout->Close();
delete fout;
}
//_______________________________________________________________________
void TMVA_MethodLikelihood::ReadWeightsFromFile( void )
{
// read coefficients from file
TString fname = GetWeightFileName();
if (!fname.EndsWith( ".root" )) fname += ".root";
cout << "--- " << GetName() << ": reading weight file: " << fname << endl;
fFin = new TFile(fname);
// build TList of input variables, and TVectors for min/max
// NOTE: the latter values are mandatory for the normalisation
// in the reader application
TList lvar;
for (Int_t ivar=0; ivar<fNvar; ivar++) {
// read variable names
TNamed t;
t.Read( (*fInputVars)[ivar] );
// sanity check
if (t.GetName() != (*fInputVars)[ivar]) {
cout << "--- " << GetName() << ": Error while reading weight file; "
<< "unknown variable: " << t.GetName() << " at position: " << ivar << ". "
<< "Expected variable: " << (*fInputVars)[ivar] << " ==> abort" << endl;
exit(1);
}
}
// read vectors
TVectorT<double> vmin( fNvar ), vmax( fNvar );
// unfortunatly the more elegant vmin/max.Read( "vmin/max" ) crash in ROOT <= V4.04.02
TVectorT<double> *tmp = (TVectorT<double>*)fFin->Get( "vmin" );
vmin = *tmp;
tmp = (TVectorT<double>*)fFin->Get( "vmax" );
vmax = *tmp;
// initialize min/max
for (Int_t ivar=0; ivar<fNvar; ivar++) {
this->SetXminNorm( ivar, vmin[ivar] );
this->SetXmaxNorm( ivar, vmax[ivar] );
}
// save configuration options
// (best would be to use a TMap here, but found implementation really complicated)
TVectorT<double>* likelOptions = (TVectorT<double>*)fFin->Get( "LikelihoodOptions" );
fSmoothMethod = (TMVA_PDF::SmoothMethod)(Int_t)(*likelOptions)(0);
fNsmooth = (Int_t)(*likelOptions)(1);
fAverageEvtPerBin = (Int_t)(*likelOptions)(2);
fDecorrVarSpace = (Bool_t)(*likelOptions)(3);
// read in SQRT matrices if diagonalization option is set
if (fDecorrVarSpace) {
if (NULL != fSqS) { delete fSqS; fSqS = 0; }
if (NULL != fSqB) { delete fSqB; fSqB = 0; }
fSqS = new TMatrixT<double>( fNvar, fNvar );
fSqB = new TMatrixT<double>( fNvar, fNvar );
fSqS->Read( "sqS" );
fSqB->Read( "sqB" );
}
// now read the histograms
fSigPDFHist = new TList();
fBgdPDFHist = new TList();
TIter next(fFin->GetListOfKeys());
TKey *key;
while ((key = (TKey*)next())) {
TClass *cl = gROOT->GetClass(key->GetClassName());
if (!cl->InheritsFrom("TH1D")) continue;
TH1D *h = (TH1D*)key->ReadObj();
TString hname= h->GetName();
if (hname.Contains("_sig_")) fSigPDFHist->Add(h);
else if (hname.Contains("_bgd_")) fBgdPDFHist->Add(h);
}
}
//_______________________________________________________________________
void TMVA_MethodLikelihood::WriteHistosToFile( void )
{
cout << "--- " << GetName() << ": write " << GetName()
<< " special histos to file: " << fBaseDir->GetPath() << endl;
gDirectory->GetListOfKeys()->Print();
fLocalTDir = fBaseDir->mkdir(GetName()+GetMethodName());
fLocalTDir->cd();
for (Int_t ivar=0; ivar<fNvar; ivar++) {
fLocalTDir->cd();
(*fHistSig)[ivar]->Write();
(*fHistBgd)[ivar]->Write();
(*fHistSig_smooth)[ivar]->Write();
(*fHistBgd_smooth)[ivar]->Write();
(*fPDFSig)[ivar]->GetPDFHist()->Write();
(*fPDFBgd)[ivar]->GetPDFHist()->Write();
// add special plots to check the smoothing in the GetVal method
Float_t xmin=((*fPDFSig)[ivar]->GetPDFHist()->GetXaxis())->GetXmin();
Float_t xmax=((*fPDFSig)[ivar]->GetPDFHist()->GetXaxis())->GetXmax();
TH1D* mm = new TH1D( (*fInputVars)[ivar]+"_additional_check",
(*fInputVars)[ivar]+"_additional_check", 15000, xmin, xmax );
Double_t intBin = (xmax-xmin)/15000;
for (Int_t bin=0; bin < 15000; bin++) {
Double_t x = (bin + 0.5)*intBin + xmin;
mm->SetBinContent(bin+1 ,(*fPDFSig)[ivar]->GetVal(x));
}
mm->Write();
// delete mm;
}
}
ROOT page - Class index - Class Hierarchy - 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.