diff --git a/.github/scripts/make_release.py b/.github/scripts/make_release.py index cdba6755ca..f9a024dee0 100644 --- a/.github/scripts/make_release.py +++ b/.github/scripts/make_release.py @@ -5,6 +5,7 @@ to create the new release. """ + import glob import re import subprocess diff --git a/.github/scripts/setup_devbranch.py b/.github/scripts/setup_devbranch.py index 2da814b92d..c7a1aa7e90 100644 --- a/.github/scripts/setup_devbranch.py +++ b/.github/scripts/setup_devbranch.py @@ -9,6 +9,7 @@ The changes are not commited to the repository. This is dealt with in the bash script `setup_devbranch.sh` (which is also the caller of this script). """ + import glob import json import re diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index f2fb5b3e54..096d0a0601 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -5,19 +5,17 @@ default_language_version: # See https://pre-commit.com/hooks.html for more hooks repos: - repo: https://github.com/pre-commit/pre-commit-hooks - rev: v3.2.0 + rev: v6.0.0 hooks: - id: end-of-file-fixer - id: trailing-whitespace - - repo: https://github.com/pycqa/isort - rev: '5.13.2' + - repo: https://github.com/astral-sh/ruff-pre-commit + rev: v0.14.5 hooks: - - id: isort - args: ["--profile", "black", "--filter-files"] - - # Using this mirror lets us use mypyc-compiled black, which is about 2x faster - - repo: https://github.com/psf/black-pre-commit-mirror - rev: '24.4.2' - hooks: - - id: black-jupyter + # Run the linter, applying safe fixes + # TODO: Enable once all existing issues are fixed + # - id: ruff-check + # args: [ --fix ] + # Run the formatter. + - id: ruff-format diff --git a/climada/engine/calibration_opt.py b/climada/engine/calibration_opt.py index 5f174b5f77..7fedc01a75 100644 --- a/climada/engine/calibration_opt.py +++ b/climada/engine/calibration_opt.py @@ -94,33 +94,28 @@ def calib_instance( for cnt_, year in years_in_common.iteritems(): df_out.loc[df_out["year"] == year, "impact_CLIMADA"] = iys[year] - else: # impact per event - if df_out.empty | df_out.index.shape[0] == 1: - for cnt_, impact in enumerate(impacts.at_event): - if cnt_ > 0: - df_out.loc[cnt_] = df_out.loc[0] # copy info from first row - df_out.loc[cnt_, "impact_CLIMADA"] = impact - df_out.loc[cnt_, "event_id"] = int(impacts.event_id[cnt_]) - df_out.loc[cnt_, "event_name"] = impacts.event_name[cnt_] - df_out.loc[cnt_, "year"] = dt.datetime.fromordinal( - impacts.date[cnt_] - ).year - df_out.loc[cnt_, "date"] = impacts.date[cnt_] - elif df_out.index.shape[0] == impacts.at_event.shape[0]: - for cnt_, (impact, ind) in enumerate(zip(impacts.at_event, df_out.index)): - df_out.loc[ind, "impact_CLIMADA"] = impact - df_out.loc[ind, "event_id"] = int(impacts.event_id[cnt_]) - df_out.loc[ind, "event_name"] = impacts.event_name[cnt_] - df_out.loc[ind, "year"] = dt.datetime.fromordinal( - impacts.date[cnt_] - ).year - df_out.loc[ind, "date"] = impacts.date[cnt_] - else: - raise ValueError( - "adding simulated impacts to reported impacts not" - " yet implemented. use yearly_impact=True or run" - " without init_impact_data." - ) + elif df_out.empty | df_out.index.shape[0] == 1: + for cnt_, impact in enumerate(impacts.at_event): + if cnt_ > 0: + df_out.loc[cnt_] = df_out.loc[0] # copy info from first row + df_out.loc[cnt_, "impact_CLIMADA"] = impact + df_out.loc[cnt_, "event_id"] = int(impacts.event_id[cnt_]) + df_out.loc[cnt_, "event_name"] = impacts.event_name[cnt_] + df_out.loc[cnt_, "year"] = dt.datetime.fromordinal(impacts.date[cnt_]).year + df_out.loc[cnt_, "date"] = impacts.date[cnt_] + elif df_out.index.shape[0] == impacts.at_event.shape[0]: + for cnt_, (impact, ind) in enumerate(zip(impacts.at_event, df_out.index)): + df_out.loc[ind, "impact_CLIMADA"] = impact + df_out.loc[ind, "event_id"] = int(impacts.event_id[cnt_]) + df_out.loc[ind, "event_name"] = impacts.event_name[cnt_] + df_out.loc[ind, "year"] = dt.datetime.fromordinal(impacts.date[cnt_]).year + df_out.loc[ind, "date"] = impacts.date[cnt_] + else: + raise ValueError( + "adding simulated impacts to reported impacts not" + " yet implemented. use yearly_impact=True or run" + " without init_impact_data." + ) if return_cost != "False": df_out = calib_cost_calc(df_out, return_cost) return df_out @@ -293,8 +288,7 @@ def init_impact_data( # em_data = emdat_impact_event(source_file) else: raise ValueError( - "init_impact_data not yet implemented for other impact_data_sources " - "than emdat." + "init_impact_data not yet implemented for other impact_data_sources than emdat." ) return em_data @@ -378,17 +372,16 @@ def calib_all( # prepare impact data if isinstance(impact_data_source, pd.DataFrame): df_impact_data = impact_data_source + elif list(impact_data_source.keys()) == ["emdat"]: + df_impact_data = init_impact_data( + hazard_type, + region_ids, + year_range, + impact_data_source["emdat"], + year_range[-1], + ) else: - if list(impact_data_source.keys()) == ["emdat"]: - df_impact_data = init_impact_data( - hazard_type, - region_ids, - year_range, - impact_data_source["emdat"], - year_range[-1], - ) - else: - raise ValueError("other impact data sources not yet implemented.") + raise ValueError("other impact data sources not yet implemented.") params_generator = ( dict(zip(param_full_dict, x)) for x in itertools.product(*param_full_dict.values()) @@ -460,17 +453,16 @@ def calib_optimize( # prepare impact data if isinstance(impact_data_source, pd.DataFrame): df_impact_data = impact_data_source + elif list(impact_data_source.keys()) == ["emdat"]: + df_impact_data = init_impact_data( + hazard_type, + region_ids, + year_range, + impact_data_source["emdat"], + year_range[-1], + ) else: - if list(impact_data_source.keys()) == ["emdat"]: - df_impact_data = init_impact_data( - hazard_type, - region_ids, - year_range, - impact_data_source["emdat"], - year_range[-1], - ) - else: - raise ValueError("other impact data sources not yet implemented.") + raise ValueError("other impact data sources not yet implemented.") # definie specific function to def specific_calib(values): diff --git a/climada/engine/cost_benefit.py b/climada/engine/cost_benefit.py index f1833d9b65..36ce023ad2 100644 --- a/climada/engine/cost_benefit.py +++ b/climada/engine/cost_benefit.py @@ -25,9 +25,9 @@ import logging from typing import Dict, Optional, Tuple, Union -import matplotlib.colors as colors import matplotlib.pyplot as plt import numpy as np +from matplotlib import colors from matplotlib.patches import FancyArrowPatch, Rectangle from tabulate import tabulate @@ -661,7 +661,7 @@ def plot_waterfall( ent_future, risk_func=risk_aai_agg, axis=None, - **kwargs + **kwargs, ): """Plot waterfall graph at future with given risk metric. Can be called before and after calc(). @@ -740,7 +740,7 @@ def plot_waterfall( 2, height=(risk_dev - curr_risk) / norm_fact, bottom=curr_risk / norm_fact, - **kwargs + **kwargs, ) axis.text( 2, @@ -755,7 +755,7 @@ def plot_waterfall( 3, height=(fut_risk - risk_dev) / norm_fact, bottom=risk_dev / norm_fact, - **kwargs + **kwargs, ) axis.text( 3, @@ -799,7 +799,7 @@ def plot_arrow_averted( risk_func=risk_aai_agg, disc_rates=None, imp_time_depen=1, - **kwargs + **kwargs, ): """Plot waterfall graph with accumulated values from present to future year. Call after calc() with save_imp=True. @@ -877,7 +877,7 @@ def plot_arrow_averted( tot_benefit, bars[3].get_height() * norm_fact, norm_fact, - **kwargs + **kwargs, ) def plot_waterfall_accumulated( @@ -888,7 +888,7 @@ def plot_waterfall_accumulated( risk_func=risk_aai_agg, imp_time_depen=1, axis=None, - **kwargs + **kwargs, ): """Plot waterfall graph with accumulated values from present to future year. Call after calc() with save_imp=True. Provide same inputs as in calc. @@ -976,7 +976,7 @@ def plot_waterfall_accumulated( 2, height=(risk_dev - risk_curr) / norm_fact, bottom=risk_curr / norm_fact, - **kwargs + **kwargs, ) axis.text( 2, @@ -991,7 +991,7 @@ def plot_waterfall_accumulated( 3, height=(risk_tot - risk_dev) / norm_fact, bottom=risk_dev / norm_fact, - **kwargs + **kwargs, ) axis.text( 3, @@ -1395,7 +1395,7 @@ def _plot_list_cost_ben(cb_list, axis=None, **kwargs): cb_res.benefit[meas_n] / norm_fact, 1 / cb_res.cost_ben_ratio[meas_n], color=cb_res.color_rgb[meas_n], - **kwargs + **kwargs, ) ) @@ -1489,7 +1489,7 @@ def _plot_averted_arrow(axis, bar_4, tot_benefit, risk_tot, norm_fact, **kwargs) bar_top[0] - (bar_top[0] - bar_bottom[0]) / 2, risk_tot / norm_fact - arrow_len, ), - **kwargs + **kwargs, ) ) diff --git a/climada/engine/forecast.py b/climada/engine/forecast.py index 49847cf5ee..72a89208a6 100644 --- a/climada/engine/forecast.py +++ b/climada/engine/forecast.py @@ -476,7 +476,7 @@ def _plot_imp_map( coord[:, 0], c=array_im, transform=ccrs.PlateCarree(), - **kwargs + **kwargs, ) if shapes: # add warning regions @@ -882,7 +882,7 @@ def _plot_exc_prob( coord[:, 0], c=array_im, transform=ccrs.PlateCarree(), - **kwargs + **kwargs, ) if shapes: # add warning regions diff --git a/climada/engine/impact.py b/climada/engine/impact.py index d8c944c7b9..feeb20f393 100644 --- a/climada/engine/impact.py +++ b/climada/engine/impact.py @@ -35,12 +35,12 @@ import contextily as ctx import geopandas as gpd import h5py -import matplotlib.animation as animation import matplotlib.pyplot as plt import numpy as np import pandas as pd import xlsxwriter from deprecation import deprecated +from matplotlib import animation from matplotlib.colors import Normalize from pandas.api.types import is_string_dtype from pyproj import CRS as pyprojCRS @@ -188,8 +188,7 @@ def __init__( ) if len(self.coord_exp) != len(self.eai_exp): raise AttributeError( - "Number of exposures points is different from" - "number of eai_exp values" + "Number of exposures points is different fromnumber of eai_exp values" ) if imp_mat is not None: self.imp_mat = imp_mat @@ -214,8 +213,7 @@ def calc( ): """This function is deprecated, use ``ImpactCalc.impact`` instead.""" LOGGER.warning( - "The use of Impact().calc() is deprecated." - " Use ImpactCalc().impact() instead." + "The use of Impact().calc() is deprecated. Use ImpactCalc().impact() instead." ) from climada.engine.impact_calc import ( # pylint: disable=import-outside-toplevel ImpactCalc, @@ -1238,8 +1236,9 @@ def plot_rp_imp( impacts_stats_vals = impacts_stats.values[:, 1:].T.astype(float) if not log10_scale: - min_impact, max_impact = np.nanmin(impacts_stats_vals), np.nanmax( - impacts_stats_vals + min_impact, max_impact = ( + np.nanmin(impacts_stats_vals), + np.nanmax(impacts_stats_vals), ) kwargs.update( { @@ -1471,7 +1470,6 @@ def write_csr(group, name, value): # Open file in write mode with h5py.File(file_path, "w") as file: - # Now write all attributes # NOTE: Remove leading underscore to write '_tot_value' as regular attribute for name, value in self.__dict__.items(): @@ -1612,8 +1610,7 @@ def from_excel(cls, file_name): def read_excel(self, *args, **kwargs): """This function is deprecated, use Impact.from_excel instead.""" LOGGER.warning( - "The use of Impact.read_excel is deprecated." - "Use Impact.from_excel instead." + "The use of Impact.read_excel is deprecated.Use Impact.from_excel instead." ) self.__dict__ = Impact.from_excel(*args, **kwargs).__dict__ @@ -1671,7 +1668,6 @@ def from_hdf5(cls, file_path: Union[str, Path]): """ kwargs = dict() with h5py.File(file_path, "r") as file: - # Impact matrix if "imp_mat" in file: impact_matrix = file["imp_mat"] diff --git a/climada/engine/impact_calc.py b/climada/engine/impact_calc.py index 0586166173..ad79dab40f 100644 --- a/climada/engine/impact_calc.py +++ b/climada/engine/impact_calc.py @@ -196,8 +196,7 @@ def impact( ) if insured: LOGGER.info( - "cover and/or deductible columns detected," - " going to calculate insured impact" + "cover and/or deductible columns detected, going to calculate insured impact" ) # TODO: make a better impact matrix generator for insured impacts when # the impact matrix is already present diff --git a/climada/engine/test/test_cost_benefit.py b/climada/engine/test/test_cost_benefit.py index e48afec110..becdf4c3f2 100644 --- a/climada/engine/test/test_cost_benefit.py +++ b/climada/engine/test/test_cost_benefit.py @@ -39,7 +39,6 @@ from climada.entity.measures.base import LOGGER as ILOG from climada.hazard.base import Hazard from climada.test import get_test_file -from climada.util.api_client import Client from climada.util.constants import ENT_DEMO_FUTURE, ENT_DEMO_TODAY ENT_TEST_MAT = get_test_file("demo_today", file_format="MAT-file") diff --git a/climada/engine/test/test_impact.py b/climada/engine/test/test_impact.py index 38b3def3d8..9f4305ebdb 100644 --- a/climada/engine/test/test_impact.py +++ b/climada/engine/test/test_impact.py @@ -1207,7 +1207,6 @@ def test__exp_build_event(self): class TestMatchCentroids(unittest.TestCase): - def test_match_centroids(self): "Test that hazard centroids get assigned correctly" exp = ENT.exposures diff --git a/climada/engine/test/test_impact_calc.py b/climada/engine/test/test_impact_calc.py index bd606c6e19..3c0c114ce0 100644 --- a/climada/engine/test/test_impact_calc.py +++ b/climada/engine/test/test_impact_calc.py @@ -35,7 +35,6 @@ from climada.entity.entity_def import Entity from climada.hazard.base import Centroids, Hazard from climada.test import get_test_file -from climada.util.api_client import Client from climada.util.config import Config from climada.util.constants import DEMO_DIR, ENT_DEMO_TODAY diff --git a/climada/engine/unsequa/calc_delta_climate.py b/climada/engine/unsequa/calc_delta_climate.py index 93fdfec969..29c411396d 100644 --- a/climada/engine/unsequa/calc_delta_climate.py +++ b/climada/engine/unsequa/calc_delta_climate.py @@ -235,8 +235,7 @@ def uncertainty( if unc_sample.samples_df.empty: raise ValueError( - "No sample was found. Please create one first" - "using UncImpact.make_sample(N)" + "No sample was found. Please create one firstusing UncImpact.make_sample(N)" ) # copy may not be needed, but is kept to prevent potential diff --git a/climada/engine/unsequa/calc_impact.py b/climada/engine/unsequa/calc_impact.py index 93d3fc6584..24d4e31ec6 100644 --- a/climada/engine/unsequa/calc_impact.py +++ b/climada/engine/unsequa/calc_impact.py @@ -197,8 +197,7 @@ def uncertainty( if unc_sample.samples_df.empty: raise ValueError( - "No sample was found. Please create one first" - "using UncImpact.make_sample(N)" + "No sample was found. Please create one firstusing UncImpact.make_sample(N)" ) # copy may not be needed, but is kept to prevent potential diff --git a/climada/engine/unsequa/input_var.py b/climada/engine/unsequa/input_var.py index 76e63d766e..f26b17a2db 100644 --- a/climada/engine/unsequa/input_var.py +++ b/climada/engine/unsequa/input_var.py @@ -798,9 +798,9 @@ def _impfset_uncfunc(IFi, MDD, PAA, IL, impf_set_list, haz_id_dict): + IFi, 0.0, ) - impf_set_tmp.get_func(haz_type=haz_type, fun_id=fun_id).intensity = ( - new_int - ) + impf_set_tmp.get_func( + haz_type=haz_type, fun_id=fun_id + ).intensity = new_int return impf_set_tmp @@ -866,7 +866,6 @@ def _ent_unc_func( exp_list, meas_set, ): - exposures = _exp_uncfunc(EN, ET, EL, exp_list, bounds_noise) impact_func_set = _impfset_uncfunc( IFi, MDD, PAA, IL, impf_set_list=impf_set_list, haz_id_dict=haz_id_dict diff --git a/climada/engine/unsequa/test/test_unsequa.py b/climada/engine/unsequa/test/test_unsequa.py index 1e7b965ed4..92686c8272 100755 --- a/climada/engine/unsequa/test/test_unsequa.py +++ b/climada/engine/unsequa/test/test_unsequa.py @@ -92,7 +92,6 @@ def haz_dem(x_haz=1, haz=None): def make_input_vars(): - exp = exp_dem exp_distr = { "x_exp": sp.stats.uniform(0.8, 2), @@ -127,7 +126,6 @@ def ent_fut_dem(): def make_costben_iv(): - entdem = ent_dem() ent_iv = InputVar.ent( impf_set_list=[entdem.impact_funcs], @@ -158,7 +156,6 @@ class TestInputVar(unittest.TestCase): """Test UncVar class""" def test_init_pass(self): - impf = impf_dem distr_dict = { "x_paa": sp.stats.beta(0.5, 1), @@ -169,7 +166,6 @@ def test_init_pass(self): self.assertTrue(isinstance(impf_iv.distr_dict, dict)) def test_evaluate_pass(self): - impf = impf_dem distr_dict = { "x_paa": sp.stats.beta(0.5, 1), @@ -225,7 +221,6 @@ def test_plot_pass(self): plt.close() def test_var_to_inputvar(self): - exp = exp_dem() distr_dict = {"x_exp": sp.stats.uniform(0.8, 1.2)} diff --git a/climada/engine/unsequa/unc_output.py b/climada/engine/unsequa/unc_output.py index 80a385395e..0bed6168f2 100644 --- a/climada/engine/unsequa/unc_output.py +++ b/climada/engine/unsequa/unc_output.py @@ -877,7 +877,7 @@ def plot_sensitivity( if not self.sensitivity_metrics: raise ValueError( - "No sensitivity present. " "Please run a sensitivity analysis first." + "No sensitivity present. Please run a sensitivity analysis first." ) if metric_list is None: @@ -989,8 +989,7 @@ def plot_sensitivity_second_order( if not self.sensitivity_metrics: raise ValueError( - "No sensitivity present for this metrics. " - "Please run a sensitivity analysis first." + "No sensitivity present for this metrics. Please run a sensitivity analysis first." ) if metric_list is None: @@ -1054,7 +1053,7 @@ def plot_sensitivity_second_order( j, i, str(round(s2_matrix[i, j], 2)) - + "\n\u00B1" # \u00B1 = +- + + "\n\u00b1" # \u00B1 = +- + str(round(s2_conf_matrix[i, j], 2)), ha="center", va="center", diff --git a/climada/entity/disc_rates/base.py b/climada/entity/disc_rates/base.py index e18daaf919..d21a660f1b 100755 --- a/climada/entity/disc_rates/base.py +++ b/climada/entity/disc_rates/base.py @@ -176,8 +176,7 @@ def net_present_value(self, ini_year, end_year, val_years): sel_disc = self.select(year_range) if sel_disc is None: raise ValueError( - "No information of discount rates for provided years:" - f" {ini_year} - {end_year}" + f"No information of discount rates for provided years: {ini_year} - {end_year}" ) return u_fin.net_present_value(sel_disc.years, sel_disc.rates, val_years) @@ -259,8 +258,7 @@ def from_mat(cls, file_name, var_names=None): def read_mat(self, *args, **kwargs): """This function is deprecated, use ``DiscRates.from_mat`` instead.""" LOGGER.warning( - "The use of DiscRates.read_mat is deprecated." - "Use DiscRates.from_mat instead." + "The use of DiscRates.read_mat is deprecated.Use DiscRates.from_mat instead." ) self.__dict__ = DiscRates.from_mat(*args, **kwargs).__dict__ @@ -305,8 +303,7 @@ def from_excel(cls, file_name, var_names=None): def read_excel(self, *args, **kwargs): """This function is deprecated, use DiscRates.from_excel instead.""" LOGGER.warning( - "The use of DiscRates.read_excel is deprecated." - "Use DiscRates.from_excel instead." + "The use of DiscRates.read_excel is deprecated.Use DiscRates.from_excel instead." ) self.__dict__ = DiscRates.from_excel(*args, **kwargs).__dict__ diff --git a/climada/entity/entity_def.py b/climada/entity/entity_def.py index d58af9efed..c57ea2c0a9 100755 --- a/climada/entity/entity_def.py +++ b/climada/entity/entity_def.py @@ -105,7 +105,7 @@ def from_mat(cls, file_name): def read_mat(self, *args, **kwargs): """This function is deprecated, use Entity.from_mat instead.""" LOGGER.warning( - "The use of Entity.read_mat is deprecated." "Use Entity.from_mat instead." + "The use of Entity.read_mat is deprecated.Use Entity.from_mat instead." ) self.__dict__ = Entity.from_mat(*args, **kwargs).__dict__ @@ -144,8 +144,7 @@ def from_excel(cls, file_name): def read_excel(self, *args, **kwargs): """This function is deprecated, use Entity.from_excel instead.""" LOGGER.warning( - "The use of Entity.read_excel is deprecated." - " Use Entity.from_excel instead." + "The use of Entity.read_excel is deprecated. Use Entity.from_excel instead." ) self.__dict__ = Entity.from_excel(*args, **kwargs).__dict__ diff --git a/climada/entity/exposures/base.py b/climada/entity/exposures/base.py index bc084628eb..554cfec809 100644 --- a/climada/entity/exposures/base.py +++ b/climada/entity/exposures/base.py @@ -480,7 +480,7 @@ def check(self): for var in sorted( set(self.vars_def).difference([INDICATOR_IMPF, INDICATOR_IMPF_OLD]) ): - if not var in self.gdf.columns: + if var not in self.gdf.columns: LOGGER.info("%s not set.", var) # special treatment for impf_* @@ -499,7 +499,7 @@ def check(self): # optional columns except centr_* for var in sorted(set(self.vars_opt).difference([INDICATOR_CENTR])): - if not var in self.gdf.columns: + if var not in self.gdf.columns: LOGGER.info("%s not set.", var) # special treatment for centr_* @@ -1175,8 +1175,7 @@ def write_hdf5(self, file_name): def read_hdf5(self, *args, **kwargs): """This function is deprecated, use Exposures.from_hdf5 instead.""" LOGGER.warning( - "The use of Exposures.read_hdf5 is deprecated." - "Use Exposures.from_hdf5 instead." + "The use of Exposures.read_hdf5 is deprecated.Use Exposures.from_hdf5 instead." ) self.__dict__ = Exposures.from_hdf5(*args, **kwargs).__dict__ @@ -1228,8 +1227,7 @@ def from_hdf5(cls, file_name): def read_mat(self, *args, **kwargs): """This function is deprecated, use Exposures.from_mat instead.""" LOGGER.warning( - "The use of Exposures.read_mat is deprecated." - "Use Exposures.from_mat instead." + "The use of Exposures.read_mat is deprecated.Use Exposures.from_mat instead." ) self.__dict__ = Exposures.from_mat(*args, **kwargs).__dict__ diff --git a/climada/entity/exposures/litpop/litpop.py b/climada/entity/exposures/litpop/litpop.py index c267d8817e..cd903c7119 100644 --- a/climada/entity/exposures/litpop/litpop.py +++ b/climada/entity/exposures/litpop/litpop.py @@ -94,8 +94,7 @@ def __init__( def set_countries(self, *args, **kwargs): """This function is deprecated, use LitPop.from_countries instead.""" LOGGER.warning( - "The use of LitPop.set_countries is deprecated." - "Use LitPop.from_countries instead." + "The use of LitPop.set_countries is deprecated.Use LitPop.from_countries instead." ) self.__dict__ = LitPop.from_countries(*args, **kwargs).__dict__ @@ -297,8 +296,7 @@ def from_countries( } except ValueError: LOGGER.warning( - "Could not write attribute meta, because exposure" - " has only 1 data point" + "Could not write attribute meta, because exposure has only 1 data point" ) exp.meta = {"crs": exp.crs} exp.check() @@ -409,8 +407,7 @@ def from_nightlight_intensity( def set_population(self, *args, **kwargs): """This function is deprecated, use LitPop.from_population instead.""" LOGGER.warning( - "The use of LitPop.set_population is deprecated." - "Use LitPop.from_population instead." + "The use of LitPop.set_population is deprecated.Use LitPop.from_population instead." ) self.__dict__ = LitPop.from_population(*args, **kwargs).__dict__ @@ -680,8 +677,7 @@ def from_shape_and_countries( def set_custom_shape(self, *args, **kwargs): """This function is deprecated, use LitPop.from_shape instead.""" LOGGER.warning( - "The use of LitPop.set_custom_shape is deprecated." - "Use LitPop.from_shape instead." + "The use of LitPop.set_custom_shape is deprecated.Use LitPop.from_shape instead." ) self.__dict__ = LitPop.from_shape(*args, **kwargs).__dict__ @@ -1219,8 +1215,7 @@ def _get_total_value_per_country(cntry_iso3a, fin_mode, reference_year): return None if fin_mode == "pop": raise NotImplementedError( - "`_get_total_value_per_country` is not " - "implemented for `fin_mode` == 'pop'." + "`_get_total_value_per_country` is not implemented for `fin_mode` == 'pop'." ) if fin_mode == "pc": return u_fin.world_bank_wealth_account( @@ -1589,8 +1584,7 @@ def _calc_admin1_one_country( grp_values = _grp_read(iso3a, admin1_info=admin1_info, data_dir=data_dir) if grp_values is None: LOGGER.error( - "No subnational GRP data found for calc_admin1" - " for country %s. Skipping.", + "No subnational GRP data found for calc_admin1 for country %s. Skipping.", country, ) return None diff --git a/climada/entity/exposures/litpop/nightlight.py b/climada/entity/exposures/litpop/nightlight.py index c24208507c..44d5502579 100644 --- a/climada/entity/exposures/litpop/nightlight.py +++ b/climada/entity/exposures/litpop/nightlight.py @@ -30,10 +30,10 @@ import matplotlib.pyplot as plt import numpy as np import rasterio -import scipy.sparse as sparse from affine import Affine from osgeo import gdal from PIL import Image +from scipy import sparse from shapefile import Shape from climada import CONFIG @@ -302,8 +302,7 @@ def check_nl_local_file_exists(required_files=None, check_path=SYSTEM_DIR, year= LOGGER.info("No satellite files found locally in %s", check_path) else: LOGGER.debug( - "Not all satellite files available. " - "Found %d out of %d required files in %s", + "Not all satellite files available. Found %d out of %d required files in %s", int(sum(files_exist)), int(sum(required_files)), check_path, @@ -583,8 +582,7 @@ def untar_noaa_stable_nightlight(f_tar_ini): ] if len(extract_name) == 0: raise ValueError( - "No stable light intensities for selected year and satellite " - f"in file {f_tar_ini}" + f"No stable light intensities for selected year and satellite in file {f_tar_ini}" ) if len(extract_name) > 1: LOGGER.warning( @@ -645,8 +643,7 @@ def load_nightlight_noaa(ref_year=2013, sat_name=None): pass if "file_down" not in locals(): raise ValueError( - f"Nightlight for reference year {ref_year} not available. " - "Try a different year." + f"Nightlight for reference year {ref_year} not available. Try a different year." ) else: url = noaa_url + sat_name + str(ref_year) + ".v4.tar" diff --git a/climada/entity/exposures/test/test_litpop.py b/climada/entity/exposures/test/test_litpop.py index 048819e5ff..113cd2dec1 100644 --- a/climada/entity/exposures/test/test_litpop.py +++ b/climada/entity/exposures/test/test_litpop.py @@ -129,7 +129,6 @@ def test_reproject_input_data_downsample(self): """test function reproject_input_data downsampling lit to pop grid (default resampling for LitPop)""" data_in, meta_list = data_arrays_resampling_demo() - # data_out, meta_out = lp.reproject_input_data( data_in, meta_list, target_grid=meta_list[0] ) diff --git a/climada/entity/exposures/test/test_nightlight.py b/climada/entity/exposures/test/test_nightlight.py index e700289917..7e7f662053 100644 --- a/climada/entity/exposures/test/test_nightlight.py +++ b/climada/entity/exposures/test/test_nightlight.py @@ -20,12 +20,10 @@ """ import unittest -from pathlib import Path import numpy as np from climada.entity.exposures.litpop import nightlight -from climada.util.constants import SYSTEM_DIR BM_FILENAMES = nightlight.BM_FILENAMES @@ -102,7 +100,6 @@ def test_get_required_nl_files(self): for bounds in BOUNDS: with self.assertRaises(ValueError) as cm: - nightlight.get_required_nl_files(bounds=bounds) self.assertEqual( diff --git a/climada/entity/impact_funcs/base.py b/climada/entity/impact_funcs/base.py index c51540d573..910f0cde90 100644 --- a/climada/entity/impact_funcs/base.py +++ b/climada/entity/impact_funcs/base.py @@ -175,7 +175,7 @@ def check(self): if num_exp == 0: LOGGER.warning( - "%s impact function with name '%s' (id=%s) has empty" " intensity.", + "%s impact function with name '%s' (id=%s) has empty intensity.", self.haz_type, self.name, self.id, diff --git a/climada/entity/impact_funcs/impact_func_set.py b/climada/entity/impact_funcs/impact_func_set.py index 030f73f2be..9b71ec3a79 100755 --- a/climada/entity/impact_funcs/impact_func_set.py +++ b/climada/entity/impact_funcs/impact_func_set.py @@ -494,8 +494,7 @@ def _get_hdf5_str(imp, idxs, file_name, var_name): def read_mat(self, *args, **kwargs): """This function is deprecated, use ImpactFuncSet.from_mat instead.""" LOGGER.warning( - "The use of ImpactFuncSet.read_mat is deprecated." - "Use ImpactFuncSet.from_mat instead." + "The use of ImpactFuncSet.read_mat is deprecated.Use ImpactFuncSet.from_mat instead." ) self.__dict__ = ImpactFuncSet.from_mat(*args, **kwargs).__dict__ @@ -550,7 +549,6 @@ def write_impf(row_ini, imp_ws, xls_data): imp_wb.close() def _fill_dfr(self, dfr, var_names): - def _get_xls_funcs(dfr, var_names): """Parse individual impact functions.""" dist_func = [] @@ -586,7 +584,7 @@ def _get_xls_funcs(dfr, var_names): try: if len(df_func[var_names["col_name"]["unit"]].unique()) != 1: raise ValueError( - "Impact function with two different" " intensity units." + "Impact function with two different intensity units." ) impf_kwargs["intensity_unit"] = df_func[ var_names["col_name"]["unit"] diff --git a/climada/entity/impact_funcs/test/test_tc.py b/climada/entity/impact_funcs/test/test_tc.py index ebcccebdce..03f1195646 100644 --- a/climada/entity/impact_funcs/test/test_tc.py +++ b/climada/entity/impact_funcs/test/test_tc.py @@ -22,7 +22,6 @@ import unittest import numpy as np -import pandas as pd from climada.entity.impact_funcs.trop_cyclone import ImpfSetTropCyclone, ImpfTropCyclone diff --git a/climada/entity/impact_funcs/trop_cyclone.py b/climada/entity/impact_funcs/trop_cyclone.py index d4a867ceab..d8780ea596 100644 --- a/climada/entity/impact_funcs/trop_cyclone.py +++ b/climada/entity/impact_funcs/trop_cyclone.py @@ -440,7 +440,6 @@ def get_impf_id_regions_per_countries(countries: list = None) -> tuple: # Find region regions_ids = [] for country in countries: - if isinstance(country, int): country = coordinates.country_to_iso( country, representation="alpha3", fillvalue=None diff --git a/climada/entity/measures/base.py b/climada/entity/measures/base.py index 4e539f9986..df86b9c4a0 100755 --- a/climada/entity/measures/base.py +++ b/climada/entity/measures/base.py @@ -507,9 +507,9 @@ def _filter_exposures( fun_ids = list(new_impfs.get_func()[self.haz_type].keys()) for key in fun_ids: new_impfs.get_func()[self.haz_type][key].id = key + IMPF_ID_FACT - new_impfs.get_func()[self.haz_type][ - key + IMPF_ID_FACT - ] = new_impfs.get_func()[self.haz_type][key] + new_impfs.get_func()[self.haz_type][key + IMPF_ID_FACT] = ( + new_impfs.get_func()[self.haz_type][key] + ) try: new_exp.gdf[INDICATOR_IMPF + self.haz_type] += IMPF_ID_FACT except KeyError: @@ -533,9 +533,7 @@ def _filter_exposures( exposures.gdf[no_chg_reg], # old values for inert regions new_exp.gdf[chg_reg], # new values for changing regions ] - ).loc[ - exposures.gdf.index, : - ], # re-establish old order + ).loc[exposures.gdf.index, :], # re-establish old order ), crs=exposures.crs, ) diff --git a/climada/entity/measures/measure_set.py b/climada/entity/measures/measure_set.py index 90a2bb43c2..1163ba5758 100755 --- a/climada/entity/measures/measure_set.py +++ b/climada/entity/measures/measure_set.py @@ -450,8 +450,7 @@ def read_att_mat(measures, data, file_name, var_names): def read_mat(self, *args, **kwargs): """This function is deprecated, use MeasureSet.from_mat instead.""" LOGGER.warning( - "The use of MeasureSet.read_mat is deprecated." - "Use MeasureSet.from_mat instead." + "The use of MeasureSet.read_mat is deprecated.Use MeasureSet.from_mat instead." ) self.__dict__ = MeasureSet.from_mat(*args, **kwargs).__dict__ @@ -556,8 +555,7 @@ def read_att_excel(measures, dfr, var_names): def read_excel(self, *args, **kwargs): """This function is deprecated, use MeasureSet.from_excel instead.""" LOGGER.warning( - "The use ofMeasureSet.read_excel is deprecated." - "Use MeasureSet.from_excel instead." + "The use ofMeasureSet.read_excel is deprecated.Use MeasureSet.from_excel instead." ) self.__dict__ = MeasureSet.from_excel(*args, **kwargs).__dict__ diff --git a/climada/entity/tag/test/test_tag.py b/climada/entity/tag/test/test_tag.py index dfd1f454bf..0f0b83689d 100644 --- a/climada/entity/tag/test/test_tag.py +++ b/climada/entity/tag/test/test_tag.py @@ -40,8 +40,7 @@ def test_append_different_increase(self): self.assertEqual(["file_name1.mat", "file_name2.mat"], tag1.file_name) self.assertEqual(["dummy file 1", "dummy file 2"], tag1.description) self.assertEqual( - " File: file_name1 + file_name2\n" - " Description: dummy file 1 + dummy file 2", + " File: file_name1 + file_name2\n Description: dummy file 1 + dummy file 2", str(tag1), ) diff --git a/climada/hazard/base.py b/climada/hazard/base.py index abcbae2e83..76a1601426 100644 --- a/climada/hazard/base.py +++ b/climada/hazard/base.py @@ -24,7 +24,6 @@ import copy import datetime as dt import logging -import warnings from typing import List, Optional import geopandas as gpd @@ -38,7 +37,6 @@ import climada.util.coordinates as u_coord import climada.util.dates_times as u_dt import climada.util.interpolation as u_interp -from climada import CONFIG from climada.hazard.centroids.centr import Centroids from climada.hazard.io import HazardIO from climada.hazard.plot import HazardPlot diff --git a/climada/hazard/centroids/test/test_centr.py b/climada/hazard/centroids/test/test_centr.py index 6ca147b1af..a1a4056e5b 100644 --- a/climada/hazard/centroids/test/test_centr.py +++ b/climada/hazard/centroids/test/test_centr.py @@ -619,7 +619,6 @@ def test_from_geodataframe(self): self.assertTrue(u_coord.equal_crs(centroids.crs, crs)) def test_from_geodataframe_invalid(self): - # Creating an invalid GeoDataFrame with geometries that are not points invalid_geometry_gdf = gpd.GeoDataFrame( { diff --git a/climada/hazard/io.py b/climada/hazard/io.py index 6f8bd01b09..3a4b2661b6 100644 --- a/climada/hazard/io.py +++ b/climada/hazard/io.py @@ -98,8 +98,7 @@ class HazardIO: def set_raster(self, *args, **kwargs): """This function is deprecated, use Hazard.from_raster.""" LOGGER.warning( - "The use of Hazard.set_raster is deprecated." - "Use Hazard.from_raster instead." + "The use of Hazard.set_raster is deprecated.Use Hazard.from_raster instead." ) self.__dict__ = self.__class__.from_raster(*args, **kwargs).__dict__ @@ -783,8 +782,7 @@ def _attrs_to_kwargs(attrs: Dict[str, Any], num_events: int) -> Dict[str, Any]: def read_excel(self, *args, **kwargs): """This function is deprecated, use Hazard.from_excel.""" LOGGER.warning( - "The use of Hazard.read_excel is deprecated." - "Use Hazard.from_excel instead." + "The use of Hazard.read_excel is deprecated.Use Hazard.from_excel instead." ) self.__dict__ = self.__class__.from_excel(*args, **kwargs).__dict__ @@ -957,7 +955,7 @@ def write_hdf5(self, file_name, todense=False): def read_hdf5(self, *args, **kwargs): """This function is deprecated, use Hazard.from_hdf5.""" LOGGER.warning( - "The use of Hazard.read_hdf5 is deprecated." "Use Hazard.from_hdf5 instead." + "The use of Hazard.read_hdf5 is deprecated.Use Hazard.from_hdf5 instead." ) self.__dict__ = self.__class__.from_hdf5(*args, **kwargs).__dict__ diff --git a/climada/hazard/plot.py b/climada/hazard/plot.py index 431b6d9f72..809872b4d9 100644 --- a/climada/hazard/plot.py +++ b/climada/hazard/plot.py @@ -364,7 +364,7 @@ def _centr_plot(self, centr_idx, mat_var, col_name, axis=None, **kwargs): array_val = mat_var[:, centr_pos].toarray() title = ( f"Centroid {centr_idx}:" - f" ({np.around(coord[centr_pos, 0], 3)}, {np.around(coord[centr_pos, 1],3)})" + f" ({np.around(coord[centr_pos, 0], 3)}, {np.around(coord[centr_pos, 1], 3)})" ) elif centr_idx < 0: max_inten = np.asarray(np.sum(mat_var, axis=0)).reshape(-1) diff --git a/climada/hazard/storm_europe.py b/climada/hazard/storm_europe.py index 2fe7c6c861..447af3c064 100644 --- a/climada/hazard/storm_europe.py +++ b/climada/hazard/storm_europe.py @@ -253,10 +253,7 @@ def _read_one_nc(cls, file_name, centroids, intensity_thres): with xr.open_dataset(file_name) as ncdf: if centroids.size != (ncdf.sizes["latitude"] * ncdf.sizes["longitude"]): LOGGER.warning( - ( - "Centroids size doesn't match NCDF dimensions. " - "Omitting file %s." - ), + ("Centroids size doesn't match NCDF dimensions. Omitting file %s."), file_name, ) return None @@ -356,7 +353,7 @@ def from_cosmoe_file( raise ValueError( "Extraction of date and coordinates failed. This is most likely " "because the selected event_date " - f'{event_date.strftime("%Y-%m-%d")} is not contained in the ' + f"{event_date.strftime('%Y-%m-%d')} is not contained in the " "weather forecast selected by fp_file {fp_file}. Please adjust " f"event_date or fp_file." ) from ker @@ -520,9 +517,9 @@ def from_icon_grib( raise ValueError( "Extraction of date and coordinates failed. This is most likely " "because the selected event_date " - f'{event_date.strftime("%Y-%m-%d")} is not contained in the ' + f"{event_date.strftime('%Y-%m-%d')} is not contained in the " "weather forecast selected by run_datetime" - f'{run_datetime.strftime("%Y-%m-%d %H:%M")}. Please adjust ' + f"{run_datetime.strftime('%Y-%m-%d %H:%M')}. Please adjust " "event_date or run_datetime." ) from ker @@ -1073,8 +1070,8 @@ def generate_WS_forecast_hazard( haz_model = "C2E" full_model_name_temp = "COSMO-2E" haz_file_name = ( - f'{HAZ_TYPE}_{haz_model}_run{run_datetime.strftime("%Y%m%d%H")}' - f'_event{event_date.strftime("%Y%m%d")}.hdf5' + f"{HAZ_TYPE}_{haz_model}_run{run_datetime.strftime('%Y%m%d%H')}" + f"_event{event_date.strftime('%Y%m%d')}.hdf5" ) haz_file = FORECAST_DIR / haz_file_name if haz_file.exists(): @@ -1103,8 +1100,8 @@ def generate_WS_forecast_hazard( full_model_name_temp = haz_model haz_model = "IDE" haz_file_name = ( - f'{HAZ_TYPE}_{haz_model}_run{run_datetime.strftime("%Y%m%d%H")}' - f'_event{event_date.strftime("%Y%m%d")}.hdf5' + f"{HAZ_TYPE}_{haz_model}_run{run_datetime.strftime('%Y%m%d%H')}" + f"_event{event_date.strftime('%Y%m%d')}.hdf5" ) haz_file = FORECAST_DIR / haz_file_name if haz_file.exists(): diff --git a/climada/hazard/tc_clim_change.py b/climada/hazard/tc_clim_change.py index 1745c43f3e..b8c06b77fe 100644 --- a/climada/hazard/tc_clim_change.py +++ b/climada/hazard/tc_clim_change.py @@ -133,7 +133,6 @@ def get_knutson_scaling_factor( or (base_end_year <= gmst_info["gmst_start_year"]) or (base_end_year >= gmst_info["gmst_end_year"]) ): - raise ValueError( "The selected historical baseline falls outside" f"the GMST data period {gmst_info['gmst_start_year']}" diff --git a/climada/hazard/tc_tracks.py b/climada/hazard/tc_tracks.py index a8027cd714..b65dfc998b 100644 --- a/climada/hazard/tc_tracks.py +++ b/climada/hazard/tc_tracks.py @@ -45,13 +45,13 @@ import numpy as np import pandas as pd import pathos -import scipy.io.matlab as matlab import shapely.ops import statsmodels.api as sm import xarray as xr from matplotlib.collections import LineCollection from matplotlib.colors import BoundaryNorm, ListedColormap from matplotlib.lines import Line2D +from scipy.io import matlab from shapely.geometry import LineString, MultiLineString, Point, Polygon from shapely.ops import unary_union from sklearn.metrics import DistanceMetric @@ -585,7 +585,6 @@ def subset_year( # Find indices corresponding to the date range index: list = [] for i, track in enumerate(self.data): - date_array = track.time[0].to_numpy() year = date_array.astype("datetime64[Y]").item().year month = date_array.astype("datetime64[M]").item().month @@ -1864,8 +1863,7 @@ def write_netcdf(self, folder_name): def read_netcdf(self, *args, **kwargs): """This function is deprecated, use TCTracks.from_netcdf instead.""" LOGGER.warning( - "The use of TCTracks.read_netcdf is deprecated. " - "Use TCTracks.from_netcdf instead." + "The use of TCTracks.read_netcdf is deprecated. Use TCTracks.from_netcdf instead." ) self.__dict__ = TCTracks.from_netcdf(*args, **kwargs).__dict__ @@ -1946,7 +1944,6 @@ def from_FAST(cls, folder_name: str): with xr.open_dataset(file) as dataset: for year in dataset.year: for i in dataset.n_trk: - # Select track track = dataset.sel(n_trk=i, year=year) # chunk dataset at first NaN value @@ -2336,7 +2333,7 @@ def compute_track_density( if time_value > (res / limit_ratio): warnings.warn( "The time step is too big for the current resolution. For the desired resolution, \n" - f"apply a time step equal or lower than {res/limit_ratio}h." + f"apply a time step equal or lower than {res / limit_ratio}h." ) elif res < 0.1: warnings.warn( @@ -2366,7 +2363,6 @@ def compute_track_density( else: hist_count = np.zeros((len(lat_bins) - 1, len(lon_bins) - 1)) for track in tqdm(self.data, desc="Processing Tracks"): - # select according to wind speed wind_speed = track.max_sustained_wind.values if wind_min and wind_max: @@ -2772,8 +2768,7 @@ def _read_file_emanuel(path, hemisphere=None, rmw_corr=False, subset=None): ntracks, nnodes = lat.shape years_uniq = np.unique(data_mat["yearstore"]) LOGGER.info( - "File contains %s tracks (at most %s nodes each), " - "representing %s years (%s-%s).", + "File contains %s tracks (at most %s nodes each), representing %s years (%s-%s).", ntracks, nnodes, years_uniq.size, diff --git a/climada/hazard/tc_tracks_synth.py b/climada/hazard/tc_tracks_synth.py index 52388fbfaf..1f0f686b95 100644 --- a/climada/hazard/tc_tracks_synth.py +++ b/climada/hazard/tc_tracks_synth.py @@ -719,9 +719,7 @@ def _apply_land_decay( """ sy_tracks = [track for track in tracks if not track.orig_event_flag] if not sy_tracks: - raise ValueError( - "No synthetic tracks contained. Synthetic tracks" " are needed." - ) + raise ValueError("No synthetic tracks contained. Synthetic tracks are needed.") if not v_rel or not p_rel: LOGGER.info("No decay coefficients.") diff --git a/climada/hazard/test/test_base.py b/climada/hazard/test/test_base.py index b4cbafd0e3..2aa55402e9 100644 --- a/climada/hazard/test/test_base.py +++ b/climada/hazard/test/test_base.py @@ -23,7 +23,6 @@ from pathlib import Path import numpy as np -from pathos.pools import ProcessPool as Pool from scipy import sparse import climada.util.coordinates as u_coord @@ -714,8 +713,7 @@ def test_select_new_fraction_zero(self): # Select a part of the hazard where fraction is zero only with self.assertRaisesRegex( RuntimeError, - "Your selection created a Hazard object where the fraction matrix is zero " - "everywhere", + "Your selection created a Hazard object where the fraction matrix is zero everywhere", ): hazard.select(event_id=[3, 4], reg_id=[2]) diff --git a/climada/hazard/test/test_storm_europe.py b/climada/hazard/test/test_storm_europe.py index 6e4fff3b29..f617e72f87 100644 --- a/climada/hazard/test/test_storm_europe.py +++ b/climada/hazard/test/test_storm_europe.py @@ -19,7 +19,6 @@ Test StormEurope class """ -import copy import datetime as dt import unittest diff --git a/climada/hazard/test/test_tc_cc.py b/climada/hazard/test/test_tc_cc.py index 0ec281510d..9d055142e7 100644 --- a/climada/hazard/test/test_tc_cc.py +++ b/climada/hazard/test/test_tc_cc.py @@ -29,9 +29,7 @@ class TestKnutson(unittest.TestCase): - def test_get_knutson_scaling_calculations(self): - basin = "NA" variable = "cat05" percentile = "5/10" diff --git a/climada/hazard/test/test_tc_tracks.py b/climada/hazard/test/test_tc_tracks.py index 6c16fda87c..22a0b84db9 100644 --- a/climada/hazard/test/test_tc_tracks.py +++ b/climada/hazard/test/test_tc_tracks.py @@ -877,20 +877,17 @@ def test_subset_years(self): # Invalid input: Mismatch between start_day and end_day with self.assertRaisesRegex( ValueError, - "Mismatch between start_year and end_year: " - "Both must be either True or False.", + "Mismatch between start_year and end_year: Both must be either True or False.", ): tc_test.subset_year((2000, False, False), (False, False, False)) with self.assertRaisesRegex( ValueError, - "Mismatch between start_month and end_month: " - "Both must be either True or False.", + "Mismatch between start_month and end_month: Both must be either True or False.", ): tc_test.subset_year((2000, False, False), (2000, 5, False)) with self.assertRaisesRegex( ValueError, - "Mismatch between start_day and end_day: " - "Both must be either True or False.", + "Mismatch between start_day and end_day: Both must be either True or False.", ): tc_test.subset_year((False, False, False), (False, False, 3)) with self.assertRaisesRegex(ValueError, "Start year is after end year."): diff --git a/climada/hazard/test/test_tc_tracks_synth.py b/climada/hazard/test/test_tc_tracks_synth.py index 4f35b05b3a..2ea0cf315e 100644 --- a/climada/hazard/test/test_tc_tracks_synth.py +++ b/climada/hazard/test/test_tc_tracks_synth.py @@ -42,7 +42,6 @@ class TestDecay(unittest.TestCase): - @classmethod def setUpClass(cls): download_ibtracs() @@ -592,7 +591,6 @@ def test_decay_penv_gt_pcen(self): class TestSynth(unittest.TestCase): - @classmethod def setUpClass(cls): download_ibtracs() @@ -699,14 +697,14 @@ def test_random_walk_decay_pass(self): use_global_decay_params=False, ) self.assertIn( - "No historical track of category Tropical Depression " "with landfall.", + "No historical track of category Tropical Depression with landfall.", cm.output[2], ) self.assertIn( "Decay parameters from category Hurricane Cat. 4 taken.", cm.output[3] ) self.assertIn( - "No historical track of category Hurricane Cat. 1 with " "landfall.", + "No historical track of category Hurricane Cat. 1 with landfall.", cm.output[4], ) self.assertIn( @@ -719,7 +717,7 @@ def test_random_walk_decay_pass(self): cm.output[6], ) self.assertIn( - "No historical track of category Hurricane Cat. 5 with " "landfall.", + "No historical track of category Hurricane Cat. 5 with landfall.", cm.output[7], ) diff --git a/climada/hazard/test/test_xarray.py b/climada/hazard/test/test_xarray.py index cf481e3c44..3e3e0799c4 100644 --- a/climada/hazard/test/test_xarray.py +++ b/climada/hazard/test/test_xarray.py @@ -149,8 +149,11 @@ def _load_and_assert(**kwargs): def test_type_error(self): """Calling 'from_xarray_raster' with wrong data type should throw""" # Passing a DataArray - with xr.open_dataset(self.netcdf_path) as dset, self.assertRaisesRegex( - TypeError, "This method only supports passing xr.Dataset" + with ( + xr.open_dataset(self.netcdf_path) as dset, + self.assertRaisesRegex( + TypeError, "This method only supports passing xr.Dataset" + ), ): Hazard.from_xarray_raster(dset["intensity"], "", "") diff --git a/climada/hazard/trop_cyclone/trop_cyclone.py b/climada/hazard/trop_cyclone/trop_cyclone.py index a42c226e28..24ff94d194 100644 --- a/climada/hazard/trop_cyclone/trop_cyclone.py +++ b/climada/hazard/trop_cyclone/trop_cyclone.py @@ -28,10 +28,10 @@ import time from typing import List, Optional, Tuple -import matplotlib.animation as animation import numpy as np import pathos.pools import xarray as xr +from matplotlib import animation from scipy import sparse from tqdm import tqdm @@ -747,7 +747,6 @@ def _apply_knutson_criterion(self, chg_int_freq: List, scaling_rcp_year: float): # Criterion per basin for basin in np.unique(tc_cc.basin): - bas_sel = np.array(tc_cc.basin) == basin # Apply intensity change diff --git a/climada/hazard/xarray.py b/climada/hazard/xarray.py index df7fc9bf67..b8881111c5 100644 --- a/climada/hazard/xarray.py +++ b/climada/hazard/xarray.py @@ -100,8 +100,7 @@ def _date_to_ordinal_accessor(array: xr.DataArray, strict: bool = True) -> np.nd raise err LOGGER.warning( - "Failed to read values of '%s' as dates or ordinals. Hazard.date " - "will be ones only", + "Failed to read values of '%s' as dates or ordinals. Hazard.date will be ones only", array.name, ) return np.ones(array.shape) @@ -118,8 +117,7 @@ def _year_month_day_accessor(array: xr.DataArray, strict: bool = True) -> np.nda raise err LOGGER.warning( - "Failed to read values of '%s' as dates. Hazard.event_name will be " - "empty strings", + "Failed to read values of '%s' as dates. Hazard.event_name will be empty strings", array.name, ) return np.full(array.shape, "") diff --git a/climada/test/test_calibration.py b/climada/test/test_calibration.py index 5b83b3a3f2..f82de6bd13 100644 --- a/climada/test/test_calibration.py +++ b/climada/test/test_calibration.py @@ -20,11 +20,9 @@ """ import unittest -from pathlib import Path import pandas as pd -import climada.hazard.test as hazard_test from climada import CONFIG from climada.engine import ImpactCalc from climada.engine.calibration_opt import calib_instance diff --git a/climada/test/test_engine.py b/climada/test/test_engine.py index 7b7256ad0f..f097d3cda8 100644 --- a/climada/test/test_engine.py +++ b/climada/test/test_engine.py @@ -29,7 +29,6 @@ from climada import CONFIG from climada.engine import impact_data as im_d -from climada.engine.test.test_impact import dummy_impact from climada.engine.unsequa import CalcCostBenefit, InputVar from climada.entity import Exposures, ImpactFunc, ImpactFuncSet from climada.entity.entity_def import Entity @@ -79,7 +78,6 @@ def haz_dem(x_haz=1, haz=None): def make_input_vars(): - exp = exp_dem exp_distr = { "x_exp": sp.stats.uniform(0.8, 2), @@ -114,7 +112,6 @@ def ent_fut_dem(): def make_costben_iv(): - entdem = ent_dem() ent_iv = InputVar.ent( impf_set_list=[entdem.impact_funcs], diff --git a/climada/test/test_hazard.py b/climada/test/test_hazard.py index 3b71c9ccb1..19b2057b85 100644 --- a/climada/test/test_hazard.py +++ b/climada/test/test_hazard.py @@ -31,7 +31,6 @@ from climada.hazard.base import Hazard from climada.hazard.centroids import Centroids from climada.hazard.storm_europe import StormEurope -from climada.hazard.test.test_base import dummy_hazard from climada.test import get_test_file from climada.util import coordinates as u_coord from climada.util.api_client import Client diff --git a/climada/test/test_nightlight.py b/climada/test/test_nightlight.py index cb463fcd7a..dfc753a6d6 100644 --- a/climada/test/test_nightlight.py +++ b/climada/test/test_nightlight.py @@ -28,9 +28,9 @@ import affine import numpy as np -import scipy.sparse as sparse from osgeo import gdal from PIL import Image +from scipy import sparse from shapely.geometry import Polygon from climada.entity.exposures.litpop import nightlight @@ -96,8 +96,7 @@ def test_load_nasa_nl_shape_single_tile(self): geometry=shape, path=path, layer=4 ) self.assertEqual( - "BlackMarble_2016_C1_geo_gray.tif has only 3 layers," - " layer 4 can't be accessed.", + "BlackMarble_2016_C1_geo_gray.tif has only 3 layers, layer 4 can't be accessed.", str(cm.exception), ) # Test logger @@ -312,8 +311,7 @@ def test_untar_noaa_stable_nighlight(self): with self.assertRaises(ValueError) as cm: nightlight.untar_noaa_stable_nightlight(path_tar) self.assertEqual( - "No stable light intensities for selected year and satellite " - f"in file {path_tar}", + f"No stable light intensities for selected year and satellite in file {path_tar}", str(cm.exception), ) path_tar.unlink() diff --git a/climada/test/test_plot.py b/climada/test/test_plot.py index 89adaf0e5c..64321d65d0 100644 --- a/climada/test/test_plot.py +++ b/climada/test/test_plot.py @@ -21,7 +21,6 @@ import copy import unittest -import urllib from pathlib import Path import contextily as ctx @@ -40,7 +39,7 @@ Measure, MeasureSet, ) -from climada.hazard import Centroids, Hazard +from climada.hazard import Hazard from climada.test import get_test_file from climada.util.api_client import Client from climada.util.constants import ENT_DEMO_TODAY, HAZ_DEMO_FL, TEST_UNC_OUTPUT_COSTBEN diff --git a/climada/util/api_client.py b/climada/util/api_client.py index fbfdecfab7..94cbedbcd4 100644 --- a/climada/util/api_client.py +++ b/climada/util/api_client.py @@ -334,8 +334,7 @@ def _request_200(self, url, params=None): else: # try to restore previous results from an identical request if not self.cache.enabled: raise Client.NoConnection( - "there is no internet connection and the client does" - " not cache results." + "there is no internet connection and the client does not cache results." ) cached_result = self.cache.fetch(url, **params) if not cached_result: @@ -464,7 +463,9 @@ def get_dataset_info( ) if len(jarr) > 1: shown = 10 - endofmessage = "" if len(jarr) <= shown else f"\nand {len(jarr)-shown} more" + endofmessage = ( + "" if len(jarr) <= shown else f"\nand {len(jarr) - shown} more" + ) datasetlist = ",\n* ".join( str(jarr[i]) for i in range(min(shown, len(jarr))) ) @@ -780,7 +781,7 @@ def get_hazard( climada.hazard.Hazard The combined hazard object """ - if not hazard_type in HAZ_TYPES: + if hazard_type not in HAZ_TYPES: raise ValueError( "Valid hazard types are a subset of CLIMADA hazard types." f" Currently these types are supported: {HAZ_TYPES}" @@ -870,7 +871,7 @@ def get_exposures( climada.entity.exposures.Exposures The combined exposures object """ - if not exposures_type in EXP_TYPES: + if exposures_type not in EXP_TYPES: raise ValueError( "Valid exposures types are a subset of CLIMADA exposures types." f" Currently these types are supported: {EXP_TYPES}" diff --git a/climada/util/calibrate/ensemble.py b/climada/util/calibrate/ensemble.py index c7570ff6db..73be5d24dc 100644 --- a/climada/util/calibrate/ensemble.py +++ b/climada/util/calibrate/ensemble.py @@ -222,16 +222,14 @@ def from_hdf(cls, filepath: Path | str): def from_csv(cls, filepath: Path | str): """Load data from CSV""" LOGGER.warning( - "Do not use CSV for storage, because it does not preserve data types. " - "Use HDF instead." + "Do not use CSV for storage, because it does not preserve data types. Use HDF instead." ) return cls(data=pd.read_csv(filepath, header=[0, 1])) def to_csv(self, filepath: Path | str): """Store data as CSV""" LOGGER.warning( - "Do not use CSV for storage, because it does not preserve data types. " - "Use HDF instead." + "Do not use CSV for storage, because it does not preserve data types. Use HDF instead." ) self.data.to_csv(filepath, index=None) diff --git a/climada/util/checker.py b/climada/util/checker.py index 0d17b60368..bbaf731303 100644 --- a/climada/util/checker.py +++ b/climada/util/checker.py @@ -30,7 +30,7 @@ import logging import numpy as np -import scipy.sparse as sparse +from scipy import sparse LOGGER = logging.getLogger(__name__) diff --git a/climada/util/config.py b/climada/util/config.py index 17975f09a9..57624b0445 100644 --- a/climada/util/config.py +++ b/climada/util/config.py @@ -87,7 +87,7 @@ def __str__(self): [ f"{k}: {v}" for (k, v) in self.__dict__.items() - if not k in {"_name", "_root"} + if k not in {"_name", "_root"} ] ) ) diff --git a/climada/util/constants.py b/climada/util/constants.py index 90f352218b..804fd88e2f 100644 --- a/climada/util/constants.py +++ b/climada/util/constants.py @@ -47,7 +47,6 @@ # pylint: disable=unused-import # without importing numpy ahead of fiona the debugger may run into an error -import numpy from fiona.crs import from_epsg from .config import CONFIG diff --git a/climada/util/coordinates.py b/climada/util/coordinates.py index 1743150275..3b5a2a0c95 100644 --- a/climada/util/coordinates.py +++ b/climada/util/coordinates.py @@ -890,7 +890,7 @@ def get_country_geometries( # raise error if a country name is not recognized for country_name in country_names: - if not country_name in nat_earth[["ISO_A3", "WB_A3", "ADM0_A3"]].values: + if country_name not in nat_earth[["ISO_A3", "WB_A3", "ADM0_A3"]].values: raise ValueError(f"ISO code {country_name} not recognized.") country_mask = np.isin( @@ -1525,7 +1525,7 @@ def _nearest_neighbor_approx( if num_warn: LOGGER.warning( - "Distance to closest centroid is greater than %s" "km for %s coordinates.", + "Distance to closest centroid is greater than %skm for %s coordinates.", threshold, num_warn, ) @@ -1651,15 +1651,14 @@ def _nearest_neighbor_euclidean( centroids = np.rad2deg(centroids) coordinates = np.rad2deg(coordinates) dist = np.rad2deg(dist) - else: - if check_antimeridian: - # if unit is not in degree, check_antimeridian is forced to False - check_antimeridian = False - LOGGER.warning( - "Handling of antimeridian crossing is not implemented for non-degree" - " coordinates ('check_antimeridian' has been set to False). Please use" - " degree-based coordinates system if you want to enable antimeridian crossing." - ) + elif check_antimeridian: + # if unit is not in degree, check_antimeridian is forced to False + check_antimeridian = False + LOGGER.warning( + "Handling of antimeridian crossing is not implemented for non-degree" + " coordinates ('check_antimeridian' has been set to False). Please use" + " degree-based coordinates system if you want to enable antimeridian crossing." + ) # Raise a warning if the minimum distance is greater than the # threshold and set an unvalid index -1 @@ -1719,8 +1718,7 @@ def _nearest_neighbor_antimeridian(centroids, coordinates, threshold, assigned, lon_max = max(centroids[:, 1].max(), coordinates[:, 1].max()) if lon_max - lon_min > 360: raise ValueError( - "Longitudinal coordinates need to be normalized" - "to a common 360 degree range" + "Longitudinal coordinates need to be normalizedto a common 360 degree range" ) mid_lon = 0.5 * (lon_max + lon_min) antimeridian = mid_lon + 180 @@ -3205,8 +3203,9 @@ def subraster_from_bounds(transform, bounds): # align the window bounds to the raster by rounding col_min, col_max = np.round(window.col_off), np.round(window.col_off + window.width) - row_min, row_max = np.round(window.row_off), np.round( - window.row_off + window.height + row_min, row_max = ( + np.round(window.row_off), + np.round(window.row_off + window.height), ) window = rasterio.windows.Window( col_min, row_min, col_max - col_min, row_max - row_min diff --git a/climada/util/dates_times.py b/climada/util/dates_times.py index 87453b0ae7..23595c2666 100644 --- a/climada/util/dates_times.py +++ b/climada/util/dates_times.py @@ -138,8 +138,7 @@ def convert_frequency_unit_to_time_unit(frequency_unit): time_unit = "weeks" else: LOGGER.warning( - f"Frequency unit {frequency_unit} is not known, " - "years will be used as time unit." + f"Frequency unit {frequency_unit} is not known, years will be used as time unit." ) time_unit = "years" return time_unit diff --git a/climada/util/finance.py b/climada/util/finance.py index 7ae54fcc45..ccee50f245 100644 --- a/climada/util/finance.py +++ b/climada/util/finance.py @@ -296,8 +296,8 @@ def world_bank(cntry_iso, ref_year, info_ind): ) except (IOError, requests.exceptions.ConnectionError) as err: raise type(err)( - "Internet connection failed while downloading " - "historical income groups: " + str(err) + "Internet connection failed while downloading historical income groups: " + + str(err) ) from err cntry_dfr = dfr_wb.loc[cntry_iso] diff --git a/climada/util/plot.py b/climada/util/plot.py index 99a7993d44..a6f7b7af1f 100644 --- a/climada/util/plot.py +++ b/climada/util/plot.py @@ -705,8 +705,7 @@ def make_map(num_sub=1, figsize=(9, 13), proj=ccrs.PlateCarree(), adapt_fontsize grid.yformatter = LATITUDE_FORMATTER if adapt_fontsize: fontsize = axis.bbox.width / 35 - if fontsize < 10: - fontsize = 10 + fontsize = max(fontsize, 10) grid.xlabel_style = {"size": fontsize} grid.ylabel_style = {"size": fontsize} else: @@ -889,13 +888,12 @@ def _get_row_col_size(num_sub): if num_sub <= 3: num_col = num_sub num_row = 1 + elif num_sub % 3 == 0: + num_col = 3 + num_row = int(num_sub / 3) else: - if num_sub % 3 == 0: - num_col = 3 - num_row = int(num_sub / 3) - else: - num_col = 2 - num_row = int(num_sub / 2) + num_sub % 2 + num_col = 2 + num_row = int(num_sub / 2) + num_sub % 2 return num_row, num_col diff --git a/climada/util/scalebar_plot.py b/climada/util/scalebar_plot.py index e30f515a6a..1f88666ed0 100644 --- a/climada/util/scalebar_plot.py +++ b/climada/util/scalebar_plot.py @@ -100,8 +100,7 @@ def _distance_along_line(start, end, distance, dist_func, tol): initial_distance = dist_func(start, end) if initial_distance < distance: raise ValueError( - f"End is closer to start ({initial_distance}) than " - f"given distance ({distance})." + f"End is closer to start ({initial_distance}) than given distance ({distance})." ) if tol <= 0: diff --git a/climada/util/select.py b/climada/util/select.py index aaee63890c..330d64dbbd 100755 --- a/climada/util/select.py +++ b/climada/util/select.py @@ -48,7 +48,6 @@ def get_attributes_with_matching_dimension(obj, dims): list_of_attrs = [] for attr, value in obj.__dict__.items(): - if isinstance(value, list): try: value = np.array(value) diff --git a/climada/util/test/test_checker.py b/climada/util/test/test_checker.py index 493f394e4f..16ad491db9 100644 --- a/climada/util/test/test_checker.py +++ b/climada/util/test/test_checker.py @@ -22,13 +22,12 @@ import unittest import numpy as np -import scipy.sparse as sparse +from scipy import sparse import climada.util.checker as u_check class DummyClass(object): - vars_oblig = {"id", "array", "sparse_arr"} vars_opt = {"list", "array_opt"} diff --git a/climada/util/test/test_coordinates.py b/climada/util/test/test_coordinates.py index b0703c568a..89bc7a775a 100644 --- a/climada/util/test/test_coordinates.py +++ b/climada/util/test/test_coordinates.py @@ -676,7 +676,7 @@ def test_get_gridcellarea(self): lat, resolution, unit="unknown" ) self.assertIn( - f"'unknown' unit not recognized. Please use any of 'm2', 'km2' or 'ha'.", + "'unknown' unit not recognized. Please use any of 'm2', 'km2' or 'ha'.", str(cm.exception), ) @@ -1968,7 +1968,6 @@ def test_pts_to_raster_irreg_pass(self): def test_points_to_raster_pass(self): """Test points_to_raster""" for scheduler in [None, "threads", "synchronous", "processes"]: - df_val = gpd.GeoDataFrame() x, y = np.meshgrid(np.linspace(0, 2, 5), np.linspace(40, 50, 10)) df_val["latitude"] = y.flatten() @@ -2453,7 +2452,7 @@ def test_align_raster_data_downsample_conserve(self): # test conserve sum: for j, data in enumerate(data_in): # src data_out, _ = u_coord.align_raster_data( - data_in[j], + data, meta_list[j]["crs"], meta_list[j]["transform"], dst_crs=meta_list[i]["crs"], @@ -2462,12 +2461,12 @@ def test_align_raster_data_downsample_conserve(self): resampling="bilinear", conserve="sum", ) - self.assertAlmostEqual(data_in[j].sum(), data_out.sum(), places=4) + self.assertAlmostEqual(data.sum(), data_out.sum(), places=4) # test conserve mean: for j, data in enumerate(data_in): data_out, _ = u_coord.align_raster_data( - data_in[j], + data, meta_list[j]["crs"], meta_list[j]["transform"], dst_crs=meta_list[i]["crs"], @@ -2476,7 +2475,7 @@ def test_align_raster_data_downsample_conserve(self): resampling="bilinear", conserve="mean", ) - self.assertAlmostEqual(data_in[j].mean(), data_out.mean(), places=4) + self.assertAlmostEqual(data.mean(), data_out.mean(), places=4) def test_align_raster_data_upsample(self): """test function align_raster_data with upsampling""" diff --git a/climada/util/test/test_files.py b/climada/util/test/test_files.py index 81b4827f1c..31a7a77708 100644 --- a/climada/util/test/test_files.py +++ b/climada/util/test/test_files.py @@ -165,10 +165,7 @@ def test_get_extension_one_pass(self): def test_get_extension_two_pass(self): """Test compressed""" - file_name = ( - "/Users/aznarsig/Documents/Python/climada_python" - "/data/demo/SC22000_VE__M1.grd.gz" - ) + file_name = "/Users/aznarsig/Documents/Python/climada_python/data/demo/SC22000_VE__M1.grd.gz" self.assertEqual(".grd.gz", get_extension(file_name)[1]) self.assertEqual( str( diff --git a/climada/util/test/test_plot.py b/climada/util/test/test_plot.py index 351010afb1..4192a0af0c 100644 --- a/climada/util/test/test_plot.py +++ b/climada/util/test/test_plot.py @@ -33,7 +33,6 @@ class TestFuncs(unittest.TestCase): - def test_get_transform_4326_pass(self): """Check _get_transformation for 4326 epsg.""" res, unit = u_plot.get_transformation("epsg:4326") @@ -55,7 +54,6 @@ def test_get_transform_3035_pass(self): class TestPlots(unittest.TestCase): - def test_geo_scatter_categorical(self): """Plots ones with geo_scatteR_categorical""" # test default with one plot diff --git a/climada/util/test/test_save.py b/climada/util/test/test_save.py index 6a43e58dd1..be29258b2c 100644 --- a/climada/util/test/test_save.py +++ b/climada/util/test/test_save.py @@ -20,7 +20,6 @@ """ import unittest -from pathlib import Path from climada import CONFIG from climada.util.save import load, save diff --git a/climada/util/test/test_select.py b/climada/util/test/test_select.py index 184a7b0c9a..a9938d5897 100755 --- a/climada/util/test/test_select.py +++ b/climada/util/test/test_select.py @@ -27,7 +27,6 @@ class Dummy: - def __init__(self): self.oneD3 = [1, 2, 3] self.oneD4 = [1, 2, 3, 4] diff --git a/climada/util/test/test_value_representation.py b/climada/util/test/test_value_representation.py index dfd662e5be..af91fab2bf 100644 --- a/climada/util/test/test_value_representation.py +++ b/climada/util/test/test_value_representation.py @@ -169,7 +169,6 @@ def test_value_to_monetary_unit_list_nan_pass(self): class TestSafeDivide(unittest.TestCase): - def test_scalar_division(self): self.assertEqual(safe_divide(10, 2), 5) self.assertEqual(safe_divide(-10, 5), -2) diff --git a/climada/util/test/test_yearsets.py b/climada/util/test/test_yearsets.py index 79e469ee48..d17ef90dcd 100755 --- a/climada/util/test/test_yearsets.py +++ b/climada/util/test/test_yearsets.py @@ -25,8 +25,8 @@ import numpy as np import climada.util.dates_times as u_dt -import climada.util.yearsets as yearsets from climada.engine import Impact +from climada.util import yearsets IMP = Impact() IMP.at_event = np.arange(10, 110, 10) diff --git a/doc/development/Guide_PythonDos-n-Donts.ipynb b/doc/development/Guide_PythonDos-n-Donts.ipynb index 222ffd0ab3..13222b5cd8 100644 --- a/doc/development/Guide_PythonDos-n-Donts.ipynb +++ b/doc/development/Guide_PythonDos-n-Donts.ipynb @@ -192,8 +192,13 @@ "outputs": [], "source": [ "spam(ham[1], {eggs: 2})\n", - "if x == 4: print x, y; x, y = y, x\n", - "def complex(real, imag=0.0):" + "if x == 4:\n", + " print(x, y)\n", + " x, y = y, x\n", + "\n", + "\n", + "def complex(real, imag=0.0):\n", + " pass" ] }, { @@ -326,10 +331,12 @@ "metadata": {}, "outputs": [], "source": [ - "# Correct: \n", + "# Correct:\n", "if isinstance(obj, int):\n", + " pass\n", "# Wrong:\n", - "if type(obj) is type(1)" + "if type(obj) is type(1):\n", + " pass" ] }, { @@ -351,10 +358,14 @@ "source": [ "# Correct:\n", "if not seq:\n", + " pass\n", "if seq:\n", + " pass\n", "# Wrong:\n", "if len(seq):\n", - "if not len(seq)" + " pass\n", + "if not len(seq):\n", + " pass" ] }, { @@ -375,9 +386,11 @@ "outputs": [], "source": [ "# Correct:\n", - "if greeting: \n", + "if greeting:\n", + " pass\n", "# Wrong:\n", - "if greeting == True: " + "if greeting == True:\n", + " pass" ] }, { @@ -398,9 +411,11 @@ "outputs": [], "source": [ "# Correct:\n", - "if foo.startswith('bar'):\n", + "if foo.startswith(\"bar\"):\n", + " pass\n", "# Wrong:\n", - "if foo[:3] == 'bar':" + "if foo[:3] == \"bar\":\n", + " pass" ] }, { diff --git a/doc/getting-started/0_intro_python.ipynb b/doc/getting-started/0_intro_python.ipynb index 8318986028..3b80b0e7ab 100644 --- a/doc/getting-started/0_intro_python.ipynb +++ b/doc/getting-started/0_intro_python.ipynb @@ -740,7 +740,6 @@ "outputs": [], "source": [ "class Dog: # same as \"class Dog(object)\"\n", - "\n", " kind = \"canine\" # class variable shared by all instances\n", "\n", " def __init__(self, name): # initialization method\n", @@ -839,7 +838,6 @@ "outputs": [], "source": [ "class Animal: # base class\n", - "\n", " def __init__(self, kind):\n", " self.kind = kind\n", " self.tricks = []\n", @@ -849,7 +847,6 @@ "\n", "\n", "class Dog(Animal): # derived class\n", - "\n", " def __init__(self): # override of __init__ base method\n", " super(Dog, self).__init__(\n", " \"canine\"\n", @@ -907,7 +904,6 @@ "\n", "\n", "class MappingSubclass(Mapping):\n", - "\n", " def update(self, keys, values):\n", " # provides new signature for update()\n", " # but does not break __init__()\n", diff --git a/doc/user-guide/0_10min_climada.ipynb b/doc/user-guide/0_10min_climada.ipynb index 1e575c19eb..5bd0e46433 100644 --- a/doc/user-guide/0_10min_climada.ipynb +++ b/doc/user-guide/0_10min_climada.ipynb @@ -69,7 +69,7 @@ "print(\n", " f\"The hazard object contains {haz.intensity.shape[0]} events. \\n\"\n", " f\"The maximal intensity contained in the Hazard object is {haz.intensity.max():.2f} {haz.units}. \\n\"\n", - " f\"The first event was observed in a time series of {int(1/haz.frequency[0])} {haz.frequency_unit[2:]}s, \\n\"\n", + " f\"The first event was observed in a time series of {int(1 / haz.frequency[0])} {haz.frequency_unit[2:]}s, \\n\"\n", " f\"which is why CLIMADA estimates an annual probability of {haz.frequency[0]:.4f} for the occurence of this event.\"\n", ")" ] diff --git a/doc/user-guide/climada_engine_Forecast.ipynb b/doc/user-guide/climada_engine_Forecast.ipynb index f0d6b3a66a..202711c8c1 100644 --- a/doc/user-guide/climada_engine_Forecast.ipynb +++ b/doc/user-guide/climada_engine_Forecast.ipynb @@ -208,7 +208,6 @@ "if not cantons_file.exists():\n", " with fiona.open(adm1_shape_file, \"r\") as source:\n", " with fiona.open(cantons_file, \"w\", **source.meta) as sink:\n", - "\n", " for f in source:\n", " if f[\"properties\"][\"adm0_a3\"] == \"CHE\":\n", " sink.write(f)\n", diff --git a/doc/user-guide/climada_engine_Impact.ipynb b/doc/user-guide/climada_engine_Impact.ipynb index d1044a6724..b70df1d9d5 100644 --- a/doc/user-guide/climada_engine_Impact.ipynb +++ b/doc/user-guide/climada_engine_Impact.ipynb @@ -1098,7 +1098,7 @@ } ], "source": [ - "print(f\"Aggregated average annual impact: {round(imp.aai_agg,0)} $\")" + "print(f\"Aggregated average annual impact: {round(imp.aai_agg, 0)} $\")" ] }, { @@ -1452,9 +1452,7 @@ ") # plot intensity per point\n", "ax_pnt.get_figure().colorbar(\n", " ax_pnt.collections[2], fraction=0.0175, pad=0.08\n", - ").set_label(\n", - " \"Intensity (m/s)\"\n", - ") # add colorbar\n", + ").set_label(\"Intensity (m/s)\") # add colorbar\n", "\n", "# Set impact function\n", "impf_tc = ImpfTropCyclone.from_emanuel_usa()\n", diff --git a/doc/user-guide/climada_engine_unsequa.ipynb b/doc/user-guide/climada_engine_unsequa.ipynb index 8c13638c9c..b7b62cc96e 100644 --- a/doc/user-guide/climada_engine_unsequa.ipynb +++ b/doc/user-guide/climada_engine_unsequa.ipynb @@ -977,7 +977,6 @@ "\n", "\n", "def impf_func(G=1, v_half=84.7, vmin=25.7, k=3, _id=1):\n", - "\n", " def xhi(v, v_half, vmin):\n", " return max([(v - vmin), 0]) / (v_half - vmin)\n", "\n", @@ -2439,7 +2438,6 @@ "\n", "\n", "def impf_func(G=1, v_half=84.7, vmin=25.7, k=3, _id=1):\n", - "\n", " def xhi(v, v_half, vmin):\n", " return max([(v - vmin), 0]) / (v_half - vmin)\n", "\n", @@ -2912,8 +2910,7 @@ "costs_1 = [meas.cost for meas in ent_fut_func(1).measures.get_measure(\"TC\")]\n", "costs_05 = [meas.cost for meas in ent_fut_func(0.5).measures.get_measure(\"TC\")]\n", "print(\n", - " f\"\\nThe cost for m_fut_cost=1 are {costs_1}\\n\"\n", - " f\"The cost for m_fut_cost=0.5 are {costs_05}\"\n", + " f\"\\nThe cost for m_fut_cost=1 are {costs_1}\\nThe cost for m_fut_cost=0.5 are {costs_05}\"\n", ");" ] }, @@ -5649,7 +5646,6 @@ "\n", "\n", "def impf_func(G=1, v_half=84.7, vmin=25.7, k=3, _id=1):\n", - "\n", " def xhi(v, v_half, vmin):\n", " return max([(v - vmin), 0]) / (v_half - vmin)\n", "\n", diff --git a/doc/user-guide/climada_hazard_copernicus_seasonal_forecast.ipynb b/doc/user-guide/climada_hazard_copernicus_seasonal_forecast.ipynb index 1e5982ba89..6a13f20442 100644 --- a/doc/user-guide/climada_hazard_copernicus_seasonal_forecast.ipynb +++ b/doc/user-guide/climada_hazard_copernicus_seasonal_forecast.ipynb @@ -1779,7 +1779,7 @@ " )\n", " ax.coastlines(color=\"white\")\n", " ax.add_feature(cfeature.BORDERS, edgecolor=\"white\")\n", - " ax.set_title(f\"Member {i+1}\", fontsize=8)\n", + " ax.set_title(f\"Member {i + 1}\", fontsize=8)\n", " ax.set_xticks([])\n", " ax.set_yticks([])\n", "\n", diff --git a/doc/user-guide/climada_util_yearsets.ipynb b/doc/user-guide/climada_util_yearsets.ipynb index 0fee5c5780..f3dcf8bfc0 100644 --- a/doc/user-guide/climada_util_yearsets.ipynb +++ b/doc/user-guide/climada_util_yearsets.ipynb @@ -208,7 +208,7 @@ "print(\"yimp.at_event = \", yimp.at_event)\n", "print(\"imp_per_year = \", imp_per_year)\n", "print(\n", - " f\"The expected annual impact {round(yimp.aai_agg,2)} differs from the one of the original impact ({round(imp.aai_agg,2)}).\"\n", + " f\"The expected annual impact {round(yimp.aai_agg, 2)} differs from the one of the original impact ({round(imp.aai_agg, 2)}).\"\n", ")" ] }, @@ -247,7 +247,7 @@ "print(\"yimp.at_event = \", np.round(yimp.at_event, 2))\n", "print(\"imp_per_year = \", np.round(imp_per_year * correction_factor, 2))\n", "print(\n", - " f\"The expected annual impact {round(yimp.aai_agg,2)} is equal to the one of the original impact ({round(imp.aai_agg,2)}).\"\n", + " f\"The expected annual impact {round(yimp.aai_agg, 2)} is equal to the one of the original impact ({round(imp.aai_agg, 2)}).\"\n", ")" ] }, diff --git a/pyproject.toml b/pyproject.toml index 25268927d5..292411bf09 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -78,7 +78,8 @@ dev = [ "pytest", "pytest-cov", "pytest-subtests", - "pre-commit" + "pre-commit", + "ruff", ] [project.urls] @@ -89,3 +90,19 @@ include-package-data = true [tool.setuptools.packages.find] include = ["climada*"] + +[tool.ruff] +target-version = "py311" + +[tool.ruff.lint] +select = ["C90", "E", "F", "I", "W", "PL", "N"] +exclude = ["*.ipynb"] + +[tool.ruff.lint.per-file-ignores] +"__init__.py" = ["F401"] + +[tool.ruff.lint.pylint] +max-args = 10 + +[tool.ruff.lint.pycodestyle] +max-line-length = 100 # Lines below this length will not be seen as issues diff --git a/script/applications/eca_san_salvador/functions_ss.py b/script/applications/eca_san_salvador/functions_ss.py index e7be253a32..3a724b0ed7 100755 --- a/script/applications/eca_san_salvador/functions_ss.py +++ b/script/applications/eca_san_salvador/functions_ss.py @@ -22,8 +22,8 @@ import contextily as ctx import geopandas as gpd -import matplotlib.patches as patches from matplotlib import colormaps as cm +from matplotlib import patches from shapely import wkt @@ -56,8 +56,7 @@ def plot_salvador_ma(): return fig -from climada.entity import Entity, Exposures -from climada.hazard import Hazard +from climada.entity import Entity def load_entity(): diff --git a/script/jenkins/test_notebooks.py b/script/jenkins/test_notebooks.py index aefacd3f95..98243d4eea 100644 --- a/script/jenkins/test_notebooks.py +++ b/script/jenkins/test_notebooks.py @@ -4,7 +4,6 @@ import os import re import sys -import unittest from pathlib import Path import nbformat @@ -23,7 +22,7 @@ (f.absolute(), f.name) for f in sorted(NOTEBOOK_DIR.iterdir()) if os.path.splitext(f)[1] == (".ipynb") - and not f.name in EXCLUDED_FROM_NOTEBOOK_TEST + and f.name not in EXCLUDED_FROM_NOTEBOOK_TEST ] @@ -54,7 +53,6 @@ def test_notebook(nb, name): # run all cells i = 0 for c in cells: - # skip markdown cells if c["cell_type"] != "code": continue @@ -130,7 +128,7 @@ def test_notebook(nb, name): def main(): # run the tests and write xml reports to tests_xml - pytest.main([f"--junitxml=tests_xml/tests.xml", __file__]) + pytest.main(["--junitxml=tests_xml/tests.xml", __file__]) if __name__ == "__main__":