X-Git-Url: http://git.uio.no/git/?a=blobdiff_plain;f=STEER%2FAliMathBase.cxx;h=cdae2369d06d0477342b06bbae8e26c2f9a8c7d2;hb=b5db117133fb58fc8399a368a6333ff795d99d8a;hp=1c8c5ec30f341f3f760a11a6745153e7c2a10811;hpb=f6659a9d8b9d1566f930bcdb14fb130a0a9039e8;p=u%2Fmrichter%2FAliRoot.git diff --git a/STEER/AliMathBase.cxx b/STEER/AliMathBase.cxx index 1c8c5ec30f3..cdae2369d06 100644 --- a/STEER/AliMathBase.cxx +++ b/STEER/AliMathBase.cxx @@ -25,19 +25,35 @@ #include "AliMathBase.h" #include "Riostream.h" #include "TH1F.h" +#include "TH3.h" #include "TF1.h" #include "TLinearFitter.h" + +#include "AliExternalTrackParam.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 + // } @@ -68,7 +84,9 @@ void AliMathBase::EvaluateUni(Int_t nvectors, Double_t *data, Double_t &mean 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; iGetMaximum()<4) return -1; if (his->GetEntries()<12) return -1; if (his->GetRMS()GetEntries()*his->GetBinWidth(1)/TMath::Sqrt((2.*TMath::Pi()*his->GetRMS())); + Float_t maxEstimate = his->GetEntries()*his->GetBinWidth(1)/TMath::Sqrt((TMath::TwoPi()*his->GetRMS())); Int_t dsmooth = TMath::Nint(6./TMath::Sqrt(maxEstimate)); if (maxEstimate<1) return -1; @@ -296,7 +314,7 @@ Double_t AliMathBase::FitGaus(TH1F* his, TVectorD *param, TMatrixD *matrix, Flo 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++){ @@ -355,4 +373,415 @@ Double_t AliMathBase::FitGaus(TH1F* his, TVectorD *param, TMatrixD *matrix, Flo 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, 3-Sum) + // 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++; + } + (*param)[0] = 0; + (*param)[1] = 0; + (*param)[2] = 0; + (*param)[3] = 0; + + 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])GetNrows()<4 ) param->ResizeTo(4); + if (!matrix) matrix = new TMatrixD(3,3); // !!!!might be a memory leek. use dummy matrix pointer to call this function! + + (*param)[1] = par[1]/(-2.*par[2]); + (*param)[2] = 1./TMath::Sqrt(TMath::Abs(-2.*par[2])); + Double_t lnparam0 = par[0]+ par[1]* (*param)[1] + par[2]*(*param)[1]*(*param)[1]; + if ( lnparam0>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; +} + +Double_t AliMathBase::ErfcFast(Double_t x){ + // Fast implementation of the complementary error function + // The error of the approximation is |eps(x)| < 5E-4 + // See Abramowitz and Stegun, p.299, 7.1.27 + + Double_t z = TMath::Abs(x); + Double_t ans = 1+z*(0.278393+z*(0.230389+z*(0.000972+z*0.078108))); + ans = 1.0/ans; + ans *= ans; + ans *= ans; + + return (x>=0.0 ? ans : 2.0 - ans); +} + +/////////////////////////////////////////////////////////////// +////////////// 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;iGetXaxis(); + TAxis * yaxis = his->GetYaxis(); + // TAxis * zaxis = his->GetZaxis(); + Int_t nbinx = xaxis->GetNbins(); + Int_t nbiny = yaxis->GetNbins(); + char name[1000]; + Int_t icount=0; + TGraph2D *graph = new TGraph2D(nbinx*nbiny); + TF1 f1("f1","gaus"); + for (Int_t ix=0; ixGetBinCenter(ix); + Float_t ycenter = yaxis->GetBinCenter(iy); + sprintf(name,"%s_%d_%d",his->GetName(), ix,iy); + TH1 *projection = his->ProjectionZ(name,ix-delta0,ix+delta0,iy-delta1,iy+delta1); + Float_t stat= 0; + if (type==0) stat = projection->GetMean(); + if (type==1) stat = projection->GetRMS(); + if (type==2 || type==3){ + TVectorD vec(3); + AliMathBase::LTM((TH1F*)projection,&vec,0.7); + if (type==2) stat= vec[1]; + if (type==3) stat= vec[0]; + } + if (type==4|| type==5){ + projection->Fit(&f1); + if (type==4) stat= f1.GetParameter(1); + if (type==5) stat= f1.GetParameter(2); + } + //printf("%d\t%f\t%f\t%f\n", icount,xcenter, ycenter, stat); + graph->SetPoint(icount,xcenter, ycenter, stat); + icount++; + } + return graph; +} + +TGraph * AliMathBase::MakeStat1D(TH3 * his, Int_t delta1, Int_t type){ + // + // + // + // delta - number of bins to integrate + // type - 0 - mean value + + TAxis * xaxis = his->GetXaxis(); + TAxis * yaxis = his->GetYaxis(); + // TAxis * zaxis = his->GetZaxis(); + Int_t nbinx = xaxis->GetNbins(); + Int_t nbiny = yaxis->GetNbins(); + char name[1000]; + Int_t icount=0; + TGraph *graph = new TGraph(nbinx); + TF1 f1("f1","gaus"); + for (Int_t ix=0; ixGetBinCenter(ix); + // Float_t ycenter = yaxis->GetBinCenter(iy); + sprintf(name,"%s_%d",his->GetName(), ix); + TH1 *projection = his->ProjectionZ(name,ix-delta1,ix+delta1,0,nbiny); + Float_t stat= 0; + if (type==0) stat = projection->GetMean(); + if (type==1) stat = projection->GetRMS(); + if (type==2 || type==3){ + TVectorD vec(3); + AliMathBase::LTM((TH1F*)projection,&vec,0.7); + if (type==2) stat= vec[1]; + if (type==3) stat= vec[0]; + } + if (type==4|| type==5){ + projection->Fit(&f1); + if (type==4) stat= f1.GetParameter(1); + if (type==5) stat= f1.GetParameter(2); + } + //printf("%d\t%f\t%f\t%f\n", icount,xcenter, ycenter, stat); + graph->SetPoint(icount,xcenter, stat); + icount++; + } + return graph; +} + +Double_t AliMathBase::TruncatedGaus(Double_t mean, Double_t sigma, Double_t cutat) +{ + // return number generated according to a gaussian distribution N(mean,sigma) truncated at cutat + // + Double_t value; + do{ + value=gRandom->Gaus(mean,sigma); + }while(TMath::Abs(value-mean)>cutat); + return value; +} + +Double_t AliMathBase::TruncatedGaus(Double_t mean, Double_t sigma, Double_t leftCut, Double_t rightCut) +{ + // return number generated according to a gaussian distribution N(mean,sigma) + // truncated at leftCut and rightCut + // + Double_t value; + do{ + value=gRandom->Gaus(mean,sigma); + }while((value-mean)<-leftCut || (value-mean)>rightCut); + return value; +} + +Double_t AliMathBase::BetheBlochAleph(Double_t bg, + Double_t kp1, + Double_t kp2, + Double_t kp3, + Double_t kp4, + Double_t kp5) { + // + // This is the empirical ALEPH parameterization of the Bethe-Bloch formula. + // It is normalized to 1 at the minimum. + // + // bg - beta*gamma + // + // The default values for the kp* parameters are for ALICE TPC. + // The returned value is in MIP units + // + + return AliExternalTrackParam::BetheBlochAleph(bg,kp1,kp2,kp3,kp4,kp5); +}