Skip to content

Commit

Permalink
Merge pull request #275 from jkittner/check-custom-bins
Browse files Browse the repository at this point in the history
check the provided bins arguments and raise an Error if wrong
  • Loading branch information
ocefpaf authored Jul 30, 2024
2 parents fcd9789 + 2b69967 commit fa46b03
Show file tree
Hide file tree
Showing 10 changed files with 61 additions and 12 deletions.
2 changes: 1 addition & 1 deletion notebooks/usage.ipynb
Original file line number Diff line number Diff line change
Expand Up @@ -483,7 +483,7 @@
"ws = np.random.random(N) * 6\n",
"wd = np.random.random(N) * 360\n",
"df = pd.DataFrame({\"speed\": ws, \"direction\": wd})\n",
"plot_windrose(df, kind=\"contour\", bins=np.arange(0.01, 8, 1), cmap=cm.hot, lw=3)"
"plot_windrose(df, kind=\"contour\", bins=np.arange(0, 8, 1), cmap=cm.hot, lw=3)"
]
},
{
Expand Down
8 changes: 4 additions & 4 deletions pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ requires = [
target-version = "py38"
line-length = 79

select = [
lint.select = [
"A", # flake8-builtins
"B", # flake8-bugbear
"C4", # flake8-comprehensions
Expand All @@ -19,13 +19,13 @@ select = [
"T20", # flake8-print
"UP", # upgrade
]
per-file-ignores."docs/conf.py" = [
lint.per-file-ignores."docs/conf.py" = [
"A001",
]
per-file-ignores."samples/example_by.py" = [
lint.per-file-ignores."samples/example_by.py" = [
"T201",
]
per-file-ignores."samples/example_pdf_by.py" = [
lint.per-file-ignores."samples/example_pdf_by.py" = [
"T201",
]

Expand Down
Binary file modified tests/output/oo/test_filled_with_colormap_calm_limit.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified tests/output/oo/test_filled_with_colormap_contours_calm_limit.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
24 changes: 24 additions & 0 deletions tests/test_windrose.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
import matplotlib.pyplot as plt
import numpy as np
import pandas as pd
import pytest
from numpy.testing import assert_allclose
from pandas.testing import assert_frame_equal

Expand Down Expand Up @@ -73,3 +74,26 @@ def test_theta_labels():
theta_labels = [t.get_text() for t in ax.get_xticklabels()]
assert theta_labels == ["a", "b", "c", "d", "e", "f", "g", "h"]
plt.close()


def test_windrose_incorrect_bins_specified():
ax = WindroseAxes.from_ax()
with pytest.raises(ValueError) as exc_info:
ax.bar(direction=wd, var=ws, bins=[1, 2, 3])

(msg,) = exc_info.value.args
assert msg == (
"the first value provided in bins must be less than or equal to the minimum "
"value of the wind speed data. Did you mean: bins=(0, 1, 2, 3) ? "
"If you want to exclude values below a certain threshold, "
"try setting calm_limit=1."
)


def test_windrose_incorrect_bins_in_combination_with_calm_limit():
ax = WindroseAxes.from_ax()
with pytest.raises(ValueError) as exc_info:
ax.bar(direction=wd, var=ws, bins=[1, 2, 3], calm_limit=2)

(msg,) = exc_info.value.args
assert msg == "the lowest value in bins must be >= 2 (=calm_limits)"
18 changes: 15 additions & 3 deletions tests/test_windrose_np_mpl_oo.py
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,8 @@ def test_windrose_stacked_histogram_not_normed_binned():
def test_windrose_stacked_histogram_not_normed_binned_calm_limit():
# Another stacked histogram representation, not normed, with bins limits and a calm limit
ax = WindroseAxes.from_ax()
ax.box(wd, ws, bins=bins, calm_limit=0.2)
# the bins most not be below the calm_limit
ax.box(wd, ws, bins=[0.2, 1, 2, 3, 4, 5, 6, 7], calm_limit=0.2)
ax.set_legend()
return ax.figure

Expand All @@ -76,7 +77,8 @@ def test_filled_with_colormap():
def test_filled_with_colormap_calm_limit():
# A windrose in filled representation, with a controlled colormap and a calm limit
ax = WindroseAxes.from_ax()
ax.contourf(wd, ws, bins=bins, cmap=cm.hot, calm_limit=0.2)
# the bins most not be below the calm_limit
ax.contourf(wd, ws, bins=[0.2, 1, 2, 3, 4, 5, 6, 7], cmap=cm.hot, calm_limit=0.2)
ax.set_legend()
return ax.figure

Expand All @@ -95,6 +97,8 @@ def test_filled_with_colormap_contours():
def test_filled_with_colormap_contours_calm_limit():
# Same as above, but with contours over each filled region...
ax = WindroseAxes.from_ax()
# the bins most not be below the calm_limit
bins = [0.2, 1, 2, 3, 4, 5, 6, 7]
ax.contourf(wd, ws, bins=bins, cmap=cm.hot, calm_limit=0.2)
ax.contour(wd, ws, bins=bins, colors="black", calm_limit=0.2)
ax.set_legend()
Expand All @@ -112,7 +116,15 @@ def test_without_filled_with_colormap_contours():
@pytest.mark.mpl_image_compare(baseline_dir="output/oo")
def test_without_filled_with_colormap_contours_calm_limit():
ax = WindroseAxes.from_ax()
ax.contour(wd, ws, bins=bins, cmap=cm.hot, lw=3, calm_limit=0.2)
# the bins most not be below the calm_limit
ax.contour(
wd,
ws,
bins=[0.2, 1, 2, 3, 4, 5, 6, 7],
cmap=cm.hot,
lw=3,
calm_limit=0.2,
)
ax.set_legend()
return ax.figure

Expand Down
8 changes: 4 additions & 4 deletions tests/test_windrose_pandas.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@
N = 500
ws = np.random.random(N) * 6
wd = np.random.random(N) * 360
bins = np.arange(0.01, 8, 1)
bins = np.arange(0, 8, 1)

df = pd.DataFrame({"speed": ws, "direction": wd})

Expand Down Expand Up @@ -45,21 +45,21 @@ def test_box():
@pytest.mark.mpl_image_compare(baseline_dir="output/df")
def test_contourf():
kind = "contourf"
ax = plot_windrose(df, kind=kind, bins=bins, cmap=cm.hot)
ax = plot_windrose(df, kind=kind, bins=np.arange(0.01, 8, 1), cmap=cm.hot)
return ax.figure


@pytest.mark.mpl_image_compare(baseline_dir="output/df")
def test_contour():
kind = "contour"
ax = plot_windrose(df, kind=kind, bins=bins, cmap=cm.hot, lw=3)
ax = plot_windrose(df, kind=kind, bins=np.arange(0.01, 8, 1), cmap=cm.hot, lw=3)
return ax.figure


@pytest.mark.mpl_image_compare(baseline_dir="output/df")
def test_pdf():
kind = "pdf"
ax, params = plot_windrose(df, kind=kind, bins=bins)
ax, params = plot_windrose(df, kind=kind, bins=np.arange(0.01, 8, 1))
return ax.figure


Expand Down
13 changes: 13 additions & 0 deletions windrose/windrose.py
Original file line number Diff line number Diff line change
Expand Up @@ -371,6 +371,19 @@ def _init_plot(self, direction, var, **kwargs):
bins = kwargs.pop("bins", None)
if bins is None:
bins = np.linspace(np.min(var), np.max(var), 6)
if isinstance(bins, (list, tuple, np.ndarray)):
if len(bins) > 0 and bins[0] > np.min(var) and not calm_limit:
raise ValueError(
f"the first value provided in bins must be less than or equal "
f"to the minimum value of the wind speed data. "
f"Did you mean: bins={(0, *bins)!r} ? "
f"If you want to exclude values below a certain threshold, "
f"try setting calm_limit={min(bins)}.",
)
elif len(bins) > 0 and calm_limit is not None and min(bins) < calm_limit:
raise ValueError(
f"the lowest value in bins must be >= {calm_limit} (=calm_limits)",
)
if isinstance(bins, int):
bins = np.linspace(np.min(var), np.max(var), bins)
bins = np.asarray(bins)
Expand Down

0 comments on commit fa46b03

Please sign in to comment.