/////////////////////////////////////////////////////////////////////////// // // // helper functions wrapped in a namespace. // // // Authors: // * Copyright(c) 1998-2009, ALICE Experiment at CERN, All rights reserved. * // Julian Book // // // /////////////////////////////////////////////////////////////////////////// #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "PairAnalysisVarManager.h" #include "PairAnalysisStyler.h" #include "PairAnalysisHelper.h" #include "CbmModuleList.h" //_____________________________________________________________________________ TVectorD* PairAnalysisHelper::MakeLogBinning(Int_t nbinsX, Double_t xmin, Double_t xmax) { // // Make logarithmic binning // the user has to delete the array afterwards!!! // //check limits 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 (xmaxGetEntries(); 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(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!!! // TVectorD *binLim=new TVectorD(nbinsX+1); 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 while( (xt+=epsilon)<=mean+5*sigma) { // 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 if(cint>=lim && pintPrint(); 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; iGetNrows(); i++) (*binLim)[i] = (*low)[i]; for(Int_t i=0; iGetNrows()-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' // if(!h || stat>1.) return 0x0; Double_t cont = 0.0; Double_t err = 0.0; Double_t from = h->GetBinLowEdge(1); Double_t to = 0.0; TArrayD *vBins = new TArrayD(1+1); vBins->AddAt(from, 0); Int_t vEle = 1; for(Int_t i=1; i<=h->GetNbinsX(); i++) { 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); err=0.0; cont=0.0; vEle++; from=to; vBins->Set(vEle+1); } } vBins->AddAt(h->GetXaxis()->GetXmax(), vBins->GetSize()-1); // for(Int_t i=0;iGetSize();i++) Printf("%d %f",i,vBins->At(i)); return vBins; } //_____________________________________________________________________________ TVectorD* PairAnalysisHelper::MakePdgBinning() { // // Make arbitrary binning using defined PDG codes // // array of pdgcodes stored in TDatabasePDG TDatabasePDG *pdg = new TDatabasePDG();//::Instance(); pdg->ReadPDGTable(); TIter next(pdg->ParticleList() ); TGraph gr; 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()); gr.SetPoint(i++, p->PdgCode(),1.); } } gr.Sort(); TVectorD *vec = new TVectorD(gr.GetN(), gr.GetX()); // 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; ipGetNpar(); 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;jGetNpar();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;jGetNpar();j++) { tform+=PairAnalysisVarManager::GetValueName((UInt_t)form->GetParameter(j)); if(j!=form->GetNpar()-1) tform+=","; } 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); // compile function if(form->Compile()) return 0x0; //set parameter/variable identifier for(Int_t i=0; iGetNpar(); 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; iGetNbinsX()+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():"")); xaxis->SetBinLabel(i,(p?GetPDGlabel(pdgCode):"")); } if(hLbl->GetDimension()==1) return; TAxis *yaxis = hLbl->GetYaxis(); TString keyY = yaxis->GetName(); if(keyY.Contains("pdg",TString::kIgnoreCase)) { for(Int_t i=1; iGetNbinsY()+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():"")); yaxis->SetBinLabel(i,(p?GetPDGlabel(pdgCode):"")); } } } //_____________________________________________________________________________ TString PairAnalysisHelper::GetPDGlabel(Int_t pdg) { // // 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{"); } // correct indices name.ReplaceAll("+","^{+}"); name.ReplaceAll("-","^{-}"); name.ReplaceAll("0","^{0}"); name.ReplaceAll("_s","_{s}"); name.ReplaceAll("_c","_{c}"); name.ReplaceAll("_b","_{b}"); name.ReplaceAll("_1","_{1}"); // specials name.ReplaceAll("/psi","/#psi"); // Printf(" %d = %s",pdg,name.Data()); return name; } //_____________________________________________________________________________ void PairAnalysisHelper::SetGEANTBinLabels( TH1 *hist) { // // build formula key with parameter names // TAxis *xaxis = hist->GetXaxis(); for(Int_t i=1; iGetNbinsX()+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 // if(det==9) return (""); 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 // if(p<0.0 || p>1.) return -1.; 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(xbinGetXaxis()->GetFirst() || xbin>h1->GetXaxis()->GetLast()) continue; if(ybinGetYaxis()->GetFirst() || ybin>h1->GetYaxis()->GetLast()) continue; Double_t con = h1->GetBinContent(i); Double_t err = h1->GetBinError(i); if(err!=0.0) { // printf("bin%d %.f+-%.f \n",i,con,err); val[nfilled]=con+(h1->GetDimension()<2 ? err : 0.0); // w or w/o err? nfilled++; } } 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; iClone("SliceInts"); hsum->Reset("CE"); for(Int_t ix = 0; ix <= hsum->GetNbinsX()+1; ix++) { Double_t ysum = h->Integral(ix,ix); 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); Double_t cumInt = 0; 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); Double_t cumInt = 0; for(Int_t ix = xstart; ix != xend; ix+=xincr) { cumInt += h->GetBinContent(ix); h->SetBinContent(ix,cumInt/integral); } } TObject* PairAnalysisHelper::FindObjectByTitle(TObjArray *arrhist, TString ref) { // // shortcut to find a certain pair type object in array // for(Int_t i=0; iGetEntriesFast(); 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; value*=1e6; while(!bfnd) { // 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; }