BornAgain  1.19.0
Simulate and fit neutron and x-ray scattering at grazing incidence
IHistogram.cpp
Go to the documentation of this file.
1 // ************************************************************************************************
2 //
3 // BornAgain: simulate and fit reflection and scattering
4 //
5 //! @file Device/Histo/IHistogram.cpp
6 //! @brief Implements class IntensityDataObject.
7 //!
8 //! @homepage http://www.bornagainproject.org
9 //! @license GNU General Public License v3 or higher (see COPYING)
10 //! @copyright Forschungszentrum Jülich GmbH 2018
11 //! @authors Scientific Computing Group at MLZ (see CITATION, AUTHORS)
12 //
13 // ************************************************************************************************
14 
15 #include "Base/Math/Numeric.h"
18 #include "Device/Histo/IntensityDataIOFactory.h" // TODO rm
19 #include <memory>
20 
21 IHistogram::IHistogram() = default;
22 
24 {
25  m_data.copyFrom(other.m_data);
26 }
27 
29 {
30  m_data.addAxis(axis_x);
31 }
32 
33 IHistogram::IHistogram(const IAxis& axis_x, const IAxis& axis_y)
34 {
35  m_data.addAxis(axis_x);
36  m_data.addAxis(axis_y);
37 }
38 
40 {
41  return m_data.getAllocatedSize();
42 }
43 
44 const IAxis& IHistogram::xAxis() const
45 {
46  check_x_axis();
47  return m_data.axis(0);
48 }
49 
50 const IAxis& IHistogram::yAxis() const
51 {
52  check_y_axis();
53  return m_data.axis(1);
54 }
55 
56 double IHistogram::getXmin() const
57 {
58  return xAxis().lowerBound();
59 }
60 
61 double IHistogram::getXmax() const
62 {
63  return xAxis().upperBound();
64 }
65 
66 size_t IHistogram::getNbinsX() const
67 {
68  return xAxis().size();
69 }
70 
71 double IHistogram::getYmin() const
72 {
73  return yAxis().lowerBound();
74 }
75 
76 double IHistogram::getYmax() const
77 {
78  return yAxis().upperBound();
79 }
80 
81 size_t IHistogram::getNbinsY() const
82 {
83  return yAxis().size();
84 }
85 
86 size_t IHistogram::getGlobalBin(size_t binx, size_t biny) const
87 {
88  std::vector<unsigned> axes_indices;
89  axes_indices.push_back(static_cast<unsigned>(binx));
90  if (rank() == 2)
91  axes_indices.push_back(static_cast<unsigned>(biny));
92  return m_data.toGlobalIndex(axes_indices);
93 }
94 
95 size_t IHistogram::findGlobalBin(double x, double y) const
96 {
97  std::vector<double> coordinates;
98  coordinates.push_back(x);
99  if (rank() == 2)
100  coordinates.push_back(y);
101  return m_data.findGlobalIndex(coordinates);
102 }
103 
104 size_t IHistogram::xAxisIndex(size_t i) const
105 {
106  return m_data.getAxisBinIndex(i, 0);
107 }
108 
109 size_t IHistogram::yAxisIndex(size_t i) const
110 {
111  return m_data.getAxisBinIndex(i, 1);
112 }
113 
114 double IHistogram::xAxisValue(size_t i)
115 {
116  check_x_axis();
117  return m_data.getAxisValue(i, 0);
118 }
119 
120 double IHistogram::yAxisValue(size_t i)
121 {
122  check_y_axis();
123  return m_data.getAxisValue(i, 1);
124 }
125 
127 {
128  return m_data;
129 }
130 
132 {
133  return m_data;
134 }
135 
136 double IHistogram::binContent(size_t i) const
137 {
138  return m_data[i].getContent();
139 }
140 
141 double IHistogram::binContent(size_t binx, size_t biny) const
142 {
143  return binContent(getGlobalBin(binx, biny));
144 }
145 
146 void IHistogram::setBinContent(size_t i, double value)
147 {
148  m_data[i].setContent(value);
149 }
150 
151 void IHistogram::addBinContent(size_t i, double value)
152 {
153  m_data[i].add(value);
154 }
155 
156 double IHistogram::binError(size_t i) const
157 {
158  return m_data[i].getRMS();
159 }
160 
161 double IHistogram::binError(size_t binx, size_t biny) const
162 {
163  return binError(getGlobalBin(binx, biny));
164 }
165 
166 double IHistogram::binAverage(size_t i) const
167 {
168  return m_data[i].getAverage();
169 }
170 
171 double IHistogram::binAverage(size_t binx, size_t biny) const
172 {
173  return binAverage(getGlobalBin(binx, biny));
174 }
175 
177 {
178  return m_data[i].getNumberOfEntries();
179 }
180 
181 int IHistogram::binNumberOfEntries(size_t binx, size_t biny) const
182 {
183  return binNumberOfEntries(getGlobalBin(binx, biny));
184 }
185 
187 {
189  return it->getContent();
190 }
191 
193 {
195  return std::distance(m_data.begin(), it);
196 }
197 
199 {
201  return it->getContent();
202 }
203 
205 {
206  return std::distance(m_data.begin(), std::min_element(m_data.begin(), m_data.end()));
207 }
208 
209 void IHistogram::scale(double value)
210 {
211  for (size_t index = 0; index < getTotalNumberOfBins(); ++index) {
212  m_data[index].setContent(value * m_data[index].getContent());
213  }
214 }
215 
216 double IHistogram::integral() const
217 {
218  double result(0.0);
219  for (size_t index = 0; index < getTotalNumberOfBins(); ++index) {
220  result += m_data[index].getContent();
221  }
222  return result;
223 }
224 
225 #ifdef BORNAGAIN_PYTHON
227 {
228  const std::unique_ptr<OutputData<double>> data(createOutputData(dataType));
229  return data->getArray();
230 }
231 
233 {
234  return array(dataType);
235 }
236 #endif // BORNAGAIN_PYTHON
237 
239 {
241 }
242 
244 {
245  if (source.rank() == 1) {
246  return new Histogram1D(source);
247  } else if (source.rank() == 2) {
248  return new Histogram2D(source);
249  } else {
250  std::ostringstream message;
251  message << "IHistogram::createHistogram(const OutputData<double>& source) -> Error. ";
252  message << "The rank of source " << source.rank() << " ";
253  message << "is not suitable for creation neither 1-dim nor 2-dim histograms.";
254  throw std::runtime_error(message.str());
255  }
256 }
257 
259 {
261 }
262 
263 IHistogram* IHistogram::createFrom(const std::vector<std::vector<double>>& data)
264 {
265  return new Histogram2D(data);
266 }
267 
269 {
270  if (rank() < 1) {
271  std::ostringstream message;
272  message << "IHistogram::check_x_axis() -> Error. X-xis does not exist. ";
273  message << "Rank of histogram " << rank() << "." << std::endl;
274  throw std::runtime_error(message.str());
275  }
276 }
277 
279 {
280  if (rank() < 2) {
281  std::ostringstream message;
282  message << "IHistogram::check_y_axis() -> Error. Y-axis does not exist. ";
283  message << "Rank of histogram " << rank() << "." << std::endl;
284  throw std::runtime_error(message.str());
285  }
286 }
287 
289 {
290  if (rank() != source.rank()) {
291  std::ostringstream message;
292  message << "IHistogram::IHistogram(const OutputData<double>& data) -> Error. ";
293  message << "The dimension of this histogram " << rank() << " ";
294  message << "is differ from the dimension of source " << m_data.rank() << std::endl;
295  throw std::runtime_error(message.str());
296  }
297 
298  m_data.copyShapeFrom(source);
299  for (size_t i = 0; i < source.getAllocatedSize(); ++i) {
300  m_data[i].add(source[i]);
301  }
302 }
303 
304 //! returns data of requested type for globalbin number
305 double IHistogram::binData(size_t i, IHistogram::DataType dataType) const
306 {
307  if (dataType == DataType::INTEGRAL) {
308  return binContent(i);
309  } else if (dataType == DataType::AVERAGE) {
310  return binAverage(i);
311  } else if (dataType == DataType::STANDARD_ERROR) {
312  return binError(i);
313  } else if (dataType == DataType::NENTRIES) {
314  return binNumberOfEntries(i);
315  } else
316  throw std::runtime_error("IHistogram::binData() -> Error. Unknown data type.");
317 }
318 
319 //! returns vector of values of requested DataType
320 std::vector<double> IHistogram::getDataVector(IHistogram::DataType dataType) const
321 {
322  std::vector<double> result;
323  result.resize(getTotalNumberOfBins(), 0.0);
324  for (size_t index = 0; index < getTotalNumberOfBins(); ++index) {
325  result[index] = binData(index, dataType);
326  }
327  return result;
328 }
329 
330 //! Copy content (but not the axes) from other histogram. Dimensions should be the same.
332 {
333  if (!hasSameDimensions(other))
334  throw std::runtime_error(
335  "IHistogram::copyContentFrom() -> Error. Can't copy the data of different shape.");
336  reset();
337  for (size_t i = 0; i < getTotalNumberOfBins(); ++i) {
338  m_data[i] = other.m_data[i];
339  }
340 }
341 
342 //! creates new OutputData with histogram's shape and put there values corresponding to DataType
344 {
346  result->copyShapeFrom(m_data);
347  for (size_t i = 0; i < getTotalNumberOfBins(); ++i) {
348  (*result)[i] = binData(i, dataType);
349  }
350  return result;
351 }
352 
353 bool IHistogram::hasSameShape(const IHistogram& other) const
354 {
355  return m_data.hasSameShape(other.m_data);
356 }
357 
359 {
360  return m_data.hasSameDimensions(other.m_data);
361 }
362 
364 {
365  if (!hasSameDimensions(right))
366  throw std::runtime_error(
367  "IHistogram::operator+=() -> Error. Histograms have different dimension");
368  for (size_t i = 0; i < getTotalNumberOfBins(); ++i)
369  addBinContent(i, right.binContent(i));
370  return *this;
371 }
372 
374 {
375  if (!hasSameDimensions(rhs))
376  throw std::runtime_error("IHistogram::relativeDifferenceHistogram() -> Error. "
377  "Histograms have different dimensions");
378 
379  IHistogram* result = this->clone();
380  result->reset();
381 
382  for (size_t i = 0; i < getTotalNumberOfBins(); ++i) {
383  double diff = Numeric::GetRelativeDifference(binContent(i), rhs.binContent(i));
384  result->setBinContent(i, diff);
385  }
386  return result;
387 }
388 
389 void IHistogram::save(const std::string& filename)
390 {
392 }
393 
394 void IHistogram::load(const std::string& filename)
395 {
396  const std::unique_ptr<IHistogram> hist(IntensityDataIOFactory::readIntensityData(filename));
397  copyContentFrom(*hist);
398 }
Defines class Histogram1D.
Defines class Histogram2D.
Defines class IntensityDataIOFactory.
Defines constants and "almost equal" in namespace Numeric.
_object PyObject
Definition: PyObject.h:25
The cumulative value with average and rms on-the-flight calculations.
One dimensional histogram.
Definition: Histogram1D.h:23
Two dimensional histogram.
Definition: Histogram2D.h:24
Interface for one-dimensional axes.
Definition: IAxis.h:25
virtual double upperBound() const =0
Returns value of last point of axis.
virtual size_t size() const =0
retrieve the number of bins
virtual double lowerBound() const =0
Returns value of first point of axis.
Base class for 1D and 2D histograms holding values of double type.
Definition: IHistogram.h:27
double getYmin() const
Returns y-axis min (lower edge of first bin) for 2D histograms.
Definition: IHistogram.cpp:71
void addBinContent(size_t i, double value)
Add the value to the bin.
Definition: IHistogram.cpp:151
double getYmax() const
Returns y-axis max (upper edge of last bin) for 2D histograms.
Definition: IHistogram.cpp:76
void scale(double value)
Multiply this histogram (every bin content value) by a constant.
Definition: IHistogram.cpp:209
size_t findGlobalBin(double x, double y) const
Returns closest global bin index for given axes coordinates.
Definition: IHistogram.cpp:95
size_t getNbinsY() const
Returns number of bins on y-axis.
Definition: IHistogram.cpp:81
size_t getNbinsX() const
Returns number of bins on x-axis.
Definition: IHistogram.cpp:66
double binError(size_t i) const
Returns error of the bin with given index.
Definition: IHistogram.cpp:156
const IAxis & yAxis() const
returns y-axis for 2D histograms
Definition: IHistogram.cpp:50
double yAxisValue(size_t i)
Returns the center of bin i of the y axis.
Definition: IHistogram.cpp:120
PyObject * getArray(DataType dataType=DataType::INTEGRAL) const
Definition: IHistogram.cpp:232
PyObject * array(DataType dataType=DataType::INTEGRAL) const
Returns numpy array with bin content (accumulated values).
Definition: IHistogram.cpp:226
size_t getGlobalBin(size_t binx, size_t biny=0) const
Returns global bin index for given axes indices. For 1D, just returns binx.
Definition: IHistogram.cpp:86
const IAxis & xAxis() const
returns x-axis
Definition: IHistogram.cpp:44
double binData(size_t i, DataType dataType) const
returns data of requested type for globalbin number
Definition: IHistogram.cpp:305
double getMinimum() const
Returns histogram minimum value (minimum of binContent() over all bins)
Definition: IHistogram.cpp:198
virtual size_t rank() const =0
Returns number of histogram dimensions.
const OutputData< CumulativeValue > & getData() const
Definition: IHistogram.cpp:126
size_t getMinimumBinIndex() const
Returns globalbin index with minimum content.
Definition: IHistogram.cpp:204
void load(const std::string &filename)
Loads histogram from file, the shape of array in file should match Following formats are available: *...
Definition: IHistogram.cpp:394
void check_x_axis() const
Definition: IHistogram.cpp:268
double getXmin() const
Returns x-axis min (lower edge of first bin).
Definition: IHistogram.cpp:56
OutputData< double > * createOutputData(DataType dataType=DataType::INTEGRAL) const
creates new OutputData with histogram's shape and values corresponding to DataType
Definition: IHistogram.cpp:343
std::vector< double > getDataVector(DataType dataType) const
returns vector of values of requested DataType
Definition: IHistogram.cpp:320
OutputData< CumulativeValue > m_data
Definition: IHistogram.h:193
static IHistogram * createFrom(const std::string &filename)
create new histogram from file content
Definition: IHistogram.cpp:258
void setBinContent(size_t i, double value)
Sets content of the bin corresponding to the globalbin number.
Definition: IHistogram.cpp:146
double integral() const
Returns integral of bins content (computed as a sum of all bin content).
Definition: IHistogram.cpp:216
size_t yAxisIndex(size_t i) const
Returns y-axis index for global bin index i.
Definition: IHistogram.cpp:109
IHistogram * relativeDifferenceHistogram(const IHistogram &rhs)
returns histogram representing relative difference of two histograms.
Definition: IHistogram.cpp:373
double xAxisValue(size_t i)
Returns the center of bin i of the x axis.
Definition: IHistogram.cpp:114
void check_y_axis() const
Definition: IHistogram.cpp:278
double binContent(size_t i) const
Returns content (accumulated value) of bin i.
Definition: IHistogram.cpp:136
size_t getTotalNumberOfBins() const
Returns total number of histogram bins.
Definition: IHistogram.cpp:39
size_t getMaximumBinIndex() const
Returns globalbin index with maximum content.
Definition: IHistogram.cpp:192
void copyContentFrom(const IHistogram &other)
Copy content (but not the axes) from other histogram. Dimensions should be the same.
Definition: IHistogram.cpp:331
double getMaximum() const
Returns histogram maximum value (maximum of binContent() over all bins)
Definition: IHistogram.cpp:186
void save(const std::string &filename)
Saves histogram in file Following formats are available: *.txt, *.tif, *.int (*.txt....
Definition: IHistogram.cpp:389
double binAverage(size_t i) const
Returns average value in the bin with given index.
Definition: IHistogram.cpp:166
int binNumberOfEntries(size_t i) const
Returns number of entries in the bin with given index.
Definition: IHistogram.cpp:176
virtual IHistogram * clone() const =0
void reset()
Reset histogram content (axes remains)
Definition: IHistogram.cpp:238
static IHistogram * createHistogram(const OutputData< double > &source)
Definition: IHistogram.cpp:243
double getXmax() const
Returns x-axis max (upper edge of last bin).
Definition: IHistogram.cpp:61
bool hasSameDimensions(const IHistogram &other) const
Returns true if object have same rank and number of axes bins.
Definition: IHistogram.cpp:358
bool hasSameShape(const IHistogram &other) const
Returns true if objects a) have same dimensions b) bin boundaries of axes coincide.
Definition: IHistogram.cpp:353
const IHistogram & operator+=(const IHistogram &right)
addition-assignment operator for two histograms
Definition: IHistogram.cpp:363
void init_from_data(const OutputData< double > &source)
Definition: IHistogram.cpp:288
size_t xAxisIndex(size_t i) const
Returns x-axis index for global bin index i.
Definition: IHistogram.cpp:104
static IHistogram * readIntensityData(const std::string &file_name)
Reads file and returns newly created Histogram object.
static void writeIntensityData(const IHistogram &histogram, const std::string &file_name)
Writes histogram in file.
void copyFrom(const OutputData< T > &x)
Definition: OutputData.h:267
size_t getAxisBinIndex(size_t global_index, size_t i_selected_axis) const
Returns axis bin index for given global index.
Definition: OutputData.h:370
iterator end()
Returns read/write iterator that points to the one past last element.
Definition: OutputData.h:93
size_t toGlobalIndex(const std::vector< unsigned > &axes_indices) const
Returns global index for specified indices of axes.
Definition: OutputData.h:392
bool hasSameShape(const OutputData< U > &right) const
Returns true if objects a) have same dimensions b) bin boundaries of axes coincide.
Definition: OutputData.h:592
size_t rank() const
Returns number of dimensions.
Definition: OutputData.h:56
void setAllTo(const T &value)
Sets content of output data to specific value.
Definition: OutputData.h:476
size_t findGlobalIndex(const std::vector< double > &coordinates) const
Returns global index for specified axes values.
Definition: OutputData.h:416
const IAxis & axis(size_t serial_number) const
returns axis with given serial number
Definition: OutputData.h:318
void copyShapeFrom(const OutputData< U > &other)
Definition: OutputData.h:277
void addAxis(const IAxis &new_axis)
Definition: OutputData.h:295
bool hasSameDimensions(const OutputData< U > &right) const
Returns true if object have same dimensions and number of axes bins.
Definition: OutputData.h:575
iterator begin()
Returns read/write iterator that points to the first element.
Definition: OutputData.h:343
size_t getAllocatedSize() const
Returns total size of data buffer (product of bin number in every dimension).
Definition: OutputData.h:59
double getAxisValue(size_t global_index, size_t i_selected_axis) const
Returns the value of selected axis for given global_index.
Definition: OutputData.h:430
std::string filename(const std::string &path)
Returns path without directory part ("Foo/Bar/Doz.int.gz" -> "Doz.int.gz")
double GetRelativeDifference(double a, double b)
Returns the safe relative difference, which is 2(|a-b|)/(|a|+|b|) except in special cases.
Definition: Numeric.cpp:29