Logo ROOT   6.10/09
Reference Guide
BinData.h
Go to the documentation of this file.
1 // @(#)root/mathcore:$Id$
2 // Author: L. Moneta Wed Aug 30 11:15:23 2006
3 
4 /**********************************************************************
5  * *
6  * Copyright (c) 2006 LCG ROOT Math Team, CERN/PH-SFT *
7  * *
8  * *
9  **********************************************************************/
10 
11 // Header file for class BinData
12 
13 #ifndef ROOT_Fit_BinData
14 #define ROOT_Fit_BinData
15 
16 #include "Fit/FitData.h"
17 #include "Math/Error.h"
18 #include <cmath>
19 
20 
21 
22 namespace ROOT {
23 
24  namespace Fit {
25 
26 
27 
28 //___________________________________________________________________________________
29 /**
30  Class describing the binned data sets :
31  vectors of x coordinates, y values and optionally error on y values and error on coordinates
32  The dimension of the coordinate is free
33  There are 4 different options:
34  - only coordinates and values (for binned likelihood fits) : kNoError
35  - coordinate, values and error on values (for normal least square fits) : kValueError
36  - coordinate, values, error on values and coordinates (for effective least square fits) : kCoordError
37  - corrdinate, values, error on coordinates and asymmettric error on valyes : kAsymError
38 
39  In addition there is the option to construct Bindata copying the data in (using the DataVector class)
40  or using pointer to external data (DataWrapper) class.
41  In general is found to be more efficient to copy the data.
42  In case of really large data sets for limiting memory consumption then the other option can be used
43  Specialized constructor exists for data up to 3 dimensions.
44 
45  When the data are copying in the number of points can be set later (or re-set) using Initialize and
46  the data are inserted one by one using the Add method.
47  It is mandatory to set the size before using the Add method.
48 
49  @ingroup FitData
50 */
51 
52 
53 class BinData : public FitData {
54 
55 public :
56 
58 
59  /**
60  constructor from dimension of point and max number of points (to pre-allocate vector)
61  Give a zero value and then use Initialize later one if the size is not known
62  */
63 
64  explicit BinData(unsigned int maxpoints = 0, unsigned int dim = 1,
65  ErrorType err = kValueError);
66 
67 
68  /**
69  constructor from option and default range
70  */
71  explicit BinData (const DataOptions & opt, unsigned int maxpoints = 0,
72  unsigned int dim = 1, ErrorType err = kValueError);
73 
74  /**
75  constructor from options and range
76  efault is 1D and value errors
77  */
78  BinData (const DataOptions & opt, const DataRange & range,
79  unsigned int maxpoints = 0, unsigned int dim = 1, ErrorType err = kValueError );
80 
81  /** constructurs using external data */
82 
83  /**
84  constructor from external data for 1D with errors on coordinate and value
85  */
86  BinData(unsigned int n, const double * dataX, const double * val,
87  const double * ex , const double * eval );
88 
89  /**
90  constructor from external data for 2D with errors on coordinate and value
91  */
92  BinData(unsigned int n, const double * dataX, const double * dataY,
93  const double * val, const double * ex , const double * ey,
94  const double * eval );
95 
96  /**
97  constructor from external data for 3D with errors on coordinate and value
98  */
99  BinData(unsigned int n, const double * dataX, const double * dataY,
100  const double * dataZ, const double * val, const double * ex ,
101  const double * ey , const double * ez , const double * eval );
102 
103  /**
104  destructor
105  */
106  virtual ~BinData();
107 
108  /**
109  copy constructors
110  */
111  BinData(const BinData & rhs);
112 
113  BinData & operator= ( const BinData & rhs );
114 
115 
116  /**
117  preallocate a data set with given size , dimension and error type (to get the full point size)
118  If the data set already exists and it is having the compatible point size space for the new points
119  is created in the data sets, while if not compatible the old data are erased and new space of
120  new size is allocated.
121  (i.e if exists initialize is equivalent to a resize( NPoints() + maxpoints)
122  */
123 
124  void Append( unsigned int newPoints, unsigned int dim = 1, ErrorType err = kValueError );
125 
126  void Initialize( unsigned int newPoints, unsigned int dim = 1, ErrorType err = kValueError );
127 
128  /**
129  flag to control if data provides error on the coordinates
130  */
131  bool HaveCoordErrors() const {
132  assert ( fErrorType == kNoError ||
133  fErrorType == kValueError ||
134  fErrorType == kCoordError ||
135  fErrorType == kAsymError );
136 
137  return fErrorType == kCoordError;
138  }
139 
140  /**
141  flag to control if data provides asymmetric errors on the value
142  */
143  bool HaveAsymErrors() const {
144  assert ( fErrorType == kNoError ||
145  fErrorType == kValueError ||
146  fErrorType == kCoordError ||
147  fErrorType == kAsymError );
148 
149  return fErrorType == kAsymError;
150  }
151 
152 
153  /**
154  apply a Log transformation of the data values
155  can be used for example when fitting an exponential or gaussian
156  Transform the data in place need to copy if want to preserve original data
157  The data sets must not contain negative values. IN case it does,
158  an empty data set is returned
159  */
160  BinData & LogTransform();
161 
162 
163  /**
164  add one dim data with only coordinate and values
165  */
166  void Add( double x, double y );
167 
168  /**
169  add one dim data with no error in the coordinate (x)
170  in this case store the inverse of the error in the value (y)
171  */
172  void Add( double x, double y, double ey );
173 
174  /**
175  add one dim data with error in the coordinate (x)
176  in this case store the value (y) error and not the inverse
177  */
178  void Add( double x, double y, double ex, double ey );
179 
180  /**
181  add one dim data with error in the coordinate (x) and asymmetric errors in the value (y)
182  in this case store the y errors and not the inverse
183  */
184  void Add( double x, double y, double ex, double eyl, double eyh );
185 
186  /**
187  add multi-dim coordinate data with only value
188  */
189  void Add( const double* x, double val );
190 
191  /**
192  add multi-dim coordinate data with only error in value
193  */
194  void Add( const double* x, double val, double eval );
195 
196  /**
197  add multi-dim coordinate data with both error in coordinates and value
198  */
199  void Add( const double* x, double val, const double* ex, double eval );
200 
201  /**
202  add multi-dim coordinate data with both error in coordinates and value
203  */
204  void Add( const double* x, double val, const double* ex, double elval, double ehval );
205 
206  /**
207  add the bin width data, a pointer to an array with the bin upper edge information.
208  This is needed when fitting with integral options
209  The information is added for the previously inserted point.
210  BinData::Add must be called before
211  */
212  void AddBinUpEdge( const double* xup );
213 
214  /**
215  return the value for the given fit point
216  */
217  double Value( unsigned int ipoint ) const
218  {
219  assert( ipoint < fMaxPoints );
220  assert( fDataPtr );
221  assert( fData.empty() || &fData.front() == fDataPtr );
222 
223  return fDataPtr[ipoint];
224  }
225 
226  /**
227  return error on the value for the given fit point
228  Safe (but slower) method returning correctly the error on the value
229  in case of asymm errors return the average 0.5(eu + el)
230  */
231  double Error( unsigned int ipoint ) const
232  {
233  assert( ipoint < fMaxPoints );
234  assert( kValueError == fErrorType || kCoordError == fErrorType ||
235  kAsymError == fErrorType || kNoError == fErrorType );
236 
237  if ( fErrorType == kNoError )
238  {
240  assert( fDataError.empty() && fDataErrorHigh.empty() && fDataErrorLow.empty() );
241  return 1.0;
242  }
243 
244  if ( fErrorType == kValueError ) // need to invert (inverror is stored)
245  {
247  assert( fDataErrorHigh.empty() && fDataErrorLow.empty() );
248  assert( fDataError.empty() || &fDataError.front() == fDataErrorPtr );
249 
250  double eval = fDataErrorPtr[ ipoint ];
251 
252  if (fWrapped)
253  return eval;
254  else
255  return (eval != 0.0) ? 1.0/eval : 0.0;
256  }
257 
258  if ( fErrorType == kAsymError )
259  { // return 1/2(el + eh)
261  assert( fDataError.empty() );
262  assert( fDataErrorHigh.empty() || &fDataErrorHigh.front() == fDataErrorHighPtr );
263  assert( fDataErrorLow.empty() || &fDataErrorLow.front() == fDataErrorLowPtr );
264  assert( fDataErrorLow.empty() == fDataErrorHigh.empty() );
265 
266  double eh = fDataErrorHighPtr[ ipoint ];
267  double el = fDataErrorLowPtr[ ipoint ];
268 
269  return (el+eh) / 2.0;
270  }
271 
272  assert( fErrorType == kCoordError );
273  return fDataErrorPtr[ ipoint ];
274  }
275 
276  void GetAsymError( unsigned int ipoint, double& lowError, double& highError ) const
277  {
278  assert( fErrorType == kAsymError );
280  assert( fDataError.empty() );
281  assert( fDataErrorHigh.empty() || &fDataErrorHigh.front() == fDataErrorHighPtr );
282  assert( fDataErrorLow.empty() || &fDataErrorLow.front() == fDataErrorLowPtr );
283  assert( fDataErrorLow.empty() == fDataErrorHigh.empty() );
284 
285  lowError = fDataErrorLowPtr[ ipoint ];
286  highError = fDataErrorHighPtr[ ipoint ];
287  }
288 
289  /**
290  Return the inverse of error on the value for the given fit point
291  useful when error in the coordinates are not stored and then this is used directly this as the weight in
292  the least square function
293  */
294  double InvError( unsigned int ipoint ) const
295  {
296  assert( ipoint < fMaxPoints );
297  assert( kValueError == fErrorType || kCoordError == fErrorType ||
298  kAsymError == fErrorType || kNoError == fErrorType );
299 
300  if ( fErrorType == kNoError )
301  {
303  assert( fDataError.empty() && fDataErrorHigh.empty() && fDataErrorLow.empty() );
304  return 1.0;
305  }
306 
307  if ( fErrorType == kValueError ) // need to invert (inverror is stored)
308  {
310  assert( fDataErrorHigh.empty() && fDataErrorLow.empty() );
311  assert( fDataError.empty() || &fDataError.front() == fDataErrorPtr );
312 
313  double eval = fDataErrorPtr[ ipoint ];
314 
315  if (fWrapped)
316  return 1.0 / eval;
317  else
318  return (eval != 0.0) ? eval : 0.0;
319  }
320 
321  if ( fErrorType == kAsymError )
322  { // return 1/2(el + eh)
324  assert( fDataError.empty() );
325  assert( fDataErrorHigh.empty() || &fDataErrorHigh.front() == fDataErrorHighPtr );
326  assert( fDataErrorLow.empty() || &fDataErrorLow.front() == fDataErrorLowPtr );
327  assert( fDataErrorLow.empty() == fDataErrorHigh.empty() );
328 
329  double eh = fDataErrorHighPtr[ ipoint ];
330  double el = fDataErrorLowPtr[ ipoint ];
331 
332  return 2.0 / (el+eh);
333  }
334 
335  assert( fErrorType == kCoordError );
336  return 1.0 / fDataErrorPtr[ ipoint ];
337  }
338 
339 
340  /**
341  retrieve at the same time a pointer to the coordinate data and the fit value
342  More efficient than calling Coords(i) and Value(i)
343  */
344  // not threadsafe, to be replaced with never constructs!
345  // for example: just return std::array or std::vector, there's
346  // is going to be only minor overhead in c++11.
347  const double * GetPoint( unsigned int ipoint, double & value ) const
348  {
349  assert( ipoint < fMaxPoints );
350  value = Value( ipoint );
351 
352  return Coords( ipoint );
353  }
354 
355  /**
356  returns a single coordinate error component of a point.
357  This function is threadsafe in contrast to Coords(...)
358  and can easily get vectorized by the compiler in loops
359  running over the ipoint-index.
360  */
361  double GetCoordErrorComponent( unsigned int ipoint, unsigned int icoord ) const
362  {
363  assert( ipoint < fMaxPoints );
364  assert( icoord < fDim );
365  assert( fCoordErrorsPtr.size() == fDim );
366  assert( fCoordErrorsPtr[icoord] );
367  assert( fCoordErrors.empty() || &fCoordErrors[icoord].front() == fCoordErrorsPtr[icoord] );
368 
369  return fCoordErrorsPtr[icoord][ipoint];
370  }
371 
372  /**
373  Return a pointer to the errors in the coordinates for the given fit point
374  */
375  // not threadsafe, to be replaced with never constructs!
376  // for example: just return std::array or std::vector, there's
377  // is going to be only minor overhead in c++11.
378  const double* CoordErrors( unsigned int ipoint ) const
379  {
380  assert( ipoint < fMaxPoints );
381  assert( fpTmpCoordErrorVector );
382  assert( fErrorType == kCoordError || fErrorType == kAsymError );
383 
384  for ( unsigned int i=0; i < fDim; i++ )
385  {
386  assert( fCoordErrorsPtr[i] );
387  assert( fCoordErrors.empty() || &fCoordErrors[i].front() == fCoordErrorsPtr[i] );
388 
389  fpTmpCoordErrorVector[i] = fCoordErrorsPtr[i][ipoint];
390  }
391 
392  return fpTmpCoordErrorVector;
393  }
394 
395 
396  /**
397  retrieve in a single call a pointer to the coordinate data, value and inverse error for
398  the given fit point.
399  To be used only when type is kValueError or kNoError. In the last case the value 1 is returned
400  for the error.
401  */
402  // not threadsafe, to be replaced with never constructs!
403  // for example: just return std::array or std::vector, there's
404  // is going to be only minor overhead in c++11.
405  const double* GetPoint( unsigned int ipoint, double & value, double & invError ) const
406  {
407  assert( ipoint < fMaxPoints );
408  assert( fErrorType == kNoError || fErrorType == kValueError );
409 
410  double e = Error( ipoint );
411 
412  if (fWrapped)
413  invError = e;
414  else
415  invError = ( e != 0.0 ) ? 1.0/e : 1.0;
416 
417  return GetPoint( ipoint, value );
418  }
419 
420  /**
421  Retrieve the errors on the point (coordinate and value) for the given fit point
422  It must be called only when the coordinate errors are stored otherwise it will produce an
423  assert.
424  */
425  // not threadsafe, to be replaced with never constructs!
426  // for example: just return std::array or std::vector, there's
427  // is going to be only minor overhead in c++11.
428  const double* GetPointError(unsigned int ipoint, double & errvalue) const
429  {
430  assert( ipoint < fMaxPoints );
431  assert( fErrorType == kCoordError || fErrorType == kAsymError );
432 
433  errvalue = Error( ipoint );
434  return CoordErrors( ipoint );
435  }
436 
437  /**
438  Get errors on the point (coordinate errors and asymmetric value errors) for the
439  given fit point.
440  It must be called only when the coordinate errors and asymmetric errors are stored
441  otherwise it will produce an assert.
442  */
443  // not threadsafe, to be replaced with never constructs!
444  // for example: just return std::array or std::vector, there's
445  // is going to be only minor overhead in c++11.
446  const double* GetPointError(unsigned int ipoint, double & errlow, double & errhigh) const
447  {
448  assert( ipoint < fMaxPoints );
449  assert( fErrorType == kAsymError );
451  assert( fDataError.empty() );
452  assert( fDataErrorHigh.empty() || &fDataErrorHigh.front() == fDataErrorHighPtr );
453  assert( fDataErrorLow.empty() || &fDataErrorLow.front() == fDataErrorLowPtr );
454  assert( fDataErrorLow.empty() == fDataErrorHigh.empty() );
455 
456  errhigh = fDataErrorHighPtr[ ipoint ];
457  errlow = fDataErrorLowPtr[ ipoint ];
458 
459  return CoordErrors( ipoint );
460  }
461 
462  /**
463  returns a single coordinate error component of a point.
464  This function is threadsafe in contrast to Coords(...)
465  and can easily get vectorized by the compiler in loops
466  running over the ipoint-index.
467  */
468  double GetBinUpEdgeComponent( unsigned int ipoint, unsigned int icoord ) const
469  {
470  assert( icoord < fDim );
471  assert( !fBinEdge.empty() );
472  assert( ipoint < fBinEdge.front().size() );
473 
474  return fBinEdge[icoord][ipoint];
475  }
476 
477  /**
478  return an array containing the upper edge of the bin for coordinate i
479  In case of empty bin they could be merged in a single larger bin
480  Return a NULL pointer if the bin width is not stored
481  */
482  // not threadsafe, to be replaced with never constructs!
483  // for example: just return std::array or std::vector, there's
484  // is going to be only minor overhead in c++11.
485  const double* BinUpEdge( unsigned int ipoint ) const
486  {
487  if ( fBinEdge.empty() || ipoint > fBinEdge.front().size() )
488  return 0;
489 
490  assert( fpTmpBinEdgeVector );
491  assert( !fBinEdge.empty() );
492  assert( ipoint < fMaxPoints );
493 
494  for ( unsigned int i=0; i < fDim; i++ )
495  {
496  fpTmpBinEdgeVector[i] = fBinEdge[i][ ipoint ];
497  }
498 
499  return fpTmpBinEdgeVector;
500  }
501 
502  /**
503  query if the data store the bin edges instead of the center
504  */
505  bool HasBinEdges() const {
506  return fBinEdge.size() == fDim && fBinEdge[0].size() > 0;
507  }
508 
509  /**
510  retrieve the reference volume used to normalize the data when the option bin volume is set
511  */
512  double RefVolume() const { return fRefVolume; }
513 
514  /**
515  set the reference volume used to normalize the data when the option bin volume is set
516  */
517  void SetRefVolume(double value) { fRefVolume = value; }
518 
519  /**
520  retrieve the errortype
521  */
523  {
524  return fErrorType;
525  }
526 
527 protected:
528  void InitDataVector ();
529 
530  void InitializeErrors();
531 
532  void InitBinEdge();
533 
534  void UnWrap( );
535 
536 private:
537 
539  double fRefVolume; // reference bin volume - used to normalize the bins in case of variable bins data
540 
541  /**
542  * Stores the data values the same way as the coordinates.
543  *
544  */
545  std::vector< double > fData;
546  const double* fDataPtr;
547 
548  std::vector< std::vector< double > > fCoordErrors;
549  std::vector< const double* > fCoordErrorsPtr;
550  // This vector contains the coordinate errors
551  // in the same way as fCoords.
552 
553  std::vector< double > fDataError;
554  std::vector< double > fDataErrorHigh;
555  std::vector< double > fDataErrorLow;
556  const double* fDataErrorPtr;
557  const double* fDataErrorHighPtr;
558  const double* fDataErrorLowPtr;
559  // This vector contains the data error.
560  // Either only fDataError or fDataErrorHigh and fDataErrorLow are used.
561 
562  double* fpTmpCoordErrorVector; // not threadsafe stuff!
563 
564  std::vector< std::vector< double > > fBinEdge;
565  // vector containing the bin upper edge (coordinate will contain low edge)
566 
567  double* fpTmpBinEdgeVector; // not threadsafe stuff!
568 };
569 
570 
571  } // end namespace Fit
572 
573 } // end namespace ROOT
574 
575 
576 
577 #endif /* ROOT_Fit_BinData */
void GetAsymError(unsigned int ipoint, double &lowError, double &highError) const
Definition: BinData.h:276
bool HaveAsymErrors() const
flag to control if data provides asymmetric errors on the value
Definition: BinData.h:143
bool HasBinEdges() const
query if the data store the bin edges instead of the center
Definition: BinData.h:505
Namespace for new ROOT classes and functions.
Definition: StringConv.hxx:21
double * fpTmpBinEdgeVector
Definition: BinData.h:567
ErrorType GetErrorType() const
retrieve the errortype
Definition: BinData.h:522
Base class for all the fit data types: Stores the coordinates and the DataOptions.
Definition: FitData.h:65
void InitDataVector()
Definition: BinData.cxx:628
const double * fDataPtr
Definition: BinData.h:546
const double * CoordErrors(unsigned int ipoint) const
Return a pointer to the errors in the coordinates for the given fit point.
Definition: BinData.h:378
const double * fDataErrorPtr
Definition: BinData.h:556
void AddBinUpEdge(const double *xup)
add the bin width data, a pointer to an array with the bin upper edge information.
Definition: BinData.cxx:596
std::vector< const double *> fCoordErrorsPtr
Definition: BinData.h:549
const double * Coords(unsigned int ipoint) const
return a pointer to the coordinates data for the given fit point
Definition: FitData.h:245
double * fpTmpCoordErrorVector
Definition: BinData.h:562
ErrorType fErrorType
Definition: BinData.h:538
const double * GetPoint(unsigned int ipoint, double &value) const
retrieve at the same time a pointer to the coordinate data and the fit value More efficient than call...
Definition: BinData.h:347
std::vector< double > fData
Stores the data values the same way as the coordinates.
Definition: BinData.h:545
std::vector< std::vector< double > > fBinEdge
Definition: BinData.h:564
Double_t x[n]
Definition: legend1.C:17
double RefVolume() const
retrieve the reference volume used to normalize the data when the option bin volume is set ...
Definition: BinData.h:512
void Initialize(unsigned int newPoints, unsigned int dim=1, ErrorType err=kValueError)
Definition: BinData.cxx:345
double Error(unsigned int ipoint) const
return error on the value for the given fit point Safe (but slower) method returning correctly the er...
Definition: BinData.h:231
const double * GetPoint(unsigned int ipoint, double &value, double &invError) const
retrieve in a single call a pointer to the coordinate data, value and inverse error for the given fit...
Definition: BinData.h:405
DataOptions : simple structure holding the options on how the data are filled.
Definition: DataOptions.h:28
void InitializeErrors()
Definition: BinData.cxx:634
double GetCoordErrorComponent(unsigned int ipoint, unsigned int icoord) const
returns a single coordinate error component of a point.
Definition: BinData.h:361
const double * BinUpEdge(unsigned int ipoint) const
return an array containing the upper edge of the bin for coordinate i In case of empty bin they could...
Definition: BinData.h:485
double fRefVolume
Definition: BinData.h:539
std::vector< double > fDataError
Definition: BinData.h:553
std::vector< double > fDataErrorHigh
Definition: BinData.h:554
virtual ~BinData()
destructor
Definition: BinData.cxx:186
Class describing the binned data sets : vectors of x coordinates, y values and optionally error on y ...
Definition: BinData.h:53
void SetRefVolume(double value)
set the reference volume used to normalize the data when the option bin volume is set ...
Definition: BinData.h:517
double GetBinUpEdgeComponent(unsigned int ipoint, unsigned int icoord) const
returns a single coordinate error component of a point.
Definition: BinData.h:468
bool HaveCoordErrors() const
flag to control if data provides error on the coordinates
Definition: BinData.h:131
BinData(unsigned int maxpoints=0, unsigned int dim=1, ErrorType err=kValueError)
constructor from dimension of point and max number of points (to pre-allocate vector) Give a zero val...
Definition: BinData.cxx:26
class describing the range in the coordinates it supports multiple range in a coordinate.
Definition: DataRange.h:34
const double * fDataErrorLowPtr
Definition: BinData.h:558
void Add(double x, double y)
add one dim data with only coordinate and values
Definition: BinData.cxx:418
TFitResultPtr Fit(FitObject *h1, TF1 *f1, Foption_t &option, const ROOT::Math::MinimizerOptions &moption, const char *goption, ROOT::Fit::DataRange &range)
Definition: HFitImpl.cxx:134
std::vector< double > fDataErrorLow
Definition: BinData.h:555
std::vector< std::vector< double > > fCoordErrors
Definition: BinData.h:548
Double_t y[n]
Definition: legend1.C:17
Double_t ey[n]
Definition: legend1.C:17
you should not use this method at all Int_t Int_t Double_t Double_t Double_t e
Definition: TRolke.cxx:630
BinData & operator=(const BinData &rhs)
Definition: BinData.cxx:225
BinData & LogTransform()
apply a Log transformation of the data values can be used for example when fitting an exponential or ...
Definition: BinData.cxx:359
double Value(unsigned int ipoint) const
return the value for the given fit point
Definition: BinData.h:217
void Append(unsigned int newPoints, unsigned int dim=1, ErrorType err=kValueError)
preallocate a data set with given size , dimension and error type (to get the full point size) If the...
Definition: BinData.cxx:324
unsigned int fDim
Definition: FitData.h:372
unsigned int fMaxPoints
Definition: FitData.h:370
const double * GetPointError(unsigned int ipoint, double &errvalue) const
Retrieve the errors on the point (coordinate and value) for the given fit point It must be called onl...
Definition: BinData.h:428
const double * fDataErrorHighPtr
Definition: BinData.h:557
double InvError(unsigned int ipoint) const
Return the inverse of error on the value for the given fit point useful when error in the coordinates...
Definition: BinData.h:294
const double * GetPointError(unsigned int ipoint, double &errlow, double &errhigh) const
Get errors on the point (coordinate errors and asymmetric value errors) for the given fit point...
Definition: BinData.h:446
Double_t ex[n]
Definition: legend1.C:17
const Int_t n
Definition: legend1.C:16