Skip to content

Commit

Permalink
Use contourpy for Bokeh contour plots (#2104)
Browse files Browse the repository at this point in the history
* Add contourpy to optional requirements

* Update kdeplot.py

* fix contourpy

* enable contourpy_kwargs

* update changelog

* fix .at to .loc

* update error msg

* update test function docstring

* update requirements docs

* update bokeh markers

* add bokeh marker changes to changelog

* Apply suggestions from code review

Co-authored-by: Colin Carroll <ColCarroll@users.noreply.github.com>

* Try fixing pyling

Co-authored-by: Colin Carroll <ColCarroll@users.noreply.github.com>
Co-authored-by: Oriol Abril-Pla <oriol.abril.pla@gmail.com>
  • Loading branch information
3 people committed Sep 8, 2022
1 parent 5ca7643 commit 19782ac
Show file tree
Hide file tree
Showing 7 changed files with 54 additions and 25 deletions.
2 changes: 2 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,8 @@
* Add exception in `az.plot_hdi` for `x` of type `np.datetime64` and `smooth=True` ([2016](https://github.com/arviz-devs/arviz/pull/2016))
* Change `ax.plot` usage to `ax.scatter` in `plot_pair` ([1990](https://github.com/arviz-devs/arviz/pull/1990))
* Example data has been moved to the [arviz_example_data](https://github.com/arviz-devs/arviz_example_data) repository and is now included as a git submodule. ([2096](https://github.com/arviz-devs/arviz/pull/2096))
* Bokeh kde contour plots started to use `contourpy` package ([2104](https://github.com/arviz-devs/arviz/pull/2104))
* Update default Bokeh markers for rcparams ([2104](https://github.com/arviz-devs/arviz/pull/2104))

### Deprecation
* Removed `fill_last`, `contour` and `plot_kwargs` arguments from `plot_pair` function ([2085](https://github.com/arviz-devs/arviz/pull/2085))
Expand Down
16 changes: 12 additions & 4 deletions arviz/plots/backends/bokeh/kdeplot.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@
from collections.abc import Callable
from numbers import Integral

from matplotlib import _contour
import numpy as np
from bokeh.models import ColumnDataSource
from bokeh.models.glyphs import Scatter
Expand Down Expand Up @@ -151,6 +150,13 @@ def plot_kde(
glyphs.append(line)

else:
try:
import contourpy
except ImportError as err:
raise ImportError(
"'bokeh' kde contour plots needs ContourPy installed (pip install countourpy)."
) from err

contour_kwargs = _init_kwargs_dict(contour_kwargs)
contourf_kwargs = _init_kwargs_dict(contourf_kwargs)
pcolormesh_kwargs = _init_kwargs_dict(pcolormesh_kwargs)
Expand All @@ -162,8 +168,10 @@ def plot_kde(

scaled_density, *scaled_density_args = _scale_axis(density)

contour_generator = _contour.QuadContourGenerator(
x_x, y_y, scaled_density, None, True, 0
contourpy_kwargs = _init_kwargs_dict(contour_kwargs.pop("contourpy_kwargs", {}))
contourpy_kwargs.setdefault("name", "serial")
contour_generator = contourpy.contour_generator(
x=x_x, y=y_y, z=scaled_density, **contourpy_kwargs
)

levels = 9
Expand Down Expand Up @@ -199,7 +207,7 @@ def plot_kde(
contour_kwargs_ = contour_kwargs.copy()
contour_kwargs_.setdefault("line_color", color)
contour_kwargs_.setdefault("fill_color", color)
vertices, _ = contour_generator.create_filled_contour(level, level_upper)
vertices, _ = contour_generator.filled(level, level_upper)
for seg in vertices:
# ax.multi_polygon would be better, but input is
# currently not suitable
Expand Down
53 changes: 35 additions & 18 deletions arviz/rcparams.py
Original file line number Diff line number Diff line change
Expand Up @@ -153,23 +153,40 @@ def validate_with_none(value):

def _validate_bokeh_marker(value):
"""Validate the markers."""
all_markers = (
"Asterisk",
"Circle",
"CircleCross",
"CircleX",
"Cross",
"Dash",
"Diamond",
"DiamondCross",
"Hex",
"InvertedTriangle",
"Square",
"SquareCross",
"SquareX",
"Triangle",
"X",
)
try:
from bokeh.core.enums import MarkerType
except ImportError:
MarkerType = [
"asterisk",
"circle",
"circle_cross",
"circle_dot",
"circle_x",
"circle_y",
"cross",
"dash",
"diamond",
"diamond_cross",
"diamond_dot",
"dot",
"hex",
"hex_dot",
"inverted_triangle",
"plus",
"square",
"square_cross",
"square_dot",
"square_pin",
"square_x",
"star",
"star_dot",
"triangle",
"triangle_dot",
"triangle_pin",
"x",
"y",
]
all_markers = list(MarkerType)
if value not in all_markers:
raise ValueError(f"{value} is not one of {all_markers}")
return value
Expand Down Expand Up @@ -274,7 +291,7 @@ def validate_iterable(value):
"above",
_make_validate_choice({"above", "below", "left", "right"}, allow_none=True),
),
"plot.bokeh.marker": ("Cross", _validate_bokeh_marker),
"plot.bokeh.marker": ("cross", _validate_bokeh_marker),
"plot.bokeh.output_backend": ("webgl", _make_validate_choice({"canvas", "svg", "webgl"})),
"plot.bokeh.show": (True, _validate_boolean),
"plot.bokeh.tools": (
Expand Down
4 changes: 2 additions & 2 deletions arviz/stats/stats.py
Original file line number Diff line number Diff line change
Expand Up @@ -303,7 +303,7 @@ def gradient(weights):
d_std_err = np.sqrt(len(diff) * np.var(diff))
std_err = ses.loc[val]
weight = weights[idx]
df_comp.at[val] = (
df_comp.loc[val] = (
idx,
res[f"elpd_{ic}"],
res[p_ic],
Expand Down Expand Up @@ -1941,7 +1941,7 @@ def apply_test_function(
>>> import arviz as az
>>> idata = az.load_arviz_data("centered_eight")
>>> az.apply_test_function(idata, lambda y, theta: np.min(y))
>>> T = np.asscalar(idata.observed_data.T)
>>> T = idata.observed_data.T.item()
>>> az.plot_posterior(idata, var_names=["T"], group="posterior_predictive", ref_val=T)
"""
Expand Down
2 changes: 1 addition & 1 deletion arvizrc.template
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@ plot.bokeh.layout.sizing_mode: fixed # Responsive layout. One of "fixed",
# "scale_width", "scale_height", "scale_both"
plot.bokeh.layout.toolbar_location : above # Location for toolbar on layouts. "None" will hide the toolbar.
# One of "above", "below", "left", "right".
plot.bokeh.marker : Cross # specify the marker type used to plot
plot.bokeh.marker : cross # specify the marker type used to plot
plot.bokeh.output_backend : webgl # one of "canvas", "svg", "webgl"
plot.bokeh.show : true # call bokeh.plotting.show for figure or grid of figures. One of "true", "false"
plot.bokeh.tools : reset,pan,box_zoom,wheel_zoom,lasso_select,undo,save,hover
Expand Down
1 change: 1 addition & 0 deletions requirements-docs.txt
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ sphinx-panels
sphinx-notfound-page
sphinx-copybutton
bokeh
contourpy
sphinx_design
sphinx-codeautolink>=0.9.0
jupyter-sphinx
1 change: 1 addition & 0 deletions requirements-optional.txt
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
numba
bokeh>=1.4.0,<3.0
contourpy
ujson
dask[distributed]
zarr>=2.5.0

0 comments on commit 19782ac

Please sign in to comment.