⚠️ This is the first operational version of the handbook, but it is still a work in progress and will be heavily updated during 2024! ⚠️

Relative Drought hazard and risk visualization#

Click Binder to launch this workflow on MyBinder.

Aims of the workflow#

This workflow aims for vizualising and exploring the relative drought risk. It includes maps of relative drought risk at NUTS3 for different European countries.

Caution

The workflow is not applicable to the following countries, as they do not have NUTS3 level: Montenegro (ME), Cyprus (CY), Malta (MT), Lithuania (LI), Luxemburg (LU).

IT_RELAMAP.png

It also includes projections for the change in absolute drought hazard index used in this workflow (the WASP index).

IT_ABS.png

Preliminaries#

Load libraries#

import os
import urllib
import pooch
os.environ['USE_PYGEOS'] = '0'
import pandas as pd
import geopandas as gpd
import json
import plotly.express as px
import plotly.graph_objects as go

Define working environment and global parameters#

This workflow relies on pre-proceessed data. The user will define the path to the data folder and the code below will create a folder for outputs.

# Set working environment
workflow_folder = "./sample_data_nuts3"

Access to sample dataset#

Load the file registry for the droughtrisk_sample_nuts3 dataset in the CLIMAAX cloud storage with pooch.

sample_data_pooch = pooch.create(
    path=workflow_folder,
    base_url="https://object-store.os-api.cci1.ecmwf.int/climaax/droughtrisk_sample_nuts3/"
)
sample_data_pooch.load_registry("files_registry.txt")

If any files requested below were downloaded before, pooch will inspect the local file contents and skip the download if the contents match expectations.

Load NUTS3 spatial data and define regions of interest#

NUTS3 data is available in various resolutions: 1:1M (01M), 1:3M (03M), 1:10M (10M), 1:20M (20M) and 1:60M (60M).

nuts3_resolution = "10M"
json_nuts_name = f'NUTS_RG_{nuts3_resolution}_2021_4326_LEVL_3.geojson'

json_nuts_file = pooch.retrieve(
    f'https://gisco-services.ec.europa.eu/distribution/v2/nuts/geojson/{json_nuts_name}',
    known_hash='c2c30148a84cc2ea0d88443790d595d651ca840df9557bac2f00c8bba7cda7f4',
    path=workflow_folder,
    fname=json_nuts_name
)
with open(json_nuts_file, 'r') as f:
    nuts = gpd.GeoDataFrame.from_features(json.load(f)['features'])

nuts['Location'] = nuts['CNTR_CODE'] + ': ' + nuts['NAME_LATN']
nuts = nuts.set_index('Location')

Select country codes#

print("Choose country code from: ", nuts['CNTR_CODE'].unique())
Choose country code from:  ['BG' 'CH' 'AL' 'AT' 'BE' 'DE' 'CY' 'CZ' 'DK' 'EE' 'EL' 'FI' 'FR' 'ES'
 'HU' 'HR' 'LT' 'IE' 'IS' 'IT' 'NL' 'LU' 'LV' 'ME' 'MK' 'LI' 'PL' 'NO'
 'MT' 'SK' 'TR' 'RS' 'SE' 'SI' 'PT' 'RO' 'UK']
# set country code
ccode = "IT" # choose from the country codes printed above
# validate country selection and subset regions
if not nuts['CNTR_CODE'].str.contains(ccode).any():
    print("Country code: ", ccode, " is not valid; please choose a valid country code.")
else:
    nuts = nuts.query('CNTR_CODE in @ccode')

Loading hazard data and concatenate historic with future datasets#

Hazard data is provided in the format required at the NUTS3 level for EU countries in the sample_data folder: e.g. “droughthazard_ES_historic.csv”. The workflow for calculating the hazard data is available in the Hazard Assessment notebook.

# Load the CSV files into a DataFrame
data = ['historic',  'ssp126_nf', 'ssp126_ff',  'ssp370_nf', 'ssp370_ff', 'ssp585_nf', 'ssp585_ff'] # choose which dataset to include
# complete list: 'historic',  'ssp126_nf', 'ssp126_ff',  'ssp370_nf', 'ssp370_ff', 'ssp585_nf', 'ssp585_ff'
count = 0

for d in data:
    df_file = sample_data_pooch.fetch(f"outputs_hazards/droughthazard_{ccode}_{d}.csv")
    df = pd.read_csv(df_file)
    # Print the first 5 rows of the DataFrame
    df['data']=f"{d}" #create a new column with the data specification

    if count == 0:
        df_ = df
        count = 1
    else:
        df_ = pd.concat([df_, df], axis=0) #concatenate the  data in a single dataframe

Choose the focal (NUTS2) area#

#create a group column for the NUTS2 regions
df_['NUTS2'] = df_['NUTS_ID'].str.slice(0,4)

# list NUTS2 region:
print("Choose nuts2 region from: ", df_['NUTS2'].unique())
Choose nuts2 region from:  ['ITF6' 'ITC1' 'ITC4' 'ITF1' 'ITF2' 'ITF3' 'ITF4' 'ITF5' 'ITG1' 'ITG2'
 'ITH1' 'ITH2' 'ITH3' 'ITC2' 'ITC3' 'ITI1' 'ITI2' 'ITI3' 'ITI4' 'ITH4'
 'ITH5']
# Set the focal area
focal = 'ITF1'  # choose from the nuts2 printed above

# Set scenarios to be loaded
data = ['historic',  'ssp126_nf', 'ssp126_ff',  'ssp370_nf', 'ssp370_ff', 'ssp585_nf', 'ssp585_ff']

Loading drought risk data and concatenate historic risk and with future risk datasets#

Drought risk data is provided in the format required at the NUTS3 level for EU countries in the sample_data folder: e.g. “droughtrisk_ES_historic.csv”. The workflow for calculating the hazard data is available in the Drought Risk assessment notebook.

# Complete list: 'historic',  'ssp126_nf', 'ssp126_ff',  'ssp370_nf', 'ssp370_ff',  'ssp585_nf', 'ssp585_ff'
count = 0

for d in data:
    df_file = sample_data_pooch.fetch(f"outputs/droughtrisk_{ccode}_{d}.csv")
    df = pd.read_csv(df_file)
    # Print the first 5 rows of the DataFrame
    df['data']=f"{d}" #create a new column with the data specification
    if count == 0:
        df_ = df
        count = 1
    else:
        df_ = pd.concat([df_, df], axis=0) #concatenate the  data in a single dataframe

loc_ = pd.DataFrame(nuts[['NUTS_ID']])
loc_['Location'] = list(pd.DataFrame(nuts[['NUTS_ID']]).index)
df_ = loc_.merge(df_, on='NUTS_ID')
# Subset dataset for the focal area
focal_area = df_['NUTS_ID'].str.slice(0,4) == focal
df_focal_area = df_[focal_area][["NUTS_ID", "wasp_raw_mean", "wasp_raw_q25", 'wasp_raw_median', "wasp_raw_q75", "wasp_raw_count", "hazard_raw", 'data']]

What is the relative drought risk in each NUTS3 of the selected country?#

Plot the risk category for NUTS3 regions on a map of a selected country. This map allows to compare the drought risk category between NUTS3 regions within a selected country. It also allows to see how the relative drought risk category of the regions changes in relation to each other in the different datasets (e.g. historical, ssp126 near future, ssp126 far future, etc.).

Note

The risk category for each region is always relative to the other regions considered in the workflow (here: country level) and therefore not directly comparable between datasets. This means that the risk category of one region may be higher or lower compared to the other regions, but not between e.g. historical vs. future datasets. Please refer to the risk assessment workflow for more details on how drought risk is calculated.

x_nuts, y_nuts = gpd.GeoSeries(nuts.geometry).unary_union.centroid.xy
slcted = nuts.loc[nuts['NUTS_ID'].str.slice(0,4) == focal, 'NUTS_ID']

fig = px.choropleth_mapbox(df_, geojson=nuts.geometry, locations='Location', color='risk_cat',\
                  animation_frame = 'data', color_continuous_scale="reds", range_color = [1,5],\
                           mapbox_style="open-street-map")

# Customize line properties for selected polygons
fig.update_geos(fitbounds="locations", visible=False)

fig.update_layout(title="Current and projected drought risk",
                  mapbox_center = {"lat": list(y_nuts)[0], "lon": list(x_nuts)[0]},
                  mapbox_zoom=4,
                  height=700,
                 coloraxis_colorbar=dict(
                    title= "Risk category",
                    tickvals = [1, 2, 3, 4, 5],
                    ticktext = [1, 2, 3, 4, 5]
                 ))

fig.show()