Skip to content

Commit

Permalink
Revise circ_diff function (#12)
Browse files Browse the repository at this point in the history
* Revise circ_diff function

* fixing type hints for poe

* add test_within_bin()

* update test_calc_wsratio_v_wd_scen

expected result is different due to new circ_diff function

* bump version

increase version because results can be slightly different with new circ_diff method

* update smarteole_example.ipynb

ensure outputs are up to date with new circ_diff
minor improvements to plots

* Update smarteole_example.ipynb

---------

Co-authored-by: aclerc <[email protected]>
  • Loading branch information
paulf81 and aclerc authored Jul 9, 2024
1 parent 5cd8fcb commit 3ebf2c9
Show file tree
Hide file tree
Showing 13 changed files with 287 additions and 298 deletions.
481 changes: 242 additions & 239 deletions examples/smarteole_example.ipynb

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion pyproject.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[project]
name = "res-wind-up"
version = "0.1.6"
version = "0.1.7"
authors = [
{ name = "Alex Clerc", email = "[email protected]" }
]
Expand Down
Binary file not shown.
5 changes: 1 addition & 4 deletions tests/test_detrend.py
Original file line number Diff line number Diff line change
Expand Up @@ -98,7 +98,4 @@ def test_calc_wsratio_v_wd_scen(test_lsa_t13_config: WindUpConfig) -> None:
plot_cfg=None,
)

# on Github Actions get error DataFrame.iloc[:, 0] (column name="hours") values are different (0.13889 %)
# At positional index 50, first diff: 45.5 != 45.666666666666664
# therefore set rtol=5e-3 so the test passes on Github Actions
assert_frame_equal(actual_pre_df, expected_pre_df, rtol=5e-3)
assert_frame_equal(actual_pre_df, expected_pre_df)
7 changes: 7 additions & 0 deletions tests/test_math_funcs.py
Original file line number Diff line number Diff line change
Expand Up @@ -24,3 +24,10 @@ def test_circ_diff(angle1: float | np.generic, angle2: float | np.generic, expec
assert_series_equal(circ_diff(angle1, angle2), (expected))
else:
assert circ_diff(angle1, angle2) == pytest.approx(expected)


def test_within_bin() -> None:
# this test replicates logic in detrend.py where an older version of circ_diff gets the wrong result
d = 242
dir_bin_width = 10.0
assert not np.abs(circ_diff(d - 5, d)) < dir_bin_width / 2
1 change: 1 addition & 0 deletions wind_up/constants.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
RANDOM_SEED = 0
SCATTER_S = 1
SCATTER_ALPHA = 0.2
SCATTER_MARKERSCALE = 4


class DataColumns:
Expand Down
30 changes: 19 additions & 11 deletions wind_up/math_funcs.py
Original file line number Diff line number Diff line change
@@ -1,14 +1,22 @@
import numpy as np
import numpy.typing as npt


def circ_diff(angle1: float | np.generic, angle2: float | np.generic) -> float | np.generic:
angle1_rad = np.radians(angle1)
angle2_rad = np.radians(angle2)
sin_angle1 = np.sin(angle1_rad)
cos_angle1 = np.cos(angle1_rad)
sin_angle2 = np.sin(angle2_rad)
cos_angle2 = np.cos(angle2_rad)
denominator = cos_angle2 * cos_angle2 + sin_angle2 * sin_angle2
temp1 = (cos_angle1 * cos_angle2 + sin_angle1 * sin_angle2) / denominator
temp2 = (sin_angle1 * cos_angle2 - cos_angle1 * sin_angle2) / denominator
return np.degrees(np.arctan2(temp2, temp1))
def circ_diff(angle1: float | npt.NDArray | list, angle2: float | npt.NDArray | list) -> float | npt.NDArray:
"""Calculate the circular difference between two angles.
Args:
angle1: First angle in degrees.
angle2: Second angle in degrees.
Returns:
Circular difference between the two angles in degrees
"""

# Convert list to numpy array
if isinstance(angle1, list):
angle1 = np.array(angle1)
if isinstance(angle2, list):
angle2 = np.array(angle2)

return np.mod(angle1 - angle2 + 180, 360) - 180
10 changes: 5 additions & 5 deletions wind_up/plots/detrend_plots.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
import pandas as pd
from matplotlib import pyplot as plt

from wind_up.constants import SCATTER_ALPHA, SCATTER_S
from wind_up.constants import SCATTER_ALPHA, SCATTER_MARKERSCALE, SCATTER_S
from wind_up.models import PlotConfig
from wind_up.result_manager import result_manager

Expand Down Expand Up @@ -116,7 +116,7 @@ def plot_apply_wsratio_v_wd_scen(
)
plot_title = f"{test_name} {ref_name} detrended wind speed {title_end}"
plt.title(plot_title)
plt.legend()
plt.legend(loc="best", markerscale=SCATTER_MARKERSCALE)
plt.xlabel("ref wind speed [m/s]")
plt.ylabel(f"{test_ws_col} [m/s]")
plt.grid()
Expand All @@ -132,7 +132,7 @@ def plot_apply_wsratio_v_wd_scen(
plt.scatter(p_df[detrend_ws_col], p_df[test_pw_col], s=SCATTER_S, alpha=SCATTER_ALPHA, label="after detrend")
plot_title = f"{test_name} {ref_name} detrended power curve {title_end}"
plt.title(plot_title)
plt.legend()
plt.legend(loc="best", markerscale=SCATTER_MARKERSCALE)
plt.xlabel("ref wind speed [m/s]")
plt.ylabel(f"{test_pw_col} [kW]")
plt.grid()
Expand Down Expand Up @@ -176,7 +176,7 @@ def plot_check_detrend_scatters(
plt.xlabel("ref wind speed before/after detrend [m/s]")
plt.ylabel(f"{test_ws_col} [m/s]")
plt.grid()
plt.legend(fontsize="small")
plt.legend(fontsize="small", loc="best", markerscale=SCATTER_MARKERSCALE)
plt.subplot(2, 1, 2)
r2_before = post_df[ref_ws_col].corr(post_df[test_ws_col]) ** 2
r2_after = post_df[detrend_ws_col].corr(post_df[test_ws_col]) ** 2
Expand All @@ -197,7 +197,7 @@ def plot_check_detrend_scatters(
plt.xlabel("ref wind speed before/after detrend [m/s]")
plt.ylabel(f"{test_ws_col} [m/s]")
plt.grid()
plt.legend(fontsize="small")
plt.legend(fontsize="small", loc="best", markerscale=SCATTER_MARKERSCALE)
plot_title = f"{test_name} vs {ref_name} wind speed detrend check"
plt.suptitle(plot_title)
plt.tight_layout()
Expand Down
33 changes: 3 additions & 30 deletions wind_up/plots/pp_analysis_plots.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
import numpy as np
import pandas as pd

from wind_up.constants import RAW_WINDSPEED_COL, SCATTER_ALPHA, SCATTER_S, DataColumns
from wind_up.constants import RAW_WINDSPEED_COL, SCATTER_ALPHA, SCATTER_MARKERSCALE, SCATTER_S, DataColumns
from wind_up.models import PlotConfig
from wind_up.result_manager import result_manager

Expand Down Expand Up @@ -129,7 +129,7 @@ def plot_pre_post_power_curves(
plt.figure()
plt.scatter(pre_df[ws_col], pre_df[pw_col], s=SCATTER_S, alpha=SCATTER_ALPHA, label="pre upgrade")
plt.scatter(post_df[ws_col], post_df[pw_col], s=SCATTER_S, alpha=SCATTER_ALPHA, label="post upgrade")
plt.legend()
plt.legend(loc="best", markerscale=SCATTER_MARKERSCALE)
plt.grid()
plot_title = f"test={test_name} ref={ref_name} power curve data"
plt.title(plot_title)
Expand Down Expand Up @@ -302,41 +302,14 @@ def plot_pre_post_conditions(
plt.close()

wd_width = 30
plt.figure()
plt.hist(
pre_df[wd_col],
weights=[1 / rows_per_hour] * len(pre_df[wd_col]),
bins=list(np.arange(0, 360 + wd_width / 2, wd_width)),
label="pre",
)
plt.hist(
post_df[wd_col],
weights=[1 / rows_per_hour] * len(post_df[wd_col]),
bins=list(np.arange(0, 360 + wd_width / 2, wd_width)),
alpha=0.5,
label="post",
)
plot_title = f"{test_name} {ref_name} {wd_col} coverage"
plt.title(plot_title)
plt.xticks(np.arange(wd_width / 2, 360 + wd_width / 2, wd_width))
plt.ylabel("hours")
plt.legend()
plt.grid()
plt.tight_layout()
if plot_cfg.show_plots:
plt.show()
if plot_cfg.save_plots:
plt.savefig(plot_cfg.plots_dir / test_name / f"{plot_title}.png")
plt.close()

plot_pre_post_condition_histogram(
pre_df,
post_df,
test_name=test_name,
ref_name=ref_name,
rows_per_hour=rows_per_hour,
col=wd_col,
bin_width=30,
bin_width=wd_width,
plot_cfg=plot_cfg,
first_bin_start=0,
last_bin_end=360,
Expand Down
6 changes: 3 additions & 3 deletions wind_up/plots/scada_funcs_plots.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
import seaborn as sns
from tabulate import tabulate

from wind_up.constants import SCATTER_ALPHA, SCATTER_S, DataColumns
from wind_up.constants import SCATTER_ALPHA, SCATTER_MARKERSCALE, SCATTER_S, DataColumns
from wind_up.models import PlotConfig, WindUpConfig
from wind_up.plots.misc_plots import bubble_plot

Expand Down Expand Up @@ -239,7 +239,7 @@ def plot_toggle_ops_curves_one_ttype_or_wtg(
plt.xlabel(f"{ws_col} [m/s]")
plt.ylabel(f"{pw_col} [kW]")
plt.grid()
plt.legend()
plt.legend(loc="best", markerscale=SCATTER_MARKERSCALE)
if plot_cfg.show_plots:
plt.show()
if plot_cfg.save_plots:
Expand Down Expand Up @@ -268,7 +268,7 @@ def plot_toggle_ops_curves_one_ttype_or_wtg(
plt.xlabel(f"{pw_col} [kW]")
plt.ylabel(f"{rpm_col} [RPM]")
plt.grid()
plt.legend()
plt.legend(loc="best", markerscale=SCATTER_MARKERSCALE)

plt.subplot(2, 2, 2)
plt.scatter(df_off[ws_col], df_off[rpm_col], s=SCATTER_S, alpha=SCATTER_ALPHA)
Expand Down
4 changes: 2 additions & 2 deletions wind_up/plots/scada_power_curve_plots.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import matplotlib.pyplot as plt
import pandas as pd

from wind_up.constants import RAW_POWER_COL, RAW_WINDSPEED_COL, SCATTER_ALPHA, SCATTER_S
from wind_up.constants import RAW_POWER_COL, RAW_WINDSPEED_COL, SCATTER_ALPHA, SCATTER_MARKERSCALE, SCATTER_S
from wind_up.models import PlotConfig, WindUpConfig


Expand Down Expand Up @@ -50,7 +50,7 @@ def plot_removed_data_one_ttype_or_wtg(
plt.title(plot_title)
plt.xlabel(f"{RAW_WINDSPEED_COL} [m/s]")
plt.ylabel(f"{RAW_POWER_COL} [kW]")
plt.legend()
plt.legend(loc="best", markerscale=SCATTER_MARKERSCALE)
plt.grid()
plt.tight_layout()
if plot_cfg.show_plots:
Expand Down
4 changes: 2 additions & 2 deletions wind_up/plots/waking_state_plots.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import matplotlib.pyplot as plt
import pandas as pd

from wind_up.constants import RAW_POWER_COL, RAW_WINDSPEED_COL, SCATTER_ALPHA, SCATTER_S
from wind_up.constants import RAW_POWER_COL, RAW_WINDSPEED_COL, SCATTER_ALPHA, SCATTER_MARKERSCALE, SCATTER_S
from wind_up.models import PlotConfig


Expand Down Expand Up @@ -36,7 +36,7 @@ def plot_waking_state_one_ttype_or_wtg(wf_df: pd.DataFrame, ttype_or_wtg: str, p
plot_title = f"{ttype_or_wtg} power curve by waking state"
plt.title(plot_title)
plt.grid()
plt.legend(loc="lower right")
plt.legend(loc="lower right", markerscale=SCATTER_MARKERSCALE)
plt.tight_layout()
if plot_cfg.show_plots:
plt.show()
Expand Down
2 changes: 1 addition & 1 deletion wind_up/plots/yaw_direction_plots.py
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@ def plot_yaw_direction_pre_post_per_signal(
plt.xlabel(f"{ref_wd_col} [deg]")
plt.ylabel(f"{test_wd_col} [deg]")
plt.grid()
plt.legend()
plt.legend(loc="best", markerscale=2)

plt.subplot(2, 1, 2)
plt.scatter(
Expand Down

0 comments on commit 3ebf2c9

Please sign in to comment.