Skip to content

Commit

Permalink
Cleaned up Element range handling and fixed QuadMesh range
Browse files Browse the repository at this point in the history
  • Loading branch information
philippjfr committed Sep 12, 2017
1 parent c061b2b commit 09a5fb1
Show file tree
Hide file tree
Showing 6 changed files with 44 additions and 66 deletions.
25 changes: 7 additions & 18 deletions holoviews/core/data/__init__.py
Expand Up @@ -9,6 +9,7 @@
import param

from ..dimension import redim
from ..util import dimension_range
from .interface import Interface, iloc, ndloc
from .array import ArrayInterface
from .dictionary import DictInterface
Expand Down Expand Up @@ -238,25 +239,13 @@ def range(self, dim, data_range=True):
dim = self.get_dimension(dim)
if dim is None:
return (None, None)
elif None not in dim.range:
return dim.range
elif dim in self.dimensions() and data_range:
if len(self):
drange = self.interface.range(self, dim)
else:
drange = (np.NaN, np.NaN)
soft_range = [r for r in dim.soft_range if r is not None]
if soft_range:
drange = util.max_range([drange, soft_range])
else:
drange = dim.soft_range
if dim.range[0] is not None:
return (dim.range[0], drange[1])
elif dim.range[1] is not None:
return (drange[0], dim.range[1])
elif all(v is not None and np.isfinite(v) for v in dim.range):
return dimension.range
elif dim in self.dimensions() and data_range and len(self):
lower, upper = self.interface.range(self, dim)
else:
return drange

lower, upper = (np.NaN, np.NaN)
return dimension_range(lower, upper, dim)


def add_dimension(self, dimension, dim_pos, dim_val, vdim=False, **kwargs):
Expand Down
20 changes: 6 additions & 14 deletions holoviews/core/dimension.py
Expand Up @@ -15,7 +15,7 @@
group_sanitizer, label_sanitizer, max_range,
find_range, dimension_sanitizer, OrderedDict,
bytes_to_unicode, unicode, dt64_to_dt, unique_array,
builtins, config)
builtins, config, dimension_range)
from .options import Store, StoreOptions
from .pprint import PrettyPrinter

Expand Down Expand Up @@ -1053,29 +1053,21 @@ def range(self, dimension, data_range=True):
dimension = self.get_dimension(dimension)
if dimension is None:
return (None, None)
if None not in dimension.range:
elif all(v is not None and np.isfinite(v) for v in dimension.range):
return dimension.range
elif data_range:
if dimension in self.kdims+self.vdims:
dim_vals = self.dimension_values(dimension.name)
drange = find_range(dim_vals)
lower, upper = find_range(dim_vals)
else:
dname = dimension.name
match_fn = lambda x: dname in x.kdims + x.vdims
range_fn = lambda x: x.range(dname)
ranges = self.traverse(range_fn, [match_fn])
drange = max_range(ranges)
soft_range = [r for r in dimension.soft_range if r is not None]
if soft_range:
drange = max_range([drange, soft_range])
lower, upper = max_range(ranges)
else:
drange = dimension.soft_range
if dimension.range[0] is not None:
return (dimension.range[0], drange[1])
elif dimension.range[1] is not None:
return (drange[0], dimension.range[1])
else:
return drange
lower, upper = (np.NaN, np.NaN)
return dimension_range(lower, upper, dimension)


def __repr__(self):
Expand Down
12 changes: 12 additions & 0 deletions holoviews/core/util.py
Expand Up @@ -710,6 +710,18 @@ def max_range(ranges):
return (np.NaN, np.NaN)


def dimension_range(lower, upper, dimension):
"""
Computes the range along a dimension by combining the data range
with the Dimension soft_range and range.
"""
lower, upper = max_range([(lower, upper), dimension.soft_range])
dmin, dmax = dimension.range
lower = lower if dmin is None or not np.isfinite(dmin) else dmin
upper = upper if dmax is None or not np.isfinite(dmax) else dmax
return lower, upper


def max_extents(extents, zrange=False):
"""
Computes the maximal extent in 2D and 3D space from
Expand Down
24 changes: 8 additions & 16 deletions holoviews/element/chart.py
Expand Up @@ -88,23 +88,19 @@ class ErrorBars(Chart):


def range(self, dim, data_range=True):
drange = super(ErrorBars, self).range(dim, data_range)
didx = self.get_dimension_index(dim)
dim = self.get_dimension(dim)
if didx == 1 and data_range:
if didx == 1 and data_range and len(self):
mean = self.dimension_values(1)
neg_error = self.dimension_values(2)
pos_idx = 3 if len(self.dimensions()) > 3 else 2
pos_error = self.dimension_values(pos_idx)
if len(self.dimensions()) > 3:
pos_error = self.dimension_values(3)
else:
pos_error = neg_error
lower = np.nanmin(mean-neg_error)
upper = np.nanmax(mean+pos_error)
lower, upper = util.max_range([(lower, upper), drange])
dmin, dmax = dim.range
lower = lower if dmin is None or not np.isfinite(dmin) else dmin
upper = upper if dmax is None or not np.isfinite(dmax) else dmax
return lower, upper
else:
return drange
return util.dimension_range(lower, upper, dim)
return super(ErrorBars, self).range(dim, data_range)



Expand Down Expand Up @@ -248,11 +244,7 @@ def range(self, dimension, data_range=True):
if self.get_dimension_index(dimension) == 0 and data_range:
dim = self.get_dimension(dimension)
lower, upper = np.min(self.edges), np.max(self.edges)
lower, upper = util.max_range([(lower, upper), dim.soft_range])
dmin, dmax = dim.range
lower = lower if dmin is None or not np.isfinite(dmin) else dmin
upper = upper if dmax is None or not np.isfinite(dmax) else dmax
return lower, upper
return util.dimension_range(lower, upper, dim)
else:
return super(Histogram, self).range(dimension, data_range)

Expand Down
25 changes: 9 additions & 16 deletions holoviews/element/raster.py
Expand Up @@ -8,7 +8,7 @@
from ..core import Dimension, Element2D, Overlay, Dataset
from ..core.boundingregion import BoundingRegion, BoundingBox
from ..core.sheetcoords import SheetCoordinateSystem, Slice
from ..core.util import max_range
from ..core.util import max_range, dimension_range
from .chart import Curve
from .tabular import Table
from .util import compute_edges, compute_slice_bounds, categorical_aggregate2d
Expand Down Expand Up @@ -71,14 +71,8 @@ def range(self, dim, data_range=True):
idx = self.get_dimension_index(dim)
if data_range and idx == 2:
dimension = self.get_dimension(dim)
drange = self.data.min(), self.data.max()
drange = max_range([drange, dimension.soft_range])
if dimension.range[0] is not None:
return (dimension.range[0], drange[1])
elif dimension.range[1] is not None:
return (drange[0], dimension.range[1])
else:
return drange
lower, upper = np.nanmin(self.data), np.nanmax(self.data)
return dimension_range(lower, upper, dimension)
return super(Raster, self).range(dim, data_range)


Expand Down Expand Up @@ -720,15 +714,14 @@ def _coord2matrix(self, coord):
for i in [1, 0])


def range(self, dimension):
def range(self, dimension, data_range=True):
idx = self.get_dimension_index(dimension)
if idx in [0, 1]:
data = self.data[idx]
return np.min(data), np.max(data)
elif idx == 2:
dim = self.get_dimension(dimension)
if idx in [0, 1, 2] and data_range:
data = self.data[idx]
return np.nanmin(data), np.nanmax(data)
super(QuadMesh, self).range(dimension)
lower, upper = np.nanmin(data), np.nanmax(data)
return dimension_range(lower, upper, dim)
return super(QuadMesh, self).range(dimension, data_range)


def dimension_values(self, dimension, expanded=True, flat=True):
Expand Down
4 changes: 2 additions & 2 deletions tests/testannotations.py
Expand Up @@ -27,13 +27,13 @@ def test_text_string_position(self):

def test_hline_dimension_values(self):
hline = HLine(0)
self.assertEqual(hline.range(0), (None, None))
self.assertEqual(hline.range(0), (np.NaN, np.NaN))
self.assertEqual(hline.range(1), (0, 0))

def test_vline_dimension_values(self):
hline = VLine(0)
self.assertEqual(hline.range(0), (0, 0))
self.assertEqual(hline.range(1), (None, None))
self.assertEqual(hline.range(1), (np.NaN, np.NaN))

def test_arrow_redim_range_aux(self):
annotations = Arrow(0, 0)
Expand Down

0 comments on commit 09a5fb1

Please sign in to comment.