From aad1c737c34b2bf663017493652838a516ee7a01 Mon Sep 17 00:00:00 2001 From: Luke Campagnola Date: Thu, 28 Sep 2017 09:11:07 -0700 Subject: [PATCH 1/4] eq(): better performance by avoiding array comparison when shapes do not match --- pyqtgraph/functions.py | 16 +++++++++++++++- 1 file changed, 15 insertions(+), 1 deletion(-) diff --git a/pyqtgraph/functions.py b/pyqtgraph/functions.py index 1aed6ace..261727cb 100644 --- a/pyqtgraph/functions.py +++ b/pyqtgraph/functions.py @@ -417,7 +417,21 @@ def eq(a, b): """ if a is b: return True - + + # Avoid comparing large arrays against scalars; this is expensive and we know it should return False. + aIsArr = isinstance(a, (np.ndarray, MetaArray)) + bIsArr = isinstance(b, (np.ndarray, MetaArray)) + if (aIsArr or bIsArr) and type(a) != type(b): + return False + + # If both inputs are arrays, we can speeed up comparison if shapes / dtypes don't match + # NOTE: arrays of dissimilar type should be considered unequal even if they are numerically + # equal because they may behave differently when computed on. + if aIsArr and bIsArr and (a.shape != b.shape or a.dtype != b.dtype): + return False + + # Test for equivalence. + # If the test raises a recognized exception, then return Falase try: try: # Sometimes running catch_warnings(module=np) generates AttributeError ??? From 7c9107fa5d9954d2f59bcabf523dc2fdb77eee34 Mon Sep 17 00:00:00 2001 From: Luke Campagnola Date: Fri, 29 Sep 2017 08:45:33 -0700 Subject: [PATCH 2/4] use ndarray() strides argument to construct subarray previously this was done manually (and imperfectly) --- pyqtgraph/functions.py | 22 +++++++--------------- 1 file changed, 7 insertions(+), 15 deletions(-) diff --git a/pyqtgraph/functions.py b/pyqtgraph/functions.py index 261727cb..b38888fe 100644 --- a/pyqtgraph/functions.py +++ b/pyqtgraph/functions.py @@ -750,23 +750,15 @@ def subArray(data, offset, shape, stride): #data = data.flatten() data = data[offset:] shape = tuple(shape) - stride = tuple(stride) extraShape = data.shape[1:] - #print data.shape, offset, shape, stride - for i in range(len(shape)): - mask = (slice(None),) * i + (slice(None, shape[i] * stride[i]),) - newShape = shape[:i+1] - if i < len(shape)-1: - newShape += (stride[i],) - newShape += extraShape - #print i, mask, newShape - #print "start:\n", data.shape, data - data = data[mask] - #print "mask:\n", data.shape, data - data = data.reshape(newShape) - #print "reshape:\n", data.shape, data + + strides = list(data.strides[::-1]) + itemsize = strides[-1] + for s in stride[1::-1]: + strides.append(itemsize * s) + strides = tuple(strides[::-1]) - return data + return np.ndarray(buffer=data, shape=shape+extraShape, strides=strides, dtype=data.dtype) def transformToArray(tr): From 9ef9f73be5b5cdb639931a4f8e68dbfe98fdbbea Mon Sep 17 00:00:00 2001 From: Luke Campagnola Date: Wed, 4 Oct 2017 09:35:57 -0700 Subject: [PATCH 3/4] minor import and test corrections --- pyqtgraph/functions.py | 2 +- pyqtgraph/tests/test_functions.py | 12 ++++++------ 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/pyqtgraph/functions.py b/pyqtgraph/functions.py index b38888fe..8ef57742 100644 --- a/pyqtgraph/functions.py +++ b/pyqtgraph/functions.py @@ -15,7 +15,7 @@ from .python2_3 import asUnicode, basestring from .Qt import QtGui, QtCore, USE_PYSIDE from . import getConfigOption, setConfigOptions from . import debug - +from .metaarray import MetaArray Colors = { diff --git a/pyqtgraph/tests/test_functions.py b/pyqtgraph/tests/test_functions.py index eff56635..68f3dc24 100644 --- a/pyqtgraph/tests/test_functions.py +++ b/pyqtgraph/tests/test_functions.py @@ -344,14 +344,14 @@ def test_eq(): a2 = a1 + 1 a3 = a2.astype('int') a4 = np.empty((0, 20)) - assert not eq(a1, a2) - assert not eq(a1, a3) - assert not eq(a1, a4) + assert not eq(a1, a2) # same shape/dtype, different values + assert not eq(a1, a3) # same shape, different dtype and values + assert not eq(a1, a4) # different shape (note: np.all gives True if one array has size 0) - assert eq(a2, a3) - assert not eq(a2, a4) + assert not eq(a2, a3) # same values, but different dtype + assert not eq(a2, a4) # different shape - assert not eq(a3, a4) + assert not eq(a3, a4) # different shape and dtype assert eq(a4, a4.copy()) assert not eq(a4, a4.T) From 0c28de5fd80f73394664e0eba888825c6714ad25 Mon Sep 17 00:00:00 2001 From: Luke Campagnola Date: Wed, 4 Oct 2017 10:24:34 -0700 Subject: [PATCH 4/4] Fix subArray when input data is discontiguous --- pyqtgraph/functions.py | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/pyqtgraph/functions.py b/pyqtgraph/functions.py index 8ef57742..7ad603f7 100644 --- a/pyqtgraph/functions.py +++ b/pyqtgraph/functions.py @@ -747,8 +747,7 @@ def subArray(data, offset, shape, stride): the input in the example above to have shape (10, 7) would cause the output to have shape (2, 3, 7). """ - #data = data.flatten() - data = data[offset:] + data = np.ascontiguousarray(data)[offset:] shape = tuple(shape) extraShape = data.shape[1:]