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
123template <> PyObject *cloneND(const std::string *carray, const int ndims, Py_intptr_t *dims) {
124 boost::python::list pystrs;
125 const std::string *iter = carray;
126 for (int i = 0; i < ndims; ++i) {
127 const Py_intptr_t length = dims[i];
128 for (Py_intptr_t j = 0; j < length; ++j) {
129 pystrs.append(iter->c_str());
130 ++iter;
131 }
132 }
133 PyObject *rawptr = pystrs.ptr();
134 Py_INCREF(rawptr); // Make sure it survives after the wrapper decrefs the count
135 return rawptr;
136}
137
138//-----------------------------------------------------------------------
139// Explicit instantiations
140//-----------------------------------------------------------------------
141#define INSTANTIATE_CLONE1D(ElementType) \
142 template DLLExport PyObject *clone1D<ElementType>(const std::vector<ElementType> &cvector);
143
144#define INSTANTIATE_CLONEND(ElementType) \
145 template DLLExport PyObject *cloneND<ElementType>(const ElementType *, const int ndims, Py_intptr_t *dims);
146
147#define INSTANTIATE_CLONE(ElementType) \
148 INSTANTIATE_CLONE1D(ElementType) \
149 INSTANTIATE_CLONEND(ElementType)
150
154INSTANTIATE_CLONE(long long)
155INSTANTIATE_CLONE(unsigned int)
156INSTANTIATE_CLONE(unsigned long)
157INSTANTIATE_CLONE(unsigned long long)
158INSTANTIATE_CLONE(double)
160// Need further 1D specialisation for string
161INSTANTIATE_CLONE1D(std::string)
162// Need further ND specialisation for DateAndTime
163INSTANTIATE_CLONEND(Types::Core::DateAndTime)
164// Need further ND specialisation for bool
167} // namespace Impl
168} // 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()
Definition: DateAndTime.cpp:46
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.