]> git.uio.no Git - u/mrichter/AliRoot.git/blob - RALICE/AliSample.cxx
Example macro for merging sets of alignment objects
[u/mrichter/AliRoot.git] / RALICE / AliSample.cxx
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 // $Id$
17
18 ///////////////////////////////////////////////////////////////////////////
19 // Class AliSample
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
30 //
31 // Example :
32 // ---------
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
35 // via s.GetMean(2).
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().
40 //
41 //--- Author: Nick van Eijndhoven 30-mar-1996 CERN Geneva
42 //- Modified: NvE $Date$ UU-SAP Utrecht
43 ///////////////////////////////////////////////////////////////////////////
44
45 #include "AliSample.h"
46 #include "Riostream.h"
47  
48 ClassImp(AliSample) // Class implementation to enable ROOT I/O
49  
50 AliSample::AliSample()
51 {
52 // Creation of an Aliample object and resetting the statistics values
53 // The dimension is initialised to maximum
54  fDim=fMaxdim;
55  fNames[0]='X';
56  fNames[1]='Y';
57  fNames[2]='Z';
58  fN=0;
59  fRemove=0;
60  fStore=0;
61  fX=0;
62  fY=0;
63  fZ=0;
64  fArr=0;
65  Reset();
66 }
67 ///////////////////////////////////////////////////////////////////////////
68 AliSample::~AliSample()
69 {
70 // Default destructor
71  if (fX)
72  {
73   delete fX;
74   fX=0;
75  }
76  if (fY)
77  {
78   delete fY;
79   fY=0;
80  }
81  if (fZ)
82  {
83   delete fZ;
84   fZ=0;
85  }
86  if (fArr)
87  {
88   delete fArr;
89   fArr=0;
90  }
91 }
92 ///////////////////////////////////////////////////////////////////////////
93 void AliSample::Reset()
94 {
95 // Resetting the statistics values for a certain Sample object
96 // Dimension and storage flag are NOT changed
97  fN=0;
98  fRemove=0;
99  for (Int_t i=0; i<fDim; i++)
100  {
101   fSum[i]=0.;
102   fMean[i]=0.;
103   fVar[i]=0.;
104   fSigma[i]=0.;
105   fMin[i]=0;
106   fMax[i]=0;
107   for (Int_t j=0; j<fDim; j++)
108   {
109    fSum2[i][j]=0.;
110    fCov[i][j]=0.;
111    fCor[i][j]=0.;
112   }
113  }
114
115  // Set storage arrays to initial size
116  if (fX) fX->Set(10);
117  if (fY) fY->Set(10);
118  if (fZ) fZ->Set(10);
119 }
120 ///////////////////////////////////////////////////////////////////////////
121 void AliSample::Enter(Float_t x)
122 {
123 // Entering a value into a 1-dim. sample
124 // In case of first entry the dimension is set to 1
125  if (fN == 0)
126  {
127   fDim=1;
128   fNames[0]='X';
129   fNames[1]='-';
130   fNames[2]='-';
131  }
132  if (fDim != 1)
133  {
134   cout << " *AliSample::enter* Error : Not a 1-dim sample." << endl;
135  }
136  else
137  {
138   fN+=1;
139   fSum[0]+=x;
140   fSum2[0][0]+=x*x;
141
142   if (fN==1)
143   {
144    fMin[0]=x;
145    fMax[0]=x;
146   }
147   else
148   {
149    if (x<fMin[0]) fMin[0]=x;
150    if (x>fMax[0]) fMax[0]=x;
151   }
152
153   // Store all entered data when storage mode has been selected 
154   if (fStore)
155   {
156    if (!fX) fX=new TArrayF(10);
157    if (fX->GetSize() < fN) fX->Set(fN+10);
158    fX->AddAt(x,fN-1);
159   }
160
161   // Compute the various statistics
162   Compute();
163  }
164 }
165 ///////////////////////////////////////////////////////////////////////////
166 void AliSample::Remove(Float_t x)
167 {
168 // Removing a value from a 1-dim. sample
169
170  if (!fN) return;
171
172  if (fDim != 1)
173  {
174   cout << " *AliSample::remove* Error : Not a 1-dim sample." << endl;
175  }
176  else
177  {
178   fRemove=1;
179   fN-=1;
180   fSum[0]-=x;
181   fSum2[0][0]-=x*x;
182
183   // Remove data entry from the storage
184   if (fStore && fX)
185   {
186    Float_t val=0;
187    for (Int_t i=0; i<=fN; i++)
188    {
189     val=fX->At(i);
190     if (fabs(x-val)>1.e-10) continue;
191
192     for (Int_t j=i+1; j<=fN; j++)
193     {
194      val=fX->At(j);
195      fX->AddAt(val,j-1);
196     }
197    }
198   }
199
200   // Compute the various statistics
201   Compute();
202  }
203 }
204 ///////////////////////////////////////////////////////////////////////////
205 void AliSample::Enter(Float_t x,Float_t y)
206 {
207 // Entering a pair (x,y) into a 2-dim. sample
208 // In case of first entry the dimension is set to 2
209  if (fN == 0)
210  {
211   fDim=2;
212   fNames[0]='X';
213   fNames[1]='Y';
214   fNames[2]='-';
215  }
216  if (fDim != 2)
217  {
218   cout << " *AliSample::enter* Error : Not a 2-dim sample." << endl;
219  }
220  else
221  {
222   fN+=1;
223   fSum[0]+=x;
224   fSum[1]+=y;
225   fSum2[0][0]+=x*x;
226   fSum2[0][1]+=x*y;
227   fSum2[1][0]+=y*x;
228   fSum2[1][1]+=y*y;
229
230   if (fN==1)
231   {
232    fMin[0]=x;
233    fMax[0]=x;
234    fMin[1]=y;
235    fMax[1]=y;
236   }
237   else
238   {
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;
243   }
244
245   // Store all entered data when storage mode has been selected 
246   if (fStore)
247   {
248    if (!fX) fX=new TArrayF(10);
249    if (fX->GetSize() < fN) fX->Set(fN+10);
250    fX->AddAt(x,fN-1);
251    if (!fY) fY=new TArrayF(10);
252    if (fY->GetSize() < fN) fY->Set(fN+10);
253    fY->AddAt(y,fN-1);
254   }
255
256   // Compute the various statistics
257   Compute();
258  }
259 }
260 ///////////////////////////////////////////////////////////////////////////
261 void AliSample::Remove(Float_t x,Float_t y)
262 {
263 // Removing a pair (x,y) from a 2-dim. sample
264
265  if (!fN) return;
266
267  if (fDim != 2)
268  {
269   cout << " *AliSample::remove* Error : Not a 2-dim sample." << endl;
270  }
271  else
272  {
273   fRemove=1;
274   fN-=1;
275   fSum[0]-=x;
276   fSum[1]-=y;
277   fSum2[0][0]-=x*x;
278   fSum2[0][1]-=x*y;
279   fSum2[1][0]-=y*x;
280   fSum2[1][1]-=y*y;
281
282   // Remove data entry from the storage
283   if (fStore && fX && fY)
284   {
285    Float_t val=0;
286    for (Int_t i=0; i<=fN; i++)
287    {
288     val=fX->At(i);
289     if (fabs(x-val)>1.e-10) continue;
290     val=fY->At(i);
291     if (fabs(y-val)>1.e-10) continue;
292
293     for (Int_t j=i+1; j<=fN; j++)
294     {
295      val=fX->At(j);
296      fX->AddAt(val,j-1);
297      val=fY->At(j);
298      fY->AddAt(val,j-1);
299     }
300    }
301   }
302
303   // Compute the various statistics
304   Compute();
305  }
306 }
307 ///////////////////////////////////////////////////////////////////////////
308 void AliSample::Enter(Float_t x,Float_t y,Float_t z)
309 {
310 // Entering a set (x,y,z) into a 3-dim. sample
311 // In case of first entry the dimension is set to 3
312  if (fN == 0)
313  {
314   fDim=3;
315   fNames[0]='X';
316   fNames[1]='Y';
317   fNames[2]='Z';
318  }
319  if (fDim != 3)
320  {
321   cout << " *AliSample::enter* Error : Not a 3-dim sample." << endl;
322  }
323  else
324  {
325   fN+=1;
326   fSum[0]+=x;
327   fSum[1]+=y;
328   fSum[2]+=z;
329   fSum2[0][0]+=x*x;
330   fSum2[0][1]+=x*y;
331   fSum2[0][2]+=x*z;
332   fSum2[1][0]+=y*x;
333   fSum2[1][1]+=y*y;
334   fSum2[1][2]+=y*z;
335   fSum2[2][0]+=z*x;
336   fSum2[2][1]+=z*y;
337   fSum2[2][2]+=z*z;
338
339   if (fN==1)
340   {
341    fMin[0]=x;
342    fMax[0]=x;
343    fMin[1]=y;
344    fMax[1]=y;
345    fMin[2]=z;
346    fMax[2]=z;
347   }
348   else
349   {
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;
356   }
357
358   // Store all entered data when storage mode has been selected 
359   if (fStore)
360   {
361    if (!fX) fX=new TArrayF(10);
362    if (fX->GetSize() < fN) fX->Set(fN+10);
363    fX->AddAt(x,fN-1);
364    if (!fY) fY=new TArrayF(10);
365    if (fY->GetSize() < fN) fY->Set(fN+10);
366    fY->AddAt(y,fN-1);
367    if (!fZ) fZ=new TArrayF(10);
368    if (fZ->GetSize() < fN) fZ->Set(fN+10);
369    fZ->AddAt(z,fN-1);
370   }
371
372   // Compute the various statistics
373   Compute();
374  }
375 }
376 ///////////////////////////////////////////////////////////////////////////
377 void AliSample::Remove(Float_t x,Float_t y,Float_t z)
378 {
379 // Removing a set (x,y,z) from a 3-dim. sample
380
381  if (!fN) return;
382
383  if (fDim != 3)
384  {
385   cout << " *AliSample::remove* Error : Not a 3-dim sample." << endl;
386  }
387  else
388  {
389   fRemove=1;
390   fN-=1;
391   fSum[0]-=x;
392   fSum[1]-=y;
393   fSum[2]-=z;
394   fSum2[0][0]-=x*x;
395   fSum2[0][1]-=x*y;
396   fSum2[0][2]-=x*z;
397   fSum2[1][0]-=y*x;
398   fSum2[1][1]-=y*y;
399   fSum2[1][2]-=y*z;
400   fSum2[2][0]-=z*x;
401   fSum2[2][1]-=z*y;
402   fSum2[2][2]-=z*z;
403
404   // Remove data entry from the storage
405   if (fStore && fX && fY && fZ)
406   {
407    Float_t val=0;
408    for (Int_t i=0; i<=fN; i++)
409    {
410     val=fX->At(i);
411     if (fabs(x-val)>1.e-10) continue;
412     val=fY->At(i);
413     if (fabs(y-val)>1.e-10) continue;
414     val=fZ->At(i);
415     if (fabs(z-val)>1.e-10) continue;
416
417     for (Int_t j=i+1; j<=fN; j++)
418     {
419      val=fX->At(j);
420      fX->AddAt(val,j-1);
421      val=fY->At(j);
422      fY->AddAt(val,j-1);
423      val=fZ->At(j);
424      fZ->AddAt(val,j-1);
425     }
426    }
427   }
428
429   // Compute the various statistics
430   Compute();
431  }
432 }
433 ///////////////////////////////////////////////////////////////////////////
434 void AliSample::Compute()
435 {
436 // Computation of the various statistical values
437 // after each entering or removing action on a certain sample
438  Float_t rn=fN;
439  for (Int_t k=0; k<fDim; k++)
440  {
441   fMean[k]=fSum[k]/rn;
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]);
445  }
446  for (Int_t i=0; i<fDim; i++)
447  {
448   for (Int_t j=0; j<fDim; j++)
449   {
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;
453   }
454  }
455 }
456 ///////////////////////////////////////////////////////////////////////////
457 Int_t AliSample::GetDimension() const
458 {
459 // Provide the dimension of a certain sample
460  return fDim;
461 }
462 ///////////////////////////////////////////////////////////////////////////
463 Int_t AliSample::GetN() const
464 {
465 // Provide the number of entries of a certain sample
466  return fN;
467 }
468 ///////////////////////////////////////////////////////////////////////////
469 Float_t AliSample::GetSum(Int_t i) const
470 {
471 // Provide the sum of a certain variable
472  if (fDim < i)
473  {
474   cout << " *AliSample::sum* Error : Dimension less than " << i << endl;
475   return 0.;
476  }
477  else
478  {
479  return fSum[i-1];
480  }
481 }
482 ///////////////////////////////////////////////////////////////////////////
483 Float_t AliSample::GetMean(Int_t i) const
484 {
485 // Provide the mean of a certain variable
486  if (fDim < i)
487  {
488   cout << " *AliSample::mean* Error : Dimension less than " << i << endl;
489   return 0.;
490  }
491  else
492  {
493  return fMean[i-1];
494  }
495 }
496 ///////////////////////////////////////////////////////////////////////////
497 Float_t AliSample::GetVar(Int_t i) const
498 {
499 // Provide the variance of a certain variable
500  if (fDim < i)
501  {
502   cout << " *AliSample::var* Error : Dimension less than " << i << endl;
503   return 0.;
504  }
505  else
506  {
507  return fVar[i-1];
508  }
509 }
510 ///////////////////////////////////////////////////////////////////////////
511 Float_t AliSample::GetSigma(Int_t i) const
512 {
513 // Provide the standard deviation of a certain variable
514  if (fDim < i)
515  {
516   cout << " *AliSample::sigma* Error : Dimension less than " << i << endl;
517   return 0.;
518  }
519  else
520  {
521  return fSigma[i-1];
522  }
523 }
524 ///////////////////////////////////////////////////////////////////////////
525 Float_t AliSample::GetCov(Int_t i,Int_t j) const
526 {
527 // Provide the covariance between variables i and j
528  if ((fDim < i) || (fDim < j))
529  {
530   Int_t k=i;
531   if (j > i) k=j;
532   cout << " *AliSample::cov* Error : Dimension less than " << k << endl;
533   return 0.;
534  }
535  else
536  {
537  return fCov[i-1][j-1];
538  }
539 }
540 ///////////////////////////////////////////////////////////////////////////
541 Float_t AliSample::GetCor(Int_t i,Int_t j) const
542 {
543 // Provide the correlation between variables i and j
544  if ((fDim < i) || (fDim < j))
545  {
546   Int_t k=i;
547   if (j > i) k=j;
548   cout << " *AliSample::cor* Error : Dimension less than " << k << endl;
549   return 0.;
550  }
551  else
552  {
553  return fCor[i-1][j-1];
554  }
555 }
556 ///////////////////////////////////////////////////////////////////////////
557 void AliSample::Data()
558 {
559 // Printing of statistics of all variables
560  for (Int_t i=0; i<fDim; i++)
561  {
562  cout << " " << fNames[i] << " : N = " << fN;
563  cout << " Sum = " << fSum[i] << " Mean = " << fMean[i];
564  cout << " Var = " << fVar[i] << " Sigma = " << fSigma[i];
565  if (fStore)
566  {
567   cout << endl;
568   cout << "     Minimum = " << GetMinimum(i+1);
569   cout << " Maximum = " << GetMaximum(i+1);
570   cout << " Median = " << GetMedian(i+1);
571  }
572  cout << endl;
573  }
574 }
575 ///////////////////////////////////////////////////////////////////////////
576 void AliSample::Data(Int_t i)
577 {
578 // Printing of statistics of ith variable
579  if (fDim < i)
580  {
581   cout << " *AliSample::Data(i)* Error : Dimension less than " << i << endl;
582  }
583  else
584  {
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];
588   if (fStore)
589   {
590    cout << endl;
591    cout << "     Minimum = " << GetMinimum(i);
592    cout << " Maximum = " << GetMaximum(i);
593    cout << " Median = " << GetMedian(i);
594   }
595   cout << endl;
596  }
597 }
598 ///////////////////////////////////////////////////////////////////////////
599 void AliSample::Data(Int_t i,Int_t j) const
600 {
601 // Printing of covariance and correlation between variables i and j
602  if ((fDim < i) || (fDim < j))
603  {
604   Int_t k=i;
605   if (j > i) k=j;
606   cout << " *AliSample::Data(i,j)* Error : Dimension less than " << k << endl;
607  }
608  else
609  {
610   cout << " " << fNames[i-1] << "-" << fNames[j-1] << " correlation :";
611   cout << " Cov. = " << fCov[i-1][j-1] << " Cor. = " << fCor[i-1][j-1] << endl;
612  }
613 }
614 ///////////////////////////////////////////////////////////////////////////
615 void AliSample::SetStoreMode(Int_t mode)
616 {
617 // Set storage mode for all entered data.
618 //
619 // mode = 0 : Entered data will not be stored
620 //        1 : All data will be stored as entered
621 //
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.
624 //
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.
631 //
632 // Note : Activation of storage mode can only be performed before the
633 //        first data item is entered. 
634
635  if (fN)
636  {
637   cout << " *AliSample::SetStore* Storage mode can only be set before first data." << endl;
638  }
639  else
640  {
641   if (mode==0 || mode==1) fStore=mode;
642  }
643 }
644 ///////////////////////////////////////////////////////////////////////////
645 Int_t AliSample::GetStoreMode() const
646 {
647 // Provide the storage mode
648  return fStore;
649 }
650 ///////////////////////////////////////////////////////////////////////////
651 Float_t AliSample::GetMedian(Int_t i)
652 {
653 // Provide the median of a certain variable.
654 // For this functionality the storage mode has to be activated.
655 //
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.
659
660  if (fDim < i)
661  {
662   cout << " *AliSample::GetMedian* Error : Dimension less than " << i << endl;
663   return 0;
664  }
665
666  if (!fStore)
667  {
668   cout << " *AliSample::GetMedian* Error : Storage of data entries was not activated." << endl;
669   return 0;
670  }
671
672  if (fN<=0) return 0;
673
674  Float_t median=0;
675
676  if (fN==1)
677  {
678   if (i==1) median=fX->At(0);
679   if (i==2) median=fY->At(0);
680   if (i==3) median=fZ->At(0);
681   return median;
682  }
683
684  // Prepare temp. array to hold the ordered values
685  if (!fArr)
686  {
687   fArr=new TArrayF(fN);
688  }
689  else
690  {
691   if (fArr->GetSize() < fN) fArr->Set(fN);
692  }
693
694  // Order the values of the specified variable
695  Float_t val=0;
696  Int_t iadd=0;
697  for (Int_t j=0; j<fN; j++)
698  {
699   if (i==1) val=fX->At(j);
700   if (i==2) val=fY->At(j);
701   if (i==3) val=fZ->At(j);
702
703   iadd=0;
704   if (j==0)
705   {
706    fArr->AddAt(val,j);
707    iadd=1;
708   }
709   else
710   {
711    for (Int_t k=0; k<j; k++)
712    {
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--)
716     {
717      fArr->AddAt(fArr->At(m),m+1);
718     }
719     fArr->AddAt(val,k);
720     iadd=1;
721     break;
722    }
723
724    if (!iadd)
725    {
726     fArr->AddAt(val,j);
727    }
728   }
729  }
730
731  median=0;
732  Int_t index=fN/2;
733  if (fN%2) // Odd number of entries
734  {
735   median=fArr->At(index);
736  }
737  else // Even number of entries
738  {
739   median=(fArr->At(index-1)+fArr->At(index))/2.;
740  }
741  return median;
742 }
743 ///////////////////////////////////////////////////////////////////////////
744 Float_t AliSample::GetSpread(Int_t i)
745 {
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.
749 //
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.
753
754  if (fDim < i)
755  {
756   cout << " *AliSample::GetSpread* Error : Dimension less than " << i << endl;
757   return 0;
758  }
759
760  if (!fStore)
761  {
762   cout << " *AliSample::GetSpread* Error : Storage of data entries was not activated." << endl;
763   return 0;
764  }
765
766  if (fN<=1) return 0;
767
768  Float_t median=GetMedian(i);
769
770  Float_t spread=0;
771  for (Int_t j=0; j<fN; j++)
772  {
773   spread+=fabs(median-(fArr->At(j)));
774  }
775
776  spread=spread/float(fN);
777
778  return spread;
779 }
780 ///////////////////////////////////////////////////////////////////////////
781 Float_t AliSample::GetMinimum(Int_t i) const
782 {
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.
786
787  if (fDim < i)
788  {
789   cout << " *AliSample::GetMinimum* Error : Dimension less than " << i << endl;
790   return 0;
791  }
792
793  if (!fRemove) return fMin[i-1];
794
795  if (!fStore)
796  {
797   cout << " *AliSample::GetMinimum* Error : Storage of data entries was not activated." << endl;
798   return 0;
799  }
800
801  if (fN<=0) return 0;
802
803  Float_t min=0;
804
805  if (i==1) min=fX->At(0);
806  if (i==2) min=fY->At(0);
807  if (i==3) min=fZ->At(0);
808
809  for (Int_t k=1; k<fN; k++)
810  {
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);
814  }
815
816  return min;
817 }
818 ///////////////////////////////////////////////////////////////////////////
819 Float_t AliSample::GetMaximum(Int_t i) const
820 {
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.
824
825  if (fDim < i)
826  {
827   cout << " *AliSample::GetMaximum* Error : Dimension less than " << i << endl;
828   return 0;
829  }
830
831  if (!fRemove) return fMax[i-1];
832
833  if (!fStore)
834  {
835   cout << " *AliSample::GetMaximum* Error : Storage of data entries was not activated." << endl;
836   return 0;
837  }
838
839  if (fN<=0) return 0;
840
841  Float_t max=0;
842
843  if (i==1) max=fX->At(0);
844  if (i==2) max=fY->At(0);
845  if (i==3) max=fZ->At(0);
846
847  for (Int_t k=1; k<fN; k++)
848  {
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);
852  }
853
854  return max;
855 }
856 ///////////////////////////////////////////////////////////////////////////
857 Double_t AliSample::GetMedian(TH1* histo,Int_t mode) const
858 {
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.
861 //
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.
866 //
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.
870 //
871 // By default mode=1 will be used, to agree with the AliSample philosophy.
872
873  if (!histo) return 0;
874
875  Double_t median=0;
876
877  if (mode==2) // Median of Y values
878  {
879   AliSample temp;
880   temp.SetStoreMode(1);
881   Float_t val=0;
882   for (Int_t i=1; i<=histo->GetNbinsX(); i++)
883   {
884    val=histo->GetBinContent(i);
885    temp.Enter(val);
886   }
887   median=temp.GetMedian(1);
888  }
889  else // Median of X values
890  {
891   Double_t q[1];
892   Double_t p[1]={0.5};
893   histo->ComputeIntegral();
894   Int_t nq=histo->GetQuantiles(1,q,p);
895
896   if (!nq) return 0;
897
898   median=q[0];
899   if (mode==1)
900   {
901    Int_t mbin=histo->FindBin(q[0]);
902    median=histo->GetBinCenter(mbin);
903   }
904  }
905
906  return median;
907 }
908 ///////////////////////////////////////////////////////////////////////////
909 Double_t AliSample::GetSpread(TH1* histo,Int_t mode) const
910 {
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.
914 //
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.
919 //
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
923 //
924 // By default mode=1 will be used, to agree with the AliSample philosophy.
925
926  if (!histo) return 0;
927
928  Double_t spread=0;
929
930  Int_t nbins=histo->GetNbinsX();
931
932  if (mode==2) // Spread in Y values
933  {
934   AliSample temp;
935   temp.SetStoreMode(1);
936   Float_t val=0;
937   for (Int_t i=1; i<=nbins; i++)
938   {
939    val=histo->GetBinContent(i);
940    temp.Enter(val);
941   }
942   spread=temp.GetSpread(1);
943  }
944  else // Spread in X values
945  {
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++)
949   {
950    x=histo->GetBinCenter(jbin);
951    y=histo->GetBinContent(jbin);
952    if (y>0)
953    {
954     spread+=fabs(x-median)*y;
955     ysum+=y;
956    }
957   }
958   if (ysum>0) spread=spread/ysum;
959  }
960
961  return spread;
962 }
963 ///////////////////////////////////////////////////////////////////////////