Skip to content

Commit 6e8523e

Browse files
committed
FIX: fixed colors for arrays with a lot of nan
the whole sample is nan but not the entire array
1 parent a6e697a commit 6e8523e

File tree

3 files changed

+33
-17
lines changed

3 files changed

+33
-17
lines changed

larray_editor/arraymodel.py

Lines changed: 24 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -327,8 +327,13 @@ def reset_minmax(self):
327327
color_value = color_value.astype(float)
328328
# ignore nan, -inf, inf (setting them to 0 or to very large numbers is not an option)
329329
color_value = color_value[np.isfinite(color_value)]
330-
self.vmin = float(np.min(color_value))
331-
self.vmax = float(np.max(color_value))
330+
if color_value.size:
331+
self.vmin = float(np.min(color_value))
332+
self.vmax = float(np.max(color_value))
333+
else:
334+
self.vmin = np.nan
335+
self.vmax = np.nan
336+
332337
self.bgcolor_possible = True
333338
# ValueError for empty arrays, TypeError for object/string arrays
334339
except (TypeError, ValueError):
@@ -398,16 +403,23 @@ def data(self, index, role=Qt.DisplayRole):
398403
if self.bg_value is None:
399404
try:
400405
v = self.color_func(value) if self.color_func is not None else value
401-
if -np.inf < v < self.vmin:
402-
# TODO: this is suboptimal, as it can reset many times (though in practice, it is usually
403-
# ok). When we get buffering, we will need to compute vmin/vmax on the whole buffer
404-
# at once, eliminating this problem (and we could even compute final colors directly
405-
# all at once)
406-
self.vmin = v
407-
self.reset()
408-
elif self.vmax < v < np.inf:
409-
self.vmax = v
410-
self.reset()
406+
if np.isnan(v):
407+
v = np.nan
408+
else:
409+
do_reset = False
410+
if np.isnan(self.vmin) or -np.inf < v < self.vmin:
411+
# TODO: this is suboptimal, as it can reset many times (though in practice, it is
412+
# usually ok). When we get buffering, we will need to compute vmin/vmax on the
413+
# whole buffer at once, eliminating this problem (and we could even compute final
414+
# colors directly all at once)
415+
self.vmin = v
416+
do_reset = True
417+
if np.isnan(self.vmax) or self.vmax < v < np.inf:
418+
self.vmax = v
419+
do_reset = True
420+
421+
if do_reset:
422+
self.reset()
411423
v = scale_to_01range(v, self.vmin, self.vmax)
412424
except TypeError:
413425
v = np.nan

larray_editor/tests/test_api_larray.py

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -99,6 +99,10 @@ def make_demo(width=20, ball_radius=5, path_radius=5, steps=30):
9999
extreme_array = la.Array([-la.inf, -1, 0, la.nan, 1, la.inf])
100100
array_scalar = la.Array(0)
101101
arr_all_nan = la.Array([la.nan, la.nan])
102+
# this is crafted so that the entire 500 points sample is all nan but
103+
# other values need coloring
104+
arr_full_buffer_nan_should_not_be_all_white = la.ndtest(1000, dtype=float)
105+
arr_full_buffer_nan_should_not_be_all_white['a0'::2] = la.nan
102106
arr_empty = la.Array([])
103107
arr_empty_2d = la.Array([[], []])
104108
arr_obj = la.ndtest((2, 3)).astype(object)

larray_editor/utils.py

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -271,7 +271,7 @@ def __getitem__(self, key):
271271
Parameters
272272
----------
273273
key : float
274-
must be between 0 and 1
274+
must be between 0 and 1 to return a color from the gradient. Otherwise, will return nan_color.
275275
276276
Returns
277277
-------
@@ -488,10 +488,10 @@ def scale_to_01range(value, vmin, vmax):
488488
Value to scale.
489489
vmin : any numeric type
490490
Minimum used to do the scaling. This is the minimum value that is valid for value, *excluding -inf*.
491-
vmin must be <= vmax.
491+
vmin must be <= vmax. vmin and vmax can be `nan`, in which case scale_to_01range will return `nan`.
492492
vmax : any numeric type
493493
Maximum used to do the scaling. This is the maximum value that is valid for value, *excluding +inf*.
494-
vmax must be >= vmin.
494+
vmax must be >= vmin. vmin and vmax can be `nan`, in which case scale_to_01range will return `nan`.
495495
496496
Returns
497497
-------
@@ -515,7 +515,7 @@ def scale_to_01range(value, vmin, vmax):
515515
array([ 0. , 1. , 0.5, 0. , 0.1, 1. ])
516516
"""
517517
if hasattr(value, 'shape') and value.shape:
518-
if (np.isnan(vmin) and np.isnan(vmax)) or (vmin == vmax):
518+
if np.isnan(vmin) or np.isnan(vmax) or (vmin == vmax):
519519
return np.where(np.isnan(value), np.nan, 0)
520520
else:
521521
assert vmin < vmax
@@ -531,7 +531,7 @@ def scale_to_01range(value, vmin, vmax):
531531
return 0.0
532532
elif value == +np.inf:
533533
return 1.0
534-
elif vmin == vmax:
534+
elif np.isnan(vmin) or np.isnan(vmax) or (vmin == vmax):
535535
return 0.0
536536
else:
537537
assert vmin < vmax

0 commit comments

Comments
 (0)