pyqtgraph/examples/test_examples.py
Martin Chase f2b4a15b2d
Performance enhancement: use CUDA in ImageItem (#1466)
* Add CLI args to video speed test for easier / automated benchmarking

* use a buffer-qimage so we can avoid allocing so much

this should improve performance under windows

* playing with numba

* oh, mins/maxes in the other order

* maybe put the cupy in here and see what happens

* pre-alloc for gpu and cpu

* handle possibility of not having cupy

* no numba in this branch

* organize imports

* name them after their use, not their expected device

* cupy.take does not support clip mode, so do it explicitly

* add CUDA option to the VideoSpeedTest

* rename private attr xp to _xp

* handle resizes at the last moment

* cupy is less accepting of lists as args

* or somehow range isn't allowed? what histogram is this?

* construct the array with python objects

* get the python value right away

* put LUT into cupy if needed

* docstring about cuda toolkit version

* better handling and display of missing cuda lib

* lint

* import need

* handle switching between cupy and numpy in a single ImageItem

* only use xp when necessary

we can now depend on numpy >= 1.17, which means __array_function__-implementing cupy can
seamlessly pass into numpy functions. the remaining uses of xp are for our functions which
need to allocate new data structures, an operation that has to be substrate-specific.

remove empty_cupy; just check if the import succeeded, instead.

* use an option to control use of cupy

* convert cupy.ceil array to int for easier mathing

* RawImageWidget gets to use the getCupy function now, too

* raise error to calm linters; rename for clarity

* Add Generated Template Files

* document things better

* cruft removal

* warnings to communicate when cupy is expected but somehow broken

* playing with settings to suss out timeout

* playing with more stuff to suss out timeout

* replace with empty list

* skip test_ExampleApp on linux+pyside2 only

Co-authored-by: Luke Campagnola <luke.campagnola@gmail.com>
Co-authored-by: Ogi Moore <ognyan.moore@gmail.com>
2021-01-19 21:26:24 -08:00

264 lines
8.9 KiB
Python

# -*- coding: utf-8 -*-
from __future__ import print_function, division, absolute_import
from collections import namedtuple
from pyqtgraph import Qt
from pyqtgraph.python2_3 import basestring
from .ExampleApp import examples
import errno
import importlib
import itertools
import pytest
import os, sys
import platform
import subprocess
import time
if __name__ == "__main__" and (__package__ is None or __package__==''):
parent_dir = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
sys.path.insert(0, parent_dir)
import examples
__package__ = "examples"
def buildFileList(examples, files=None):
if files is None:
files = [("Example App", "test_ExampleApp.py")]
for key, val in examples.items():
if isinstance(val, basestring):
files.append((key,val))
else:
buildFileList(val, files)
return files
path = os.path.abspath(os.path.dirname(__file__))
files = sorted(set(buildFileList(examples)))
frontends = {
Qt.PYQT4: False,
Qt.PYQT5: False,
Qt.PYSIDE: False,
Qt.PYSIDE2: False
}
# sort out which of the front ends are available
for frontend in frontends.keys():
try:
importlib.import_module(frontend)
frontends[frontend] = True
except ImportError:
pass
installedFrontends = sorted([
frontend for frontend, isPresent in frontends.items() if isPresent
])
exceptionCondition = namedtuple("exceptionCondition", ["condition", "reason"])
conditionalExamples = {
"test_ExampleApp.py": exceptionCondition(
not(platform.system() == "Linux" and frontends[Qt.PYSIDE2]),
reason="Unexplained, intermittent segfault and subsequent timeout on CI"
),
"hdf5.py": exceptionCondition(
False,
reason="Example requires user interaction"
),
"RemoteSpeedTest.py": exceptionCondition(
False,
reason="Test is being problematic on CI machines"
),
"optics_demos.py": exceptionCondition(
not frontends[Qt.PYSIDE],
reason=(
"Test fails due to PySide bug: ",
"https://bugreports.qt.io/browse/PYSIDE-671"
)
),
'GLVolumeItem.py': exceptionCondition(
not(platform.system() == "Darwin" and
tuple(map(int, platform.mac_ver()[0].split("."))) >= (10, 16) and
(sys.version_info <= (3, 8, 7) or
(sys.version_info >= (3, 9) and sys.version_info < (3, 9, 1)))),
reason=(
"pyopenGL cannot find openGL libray on big sur: "
"https://github.com/python/cpython/pull/21241"
)
),
'GLIsosurface.py': exceptionCondition(
not(platform.system() == "Darwin" and
tuple(map(int, platform.mac_ver()[0].split("."))) >= (10, 16) and
(sys.version_info <= (3, 8, 7) or
(sys.version_info >= (3, 9) and sys.version_info < (3, 9, 1)))),
reason=(
"pyopenGL cannot find openGL libray on big sur: "
"https://github.com/python/cpython/pull/21241"
)
),
'GLSurfacePlot.py': exceptionCondition(
not(platform.system() == "Darwin" and
tuple(map(int, platform.mac_ver()[0].split("."))) >= (10, 16) and
(sys.version_info <= (3, 8, 7) or
(sys.version_info >= (3, 9) and sys.version_info < (3, 9, 1)))),
reason=(
"pyopenGL cannot find openGL libray on big sur: "
"https://github.com/python/cpython/pull/21241"
)
),
'GLScatterPlotItem.py': exceptionCondition(
not(platform.system() == "Darwin" and
tuple(map(int, platform.mac_ver()[0].split("."))) >= (10, 16) and
(sys.version_info <= (3, 8, 7) or
(sys.version_info >= (3, 9) and sys.version_info < (3, 9, 1)))),
reason=(
"pyopenGL cannot find openGL libray on big sur: "
"https://github.com/python/cpython/pull/21241"
)
),
'GLshaders.py': exceptionCondition(
not(platform.system() == "Darwin" and
tuple(map(int, platform.mac_ver()[0].split("."))) >= (10, 16) and
(sys.version_info <= (3, 8, 7) or
(sys.version_info >= (3, 9) and sys.version_info < (3, 9, 1)))),
reason=(
"pyopenGL cannot find openGL libray on big sur: "
"https://github.com/python/cpython/pull/21241"
)
),
'GLLinePlotItem.py': exceptionCondition(
not(platform.system() == "Darwin" and
tuple(map(int, platform.mac_ver()[0].split("."))) >= (10, 16) and
(sys.version_info <= (3, 8, 7) or
(sys.version_info >= (3, 9) and sys.version_info < (3, 9, 1)))),
reason=(
"pyopenGL cannot find openGL libray on big sur: "
"https://github.com/python/cpython/pull/21241"
)
),
'GLMeshItem.py': exceptionCondition(
not(platform.system() == "Darwin" and
tuple(map(int, platform.mac_ver()[0].split("."))) >= (10, 16) and
(sys.version_info <= (3, 8, 7) or
(sys.version_info >= (3, 9) and sys.version_info < (3, 9, 1)))),
reason=(
"pyopenGL cannot find openGL libray on big sur: "
"https://github.com/python/cpython/pull/21241"
)
),
'GLImageItem.py': exceptionCondition(
not(platform.system() == "Darwin" and
tuple(map(int, platform.mac_ver()[0].split("."))) >= (10, 16) and
(sys.version_info <= (3, 8, 7) or
(sys.version_info >= (3, 9) and sys.version_info < (3, 9, 1)))),
reason=(
"pyopenGL cannot find openGL libray on big sur: "
"https://github.com/python/cpython/pull/21241"
)
)
}
@pytest.mark.skipif(
Qt.QT_LIB == "PySide2"
and tuple(map(int, Qt.PySide2.__version__.split("."))) >= (5, 14)
and tuple(map(int, Qt.PySide2.__version__.split("."))) < (5, 14, 2, 2),
reason="new PySide2 doesn't have loadUi functionality"
)
@pytest.mark.parametrize(
"frontend, f",
[
pytest.param(
frontend,
f,
marks=pytest.mark.skipif(
conditionalExamples[f[1]].condition is False,
reason=conditionalExamples[f[1]].reason
) if f[1] in conditionalExamples.keys() else (),
)
for frontend, f, in itertools.product(installedFrontends, files)
],
ids = [
" {} - {} ".format(f[1], frontend)
for frontend, f in itertools.product(
installedFrontends,
files
)
]
)
def testExamples(frontend, f, graphicsSystem=None):
# runExampleFile(f[0], f[1], sys.executable, frontend)
name, file = f
global path
fn = os.path.join(path, file)
os.chdir(path)
sys.stdout.write("{} ".format(name))
sys.stdout.flush()
import1 = "import %s" % frontend if frontend != '' else ''
import2 = os.path.splitext(os.path.split(fn)[1])[0]
graphicsSystem = (
'' if graphicsSystem is None else "pg.QtGui.QApplication.setGraphicsSystem('%s')" % graphicsSystem
)
code = """
try:
%s
import initExample
import pyqtgraph as pg
%s
import %s
import sys
print("test complete")
sys.stdout.flush()
import time
while True: ## run a little event loop
pg.QtGui.QApplication.processEvents()
time.sleep(0.01)
except:
print("test failed")
raise
""" % (import1, graphicsSystem, import2)
if sys.platform.startswith('win'):
process = subprocess.Popen([sys.executable],
stdin=subprocess.PIPE,
stderr=subprocess.PIPE,
stdout=subprocess.PIPE)
else:
process = subprocess.Popen(['exec %s -i' % (sys.executable)],
shell=True,
stdin=subprocess.PIPE,
stderr=subprocess.PIPE,
stdout=subprocess.PIPE)
process.stdin.write(code.encode('UTF-8'))
process.stdin.close()
output = ''
fail = False
while True:
try:
c = process.stdout.read(1).decode()
except IOError as err:
if err.errno == errno.EINTR:
# Interrupted system call; just try again.
c = ''
else:
raise
output += c
if output.endswith('test complete'):
break
if output.endswith('test failed'):
fail = True
break
time.sleep(1)
process.kill()
#res = process.communicate()
res = (process.stdout.read(), process.stderr.read())
if (fail or
'exception' in res[1].decode().lower() or
'error' in res[1].decode().lower()):
print(res[0].decode())
print(res[1].decode())
pytest.fail("{}\n{}\nFailed {} Example Test Located in {} "
.format(res[0].decode(), res[1].decode(), name, file),
pytrace=False)
if __name__ == "__main__":
pytest.cmdline.main()