From d422918b3d9ce389bf8b53dcfbfb5210d8000aa2 Mon Sep 17 00:00:00 2001 From: Lukas Brunner Date: Mon, 29 Mar 2021 14:12:56 +0200 Subject: [PATCH 1/5] Add fix for iris longitude bug --- .../weighting/weighted_temperature_map.py | 44 ++++++++++++++++--- 1 file changed, 37 insertions(+), 7 deletions(-) diff --git a/esmvaltool/diag_scripts/weighting/weighted_temperature_map.py b/esmvaltool/diag_scripts/weighting/weighted_temperature_map.py index 7a0660871d..6a932d0cd6 100644 --- a/esmvaltool/diag_scripts/weighting/weighted_temperature_map.py +++ b/esmvaltool/diag_scripts/weighting/weighted_temperature_map.py @@ -11,15 +11,12 @@ import matplotlib.pyplot as plt import numpy as np from cartopy.mpl.ticker import LatitudeFormatter, LongitudeFormatter -from climwip.io_functions import ( - log_provenance, - read_model_data, -) +from climwip.io_functions import log_provenance, read_model_data from esmvaltool.diag_scripts.shared import ( - run_diagnostic, - get_plot_filename, get_diagnostic_filename, + get_plot_filename, + run_diagnostic, ) from esmvaltool.diag_scripts.weighting.plot_utilities import ( calculate_percentiles, @@ -30,6 +27,37 @@ logger = logging.getLogger(os.path.basename(__file__)) +def set_antimeridian(dataarray: 'xr.DataArray', to: str) -> 'xr.DataArray': + """Flip the antimeridian (i.e. longitude discontinuity) between Europe + (i.e., [0, 360)) and the Pacific (i.e., [-180, 180)). + + Parameters + ---------- + - dataarray : xarray.DataArray + - to : string, {'pacific', 'europe'} + * 'europe': Longitude will be in [0, 360) + * 'pacific': Longitude will be in [-180, 180) + + Returns + ------- + dataarray : xarray.DataArray + """ + lon = dataarray['lon'] + + if to.lower() == 'europe': + dataarray = dataarray.assign_coords(lon=lon % 360) + elif to.lower() == 'pacific': + dataarray = dataarray.assign_coords(lon=((lon + 180) % 360) - 180) + else: + errmsg = "to has to be one of {'europe', 'pacific'} not {}".format(to) + raise ValueError(errmsg) + + idx = np.argmin(dataarray['lon'].values) + dataarray = dataarray.roll(lon=-idx, roll_coords=True) + dataarray['lon'].attrs = lon.attrs + return dataarray + + def mapplot(dataarray, cfg, title_pattern, filename_part, ancestors, **colormesh_args): """Visualize weighted temperature.""" @@ -44,6 +72,8 @@ def mapplot(dataarray, cfg, title_pattern, filename_part, ancestors, proj = ccrs.PlateCarree(central_longitude=0) figure, axes = plt.subplots(subplot_kw={'projection': proj}) + dataarray = set_antimeridian(dataarray, cfg.get('antimeridian', 'europe')) + dataarray.plot.pcolormesh( ax=axes, transform=ccrs.PlateCarree(), @@ -104,7 +134,7 @@ def visualize_and_save_difference(temperature_difference, cfg: dict, ancestors: list): """Wrap mapplot: temperature difference between weighted and unweighted.""" title_pattern = '\n'.join([ - 'Difference: weighted minus unweighted {metric} temperature', + 'Weighted minus unweighted {metric} temperature', r'{period} ($\degree$C)', ]) filename_part = 'temperature_change_difference_map' From 9c09b2c21c1a15cef8b4268f4c0cb86241243bad Mon Sep 17 00:00:00 2001 From: Lukas Brunner Date: Mon, 29 Mar 2021 16:12:32 +0200 Subject: [PATCH 2/5] Fix flake8 issues --- esmvaltool/diag_scripts/weighting/weighted_temperature_map.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/esmvaltool/diag_scripts/weighting/weighted_temperature_map.py b/esmvaltool/diag_scripts/weighting/weighted_temperature_map.py index 6a932d0cd6..6107f46ed9 100644 --- a/esmvaltool/diag_scripts/weighting/weighted_temperature_map.py +++ b/esmvaltool/diag_scripts/weighting/weighted_temperature_map.py @@ -27,7 +27,7 @@ logger = logging.getLogger(os.path.basename(__file__)) -def set_antimeridian(dataarray: 'xr.DataArray', to: str) -> 'xr.DataArray': +def set_antimeridian(dataarray, to: str): """Flip the antimeridian (i.e. longitude discontinuity) between Europe (i.e., [0, 360)) and the Pacific (i.e., [-180, 180)). @@ -49,7 +49,7 @@ def set_antimeridian(dataarray: 'xr.DataArray', to: str) -> 'xr.DataArray': elif to.lower() == 'pacific': dataarray = dataarray.assign_coords(lon=((lon + 180) % 360) - 180) else: - errmsg = "to has to be one of {'europe', 'pacific'} not {}".format(to) + errmsg = "to has to be one of ['europe', 'pacific'] not {}".format(to) raise ValueError(errmsg) idx = np.argmin(dataarray['lon'].values) From 5f21feb81d7e806398068b30ef4a57f9c457f714 Mon Sep 17 00:00:00 2001 From: Lukas Brunner Date: Thu, 8 Apr 2021 12:14:18 +0200 Subject: [PATCH 3/5] Fix default anti-meridian --- esmvaltool/diag_scripts/weighting/weighted_temperature_map.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/esmvaltool/diag_scripts/weighting/weighted_temperature_map.py b/esmvaltool/diag_scripts/weighting/weighted_temperature_map.py index 6107f46ed9..0708ac68c4 100644 --- a/esmvaltool/diag_scripts/weighting/weighted_temperature_map.py +++ b/esmvaltool/diag_scripts/weighting/weighted_temperature_map.py @@ -72,7 +72,7 @@ def mapplot(dataarray, cfg, title_pattern, filename_part, ancestors, proj = ccrs.PlateCarree(central_longitude=0) figure, axes = plt.subplots(subplot_kw={'projection': proj}) - dataarray = set_antimeridian(dataarray, cfg.get('antimeridian', 'europe')) + dataarray = set_antimeridian(dataarray, cfg.get('antimeridian', 'pacific')) dataarray.plot.pcolormesh( ax=axes, From 38cc2b7b1625cb5220c45c7ea8478850bddcf54c Mon Sep 17 00:00:00 2001 From: Lukas Brunner Date: Thu, 8 Apr 2021 12:14:32 +0200 Subject: [PATCH 4/5] Update basic recipe to test antimeridian --- esmvaltool/recipes/recipe_climwip_test_basic.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/esmvaltool/recipes/recipe_climwip_test_basic.yml b/esmvaltool/recipes/recipe_climwip_test_basic.yml index 08cb22bbe0..67065d0fa4 100644 --- a/esmvaltool/recipes/recipe_climwip_test_basic.yml +++ b/esmvaltool/recipes/recipe_climwip_test_basic.yml @@ -42,7 +42,7 @@ preprocessors: mask_landsea: mask_out: sea extract_region: - start_longitude: 0.0 + start_longitude: -10.0 end_longitude: 39.0 start_latitude: 30.0 end_latitude: 76.25 @@ -134,5 +134,5 @@ diagnostics: weights: 'weights.nc' # optional arguments model_aggregation: mean # [ mean (default) | median | integer in (0, 100) ] - xticks: [0, 10, 20, 30, 40] # if not given ticks will be set automatically + xticks: [-10, 0, 10, 20, 30, 40] # if not given ticks will be set automatically yticks: [30, 40, 50, 60, 70, 80] From 5636282690a703c3a29c7b4ff21ff96ccb959717 Mon Sep 17 00:00:00 2001 From: Lukas Brunner Date: Mon, 19 Apr 2021 10:11:21 +0200 Subject: [PATCH 5/5] Add fix for not-dropped lats/lons --- esmvaltool/diag_scripts/weighting/weighted_temperature_map.py | 1 + 1 file changed, 1 insertion(+) diff --git a/esmvaltool/diag_scripts/weighting/weighted_temperature_map.py b/esmvaltool/diag_scripts/weighting/weighted_temperature_map.py index 0708ac68c4..ff12e4c1c5 100644 --- a/esmvaltool/diag_scripts/weighting/weighted_temperature_map.py +++ b/esmvaltool/diag_scripts/weighting/weighted_temperature_map.py @@ -73,6 +73,7 @@ def mapplot(dataarray, cfg, title_pattern, filename_part, ancestors, figure, axes = plt.subplots(subplot_kw={'projection': proj}) dataarray = set_antimeridian(dataarray, cfg.get('antimeridian', 'pacific')) + dataarray = dataarray.dropna('lon', how='all').dropna('lat', how='all') dataarray.plot.pcolormesh( ax=axes,