From 66027a1e68e04c6dcf1f7cef430e4bbac61f4cf0 Mon Sep 17 00:00:00 2001 From: RHammond2 <13874373+RHammond2@users.noreply.github.com> Date: Tue, 6 Feb 2024 15:33:33 -0800 Subject: [PATCH 1/3] run pyupgrade --py38-plus against codebase --- openoa/analysis/aep.py | 24 +++++-------- openoa/analysis/electrical_losses.py | 4 +-- .../turbine_long_term_gross_energy.py | 7 ++-- openoa/analysis/wake_losses.py | 4 +-- openoa/analysis/yaw_misalignment.py | 2 +- openoa/logging.py | 2 +- openoa/plant.py | 12 +++---- openoa/utils/imputing.py | 2 +- openoa/utils/plot.py | 34 ++++++++----------- openoa/utils/qa.py | 2 +- 10 files changed, 39 insertions(+), 54 deletions(-) diff --git a/openoa/analysis/aep.py b/openoa/analysis/aep.py index 6f5f0290..89f6c523 100644 --- a/openoa/analysis/aep.py +++ b/openoa/analysis/aep.py @@ -229,7 +229,7 @@ def __attrs_post_init__(self): else: analysis_type = "MonteCarloAEP" - if set((analysis_type, "all")).intersection(self.plant.analysis_type) == set(): + if {analysis_type, "all"}.intersection(self.plant.analysis_type) == set(): self.plant.analysis_type.append(analysis_type) # Ensure the data are up to spec before continuing with initialization @@ -370,7 +370,7 @@ def run( num_sim=self.num_sim, reanalysis_products=self.reanalysis_products, ) - logger.info("Running with parameters: {}".format(logged_params)) + logger.info(f"Running with parameters: {logged_params}") # Start the computation self.calculate_long_term_losses() @@ -563,11 +563,9 @@ def process_reanalysis_data(self): if self.end_date_lt > end_date: raise ValueError( - ( - "Invalid end date for long-term correction. The end date cannot exceed the " - "last full time period (defined by the time resolution) in the provided " - "reanalysis data." - ) + "Invalid end date for long-term correction. The end date cannot exceed the " + "last full time period (defined by the time resolution) in the provided " + "reanalysis data." ) else: # replace end date @@ -592,17 +590,13 @@ def process_reanalysis_data(self): if self._reanalysis_aggregate.index[0] > start_date_required: if self.end_date_lt is not None: raise ValueError( - ( - "Invalid end date argument for long-term correction. This end date does not " - "provide enough reanalysis data for the long-term correction." - ) + "Invalid end date argument for long-term correction. This end date does not " + "provide enough reanalysis data for the long-term correction." ) else: raise ValueError( - ( - "The date range of the provided reanalysis data is not long enough to " - "perform the long-term correction." - ) + "The date range of the provided reanalysis data is not long enough to " + "perform the long-term correction." ) # Correct each reanalysis product, density-correct wind speeds, and take monthly averages diff --git a/openoa/analysis/electrical_losses.py b/openoa/analysis/electrical_losses.py index 63dbf574..0c3b0e43 100644 --- a/openoa/analysis/electrical_losses.py +++ b/openoa/analysis/electrical_losses.py @@ -108,7 +108,7 @@ def __attrs_post_init__(self): """ Initialize logging and post-initialization setup steps. """ - if set(("ElectricalLosses", "all")).intersection(self.plant.analysis_type) == set(): + if {"ElectricalLosses", "all"}.intersection(self.plant.analysis_type) == set(): self.plant.analysis_type.append("ElectricalLosses") # Ensure the data are up to spec before continuing with initialization @@ -371,7 +371,7 @@ def plot_monthly_losses( std = losses.std() ax.plot( losses * 100, - label=f"Electrical Losses\n$\mu$={mean:.2%}, $\sigma$={std:.2%}", # noqa: W605 + label=f"Electrical Losses\n$\\mu$={mean:.2%}, $\\sigma$={std:.2%}", # noqa: W605 **plot_kwargs, ) diff --git a/openoa/analysis/turbine_long_term_gross_energy.py b/openoa/analysis/turbine_long_term_gross_energy.py index 8c9106b6..ba793f29 100644 --- a/openoa/analysis/turbine_long_term_gross_energy.py +++ b/openoa/analysis/turbine_long_term_gross_energy.py @@ -155,10 +155,7 @@ def __attrs_post_init__(self): """ Runs any non-automated setup steps for the analysis class. """ - if ( - set(("TurbineLongTermGrossEnergy", "all")).intersection(self.plant.analysis_type) - == set() - ): + if {"TurbineLongTermGrossEnergy", "all"}.intersection(self.plant.analysis_type) == set(): self.plant.analysis_type.append("TurbineLongTermGrossEnergy") # Ensure the data are up to spec before continuing with initialization @@ -431,7 +428,7 @@ def setup_daily_reanalysis_data(self) -> None: # Capture the runs reanalysis data set and ensure the U/V components exist reanalysis_df = self.plant.reanalysis[self._run.reanalysis_product] - if len(set(("WMETR_HorWdSpdU", "WMETR_HorWdSpdV")).intersection(reanalysis_df.columns)) < 2: + if len({"WMETR_HorWdSpdU", "WMETR_HorWdSpdV"}.intersection(reanalysis_df.columns)) < 2: ( reanalysis_df["WMETR_HorWdSpdU"], reanalysis_df["WMETR_HorWdSpdV"], diff --git a/openoa/analysis/wake_losses.py b/openoa/analysis/wake_losses.py index ba98afc9..14ea09bd 100644 --- a/openoa/analysis/wake_losses.py +++ b/openoa/analysis/wake_losses.py @@ -322,10 +322,10 @@ def __attrs_post_init__(self): logger.info("Initializing WakeLosses analysis object") if self.wind_direction_data_type == "scada": - if set(("WakeLosses-scada", "all")).intersection(self.plant.analysis_type) == set(): + if {"WakeLosses-scada", "all"}.intersection(self.plant.analysis_type) == set(): self.plant.analysis_type.append("WakeLosses-scada") if self.wind_direction_data_type == "tower": - if set(("WakeLosses-tower", "all")).intersection(self.plant.analysis_type) == set(): + if {"WakeLosses-tower", "all"}.intersection(self.plant.analysis_type) == set(): self.plant.analysis_type.append("WakeLosses-tower") # Ensure the data are up to spec before continuing with initialization diff --git a/openoa/analysis/yaw_misalignment.py b/openoa/analysis/yaw_misalignment.py index d1053178..9521c37b 100644 --- a/openoa/analysis/yaw_misalignment.py +++ b/openoa/analysis/yaw_misalignment.py @@ -209,7 +209,7 @@ def __attrs_post_init__(self): """ Initialize logging and post-initialization setup steps. """ - if set(("StaticYawMisalignment", "all")).intersection(self.plant.analysis_type) == set(): + if {"StaticYawMisalignment", "all"}.intersection(self.plant.analysis_type) == set(): self.plant.analysis_type.append("StaticYawMisalignment") # Ensure the data are up to spec before continuing with initialization diff --git a/openoa/logging.py b/openoa/logging.py index 696ceedd..bdff6bd9 100644 --- a/openoa/logging.py +++ b/openoa/logging.py @@ -35,7 +35,7 @@ def _wrapper(self, *args, **kwargs): def logged_function_call(the_function, msg="call"): def _wrapper(*args, **kwargs): logger = logging.getLogger(the_function.__module__) - logger.debug("{}: {}".format(the_function.__name__, msg)) + logger.debug(f"{the_function.__name__}: {msg}") return the_function(*args, **kwargs) return _wrapper diff --git a/openoa/plant.py b/openoa/plant.py index ea43867f..8c68314b 100644 --- a/openoa/plant.py +++ b/openoa/plant.py @@ -79,10 +79,10 @@ def _analysis_filter( for k in reanalysis_keys: name = k.split("-")[1] col_map = getattr(metadata, key)[name].col_map - _add[k] = set([col_map[v] for v in value]) + _add[k] = {col_map[v] for v in value} else: col_map = getattr(metadata, key).col_map - column_requirements.update({key: set([col_map[v] for v in value])}) + column_requirements.update({key: {col_map[v] for v in value}}) column_requirements.update(_add) # Filter the missing columns, so only analysis-specific columns are provided @@ -148,7 +148,7 @@ def _compose_error_message( @logged_method_call def frequency_validator( actual_freq: str | int | float | None, - desired_freq: Optional[str | None | set[str]], + desired_freq: str | None | set[str] | None, exact: bool, ) -> bool: """Helper function to check if the actual datetime stamp frequency is valid compared @@ -173,11 +173,11 @@ def frequency_validator( return False if isinstance(desired_freq, str): - desired_freq = set([desired_freq]) + desired_freq = {desired_freq} # If an offset alias couldn't be found, then convert the desired frequency strings to seconds if not isinstance(actual_freq, str): - desired_freq = set([ts.offset_to_seconds(el) for el in desired_freq]) + desired_freq = {ts.offset_to_seconds(el) for el in desired_freq} if exact: return actual_freq in desired_freq @@ -987,7 +987,7 @@ def _validate_frequency(self, category: str = "all") -> list[str]: return invalid_freq @logged_method_call - def validate(self, metadata: Optional[dict | str | Path | PlantMetaData] = None) -> None: + def validate(self, metadata: dict | str | Path | PlantMetaData | None = None) -> None: """Secondary method to validate the plant data objects after loading or changing data with option to provide an updated `metadata` object/file as well diff --git a/openoa/utils/imputing.py b/openoa/utils/imputing.py index 5823d38b..03124ee7 100644 --- a/openoa/utils/imputing.py +++ b/openoa/utils/imputing.py @@ -67,7 +67,7 @@ def impute_data( """ final_col_name = deepcopy(target_col) if data is None: - if any((not isinstance(x, pd.DataFrame) for x in (target_data, reference_data))): + if any(not isinstance(x, pd.DataFrame) for x in (target_data, reference_data)): raise TypeError( "If `data` is not provided, then `ref_data` and `target_data` must be provided as pandas DataFrames." ) diff --git a/openoa/utils/plot.py b/openoa/utils/plot.py index 53e0c7d2..7b9da76f 100644 --- a/openoa/utils/plot.py +++ b/openoa/utils/plot.py @@ -1177,10 +1177,8 @@ def plot_wake_losses( plot_norm_energy = True else: raise ValueError( - ( - "The inputs `energy_data_por` and `energy_data_lt` must both have the same dimensions" - "as `efficiency_data_por` and `efficiency_data_lt`." - ) + "The inputs `energy_data_por` and `energy_data_lt` must both have the same dimensions" + "as `efficiency_data_por` and `efficiency_data_lt`." ) elif (energy_data_por is None) & (energy_data_lt is None): plot_norm_energy = False @@ -1509,7 +1507,7 @@ def plot_yaw_misalignment( ], color=curve_fit_color_code, linestyle="--", - label=f"Max. Power Vane Angle = {round(curve_fit_params_ws[:,i,1].mean(),1)}$^\circ$", # noqa: W605 + label=rf"Max. Power Vane Angle = {round(curve_fit_params_ws[:,i,1].mean(),1)}$^\circ$", # noqa: W605 ) yaw_mis_mean = np.round(np.mean(yaw_misalignment_ws[:, i]), 1) @@ -1517,10 +1515,8 @@ def plot_yaw_misalignment( yaw_mis_ub = np.round(np.percentile(yaw_misalignment_ws[:, i], 97.5), 1) ax.set_title( - ( - f"{ws} m/s\nYaw Misalignment = " - f"{yaw_mis_mean}$^\circ$ [{yaw_mis_lb}$^\circ$, {yaw_mis_ub}$^\circ$]" # noqa: W605 - ) + f"{ws} m/s\nYaw Misalignment = " + rf"{yaw_mis_mean}$^\circ$ [{yaw_mis_lb}$^\circ$, {yaw_mis_ub}$^\circ$]" # noqa: W605 ) else: norm_factor = curve_fit_params_ws[i, 0] @@ -1555,11 +1551,11 @@ def plot_yaw_misalignment( ], color=curve_fit_color_code, linestyle="--", - label=f"Max. Power Vane Angle = {round(curve_fit_params_ws[i,1],1)}$^\circ$", # noqa: W605 + label=rf"Max. Power Vane Angle = {round(curve_fit_params_ws[i,1],1)}$^\circ$", # noqa: W605 ) ax.set_title( - f"{ws} m/s\nYaw Misalignment = {np.round(yaw_misalignment_ws[i],1)}$^\circ$" # noqa: W605 + f"{ws} m/s\nYaw Misalignment = {np.round(yaw_misalignment_ws[i],1)}$^\\circ$" # noqa: W605 ) ax.plot( @@ -1570,7 +1566,7 @@ def plot_yaw_misalignment( ], color=mean_vane_color_code, linestyle="--", - label=f"Mean Vane Angle = {round(mean_vane_angle_ws[i],1)}$^\circ$", # noqa: W605 + label=rf"Mean Vane Angle = {round(mean_vane_angle_ws[i],1)}$^\circ$", # noqa: W605 ) ax.grid("on") @@ -1596,13 +1592,13 @@ def plot_yaw_misalignment( for i in range(len(ws_bins) % 3, 3): axs[last_row][i].remove() axs[last_row - 1][i].tick_params(labelbottom=True) - axs[last_row - 1][i].set_xlabel("Wind Vane Angle ($^\circ$)") # noqa: W605 + axs[last_row - 1][i].set_xlabel(r"Wind Vane Angle ($^\circ$)") # noqa: W605 for i in range(len(ws_bins) % 3): - axs[last_row][i].set_xlabel("Wind Vane Angle ($^\circ$)") # noqa: W605 + axs[last_row][i].set_xlabel(r"Wind Vane Angle ($^\circ$)") # noqa: W605 else: for i in range(N_col): - axs[last_row][i].set_xlabel("Wind Vane Angle ($^\circ$)") # noqa: W605 + axs[last_row][i].set_xlabel(r"Wind Vane Angle ($^\circ$)") # noqa: W605 mean_yaw_mis = np.round(np.mean(yaw_misalignment_ws), 1) if UQ: @@ -1610,14 +1606,12 @@ def plot_yaw_misalignment( np.percentile(np.mean(yaw_misalignment_ws, 1), [2.5, 97.5]), 1 ) fig.suptitle( - ( - f"Turbine {turbine_id}, Yaw Misalignment = {mean_yaw_mis}$^\circ$ " # noqa: W605 - f"[{yaw_misalignment_95CI[0]}$^\circ$, {yaw_misalignment_95CI[1]}$^\circ$]" # noqa: W605 - ) + rf"Turbine {turbine_id}, Yaw Misalignment = {mean_yaw_mis}$^\circ$ " # noqa: W605 + rf"[{yaw_misalignment_95CI[0]}$^\circ$, {yaw_misalignment_95CI[1]}$^\circ$]" # noqa: W605 ) else: fig.suptitle( - f"Turbine {turbine_id}, Mean Yaw Misalignment = {str(mean_yaw_mis)}$^\circ$" # noqa: W605 + rf"Turbine {turbine_id}, Mean Yaw Misalignment = {str(mean_yaw_mis)}$^\circ$" # noqa: W605 ) plt.tight_layout() diff --git a/openoa/utils/qa.py b/openoa/utils/qa.py index 00ac16c0..d98b9794 100644 --- a/openoa/utils/qa.py +++ b/openoa/utils/qa.py @@ -24,7 +24,7 @@ set_styling() -def _remove_tz(df: pd.DataFrame, t_local_column: str) -> Tuple[np.ndarray, np.ndarray]: +def _remove_tz(df: pd.DataFrame, t_local_column: str) -> tuple[np.ndarray, np.ndarray]: """Identify the non-timestamp elements in the DataFrame timestamp column and return a truth array for filtering the values and the timezone-naive timestamps. From 19b6a8b1af544467be9b1b67c73c1597e66f3fa1 Mon Sep 17 00:00:00 2001 From: RHammond2 <13874373+RHammond2@users.noreply.github.com> Date: Tue, 6 Feb 2024 15:44:14 -0800 Subject: [PATCH 2/3] add pyupgrade to pre-commit workflow --- .pre-commit-config.yaml | 5 +++++ setup.py | 3 ++- 2 files changed, 7 insertions(+), 1 deletion(-) diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index ee3a88db..0278cd3f 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -14,6 +14,11 @@ repos: additional_dependencies: [toml] types: [pyi] + - repo: https://github.com/asottile/pyupgrade + rev: v3.15.0 + hooks: + - id: pyupgrade + args: [--py38-plus] - repo: https://github.com/psf/black rev: 23.3.0 diff --git a/setup.py b/setup.py index 021d84e6..2fa23db8 100644 --- a/setup.py +++ b/setup.py @@ -50,6 +50,7 @@ "isort", "flake8", "flake8-docstrings", + "pyupgrade", ], "examples": [ "jupyterlab", @@ -70,7 +71,7 @@ # Read the version from the __init__.py file without importing it def read(*names, **kwargs): directory = Path(__file__).resolve().parent - with io.open(Path(directory, *names), encoding=kwargs.get("encoding", "utf8")) as fp: + with open(Path(directory, *names), encoding=kwargs.get("encoding", "utf8")) as fp: return fp.read() From 3a4108a935f4d07d6eb9d8422645ef4994dd9d08 Mon Sep 17 00:00:00 2001 From: RHammond2 <13874373+RHammond2@users.noreply.github.com> Date: Fri, 9 Feb 2024 16:25:10 -0800 Subject: [PATCH 3/3] fix bad fix --- openoa/plant.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/openoa/plant.py b/openoa/plant.py index 8c68314b..ff0bee56 100644 --- a/openoa/plant.py +++ b/openoa/plant.py @@ -148,7 +148,7 @@ def _compose_error_message( @logged_method_call def frequency_validator( actual_freq: str | int | float | None, - desired_freq: str | None | set[str] | None, + desired_freq: str | set[str] | None, exact: bool, ) -> bool: """Helper function to check if the actual datetime stamp frequency is valid compared