From 7595f994468db4e3fcfbe2302eebead8534a880d Mon Sep 17 00:00:00 2001 From: Chris Fairless Date: Mon, 9 Sep 2024 09:55:28 +0100 Subject: [PATCH 01/10] Supply chain: prevent warnings from dtype incompatibilities (#115) Pandas now throws warnings when you try to combine different data types rather than coercing the data. The supplychain module fills an empty data frame with '0' and adds calculated values into the frame. This update fills the frame with '0.0' so that the dtypes match and pandas will shut up. Co-authored-by: emanuel-schmid --- climada_petals/engine/supplychain.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/climada_petals/engine/supplychain.py b/climada_petals/engine/supplychain.py index dab98f9e..aae8d360 100644 --- a/climada_petals/engine/supplychain.py +++ b/climada_petals/engine/supplychain.py @@ -566,12 +566,12 @@ def calc_shock_to_sectors(self, self.events_date = impact.date[events_w_imp_bool] self.secs_exp = pd.DataFrame( - 0, + 0.0, index=["total_value"], columns=self.mriot.Z.columns ) self.secs_imp = pd.DataFrame( - 0, + 0.0, index=impact.event_id[events_w_imp_bool], columns=self.mriot.Z.columns ) From 83482aff12dd8e045c750144481cddd0d063f2b4 Mon Sep 17 00:00:00 2001 From: Emanuel Schmid <51439563+emanuel-schmid@users.noreply.github.com> Date: Fri, 27 Sep 2024 14:36:27 +0200 Subject: [PATCH 02/10] doc: installation standard python 3.11 (#143) --- script/jenkins/install_env.sh | 2 +- setup.py | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/script/jenkins/install_env.sh b/script/jenkins/install_env.sh index 37f7ea8a..efdef902 100644 --- a/script/jenkins/install_env.sh +++ b/script/jenkins/install_env.sh @@ -1,7 +1,7 @@ #!/bin/bash -e mamba env remove -n petals_env -mamba create -n petals_env python=3.9 +mamba create -n petals_env python=3.11 mamba env update -n petals_env -f ~/jobs/climada_install_env/workspace/requirements/env_climada.yml mamba env update -n petals_env -f requirements/env_climada.yml diff --git a/setup.py b/setup.py index 878586e9..aa66a432 100644 --- a/setup.py +++ b/setup.py @@ -28,7 +28,7 @@ classifiers=[ 'Development Status :: 4 - Beta', - 'Programming Language :: Python :: 3.9', + 'Programming Language :: Python :: 3', 'Topic :: Scientific/Engineering :: Atmospheric Science', 'Topic :: Scientific/Engineering :: GIS', 'Topic :: Scientific/Engineering :: Mathematics', From 1963a9c0947596a90234437636a4230b7e0d2441 Mon Sep 17 00:00:00 2001 From: emanuel-schmid Date: Fri, 27 Sep 2024 15:58:56 +0200 Subject: [PATCH 03/10] climada_petal.hazard.tc_tracks_forecast: fix error message in fetch_bufr_ftp --- climada_petals/hazard/tc_tracks_forecast.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/climada_petals/hazard/tc_tracks_forecast.py b/climada_petals/hazard/tc_tracks_forecast.py index 4fbdffa6..ef40f9bf 100644 --- a/climada_petals/hazard/tc_tracks_forecast.py +++ b/climada_petals/hazard/tc_tracks_forecast.py @@ -210,9 +210,9 @@ def fetch_bufr_ftp(target_dir=None, remote_dir=None): remotefiles = fnmatch.filter(remotefiles_temp, '*ECEP*') if len(remotefiles) == 0: - msg = 'No tracks found at ftp://{}/{}' - msg.format(ECMWF_FTP.host.dir(), remote_dir) - raise FileNotFoundError(msg) + raise FileNotFoundError( + f'No tracks found at ftp://{ECMWF_FTP.host.str()}/{remote_dir}' + ) localfiles = [] From f89e4968edd4d864039c4d10ebac284a6dde7e54 Mon Sep 17 00:00:00 2001 From: emanuel-schmid Date: Fri, 27 Sep 2024 16:21:41 +0200 Subject: [PATCH 04/10] suppress datetime conversion warning --- climada_petals/hazard/tc_tracks_forecast.py | 58 ++++++++++++--------- 1 file changed, 32 insertions(+), 26 deletions(-) diff --git a/climada_petals/hazard/tc_tracks_forecast.py b/climada_petals/hazard/tc_tracks_forecast.py index ef40f9bf..786b3c1d 100644 --- a/climada_petals/hazard/tc_tracks_forecast.py +++ b/climada_petals/hazard/tc_tracks_forecast.py @@ -30,6 +30,7 @@ import os import tempfile from pathlib import Path +import warnings # additional libraries import eccodes as ec @@ -506,33 +507,38 @@ def _subset_to_track(msg, index, provider, timestamp_origin, name, id_no): # 0 means the deterministic analysis, which we want to flag. # See documentation for link to ensemble types. ens_bool = msg['ens_type'][index] != 0 - try: - track = xr.Dataset( - data_vars={ - 'max_sustained_wind': ('time', np.squeeze(wnd)), - 'central_pressure': ('time', np.squeeze(pre)/100), - 'radius_max_wind': ('time', np.squeeze(rad)), - 'ts_int': ('time', timestep_int), - }, - coords={ - 'time': timestamp, - 'lat': ('time', lat), - 'lon': ('time', lon), - }, - attrs={ - 'max_sustained_wind_unit': 'm/s', - 'central_pressure_unit': 'mb', - 'name': name, - 'sid': sid, - 'orig_event_flag': False, - 'data_provider': provider, - 'id_no': (int(id_no) + index / 100), - 'ensemble_number': msg['ens_number'][index], - 'is_ensemble': ens_bool, - 'run_datetime': timestamp_origin, - } - ) + with warnings.catch_warnings(): + # prevent issueing a million warnings about conversion of non-nanosecond precision + # datetime to nanosecond precision, e.g. in fetch_ecmwf + # TODO: fix it through converting those _before_ creating the xr.Dataset + warnings.simplefilter(action='error', category=UserWarning) + + track = xr.Dataset( + data_vars={ + 'max_sustained_wind': ('time', np.squeeze(wnd)), + 'central_pressure': ('time', np.squeeze(pre)/100), + 'radius_max_wind': ('time', np.squeeze(rad)), + 'ts_int': ('time', timestep_int), + }, + coords={ + 'time': timestamp, + 'lat': ('time', lat), + 'lon': ('time', lon), + }, + attrs={ + 'max_sustained_wind_unit': 'm/s', + 'central_pressure_unit': 'mb', + 'name': name, + 'sid': sid, + 'orig_event_flag': False, + 'data_provider': provider, + 'id_no': (int(id_no) + index / 100), + 'ensemble_number': msg['ens_number'][index], + 'is_ensemble': ens_bool, + 'run_datetime': timestamp_origin, + } + ) except ValueError as err: LOGGER.warning( 'Could not process track %s subset %d, error: %s', From 39fa478b473594ef1b5373dd293480f2f80a0602 Mon Sep 17 00:00:00 2001 From: emanuel-schmid Date: Fri, 27 Sep 2024 16:26:32 +0200 Subject: [PATCH 05/10] suppress datetime conversion warning --- climada_petals/hazard/tc_tracks_forecast.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/climada_petals/hazard/tc_tracks_forecast.py b/climada_petals/hazard/tc_tracks_forecast.py index 786b3c1d..f52b442e 100644 --- a/climada_petals/hazard/tc_tracks_forecast.py +++ b/climada_petals/hazard/tc_tracks_forecast.py @@ -512,7 +512,7 @@ def _subset_to_track(msg, index, provider, timestamp_origin, name, id_no): # prevent issueing a million warnings about conversion of non-nanosecond precision # datetime to nanosecond precision, e.g. in fetch_ecmwf # TODO: fix it through converting those _before_ creating the xr.Dataset - warnings.simplefilter(action='error', category=UserWarning) + warnings.simplefilter(action='ignore', category=UserWarning) track = xr.Dataset( data_vars={ From e7e9ed977bef5c2fb7177ee6b502a5ead59e0866 Mon Sep 17 00:00:00 2001 From: emanuel-schmid Date: Thu, 3 Oct 2024 14:41:25 +0200 Subject: [PATCH 06/10] pin esmpy to <8.4.1 --- requirements/env_climada.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/requirements/env_climada.yml b/requirements/env_climada.yml index 21f0bac7..0086825f 100644 --- a/requirements/env_climada.yml +++ b/requirements/env_climada.yml @@ -6,6 +6,7 @@ dependencies: - boario>=0.5 - cdsapi>=0.7 - importlib-metadata<8.0 # 8.0 is incompatible with esmpy 8.4 (which is the only version available for windows 2024-07) + - esmpy>=8.3,<8.4.1 # 8.4.1 has an issue with ESMFMKFILE env var being required (otherwise, listing esmpy is redundant as xesmf needs it) - meson-python>=0.15,<0.16 # as of 2024-04 something seems to be wrong with 0.16 - osm-flex>=1.1 - overpy>=0.7 From a356e4efe113158e94182a8227d3ce565edeccaa Mon Sep 17 00:00:00 2001 From: Emanuel Schmid <51439563+emanuel-schmid@users.noreply.github.com> Date: Fri, 4 Oct 2024 10:42:10 +0200 Subject: [PATCH 07/10] CI/GitHub Actions: set job timeout 10 minutes (#147) --- .github/workflows/testing.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.github/workflows/testing.yml b/.github/workflows/testing.yml index fc7f6ff7..792d1b86 100644 --- a/.github/workflows/testing.yml +++ b/.github/workflows/testing.yml @@ -25,6 +25,7 @@ jobs: build-and-test: name: Unit Test Pipeline runs-on: ubuntu-latest + timeout-minutes: 10 permissions: # For publishing results checks: write From 91a1b9629f599f56557bb0afd706b18b22e1ec70 Mon Sep 17 00:00:00 2001 From: Emanuel Schmid <51439563+emanuel-schmid@users.noreply.github.com> Date: Mon, 21 Oct 2024 19:51:50 +0200 Subject: [PATCH 08/10] exposures-init-geometry (#128) * adaptations * adaptations * adaptations * enable venv over conda environment * setup venv for lint as well * fix erroneous Jenksfile * strip branch name * try again: strip new line * fail when make fails * failing lint is non-constructive * testing * simplify * adapt to changed Exposures interface * adapt to changed Exposures interface * Exposures: rename pmeta property to _metaadapt to changed Exposures interface * deprecate set_geomety_points * _meta property has been renamed to derive_raster method * explicitly set impf in test_copyield as there is no default set in check() anymore * revert Makefile changes * Makefile: force environmental pytest and pylint --- Makefile | 10 +- .../engine/test/test_supplychain.py | 15 +- .../entity/exposures/black_marble.py | 12 +- .../entity/exposures/crop_production.py | 118 +++++++------- climada_petals/entity/exposures/gdp_asset.py | 21 +-- climada_petals/entity/exposures/spam_agrar.py | 11 +- .../exposures/test/test_crop_production.py | 125 +++++++-------- .../entity/exposures/test/test_gdp_asset.py | 72 +++------ climada_petals/test/test_blackmarble.py | 39 ++--- climada_petals/test/test_cropyield_integr.py | 14 +- climada_petals/test/test_drought_integr.py | 4 +- climada_petals/test/test_gdp_asset_integr.py | 146 ++++++++---------- climada_petals/test/test_spamagrar_integr.py | 18 +-- script/jenkins/branches/Jenkinsfile | 27 ++-- script/jenkins/branches/make_in_venv.sh | 23 +++ script/jenkins/branches/setup_venv.sh | 24 +++ 16 files changed, 344 insertions(+), 335 deletions(-) create mode 100644 script/jenkins/branches/make_in_venv.sh create mode 100644 script/jenkins/branches/setup_venv.sh diff --git a/Makefile b/Makefile index 6253c9e2..8aa293f0 100644 --- a/Makefile +++ b/Makefile @@ -16,15 +16,15 @@ help: ## Use one of the following instructions: .PHONY : lint lint : ## Static code analysis with Pylint - pylint -ry climada_petals > pylint.log || true + python -m pylint -ry climada_petals > pylint.log || true .PHONY : unit_test unit_test : ## Unit tests execution with coverage and xml reports - pytest $(PYTEST_ARGS) --ignore=climada_petals/test climada_petals/ + python -m pytest $(PYTEST_ARGS) --ignore=climada_petals/test climada_petals/ .PHONY : install_test install_test : ## Test installation was successful - pytest $(PYTEST_JUNIT_ARGS) --pyargs climada.engine.test.test_cost_benefit \ + python -m pytest $(PYTEST_JUNIT_ARGS) --pyargs climada.engine.test.test_cost_benefit \ climada.engine.test.test_impact .PHONY : data_test @@ -37,11 +37,11 @@ notebook_test : ## Test notebooks in doc/tutorial .PHONY : integ_test integ_test : ## Integration tests execution with xml reports - pytest $(PYTEST_ARGS) climada_petals/test/ + python -m pytest $(PYTEST_ARGS) climada_petals/test/ .PHONY : test test : ## Unit and integration tests execution with coverage and xml reports - pytest $(PYTEST_ARGS) climada_petals/ + python -m pytest $(PYTEST_ARGS) climada_petals/ .PHONY : ci-clean ci-clean : diff --git a/climada_petals/engine/test/test_supplychain.py b/climada_petals/engine/test/test_supplychain.py index 45ae6440..17fc9fc8 100644 --- a/climada_petals/engine/test/test_supplychain.py +++ b/climada_petals/engine/test/test_supplychain.py @@ -179,11 +179,16 @@ def dummy_exp_imp(): " Generate dummy exposure and impacts " lat = np.array([1, 3]) lon = np.array([1.5, 3.5]) - exp = Exposures(crs=DEF_CRS) - exp.gdf['longitude'] = lon - exp.gdf['latitude'] = lat - exp.gdf['value'] = np.array([150., 80.]) - exp.gdf["region_id"] = [840, 608] # USA, PHL (ROW) + + exp = Exposures( + crs=DEF_CRS, + lon = lon, + lat = lat, + data = dict( + value = np.array([150., 80.]), + region_id = [840, 608], # USA, PHL (ROW) + ) + ) imp = Impact( event_id=np.arange(2) + 10, diff --git a/climada_petals/entity/exposures/black_marble.py b/climada_petals/entity/exposures/black_marble.py index 33a88ac9..735a198f 100644 --- a/climada_petals/entity/exposures/black_marble.py +++ b/climada_petals/entity/exposures/black_marble.py @@ -61,6 +61,11 @@ class BlackMarble(Exposures): _metadata = Exposures._metadata + ['nightlight_file'] + def __init__(self, *args, meta=None, nightlight_file=None, **kwargs): + super().__init__(*args, meta=meta, **kwargs) + meta = meta or {} + self.nightlight_file = Exposures._consolidate(meta, 'nightlight_file', nightlight_file) + def set_countries(self, countries, ref_year=2016, res_km=None, from_hr=None, admin_file='admin_0_countries', **kwargs): """ Model countries using values at reference year. If GDP or income @@ -124,13 +129,6 @@ def set_countries(self, countries, ref_year=2016, res_km=None, from_hr=None, nightlight_file = Path(fn_nl).name, ) - rows, cols, ras_trans = u_coord.pts_to_raster_meta( - (self.gdf.longitude.min(), self.gdf.latitude.min(), - self.gdf.longitude.max(), self.gdf.latitude.max()), - (coord_nl[0, 1], -coord_nl[0, 1]) - ) - self.meta = {'width': cols, 'height': rows, 'crs': self.crs, 'transform': ras_trans} - @staticmethod def _set_one_country(cntry_info, nightlight, coord_nl, res_fact, res_km, admin1_geom, **kwargs): diff --git a/climada_petals/entity/exposures/crop_production.py b/climada_petals/entity/exposures/crop_production.py index 4f493da3..70bd713d 100644 --- a/climada_petals/entity/exposures/crop_production.py +++ b/climada_petals/entity/exposures/crop_production.py @@ -148,6 +148,11 @@ class CropProduction(Exposures): _metadata = Exposures._metadata + ['crop'] + def __init__(self, *args, meta=None, crop=None, **kwargs): + super().__init__(*args, meta=meta, **kwargs) + meta = meta or {} + self.crop = Exposures._consolidate(meta, 'crop', crop) + def set_from_isimip_netcdf(self, *args, **kwargs): """This function is deprecated, use LitPop.from_isimip_netcdf instead.""" LOGGER.warning("The use of LitPop.set_from_isimip_netcdf is deprecated." @@ -269,13 +274,27 @@ def from_isimip_netcdf(cls, input_dir=None, filename=None, hist_mean=None, # The latitude and longitude are set; the region_id is determined lon, lat = np.meshgrid(data.lon.values, data.lat.values) - exp = cls() - exp.gdf['latitude'] = lat.flatten() - exp.gdf['longitude'] = lon.flatten() - exp.gdf['region_id'] = u_coord.get_country_code(exp.gdf.latitude, - exp.gdf.longitude, - gridded=True) - + latitude = lat.flatten() + longitude = lon.flatten() + region_id = u_coord.get_country_code( + lat=latitude, + lon=longitude, + gridded=True + ) + exp = cls( + lat = latitude, + lon = longitude, + data = dict( + region_id=region_id, + ), + description = "Crop production exposure from ISIMIP" + f" {CROP_NAME[crop]['print']} {irr}" + f" {yearrange[0]} {yearrange[-1]}", + value_unit = 't/y', # input unit, will be reset below if required by user + crop = crop, + ref_year = yearrange, + ) + # The indeces of the yearrange to be extracted are determined time_idx = (int(yearrange[0] - yearchunk['startyear']), int(yearrange[1] - yearchunk['startyear'])) @@ -310,10 +329,10 @@ def from_isimip_netcdf(cls, input_dir=None, filename=None, hist_mean=None, # if irr=='combined', both 'firr' and 'noirr' are required. raise ValueError(f'Invalid hist_mean provided: {hist_mean}') hist_mean_dict = hist_mean - lat_mean = exp.gdf.latitude.values + lat_mean = exp.latitude elif isinstance(hist_mean, np.ndarray) or isinstance(hist_mean, list): hist_mean_dict[irr_types[0]] = np.array(hist_mean) - lat_mean = exp.gdf.latitude.values + lat_mean = exp.latitude elif Path(hist_mean).is_dir(): # else if hist_mean is given as path to directory # The adequate file from the directory (depending on crop and irrigation) is extracted # and the variables hist_mean, lat_mean and lon_mean are set accordingly @@ -343,12 +362,12 @@ def from_isimip_netcdf(cls, input_dir=None, filename=None, hist_mean=None, raise ValueError(f"Invalid hist_mean provided: {hist_mean}") # The bbox is cut out of the hist_mean data file if needed - if len(lat_mean) != len(exp.gdf.latitude.values): - idx_mean = np.zeros(len(exp.gdf.latitude.values), dtype=int) - for i in range(len(exp.gdf.latitude.values)): + if len(lat_mean) != len(exp.latitude): + idx_mean = np.zeros(len(exp.latitude), dtype=int) + for i in range(len(exp.latitude)): idx_mean[i] = np.where( - (lat_mean == exp.gdf.latitude.values[i]) - & (lon_mean == exp.gdf.longitude.values[i]) + (lat_mean == exp.latitude[i]) + & (lon_mean == exp.longitude[i]) )[0][0] else: idx_mean = np.arange(0, len(lat_mean)) @@ -362,27 +381,6 @@ def from_isimip_netcdf(cls, input_dir=None, filename=None, hist_mean=None, value_tmp = np.squeeze(area_crop[irr_val]*hist_mean_dict[irr_val][idx_mean]) value_tmp = np.nan_to_num(value_tmp) # replace NaN by 0.0 exp.gdf['value'] += value_tmp - exp.description=("Crop production exposure from ISIMIP" - f" {CROP_NAME[crop]['print']} {irr}" - f" {yearrange[0]} {yearrange[-1]}") - exp.value_unit = 't/y' # input unit, will be reset below if required by user - exp.crop = crop - exp.ref_year = yearrange - try: - rows, cols, ras_trans = u_coord.pts_to_raster_meta( - (exp.gdf.longitude.min(), exp.gdf.latitude.min(), - exp.gdf.longitude.max(), exp.gdf.latitude.max()), - u_coord.get_resolution(exp.gdf.longitude, exp.gdf.latitude)) - exp.meta = { - 'width': cols, - 'height': rows, - 'crs': exp.crs, - 'transform': ras_trans, - } - except ValueError: - LOGGER.warning('Could not write attribute meta, because exposure' - ' has only 1 data point') - exp.meta = {} if 'USD' in unit: # set_value_to_usd() is called to compute the exposure in USD/y (country specific) @@ -471,36 +469,32 @@ def from_area_and_yield_nc4(cls, crop_type, layer_yield, layer_area, # The latitude and longitude are set; region_id is determined lon, lat = np.meshgrid(data_area.lon.values, data_area.lat.values) - exp = cls() # initiate coordinates and values in GeoDatFrame: - exp.gdf['latitude'] = lat.flatten() - exp.gdf['longitude'] = lon.flatten() - exp.gdf['region_id'] = u_coord.get_country_code(exp.gdf.latitude, - exp.gdf.longitude, gridded=True) + latitude = lat.flatten() + longitude = lon.flatten() + region_id = u_coord.get_country_code( + lat=latitude, + lon=longitude, + gridded=True) + # calc annual crop production, [t/y] = [ha] * [t/ha/y]: + value = np.multiply(data_area.values, data_yield.values).flatten() + + exp = cls( + lat=latitude, + lon=longitude, + data=dict( + region_id=region_id, + value=value, + ), + crop=crop_type, + description=f"Annual crop production from {var_area} and {var_yield} for" + f" {crop_type} from files {filename_area} and {filename_yield}", + value_unit = 't/y' + ) + exp.gdf[INDICATOR_IMPF + DEF_HAZ_TYPE] = 1 exp.gdf[INDICATOR_IMPF] = 1 - # calc annual crop production, [t/y] = [ha] * [t/ha/y]: - exp.gdf['value'] = np.multiply(data_area.values, data_yield.values).flatten() - - exp.crop = crop_type - exp.description=(f"Annual crop production from {var_area} and {var_yield} for" - f" {exp.crop} from files {filename_area} and {filename_yield}") - exp.value_unit = 't/y' - try: - rows, cols, ras_trans = u_coord.pts_to_raster_meta( - (exp.gdf.longitude.min(), exp.gdf.latitude.min(), - exp.gdf.longitude.max(), exp.gdf.latitude.max()), - u_coord.get_resolution(exp.gdf.longitude, exp.gdf.latitude)) - exp.meta = { - 'width': cols, - 'height': rows, - 'crs': exp.crs, - 'transform': ras_trans, - } - except ValueError: - LOGGER.warning('Could not write attribute meta, because exposure' - ' has only 1 data point') - exp.meta = {} + return exp def set_from_spam_ray_mirca(self, *args, **kwargs): diff --git a/climada_petals/entity/exposures/gdp_asset.py b/climada_petals/entity/exposures/gdp_asset.py index 0e969dc3..afb011ba 100644 --- a/climada_petals/entity/exposures/gdp_asset.py +++ b/climada_petals/entity/exposures/gdp_asset.py @@ -92,8 +92,8 @@ def set_countries(self, countries=[], reg=[], ref_year=2000, res = 0.0416666 rows, cols, ras_trans = u_coord.pts_to_raster_meta( - (self.gdf.longitude.min(), self.gdf.latitude.min(), - self.gdf.longitude.max(), self.gdf.latitude.max()), res) + (self.longitude.min(), self.latitude.min(), + self.longitude.max(), self.latitude.max()), res) self.meta = {'width': cols, 'height': rows, 'crs': self.crs, 'transform': ras_trans} @@ -130,13 +130,16 @@ def _set_one_country(countryISO, ref_year, path=None): reg_id_info = np.full((len(assets),), reg_id) impf_rf_info = np.full((len(assets),), impf_rf) - exp_gdpasset = GDP2Asset() - exp_gdpasset.gdf['value'] = assets - exp_gdpasset.gdf['latitude'] = coord[:, 0] - exp_gdpasset.gdf['longitude'] = coord[:, 1] - exp_gdpasset.gdf[INDICATOR_IMPF + DEF_HAZ_TYPE] = impf_rf_info - exp_gdpasset.gdf['region_id'] = reg_id_info - return exp_gdpasset + return GDP2Asset( + ref_year = ref_year, + value = assets, + lat = coord[:, 0], + lon = coord[:, 1], + data = { + INDICATOR_IMPF + DEF_HAZ_TYPE: impf_rf_info, + 'region_id': reg_id_info, + } + ) def _read_GDP(shp_exposures, ref_year, path=None): diff --git a/climada_petals/entity/exposures/spam_agrar.py b/climada_petals/entity/exposures/spam_agrar.py index 6663d6a5..3bb8741a 100644 --- a/climada_petals/entity/exposures/spam_agrar.py +++ b/climada_petals/entity/exposures/spam_agrar.py @@ -24,6 +24,7 @@ from pathlib import Path import pandas as pd import numpy as np +from shapely.geometry import Point from climada import CONFIG from climada.entity.exposures.base import Exposures, INDICATOR_IMPF @@ -153,12 +154,11 @@ def init_spam_agrar(self, **parameters): i_1 = 7 # get sum over all crops (columns 7 to 48) i_2 = 49 self.gdf['value'] = data.iloc[:, i_1:i_2].sum(axis=1).values - self.gdf['latitude'] = lat.values - self.gdf['longitude'] = lon.values + self.gdf['geometry'] = [Point(x,y) for x,y in zip(lon.values, lat.values)] LOGGER.info('Lat. range: {:+.3f} to {:+.3f}.'.format( - np.min(self.gdf.latitude), np.max(self.gdf.latitude))) + np.min(self.gdf.geometry.y), np.max(self.gdf.geometry.y))) LOGGER.info('Lon. range: {:+.3f} to {:+.3f}.'.format( - np.min(self.gdf.longitude), np.max(self.gdf.longitude))) + np.min(self.gdf.geometry.x), np.max(self.gdf.geometry.x))) # set region_id (numeric ISO3): country_id = data.loc[:, 'iso3'] @@ -189,7 +189,7 @@ def init_spam_agrar(self, **parameters): self.value_unit = 'USD' LOGGER.info('Total {} {} {}: {:.1f} {}.'.format( - spam_v, spam_t, region, self.gdf.value.sum(), self.value_unit)) + spam_v, spam_t, region, self.value.sum(), self.value_unit)) self.check() def _set_impf(self, spam_t, haz_type): @@ -218,7 +218,6 @@ def _set_impf(self, spam_t, haz_type): self.description += "\nrainfed portion of crop (= TA - TI)" else: self.gdf[INDICATOR_IMPF + haz_type] = 1 - self.set_geometry_points() def _read_spam_file(self, **parameters): """Reads data from SPAM CSV file and cuts out the data for the diff --git a/climada_petals/entity/exposures/test/test_crop_production.py b/climada_petals/entity/exposures/test/test_crop_production.py index f21b615f..0e08c047 100644 --- a/climada_petals/entity/exposures/test/test_crop_production.py +++ b/climada_petals/entity/exposures/test/test_crop_production.py @@ -42,9 +42,10 @@ def test_from_area_and_yield_nc4(self): self.assertEqual(exp.crop, 'whe') self.assertEqual(exp.gdf.shape[0], 55) - self.assertEqual(exp.meta['width'] * exp.meta['height'], 55) - self.assertIn(756, exp.gdf.region_id.values) - self.assertIn(380, exp.gdf.region_id.values) + raster = exp.derive_raster() + self.assertEqual(raster['width'] * raster['height'], 55) + self.assertIn(756, exp.region_id) + self.assertIn(380, exp.region_id) self.assertAlmostEqual(exp.gdf['value'].max(), 253225.66611428373) def test_isimip_load_central_EU(self): @@ -54,14 +55,14 @@ def test_isimip_load_central_EU(self): bbox=[-5, 42, 16, 55], yearrange=np.array([2001, 2005]), scenario='flexible', unit='t/y', crop = 'mai', irr='firr') - self.assertEqual(exp.gdf.longitude.min(), -4.75) - self.assertEqual(exp.gdf.longitude.max(), 15.75) - self.assertEqual(exp.gdf.latitude.min(), 42.25) - self.assertEqual(exp.gdf.latitude.max(), 54.75) - self.assertEqual(exp.gdf.value.shape, (1092,)) + self.assertEqual(exp.longitude.min(), -4.75) + self.assertEqual(exp.longitude.max(), 15.75) + self.assertEqual(exp.latitude.min(), 42.25) + self.assertEqual(exp.latitude.max(), 54.75) + self.assertEqual(exp.value.shape, (1092,)) self.assertEqual(exp.value_unit, 't/y') self.assertEqual(exp.crop, 'mai') - self.assertAlmostEqual(exp.gdf.value.max(), 284244.81023404596, places=5) + self.assertAlmostEqual(exp.value.max(), 284244.81023404596, places=5) def test_set_value_to_usd(self): """Test calculating crop_production Exposure in [USD/y] (deprecated set method)""" @@ -69,17 +70,17 @@ def test_set_value_to_usd(self): bbox=[-5, 42, 16, 55], yearrange=np.array([2001, 2005]), scenario='flexible', unit='t/y', crop = 'mai', irr='firr') exp.set_value_to_usd(INPUT_DIR, yearrange=(2000, 2018)) - self.assertEqual(exp.gdf.longitude.min(), -4.75) - self.assertEqual(exp.gdf.longitude.max(), 15.75) - self.assertEqual(exp.gdf.latitude.min(), 42.25) - self.assertEqual(exp.gdf.latitude.max(), 54.75) - self.assertEqual(exp.gdf.value.shape, (1092,)) + self.assertEqual(exp.longitude.min(), -4.75) + self.assertEqual(exp.longitude.max(), 15.75) + self.assertEqual(exp.latitude.min(), 42.25) + self.assertEqual(exp.latitude.max(), 54.75) + self.assertEqual(exp.value.shape, (1092,)) self.assertEqual(exp.value_unit, 'USD/y') self.assertEqual(exp.crop, 'mai') - self.assertAlmostEqual(exp.gdf.tonnes_per_year[28], 1998.3634803238633) - self.assertAlmostEqual(exp.gdf.value.max(), 51603897.28533253, places=5) - self.assertAlmostEqual(exp.gdf.value.mean(), 899384.5340130781, places=5) - self.assertEqual(exp.gdf.value.min(), 0.0) + self.assertAlmostEqual(exp.data["tonnes_per_year"][28], 1998.3634803238633) + self.assertAlmostEqual(exp.value.max(), 51603897.28533253, places=5) + self.assertAlmostEqual(exp.value.mean(), 899384.5340130781, places=5) + self.assertEqual(exp.value.min(), 0.0) def test_value_to_usd(self): """Test calculating crop_production Exposure in [USD/y] (new function)""" @@ -87,17 +88,17 @@ def test_value_to_usd(self): bbox=[-5, 42, 16, 55], yearrange=np.array([2001, 2005]), scenario='flexible', unit='t/y', crop = 'mai', irr='firr') exp = cp.value_to_usd(exp, INPUT_DIR, yearrange=(2000, 2018)) - self.assertEqual(exp.gdf.longitude.min(), -4.75) - self.assertEqual(exp.gdf.longitude.max(), 15.75) - self.assertEqual(exp.gdf.latitude.min(), 42.25) - self.assertEqual(exp.gdf.latitude.max(), 54.75) - self.assertEqual(exp.gdf.value.shape, (1092,)) + self.assertEqual(exp.longitude.min(), -4.75) + self.assertEqual(exp.longitude.max(), 15.75) + self.assertEqual(exp.latitude.min(), 42.25) + self.assertEqual(exp.latitude.max(), 54.75) + self.assertEqual(exp.value.shape, (1092,)) self.assertEqual(exp.value_unit, 'USD/y') self.assertEqual(exp.crop, 'mai') - self.assertAlmostEqual(exp.gdf.tonnes_per_year[28], 1998.3634803238633) - self.assertAlmostEqual(exp.gdf.value.max(), 51603897.28533253, places=5) - self.assertAlmostEqual(exp.gdf.value.mean(), 899384.5340130781, places=5) - self.assertEqual(exp.gdf.value.min(), 0.0) + self.assertAlmostEqual(exp.data["tonnes_per_year"][28], 1998.3634803238633) + self.assertAlmostEqual(exp.value.max(), 51603897.28533253, places=5) + self.assertAlmostEqual(exp.value.mean(), 899384.5340130781, places=5) + self.assertEqual(exp.value.min(), 0.0) def test_set_value_to_kcal(self): """Test calculating crop_production Exposure in [kcal/y] (deprecated setmethod)""" @@ -106,28 +107,28 @@ def test_set_value_to_kcal(self): exp = cp.CropProduction.from_isimip_netcdf(input_dir=INPUT_DIR, filename=FILENAME, hist_mean=FILENAME_MEAN, bbox=[-5, 45, 10, 50], yearrange=np.array([2001, 2005]), scenario='flexible', unit='t/y', crop = 'mai', irr='firr') - max_tonnes = exp.gdf.value.max() + max_tonnes = exp.value.max() exp.set_value_to_kcal() - self.assertEqual(exp.gdf.latitude.min(), 45.25) - self.assertEqual(exp.gdf.latitude.max(), 49.75) - self.assertEqual(exp.gdf.value.shape, (300,)) - self.assertAlmostEqual(exp.gdf.value.max(), 3.56e6 * max_tonnes, places=3) - self.assertAlmostEqual(exp.gdf.value.max(), 852926234509.3002, places=3) - self.assertAlmostEqual(exp.gdf.value.mean(), 19419372198.727455, places=4) - self.assertEqual(exp.gdf.value.min(), 0.0) + self.assertEqual(exp.latitude.min(), 45.25) + self.assertEqual(exp.latitude.max(), 49.75) + self.assertEqual(exp.value.shape, (300,)) + self.assertAlmostEqual(exp.value.max(), 3.56e6 * max_tonnes, places=3) + self.assertAlmostEqual(exp.value.max(), 852926234509.3002, places=3) + self.assertAlmostEqual(exp.value.mean(), 19419372198.727455, places=4) + self.assertEqual(exp.value.min(), 0.0) # (2) biomass = False exp = cp.CropProduction.from_isimip_netcdf(input_dir=INPUT_DIR, filename=FILENAME, hist_mean=FILENAME_MEAN, bbox=[-5, 45, 10, 50], yearrange=np.array([2001, 2005]), scenario='flexible', unit='t/y', crop = 'mai', irr='firr') - max_tonnes = exp.gdf.value.max() + max_tonnes = exp.value.max() exp.set_value_to_kcal(biomass=False) - self.assertEqual(exp.gdf.latitude.min(), 45.25) - self.assertEqual(exp.gdf.value.shape, (300,)) - self.assertAlmostEqual(exp.gdf.value.max(), 3.56e6 * max_tonnes /(1-.12), + self.assertEqual(exp.latitude.min(), 45.25) + self.assertEqual(exp.value.shape, (300,)) + self.assertAlmostEqual(exp.value.max(), 3.56e6 * max_tonnes /(1-.12), places=3) - self.assertAlmostEqual(exp.gdf.value.mean(), 22067468407.644833, places=4) + self.assertAlmostEqual(exp.value.mean(), 22067468407.644833, places=4) def test_value_to_kcal(self): """Test calculating crop_production Exposure in [kcal/y] (new function)""" @@ -136,27 +137,27 @@ def test_value_to_kcal(self): exp = cp.CropProduction.from_isimip_netcdf(input_dir=INPUT_DIR, filename=FILENAME, hist_mean=FILENAME_MEAN, bbox=[-5, 45, 10, 50], yearrange=np.array([2001, 2005]), scenario='flexible', unit='t/y', crop = 'mai', irr='firr') - max_tonnes = exp.gdf.value.max() + max_tonnes = exp.value.max() exp = cp.value_to_kcal(exp) - self.assertEqual(exp.gdf.latitude.min(), 45.25) - self.assertEqual(exp.gdf.latitude.max(), 49.75) - self.assertEqual(exp.gdf.value.shape, (300,)) - self.assertAlmostEqual(exp.gdf.value.max(), 3.56e6 * max_tonnes, places=3) - self.assertAlmostEqual(exp.gdf.value.max(), 852926234509.3002, places=3) - self.assertEqual(exp.gdf.value.min(), 0.0) + self.assertEqual(exp.latitude.min(), 45.25) + self.assertEqual(exp.latitude.max(), 49.75) + self.assertEqual(exp.value.shape, (300,)) + self.assertAlmostEqual(exp.value.max(), 3.56e6 * max_tonnes, places=3) + self.assertAlmostEqual(exp.value.max(), 852926234509.3002, places=3) + self.assertEqual(exp.value.min(), 0.0) # (2) biomass = False exp = cp.CropProduction.from_isimip_netcdf(input_dir=INPUT_DIR, filename=FILENAME, hist_mean=FILENAME_MEAN, bbox=[-5, 45, 10, 50], yearrange=np.array([2001, 2005]), scenario='flexible', unit='t/y', crop = 'mai', irr='firr') - max_tonnes = exp.gdf.value.max() + max_tonnes = exp.value.max() exp = cp.value_to_kcal(exp, biomass=False) - self.assertEqual(exp.gdf.latitude.min(), 45.25) - self.assertEqual(exp.gdf.value.shape, (300,)) - self.assertAlmostEqual(exp.gdf.value.max(), 3.56e6 * max_tonnes /(1-.12), + self.assertEqual(exp.latitude.min(), 45.25) + self.assertEqual(exp.value.shape, (300,)) + self.assertAlmostEqual(exp.value.max(), 3.56e6 * max_tonnes /(1-.12), places=3) - self.assertAlmostEqual(exp.gdf.value.mean(), 22067468407.644833, places=4) + self.assertAlmostEqual(exp.value.mean(), 22067468407.644833, places=4) def set_value_to_usd(self): @@ -164,14 +165,14 @@ def set_value_to_usd(self): exp = cp.CropProduction.from_isimip_netcdf(input_dir=INPUT_DIR, filename=FILENAME, hist_mean=FILENAME_MEAN, bbox=[-5, 42, 16, 55], yearrange=np.array([2001, 2005]), scenario='flexible', crop = 'mai', irr='firr', unit='USD/y') - self.assertEqual(exp.gdf.longitude.min(), -4.75) - self.assertEqual(exp.gdf.longitude.max(), 15.75) - self.assertEqual(exp.gdf.latitude.min(), 42.25) - self.assertEqual(exp.gdf.latitude.max(), 54.75) - self.assertEqual(exp.gdf.value.shape, (1092,)) + self.assertEqual(exp.longitude.min(), -4.75) + self.assertEqual(exp.longitude.max(), 15.75) + self.assertEqual(exp.latitude.min(), 42.25) + self.assertEqual(exp.latitude.max(), 54.75) + self.assertEqual(exp.value.shape, (1092,)) self.assertEqual(exp.value_unit, 'USD/y') self.assertEqual(exp.crop, 'mai') - self.assertAlmostEqual(exp.gdf.value.max(), 51603897.28533253, places=6) + self.assertAlmostEqual(exp.value.max(), 51603897.28533253, places=6) def test_normalize_with_fao_cp(self): """ Test normalizing of two given exposures countrywise (usually firr + norr) @@ -186,10 +187,10 @@ def test_normalize_with_fao_cp(self): self.assertAlmostEqual(ratio[11], .86250775) self.assertAlmostEqual(fao_crop_production[2], 673416.4) self.assertAlmostEqual(fao_crop_production[11], 160328.7) - self.assertAlmostEqual(np.nanmax(exp_firr_norm.gdf.value.values), 220735.69212710857) - self.assertAlmostEqual(np.nanmax(exp_firr_norm.gdf.value.values), np.nanmax(exp_noirr_norm.gdf.value.values)) - self.assertAlmostEqual(np.nanmax(exp.gdf.value.values), 284244.81023404596) - self.assertAlmostEqual(np.nansum(exp_noirr_norm.gdf.value.values) + np.nansum(exp_firr_norm.gdf.value.values), np.nansum(fao_crop_production), places=1) + self.assertAlmostEqual(np.nanmax(exp_firr_norm.value), 220735.69212710857) + self.assertAlmostEqual(np.nanmax(exp_firr_norm.value), np.nanmax(exp_noirr_norm.value)) + self.assertAlmostEqual(np.nanmax(exp.value), 284244.81023404596) + self.assertAlmostEqual(np.nansum(exp_noirr_norm.value) + np.nansum(exp_firr_norm.value), np.nansum(fao_crop_production), places=1) self.assertListEqual(list(country_list), [0, 40, 56, 70, 191, 203, 208, 250, 276, 380, 442, 528, 616, 705, 724, 756, 826]) diff --git a/climada_petals/entity/exposures/test/test_gdp_asset.py b/climada_petals/entity/exposures/test/test_gdp_asset.py index 8c57d004..4ded1a0d 100644 --- a/climada_petals/entity/exposures/test/test_gdp_asset.py +++ b/climada_petals/entity/exposures/test/test_gdp_asset.py @@ -53,54 +53,26 @@ def test_set_one_country(self): with self.assertRaises(KeyError): ga.GDP2Asset._set_one_country('LIE', 2001, path=DEMO_GDP2ASSET) - exp_test = ga.GDP2Asset._set_one_country('LIE', 2000, path=DEMO_GDP2ASSET).gdf - - self.assertAlmostEqual(exp_test.iloc[0, 2], 9.5206968) - self.assertAlmostEqual(exp_test.iloc[1, 2], 9.5623634) - self.assertAlmostEqual(exp_test.iloc[2, 2], 9.60403) - self.assertAlmostEqual(exp_test.iloc[3, 2], 9.5206968) - self.assertAlmostEqual(exp_test.iloc[4, 2], 9.5623634) - self.assertAlmostEqual(exp_test.iloc[5, 2], 9.60403) - self.assertAlmostEqual(exp_test.iloc[6, 2], 9.5206968) - self.assertAlmostEqual(exp_test.iloc[7, 2], 9.5623634) - self.assertAlmostEqual(exp_test.iloc[8, 2], 9.60403) - self.assertAlmostEqual(exp_test.iloc[9, 2], 9.5206968) - self.assertAlmostEqual(exp_test.iloc[10, 2], 9.5623634) - self.assertAlmostEqual(exp_test.iloc[11, 2], 9.5206968) - self.assertAlmostEqual(exp_test.iloc[12, 2], 9.5623634) - - self.assertAlmostEqual(exp_test.iloc[0, 1], 47.0622474) - self.assertAlmostEqual(exp_test.iloc[1, 1], 47.0622474) - self.assertAlmostEqual(exp_test.iloc[2, 1], 47.0622474) - self.assertAlmostEqual(exp_test.iloc[3, 1], 47.103914) - self.assertAlmostEqual(exp_test.iloc[4, 1], 47.103914) - self.assertAlmostEqual(exp_test.iloc[5, 1], 47.103914) - self.assertAlmostEqual(exp_test.iloc[6, 1], 47.1455806) - self.assertAlmostEqual(exp_test.iloc[7, 1], 47.1455806) - self.assertAlmostEqual(exp_test.iloc[8, 1], 47.1455806) - self.assertAlmostEqual(exp_test.iloc[9, 1], 47.1872472) - self.assertAlmostEqual(exp_test.iloc[10, 1], 47.1872472) - self.assertAlmostEqual(exp_test.iloc[11, 1], 47.2289138) - self.assertAlmostEqual(exp_test.iloc[12, 1], 47.2289138) - - self.assertAlmostEqual(exp_test.iloc[0, 0], 174032107.65846416) - self.assertAlmostEqual(exp_test.iloc[1, 0], 20386409.991937194) - self.assertAlmostEqual(exp_test.iloc[2, 0], 2465206.6989314994) - self.assertAlmostEqual(exp_test.iloc[3, 0], 0.0) - self.assertAlmostEqual(exp_test.iloc[4, 0], 12003959.733058406) - self.assertAlmostEqual(exp_test.iloc[5, 0], 97119771.42771776) - self.assertAlmostEqual(exp_test.iloc[6, 0], 0.0) - self.assertAlmostEqual(exp_test.iloc[7, 0], 4137081.3646739507) - self.assertAlmostEqual(exp_test.iloc[8, 0], 27411196.308422357) - self.assertAlmostEqual(exp_test.iloc[9, 0], 0.0) - self.assertAlmostEqual(exp_test.iloc[10, 0], 4125847.312198318) - self.assertAlmostEqual(exp_test.iloc[11, 0], 88557558.43543366) - self.assertAlmostEqual(exp_test.iloc[12, 0], 191881403.05181965) - - self.assertAlmostEqual(exp_test.iloc[0, 3], 3.0) - self.assertAlmostEqual(exp_test.iloc[12, 3], 3.0) - self.assertAlmostEqual(exp_test.iloc[0, 4], 11.0) - self.assertAlmostEqual(exp_test.iloc[12, 4], 11.0) + exp_test = ga.GDP2Asset._set_one_country('LIE', 2000, path=DEMO_GDP2ASSET) + + np.testing.assert_allclose(exp_test.latitude, np.array( + [47.0622474, 47.0622474, 47.0622474, 47.103914, 47.103914, 47.103914, 47.1455806, + 47.1455806, 47.1455806, 47.1872472, 47.1872472, 47.2289138, 47.2289138] + )) + np.testing.assert_allclose(exp_test.longitude, np.array( + [9.5206968, 9.5623634, 9.60403, 9.5206968, 9.5623634, 9.60403, 9.5206968, + 9.5623634, 9.60403, 9.5206968, 9.5623634, 9.5206968, 9.5623634] + )) + + np.testing.assert_allclose(exp_test.value, np.array( + [174032107.65846416, 20386409.991937194, 2465206.6989314994, + 0.0, 12003959.733058406, 97119771.42771776, + 0.0, 4137081.3646739507, 27411196.308422357, + 0.0, 4125847.312198318, 88557558.43543366, 191881403.05181965] + )) + + self.assertTrue((exp_test.gdf.impf_RF == 3).all()) + self.assertTrue((exp_test.gdf.region_id ==11).all()) def test_fast_impf_mapping(self): @@ -118,8 +90,8 @@ def test_read_GDP(self): exp_test = ga.GDP2Asset._set_one_country('LIE', 2000, DEMO_GDP2ASSET) coordinates = np.zeros((exp_test.gdf.shape[0], 2)) - coordinates[:, 0] = np.array(exp_test.gdf['latitude']) - coordinates[:, 1] = np.array(exp_test.gdf['longitude']) + coordinates[:, 0] = exp_test.latitude + coordinates[:, 1] = exp_test.longitude with self.assertRaises(KeyError): ga._read_GDP(coordinates, ref_year=2600, path=DEMO_GDP2ASSET) diff --git a/climada_petals/test/test_blackmarble.py b/climada_petals/test/test_blackmarble.py index 145b2fbc..8789a7b1 100644 --- a/climada_petals/test/test_blackmarble.py +++ b/climada_petals/test/test_blackmarble.py @@ -45,17 +45,18 @@ def test_spain_pass(self): cm.output[0]) self.assertIn("Processing country Spain.", cm.output[1]) self.assertIn("Generating resolution of approx 1 km.", cm.output[2]) - self.assertTrue(np.isclose(ent.gdf.value.sum(), 1.355e+12 * (4 + 1), 0.001)) + self.assertTrue(np.isclose(ent.value.sum(), 1.355e+12 * (4 + 1), 0.001)) self.assertTrue(u_coord.equal_crs(ent.crs, 'epsg:4326')) - self.assertEqual(ent.meta['width'], 2699) - self.assertEqual(ent.meta['height'], 1938) - self.assertTrue(u_coord.equal_crs(ent.meta['crs'], 'epsg:4326')) - self.assertAlmostEqual(ent.meta['transform'][0], 0.008333333333333333) - self.assertAlmostEqual(ent.meta['transform'][1], 0) - self.assertAlmostEqual(ent.meta['transform'][2], -18.1625000000000) - self.assertAlmostEqual(ent.meta['transform'][3], 0) - self.assertAlmostEqual(ent.meta['transform'][4], -0.008333333333333333) - self.assertAlmostEqual(ent.meta['transform'][5], 43.79583333333333) + ent_meta = ent.derive_raster() + self.assertEqual(ent_meta['width'], 2699) + self.assertEqual(ent_meta['height'], 1938) + self.assertTrue(u_coord.equal_crs(ent_meta['crs'], 'epsg:4326')) + self.assertAlmostEqual(ent_meta['transform'][0], 0.008333333333333333) + self.assertAlmostEqual(ent_meta['transform'][1], 0) + self.assertAlmostEqual(ent_meta['transform'][2], -18.1625000000000) + self.assertAlmostEqual(ent_meta['transform'][3], 0) + self.assertAlmostEqual(ent_meta['transform'][4], -0.008333333333333333) + self.assertAlmostEqual(ent_meta['transform'][5], 43.79583333333333) def test_sint_maarten_pass(self): country_name = ['Sint Maarten'] @@ -72,7 +73,7 @@ def test_sint_maarten_pass(self): cm.output[0]) self.assertIn("Processing country Sint Maarten.", cm.output[1]) self.assertIn("Generating resolution of approx 0.2 km.", cm.output[2]) - self.assertTrue(np.isclose(ent.gdf.value.sum(), 1.023e+09 * (4 + 1), 0.001)) + self.assertTrue(np.isclose(ent.value.sum(), 1.023e+09 * (4 + 1), 0.001)) self.assertTrue(u_coord.equal_crs(ent.crs, 'epsg:4326')) def test_anguilla_pass(self): @@ -81,7 +82,7 @@ def test_anguilla_pass(self): ent.set_countries(country_name, 2013, res_km=0.2) self.assertEqual(ent.ref_year, 2013) self.assertEqual("Anguilla 2013 GDP: 1.750e+08 income group: 3", ent.description) - self.assertAlmostEqual(ent.gdf.value.sum(), 1.75e+08 * (3 + 1)) + self.assertAlmostEqual(ent.value.sum(), 1.75e+08 * (3 + 1)) self.assertTrue(u_coord.equal_crs(ent.crs, 'epsg:4326')) class Test1968(unittest.TestCase): @@ -100,7 +101,7 @@ def test_switzerland_pass(self): cm.output[0]) self.assertTrue("Processing country Switzerland." in cm.output[-2]) self.assertTrue("Generating resolution of approx 0.5 km." in cm.output[-1]) - self.assertTrue(np.isclose(ent.gdf.value.sum(), 1.894e+10 * (4 + 1), 4)) + self.assertTrue(np.isclose(ent.value.sum(), 1.894e+10 * (4 + 1), 4)) self.assertTrue(u_coord.equal_crs(ent.crs, 'epsg:4326')) class Test2012(unittest.TestCase): @@ -114,17 +115,17 @@ def test_from_hr_flag_pass(self): with self.assertLogs('climada_petals.entity.exposures.black_marble', level='INFO') as cm: ent.set_countries(country_name, 2012, res_km=5.0) self.assertTrue('NOAA' in cm.output[-3]) - size1 = ent.gdf.value.size - self.assertTrue(np.isclose(ent.gdf.value.sum(), 8.740e+11 * (3 + 1), 4)) + size1 = ent.value.size + self.assertTrue(np.isclose(ent.value.sum(), 8.740e+11 * (3 + 1), 4)) try: ent = BlackMarble() with self.assertLogs('climada_petals.entity.exposures.black_marble', level='INFO') as cm: ent.set_countries(country_name, 2012, res_km=5.0, from_hr=True) self.assertTrue('NASA' in cm.output[-3]) - size2 = ent.gdf.value.size + size2 = ent.value.size self.assertTrue(size1 < size2) - self.assertTrue(np.isclose(ent.gdf.value.sum(), 8.740e+11 * (3 + 1), 4)) + self.assertTrue(np.isclose(ent.value.sum(), 8.740e+11 * (3 + 1), 4)) except TypeError: print('MemoryError caught') pass @@ -133,8 +134,8 @@ def test_from_hr_flag_pass(self): with self.assertLogs('climada_petals.entity.exposures.black_marble', level='INFO') as cm: ent.set_countries(country_name, 2012, res_km=5.0, from_hr=False) self.assertTrue('NOAA' in cm.output[-3]) - self.assertTrue(np.isclose(ent.gdf.value.sum(), 8.740e+11 * (3 + 1), 4)) - size3 = ent.gdf.value.size + self.assertTrue(np.isclose(ent.value.sum(), 8.740e+11 * (3 + 1), 4)) + size3 = ent.value.size self.assertEqual(size1, size3) self.assertTrue(u_coord.equal_crs(ent.crs, 'epsg:4326')) diff --git a/climada_petals/test/test_cropyield_integr.py b/climada_petals/test/test_cropyield_integr.py index a36e5a5f..9aa1e210 100644 --- a/climada_petals/test/test_cropyield_integr.py +++ b/climada_petals/test/test_cropyield_integr.py @@ -23,6 +23,7 @@ import numpy as np from climada.engine import Impact from climada.entity import ImpactFuncSet +from climada.entity.exposures import INDICATOR_IMPF from climada.util.constants import DEMO_DIR as INPUT_DIR from climada_petals.entity import ImpfRelativeCropyield from climada_petals.entity.exposures.crop_production import CropProduction, value_to_usd @@ -52,6 +53,7 @@ def test_EU(self): crop='whe', irr='firr') exp = value_to_usd(exp, INPUT_DIR, yearrange=(2000, 2018)) exp.assign_centroids(haz, threshold=20) + exp.data[INDICATOR_IMPF + haz_new.haz_type] = 1 impf_cp = ImpactFuncSet() impf_def = ImpfRelativeCropyield.impf_relativeyield() @@ -60,7 +62,7 @@ def test_EU(self): impact = Impact() reg_sel = exp.copy() - reg_sel.gdf = reg_sel.gdf[reg_sel.gdf.region_id == 276] + reg_sel.data = reg_sel.gdf[reg_sel.gdf.region_id == 276] impact.calc(reg_sel, impf_cp, haz_new.select(['2002']), save_mat=True) exp_manual = reg_sel.gdf.value @@ -71,10 +73,10 @@ def test_EU(self): self.assertEqual(haz_new.size, 5) self.assertEqual(haz_new.centroids.size, 1092) self.assertAlmostEqual(haz_new.intensity.mean(), -2.0489097e-08, places=0) - self.assertAlmostEqual(exp.gdf.value.max(), 52278210.72839116, places=0) - self.assertEqual(exp.gdf.latitude.values.size, 1092) - self.assertAlmostEqual(exp.gdf.value[3], 0.0) - self.assertAlmostEqual(exp.gdf.value[1077], 398947.79657832277, places=0) + self.assertAlmostEqual(exp.value.max(), 52278210.72839116, places=0) + self.assertEqual(exp.latitude.size, 1092) + self.assertAlmostEqual(exp.value[3], 0.0) + self.assertAlmostEqual(exp.value[1077], 398947.79657832277, places=0) self.assertAlmostEqual(impact.imp_mat.data[3], -178745.59091285995, places=0) self.assertEqual(len(dif), 0) @@ -93,6 +95,7 @@ def test_EU_nan(self): bbox=bbox, yearrange=(2001, 2005), scenario='flexible', unit='t/y', crop='whe', irr='firr') exp.assign_centroids(haz, threshold=20) + exp.data[INDICATOR_IMPF + haz.haz_type] = 1 impf_cp = ImpactFuncSet() impf_def = ImpfRelativeCropyield.impf_relativeyield() @@ -107,6 +110,7 @@ def test_EU_nan(self): scenario='flexible', unit='t/y', crop='whe', irr='firr') exp_nan.gdf.value[exp_nan.gdf.value==0] = np.nan exp_nan.assign_centroids(haz, threshold=20) + exp_nan.data[INDICATOR_IMPF + haz.haz_type] = 1 impact_nan = Impact() impact_nan.calc(exp_nan, impf_cp, haz, save_mat=True) diff --git a/climada_petals/test/test_drought_integr.py b/climada_petals/test/test_drought_integr.py index 9bf30d0f..d97615aa 100644 --- a/climada_petals/test/test_drought_integr.py +++ b/climada_petals/test/test_drought_integr.py @@ -53,8 +53,8 @@ def test_switzerland(self): self.assertEqual(hazard_set.haz_type, 'DR') self.assertEqual(hazard_set.size, 114) self.assertEqual(hazard_set.centroids.size, 130) - self.assertEqual(exposure_agrar.gdf.latitude.values.size, 766 / 2) - self.assertAlmostEqual(exposure_agrar.gdf.value[3], 1720024.4) + self.assertEqual(exposure_agrar.latitude.size, 766 / 2) + self.assertAlmostEqual(exposure_agrar.value[3], 1720024.4) self.assertAlmostEqual(damages_drought, 61995472.555223145) diff --git a/climada_petals/test/test_gdp_asset_integr.py b/climada_petals/test/test_gdp_asset_integr.py index b6feda94..24548502 100644 --- a/climada_petals/test/test_gdp_asset_integr.py +++ b/climada_petals/test/test_gdp_asset_integr.py @@ -43,88 +43,76 @@ def test_one_set_countries(self): testGDP2A_LIE = ga.GDP2Asset() testGDP2A_LIE.set_countries(countries=['LIE'], path=DEMO_GDP2ASSET) - self.assertAlmostEqual(testGDP2A_LIE.gdf.iloc[0, 2], 9.5206968) - self.assertAlmostEqual(testGDP2A_LIE.gdf.iloc[1, 2], 9.5623634) - self.assertAlmostEqual(testGDP2A_LIE.gdf.iloc[2, 2], 9.60403) - self.assertAlmostEqual(testGDP2A_LIE.gdf.iloc[3, 2], 9.5206968) - self.assertAlmostEqual(testGDP2A_LIE.gdf.iloc[4, 2], 9.5623634) - self.assertAlmostEqual(testGDP2A_LIE.gdf.iloc[5, 2], 9.60403) - self.assertAlmostEqual(testGDP2A_LIE.gdf.iloc[6, 2], 9.5206968) - self.assertAlmostEqual(testGDP2A_LIE.gdf.iloc[7, 2], 9.5623634) - self.assertAlmostEqual(testGDP2A_LIE.gdf.iloc[8, 2], 9.60403) - self.assertAlmostEqual(testGDP2A_LIE.gdf.iloc[9, 2], 9.5206968) - self.assertAlmostEqual(testGDP2A_LIE.gdf.iloc[10, 2], 9.5623634) - self.assertAlmostEqual(testGDP2A_LIE.gdf.iloc[11, 2], 9.5206968) - self.assertAlmostEqual(testGDP2A_LIE.gdf.iloc[12, 2], 9.5623634) - - self.assertAlmostEqual(testGDP2A_LIE.gdf.iloc[0, 1], 47.0622474) - self.assertAlmostEqual(testGDP2A_LIE.gdf.iloc[1, 1], 47.0622474) - self.assertAlmostEqual(testGDP2A_LIE.gdf.iloc[2, 1], 47.0622474) - self.assertAlmostEqual(testGDP2A_LIE.gdf.iloc[3, 1], 47.103914) - self.assertAlmostEqual(testGDP2A_LIE.gdf.iloc[4, 1], 47.103914) - self.assertAlmostEqual(testGDP2A_LIE.gdf.iloc[5, 1], 47.103914) - self.assertAlmostEqual(testGDP2A_LIE.gdf.iloc[6, 1], 47.1455806) - self.assertAlmostEqual(testGDP2A_LIE.gdf.iloc[7, 1], 47.1455806) - self.assertAlmostEqual(testGDP2A_LIE.gdf.iloc[8, 1], 47.1455806) - self.assertAlmostEqual(testGDP2A_LIE.gdf.iloc[9, 1], 47.1872472) - self.assertAlmostEqual(testGDP2A_LIE.gdf.iloc[10, 1], 47.1872472) - self.assertAlmostEqual(testGDP2A_LIE.gdf.iloc[11, 1], 47.2289138) - self.assertAlmostEqual(testGDP2A_LIE.gdf.iloc[12, 1], 47.2289138) - - self.assertAlmostEqual(testGDP2A_LIE.gdf.iloc[0, 0], 174032107.65846416) - self.assertAlmostEqual(testGDP2A_LIE.gdf.iloc[1, 0], 20386409.991937194) - self.assertAlmostEqual(testGDP2A_LIE.gdf.iloc[2, 0], 2465206.6989314994) - self.assertAlmostEqual(testGDP2A_LIE.gdf.iloc[3, 0], 0.0) - self.assertAlmostEqual(testGDP2A_LIE.gdf.iloc[4, 0], 12003959.733058406) - self.assertAlmostEqual(testGDP2A_LIE.gdf.iloc[5, 0], 97119771.42771776) - self.assertAlmostEqual(testGDP2A_LIE.gdf.iloc[6, 0], 0.0) - self.assertAlmostEqual(testGDP2A_LIE.gdf.iloc[7, 0], 4137081.3646739507) - self.assertAlmostEqual(testGDP2A_LIE.gdf.iloc[8, 0], 27411196.308422357) - self.assertAlmostEqual(testGDP2A_LIE.gdf.iloc[9, 0], 0.0) - self.assertAlmostEqual(testGDP2A_LIE.gdf.iloc[10, 0], 4125847.312198318) - self.assertAlmostEqual(testGDP2A_LIE.gdf.iloc[11, 0], 88557558.43543366) - self.assertAlmostEqual(testGDP2A_LIE.gdf.iloc[12, 0], 191881403.05181965) - - self.assertAlmostEqual(testGDP2A_LIE.gdf.iloc[0, 3], 3.0) - self.assertAlmostEqual(testGDP2A_LIE.gdf.iloc[12, 3], 3.0) - self.assertAlmostEqual(testGDP2A_LIE.gdf.iloc[0, 4], 11.0) - self.assertAlmostEqual(testGDP2A_LIE.gdf.iloc[12, 4], 11.0) + self.assertAlmostEqual(testGDP2A_LIE.longitude[0], 9.5206968) + self.assertAlmostEqual(testGDP2A_LIE.longitude[1], 9.5623634) + self.assertAlmostEqual(testGDP2A_LIE.longitude[2], 9.60403) + self.assertAlmostEqual(testGDP2A_LIE.longitude[3], 9.5206968) + self.assertAlmostEqual(testGDP2A_LIE.longitude[4], 9.5623634) + self.assertAlmostEqual(testGDP2A_LIE.longitude[5], 9.60403) + self.assertAlmostEqual(testGDP2A_LIE.longitude[6], 9.5206968) + self.assertAlmostEqual(testGDP2A_LIE.longitude[7], 9.5623634) + self.assertAlmostEqual(testGDP2A_LIE.longitude[8], 9.60403) + self.assertAlmostEqual(testGDP2A_LIE.longitude[9], 9.5206968) + self.assertAlmostEqual(testGDP2A_LIE.longitude[10], 9.5623634) + self.assertAlmostEqual(testGDP2A_LIE.longitude[11], 9.5206968) + self.assertAlmostEqual(testGDP2A_LIE.longitude[12], 9.5623634) + + self.assertAlmostEqual(testGDP2A_LIE.latitude[0], 47.0622474) + self.assertAlmostEqual(testGDP2A_LIE.latitude[1], 47.0622474) + self.assertAlmostEqual(testGDP2A_LIE.latitude[2], 47.0622474) + self.assertAlmostEqual(testGDP2A_LIE.latitude[3], 47.103914) + self.assertAlmostEqual(testGDP2A_LIE.latitude[4], 47.103914) + self.assertAlmostEqual(testGDP2A_LIE.latitude[5], 47.103914) + self.assertAlmostEqual(testGDP2A_LIE.latitude[6], 47.1455806) + self.assertAlmostEqual(testGDP2A_LIE.latitude[7], 47.1455806) + self.assertAlmostEqual(testGDP2A_LIE.latitude[8], 47.1455806) + self.assertAlmostEqual(testGDP2A_LIE.latitude[9], 47.1872472) + self.assertAlmostEqual(testGDP2A_LIE.latitude[10], 47.1872472) + self.assertAlmostEqual(testGDP2A_LIE.latitude[11], 47.2289138) + self.assertAlmostEqual(testGDP2A_LIE.latitude[12], 47.2289138) + + self.assertAlmostEqual(testGDP2A_LIE.value[0], 174032107.65846416) + self.assertAlmostEqual(testGDP2A_LIE.value[1], 20386409.991937194) + self.assertAlmostEqual(testGDP2A_LIE.value[2], 2465206.6989314994) + self.assertAlmostEqual(testGDP2A_LIE.value[3], 0.0) + self.assertAlmostEqual(testGDP2A_LIE.value[4], 12003959.733058406) + self.assertAlmostEqual(testGDP2A_LIE.value[5], 97119771.42771776) + self.assertAlmostEqual(testGDP2A_LIE.value[6], 0.0) + self.assertAlmostEqual(testGDP2A_LIE.value[7], 4137081.3646739507) + self.assertAlmostEqual(testGDP2A_LIE.value[8], 27411196.308422357) + self.assertAlmostEqual(testGDP2A_LIE.value[9], 0.0) + self.assertAlmostEqual(testGDP2A_LIE.value[10], 4125847.312198318) + self.assertAlmostEqual(testGDP2A_LIE.value[11], 88557558.43543366) + self.assertAlmostEqual(testGDP2A_LIE.value[12], 191881403.05181965) + + self.assertAlmostEqual(testGDP2A_LIE.gdf.impf_RF[0], 3.0) + self.assertAlmostEqual(testGDP2A_LIE.gdf.impf_RF[12], 3.0) + self.assertAlmostEqual(testGDP2A_LIE.gdf.region_id[0], 11.0) + self.assertAlmostEqual(testGDP2A_LIE.gdf.region_id[12], 11.0) def test_two_countries(self): testGDP2A_LIE_CHE = ga.GDP2Asset() - testGDP2A_LIE_CHE.set_countries(countries=['LIE', 'CHE'], - path=DEMO_GDP2ASSET) - - self.assertAlmostEqual(testGDP2A_LIE_CHE.gdf.iloc[0, 2], 9.520696799999968, - 4) - self.assertAlmostEqual(testGDP2A_LIE_CHE.gdf.iloc[45, 2], 7.39570019999996, - 4) - self.assertAlmostEqual(testGDP2A_LIE_CHE.gdf.iloc[1000, 2], - 9.604029999999966, 4) - self.assertAlmostEqual(testGDP2A_LIE_CHE.gdf.iloc[2500, 2], - 9.395696999999984, 4) - - self.assertAlmostEqual(testGDP2A_LIE_CHE.gdf.iloc[0, 1], - 47.062247399999976, 4) - self.assertAlmostEqual(testGDP2A_LIE_CHE.gdf.iloc[45, 1], - 45.978915799999996, 4) - self.assertAlmostEqual(testGDP2A_LIE_CHE.gdf.iloc[1000, 1], 46.6039148, 4) - self.assertAlmostEqual(testGDP2A_LIE_CHE.gdf.iloc[2500, 1], - 47.3955802, 4) - - self.assertAlmostEqual(testGDP2A_LIE_CHE.gdf.iloc[0, 0], - 174032107.65846416, 4) - self.assertAlmostEqual(testGDP2A_LIE_CHE.gdf.iloc[45, 0], - 11682292.467251074, 4) - self.assertAlmostEqual(testGDP2A_LIE_CHE.gdf.iloc[1000, 0], - 508470546.39168245, 4) - self.assertAlmostEqual(testGDP2A_LIE_CHE.gdf.iloc[2500, 0], - 949321115.5175464, 4) - - self.assertAlmostEqual(testGDP2A_LIE_CHE.gdf.iloc[0, 3], 3.0) - self.assertAlmostEqual(testGDP2A_LIE_CHE.gdf.iloc[12, 3], 3.0) - self.assertAlmostEqual(testGDP2A_LIE_CHE.gdf.iloc[0, 4], 11.0) - self.assertAlmostEqual(testGDP2A_LIE_CHE.gdf.iloc[2500, 4], 11.0) + testGDP2A_LIE_CHE.set_countries(countries=['LIE', 'CHE'], path=DEMO_GDP2ASSET) + + self.assertAlmostEqual(testGDP2A_LIE_CHE.longitude[0], 9.520696799999968, 4) + self.assertAlmostEqual(testGDP2A_LIE_CHE.longitude[45], 7.39570019999996, 4) + self.assertAlmostEqual(testGDP2A_LIE_CHE.longitude[1000], 9.604029999999966, 4) + self.assertAlmostEqual(testGDP2A_LIE_CHE.longitude[2500], 9.395696999999984, 4) + + self.assertAlmostEqual(testGDP2A_LIE_CHE.latitude[0], 47.062247399999976, 4) + self.assertAlmostEqual(testGDP2A_LIE_CHE.latitude[45], 45.978915799999996, 4) + self.assertAlmostEqual(testGDP2A_LIE_CHE.latitude[1000], 46.6039148, 4) + self.assertAlmostEqual(testGDP2A_LIE_CHE.latitude[2500], 47.3955802, 4) + + self.assertAlmostEqual(testGDP2A_LIE_CHE.value[0], 174032107.65846416, 4) + self.assertAlmostEqual(testGDP2A_LIE_CHE.value[45], 11682292.467251074, 4) + self.assertAlmostEqual(testGDP2A_LIE_CHE.value[1000], 508470546.39168245, 4) + self.assertAlmostEqual(testGDP2A_LIE_CHE.value[2500], 949321115.5175464, 4) + + self.assertAlmostEqual(testGDP2A_LIE_CHE.gdf.impf_RF[0], 3.0) + self.assertAlmostEqual(testGDP2A_LIE_CHE.gdf.impf_RF[12], 3.0) + self.assertAlmostEqual(testGDP2A_LIE_CHE.gdf.region_id[0], 11.0) + self.assertAlmostEqual(testGDP2A_LIE_CHE.gdf.region_id[2500], 11.0) if __name__ == "__main__": diff --git a/climada_petals/test/test_spamagrar_integr.py b/climada_petals/test/test_spamagrar_integr.py index 3b0adb06..2b2522ce 100644 --- a/climada_petals/test/test_spamagrar_integr.py +++ b/climada_petals/test/test_spamagrar_integr.py @@ -37,9 +37,9 @@ def test_global_pass(self): self.assertIn('Lat. range: -55.375 to +71.125.', cm.output[0]) self.assertIn('Lon. range: -179.125 to +179.958.', cm.output[1]) self.assertIn("Total V_agg TA global: 1301919384722.2 USD.", cm.output[2]) - self.assertEqual(ent.gdf.region_id.min(), 4) - self.assertEqual(ent.gdf.region_id[10000], 246) - self.assertEqual(ent.gdf.region_id.max(), 894) + self.assertEqual(ent.region_id.min(), 4) + self.assertEqual(ent.region_id[10000], 246) + self.assertEqual(ent.region_id.max(), 894) self.assertEqual(ent_select.value.sum(), 1878858118.0) self.assertEqual(ent_select.region_id.min(), 208) self.assertEqual(ent_select.region_id.max(), 208) @@ -57,8 +57,8 @@ def test_suriname_pass(self): self.assertIn('Lat. range: +1.875 to +5.958.', cm.output[0]) self.assertIn('Lon. range: -58.042 to -54.042.', cm.output[1]) self.assertIn("Total V_agg TA Suriname: 78879225.2 USD.", cm.output[2]) - self.assertEqual(ent.gdf.region_id.min(), 740) - self.assertEqual(ent.gdf.region_id.max(), 740) + self.assertEqual(ent.region_id.min(), 740) + self.assertEqual(ent.region_id.max(), 740) self.assertEqual(ent.spam_file, "spam2005V3r2_global_V_agg_TA.csv") self.assertEqual(ent.description, "SPAM agrar exposure for variable V_agg and technology TA\n" @@ -74,8 +74,8 @@ def test_zurich_pass(self): self.assertIn('Lat. range: +47.208 to +47.625.', cm.output[0]) self.assertIn('Lon. range: +8.375 to +8.875.', cm.output[1]) self.assertIn("Total V_agg TA CHE Zurich: 56644555.1 USD.", cm.output[2]) - self.assertEqual(ent.gdf.region_id.min(), 756) - self.assertEqual(ent.gdf.region_id.max(), 756) + self.assertEqual(ent.region_id.min(), 756) + self.assertEqual(ent.region_id.max(), 756) self.assertEqual(ent.spam_file, "spam2005V3r2_global_V_agg_TA.csv") self.assertEqual(ent.description, "SPAM agrar exposure for variable V_agg and technology TA\n" @@ -95,8 +95,8 @@ def test_switzerland_pass(self): self.assertIn('Lat. range: +45.875 to +47.792.', cm.output[0]) self.assertIn('Lon. range: +6.042 to +10.375.', cm.output[1]) self.assertIn("Total H TI CHE: 28427.1 Ha.", cm.output[2]) - self.assertEqual(ent.gdf.region_id.min(), 756) - self.assertEqual(ent.gdf.region_id.max(), 756) + self.assertEqual(ent.region_id.min(), 756) + self.assertEqual(ent.region_id.max(), 756) self.assertEqual(ent.spam_file, "spam2005V3r2_global_H_TI.csv") self.assertEqual(ent.description, "SPAM agrar exposure for variable H and technology TI\n" diff --git a/script/jenkins/branches/Jenkinsfile b/script/jenkins/branches/Jenkinsfile index a40e2ff1..ae80840f 100644 --- a/script/jenkins/branches/Jenkinsfile +++ b/script/jenkins/branches/Jenkinsfile @@ -1,18 +1,23 @@ pipeline { agent any + environment { + FULL_PATH_BRANCH = "${sh(script:'git name-rev --name-only HEAD', returnStdout: true)}" + GIT_BRANCH = FULL_PATH_BRANCH.substring(FULL_PATH_BRANCH.lastIndexOf('/') + 1, FULL_PATH_BRANCH.length() - 1) + } + stages { + stage('setup-environment') { + steps { + sh "bash script/jenkins/branches/setup_venv.sh ${env.GIT_BRANCH}" + } + } stage('ci') { parallel { stage('lint') { steps { - sh '''#!/bin/bash - export PATH=$PATH:$CONDAPATH - source activate petals_env - rm -f pylint.log - pylint -ry climada_petals | tee pylint.log''' - + sh "bash script/jenkins/branches/make_in_venv.sh ${env.GIT_BRANCH} lint" discoverGitReferenceBuild referenceJob: 'petals_branches/develop' recordIssues tools: [pyLint(pattern: 'pylint.log')] } @@ -20,15 +25,7 @@ pipeline { stage('unit_test') { steps { - sh '''#!/bin/bash - export PATH=$PATH:$CONDAPATH - source activate - - mamba env update -n petals_env -f requirements/env_climada.yml - conda activate petals_env - rm -rf tests_xml/ - rm -rf coverage/ - make unit_test''' + sh "bash script/jenkins/branches/make_in_venv.sh ${env.GIT_BRANCH} unit_test" } } diff --git a/script/jenkins/branches/make_in_venv.sh b/script/jenkins/branches/make_in_venv.sh new file mode 100644 index 00000000..661d102b --- /dev/null +++ b/script/jenkins/branches/make_in_venv.sh @@ -0,0 +1,23 @@ +#!/bin/bash +set -e + +export PATH=$PATH:$CONDAPATH + +source activate petals_env +rm -rf tests_xml/ +rm -rf coverage/ + +BRANCH=$1 +shift +CORENV=~/jobs/petals_branches/core_env +if [ -f $CORENV/$BRANCH ]; then + source tvenv/bin/activate +fi + +make $@ + +if [ -f $CORENV/$BRANCH ]; then + deactivate +fi + +conda deactivate diff --git a/script/jenkins/branches/setup_venv.sh b/script/jenkins/branches/setup_venv.sh new file mode 100644 index 00000000..32853d58 --- /dev/null +++ b/script/jenkins/branches/setup_venv.sh @@ -0,0 +1,24 @@ +#!/bin/bash +set -e + +export PATH=$PATH:$CONDAPATH + +BRANCH=$1 +CORENV=~/jobs/petals_branches/core_env + +echo $CORENV/$BRANCH + +if [ -f $CORENV/$BRANCH ]; then + echo file exists + cat $CORENV/$BRANCH + + source activate petals_env + + python -m venv --system-site-packages tvenv + source tvenv/bin/activate + + pip install -e `cat $CORENV/$BRANCH` + + deactivate + conda deactivate +fi From 2a6837e2c5bb0dc284f2f21929a59d03beb4e303 Mon Sep 17 00:00:00 2001 From: Alessio Ciullo <29018864+aleeciu@users.noreply.github.com> Date: Thu, 31 Oct 2024 11:14:40 +0100 Subject: [PATCH 09/10] Feature/add missing jrc flood impact functions (#111) * add sectorial impact functions * adjust tests due to different roundin, kwargs and function names * update tutorial * capture unknown sector * add tests looping through params and testing unknown ones * impact_funcs.river_flood: use dicts instead of if/else blocks * remove unnecessary mdr attribute * remove un-used dictionary * adjust object initiation --------- Co-authored-by: emanuel-schmid --- .../entity/impact_funcs/river_flood.py | 423 +++++++++++++----- .../entity/impact_funcs/test/test_fl.py | 194 ++++---- 2 files changed, 388 insertions(+), 229 deletions(-) diff --git a/climada_petals/entity/impact_funcs/river_flood.py b/climada_petals/entity/impact_funcs/river_flood.py index f38963ec..e5082cb7 100644 --- a/climada_petals/entity/impact_funcs/river_flood.py +++ b/climada_petals/entity/impact_funcs/river_flood.py @@ -29,21 +29,27 @@ from climada.util.constants import RIVER_FLOOD_REGIONS_CSV from climada.entity import ImpactFunc, ImpactFuncSet -LOGGER = logging.getLogger(__name__) -DEF_VAR_EXCEL = {'sheet_name': 'damagefunctions', - 'col_name': {'func_id': 'DamageFunID', - 'inten': 'Intensity', - 'mdd': 'MDD', - 'paa': 'PAA', - 'mdr': 'MDR', - 'name': 'name', - 'peril': 'peril_ID', - 'unit': 'Intensity_unit' - } - } +SECTOR_CO_ID = { + "Residential": 1, + "Commercial": 2, + "Industrial": 3, + "Transport": 4, + "Infrastructure": 5, + "Agriculture": 6, +} +REGION_CO_ID = { + "africa": 10, + "asia": 20, + "europe": 30, + "northamerica": 40, + "oceania": 50, + "southamerica": 60, +} +VALID_REGIONS = "Africa, Asia, Europe, North America, Oceania, South America" +LOGGER = logging.getLogger(__name__) class ImpfRiverFlood(ImpactFunc): """Impact functions for tropical cyclones.""" @@ -55,144 +61,329 @@ def __init__(self): self.continent = '' @classmethod - def from_region(cls, region): - """Create a new ImpfRiverFlood object with parameters for the specified world region. + def from_jrc_region_sector(cls, region, sector="residential"): + """Create a new ImpfRiverFlood object based on the specified world region and sector. + Impact functions come from the following JRC publication: + + Huizinga, J., De Moel, H. and Szewczyk, W., Global flood depth-damage functions: Methodology + and the database with guidelines, EUR 28552 EN, Publications Office of the European Union, + Luxembourg, 2017, ISBN 978-92-79-67781-6, doi:10.2760/16510, JRC105688. + + Notes + ----- + The impact functions assess percentage losses at 0, 0.5, 1, 1.5, 2, 3, 4, 5, 6 meters of + water. For North America, percentage losses higher than 0 are already registerd at 0 meters + of water, because it accounts for the presence of basements (see main publication). Since + this could be problematic when computing impacts, as one would have losses also when there + is no flood, a 0.05 meters of water point is added to all functions (not only North America, + for consistency), and this corresponds to the 0 meters point in the JRC functions. Parameters ---------- region : str - Use damage function parameters for this world region. Supported values: "Africa", - "Asia", "Europe", "NorthAmerica", "Oceania", "SouthAmerica". + world region for which the impact function was defined. Supported values: + "Africa", "Asia", "Europe", "North America", "Oceania", "South America". + + sector: str + sector for which the impact function was defined. Supported values: "residential", + "commercial", "industrial", "transport", "infrastructure", "agriculture". Returns ------- impf : ImpfRiverFlood - New ImpfRiverFlood object with parameters for the specified world region. + New ImpfRiverFlood object with parameters for the specified world region and sector. Raises ------ ValueError """ - impf = cls() - if region.lower() == "africa": - impf.id = 1 - impf.name = "Flood Africa JRC Residential noPAA" - impf.continent = 'Africa' - impf.intensity = np.array([0., 0.5, 1., 1.5, 2., 3., 4., 5., 6., 12.]) - impf.mdd = np.array([0.0000, 0.2199, 0.3782, 0.5306, 0.6356, 0.8169, - 0.9034, 0.9572, 1.0000, 1.0000]) - impf.mdr = np.array([0.0000, 0.2199, 0.3782, 0.5306, 0.6356, 0.8169, - 0.9034, 0.9572, 1.0000, 1.0000]) - elif region.lower() == "asia": - impf.id = 2 - impf.name = "Flood Asia JRC Residential noPAA" - impf.continent = 'Asia' - impf.intensity = np.array([0., 0.5, 1., 1.5, 2., 3., 4., 5., 6., 12.]) - impf.mdd = np.array([0.000, 0.3266, 0.4941, 0.6166, 0.7207, 0.8695, - 0.9315, 0.9836, 1.0000, 1.0000]) - impf.mdr = np.array([0.000, 0.3266, 0.4941, 0.6166, 0.7207, 0.8695, - 0.9315, 0.9836, 1.0000, 1.0000]) - elif region.lower() == "europe": - impf.id = 3 - impf.name = "Flood Europe JRC Residential noPAA" - impf.continent = 'Europe' - impf.intensity = np.array([0., 0.5, 1., 1.5, 2., 3., 4., 5., 6., 12.]) - impf.mdd = np.array([0.00, 0.25, 0.40, 0.50, 0.60, 0.75, 0.85, 0.95, - 1.00, 1.00]) - impf.mdr = np.array([0.000, 0.250, 0.400, 0.500, 0.600, 0.750, 0.850, - 0.950, 1.000, 1.000]) - elif region.lower().replace(" ", "") == "northamerica": - impf.id = 4 - impf.name = "Flood North America JRC Residential noPAA" - impf.continent = 'NorthAmerica' - impf.intensity = np.array([0., 0.1, 0.5, 1., 1.5, 2., 3., 4., 5., - 6., 12.]) - impf.mdd = np.array([0.0000, 0.2018, 0.4433, 0.5828, 0.6825, 0.7840, - 0.8543, 0.9237, 0.9585, 1.0000, 1.0000]) - impf.mdr = np.array([0.0000, 0.2018, 0.4433, 0.5828, 0.6825, 0.7840, - 0.8543, 0.9237, 0.9585, 1.0000, 1.0000]) - elif region.lower() == "oceania": - impf.id = 5 - impf.name = "Flood Oceania JRC Residential noPAA" - impf.continent = 'Oceania' - impf.intensity = np.array([0., 0.5, 1., 1.5, 2., 3., 4., 5., 6., 12.]) - impf.mdd = np.array([0.00, 0.48, 0.64, 0.71, 0.79, 0.93, 0.97, 0.98, - 1.00, 1.00]) - impf.mdr = np.array([0.000, 0.480, 0.640, 0.710, 0.790, 0.930, 0.970, - 0.980, 1.000, 1.000]) - elif region.lower().replace(" ", "") == "southamerica": - impf.id = 6 - impf.name = "Flood South America JRC Residential noPAA" - impf.continent = 'SouthAmerica' - impf.intensity = np.array([0., 0.5, 1., 1.5, 2., 3., 4., 5., 6., 12.]) - impf.mdd = np.array([0.0000, 0.4908, 0.7112, 0.8420, 0.9494, - 0.9836, 1.0000, 1.0000, 1.0000, 1.0000]) - impf.mdr = np.array([0.0000, 0.4908, 0.7112, 0.8420, 0.9494, 0.9836, - 1.0000, 1.0000, 1.0000, 1.0000]) + + if sector == 'residential': + impf_values, impf_id = from_jrc_impf_residential(region) + + elif sector == 'industrial': + impf_values, impf_id = from_jrc_impf_industrial(region) + + elif sector == 'commercial': + impf_values, impf_id = from_jrc_impf_commercial(region) + + elif sector == 'transport': + impf_values, impf_id = from_jrc_impf_transport(region) + + elif sector == 'infrastructure': + impf_values, impf_id = from_jrc_impf_infrastructure(region) + + elif sector == 'agriculture': + impf_values, impf_id = from_jrc_impf_agriculture(region) + else: - raise ValueError(f"Unrecognized world region: {region}") + raise ValueError(f"Unrecognized sector: {sector}") + + impf = cls() + impf.name = f"Flood {region} JRC {sector.capitalize()} noPAA" + impf.continent = f"{region}" + impf.id = impf_id + impf.mdd = impf_values + impf.intensity = np.array([0., 0.05, 0.5, 1., 1.5, 2., 3., 4., 5., 6., 12.]) impf.paa = np.ones(len(impf.intensity)) + return impf def set_RF_Impf_Africa(self, *args, **kwargs): - """This function is deprecated, use ImpfRiverFlood.from_region instead.""" + """This function is deprecated, use ImpfRiverFlood.from_region_sector instead.""" LOGGER.warning("The use of ImpfRiverFlood.set_RF_Impf_Africa is deprecated." - "Use ImpfRiverFlood.from_region instead.") - self.__dict__ = ImpfRiverFlood.from_region("Africa", *args, **kwargs).__dict__ + "Use ImpfRiverFlood.from_region_sector instead.") + self.__dict__ = ImpfRiverFlood.from_jrc_region_sector("Africa", *args, **kwargs).__dict__ def set_RF_Impf_Asia(self, *args, **kwargs): - """This function is deprecated, use ImpfRiverFlood.from_region instead.""" + """This function is deprecated, use ImpfRiverFlood.from_region_sector instead.""" LOGGER.warning("The use of ImpfRiverFlood.set_RF_Impf_Asia is deprecated." - "Use ImpfRiverFlood.from_region instead.") - self.__dict__ = ImpfRiverFlood.from_region("Asia", *args, **kwargs).__dict__ + "Use ImpfRiverFlood.from_region_sector instead.") + self.__dict__ = ImpfRiverFlood.from_jrc_region_sector("Asia", *args, **kwargs).__dict__ def set_RF_Impf_Europe(self, *args, **kwargs): - """This function is deprecated, use ImpfRiverFlood.from_region instead.""" + """This function is deprecated, use ImpfRiverFlood.from_region_sector instead.""" LOGGER.warning("The use of ImpfRiverFlood.set_RF_Impf_Europe is deprecated." - "Use ImpfRiverFlood.from_region instead.") - self.__dict__ = ImpfRiverFlood.from_region("Europe", *args, **kwargs).__dict__ + "Use ImpfRiverFlood.from_region_sector instead.") + self.__dict__ = ImpfRiverFlood.from_jrc_region_sector("Europe", *args, **kwargs).__dict__ def set_RF_Impf_NorthAmerica(self, *args, **kwargs): - """This function is deprecated, use ImpfRiverFlood.from_region instead.""" + """This function is deprecated, use ImpfRiverFlood.from_region_sector instead.""" LOGGER.warning("The use of ImpfRiverFlood.set_RF_Impf_NorthAmerica is deprecated." - "Use ImpfRiverFlood.from_region instead.") - self.__dict__ = ImpfRiverFlood.from_region("NorthAmerica", *args, **kwargs).__dict__ + "Use ImpfRiverFlood.from_region_sector instead.") + self.__dict__ = ImpfRiverFlood.from_jrc_region_sector("NorthAmerica", *args, **kwargs).__dict__ def set_RF_Impf_Oceania(self, *args, **kwargs): - """This function is deprecated, use ImpfRiverFlood.from_region instead.""" + """This function is deprecated, use ImpfRiverFlood.from_region_sector instead.""" LOGGER.warning("The use of ImpfRiverFlood.set_RF_Impf_Oceania is deprecated." - "Use ImpfRiverFlood.from_region instead.") - self.__dict__ = ImpfRiverFlood.from_region("Oceania", *args, **kwargs).__dict__ + "Use ImpfRiverFlood.from_region_sector instead.") + self.__dict__ = ImpfRiverFlood.from_jrc_region_sector("Oceania", *args, **kwargs).__dict__ def set_RF_Impf_SouthAmerica(self, *args, **kwargs): - """This function is deprecated, use ImpfRiverFlood.from_region instead.""" + """This function is deprecated, use ImpfRiverFlood.from_region_sector instead.""" LOGGER.warning("The use of ImpfRiverFlood.set_RF_Impf_SouthAmerica is deprecated." - "Use ImpfRiverFlood.from_region instead.") - self.__dict__ = ImpfRiverFlood.from_region("SouthAmerica", *args, **kwargs).__dict__ - - -def flood_imp_func_set(): - """Builds impact function set for river flood, using standard files""" - - impf_set = ImpactFuncSet() - - impf_africa = ImpfRiverFlood.from_region("Africa") - impf_set.append(impf_africa) - - impf_asia = ImpfRiverFlood.from_region("Asia") - impf_set.append(impf_asia) - - impf_europe = ImpfRiverFlood.from_region("Europe") - impf_set.append(impf_europe) - - impf_na = ImpfRiverFlood.from_region("NorthAmerica") - impf_set.append(impf_na) - - impf_oceania = ImpfRiverFlood.from_region("Oceania") - impf_set.append(impf_oceania) - - impf_sa = ImpfRiverFlood.from_region("SouthAmerica") - impf_set.append(impf_sa) + "Use ImpfRiverFlood.from_region_sector instead.") + self.__dict__ = ImpfRiverFlood.from_jrc_region_sector("SouthAmerica", *args, **kwargs).__dict__ + + + +def _from_jrc_impf(region, sector, impf_values_map): + """Boiler plate function for the public from_jrc_impf_*** functions""" + regkey = region.replace(' ', '').lower() + if regkey not in REGION_CO_ID: + raise ValueError(f"Unrecognized world region: {region}, must be one of {VALID_REGIONS}") + impf_id = REGION_CO_ID[regkey] + SECTOR_CO_ID[sector] + + impf_values = impf_values_map.get(regkey) + if impf_values is None: + raise ValueError(f"No impact function implemented for the {sector} sector in {region}") + return np.array(impf_values), impf_id + + + +def from_jrc_impf_residential(region): + """Create a new ImpfRiverFlood object for the residential sector of the a given + world region. + + Parameters + ---------- + region : str + world region for which the impact function was defined. Supported values: + "Africa", "Asia", "Europe", "North America", "Oceania", "South America". + + Returns + ------- + impf : ImpfRiverFlood + New ImpfRiverFlood object with parameters for the specified sector. + + Raises + ------ + ValueError + """ + return _from_jrc_impf( + region=region, + sector="Residential", + impf_values_map={ + "africa": [0., 0., 0.22, 0.378, 0.531, 0.636, 0.817, 0.903, 0.957, 1., 1.], + "asia": [0., 0., 0.327, 0.494, 0.617, 0.721, 0.87, 0.931, 0.984, 1., 1.], + "europe": [0., 0., 0.25, 0.4, 0.5, 0.6, 0.75, 0.85, 0.95, 1., 1.], + "northamerica": [0., 0.202, 0.443, 0.583, 0.683, 0.784, 0.854, 0.924, 0.959, 1., 1.], + "oceania": [0., 0., 0.475, 0.640, 0.715, 0.788, 0.929, 0.967, 0.983, 1., 1.], + "southamerica": [0., 0., 0.491, 0.711, 0.842, 0.949, 0.984, 1., 1., 1., 1.], + } + ) + + +def from_jrc_impf_commercial(region): + """Create a new ImpfRiverFlood object for the commercial sector of the a given world region. + + Parameters + ---------- + region : str + world region for which the impact function was defined. Supported values: + "Africa", "Asia", "Europe", "North America", "Oceania", "South America". + + Returns + ------- + impf : ImpfRiverFlood + New ImpfRiverFlood object with parameters for the specified sector. + + Raises + ------ + ValueError + """ + + return _from_jrc_impf( + region=region, + sector="Commercial", + impf_values_map={ + "asia": [0., 0., 0.377, 0.538, 0.659, 0.763, 0.883, 0.942, 0.981, 1., 1.], + "europe": [0., 0., 0.15, 0.3, 0.45, 0.55, 0.75, 0.9, 1., 1., 1.], + "northamerica": [0., 0.018, 0.239, 0.374, 0.466, 0.552, 0.687, 0.822, 0.908, 1., 1.], + "oceania": [0., 0., 0.239, 0.481, 0.674, 0.865, 1., 1., 1., 1., 1.], + "southamerica": [0., 0., 0.611, 0.84 , 0.924, 0.992, 1., 1., 1., 1., 1.], + } + ) + + +def from_jrc_impf_industrial(region): + """Create a new ImpfRiverFlood object for the industrial sector of the a given world region. + + Parameters + ---------- + region : str + world region for which the impact function was defined. Supported values: + "Africa", "Asia", "Europe", "North America", "Oceania", "South America". + + Returns + ------- + impf : ImpfRiverFlood + New ImpfRiverFlood object with parameters for the specified sector. + + Raises + ------ + ValueError + """ + + return _from_jrc_impf( + region=region, + sector="Industrial", + impf_values_map={ + "africa": [0., 0., 0.063, 0.247, 0.403, 0.494, 0.685, 0.919, 1., 1., 1.], + "asia": [0., 0., 0.283, 0.482, 0.629, 0.717, 0.857, 0.909, 0.955, 1., 1.], + "europe": [0., 0., 0.15, 0.27, 0.4, 0.52, 0.7, 0.85, 1., 1., 1.], + "northamerica": [0., 0.026, 0.323, 0.511, 0.637, 0.74, 0.86, 0.937, 0.98, 1., 1.], + "southamerica": [0., 0., 0.667, 0.889, 0.947, 1., 1., 1., 1., 1., 1.], + } + ) + + +def from_jrc_impf_transport(region): + """Create a new ImpfRiverFlood object for the transport sector of the a given world region. + + Parameters + ---------- + region : str + world region for which the impact function was defined. Supported values: + "Africa", "Asia", "Europe", "North America", "Oceania", "South America". + + Returns + ------- + impf : ImpfRiverFlood + New ImpfRiverFlood object with parameters for the specified sector. + + Raises + ------ + ValueError + """ + return _from_jrc_impf( + region=region, + sector="Transport", + impf_values_map={ + "asia": [0., 0., 0.358, 0.572, 0.733, 0.847, 1., 1., 1., 1., 1.], + "europe": [0., 0., 0.317, 0.542, 0.702, 0.832, 1., 1., 1., 1., 1.], + "southamerica": [0., 0., 0.088, 0.175, 0.596, 0.842, 1., 1., 1., 1., 1.], + } + ) + + +def from_jrc_impf_infrastructure(region): + """Create a new ImpfRiverFlood object for the infrastructure sector of the a given world region. + + Parameters + ---------- + region : str + world region for which the impact function was defined. Supported values: + "Africa", "Asia", "Europe", "North America", "Oceania", "South America". + + Returns + ------- + impf : ImpfRiverFlood + New ImpfRiverFlood object with parameters for the specified sector. + + Raises + ------ + ValueError + """ + return _from_jrc_impf( + region=region, + sector="Infrastructure", + impf_values_map={ + "asia": [0., 0., 0.214, 0.373, 0.604, 0.71, 0.808, 0.887, 0.969, 1., 1.], + "europe": [0., 0., 0.25, 0.42, 0.55, 0.65, 0.8, 0.9, 1., 1., 1.], + } + ) + + +def from_jrc_impf_agriculture(region): + """Create a new ImpfRiverFlood object for the agriculture sector of the a given world region. + + Parameters + ---------- + region : str + world region for which the impact function was defined. Supported values: + "Africa", "Asia", "Europe", "North America", "Oceania", "South America". + + Returns + ------- + impf : ImpfRiverFlood + New ImpfRiverFlood object with parameters for the specified sector. + + Raises + ------ + ValueError + """ + return _from_jrc_impf( + region=region, + sector="Agriculture", + impf_values_map={ + "africa": [0., 0., 0.243, 0.472, 0.741, 0.917, 1., 1., 1., 1., 1.], + "asia": [0., 0., 0.135, 0.37 , 0.524, 0.558, 0.66, 0.834, 0.988, 1., 1.], + "europe": [0., 0., 0.3, 0.55, 0.65, 0.75, 0.85, 0.95, 1., 1., 1.], + "northamerica": [0., 0.019, 0.268, 0.474, 0.551, 0.602, 0.76, 0.874, 0.954, 1., 1.], + } + ) + + +def flood_imp_func_set(sector="residential"): + """Builds impact function set for river flood, using standard files. By default, it reads + functions for the residential sector""" + + impf_africa = ImpfRiverFlood.from_jrc_region_sector("Africa", sector=sector) + impf_asia = ImpfRiverFlood.from_jrc_region_sector("Asia", sector=sector) + impf_europe = ImpfRiverFlood.from_jrc_region_sector("Europe", sector=sector) + impf_na = ImpfRiverFlood.from_jrc_region_sector("NorthAmerica", sector=sector) + impf_oceania = ImpfRiverFlood.from_jrc_region_sector("Oceania", sector=sector) + impf_sa = ImpfRiverFlood.from_jrc_region_sector("SouthAmerica", sector=sector) + + impf_set = ImpactFuncSet([ + impf_africa, + impf_asia, + impf_europe, + impf_na, + impf_oceania, + impf_sa + ]) return impf_set diff --git a/climada_petals/entity/impact_funcs/test/test_fl.py b/climada_petals/entity/impact_funcs/test/test_fl.py index 5ec9930c..d7950128 100644 --- a/climada_petals/entity/impact_funcs/test/test_fl.py +++ b/climada_petals/entity/impact_funcs/test/test_fl.py @@ -21,9 +21,51 @@ import unittest import numpy as np - +from itertools import product from climada_petals.entity.impact_funcs import river_flood as fl +IMPF_REGIONS = {1: 'Africa', 2: 'Asia', 3: 'Europe', 4: 'North America', 5: 'Oceania', 6: 'South America'} +IMPF_SECTORS = {1: 'residential', 2: 'commercial', 3: 'industrial', 4: 'transport', 5: 'infrastructure', + 6: 'agriculture'} + +IMPF_MDD = { + 11: np.array([0., 0., 0.22, 0.378, 0.531, 0.636, 0.817, 0.903, 0.957, 1., 1.]), + 21: np.array([0., 0., 0.327, 0.494, 0.617, 0.721, 0.87, 0.931, 0.984, 1., 1.]), + 31: np.array([0., 0., 0.25, 0.4, 0.5, 0.6, 0.75, 0.85, 0.95, 1., 1.]), + 41: np.array([0., 0.202, 0.443, 0.583, 0.683, 0.784, 0.854, 0.924, 0.959, 1., 1.]), + 51: np.array([0., 0., 0.475, 0.640, 0.715, 0.788, 0.929, 0.967, 0.983, 1., 1.]), + 61: np.array([0., 0., 0.491, 0.711, 0.842, 0.949, 0.984, 1., 1., 1., 1.]), + 12: np.array([]), + 22: np.array([0., 0., 0.377, 0.538, 0.659, 0.763, 0.883, 0.942, 0.981, 1., 1.]), + 32: np.array([0., 0., 0.15, 0.3, 0.45, 0.55, 0.75, 0.9, 1., 1., 1.]), + 42: np.array([0., 0.018, 0.239, 0.374, 0.466, 0.552, 0.687, 0.822, 0.908, 1., 1.]), + 52: np.array([0., 0., 0.239, 0.481, 0.674, 0.865, 1., 1., 1., 1., 1.]), + 62: np.array([0., 0., 0.611, 0.84 , 0.924, 0.992, 1., 1., 1., 1., 1.]), + 13: np.array([0., 0., 0.063, 0.247, 0.403, 0.494, 0.685, 0.919, 1., 1., 1.]), + 23: np.array([0., 0., 0.283, 0.482, 0.629, 0.717, 0.857, 0.909, 0.955, 1., 1.]), + 33: np.array([0., 0., 0.15, 0.27, 0.4, 0.52, 0.7, 0.85, 1., 1., 1.]), + 43: np.array([0., 0.026, 0.323, 0.511, 0.637, 0.74, 0.86, 0.937, 0.98, 1., 1.]), + 53: np.array([]), + 63: np.array([0., 0., 0.667, 0.889, 0.947, 1., 1., 1., 1., 1., 1.]), + 14: np.array([]), + 24: np.array([0., 0., 0.358, 0.572, 0.733, 0.847, 1., 1., 1., 1., 1.]), + 34: np.array([0., 0., 0.317, 0.542, 0.702, 0.832, 1., 1., 1., 1., 1.]), + 44: np.array([]), + 54: np.array([]), + 64: np.array([0., 0., 0.088, 0.175, 0.596, 0.842, 1., 1., 1., 1., 1.]), + 15: np.array([]), + 25: np.array([0., 0., 0.214, 0.373, 0.604, 0.71 , 0.808, 0.887, 0.969, 1., 1.]), + 35: np.array([0., 0., 0.25, 0.42, 0.55, 0.65, 0.8, 0.9, 1., 1., 1.]), + 45: np.array([]), + 55: np.array([]), + 65: np.array([]), + 16: np.array([0., 0., 0.243, 0.472, 0.741, 0.917, 1., 1., 1., 1., 1.]), + 26: np.array([0., 0., 0.135, 0.37 , 0.524, 0.558, 0.66, 0.834, 0.988, 1., 1.]), + 36: np.array([0., 0., 0.3, 0.55, 0.65, 0.75, 0.85, 0.95, 1., 1., 1.]), + 46: np.array([0., 0.019, 0.268, 0.474, 0.551, 0.602, 0.76, 0.874, 0.954, 1., 1.]), + 56: np.array([]), + 66: np.array([]) +} class TestIFRiverFlood(unittest.TestCase): """Impact function test""" @@ -33,118 +75,44 @@ def test_flood_imp_func_set(self): np.array(['RF']))) self.assertEqual(test_set.size(), 6) - def test_region_Africa(self): - - impf_1 = fl.ImpfRiverFlood.from_region("Africa") - - self.assertEqual(impf_1.continent, 'Africa') - self.assertEqual(impf_1.name, 'Flood Africa JRC Residential noPAA') - self.assertEqual(impf_1.haz_type, 'RF') - self.assertEqual(impf_1.id, 1) - self.assertEqual(impf_1.intensity_unit, 'm') - self.assertTrue(np.array_equal(impf_1.intensity, - np.array([0., 0.5, 1., 1.5, - 2., 3., 4., 5., 6., 12.]))) - self.assertTrue(np.allclose(impf_1.mdd, - np.array([0., 0.2199, 0.3782, - 0.5306, 0.6356, 0.8169, - 0.9034, 0.9572, 1., 1.]))) - self.assertTrue(np.allclose(impf_1.paa, - np.array([1, 1, 1, 1, 1, 1, 1, 1, 1, 1]))) - - def test_region_Asia(self): - - impf_2 = fl.ImpfRiverFlood.from_region("Asia") - - self.assertEqual(impf_2.continent, 'Asia') - self.assertEqual(impf_2.name, 'Flood Asia JRC Residential noPAA') - self.assertEqual(impf_2.haz_type, 'RF') - self.assertEqual(impf_2.id, 2) - self.assertEqual(impf_2.intensity_unit, 'm') - self.assertTrue(np.array_equal(impf_2.intensity, - np.array([0., 0.5, 1., 1.5, - 2., 3., 4., 5., 6., 12.]))) - self.assertTrue(np.allclose(impf_2.mdd, - np.array([0.000, 0.3266, 0.4941, 0.6166, 0.7207, - 0.8695, 0.9315, 0.9836, 1.0000, 1.0000]))) - self.assertTrue(np.allclose(impf_2.paa, - np.array([1, 1, 1, 1, 1, 1, 1, 1, 1, 1]))) - - def test_region_Europe(self): - - impf_3 = fl.ImpfRiverFlood.from_region("Europe") - - self.assertEqual(impf_3.continent, 'Europe') - self.assertEqual(impf_3.name, 'Flood Europe JRC Residential noPAA') - self.assertEqual(impf_3.haz_type, 'RF') - self.assertEqual(impf_3.id, 3) - self.assertEqual(impf_3.intensity_unit, 'm') - self.assertTrue(np.array_equal(impf_3.intensity, - np.array([0., 0.5, 1., 1.5, - 2., 3., 4., 5., 6., 12.]))) - self.assertTrue(np.allclose(impf_3.mdd, - np.array([0.00, 0.25, 0.40, 0.50, 0.60, 0.75, 0.85, - 0.95, 1.00, 1.00]))) - self.assertTrue(np.allclose(impf_3.paa, - np.array([1, 1, 1, 1, 1, 1, 1, 1, 1, 1]))) - - def test_region_NorthAmerica(self): - - impf_4 = fl.ImpfRiverFlood.from_region("NorthAmerica") - - self.assertEqual(impf_4.continent, 'NorthAmerica') - self.assertEqual(impf_4.name, - 'Flood North America JRC Residential noPAA') - self.assertEqual(impf_4.haz_type, 'RF') - self.assertEqual(impf_4.id, 4) - self.assertEqual(impf_4.intensity_unit, 'm') - self.assertTrue(np.array_equal(impf_4.intensity, - np.array([0., 0.1, 0.5, 1., 1.5, 2., 3., 4., 5., - 6., 12.]))) - - self.assertTrue(np.allclose(impf_4.mdd, - np.array([0.0000, 0.2018, 0.4433, 0.5828, 0.6825, - 0.7840, 0.8543, 0.9237, 0.9585, 1.0000, - 1.0000]))) - self.assertTrue(np.allclose(impf_4.paa, - np.array([1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1]))) - - def test_region_Oceania(self): - - impf_5 = fl.ImpfRiverFlood.from_region("Oceania") - - self.assertEqual(impf_5.continent, 'Oceania') - self.assertEqual(impf_5.name, 'Flood Oceania JRC Residential noPAA') - self.assertEqual(impf_5.haz_type, 'RF') - self.assertEqual(impf_5.id, 5) - self.assertEqual(impf_5.intensity_unit, 'm') - self.assertTrue(np.array_equal(impf_5.intensity, - np.array([0., 0.5, 1., 1.5, - 2., 3., 4., 5., 6., 12.]))) - self.assertTrue(np.allclose(impf_5.mdd, - np.array([0.00, 0.48, 0.64, 0.71, 0.79, 0.93, 0.97, - 0.98, 1.00, 1.00]))) - self.assertTrue(np.allclose(impf_5.paa, - np.array([1, 1, 1, 1, 1, 1, 1, 1, 1, 1]))) - - def test_region_SouthAmerica(self): - - impf_6 = fl.ImpfRiverFlood.from_region("SouthAmerica") - self.assertEqual(impf_6.continent, 'SouthAmerica') - self.assertEqual(impf_6.name, - 'Flood South America JRC Residential noPAA') - self.assertEqual(impf_6.haz_type, 'RF') - self.assertEqual(impf_6.id, 6) - self.assertEqual(impf_6.intensity_unit, 'm') - self.assertTrue(np.array_equal(impf_6.intensity, - np.array([0., 0.5, 1., 1.5, - 2., 3., 4., 5., 6., 12.]))) - self.assertTrue(np.allclose(impf_6.mdd, - np.array([0.0000, 0.4908, 0.7112, 0.8420, 0.9494, - 0.9836, 1.0000, 1.0000, 1.0000, 1.0000]))) - self.assertTrue(np.allclose(impf_6.paa, - np.array([1, 1, 1, 1, 1, 1, 1, 1, 1, 1]))) - + def test_flood_imp_func_parameters(self): + for reg_id, sec_id in product(range(1,7), range(1,7)): + region, sector = IMPF_REGIONS[reg_id], IMPF_SECTORS[sec_id] + impf_id = int(f"{reg_id}{sec_id}") + impf_mdd = IMPF_MDD[impf_id] + + if impf_mdd.size == 0: + with self.assertRaises(ValueError): + fl.ImpfRiverFlood.from_jrc_region_sector(region, sector) + continue + + impf = fl.ImpfRiverFlood.from_jrc_region_sector(region, sector) + self.assertEqual(impf.continent, region) + self.assertEqual( + impf.name, f'Flood {region} JRC {sector.capitalize()} noPAA' + ) + self.assertEqual(impf.haz_type, 'RF') + self.assertEqual(impf.intensity_unit, 'm') + + self.assertEqual(impf.id, impf_id) + np.testing.assert_array_almost_equal( + impf.intensity, + np.array([0., 0.05, 0.5, 1., 1.5, 2., 3., 4., 5., 6., 12.]) + ) + np.testing.assert_array_almost_equal( + impf.mdd, + impf_mdd + ) + np.testing.assert_array_almost_equal( + impf.paa, + np.ones_like(impf.intensity) + ) + + def test_flood_imp_func_invalid_inputs(self): + with self.assertRaises(ValueError): + fl.ImpfRiverFlood.from_jrc_region_sector('unknown country', 'residential') + with self.assertRaises(ValueError): + fl.ImpfRiverFlood.from_jrc_region_sector('Africa', 'unknown sector') # Execute Tests if __name__ == "__main__": From e12e2b85afbc79b5e93a9682bbdbe210c63caee4 Mon Sep 17 00:00:00 2001 From: emanuel-schmid Date: Fri, 1 Nov 2024 16:46:00 +0100 Subject: [PATCH 10/10] undo previous commit --- .../entity/impact_funcs/river_flood.py | 423 +++++------------- .../entity/impact_funcs/test/test_fl.py | 194 ++++---- 2 files changed, 229 insertions(+), 388 deletions(-) diff --git a/climada_petals/entity/impact_funcs/river_flood.py b/climada_petals/entity/impact_funcs/river_flood.py index e5082cb7..f38963ec 100644 --- a/climada_petals/entity/impact_funcs/river_flood.py +++ b/climada_petals/entity/impact_funcs/river_flood.py @@ -29,27 +29,21 @@ from climada.util.constants import RIVER_FLOOD_REGIONS_CSV from climada.entity import ImpactFunc, ImpactFuncSet +LOGGER = logging.getLogger(__name__) -SECTOR_CO_ID = { - "Residential": 1, - "Commercial": 2, - "Industrial": 3, - "Transport": 4, - "Infrastructure": 5, - "Agriculture": 6, -} -REGION_CO_ID = { - "africa": 10, - "asia": 20, - "europe": 30, - "northamerica": 40, - "oceania": 50, - "southamerica": 60, -} -VALID_REGIONS = "Africa, Asia, Europe, North America, Oceania, South America" +DEF_VAR_EXCEL = {'sheet_name': 'damagefunctions', + 'col_name': {'func_id': 'DamageFunID', + 'inten': 'Intensity', + 'mdd': 'MDD', + 'paa': 'PAA', + 'mdr': 'MDR', + 'name': 'name', + 'peril': 'peril_ID', + 'unit': 'Intensity_unit' + } + } -LOGGER = logging.getLogger(__name__) class ImpfRiverFlood(ImpactFunc): """Impact functions for tropical cyclones.""" @@ -61,329 +55,144 @@ def __init__(self): self.continent = '' @classmethod - def from_jrc_region_sector(cls, region, sector="residential"): - """Create a new ImpfRiverFlood object based on the specified world region and sector. - Impact functions come from the following JRC publication: - - Huizinga, J., De Moel, H. and Szewczyk, W., Global flood depth-damage functions: Methodology - and the database with guidelines, EUR 28552 EN, Publications Office of the European Union, - Luxembourg, 2017, ISBN 978-92-79-67781-6, doi:10.2760/16510, JRC105688. - - Notes - ----- - The impact functions assess percentage losses at 0, 0.5, 1, 1.5, 2, 3, 4, 5, 6 meters of - water. For North America, percentage losses higher than 0 are already registerd at 0 meters - of water, because it accounts for the presence of basements (see main publication). Since - this could be problematic when computing impacts, as one would have losses also when there - is no flood, a 0.05 meters of water point is added to all functions (not only North America, - for consistency), and this corresponds to the 0 meters point in the JRC functions. + def from_region(cls, region): + """Create a new ImpfRiverFlood object with parameters for the specified world region. Parameters ---------- region : str - world region for which the impact function was defined. Supported values: - "Africa", "Asia", "Europe", "North America", "Oceania", "South America". - - sector: str - sector for which the impact function was defined. Supported values: "residential", - "commercial", "industrial", "transport", "infrastructure", "agriculture". + Use damage function parameters for this world region. Supported values: "Africa", + "Asia", "Europe", "NorthAmerica", "Oceania", "SouthAmerica". Returns ------- impf : ImpfRiverFlood - New ImpfRiverFlood object with parameters for the specified world region and sector. + New ImpfRiverFlood object with parameters for the specified world region. Raises ------ ValueError """ - - if sector == 'residential': - impf_values, impf_id = from_jrc_impf_residential(region) - - elif sector == 'industrial': - impf_values, impf_id = from_jrc_impf_industrial(region) - - elif sector == 'commercial': - impf_values, impf_id = from_jrc_impf_commercial(region) - - elif sector == 'transport': - impf_values, impf_id = from_jrc_impf_transport(region) - - elif sector == 'infrastructure': - impf_values, impf_id = from_jrc_impf_infrastructure(region) - - elif sector == 'agriculture': - impf_values, impf_id = from_jrc_impf_agriculture(region) - - else: - raise ValueError(f"Unrecognized sector: {sector}") - impf = cls() - impf.name = f"Flood {region} JRC {sector.capitalize()} noPAA" - impf.continent = f"{region}" - impf.id = impf_id - impf.mdd = impf_values - impf.intensity = np.array([0., 0.05, 0.5, 1., 1.5, 2., 3., 4., 5., 6., 12.]) + if region.lower() == "africa": + impf.id = 1 + impf.name = "Flood Africa JRC Residential noPAA" + impf.continent = 'Africa' + impf.intensity = np.array([0., 0.5, 1., 1.5, 2., 3., 4., 5., 6., 12.]) + impf.mdd = np.array([0.0000, 0.2199, 0.3782, 0.5306, 0.6356, 0.8169, + 0.9034, 0.9572, 1.0000, 1.0000]) + impf.mdr = np.array([0.0000, 0.2199, 0.3782, 0.5306, 0.6356, 0.8169, + 0.9034, 0.9572, 1.0000, 1.0000]) + elif region.lower() == "asia": + impf.id = 2 + impf.name = "Flood Asia JRC Residential noPAA" + impf.continent = 'Asia' + impf.intensity = np.array([0., 0.5, 1., 1.5, 2., 3., 4., 5., 6., 12.]) + impf.mdd = np.array([0.000, 0.3266, 0.4941, 0.6166, 0.7207, 0.8695, + 0.9315, 0.9836, 1.0000, 1.0000]) + impf.mdr = np.array([0.000, 0.3266, 0.4941, 0.6166, 0.7207, 0.8695, + 0.9315, 0.9836, 1.0000, 1.0000]) + elif region.lower() == "europe": + impf.id = 3 + impf.name = "Flood Europe JRC Residential noPAA" + impf.continent = 'Europe' + impf.intensity = np.array([0., 0.5, 1., 1.5, 2., 3., 4., 5., 6., 12.]) + impf.mdd = np.array([0.00, 0.25, 0.40, 0.50, 0.60, 0.75, 0.85, 0.95, + 1.00, 1.00]) + impf.mdr = np.array([0.000, 0.250, 0.400, 0.500, 0.600, 0.750, 0.850, + 0.950, 1.000, 1.000]) + elif region.lower().replace(" ", "") == "northamerica": + impf.id = 4 + impf.name = "Flood North America JRC Residential noPAA" + impf.continent = 'NorthAmerica' + impf.intensity = np.array([0., 0.1, 0.5, 1., 1.5, 2., 3., 4., 5., + 6., 12.]) + impf.mdd = np.array([0.0000, 0.2018, 0.4433, 0.5828, 0.6825, 0.7840, + 0.8543, 0.9237, 0.9585, 1.0000, 1.0000]) + impf.mdr = np.array([0.0000, 0.2018, 0.4433, 0.5828, 0.6825, 0.7840, + 0.8543, 0.9237, 0.9585, 1.0000, 1.0000]) + elif region.lower() == "oceania": + impf.id = 5 + impf.name = "Flood Oceania JRC Residential noPAA" + impf.continent = 'Oceania' + impf.intensity = np.array([0., 0.5, 1., 1.5, 2., 3., 4., 5., 6., 12.]) + impf.mdd = np.array([0.00, 0.48, 0.64, 0.71, 0.79, 0.93, 0.97, 0.98, + 1.00, 1.00]) + impf.mdr = np.array([0.000, 0.480, 0.640, 0.710, 0.790, 0.930, 0.970, + 0.980, 1.000, 1.000]) + elif region.lower().replace(" ", "") == "southamerica": + impf.id = 6 + impf.name = "Flood South America JRC Residential noPAA" + impf.continent = 'SouthAmerica' + impf.intensity = np.array([0., 0.5, 1., 1.5, 2., 3., 4., 5., 6., 12.]) + impf.mdd = np.array([0.0000, 0.4908, 0.7112, 0.8420, 0.9494, + 0.9836, 1.0000, 1.0000, 1.0000, 1.0000]) + impf.mdr = np.array([0.0000, 0.4908, 0.7112, 0.8420, 0.9494, 0.9836, + 1.0000, 1.0000, 1.0000, 1.0000]) + else: + raise ValueError(f"Unrecognized world region: {region}") impf.paa = np.ones(len(impf.intensity)) - return impf def set_RF_Impf_Africa(self, *args, **kwargs): - """This function is deprecated, use ImpfRiverFlood.from_region_sector instead.""" + """This function is deprecated, use ImpfRiverFlood.from_region instead.""" LOGGER.warning("The use of ImpfRiverFlood.set_RF_Impf_Africa is deprecated." - "Use ImpfRiverFlood.from_region_sector instead.") - self.__dict__ = ImpfRiverFlood.from_jrc_region_sector("Africa", *args, **kwargs).__dict__ + "Use ImpfRiverFlood.from_region instead.") + self.__dict__ = ImpfRiverFlood.from_region("Africa", *args, **kwargs).__dict__ def set_RF_Impf_Asia(self, *args, **kwargs): - """This function is deprecated, use ImpfRiverFlood.from_region_sector instead.""" + """This function is deprecated, use ImpfRiverFlood.from_region instead.""" LOGGER.warning("The use of ImpfRiverFlood.set_RF_Impf_Asia is deprecated." - "Use ImpfRiverFlood.from_region_sector instead.") - self.__dict__ = ImpfRiverFlood.from_jrc_region_sector("Asia", *args, **kwargs).__dict__ + "Use ImpfRiverFlood.from_region instead.") + self.__dict__ = ImpfRiverFlood.from_region("Asia", *args, **kwargs).__dict__ def set_RF_Impf_Europe(self, *args, **kwargs): - """This function is deprecated, use ImpfRiverFlood.from_region_sector instead.""" + """This function is deprecated, use ImpfRiverFlood.from_region instead.""" LOGGER.warning("The use of ImpfRiverFlood.set_RF_Impf_Europe is deprecated." - "Use ImpfRiverFlood.from_region_sector instead.") - self.__dict__ = ImpfRiverFlood.from_jrc_region_sector("Europe", *args, **kwargs).__dict__ + "Use ImpfRiverFlood.from_region instead.") + self.__dict__ = ImpfRiverFlood.from_region("Europe", *args, **kwargs).__dict__ def set_RF_Impf_NorthAmerica(self, *args, **kwargs): - """This function is deprecated, use ImpfRiverFlood.from_region_sector instead.""" + """This function is deprecated, use ImpfRiverFlood.from_region instead.""" LOGGER.warning("The use of ImpfRiverFlood.set_RF_Impf_NorthAmerica is deprecated." - "Use ImpfRiverFlood.from_region_sector instead.") - self.__dict__ = ImpfRiverFlood.from_jrc_region_sector("NorthAmerica", *args, **kwargs).__dict__ + "Use ImpfRiverFlood.from_region instead.") + self.__dict__ = ImpfRiverFlood.from_region("NorthAmerica", *args, **kwargs).__dict__ def set_RF_Impf_Oceania(self, *args, **kwargs): - """This function is deprecated, use ImpfRiverFlood.from_region_sector instead.""" + """This function is deprecated, use ImpfRiverFlood.from_region instead.""" LOGGER.warning("The use of ImpfRiverFlood.set_RF_Impf_Oceania is deprecated." - "Use ImpfRiverFlood.from_region_sector instead.") - self.__dict__ = ImpfRiverFlood.from_jrc_region_sector("Oceania", *args, **kwargs).__dict__ + "Use ImpfRiverFlood.from_region instead.") + self.__dict__ = ImpfRiverFlood.from_region("Oceania", *args, **kwargs).__dict__ def set_RF_Impf_SouthAmerica(self, *args, **kwargs): - """This function is deprecated, use ImpfRiverFlood.from_region_sector instead.""" + """This function is deprecated, use ImpfRiverFlood.from_region instead.""" LOGGER.warning("The use of ImpfRiverFlood.set_RF_Impf_SouthAmerica is deprecated." - "Use ImpfRiverFlood.from_region_sector instead.") - self.__dict__ = ImpfRiverFlood.from_jrc_region_sector("SouthAmerica", *args, **kwargs).__dict__ - - - -def _from_jrc_impf(region, sector, impf_values_map): - """Boiler plate function for the public from_jrc_impf_*** functions""" - regkey = region.replace(' ', '').lower() - if regkey not in REGION_CO_ID: - raise ValueError(f"Unrecognized world region: {region}, must be one of {VALID_REGIONS}") - impf_id = REGION_CO_ID[regkey] + SECTOR_CO_ID[sector] - - impf_values = impf_values_map.get(regkey) - if impf_values is None: - raise ValueError(f"No impact function implemented for the {sector} sector in {region}") - return np.array(impf_values), impf_id - - - -def from_jrc_impf_residential(region): - """Create a new ImpfRiverFlood object for the residential sector of the a given - world region. - - Parameters - ---------- - region : str - world region for which the impact function was defined. Supported values: - "Africa", "Asia", "Europe", "North America", "Oceania", "South America". - - Returns - ------- - impf : ImpfRiverFlood - New ImpfRiverFlood object with parameters for the specified sector. - - Raises - ------ - ValueError - """ - return _from_jrc_impf( - region=region, - sector="Residential", - impf_values_map={ - "africa": [0., 0., 0.22, 0.378, 0.531, 0.636, 0.817, 0.903, 0.957, 1., 1.], - "asia": [0., 0., 0.327, 0.494, 0.617, 0.721, 0.87, 0.931, 0.984, 1., 1.], - "europe": [0., 0., 0.25, 0.4, 0.5, 0.6, 0.75, 0.85, 0.95, 1., 1.], - "northamerica": [0., 0.202, 0.443, 0.583, 0.683, 0.784, 0.854, 0.924, 0.959, 1., 1.], - "oceania": [0., 0., 0.475, 0.640, 0.715, 0.788, 0.929, 0.967, 0.983, 1., 1.], - "southamerica": [0., 0., 0.491, 0.711, 0.842, 0.949, 0.984, 1., 1., 1., 1.], - } - ) - - -def from_jrc_impf_commercial(region): - """Create a new ImpfRiverFlood object for the commercial sector of the a given world region. - - Parameters - ---------- - region : str - world region for which the impact function was defined. Supported values: - "Africa", "Asia", "Europe", "North America", "Oceania", "South America". - - Returns - ------- - impf : ImpfRiverFlood - New ImpfRiverFlood object with parameters for the specified sector. - - Raises - ------ - ValueError - """ - - return _from_jrc_impf( - region=region, - sector="Commercial", - impf_values_map={ - "asia": [0., 0., 0.377, 0.538, 0.659, 0.763, 0.883, 0.942, 0.981, 1., 1.], - "europe": [0., 0., 0.15, 0.3, 0.45, 0.55, 0.75, 0.9, 1., 1., 1.], - "northamerica": [0., 0.018, 0.239, 0.374, 0.466, 0.552, 0.687, 0.822, 0.908, 1., 1.], - "oceania": [0., 0., 0.239, 0.481, 0.674, 0.865, 1., 1., 1., 1., 1.], - "southamerica": [0., 0., 0.611, 0.84 , 0.924, 0.992, 1., 1., 1., 1., 1.], - } - ) - - -def from_jrc_impf_industrial(region): - """Create a new ImpfRiverFlood object for the industrial sector of the a given world region. - - Parameters - ---------- - region : str - world region for which the impact function was defined. Supported values: - "Africa", "Asia", "Europe", "North America", "Oceania", "South America". - - Returns - ------- - impf : ImpfRiverFlood - New ImpfRiverFlood object with parameters for the specified sector. - - Raises - ------ - ValueError - """ - - return _from_jrc_impf( - region=region, - sector="Industrial", - impf_values_map={ - "africa": [0., 0., 0.063, 0.247, 0.403, 0.494, 0.685, 0.919, 1., 1., 1.], - "asia": [0., 0., 0.283, 0.482, 0.629, 0.717, 0.857, 0.909, 0.955, 1., 1.], - "europe": [0., 0., 0.15, 0.27, 0.4, 0.52, 0.7, 0.85, 1., 1., 1.], - "northamerica": [0., 0.026, 0.323, 0.511, 0.637, 0.74, 0.86, 0.937, 0.98, 1., 1.], - "southamerica": [0., 0., 0.667, 0.889, 0.947, 1., 1., 1., 1., 1., 1.], - } - ) - - -def from_jrc_impf_transport(region): - """Create a new ImpfRiverFlood object for the transport sector of the a given world region. - - Parameters - ---------- - region : str - world region for which the impact function was defined. Supported values: - "Africa", "Asia", "Europe", "North America", "Oceania", "South America". - - Returns - ------- - impf : ImpfRiverFlood - New ImpfRiverFlood object with parameters for the specified sector. - - Raises - ------ - ValueError - """ - return _from_jrc_impf( - region=region, - sector="Transport", - impf_values_map={ - "asia": [0., 0., 0.358, 0.572, 0.733, 0.847, 1., 1., 1., 1., 1.], - "europe": [0., 0., 0.317, 0.542, 0.702, 0.832, 1., 1., 1., 1., 1.], - "southamerica": [0., 0., 0.088, 0.175, 0.596, 0.842, 1., 1., 1., 1., 1.], - } - ) - - -def from_jrc_impf_infrastructure(region): - """Create a new ImpfRiverFlood object for the infrastructure sector of the a given world region. - - Parameters - ---------- - region : str - world region for which the impact function was defined. Supported values: - "Africa", "Asia", "Europe", "North America", "Oceania", "South America". - - Returns - ------- - impf : ImpfRiverFlood - New ImpfRiverFlood object with parameters for the specified sector. - - Raises - ------ - ValueError - """ - return _from_jrc_impf( - region=region, - sector="Infrastructure", - impf_values_map={ - "asia": [0., 0., 0.214, 0.373, 0.604, 0.71, 0.808, 0.887, 0.969, 1., 1.], - "europe": [0., 0., 0.25, 0.42, 0.55, 0.65, 0.8, 0.9, 1., 1., 1.], - } - ) - - -def from_jrc_impf_agriculture(region): - """Create a new ImpfRiverFlood object for the agriculture sector of the a given world region. - - Parameters - ---------- - region : str - world region for which the impact function was defined. Supported values: - "Africa", "Asia", "Europe", "North America", "Oceania", "South America". - - Returns - ------- - impf : ImpfRiverFlood - New ImpfRiverFlood object with parameters for the specified sector. - - Raises - ------ - ValueError - """ - return _from_jrc_impf( - region=region, - sector="Agriculture", - impf_values_map={ - "africa": [0., 0., 0.243, 0.472, 0.741, 0.917, 1., 1., 1., 1., 1.], - "asia": [0., 0., 0.135, 0.37 , 0.524, 0.558, 0.66, 0.834, 0.988, 1., 1.], - "europe": [0., 0., 0.3, 0.55, 0.65, 0.75, 0.85, 0.95, 1., 1., 1.], - "northamerica": [0., 0.019, 0.268, 0.474, 0.551, 0.602, 0.76, 0.874, 0.954, 1., 1.], - } - ) - - -def flood_imp_func_set(sector="residential"): - """Builds impact function set for river flood, using standard files. By default, it reads - functions for the residential sector""" - - impf_africa = ImpfRiverFlood.from_jrc_region_sector("Africa", sector=sector) - impf_asia = ImpfRiverFlood.from_jrc_region_sector("Asia", sector=sector) - impf_europe = ImpfRiverFlood.from_jrc_region_sector("Europe", sector=sector) - impf_na = ImpfRiverFlood.from_jrc_region_sector("NorthAmerica", sector=sector) - impf_oceania = ImpfRiverFlood.from_jrc_region_sector("Oceania", sector=sector) - impf_sa = ImpfRiverFlood.from_jrc_region_sector("SouthAmerica", sector=sector) - - impf_set = ImpactFuncSet([ - impf_africa, - impf_asia, - impf_europe, - impf_na, - impf_oceania, - impf_sa - ]) + "Use ImpfRiverFlood.from_region instead.") + self.__dict__ = ImpfRiverFlood.from_region("SouthAmerica", *args, **kwargs).__dict__ + + +def flood_imp_func_set(): + """Builds impact function set for river flood, using standard files""" + + impf_set = ImpactFuncSet() + + impf_africa = ImpfRiverFlood.from_region("Africa") + impf_set.append(impf_africa) + + impf_asia = ImpfRiverFlood.from_region("Asia") + impf_set.append(impf_asia) + + impf_europe = ImpfRiverFlood.from_region("Europe") + impf_set.append(impf_europe) + + impf_na = ImpfRiverFlood.from_region("NorthAmerica") + impf_set.append(impf_na) + + impf_oceania = ImpfRiverFlood.from_region("Oceania") + impf_set.append(impf_oceania) + + impf_sa = ImpfRiverFlood.from_region("SouthAmerica") + impf_set.append(impf_sa) return impf_set diff --git a/climada_petals/entity/impact_funcs/test/test_fl.py b/climada_petals/entity/impact_funcs/test/test_fl.py index d7950128..5ec9930c 100644 --- a/climada_petals/entity/impact_funcs/test/test_fl.py +++ b/climada_petals/entity/impact_funcs/test/test_fl.py @@ -21,51 +21,9 @@ import unittest import numpy as np -from itertools import product + from climada_petals.entity.impact_funcs import river_flood as fl -IMPF_REGIONS = {1: 'Africa', 2: 'Asia', 3: 'Europe', 4: 'North America', 5: 'Oceania', 6: 'South America'} -IMPF_SECTORS = {1: 'residential', 2: 'commercial', 3: 'industrial', 4: 'transport', 5: 'infrastructure', - 6: 'agriculture'} - -IMPF_MDD = { - 11: np.array([0., 0., 0.22, 0.378, 0.531, 0.636, 0.817, 0.903, 0.957, 1., 1.]), - 21: np.array([0., 0., 0.327, 0.494, 0.617, 0.721, 0.87, 0.931, 0.984, 1., 1.]), - 31: np.array([0., 0., 0.25, 0.4, 0.5, 0.6, 0.75, 0.85, 0.95, 1., 1.]), - 41: np.array([0., 0.202, 0.443, 0.583, 0.683, 0.784, 0.854, 0.924, 0.959, 1., 1.]), - 51: np.array([0., 0., 0.475, 0.640, 0.715, 0.788, 0.929, 0.967, 0.983, 1., 1.]), - 61: np.array([0., 0., 0.491, 0.711, 0.842, 0.949, 0.984, 1., 1., 1., 1.]), - 12: np.array([]), - 22: np.array([0., 0., 0.377, 0.538, 0.659, 0.763, 0.883, 0.942, 0.981, 1., 1.]), - 32: np.array([0., 0., 0.15, 0.3, 0.45, 0.55, 0.75, 0.9, 1., 1., 1.]), - 42: np.array([0., 0.018, 0.239, 0.374, 0.466, 0.552, 0.687, 0.822, 0.908, 1., 1.]), - 52: np.array([0., 0., 0.239, 0.481, 0.674, 0.865, 1., 1., 1., 1., 1.]), - 62: np.array([0., 0., 0.611, 0.84 , 0.924, 0.992, 1., 1., 1., 1., 1.]), - 13: np.array([0., 0., 0.063, 0.247, 0.403, 0.494, 0.685, 0.919, 1., 1., 1.]), - 23: np.array([0., 0., 0.283, 0.482, 0.629, 0.717, 0.857, 0.909, 0.955, 1., 1.]), - 33: np.array([0., 0., 0.15, 0.27, 0.4, 0.52, 0.7, 0.85, 1., 1., 1.]), - 43: np.array([0., 0.026, 0.323, 0.511, 0.637, 0.74, 0.86, 0.937, 0.98, 1., 1.]), - 53: np.array([]), - 63: np.array([0., 0., 0.667, 0.889, 0.947, 1., 1., 1., 1., 1., 1.]), - 14: np.array([]), - 24: np.array([0., 0., 0.358, 0.572, 0.733, 0.847, 1., 1., 1., 1., 1.]), - 34: np.array([0., 0., 0.317, 0.542, 0.702, 0.832, 1., 1., 1., 1., 1.]), - 44: np.array([]), - 54: np.array([]), - 64: np.array([0., 0., 0.088, 0.175, 0.596, 0.842, 1., 1., 1., 1., 1.]), - 15: np.array([]), - 25: np.array([0., 0., 0.214, 0.373, 0.604, 0.71 , 0.808, 0.887, 0.969, 1., 1.]), - 35: np.array([0., 0., 0.25, 0.42, 0.55, 0.65, 0.8, 0.9, 1., 1., 1.]), - 45: np.array([]), - 55: np.array([]), - 65: np.array([]), - 16: np.array([0., 0., 0.243, 0.472, 0.741, 0.917, 1., 1., 1., 1., 1.]), - 26: np.array([0., 0., 0.135, 0.37 , 0.524, 0.558, 0.66, 0.834, 0.988, 1., 1.]), - 36: np.array([0., 0., 0.3, 0.55, 0.65, 0.75, 0.85, 0.95, 1., 1., 1.]), - 46: np.array([0., 0.019, 0.268, 0.474, 0.551, 0.602, 0.76, 0.874, 0.954, 1., 1.]), - 56: np.array([]), - 66: np.array([]) -} class TestIFRiverFlood(unittest.TestCase): """Impact function test""" @@ -75,44 +33,118 @@ def test_flood_imp_func_set(self): np.array(['RF']))) self.assertEqual(test_set.size(), 6) - def test_flood_imp_func_parameters(self): - for reg_id, sec_id in product(range(1,7), range(1,7)): - region, sector = IMPF_REGIONS[reg_id], IMPF_SECTORS[sec_id] - impf_id = int(f"{reg_id}{sec_id}") - impf_mdd = IMPF_MDD[impf_id] - - if impf_mdd.size == 0: - with self.assertRaises(ValueError): - fl.ImpfRiverFlood.from_jrc_region_sector(region, sector) - continue - - impf = fl.ImpfRiverFlood.from_jrc_region_sector(region, sector) - self.assertEqual(impf.continent, region) - self.assertEqual( - impf.name, f'Flood {region} JRC {sector.capitalize()} noPAA' - ) - self.assertEqual(impf.haz_type, 'RF') - self.assertEqual(impf.intensity_unit, 'm') - - self.assertEqual(impf.id, impf_id) - np.testing.assert_array_almost_equal( - impf.intensity, - np.array([0., 0.05, 0.5, 1., 1.5, 2., 3., 4., 5., 6., 12.]) - ) - np.testing.assert_array_almost_equal( - impf.mdd, - impf_mdd - ) - np.testing.assert_array_almost_equal( - impf.paa, - np.ones_like(impf.intensity) - ) - - def test_flood_imp_func_invalid_inputs(self): - with self.assertRaises(ValueError): - fl.ImpfRiverFlood.from_jrc_region_sector('unknown country', 'residential') - with self.assertRaises(ValueError): - fl.ImpfRiverFlood.from_jrc_region_sector('Africa', 'unknown sector') + def test_region_Africa(self): + + impf_1 = fl.ImpfRiverFlood.from_region("Africa") + + self.assertEqual(impf_1.continent, 'Africa') + self.assertEqual(impf_1.name, 'Flood Africa JRC Residential noPAA') + self.assertEqual(impf_1.haz_type, 'RF') + self.assertEqual(impf_1.id, 1) + self.assertEqual(impf_1.intensity_unit, 'm') + self.assertTrue(np.array_equal(impf_1.intensity, + np.array([0., 0.5, 1., 1.5, + 2., 3., 4., 5., 6., 12.]))) + self.assertTrue(np.allclose(impf_1.mdd, + np.array([0., 0.2199, 0.3782, + 0.5306, 0.6356, 0.8169, + 0.9034, 0.9572, 1., 1.]))) + self.assertTrue(np.allclose(impf_1.paa, + np.array([1, 1, 1, 1, 1, 1, 1, 1, 1, 1]))) + + def test_region_Asia(self): + + impf_2 = fl.ImpfRiverFlood.from_region("Asia") + + self.assertEqual(impf_2.continent, 'Asia') + self.assertEqual(impf_2.name, 'Flood Asia JRC Residential noPAA') + self.assertEqual(impf_2.haz_type, 'RF') + self.assertEqual(impf_2.id, 2) + self.assertEqual(impf_2.intensity_unit, 'm') + self.assertTrue(np.array_equal(impf_2.intensity, + np.array([0., 0.5, 1., 1.5, + 2., 3., 4., 5., 6., 12.]))) + self.assertTrue(np.allclose(impf_2.mdd, + np.array([0.000, 0.3266, 0.4941, 0.6166, 0.7207, + 0.8695, 0.9315, 0.9836, 1.0000, 1.0000]))) + self.assertTrue(np.allclose(impf_2.paa, + np.array([1, 1, 1, 1, 1, 1, 1, 1, 1, 1]))) + + def test_region_Europe(self): + + impf_3 = fl.ImpfRiverFlood.from_region("Europe") + + self.assertEqual(impf_3.continent, 'Europe') + self.assertEqual(impf_3.name, 'Flood Europe JRC Residential noPAA') + self.assertEqual(impf_3.haz_type, 'RF') + self.assertEqual(impf_3.id, 3) + self.assertEqual(impf_3.intensity_unit, 'm') + self.assertTrue(np.array_equal(impf_3.intensity, + np.array([0., 0.5, 1., 1.5, + 2., 3., 4., 5., 6., 12.]))) + self.assertTrue(np.allclose(impf_3.mdd, + np.array([0.00, 0.25, 0.40, 0.50, 0.60, 0.75, 0.85, + 0.95, 1.00, 1.00]))) + self.assertTrue(np.allclose(impf_3.paa, + np.array([1, 1, 1, 1, 1, 1, 1, 1, 1, 1]))) + + def test_region_NorthAmerica(self): + + impf_4 = fl.ImpfRiverFlood.from_region("NorthAmerica") + + self.assertEqual(impf_4.continent, 'NorthAmerica') + self.assertEqual(impf_4.name, + 'Flood North America JRC Residential noPAA') + self.assertEqual(impf_4.haz_type, 'RF') + self.assertEqual(impf_4.id, 4) + self.assertEqual(impf_4.intensity_unit, 'm') + self.assertTrue(np.array_equal(impf_4.intensity, + np.array([0., 0.1, 0.5, 1., 1.5, 2., 3., 4., 5., + 6., 12.]))) + + self.assertTrue(np.allclose(impf_4.mdd, + np.array([0.0000, 0.2018, 0.4433, 0.5828, 0.6825, + 0.7840, 0.8543, 0.9237, 0.9585, 1.0000, + 1.0000]))) + self.assertTrue(np.allclose(impf_4.paa, + np.array([1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1]))) + + def test_region_Oceania(self): + + impf_5 = fl.ImpfRiverFlood.from_region("Oceania") + + self.assertEqual(impf_5.continent, 'Oceania') + self.assertEqual(impf_5.name, 'Flood Oceania JRC Residential noPAA') + self.assertEqual(impf_5.haz_type, 'RF') + self.assertEqual(impf_5.id, 5) + self.assertEqual(impf_5.intensity_unit, 'm') + self.assertTrue(np.array_equal(impf_5.intensity, + np.array([0., 0.5, 1., 1.5, + 2., 3., 4., 5., 6., 12.]))) + self.assertTrue(np.allclose(impf_5.mdd, + np.array([0.00, 0.48, 0.64, 0.71, 0.79, 0.93, 0.97, + 0.98, 1.00, 1.00]))) + self.assertTrue(np.allclose(impf_5.paa, + np.array([1, 1, 1, 1, 1, 1, 1, 1, 1, 1]))) + + def test_region_SouthAmerica(self): + + impf_6 = fl.ImpfRiverFlood.from_region("SouthAmerica") + self.assertEqual(impf_6.continent, 'SouthAmerica') + self.assertEqual(impf_6.name, + 'Flood South America JRC Residential noPAA') + self.assertEqual(impf_6.haz_type, 'RF') + self.assertEqual(impf_6.id, 6) + self.assertEqual(impf_6.intensity_unit, 'm') + self.assertTrue(np.array_equal(impf_6.intensity, + np.array([0., 0.5, 1., 1.5, + 2., 3., 4., 5., 6., 12.]))) + self.assertTrue(np.allclose(impf_6.mdd, + np.array([0.0000, 0.4908, 0.7112, 0.8420, 0.9494, + 0.9836, 1.0000, 1.0000, 1.0000, 1.0000]))) + self.assertTrue(np.allclose(impf_6.paa, + np.array([1, 1, 1, 1, 1, 1, 1, 1, 1, 1]))) + # Execute Tests if __name__ == "__main__":