Newer
Older
///////////////////////////////////////////////////////////////////////////
// //
// helper functions wrapped in a namespace.
//
//
// * Copyright(c) 1998-2009, ALICE Experiment at CERN, All rights reserved. *
// Julian Book <Julian.Book@cern.ch>
//
// //
///////////////////////////////////////////////////////////////////////////
#include <TError.h>
#include <TF1.h>
#include <TFormula.h>
#include <TGraph.h>
#include <TH1.h>
#include <TH2.h>
#include <THashList.h>
#include <TMCProcess.h>
#include <TMath.h>
#include <TObjArray.h>
#include <TObjString.h>
#include <TPad.h>
#include <TParticlePDG.h>
#include <TProfile.h>
#include <TRandom.h>
#include <TVectorD.h>
#include "CbmModuleList.h"
#include "PairAnalysisHelper.h"
#include "PairAnalysisStyler.h"
#include "PairAnalysisVarManager.h"
//_____________________________________________________________________________
TVectorD*
PairAnalysisHelper::MakeLogBinning(Int_t nbinsX, Double_t xmin, Double_t xmax) {
//
// Make logarithmic binning
// the user has to delete the array afterwards!!!
//
if (xmin < 1e-20 || xmax < 1e-20) {
Error("PairAnalysisHelper::MakeLogBinning",
"For Log binning xmin and xmax must be > 1e-20. Using linear binning "
"instead!");
return PairAnalysisHelper::MakeLinBinning(nbinsX, xmin, xmax);
}
if (xmax < xmin) {
Double_t tmp = xmin;
xmin = xmax;
xmax = tmp;
TVectorD* binLim = new TVectorD(nbinsX + 1);
Double_t first = xmin;
Double_t last = xmax;
Double_t expMax = TMath::Log(last / first);
for (Int_t i = 0; i < nbinsX + 1; ++i) {
(*binLim)[i] = first * TMath::Exp(expMax / nbinsX * (Double_t) i);
}
return binLim;
}
//_____________________________________________________________________________
TVectorD*
PairAnalysisHelper::MakeLinBinning(Int_t nbinsX, Double_t xmin, Double_t xmax) {
//
// Make linear binning
// the user has to delete the array afterwards!!!
//
if (xmax < xmin) {
Double_t tmp = xmin;
xmin = xmax;
xmax = tmp;
TVectorD* binLim = new TVectorD(nbinsX + 1);
Double_t first = xmin;
Double_t last = xmax;
Double_t binWidth = (last - first) / nbinsX;
for (Int_t i = 0; i < nbinsX + 1; ++i) {
(*binLim)[i] = first + binWidth * (Double_t) i;
}
return binLim;
}
//_____________________________________________________________________________
TVectorD* PairAnalysisHelper::MakeArbitraryBinning(const char* bins) {
//
// Make arbitrary binning, bins separated by a ','
//
TString limits(bins);
if (limits.IsNull()) {
Error("PairAnalysisHelper::MakeArbitraryBinning",
"Bin Limit string is empty, cannot add the variable");
TObjArray* arr = limits.Tokenize(",");
Int_t nLimits = arr->GetEntries();
if (nLimits < 2) {
Error("PairAnalysisHelper::MakeArbitraryBinning",
"Need at leas 2 bin limits, cannot add the variable");
delete arr;
return 0x0;
}
TVectorD* binLimits = new TVectorD(nLimits);
for (Int_t iLim = 0; iLim < nLimits; ++iLim) {
(*binLimits)[iLim] =
(static_cast<TObjString*>(arr->At(iLim)))->GetString().Atof();
delete arr;
return binLimits;
}
//_____________________________________________________________________________
TVectorD* PairAnalysisHelper::MakeGausBinning(Int_t nbinsX,
Double_t mean,
Double_t sigma) {
//
// Make gaussian binning
// the user has to delete the array afterwards!!!
//
TF1 g("g", "gaus", mean - 5 * sigma, mean + 5 * sigma);
g.SetParameters(1, mean, sigma);
Double_t sum = g.Integral(mean - 5 * sigma, mean + 5 * sigma);
//printf("full integral gaussian: %f \n",sum);
TF1 g2("g2", "gaus(0)/[3]", mean - 5 * sigma, mean + 5 * sigma);
g2.SetParameters(1, mean, sigma, sum); /// normalize with sum
// Double_t *params=g2.GetParameters();
Double_t epsilon = sigma / 10000; // step size
Double_t xt = mean - 5 * sigma; // bin limit
Double_t pint = 0.0; // previous integral
Int_t bin = 0; // current entry
Double_t lim = epsilon; // requested integral values (start,..., end values)
// calculate intergral until you found all limits
// current integral
// Double_t cint = g2.Integral(mean-5*sigma,xt,params,epsilon); //fast, but NOT root 6 (Integral(min,max,epsilon)) compatible
Double_t cint =
g2.Integral(mean - 5 * sigma, xt); //,params,epsilon); //slow
// printf(" integral to %f: %f , search limit: %f \n",xt,cint,lim);
/// condition for bin limit
// printf(" %d bin found for %f with requested integral %f, actual integral is %f \n",bin,xt,lim,cint);
/// set value to vector
/// next bin and limit
bin++;
/// fix end integral value
}
/// store prevoius integral value
}
// binLim->Print();
return binLim;
}
//_____________________________________________________________________________
TVectorD* PairAnalysisHelper::CombineBinning(TVectorD* low, TVectorD* high) {
//
// Make a new combined binning of "low" and "high"
// the user has to delete the returned array afterwards!!!
//
// fill final vector
Int_t lastEqualsFirst =
(Int_t)(TMath::Abs((*low)[low->GetNrows() - 1] - (*high)[0]) < 1.e-15);
TVectorD* binLim =
new TVectorD(low->GetNrows() + high->GetNrows() - lastEqualsFirst);
for (Int_t i = 0; i < low->GetNrows(); i++)
(*binLim)[i] = (*low)[i];
for (Int_t i = 0; i < high->GetNrows() - lastEqualsFirst; i++)
(*binLim)[low->GetNrows() + i] = (*high)[i + lastEqualsFirst];
// clean up
// delete low; delete high;
// binLim->Print();
return binLim;
}
//_____________________________________________________________________________
TArrayD* PairAnalysisHelper::MakeStatBinLimits(TH1* h, Double_t stat) {
//
// get bin limits for stat. error less than 'stat'
//
Double_t cont = 0.0;
Double_t err = 0.0;
Double_t from = h->GetBinLowEdge(1);
Double_t to = 0.0;
if (h->GetBinContent(i) == 0.0 && h->GetBinError(i) == 0.) continue;
to = h->GetBinLowEdge(i + 1);
cont += h->GetBinContent(i);
err += (h->GetBinError(i) * h->GetBinError(i));
vBins->AddAt(to, vEle);
// Printf("cont %f/%f=%f err %f(%f) sum of -> rel err %f%% (current: %f%%)",
// h->GetBinContent(i),h->Integral(),h->GetBinContent(i)/h->Integral(), h->GetBinError(i), TMath::Sqrt(h->GetBinContent(i)),h->GetBinError(i)/h->GetBinContent(i)*100, TMath::Sqrt(err)/cont*100);
// check for new bin
if (
TMath::Sqrt(err) / cont <= stat
// || (h->GetBinContent(i)/h->Integral()) < 0.01
// || (h->GetBinContent(i)==0.0 && h->GetBinError(i)==0. && vEle==1)
) {
// Printf("bin from %f to %f with err %f%%",from,to,TMath::Sqrt(err)/cont*100);
vBins->AddAt(h->GetXaxis()->GetXmax(), vBins->GetSize() - 1);
// for(Int_t i=0;i<vBins->GetSize();i++) Printf("%d %f",i,vBins->At(i));
return vBins;
}
//_____________________________________________________________________________
//
// Make arbitrary binning using defined PDG codes
//
// array of pdgcodes stored in TDatabasePDG
TParticlePDG* p;
Int_t i = 0;
while ((p = (TParticlePDG*) next())) {
if (TMath::Abs(p->PdgCode()) < 1e+6) {
// printf("%s -> %d \n",p->GetName(),p->PdgCode());
// vec->Print();
delete pdg;
return vec;
}
//_____________________________________________________________________________
Double_t PairAnalysisHelper::EvalFormula(TFormula* form,
const Double_t* values) {
//
// evaluate return value for formula with current parameter values
//
Double_t params[10] = {0.};
//put parameter values into array using variables stored as the parameters
for (Int_t ip = 0; ip < form->GetNpar(); ip++)
params[ip] = values[(UInt_t) form->GetParameter(ip)];
return (form->EvalPar(0x0, params));
}
//_____________________________________________________________________________
TString PairAnalysisHelper::GetFormulaTitle(TFormula* form) {
//
// evaluate the formula in a readable way (for axis etc)
//
// TODO: add units, switch to TMathText, get ride of obsolete parentheses
TString tform(form->GetExpFormula());
// TMathText
// tform.ReplaceAll("*","\\cdot"); // multiplication sign
// tform.ReplaceAll("TMath::","\\"); // get ride of TMath::
// TLatex
tform.ReplaceAll("*", "#upoint"); // multiplication sign
// tform.ReplaceAll("Sqrt","sqrt"); // sqrt sign
tform.ReplaceAll("TMath::", ""); // get ride of TMath::
tform.ReplaceAll("()", ""); // remove function parenthesis
tform.ToLower(); // lower cases (e.g. Cos -> cos)
// replace parameter variables with proper labels
for (Int_t j = 0; j < form->GetNpar(); j++)
tform.ReplaceAll(
Form("[%d]", j),
PairAnalysisVarManager::GetValueLabel((UInt_t) form->GetParameter(j)));
return (tform);
}
//_____________________________________________________________________________
TString PairAnalysisHelper::GetFormulaName(TFormula* form) {
//
// build formula key with parameter names
//
TString tform("f(");
for (Int_t j = 0; j < form->GetNpar(); j++) {
tform +=
PairAnalysisVarManager::GetValueName((UInt_t) form->GetParameter(j));
if (j != form->GetNpar() - 1) tform += ",";
return (tform);
}
//_____________________________________________________________________________
TFormula* PairAnalysisHelper::GetFormula(const char* name,
const char* formula) {
//
// build a TFormula object
//
TString check(formula);
if (check.IsNull()) return 0x0;
TFormula* form = new TFormula(name, formula);
//set parameter/variable identifier
for (Int_t i = 0; i < form->GetNpar(); i++) {
form->SetParName(
i, PairAnalysisVarManager::GetValueName(form->GetParameter(i)));
// fUsedVars->SetBitNumber((Int_t)form->GetParameter(i),kTRUE);
}
return form;
}
//_____________________________________________________________________________
void PairAnalysisHelper::SetPDGBinLabels(TH1* hist, Bool_t clean) {
//
// build formula key with parameter names
//
TH1* hLbl = PairAnalysisStyler::GetFirstHistogram();
if (!hLbl) hLbl = hist;
TDatabasePDG* pdg = TDatabasePDG::Instance();
TAxis* xaxis = hLbl->GetXaxis();
for (Int_t i = 1; i < hist->GetNbinsX() + 1; i++) {
// printf("bin %d: low edge: %.0f --> %s \n",i,xaxis->GetBinLowEdge(i), pdg->GetParticle(xaxis->GetBinLowEdge(i))->GetName());
if (clean && !hist->GetBinContent(i)) continue;
Int_t pdgCode = (Int_t) xaxis->GetBinLowEdge(i);
TParticlePDG* p = pdg->GetParticle(pdgCode);
// xaxis->SetBinLabel(i,(p?p->GetName():""));
TString keyY = yaxis->GetName();
if (keyY.Contains("pdg", TString::kIgnoreCase)) {
for (Int_t i = 1; i < hist->GetNbinsY() + 1; i++) {
// printf("bin %d: low edge: %.0f --> %s \n",i,yaxis->GetBinLowEdge(i), pdg->GetParticle(yaxis->GetBinLowEdge(i))->GetName());
if (clean && !hist->GetBinContent(i)) continue;
Int_t pdgCode = (Int_t) yaxis->GetBinLowEdge(i);
TParticlePDG* p = pdg->GetParticle(pdgCode);
// yaxis->SetBinLabel(i,(p?p->GetName():""));
}
}
}
//_____________________________________________________________________________
//
// return the label in latex format corresponding to pdg code
//
TString name = TDatabasePDG::Instance()->GetParticle(pdg)->GetName();
name.ReplaceAll("dd_1_bar", "primary");
name.ReplaceAll("proton", "p");
// correct greek letters
/*
if(name.Contains("delta",TString::kIgnoreCase) ||
name.Contains("gamma",TString::kIgnoreCase) ||
name.Contains("sigma",TString::kIgnoreCase) ||
name.Contains("xi",TString::kIgnoreCase) ||
name.Contains("lambda",TString::kIgnoreCase) ||
name.Contains("omega",TString::kIgnoreCase) ||
name.Contains("eta",TString::kIgnoreCase) ||
name.Contains("tau",TString::kIgnoreCase) ||
name.Contains("phi",TString::kIgnoreCase) ||
name.Contains("eta",TString::kIgnoreCase) ||
name.Contains("upsilon",TString::kIgnoreCase) ||
name.Contains("nu",TString::kIgnoreCase) ||
name.Contains("pi",TString::kIgnoreCase) ||
name.Contains("rho",TString::kIgnoreCase) ) name.Prepend("#");
*/
name.ReplaceAll("delta", "#delta");
name.ReplaceAll("gamma", "#gamma");
name.ReplaceAll("psi", "#psi");
name.ReplaceAll("sigma", "#sigma");
name.ReplaceAll("xi", "#xi");
name.ReplaceAll("lambda", "#lambda");
name.ReplaceAll("omega", "#omega");
name.ReplaceAll("eta", "#eta");
name.ReplaceAll("tau", "#tau");
name.ReplaceAll("phi", "#phi");
name.ReplaceAll("upsilon", "#upsilon");
name.ReplaceAll("nu", "#nu");
name.ReplaceAll("mu", "#mu");
name.ReplaceAll("pi", "#pi");
name.ReplaceAll("rho", "#rho");
// correct anti particles
if (name.Contains("anti")) {
name.ReplaceAll("anti", "#bar{");
name.Append("}");
} else if (name.Contains("_bar")) {
name.ReplaceAll("_bar", "}");
name.Prepend("#bar{");
}
name.ReplaceAll("+", "^{+}");
name.ReplaceAll("-", "^{-}");
name.ReplaceAll("0", "^{0}");
name.ReplaceAll("_s", "_{s}");
name.ReplaceAll("_c", "_{c}");
name.ReplaceAll("_b", "_{b}");
name.ReplaceAll("_1", "_{1}");
// Printf(" %d = %s",pdg,name.Data());
return name;
}
//_____________________________________________________________________________
//
// build formula key with parameter names
//
TAxis* xaxis = hist->GetXaxis();
for (Int_t i = 1; i < hist->GetNbinsX() + 1; i++) {
xaxis->SetBinLabel(i, TMCProcessName[i - 1]);
xaxis->LabelsOption("v"); // vertical labels
if (gPad) {
xaxis->SetTitleOffset(3.6);
gPad->SetTopMargin(0.01);
gPad->SetBottomMargin(0.4);
}
}
//_____________________________________________________________________________
TString PairAnalysisHelper::GetDetName(ECbmModuleId det) {
//
// get detector name
//
TString name = CbmModuleList::GetModuleNameCaps(det);
// TString name = CbmModuleList::GetModuleName(det);
return (name);
}
//_____________________________________________________________________________
Double_t PairAnalysisHelper::GetContentMinimum(TH1* h, Bool_t inclErr) {
//
// get minimum bin content of histogram (having entries)
//
Int_t bin, binx, biny, binz;
Int_t xfirst = h->GetXaxis()->GetFirst();
Int_t xlast = h->GetXaxis()->GetLast();
Int_t yfirst = h->GetYaxis()->GetFirst();
Int_t ylast = h->GetYaxis()->GetLast();
Int_t zfirst = h->GetZaxis()->GetFirst();
Int_t zlast = h->GetZaxis()->GetLast();
Double_t minimum = FLT_MAX, value = 0., error = 0.;
for (binz = zfirst; binz <= zlast; binz++) {
for (biny = yfirst; biny <= ylast; biny++) {
for (binx = xfirst; binx <= xlast; binx++) {
bin = h->GetBin(binx, biny, binz);
value = h->GetBinContent(bin);
error = h->GetBinError(bin);
// Printf(" \t hist%s bin%d value%f error%f \n",h->GetTitle(),bin,value,error);
if (gPad->GetLogy() && (value - error) <= 0.) continue;
if (error > value * 0.9) continue;
if (inclErr) value -= h->GetBinError(bin);
if (value < minimum
&& TMath::Abs(h->GetBinError(bin) - 1.e-15) > 1.e-15) {
minimum = value;
}
}
}
}
// Printf(" RETURN VALUE: hist%s %f \n",h->GetTitle(),minimum);
return minimum;
}
Double_t PairAnalysisHelper::GetContentMaximum(TH1* h, Bool_t inclErr) {
//
// get maximum bin content+error of histogram (having entries)
//
Int_t bin, binx, biny, binz;
Int_t xfirst = h->GetXaxis()->GetFirst();
Int_t xlast = h->GetXaxis()->GetLast();
Int_t yfirst = h->GetYaxis()->GetFirst();
Int_t ylast = h->GetYaxis()->GetLast();
Int_t zfirst = h->GetZaxis()->GetFirst();
Int_t zlast = h->GetZaxis()->GetLast();
Double_t maximum = -1. * FLT_MAX, value = 0., error = 0.;
for (binz = zfirst; binz <= zlast; binz++) {
for (biny = yfirst; biny <= ylast; biny++) {
for (binx = xfirst; binx <= xlast; binx++) {
bin = h->GetBin(binx, biny, binz);
value = h->GetBinContent(bin);
error = h->GetBinError(bin);
if (inclErr) value += h->GetBinError(bin);
if (value > maximum && TMath::Abs(error - 1.e-15) > 1.e-15) {
maximum = value;
}
}
}
}
return maximum;
}
Double_t PairAnalysisHelper::GetQuantile(TH1* h1, Double_t p /*=0.5*/) {
//
// calculates the quantile of the bin contents, p=0.5 -> Median
// useful functionallity for plotting 2D distibutions with some extreme outliers
//
Int_t nbinsX = h1->GetNbinsX();
Int_t nbinsY = h1->GetNbinsY();
Int_t nbinsZ = h1->GetNbinsZ();
Int_t nbins = (nbinsX * (nbinsY ? nbinsY : 1) * (nbinsZ ? nbinsZ : 1));
Int_t xbin = -1;
Int_t ybin = -1;
Int_t zbin = -1;
Double_t val[nbins];
Int_t idx[nbins];
Int_t nfilled = 0;
for (Int_t i = 1; i <= nbins; i++) {
h1->GetBinXYZ(i, xbin, ybin, zbin);
if (xbin < h1->GetXaxis()->GetFirst() || xbin > h1->GetXaxis()->GetLast())
continue;
if (ybin < h1->GetYaxis()->GetFirst() || ybin > h1->GetYaxis()->GetLast())
continue;
Double_t con = h1->GetBinContent(i);
Double_t err = h1->GetBinError(i);
// printf("bin%d %.f+-%.f \n",i,con,err);
val[nfilled] =
con + (h1->GetDimension() < 2 ? err : 0.0); // w or w/o err?
if (nfilled == 0) return -1.;
TMath::Sort(nfilled, val, idx, kFALSE); // kFALSE=increasing numbers
Int_t pos = (Int_t)((Double_t) nfilled * p);
//for(int i=0; i<nfilled; i++) cout << i << " " << idx[i] << " " << val[idx[i]] << endl;
//printf("nfilled %d quantile %f pos %d: %f \n",nfilled,p,pos,val[idx[pos]]);
return val[idx[pos]];
}
//
// normalize slices along Y in case of a 2D histogram
//
Double_t ysum = h->Integral(ix, ix, 0, hsum->GetNbinsY() + 1);
for (Int_t iy = 0; iy <= hsum->GetNbinsY() + 1; iy++) {
hsum->SetBinContent(ix, iy, ysum);
}
}
/// normalize
h->Divide(hsum);
delete hsum;
}
void PairAnalysisHelper::CumulateSlicesX(TH2* h, Bool_t reverse, Bool_t norm) {
//
// caluclate cumulative sum of bins (normalized to one)
// for slices along X in case of a 2D histogram
//
/// NOTE: addition +-1 for limits because of != loop
Int_t xstart = (reverse ? h->GetNbinsX() + 1 : 0 - 1);
Int_t xend = (reverse ? 0 : h->GetNbinsX() + 1 + 1);
Int_t xincr = (reverse ? -1 : +1);
Double_t integral = 1.;
for (Int_t iy = 0; iy <= h->GetNbinsY() + 1; iy++) {
if (norm) integral = h->Integral(0, h->GetNbinsX() + 1, iy, iy);
for (Int_t ix = xstart; ix != xend; ix += xincr) {
cumInt += h->GetBinContent(ix, iy);
h->SetBinContent(ix, iy, cumInt / integral);
void PairAnalysisHelper::Cumulate(TH1* h, Bool_t reverse, Bool_t norm) {
//
// caluclate cumulative sum of bins (normalized to one)
//
/// NOTE: addition +-1 for limits because of != loop
Int_t xstart = (reverse ? h->GetNbinsX() + 1 : 0 - 1);
Int_t xend = (reverse ? 0 : h->GetNbinsX() + 1 + 1);
Int_t xincr = (reverse ? -1 : +1);
Double_t integral = 1.;
if (norm) integral = h->Integral(0, h->GetNbinsX() + 1);
cumInt += h->GetBinContent(ix);
TObject* PairAnalysisHelper::FindObjectByTitle(TObjArray* arrhist,
TString ref) {
//
// shortcut to find a certain pair type object in array
//
for (Int_t i = 0; i < arrhist->GetEntriesFast(); i++) {
if (!ref.CompareTo(arrhist->UncheckedAt(i)->GetTitle())) {
return arrhist->UncheckedAt(i);
}
}
return 0x0;
// return ( arrhist->FindObject(Form("Pair.%s",PairAnalysis::PairClassName(type))) );
// TString ref=Form("Pair.%s",PairAnalysis::PairClassName(type));
}
//_____________________________________________________________________________
Int_t PairAnalysisHelper::GetPrecision(Double_t value) {
//
// computes the precision of a double
// usefull for axis ranges etc
Bool_t bfnd = kFALSE;
Int_t precision = 0;
// Printf(" value %f precision %d bfnd %d",TMath::Abs(value*TMath::Power(10,precision)), precision, bfnd);
bfnd =
((TMath::Abs(value * TMath::Power(10, precision)) / 1e6
- TMath::Floor(TMath::Abs(value * TMath::Power(10, precision)) / 1e6))
!= 0.0
? kFALSE
: kTRUE);
if (!bfnd) precision++;
}
// Printf("precision for %f found to be %d", value, precision);
return precision;
}