Line data Source code
1 : // SPDX-License-Identifier: BSD-3-Clause 2 : // Copyright (c) 2023 Scipp contributors (https://github.com/scipp) 3 : /// @file 4 : /// @author Simon Heybrock 5 : #include "scipp/core/element_array_view.h" 6 : #include "scipp/core/array_to_string.h" 7 : #include "scipp/core/dtype.h" 8 : #include "scipp/core/eigen.h" 9 : #include "scipp/core/except.h" 10 : #include "scipp/dataset/dataset.h" 11 : #include "scipp/dataset/except.h" 12 : 13 : #include "pybind11.h" 14 : 15 : #include "py_object.h" 16 : 17 : using namespace scipp; 18 : using namespace scipp::core; 19 : 20 : namespace py = pybind11; 21 : 22 : namespace { 23 : template <class T> struct is_bins : std::false_type {}; 24 : template <class T> struct is_bins<core::bin<T>> : std::true_type {}; 25 : 26 78 : template <typename T> decltype(auto) to_python_object(T &&val) { 27 : if constexpr (std::is_same_v<std::remove_const_t<std::remove_reference_t<T>>, 28 : scipp::python::PyObject>) { 29 5 : return std::forward<T>(val).to_pybind(); 30 : } else { 31 73 : return std::forward<T>(val); 32 : } 33 : } 34 : } // namespace 35 : 36 : template <class T> 37 90 : void declare_ElementArrayView(py::module &m, const std::string &suffix) { 38 180 : py::class_<ElementArrayView<T>> view( 39 180 : m, (std::string("ElementArrayView_") + suffix).c_str()); 40 90 : view.def( 41 : "__repr__", 42 1 : [](const ElementArrayView<T> &self) { return array_to_string(self); }) 43 0 : .def( 44 : "__getitem__", 45 78 : [](const ElementArrayView<T> &self, const scipp::index i) { 46 78 : return to_python_object(self[i]); 47 : }, 48 90 : py::return_value_policy::reference) 49 90 : .def("__len__", &ElementArrayView<T>::size) 50 110 : .def("__iter__", [](const ElementArrayView<T> &self) { 51 20 : return py::make_iterator(self.begin(), self.end()); 52 : }); 53 : if constexpr (std::is_same_v<std::remove_const_t<std::remove_reference_t<T>>, 54 : scipp::python::PyObject>) { 55 6 : view.def("__setitem__", [](ElementArrayView<T> &self, 56 : [[maybe_unused]] const scipp::index i, 57 : [[maybe_unused]] const py::object &value) { 58 : if constexpr (is_bins<T>::value || std::is_const_v<T>) 59 0 : throw std::invalid_argument("assignment destination is read-only"); 60 : else 61 0 : to_python_object(self[i]) = value; 62 : }); 63 : } else { 64 114 : view.def("__setitem__", [](ElementArrayView<T> &self, 65 : [[maybe_unused]] const scipp::index i, 66 : [[maybe_unused]] const T &value) { 67 : if constexpr (is_bins<T>::value || std::is_const_v<T>) 68 0 : throw std::invalid_argument("assignment destination is read-only"); 69 : else 70 15 : self[i] = value; 71 : }); 72 : } 73 90 : } 74 : 75 3 : void init_element_array_view(py::module &m) { 76 3 : declare_ElementArrayView<double>(m, "double"); 77 3 : declare_ElementArrayView<float>(m, "float"); 78 3 : declare_ElementArrayView<int64_t>(m, "int64"); 79 3 : declare_ElementArrayView<int32_t>(m, "int32"); 80 3 : declare_ElementArrayView<std::string>(m, "string"); 81 3 : declare_ElementArrayView<bool>(m, "bool"); 82 3 : declare_ElementArrayView<Variable>(m, "Variable"); 83 3 : declare_ElementArrayView<DataArray>(m, "DataArray"); 84 3 : declare_ElementArrayView<Dataset>(m, "Dataset"); 85 3 : declare_ElementArrayView<Eigen::Vector3d>(m, "Eigen_Vector3d"); 86 3 : declare_ElementArrayView<Eigen::Matrix3d>(m, "Eigen_Matrix3d"); 87 3 : declare_ElementArrayView<bucket<Variable>>(m, "bin_Variable"); 88 3 : declare_ElementArrayView<bucket<DataArray>>(m, "bin_DataArray"); 89 3 : declare_ElementArrayView<bucket<Dataset>>(m, "bin_Dataset"); 90 3 : declare_ElementArrayView<scipp::python::PyObject>(m, "PyObject"); 91 : 92 3 : declare_ElementArrayView<const double>(m, "double_const"); 93 3 : declare_ElementArrayView<const float>(m, "float_const"); 94 3 : declare_ElementArrayView<const int64_t>(m, "int64_const"); 95 3 : declare_ElementArrayView<const int32_t>(m, "int32_const"); 96 3 : declare_ElementArrayView<const std::string>(m, "string_const"); 97 3 : declare_ElementArrayView<const bool>(m, "bool_const"); 98 3 : declare_ElementArrayView<const Variable>(m, "Variable_const"); 99 3 : declare_ElementArrayView<const DataArray>(m, "DataArray_const"); 100 3 : declare_ElementArrayView<const Dataset>(m, "Dataset_const"); 101 3 : declare_ElementArrayView<const Eigen::Vector3d>(m, "Eigen_Vector3d_const"); 102 3 : declare_ElementArrayView<const Eigen::Matrix3d>(m, "Eigen_Matrix3d_const"); 103 3 : declare_ElementArrayView<const bucket<Variable>>(m, "bin_Variable_const"); 104 3 : declare_ElementArrayView<const bucket<DataArray>>(m, "bin_DataArray_const"); 105 3 : declare_ElementArrayView<const bucket<Dataset>>(m, "bin_Dataset_const"); 106 3 : declare_ElementArrayView<const scipp::python::PyObject>(m, "PyObject_const"); 107 3 : }