useCupy option should be settable after ImageItem init (#1749)
* do not cache the cupy so the config option can be set later * getCupy will always return None if the option is not set * test of failing behavior * divorce skip from option; restore option after test
This commit is contained in:
parent
7dc4823cc6
commit
85e2574230
@ -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]
|
||||
|
||||
|
@ -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')
|
||||
|
@ -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")
|
||||
|
@ -1,8 +1,10 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
import os
|
||||
from warnings import warn
|
||||
|
||||
from .. import getConfigOption
|
||||
|
||||
|
||||
def getCupy():
|
||||
if getConfigOption("useCupy"):
|
||||
try:
|
||||
|
Loading…
Reference in New Issue
Block a user