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 "MantidTypes/Core/DateAndTime.h"
15#include <boost/python/list.hpp>
16#include <string>
17
18#define PY_ARRAY_UNIQUE_SYMBOL CORE_ARRAY_API
19#define NO_IMPORT_ARRAY
20#include <numpy/arrayobject.h>
21
23#ifdef __APPLE__
24extern template int NDArrayTypeIndex<bool>::typenum;
25extern template int NDArrayTypeIndex<int>::typenum;
26extern template int NDArrayTypeIndex<long>::typenum;
27extern template int NDArrayTypeIndex<long long>::typenum;
31extern template int NDArrayTypeIndex<float>::typenum;
32extern template int NDArrayTypeIndex<double>::typenum;
34#endif
35namespace Impl {
42template <typename ElementType> PyObject *clone1D(const std::vector<ElementType> &cvector) {
43 Py_intptr_t dims[1] = {static_cast<int>(cvector.size())};
44 return cloneND(cvector.data(), 1, dims);
45}
46
52template <> MANTID_PYTHONINTERFACE_CORE_DLL PyObject *clone1D(const std::vector<Types::Core::DateAndTime> &cvector) {
53 // create an empty array
55 Py_intptr_t dims[1] = {static_cast<int>(cvector.size())};
56 auto *nparray = reinterpret_cast<PyArrayObject *>(
57 PyArray_NewFromDescr(&PyArray_Type, descr, 1, dims, nullptr, nullptr, 0, nullptr));
58
59 for (Py_intptr_t i = 0; i < dims[0]; ++i) {
60 void *itemPtr = PyArray_GETPTR1(nparray, i);
61 npy_datetime abstime = Converters::to_npy_datetime(cvector[i]);
62 auto scalar = PyArray_Scalar(reinterpret_cast<char *>(&abstime), descr, nullptr);
63 PyArray_SETITEM(nparray, reinterpret_cast<char *>(itemPtr), scalar);
64 Py_DECREF(scalar);
65 }
66 return reinterpret_cast<PyObject *>(nparray);
67}
68
75template <> MANTID_PYTHONINTERFACE_CORE_DLL PyObject *clone1D(const std::vector<bool> &cvector) {
76 Py_intptr_t dims[1] = {static_cast<int>(cvector.size())};
78 PyArrayObject *nparray = func_PyArray_NewFromDescr(datatype, 1, &dims[0]);
79
80 for (Py_intptr_t i = 0; i < dims[0]; ++i) {
81 void *itemPtr = PyArray_GETPTR1(nparray, i);
82 auto py_bool = PyBool_FromLong(static_cast<long int>(cvector[i]));
83 PyArray_SETITEM(nparray, reinterpret_cast<char *>(itemPtr), py_bool);
84 Py_DECREF(py_bool);
85 }
86 return reinterpret_cast<PyObject *>(nparray);
87}
88
98template <typename ElementType> PyObject *cloneND(const ElementType *carray, const int ndims, Py_intptr_t *dims) {
100 PyArrayObject *nparray = func_PyArray_NewFromDescr(datatype, ndims, &dims[0]);
101 // Compute total number of elements
102 size_t length(dims[0]);
103 if (ndims > 1) {
104 for (int i = 1; i < ndims; ++i) {
105 length *= dims[i];
106 }
107 }
108 void *arrayData = PyArray_DATA(nparray);
109 const void *data = static_cast<void *>(const_cast<ElementType *>(carray));
110 if (dims[0] > 0) {
111 std::memcpy(arrayData, data, PyArray_ITEMSIZE(nparray) * length);
112 }
113 return reinterpret_cast<PyObject *>(nparray);
114}
115
123// cppcheck-suppress constParameterPointer
124// Suppressed because one of the cloneND overloads calls
125// PyArray_NewFromDescrclasses inside NumpyFunctions::func_PyArray_NewFromDescr, which
126// requires the dim parameter to be non-const.
127template <> PyObject *cloneND(const std::string *carray, const int ndims, Py_intptr_t *dims) {
128 boost::python::list pystrs;
129 const std::string *iter = carray;
130 for (int i = 0; i < ndims; ++i) {
131 const Py_intptr_t length = dims[i];
132 for (Py_intptr_t j = 0; j < length; ++j) {
133 pystrs.append(iter->c_str());
134 ++iter;
135 }
136 }
137 PyObject *rawptr = pystrs.ptr();
138 Py_INCREF(rawptr); // Make sure it survives after the wrapper decrefs the count
139 return rawptr;
140}
141
142//-----------------------------------------------------------------------
143// Explicit instantiations
144//-----------------------------------------------------------------------
145#define INSTANTIATE_CLONE1D(ElementType) \
146 template DLLExport PyObject *clone1D<ElementType>(const std::vector<ElementType> &cvector);
147
148#define INSTANTIATE_CLONEND(ElementType) \
149 template DLLExport PyObject *cloneND<ElementType>(const ElementType *, const int ndims, Py_intptr_t *dims);
150
151#define INSTANTIATE_CLONE(ElementType) \
152 INSTANTIATE_CLONE1D(ElementType) \
153 INSTANTIATE_CLONEND(ElementType)
154
158INSTANTIATE_CLONE(long long)
159INSTANTIATE_CLONE(unsigned int)
160INSTANTIATE_CLONE(unsigned long)
161INSTANTIATE_CLONE(unsigned long long)
162INSTANTIATE_CLONE(double)
164// Need further 1D specialisation for string
165INSTANTIATE_CLONE1D(std::string)
166// Need further ND specialisation for DateAndTime
167INSTANTIATE_CLONEND(Types::Core::DateAndTime)
168// Need further ND specialisation for bool
171} // namespace Impl
172} // namespace Mantid::PythonInterface::Converters
#define INSTANTIATE_CLONE(ElementType)
#define INSTANTIATE_CLONEND(ElementType)
#define INSTANTIATE_CLONE1D(ElementType)
tagPyArrayObject PyArrayObject
_PyArray_Descr PyArray_Descr
#define MANTID_PYTHONINTERFACE_CORE_DLL
Definition DllConfig.h:17
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.