1 /**************************************************************************
2 * Copyright(c) 1998-1999, ALICE Experiment at CERN, All rights reserved. *
4 * Author: The ALICE Off-line Project. *
5 * Contributors are mentioned in the code where appropriate. *
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 **************************************************************************/
18 ///////////////////////////////////////////////////////////////////////////
20 // Perform statistics on various multi-dimensional data samples.
21 // A data sample can be filled using the "Enter" and/or "Remove" functions,
22 // whereas the "Reset" function resets the complete sample to 'empty'.
23 // The info which can be extracted from a certain data sample are the
24 // sum, mean, variance, sigma, covariance and correlation.
25 // The "Data" function provides all statistics data for a certain sample.
26 // The variables for which these stat. parameters have to be calculated
27 // are indicated by the index of the variable which is passed as an
28 // argument to the various member functions.
29 // The index convention for a data point (x,y) is : x=1 y=2
33 // For an AliSample s a data point (x,y) can be entered as s.Enter(x,y) and
34 // the mean_x can be obtained as s.GetMean(1) whereas the mean_y is obtained
36 // The correlation between x and y is available via s.GetCor(1,2).
37 // The x-statistics are obtained via s.Data(1), y-statistics via s.Data(2),
38 // and the covariance and correlation between x and y via s.Data(1,2).
39 // All statistics of a sample are obtained via s.Data().
41 //--- Author: Nick van Eijndhoven 30-mar-1996 CERN Geneva
42 //- Modified: NvE $Date$ UU-SAP Utrecht
43 ///////////////////////////////////////////////////////////////////////////
45 #include "AliSample.h"
46 #include "Riostream.h"
48 ClassImp(AliSample) // Class implementation to enable ROOT I/O
50 AliSample::AliSample()
52 // Creation of an Aliample object and resetting the statistics values
53 // The dimension is initialised to maximum
67 ///////////////////////////////////////////////////////////////////////////
68 AliSample::~AliSample()
92 ///////////////////////////////////////////////////////////////////////////
93 void AliSample::Reset()
95 // Resetting the statistics values for a certain Sample object
96 // Dimension and storage flag are NOT changed
99 for (Int_t i=0; i<fDim; i++)
107 for (Int_t j=0; j<fDim; j++)
115 // Set storage arrays to initial size
120 ///////////////////////////////////////////////////////////////////////////
121 void AliSample::Enter(Float_t x)
123 // Entering a value into a 1-dim. sample
124 // In case of first entry the dimension is set to 1
134 cout << " *AliSample::enter* Error : Not a 1-dim sample." << endl;
149 if (x<fMin[0]) fMin[0]=x;
150 if (x>fMax[0]) fMax[0]=x;
153 // Store all entered data when storage mode has been selected
156 if (!fX) fX=new TArrayF(10);
157 if (fX->GetSize() < fN) fX->Set(fN+10);
161 // Compute the various statistics
165 ///////////////////////////////////////////////////////////////////////////
166 void AliSample::Remove(Float_t x)
168 // Removing a value from a 1-dim. sample
174 cout << " *AliSample::remove* Error : Not a 1-dim sample." << endl;
183 // Remove data entry from the storage
187 for (Int_t i=0; i<=fN; i++)
190 if (fabs(x-val)>1.e-10) continue;
192 for (Int_t j=i+1; j<=fN; j++)
200 // Compute the various statistics
204 ///////////////////////////////////////////////////////////////////////////
205 void AliSample::Enter(Float_t x,Float_t y)
207 // Entering a pair (x,y) into a 2-dim. sample
208 // In case of first entry the dimension is set to 2
218 cout << " *AliSample::enter* Error : Not a 2-dim sample." << endl;
239 if (x<fMin[0]) fMin[0]=x;
240 if (x>fMax[0]) fMax[0]=x;
241 if (y<fMin[1]) fMin[1]=y;
242 if (y>fMax[1]) fMax[1]=y;
245 // Store all entered data when storage mode has been selected
248 if (!fX) fX=new TArrayF(10);
249 if (fX->GetSize() < fN) fX->Set(fN+10);
251 if (!fY) fY=new TArrayF(10);
252 if (fY->GetSize() < fN) fY->Set(fN+10);
256 // Compute the various statistics
260 ///////////////////////////////////////////////////////////////////////////
261 void AliSample::Remove(Float_t x,Float_t y)
263 // Removing a pair (x,y) from a 2-dim. sample
269 cout << " *AliSample::remove* Error : Not a 2-dim sample." << endl;
282 // Remove data entry from the storage
283 if (fStore && fX && fY)
286 for (Int_t i=0; i<=fN; i++)
289 if (fabs(x-val)>1.e-10) continue;
291 if (fabs(y-val)>1.e-10) continue;
293 for (Int_t j=i+1; j<=fN; j++)
303 // Compute the various statistics
307 ///////////////////////////////////////////////////////////////////////////
308 void AliSample::Enter(Float_t x,Float_t y,Float_t z)
310 // Entering a set (x,y,z) into a 3-dim. sample
311 // In case of first entry the dimension is set to 3
321 cout << " *AliSample::enter* Error : Not a 3-dim sample." << endl;
350 if (x<fMin[0]) fMin[0]=x;
351 if (x>fMax[0]) fMax[0]=x;
352 if (y<fMin[1]) fMin[1]=y;
353 if (y>fMax[1]) fMax[1]=y;
354 if (z<fMin[2]) fMin[2]=z;
355 if (z>fMax[2]) fMax[2]=z;
358 // Store all entered data when storage mode has been selected
361 if (!fX) fX=new TArrayF(10);
362 if (fX->GetSize() < fN) fX->Set(fN+10);
364 if (!fY) fY=new TArrayF(10);
365 if (fY->GetSize() < fN) fY->Set(fN+10);
367 if (!fZ) fZ=new TArrayF(10);
368 if (fZ->GetSize() < fN) fZ->Set(fN+10);
372 // Compute the various statistics
376 ///////////////////////////////////////////////////////////////////////////
377 void AliSample::Remove(Float_t x,Float_t y,Float_t z)
379 // Removing a set (x,y,z) from a 3-dim. sample
385 cout << " *AliSample::remove* Error : Not a 3-dim sample." << endl;
404 // Remove data entry from the storage
405 if (fStore && fX && fY && fZ)
408 for (Int_t i=0; i<=fN; i++)
411 if (fabs(x-val)>1.e-10) continue;
413 if (fabs(y-val)>1.e-10) continue;
415 if (fabs(z-val)>1.e-10) continue;
417 for (Int_t j=i+1; j<=fN; j++)
429 // Compute the various statistics
433 ///////////////////////////////////////////////////////////////////////////
434 void AliSample::Compute()
436 // Computation of the various statistical values
437 // after each entering or removing action on a certain sample
439 for (Int_t k=0; k<fDim; k++)
442 fVar[k]=(fSum2[k][k]/rn)-(fMean[k]*fMean[k]);
443 if (fVar[k] < 0.) fVar[k]=0.;
444 fSigma[k]=sqrt(fVar[k]);
446 for (Int_t i=0; i<fDim; i++)
448 for (Int_t j=0; j<fDim; j++)
450 fCov[i][j]=(fSum2[i][j]/rn)-(fMean[i]*fMean[j]);
451 Float_t sigij=fSigma[i]*fSigma[j];
452 if (sigij != 0.) fCor[i][j]=fCov[i][j]/sigij;
456 ///////////////////////////////////////////////////////////////////////////
457 Int_t AliSample::GetDimension() const
459 // Provide the dimension of a certain sample
462 ///////////////////////////////////////////////////////////////////////////
463 Int_t AliSample::GetN() const
465 // Provide the number of entries of a certain sample
468 ///////////////////////////////////////////////////////////////////////////
469 Float_t AliSample::GetSum(Int_t i) const
471 // Provide the sum of a certain variable
474 cout << " *AliSample::sum* Error : Dimension less than " << i << endl;
482 ///////////////////////////////////////////////////////////////////////////
483 Float_t AliSample::GetMean(Int_t i) const
485 // Provide the mean of a certain variable
488 cout << " *AliSample::mean* Error : Dimension less than " << i << endl;
496 ///////////////////////////////////////////////////////////////////////////
497 Float_t AliSample::GetVar(Int_t i) const
499 // Provide the variance of a certain variable
502 cout << " *AliSample::var* Error : Dimension less than " << i << endl;
510 ///////////////////////////////////////////////////////////////////////////
511 Float_t AliSample::GetSigma(Int_t i) const
513 // Provide the standard deviation of a certain variable
516 cout << " *AliSample::sigma* Error : Dimension less than " << i << endl;
524 ///////////////////////////////////////////////////////////////////////////
525 Float_t AliSample::GetCov(Int_t i,Int_t j) const
527 // Provide the covariance between variables i and j
528 if ((fDim < i) || (fDim < j))
532 cout << " *AliSample::cov* Error : Dimension less than " << k << endl;
537 return fCov[i-1][j-1];
540 ///////////////////////////////////////////////////////////////////////////
541 Float_t AliSample::GetCor(Int_t i,Int_t j) const
543 // Provide the correlation between variables i and j
544 if ((fDim < i) || (fDim < j))
548 cout << " *AliSample::cor* Error : Dimension less than " << k << endl;
553 return fCor[i-1][j-1];
556 ///////////////////////////////////////////////////////////////////////////
557 void AliSample::Data()
559 // Printing of statistics of all variables
560 for (Int_t i=0; i<fDim; i++)
562 cout << " " << fNames[i] << " : N = " << fN;
563 cout << " Sum = " << fSum[i] << " Mean = " << fMean[i];
564 cout << " Var = " << fVar[i] << " Sigma = " << fSigma[i];
568 cout << " Minimum = " << GetMinimum(i+1);
569 cout << " Maximum = " << GetMaximum(i+1);
570 cout << " Median = " << GetMedian(i+1);
575 ///////////////////////////////////////////////////////////////////////////
576 void AliSample::Data(Int_t i)
578 // Printing of statistics of ith variable
581 cout << " *AliSample::Data(i)* Error : Dimension less than " << i << endl;
585 cout << " " << fNames[i-1] << " : N = " << fN;
586 cout << " Sum = " << fSum[i-1] << " Mean = " << fMean[i-1];
587 cout << " Var = " << fVar[i-1] << " Sigma = " << fSigma[i-1];
591 cout << " Minimum = " << GetMinimum(i);
592 cout << " Maximum = " << GetMaximum(i);
593 cout << " Median = " << GetMedian(i);
598 ///////////////////////////////////////////////////////////////////////////
599 void AliSample::Data(Int_t i,Int_t j) const
601 // Printing of covariance and correlation between variables i and j
602 if ((fDim < i) || (fDim < j))
606 cout << " *AliSample::Data(i,j)* Error : Dimension less than " << k << endl;
610 cout << " " << fNames[i-1] << "-" << fNames[j-1] << " correlation :";
611 cout << " Cov. = " << fCov[i-1][j-1] << " Cor. = " << fCor[i-1][j-1] << endl;
614 ///////////////////////////////////////////////////////////////////////////
615 void AliSample::SetStoreMode(Int_t mode)
617 // Set storage mode for all entered data.
619 // mode = 0 : Entered data will not be stored
620 // 1 : All data will be stored as entered
622 // By default the storage mode is set to 0 in the constructor of this class.
623 // The default at invokation of this memberfunction is mode=1.
625 // For normal statistics evaluation (e.g. mean, sigma, covariance etc...)
626 // storage of entered data is not needed. This is the default mode
627 // of operation and is the most efficient w.r.t. cpu time and memory.
628 // However, when calculation of a median, minimum or maximum is required,
629 // then the data storage mode has be activated, unless the statistics
630 // are obtained from a specified input histogram.
632 // Note : Activation of storage mode can only be performed before the
633 // first data item is entered.
637 cout << " *AliSample::SetStore* Storage mode can only be set before first data." << endl;
641 if (mode==0 || mode==1) fStore=mode;
644 ///////////////////////////////////////////////////////////////////////////
645 Int_t AliSample::GetStoreMode() const
647 // Provide the storage mode
650 ///////////////////////////////////////////////////////////////////////////
651 Float_t AliSample::GetMedian(Int_t i)
653 // Provide the median of a certain variable.
654 // For this functionality the storage mode has to be activated.
656 // Note : For large datasets it is more efficient to determine the median
657 // via the specification of a histogram.
658 // See the other GetMedian memberfunction for details.
662 cout << " *AliSample::GetMedian* Error : Dimension less than " << i << endl;
668 cout << " *AliSample::GetMedian* Error : Storage of data entries was not activated." << endl;
678 if (i==1) median=fX->At(0);
679 if (i==2) median=fY->At(0);
680 if (i==3) median=fZ->At(0);
684 // Prepare temp. array to hold the ordered values
687 fArr=new TArrayF(fN);
691 if (fArr->GetSize() < fN) fArr->Set(fN);
694 // Order the values of the specified variable
697 for (Int_t j=0; j<fN; j++)
699 if (i==1) val=fX->At(j);
700 if (i==2) val=fY->At(j);
701 if (i==3) val=fZ->At(j);
711 for (Int_t k=0; k<j; k++)
713 if (val>=fArr->At(k)) continue;
714 // Put value in between the existing ones
715 for (Int_t m=j-1; m>=k; m--)
717 fArr->AddAt(fArr->At(m),m+1);
733 if (fN%2) // Odd number of entries
735 median=fArr->At(index);
737 else // Even number of entries
739 median=(fArr->At(index-1)+fArr->At(index))/2.;
743 ///////////////////////////////////////////////////////////////////////////
744 Float_t AliSample::GetSpread(Int_t i)
746 // Provide the spread w.r.t. the median of a certain variable.
747 // The spread is defined as the average of |median-val(i)|.
748 // For this functionality the storage mode has to be activated.
750 // Note : For large datasets it is more efficient to determine the spread
751 // via the specification of a histogram.
752 // See the other GetSpread memberfunction for details.
756 cout << " *AliSample::GetSpread* Error : Dimension less than " << i << endl;
762 cout << " *AliSample::GetSpread* Error : Storage of data entries was not activated." << endl;
768 Float_t median=GetMedian(i);
771 for (Int_t j=0; j<fN; j++)
773 spread+=fabs(median-(fArr->At(j)));
776 spread=spread/float(fN);
780 ///////////////////////////////////////////////////////////////////////////
781 Float_t AliSample::GetMinimum(Int_t i) const
783 // Provide the minimum value of a certain variable.
784 // In case entries have been removed from the sample, a correct value can
785 // only be obtained if the storage mode has been activated.
789 cout << " *AliSample::GetMinimum* Error : Dimension less than " << i << endl;
793 if (!fRemove) return fMin[i-1];
797 cout << " *AliSample::GetMinimum* Error : Storage of data entries was not activated." << endl;
805 if (i==1) min=fX->At(0);
806 if (i==2) min=fY->At(0);
807 if (i==3) min=fZ->At(0);
809 for (Int_t k=1; k<fN; k++)
811 if (i==1 && fX->At(k)<min) min=fX->At(k);
812 if (i==2 && fY->At(k)<min) min=fY->At(k);
813 if (i==3 && fZ->At(k)<min) min=fZ->At(k);
818 ///////////////////////////////////////////////////////////////////////////
819 Float_t AliSample::GetMaximum(Int_t i) const
821 // Provide the maxmum value of a certain variable.
822 // In case entries have been removed from the sample, a correct value can
823 // only be obtained if the storage mode has been activated.
827 cout << " *AliSample::GetMaximum* Error : Dimension less than " << i << endl;
831 if (!fRemove) return fMax[i-1];
835 cout << " *AliSample::GetMaximum* Error : Storage of data entries was not activated." << endl;
843 if (i==1) max=fX->At(0);
844 if (i==2) max=fY->At(0);
845 if (i==3) max=fZ->At(0);
847 for (Int_t k=1; k<fN; k++)
849 if (i==1 && fX->At(k)>max) max=fX->At(k);
850 if (i==2 && fY->At(k)>max) max=fY->At(k);
851 if (i==3 && fZ->At(k)>max) max=fZ->At(k);
856 ///////////////////////////////////////////////////////////////////////////
857 Double_t AliSample::GetMedian(TH1* histo,Int_t mode) const
859 // Provide the median in X or Y from the specified 1D histogram.
860 // For this functionality it is not needed to activate the storage mode.
862 // In case of X-median, this facility uses TH1::GetQuantiles, which
863 // provides a median value which in general is different from any of the
864 // central bin X values. The user may force the returned X-median to be
865 // the corresponding central bin X value via the "mode" input argument.
867 // mode = 0 ==> The pure TH1::GetQuantiles X-median value is returned.
868 // 1 ==> The corresponding central bin X value is returned as X-median.
869 // 2 ==> The Y-median value is returned.
871 // By default mode=1 will be used, to agree with the AliSample philosophy.
873 if (!histo) return 0;
877 if (mode==2) // Median of Y values
880 temp.SetStoreMode(1);
882 for (Int_t i=1; i<=histo->GetNbinsX(); i++)
884 val=histo->GetBinContent(i);
887 median=temp.GetMedian(1);
889 else // Median of X values
893 histo->ComputeIntegral();
894 Int_t nq=histo->GetQuantiles(1,q,p);
901 Int_t mbin=histo->FindBin(q[0]);
902 median=histo->GetBinCenter(mbin);
908 ///////////////////////////////////////////////////////////////////////////
909 Double_t AliSample::GetSpread(TH1* histo,Int_t mode) const
911 // Provide the spread w.r.t. the X or Y median for the specified 1D histogram.
912 // The spread is defined as the average of |median-val|.
913 // For this functionality it is not needed to activate the storage mode.
915 // In case of X-spread, this facility uses TH1::GetQuantiles to determine
916 // the X-median, which provides a median value which in general is different
917 // from any of the central bin X values. The user may force the used X-median
918 // to be the corresponding central bin X value via the "mode" input argument.
920 // mode = 0 ==> The pure TH1::GetQuantiles X-median value is used
921 // 1 ==> The corresponding central bin X value is used as X-median
922 // 2 ==> The spread in Y-values w.r.t. the Y-median will be provided
924 // By default mode=1 will be used, to agree with the AliSample philosophy.
926 if (!histo) return 0;
930 Int_t nbins=histo->GetNbinsX();
932 if (mode==2) // Spread in Y values
935 temp.SetStoreMode(1);
937 for (Int_t i=1; i<=nbins; i++)
939 val=histo->GetBinContent(i);
942 spread=temp.GetSpread(1);
944 else // Spread in X values
946 Double_t median=GetMedian(histo,mode);
947 Double_t x=0,y=0,ysum=0;
948 for (Int_t jbin=1; jbin<=nbins; jbin++)
950 x=histo->GetBinCenter(jbin);
951 y=histo->GetBinContent(jbin);
954 spread+=fabs(x-median)*y;
958 if (ysum>0) spread=spread/ysum;
963 ///////////////////////////////////////////////////////////////////////////