_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)
|
||||
|
||||
|
||||
def _fill_nonfinite(arr, isfinite):
|
||||
def _compute_backfill_indices(isfinite):
|
||||
# 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
|
||||
# https://github.com/qt/qtbase/commit/c04bd30de072793faee5166cff866a4c4e0a9dd7
|
||||
@ -1878,14 +1878,16 @@ def _fill_nonfinite(arr, isfinite):
|
||||
|
||||
# credit: Divakar https://stackoverflow.com/a/41191127/643629
|
||||
mask = ~isfinite
|
||||
idx = np.arange(len(arr))
|
||||
idx = np.arange(len(isfinite))
|
||||
idx[mask] = -1
|
||||
np.maximum.accumulate(idx, out=idx)
|
||||
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
|
||||
idx[:first] = first
|
||||
arr[:] = arr[:][idx]
|
||||
return idx
|
||||
else:
|
||||
return None
|
||||
|
||||
|
||||
def _arrayToQPath_all(x, y, finiteCheck):
|
||||
@ -1905,26 +1907,29 @@ def _arrayToQPath_all(x, y, finiteCheck):
|
||||
# too few chunks, batching would be a pessimization
|
||||
poly = create_qpolygonf(n)
|
||||
arr = ndarray_from_qpolygonf(poly)
|
||||
arr[:, 0] = x
|
||||
arr[:, 1] = y
|
||||
|
||||
backfill_idx = None
|
||||
if finiteCheck and not all_isfinite:
|
||||
_fill_nonfinite(arr, isfinite)
|
||||
backfill_idx = _compute_backfill_indices(isfinite)
|
||||
|
||||
if backfill_idx is None:
|
||||
arr[:, 0] = x
|
||||
arr[:, 1] = y
|
||||
else:
|
||||
arr[:, 0] = x[backfill_idx]
|
||||
arr[:, 1] = y[backfill_idx]
|
||||
|
||||
path = QtGui.QPainterPath()
|
||||
if hasattr(path, 'reserve'): # Qt 5.13
|
||||
path.reserve(n)
|
||||
path.addPolygon(poly)
|
||||
return path
|
||||
|
||||
backfill_idx = None
|
||||
if finiteCheck and not all_isfinite:
|
||||
# this section here is inefficient as a full copy of the input data is made.
|
||||
arr = np.column_stack((x, y))
|
||||
_fill_nonfinite(arr, isfinite)
|
||||
x = arr[:, 0]
|
||||
y = arr[:, 1]
|
||||
backfill_idx = _compute_backfill_indices(isfinite)
|
||||
|
||||
# at this point, we have:
|
||||
# 1) numchunks >= minchunks
|
||||
# 2) x, y filled with finite only
|
||||
# at this point, we have numchunks >= minchunks
|
||||
|
||||
path = QtGui.QPainterPath()
|
||||
if hasattr(path, 'reserve'): # Qt 5.13
|
||||
@ -1932,17 +1937,21 @@ def _arrayToQPath_all(x, y, finiteCheck):
|
||||
subpoly = QtGui.QPolygonF()
|
||||
subpath = None
|
||||
for idx in range(numchunks):
|
||||
xchunk = x[idx*chunksize:(idx+1)*chunksize]
|
||||
ychunk = y[idx*chunksize:(idx+1)*chunksize]
|
||||
currsize = xchunk.size
|
||||
sl = slice(idx*chunksize, min((idx+1)*chunksize, n))
|
||||
currsize = sl.stop - sl.start
|
||||
if currsize != subpoly.size():
|
||||
if hasattr(subpoly, 'resize'):
|
||||
subpoly.resize(currsize)
|
||||
else:
|
||||
subpoly.fill(QtCore.QPointF(), currsize)
|
||||
subarr = ndarray_from_qpolygonf(subpoly)
|
||||
subarr[:, 0] = xchunk
|
||||
subarr[:, 1] = ychunk
|
||||
if backfill_idx is None:
|
||||
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:
|
||||
subpath = QtGui.QPainterPath()
|
||||
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')],
|
||||
count=n, offset=4)
|
||||
|
||||
# Fill array with vertex values
|
||||
arr['x'] = x
|
||||
arr['y'] = y
|
||||
|
||||
backfill_idx = None
|
||||
if finiteCheck:
|
||||
if isfinite is None:
|
||||
isfinite = np.isfinite(x) & np.isfinite(y)
|
||||
all_isfinite = np.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
|
||||
if connect == 'pairs':
|
||||
|
Loading…
Reference in New Issue
Block a user