14#include <boost/python/class.hpp>
15#include <boost/python/copy_non_const_reference.hpp>
16#define PY_ARRAY_UNIQUE_SYMBOL API_ARRAY_API
17#define NO_IMPORT_ARRAY
18#include <numpy/arrayobject.h>
45PyObject *WrapReadOnlyNumpyFArray(
const Mantid::signal_t *arr, std::vector<Py_intptr_t> dims) {
47#if NPY_API_VERSION >= 0x00000007
49 PyArray_New(&PyArray_Type,
static_cast<int>(dims.size()), &dims[0], datatype,
nullptr,
50 static_cast<void *
>(
const_cast<double *
>(arr)), 0, NPY_ARRAY_FARRAY,
nullptr));
51 PyArray_CLEARFLAGS(nparray, NPY_ARRAY_WRITEABLE);
54 PyArray_New(&PyArray_Type,
static_cast<int>(dims.size()), &dims[0], datatype,
nullptr,
55 static_cast<void *
>(
const_cast<double *
>(arr)), 0, NPY_FARRAY,
nullptr));
56 nparray->flags &= ~NPY_WRITEABLE;
58 return reinterpret_cast<PyObject *
>(nparray);
68 std::vector<size_t> nd;
72 for (
size_t i = 0; i < ndims; ++i) {
77 std::vector<Py_intptr_t> dims(ndims);
78 for (
size_t i = 0; i < ndims; ++i)
79 dims[i] =
static_cast<Py_intptr_t
>(nd[i]);
82 throw std::runtime_error(
"Workspace has zero dimensions!");
93 auto dims = countDimensions(self);
102 auto dims = countDimensions(self);
111 auto dims = countDimensions(self);
123 auto wsShape = countDimensions(self);
124 const size_t ndims = wsShape.size();
125 auto arrShape = signal.attr(
"shape");
126 if (ndims !=
static_cast<size_t>(len(arrShape))) {
127 std::ostringstream os;
129 <<
": The number of dimensions doe not match the current "
130 "workspace size. Workspace="
131 << ndims <<
" array=" << len(arrShape);
132 throw std::invalid_argument(os.str());
135 for (
size_t i = 0; i < ndims; ++i) {
136 int arrDim = extract<int>(arrShape[i])();
137 if (wsShape[i] != arrDim) {
138 std::ostringstream os;
139 os << fnLabel <<
": The dimension size for the " <<
std::to_string(i) <<
"th dimension do not match. "
140 <<
"Workspace dimension size=" << wsShape[i] <<
", array size=" << arrDim;
141 throw std::invalid_argument(os.str());
160 int flags = NPY_ARRAY_F_CONTIGUOUS | NPY_ARRAY_ALIGNED;
161 const int type = PyArray_TYPE(
reinterpret_cast<PyArrayObject *
>(values.ptr()));
162 if (type == NPY_OBJECT || PyTypeNum_ISFLOAT(type))
163 flags |= NPY_ARRAY_FORCECAST;
164 PyObject *converted = PyArray_FROMANY(values.ptr(), NPY_DOUBLE, 0, 0, flags);
167 throw error_already_set();
168 handle<> owner(converted);
171 if (PyArray_TYPE(array) != NPY_DOUBLE || !PyArray_ISFARRAY_RO(array) || !PyArray_ISNOTSWAPPED(array))
172 throw std::runtime_error(
"numpy did not convert the array to an aligned, native float64 array in Fortran order");
173 const auto *source =
static_cast<const double *
>(PyArray_DATA(array));
174 std::copy(source, source + PyArray_SIZE(array), dest);
185 throwIfSizeIncorrect(self, signalValues,
"setSignalArray");
198 throwIfSizeIncorrect(self, errorSquared,
"setErrorSquaredArray");
210 throwIfSizeIncorrect(self, numEvents,
"setNumEventsArray");
220 throw std::invalid_argument(
"setSignalAt: The index is greater than the "
221 "number of bins in the workspace");
229 class_<IMDHistoWorkspace, bases<IMDWorkspace, MultipleExperimentInfos>, boost::noncopyable>(
"IMDHistoWorkspace",
231 .def(
"getSignalArray", &getSignalArrayAsNumpyArray, arg(
"self"),
232 "Returns a read-only numpy array containing the signal values")
234 .def(
"getErrorSquaredArray", &getErrorSquaredArrayAsNumpyArray, arg(
"self"),
235 "Returns a read-only numpy array containing the square of the error "
238 .def(
"getNumEventsArray", &getNumEventsArrayAsNumpyArray, arg(
"self"),
239 "Returns a read-only numpy array containing the number of MD events "
243 return_value_policy<copy_non_const_reference>(),
"Return a reference to the signal at the linear index")
246 return_value_policy<copy_non_const_reference>(),
"Return the squared-errors at the linear index")
248 .def(
"setSignalAt", &setSignalAt, (arg(
"self"), arg(
"index"), arg(
"value")),
249 "Sets the signal at the specified index.")
252 "Sets the squared-error at the specified index.")
254 .def(
"setSignalArray", &setSignalArray, (arg(
"self"), arg(
"signalValues")),
255 "Sets the signal from a numpy array. The sizes must match the "
256 "current workspace sizes. A ValueError is thrown if not. Any link "
257 "to the original MDEventWorkspace(s) is cleared.")
259 .def(
"setErrorSquaredArray", &setErrorSquaredArray, (arg(
"self"), arg(
"errorSquared")),
260 "Sets the square of the errors from a numpy array. The sizes must "
261 "match the current workspace sizes. A ValueError is thrown if not. Any "
262 "link to the original MDEventWorkspace(s) is cleared.")
264 .def(
"setNumEventsArray", &setNumEventsArray, (arg(
"self"), arg(
"numEvents")),
265 "Sets the number of events from a numpy array. The sizes must match "
266 "the current workspace sizes, otherwise a ValueError is thrown. Any link "
267 "to the original MDEventWorkspace(s) is cleared.")
270 "Sets all signals/errors in the workspace to the given values")
273 return_value_policy<return_by_value>(),
"Return the inverse of volume of EACH cell in the workspace.")
276 (arg(
"self"), arg(
"index1"), arg(
"index2")), return_value_policy<return_by_value>(),
277 "Get the 1D linear index from the 2D array")
279 .def(
"getLinearIndex",
281 (arg(
"self"), arg(
"index1"), arg(
"index2"), arg(
"index3")), return_value_policy<return_by_value>(),
282 "Get the 1D linear index from the 3D array")
284 .def(
"getLinearIndex",
286 (arg(
"self"), arg(
"index1"), arg(
"index2"), arg(
"index3"), arg(
"index4")),
287 return_value_policy<return_by_value>(),
"Get the 1D linear index from the 4D array")
290 return_value_policy<return_by_value>(),
"Return the position of the center of a bin at a given position")
293 "Sets the visual normalization of"
double value
The value of the point.
#define GET_POINTER_SPECIALIZATION(TYPE)
std::map< DeltaEMode::Type, std::string > index
tagPyArrayObject PyArrayObject
void export_IMDHistoWorkspace()
Abstract interface to MDHistoWorkspace, for use in exposing to Python.
virtual signal_t & errorSquaredAt(size_t index)=0
virtual Mantid::Kernel::VMD getCenter(size_t linearIndex) const =0
virtual const signal_t * getErrorSquaredArray() const =0
virtual const signal_t * getNumEventsArray() const =0
virtual signal_t & signalAt(size_t index)=0
virtual signal_t * mutableNumEventsArray()=0
virtual void setErrorSquaredAt(size_t index, signal_t value)=0
virtual const signal_t * getSignalArray() const =0
virtual signal_t * mutableSignalArray()=0
virtual void setDisplayNormalization(const Mantid::API::MDNormalization &preferredNormalization)=0
virtual void setSignalAt(size_t index, signal_t value)=0
virtual coord_t getInverseVolume() const =0
See the MDHistoWorkspace definition for descriptions of these.
virtual signal_t * mutableErrorSquaredArray()=0
virtual size_t getLinearIndex(size_t index1, size_t index2) const =0
virtual void setTo(signal_t signal, signal_t errorSquared, signal_t numEvents)=0
virtual uint64_t getNPoints() const =0
Get the number of points associated with the workspace.
virtual std::shared_ptr< const Mantid::Geometry::IMDDimension > getDimension(size_t index) const
Get a dimension.
virtual size_t getNumDims() const
void clearOriginalWorkspaces()
Clear original workspaces.
Thin object wrapper around a numpy array.
double signal_t
Typedef for the signal recorded in a MDBox, etc.
std::string to_string(const wide_integer< Bits, Signed > &n)
Defines a mapping between C++ type given by the template parameter and numpy type enum NPY_TYPES.
Encapsulates the registration required for an interface type T that sits on top of a Kernel::DataItem...