diff --git a/pyqtgraph/graphicsItems/ImageItem.py b/pyqtgraph/graphicsItems/ImageItem.py index 9d9efa97..107334bf 100644 --- a/pyqtgraph/graphicsItems/ImageItem.py +++ b/pyqtgraph/graphicsItems/ImageItem.py @@ -60,7 +60,6 @@ class ImageItem(GraphicsObject): self._displayBuffer = None self._renderRequired = True self._unrenderable = False - self._cupy = getCupy() self._xp = None # either numpy or cupy, to match the image data self._defferedLevels = None @@ -216,7 +215,7 @@ class ImageItem(GraphicsObject): def _buildQImageBuffer(self, shape): self._displayBuffer = numpy.empty(shape[:2] + (4,), dtype=numpy.ubyte) - if self._xp == self._cupy: + if self._xp == getCupy(): self._processingBuffer = self._xp.empty(shape[:2] + (4,), dtype=self._xp.ubyte) else: self._processingBuffer = self._displayBuffer @@ -273,7 +272,8 @@ class ImageItem(GraphicsObject): return else: old_xp = self._xp - self._xp = self._cupy.get_array_module(image) if self._cupy else numpy + cp = getCupy() + self._xp = cp.get_array_module(image) if cp else numpy gotNewData = True processingSubstrateChanged = old_xp != self._xp if processingSubstrateChanged: @@ -449,7 +449,7 @@ class ImageItem(GraphicsObject): self._buildQImageBuffer(image.shape) fn.makeARGB(image, lut=lut, levels=levels, output=self._processingBuffer) - if self._xp == self._cupy: + if self._xp == getCupy(): self._processingBuffer.get(out=self._displayBuffer) self._renderRequired = False self._unrenderable = False @@ -535,22 +535,23 @@ class ImageItem(GraphicsObject): kwds['bins'] = bins + cp = getCupy() if perChannel: hist = [] for i in range(stepData.shape[-1]): stepChan = stepData[..., i] stepChan = stepChan[self._xp.isfinite(stepChan)] h = self._xp.histogram(stepChan, **kwds) - if self._cupy: - hist.append((self._cupy.asnumpy(h[1][:-1]), self._cupy.asnumpy(h[0]))) + if cp: + hist.append((cp.asnumpy(h[1][:-1]), cp.asnumpy(h[0]))) else: hist.append((h[1][:-1], h[0])) return hist else: stepData = stepData[self._xp.isfinite(stepData)] hist = self._xp.histogram(stepData, **kwds) - if self._cupy: - return self._cupy.asnumpy(hist[1][:-1]), self._cupy.asnumpy(hist[0]) + if cp: + return cp.asnumpy(hist[1][:-1]), cp.asnumpy(hist[0]) else: return hist[1][:-1], hist[0] diff --git a/pyqtgraph/graphicsItems/tests/test_ImageItem.py b/pyqtgraph/graphicsItems/tests/test_ImageItem.py index 76fa0510..b69ec9c1 100644 --- a/pyqtgraph/graphicsItems/tests/test_ImageItem.py +++ b/pyqtgraph/graphicsItems/tests/test_ImageItem.py @@ -1,15 +1,39 @@ +# -*- coding: utf-8 -*- import time import pytest + from pyqtgraph.Qt import QtCore, QtGui, QtTest import numpy as np import pyqtgraph as pg from pyqtgraph.tests import assertImageApproved, TransposedImageItem - +try: + import cupy +except ImportError: + cupy = None app = pg.mkQApp() +@pytest.mark.skipif(cupy is None, reason="CuPy unavailable to test") +def test_useCupy_can_be_set_after_init(): + prev_setting = pg.getConfigOption("useCupy") + try: + pg.setConfigOption("useCupy", False) + w = pg.GraphicsLayoutWidget() + w.show() + view = pg.ViewBox() + w.setCentralWidget(view) + w.resize(200, 200) + img = cupy.random.randint(0, 255, size=(32, 32)).astype(cupy.uint8) + ii = pg.ImageItem() + view.addItem(ii) + pg.setConfigOption("useCupy", True) + ii.setImage(img) + w.hide() + finally: + pg.setConfigOption("useCupy", prev_setting) + + def test_ImageItem(transpose=False): - w = pg.GraphicsLayoutWidget() w.show() view = pg.ViewBox() @@ -123,6 +147,7 @@ def test_ImageItem(transpose=False): w.hide() + def test_ImageItem_axisorder(): # All image tests pass again using the opposite axis order origMode = pg.getConfigOption('imageAxisOrder') diff --git a/pyqtgraph/tests/test_makeARGB.py b/pyqtgraph/tests/test_makeARGB.py index 73b29f1b..e11938ae 100644 --- a/pyqtgraph/tests/test_makeARGB.py +++ b/pyqtgraph/tests/test_makeARGB.py @@ -6,6 +6,10 @@ from typing import Dict, Any, Union, Type from pyqtgraph import getCupy, getConfigOption, setConfigOption from pyqtgraph.functions import makeARGB as real_makeARGB +try: + import cupy +except ImportError: + cupy = None IN_2D_INT8 = np.array([[173, 48, 122, 41], [210, 192, 0, 5], [104, 56, 102, 115], [78, 19, 255, 6]], dtype=np.uint8) IN_RGB_INT8 = np.array( @@ -4290,30 +4294,36 @@ def test_makeARGB_against_generated_references(): _do_something_for_every_combo(assert_correct) -@pytest.mark.skipif(getCupy() is None, reason="CuPy unavailable to test") +@pytest.mark.skipif(cupy is None, reason="CuPy unavailable to test") def test_cupy_makeARGB_against_generated_references(): - setConfigOption("useCupy", True) - cp = getCupy() - def assert_cupy_correct(data, key, levels, lut, scale, use_rgba): - data = cp.asarray(data) - if lut is not None: - lut = cp.asarray(lut) - expectation = EXPECTED_OUTPUTS[key] - if isinstance(expectation, type) and issubclass(expectation, Exception): - try: - _makeARGB(data, lut=lut, levels=levels, scale=scale, useRGBA=use_rgba) - except Exception as e: - assert expectation == type(e) - else: - assert False, f"makeARGB({key!r}) was supposed to raise {expectation} but didn't raise anything." - else: - expectation = cp.asarray(expectation) - output, alpha = _makeARGB(data, lut=lut, levels=levels, scale=scale, useRGBA=use_rgba) - assert ( - output == expectation - ).all(), f"Incorrect _makeARGB({key!r}) output! Expected:\n{expectation!r}\n Got:\n{output!r}" + prev_setting = getConfigOption("useCupy") + try: + setConfigOption("useCupy", True) - _do_something_for_every_combo(assert_cupy_correct) + cupy = getCupy() + + def assert_cupy_correct(data, key, levels, lut, scale, use_rgba): + data = cupy.asarray(data) + if lut is not None: + lut = cupy.asarray(lut) + expectation = EXPECTED_OUTPUTS[key] + if isinstance(expectation, type) and issubclass(expectation, Exception): + try: + _makeARGB(data, lut=lut, levels=levels, scale=scale, useRGBA=use_rgba) + except Exception as e: + assert expectation == type(e) + else: + assert False, f"makeARGB({key!r}) was supposed to raise {expectation} but didn't raise anything." + else: + expectation = cupy.asarray(expectation) + output, alpha = _makeARGB(data, lut=lut, levels=levels, scale=scale, useRGBA=use_rgba) + assert ( + output == expectation + ).all(), f"Incorrect _makeARGB({key!r}) output! Expected:\n{expectation!r}\n Got:\n{output!r}" + + _do_something_for_every_combo(assert_cupy_correct) + finally: + setConfigOption("useCupy", prev_setting) @pytest.mark.filterwarnings("ignore:invalid value encountered") diff --git a/pyqtgraph/util/cupy_helper.py b/pyqtgraph/util/cupy_helper.py index fadfaebe..40059c8f 100644 --- a/pyqtgraph/util/cupy_helper.py +++ b/pyqtgraph/util/cupy_helper.py @@ -1,8 +1,10 @@ +# -*- coding: utf-8 -*- import os from warnings import warn from .. import getConfigOption + def getCupy(): if getConfigOption("useCupy"): try: