From 45ba07e3145dc0977383b1a0633e72eda4270ffd Mon Sep 17 00:00:00 2001 From: Friedemann Kleint Date: Thu, 4 May 2023 14:44:40 +0200 Subject: Numpy support: Handle short/long/long long integer types The default type of numpy is int64 on Linux and long in Windows these days. As numpy is still based on the old long/long long scheme for the types, add some mapping. [ChangeLog][shiboken6] numpy support has been extended to handle short/long long integer types. Fixes: PYSIDE-2313 Change-Id: I75d9277ae0867401c2c188efb3a50f4c53c4fc24 Reviewed-by: Christian Tismer Reviewed-by: Qt CI Bot (cherry picked from commit 499832abfdf13eac5aa35f84a62166fb5aa2e034) Reviewed-by: Qt Cherry-pick Bot --- .../qtdatavisualization_helper.cpp | 16 ++++++ sources/pyside6/libpyside/pyside_numpy.cpp | 16 ++++++ sources/pyside6/tests/QtCharts/CMakeLists.txt | 1 + .../pyside6/tests/QtCharts/qcharts_numpy_test.py | 43 ++++++++++++++ sources/shiboken6/libshiboken/sbknumpyview.cpp | 66 +++++++++++++++++++++- sources/shiboken6/libshiboken/sbknumpyview.h | 2 +- 6 files changed, 141 insertions(+), 3 deletions(-) create mode 100644 sources/pyside6/tests/QtCharts/qcharts_numpy_test.py diff --git a/sources/pyside6/PySide6/QtDataVisualization/qtdatavisualization_helper.cpp b/sources/pyside6/PySide6/QtDataVisualization/qtdatavisualization_helper.cpp index 12384a093..8ad31a77a 100644 --- a/sources/pyside6/PySide6/QtDataVisualization/qtdatavisualization_helper.cpp +++ b/sources/pyside6/PySide6/QtDataVisualization/qtdatavisualization_helper.cpp @@ -57,6 +57,14 @@ QSurfaceDataArray *surfaceDataFromNp(double xStart, double deltaX, double zStart return result; switch (view.type) { + case Shiboken::Numpy::View::Int16: + populateArray(xStart, deltaX, zStart, deltaZ, xSize, zSize, view.stride[0], + reinterpret_cast(view.data), result); + break; + case Shiboken::Numpy::View::Unsigned16: + populateArray(xStart, deltaX, zStart, deltaZ, xSize, zSize, view.stride[0], + reinterpret_cast(view.data), result); + break; case Shiboken::Numpy::View::Int: populateArray(xStart, deltaX, zStart, deltaZ, xSize, zSize, view.stride[0], reinterpret_cast(view.data), result); @@ -65,6 +73,14 @@ QSurfaceDataArray *surfaceDataFromNp(double xStart, double deltaX, double zStart populateArray(xStart, deltaX, zStart, deltaZ, xSize, zSize, view.stride[0], reinterpret_cast(view.data), result); break; + case Shiboken::Numpy::View::Int64: + populateArray(xStart, deltaX, zStart, deltaZ, xSize, zSize, view.stride[0], + reinterpret_cast(view.data), result); + break; + case Shiboken::Numpy::View::Unsigned64: + populateArray(xStart, deltaX, zStart, deltaZ, xSize, zSize, view.stride[0], + reinterpret_cast(view.data), result); + break; case Shiboken::Numpy::View::Float: populateArray(xStart, deltaX, zStart, deltaZ, xSize, zSize, view.stride[0], reinterpret_cast(view.data), result); diff --git a/sources/pyside6/libpyside/pyside_numpy.cpp b/sources/pyside6/libpyside/pyside_numpy.cpp index a6634fc56..5f43cc5ce 100644 --- a/sources/pyside6/libpyside/pyside_numpy.cpp +++ b/sources/pyside6/libpyside/pyside_numpy.cpp @@ -45,10 +45,18 @@ QList xyDataToQPointFList(PyObject *pyXIn, PyObject *pyYIn) if (size == 0) return {}; switch (xv.type) { + case Shiboken::Numpy::View::Int16: + return xyDataToQPointHelper(xv.data, yv.data, size); + case Shiboken::Numpy::View::Unsigned16: + return xyDataToQPointHelper(xv.data, yv.data, size); case Shiboken::Numpy::View::Int: return xyDataToQPointHelper(xv.data, yv.data, size); case Shiboken::Numpy::View::Unsigned: return xyDataToQPointHelper(xv.data, yv.data, size); + case Shiboken::Numpy::View::Int64: + return xyDataToQPointHelper(xv.data, yv.data, size); + case Shiboken::Numpy::View::Unsigned64: + return xyDataToQPointHelper(xv.data, yv.data, size); case Shiboken::Numpy::View::Float: return xyDataToQPointHelper(xv.data, yv.data, size); case Shiboken::Numpy::View::Double: @@ -67,10 +75,18 @@ QList xyDataToQPointList(PyObject *pyXIn, PyObject *pyYIn) if (size == 0) return {}; switch (xv.type) { + case Shiboken::Numpy::View::Int16: + return xyDataToQPointHelper(xv.data, yv.data, size); + case Shiboken::Numpy::View::Unsigned16: + return xyDataToQPointHelper(xv.data, yv.data, size); case Shiboken::Numpy::View::Int: return xyDataToQPointHelper(xv.data, yv.data, size); case Shiboken::Numpy::View::Unsigned: return xyDataToQPointHelper(xv.data, yv.data, size); + case Shiboken::Numpy::View::Int64: + return xyDataToQPointHelper(xv.data, yv.data, size); + case Shiboken::Numpy::View::Unsigned64: + return xyDataToQPointHelper(xv.data, yv.data, size); case Shiboken::Numpy::View::Float: return xyFloatDataToQPointHelper(xv.data, yv.data, size); case Shiboken::Numpy::View::Double: diff --git a/sources/pyside6/tests/QtCharts/CMakeLists.txt b/sources/pyside6/tests/QtCharts/CMakeLists.txt index 16e8b4bc9..4d031937a 100644 --- a/sources/pyside6/tests/QtCharts/CMakeLists.txt +++ b/sources/pyside6/tests/QtCharts/CMakeLists.txt @@ -1 +1,2 @@ PYSIDE_TEST(qcharts_test.py) +PYSIDE_TEST(qcharts_numpy_test.py) diff --git a/sources/pyside6/tests/QtCharts/qcharts_numpy_test.py b/sources/pyside6/tests/QtCharts/qcharts_numpy_test.py new file mode 100644 index 000000000..044fab34c --- /dev/null +++ b/sources/pyside6/tests/QtCharts/qcharts_numpy_test.py @@ -0,0 +1,43 @@ +#!/usr/bin/python +# Copyright (C) 2023 The Qt Company Ltd. +# SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0 + +'''Test cases for QCharts/numpy''' + +import os +import sys +import unittest +try: + import numpy as np + HAVE_NUMPY = True +except ModuleNotFoundError: + HAVE_NUMPY = False + +from pathlib import Path +sys.path.append(os.fspath(Path(__file__).resolve().parents[1])) +from init_paths import init_test_paths +init_test_paths(False) + +from helper.usesqapplication import UsesQApplication +from PySide6.QtCore import QCoreApplication +from PySide6.QtCharts import QLineSeries + + +class QChartsNumpyTestCase(UsesQApplication): + '''Tests related to QCharts/numpy''' + + @unittest.skipUnless(HAVE_NUMPY, "requires numpy") + def test(self): + """PYSIDE-2313: Verify various types.""" + line_series = QLineSeries() + data_types = [np.short, np.ushort, np.int32, np.uint32, + np.int64, np.uint64, np.float32, np.float64] + for dt in data_types: + old_size = line_series.count() + arr = np.array([2], dtype=dt) + line_series.appendNp(arr, arr) + self.assertEqual(line_series.count(), old_size + 1) + + +if __name__ == '__main__': + unittest.main() diff --git a/sources/shiboken6/libshiboken/sbknumpyview.cpp b/sources/shiboken6/libshiboken/sbknumpyview.cpp index 44a4b5587..e83a5bda7 100644 --- a/sources/shiboken6/libshiboken/sbknumpyview.cpp +++ b/sources/shiboken6/libshiboken/sbknumpyview.cpp @@ -25,12 +25,38 @@ View View::fromPyObject(PyObject *pyIn) View::Type type; switch (PyArray_TYPE(ar)) { + case NPY_SHORT: + type = View::Int16; + break; + case NPY_USHORT: + type = View::Unsigned16; + break; case NPY_INT: type = View::Int; break; case NPY_UINT: type = View::Unsigned; break; + case NPY_LONG: + if constexpr (sizeof(long) == sizeof(int)) + type = View::Int; + else if constexpr (sizeof(long) == sizeof(int64_t)) + type = View::Int64; + break; + case NPY_ULONG: + if constexpr (sizeof(long) == sizeof(int)) + type = View::Unsigned; + else if constexpr (sizeof(long) == sizeof(int64_t)) + type = View::Unsigned64; + break; + case NPY_LONGLONG: + if constexpr (sizeof(long long) == 64) + type = View::Int64; + break; + case NPY_ULONGLONG: + if constexpr (sizeof(long long) == 64) + type = View::Unsigned64; + break; case NPY_FLOAT: type = View::Float; break; @@ -91,11 +117,29 @@ std::ostream &operator<<(std::ostream &str, const debugPyArrayObject &a) } str << "], type="; switch (type) { + case NPY_SHORT: + str << "short"; + break; + case NPY_USHORT: + str << "ushort"; + break; case NPY_INT: - str << "int"; + str << "int32"; break; case NPY_UINT: - str << "uint"; + str << "uint32"; + break; + case NPY_LONG: + str << "long"; + break; + case NPY_ULONG: + str << "ulong"; + break; + case NPY_LONGLONG: + str << "long long"; + break; + case NPY_ULONGLONG: + str << "ulong long"; break; case NPY_FLOAT: str << "float"; @@ -122,12 +166,30 @@ std::ostream &operator<<(std::ostream &str, const debugPyArrayObject &a) if (const int dim0 = PyArray_DIMS(ar)[0]) { auto *data = PyArray_DATA(ar); switch (type) { + case NPY_SHORT: + debugArray(str, reinterpret_cast(data), dim0); + break; + case NPY_USHORT: + debugArray(str, reinterpret_cast(data), dim0); + break; case NPY_INT: debugArray(str, reinterpret_cast(data), dim0); break; case NPY_UINT: debugArray(str, reinterpret_cast(data), dim0); break; + case NPY_LONG: + debugArray(str, reinterpret_cast(data), dim0); + break; + case NPY_ULONG: + debugArray(str, reinterpret_cast(data), dim0); + break; + case NPY_LONGLONG: + debugArray(str, reinterpret_cast(data), dim0); + break; + case NPY_ULONGLONG: + debugArray(str, reinterpret_cast(data), dim0); + break; case NPY_FLOAT: debugArray(str, reinterpret_cast(data), dim0); break; diff --git a/sources/shiboken6/libshiboken/sbknumpyview.h b/sources/shiboken6/libshiboken/sbknumpyview.h index d41e2c716..918913b78 100644 --- a/sources/shiboken6/libshiboken/sbknumpyview.h +++ b/sources/shiboken6/libshiboken/sbknumpyview.h @@ -22,7 +22,7 @@ LIBSHIBOKEN_API bool check(PyObject *pyIn); /// numpy headers. struct LIBSHIBOKEN_API View { - enum Type { Int, Unsigned, Float, Double}; + enum Type { Int, Unsigned, Float, Double, Int16, Unsigned16, Int64, Unsigned64 }; static View fromPyObject(PyObject *pyIn); -- cgit v1.2.3