X-Git-Url: http://git.uio.no/git/?a=blobdiff_plain;f=STEER%2FAliMathBase.cxx;h=89d9a87c40a4a93f4eff770a3bd99e9b350c7790;hb=86ee89e6a8f3b6a0cd5b84a8615847f971bcde12;hp=7d02171e8d2816fff2973fc8a35be7b9efe5d230;hpb=284050f74c33ba291c793e202ee72cdfa446b08e;p=u%2Fmrichter%2FAliRoot.git diff --git a/STEER/AliMathBase.cxx b/STEER/AliMathBase.cxx index 7d02171e8d2..89d9a87c40a 100644 --- a/STEER/AliMathBase.cxx +++ b/STEER/AliMathBase.cxx @@ -24,17 +24,33 @@ #include "TMath.h" #include "AliMathBase.h" #include "Riostream.h" +#include "TH1F.h" +#include "TF1.h" +#include "TLinearFitter.h" + +// +// includes neccessary for test functions +// + +#include "TSystem.h" +#include "TRandom.h" +#include "TStopwatch.h" +#include "TTreeStream.h" ClassImp(AliMathBase) // Class implementation to enable ROOT I/O AliMathBase::AliMathBase() : TObject() { -// Default constructor + // + // Default constructor + // } /////////////////////////////////////////////////////////////////////////// AliMathBase::~AliMathBase() { -// Destructor + // + // Destructor + // } @@ -59,13 +75,15 @@ void AliMathBase::EvaluateUni(Int_t nvectors, Double_t *data, Double_t &mean TMath::Sort(nvectors, data, index, kFALSE); Int_t nquant = TMath::Min(Int_t(Double_t(((hh*1./nvectors)-0.5)*40))+1, 11); - Double_t factor = faclts[nquant-1]; + Double_t factor = faclts[TMath::Max(0,nquant-1)]; Double_t sumx =0; Double_t sumx2 =0; Int_t bestindex = -1; Double_t bestmean = 0; - Double_t bestsigma = data[index[nvectors-1]]-data[index[0]]; // maximal possible sigma + Double_t bestsigma = (data[index[nvectors-1]]-data[index[0]]+1.); // maximal possible sigma + bestsigma *=bestsigma; + for (Int_t i=0; iGetNbinsX(); + Float_t nentries = his->GetEntries(); + Float_t sum =0; + Float_t mean = 0; + Float_t sigma2 = 0; + Float_t ncumul=0; + for (Int_t ibin=1;ibinGetBinContent(ibin); + Float_t fraction = Float_t(ncumul)/Float_t(nentries); + if (fraction>down && fractionGetBinContent(ibin); + mean+=his->GetBinCenter(ibin)*his->GetBinContent(ibin); + sigma2+=his->GetBinCenter(ibin)*his->GetBinCenter(ibin)*his->GetBinContent(ibin); + } + } + mean/=sum; + sigma2= TMath::Sqrt(TMath::Abs(sigma2/sum-mean*mean)); + if (param){ + (*param)[0] = his->GetMaximum(); + (*param)[1] = mean; + (*param)[2] = sigma2; + + } + if (verbose) printf("Mean\t%f\t Sigma2\t%f\n", mean,sigma2); +} + +void AliMathBase::LTM(TH1F * his, TVectorD *param , Float_t fraction, Bool_t verbose){ + // + // LTM + // + Int_t nbins = his->GetNbinsX(); + Int_t nentries = (Int_t)his->GetEntries(); + Double_t *data = new Double_t[nentries]; + Int_t npoints=0; + for (Int_t ibin=1;ibinGetBinContent(ibin); + Float_t xcenter= his->GetBinCenter(ibin); + for (Int_t ic=0; icGetMaximum(); + (*param)[1] = mean; + (*param)[2] = sigma; + } +} + +Double_t AliMathBase::FitGaus(TH1F* his, TVectorD *param, TMatrixD *matrix, Float_t xmin, Float_t xmax, Bool_t verbose){ + // + // Fit histogram with gaussian function + // + // Prameters: + // return value- chi2 - if negative ( not enough points) + // his - input histogram + // param - vector with parameters + // xmin, xmax - range to fit - if xmin=xmax=0 - the full histogram range used + // Fitting: + // 1. Step - make logarithm + // 2. Linear fit (parabola) - more robust - always converge + // 3. In case of small statistic bins are averaged + // + static TLinearFitter fitter(3,"pol2"); + TVectorD par(3); + TVectorD sigma(3); + TMatrixD mat(3,3); + if (his->GetMaximum()<4) return -1; + if (his->GetEntries()<12) return -1; + if (his->GetRMS()GetEntries()*his->GetBinWidth(1)/TMath::Sqrt((TMath::TwoPi()*his->GetRMS())); + Int_t dsmooth = TMath::Nint(6./TMath::Sqrt(maxEstimate)); + + if (maxEstimate<1) return -1; + Int_t nbins = his->GetNbinsX(); + Int_t npoints=0; + // + + + if (xmin>=xmax){ + xmin = his->GetXaxis()->GetXmin(); + xmax = his->GetXaxis()->GetXmax(); + } + for (Int_t iter=0; iter<2; iter++){ + fitter.ClearPoints(); + npoints=0; + for (Int_t ibin=1;ibinGetBinContent(ibin); + for (Int_t delta = -dsmooth; delta<=dsmooth; delta++){ + if (ibin+delta>1 &&ibin+deltaGetBinContent(ibin+delta); + countB++; + } + } + entriesI/=countB; + Double_t xcenter= his->GetBinCenter(ibin); + if (xcenterxmax) continue; + Double_t error=1./TMath::Sqrt(countB); + Float_t cont=2; + if (iter>0){ + if (par[0]+par[1]*xcenter+par[2]*xcenter*xcenter>20) return 0; + cont = TMath::Exp(par[0]+par[1]*xcenter+par[2]*xcenter*xcenter); + if (cont>1.) error = 1./TMath::Sqrt(cont*Float_t(countB)); + } + if (entriesI>1&&cont>1){ + fitter.AddPoint(&xcenter,TMath::Log(Float_t(entriesI)),error); + npoints++; + } + } + if (npoints>3){ + fitter.Eval(); + fitter.GetParameters(par); + }else{ + break; + } + } + if (npoints<=3){ + return -1; + } + fitter.GetParameters(par); + fitter.GetCovarianceMatrix(mat); + if (TMath::Abs(par[1])Print(); + printf("Chi2=%f\n",chi2); + TF1 * f1= new TF1("f1","[0]*exp(-(x-[1])^2/(2*[2]*[2]))",his->GetXaxis()->GetXmin(),his->GetXaxis()->GetXmax()); + f1->SetParameter(0, (*param)[0]); + f1->SetParameter(1, (*param)[1]); + f1->SetParameter(2, (*param)[2]); + f1->Draw("same"); + } + return chi2; +} + +Double_t AliMathBase::FitGaus(Float_t *arr, Int_t nBins, Float_t xMin, Float_t xMax, TVectorD *param, TMatrixD *matrix, Bool_t verbose){ + // + // Fit histogram with gaussian function + // + // Prameters: + // nbins: size of the array and number of histogram bins + // xMin, xMax: histogram range + // param: paramters of the fit (0-Constant, 1-Mean, 2-Sigma) + // matrix: covariance matrix -- not implemented yet, pass dummy matrix!!! + // + // Return values: + // >0: the chi2 returned by TLinearFitter + // -3: only three points have been used for the calculation - no fitter was used + // -2: only two points have been used for the calculation - center of gravity was uesed for calculation + // -1: only one point has been used for the calculation - center of gravity was uesed for calculation + // -4: invalid result!! + // + // Fitting: + // 1. Step - make logarithm + // 2. Linear fit (parabola) - more robust - always converge + // + static TLinearFitter fitter(3,"pol2"); + static TMatrixD mat(3,3); + static Double_t kTol = mat.GetTol(); + fitter.StoreData(kFALSE); + fitter.ClearPoints(); + TVectorD par(3); + TVectorD sigma(3); + TMatrixD A(3,3); + TMatrixD b(3,1); + Float_t rms = TMath::RMS(nBins,arr); + Float_t max = TMath::MaxElement(nBins,arr); + Float_t binWidth = (xMax-xMin)/(Float_t)nBins; + + Float_t meanCOG = 0; + Float_t rms2COG = 0; + Float_t sumCOG = 0; + + Float_t entries = 0; + Int_t nfilled=0; + + for (Int_t i=0; i0) nfilled++; + } + + if (max<4) return -4; + if (entries<12) return -4; + if (rms1){ + Double_t xcenter = xMin+(ibin+0.5)*binWidth; + + Float_t error = 1./TMath::Sqrt(entriesI); + Float_t val = TMath::Log(Float_t(entriesI)); + fitter.AddPoint(&xcenter,val,error); + if (npoints<3){ + A(npoints,0)=1; + A(npoints,1)=xcenter; + A(npoints,2)=xcenter*xcenter; + b(npoints,0)=val; + meanCOG+=xcenter*entriesI; + rms2COG +=xcenter*entriesI*xcenter; + sumCOG +=entriesI; + } + npoints++; + } + } + + + Double_t chi2 = 0; + if (npoints>=3){ + if ( npoints == 3 ){ + //analytic calculation of the parameters for three points + A.Invert(); + TMatrixD res(1,3); + res.Mult(A,b); + par[0]=res(0,0); + par[1]=res(0,1); + par[2]=res(0,2); + chi2 = -3.; + } else { + // use fitter for more than three points + fitter.Eval(); + fitter.GetParameters(par); + fitter.GetCovarianceMatrix(mat); + chi2 = fitter.GetChisquare()/Float_t(npoints); + } + if (TMath::Abs(par[1])307 ) return -4; + (*param)[0] = TMath::Exp(lnparam0); + if (verbose){ + par.Print(); + mat.Print(); + param->Print(); + printf("Chi2=%f\n",chi2); + TF1 * f1= new TF1("f1","[0]*exp(-(x-[1])^2/(2*[2]*[2]))",xMin,xMax); + f1->SetParameter(0, (*param)[0]); + f1->SetParameter(1, (*param)[1]); + f1->SetParameter(2, (*param)[2]); + f1->Draw("same"); + } + return chi2; + } + + if (npoints == 2){ + //use center of gravity for 2 points + meanCOG/=sumCOG; + rms2COG /=sumCOG; + (*param)[0] = max; + (*param)[1] = meanCOG; + (*param)[2] = TMath::Sqrt(TMath::Abs(meanCOG*meanCOG-rms2COG)); + chi2=-2.; + } + if ( npoints == 1 ){ + meanCOG/=sumCOG; + (*param)[0] = max; + (*param)[1] = meanCOG; + (*param)[2] = binWidth/TMath::Sqrt(12); + chi2=-1.; + } + return chi2; + +} + + +Float_t AliMathBase::GetCOG(Short_t *arr, Int_t nBins, Float_t xMin, Float_t xMax, Float_t *rms, Float_t *sum) +{ + // + // calculate center of gravity rms and sum for array 'arr' with nBins an a x range xMin to xMax + // return COG; in case of failure return xMin + // + Float_t meanCOG = 0; + Float_t rms2COG = 0; + Float_t sumCOG = 0; + Int_t npoints = 0; + + Float_t binWidth = (xMax-xMin)/(Float_t)nBins; + + for (Int_t ibin=0; ibin0 ){ + meanCOG += xcenter*entriesI; + rms2COG += xcenter*entriesI*xcenter; + sumCOG += entriesI; + npoints++; + } + } + if ( sumCOG == 0 ) return xMin; + meanCOG/=sumCOG; + + if ( rms ){ + rms2COG /=sumCOG; + (*rms) = TMath::Sqrt(TMath::Abs(meanCOG*meanCOG-rms2COG)); + if ( npoints == 1 ) (*rms) = binWidth/TMath::Sqrt(12); + } + + if ( sum ) + (*sum) = sumCOG; + + return meanCOG; +} + + + +/////////////////////////////////////////////////////////////// +////////////// TEST functions ///////////////////////// +/////////////////////////////////////////////////////////////// + + + + + +void AliMathBase::TestGausFit(Int_t nhistos){ + // + // Test performance of the parabolic - gaussian fit - compare it with + // ROOT gauss fit + // nhistos - number of histograms to be used for test + // + TTreeSRedirector *pcstream = new TTreeSRedirector("fitdebug.root"); + + Float_t *xTrue = new Float_t[nhistos]; + Float_t *sTrue = new Float_t[nhistos]; + TVectorD **par1 = new TVectorD*[nhistos]; + TVectorD **par2 = new TVectorD*[nhistos]; + TMatrixD dummy(3,3); + + + TH1F **h1f = new TH1F*[nhistos]; + TF1 *myg = new TF1("myg","gaus"); + TF1 *fit = new TF1("fit","gaus"); + gRandom->SetSeed(0); + + //init + for (Int_t i=0;iRndm(); + gSystem->Sleep(2); + sTrue[i]= .75+gRandom->Rndm()*.5; + myg->SetParameters(1,xTrue[i],sTrue[i]); + h1f[i]->FillRandom("myg"); + } + + TStopwatch s; + s.Start(); + //standard gaus fit + for (Int_t i=0; iFit(fit,"0q"); + (*par1[i])(0) = fit->GetParameter(0); + (*par1[i])(1) = fit->GetParameter(1); + (*par1[i])(2) = fit->GetParameter(2); + } + s.Stop(); + printf("Gaussian fit\t"); + s.Print(); + + s.Start(); + //AliMathBase gaus fit + for (Int_t i=0; iGetArray()+1,h1f[i]->GetNbinsX(),h1f[i]->GetXaxis()->GetXmin(),h1f[i]->GetXaxis()->GetXmax(),par2[i],&dummy); + } + + s.Stop(); + printf("Parabolic fit\t"); + s.Print(); + //write stream + for (Int_t i=0;i