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

Risk assessment for heavy snowfall & blizzards#

Risk assessment methodology#

The method involves visually representing the susceptible population exposed to intense snowfall and blizzards. This can be achieved by overlaying indicators for heavy snowfall and blizzards with population data. The objective is to understand the present probability of severe snowfall and blizzards, pinpointing the regions most impacted within Europe. Additionally, we seek to investigate how climate change may modify this exposure over time.

Blizzard#

A blizzard is a severe storm condition defined by low temperature, sustained wind or frequent wind gust and considerable precipitating or blowing snow. For blizzard conditions we propose the use of following impact indicator:

Blizzard days = Tmean ≤ 0 °C, Rs (snow amount) ≥ 10 cm and Wg (wind gust) ≥ 17 m/s ( Vajda et al., 2014).

This impact indicator was defined taking into account the exposure of critical infrastructure, i.e., roads, rails, power lines, telecommunication to the hazard and is based on an extensive literature review, media reports, surveys conducted with European CI operators and case studies.

Heavy Snow#

Heavy snowfall may cause many disruptions and impacts in various sectors; however, the impacts and consequences of this hazard depend on the affected sector, infrastructure and also preparedness of society that varies over Europe. For example, already a few centimeters of snow can disrupt road traffic, but doesn’t normally cause any harm to energy infrastructure. Many weather services have three warning levels based on the severity of expected impacts, which are typically different for different sectors of infrastructure. There is a large variation in the national warning criteria or thresholds.

Similarly to blizzard, the impact indicators for heavy snowfall were defined taking into account the exposure of critical infrastructure, i.e., roads, rails, power lines, telecommunication to the hazard and is based on an extensive literature review, media reports, surveys conducted with European CI operators and case studies. The qualitative description of the two-level thresholds are:

1st threshold ( > 6 cm): Some adverse impacts are expected, their severity depends on the resilience of the system, transportation is mainly affected.

2nd threshold ( > 25 cm): The weather phenomena are so severe that is likely that adverse impact will occur, CI system is seriously impacted.

This code calculates the Annual probability (%) of a blizzard and heavy snowfall days during the specified period and a region of interest.

The annual probability

The annual probability is determined by dividing the count of events surpassing predefined thresholds within a year by the total number of days in that year. The result is then multiplied by 100 to express the probability as a percentage

P = ((variable > threshold) / days in year ) X 100

Preparation work#

Select area of interest#

Before accessing the data, we will define the area of interest. Prior to commencing this workflow, you should have already prepared by downloading the heavy snowfall and blizzards hazard map to your local directory (using the SNOW hazard workflow for heavy snowfall and blizzards or by using your own data). Please specify the name of the area for the snow hazard maps below.

areaname = 'Europe'

Load libraries#

import warnings
warnings.filterwarnings("ignore", message=".*The 'nopython' keyword.*")

import os

import pooch
import numpy as np
np.warnings = warnings
import xarray as xr
import xesmf as xe
import rioxarray as rxr
import matplotlib.pyplot as plt
import cartopy.crs as ccrs
import cartopy.feature as cfeature

Create the directory structure#

In order for this workflow to work even if you download and use just this notebook, we need to have the directory structure for accessing and storing data. If you have already executed the hazard assessment workflow for snow, you would already have created the workflow folder ‘SNOW_hazard’ where the hazard data is stored. We create an additional folder for the risk workflow, called ‘SNOW_risk’.

workflow_folder = 'SNOW_hazard'
if not os.path.exists(workflow_folder):
    os.makedirs(workflow_folder)

general_data_folder = os.path.join(workflow_folder, 'general_data')

# Check if the general data folder exists, if not, create it
if not os.path.exists(general_data_folder):
    os.makedirs(general_data_folder)
data_dir = os.path.join(workflow_folder,f'data_{areaname}')
if not os.path.exists(data_dir):
    os.makedirs(data_dir)

plot_dir = os.path.join(workflow_folder,f'plots_{areaname}')
if not os.path.exists(plot_dir):
    os.makedirs(plot_dir)

Download and explore the data#

Hazard data - intense snowfall and blizzards maps#

As default option, we use the intense snowfall and blizzards maps from the ERA5 single level dataset and CORDEX single level dataset, that were downloaded using the hazard assessment workflow for snow and blizzards. Below we load the maps and visualize them to check the contents.

# ERA5
BdayCount_anaProb_mean_path = os.path.join(data_dir,f'BdayCount_AnaProb_mean_ERA.nc')
BdayCount_anaProb_mean_ERA = xr.open_dataset(BdayCount_anaProb_mean_path,decode_coords='all')

snow6Prob_annual_mean_path = os.path.join(data_dir,f'snow6Prob_annual_mean_ERA.nc')
snow6Prob_annual_mean_ERA = xr.open_dataset(snow6Prob_annual_mean_path,decode_coords='all')

snow25Prob_annual_mean_path = os.path.join(data_dir,f'snow25Prob_annual_mean_ERA.nc')
snow25Prob_annual_mean_ERA = xr.open_dataset(snow25Prob_annual_mean_path,decode_coords='all')
# CORDEX Hist
BdayCount_anaProb_mean_path = os.path.join(data_dir,f'BdayCount_AnaProb_mean_hist.nc')
BdayCount_anaProb_mean_hist = xr.open_dataset(BdayCount_anaProb_mean_path,decode_coords='all')

snow6Prob_annual_mean_path = os.path.join(data_dir,f'snow6Prob_annual_mean_hist.nc')
snow6Prob_annual_mean_hist = xr.open_dataset(snow6Prob_annual_mean_path,decode_coords='all')

snow25Prob_annual_mean_path = os.path.join(data_dir,f'snow25Prob_annual_mean_hist.nc')
snow25Prob_annual_mean_hist = xr.open_dataset(snow25Prob_annual_mean_path,decode_coords='all')
# CORDEX Future
BdayCount_anaProb_mean_path = os.path.join(data_dir,f'BdayCount_AnaProb_mean_fur.nc')
BdayCount_anaProb_mean_fur = xr.open_dataset(BdayCount_anaProb_mean_path,decode_coords='all')

snow6Prob_annual_mean_path = os.path.join(data_dir,f'snow6Prob_annual_mean_fur.nc')
snow6Prob_annual_mean_fur = xr.open_dataset(snow6Prob_annual_mean_path,decode_coords='all')

snow25Prob_annual_mean_path = os.path.join(data_dir,f'snow25Prob_annual_mean_fur.nc')
snow25Prob_annual_mean_fur = xr.open_dataset(snow25Prob_annual_mean_path,decode_coords='all')
BdayCount_anaProb_mean_change = BdayCount_anaProb_mean_fur - BdayCount_anaProb_mean_hist
BdayCount_anaProb_mean_change = BdayCount_anaProb_mean_change.where(BdayCount_anaProb_mean_hist > 1, other=0)

snow6Prob_annual_mean_change = snow6Prob_annual_mean_fur - snow6Prob_annual_mean_hist
snow6Prob_annual_mean_change = snow6Prob_annual_mean_change.where(snow6Prob_annual_mean_hist > 1, other=0)

snow25Prob_annual_mean_change = snow25Prob_annual_mean_fur - snow25Prob_annual_mean_hist
snow25Prob_annual_mean_change = snow25Prob_annual_mean_change.where(snow25Prob_annual_mean_hist > 1, other=0)

BdayCount_anaProb_mean_change = BdayCount_anaProb_mean_change.drop_vars(['rotated_pole','height'])
snow6Prob_annual_mean_change  = snow6Prob_annual_mean_change.drop_vars(['rotated_pole','height'])
snow25Prob_annual_mean_change = snow25Prob_annual_mean_change.drop_vars(['rotated_pole','height'])

Ploting functions#

def plot_overlay_map(var1, var2, V1_p_levels, V2_p_levels, V1_cmap, V2_cmap, Tit1,
                     V1_cb_tit, V2_cb_tit,fileout,min_lon, max_lon, min_lat, max_lat):
    """Plot overlay plot variable with rotated grid and standard grid"""
    np.warnings.filterwarnings('ignore')
    # Create a figure and subplot
    fig = plt.figure(figsize=(16, 8))
    ax = fig.add_subplot(1, 1, 1, projection=ccrs.Orthographic(0, 35))

    # Plot Var1 data
    p_var1 = var1.plot.contourf(ax=ax, levels=V1_p_levels, cmap=V1_cmap,
                                                                 transform=ccrs.PlateCarree(), alpha=0.5, add_colorbar=False)
    # Plot Var2 data
    p_var2 = var2.plot.pcolormesh(ax=ax, x='lon', y='lat', transform=ccrs.PlateCarree(), levels=V2_p_levels,
                                                                        cmap=V2_cmap, alpha=0.5, add_colorbar=False)
    # Set the extent of the plot to the specified latitude and longitude box
    ax.set_extent([min_lon, max_lon, min_lat, max_lat], crs=ccrs.PlateCarree())

    # Add coastlines and features
    ax.coastlines()
    ax.add_feature(cfeature.BORDERS, linestyle=':')
    ax.add_feature(cfeature.LAND, edgecolor='black', facecolor='none')
    ax.add_feature(cfeature.OCEAN, edgecolor='black', facecolor='aliceblue')

    # Add latitude and longitude labels
    gl = ax.gridlines(crs=ccrs.PlateCarree(), draw_labels=True, linewidth=1, color='gray', alpha=0.5, linestyle='--')
    gl.xlabels_top = False
    gl.ylabels_right = False

    # Set title
    plt.title(Tit1, loc="left", fontsize=16)

    # Add colorbars
    cbar_var2 = fig.colorbar(p_var2, ax=ax, location='left', shrink=0.5,  pad=0.05)
    cbar_var2.set_label(V1_cb_tit)
    cbar_var1 = fig.colorbar(p_var1, ax=ax, location='right', shrink=0.5,  pad=0.05)
    cbar_var1.set_label(V2_cb_tit)
    plt.subplots_adjust(right=0.8, left=0.2)

    # Save the figure
    fig.savefig(fileout)
def plot_map_ERA5(var1, V1_p_levels, V1_cmap,Tit1, V1_cb_tit,fileout):
    """Plot ERA5 data"""
    np.warnings.filterwarnings('ignore')
    # Create a figure and subplot
    fig = plt.figure(figsize=(16, 8))
    ax = fig.add_subplot(1, 1, 1, projection=ccrs.Orthographic(0, 35))

    # Plot Var1 data
    p_var1 = var1.plot.contourf(ax=ax, levels=V1_p_levels, cmap=V1_cmap,
                                                                 transform=ccrs.PlateCarree(), add_colorbar=False)

    # Add coastlines and features
    ax.coastlines()
    ax.add_feature(cfeature.BORDERS, linestyle=':')
    ax.add_feature(cfeature.LAND, edgecolor='black', facecolor='none')
    ax.add_feature(cfeature.OCEAN, edgecolor='black', facecolor='aliceblue')

    # Add latitude and longitude labels
    gl = ax.gridlines(crs=ccrs.PlateCarree(), draw_labels=True, linewidth=1, color='gray', alpha=0.5, linestyle='--')
    gl.xlabels_top = False
    gl.ylabels_right = False

    # Set title
    plt.title(Tit1, loc="left", fontsize=16)

    # Add colorbars
    cbar_var1 = fig.colorbar(p_var1, ax=ax, location='right', shrink=0.5,  pad=0.05)
    cbar_var1.set_label(V1_cb_tit)
    #plt.subplots_adjust(right=0.8, left=0.2)

    # Save the figure
    fig.savefig(fileout)
def plot_map_CORDEX(var1, V1_p_levels, V1_cmap, Tit1, V1_cb_tit,fileout):
    """Plot CORDEX data"""
    np.warnings.filterwarnings('ignore')
    # Create a figure and subplot
    fig = plt.figure(figsize=(16, 8))
    ax = fig.add_subplot(1, 1, 1, projection=ccrs.Orthographic(0, 35))

    # Plot Var1 data
    p_var1 = var1.plot.pcolormesh(ax=ax, x='lon', y='lat', transform=ccrs.PlateCarree(), levels=V1_p_levels,
                                                                        cmap=V1_cmap, add_colorbar=False)
    # Add coastlines and features
    ax.coastlines()
    ax.add_feature(cfeature.BORDERS, linestyle=':')
    ax.add_feature(cfeature.LAND, edgecolor='black', facecolor='none')
    ax.add_feature(cfeature.OCEAN, edgecolor='black', facecolor='aliceblue')

    # Add latitude and longitude labels
    gl = ax.gridlines(crs=ccrs.PlateCarree(), draw_labels=True, linewidth=1, color='gray', alpha=0.5, linestyle='--')
    gl.xlabels_top = False
    gl.ylabels_right = False

    # Set title
    plt.title(Tit1, loc="left", fontsize=16)

    # Add colorbars
    cbar_var1 = fig.colorbar(p_var1, ax=ax, location='right', shrink=0.5,  pad=0.05)
    cbar_var1.set_label(V1_cb_tit)

    # Save the figure
    fig.savefig(fileout)

Plot change in annual probability#

# Plot change in Annual probability of blizzard days
var1 = BdayCount_anaProb_mean_change.blizzard_days
V1_p_levels = [-1, -0.8, -0.6, -0.4, -0.2, 0.2, 0.4, 0.6, 0.8, 1]
V1_cmap = 'seismic_r'

Tit1 = 'Change in annual probability of blizzard days'
V1_cb_tit = ' '
fileout = os.path.join(plot_dir, 'Chan_Ann_prob_blizzard_days_CORDEX.png')

plot_map_CORDEX(var1, V1_p_levels, V1_cmap, Tit1, V1_cb_tit,fileout)
../../../../_images/27611e6e8639c4534667478fdecf6da74efa274d7423f27e3fbeffac1e8cb41f.png
# Plot change in Annual probability of snowfall exceeding 6 cm
var1 = snow6Prob_annual_mean_change.snow_days

V1_p_levels = [-10, -8, -6, -4, -2, 2, 4, 6, 8, 10]
V1_cmap = 'seismic_r'

Tit1 = 'Change in Annual probability of snowfall days > 6 cm'
V1_cb_tit = ' '
fileout = os.path.join(plot_dir, 'Chan_Ann_prob_snow_days_6_CORDEX.png')

plot_map_CORDEX(var1, V1_p_levels, V1_cmap, Tit1, V1_cb_tit,fileout)
../../../../_images/54fe210b89785b9556d2e142bc6000dc4755a37454587bafbaa8df368b4b8199.png
# Plot change in Annual probability of snowfall exceeding 25 cm
var1 = snow25Prob_annual_mean_change.snow_days
V1_p_levels = [-10, -8, -6, -4, -1, 1, 4, 6, 8, 10]
V1_cmap = 'seismic_r'

Tit1 = 'Change in Annual probability of snowfall days > 25 cm'
V1_cb_tit = ' '
fileout = os.path.join(plot_dir, 'Chan_Ann_prob_snow_days_25_CORDEX.png')

plot_map_CORDEX(var1, V1_p_levels, V1_cmap, Tit1, V1_cb_tit,fileout)
../../../../_images/8dce24054b68403c7c1b34d5609a447b81f6df005b418e173c69f7dbb1b2cbf2.png

Exposure - Population data#

In this illustration, we are using population data sourced from the JRC data portal, specifically the Global Human Settlement Layer Global Human Settlement Layer GHSL, with 30 arcsec resolution global datasets. After downloading and extracting the data, Pooch will list the contents within the data directory.

url = 'https://jeodpp.jrc.ec.europa.eu/ftp/jrc-opendata/GHSL/GHS_POP_GLOBE_R2023A/GHS_POP_E2015_GLOBE_R2023A_4326_30ss/V1-0/GHS_POP_E2015_GLOBE_R2023A_4326_30ss_V1_0.zip'
pop_files = pooch.retrieve(
    url=url,
    known_hash=None,
    path=data_dir,
    processor=pooch.Unzip(extract_dir='')
)

The zip file contains data, as well as metadata and the documentation in the pdf file.

Explore the data#

Population data#

Population data is in file with filename: GHS_POP_E2015_GLOBE_R2023A_4326_30ss_V1_0.tif

We can use rioxarray to load this file and explore the projections of the dataset.

filename_population = f'{data_dir}/GHS_POP_E2015_GLOBE_R2023A_4326_30ss_V1_0.tif'

population = rxr.open_rasterio(filename_population)

population = population.rename({'x': 'longitude', 'y': 'latitude'})
population.rio.crs
CRS.from_epsg(4326)

Note that now, we have a directory snow_workflow/data where all the zip files and unzipped files are stored.

Process the data#

Population data#

In this workflow, we want to overlay the population data on snowfall and blizzard indicators to better understand where these indicators affect densely populated areas.

Take a closer look at the dimensions and coordinates of our two data objects.

  • Notice that the population data has x and y as spatial dimensions, while ERA5 has latitude and longitude.

  • Both datasets are in the same projection: WSG84/epsg 4326.

  • However, the resolutions of the datasets are different.

To be able to plot these two datasets together, we must have them at the same resolution and zoomed in to the same area.

To regrid the data, we utilize the xESMF library, a Universal Regridder for Geospatial Data, to regrid the population data to match the ERA5 resolution. Prior to regridding, the population data is cropped specifically for the European region.

Europe_population = population.sel(latitude=slice(80.0,20.0), longitude=slice(-10.0,45.0))
snow6Prob_annual_mean_ERA.rio.write_crs(4326, inplace=True)
snow6Prob_annual_mean_ERA.rio.crs
CRS.from_epsg(4326)
# Building the regridder can take a while
regridder = xe.Regridder(Europe_population, snow6Prob_annual_mean_ERA, 'bilinear', periodic=True)

Europe_population_025deg = regridder(Europe_population)

# Alternatively, a much faster, but low-quality interpolation can be carried out with xarray:
#Europe_population_025deg = Europe_population.interp({
#    'latitude': snow6Prob_annual_mean_ERA["latitude"],
#    'longitude': snow6Prob_annual_mean_ERA["longitude"]
#})

del Europe_population_025deg['band']
del Europe_population_025deg['spatial_ref']

Europe_population_025deg.to_netcdf(path=os.path.join(data_dir, "Europe_population_25deg.nc"))
# Explore the Population Density
var1 = np.squeeze(Europe_population_025deg)
V1_p_levels =  [1, 10, 30, 60, 100, 500, 1000]
V1_cmap = "hot_r"
Tit1 = 'Population Density'
V1_cb_tit = ' '
fileout = os.path.join(plot_dir, 'Population_Density.png')

plot_map_ERA5(var1, V1_p_levels, V1_cmap, Tit1, V1_cb_tit, fileout)
../../../../_images/49ef69279a3c1e90c94d4a67b9f8529cc7d6043de74c8a6bca3125f2353dea9e.png

Plot the results#

Select the area of interest#

We are currently selecting the Alpine region because pollution density is higher in this area, and there is also a greater probability of heavy snow and blizzards, using the specified latitude and longitude extents, which can be modified as needed.

xmin=4  # Min Longitude
xmax=15 # Max Longitude

ymin=42 # Min Latitude
ymax=50 # Max Latitude

SelArea_population  = Europe_population_025deg.sel(latitude=slice(ymax,ymin), longitude=slice(xmin,xmax))

SelArea_6cm_ind     = snow6Prob_annual_mean_ERA.sel(latitude=slice(ymax,ymin), longitude=slice(xmin,xmax))
SelArea_25cm_ind    = snow25Prob_annual_mean_ERA.sel(latitude=slice(ymax,ymin), longitude=slice(xmin,xmax))
SelArea_blizard_ind = BdayCount_anaProb_mean_ERA.sel(latitude=slice(ymax,ymin), longitude=slice(xmin,xmax))

To explore the exposure and vulnerability of the population, plot them together#

We are exclusively plotting snow indices in regions where the population density exceeds 1/km.

Plot population with Historical snow indices#

# Create a mask for snow data where pollution density is below 1
SelArea_6cm_ind_masked = SelArea_6cm_ind.snow_days.where(SelArea_population >= 1)
SelArea_25cm_ind_masked = SelArea_25cm_ind.snow_days.where(SelArea_population >= 1)
SelArea_blizard_ind_masked = SelArea_blizard_ind.blizzard_days.where(SelArea_population >= 1)

population_masked_Blizard = SelArea_population.where(SelArea_blizard_ind.blizzard_days > 0)

min_lon = xmin
max_lon = xmax
min_lat = ymin
max_lat = ymax

SelArea_population = SelArea_population.rename({'longitude': 'lon','latitude': 'lat'})

var1 = np.squeeze(SelArea_6cm_ind_masked)
var2 = np.squeeze(SelArea_population)

V1_p_levels = [0, 1, 5, 10, 30, 40]
V2_p_levels =  [1, 10, 30, 60, 100, 500, 1000]

V1_cmap = "GnBu"
V2_cmap = "hot_r"

Tit1 = 'Annual probability (%) of snowfall exceeding 6 cm'
V1_cb_tit = 'Population Density'
V2_cb_tit = 'Snow days'

fileout = os.path.join(plot_dir,'Population_Density_Annual_probability_snowfall_days_6cm.png'.format(areaname))

#plot_overlay_map(var1, var2, V1_p_levels, V2_p_levels, V1_cmap, V2_cmap, Tit1, V1_cb_tit, V2_cb_tit,fileout)
plot_overlay_map(var1, var2, V1_p_levels, V2_p_levels, V1_cmap, V2_cmap, Tit1, V1_cb_tit, V2_cb_tit,fileout,min_lon, max_lon, min_lat, max_lat)
../../../../_images/ecbdd7f260aff0241f3a9fa723206b2205b11bc1097517ffeb8a1b87c3e8843e.png
# Create a mask for snow data where pollution density is below 1
var1 = np.squeeze(SelArea_25cm_ind_masked)
var2 = np.squeeze(SelArea_population)

V1_p_levels = [0, 1, 5, 10, 30, 40]
V2_p_levels =  [1, 10, 30, 60, 100, 500, 1000]

V1_cmap = "GnBu"
V2_cmap = "hot_r"

Tit1 = 'Annual probability (%) of snowfall exceeding 25 cm'
V1_cb_tit = 'Population Density'
V2_cb_tit = 'Snow days'

fileout = os.path.join(plot_dir,'Population_Density_Annual_probability_snowfall_days_25cm.png'.format(areaname))

plot_overlay_map(var1, var2, V1_p_levels, V2_p_levels, V1_cmap, V2_cmap, Tit1, V1_cb_tit, V2_cb_tit,fileout,min_lon, max_lon, min_lat, max_lat)
../../../../_images/71ee9606a7758971653d73728c7bbc8e29bfcadfab7d6e41cf016b33014d4cd1.png
population_masked_Blizard = population_masked_Blizard.rename({'longitude': 'lon','latitude': 'lat'})

var1 = np.squeeze(SelArea_blizard_ind_masked)
var2 = np.squeeze(population_masked_Blizard)

V1_p_levels = [0, 1, 5, 10, 30, 40]
V2_p_levels =  [1, 10, 30, 60, 100, 500, 1000]

V1_cmap = "GnBu"
V2_cmap = "hot_r"

Tit1 = 'Change in annual probability of blizzard days'
V1_cb_tit = 'Population Density'
V2_cb_tit = ' '

fileout = os.path.join(plot_dir,'Population_Density_Annual_probability_blizzard.png'.format(areaname))

plot_overlay_map(var1, var2, V1_p_levels, V2_p_levels, V1_cmap, V2_cmap, Tit1, V1_cb_tit, V2_cb_tit,fileout,min_lon, max_lon, min_lat, max_lat)
../../../../_images/8b4da41b41e2f7dc2d03dbc9154fcc5e3251a24a32489d92f9e667889254472c.png

Plot population with change in snow indices by mid-century#

var2 = np.squeeze(BdayCount_anaProb_mean_change.blizzard_days)
var1 = np.squeeze(SelArea_population)

V2_p_levels = [-1, -0.8, -0.6, -0.4, -0.2, 0.2, 0.4, 0.6, 0.8, 1]
V1_p_levels =  [1, 10, 30, 60, 100, 500, 1000]

V2_cmap = "PiYG"
V1_cmap = "hot_r"

Tit1 = 'Change in Annual probability (%) of snowfall exceeding 6 cm'
V2_cb_tit = 'Population Density'
V1_cb_tit = ' '

fileout = os.path.join(plot_dir,'Population_Density_Annual_probability_snowfall_days_6cm.png'.format(areaname))

plot_overlay_map(var1, var2, V1_p_levels, V2_p_levels, V1_cmap, V2_cmap, Tit1, V1_cb_tit, V2_cb_tit,fileout,min_lon, max_lon, min_lat, max_lat)
../../../../_images/0a26189fb4487be01add12e893657cd5b6748be1e20fe357d75819d15c759638.png
var2 = np.squeeze(snow6Prob_annual_mean_change.snow_days)
var1 = np.squeeze(SelArea_population)

V2_p_levels = [-10, -8, -6, -4, -2, 2, 4, 6, 8, 10]
V1_p_levels =  [1, 10, 30, 60, 100, 500, 1000]

V2_cmap = "PiYG"
V1_cmap = "hot_r"

Tit1 = 'Change in Annual probability (%) of snowfall exceeding 6 cm'
V2_cb_tit = 'Population Density'
V1_cb_tit = ' '

fileout = os.path.join(plot_dir,'Population_Density_Annual_probability_snowfall_days_6cm.png'.format(areaname))

plot_overlay_map(var1, var2, V1_p_levels, V2_p_levels, V1_cmap, V2_cmap, Tit1, V1_cb_tit, V2_cb_tit,fileout,min_lon, max_lon, min_lat, max_lat)
../../../../_images/e1880fedfb5e80015d6da36721162d23fbc21677d6781b706acda9b153b1cdc8.png
var2 = np.squeeze(snow25Prob_annual_mean_change.snow_days)
var1 = np.squeeze(SelArea_population)

V2_p_levels = [-10, -8, -6, -4, -2, 2, 4, 6, 8, 10]
V1_p_levels =  [1, 10, 30, 60, 100, 500, 1000]

V2_cmap = "PiYG"
V1_cmap = "hot_r"

Tit1 = 'Change in Annual probability (%) of snowfall exceeding 25 cm'
V2_cb_tit = 'Population Density'
V1_cb_tit = ' '

fileout = os.path.join(plot_dir,'Population_Density_Annual_probability_snowfall_days_25cm.png'.format(areaname))

plot_overlay_map(var1, var2, V1_p_levels, V2_p_levels, V1_cmap, V2_cmap, Tit1, V1_cb_tit, V2_cb_tit,fileout,min_lon, max_lon, min_lat, max_lat)
../../../../_images/d2f54bb29dd2e345ca5cb371250d934cffe8c2bf8ea1cad0271d5e9afcc20f3c.png

Conclusions#

In this workflow, we’ve illustrated the process of exploring, processing, and visualizing data necessary for analyzing the influence of heavy snowfall and blizzard day indices on population density. These indices are presented as annual probabilities of occurrence, reflecting the likelihood of a particular event happening over several years. In the present climate, communities in the northern Alpine region face heightened vulnerability to heavy snowfall and blizzards. However, under the RCP2.5 scenario by mid-century, we observe a significant reduction in the severity of these hazards across the region compared to the current climate.

Contributors#

  • Suraj Polade, Finnish Meteorological Institute

  • Andrea Vajda, Finnish Meteorological Institute