Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .github/workflows/full_test.yml
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ jobs:

- uses: astral-sh/ruff-action@v2
with:
version: 0.6.2
version: 0.14.5
src: src

- name: Set up uv
Expand Down
6 changes: 3 additions & 3 deletions pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,7 @@ classifiers = [
dev = [
"pytest",
"plotly >= 4.5",
"ruff==0.6.2",
"ruff==0.14.5",
"quarto-cli==1.5.57",
"quartodoc==0.11.1",
"netCDF4",
Expand All @@ -70,8 +70,8 @@ notebooks = ["nbformat", "nbconvert", "jupyter", "plotly", "shapely", "seaborn"]


[tool.ruff.lint]
ignore = ["E501"]
select = ["E4", "E7", "E9", "F", "D200", "D205"]
ignore = ["E501", "PD011"]
select = ["E4", "E7", "E9", "F", "D200", "D205", "NPY", "PD"]

[tool.mypy]
python_version = "3.10"
Expand Down
6 changes: 6 additions & 0 deletions src/modelskill/comparison/_collection_plotter.py
Original file line number Diff line number Diff line change
Expand Up @@ -72,6 +72,7 @@ def scatter(
xlabel: Optional[str] = None,
ylabel: Optional[str] = None,
skill_table: Optional[Union[str, List[str], Mapping[str, str], bool]] = None,
random_state: Optional[int] = None,
ax: Optional[Axes] = None,
**kwargs,
) -> Axes | list[Axes]:
Expand Down Expand Up @@ -138,6 +139,8 @@ def scatter(
This kword adds a box at the right of the scatter plot.
mapping can be used to rename the metrics in the table.
by default False
random_state : int, optional
random seed for point sampling, by default None
ax : matplotlib axes, optional
axes to plot on, by default None
**kwargs
Expand Down Expand Up @@ -176,6 +179,7 @@ def scatter(
xlabel=xlabel,
ylabel=ylabel,
skill_table=skill_table,
random_state=random_state,
ax=ax,
**kwargs,
)
Expand All @@ -201,6 +205,7 @@ def _scatter_one_model(
xlabel: Optional[str],
ylabel: Optional[str],
skill_table: Optional[Union[str, List[str], Mapping[str, str], bool]],
random_state: Optional[int] = None,
ax,
**kwargs,
):
Expand Down Expand Up @@ -268,6 +273,7 @@ def _scatter_one_model(
skill_scores=skill_scores,
skill_score_unit=skill_score_unit,
ax=ax,
random_state=random_state,
**kwargs,
)

Expand Down
13 changes: 12 additions & 1 deletion src/modelskill/comparison/_comparer_plotter.py
Original file line number Diff line number Diff line change
Expand Up @@ -476,6 +476,7 @@ def scatter(
xlabel: Optional[str] = None,
ylabel: Optional[str] = None,
skill_table: Optional[Union[str, List[str], Mapping[str, str], bool]] = None,
random_state: Optional[int] = None,
ax: Optional[matplotlib.axes.Axes] = None,
**kwargs,
) -> matplotlib.axes.Axes | list[matplotlib.axes.Axes]:
Expand Down Expand Up @@ -542,6 +543,8 @@ def scatter(
modelskill.options.metrics.list. This kword adds a box at the
right of the scatter plot, by default False
mapping can be used to rename the metrics in the table.
random_state : int, optional
random seed for point sampling, by default None
ax : matplotlib.axes.Axes, optional
axes to plot on, by default None
**kwargs
Expand Down Expand Up @@ -581,6 +584,7 @@ def scatter(
ylabel=ylabel,
skill_table=skill_table,
ax=ax,
random_state=random_state,
**kwargs,
)
axes.append(ax_mod)
Expand Down Expand Up @@ -746,7 +750,14 @@ def taylor(
df = df.rename(columns={"_std_obs": "obs_std", "_std_mod": "std"})

pts = [
TaylorPoint(name=r.model, obs_std=r.obs_std, std=r.std, cc=r.cc, marker=marker, marker_size=marker_size)
TaylorPoint(
name=r.model,
obs_std=r.obs_std,
std=r.std,
cc=r.cc,
marker=marker,
marker_size=marker_size,
)
for r in df.itertuples()
]

Expand Down
2 changes: 1 addition & 1 deletion src/modelskill/comparison/_comparison.py
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,7 @@ def _parse_dataset(data: xr.Dataset) -> xr.Dataset:
assert "Observation" in data.data_vars

# no missing values allowed in Observation
if data["Observation"].isnull().any():
if data["Observation"].isnull().any(): # noqa: PD003
raise ValueError("Observation data must not contain missing values.")

# coordinates
Expand Down
2 changes: 1 addition & 1 deletion src/modelskill/metrics.py
Original file line number Diff line number Diff line change
Expand Up @@ -632,7 +632,7 @@ def peak_ratio(
}
)
df_filter["Maximum"] = df_filter.max(axis=1)
df_filter.sort_values(by="Maximum", ascending=False, inplace=True)
df_filter = df_filter.sort_values(by="Maximum", ascending=False)
# Finally we do the selection of the N- largest peaks from either model or measured
df_filter = df_filter.iloc[0:top_n_peaks, :]
# Rename to avoid further refactoring
Expand Down
6 changes: 3 additions & 3 deletions src/modelskill/model/dfsu.py
Original file line number Diff line number Diff line change
Expand Up @@ -219,7 +219,7 @@ def _extract_point(

# TODO not sure why we rename here
assert self.name is not None
ds_model.rename({ds_model.items[0].name: self.name}, inplace=True)
ds_model = ds_model.rename({ds_model.items[0].name: self.name})

return PointModelResult(
data=ds_model,
Expand Down Expand Up @@ -268,7 +268,7 @@ def _extract_track(

if isinstance(self.data, mikeio.DataArray):
ds_model = self.data.extract_track(track=track, method=method)
ds_model.rename({self.data.name: self.name}, inplace=True)
ds_model = ds_model.rename({self.data.name: self.name})
aux_items = None
else:
if isinstance(self.data, mikeio.dfsu.Dfsu2DH):
Expand All @@ -279,7 +279,7 @@ def _extract_track(
ds_model = self.data[self.sel_items.all].extract_track(
track=track, method=method
)
ds_model.rename({self.sel_items.values: self.name}, inplace=True)
ds_model = ds_model.rename({self.sel_items.values: self.name})
aux_items = self.sel_items.aux

item_names = [i.name for i in ds_model.items]
Expand Down
26 changes: 6 additions & 20 deletions src/modelskill/plotting/_misc.py
Original file line number Diff line number Diff line change
Expand Up @@ -53,25 +53,11 @@ def _xyticks(n_sectors=8, lim=None):


def sample_points(
x: np.ndarray, y: np.ndarray, show_points: bool | int | float | None = None
x: np.ndarray,
y: np.ndarray,
show_points: bool | int | float | None = None,
random_state: int | None = None,
) -> Tuple[np.ndarray, np.ndarray]:
"""Sample points to be plotted

Parameters
----------
x: np.ndarray, 1d
y: np.ndarray, 1d
include: bool, int or float, optional
default is subset the data to 50k points

Returns
-------
np.ndarray, np.ndarray
x and y arrays with sampled points
"""

assert len(x) == len(y), "x and y must have same length"

if show_points is True:
return x, y

Expand Down Expand Up @@ -104,8 +90,8 @@ def sample_points(
show_points = len(x)
n_samples = show_points

np.random.seed(20) # TODO should this be a parameter?
ran_index = np.random.choice(range(len(x)), n_samples, replace=False)
rng = np.random.default_rng(seed=random_state)
ran_index = rng.choice(range(len(x)), n_samples, replace=False)
x_sample = x[ran_index]
y_sample = y[ran_index]

Expand Down
5 changes: 4 additions & 1 deletion src/modelskill/plotting/_scatter.py
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,7 @@ def scatter(
skill_scores: Mapping[str, float] | None = None,
skill_score_unit: Optional[str] = "",
ax: Optional[Axes] = None,
random_state: Optional[int] = None,
**kwargs,
) -> Axes:
"""Scatter plot tailored for model skill comparison.
Expand Down Expand Up @@ -120,6 +121,8 @@ def scatter(
unit for skill_scores, by default None
ax : matplotlib.axes.Axes, optional
axes to plot on, by default None
random_state : int, optional
random seed for point sampling, by default None
**kwargs

Returns
Expand Down Expand Up @@ -155,7 +158,7 @@ def scatter(
if norm is None:
norm = colors.PowerNorm(vmin=1, gamma=0.5)

x_sample, y_sample = sample_points(x, y, show_points)
x_sample, y_sample = sample_points(x, y, show_points, random_state=random_state)
show_points = len(x_sample) > 0
xq, yq = quantiles_xy(x, y, quantiles)

Expand Down
4 changes: 2 additions & 2 deletions src/modelskill/skill.py
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,7 @@ def _name_to_title_in_kwargs(self, kwargs: Any) -> None:
def _get_plot_df(self, level: int | str = 0) -> pd.DataFrame:
ser = self.skillarray._ser
if isinstance(ser.index, pd.MultiIndex):
df = ser.unstack(level=level)
df = ser.unstack(level=level) # noqa: PD010
else:
df = ser.to_frame()
return df
Expand Down Expand Up @@ -226,7 +226,7 @@ def grid(
# TODO raise error?
return None
# df = self.df[field] TODO: at_least_2d...
df = ser.unstack()
df = ser.unstack() # noqa: PD010

vmin = None
vmax = None
Expand Down
6 changes: 3 additions & 3 deletions tests/plot/test_plot.py
Original file line number Diff line number Diff line change
Expand Up @@ -122,9 +122,9 @@ def test_format_skill_table():

@pytest.fixture
def x_y():
np.random.seed(42)
x = np.random.rand(100000)
y = np.random.rand(100000)
rng = np.random.default_rng(seed=42)
x = rng.random(100000)
y = rng.random(100000)
return x, y


Expand Down
2 changes: 1 addition & 1 deletion tests/test_comparercollection.py
Original file line number Diff line number Diff line change
Expand Up @@ -455,7 +455,7 @@ def test_save_and_load_preserves_raw_model_data(cc, tmp_path):


def test_plot_scatter(cc):
ax = cc.plot.scatter(skill_table=True)
ax = cc.plot.scatter(skill_table=True, random_state=20)
assert ax is not None


Expand Down