Skip to content

Commit

Permalink
Merge branch 'master' into jupyterlite_support
Browse files Browse the repository at this point in the history
  • Loading branch information
hoxbro committed Nov 1, 2022
2 parents 0926384 + b66d493 commit 476f55c
Show file tree
Hide file tree
Showing 15 changed files with 133 additions and 48 deletions.
23 changes: 13 additions & 10 deletions .github/workflows/test.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,6 @@ jobs:
env:
HV_REQUIREMENTS: "-o flakes -o tests -o examples_tests"
MPLBACKEND: "Agg"
CHANS_DEV: "-c pyviz/label/dev -c bokeh/label/dev -c conda-forge -c nodefaults"
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
steps:
- uses: actions/checkout@v3
Expand All @@ -55,50 +54,54 @@ jobs:
run: git fetch --prune --tags --unshallow
- name: conda setup
run: |
eval "$(conda shell.bash hook)"
conda update -n base -c defaults conda
conda config --prepend channels nodefaults
conda config --prepend channels conda-forge
conda config --prepend channels bokeh/label/dev
conda config --prepend channels pyviz/label/dev
conda config --remove channels defaults
conda config --set channel_priority strict
conda create -n test-environment python=${{ matrix.python-version }} pyctdev
- name: doit env_capture
run: |
eval "$(conda shell.bash hook)"
conda activate test-environment
doit env_capture
- name: doit develop_install
if: matrix.os != 'macos-latest'
run: |
eval "$(conda shell.bash hook)"
conda activate test-environment
conda list
doit develop_install ${{ env.HV_REQUIREMENTS }}
python -c "from param import version; print(version.Version.setup_version('.', 'holoviews', archive_commit='$Format:%h$'))"
echo "-----"
git describe
# Temporary hacked step as on MacOS doit develop_install updated CPython leading to a pyctdev failure
- name: doit develop_install
if: matrix.os == 'macos-latest'
run: |
conda activate test-environment
conda list
doit develop_install ${{ env.HV_REQUIREMENTS }} || echo "Keep going"
pip install --no-deps --no-build-isolation -e .
python -c "from param import version; print(version.Version.setup_version('.', 'holoviews', archive_commit='$Format:%h$'))"
echo "-----"
git describe
- name: doit env_capture
run: |
eval "$(conda shell.bash hook)"
conda activate test-environment
doit env_capture
- name: doit test_flakes
run: |
eval "$(conda shell.bash hook)"
conda activate test-environment
doit test_flakes
- name: doit test_unit
run: |
eval "$(conda shell.bash hook)"
conda activate test-environment
doit test_unit
- name: test examples
run: |
eval "$(conda shell.bash hook)"
conda activate test-environment
doit test_examples
- name: codecov
run: |
eval "$(conda shell.bash hook)"
conda activate test-environment
codecov
29 changes: 26 additions & 3 deletions holoviews/core/data/pandas.py
Original file line number Diff line number Diff line change
@@ -1,9 +1,12 @@
from packaging.version import Version

import numpy as np
import pandas as pd
from pandas.api.types import is_numeric_dtype

from ...util._exception import deprecation_warning
from .interface import Interface, DataError
from ..dimension import dimension_name
from ..dimension import dimension_name, Dimension
from ..element import Element
from ..dimension import OrderedDict as cyODict
from ..ndmapping import NdMapping, item_check, sorted_context
Expand Down Expand Up @@ -56,7 +59,7 @@ def init(cls, eltype, data, kdims, vdims):
elif kdims == [] and vdims is None:
vdims = list(data.columns[:nvdim if nvdim else None])

if any(not isinstance(d, str) for d in kdims+vdims):
if any(not isinstance(d, (str, Dimension)) for d in kdims+vdims):
deprecation_warning(
"Having a non-string as a column name in a DataFrame is deprecated "
"and will not be supported in Holoviews version 1.16."
Expand Down Expand Up @@ -220,6 +223,12 @@ def groupby(cls, dataset, dimensions, container_type, group_type, **kwargs):
group_kwargs['dataset'] = dataset.dataset

group_by = [d.name for d in index_dims]
if len(group_by) == 1 and Version(pd.__version__) >= Version("1.5.0"):
# Because of this deprecation warning from pandas 1.5.0:
# In a future version of pandas, a length 1 tuple will be returned
# when iterating over a groupby with a grouper equal to a list of length 1.
# Don't supply a list with a single grouper to avoid this warning.
group_by = group_by[0]
data = [(k, group_type(v, **group_kwargs)) for k, v in
dataset.data.groupby(group_by, sort=False)]
if issubclass(container_type, NdMapping):
Expand All @@ -242,8 +251,22 @@ def aggregate(cls, dataset, dimensions, function, **kwargs):
else:
fn = function
if len(dimensions):
# The reason to use `numeric_cols` is to prepare for when pandas will not
# automatically drop columns that are not numerical for numerical
# functions, e.g., `np.mean`.
# pandas started warning about this in v1.5.0
if fn in [np.size]:
# np.size actually works with non-numerical columns
numeric_cols = [
c for c in reindexed.columns if c not in cols
]
else:
numeric_cols = [
c for c, d in zip(reindexed.columns, reindexed.dtypes)
if is_numeric_dtype(d) and c not in cols
]
grouped = reindexed.groupby(cols, sort=False)
df = grouped.aggregate(fn, **kwargs).reset_index()
df = grouped[numeric_cols].aggregate(fn, **kwargs).reset_index()
else:
agg = reindexed.apply(fn, **kwargs)
data = dict(((col, [v]) for col, v in zip(agg.index, agg.values)))
Expand Down
3 changes: 2 additions & 1 deletion holoviews/element/util.py
Original file line number Diff line number Diff line change
Expand Up @@ -302,9 +302,10 @@ def connect_tri_edges_pd(trimesh):
"""
edges = trimesh.dframe().copy()
edges.index.name = 'trimesh_edge_index'
edges = edges.reset_index()
edges = edges.drop("color", errors="ignore", axis=1).reset_index()
nodes = trimesh.nodes.dframe().copy()
nodes.index.name = 'node_index'
nodes = nodes.drop("color", errors="ignore", axis=1)
v1, v2, v3 = trimesh.kdims
x, y, idx = trimesh.nodes.kdims[:3]

Expand Down
7 changes: 6 additions & 1 deletion holoviews/plotting/mpl/chart3d.py
Original file line number Diff line number Diff line change
Expand Up @@ -64,7 +64,12 @@ def _finalize_axis(self, key, **kwargs):
self.handles['fig'].set_frameon(False)
axis.grid(self.show_grid)
axis.view_init(elev=self.elevation, azim=self.azimuth)
axis.dist = self.distance
try:
axis._dist = self.distance
except Exception:
# axis.dist is deprecated see here:
# https://github.com/matplotlib/matplotlib/pull/22084
axis.dist = self.distance

if self.xaxis is None:
axis.w_xaxis.line.set_lw(0.)
Expand Down
5 changes: 4 additions & 1 deletion holoviews/plotting/mpl/element.py
Original file line number Diff line number Diff line change
Expand Up @@ -544,7 +544,10 @@ def init_artists(self, ax, plot_args, plot_kwargs):
if 'norm' in plot_kwargs: # vmin/vmax should now be exclusively in norm
plot_kwargs.pop('vmin', None)
plot_kwargs.pop('vmax', None)
artist = plot_fn(*plot_args, **plot_kwargs)
with warnings.catch_warnings():
# scatter have a default cmap and with an empty array will emit this warning
warnings.filterwarnings('ignore', "No data for colormapping provided via 'c'")
artist = plot_fn(*plot_args, **plot_kwargs)
return {'artist': artist[0] if isinstance(artist, list) and
len(artist) == 1 else artist}

Expand Down
7 changes: 6 additions & 1 deletion holoviews/plotting/mpl/graphs.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
import warnings

import param
import numpy as np

Expand Down Expand Up @@ -168,7 +170,10 @@ def init_artists(self, ax, plot_args, plot_kwargs):
xs, ys = plot_args['nodes']
groups = [g for g in self._style_groups if g != 'node']
node_opts = filter_styles(plot_kwargs, 'node', groups)
nodes = ax.scatter(xs, ys, **node_opts)
with warnings.catch_warnings():
# scatter have a default cmap and with an empty array will emit this warning
warnings.filterwarnings('ignore', "No data for colormapping provided via 'c'")
nodes = ax.scatter(xs, ys, **node_opts)

return {'nodes': nodes, 'edges': edges}

Expand Down
2 changes: 1 addition & 1 deletion holoviews/plotting/mpl/heatmap.py
Original file line number Diff line number Diff line change
Expand Up @@ -349,7 +349,7 @@ def _pprint(dim_label, vals):
for i in range(len(xvals))[::-1]:
xbin = np.rad2deg(bins_segment[i:i+2])
width = ybin[1]-ybin[0]
wedge = Wedge((0.5, 0.5), ybin[1], xbin[0], xbin[1], width)
wedge = Wedge((0.5, 0.5), ybin[1], xbin[0], xbin[1], width=width)
patches.append(wedge)

angles = self._get_markers(segment_ticks, self.xmarks)
Expand Down
9 changes: 5 additions & 4 deletions holoviews/plotting/plotly/element.py
Original file line number Diff line number Diff line change
Expand Up @@ -520,10 +520,11 @@ def init_layout(self, key, element, ranges, is_geo=False):
x_delta = r - l
y_delta = t - b

max_x_zoom = (np.log2(max_delta / x_delta) -
np.log2(mapbox_tile_size / viewport_width))
max_y_zoom = (np.log2(max_delta / y_delta) -
np.log2(mapbox_tile_size / viewport_height))
with np.errstate(divide="ignore"):
max_x_zoom = (np.log2(max_delta / x_delta) -
np.log2(mapbox_tile_size / viewport_width))
max_y_zoom = (np.log2(max_delta / y_delta) -
np.log2(mapbox_tile_size / viewport_height))
mapbox["zoom"] = min(max_x_zoom, max_y_zoom)
layout["mapbox"] = mapbox

Expand Down
20 changes: 15 additions & 5 deletions holoviews/plotting/util.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
import bisect

from collections import defaultdict, namedtuple
from packaging.version import Version

import numpy as np
import param
Expand Down Expand Up @@ -547,18 +548,27 @@ def mplcmap_to_palette(cmap, ncolors=None, categorical=False):
"""
Converts a matplotlib colormap to palette of RGB hex strings."
"""
import matplotlib as mpl
from matplotlib.colors import Colormap, ListedColormap

ncolors = ncolors or 256
if not isinstance(cmap, Colormap):
import matplotlib.cm as cm
# Alias bokeh Category cmaps with mpl tab cmaps
if cmap.startswith('Category'):
cmap = cmap.replace('Category', 'tab')
try:
cmap = cm.get_cmap(cmap)
except:
cmap = cm.get_cmap(cmap.lower())

if Version(mpl.__version__) < Version("3.5"):
# This will stop working and can be removed
# when we do not support python 3.7
import matplotlib.cm as cm
try:
cmap = cm.get_cmap(cmap)
except:
cmap = cm.get_cmap(cmap.lower())
else:
from matplotlib import colormaps
cmap = colormaps.get(cmap, colormaps.get(cmap.lower()))

if isinstance(cmap, ListedColormap):
if categorical:
palette = [rgb2hex(cmap.colors[i%cmap.N]) for i in range(ncolors)]
Expand Down
28 changes: 16 additions & 12 deletions holoviews/tests/plotting/plotly/test_rgb.py
Original file line number Diff line number Diff line change
@@ -1,12 +1,22 @@
import numpy as np

import PIL.Image

from holoviews.element import RGB, Tiles

import plotly.graph_objs as go

from .test_plot import TestPlotlyPlot, plotly_renderer

try:
from PIL.Image import Transpose
FLIP_LEFT_RIGHT = Transpose.FLIP_LEFT_RIGHT
FLIP_TOP_BOTTOM = Transpose.FLIP_TOP_BOTTOM
ROTATE_90 = Transpose.ROTATE_90
ROTATE_270 = Transpose.ROTATE_270
except ImportError:
# Gives following deprecation warning:
# deprecated and will be removed in Pillow 10 (2023-07-01)
from PIL.Image import FLIP_LEFT_RIGHT, FLIP_TOP_BOTTOM, ROTATE_90, ROTATE_270


class TestRGBPlot(TestPlotlyPlot):

Expand Down Expand Up @@ -82,7 +92,7 @@ def test_rgb_invert_xaxis(self):
pil_img = self.rgb_element_to_pil_img(rgb.data)

# Flip left-to-right since x-axis is inverted
pil_img = pil_img.transpose(PIL.Image.FLIP_LEFT_RIGHT)
pil_img = pil_img.transpose(FLIP_LEFT_RIGHT)

expected_source = go.layout.Image(source=pil_img).source

Expand Down Expand Up @@ -122,9 +132,7 @@ def test_rgb_invert_xaxis_and_yaxis(self):
pil_img = self.rgb_element_to_pil_img(rgb.data)

# Flip left-to-right and top-to-bottom since both x-axis and y-axis are inverted
pil_img = (pil_img
.transpose(PIL.Image.FLIP_LEFT_RIGHT)
.transpose(PIL.Image.FLIP_TOP_BOTTOM))
pil_img = pil_img.transpose(FLIP_LEFT_RIGHT).transpose(FLIP_TOP_BOTTOM)

expected_source = go.layout.Image(source=pil_img).source

Expand Down Expand Up @@ -164,9 +172,7 @@ def test_rgb_invert_axes(self):
pil_img = self.rgb_element_to_pil_img(rgb.data)

# Flip left-to-right and top-to-bottom since both x-axis and y-axis are inverted
pil_img = (pil_img
.transpose(PIL.Image.ROTATE_90)
.transpose(PIL.Image.FLIP_LEFT_RIGHT))
pil_img = pil_img.transpose(ROTATE_90).transpose(FLIP_LEFT_RIGHT)

expected_source = go.layout.Image(source=pil_img).source

Expand Down Expand Up @@ -206,9 +212,7 @@ def test_rgb_invert_xaxis_and_yaxis_and_axes(self):
pil_img = self.rgb_element_to_pil_img(rgb.data)

# Flip left-to-right and top-to-bottom since both x-axis and y-axis are inverted
pil_img = (pil_img
.transpose(PIL.Image.ROTATE_270)
.transpose(PIL.Image.FLIP_LEFT_RIGHT))
pil_img = pil_img.transpose(ROTATE_270).transpose(FLIP_LEFT_RIGHT)

expected_source = go.layout.Image(source=pil_img).source

Expand Down
11 changes: 9 additions & 2 deletions holoviews/tests/plotting/test_plotutils.py
Original file line number Diff line number Diff line change
Expand Up @@ -476,8 +476,15 @@ def test_mpl_colormap_name_palette(self):
self.assertEqual(colors, ['#ffffff', '#959595', '#000000'])

def test_mpl_colormap_instance(self):
from matplotlib.cm import get_cmap
cmap = get_cmap('Greys')
try:
from matplotlib import colormaps
cmap = colormaps.get('Greys')
except ImportError:
# This will stop working and can be removed
# when we do not support python 3.7
from matplotlib.cm import get_cmap
cmap = get_cmap('Greys')

colors = process_cmap(cmap, 3, provider='matplotlib')
self.assertEqual(colors, ['#ffffff', '#959595', '#000000'])

Expand Down
4 changes: 2 additions & 2 deletions holoviews/tests/test_annotators.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
from holoviews import Overlay
from holoviews.annotators import annotate, PointAnnotator, PathAnnotator
from holoviews.element import Points, Path, Table
from holoviews.element.tiles import Wikipedia, Tiles
from holoviews.element.tiles import EsriStreet, Tiles

from holoviews.tests.plotting.bokeh.test_plot import TestBokehPlot

Expand All @@ -25,7 +25,7 @@ def test_compose_annotators(self):
self.assertEqual(len(tables), 3)

def test_annotate_overlay(self):
layout = annotate(Wikipedia() * Points([]), annotations=['Label'])
layout = annotate(EsriStreet() * Points([]), annotations=['Label'])

overlay = layout.DynamicMap.I[()]
tables = layout.Annotator.PointAnnotator[()]
Expand Down
9 changes: 8 additions & 1 deletion holoviews/tests/util/test_transform.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
Unit tests for dim transforms
"""
import pickle
import warnings

from collections import OrderedDict
from unittest import skipIf
Expand Down Expand Up @@ -462,7 +463,13 @@ def test_pandas_str_accessor(self):

def test_pandas_chained_methods(self):
expr = dim('int').df.rolling(1).mean()
self.assert_apply(expr, self.linear_ints.rolling(1).mean())

with warnings.catch_warnings():
# The kwargs is {'axis': None} and is already handled by the code.
# This context manager can be removed, when it raises an TypeError instead of warning.
warnings.simplefilter("ignore", "Passing additional kwargs to Rolling.mean")
self.assert_apply(expr, self.linear_ints.rolling(1).mean())


@xr_skip
def test_xarray_namespace_method_repr(self):
Expand Down
Loading

0 comments on commit 476f55c

Please sign in to comment.