Mantid
Loading...
Searching...
No Matches
NDArrayToVector.cpp
Go to the documentation of this file.
1// Mantid Repository : https://github.com/mantidproject/mantid
2//
3// Copyright © 2018 ISIS Rutherford Appleton Laboratory UKRI,
4// NScD Oak Ridge National Laboratory, European Spallation Source,
5// Institut Laue - Langevin & CSNS, Institute of High Energy Physics, CAS
6// SPDX - License - Identifier: GPL - 3.0 +
7//-----------------------------------------------------------------------------
8// Includes
9//-----------------------------------------------------------------------------
13#include "MantidPythonInterface/core/DllConfig.h"
14
15#include <boost/python/extract.hpp>
16#include <boost/python/stl_iterator.hpp>
17#include <boost/python/str.hpp>
18
19#define PY_ARRAY_UNIQUE_SYMBOL CORE_ARRAY_API
20#define NO_IMPORT_ARRAY
21#include <numpy/arrayobject.h>
22
23using boost::python::extract;
24using boost::python::handle;
25using boost::python::object;
26using boost::python::str;
27
29namespace Converters {
30
33#define DECLARE_EXTERN(HeldType) \
34 extern template int NDArrayTypeIndex<HeldType>::typenum; \
35 extern template char NDArrayTypeIndex<HeldType>::typecode;
36
40DECLARE_EXTERN(long long)
41DECLARE_EXTERN(unsigned int)
42DECLARE_EXTERN(unsigned long)
43DECLARE_EXTERN(unsigned long long)
44DECLARE_EXTERN(double)
45DECLARE_EXTERN(float)
46
47} // namespace Converters
48
49namespace {
50
51//-------------------------------------------------------------------------
52// Template helpers
53//-------------------------------------------------------------------------
60template <typename DestElementType> struct CopyToImpl {
62 PyArrayObject *arr) {
63 // Use the iterator API to iterate through the array
64 // and assign each value to the corresponding vector
65 object iter(handle<>(Converters::Impl::func_PyArray_IterNew(arr)));
66 do {
67 void *data = PyArray_ITER_DATA(iter.ptr());
68 *first++ = *static_cast<DestElementType *>(data);
69 PyArray_ITER_NEXT(iter.ptr());
70 } while (PyArray_ITER_NOTDONE(iter.ptr()));
71 }
72};
73
78template <> struct CopyToImpl<std::string> {
79 void operator()(typename std::vector<std::string>::iterator first, PyArrayObject *arr) {
80 object flattened(handle<>(PyArray_Ravel(arr, NPY_CORDER)));
81 const Py_ssize_t nelements = PyArray_Size(flattened.ptr());
82 for (Py_ssize_t i = 0; i < nelements; ++i) {
83 *first++ = extract<std::string>(str(flattened[i]))();
84 }
85 }
86};
87
93template <typename DestElementType> struct CoerceType {
94 NDArray operator()(const NDArray &x) {
96 }
97};
98
103template <> struct CoerceType<std::string> {
104 object operator()(const NDArray &x) { return x; }
105};
106} // namespace
107
108namespace Converters {
109//-------------------------------------------------------------------------
110// NDArrayToVector definitions
111//-------------------------------------------------------------------------
112
117template <typename DestElementType>
118NDArrayToVector<DestElementType>::NDArrayToVector(const NDArray &value) : m_arr(CoerceType<DestElementType>()(value)) {}
119
125template <typename DestElementType>
127 std::vector<DestElementType> cvector(PyArray_SIZE(reinterpret_cast<PyArrayObject *>(m_arr.ptr())));
128 copyTo(cvector);
129 return cvector;
130}
131
137template <typename DestElementType> void NDArrayToVector<DestElementType>::copyTo(TypedVector &dest) const {
138 if (PyArray_SIZE(reinterpret_cast<PyArrayObject *>(m_arr.ptr())) > 0) {
139 throwIfSizeMismatched(dest);
140 CopyToImpl<DestElementType>()(std::begin(dest), reinterpret_cast<PyArrayObject *>(m_arr.ptr()));
141 }
142}
143
150template <typename DestElementType>
152 if (PyArray_SIZE(reinterpret_cast<PyArrayObject *>(m_arr.ptr())) ==
153 static_cast<boost::python::ssize_t>(dest.size())) {
154 return;
155 } else {
156 throw std::invalid_argument("Invalid number of elements while copying from ndarray. "
157 "ndarray=" +
158 std::to_string(PyArray_SIZE(reinterpret_cast<PyArrayObject *>(m_arr.ptr()))) +
159 " destination=(" + std::to_string(dest.size()) + ",)");
160 }
161}
162
163//------------------------------------------------------------------------
164// Explicit instantiations
165//------------------------------------------------------------------------
166#define INSTANTIATE_TOVECTOR(ElementType) template struct MANTID_PYTHONINTERFACE_CORE_DLL NDArrayToVector<ElementType>;
167
171INSTANTIATE_TOVECTOR(long long)
172INSTANTIATE_TOVECTOR(unsigned int)
173INSTANTIATE_TOVECTOR(unsigned long)
174INSTANTIATE_TOVECTOR(unsigned long long)
178INSTANTIATE_TOVECTOR(std::string)
180} // namespace Converters
181} // namespace Mantid::PythonInterface
double value
The value of the point.
Definition FitMW.cpp:51
#define INSTANTIATE_TOVECTOR(ElementType)
#define DECLARE_EXTERN(HeldType)
Macro to declare template instantiations as extern; those are defined in NDArrayTypeIndex....
tagPyArrayObject PyArrayObject
Thin object wrapper around a numpy array.
Definition NDArray.h:31
MANTID_PYTHONINTERFACE_CORE_DLL PyObject * func_PyArray_IterNew(PyArrayObject *arr)
equivalent to macro PyArray_IterNew
STL namespace.
std::string to_string(const wide_integer< Bits, Signed > &n)
Converter taking an input numpy array and converting it to a std::vector.
void throwIfSizeMismatched(const TypedVector &dest) const
void copyTo(TypedVector &dest) const
Fill the container with data from the array.
TypedVector operator()()
Create a new vector from the contents of the array.
Defines a mapping between C++ type given by the template parameter and numpy type enum NPY_TYPES.