Reference documentation for deal.II version 8.5.1
histogram.cc
1 // ---------------------------------------------------------------------
2 //
3 // Copyright (C) 1999 - 2015 by the deal.II authors
4 //
5 // This file is part of the deal.II library.
6 //
7 // The deal.II library is free software; you can use it, redistribute
8 // it, and/or modify it under the terms of the GNU Lesser General
9 // Public License as published by the Free Software Foundation; either
10 // version 2.1 of the License, or (at your option) any later version.
11 // The full text of the license can be found in the file LICENSE at
12 // the top level of the deal.II distribution.
13 //
14 // ---------------------------------------------------------------------
15 
16 #include <deal.II/base/memory_consumption.h>
17 #include <deal.II/lac/vector.h>
18 #include <deal.II/numerics/histogram.h>
19 #include <algorithm>
20 #include <cmath>
21 
22 DEAL_II_NAMESPACE_OPEN
23 
24 
25 template <typename number>
26 bool Histogram::logarithmic_less (const number n1,
27  const number n2)
28 {
29  return (((n1<n2) && (n1>0)) ||
30  ((n1<n2) && (n2<=0)) ||
31  ((n2<n1) && (n1>0) && (n2<=0)));
32 }
33 
34 
35 
36 Histogram::Interval::Interval (const double left_point,
37  const double right_point) :
38  left_point (left_point),
39  right_point (right_point),
40  content (0)
41 {}
42 
43 
44 
45 std::size_t
47 {
48  return sizeof(*this);
49 }
50 
51 
52 
53 template <typename number>
54 void Histogram::evaluate (const std::vector<Vector<number> > &values,
55  const std::vector<double> &y_values_,
56  const unsigned int n_intervals,
57  const IntervalSpacing interval_spacing)
58 {
59  Assert (values.size() > 0,
60  ExcMessage("Your input data needs to contain at least one input vector."));
61  Assert (n_intervals > 0,
62  ExcMessage("The number of intervals needs to be at least one."));
63  for (unsigned int i=0; i<values.size(); ++i)
64  Assert (values[i].size() > 0, ExcEmptyData());
65  Assert (values.size() == y_values_.size(),
66  ExcIncompatibleArraySize(values.size(), y_values_.size()));
67 
68  // store y_values
69  y_values = y_values_;
70 
71  // first find minimum and maximum value
72  // in the indicators
73  number min_value=0, max_value=0;
74  switch (interval_spacing)
75  {
76  case linear:
77  {
78  min_value = *std::min_element(values[0].begin(),
79  values[0].end());
80  max_value = *std::max_element(values[0].begin(),
81  values[0].end());
82 
83  for (unsigned int i=1; i<values.size(); ++i)
84  {
85  min_value = std::min (min_value,
86  *std::min_element(values[i].begin(),
87  values[i].end()));
88  max_value = std::max (max_value,
89  *std::max_element(values[i].begin(),
90  values[i].end()));
91  };
92 
93  break;
94  };
95 
96  case logarithmic:
97  {
98  typedef bool (*comparator) (const number, const number);
99  const comparator logarithmic_less_function
100  = &Histogram::template logarithmic_less<number>;
101 
102  min_value = *std::min_element(values[0].begin(),
103  values[0].end(),
104  logarithmic_less_function);
105 
106  max_value = *std::max_element(values[0].begin(),
107  values[0].end(),
108  logarithmic_less_function);
109 
110  for (unsigned int i=1; i<values.size(); ++i)
111  {
112  min_value = std::min (min_value,
113  *std::min_element(values[i].begin(),
114  values[i].end(),
115  logarithmic_less_function),
116  logarithmic_less_function);
117 
118  max_value = std::max (max_value,
119  *std::max_element(values[i].begin(),
120  values[i].end(),
121  logarithmic_less_function),
122  logarithmic_less_function);
123  }
124 
125  break;
126  }
127 
128  default:
129  Assert (false, ExcInternalError());
130  }
131 
132  // move right bound arbitrarily if
133  // necessary. sometimes in logarithmic
134  // mode, max_value may be larger than
135  // min_value, but only up to rounding
136  // precision.
137  if (max_value <= min_value)
138  max_value = min_value+1;
139 
140 
141  // now set up the intervals based on
142  // the min and max values
143  intervals.clear ();
144  // set up one list of intervals
145  // for the first data vector. we will
146  // then produce all the other lists
147  // for the other data vectors by
148  // copying
149  intervals.push_back (std::vector<Interval>());
150 
151  switch (interval_spacing)
152  {
153  case linear:
154  {
155  const float delta = (max_value-min_value)/n_intervals;
156 
157  for (unsigned int n=0; n<n_intervals; ++n)
158  intervals[0].push_back (Interval(min_value+n*delta,
159  min_value+(n+1)*delta));
160 
161  break;
162  };
163 
164  case logarithmic:
165  {
166  const float delta = (std::log(max_value)-std::log(min_value))/n_intervals;
167 
168  for (unsigned int n=0; n<n_intervals; ++n)
169  intervals[0].push_back (Interval(std::exp(std::log(min_value)+n*delta),
170  std::exp(std::log(min_value)+(n+1)*delta)));
171 
172  break;
173  };
174 
175  default:
176  Assert (false, ExcInternalError());
177  };
178 
179  // fill the other lists of intervals
180  for (unsigned int i=1; i<values.size(); ++i)
181  intervals.push_back (intervals[0]);
182 
183 
184  // finally fill the intervals
185  for (unsigned int i=0; i<values.size(); ++i)
186  for (typename Vector<number>::const_iterator p=values[i].begin();
187  p < values[i].end(); ++p)
188  {
189  // find the right place for *p in
190  // intervals[i]. use regular
191  // operator< here instead of
192  // the logarithmic one to
193  // map negative or zero value
194  // to the leftmost interval always
195  for (unsigned int n=0; n<n_intervals; ++n)
196  if (*p <= intervals[i][n].right_point)
197  {
198  ++intervals[i][n].content;
199  break;
200  };
201  };
202 }
203 
204 
205 
206 template <typename number>
208  const unsigned int n_intervals,
209  const IntervalSpacing interval_spacing)
210 {
211  std::vector<Vector<number> > values_list (1,
212  values);
213  evaluate (values_list, std::vector<double>(1,0.), n_intervals, interval_spacing);
214 }
215 
216 
217 
218 void Histogram::write_gnuplot (std::ostream &out) const
219 {
220  AssertThrow (out, ExcIO());
221  Assert (!intervals.empty(),
222  ExcMessage("There is nothing to write into the output file. "
223  "Did you forget to call the evaluate() function?"));
224 
225  // do a simple 2d plot, if only
226  // one data set is available
227  if (intervals.size()==1)
228  {
229  for (unsigned int n=0; n<intervals[0].size(); ++n)
230  out << intervals[0][n].left_point
231  << ' '
232  << intervals[0][n].content
233  << std::endl
234  << intervals[0][n].right_point
235  << ' '
236  << intervals[0][n].content
237  << std::endl;
238  }
239  else
240  // otherwise create a whole 3d plot
241  // for the data. use th patch method
242  // of gnuplot for this
243  //
244  // run this loop backwards since otherwise
245  // gnuplot thinks the upper side is the
246  // lower side and draws the diagram in
247  // strange colors
248  for (int i=intervals.size()-1; i>=0; --i)
249  {
250  for (unsigned int n=0; n<intervals[i].size(); ++n)
251  out << intervals[i][n].left_point
252  << ' '
253  << (i<static_cast<int>(intervals.size())-1 ?
254  y_values[i+1] :
255  y_values[i] + (y_values[i]-y_values[i-1]))
256  << ' '
257  << intervals[i][n].content
258  << std::endl
259  << intervals[i][n].right_point
260  << ' '
261  << (i<static_cast<int>(intervals.size())-1 ?
262  y_values[i+1] :
263  y_values[i] + (y_values[i]-y_values[i-1]))
264  << ' '
265  << intervals[i][n].content
266  << std::endl;
267 
268  out << std::endl;
269  for (unsigned int n=0; n<intervals[i].size(); ++n)
270  out << intervals[i][n].left_point
271  << ' '
272  << y_values[i]
273  << ' '
274  << intervals[i][n].content
275  << std::endl
276  << intervals[i][n].right_point
277  << ' '
278  << y_values[i]
279  << ' '
280  << intervals[i][n].content
281  << std::endl;
282 
283  out << std::endl;
284 
285  };
286 
287  AssertThrow (out, ExcIO());
288 }
289 
290 
291 
293 {
294  return "linear|logarithmic";
295 }
296 
297 
298 
300 Histogram::parse_interval_spacing (const std::string &name)
301 {
302  if (name=="linear")
303  return linear;
304  else if (name=="logarithmic")
305  return logarithmic;
306  else
307  {
308  AssertThrow (false, ExcInvalidName(name));
309 
310  return linear;
311  };
312 }
313 
314 
315 
316 std::size_t
318 {
321 }
322 
323 
324 
325 // explicit instantiations for float
326 template
327 void Histogram::evaluate<float> (const std::vector<Vector<float> > &values,
328  const std::vector<double> &y_values,
329  const unsigned int n_intervals,
330  const IntervalSpacing interval_spacing);
331 template
332 void Histogram::evaluate<float> (const Vector<float> &values,
333  const unsigned int n_intervals,
334  const IntervalSpacing interval_spacing);
335 
336 
337 // explicit instantiations for double
338 template
339 void Histogram::evaluate<double> (const std::vector<Vector<double> > &values,
340  const std::vector<double> &y_values,
341  const unsigned int n_intervals,
342  const IntervalSpacing interval_spacing);
343 template
344 void Histogram::evaluate<double> (const Vector<double> &values,
345  const unsigned int n_intervals,
346  const IntervalSpacing interval_spacing);
347 
348 DEAL_II_NAMESPACE_CLOSE
std::vector< std::vector< Interval > > intervals
Definition: histogram.h:226
static ::ExceptionBase & ExcInvalidName(std::string arg1)
static ::ExceptionBase & ExcIO()
Interval(const double left_point, const double right_point)
Definition: histogram.cc:36
static ::ExceptionBase & ExcIncompatibleArraySize(int arg1, int arg2)
#define AssertThrow(cond, exc)
Definition: exceptions.h:369
iterator end()
std::size_t memory_consumption() const
Definition: histogram.cc:317
static ::ExceptionBase & ExcMessage(std::string arg1)
void evaluate(const std::vector< Vector< number > > &values, const std::vector< double > &y_values, const unsigned int n_intervals, const IntervalSpacing interval_spacing=linear)
Definition: histogram.cc:54
void write_gnuplot(std::ostream &out) const
Definition: histogram.cc:218
#define Assert(cond, exc)
Definition: exceptions.h:313
static bool logarithmic_less(const number n1, const number n2)
Definition: histogram.cc:26
std::size_t memory_consumption() const
Definition: histogram.cc:46
std_cxx11::enable_if< std_cxx11::is_fundamental< T >::value, std::size_t >::type memory_consumption(const T &t)
std::vector< double > y_values
Definition: histogram.h:232
IntervalSpacing
Definition: histogram.h:75
static IntervalSpacing parse_interval_spacing(const std::string &name)
Definition: histogram.cc:300
static ::ExceptionBase & ExcEmptyData()
static std::string get_interval_spacing_names()
Definition: histogram.cc:292
static ::ExceptionBase & ExcInternalError()