ROOT  6.06/09
Reference Guide
SparseData.cxx
Go to the documentation of this file.
1 // @(#)root/mathcore:$Id$
2 // Author: David Gonzalez Maline Wed Aug 28 15:33:03 2009
3 
4 /**********************************************************************
5  * *
6  * Copyright (c) 2006 LCG ROOT Math Team, CERN/PH-SFT *
7  * *
8  * *
9  **********************************************************************/
10 
11 // Implementation file for class BinData
12 
13 #include <iostream>
14 #include <iterator>
15 #include <algorithm>
16 
17 #include <vector>
18 #include <list>
19 
20 #include <stdexcept>
21 
22 #include <cmath>
23 #include <limits>
24 
25 // #include "TMath.h"
26 #include "Fit/SparseData.h"
27 
28 using namespace std;
29 
30 namespace ROOT {
31 
32  namespace Fit {
33 
34  //This class is a helper. It represents a bin in N
35  //dimensions. The change in the name is to avoid name collision.
36  class Box
37  {
38  public:
39  // Creates a Box with limits specified by the vectors and
40  // content=value and error=error
41  Box(const vector<double>& min, const vector<double>& max,
42  const double value = 0.0, const double error = 1.0):
43  fMin(min), fMax(max), fVal(value), fError(error)
44  { }
45 
46  // Compares to Boxes to see if they are equal in all its
47  // variables. This is to be used by the std::find algorithm
48  bool operator==(const Box& b)
49  { return (fMin == b.fMin) && (fMax == b.fMax)
50  && (fVal == b.fVal) && (fError == b.fError); }
51 
52  // Get the list of minimum coordinates
53  const vector<double>& GetMin() const { return fMin; }
54  // Get the list of maximum coordinates
55  const vector<double>& GetMax() const { return fMax; }
56  // Get the value of the Box
57  double GetVal() const { return fVal; }
58  // Get the rror of the Box
59  double GetError() const { return fError; }
60 
61  // Add an amount to the content of the Box
62  void AddVal(const double value) { fVal += value; }
63 
64  friend class BoxContainer;
65  friend ostream& operator <<(ostream& os, const Box& b);
66 
67  private:
68  vector<double> fMin;
69  vector<double> fMax;
70  double fVal;
71  double fError;
72  };
73 
74  // This class is just a helper to be used in std::for_each to
75  // simplify the code later. It's just a definition of a method
76  // that will discern whether a Box is included into another one
77  class BoxContainer
78  {
79  private:
80  const Box& fBox;
81  public:
82  //Constructs the BoxContainer object with a Box that is meant
83  //to include another one that will be provided later
84  BoxContainer(const Box& b): fBox(b) {}
85 
86  bool operator() (const Box& b1)
87  { return operator()(fBox, b1); }
88 
89  // Looks if b2 is included in b1
90  bool operator() (const Box& b1, const Box& b2)
91  {
92  bool isIn = true;
93  vector<double>::const_iterator boxit = b2.fMin.begin();
94  vector<double>::const_iterator bigit = b1.fMax.begin();
95  while ( isIn && boxit != b2.fMin.end() )
96  {
97  if ( (*boxit) >= (*bigit) ) isIn = false;
98  boxit++;
99  bigit++;
100  }
101 
102  boxit = b2.fMax.begin();
103  bigit = b1.fMin.begin();
104  while ( isIn && boxit != b2.fMax.end() )
105  {
106  if ( (*boxit) <= (*bigit) ) isIn = false;
107  boxit++;
108  bigit++;
109  }
110 
111  return isIn;
112  }
113  };
114 
115  // Another helper class to be used in std::for_each to simplify
116  // the code later. It implements the operator() to know if a
117  // specified Box is big enough to contain any 'space' inside.
118  class AreaComparer
119  {
120  public:
121  AreaComparer(vector<double>::iterator iter):
122  fThereIsArea(true),
123  fIter(iter),
124  fLimit(8 * std::numeric_limits<double>::epsilon())
125  {};
126 
127  void operator() (double value)
128  {
129  if ( fabs(value- (*fIter)) < fLimit )
130 // if ( TMath::AreEqualRel(value, (*fIter), fLimit) )
131  fThereIsArea = false;
132 
133  fIter++;
134  }
135 
136  bool IsThereArea() { return fThereIsArea; }
137 
138  private:
139  bool fThereIsArea;
140  vector<double>::iterator fIter;
141  double fLimit;
142  };
143 
144 
145  // This is the key of the SparseData structure. This method
146  // will, by recursion, divide the area passed as an argument in
147  // min and max into pieces to insert the Box defined by bmin and
148  // bmax. It will do so from the highest dimension until it gets
149  // to 1 and create the corresponding boxes to divide the
150  // original space.
151  void DivideBox( const vector<double>& min, const vector<double>& max,
152  const vector<double>& bmin, const vector<double>& bmax,
153  const unsigned int size, const unsigned int n,
154  list<Box>& l, const double val, const double error)
155  {
156  vector<double> boxmin(min);
157  vector<double> boxmax(max);
158 
159  boxmin[n] = min[n];
160  boxmax[n] = bmin[n];
161  if ( for_each(boxmin.begin(), boxmin.end(), AreaComparer(boxmax.begin())).IsThereArea() )
162  l.push_back(Box(boxmin, boxmax));
163 
164  boxmin[n] = bmin[n];
165  boxmax[n] = bmax[n];
166  if ( n == 0 )
167  {
168  if ( for_each(boxmin.begin(), boxmin.end(), AreaComparer(boxmax.begin())).IsThereArea() )
169  l.push_back(Box(boxmin, boxmax, val, error));
170  }
171  else
172  DivideBox(boxmin, boxmax, bmin, bmax, size, n-1, l, val, error);
173 
174  boxmin[n] = bmax[n];
175  boxmax[n] = max[n];
176  if ( for_each(boxmin.begin(), boxmin.end(), AreaComparer(boxmax.begin())).IsThereArea() )
177  l.push_back(Box(boxmin, boxmax));
178  }
179 
180  class ProxyListBox
181  {
182  public:
183  void PushBack(Box& box) { fProxy.push_back(box); }
184  list<Box>::iterator Begin() { return fProxy.begin(); }
185  list<Box>::iterator End() { return fProxy.end(); }
186  void Remove(list<Box>::iterator it) { fProxy.erase(it); }
187  list<Box>& GetList() { return fProxy; }
188  private:
189  list<Box> fProxy;
190  };
191 
192 
193  SparseData::SparseData(vector<double>& min, vector<double>& max)
194  {
195  // Creates a SparseData convering the range defined by min
196  // and max. For this it will create an empty Box for that
197  // range.
198  Box originalBox(min, max);
199  fList = new ProxyListBox();
200  fList->PushBack(originalBox);
201  }
202 
203  SparseData::SparseData(const unsigned int dim, double min[], double max[])
204  {
205  // Creates a SparseData convering the range defined by min
206  // and max. For this it will create an empty Box for that
207  // range.
208  vector<double> minv(min,min+dim);
209  vector<double> maxv(max,max+dim);
210  Box originalBox(minv, maxv);
211  fList = new ProxyListBox();
212  fList->PushBack(originalBox);
213  }
214 
215  SparseData::~SparseData()
216  { delete fList; }
217 
218  unsigned int SparseData::NPoints() const
219  {
220  // Returns the number of points stored, including the 0 ones.
221  return fList->GetList().size();
222  }
223 
224  unsigned int SparseData::NDim() const
225  {
226  // Returns the number of dimension of the SparseData object.
227  return fList->Begin()->GetMin().size();
228  }
229 
230  void SparseData::Add(std::vector<double>& min, std::vector<double>& max,
231  const double content, const double error)
232  {
233  // Add a box to the stored ones. For that, it will look for
234  // the box that contains the new data and either replace it
235  // or updated it.
236 
237  // Little box is the new Bin to be added
238  Box littleBox(min, max);
239  list<Box>::iterator it;
240  // So we look for the Bin already in the list that contains
241  // littleBox
242  it = std::find_if(fList->Begin(), fList->End(), BoxContainer(littleBox));
243  if ( it != fList->End() )
244 // cout << "Found: " << *it << endl;
245  ;
246  else {
247  cout << "SparseData::Add -> FAILED! box not found! " << endl;
248  cout << littleBox << endl;
249  return; // Does not add the box, as it is part of the
250  // underflow/overflow bin
251  }
252  // If it happens to have a value, then we add the value,
253  if ( it->GetVal() )
254  it->AddVal( content );
255  else
256  {
257  // otherwise, we divide the container!
258  DivideBox(it->GetMin(), it->GetMax(),
259  littleBox.GetMin(), littleBox.GetMax(),
260  it->GetMin().size(), it->GetMin().size() - 1,
261  fList->GetList(), content, error );
262  // and remove it from the list
263  fList->Remove(it);
264  }
265  }
266 
267  void SparseData::GetPoint(const unsigned int i,
268  std::vector<double>& min, std::vector<double>&max,
269  double& content, double& error)
270  {
271  // Get the point number i. This is a method to explore the
272  // data stored in the class.
273 
274  unsigned int counter = 0;
275  list<Box>::iterator it = fList->Begin();
276  while ( it != fList->End() && counter != i ) {
277  ++it;
278  ++counter;
279  }
280 
281  if ( (it == fList->End()) || (counter != i) )
282  throw std::out_of_range("SparseData::GetPoint");
283 
284  min = it->GetMin();
285  max = it->GetMax();
286  content = it->GetVal();
287  error = it->GetError();
288  }
289 
290  void SparseData::PrintList() const
291  {
292  // Debug method to print a list with all the data stored.
293  copy(fList->Begin(), fList->End(), ostream_iterator<Box>(cout, "\n------\n"));
294  }
295 
296 
297  void SparseData::GetBinData(BinData& bd) const
298  {
299  // Created the corresponding BinData
300 
301  list<Box>::iterator it = fList->Begin();
302  const unsigned int dim = it->GetMin().size();
303 
304  bd.Initialize(fList->GetList().size(), dim);
305  // Visit all the stored Boxes
306  for ( ; it != fList->End(); ++it )
307  {
308  vector<double> mid(dim);
309  // fill up the vector with the mid point of the Bin
310  for ( unsigned int i = 0; i < dim; ++i)
311  {
312  mid[i] = ((it->GetMax()[i] - it->GetMin()[i]) /2) + it->GetMin()[i];
313  }
314  // And store it into the BinData structure
315  bd.Add(&mid[0], it->GetVal(), it->GetError());
316  }
317  }
318 
319  void SparseData::GetBinDataIntegral(BinData& bd) const
320  {
321  // Created the corresponding BinData as with the Integral
322  // option.
323 
324  list<Box>::iterator it = fList->Begin();
325 
326  bd.Initialize(fList->GetList().size(), it->GetMin().size());
327  // Visit all the stored Boxes
328  for ( ; it != fList->End(); ++it )
329  {
330  //Store the minimum value
331  bd.Add(&(it->GetMin()[0]), it->GetVal(), it->GetError());
332  //and the maximum
333  bd.AddBinUpEdge(&(it->GetMax()[0]));
334  }
335  }
336 
337  void SparseData::GetBinDataNoZeros(BinData& bd) const
338  {
339  // Created the corresponding BinData, but it does not include
340  // all the data with value equal to 0.
341 
342  list<Box>::iterator it = fList->Begin();
343  const unsigned int dim = it->GetMin().size();
344 
345  bd.Initialize(fList->GetList().size(), dim);
346  // Visit all the stored Boxes
347  for ( ; it != fList->End(); ++it )
348  {
349  // if the value is zero, jump to the next
350  if ( it->GetVal() == 0 ) continue;
351  vector<double> mid(dim);
352  // fill up the vector with the mid point of the Bin
353  for ( unsigned int i = 0; i < dim; ++i)
354  {
355  mid[i] = ((it->GetMax()[i] - it->GetMin()[i]) /2) + it->GetMin()[i];
356  }
357  // And store it into the BinData structure
358  bd.Add(&mid[0], it->GetVal(), it->GetError());
359  }
360  }
361 
362  // Just for debugging pourposes
363  ostream& operator <<(ostream& os, const ROOT::Fit::Box& b)
364  {
365  os << "min: ";
366  copy(b.GetMin().begin(), b.GetMin().end(), ostream_iterator<double>(os, " "));
367  os << "max: ";
368  copy(b.GetMax().begin(), b.GetMax().end(), ostream_iterator<double>(os, " "));
369  os << "val: " << b.GetVal();
370 
371  return os;
372  }
373  } // end namespace Fit
374 
375 } // end namespace ROOT
void Begin(Int_t type)
void Initialize(unsigned int maxpoints, 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:215
static Vc_ALWAYS_INLINE int_v min(const int_v &x, const int_v &y)
Definition: vector.h:433
void Add(THist< DIMENSION, PRECISIONA > &to, THist< DIMENSION, PRECISIONB > &from)
Definition: THist.h:335
Namespace for new ROOT classes and functions.
Definition: ROOT.py:1
void DivideBox(const vector< double > &min, const vector< double > &max, const vector< double > &bmin, const vector< double > &bmax, const unsigned int size, const unsigned int n, list< Box > &l, const double val, const double error)
Definition: SparseData.cxx:151
STL namespace.
void AddBinUpEdge(const double *xup)
add the bin width data, a pointer to an array with the bin upper edge information.
Definition: BinData.cxx:451
std::map< std::string, std::string >::const_iterator iter
Definition: TAlienJob.cxx:54
const int NPoints
Definition: testNdimFit.cxx:35
VecExpr< UnaryOp< Fabs< T >, VecExpr< A, T, D >, T >, T, D > fabs(const VecExpr< A, T, D > &rhs)
TLine * l
Definition: textangle.C:4
Class describing the binned data sets : vectors of x coordinates, y values and optionally error on y ...
Definition: BinData.h:61
REAL epsilon
Definition: triangle.c:617
TRObject operator()(const T1 &t1) const
void Add(double x, double y)
add one dim data with only coordinate and values
Definition: BinData.cxx:264
TFitResultPtr Fit(FitObject *h1, TF1 *f1, Foption_t &option, const ROOT::Math::MinimizerOptions &moption, const char *goption, ROOT::Fit::DataRange &range)
Definition: HFitImpl.cxx:132
static Vc_ALWAYS_INLINE int_v max(const int_v &x, const int_v &y)
Definition: vector.h:440
Bool_t operator==(const TDatime &d1, const TDatime &d2)
Definition: TDatime.h:101
void End()
ostream & operator<<(ostream &os, const ROOT::Fit::Box &b)
Definition: SparseData.cxx:363
float value
Definition: math.cpp:443
const Int_t n
Definition: legend1.C:16