diff --git a/examples/user_guide/01-Annotating_Data.ipynb b/examples/user_guide/01-Annotating_Data.ipynb
index 21892cfcb2..11a55bec84 100644
--- a/examples/user_guide/01-Annotating_Data.ipynb
+++ b/examples/user_guide/01-Annotating_Data.ipynb
@@ -137,12 +137,12 @@
"source": [
"### Dimension parameters\n",
"\n",
- "``Dimensions`` are not just names, they are rich objects with numerous parameters that can be used to describe the space in which the data resides. Only two of these are considered *core* parameters that uniquely identify the dimension object; the rest are auxiliary metadata. The most important parameters are:\n",
+ "``Dimensions`` are not just names, they are rich objects with numerous parameters that can be used to describe the space in which the data resides. Only two of these are considered *core* parameters the dimension object; the rest are auxiliary metadata. The most important parameters are:\n",
"\n",
"
\n",
"
\n",
- " - name
- (core) A concise name for the dimension, which for convenient usage as a keyword argument should usually be a legal Python identifier.
\n",
- " - label
- (core) A optional longer description of the dimension, which is convenient if you want the displayed label to contain arbitrary spaces, symbols, or unicode.
\n",
+ " - name
- (core) A concise name for the dimension, which for convenient usage as a keyword argument should usually be a legal Python identifier. The name also corresponds to the name of the variable in the underlying data, e.g. when providing a dictionary of columns or a DataFrame.
\n",
+ " - label
- (core) A optional longer description of the dimension, which is convenient if you want the displayed label to contain arbitrary spaces, symbols, or unicode. By default this is identical to the name but if provided this value uniquely identifies the dimension.
\n",
" - range
- The minimum and maximum allowable values for the dimension, for error checking and generating widgets when needed.
\n",
" - soft_range
- Suggested minimum and maximum values within the allowed range, used to specify a useful portion of the range for widgets and animations.
\n",
" - step
- Suggested interval for sampling a continuous range, if needed for a widget or animation.
\n",
@@ -167,7 +167,7 @@
" ('height','Height above sea level'))\n",
"\n",
"distance = hv.Dimension('distance', label='Horizontal distance', unit='m')\n",
- "height = hv.Dimension(('height','Height above sea level'), unit='m')\n",
+ "height = hv.Dimension(('height', 'Height above sea level'), unit='m')\n",
"with_unit = hv.Curve((xs, ys), distance, height)\n",
"\n",
"# (using + to compose elements is described in the next guide)\n",
@@ -254,5 +254,5 @@
}
},
"nbformat": 4,
- "nbformat_minor": 2
+ "nbformat_minor": 4
}
diff --git a/examples/user_guide/08-Tabular_Datasets.ipynb b/examples/user_guide/08-Tabular_Datasets.ipynb
index 2ee138585f..87aa7b63e4 100644
--- a/examples/user_guide/08-Tabular_Datasets.ipynb
+++ b/examples/user_guide/08-Tabular_Datasets.ipynb
@@ -264,6 +264,32 @@
"cell_type": "markdown",
"metadata": {},
"source": [
+ "This is particularly useful when you're working with wide data where you have one column (or index) representing the shared x-values and multiple columns measuring some quantity, e.g. a set of stocks indexed by date. By providing a name and label for the value dimension of our `Curve` we can correctly label the dimension as the stock `Price` while referring to the underlying equity by name:"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "stocks = pd.DataFrame({\n",
+ " 'AAPL': np.random.randn(100).cumsum() + 20,\n",
+ " 'MSFT': np.random.randn(100).cumsum() + 25,\n",
+ " 'IBM': np.random.randn(100).cumsum() + 10,\n",
+ "}, index=pd.date_range('2024-01-01', '2024-04-09'))\n",
+ "\n",
+ "hv.NdOverlay(\n",
+ " {col: hv.Curve(stocks, 'index', (col, 'Price')) for col in stocks.columns}, 'Ticker'\n",
+ ")"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "Each Element merely provides a view into the underlying data.\n",
+ "\n",
"For columnar data, this approach is much more efficient than creating copies of the data for each Element, and allows for some advanced features like linked brushing in the [Bokeh backend](./Plotting_with_Bokeh.ipynb)."
]
},
@@ -591,5 +617,5 @@
}
},
"nbformat": 4,
- "nbformat_minor": 1
+ "nbformat_minor": 4
}
diff --git a/holoviews/core/dimension.py b/holoviews/core/dimension.py
index 3da9ac4898..56b348a637 100644
--- a/holoviews/core/dimension.py
+++ b/holoviews/core/dimension.py
@@ -347,7 +347,7 @@ def __eq__(self, other):
"Implements equals operator including sanitized comparison."
if isinstance(other, Dimension):
- return self.spec == other.spec
+ return self.label == other.label
# For comparison to strings. Name may be sanitized.
return other in [self.name, self.label, util.dimension_sanitizer(self.name)]
diff --git a/holoviews/core/pprint.py b/holoviews/core/pprint.py
index 958aa3882c..f3b070d3ee 100644
--- a/holoviews/core/pprint.py
+++ b/holoviews/core/pprint.py
@@ -355,7 +355,7 @@ def element_info(cls_or_slf, node, siblings, level, value_dims):
if len(node.kdims) >= 1:
info += cls_or_slf.tab + f"[{','.join(d.name for d in node.kdims)}]"
if value_dims and len(node.vdims) >= 1:
- info += cls_or_slf.tab + f"({','.join(d.name for d in node.vdims)})"
+ info += cls_or_slf.tab + f"({','.join(d.label for d in node.vdims)})"
return level, [(level, info)]
@bothmethod
diff --git a/holoviews/plotting/bokeh/chart.py b/holoviews/plotting/bokeh/chart.py
index 65762e73bb..0bbd705ada 100644
--- a/holoviews/plotting/bokeh/chart.py
+++ b/holoviews/plotting/bokeh/chart.py
@@ -447,10 +447,10 @@ def get_data(self, element, ranges, style):
def get_extents(self, element, ranges, range_type='combined', **kwargs):
ydim = element.get_dimension(1)
- s0, s1 = ranges[ydim.name]['soft']
+ s0, s1 = ranges[ydim.label]['soft']
s0 = min(s0, 0) if isfinite(s0) else 0
s1 = max(s1, 0) if isfinite(s1) else 0
- ranges[ydim.name]['soft'] = (s0, s1)
+ ranges[ydim.label]['soft'] = (s0, s1)
return super().get_extents(element, ranges, range_type)
@@ -888,8 +888,8 @@ def get_data(self, element, ranges, style):
stack_dim = element.get_dimension(1)
if stack_dim.values:
stack_order = stack_dim.values
- elif stack_dim in ranges and ranges[stack_dim.name].get('factors'):
- stack_order = ranges[stack_dim]['factors']
+ elif stack_dim in ranges and ranges[stack_dim.label].get('factors'):
+ stack_order = ranges[stack_dim.label]['factors']
else:
stack_order = element.dimension_values(1, False)
stack_order = list(stack_order)
@@ -904,7 +904,7 @@ def get_data(self, element, ranges, style):
color_index = (group_dim or stack_dim) if no_cidx else self.color_index
color_dim = element.get_dimension(color_index)
if color_dim:
- self.color_index = color_dim.name
+ self.color_index = color_dim.label
# Define style information
width = style.get('bar_width', style.get('width', 1))
@@ -935,7 +935,7 @@ def get_data(self, element, ranges, style):
datatype=['dataframe', 'dictionary'])
width = abs(width)
- y0, y1 = ranges.get(ydim.name, {'combined': (None, None)})['combined']
+ y0, y1 = ranges.get(ydim.label, {'combined': (None, None)})['combined']
if self.logy:
bottom = (ydim.range[0] or (0.01 if y1 > 0.01 else 10**(np.log10(y1)-2)))
else:
diff --git a/holoviews/plotting/bokeh/element.py b/holoviews/plotting/bokeh/element.py
index 71384e9f0b..8c2b2bdf23 100644
--- a/holoviews/plotting/bokeh/element.py
+++ b/holoviews/plotting/bokeh/element.py
@@ -713,7 +713,7 @@ def _axis_props(self, plots, subplots, element, ranges, pos, *, dim=None,
dims = [dim]
v0, v1 = dim.range
axis_label = str(dim)
- specs = ((dim.name, dim.label, dim.unit),)
+ specs = ((dim.label, dim.unit),)
# For y-axes check if we explicitly passed in a dimension.
# This is used by certain plot types to create an axis from
# a synthetic dimension and exclusively supported for y-axes.
@@ -724,7 +724,7 @@ def _axis_props(self, plots, subplots, element, ranges, pos, *, dim=None,
for elrange in ranges.values()
])
axis_label = str(dim)
- specs = ((dim.name, dim.label, dim.unit),)
+ specs = ((dim.label, dim.unit),)
else:
try:
l, b, r, t = self.get_extents(range_el, ranges, dimension=dim)
@@ -756,7 +756,7 @@ def _axis_props(self, plots, subplots, element, ranges, pos, *, dim=None,
if dims:
if not isinstance(dims, list):
dims = [dims]
- specs = tuple((d.name, d.label, d.unit) for d in dims)
+ specs = tuple((d.label, d.unit) for d in dims)
else:
specs = None
@@ -773,7 +773,7 @@ def _axis_props(self, plots, subplots, element, ranges, pos, *, dim=None,
categorical = any(self.traverse(lambda plot: plot._categorical))
if self.subcoordinate_y:
categorical = False
- elif dims is not None and any(dim.name in ranges and 'factors' in ranges[dim.name] for dim in dims):
+ elif dims is not None and any(dim.label in ranges and 'factors' in ranges[dim.label] for dim in dims):
categorical = True
else:
categorical = any(isinstance(v, (str, bytes)) for v in (v0, v1))
@@ -1663,8 +1663,8 @@ def get_aspect(self, xspan, yspan):
def _get_dimension_factors(self, element, ranges, dimension):
if dimension.values:
values = dimension.values
- elif 'factors' in ranges.get(dimension.name, {}):
- values = ranges[dimension.name]['factors']
+ elif 'factors' in ranges.get(dimension.label, {}):
+ values = ranges[dimension.label]['factors']
else:
values = element.dimension_values(dimension, False)
values = np.asarray(values)
diff --git a/holoviews/plotting/bokeh/graphs.py b/holoviews/plotting/bokeh/graphs.py
index c9201d6560..5c95d6d6bf 100644
--- a/holoviews/plotting/bokeh/graphs.py
+++ b/holoviews/plotting/bokeh/graphs.py
@@ -164,8 +164,8 @@ def _get_edge_paths(self, element, ranges):
"Expected %d, found %d paths." % (len(element), len(edges)))
elif self.directed:
xdim, ydim = element.nodes.kdims[:2]
- x_range = ranges[xdim.name]['combined']
- y_range = ranges[ydim.name]['combined']
+ x_range = ranges[xdim.label]['combined']
+ y_range = ranges[ydim.label]['combined']
arrow_len = np.hypot(y_range[1]-y_range[0], x_range[1]-x_range[0])*self.arrowhead_length
arrows = get_directed_graph_paths(element, arrow_len)
path_data['xs'] = [arr[:, 0] for arr in arrows]
diff --git a/holoviews/plotting/bokeh/hex_tiles.py b/holoviews/plotting/bokeh/hex_tiles.py
index adcb473c25..1538f9686d 100644
--- a/holoviews/plotting/bokeh/hex_tiles.py
+++ b/holoviews/plotting/bokeh/hex_tiles.py
@@ -150,16 +150,16 @@ class HexTilesPlot(ColorbarPlot):
def get_extents(self, element, ranges, range_type='combined', **kwargs):
xdim, ydim = element.kdims[:2]
- ranges[xdim.name]['data'] = xdim.range
- ranges[ydim.name]['data'] = ydim.range
+ ranges[xdim.label]['data'] = xdim.range
+ ranges[ydim.label]['data'] = ydim.range
xd = element.cdims.get(xdim.name)
- if xd and xdim.name in ranges:
- ranges[xdim.name]['hard'] = xd.range
- ranges[xdim.name]['soft'] = max_range([xd.soft_range, ranges[xdim.name]['soft']])
+ if xd and xdim.label in ranges:
+ ranges[xdim.label]['hard'] = xd.range
+ ranges[xdim.label]['soft'] = max_range([xd.soft_range, ranges[xdim.label]['soft']])
yd = element.cdims.get(ydim.name)
- if yd and ydim.name in ranges:
- ranges[ydim.name]['hard'] = yd.range
- ranges[ydim.name]['hard'] = max_range([yd.soft_range, ranges[ydim.name]['soft']])
+ if yd and ydim.label in ranges:
+ ranges[ydim.label]['hard'] = yd.range
+ ranges[ydim.label]['hard'] = max_range([yd.soft_range, ranges[ydim.label]['soft']])
return super().get_extents(element, ranges, range_type)
def _hover_opts(self, element):
diff --git a/holoviews/plotting/bokeh/path.py b/holoviews/plotting/bokeh/path.py
index d331d3dc7b..74c7a8c68f 100644
--- a/holoviews/plotting/bokeh/path.py
+++ b/holoviews/plotting/bokeh/path.py
@@ -268,8 +268,8 @@ def get_data(self, element, ranges, style):
data[dim_name] = values
factors = None
- if cdim.name in ranges and 'factors' in ranges[cdim.name]:
- factors = ranges[cdim.name]['factors']
+ if cdim.label in ranges and 'factors' in ranges[cdim.label]:
+ factors = ranges[cdim.label]['factors']
elif values.dtype.kind in 'SUO' and len(values):
if isinstance(values[0], np.ndarray):
values = np.concatenate(values)
diff --git a/holoviews/plotting/bokeh/sankey.py b/holoviews/plotting/bokeh/sankey.py
index 7a0d76ac53..8115ca1a21 100644
--- a/holoviews/plotting/bokeh/sankey.py
+++ b/holoviews/plotting/bokeh/sankey.py
@@ -233,8 +233,8 @@ def get_extents(self, element, ranges, range_type='combined', **kwargs):
return element.nodes.extents
xdim, ydim = element.nodes.kdims[:2]
xpad = .05 if self.label_index is None else 0.25
- x0, x1 = ranges[xdim.name][range_type]
- y0, y1 = ranges[ydim.name][range_type]
+ x0, x1 = ranges[xdim.label][range_type]
+ y0, y1 = ranges[ydim.label][range_type]
xdiff = (x1-x0)
ydiff = (y1-y0)
diff --git a/holoviews/plotting/bokeh/stats.py b/holoviews/plotting/bokeh/stats.py
index cc2adcccbb..25d31d4f92 100644
--- a/holoviews/plotting/bokeh/stats.py
+++ b/holoviews/plotting/bokeh/stats.py
@@ -509,7 +509,7 @@ def get_data(self, element, ranges, style):
groups = dict([((element.label,), element)])
if split_dim:
- split_name = split_dim.dimension.name
+ split_name = split_dim.dimension.label
if split_name in ranges and not split_dim.ops and 'factors' in ranges[split_name]:
split_cats = ranges[split_name].get('factors')
elif split_dim:
diff --git a/holoviews/plotting/mixins.py b/holoviews/plotting/mixins.py
index db3d2d75aa..524308a1c7 100644
--- a/holoviews/plotting/mixins.py
+++ b/holoviews/plotting/mixins.py
@@ -16,8 +16,8 @@ def get_extents(self, element, ranges, range_type='combined', **kwargs):
kdims = element.kdims
# loop over start and end points of segments
# simultaneously in each dimension
- for kdim0, kdim1 in zip([kdims[i].name for i in range(2)],
- [kdims[i].name for i in range(2,4)]):
+ for kdim0, kdim1 in zip([kdims[i].label for i in range(2)],
+ [kdims[i].label for i in range(2,4)]):
new_range = {}
for kdim in [kdim0, kdim1]:
# for good measure, update ranges for both start and end kdim
@@ -85,10 +85,10 @@ def get_extents(self, element, ranges, range_type='combined', **kwargs):
opts = self.lookup_options(element, 'plot').options
if len(element.dimensions()) > 1 and 'spike_length' not in opts:
ydim = element.get_dimension(1)
- s0, s1 = ranges[ydim.name]['soft']
+ s0, s1 = ranges[ydim.label]['soft']
s0 = min(s0, 0) if util.isfinite(s0) else 0
s1 = max(s1, 0) if util.isfinite(s1) else 0
- ranges[ydim.name]['soft'] = (s0, s1)
+ ranges[ydim.label]['soft'] = (s0, s1)
proxy_dim = None
if 'spike_length' in opts or len(element.dimensions()) == 1:
proxy_dim = Dimension('proxy_dim')
@@ -118,12 +118,12 @@ class AreaMixin:
def get_extents(self, element, ranges, range_type='combined', **kwargs):
vdims = element.vdims[:2]
- vdim = vdims[0].name
+ vdim = vdims[0].label
if len(vdims) > 1:
new_range = {}
for r in ranges[vdim]:
if r != 'values':
- new_range[r] = util.max_range([ranges[vd.name][r] for vd in vdims])
+ new_range[r] = util.max_range([ranges[vd.label][r] for vd in vdims])
ranges[vdim] = new_range
else:
s0, s1 = ranges[vdim]['soft']
@@ -153,9 +153,9 @@ def get_extents(self, element, ranges, range_type='combined', **kwargs):
element = Bars(overlay.table(), kdims=element.kdims+overlay.kdims,
vdims=element.vdims)
for kd in overlay.kdims:
- ranges[kd.name]['combined'] = overlay.range(kd)
+ ranges[kd.label]['combined'] = overlay.range(kd)
- vdim = element.vdims[0].name
+ vdim = element.vdims[0].label
s0, s1 = ranges[vdim]['soft']
s0 = min(s0, 0) if util.isfinite(s0) else 0
s1 = max(s1, 0) if util.isfinite(s1) else 0
@@ -209,15 +209,15 @@ def _get_coords(self, element, ranges, as_string=True):
else:
if gdim.values:
gvals = gdim.values
- elif ranges.get(gdim.name, {}).get('factors') is not None:
- gvals = ranges[gdim.name]['factors']
+ elif ranges.get(gdim.label, {}).get('factors') is not None:
+ gvals = ranges[gdim.label]['factors']
else:
gvals = element.dimension_values(gdim, False)
gvals = np.asarray(gvals)
if xvals:
pass
- elif ranges.get(xdim.name, {}).get('factors') is not None:
- xvals = ranges[xdim.name]['factors']
+ elif ranges.get(xdim.label, {}).get('factors') is not None:
+ xvals = ranges[xdim.label]['factors']
else:
xvals = element.dimension_values(0, False)
xvals = np.asarray(xvals)
@@ -229,8 +229,8 @@ def _get_coords(self, element, ranges, as_string=True):
else:
if xvals:
pass
- elif ranges.get(xdim.name, {}).get('factors') is not None:
- xvals = ranges[xdim.name]['factors']
+ elif ranges.get(xdim.label, {}).get('factors') is not None:
+ xvals = ranges[xdim.label]['factors']
else:
xvals = element.dimension_values(0, False)
xvals = np.asarray(xvals)
diff --git a/holoviews/plotting/mpl/chart.py b/holoviews/plotting/mpl/chart.py
index 05dba48efd..879fd260e6 100644
--- a/holoviews/plotting/mpl/chart.py
+++ b/holoviews/plotting/mpl/chart.py
@@ -6,7 +6,7 @@
from matplotlib.dates import DateFormatter, date2num
from packaging.version import Version
-from ...core.dimension import Dimension, dimension_name
+from ...core.dimension import Dimension
from ...core.options import Store, abbreviated_exception
from ...core.util import (
dt64_to_dt,
@@ -23,7 +23,7 @@
from ...util.transform import dim
from ..mixins import AreaMixin, BarsMixin, SpikesMixin
from ..plot import PlotSelector
-from ..util import compute_sizes, get_min_distance, get_sideplot_ranges
+from ..util import compute_sizes, dim_range_key, get_min_distance, get_sideplot_ranges
from .element import ColorbarPlot, ElementPlot, LegendPlot
from .path import PathPlot
from .plot import AdjoinedPlot, mpl_rc_context
@@ -396,10 +396,10 @@ def _compute_ticks(self, element, edges, widths, lims):
def get_extents(self, element, ranges, range_type='combined', **kwargs):
ydim = element.get_dimension(1)
- s0, s1 = ranges[ydim.name]['soft']
+ s0, s1 = ranges[ydim.label]['soft']
s0 = min(s0, 0) if isfinite(s0) else 0
s1 = max(s1, 0) if isfinite(s1) else 0
- ranges[ydim.name]['soft'] = (s0, s1)
+ ranges[ydim.label]['soft'] = (s0, s1)
return super().get_extents(element, ranges, range_type)
def _process_axsettings(self, hist, lims, ticks):
@@ -644,11 +644,11 @@ def update_handles(self, key, axis, element, ranges, style):
paths = self.handles['artist']
(xs, ys), style, _ = self.get_data(element, ranges, style)
xdim, ydim = element.dimensions()[:2]
- if 'factors' in ranges.get(xdim.name, {}):
- factors = list(ranges[xdim.name]['factors'])
+ if 'factors' in ranges.get(xdim.label, {}):
+ factors = list(ranges[xdim.label]['factors'])
xs = [factors.index(x) for x in xs if x in factors]
- if 'factors' in ranges.get(ydim.name, {}):
- factors = list(ranges[ydim.name]['factors'])
+ if 'factors' in ranges.get(ydim.label, {}):
+ factors = list(ranges[ydim.label]['factors'])
ys = [factors.index(y) for y in ys if y in factors]
paths.set_offsets(np.column_stack([xs, ys]))
if 's' in style:
@@ -752,7 +752,7 @@ def _get_magnitudes(self, element, style, ranges):
magnitudes = mag_dim.apply(element, flat=True)
else:
magnitudes = element.dimension_values(mag_dim)
- _, max_magnitude = ranges[dimension_name(mag_dim)]['combined']
+ _, max_magnitude = ranges[dim_range_key(mag_dim)]['combined']
if self.normalize_lengths and max_magnitude != 0:
magnitudes = magnitudes / max_magnitude
else:
@@ -873,8 +873,8 @@ def _get_values(self, element, ranges):
dimensions = [kdims[0], None, stack_dim]
if stack_dim.values:
stack_order = stack_dim.values
- elif stack_dim in ranges and ranges[stack_dim.name].get('factors'):
- stack_order = ranges[stack_dim]['factors']
+ elif stack_dim in ranges and ranges[stack_dim.label].get('factors'):
+ stack_order = ranges[stack_dim.label]['factors']
else:
stack_order = element.dimension_values(1, False)
stack_order = list(stack_order)
@@ -1042,7 +1042,7 @@ def _create_bars(self, axis, element, ranges, style):
legend_opts.update(**leg_spec)
axis.legend(title=title, **legend_opts)
- x_range = ranges[gdim.name]["data"]
+ x_range = ranges[gdim.label]["data"]
if continuous and not is_dt:
if style.get('align', 'center') == 'center':
left_multiplier = 0.5
@@ -1050,7 +1050,7 @@ def _create_bars(self, axis, element, ranges, style):
else:
left_multiplier = 0
right_multiplier = 1
- ranges[gdim.name]["data"] = (
+ ranges[gdim.label]["data"] = (
x_range[0] - width * left_multiplier,
x_range[1] + width * right_multiplier
)
diff --git a/holoviews/plotting/mpl/graphs.py b/holoviews/plotting/mpl/graphs.py
index c16a800eb0..6279018aef 100644
--- a/holoviews/plotting/mpl/graphs.py
+++ b/holoviews/plotting/mpl/graphs.py
@@ -131,8 +131,8 @@ def get_data(self, element, ranges, style):
if self.directed:
xdim, ydim = element.nodes.kdims[:2]
- x_range = ranges[xdim.name]['combined']
- y_range = ranges[ydim.name]['combined']
+ x_range = ranges[xdim.label]['combined']
+ y_range = ranges[ydim.label]['combined']
arrow_len = np.hypot(y_range[1]-y_range[0], x_range[1]-x_range[0])*self.arrowhead_length
paths = get_directed_graph_paths(element, arrow_len)
else:
diff --git a/holoviews/plotting/mpl/heatmap.py b/holoviews/plotting/mpl/heatmap.py
index 67cf98fb61..273abea9c8 100644
--- a/holoviews/plotting/mpl/heatmap.py
+++ b/holoviews/plotting/mpl/heatmap.py
@@ -173,8 +173,8 @@ def get_data(self, element, ranges, style):
yvals = aggregate.dimension_values(ydim, expanded=False)
yvals = GridInterface._infer_interval_breaks(yvals)
- xfactors = list(ranges.get(xdim.name, {}).get('factors', []))
- yfactors = list(ranges.get(ydim.name, {}).get('factors', []))
+ xfactors = list(ranges.get(xdim.label, {}).get('factors', []))
+ yfactors = list(ranges.get(ydim.label, {}).get('factors', []))
xticks, yticks = self._compute_ticks(element, xvals, yvals, xfactors, yfactors)
style['xfactors'] = xfactors
diff --git a/holoviews/plotting/mpl/raster.py b/holoviews/plotting/mpl/raster.py
index 890d41d7f5..6c35279903 100644
--- a/holoviews/plotting/mpl/raster.py
+++ b/holoviews/plotting/mpl/raster.py
@@ -330,7 +330,7 @@ def initialize_plot(self, ranges=None):
ranges = self.compute_ranges(vmap, key, ranges)
opts = self.lookup_options(pane, 'style')[self.cyclic_index]
plot = self.handles['axis'].imshow(data, extent=(x,x+w, y, y+h), **opts)
- cdim = pane.vdims[0].name
+ cdim = pane.vdims[0].label
valrange = match_spec(pane, ranges).get(cdim, pane.range(cdim))['combined']
plot.set_clim(valrange)
if data is None:
diff --git a/holoviews/plotting/mpl/sankey.py b/holoviews/plotting/mpl/sankey.py
index 40fe39f3e4..606f960af4 100644
--- a/holoviews/plotting/mpl/sankey.py
+++ b/holoviews/plotting/mpl/sankey.py
@@ -54,8 +54,8 @@ def get_extents(self, element, ranges, range_type='combined', **kwargs):
return element.nodes.extents
xdim, ydim = element.nodes.kdims[:2]
xpad = .05 if self.label_index is None else 0.25
- x0, x1 = ranges[xdim.name][range_type]
- y0, y1 = ranges[ydim.name][range_type]
+ x0, x1 = ranges[xdim.label][range_type]
+ y0, y1 = ranges[ydim.label][range_type]
xdiff = (x1-x0)
ydiff = (y1-y0)
if self.label_position == 'right':
diff --git a/holoviews/plotting/plot.py b/holoviews/plotting/plot.py
index 99ddd489d4..774842989f 100644
--- a/holoviews/plotting/plot.py
+++ b/holoviews/plotting/plot.py
@@ -788,7 +788,7 @@ def _compute_group_range(cls, group, elements, ranges, framewise,
# Compute dimension normalization
for el_dim in el.dimensions('ranges'):
- dim_name = el_dim.name
+ dim_name = el_dim.label
if dim_name in prev_ranges and not framewise:
continue
data_range = data_ranges[(el, el_dim)]
diff --git a/holoviews/plotting/plotly/chart.py b/holoviews/plotting/plotly/chart.py
index b44b109ded..fcb2235588 100644
--- a/holoviews/plotting/plotly/chart.py
+++ b/holoviews/plotting/plotly/chart.py
@@ -231,8 +231,8 @@ def get_data(self, element, ranges, style, **kwargs):
stack_dim = element.get_dimension(1)
if stack_dim.values:
svals = stack_dim.values
- elif stack_dim in ranges and ranges[stack_dim.name].get('factors'):
- svals = ranges[stack_dim]['factors']
+ elif stack_dim in ranges and ranges[stack_dim.label].get('factors'):
+ svals = ranges[stack_dim.label]['factors']
else:
svals = element.dimension_values(1, False)
else:
diff --git a/holoviews/plotting/util.py b/holoviews/plotting/util.py
index 4cb3fc26da..27b035ab81 100644
--- a/holoviews/plotting/util.py
+++ b/holoviews/plotting/util.py
@@ -407,10 +407,10 @@ def get_range(element, ranges, dimension):
an element and a dictionary of ranges.
"""
if dimension and dimension != 'categorical':
- if ranges and dimension.name in ranges:
- drange = ranges[dimension.name]['data']
- srange = ranges[dimension.name]['soft']
- hrange = ranges[dimension.name]['hard']
+ if ranges and dimension.label in ranges:
+ drange = ranges[dimension.label]['data']
+ srange = ranges[dimension.label]['soft']
+ hrange = ranges[dimension.label]['hard']
else:
drange = element.range(dimension, dimension_range=False)
srange = dimension.soft_range
@@ -439,8 +439,8 @@ def get_sideplot_ranges(plot, element, main, ranges):
range_item = HoloMap({0: main}, kdims=['Frame'])
ranges = match_spec(range_item.last, ranges)
- if dim.name in ranges:
- main_range = ranges[dim.name]['combined']
+ if dim.label in ranges:
+ main_range = ranges[dim.label]['combined']
else:
framewise = plot.lookup_options(range_item.last, 'norm').options.get('framewise')
if framewise and range_item.get(key, False):
@@ -1116,7 +1116,7 @@ def dim_range_key(eldim):
if dim_name.startswith("dim('") and dim_name.endswith("')"):
dim_name = dim_name[5:-2]
else:
- dim_name = eldim.name
+ dim_name = eldim.label
return dim_name
diff --git a/holoviews/tests/plotting/bokeh/test_layoutplot.py b/holoviews/tests/plotting/bokeh/test_layoutplot.py
index 80f90571a0..97757a39ba 100644
--- a/holoviews/tests/plotting/bokeh/test_layoutplot.py
+++ b/holoviews/tests/plotting/bokeh/test_layoutplot.py
@@ -296,13 +296,26 @@ def test_layout_shared_source_synced_update(self):
self.assertEqual(data['D'], np.full_like(hmap1[1].dimension_values(0), np.nan))
def test_shared_axes(self):
- curve = Curve(range(10))
+ curve = Curve(range(10), )
img = Image(np.random.rand(10,10))
plot = bokeh_renderer.get_plot(curve+img)
- plot = plot.subplots[(0, 1)].subplots['main']
- x_range, y_range = plot.handles['x_range'], plot.handles['y_range']
- self.assertEqual((x_range.start, x_range.end), (-.5, 9))
- self.assertEqual((y_range.start, y_range.end), (-.5, 9))
+ plot1 = plot.subplots[(0, 0)].subplots['main']
+ plot2 = plot.subplots[(0, 1)].subplots['main']
+ x_range1, y_range1 = plot1.handles['x_range'], plot1.handles['y_range']
+ x_range2, y_range2 = plot2.handles['x_range'], plot2.handles['y_range']
+ assert x_range1 is x_range2
+ assert y_range1 is y_range2
+
+ def test_shared_axes_different_dimension_names(self):
+ curve = Curve(range(10), ('x1', 'foo'), ('y1', 'bar'))
+ img = Image(np.random.rand(10,10), [('x2', 'foo'), ('y2', 'bar')])
+ plot = bokeh_renderer.get_plot(curve+img)
+ plot1 = plot.subplots[(0, 0)].subplots['main']
+ plot2 = plot.subplots[(0, 1)].subplots['main']
+ x_range1, y_range1 = plot1.handles['x_range'], plot1.handles['y_range']
+ x_range2, y_range2 = plot2.handles['x_range'], plot2.handles['y_range']
+ assert x_range1 is x_range2
+ assert y_range1 is y_range2
def test_shared_axes_disable(self):
curve = Curve(range(10))
@@ -356,8 +369,8 @@ def test_layout_axis_link_matching_name_label(self):
p1, p2 = (sp.subplots['main'] for sp in plot.subplots.values())
self.assertIs(p1.handles['y_range'], p2.handles['y_range'])
- def test_layout_axis_not_linked_mismatching_name(self):
- layout = Curve([1, 2, 3], vdims=('b', 'A')) + Curve([1, 2, 3], vdims=('a', 'A'))
+ def test_layout_axis_not_linked_mismatching_label(self):
+ layout = Curve([1, 2, 3], vdims=('a', 'A')) + Curve([1, 2, 3], vdims=('a', 'B'))
plot = bokeh_renderer.get_plot(layout)
p1, p2 = (sp.subplots['main'] for sp in plot.subplots.values())
self.assertIsNot(p1.handles['y_range'], p2.handles['y_range'])