From f43fdac6f7ed387da6551015a538819b5d8ec1c2 Mon Sep 17 00:00:00 2001 From: Thomas VINCENT Date: Mon, 21 Sep 2026 15:56:44 +0200 Subject: [PATCH 01/15] fix numpt v1 support --- src/silx/gui/plot/_utils/axis_scale.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/silx/gui/plot/_utils/axis_scale.py b/src/silx/gui/plot/_utils/axis_scale.py index c101c70953..f8756e06ed 100644 --- a/src/silx/gui/plot/_utils/axis_scale.py +++ b/src/silx/gui/plot/_utils/axis_scale.py @@ -57,7 +57,7 @@ def revert(axisScale: AxisScaleType, value: float | ArrayLike) -> float | numpy. return value elif axisScale == "log": with numpy.errstate(over="ignore"): - return numpy.pow(10.0, value) + return numpy.power(10.0, value) elif axisScale == "asinh": with numpy.errstate(over="ignore"): return numpy.sinh(value) From 6ea9d6d70ef8d6720ba35879751e61548ef9d081 Mon Sep 17 00:00:00 2001 From: Thomas VINCENT Date: Tue, 22 Sep 2026 09:19:10 +0200 Subject: [PATCH 02/15] add numpy v1 test to ci --- .github/workflows/ci.yml | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index c0b7f3bd3a..b1f0d27af3 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -32,7 +32,7 @@ jobs: python ./tools/check_meson.py dist/silx-*.whl build: - name: "Python ${{ matrix.python-version }} on ${{ matrix.os }} ${{ matrix.QT_API }}" + name: "Python ${{ matrix.python-version }} on ${{ matrix.os }} ${{ matrix.QT_API }} ${{ matrix.numpy_version }}" runs-on: ${{ matrix.os }} strategy: fail-fast: false @@ -43,18 +43,21 @@ jobs: QT_API: PySide6 with_opencl: true with_gl_test: true + numpy_version: "" - os: macos-latest python-version: "3.14" QT_API: PyQt6 with_opencl: false with_gl_test: false + numpy_version: "" - os: windows-latest python-version: "3.10" QT_API: PyQt5 with_opencl: false with_gl_test: true + numpy_version: "numpy<2" steps: - uses: actions/checkout@v5 @@ -77,6 +80,9 @@ jobs: - name: Install run: | pip install -r ci/requirements-pinned.txt + if [ -n "${{ matrix.numpy_version }}" ]; then + pip install "${{ matrix.numpy_version }}" + fi pip install --pre "${{ matrix.QT_API }}" pip install --pre "$(ls dist/silx*.whl)[full,test]" python ./ci/info_platform.py From 2ee62b8cd3d89c0db63c83fe788b59b7e8cde733 Mon Sep 17 00:00:00 2001 From: Thomas VINCENT Date: Tue, 22 Sep 2026 15:14:46 +0200 Subject: [PATCH 03/15] enforce numpy<2 after silx install --- .github/workflows/ci.yml | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index b1f0d27af3..b5396df3ef 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -80,11 +80,12 @@ jobs: - name: Install run: | pip install -r ci/requirements-pinned.txt - if [ -n "${{ matrix.numpy_version }}" ]; then - pip install "${{ matrix.numpy_version }}" - fi pip install --pre "${{ matrix.QT_API }}" pip install --pre "$(ls dist/silx*.whl)[full,test]" + if [ -n "${{ matrix.numpy_version }}" ]; then + pip uninstall -y h5pyd; + pip install "${{ matrix.numpy_version }}"; + fi python ./ci/info_platform.py pip list From b08502f9c0ab0070b9761e9d3740203c9b165c1a Mon Sep 17 00:00:00 2001 From: Thomas VINCENT Date: Tue, 22 Sep 2026 16:05:27 +0200 Subject: [PATCH 04/15] use numpy v1 compatible functions --- src/silx/gui/plot/_utils/axis_scale.py | 2 +- src/silx/math/test/test_combo.py | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/silx/gui/plot/_utils/axis_scale.py b/src/silx/gui/plot/_utils/axis_scale.py index f8756e06ed..1250f0ac56 100644 --- a/src/silx/gui/plot/_utils/axis_scale.py +++ b/src/silx/gui/plot/_utils/axis_scale.py @@ -44,7 +44,7 @@ def apply(axisScale: AxisScaleType, value: float | ArrayLike) -> float | numpy.n scaled[~numpy.isfinite(scaled)] = numpy.nan return scaled elif axisScale == "asinh": - return numpy.asinh(value) + return numpy.arcsinh(value) else: raise ValueError(f"Unsupported axis scale: {axisScale}") diff --git a/src/silx/math/test/test_combo.py b/src/silx/math/test/test_combo.py index 4bb5a71119..dba6a88048 100644 --- a/src/silx/math/test/test_combo.py +++ b/src/silx/math/test/test_combo.py @@ -216,7 +216,7 @@ def np_mean_std(img, mask=None, dummy=None, delta_dummy=None): fimg = img.astype(numpy.float64) fimg[mask] = numpy.nan mean = numpy.nanmean(fimg) - std = numpy.nanstd(fimg, mean=mean) + std = numpy.nanstd(fimg) return mean, std From 253772dd1859d4be5c0dc650790988fd2e56409c Mon Sep 17 00:00:00 2001 From: Thomas VINCENT Date: Tue, 22 Sep 2026 16:05:40 +0200 Subject: [PATCH 05/15] skip test if h5pyd is not available --- src/silx/io/test/test_utils.py | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/silx/io/test/test_utils.py b/src/silx/io/test/test_utils.py index 1e0143abe9..57a64a834f 100644 --- a/src/silx/io/test/test_utils.py +++ b/src/silx/io/test/test_utils.py @@ -29,6 +29,8 @@ import tempfile import unittest +import pytest + from .. import utils from ..._version import calc_hexversion import silx.io.url @@ -1142,6 +1144,8 @@ def test_recursive_match_commonh5(): def test_open_h5pyd(httpserver): + pytest.importorskip("h5pyd") + httpserver.check_assertions() httpserver.expect_request("/about", query_string=None).respond_with_json({}) httpserver.expect_request("/", query_string=None).respond_with_json( From 77041bf034dab3f57decccfb2c0e0a0430a35234 Mon Sep 17 00:00:00 2001 From: Thomas VINCENT Date: Tue, 22 Sep 2026 14:46:07 +0200 Subject: [PATCH 06/15] fix support of pyopengl>=4.0.0a4 and wayland --- src/silx/gui/utils/glutils/__init__.py | 33 ++++++++++++++++---------- 1 file changed, 21 insertions(+), 12 deletions(-) diff --git a/src/silx/gui/utils/glutils/__init__.py b/src/silx/gui/utils/glutils/__init__.py index 88094e2c88..a8f1e0fbe1 100644 --- a/src/silx/gui/utils/glutils/__init__.py +++ b/src/silx/gui/utils/glutils/__init__.py @@ -26,6 +26,8 @@ import os import sys import subprocess + +from packaging.version import Version from silx.gui import qt @@ -129,11 +131,15 @@ def isOpenGLAvailable( # Check pyopengl availability try: - from silx.gui._glutils import gl + import OpenGL except ImportError: return _IsOpenGLAvailableResult( - "Cannot import OpenGL wrapper: pyopengl is not installed" + "Cannot import OpenGL: pyopengl is not installed" ) + try: + from silx.gui._glutils import gl + except ImportError: + return _IsOpenGLAvailableResult("Failed to import OpenGL wrapper") # Pre checks for Qt < 5.4 if not hasattr(qt, "QOpenGLWidget"): @@ -149,15 +155,16 @@ def isOpenGLAvailable( # so this is only checked if the QApplication is already created return _IsOpenGLAvailableResult("Qt reports OpenGL not available") - # Check compatibility between Qt platform and pyopengl selected platform - qt_qpa_platform = qt.QGuiApplication.platformName() - pyopengl_platform = gl.getPlatform() - if (qt_qpa_platform == "wayland" and pyopengl_platform != "EGLPlatform") or ( - qt_qpa_platform == "xcb" and pyopengl_platform != "GLXPlatform" - ): - return _IsOpenGLAvailableResult( - f"Qt platform '{qt_qpa_platform}' is not compatible with PyOpenGL platform '{pyopengl_platform}'" - ) + if Version(OpenGL.__version__) < Version("4.0.0a4"): + # Check compatibility between Qt platform and pyopengl selected platform + qt_qpa_platform = qt.QGuiApplication.platformName() + pyopengl_platform = gl.getPlatform() + if (qt_qpa_platform == "wayland" and pyopengl_platform != "EGLPlatform") or ( + qt_qpa_platform == "xcb" and pyopengl_platform != "GLXPlatform" + ): + return _IsOpenGLAvailableResult( + f"Qt platform '{qt_qpa_platform}' is not compatible with PyOpenGL platform '{pyopengl_platform}'" + ) keyCache = version, shareOpenGLContexts if keyCache in _runtimeCheckCache: # Use cache @@ -217,10 +224,12 @@ def paintGL(self): qt.QCoreApplication.setAttribute(qt.Qt.AA_ShareOpenGLContexts) app = qt.QApplication([]) window = qt.QMainWindow( - flags=qt.Qt.Popup + flags=qt.Qt.Window | qt.Qt.FramelessWindowHint | qt.Qt.NoDropShadowWindowHint | qt.Qt.WindowStaysOnTopHint + | qt.Qt.WindowTransparentForInput + | qt.Qt.WindowDoesNotAcceptFocus ) window.setAttribute(qt.Qt.WA_ShowWithoutActivating) window.move(0, 0) From d8ff703ef0df116f220609c7a9792fa466d37e9d Mon Sep 17 00:00:00 2001 From: Thomas VINCENT Date: Wed, 23 Sep 2026 09:11:30 +0200 Subject: [PATCH 07/15] remove try/except around lazy import --- src/silx/gui/utils/glutils/__init__.py | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/src/silx/gui/utils/glutils/__init__.py b/src/silx/gui/utils/glutils/__init__.py index a8f1e0fbe1..117b0c3492 100644 --- a/src/silx/gui/utils/glutils/__init__.py +++ b/src/silx/gui/utils/glutils/__init__.py @@ -136,10 +136,7 @@ def isOpenGLAvailable( return _IsOpenGLAvailableResult( "Cannot import OpenGL: pyopengl is not installed" ) - try: - from silx.gui._glutils import gl - except ImportError: - return _IsOpenGLAvailableResult("Failed to import OpenGL wrapper") + from silx.gui._glutils import gl # Pre checks for Qt < 5.4 if not hasattr(qt, "QOpenGLWidget"): From f1b032e7f78e810dddd6bf5a60da083adbcb261b Mon Sep 17 00:00:00 2001 From: Thomas VINCENT Date: Wed, 23 Sep 2026 11:41:22 +0200 Subject: [PATCH 08/15] use Qtool instead of QWindow or QPopup to work with wayland --- src/silx/gui/utils/glutils/__init__.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/silx/gui/utils/glutils/__init__.py b/src/silx/gui/utils/glutils/__init__.py index 117b0c3492..930876d5c9 100644 --- a/src/silx/gui/utils/glutils/__init__.py +++ b/src/silx/gui/utils/glutils/__init__.py @@ -221,7 +221,7 @@ def paintGL(self): qt.QCoreApplication.setAttribute(qt.Qt.AA_ShareOpenGLContexts) app = qt.QApplication([]) window = qt.QMainWindow( - flags=qt.Qt.Window + flags=qt.Qt.Tool | qt.Qt.FramelessWindowHint | qt.Qt.NoDropShadowWindowHint | qt.Qt.WindowStaysOnTopHint From be8b9776132fda72fe5dec778fad1adce0d3335d Mon Sep 17 00:00:00 2001 From: Thomas VINCENT Date: Wed, 23 Sep 2026 16:28:14 +0200 Subject: [PATCH 09/15] remove pinning of cython<3.3.0 --- ci/requirements-pinned.txt | 1 - pyproject.toml | 4 ++-- 2 files changed, 2 insertions(+), 3 deletions(-) diff --git a/ci/requirements-pinned.txt b/ci/requirements-pinned.txt index 54d7a3d9c2..8996170d01 100644 --- a/ci/requirements-pinned.txt +++ b/ci/requirements-pinned.txt @@ -2,4 +2,3 @@ --find-links http://www.silx.org/pub/wheelhouse/ # Placeholder for pinned packages used by CI -Cython==3.2.6 \ No newline at end of file diff --git a/pyproject.toml b/pyproject.toml index 68a645e364..3b0c02d64d 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -43,7 +43,7 @@ dependencies = [ build-backend = 'mesonpy' requires = [ 'meson-python', - 'cython>=3.1,<3.3', + 'cython>=3.1', ] @@ -98,7 +98,7 @@ dev = [ 'wheel', # To build wheels 'meson-python', 'ninja', - 'cython>=3.1,<3.3', + 'cython>=3.1', "tomli>=1.0.0; python_version < '3.11'", # For bootstrap.py and build_man_page.py 'ruff', # Formatting and linting 'pyinstaller>=6.0.0; sys_platform == "win32"', From 2e994dd1cf596eacc2c4979a5ae501201db1a83e Mon Sep 17 00:00:00 2001 From: Thomas VINCENT Date: Wed, 23 Sep 2026 16:23:06 +0200 Subject: [PATCH 10/15] avoid python 3.15 deprecation warning --- src/silx/utils/test/test_external_resources.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/silx/utils/test/test_external_resources.py b/src/silx/utils/test/test_external_resources.py index ffb72d9f28..3b476cfe4c 100644 --- a/src/silx/utils/test/test_external_resources.py +++ b/src/silx/utils/test/test_external_resources.py @@ -81,7 +81,7 @@ def test_download_all(self): filelist = self.resources.getdir(directory) # download file and remove it to create a json mapping file os.remove(filename) - directory_path = os.path.commonprefix(filelist) + directory_path = os.path.commonpath(filelist) # Make sure we will rmtree a dangerous path like "/" self.assertIn(self.resources.data_home, directory_path) shutil.rmtree(directory_path) From 5e575e954b0d956571baba6cc3cba009a23cabc4 Mon Sep 17 00:00:00 2001 From: Thomas VINCENT Date: Wed, 23 Sep 2026 16:39:02 +0200 Subject: [PATCH 11/15] build python 3.15 wheels in release ci, tests are disabled --- .github/workflows/release.yml | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index cce0dfd5aa..6827750cee 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -219,7 +219,7 @@ jobs: if: runner.os == 'Linux' with: platforms: all - - uses: pypa/cibuildwheel@v3.3.1 + - uses: pypa/cibuildwheel@v4.2.1 env: # Configure silx tests WITH_QT_TEST: "False" @@ -229,7 +229,7 @@ jobs: CIBW_ENVIRONMENT_PASS_LINUX: WITH_QT_TEST WITH_GL_TEST SILX_OPENCL CIBW_BUILD_VERBOSITY: 1 - CIBW_BUILD: cp310-* cp311-* cp312-* cp313-* cp314-* + CIBW_BUILD: cp310-* cp311-* cp312-* cp313-* cp314-* cp315-* CIBW_SKIP: cp310-win_arm64 *-musllinux_* CIBW_ARCHS: ${{ matrix.cibw_archs }} CIBW_BUILD_FRONTEND: "build; args: -C setup-args=-Duse_openmp=disabled" @@ -243,7 +243,8 @@ jobs: # - ARM64 windows: Wheels missing for some dependencies # - Windows python 3.14: PyOpencl wheel missing # - Linux python 3.14: PySide6 wheel requires a too recent manylinux version - CIBW_TEST_SKIP: "*-*linux_{aarch64,ppc64le,s390x} *-win_arm64 cp314-win_amd64 cp314-manylinux_x86_64" + # - Python 3.15 until all dependencies are available + CIBW_TEST_SKIP: "*-*linux_{aarch64,ppc64le,s390x} *-win_arm64 cp314-win_amd64 cp314-manylinux_x86_64 cp315-*" - uses: actions/upload-artifact@v6 with: From 9308958efda2a025de25025433ddb445e9bfb480 Mon Sep 17 00:00:00 2001 From: Thomas VINCENT Date: Fri, 25 Sep 2026 14:24:27 +0200 Subject: [PATCH 12/15] use layout args (tight_layout= is discouraged) --- src/silx/gui/plot/backends/BackendMatplotlib.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/silx/gui/plot/backends/BackendMatplotlib.py b/src/silx/gui/plot/backends/BackendMatplotlib.py index 7433eda591..4d033eea14 100755 --- a/src/silx/gui/plot/backends/BackendMatplotlib.py +++ b/src/silx/gui/plot/backends/BackendMatplotlib.py @@ -522,7 +522,7 @@ def __init__(self, plot, parent=None): self._axesDisplayed = True self.fig = Figure( - tight_layout=config._MPL_TIGHT_LAYOUT, + layout="tight" if config._MPL_TIGHT_LAYOUT else None, ) self.fig.set_facecolor("w") From c92e8c75c21aa43360b4b25b588e8eb46cae3538 Mon Sep 17 00:00:00 2001 From: Thomas VINCENT Date: Fri, 25 Sep 2026 14:25:42 +0200 Subject: [PATCH 13/15] use plot bounds instead of fig.get_window_extent to match effective plot area aspect ratio --- src/silx/gui/plot/backends/BackendMatplotlib.py | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/silx/gui/plot/backends/BackendMatplotlib.py b/src/silx/gui/plot/backends/BackendMatplotlib.py index 4d033eea14..26adcef7a0 100755 --- a/src/silx/gui/plot/backends/BackendMatplotlib.py +++ b/src/silx/gui/plot/backends/BackendMatplotlib.py @@ -1247,13 +1247,13 @@ def _setPlotBounds( if not self.isKeepDataAspectRatio(): newXRange, newYRange, newY2Range = xRange, yRange, y2Range else: - bbox = self.fig.get_window_extent() + plotWidth, plotHeight = self.getPlotBoundsInPixels()[2:] if keepDim is None: xDataRange, yDataRange, _ = self._plot.getDataRange() - keepDim = findDimToKeep(bbox.width, bbox.height, xDataRange, yDataRange) + keepDim = findDimToKeep(plotWidth, plotHeight, xDataRange, yDataRange) newXRange, newYRange, newY2Range = ensureAspectRatio( - bbox.width, - bbox.height, + plotWidth, + plotHeight, xRange, yRange, y2Range, From 5441bda9639f2fe99044b85c8494c3593a121a8f Mon Sep 17 00:00:00 2001 From: Thomas VINCENT Date: Thu, 24 Sep 2026 09:27:08 +0200 Subject: [PATCH 14/15] bump version to 3.1.3 --- src/silx/_version.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/silx/_version.py b/src/silx/_version.py index d1e03e4e09..876e9f8196 100755 --- a/src/silx/_version.py +++ b/src/silx/_version.py @@ -71,7 +71,7 @@ MAJOR = 3 MINOR = 1 -MICRO = 2 +MICRO = 3 RELEV = "final" # <16 SERIAL = 0 # <16 From bdb0ed243c825fe3a72c61b8157d54ea9bc6b7cd Mon Sep 17 00:00:00 2001 From: Thomas VINCENT Date: Thu, 24 Sep 2026 09:27:16 +0200 Subject: [PATCH 15/15] update changelog --- CHANGELOG.rst | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/CHANGELOG.rst b/CHANGELOG.rst index 0bf185c2b7..7e3fd8cff3 100644 --- a/CHANGELOG.rst +++ b/CHANGELOG.rst @@ -1,6 +1,18 @@ Release Notes ============= + +3.1.3: 2026/10/06 +----------------- + +* `silx.gui.plot.PlotWidget`: Fixed keep aspect ratio with matplotlib tight layout (`PR #4734 `_) +* `silx.gui.utils.glutils.isOpenGLAvailable`: Fixed support of `pyopengl`>=4.0.0a4 and wayland (`PR #4727 `_) +* Dependencies: + + * Added cython>=3.3.0 support (`PR #4731 `_) + * Added Python3.15 support (`PR #4732 `_) + * Fixed support of `numpy` v1 (`PR #4725 `_, `PR #4728 `_) + 3.1.2: 2026/09/03 -----------------