Skip to content

Commit

Permalink
Merge branch 'main' into fix_ui_without_geoviews
Browse files Browse the repository at this point in the history
  • Loading branch information
maximlt committed Dec 12, 2024
2 parents 31df383 + c2f9d2b commit 757dfcf
Show file tree
Hide file tree
Showing 11 changed files with 109 additions and 69 deletions.
10 changes: 6 additions & 4 deletions .github/workflows/test.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -150,7 +150,7 @@ jobs:
matrix: ${{ fromJson(needs.setup.outputs.matrix) }}
defaults:
run:
shell: bash -l {0}
shell: bash -e {0}
steps:
- uses: actions/checkout@v4
with:
Expand All @@ -159,9 +159,11 @@ jobs:
with:
python-version: ${{ matrix.python-version }}
- name: install with geo
run: pip install -v --prefer-binary -e '.[tests, examples-tests, geo, hvdev, hvdev-geo, dev-extras]'
- name: pip list
run: pip list
run: python -m pip install -v --prefer-binary -e '.[tests, examples-tests, geo, hvdev, hvdev-geo, dev-extras]'
- name: python version and pip list
run: |
python --version --version
python -m pip list
- name: bokeh sampledata
if: ${{ matrix.python-version == '3.9'}}
run: bokeh sampledata
Expand Down
75 changes: 34 additions & 41 deletions .pre-commit-config.yaml
Original file line number Diff line number Diff line change
@@ -1,48 +1,41 @@
# This is the configuration for pre-commit, a local framework for managing pre-commit hooks
# Check out the docs at: https://pre-commit.com/

default_stages: [commit]
default_stages: [pre-commit]
repos:
- repo: https://github.com/nbQA-dev/nbQA
rev: 1.8.5
- repo: https://github.com/pre-commit/pre-commit-hooks
rev: v5.0.0
hooks:
- id: nbqa-ruff
additional_dependencies: [ruff==0.3.7]
- repo: https://github.com/pre-commit/pre-commit-hooks
rev: v4.6.0
hooks:
- id: check-builtin-literals
- id: check-case-conflict
- id: check-docstring-first
- id: check-executables-have-shebangs
- id: check-toml
- id: detect-private-key
- id: end-of-file-fixer
- id: check-builtin-literals
- id: check-case-conflict
- id: check-docstring-first
- id: check-executables-have-shebangs
- id: check-toml
- id: detect-private-key
- id: end-of-file-fixer
exclude: (\.min\.js$|\.svg$)
- id: trailing-whitespace
- repo: https://github.com/astral-sh/ruff-pre-commit
rev: v0.3.7
- id: trailing-whitespace
- repo: https://github.com/astral-sh/ruff-pre-commit
rev: v0.7.2
hooks:
- id: ruff
- id: ruff-format
- repo: https://github.com/hoxbro/clean_notebook
rev: v0.1.14
- id: ruff
- id: ruff-format
exclude: \.ipynb$
- repo: https://github.com/hoxbro/clean_notebook
rev: v0.1.15
hooks:
- id: clean-notebook
args: [-i, tags]
- repo: https://github.com/codespell-project/codespell
rev: v2.2.6
- id: clean-notebook
args: [-i, tags]
- repo: https://github.com/codespell-project/codespell
rev: v2.3.0
hooks:
- id: codespell
exclude: (\.min\.js$|\.svg$|\.html$)
additional_dependencies:
- tomli
- repo: local
- id: codespell
exclude: (\.min\.js$|\.svg$|\.html$)
additional_dependencies:
- tomli
- repo: local
hooks:
- id: update_conda_envs
name: Update conda envs
entry: python scripts/update_conda_envs.py
language: python
additional_dependencies: [pyproject2conda]
files: '(pyproject.toml|update_conda_envs)'
pass_filenames: false
- id: update_conda_envs
name: Update conda envs
entry: python scripts/update_conda_envs.py
language: python
additional_dependencies: [pyproject2conda]
files: "(pyproject.toml|update_conda_envs)"
pass_filenames: false
2 changes: 1 addition & 1 deletion doc/user_guide/Explorer.ipynb
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,7 @@
"id": "2f572b55-5002-4b81-9c92-6a2b56e2cde2",
"metadata": {},
"source": [
"For an explorer to be displayed in a notebook you need to load the hvPlot extension, which happens automatically when you execute an import like `import hvplot.pandas`. You could also just run `hvplot.extension('bokeh')`. If instead of building Bokeh plots you would rather build Matplotlib or Plotly plots, simply execute once `hvplot.extension('matplotlib')` or `hvplot.extension('matplotlib')` before displaying the explorer."
"For an explorer to be displayed in a notebook you need to load the hvPlot extension, which happens automatically when you execute an import like `import hvplot.pandas`. You could also just run `hvplot.extension('bokeh')`. If instead of building Bokeh plots you would rather build Matplotlib or Plotly plots, simply execute once `hvplot.extension('matplotlib')` or `hvplot.extension('plotly')` before displaying the explorer."
]
},
{
Expand Down
4 changes: 2 additions & 2 deletions doc/user_guide/Geographic_Data.ipynb
Original file line number Diff line number Diff line change
Expand Up @@ -60,7 +60,7 @@
"source": [
"## Tiled web map\n",
"\n",
"A [tiled web map](https://en.wikipedia.org/wiki/Tiled_web_map), or tile map, is an interactive map displayed on a web browser that is divided into small, pre-rendered image tiles, allowing for efficient loading and seamless navigation across various zoom levels and geographic areas. hvPlot allows to add a tile map as a basemap to a plot with the `tiles` parameter. Importantly, `tiles` is a parameter that can be used **without installing GeoViews**.\n",
"A [tiled web map](https://en.wikipedia.org/wiki/Tiled_web_map), or tile map, is an interactive map displayed on a web browser that is divided into small, pre-rendered image tiles, allowing for efficient loading and seamless navigation across various zoom levels and geographic areas. hvPlot allows us to add a tile map as a basemap to a plot with the `tiles` parameter. Importantly, `tiles` is a parameter that can be used **without installing GeoViews**.\n",
"\n",
"We'll display this dataframe of all US airports (including military bases overseas), the points are expressed in latitude/longitude coordinates:"
]
Expand All @@ -80,7 +80,7 @@
"source": [
"We'll first start by displaying the airports **without GeoViews** with tiles by setting `tiles=True`. \n",
"\n",
"Under the hood, hvPlot projects lat/lon to easting/northing ([EPSG:4326](https://epsg.io/4326) to [EPSG:3857](https://epsg.io/3857)) coordinates without additional package dependencies if it detects that the values falls within expected lat/lon ranges, **unless the data is lazily loaded (dask / ibis).**\n",
"Under the hood, hvPlot projects lat/lon to easting/northing ([EPSG:4326](https://epsg.io/4326) to [EPSG:3857](https://epsg.io/3857)) coordinates without additional package dependencies if it detects that the values falls within expected lat/lon ranges, **unless the data is lazily loaded (dask / ibis), or the data is a spatialpandas object.**\n",
"\n",
"Note, **this feature is only available after `hvplot>=0.11.0`**; older versions, `hvplot<0.11.0`, require manual projection (see below)."
]
Expand Down
10 changes: 5 additions & 5 deletions doc/user_guide/NetworkX.ipynb
Original file line number Diff line number Diff line change
Expand Up @@ -270,10 +270,10 @@
"\n",
"print(\"radius: %d\" % nx.radius(G))\n",
"print(\"diameter: %d\" % nx.diameter(G))\n",
"print(\"eccentricity: %s\" % nx.eccentricity(G))\n",
"print(\"center: %s\" % nx.center(G))\n",
"print(\"periphery: %s\" % nx.periphery(G))\n",
"print(\"density: %s\" % nx.density(G))\n",
"print(f\"eccentricity: {nx.eccentricity(G)}\")\n",
"print(f\"center: {nx.center(G)}\")\n",
"print(f\"periphery: {nx.periphery(G)}\")\n",
"print(f\"density: {nx.density(G)}\")\n",
"\n",
"hvnx.draw(G, with_labels=True)"
]
Expand Down Expand Up @@ -757,7 +757,7 @@
" edge_width=5.0\n",
" )\n",
" other_edges.append(edge)\n",
" plots.append((g*edges*hv.Overlay(other_edges)).relabel(\"p = %6.3f\" % (p)))\n",
" plots.append((g*edges*hv.Overlay(other_edges)).relabel(f\"p = {p:6.3f}\"))\n",
"\n",
"hv.Layout(plots).cols(2)"
]
Expand Down
25 changes: 17 additions & 8 deletions hvplot/converter.py
Original file line number Diff line number Diff line change
Expand Up @@ -77,6 +77,7 @@
_convert_col_names_to_str,
import_datashader,
import_geoviews,
is_mpl_cmap,
)
from .utilities import hvplot_extension

Expand Down Expand Up @@ -1414,7 +1415,7 @@ def _process_style(self, kwds, plot_opts):
valid_opts = []

cmap_opts = ('cmap', 'colormap', 'color_key')
categories = [
categorical_cmaps = [
'accent',
'category',
'dark',
Expand Down Expand Up @@ -1479,7 +1480,13 @@ def _process_style(self, kwds, plot_opts):
if 'color' in style_opts:
color = style_opts['color']
elif not isinstance(cmap, dict):
if cmap and any(c in cmap for c in categories):
# Checks if any of the categorical cmaps matches cmap;
# uses any() instead of `cmap in categorical_cmaps` to handle reversed colormaps (suffixed with `_r`).
# If cmap is LinearSegmentedColormap, get the name attr, else return the str typed cmap.
if (isinstance(cmap, str) or is_mpl_cmap(cmap)) and any(
categorical_cmap in getattr(cmap, 'name', cmap)
for categorical_cmap in categorical_cmaps
):
color = process_cmap(cmap or self._default_cmaps['categorical'], categorical=True)
else:
color = cmap
Expand Down Expand Up @@ -2164,12 +2171,13 @@ def _process_tiles_without_geo(self, data, x, y):
elif not is_geodataframe(data) and (x is None or y is None):
return data, x, y

if is_geodataframe(data):
if data.crs is not None:
data = data.to_crs(epsg=3857)
return data, x, y
elif not is_lazy_data(data):
if is_lazy_data(data):
# To prevent eager evaluation: https://github.com/holoviz/hvplot/pull/1432
pass
elif is_geodataframe(data):
if getattr(data, 'crs', None) is not None:
data = data.to_crs(epsg=3857)
else:
min_x = np.min(data[x])
max_x = np.max(data[x])
min_y = np.min(data[y])
Expand All @@ -2187,7 +2195,8 @@ def _process_tiles_without_geo(self, data, x, y):
data[new_y] = northing
if is_xarray(data):
data = data.swap_dims({x: new_x, y: new_y})
return data, new_x, new_y
x = new_x
y = new_y
return data, x, y

def chart(self, element, x, y, data=None):
Expand Down
3 changes: 2 additions & 1 deletion hvplot/plotting/scatter_matrix.py
Original file line number Diff line number Diff line change
Expand Up @@ -113,10 +113,11 @@ def scatter_matrix(
raise ValueError('dynspread or spread need rasterize or datashade to be set to True.')

if rasterize:
import datashader as ds
import holoviews.operation.datashader as hd

if dynspread or spread:
if hd.ds_version < Version('0.12.0'):
if Version(ds.__version__) < Version('0.12.0'):
raise RuntimeError(
'Any version of datashader less than 0.12.0 does '
'not support rasterize with dynspread or spread.'
Expand Down
11 changes: 11 additions & 0 deletions hvplot/tests/testcharts.py
Original file line number Diff line number Diff line change
Expand Up @@ -606,3 +606,14 @@ def test_table_datetime_index_displayed(self):

def test_table_multi_index_displayed(self):
raise SkipTest('Dask does not support MultiIndex Dataframes.')


def test_cmap_LinearSegmentedColormap():
# test for https://github.com/holoviz/hvplot/pull/1461
xr = pytest.importorskip('xarray')
mpl = pytest.importorskip('matplotlib')
import hvplot.xarray # noqa

data = np.arange(25).reshape(5, 5)
xr_da = xr.DataArray(data)
xr_da.hvplot.image(cmap=mpl.colormaps['viridis'])
21 changes: 21 additions & 0 deletions hvplot/tests/testgeowithoutgv.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,12 +8,19 @@
import pandas as pd
import pytest

from hvplot.util import is_geodataframe

try:
import dask.dataframe as dd
import hvplot.dask # noqa
except ImportError:
dd = None

try:
import spatialpandas as spd
except ModuleNotFoundError:
spd = None


bk_renderer = hv.Store.renderers['bokeh']

Expand Down Expand Up @@ -83,3 +90,17 @@ def test_plot_with_dask(self, simple_df):
assert isinstance(plot.get(0), hv.Tiles)
bk_plot = bk_renderer.get_plot(plot)
assert bk_plot.projection == 'mercator'

@pytest.mark.skipif(spd is None, reason='spatialpandas not installed')
def test_plot_without_crs(self):
square = spd.geometry.Polygon([(0.0, 0), (0, 1), (1, 1), (1, 0)])
sdf = spd.GeoDataFrame({'geometry': spd.GeoSeries([square, square]), 'name': ['A', 'B']})
plot = sdf.hvplot.polygons(tiles=True)

assert len(plot) == 2
assert is_geodataframe(sdf)
assert not hasattr(sdf, 'crs')
assert isinstance(plot.get(0), hv.Tiles)
assert isinstance(plot.get(1), hv.Polygons)
bk_plot = bk_renderer.get_plot(plot)
assert bk_plot.projection == 'mercator' # projection enabled due to `tiles=True`
9 changes: 9 additions & 0 deletions hvplot/util.py
Original file line number Diff line number Diff line change
Expand Up @@ -763,3 +763,12 @@ def relabel_redim(hv_obj, relabel_kwargs, redim_kwargs):
if redim_kwargs:
hv_obj = hv_obj.redim(**redim_kwargs)
return hv_obj


def is_mpl_cmap(obj):
"""Check if the object is a Matplotlib LinearSegmentedColormap."""
if 'matplotlib' not in sys.modules:
return False
from matplotlib.colors import LinearSegmentedColormap

return isinstance(obj, LinearSegmentedColormap)
8 changes: 1 addition & 7 deletions pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -196,7 +196,7 @@ filterwarnings = [
]

[tool.codespell]
ignore-words-list = "ser"
ignore-words-list = "ser,assertIn"
skip = "doc/generate_modules.py"
write-changes = true

Expand All @@ -211,12 +211,6 @@ extend-select = [
[tool.ruff.format]
quote-style = "single"

[tool.nbqa.addopts]
# E402 Module level import not at top of file
ruff = [
"--extend-ignore=E402"
]

[tool.pyproject2conda.dependencies]
geoviews = { skip = true, packages = "geoviews-core >=1.9.0" }
# It should be ibis-framework[duckdb], but it works anyway.
Expand Down

0 comments on commit 757dfcf

Please sign in to comment.