Mantid
Loading...
Searching...
No Matches
CloneToNDArray.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//-----------------------------------------------------------------------------
14#include "MantidPythonInterface/core/DllConfig.h"
15#include "MantidTypes/Core/DateAndTime.h"
16#include <boost/python/list.hpp>
17#include <string>
18
19#define PY_ARRAY_UNIQUE_SYMBOL CORE_ARRAY_API
20#define NO_IMPORT_ARRAY
21#include <numpy/arrayobject.h>
22
24#ifdef __APPLE__
25extern template int NDArrayTypeIndex<bool>::typenum;
26extern template int NDArrayTypeIndex<int>::typenum;
27extern template int NDArrayTypeIndex<long>::typenum;
28extern template int NDArrayTypeIndex<long long>::typenum;
32extern template int NDArrayTypeIndex<float>::typenum;
33extern template int NDArrayTypeIndex<double>::typenum;
35#endif
36namespace Impl {
43template <typename ElementType> PyObject *clone1D(const std::vector<ElementType> &cvector) {
44 Py_intptr_t dims[1] = {static_cast<int>(cvector.size())};
45 return cloneND(cvector.data(), 1, dims);
46}
47
53template <> MANTID_PYTHONINTERFACE_CORE_DLL PyObject *clone1D(const std::vector<Types::Core::DateAndTime> &cvector) {
54 // create an empty array
56 Py_intptr_t dims[1] = {static_cast<int>(cvector.size())};
57 auto *nparray = reinterpret_cast<PyArrayObject *>(
58 PyArray_NewFromDescr(&PyArray_Type, descr, 1, dims, nullptr, nullptr, 0, nullptr));
59
60 for (Py_intptr_t i = 0; i < dims[0]; ++i) {
61 void *itemPtr = PyArray_GETPTR1(nparray, i);
62 npy_datetime abstime = Converters::to_npy_datetime(cvector[i]);
63 auto scalar = PyArray_Scalar(reinterpret_cast<char *>(&abstime), descr, nullptr);
64 PyArray_SETITEM(nparray, reinterpret_cast<char *>(itemPtr), scalar);
65 Py_DECREF(scalar);
66 }
67 return reinterpret_cast<PyObject *>(nparray);
68}
69
76template <> MANTID_PYTHONINTERFACE_CORE_DLL PyObject *clone1D(const std::vector<bool> &cvector) {
77 Py_intptr_t dims[1] = {static_cast<int>(cvector.size())};
79 PyArrayObject *nparray = func_PyArray_NewFromDescr(datatype, 1, &dims[0]);
80
81 for (Py_intptr_t i = 0; i < dims[0]; ++i) {
82 void *itemPtr = PyArray_GETPTR1(nparray, i);
83 auto py_bool = PyBool_FromLong(static_cast<long int>(cvector[i]));
84 PyArray_SETITEM(nparray, reinterpret_cast<char *>(itemPtr), py_bool);
85 Py_DECREF(py_bool);
86 }
87 return reinterpret_cast<PyObject *>(nparray);
88}
89
99template <typename ElementType> PyObject *cloneND(const ElementType *carray, const int ndims, Py_intptr_t *dims) {
101 PyArrayObject *nparray = func_PyArray_NewFromDescr(datatype, ndims, &dims[0]);
102 // Compute total number of elements
103 size_t length(dims[0]);
104 if (ndims > 1) {
105 for (int i = 1; i < ndims; ++i) {
106 length *= dims[i];
107 }
108 }
109 void *arrayData = PyArray_DATA(nparray);
110 const void *data = static_cast<void *>(const_cast<ElementType *>(carray));
111 if (dims[0] > 0) {
112 std::memcpy(arrayData, data, PyArray_ITEMSIZE(nparray) * length);
113 }
114 return reinterpret_cast<PyObject *>(nparray);
115}
116
124// cppcheck-suppress constParameterPointer
125// Suppressed because one of the cloneND overloads calls
126// PyArray_NewFromDescrclasses inside NumpyFunctions::func_PyArray_NewFromDescr, which
127// requires the dim parameter to be non-const.
128template <> PyObject *cloneND(const std::string *carray, const int ndims, Py_intptr_t *dims) {
129 boost::python::list pystrs;
130 const std::string *iter = carray;
131 for (int i = 0; i < ndims; ++i) {
132 const Py_intptr_t length = dims[i];
133 for (Py_intptr_t j = 0; j < length; ++j) {
134 pystrs.append(iter->c_str());
135 ++iter;
136 }
137 }
138 PyObject *rawptr = pystrs.ptr();
139 Py_INCREF(rawptr); // Make sure it survives after the wrapper decrefs the count
140 return rawptr;
141}
142
143//-----------------------------------------------------------------------
144// Explicit instantiations
145//-----------------------------------------------------------------------
146#define INSTANTIATE_CLONE1D(ElementType) \
147 template MANTID_PYTHONINTERFACE_CORE_DLL PyObject *clone1D<ElementType>(const std::vector<ElementType> &cvector);
148
149#define INSTANTIATE_CLONEND(ElementType) \
150 template MANTID_PYTHONINTERFACE_CORE_DLL PyObject *cloneND<ElementType>(const ElementType *, const int ndims, \
151 Py_intptr_t *dims);
152
153#define INSTANTIATE_CLONE(ElementType) \
154 INSTANTIATE_CLONE1D(ElementType) \
155 INSTANTIATE_CLONEND(ElementType)
156
160INSTANTIATE_CLONE(long long)
161INSTANTIATE_CLONE(unsigned int)
162INSTANTIATE_CLONE(unsigned long)
163INSTANTIATE_CLONE(unsigned long long)
164INSTANTIATE_CLONE(double)
166// Need further 1D specialisation for string
167INSTANTIATE_CLONE1D(std::string)
168// Need further ND specialisation for DateAndTime
169INSTANTIATE_CLONEND(Types::Core::DateAndTime)
170// Need further ND specialisation for bool
173} // namespace Impl
174} // namespace Mantid::PythonInterface::Converters
#define INSTANTIATE_CLONE(ElementType)
#define INSTANTIATE_CLONEND(ElementType)
#define INSTANTIATE_CLONE1D(ElementType)
tagPyArrayObject PyArrayObject
_PyArray_Descr PyArray_Descr
PyObject * cloneND(const ElementType *carray, const int ndims, Py_intptr_t *dims)
Returns a new numpy array with the a copy of the data from array.
PyObject * clone1D(const std::vector< ElementType > &cvector)
Returns a new numpy array with the a copy of the data from 1D vector with the exception of string ele...
MANTID_PYTHONINTERFACE_CORE_DLL PyArrayObject * func_PyArray_NewFromDescr(int datatype, int ndims, Py_intptr_t *dims)
equivalent to macro PyArray_NewFromDescr
MANTID_PYTHONINTERFACE_CORE_DLL PyArray_Descr * descr_ns()
MANTID_PYTHONINTERFACE_CORE_DLL npy_datetime to_npy_datetime(const Types::Core::DateAndTime &dateandtime)
Total nanoseconds since the unix epoch.
Defines a mapping between C++ type given by the template parameter and numpy type enum NPY_TYPES.