LCOV - code coverage report
Current view: top level - STAT - TStatToolkit.cxx (source / functions) Hit Total Coverage
Test: coverage.info Lines: 0 1415 0.0 %
Date: 2016-06-14 17:26:59 Functions: 0 38 0.0 %

          Line data    Source code
       1             : /**************************************************************************
       2             :  * Copyright(c) 1998-1999, ALICE Experiment at CERN, All rights reserved. *
       3             :  *                                                                        *
       4             :  * Author: The ALICE Off-line Project.                                    *
       5             :  * Contributors are mentioned in the code where appropriate.              *
       6             :  *                                                                        *
       7             :  * Permission to use, copy, modify and distribute this software and its   *
       8             :  * documentation strictly for non-commercial purposes is hereby granted   *
       9             :  * without fee, provided that the above copyright notice appears in all   *
      10             :  * copies and that both the copyright notice and this permission notice   *
      11             :  * appear in the supporting documentation. The authors make no claims     *
      12             :  * about the suitability of this software for any purpose. It is          *
      13             :  * provided "as is" without express or implied warranty.                  *
      14             :  **************************************************************************/
      15             : 
      16             : 
      17             : ///////////////////////////////////////////////////////////////////////////
      18             : /// \file TStatToolkit.cxx
      19             : /// \class TStatToolkit
      20             : /// \brief Summary of statistics functions
      21             : /// Subset of  matheamtical functions  not included in the TMath
      22             : //
      23             : //
      24             : /////////////////////////////////////////////////////////////////////////
      25             : #include "TStopwatch.h"
      26             : #include "TStatToolkit.h"
      27             : #include "TTreeFormula.h"
      28             : 
      29             : using std::cout;
      30             : using std::cerr;
      31             : using std::endl;
      32             : 
      33             : //_____________________________________________________________________________
      34             : void TStatToolkit::EvaluateUni(Int_t nvectors, Double_t *data, Double_t &mean
      35             :                            , Double_t &sigma, Int_t hh)
      36             : {
      37             :   //
      38             :   // Robust estimator in 1D case MI version - (faster than ROOT version)
      39             :   //
      40             :   // For the univariate case
      41             :   // estimates of location and scatter are returned in mean and sigma parameters
      42             :   // the algorithm works on the same principle as in multivariate case -
      43             :   // it finds a subset of size hh with smallest sigma, and then returns mean and
      44             :   // sigma of this subset
      45             :   //
      46             : 
      47           0 :   if (hh==0)
      48           0 :     hh=(nvectors+2)/2;
      49           0 :   Double_t faclts[]={2.6477,2.5092,2.3826,2.2662,2.1587,2.0589,1.9660,1.879,1.7973,1.7203,1.6473};
      50           0 :   Int_t *index=new Int_t[nvectors];
      51           0 :   TMath::Sort(nvectors, data, index, kFALSE);
      52             :   
      53           0 :   Int_t    nquant = TMath::Min(Int_t(Double_t(((hh*1./nvectors)-0.5)*40))+1, 11);
      54           0 :   Double_t factor = faclts[TMath::Max(0,nquant-1)];
      55             :   
      56             :   Double_t sumx  =0;
      57             :   Double_t sumx2 =0;
      58             :   Int_t    bestindex = -1;
      59             :   Double_t bestmean  = 0; 
      60           0 :   Double_t bestsigma = (data[index[nvectors-1]]-data[index[0]]+1.);   // maximal possible sigma
      61           0 :   bestsigma *=bestsigma;
      62             : 
      63           0 :   for (Int_t i=0; i<hh; i++){
      64           0 :     sumx  += data[index[i]];
      65           0 :     sumx2 += data[index[i]]*data[index[i]];
      66             :   }
      67             :   
      68           0 :   Double_t norm = 1./Double_t(hh);
      69           0 :   Double_t norm2 = (hh-1)>0 ? 1./Double_t(hh-1):1;
      70           0 :   for (Int_t i=hh; i<nvectors; i++){
      71           0 :     Double_t cmean  = sumx*norm;
      72           0 :     Double_t csigma = (sumx2 - hh*cmean*cmean)*norm2;
      73           0 :     if (csigma<bestsigma){
      74             :       bestmean  = cmean;
      75             :       bestsigma = csigma;
      76             :       bestindex = i-hh;
      77           0 :     }
      78             :     
      79           0 :     sumx  += data[index[i]]-data[index[i-hh]];
      80           0 :     sumx2 += data[index[i]]*data[index[i]]-data[index[i-hh]]*data[index[i-hh]];
      81             :   }
      82             :   
      83           0 :   Double_t bstd=factor*TMath::Sqrt(TMath::Abs(bestsigma));
      84           0 :   mean  = bestmean;
      85           0 :   sigma = bstd;
      86           0 :   delete [] index;
      87             : 
      88           0 : }
      89             : 
      90             : 
      91             : 
      92             : void TStatToolkit::EvaluateUniExternal(Int_t nvectors, Double_t *data, Double_t &mean, Double_t &sigma, Int_t hh,  Float_t externalfactor)
      93             : {
      94             :   // Modified version of ROOT robust EvaluateUni
      95             :   // robust estimator in 1D case MI version
      96             :   // added external factor to include precision of external measurement
      97             :   // 
      98             : 
      99           0 :   if (hh==0)
     100           0 :     hh=(nvectors+2)/2;
     101           0 :   Double_t faclts[]={2.6477,2.5092,2.3826,2.2662,2.1587,2.0589,1.9660,1.879,1.7973,1.7203,1.6473};
     102           0 :   Int_t *index=new Int_t[nvectors];
     103           0 :   TMath::Sort(nvectors, data, index, kFALSE);
     104             :   //
     105           0 :   Int_t    nquant = TMath::Min(Int_t(Double_t(((hh*1./nvectors)-0.5)*40))+1, 11);
     106           0 :   Double_t factor = faclts[0];
     107           0 :   if (nquant>0){
     108             :     // fix proper normalization - Anja
     109           0 :     factor = faclts[nquant-1];
     110           0 :   }
     111             : 
     112             :   //
     113             :   //
     114             :   Double_t sumx  =0;
     115             :   Double_t sumx2 =0;
     116             :   Int_t    bestindex = -1;
     117             :   Double_t bestmean  = 0; 
     118             :   Double_t bestsigma = -1;
     119           0 :   for (Int_t i=0; i<hh; i++){
     120           0 :     sumx  += data[index[i]];
     121           0 :     sumx2 += data[index[i]]*data[index[i]];
     122             :   }
     123             :   //   
     124           0 :   Double_t kfactor = 2.*externalfactor - externalfactor*externalfactor;
     125           0 :   Double_t norm = 1./Double_t(hh);
     126           0 :   for (Int_t i=hh; i<nvectors; i++){
     127           0 :     Double_t cmean  = sumx*norm;
     128           0 :     Double_t csigma = (sumx2*norm - cmean*cmean*kfactor);
     129           0 :     if (csigma<bestsigma ||  bestsigma<0){
     130             :       bestmean  = cmean;
     131             :       bestsigma = csigma;
     132             :       bestindex = i-hh;
     133           0 :     }
     134             :     //
     135             :     //
     136           0 :     sumx  += data[index[i]]-data[index[i-hh]];
     137           0 :     sumx2 += data[index[i]]*data[index[i]]-data[index[i-hh]]*data[index[i-hh]];
     138             :   }
     139             :   
     140           0 :   Double_t bstd=factor*TMath::Sqrt(TMath::Abs(bestsigma));
     141           0 :   mean  = bestmean;
     142           0 :   sigma = bstd;
     143           0 :   delete [] index;
     144           0 : }
     145             : 
     146             : 
     147             : //_____________________________________________________________________________
     148             : Int_t TStatToolkit::Freq(Int_t n, const Int_t *inlist
     149             :                         , Int_t *outlist, Bool_t down)
     150             : {    
     151             :   //
     152             :   //  Sort eleements according occurancy 
     153             :   //  The size of output array has is 2*n 
     154             :   //
     155             : 
     156           0 :   Int_t * sindexS = new Int_t[n];     // temp array for sorting
     157           0 :   Int_t * sindexF = new Int_t[2*n];   
     158           0 :   for (Int_t i=0;i<n;i++) sindexS[i]=0;
     159           0 :   for (Int_t i=0;i<2*n;i++) sindexF[i]=0;
     160             :   //
     161           0 :   TMath::Sort(n,inlist, sindexS, down);  
     162           0 :   Int_t last      = inlist[sindexS[0]];
     163             :   Int_t val       = last;
     164           0 :   sindexF[0]      = 1;
     165           0 :   sindexF[0+n]    = last;
     166             :   Int_t countPos  = 0;
     167             :   //
     168             :   //  find frequency
     169           0 :   for(Int_t i=1;i<n; i++){
     170           0 :     val = inlist[sindexS[i]];
     171           0 :     if (last == val)   sindexF[countPos]++;
     172             :     else{      
     173           0 :       countPos++;
     174           0 :       sindexF[countPos+n] = val;
     175           0 :       sindexF[countPos]++;
     176             :       last =val;
     177             :     }
     178             :   }
     179           0 :   if (last==val) countPos++;
     180             :   // sort according frequency
     181           0 :   TMath::Sort(countPos, sindexF, sindexS, kTRUE);
     182           0 :   for (Int_t i=0;i<countPos;i++){
     183           0 :     outlist[2*i  ] = sindexF[sindexS[i]+n];
     184           0 :     outlist[2*i+1] = sindexF[sindexS[i]];
     185             :   }
     186           0 :   delete [] sindexS;
     187           0 :   delete [] sindexF;
     188             :   
     189           0 :   return countPos;
     190             : 
     191             : }
     192             : 
     193             : 
     194             : 
     195             : void TStatToolkit::MedianFilter(TH1 * his1D, Int_t nmedian){
     196             :   //
     197             :   // Algorithm to filter  histogram
     198             :   // author:  marian.ivanov@cern.ch
     199             :   // Details of algorithm:
     200             :   // http://en.wikipedia.org/w/index.php?title=Median_filter&oldid=582191524
     201             :   // Input parameters:
     202             :   //    his1D - input histogam - to be modiefied by Medianfilter
     203             :   //    nmendian - number of bins in median filter
     204             :   //
     205           0 :   Int_t nbins    = his1D->GetNbinsX();
     206           0 :   TVectorD vectorH(nbins);
     207           0 :   for (Int_t ibin=0; ibin<nbins; ibin++) vectorH[ibin]=his1D->GetBinContent(ibin+1);
     208           0 :   for (Int_t ibin=0; ibin<nbins; ibin++) {
     209           0 :     Int_t index0=ibin-nmedian;
     210           0 :     Int_t index1=ibin+nmedian;
     211           0 :     if (index0<0) {index1+=-index0; index0=0;}
     212           0 :     if (index1>=nbins) {index0-=index1-nbins+1; index1=nbins-1;}    
     213           0 :     Double_t value= TMath::Median(index1-index0,&(vectorH.GetMatrixArray()[index0]));
     214           0 :     his1D->SetBinContent(ibin+1, value);
     215             :   }  
     216           0 : }
     217             : 
     218             : 
     219             : 
     220             : Float_t TStatToolkit::GetCOG(const Short_t *arr, Int_t nBins, Float_t xMin, Float_t xMax, Float_t *rms, Float_t *sum)
     221             : {
     222             :     //
     223             :     //  calculate center of gravity rms and sum for array 'arr' with nBins an a x range xMin to xMax
     224             :     //  return COG; in case of failure return xMin
     225             :     //
     226             :     Float_t meanCOG = 0;
     227             :     Float_t rms2COG = 0;
     228             :     Float_t sumCOG  = 0;
     229             :     Int_t npoints   = 0;
     230             : 
     231           0 :     Float_t binWidth = (xMax-xMin)/(Float_t)nBins;
     232             : 
     233           0 :     for (Int_t ibin=0; ibin<nBins; ibin++){
     234           0 :         Float_t entriesI = (Float_t)arr[ibin];
     235           0 :         Double_t xcenter = xMin+(ibin+0.5)*binWidth;
     236           0 :         if ( entriesI>0 ){
     237           0 :             meanCOG += xcenter*entriesI;
     238           0 :             rms2COG += xcenter*entriesI*xcenter;
     239           0 :             sumCOG  += entriesI;
     240           0 :             npoints++;
     241           0 :         }
     242             :     }
     243           0 :     if ( sumCOG == 0 ) return xMin;
     244           0 :     meanCOG/=sumCOG;
     245             : 
     246           0 :     if ( rms ){
     247           0 :         rms2COG /=sumCOG;
     248           0 :         (*rms) = TMath::Sqrt(TMath::Abs(meanCOG*meanCOG-rms2COG));
     249           0 :         if ( npoints == 1 ) (*rms) = binWidth/TMath::Sqrt(12);
     250             :     }
     251             : 
     252           0 :     if ( sum )
     253           0 :         (*sum) = sumCOG;
     254             : 
     255           0 :     return meanCOG;
     256           0 : }
     257             : 
     258             : 
     259             : 
     260             : ///////////////////////////////////////////////////////////////
     261             : //////////////         TEST functions /////////////////////////
     262             : ///////////////////////////////////////////////////////////////
     263             : 
     264             : 
     265             : 
     266             : 
     267             : 
     268             : void TStatToolkit::TestGausFit(Int_t nhistos){
     269             :   //
     270             :   // Test performance of the parabolic - gaussian fit - compare it with 
     271             :   // ROOT gauss fit
     272             :   //  nhistos - number of histograms to be used for test
     273             :   //
     274           0 :   TTreeSRedirector *pcstream = new TTreeSRedirector("fitdebug.root","recreate");
     275             :   
     276           0 :   Float_t  *xTrue = new Float_t[nhistos];
     277           0 :   Float_t  *sTrue = new Float_t[nhistos];
     278           0 :   TVectorD **par1  = new TVectorD*[nhistos];
     279           0 :   TVectorD **par2  = new TVectorD*[nhistos];
     280           0 :   TMatrixD dummy(3,3);
     281             :   
     282             :   
     283           0 :   TH1F **h1f = new TH1F*[nhistos];
     284           0 :   TF1  *myg = new TF1("myg","gaus");
     285           0 :   TF1  *fit = new TF1("fit","gaus");
     286           0 :   gRandom->SetSeed(0);
     287             :   
     288             :   //init
     289           0 :   for (Int_t i=0;i<nhistos; i++){
     290           0 :     par1[i] = new TVectorD(3);
     291           0 :     par2[i] = new TVectorD(3);
     292           0 :     h1f[i]  = new TH1F(Form("h1f%d",i),Form("h1f%d",i),20,-10,10);
     293           0 :     xTrue[i]= gRandom->Rndm();
     294           0 :     gSystem->Sleep(2);
     295           0 :     sTrue[i]= .75+gRandom->Rndm()*.5;
     296           0 :     myg->SetParameters(1,xTrue[i],sTrue[i]);
     297           0 :     h1f[i]->FillRandom("myg");
     298             :   }
     299             :   
     300           0 :   TStopwatch s; 
     301           0 :   s.Start();
     302             :   //standard gaus fit
     303           0 :   for (Int_t i=0; i<nhistos; i++){
     304           0 :     h1f[i]->Fit(fit,"0q");
     305           0 :     (*par1[i])(0) = fit->GetParameter(0);
     306           0 :     (*par1[i])(1) = fit->GetParameter(1);
     307           0 :     (*par1[i])(2) = fit->GetParameter(2);
     308             :   }
     309           0 :   s.Stop();
     310           0 :   printf("Gaussian fit\t");
     311           0 :   s.Print();
     312             :   
     313           0 :   s.Start();
     314             :   //TStatToolkit gaus fit
     315           0 :   for (Int_t i=0; i<nhistos; i++){
     316           0 :     TStatToolkit::FitGaus(h1f[i]->GetArray()+1,h1f[i]->GetNbinsX(),h1f[i]->GetXaxis()->GetXmin(),h1f[i]->GetXaxis()->GetXmax(),par2[i],&dummy);
     317             :   }
     318             :   
     319           0 :   s.Stop();
     320           0 :   printf("Parabolic fit\t");
     321           0 :   s.Print();
     322             :   //write stream
     323           0 :   for (Int_t i=0;i<nhistos; i++){
     324           0 :     Float_t xt  = xTrue[i];
     325           0 :     Float_t st  = sTrue[i];
     326           0 :     (*pcstream)<<"data"
     327           0 :                <<"xTrue="<<xt
     328           0 :                <<"sTrue="<<st
     329           0 :                <<"pg.="<<(par1[i])
     330           0 :                <<"pa.="<<(par2[i])
     331           0 :                <<"\n";
     332           0 :   }    
     333             :   //delete pointers
     334           0 :   for (Int_t i=0;i<nhistos; i++){
     335           0 :     delete par1[i];
     336           0 :     delete par2[i];
     337           0 :     delete h1f[i];
     338             :   }
     339           0 :   delete pcstream;
     340           0 :   delete []h1f;
     341           0 :   delete []xTrue;
     342           0 :   delete []sTrue;
     343             :   //
     344           0 :   delete []par1;
     345           0 :   delete []par2;
     346             : 
     347           0 : }
     348             : 
     349             : 
     350             : 
     351             : TGraph2D * TStatToolkit::MakeStat2D(TH3 * his, Int_t delta0, Int_t delta1, Int_t type){
     352             :   //
     353             :   //
     354             :   //
     355             :   // delta - number of bins to integrate
     356             :   // type - 0 - mean value
     357             : 
     358           0 :   TAxis * xaxis  = his->GetXaxis();
     359           0 :   TAxis * yaxis  = his->GetYaxis();
     360             :   //  TAxis * zaxis  = his->GetZaxis();
     361           0 :   Int_t   nbinx  = xaxis->GetNbins();
     362           0 :   Int_t   nbiny  = yaxis->GetNbins();
     363           0 :   char name[1000];
     364             :   Int_t icount=0;
     365           0 :   TGraph2D  *graph = new TGraph2D(nbinx*nbiny);
     366           0 :   TF1 f1("f1","gaus");
     367           0 :   for (Int_t ix=0; ix<nbinx;ix++)
     368           0 :     for (Int_t iy=0; iy<nbiny;iy++){
     369           0 :       Float_t xcenter = xaxis->GetBinCenter(ix); 
     370           0 :       Float_t ycenter = yaxis->GetBinCenter(iy); 
     371           0 :       snprintf(name,1000,"%s_%d_%d",his->GetName(), ix,iy);
     372           0 :       TH1 *projection = his->ProjectionZ(name,ix-delta0,ix+delta0,iy-delta1,iy+delta1);
     373             :       Float_t stat= 0;
     374           0 :       if (type==0) stat = projection->GetMean();
     375           0 :       if (type==1) stat = projection->GetRMS();
     376           0 :       if (type==2 || type==3){
     377           0 :         TVectorD vec(10);
     378           0 :         TStatToolkit::LTM((TH1F*)projection,&vec,0.7);
     379           0 :         if (type==2) stat= vec[1];
     380           0 :         if (type==3) stat= vec[0];      
     381           0 :       }
     382           0 :       if (type==4|| type==5){
     383           0 :         projection->Fit(&f1);
     384           0 :         if (type==4) stat= f1.GetParameter(1);
     385           0 :         if (type==5) stat= f1.GetParameter(2);
     386             :       }
     387             :       //printf("%d\t%f\t%f\t%f\n", icount,xcenter, ycenter, stat);
     388           0 :       graph->SetPoint(icount,xcenter, ycenter, stat);
     389           0 :       icount++;
     390             :     }
     391             :   return graph;
     392           0 : }
     393             : 
     394             : TGraphErrors * TStatToolkit::MakeStat1D(TH2 * his, Int_t deltaBin, Double_t fraction, Int_t returnType, Int_t markerStyle, Int_t markerColor){
     395             :   //
     396             :   // function to retrieve the "mean and RMS estimate" of 2D histograms
     397             :   //     
     398             :   // Robust statistic to estimate properties of the distribution
     399             :   // See http://en.wikipedia.org/wiki/Trimmed_estimator
     400             :   //
     401             :   // deltaBin - number of bins to integrate (bin+-deltaBin)
     402             :   // fraction - fraction of values for the LTM and for the gauss fit
     403             :   // returnType - 
     404             :   //        0 - mean value
     405             :   //        1 - RMS
     406             :   //        2 - LTM mean
     407             :   //        3 - LTM sigma
     408             :   //        4 - Gaus fit mean  - on LTM range
     409             :   //        5 - Gaus fit sigma - on LTM  range
     410             :   //        6 - Robust bin median
     411             :   // 
     412           0 :   TAxis * xaxis  = his->GetXaxis();
     413           0 :   Int_t   nbinx  = xaxis->GetNbins();
     414           0 :   char name[1000];
     415             :   Int_t icount=0;
     416             :   //
     417           0 :   TVectorD vecX(nbinx);
     418           0 :   TVectorD vecXErr(nbinx);
     419           0 :   TVectorD vecY(nbinx);
     420           0 :   TVectorD vecYErr(nbinx);
     421             :   //
     422           0 :   TF1 f1("f1","gaus");
     423           0 :   TVectorD vecLTM(10);
     424             : 
     425           0 :   for (Int_t jx=1; jx<=nbinx;jx++){
     426           0 :     Int_t ix=jx-1;
     427           0 :     Float_t xcenter = xaxis->GetBinCenter(jx); 
     428           0 :     snprintf(name,1000,"%s_%d",his->GetName(), ix);
     429           0 :     TH1 *projection = his->ProjectionY(name,TMath::Max(jx-deltaBin,1),TMath::Min(jx+deltaBin,nbinx));
     430             :     Double_t stat= 0;
     431             :     Double_t err =0;
     432           0 :     TStatToolkit::LTMHisto((TH1F*)projection,vecLTM,fraction);  
     433             :     //
     434           0 :     if (returnType==0) {
     435           0 :       stat = projection->GetMean();
     436           0 :       err  = projection->GetMeanError();
     437           0 :     }
     438           0 :     else if (returnType==1) {
     439           0 :       stat = projection->GetRMS();
     440           0 :       err = projection->GetRMSError();
     441           0 :     }
     442           0 :     else if (returnType==2 || returnType==3){
     443           0 :       if (returnType==2) {stat= vecLTM[1];  err =projection->GetRMSError();}
     444           0 :         if (returnType==3) {stat= vecLTM[2];     err =projection->GetRMSError();}
     445             :     }
     446           0 :     else if (returnType==4|| returnType==5){
     447           0 :       f1.SetParameters(vecLTM[0], vecLTM[1], vecLTM[2]+0.05);
     448           0 :       projection->Fit(&f1,"QN","QN", vecLTM[7]-vecLTM[2], vecLTM[8]+vecLTM[2]);
     449           0 :       if (returnType==4) {
     450           0 :         stat= f1.GetParameter(1);
     451           0 :         err=f1.GetParError(1);
     452           0 :       }
     453           0 :       if (returnType==5) {
     454           0 :         stat= f1.GetParameter(2);
     455           0 :         err=f1.GetParError(2);
     456           0 :       }
     457             :     }
     458           0 :     else if (returnType==6) {
     459           0 :       stat=RobustBinMedian(projection,fraction);
     460           0 :     }
     461             : 
     462           0 :     vecX[icount]=xcenter;
     463           0 :     vecY[icount]=stat;
     464           0 :     vecYErr[icount]=err;
     465           0 :     icount++;
     466           0 :     delete projection;
     467             :   }
     468           0 :   TGraphErrors  *graph = new TGraphErrors(icount,vecX.GetMatrixArray(), vecY.GetMatrixArray(),0, vecYErr.GetMatrixArray());
     469           0 :   graph->SetMarkerStyle(markerStyle);
     470           0 :   graph->SetMarkerColor(markerColor);
     471             :   return graph;
     472           0 : }
     473             : 
     474             : Double_t TStatToolkit::RobustBinMedian(TH1* hist, Double_t fractionCut/*=1.*/)
     475             : {
     476             :   // Robust median with average from neighbouring bins
     477           0 :   const Int_t nbins1D=hist->GetNbinsX();
     478             :   Double_t binMedian=0;
     479           0 :   Double_t limits[2]={hist->GetBinCenter(1), hist->GetBinCenter(nbins1D)};
     480             : 
     481           0 :   Double_t* integral=hist->GetIntegral();
     482           0 :   for (Int_t i=1; i<nbins1D-1; i++){
     483           0 :     if (integral[i-1]<0.5 && integral[i]>=0.5){
     484           0 :       if (hist->GetBinContent(i-1)+hist->GetBinContent(i)>0){
     485           0 :         binMedian=hist->GetBinCenter(i);
     486           0 :         Double_t dIdx=-(integral[i-1]-integral[i]);
     487           0 :         Double_t dx=(0.5+(0.5-integral[i])/dIdx)*hist->GetBinWidth(i);
     488           0 :         binMedian+=dx;
     489           0 :       }
     490             :     }
     491           0 :     if (integral[i-1]<fractionCut && integral[i]>=fractionCut){
     492           0 :       limits[0]=hist->GetBinCenter(i-1)-hist->GetBinWidth(i);
     493           0 :     }
     494           0 :     if (integral[i]<1-fractionCut && integral[i+1]>=1-fractionCut){
     495           0 :       limits[1]=hist->GetBinCenter(i+1)+hist->GetBinWidth(i);
     496           0 :     }
     497             :   }
     498             : 
     499           0 :   return binMedian;
     500             : }
     501             : 
     502             : 
     503             : TString* TStatToolkit::FitPlane(TTree *tree, const char* drawCommand, const char* formula, const char* cuts, Double_t & chi2, Int_t &npoints, TVectorD &fitParam, TMatrixD &covMatrix, Float_t frac, Int_t start, Int_t stop,Bool_t fix0){
     504             :    //
     505             :    // fit an arbitrary function, specified by formula into the data, specified by drawCommand and cuts
     506             :    // returns chi2, fitParam and covMatrix
     507             :    // returns TString with fitted formula
     508             :    //
     509             : 
     510           0 :    TString formulaStr(formula); 
     511           0 :    TString drawStr(drawCommand);
     512           0 :    TString cutStr(cuts);
     513           0 :    TString ferr("1");
     514             : 
     515           0 :    TString strVal(drawCommand);
     516           0 :    if (strVal.Contains(":")){
     517           0 :      TObjArray* valTokens = strVal.Tokenize(":");
     518           0 :      drawStr = valTokens->At(0)->GetName();
     519           0 :      ferr       = valTokens->At(1)->GetName();     
     520           0 :      delete valTokens;
     521           0 :    }
     522             : 
     523             :       
     524           0 :    formulaStr.ReplaceAll("++", "~");
     525           0 :    TObjArray* formulaTokens = formulaStr.Tokenize("~"); 
     526           0 :    Int_t dim = formulaTokens->GetEntriesFast();
     527             :    
     528           0 :    fitParam.ResizeTo(dim);
     529           0 :    covMatrix.ResizeTo(dim,dim);
     530             :    
     531           0 :    TLinearFitter* fitter = new TLinearFitter(dim+1, Form("hyp%d",dim));
     532           0 :    fitter->StoreData(kTRUE);   
     533           0 :    fitter->ClearPoints();
     534             :    
     535           0 :    Int_t entries = tree->Draw(drawStr.Data(), cutStr.Data(), "goff",  stop-start, start);
     536           0 :    if (entries == -1) {
     537           0 :      delete formulaTokens;
     538           0 :      return new TString(TString::Format("ERROR expr: %s\t%s\tEntries==0",drawStr.Data(),cutStr.Data()));
     539             :    }
     540           0 :    Double_t **values = new Double_t*[dim+1] ;
     541           0 :    for (Int_t i=0; i<dim+1; i++) values[i]=NULL; 
     542             :    //
     543           0 :    entries = tree->Draw(ferr.Data(), cutStr.Data(), "goff",  stop-start, start);
     544           0 :    if (entries == -1) {
     545           0 :      delete formulaTokens;
     546           0 :      delete []values;
     547           0 :      return new TString(TString::Format("ERROR error part: %s\t%s\tEntries==0",ferr.Data(),cutStr.Data()));
     548             :    }
     549           0 :    Double_t *errors = new Double_t[entries];
     550           0 :    memcpy(errors,  tree->GetV1(), entries*sizeof(Double_t));
     551             :    
     552           0 :    for (Int_t i = 0; i < dim + 1; i++){
     553             :       Int_t centries = 0;
     554           0 :       if (i < dim) centries = tree->Draw(((TObjString*)formulaTokens->At(i))->GetName(), cutStr.Data(), "goff", stop-start,start);
     555           0 :       else  centries = tree->Draw(drawStr.Data(), cutStr.Data(), "goff", stop-start,start);
     556             :       
     557           0 :       if (entries != centries) {
     558           0 :         delete []errors;
     559           0 :         delete []values;
     560           0 :         return new TString(TString::Format("ERROR: %s\t%s\tEntries==%d\tEntries2=%d\n",drawStr.Data(),cutStr.Data(),entries,centries));
     561             :       }
     562           0 :       values[i] = new Double_t[entries];
     563           0 :       memcpy(values[i],  tree->GetV1(), entries*sizeof(Double_t)); 
     564           0 :    }
     565             :    
     566             :    // add points to the fitter
     567           0 :    for (Int_t i = 0; i < entries; i++){
     568           0 :       Double_t x[1000];
     569           0 :       for (Int_t j=0; j<dim;j++) x[j]=values[j][i];
     570           0 :       fitter->AddPoint(x, values[dim][i], errors[i]);
     571           0 :    }
     572             : 
     573           0 :    fitter->Eval();
     574           0 :    if (frac>0.5 && frac<1){
     575           0 :      fitter->EvalRobust(frac);
     576             :    }else{
     577           0 :      if (fix0) {
     578           0 :        fitter->FixParameter(0,0);
     579           0 :        fitter->Eval();     
     580             :      }
     581             :    }
     582           0 :    fitter->GetParameters(fitParam);
     583           0 :    fitter->GetCovarianceMatrix(covMatrix);
     584           0 :    chi2 = fitter->GetChisquare();
     585           0 :    npoints = entries;   
     586           0 :    TString *preturnFormula = new TString(Form("( %f+",fitParam[0])), &returnFormula = *preturnFormula; 
     587             :    
     588           0 :    for (Int_t iparam = 0; iparam < dim; iparam++) {
     589           0 :      returnFormula.Append(Form("%s*(%f)",((TObjString*)formulaTokens->At(iparam))->GetName(),fitParam[iparam+1]));
     590           0 :      if (iparam < dim-1) returnFormula.Append("+");
     591             :    }
     592           0 :    returnFormula.Append(" )");
     593             :    
     594             :    
     595           0 :    for (Int_t j=0; j<dim+1;j++) delete [] values[j];
     596             : 
     597             : 
     598           0 :    delete formulaTokens;
     599           0 :    delete fitter;
     600           0 :    delete[] values;
     601           0 :    delete[] errors;
     602             :    return preturnFormula;
     603           0 : }
     604             : 
     605             : TString* TStatToolkit::FitPlaneConstrain(TTree *tree, const char* drawCommand, const char* formula, const char* cuts, Double_t & chi2, Int_t &npoints, TVectorD &fitParam, TMatrixD &covMatrix, Float_t frac, Int_t start, Int_t stop,Double_t constrain){
     606             :    //
     607             :    // fit an arbitrary function, specified by formula into the data, specified by drawCommand and cuts
     608             :    // returns chi2, fitParam and covMatrix
     609             :    // returns TString with fitted formula
     610             :    //
     611             : 
     612           0 :    TString formulaStr(formula); 
     613           0 :    TString drawStr(drawCommand);
     614           0 :    TString cutStr(cuts);
     615           0 :    TString ferr("1");
     616             : 
     617           0 :    TString strVal(drawCommand);
     618           0 :    if (strVal.Contains(":")){
     619           0 :      TObjArray* valTokens = strVal.Tokenize(":");
     620           0 :      drawStr = valTokens->At(0)->GetName();
     621           0 :      ferr       = valTokens->At(1)->GetName();     
     622           0 :      delete valTokens;
     623           0 :    }
     624             : 
     625             :       
     626           0 :    formulaStr.ReplaceAll("++", "~");
     627           0 :    TObjArray* formulaTokens = formulaStr.Tokenize("~"); 
     628           0 :    Int_t dim = formulaTokens->GetEntriesFast();
     629             :    
     630           0 :    fitParam.ResizeTo(dim);
     631           0 :    covMatrix.ResizeTo(dim,dim);
     632             :    
     633           0 :    TLinearFitter* fitter = new TLinearFitter(dim+1, Form("hyp%d",dim));
     634           0 :    fitter->StoreData(kTRUE);   
     635           0 :    fitter->ClearPoints();
     636             :    
     637           0 :    Int_t entries = tree->Draw(drawStr.Data(), cutStr.Data(), "goff",  stop-start, start);
     638           0 :    if (entries == -1) {
     639           0 :      delete formulaTokens;
     640           0 :      return new TString("An ERROR has occured during fitting!");
     641             :    }
     642           0 :    Double_t **values = new Double_t*[dim+1] ; 
     643           0 :    for (Int_t i=0; i<dim+1; i++) values[i]=NULL; 
     644             :    //
     645           0 :    entries = tree->Draw(ferr.Data(), cutStr.Data(), "goff",  stop-start, start);
     646           0 :    if (entries == -1) {
     647           0 :      delete formulaTokens;
     648           0 :      delete [] values;
     649           0 :      return new TString("An ERROR has occured during fitting!");
     650             :    }
     651           0 :    Double_t *errors = new Double_t[entries];
     652           0 :    memcpy(errors,  tree->GetV1(), entries*sizeof(Double_t));
     653             :    
     654           0 :    for (Int_t i = 0; i < dim + 1; i++){
     655             :       Int_t centries = 0;
     656           0 :       if (i < dim) centries = tree->Draw(((TObjString*)formulaTokens->At(i))->GetName(), cutStr.Data(), "goff", stop-start,start);
     657           0 :       else  centries = tree->Draw(drawStr.Data(), cutStr.Data(), "goff", stop-start,start);
     658             :       
     659           0 :       if (entries != centries) {
     660           0 :         delete []errors;
     661           0 :         delete []values;
     662           0 :         delete formulaTokens;
     663           0 :         return new TString("An ERROR has occured during fitting!");
     664             :       }
     665           0 :       values[i] = new Double_t[entries];
     666           0 :       memcpy(values[i],  tree->GetV1(), entries*sizeof(Double_t)); 
     667           0 :    }
     668             :    
     669             :    // add points to the fitter
     670           0 :    for (Int_t i = 0; i < entries; i++){
     671           0 :       Double_t x[1000];
     672           0 :       for (Int_t j=0; j<dim;j++) x[j]=values[j][i];
     673           0 :       fitter->AddPoint(x, values[dim][i], errors[i]);
     674           0 :    }
     675           0 :    if (constrain>0){
     676           0 :      for (Int_t i = 0; i < dim; i++){
     677           0 :        Double_t x[1000];
     678           0 :        for (Int_t j=0; j<dim;j++) if (i!=j) x[j]=0;
     679           0 :        x[i]=1.;
     680           0 :        fitter->AddPoint(x, 0, constrain);
     681           0 :      }
     682           0 :    }
     683             : 
     684             : 
     685           0 :    fitter->Eval();
     686           0 :    if (frac>0.5 && frac<1){
     687           0 :      fitter->EvalRobust(frac);   
     688             :    }
     689           0 :    fitter->GetParameters(fitParam);
     690           0 :    fitter->GetCovarianceMatrix(covMatrix);
     691           0 :    chi2 = fitter->GetChisquare();
     692           0 :    npoints = entries;
     693             :    
     694           0 :    TString *preturnFormula = new TString(Form("( %f+",fitParam[0])), &returnFormula = *preturnFormula; 
     695             :    
     696           0 :    for (Int_t iparam = 0; iparam < dim; iparam++) {
     697           0 :      returnFormula.Append(Form("%s*(%f)",((TObjString*)formulaTokens->At(iparam))->GetName(),fitParam[iparam+1]));
     698           0 :      if (iparam < dim-1) returnFormula.Append("+");
     699             :    }
     700           0 :    returnFormula.Append(" )");
     701             :    
     702           0 :    for (Int_t j=0; j<dim+1;j++) delete [] values[j];
     703             :    
     704             : 
     705             : 
     706           0 :    delete formulaTokens;
     707           0 :    delete fitter;
     708           0 :    delete[] values;
     709           0 :    delete[] errors;
     710             :    return preturnFormula;
     711           0 : }
     712             : 
     713             : 
     714             : 
     715             : TString* TStatToolkit::FitPlaneFixed(TTree *tree, const char* drawCommand, const char* formula, const char* cuts, Double_t & chi2, Int_t &npoints, TVectorD &fitParam, TMatrixD &covMatrix, Float_t frac, Int_t start, Int_t stop){
     716             :    //
     717             :    // fit an arbitrary function, specified by formula into the data, specified by drawCommand and cuts
     718             :    // returns chi2, fitParam and covMatrix
     719             :    // returns TString with fitted formula
     720             :    //
     721             : 
     722           0 :    TString formulaStr(formula); 
     723           0 :    TString drawStr(drawCommand);
     724           0 :    TString cutStr(cuts);
     725           0 :    TString ferr("1");
     726             : 
     727           0 :    TString strVal(drawCommand);
     728           0 :    if (strVal.Contains(":")){
     729           0 :      TObjArray* valTokens = strVal.Tokenize(":");
     730           0 :      drawStr = valTokens->At(0)->GetName();
     731           0 :      ferr       = valTokens->At(1)->GetName();
     732           0 :      delete valTokens;
     733           0 :    }
     734             : 
     735             :       
     736           0 :    formulaStr.ReplaceAll("++", "~");
     737           0 :    TObjArray* formulaTokens = formulaStr.Tokenize("~"); 
     738           0 :    Int_t dim = formulaTokens->GetEntriesFast();
     739             :    
     740           0 :    fitParam.ResizeTo(dim);
     741           0 :    covMatrix.ResizeTo(dim,dim);
     742           0 :    TString fitString="x0";
     743           0 :    for (Int_t i=1; i<dim; i++) fitString+=Form("++x%d",i);     
     744           0 :    TLinearFitter* fitter = new TLinearFitter(dim, fitString.Data());
     745           0 :    fitter->StoreData(kTRUE);   
     746           0 :    fitter->ClearPoints();
     747             :    
     748           0 :    Int_t entries = tree->Draw(drawStr.Data(), cutStr.Data(), "goff",  stop-start, start);
     749           0 :    if (entries == -1) {
     750           0 :      delete formulaTokens;
     751           0 :      return new TString("An ERROR has occured during fitting!");
     752             :    }
     753           0 :    Double_t **values = new Double_t*[dim+1] ; 
     754           0 :    for (Int_t i=0; i<dim+1; i++) values[i]=NULL; 
     755             :    //
     756           0 :    entries = tree->Draw(ferr.Data(), cutStr.Data(), "goff",  stop-start, start);
     757           0 :    if (entries == -1) {
     758           0 :      delete []values;
     759           0 :      delete formulaTokens;
     760           0 :      return new TString("An ERROR has occured during fitting!");
     761             :    }
     762           0 :    Double_t *errors = new Double_t[entries];
     763           0 :    memcpy(errors,  tree->GetV1(), entries*sizeof(Double_t));
     764             :    
     765           0 :    for (Int_t i = 0; i < dim + 1; i++){
     766             :       Int_t centries = 0;
     767           0 :       if (i < dim) centries = tree->Draw(((TObjString*)formulaTokens->At(i))->GetName(), cutStr.Data(), "goff", stop-start,start);
     768           0 :       else  centries = tree->Draw(drawStr.Data(), cutStr.Data(), "goff", stop-start,start);
     769             :       
     770           0 :       if (entries != centries) {
     771           0 :         delete []errors;
     772           0 :         delete []values;
     773           0 :         delete formulaTokens;
     774           0 :         return new TString("An ERROR has occured during fitting!");
     775             :       }
     776           0 :       values[i] = new Double_t[entries];
     777           0 :       memcpy(values[i],  tree->GetV1(), entries*sizeof(Double_t)); 
     778           0 :    }
     779             :    
     780             :    // add points to the fitter
     781           0 :    for (Int_t i = 0; i < entries; i++){
     782           0 :       Double_t x[1000];
     783           0 :       for (Int_t j=0; j<dim;j++) x[j]=values[j][i];
     784           0 :       fitter->AddPoint(x, values[dim][i], errors[i]);
     785           0 :    }
     786             : 
     787           0 :    fitter->Eval();
     788           0 :    if (frac>0.5 && frac<1){
     789           0 :      fitter->EvalRobust(frac);
     790             :    }
     791           0 :    fitter->GetParameters(fitParam);
     792           0 :    fitter->GetCovarianceMatrix(covMatrix);
     793           0 :    chi2 = fitter->GetChisquare();
     794           0 :    npoints = entries;
     795             :    
     796           0 :    TString *preturnFormula = new TString("("), &returnFormula = *preturnFormula; 
     797             :    
     798           0 :    for (Int_t iparam = 0; iparam < dim; iparam++) {
     799           0 :      returnFormula.Append(Form("%s*(%f)",((TObjString*)formulaTokens->At(iparam))->GetName(),fitParam[iparam]));
     800           0 :      if (iparam < dim-1) returnFormula.Append("+");
     801             :    }
     802           0 :    returnFormula.Append(" )");
     803             :    
     804             :    
     805           0 :    for (Int_t j=0; j<dim+1;j++) delete [] values[j];
     806             :    
     807           0 :    delete formulaTokens;
     808           0 :    delete fitter;
     809           0 :    delete[] values;
     810           0 :    delete[] errors;
     811             :    return preturnFormula;
     812           0 : }
     813             : 
     814             : 
     815             : 
     816             : 
     817             : 
     818             : Int_t TStatToolkit::GetFitIndex(const TString fString, const TString subString){
     819             :   //
     820             :   // fitString - ++ separated list of fits
     821             :   // substring - ++ separated list of the requiered substrings
     822             :   //
     823             :   // return the last occurance of substring in fit string
     824             :   // 
     825           0 :   TObjArray *arrFit = fString.Tokenize("++");
     826           0 :   TObjArray *arrSub = subString.Tokenize("++");
     827             :   Int_t index=-1;
     828           0 :   for (Int_t i=0; i<arrFit->GetEntries(); i++){
     829             :     Bool_t isOK=kTRUE;
     830           0 :     TString str =arrFit->At(i)->GetName();
     831           0 :     for (Int_t isub=0; isub<arrSub->GetEntries(); isub++){
     832           0 :       if (str.Contains(arrSub->At(isub)->GetName())==0) isOK=kFALSE;
     833             :     }
     834           0 :     if (isOK) index=i;
     835           0 :   }
     836           0 :   delete arrFit;
     837           0 :   delete arrSub;
     838           0 :   return index;
     839           0 : }
     840             : 
     841             : 
     842             : TString  TStatToolkit::FilterFit(const TString &input, const TString filter, TVectorD &param, TMatrixD & covar){
     843             :   //
     844             :   // Filter fit expression make sub-fit
     845             :   //
     846           0 :   TObjArray *array0= input.Tokenize("++");
     847           0 :   TObjArray *array1= filter.Tokenize("++");
     848             :   //TString *presult=new TString("(0");
     849           0 :   TString result="(0.0";
     850           0 :   for (Int_t i=0; i<array0->GetEntries(); i++){
     851             :     Bool_t isOK=kTRUE;
     852           0 :     TString str(array0->At(i)->GetName());
     853           0 :     for (Int_t j=0; j<array1->GetEntries(); j++){
     854           0 :       if (str.Contains(array1->At(j)->GetName())==0) isOK=kFALSE;      
     855             :     }
     856           0 :     if (isOK) {
     857           0 :       result+="+"+str;
     858           0 :       result+=Form("*(%f)",param[i+1]);
     859           0 :       printf("%f\t%f\t%s\n",param[i+1], TMath::Sqrt(covar(i+1,i+1)),str.Data());    
     860             :     }
     861           0 :   }
     862           0 :   result+="-0.)";
     863           0 :   delete array0;
     864           0 :   delete array1;
     865             :   return result;
     866           0 : }
     867             : 
     868             : void TStatToolkit::Update1D(Double_t delta, Double_t sigma, Int_t s1, TMatrixD &vecXk, TMatrixD &covXk){
     869             :   //
     870             :   // Update parameters and covariance - with one measurement
     871             :   // Input:
     872             :   // vecXk - input vector - Updated in function 
     873             :   // covXk - covariance matrix - Updated in function
     874             :   // delta, sigma, s1 - new measurement, rms of new measurement and the index of measurement
     875             :   const Int_t knMeas=1;
     876           0 :   Int_t knElem=vecXk.GetNrows();
     877             :  
     878           0 :   TMatrixD mat1(knElem,knElem);            // update covariance matrix
     879           0 :   TMatrixD matHk(1,knElem);        // vector to mesurement
     880           0 :   TMatrixD vecYk(knMeas,1);        // Innovation or measurement residual
     881           0 :   TMatrixD matHkT(knElem,knMeas);  // helper matrix Hk transpose
     882           0 :   TMatrixD matSk(knMeas,knMeas);   // Innovation (or residual) covariance
     883           0 :   TMatrixD matKk(knElem,knMeas);   // Optimal Kalman gain
     884           0 :   TMatrixD covXk2(knElem,knElem);  // helper matrix
     885           0 :   TMatrixD covXk3(knElem,knElem);  // helper matrix
     886           0 :   TMatrixD vecZk(1,1);
     887           0 :   TMatrixD measR(1,1);
     888           0 :   vecZk(0,0)=delta;
     889           0 :   measR(0,0)=sigma*sigma;
     890             :   //
     891             :   // reset matHk
     892           0 :   for (Int_t iel=0;iel<knElem;iel++) 
     893           0 :     for (Int_t ip=0;ip<knMeas;ip++) matHk(ip,iel)=0; 
     894             :   //mat1
     895           0 :   for (Int_t iel=0;iel<knElem;iel++) {
     896           0 :     for (Int_t jel=0;jel<knElem;jel++) mat1(iel,jel)=0;
     897           0 :     mat1(iel,iel)=1;
     898             :   }
     899             :   //
     900           0 :   matHk(0, s1)=1;
     901           0 :   vecYk = vecZk-matHk*vecXk;               // Innovation or measurement residual
     902           0 :   matHkT=matHk.T(); matHk.T();
     903           0 :   matSk = (matHk*(covXk*matHkT))+measR;    // Innovation (or residual) covariance
     904           0 :   matSk.Invert();
     905           0 :   matKk = (covXk*matHkT)*matSk;            //  Optimal Kalman gain
     906           0 :   vecXk += matKk*vecYk;                    //  updated vector 
     907           0 :   covXk2= (mat1-(matKk*matHk));
     908           0 :   covXk3 =  covXk2*covXk;          
     909           0 :   covXk = covXk3;  
     910           0 :   Int_t nrows=covXk3.GetNrows();
     911             :   
     912           0 :   for (Int_t irow=0; irow<nrows; irow++)
     913           0 :     for (Int_t icol=0; icol<nrows; icol++){
     914             :       // rounding problems - make matrix again symteric
     915           0 :       covXk(irow,icol)=(covXk3(irow,icol)+covXk3(icol,irow))*0.5; 
     916             :     }
     917           0 : }
     918             : 
     919             : 
     920             : 
     921             : void   TStatToolkit::Constrain1D(const TString &input, const TString filter, TVectorD &param, TMatrixD & covar, Double_t mean, Double_t sigma){
     922             :   //
     923             :   // constrain linear fit
     924             :   // input  - string description of fit function
     925             :   // filter - string filter to select sub fits
     926             :   // param,covar - parameters and covariance matrix of the fit
     927             :   // mean,sigma  - new measurement uning which the fit is updated
     928             :   //
     929             :   
     930           0 :   TObjArray *array0= input.Tokenize("++");
     931           0 :   TObjArray *array1= filter.Tokenize("++");
     932           0 :   TMatrixD paramM(param.GetNrows(),1);
     933           0 :   for (Int_t i=0; i<=array0->GetEntries(); i++){paramM(i,0)=param(i);}
     934             :   
     935           0 :   if (filter.Length()==0){
     936           0 :     TStatToolkit::Update1D(mean, sigma, 0, paramM, covar);//
     937             :   }else{  
     938           0 :     for (Int_t i=0; i<array0->GetEntries(); i++){
     939             :       Bool_t isOK=kTRUE;
     940           0 :       TString str(array0->At(i)->GetName());
     941           0 :       for (Int_t j=0; j<array1->GetEntries(); j++){
     942           0 :         if (str.Contains(array1->At(j)->GetName())==0) isOK=kFALSE;      
     943             :       }
     944           0 :       if (isOK) {
     945           0 :         TStatToolkit::Update1D(mean, sigma, i+1, paramM, covar);//
     946             :       }
     947           0 :     }
     948             :   }
     949           0 :   for (Int_t i=0; i<=array0->GetEntries(); i++){
     950           0 :     param(i)=paramM(i,0);
     951             :   }
     952           0 :   delete array0;
     953           0 :   delete array1;
     954           0 : }
     955             : 
     956             : TString  TStatToolkit::MakeFitString(const TString &input, const TVectorD &param, const TMatrixD & covar, Bool_t verbose){
     957             :   //
     958             :   //
     959             :   //
     960           0 :   TObjArray *array0= input.Tokenize("++");
     961           0 :   TString result=Form("(%f",param[0]);
     962           0 :   printf("%f\t%f\t\n", param[0], TMath::Sqrt(covar(0,0))); 
     963           0 :   for (Int_t i=0; i<array0->GetEntries(); i++){
     964           0 :     TString str(array0->At(i)->GetName());
     965           0 :     result+="+"+str;
     966           0 :     result+=Form("*(%f)",param[i+1]);
     967           0 :     if (verbose) printf("%f\t%f\t%s\n", param[i+1], TMath::Sqrt(covar(i+1,i+1)),str.Data());    
     968           0 :   }
     969           0 :   result+="-0.)";
     970           0 :   delete array0;
     971             :   return result;
     972           0 : }
     973             : 
     974             : TGraphErrors * TStatToolkit::MakeGraphErrors(TTree * tree, const char * expr, const char * cut,  Int_t mstyle, Int_t mcolor, Float_t msize, Float_t offset, Int_t drawEntries, Int_t firstEntry){
     975             :   //
     976             :   // Query a graph errors
     977             :   // return TGraphErrors specified by expr and cut 
     978             :   // Example  usage TStatToolkit::MakeGraphError(tree,"Y:X:ErrY","X>0", 25,2,0.4)
     979             :   // tree   - tree with variable
     980             :   // expr   - examp 
     981           0 :   const Int_t entries =  tree->Draw(expr,cut,"goff",drawEntries,firstEntry);
     982             :  
     983           0 :   if (entries<=0) {
     984           0 :     ::Error("TStatToolkit::MakeGraphError","Empty or Not valid expression (%s) or cut *%s)", expr,cut);
     985           0 :     return 0;
     986             :   }
     987           0 :   if (  tree->GetV2()==0){
     988           0 :     ::Error("TStatToolkit::MakeGraphError","Not valid expression (%s) ", expr);
     989           0 :     return 0;
     990             :   }
     991             :   TGraphErrors * graph=0;
     992           0 :   if ( tree->GetV3()!=0){
     993           0 :     graph = new TGraphErrors (entries, tree->GetV2(),tree->GetV1(),0,tree->GetV3());
     994           0 :   }else{
     995           0 :     graph = new TGraphErrors (entries, tree->GetV2(),tree->GetV1(),0,0);
     996             :   }
     997             : 
     998           0 :   graph->SetMarkerStyle(mstyle); 
     999           0 :   graph->SetMarkerColor(mcolor);
    1000           0 :   graph->SetLineColor(mcolor);
    1001           0 :   graph->SetTitle(expr);
    1002           0 :   TString chstring(expr);
    1003           0 :   TObjArray *charray = chstring.Tokenize(":");
    1004           0 :   graph->GetXaxis()->SetTitle(charray->At(1)->GetName());
    1005           0 :   graph->GetYaxis()->SetTitle(charray->At(0)->GetName());
    1006           0 :   THashList * metaData = (THashList*) tree->GetUserInfo()->FindObject("metaTable");
    1007           0 :   if (!metaData == 0){    
    1008           0 :     TNamed *nmdTitle0 = TStatToolkit::GetMetadata(tree,Form("%s.Title",charray->At(0)->GetName()));
    1009           0 :     TNamed *nmdTitle1 = TStatToolkit::GetMetadata(tree,Form("%s.Title",charray->At(1)->GetName()));
    1010           0 :     TNamed *nmdYAxis  = TStatToolkit::GetMetadata(tree,Form("%s.AxisTitle",charray->At(0)->GetName()));
    1011           0 :     TNamed *nmdXAxis  = TStatToolkit::GetMetadata(tree,Form("%s.AxisTitle",charray->At(1)->GetName())); 
    1012             :     //
    1013           0 :     TString grTitle=charray->At(0)->GetName();
    1014           0 :     if (nmdTitle0)  grTitle=nmdTitle0->GetTitle();
    1015           0 :     if (nmdTitle1)  {
    1016           0 :       grTitle+=":";
    1017           0 :       grTitle+=nmdTitle1->GetTitle();
    1018             :     }else{
    1019           0 :       grTitle+=":";
    1020           0 :       grTitle+=charray->At(1)->GetName();
    1021             :     }
    1022           0 :     if (nmdYAxis) {graph->GetYaxis()->SetTitle(nmdYAxis->GetTitle());}
    1023           0 :     if (nmdXAxis) {graph->GetXaxis()->SetTitle(nmdXAxis->GetTitle());}  
    1024           0 :     graph->SetTitle(grTitle.Data());
    1025           0 :   }  
    1026           0 :   delete charray;
    1027           0 :   if (msize>0) graph->SetMarkerSize(msize);
    1028           0 :   for(Int_t i=0;i<graph->GetN();i++) graph->GetX()[i]+=offset;
    1029             :   //
    1030           0 :   if (tree->GetVar(1)->IsInteger()){
    1031           0 :     TAxis * axis = tree->GetHistogram()->GetXaxis();
    1032           0 :     axis->Copy(*(graph->GetXaxis()));
    1033           0 :   }
    1034           0 :   if (tree->GetVar(0)->IsInteger()){
    1035           0 :     TAxis * axis = tree->GetHistogram()->GetYaxis();
    1036           0 :     axis->Copy(*(graph->GetYaxis()));
    1037           0 :   }
    1038           0 :   graph->Sort();
    1039             :   return graph;
    1040             :   
    1041           0 : }
    1042             : 
    1043             : THashList*  TStatToolkit::AddMetadata(TTree* tree, const char *varTagName,const char *varTagValue){
    1044             :   //
    1045             :   // Add metadata infromation as user info to the tree - see https://alice.its.cern.ch/jira/browse/ATO-290
    1046             :   // TTree metdata are used for the Drawing methods in the folling drawing functions
    1047             :   /*
    1048             :     Supported metadata:
    1049             :     - <varName>.AxisTitle
    1050             :     - <varName>.Legend
    1051             :     - <varname>.Color
    1052             :     - <varname>.MarkerStyle
    1053             :     This metadata than can be used by the TStatToolkit
    1054             :     - TStatToolkit::MakeGraphSparse
    1055             :     - TStatToolkit::MakeGraphErrors
    1056             :    */
    1057             :   // 
    1058           0 :   if (!tree) return NULL;
    1059           0 :   THashList * metaData = (THashList*) tree->GetUserInfo()->FindObject("metaTable");
    1060           0 :   if (metaData == NULL){  
    1061           0 :     metaData=new THashList;
    1062           0 :     metaData->SetName("metaTable");
    1063           0 :     tree->GetUserInfo()->AddLast(metaData);
    1064           0 :   } 
    1065           0 :   if (varTagName!=NULL && varTagValue!=NULL){
    1066           0 :     TNamed * named = TStatToolkit::GetMetadata(tree, varTagName);
    1067           0 :     if (named==NULL){
    1068           0 :       metaData->AddLast(new TNamed(varTagName,varTagValue));
    1069           0 :     }else{
    1070           0 :       named->SetTitle(varTagValue);
    1071             :     }
    1072           0 :   }
    1073             :   return metaData;
    1074           0 : }
    1075             : 
    1076             : TNamed* TStatToolkit::GetMetadata(TTree* tree, const char *vartagName){
    1077             :   //
    1078             :   //  Get metadata description
    1079             :   //
    1080           0 :   if (!tree) return 0;
    1081           0 :   THashList * metaData = (THashList*) tree->GetUserInfo()->FindObject("metaTable");
    1082           0 :   if (metaData == NULL){  
    1083           0 :     metaData=new THashList;
    1084           0 :     metaData->SetName("metaTable");
    1085           0 :     tree->GetUserInfo()->AddLast(metaData);
    1086           0 :     return 0;
    1087             :   } 
    1088           0 :   TNamed * named = (TNamed*)metaData->FindObject(vartagName);
    1089             :   return named;
    1090           0 : }
    1091             : 
    1092             : 
    1093             : 
    1094             : TGraph * TStatToolkit::MakeGraphSparse(TTree * tree, const char * expr, const char * cut, Int_t mstyle, Int_t mcolor, Float_t msize, Float_t offset){
    1095             :   //
    1096             :   // Make a sparse draw of the variables
    1097             :   // Format of expr : Var:Run or Var:Run:ErrorY or Var:Run:ErrorY:ErrorX
    1098             :   // offset : points can slightly be shifted in x for better visibility with more graphs
    1099             :   //
    1100             :   // Patrick Reichelt and Marian Ivanov
    1101             :   // maintained and updated by Marian Ivanov
    1102           0 :   const Int_t entries = tree->Draw(expr,cut,"goff");
    1103           0 :   if (entries<=0) {
    1104           0 :     ::Error("TStatToolkit::MakeGraphSparse","Empty or Not valid expression (%s) or cut (%s)", expr, cut);
    1105           0 :     return 0;
    1106             :   }
    1107             :   //  TGraph * graph = (TGraph*)gPad->GetPrimitive("Graph"); // 2D
    1108             : 
    1109             :   Double_t *graphY, *graphX;
    1110           0 :   graphY = tree->GetV1();
    1111           0 :   graphX = tree->GetV2();
    1112             : 
    1113             :   // sort according to run number
    1114           0 :   Int_t *index = new Int_t[entries*4];
    1115           0 :   TMath::Sort(entries,graphX,index,kFALSE);
    1116             : 
    1117             :   // define arrays for the new graph
    1118           0 :   Double_t *unsortedX = new Double_t[entries];
    1119           0 :   Int_t *runNumber = new Int_t[entries];
    1120             :   Double_t count = 0.5;
    1121             : 
    1122             :   // evaluate arrays for the new graph according to the run-number
    1123             :   Int_t icount=0;
    1124             :   //first entry
    1125           0 :   unsortedX[index[0]] = count;
    1126           0 :   runNumber[0] = graphX[index[0]];
    1127             :   // loop the rest of entries
    1128           0 :   for(Int_t i=1;i<entries;i++)
    1129             :   {
    1130           0 :     if(graphX[index[i]]==graphX[index[i-1]])
    1131           0 :       unsortedX[index[i]] = count;
    1132           0 :     else if(graphX[index[i]]!=graphX[index[i-1]]){
    1133           0 :       count++;
    1134           0 :       icount++;
    1135           0 :       unsortedX[index[i]] = count;
    1136           0 :       runNumber[icount]=graphX[index[i]];
    1137           0 :     }
    1138             :   }
    1139             : 
    1140             :   // count the number of xbins (run-wise) for the new graph
    1141           0 :   const Int_t newNbins = int(count+0.5);
    1142           0 :   Double_t *newBins = new Double_t[newNbins+1];
    1143           0 :   for(Int_t i=0; i<=count+1;i++){
    1144           0 :     newBins[i] = i;
    1145             :   }
    1146             : 
    1147             :   // define and fill the new graph
    1148             :   TGraph *graphNew = 0;
    1149           0 :   if (tree->GetV3()) {
    1150           0 :     if (tree->GetV4()) {
    1151           0 :       graphNew = new TGraphErrors(entries,unsortedX,graphY,tree->GetV4(),tree->GetV3());
    1152           0 :     }
    1153           0 :     else { graphNew = new TGraphErrors(entries,unsortedX,graphY,0,tree->GetV3()); }
    1154             :   }
    1155           0 :   else { graphNew = new TGraphErrors(entries,unsortedX,graphY,0,0); }
    1156             :   // with "Set(...)", the x-axis is being sorted
    1157           0 :   graphNew->GetXaxis()->Set(newNbins,newBins);
    1158             : 
    1159             :   // set the bins for the x-axis, apply shifting of points
    1160           0 :   Char_t xName[50];
    1161           0 :   for(Int_t i=0;i<count;i++){
    1162           0 :     snprintf(xName,50,"%d",runNumber[i]);
    1163           0 :     graphNew->GetXaxis()->SetBinLabel(i+1,xName);
    1164           0 :     graphNew->GetX()[i]+=offset;
    1165             :   }
    1166           0 :   if (tree->GetVar(1)->IsInteger() && strlen(tree->GetHistogram()->GetXaxis()->GetBinLabel(1))>0){    
    1167           0 :     for(Int_t i=0;i<count;i++){
    1168           0 :       graphNew->GetXaxis()->SetBinLabel(i+1,tree->GetHistogram()->GetXaxis()->GetBinLabel(i+1));
    1169             :     }
    1170           0 :   }
    1171           0 :   if (tree->GetVar(0)->IsInteger() &&  strlen(tree->GetHistogram()->GetXaxis()->GetBinLabel(1))>0 ){
    1172           0 :     for(Int_t i=0;i<count;i++){
    1173           0 :       graphNew->GetYaxis()->SetBinLabel(i+1,tree->GetHistogram()->GetYaxis()->GetBinLabel(i+1));
    1174             :     }
    1175           0 :   }
    1176             : 
    1177             : 
    1178             : 
    1179             : 
    1180           0 :   graphNew->GetHistogram()->SetTitle("");
    1181           0 :   graphNew->SetMarkerStyle(mstyle);
    1182           0 :   graphNew->SetMarkerColor(mcolor);  graphNew->SetLineColor(mcolor);
    1183           0 :   if (msize>0) { graphNew->SetMarkerSize(msize); graphNew->SetLineWidth(msize); }
    1184           0 :   delete [] unsortedX;
    1185           0 :   delete [] runNumber;
    1186           0 :   delete [] index;
    1187           0 :   delete [] newBins;
    1188             :   // 
    1189           0 :   TString chstring(expr);
    1190           0 :   if (cut) chstring+=TString::Format(" ( %s )", cut);
    1191           0 :   graphNew->SetTitle(chstring);
    1192             : 
    1193           0 :   THashList * metaData = (THashList*) tree->GetUserInfo()->FindObject("metaTable");
    1194           0 :   if (!metaData == 0){    
    1195           0 :     chstring=expr;
    1196           0 :     TObjArray *charray = chstring.Tokenize(":");
    1197           0 :     graphNew->GetXaxis()->SetTitle(charray->At(1)->GetName());
    1198           0 :     graphNew->GetYaxis()->SetTitle(charray->At(0)->GetName());    
    1199           0 :     TNamed *nmdTitle0 = TStatToolkit::GetMetadata(tree,Form("%s.Title",charray->At(0)->GetName()));
    1200           0 :     TNamed *nmdTitle1 = TStatToolkit::GetMetadata(tree,Form("%s.Title",charray->At(1)->GetName()));
    1201           0 :     TNamed *nmdYAxis  = TStatToolkit::GetMetadata(tree,Form("%s.AxisTitle",charray->At(0)->GetName()));
    1202           0 :     TNamed *nmdXAxis  = TStatToolkit::GetMetadata(tree,Form("%s.AxisTitle",charray->At(1)->GetName())); 
    1203             :     //
    1204           0 :     TString grTitle=charray->At(0)->GetName();
    1205           0 :     if (nmdTitle0)  grTitle=nmdTitle0->GetTitle();
    1206           0 :     if (nmdTitle1)  {
    1207           0 :       grTitle+=":";
    1208           0 :       grTitle+=nmdTitle1->GetTitle();
    1209             :     }else{
    1210           0 :       grTitle+=":";
    1211           0 :       grTitle+=charray->At(1)->GetName();
    1212             :     }
    1213           0 :     if (cut)  grTitle+=TString::Format(" ( %s )", cut);
    1214           0 :     graphNew->SetTitle(grTitle);
    1215           0 :     if (nmdYAxis) {graphNew->GetYaxis()->SetTitle(nmdYAxis->GetTitle());}
    1216           0 :     if (nmdXAxis) {graphNew->GetXaxis()->SetTitle(nmdXAxis->GetTitle());}            
    1217           0 :     delete charray;
    1218           0 :   }
    1219             :   return graphNew;
    1220           0 : }
    1221             : 
    1222             : 
    1223             : 
    1224             : //
    1225             : // functions used for the trending
    1226             : //
    1227             : 
    1228             : 
    1229             : Int_t  TStatToolkit::MakeStatAlias(TTree * tree, const char * expr, const char * cut, const char * alias) 
    1230             : {
    1231             :   //
    1232             :   // Add alias using statistical values of a given variable.
    1233             :   // (by MI, Patrick Reichelt)
    1234             :   //
    1235             :   // tree - input tree
    1236             :   // expr - variable expression
    1237             :   // cut  - selection criteria
    1238             :   // Output - return number of entries used to define variable
    1239             :   // In addition mean, rms, median, and robust mean and rms (choosing fraction of data with smallest RMS)
    1240             :   // 
    1241             :   /* Example usage:
    1242             :      1.) create the robust estimators for variable expr="QA.TPC.CPass1.meanTPCncl" and create a corresponding
    1243             :      aliases with the prefix alias[0]="ncl", calculated using fraction alias[1]="0.90"
    1244             : 
    1245             :      TStatToolkit::MakeStatAlias(tree,"QA.TPC.CPass1.meanTPCncl","QA.TPC.CPass1.status>0","ncl:0.9");
    1246             :      root [4] tree->GetListOfAliases().Print()
    1247             :      OBJ: TNamed    ncl_Median      (130.964333+0)
    1248             :      OBJ: TNamed    ncl_Mean        (122.120387+0)
    1249             :      OBJ: TNamed    ncl_RMS         (33.509623+0)
    1250             :      OBJ: TNamed    ncl_Mean90      (131.503862+0)
    1251             :      OBJ: TNamed    ncl_RMS90       (3.738260+0)    
    1252             :   */
    1253             :   // 
    1254           0 :   Int_t entries = tree->Draw(expr,cut,"goff");
    1255           0 :   if (entries<=1){
    1256           0 :     printf("Expression or cut not valid:\t%s\t%s\n", expr, cut);
    1257           0 :     return 0;
    1258             :   }
    1259             :   //
    1260           0 :   TObjArray* oaAlias = TString(alias).Tokenize(":");
    1261           0 :   if (oaAlias->GetEntries()<2) {
    1262           0 :     printf("Alias must have 2 arguments:\t%s\n", alias);
    1263           0 :     return 0;
    1264             :   }
    1265           0 :   Float_t entryFraction = atof( oaAlias->At(1)->GetName() );
    1266             :   //
    1267           0 :   Double_t median = TMath::Median(entries,tree->GetV1());
    1268           0 :   Double_t mean   = TMath::Mean(entries,tree->GetV1());
    1269           0 :   Double_t rms    = TMath::RMS(entries,tree->GetV1());
    1270           0 :   Double_t meanEF=0, rmsEF=0;
    1271           0 :   TStatToolkit::EvaluateUni(entries, tree->GetV1(), meanEF, rmsEF, entries*entryFraction);
    1272             :   //
    1273           0 :   tree->SetAlias(Form("%s_Median",oaAlias->At(0)->GetName()), Form("(%f+0)",median));
    1274           0 :   tree->SetAlias(Form("%s_Mean",oaAlias->At(0)->GetName()), Form("(%f+0)",mean));
    1275           0 :   tree->SetAlias(Form("%s_RMS",oaAlias->At(0)->GetName()), Form("(%f+0)",rms));
    1276           0 :   tree->SetAlias(Form("%s_Mean%d",oaAlias->At(0)->GetName(),Int_t(entryFraction*100)), Form("(%f+0)",meanEF));
    1277           0 :   tree->SetAlias(Form("%s_RMS%d",oaAlias->At(0)->GetName(),Int_t(entryFraction*100)), Form("(%f+0)",rmsEF));
    1278           0 :   delete oaAlias; 
    1279             :   return entries;
    1280           0 : }
    1281             : 
    1282             : Int_t  TStatToolkit::SetStatusAlias(TTree * tree, const char * expr, const char * cut, const char * alias) 
    1283             : {
    1284             :   //
    1285             :   // Add alias to trending tree using statistical values of a given variable.
    1286             :   // (by MI, Patrick Reichelt)
    1287             :   //
    1288             :   // format of expr :  varname (e.g. meanTPCncl)
    1289             :   // format of cut  :  char like in TCut
    1290             :   // format of alias:  alias:query:entryFraction(EF) (fraction of entries used for uniformity evaluation)
    1291             :   //            e.g.:  varname_Out:(abs(varname-meanEF)>6.*rmsEF):0.8
    1292             :   // available internal variables are: 'varname, Median, Mean, MeanEF, RMS, RMSEF'
    1293             :   // in the alias, 'varname' will be replaced by its content, and 'EF' by the percentage (e.g. MeanEF -> Mean80)
    1294             :   //
    1295             :   /* Example usage:
    1296             :      1.) Define robust mean (possible, but easier done with TStatToolkit::MakeStatAlias(...)) 
    1297             :      TStatToolkit::SetStatusAlias(tree, "meanTPCnclF", "meanTPCnclF>0", "meanTPCnclF_MeanEF:MeanEF:0.80") ;
    1298             :      root [10] tree->GetListOfAliases()->Print()
    1299             :                Collection name='TList', class='TList', size=1
    1300             :                OBJ: TNamed    meanTPCnclF_Mean80      0.899308
    1301             :      2.) create alias outlyers  - 6 sigma cut
    1302             :      TStatToolkit::SetStatusAlias(tree, "meanTPCnclF", "meanTPCnclF>0", "meanTPCnclF_Out:(abs(meanTPCnclF-MeanEF)>6.*RMSEF):0.8")
    1303             :      meanTPCnclF_Out ==> (abs(meanTPCnclF-0.899308)>6.*0.016590)
    1304             :      3.) the same functionality as in 2.)
    1305             :      TStatToolkit::SetStatusAlias(tree, "meanTPCnclF", "meanTPCnclF>0", "varname_Out2:(abs(varname-MeanEF)>6.*RMSEF):0.8") 
    1306             :      meanTPCnclF_Out2 ==> (abs(meanTPCnclF-0.899308)>6.*0.016590)
    1307             :   */
    1308             :   //
    1309           0 :   Int_t entries = tree->Draw(expr,cut,"goff");
    1310           0 :   if (entries<1){
    1311           0 :     printf("Expression or cut not valid:\t%s\t%s\n", expr, cut);
    1312           0 :     return 0;
    1313             :   }
    1314             :   //
    1315           0 :   TObjArray* oaVar = TString(expr).Tokenize(":");
    1316           0 :   char varname[50];
    1317           0 :   snprintf(varname,50,"%s", oaVar->At(0)->GetName());
    1318             :   Float_t entryFraction = 0.8;
    1319             :   //
    1320           0 :   TObjArray* oaAlias = TString(alias).Tokenize(":");
    1321           0 :   if (oaAlias->GetEntries()<2) {
    1322           0 :     printf("Alias must have at least 2 arguments:\t%s\n", alias);
    1323           0 :     return 0;
    1324             :   }
    1325           0 :   else if (oaAlias->GetEntries()<3) {
    1326             :     //printf("Using default entryFraction if needed:\t%f\n", entryFraction);
    1327             :   }
    1328           0 :   else entryFraction = atof( oaAlias->At(2)->GetName() );
    1329             :   //
    1330           0 :   Double_t median = TMath::Median(entries,tree->GetV1());
    1331           0 :   Double_t mean   = TMath::Mean(entries,tree->GetV1());
    1332           0 :   Double_t rms    = TMath::RMS(entries,tree->GetV1());
    1333           0 :   Double_t meanEF=0, rmsEF=0;
    1334           0 :   TStatToolkit::EvaluateUni(entries, tree->GetV1(), meanEF, rmsEF, entries*entryFraction);
    1335             :   //
    1336           0 :   TString sAlias( oaAlias->At(0)->GetName() );
    1337           0 :   sAlias.ReplaceAll("varname",varname);
    1338           0 :   sAlias.ReplaceAll("MeanEF", Form("Mean%1.0f",entryFraction*100) );
    1339           0 :   sAlias.ReplaceAll("RMSEF",  Form("RMS%1.0f",entryFraction*100) );
    1340           0 :   TString sQuery( oaAlias->At(1)->GetName() );
    1341           0 :   sQuery.ReplaceAll("varname",varname);
    1342           0 :   sQuery.ReplaceAll("MeanEF", Form("%f",meanEF) );
    1343           0 :   sQuery.ReplaceAll("RMSEF",  Form("%f",rmsEF) ); //make sure to replace 'RMSEF' before 'RMS'...
    1344           0 :   sQuery.ReplaceAll("Median", Form("%f",median) );
    1345           0 :   sQuery.ReplaceAll("Mean",   Form("%f",mean) );
    1346           0 :   sQuery.ReplaceAll("RMS",    Form("%f",rms) );
    1347           0 :   printf("define alias:\t%s = %s\n", sAlias.Data(), sQuery.Data());
    1348             :   //
    1349           0 :   char query[200];
    1350           0 :   char aname[200];
    1351           0 :   snprintf(query,200,"%s", sQuery.Data());
    1352           0 :   snprintf(aname,200,"%s", sAlias.Data());
    1353           0 :   tree->SetAlias(aname, query);
    1354           0 :   delete oaVar;
    1355           0 :   delete oaAlias;
    1356             :   return entries;
    1357           0 : }
    1358             : 
    1359             : TMultiGraph*  TStatToolkit::MakeStatusMultGr(TTree * tree, const char * expr, const char * cut, const char * alias, Int_t igr) 
    1360             : {
    1361             :   //
    1362             :   // Compute a trending multigraph that shows for which runs a variable has outliers.
    1363             :   // (by MI, Patrick Reichelt)
    1364             :   //
    1365             :   // format of expr :  varname:xaxis (e.g. meanTPCncl:run, but 'varname' can be any string that you need for seach-and-replace)
    1366             :   // format of cut  :  char like in TCut
    1367             :   // format of alias:  (1):(statisticOK):(varname_Warning):(varname_Out)[:(varname_PhysAcc):(varname_Extra)]
    1368             :   //
    1369             :   // function MakeGraphSparse() is called for each alias argument, which will be used as tree expression.
    1370             :   // each alias argument is supposed to be a Boolean statement which can be evaluated as tree expression.
    1371             :   // the order of these criteria should be kept, as the marker styles and colors are chosen to be meaningful this way!
    1372             :   // 'statisticOK' could e.g. be an alias for '(meanTPCncl>0)'.
    1373             :   // if you dont need e.g. a 'warning' condition, then just replace it by (0).
    1374             :   // in the alias, 'varname' will be replaced by its content (e.g. varname_Out -> meanTPCncl_Out)
    1375             :   // note: the aliases 'varname_Out' etc have to be defined by function TStatToolkit::SetStatusAlias(...)
    1376             :   // counter igr is used to shift the multigraph in y when filling a TObjArray.
    1377             :   //
    1378             :   //
    1379             :   // To create the Status Bar, the following is done in principle.
    1380             :   //    ( example current usage in $ALICE_ROOT/PWGPP/TPC/macros/drawPerformanceTPCQAMatchTrends.C and ./qaConfig.C. )
    1381             :   //
    1382             :   //  TStatToolkit::SetStatusAlias(tree, "meanTPCncl",    "", "varname_Out:(abs(varname-MeanEF)>6.*RMSEF):0.8");
    1383             :   //  TStatToolkit::SetStatusAlias(tree, "tpcItsMatchA",  "", "varname_Out:(abs(varname-MeanEF)>6.*RMSEF):0.8");
    1384             :   //  TStatToolkit::SetStatusAlias(tree, "meanTPCncl",    "", "varname_Warning:(abs(varname-MeanEF)>3.*RMSEF):0.8");
    1385             :   //  TStatToolkit::SetStatusAlias(tree, "tpcItsMatchA",  "", "varname_Warning:(abs(varname-MeanEF)>3.*RMSEF):0.8");
    1386             :   //  TObjArray* oaMultGr = new TObjArray(); int igr=0;
    1387             :   //  oaMultGr->Add( TStatToolkit::MakeStatusMultGr(tree, "tpcItsMatchA:run",  "", "(1):(meanTPCncl>0):(varname_Warning):(varname_Outlier):", igr) ); igr++;
    1388             :   //  oaMultGr->Add( TStatToolkit::MakeStatusMultGr(tree, "meanTPCncl:run",    "", "(1):(meanTPCncl>0):(varname_Warning):(varname_Outlier):", igr) ); igr++;
    1389             :   //  TCanvas *c1 = new TCanvas("c1","c1");
    1390             :   //  TStatToolkit::AddStatusPad(c1, 0.30, 0.40);
    1391             :   //  TStatToolkit::DrawStatusGraphs(oaMultGr);
    1392             :   
    1393             :   
    1394           0 :   TObjArray* oaVar = TString(expr).Tokenize(":");
    1395           0 :   if (oaVar->GetEntries()<2) {
    1396           0 :     printf("Expression has to be of type 'varname:xaxis':\t%s\n", expr);
    1397           0 :     return 0;
    1398             :   }
    1399           0 :   char varname[50];
    1400           0 :   char var_x[50];
    1401           0 :   snprintf(varname,50,"%s", oaVar->At(0)->GetName());
    1402           0 :   snprintf(var_x  ,50,"%s", oaVar->At(1)->GetName());
    1403             :   //
    1404           0 :   TString sAlias(alias);
    1405           0 :   sAlias.ReplaceAll("varname",varname);
    1406           0 :   TObjArray* oaAlias = TString(sAlias.Data()).Tokenize(":");
    1407           0 :   if (oaAlias->GetEntries()<2) {
    1408           0 :     printf("Alias must have 2-6 arguments:\t%s\n", alias);
    1409           0 :     return 0;
    1410             :   }
    1411           0 :   char query[200];
    1412           0 :   TMultiGraph* multGr = new TMultiGraph();
    1413           0 :   Int_t marArr[6]      = {24+igr%2, 20+igr%2, 20+igr%2, 20+igr%2, 20+igr%2, 20+igr%2};
    1414           0 :   Int_t colArr[6]      = {kBlack, kBlack, kOrange, kRed, kGreen+1, kBlue};
    1415           0 :   Double_t sizeArr[6]  = {1.4, 1.1, 1.5, 1.1, 1.4, 0.8};
    1416           0 :   Double_t shiftArr[6] = {0., 0., 0.25, 0.25, -0.25, -0.25};
    1417           0 :   const Int_t ngr = oaAlias->GetEntriesFast();
    1418           0 :   for (Int_t i=0; i<ngr; i++){
    1419           0 :     snprintf(query,200, "%f*(%s-0.5):%s", 1.+igr, oaAlias->At(i)->GetName(), var_x);
    1420           0 :     TGraphErrors * gr = (TGraphErrors*) TStatToolkit::MakeGraphSparse(tree,query,cut,marArr[i],colArr[i],sizeArr[i],shiftArr[i]);
    1421           0 :     if (gr) multGr->Add(gr);
    1422             :   }
    1423             :   //
    1424           0 :   multGr->SetName(varname);
    1425           0 :   multGr->SetTitle(varname); // used for y-axis labels of status bar, can be modified by calling function.
    1426           0 :   delete oaVar;
    1427           0 :   delete oaAlias;
    1428             :   return multGr;
    1429           0 : }
    1430             : 
    1431             : 
    1432             : void  TStatToolkit::AddStatusPad(TCanvas* c1, Float_t padratio, Float_t bottommargin)
    1433             : {
    1434             :   //
    1435             :   // add pad to bottom of canvas for Status graphs (by Patrick Reichelt)
    1436             :   // call function "DrawStatusGraphs(...)" afterwards
    1437             :   //
    1438           0 :   TCanvas* c1_clone = (TCanvas*) c1->Clone("c1_clone");
    1439           0 :   c1->Clear();
    1440             :   // produce new pads
    1441           0 :   c1->cd();
    1442           0 :   TPad* pad1 = new TPad("pad1", "pad1", 0., padratio, 1., 1.); 
    1443           0 :   pad1->Draw();
    1444           0 :   pad1->SetNumber(1); // so it can be called via "c1->cd(1);"
    1445           0 :   c1->cd();
    1446           0 :   TPad* pad2 = new TPad("pad2", "pad2", 0., 0., 1., padratio);
    1447           0 :   pad2->Draw();
    1448           0 :   pad2->SetNumber(2);
    1449             :   // draw original canvas into first pad
    1450           0 :   c1->cd(1);
    1451           0 :   c1_clone->DrawClonePad();
    1452           0 :   pad1->SetBottomMargin(0.001);
    1453           0 :   pad1->SetRightMargin(0.01);
    1454             :   // set up second pad
    1455           0 :   c1->cd(2);
    1456           0 :   pad2->SetGrid(3);
    1457           0 :   pad2->SetTopMargin(0);
    1458           0 :   pad2->SetBottomMargin(bottommargin); // for the long x-axis labels (runnumbers)
    1459           0 :   pad2->SetRightMargin(0.01);
    1460           0 : }
    1461             : 
    1462             : 
    1463             : void  TStatToolkit::DrawStatusGraphs(TObjArray* oaMultGr)
    1464             : {
    1465             :   //
    1466             :   // draw Status graphs into active pad of canvas (by MI, Patrick Reichelt)
    1467             :   // ...into bottom pad, if called after "AddStatusPad(...)"
    1468             :   //
    1469           0 :   const Int_t nvars = oaMultGr->GetEntriesFast();
    1470           0 :   TGraph* grAxis = (TGraph*) ((TMultiGraph*) oaMultGr->At(0))->GetListOfGraphs()->At(0);
    1471           0 :   grAxis->SetMaximum(0.5*nvars+0.5);
    1472           0 :   grAxis->SetMinimum(0);
    1473           0 :   grAxis->GetYaxis()->SetLabelSize(0);
    1474           0 :   grAxis->GetYaxis()->SetTitle("");
    1475           0 :   grAxis->SetTitle("");
    1476           0 :   Int_t entries = grAxis->GetN();
    1477           0 :   grAxis->GetXaxis()->SetLabelSize(5.7*TMath::Min(TMath::Max(5./entries,0.01),0.03));
    1478           0 :   grAxis->GetXaxis()->LabelsOption("v");
    1479           0 :   grAxis->Draw("ap");
    1480             :   //
    1481             :   // draw multigraphs & names of status variables on the y axis
    1482           0 :   for (Int_t i=0; i<nvars; i++){
    1483           0 :     ((TMultiGraph*) oaMultGr->At(i))->Draw("p");
    1484           0 :     TLatex* ylabel = new TLatex(-0.1, 0.5*i+0.5, ((TMultiGraph*) oaMultGr->At(i))->GetTitle());
    1485           0 :     ylabel->SetTextAlign(32); //hor:right & vert:centered
    1486           0 :     ylabel->SetTextSize(0.025/gPad->GetHNDC());
    1487           0 :     ylabel->Draw();
    1488             :   }
    1489           0 : }
    1490             : 
    1491             : 
    1492             : TTree*  TStatToolkit::WriteStatusToTree(TObject* oStatusGr) 
    1493             : {
    1494             :   //
    1495             :   // Create Tree with Integers for each status variable flag (warning, outlier, physacc).
    1496             :   // (by Patrick Reichelt)
    1497             :   //
    1498             :   // input: either a TMultiGraph with status of single variable, which 
    1499             :   //        was computed by TStatToolkit::MakeStatusMultGr(),
    1500             :   //        or a TObjArray which contains up to 10 of such variables.
    1501             :   //        example: TTree* statusTree = WriteStatusToTree( TStatToolkit::MakeStatusMultGr(tree, "tpcItsMatch:run",  "", sCriteria.Data(), 0) );
    1502             :   //        or     : TTree* statusTree = TStatToolkit::WriteStatusToTree(oaMultGr);
    1503             :   // 
    1504             :   // output tree: 1=flag is true, 0=flag is false, -1=flag was not computed.
    1505             :   // To be rewritten to the pcstream
    1506             :   
    1507             :   TObjArray* oaMultGr = NULL;
    1508             :   Bool_t needDeletion=kFALSE;
    1509           0 :   if (oStatusGr->IsA() == TObjArray::Class()) {
    1510           0 :     oaMultGr = (TObjArray*) oStatusGr;
    1511           0 :   }
    1512           0 :   else if (oStatusGr->IsA() == TMultiGraph::Class()) {
    1513           0 :     oaMultGr = new TObjArray(); needDeletion=kTRUE;
    1514           0 :     oaMultGr->Add((TMultiGraph*) oStatusGr);
    1515             :   }
    1516             :   else {
    1517           0 :     Printf("WriteStatusToTree(): Error! 'oStatusGr' must be a TMultiGraph or a TObjArray of them!");
    1518           0 :     return 0;
    1519             :   }
    1520             :   // variables for output tree
    1521             :   const int nvarsMax=10;
    1522             :   const int ncritMax=5;
    1523           0 :   Int_t    currentRun;
    1524           0 :   Int_t    treevars[nvarsMax*ncritMax];
    1525           0 :   TString  varnames[nvarsMax*ncritMax];
    1526           0 :   for (int i=0; i<nvarsMax*ncritMax; i++) treevars[i]=-1;
    1527             :   
    1528           0 :   Printf("WriteStatusToTree(): writing following variables to TTree (maybe only subset of listed criteria filled)");
    1529           0 :   for (Int_t vari=0; vari<nvarsMax; vari++) 
    1530             :   {
    1531           0 :     if (vari < oaMultGr->GetEntriesFast()) {
    1532           0 :       varnames[vari*ncritMax+0] = Form("%s_statisticOK", ((TMultiGraph*) oaMultGr->At(vari))->GetName());
    1533           0 :       varnames[vari*ncritMax+1] = Form("%s_Warning",     ((TMultiGraph*) oaMultGr->At(vari))->GetName());
    1534           0 :       varnames[vari*ncritMax+2] = Form("%s_Outlier",     ((TMultiGraph*) oaMultGr->At(vari))->GetName());
    1535           0 :       varnames[vari*ncritMax+3] = Form("%s_PhysAcc",     ((TMultiGraph*) oaMultGr->At(vari))->GetName());
    1536           0 :       varnames[vari*ncritMax+4] = Form("%s_Extra",       ((TMultiGraph*) oaMultGr->At(vari))->GetName());
    1537             :     }
    1538             :     else {
    1539           0 :       varnames[vari*ncritMax+0] = Form("dummy");
    1540           0 :       varnames[vari*ncritMax+1] = Form("dummy");
    1541           0 :       varnames[vari*ncritMax+2] = Form("dummy");
    1542           0 :       varnames[vari*ncritMax+3] = Form("dummy");
    1543           0 :       varnames[vari*ncritMax+4] = Form("dummy");
    1544             :     }
    1545           0 :     cout << "  " << varnames[vari*ncritMax+0].Data() << " " << varnames[vari*ncritMax+1].Data() << " " << varnames[vari*ncritMax+2].Data() << " " << varnames[vari*ncritMax+3].Data() << " " << varnames[vari*ncritMax+4].Data() << endl;
    1546             :   }
    1547             :   
    1548           0 :   TTree* statusTree = new TTree("statusTree","statusTree");
    1549           0 :   statusTree->Branch("run",                &currentRun  );
    1550           0 :   statusTree->Branch(varnames[ 0].Data(),  &treevars[ 0]);
    1551           0 :   statusTree->Branch(varnames[ 1].Data(),  &treevars[ 1]);
    1552           0 :   statusTree->Branch(varnames[ 2].Data(),  &treevars[ 2]);
    1553           0 :   statusTree->Branch(varnames[ 3].Data(),  &treevars[ 3]);
    1554           0 :   statusTree->Branch(varnames[ 4].Data(),  &treevars[ 4]);
    1555           0 :   statusTree->Branch(varnames[ 5].Data(),  &treevars[ 5]);
    1556           0 :   statusTree->Branch(varnames[ 6].Data(),  &treevars[ 6]);
    1557           0 :   statusTree->Branch(varnames[ 7].Data(),  &treevars[ 7]);
    1558           0 :   statusTree->Branch(varnames[ 8].Data(),  &treevars[ 8]);
    1559           0 :   statusTree->Branch(varnames[ 9].Data(),  &treevars[ 9]);
    1560           0 :   statusTree->Branch(varnames[10].Data(),  &treevars[10]);
    1561           0 :   statusTree->Branch(varnames[11].Data(),  &treevars[11]);
    1562           0 :   statusTree->Branch(varnames[12].Data(),  &treevars[12]);
    1563           0 :   statusTree->Branch(varnames[13].Data(),  &treevars[13]);
    1564           0 :   statusTree->Branch(varnames[14].Data(),  &treevars[14]);
    1565           0 :   statusTree->Branch(varnames[15].Data(),  &treevars[15]);
    1566           0 :   statusTree->Branch(varnames[16].Data(),  &treevars[16]);
    1567           0 :   statusTree->Branch(varnames[17].Data(),  &treevars[17]);
    1568           0 :   statusTree->Branch(varnames[18].Data(),  &treevars[18]);
    1569           0 :   statusTree->Branch(varnames[19].Data(),  &treevars[19]);
    1570           0 :   statusTree->Branch(varnames[20].Data(),  &treevars[20]);
    1571           0 :   statusTree->Branch(varnames[21].Data(),  &treevars[21]);
    1572           0 :   statusTree->Branch(varnames[22].Data(),  &treevars[22]);
    1573           0 :   statusTree->Branch(varnames[23].Data(),  &treevars[23]);
    1574           0 :   statusTree->Branch(varnames[24].Data(),  &treevars[24]);
    1575           0 :   statusTree->Branch(varnames[25].Data(),  &treevars[25]);
    1576           0 :   statusTree->Branch(varnames[26].Data(),  &treevars[26]);
    1577           0 :   statusTree->Branch(varnames[27].Data(),  &treevars[27]);
    1578           0 :   statusTree->Branch(varnames[28].Data(),  &treevars[28]);
    1579           0 :   statusTree->Branch(varnames[29].Data(),  &treevars[29]);
    1580           0 :   statusTree->Branch(varnames[30].Data(),  &treevars[30]);
    1581           0 :   statusTree->Branch(varnames[31].Data(),  &treevars[31]);
    1582           0 :   statusTree->Branch(varnames[32].Data(),  &treevars[32]);
    1583           0 :   statusTree->Branch(varnames[33].Data(),  &treevars[33]);
    1584           0 :   statusTree->Branch(varnames[34].Data(),  &treevars[34]);
    1585           0 :   statusTree->Branch(varnames[35].Data(),  &treevars[35]);
    1586           0 :   statusTree->Branch(varnames[36].Data(),  &treevars[36]);
    1587           0 :   statusTree->Branch(varnames[37].Data(),  &treevars[37]);
    1588           0 :   statusTree->Branch(varnames[38].Data(),  &treevars[38]);
    1589           0 :   statusTree->Branch(varnames[39].Data(),  &treevars[39]);
    1590           0 :   statusTree->Branch(varnames[40].Data(),  &treevars[40]);
    1591           0 :   statusTree->Branch(varnames[41].Data(),  &treevars[41]);
    1592           0 :   statusTree->Branch(varnames[42].Data(),  &treevars[42]);
    1593           0 :   statusTree->Branch(varnames[43].Data(),  &treevars[43]);
    1594           0 :   statusTree->Branch(varnames[44].Data(),  &treevars[44]);
    1595           0 :   statusTree->Branch(varnames[45].Data(),  &treevars[45]);
    1596           0 :   statusTree->Branch(varnames[46].Data(),  &treevars[46]);
    1597           0 :   statusTree->Branch(varnames[47].Data(),  &treevars[47]);
    1598           0 :   statusTree->Branch(varnames[48].Data(),  &treevars[48]);
    1599           0 :   statusTree->Branch(varnames[49].Data(),  &treevars[49]);
    1600             :   
    1601             :   // run loop
    1602           0 :   Double_t graphX; // x-position of marker (0.5, 1.5, ...)
    1603           0 :   Double_t graphY; // if >0 -> warning/outlier/physacc! if =-0.5 -> no warning/outlier/physacc
    1604           0 :   TList* arrRuns = (TList*) ((TGraph*) ((TMultiGraph*) oaMultGr->At(0))->GetListOfGraphs()->At(0))->GetXaxis()->GetLabels();
    1605             :   //'TAxis->GetLabels()' returns THashList of TObjString, but using THashList gives compilation error "... incomplete type 'struct THashList' "
    1606           0 :   for (Int_t runi=0; runi<arrRuns->GetSize(); runi++) 
    1607             :   {
    1608           0 :     currentRun = atoi( arrRuns->At(runi)->GetName() );
    1609             :     //Printf(" runi=%2i, name: %s \t run number: %i", runi, arrRuns->At(runi)->GetName(), currentRun);
    1610             :     
    1611             :     // status variable loop
    1612           0 :     for (Int_t vari=0; vari<oaMultGr->GetEntriesFast(); vari++) 
    1613             :     {
    1614           0 :       TMultiGraph* multGr = (TMultiGraph*) oaMultGr->At(vari);
    1615             :       
    1616             :       // criteria loop
    1617             :       // the order is given by TStatToolkit::MakeStatusMultGr().
    1618             :       // criterion #1 is 'statisticOK' and mandatory, the rest is optional. (#0 is always True, thus skipped)
    1619           0 :       for (Int_t criti=1; criti<multGr->GetListOfGraphs()->GetEntries(); criti++) 
    1620             :       {
    1621           0 :         TGraph* grCriterion = (TGraph*) multGr->GetListOfGraphs()->At(criti);
    1622           0 :         graphX = -1, graphY = -1;
    1623           0 :         grCriterion->GetPoint(runi, graphX, graphY);
    1624           0 :         treevars[(vari)*ncritMax+(criti-1)] = (graphY>0)?1:0;
    1625             :       }
    1626             :     }
    1627           0 :     statusTree->Fill();
    1628             :   }
    1629             :   
    1630           0 :   if (needDeletion) delete oaMultGr;
    1631             :   
    1632             :   return statusTree;
    1633           0 : }
    1634             : 
    1635             : 
    1636             : void   TStatToolkit::MakeSummaryTree(TTree* treeIn, TTreeSRedirector *pcstream, TObjString & sumID, TCut &selection){
    1637             :   //
    1638             :   // Make a  summary tree for the input tree 
    1639             :   // For the moment statistic works only for the primitive branches (Float/Double/Int)
    1640             :   // Extension recursive version planned for graphs a and histograms
    1641             :   //
    1642             :   // Following statistics are exctracted:
    1643             :   //   - Standard: mean, meadian, rms
    1644             :   //   - LTM robust statistic: mean60, rms60, mean90, rms90
    1645             :   // Parameters:
    1646             :   //    treeIn    - input tree 
    1647             :   //    pctream   - Output redirector
    1648             :   //    sumID     - ID as will be used in output tree
    1649             :   //    selection - selection criteria define the set of entries used to evaluat statistic 
    1650             :   //
    1651             :   // Curently only predefined statistic used to fill summary information
    1652             :   // Future plans an option user defined statistic descriptor instead of the defualt (if exist)
    1653             :   // 
    1654             :   //      e.g 
    1655             :   //          default.Branches=median:mean90:rms90:mean60:rms60
    1656             :   //          interactionRate.Branches   mean90:median:rms90:mean95:rms95:mean60:rms60
    1657             :   //
    1658           0 :   TObjArray * brArray = treeIn->GetListOfBranches();
    1659           0 :   Int_t tEntries= treeIn->GetEntries();
    1660           0 :   Int_t nBranches=brArray->GetEntries();
    1661           0 :   TString treeName = treeIn->GetName();
    1662             : 
    1663           0 :   (*pcstream)<<treeName.Data()<<"entries="<<tEntries;
    1664           0 :   (*pcstream)<<treeName.Data()<<"ID.="<<&sumID;
    1665             :   
    1666           0 :   TMatrixD valBranch(nBranches,7);
    1667           0 :   for (Int_t iBr=0; iBr<nBranches; iBr++){    
    1668           0 :     TString brName= brArray->At(iBr)->GetName();
    1669           0 :     Int_t entries=treeIn->Draw(TString::Format("%s>>dummy(10,0,1)",brArray->At(iBr)->GetName()).Data(),selection,"goff");
    1670           0 :     if (entries==0) continue;
    1671           0 :     Double_t median, mean, rms, mean60,rms60, mean90, rms90;
    1672           0 :     mean  = TMath::Mean(entries,treeIn->GetV1());
    1673           0 :     median= TMath::Median(entries,treeIn->GetV1());
    1674           0 :     rms   = TMath::RMS(entries,treeIn->GetV1());
    1675           0 :     TStatToolkit::EvaluateUni(entries, treeIn->GetV1(), mean60,rms60,TMath::Min(TMath::Max(2., 0.60*entries),Double_t(entries)));
    1676           0 :     TStatToolkit::EvaluateUni(entries, treeIn->GetV1(), mean90,rms90,TMath::Min(TMath::Max(2., 0.90*entries),Double_t(entries)));
    1677           0 :     valBranch(iBr,0)=mean; 
    1678           0 :     valBranch(iBr,1)=median; 
    1679           0 :     valBranch(iBr,2)=rms; 
    1680           0 :     valBranch(iBr,3)=mean60; 
    1681           0 :     valBranch(iBr,4)=rms60; 
    1682           0 :     valBranch(iBr,5)=mean90; 
    1683           0 :     valBranch(iBr,6)=rms90; 
    1684           0 :     (*pcstream)<<treeName.Data()<<
    1685           0 :       brName+"="<<valBranch(iBr,1)<<           // use as an default median estimator
    1686           0 :       brName+"_Mean="<<valBranch(iBr,0)<< 
    1687           0 :       brName+"_Median="<<valBranch(iBr,1)<<
    1688           0 :       brName+"_RMS="<<valBranch(iBr,2)<<
    1689           0 :       brName+"_Mean60="<<valBranch(iBr,3)<<
    1690           0 :       brName+"_RMS60="<<valBranch(iBr,4)<<
    1691           0 :       brName+"_Mean90="<<valBranch(iBr,5)<<
    1692           0 :       brName+"_RMS90="<<valBranch(iBr,6);  
    1693           0 :   }
    1694           0 :   (*pcstream)<<treeName.Data()<<"\n";
    1695           0 : }
    1696             : 
    1697             : 
    1698             : 
    1699             : TMultiGraph*  TStatToolkit::MakeStatusLines(TTree * tree, const char * expr, const char * cut, const char * alias) 
    1700             : {
    1701             :   //
    1702             :   // Create status lines for trending using MakeGraphSparse(), very similar to MakeStatusMultGr().
    1703             :   // (by Patrick Reichelt)
    1704             :   //
    1705             :   // format of expr :  varname:xaxis (e.g. meanTPCncl:run, but 'varname' can be any string that you need for seach-and-replace)
    1706             :   // format of cut  :  char like in TCut
    1707             :   // format of alias:  varname_OutlierMin:varname_OutlierMax:varname_WarningMin:varname_WarningMax:varname_PhysAccMin:varname_PhysAccMax:varname_RobustMean
    1708             :   //
    1709           0 :   TObjArray* oaVar = TString(expr).Tokenize(":");
    1710           0 :   if (oaVar->GetEntries()<2) {
    1711           0 :     printf("Expression has to be of type 'varname:xaxis':\t%s\n", expr);
    1712           0 :     return 0;
    1713             :   }
    1714           0 :   char varname[50];
    1715           0 :   char var_x[50];
    1716           0 :   snprintf(varname,50,"%s", oaVar->At(0)->GetName());
    1717           0 :   snprintf(var_x  ,50,"%s", oaVar->At(1)->GetName());
    1718             :   //
    1719           0 :   TString sAlias(alias);
    1720           0 :   if (sAlias.IsNull()) { // alias for default usage set here:
    1721           0 :     sAlias = "varname_OutlierMin:varname_OutlierMax:varname_WarningMin:varname_WarningMax:varname_PhysAccMin:varname_PhysAccMax:varname_RobustMean";
    1722             :   }
    1723           0 :   sAlias.ReplaceAll("varname",varname);
    1724           0 :   TObjArray* oaAlias = TString(sAlias.Data()).Tokenize(":");
    1725           0 :   if (oaAlias->GetEntries()<2) {
    1726           0 :     printf("Alias must have 2-7 arguments:\t%s\n", alias);
    1727           0 :     return 0;
    1728             :   }
    1729           0 :   char query[200];
    1730           0 :   TMultiGraph* multGr = new TMultiGraph();
    1731           0 :   Int_t colArr[7] = {kRed, kRed, kOrange, kOrange, kGreen+1, kGreen+1, kGray+2};
    1732           0 :   const Int_t ngr = oaAlias->GetEntriesFast();
    1733           0 :   for (Int_t i=0; i<ngr; i++){
    1734           0 :     snprintf(query,200, "%s:%s", oaAlias->At(i)->GetName(), var_x);
    1735           0 :     multGr->Add( (TGraphErrors*) TStatToolkit::MakeGraphSparse(tree,query,cut,29,colArr[i],1.5) );
    1736             :   }
    1737             :   //
    1738           0 :   multGr->SetName(varname);
    1739           0 :   multGr->SetTitle(varname);
    1740           0 :   delete oaVar;
    1741           0 :   delete oaAlias;
    1742             :   return multGr;
    1743           0 : }
    1744             : 
    1745             : 
    1746             : TH1* TStatToolkit::DrawHistogram(TTree * tree, const char* drawCommand, const char* cuts, const char* histoname, const char* histotitle, Int_t nsigma, Float_t fraction, TObjArray *description )
    1747             : {
    1748             :   //
    1749             :   // Draw histogram from TTree with robust range
    1750             :   // Only for 1D so far!
    1751             :   // 
    1752             :   // Parameters:
    1753             :   // - histoname:  name of histogram
    1754             :   // - histotitle: title of histgram
    1755             :   // - fraction:   fraction of data to define the robust mean
    1756             :   // - nsigma:     nsigma value for range
    1757             :   //
    1758             :   // To add:
    1759             :   //    automatic ranges - separatelly for X, Y and Z nbins  - as string
    1760             :   //    names for the variables
    1761             :   //    option, entries, first entry  like in tree draw
    1762             :   //
    1763           0 :    TString drawStr(drawCommand);
    1764           0 :    TString cutStr(cuts);
    1765             :    Int_t dim = 1;
    1766             : 
    1767           0 :    if(!tree) {
    1768           0 :      ::Error("TStatToolkit::DrawHistogram","Tree pointer is NULL!");
    1769           0 :      return 0;
    1770             :    }
    1771             : 
    1772             :    // get entries
    1773           0 :    Int_t entries = tree->Draw(drawStr.Data(), cutStr.Data(), "goff");
    1774           0 :    if (entries == -1) {
    1775           0 :      ::Error("TStatToolkit::DrawHistogram","Tree draw returns -!");
    1776           0 :      return 0;
    1777             :    }
    1778           0 :    TObjArray *charray = drawStr.Tokenize(":");
    1779             : 
    1780             :    // get dimension
    1781           0 :    if(tree->GetV1()) dim = 1;
    1782           0 :    if(tree->GetV2()) dim = 2;
    1783           0 :    if(tree->GetV3()) dim = 3;
    1784           0 :    if(dim > 2){
    1785           0 :      cerr<<"TTree has more than 2 dimensions (not yet supported)"<<endl;
    1786           0 :      return 0;
    1787             :    }
    1788             : 
    1789             :    // draw robust
    1790             :    // Get estimators
    1791           0 :    Double_t mean1=0, rms1=0, min1=0, max1=0;
    1792           0 :    Double_t mean2=0, rms2=0, min2=0, max2=0;
    1793           0 :    Double_t mean3=0, rms3=0, min3=0, max3=0;
    1794             :    
    1795           0 :    TStatToolkit::GetMinMaxMean( tree->GetV1(),entries, min1,max1, mean1);  
    1796           0 :    TStatToolkit::EvaluateUni(entries, tree->GetV1(),mean1,rms1, fraction*entries);
    1797           0 :    if(dim>1){
    1798           0 :      TStatToolkit::GetMinMaxMean( tree->GetV2(),entries, min2,max2, mean2);  
    1799           0 :      TStatToolkit::EvaluateUni(entries, tree->GetV1(),mean2,rms2, fraction*entries);
    1800             :    }
    1801           0 :    if(dim>2){
    1802           0 :      TStatToolkit::GetMinMaxMean( tree->GetV3(),entries, min3,max3, mean3);  
    1803           0 :      TStatToolkit::EvaluateUni(entries, tree->GetV3(),mean3,rms3, fraction*entries);
    1804             :    }
    1805             : 
    1806             :    TH1* hOut=NULL;
    1807           0 :    if(dim==1){
    1808           0 :      hOut = new TH1F(histoname, histotitle, 200, mean1-nsigma*rms1, mean1+nsigma*rms1);
    1809           0 :      for (Int_t i=0; i<entries; i++) hOut->Fill(tree->GetV1()[i]);
    1810           0 :      hOut->GetXaxis()->SetTitle(tree->GetHistogram()->GetXaxis()->GetTitle());
    1811             :    }
    1812           0 :    else if(dim==2){
    1813           0 :      hOut = new TH2F(histoname, histotitle, 200, min2, max2,200, mean1-nsigma*rms1, mean1+nsigma*rms1);
    1814           0 :      for (Int_t i=0; i<entries; i++) hOut->Fill(tree->GetV2()[i],tree->GetV1()[i]);
    1815           0 :      hOut->GetXaxis()->SetTitle(tree->GetHistogram()->GetXaxis()->GetTitle());
    1816           0 :      hOut->GetYaxis()->SetTitle(tree->GetHistogram()->GetYaxis()->GetTitle());
    1817             :    }
    1818           0 :    THashList * metaData = (THashList*) tree->GetUserInfo()->FindObject("metaTable");
    1819             :    
    1820           0 :    if (!metaData == 0){    
    1821           0 :     TNamed *nmdTitle0 = TStatToolkit::GetMetadata(tree,Form("%s.Title",charray->At(0)->GetName()));
    1822           0 :     TNamed *nmdXAxis  = TStatToolkit::GetMetadata(tree,Form("%s.AxisTitle",charray->At(1)->GetName())); 
    1823           0 :     TNamed *nmdTitle1 = TStatToolkit::GetMetadata(tree,Form("%s.Title",charray->At(1)->GetName()));
    1824           0 :     TNamed *nmdYAxis  = TStatToolkit::GetMetadata(tree,Form("%s.AxisTitle",charray->At(0)->GetName()));
    1825             :     //
    1826           0 :     TString hisTitle=charray->At(0)->GetName();
    1827           0 :     if (nmdTitle0)  hisTitle=nmdTitle0->GetTitle();
    1828           0 :     if (nmdTitle1)  {
    1829           0 :       hisTitle+=":";
    1830           0 :       hisTitle+=nmdTitle1->GetTitle();
    1831             :     }else{
    1832           0 :       hisTitle+=":";
    1833           0 :       hisTitle+=charray->At(1)->GetName();
    1834             :     }
    1835           0 :     if (nmdYAxis) {hOut->GetYaxis()->SetTitle(nmdYAxis->GetTitle());}
    1836           0 :     if (nmdXAxis) {hOut->GetXaxis()->SetTitle(nmdXAxis->GetTitle());}            
    1837           0 :     hOut->SetTitle(hisTitle);
    1838           0 :   }
    1839           0 :   delete charray;
    1840             :   // if (option) hOut->Draw(option);
    1841             :   return hOut;
    1842           0 : }
    1843             : 
    1844             : void TStatToolkit::CheckTreeAliases(TTree * tree, Int_t ncheck){
    1845             :   //
    1846             :   // Check consistency of tree aliases
    1847             :   //
    1848             :   Int_t nCheck=100;
    1849           0 :   TList * aliases = (TList*)tree->GetListOfAliases();
    1850           0 :   Int_t entries = aliases->GetEntries();
    1851           0 :   for (Int_t i=0; i<entries; i++){
    1852           0 :     TObject * object= aliases->At(i);
    1853           0 :     if (!object) continue;
    1854           0 :     Int_t ndraw=tree->Draw(aliases->At(i)->GetName(),"1","goff",nCheck);
    1855           0 :     if (ndraw==0){
    1856           0 :       ::Error("Alias:\tProblem","%s",aliases->At(i)->GetName());
    1857           0 :     }else{
    1858           0 :       ::Info("Alias:\tOK","%s",aliases->At(i)->GetName());
    1859             :     }
    1860           0 :   }
    1861           0 : }
    1862             : 
    1863             : 
    1864             : 
    1865             : 
    1866             : Double_t TStatToolkit::GetDefaultStat(TTree * tree, const char * var, const char * selection, TStatType statType){
    1867             :   //
    1868             :   //
    1869             :   //
    1870           0 :   Int_t entries = tree->Draw(var,selection,"goff");
    1871           0 :   if (entries==0) return 0;
    1872           0 :   switch(statType){    
    1873             :   case kEntries:    
    1874           0 :     return entries;
    1875             :   case kSum:    
    1876           0 :     return entries*TMath::Mean(entries, tree->GetV1());
    1877             :   case kMean:    
    1878           0 :     return TMath::Mean(entries, tree->GetV1());
    1879             :   case kRMS:     
    1880           0 :     return TMath::RMS(entries, tree->GetV1());
    1881             :   case kMedian:  
    1882           0 :     return TMath::Median(entries, tree->GetV1());    
    1883             :   }
    1884           0 :   return 0;
    1885           0 : }
    1886             : 
    1887             : //_____________________________________________________________________________
    1888             : void TStatToolkit::CombineArray(TTree *tree, TVectorD &values)
    1889             : {
    1890             :   /// Collect all variables from the last draw in one array.
    1891             :   ///
    1892             :   /// It is assumed that the Draw function of the TTree was called before
    1893             :   /// if e.g. Draw("v1:v2:v3") had been called, then values will contain
    1894             :   /// the concatenated array of the values from v1,v2 and v3.
    1895             :   /// E.g. if the v1[0..n], v2[0..n], v3[0..n] then
    1896             :   /// values[0..3n] = [v1, v2, v3]
    1897             :   /// \param[in]  tree   input tree
    1898             :   /// \param[out] values array in which to summarise all 'drawn' values
    1899           0 :   const Int_t numberOfDimensions = tree->GetPlayer()->GetDimension();
    1900           0 :   if (numberOfDimensions==1) {
    1901           0 :     values.Use(tree->GetSelectedRows(), tree->GetVal(0));
    1902           0 :     return;
    1903             :   }
    1904             : 
    1905           0 :   const Int_t numberOfSelectedRows = tree->GetSelectedRows();
    1906           0 :   values.ResizeTo(numberOfDimensions * numberOfSelectedRows);
    1907             : 
    1908             :   Int_t nfill=0;
    1909           0 :   for (Int_t idim=0; idim<numberOfDimensions; ++idim) {
    1910           0 :     const Double_t *arr = tree->GetVal(idim);
    1911           0 :     if (!arr) continue;
    1912             : 
    1913           0 :     for (Int_t ival=0; ival<numberOfSelectedRows; ++ival) {
    1914           0 :       values.GetMatrixArray()[nfill++] = arr[ival];
    1915             :     }
    1916           0 :   }
    1917             : 
    1918           0 : }
    1919             : 
    1920             : //_____________________________________________________________________________
    1921             : Double_t TStatToolkit::GetDistance(const TVectorD &values, const ENormType normType,
    1922             :                                    const Bool_t normaliseToEntries/*=kFALSE*/, const Double_t pvalue/*=1*/)
    1923             : {
    1924             :   /// Calculate the distance of the elements in values using a certain norm
    1925             :   /// \param[in] values             array with input values
    1926             :   /// \param[in] normType           normalisation to use
    1927             :   /// \param[in] normaliseToEntries divide the norm by the number of eleements ('average norm')
    1928             :   /// \param[in] pvalue             the p value for the p-type norm, ignored for all other norms
    1929             :   /// \return                       calculated distance
    1930             : 
    1931             :   Double_t norm=0.;
    1932             : 
    1933           0 :   switch (normType) {
    1934             :     case kL1:
    1935           0 :       norm=values.Norm1();
    1936           0 :       break;
    1937             :     case kL2:
    1938           0 :       norm=TMath::Sqrt(values.Norm2Sqr());
    1939           0 :       break;
    1940             :     case kLp:
    1941             :     {
    1942           0 :       if (pvalue<1.) {
    1943           0 :         ::Error("TStatToolkit::GetDistance","Lp norm: p-value=%5.3g not valid. Only p-value>=1 is allowed", pvalue);
    1944           0 :         break;
    1945             :       }
    1946             :       Double_t sum=0.;
    1947           0 :       for (Int_t ival=0; ival<values.GetNrows(); ++ival) {
    1948           0 :         sum+=TMath::Power(TMath::Abs(values.GetMatrixArray()[ival]), pvalue);
    1949             :       }
    1950           0 :       norm=TMath::Power(sum, 1./pvalue);
    1951             :     }
    1952           0 :     break;
    1953             :     case kMax:
    1954           0 :       norm=values.NormInf();
    1955           0 :       break;
    1956             :     case kHamming:
    1957             :     {
    1958             :       Double_t sum=0.;
    1959           0 :       for (Int_t ival=0; ival<values.GetNrows(); ++ival) {
    1960           0 :         if (TMath::Abs(values.GetMatrixArray()[ival])>1e-30) ++sum;
    1961             :       }
    1962             :       norm=sum;
    1963             :     }
    1964           0 :     break;
    1965             :   }
    1966           0 :   if (normaliseToEntries && values.GetNrows()>0) {
    1967           0 :     norm/=values.GetNrows();
    1968           0 :   }
    1969           0 :   return norm;
    1970             : }
    1971             : 
    1972             : //_____________________________________________________________________________
    1973             : Double_t TStatToolkit::GetDistance(const Int_t size, const Double_t *values, const ENormType normType,
    1974             :                                    const Bool_t normaliseToEntries/*=kFALSE*/, const Double_t pvalue/*=1*/)
    1975             : {
    1976             :   /// Calculate the distance of the elements in values using a certain norm
    1977             :   /// \sa GetDistance()
    1978           0 :   TVectorD vecvalues;
    1979           0 :   vecvalues.Use(size, values);
    1980           0 :   return GetDistance(vecvalues, normType, normaliseToEntries, pvalue);
    1981           0 : }
    1982             : 
    1983             : //_____________________________________________________________________________
    1984             : Double_t TStatToolkit::GetDistance(TTree * tree, const char* var, const char * selection,
    1985             :                                    const ENormType normType, const Bool_t normaliseToEntries/*=kFALSE*/, const Double_t pvalue/*=1*/)
    1986             : {
    1987             :   /// Calculate the distance of the values selecte in tree->Draw(var, selection)
    1988             :   ///
    1989             :   /// If var contains more than one variable (separated by ':' as usual) the arrays
    1990             :   /// are concatenated:<BR>
    1991             :   /// E.g. if var="v1:v2:v3", then the norm of the
    1992             :   /// the concatenated array of the values from v1,v2 and v3 will be calculated:<BR>
    1993             :   /// This means if the internal tree arrays for each variable are v1[0..n], v2[0..n], v3[0..n] then
    1994             :   /// the norm of vx[0..3n] = [v1, v2, v3] is calculated.
    1995             :   /// \param[in] tree               input tree
    1996             :   /// \param[in] var                variable expression for the tree->Draw()
    1997             :   /// \param[in] selection          selection for the tree->Draw()
    1998             :   /// \param[in] normType           norm to use for calculating the point distances
    1999             :   /// \param[in] normaliseToEntries divide the norm by the number of eleements ('average norm')
    2000             :   /// \param[in] pvalue             p-value for the p-norm (ignored for other norm types
    2001             :   /// \return                       calculated distnace
    2002           0 :   Int_t entries = tree->Draw(var,selection,"goff");
    2003           0 :   if (entries==0) return 0.;
    2004             : 
    2005           0 :   TVectorD values;
    2006           0 :   CombineArray(tree, values);
    2007           0 :   return GetDistance(values, normType, normaliseToEntries, pvalue);
    2008           0 : }
    2009             : 
    2010             : 
    2011             : 
    2012             : void TStatToolkit::MakeDistortionMap(Int_t iter, THnBase * histo, TTreeSRedirector *pcstream, TMatrixD &projectionInfo,Int_t dumpHisto, Int_t verbose){
    2013             :   //
    2014             :   // Recursive function to calculate Distortion maps from the residual histograms
    2015             :   // Input:
    2016             :   //   iter     - ndim..0
    2017             :   //   histo    - THn histogram
    2018             :   //   pcstream -
    2019             :   //   projectionInfo  - TMatrix speicifiing distortion map cration setup
    2020             :   //     user specify columns:
    2021             :   //       0.) sequence of dimensions 
    2022             :   //       1.) grouping in dimensions (how many bins will be groupd in specific dimension - 0 means onl specified bin 1, curren +-1 bin ...)
    2023             :   //       2.) step in dimension ( in case >1 some n(projectionInfo(<dim>,2) bins will be not exported
    2024             :   //     internally used collumns (needed to pass current bin index and bin center to the recursive function) 
    2025             :   //       3.) current bin value  
    2026             :   //       4.) current bin center
    2027             :   //
    2028             :   //  Output:
    2029             :   //   pcstream - file with output distortion tree
    2030             :   //    1.) distortion characteristic: mean, rms, gaussian fit parameters, meang, rmsG chi2 ... at speciefied bin 
    2031             :   //    2.) specidfied bins (tree branches) are defined by the name of the histogram axis in input histograms
    2032             :   //  
    2033             :   //    
    2034             :   //   Example projection info
    2035             :   /*
    2036             :     TFile *f  = TFile::Open("/hera/alice/hellbaer/alice-tpc-notes/SpaceChargeDistortion/data/ATO-108/fullMerge/SCcalibMergeLHC12d.root");
    2037             :     THnF* histof= (THnF*) f->Get("deltaY_ClTPC_ITSTOF");
    2038             :     histof->SetName("deltaRPhiTPCTISTOF");
    2039             :     histof->GetAxis(4)->SetName("qpt");
    2040             :     TH1::SetDirectory(0);
    2041             :     TTreeSRedirector * pcstream = new TTreeSRedirector("distortion.root","recreate");
    2042             :     TMatrixD projectionInfo(5,5);
    2043             :     projectionInfo(0,0)=0;  projectionInfo(0,1)=0;  projectionInfo(0,2)=0;
    2044             :     projectionInfo(1,0)=4;  projectionInfo(1,1)=0;  projectionInfo(1,2)=1; 
    2045             :     projectionInfo(2,0)=3;  projectionInfo(2,1)=3;  projectionInfo(2,2)=2;
    2046             :     projectionInfo(3,0)=2;  projectionInfo(3,1)=0;  projectionInfo(3,2)=5;
    2047             :     projectionInfo(4,0)=1;  projectionInfo(4,1)=5;  projectionInfo(4,2)=20;
    2048             :     MakeDistortionMap(4, histof, pcstream, projectionInfo); 
    2049             :     delete pcstream;
    2050             :   */
    2051             :   //
    2052           0 :   static TF1 fgaus("fgaus","gaus",-10,10);
    2053             :   const Double_t kMinEntries=50;
    2054           0 :   Int_t ndim=histo->GetNdimensions();
    2055           0 :   Int_t axis[ndim];
    2056           0 :   Double_t meanVector[ndim];
    2057           0 :   Int_t binVector[ndim];
    2058           0 :   Double_t centerVector[ndim];
    2059           0 :   for (Int_t idim=0; idim<ndim; idim++) axis[idim]=idim;
    2060             :   //
    2061           0 :   if (iter==0){
    2062           0 :     char tname[100];
    2063           0 :     char aname[100];
    2064           0 :     char bname[100];
    2065           0 :     char cname[100];
    2066             :     
    2067           0 :     snprintf(tname, 100, "%sDist",histo->GetName());
    2068             :     //
    2069             :     //
    2070             :     // 1.) Calculate  properties   - mean, rms, gaus fit, chi2, entries
    2071             :     // 2.) Dump properties to tree 1D properties  - plus dimension descriptor f
    2072             :     Int_t axis1D[1]={0};
    2073           0 :     Int_t dimProject   = TMath::Nint(projectionInfo(iter,0));
    2074             :     axis1D[0]=dimProject;
    2075           0 :     TH1 *his1DFull = histo->Projection(dimProject);
    2076           0 :     Double_t mean= his1DFull->GetMean();
    2077           0 :     Double_t rms= his1DFull->GetRMS();
    2078           0 :     Int_t entries=  his1DFull->GetEntries();
    2079           0 :     TString hname="his_";
    2080           0 :     for (Int_t idim=0; idim<ndim; idim++) {hname+="_"; hname+=TMath::Nint(projectionInfo(idim,3));}
    2081           0 :     Double_t meanG=0, rmsG=0, chi2G=0;
    2082           0 :     if (entries>kMinEntries){
    2083           0 :       fgaus.SetParameters(entries,mean,rms);
    2084           0 :       his1DFull->Fit(&fgaus,"qnr","qnr");
    2085           0 :       meanG = fgaus.GetParameter(1);
    2086           0 :       rmsG = fgaus.GetParameter(2);
    2087           0 :       chi2G = fgaus.GetChisquare()/fgaus.GetNumberFreeParameters();
    2088           0 :     }
    2089           0 :     if (dumpHisto>=0) {
    2090             :       static Int_t histoCounter=0;
    2091           0 :       if ((histoCounter%dumpHisto)==0) his1DFull->Write(hname.Data());
    2092           0 :       histoCounter++;
    2093           0 :     }
    2094           0 :     delete his1DFull;
    2095           0 :     (*pcstream)<<tname<<
    2096           0 :     "entries="<<entries<< // number of entries
    2097           0 :     "mean="<<mean<<       // mean value of the last dimension
    2098           0 :     "rms="<<rms<<         // rms value of the last dimension
    2099           0 :     "meanG="<<meanG<<     // mean of the gaus fit
    2100           0 :     "rmsG="<<rmsG<<       // rms of the gaus fit
    2101           0 :     "chi2G="<<chi2G;      // chi2 of the gaus fit
    2102             :     
    2103           0 :     for (Int_t idim=0; idim<ndim; idim++){
    2104             :       axis1D[0]=idim;
    2105           0 :       TH1 *his1DAxis = histo->Projection(idim);
    2106           0 :       meanVector[idim] = his1DAxis->GetMean();
    2107           0 :       snprintf(aname, 100, "%sMean=",histo->GetAxis(idim)->GetName());
    2108           0 :       (*pcstream)<<tname<<
    2109           0 :       aname<<meanVector[idim];      // current bin means
    2110           0 :       delete his1DAxis;
    2111             :     }
    2112           0 :     for (Int_t iIter=0; iIter<ndim; iIter++){
    2113           0 :       Int_t idim = TMath::Nint(projectionInfo(iIter,0));
    2114           0 :       binVector[idim] = TMath::Nint(projectionInfo(iIter,3));
    2115           0 :       centerVector[idim] = projectionInfo(iIter,4);
    2116           0 :       snprintf(bname, 100, "%sBin=",histo->GetAxis(idim)->GetName());
    2117           0 :       snprintf(cname, 100, "%sCenter=",histo->GetAxis(idim)->GetName());
    2118           0 :       (*pcstream)<<tname<<
    2119           0 :       bname<<binVector[idim]<<      // current bin values
    2120           0 :       cname<<centerVector[idim];    // current bin centers
    2121             :     }
    2122           0 :     (*pcstream)<<tname<<"\n";
    2123           0 :   }else{
    2124             :     // loop over the diminsion of interest
    2125             :     //      project selecting bin+-deltabin histoProj
    2126             :     //      MakeDistortionMap(histoProj ...) 
    2127             :     //
    2128           0 :     Int_t dimProject   = TMath::Nint(projectionInfo(iter,0));
    2129           0 :     Int_t groupProject =  TMath::Nint(projectionInfo(iter,1));
    2130           0 :     Int_t stepProject =  TMath::Nint(projectionInfo(iter,2));
    2131           0 :     if (stepProject<1) stepProject=1;
    2132           0 :     Int_t nbins = histo->GetAxis(dimProject)->GetNbins();
    2133             :     
    2134           0 :     for (Int_t ibin=1; ibin<=nbins; ibin+=stepProject){
    2135           0 :       if (iter>1 && verbose){
    2136           0 :         for (Int_t idim=0; idim<ndim; idim++){
    2137           0 :           printf("\t%d(%d,%d)",TMath::Nint(projectionInfo(idim,3)),TMath::Nint(projectionInfo(idim,0)),TMath::Nint(projectionInfo(idim,1) ));
    2138             :         }
    2139           0 :         printf("\n");     
    2140           0 :         AliSysInfo::AddStamp("xxx",iter, dimProject);
    2141           0 :       }
    2142           0 :       Int_t bin0=TMath::Max(ibin-groupProject,1);
    2143           0 :       Int_t bin1=TMath::Min(ibin+groupProject,nbins);
    2144           0 :       histo->GetAxis(dimProject)->SetRange(bin0,bin1);
    2145           0 :       projectionInfo(iter,3)=ibin;
    2146           0 :       projectionInfo(iter,4)=histo->GetAxis(dimProject)->GetBinCenter(ibin);
    2147           0 :       Int_t iterProject=iter-1;
    2148           0 :       MakeDistortionMap(iterProject, histo, pcstream, projectionInfo);
    2149             :     }
    2150             :   }
    2151             :   //
    2152           0 : }
    2153             : 
    2154             : void TStatToolkit::MakeDistortionMapFast(THnBase * histo, TTreeSRedirector *pcstream, TMatrixD &projectionInfo,Int_t verbose,  Double_t fractionCut, const char * estimators)
    2155             : {
    2156             :   //
    2157             :   // Function to calculate Distortion maps from the residual histograms
    2158             :   // Input:
    2159             :   //   histo    - THn histogram
    2160             :   //   pcstream -
    2161             :   //   projectionInfo  - TMatrix speicifiing distortion map cration setup
    2162             :   //     user specify columns:
    2163             :   //       0.) sequence of dimensions 
    2164             :   //       1.) grouping in dimensions (how many bins will be groupd in specific dimension - 0 means onl specified bin 1, curren +-1 bin ...)
    2165             :   //       2.) step in dimension ( in case >1 some n(projectionInfo(<dim>,2) bins will be not exported
    2166             :   //
    2167             :   //  Output:
    2168             :   //   pcstream - file with output distortion tree
    2169             :   //    1.) distortion characteristic: mean, rms, gaussian fit parameters, meang, rmsG chi2 ... at speciefied bin 
    2170             :   //    2.) specidfied bins (tree branches) are defined by the name of the histogram axis in input histograms
    2171             :   //    3.) in debug mode - controlled by env variable "gDumpHistoFraction" fractio of histogram + fits dumped to the file 
    2172             :   //    
    2173             :   //   Example projection info
    2174             :   /*
    2175             :     TFile *f  = TFile::Open("/hera/alice/hellbaer/alice-tpc-notes/SpaceChargeDistortion/data/ATO-108/fullMerge/SCcalibMergeLHC12d.root");
    2176             :     THnF* histof= (THnF*) f->Get("deltaY_ClTPC_ITSTOF");
    2177             :     histof->SetName("deltaRPhiTPCTISTOF");
    2178             :     histof->GetAxis(4)->SetName("qpt");
    2179             :     TH1::SetDirectory(0);
    2180             :     TTreeSRedirector * pcstream = new TTreeSRedirector("distortion.root","recreate");
    2181             :     TMatrixD projectionInfo(5,3);
    2182             :     projectionInfo(0,0)=0;  projectionInfo(0,1)=0;  projectionInfo(0,2)=0;
    2183             :     projectionInfo(1,0)=4;  projectionInfo(1,1)=0;  projectionInfo(1,2)=1; 
    2184             :     projectionInfo(2,0)=3;  projectionInfo(2,1)=3;  projectionInfo(2,2)=2;
    2185             :     projectionInfo(3,0)=2;  projectionInfo(3,1)=0;  projectionInfo(3,2)=5;
    2186             :     projectionInfo(4,0)=1;  projectionInfo(4,1)=5;  projectionInfo(4,2)=20;
    2187             :     MakeDistortionMap(histof, pcstream, projectionInfo); 
    2188             :     delete pcstream;
    2189             :   */
    2190             :   //
    2191             :   const Double_t kMinEntries=30, kUseLLFrom=20;
    2192           0 :   const Float_t  kDumpHistoFraction = TString(gSystem->Getenv("gDumpHistoFraction")).Atof();  // in debug mode - controlled by env variable "gDumpHistoFraction" fractio of histogram + fits dumped to the file 
    2193           0 :   char tname[100];
    2194           0 :   char aname[100];
    2195           0 :   char bname[100];
    2196           0 :   char cname[100];
    2197           0 :   Float_t fractionLTM[100]={0.8};
    2198           0 :   TVectorF *vecLTM[100]={0};
    2199             :   Int_t nestimators=1;
    2200           0 :   if (estimators!=NULL){
    2201           0 :     TObjArray * array=TString(estimators).Tokenize(":");
    2202           0 :     nestimators=array->GetEntries();
    2203           0 :     for (Int_t iest=0; iest<nestimators; iest++){
    2204           0 :       fractionLTM[iest]=TString(array->At(iest)->GetName()).Atof();
    2205             :     }
    2206           0 :   }
    2207           0 :   for (Int_t iest=0; iest<nestimators; iest++) {
    2208           0 :     vecLTM[iest]=new TVectorF(10);
    2209           0 :     (*(vecLTM[iest]))[9]= fractionLTM[iest];
    2210             :   }
    2211             : 
    2212             :   //
    2213           0 :   int ndim = histo->GetNdimensions();
    2214           0 :   int nbins[ndim],idx[ndim],idxmin[ndim],idxmax[ndim],idxSav[ndim];
    2215           0 :   for (int id=0;id<ndim;id++) nbins[id] = histo->GetAxis(id)->GetNbins();
    2216             :   //
    2217           0 :   int axOrd[ndim],binSt[ndim],binGr[ndim];
    2218           0 :   for (int i=0;i<ndim;i++) {
    2219           0 :     axOrd[i] = TMath::Nint(projectionInfo(i,0));
    2220           0 :     binGr[i] = TMath::Nint(projectionInfo(i,1));
    2221           0 :     binSt[i] = TMath::Max(1,TMath::Nint(projectionInfo(i,2)));
    2222             :   }
    2223           0 :   int tgtDim = axOrd[0],tgtStep=binSt[0],tgtNb=nbins[tgtDim],tgtNb1=tgtNb+1;
    2224           0 :   double binY[tgtNb],binX[tgtNb],meanVector[ndim],centerVector[ndim];
    2225           0 :   Int_t binVector[ndim];
    2226             :   // prepare X axis
    2227           0 :   TAxis* xax = histo->GetAxis(tgtDim);
    2228           0 :   for (int i=tgtNb;i--;) binX[i] = xax->GetBinCenter(i+1);
    2229           0 :   for (int i=ndim;i--;) idx[i]=1;
    2230             :   Bool_t grpOn = kFALSE;
    2231           0 :   for (int i=1;i<ndim;i++) if (binGr[i]) grpOn = kTRUE;
    2232             :   //
    2233             :   // estimate number of output fits
    2234           0 :   histo->GetListOfAxes()->Print();
    2235             :   ULong64_t nfits = 1, fitCount=0;
    2236           0 :   printf("index\tdim\t|\tnbins\tgrouping\tstep\tnfits\n");
    2237           0 :   for (int i=1;i<ndim;i++) {
    2238           0 :     int idim = axOrd[i];
    2239           0 :     nfits *= TMath::Max(1,nbins[idim]/binSt[idim]);
    2240           0 :     printf("%d %d | %d %d %d %lld\n",i,idim,nbins[idim],binGr[idim], binSt[idim],nfits);
    2241             :   }
    2242           0 :   printf("Expect %lld nfits\n",nfits);
    2243           0 :   ULong64_t fitProgress = nfits/100;
    2244             :   //
    2245             :   // setup fit function, at the moment full root fit
    2246           0 :   static TF1 fgaus("fgaus","gaus",-10,10);
    2247           0 :   fgaus.SetRange(xax->GetXmin(),xax->GetXmax());
    2248             :   //  TGraph grafFit(tgtNb);
    2249           0 :   TH1F* hfit = new TH1F("hfit","hfit",tgtNb,xax->GetXmin(),xax->GetXmax());
    2250             :   //
    2251           0 :   snprintf(tname, 100, "%sDist",histo->GetName());
    2252           0 :   TStopwatch sw;
    2253           0 :   sw.Start();
    2254           0 :   int dimVar=1, dimVarID = axOrd[dimVar];
    2255             :   //
    2256             :   //  TVectorF  vecLTM(9);
    2257           0 :   while(1) {
    2258             :     //
    2259           0 :     double dimVarCen = histo->GetAxis(dimVarID)->GetBinCenter(idx[dimVarID]); // center of currently varied bin
    2260             :     //
    2261           0 :     if (grpOn) { //>> grouping requested?
    2262           0 :       memset(binY,0,tgtNb*sizeof(double)); // need to accumulate
    2263             :       //
    2264           0 :       for (int idim=1;idim<ndim;idim++) {
    2265           0 :         int grp = binGr[idim];
    2266           0 :         int idimR = axOrd[idim]; // real axis id
    2267           0 :         idxSav[idimR]=idx[idimR]; // save central bins
    2268           0 :         idxmax[idimR] = TMath::Min(idx[idimR]+grp,nbins[idimR]);
    2269           0 :         idx[idimR] = idxmin[idimR] = TMath::Max(1,idx[idimR]-grp);
    2270             :         // 
    2271             :         // effective bin center
    2272           0 :         meanVector[idimR] = 0;
    2273           0 :         TAxis* ax = histo->GetAxis(idimR);
    2274           0 :         if (grp>0) {
    2275           0 :           for (int k=idxmin[idimR];k<=idxmax[idimR];k++) meanVector[idimR] += ax->GetBinCenter(k);
    2276           0 :           meanVector[idimR] /= (1+(grp<<1));
    2277           0 :         }
    2278           0 :         else meanVector[idimR] = ax->GetBinCenter(idxSav[idimR]);
    2279             :       } // set limits for grouping
    2280           0 :       if (verbose>0) {
    2281           0 :         printf("output bin: "); 
    2282           0 :         for (int i=0;i<ndim;i++) if (i!=tgtDim) printf("[D:%d]:%d ",i,idxSav[i]); printf("\n");
    2283           0 :         printf("integrates: ");
    2284           0 :         for (int i=0;i<ndim;i++) if (i!=tgtDim) printf("[D:%d]:%d-%d ",i,idxmin[i],idxmax[i]); printf("\n");
    2285             :       }
    2286             :       //
    2287             :       while(1) {
    2288             :         // loop over target dimension: accumulation
    2289           0 :         int &it = idx[tgtDim];
    2290           0 :         for (it=1;it<tgtNb1;it+=tgtStep) {
    2291           0 :           binY[it-1] += histo->GetBinContent(idx);
    2292           0 :           if (verbose>1) {for (int i=0;i<ndim;i++) printf("%d ",idx[i]); printf(" | accumulation\n");}
    2293             :         }
    2294             :         //
    2295             :         int idim;
    2296           0 :         for (idim=1;idim<ndim;idim++) { // dimension being groupped
    2297           0 :           int idimR = axOrd[idim]; // real axis id in the histo
    2298           0 :           if ( (++idx[idimR]) > idxmax[idimR] ) idx[idimR]=idxmin[idimR];
    2299           0 :           else break;
    2300           0 :         }
    2301           0 :         if (idim==ndim) break;
    2302           0 :       }
    2303             :     } // <<grouping requested
    2304             :     else {
    2305           0 :       int &it = idx[tgtDim];
    2306           0 :       for (it=1;it<tgtNb1;it+=tgtStep) {
    2307           0 :         binY[it-1] = histo->GetBinContent(idx);
    2308             :         //
    2309             :         //for (int i=0;i<ndim;i++) printf("%d ",idx[i]); printf(" | \n");
    2310             :       }
    2311           0 :       for (int idim=1;idim<ndim;idim++) {
    2312           0 :         int idimR = axOrd[idim]; // real axis id
    2313           0 :         meanVector[idimR] = histo->GetAxis(idimR)->GetBinCenter(idx[idimR]);
    2314             :       }
    2315             :     }
    2316           0 :     if (grpOn) for (int i=ndim;i--;) idx[i]=idxSav[i]; // restore central bins
    2317           0 :     idx[tgtDim] = 0;
    2318           0 :     if (verbose>0) {for (int i=0;i<ndim;i++) printf("%d ",idx[i]); printf(" | central bin fit\n");}
    2319             :     // 
    2320             :     // >> ------------- do fit
    2321           0 :     float mean=0,mom2=0,rms=0,m3=0, m4=0, nrm=0,meanG=0,rmsG=0,chi2G=0,maxVal=0,entriesG=0,mean0=0, rms0=0, curt0=0;
    2322           0 :     hfit->Reset();
    2323           0 :     for (int ip=tgtNb;ip--;) {
    2324             :       //grafFit.SetPoint(ip,binX[ip],binY[ip]);
    2325           0 :       hfit->SetBinContent(ip+1,binY[ip]);
    2326           0 :       nrm  += binY[ip];
    2327           0 :       mean += binX[ip]*binY[ip];
    2328           0 :       mom2 += binX[ip]*binX[ip]*binY[ip];
    2329           0 :       if (maxVal<binY[ip]) maxVal = binY[ip];
    2330             :     }
    2331           0 :     if (nrm>0) {
    2332           0 :       mean /= nrm;
    2333           0 :       mom2 /= nrm;
    2334           0 :       rms = mom2 - mean*mean;
    2335           0 :       rms = rms>0 ? TMath::Sqrt(rms):0;
    2336           0 :     }
    2337           0 :     mean0=mean;
    2338           0 :     rms0=rms;
    2339             :     
    2340             : 
    2341           0 :     Int_t nbins1D=hfit->GetNbinsX();
    2342           0 :     Float_t binMedian=0;
    2343           0 :     Double_t limits[2]={hfit->GetBinCenter(1), hfit->GetBinCenter(nbins1D)};
    2344           0 :     if (nrm>5) {
    2345           0 :       for (Int_t iest=0; iest<nestimators; iest++){
    2346           0 :         TStatToolkit::LTMHisto(hfit, *(vecLTM[iest]), fractionLTM[iest]); 
    2347             :       }
    2348           0 :       Double_t* integral=hfit->GetIntegral();      
    2349           0 :       for (Int_t i=1; i<nbins1D-1; i++){
    2350           0 :         if (integral[i-1]<0.5 && integral[i]>=0.5){
    2351           0 :           if (hfit->GetBinContent(i-1)+hfit->GetBinContent(i)>0){
    2352           0 :             binMedian=hfit->GetBinCenter(i);
    2353           0 :             Double_t dIdx=-(integral[i-1]-integral[i]);
    2354           0 :             Double_t dx=(0.5+(0.5-integral[i])/dIdx)*hfit->GetBinWidth(i);
    2355           0 :             binMedian+=dx;
    2356           0 :           }
    2357             :         }
    2358           0 :         if (integral[i-1]<fractionCut && integral[i]>=fractionCut){
    2359           0 :           limits[0]=hfit->GetBinCenter(i-1)-hfit->GetBinWidth(i);
    2360           0 :         }
    2361           0 :         if (integral[i]<1-fractionCut && integral[i+1]>=1-fractionCut){
    2362           0 :           limits[1]=hfit->GetBinCenter(i+1)+hfit->GetBinWidth(i);
    2363           0 :         }
    2364             :       }
    2365           0 :     }
    2366           0 :     if (nrm>5&&fractionCut>0 &&rms>0) {
    2367           0 :       hfit->GetXaxis()->SetRangeUser(limits[0], limits[1]);
    2368           0 :       mean=hfit->GetMean();
    2369           0 :       rms=hfit->GetRMS();
    2370           0 :       if (nrm>0 && rms>0) {
    2371           0 :         m3=hfit->GetSkewness();
    2372           0 :         m4=hfit->GetKurtosis();
    2373           0 :       }
    2374           0 :       fgaus.SetRange(limits[0]-rms, limits[1]+rms);
    2375             :     }else{
    2376           0 :       fgaus.SetRange(xax->GetXmin(),xax->GetXmax());
    2377             :     }
    2378             : 
    2379             : 
    2380           0 :     Bool_t isFitValid=kFALSE; 
    2381           0 :     if (nrm>=kMinEntries && rms>0) {      
    2382           0 :       fgaus.SetParameters(nrm/(rms/hfit->GetBinWidth(nbins1D)),mean,rms);
    2383             :       //grafFit.Fit(&fgaus,/*maxVal<kUseLLFrom ? "qnrl":*/"qnr");
    2384           0 :       TFitResultPtr fitPtr= hfit->Fit(&fgaus,maxVal<kUseLLFrom ? "qnrlS":"qnrS");
    2385           0 :       entriesG = fgaus.GetParameter(0);
    2386           0 :       meanG = fgaus.GetParameter(1);
    2387           0 :       rmsG  = fgaus.GetParameter(2);
    2388           0 :       chi2G = fgaus.GetChisquare()/fgaus.GetNumberFreeParameters();
    2389           0 :       TFitResult * result = fitPtr.Get();
    2390           0 :       if (result!=NULL){
    2391           0 :         isFitValid = result->IsValid();
    2392           0 :       }
    2393             :       //
    2394           0 :     }
    2395             :     TH1 * hDump=0;
    2396           0 :     if (nrm>=kMinEntries&& kDumpHistoFraction>0 && (gRandom->Rndm()<kDumpHistoFraction ||  isFitValid!=kTRUE)){
    2397             :       hDump=hfit;
    2398           0 :     }
    2399           0 :     if (hDump){
    2400           0 :       (*pcstream)<<TString::Format("%sDump", tname).Data()<<
    2401           0 :         "entries="<<nrm<<     // number of entries
    2402           0 :         "isFitValid="<<isFitValid<< // true if the gaus fit converged
    2403           0 :         "hDump.="<<hDump<<    // histogram  - by default not filled
    2404           0 :         "mean0="<<mean0<<       // mean value of the last dimension - without fraction cut
    2405           0 :         "rms0="<<rms0<<         // rms value of the last dimension - without fraction cut
    2406           0 :         "mean="<<mean<<       // mean value of the last dimension
    2407           0 :         "rms="<<rms<<         // rms value of the last dimension
    2408           0 :         "m3="<<m3<<            // m3 (skewnes) of the last dimension
    2409           0 :         "m4="<<m4<<            // m4 (kurtosis) of the last dimension
    2410           0 :         "binMedian="<<binMedian<< //binned median value of 1D histogram
    2411           0 :         "entriesG="<<entriesG<< 
    2412           0 :         "meanG="<<meanG<<     // mean of the gaus fit
    2413           0 :         "rmsG="<<rmsG<<       // rms of the gaus fit      
    2414           0 :         "vecLTM.="<<vecLTM[0]<<   // LTM  frac% statistic
    2415           0 :         "chi2G="<<chi2G;      // chi2 of the gaus fit      
    2416           0 :       for (Int_t iest=1; iest<nestimators; iest++) 
    2417           0 :         (*pcstream)<<TString::Format("%sDump", tname).Data()<<TString::Format("vecLTM%d.=",iest)<<vecLTM[iest];   // LTM  frac% statistic
    2418             :       
    2419           0 :     }
    2420             : 
    2421           0 :     (*pcstream)<<tname<<
    2422           0 :       "entries="<<nrm<<     // number of entries
    2423           0 :       "isFitValid="<<isFitValid<< // true if the gaus fit converged
    2424           0 :       "mean0="<<mean0<<       // mean value of the last dimension - without fraction cut
    2425           0 :       "rms0="<<rms0<<         // rms value of the last dimension - without fraction cut
    2426           0 :       "mean="<<mean<<       // mean value of the last dimension
    2427           0 :       "rms="<<rms<<         // rms value of the last dimension
    2428           0 :       "m3="<<m3<<            // m3 (skewnes) of the last dimension
    2429           0 :       "m4="<<m4<<            // m4 (kurtosis) of the last dimension
    2430           0 :       "binMedian="<<binMedian<< //binned median value of 1D histogram
    2431           0 :       "entriesG="<<entriesG<<   // 
    2432           0 :       "meanG="<<meanG<<     // mean of the gaus fit
    2433           0 :       "rmsG="<<rmsG<<       // rms of the gaus fit
    2434           0 :       "vecLTM.="<<vecLTM[0]<<   // LTM  frac% statistic
    2435           0 :       "chi2G="<<chi2G;      // chi2 of the gaus fit
    2436           0 :     for (Int_t iest=1; iest<nestimators; iest++) 
    2437           0 :       (*pcstream)<<tname<<TString::Format("vecLTM%d.=",iest)<<vecLTM[iest];   // LTM  frac% statistic
    2438             : 
    2439             : 
    2440             :     //
    2441           0 :     meanVector[tgtDim] = mean; // what's a point of this?
    2442           0 :     for (Int_t idim=0; idim<ndim; idim++){
    2443           0 :       snprintf(aname, 100, "%sMean=",histo->GetAxis(idim)->GetName());
    2444           0 :       (*pcstream)<<tname<<
    2445           0 :         aname<<meanVector[idim];      // current bin means
    2446             :     }
    2447             :     //
    2448           0 :     for (Int_t iIter=0; iIter<ndim; iIter++){
    2449           0 :       Int_t idim = axOrd[iIter];
    2450           0 :       binVector[idim] = idx[idim];
    2451           0 :       centerVector[idim] = histo->GetAxis(idim)->GetBinCenter(idx[idim]);
    2452           0 :       snprintf(bname, 100, "%sBin=",histo->GetAxis(idim)->GetName());
    2453           0 :       snprintf(cname, 100, "%sCenter=",histo->GetAxis(idim)->GetName());
    2454           0 :       (*pcstream)<<tname<<
    2455           0 :         bname<<binVector[idim]<<      // current bin values
    2456           0 :         cname<<centerVector[idim];    // current bin centers
    2457           0 :       if (hDump){
    2458           0 :         (*pcstream)<<TString::Format("%sDump", tname).Data()<<
    2459           0 :           bname<<binVector[idim]<<      // current bin values
    2460           0 :           cname<<centerVector[idim];    // current bin centers
    2461           0 :        }      
    2462             :     }
    2463           0 :     (*pcstream)<<tname<<"\n";
    2464           0 :     if (hDump)  (*pcstream)<<TString::Format("%sDump", tname).Data()<<"\n";
    2465             :     // << ------------- do fit
    2466             :     //
    2467           0 :     if (((++fitCount)%fitProgress)==0) {
    2468           0 :       printf("fit %lld %4.1f%% done\n",fitCount,100*double(fitCount)/nfits); 
    2469           0 :       AliSysInfo::AddStamp("fitCout", 1,fitCount,100*double(fitCount)/nfits);
    2470             :     }
    2471             :     //
    2472             :     //next global bin in which target dimention will be looped
    2473           0 :     for (dimVar=1;dimVar<ndim;dimVar++) { // varying dimension
    2474           0 :       dimVarID = axOrd[dimVar]; // real axis id in the histo
    2475           0 :       if ( (idx[dimVarID]+=binSt[dimVar]) > nbins[dimVarID] ) idx[dimVarID]=1;
    2476             :       else break;
    2477             :     }
    2478           0 :     if (dimVar==ndim) break;
    2479           0 :   }
    2480           0 :   delete hfit;
    2481           0 :   sw.Stop();
    2482           0 :   sw.Print();
    2483             :   /*
    2484             :   int nb = histo->GetNbins();
    2485             :   int prc = nb/100;
    2486             :   for (int i=0;i<nb;i++) {
    2487             :     histo->GetBinContent(i);
    2488             :     if (i && (i%prc)==0) printf("Done %d%%\n",int(float(100*i)/prc));
    2489             :   }
    2490             :   */
    2491           0 : }

Generated by: LCOV version 1.11