BornAgain  1.19.0
Simulate and fit neutron and x-ray scattering at grazing incidence
ArrayUtils.h
Go to the documentation of this file.
1 // ************************************************************************************************
2 //
3 // BornAgain: simulate and fit reflection and scattering
4 //
5 //! @file Device/Data/ArrayUtils.h
6 //! @brief Defines various functions to interact from numpy on Python side
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 #ifdef SWIG
16 #error no need to expose this header to Swig
17 #endif
18 
19 #ifndef USER_API
20 #ifndef BORNAGAIN_DEVICE_DATA_ARRAYUTILS_H
21 #define BORNAGAIN_DEVICE_DATA_ARRAYUTILS_H
22 
23 #include "Device/Data/OutputData.h"
24 #include <memory>
25 #include <stdexcept>
26 #include <vector>
27 
28 //! Array utility functions getShape
29 
30 namespace ArrayUtils {
31 
32 //! Returns shape nrows, ncols of 2D array.
33 template <class T> std::pair<size_t, size_t> getShape(const T& data);
34 
36  //! Holds the dimensionality of template argument as the enum value.
37  //! Intended for vectors only.
38  template <typename T> struct nDim {
39  enum { value = 0 };
40  };
41  template <typename T, typename A> struct nDim<std::vector<T, A>> {
42  enum { value = 1 + nDim<T>::value };
43  };
44 
45  template <typename T> struct baseClass {
46  using value = T;
47  };
48  template <typename T, typename A> struct baseClass<std::vector<T, A>> {
49  using value = typename baseClass<T>::value;
50  };
51 
52  template <class T>
53  using ReturnType = std::unique_ptr<OutputData<typename CreateDataImpl::baseClass<T>::value>>;
54 
55  template <class T> friend ReturnType<T> createData(const T& vec);
56 
57  template <class T>
58  static std::unique_ptr<OutputData<T>> createDataImpl(const std::vector<T>& vec);
59 
60  template <class T>
61  static std::unique_ptr<OutputData<T>> createDataImpl(const std::vector<std::vector<T>>& vec);
62 };
63 
64 //! Creates OutputData array from input vector.
65 template <class T> CreateDataImpl::ReturnType<T> createData(const T& vec)
66 {
67  constexpr const int size = CreateDataImpl::nDim<T>::value;
68  static_assert(
69  size == 1 || size == 2,
70  "Error in ArrayUtils::createData: invalid dimensionality or type of the input argument");
71  static_assert(std::is_same<CreateDataImpl::ReturnType<T>,
72  decltype(CreateDataImpl::createDataImpl(vec))>::value,
73  "Error in ArrayUtils::createData: invalid return type.");
75 }
76 
77 //! Creates 1D vector from OutputData.
78 template <class T> decltype(auto) createVector1D(const T& data);
79 
80 //! Creates 2D vector from OutputData.
81 template <class T> decltype(auto) createVector2D(const T& data);
82 
83 } // namespace ArrayUtils
84 
85 // ************************************************************************************************
86 // implementation
87 // ************************************************************************************************
88 
89 template <class T>
90 std::unique_ptr<OutputData<T>> ArrayUtils::CreateDataImpl::createDataImpl(const std::vector<T>& vec)
91 {
92  auto result = std::make_unique<OutputData<T>>();
93  const size_t length = vec.size();
94  result->addAxis(FixedBinAxis("axis0", length, 0.0, static_cast<double>(length)));
95  result->setRawDataVector(vec);
96  return result;
97 }
98 
99 template <class T>
100 std::unique_ptr<OutputData<T>>
101 ArrayUtils::CreateDataImpl::createDataImpl(const std::vector<std::vector<T>>& vec)
102 {
103  auto result = std::make_unique<OutputData<T>>();
104 
105  auto shape = ArrayUtils::getShape(vec);
106  const size_t nrows = shape.first;
107  const size_t ncols = shape.second;
108 
109  if (nrows == 0 || ncols == 0)
110  throw std::runtime_error(
111  "Error in ArrayUtils::createDataImpl: input argument contains empty dimensions");
112 
113  result->addAxis(FixedBinAxis("axis0", ncols, 0.0, static_cast<double>(ncols)));
114  result->addAxis(FixedBinAxis("axis1", nrows, 0.0, static_cast<double>(nrows)));
115 
116  // filling the data
117  for (size_t row = 0; row < nrows; ++row) {
118  for (size_t col = 0; col < ncols; ++col) {
119  size_t globalbin = nrows - row - 1 + col * nrows;
120  (*result)[globalbin] = vec[row][col];
121  }
122  }
123 
124  return result;
125 }
126 
127 template <class T> std::pair<size_t, size_t> ArrayUtils::getShape(const T& data)
128 {
129  size_t nrows = data.size();
130  size_t ncols(0);
131  if (nrows)
132  ncols = data[0].size();
133  for (size_t row = 0; row < nrows; row++)
134  if (data[row].size() != ncols)
135  throw std::runtime_error("Util::getShape() -> Error. "
136  "Number of elements is different from row to row.");
137  return std::make_pair(nrows, ncols);
138 }
139 
140 template <class T> decltype(auto) ArrayUtils::createVector1D(const T& data)
141 {
142  if (data.rank() != 1)
143  throw std::runtime_error("ArrayUtils::createVector1D() -> Error. Not 1D data.");
144 
145  using value_type = typename T::value_type;
146  std::vector<value_type> result = data.getRawDataVector();
147  return result;
148 }
149 
150 template <class T> decltype(auto) ArrayUtils::createVector2D(const T& data)
151 {
152  using value_type = typename T::value_type;
153  std::vector<std::vector<value_type>> result;
154 
155  const size_t nrows = data.axis(1).size();
156  const size_t ncols = data.axis(0).size();
157 
158  result.resize(nrows);
159 
160  for (size_t row = 0; row < nrows; ++row) {
161  result[row].resize(ncols, 0.0);
162  for (size_t col = 0; col < ncols; ++col) {
163  size_t globalbin = nrows - row - 1 + col * nrows;
164  result[row][col] = data[globalbin];
165  }
166  }
167 
168  return result;
169 }
170 
171 #endif // BORNAGAIN_DEVICE_DATA_ARRAYUTILS_H
172 #endif // USER_API
Defines and implements templated class OutputData.
friend ReturnType< T > createData(const T &vec)
Creates OutputData array from input vector.
Definition: ArrayUtils.h:65
std::unique_ptr< OutputData< typename CreateDataImpl::baseClass< T >::value > > ReturnType
Definition: ArrayUtils.h:53
static std::unique_ptr< OutputData< T > > createDataImpl(const std::vector< T > &vec)
Definition: ArrayUtils.h:90
Axis with fixed bin size.
Definition: FixedBinAxis.h:23
Templated class to store data of type double or CumulativeValue in multi-dimensional space.
Definition: OutputData.h:32
Array utility functions getShape.
Definition: ArrayUtils.h:30
decltype(auto) createVector2D(const T &data)
Creates 2D vector from OutputData.
CreateDataImpl::ReturnType< T > createData(const T &vec)
Creates OutputData array from input vector.
Definition: ArrayUtils.h:65
decltype(auto) createVector1D(const T &data)
Creates 1D vector from OutputData.
std::pair< size_t, size_t > getShape(const T &data)
Returns shape nrows, ncols of 2D array.
Definition: ArrayUtils.h:127
Definition: filesystem.h:81
Holds the dimensionality of template argument as the enum value.
Definition: ArrayUtils.h:38