_fill_nonfinite() -> _compute_backfill_indices()
this allows us to defer the backfilling
This commit is contained in:
parent
679c1002c1
commit
44e32f00c7
@ -1870,7 +1870,7 @@ def downsample(data, n, axis=0, xvals='subsample'):
|
|||||||
return MetaArray(d2, info=info)
|
return MetaArray(d2, info=info)
|
||||||
|
|
||||||
|
|
||||||
def _fill_nonfinite(arr, isfinite):
|
def _compute_backfill_indices(isfinite):
|
||||||
# the presence of inf/nans result in an empty QPainterPath being generated
|
# the presence of inf/nans result in an empty QPainterPath being generated
|
||||||
# this behavior started in Qt 5.12.3 and was introduced in this commit
|
# this behavior started in Qt 5.12.3 and was introduced in this commit
|
||||||
# https://github.com/qt/qtbase/commit/c04bd30de072793faee5166cff866a4c4e0a9dd7
|
# https://github.com/qt/qtbase/commit/c04bd30de072793faee5166cff866a4c4e0a9dd7
|
||||||
@ -1878,14 +1878,16 @@ def _fill_nonfinite(arr, isfinite):
|
|||||||
|
|
||||||
# credit: Divakar https://stackoverflow.com/a/41191127/643629
|
# credit: Divakar https://stackoverflow.com/a/41191127/643629
|
||||||
mask = ~isfinite
|
mask = ~isfinite
|
||||||
idx = np.arange(len(arr))
|
idx = np.arange(len(isfinite))
|
||||||
idx[mask] = -1
|
idx[mask] = -1
|
||||||
np.maximum.accumulate(idx, out=idx)
|
np.maximum.accumulate(idx, out=idx)
|
||||||
first = np.searchsorted(idx, 0)
|
first = np.searchsorted(idx, 0)
|
||||||
if first < len(arr):
|
if first < len(isfinite):
|
||||||
# Replace all non-finite entries from beginning of arr with the first finite one
|
# Replace all non-finite entries from beginning of arr with the first finite one
|
||||||
idx[:first] = first
|
idx[:first] = first
|
||||||
arr[:] = arr[:][idx]
|
return idx
|
||||||
|
else:
|
||||||
|
return None
|
||||||
|
|
||||||
|
|
||||||
def _arrayToQPath_all(x, y, finiteCheck):
|
def _arrayToQPath_all(x, y, finiteCheck):
|
||||||
@ -1905,26 +1907,29 @@ def _arrayToQPath_all(x, y, finiteCheck):
|
|||||||
# too few chunks, batching would be a pessimization
|
# too few chunks, batching would be a pessimization
|
||||||
poly = create_qpolygonf(n)
|
poly = create_qpolygonf(n)
|
||||||
arr = ndarray_from_qpolygonf(poly)
|
arr = ndarray_from_qpolygonf(poly)
|
||||||
|
|
||||||
|
backfill_idx = None
|
||||||
|
if finiteCheck and not all_isfinite:
|
||||||
|
backfill_idx = _compute_backfill_indices(isfinite)
|
||||||
|
|
||||||
|
if backfill_idx is None:
|
||||||
arr[:, 0] = x
|
arr[:, 0] = x
|
||||||
arr[:, 1] = y
|
arr[:, 1] = y
|
||||||
|
else:
|
||||||
if finiteCheck and not all_isfinite:
|
arr[:, 0] = x[backfill_idx]
|
||||||
_fill_nonfinite(arr, isfinite)
|
arr[:, 1] = y[backfill_idx]
|
||||||
|
|
||||||
path = QtGui.QPainterPath()
|
path = QtGui.QPainterPath()
|
||||||
|
if hasattr(path, 'reserve'): # Qt 5.13
|
||||||
|
path.reserve(n)
|
||||||
path.addPolygon(poly)
|
path.addPolygon(poly)
|
||||||
return path
|
return path
|
||||||
|
|
||||||
|
backfill_idx = None
|
||||||
if finiteCheck and not all_isfinite:
|
if finiteCheck and not all_isfinite:
|
||||||
# this section here is inefficient as a full copy of the input data is made.
|
backfill_idx = _compute_backfill_indices(isfinite)
|
||||||
arr = np.column_stack((x, y))
|
|
||||||
_fill_nonfinite(arr, isfinite)
|
|
||||||
x = arr[:, 0]
|
|
||||||
y = arr[:, 1]
|
|
||||||
|
|
||||||
# at this point, we have:
|
# at this point, we have numchunks >= minchunks
|
||||||
# 1) numchunks >= minchunks
|
|
||||||
# 2) x, y filled with finite only
|
|
||||||
|
|
||||||
path = QtGui.QPainterPath()
|
path = QtGui.QPainterPath()
|
||||||
if hasattr(path, 'reserve'): # Qt 5.13
|
if hasattr(path, 'reserve'): # Qt 5.13
|
||||||
@ -1932,17 +1937,21 @@ def _arrayToQPath_all(x, y, finiteCheck):
|
|||||||
subpoly = QtGui.QPolygonF()
|
subpoly = QtGui.QPolygonF()
|
||||||
subpath = None
|
subpath = None
|
||||||
for idx in range(numchunks):
|
for idx in range(numchunks):
|
||||||
xchunk = x[idx*chunksize:(idx+1)*chunksize]
|
sl = slice(idx*chunksize, min((idx+1)*chunksize, n))
|
||||||
ychunk = y[idx*chunksize:(idx+1)*chunksize]
|
currsize = sl.stop - sl.start
|
||||||
currsize = xchunk.size
|
|
||||||
if currsize != subpoly.size():
|
if currsize != subpoly.size():
|
||||||
if hasattr(subpoly, 'resize'):
|
if hasattr(subpoly, 'resize'):
|
||||||
subpoly.resize(currsize)
|
subpoly.resize(currsize)
|
||||||
else:
|
else:
|
||||||
subpoly.fill(QtCore.QPointF(), currsize)
|
subpoly.fill(QtCore.QPointF(), currsize)
|
||||||
subarr = ndarray_from_qpolygonf(subpoly)
|
subarr = ndarray_from_qpolygonf(subpoly)
|
||||||
subarr[:, 0] = xchunk
|
if backfill_idx is None:
|
||||||
subarr[:, 1] = ychunk
|
subarr[:, 0] = x[sl]
|
||||||
|
subarr[:, 1] = y[sl]
|
||||||
|
else:
|
||||||
|
bfv = backfill_idx[sl] # view
|
||||||
|
subarr[:, 0] = x[bfv]
|
||||||
|
subarr[:, 1] = y[bfv]
|
||||||
if subpath is None:
|
if subpath is None:
|
||||||
subpath = QtGui.QPainterPath()
|
subpath = QtGui.QPainterPath()
|
||||||
subpath.addPolygon(subpoly)
|
subpath.addPolygon(subpoly)
|
||||||
@ -2116,16 +2125,20 @@ def arrayToQPath(x, y, connect='all', finiteCheck=True):
|
|||||||
arr = np.frombuffer(backstore, dtype=[('c', '>i4'), ('x', '>f8'), ('y', '>f8')],
|
arr = np.frombuffer(backstore, dtype=[('c', '>i4'), ('x', '>f8'), ('y', '>f8')],
|
||||||
count=n, offset=4)
|
count=n, offset=4)
|
||||||
|
|
||||||
# Fill array with vertex values
|
backfill_idx = None
|
||||||
arr['x'] = x
|
|
||||||
arr['y'] = y
|
|
||||||
|
|
||||||
if finiteCheck:
|
if finiteCheck:
|
||||||
if isfinite is None:
|
if isfinite is None:
|
||||||
isfinite = np.isfinite(x) & np.isfinite(y)
|
isfinite = np.isfinite(x) & np.isfinite(y)
|
||||||
all_isfinite = np.all(isfinite)
|
all_isfinite = np.all(isfinite)
|
||||||
if not all_isfinite:
|
if not all_isfinite:
|
||||||
_fill_nonfinite(arr, isfinite)
|
backfill_idx = _compute_backfill_indices(isfinite)
|
||||||
|
|
||||||
|
if backfill_idx is None:
|
||||||
|
arr['x'] = x
|
||||||
|
arr['y'] = y
|
||||||
|
else:
|
||||||
|
arr['x'] = x[backfill_idx]
|
||||||
|
arr['y'] = y[backfill_idx]
|
||||||
|
|
||||||
# decide which points are connected by lines
|
# decide which points are connected by lines
|
||||||
if connect == 'pairs':
|
if connect == 'pairs':
|
||||||
|
Loading…
Reference in New Issue
Block a user