Instructions¶
Objectives
In this final project, you will apply the methods you learned over the past weeks to answer the questions below.
Deadline
Please submit your project via OLAT before Thursday January 11 at 00H (in the night from Wednesday to Thursday).
Formal requirements
You will work in groups of two. If we are an odd number of students, one group can have three participants. (Tip: I recommend that students who have not followed a programming class to team up with students who have).
Each group will submit one (executed) jupyter notebook containing the code, plots, and answers to the questions (text in the markdown format). Please also submit an HTML version of the notebook. Each group member must contribute to the notebook. The notebook should be self-contained and the answers must be well structured. The plots must be as understandable as possible (title, units, x and y axis labels, appropriate colors and levels…).
Please be concise in your answer. We expect a few sentences per answer at most - there is no need to write a new text book in this project! Use links and references to the literature or your class slides where appropriate.
Grading
We will give one grade per project, according to the following table (total 10 points):
- correctness of the code and the plots: content, legends, colors, units, etc. (3 points)
- quality of the answers: correctness, preciseness, appropriate use of links and references to literature or external resources (5 points)
- originality and quality of the open research question (2 points)
# Import the tools we are going to need today:
import matplotlib.pyplot as plt # plotting library
import numpy as np # numerical library
import xarray as xr # netCDF library
import pandas as pd # tabular library
import cartopy # Map projections libary
import cartopy.crs as ccrs # Projections list
import cartopy.feature as cfeature
# Some defaults:
plt.rcParams['figure.figsize'] = (12, 5) # Default plot size
Part 1 - temperature climatology¶
Open the ERA5 temperature data:
ds = xr.open_dataset('ERA5_LowRes_Monthly_t2m.nc')
ds
<xarray.Dataset> Dimensions: (longitude: 480, latitude: 241, time: 480) Coordinates: * longitude (longitude) float32 -179.6 -178.9 -178.1 ... 178.1 178.9 179.6 * latitude (latitude) float32 90.0 89.25 88.5 87.75 ... -88.5 -89.25 -90.0 * time (time) datetime64[ns] 1979-01-01 1979-02-01 ... 2018-12-01 Data variables: t2m (time, latitude, longitude) float32 ... Attributes: Conventions: CF-1.6 history: 2019-11-18 09:36:58 GMT by grib_to_netcdf-2.14.0: /opt/ecmw...
Plot three global maps:
- Compute and plot the temporal mean temperature ¯T for the entire period (unit °C)
- Compute and plot ¯T∗ (see lesson), the zonal anomaly map of average temperature.
- Compute and plot the monthly average temperature for each month ¯TM (annual cycle). I expect a variable of dimensions (month: 12, latitude: 241, longitude: 480). Hint: remember the
.groupby()
command we learned in the lesson. Now plot the average monthly temperature range, i.e. ¯TMmax - ¯TMmin on a map.
t2_tavg=ds.t2m.mean(dim='time')-273.15
ax = plt.axes(projection=ccrs.Robinson())
t2_tavg.plot(ax=ax, transform=ccrs.PlateCarree(), center=False,
vmin=-40, vmax=20, levels=7, cbar_kwargs={'label': 'degrees celsius'})
ax.set_title('Average 2m air temperature, ERA5 1979-2018')
ax.coastlines(); ax.gridlines();
t_avg_dep = t2_tavg - t2_tavg.mean(dim='longitude')
ax = plt.axes(projection=ccrs.Robinson())
t_avg_dep.plot.imshow(ax=ax, transform=ccrs.PlateCarree(), cbar_kwargs={'label': 'Difference in degrees'})
ax.set_title('Zonal anomaly map of average temperature, ERA5 1979-2018')
ax.coastlines(); ax.gridlines();
t_monthly = ds['t2m'].groupby('time.month').mean(dim='time')-273.15
max_temp = t_monthly.max()
min_temp = t_monthly.min()
plt.figure(figsize=(12, 24))
for i in range(1, 13):
ax = plt.subplot(6, 2, i, projection=ccrs.PlateCarree())
t_monthly.sel(month=i).plot(ax=ax, transform=ccrs.PlateCarree(), add_colorbar=False, vmin=min_temp, vmax=max_temp, cmap='RdBu_r')
ax.coastlines()
ax.set_title('Month: {}'.format(i))
plt.tight_layout()
plt.show()
Questions:
- Look at the zonal temperature anomaly map.
- Explain why norther Europe and the North Atlantic region is significantly warmer than the same latitudes in North America or Russia.
- Explain why the Northern Pacific Ocean does not have a similar pattern.
- Look at the average monthly temperature range map.
- Explain why the temperature range is smaller in the tropics than at higher latitudes
- Explain why the temperature range is smaller over oceans than over land
- Where is the temperature range largest? Explain why.
Answers: 1. - Mostly because of the gulf stream: "For example, during summer, under conditions of southerly low level flow, there often exists a sharp contrast between humid air advected northward from the Gulf of Mexico and much drier air that has subsided along the eastern slopes of the Rockies" - Atmospheric science from Wallace&Hobbs in 8.1.c - The Northern Pacific Ocean does not have a similar pattern, because the Kusohio stream is much weaker than the gulf and also not reaching that high north than the gulf. (Seen in the same book, chapter two in figure 2.4) 2. - The angle of the solar insulation is not varying so much over the year in the tropics, which has a huge impact on the temperature range. - The oceans are able to store more heat than land, so the temperature range decreases over the oceans. - Atmospheric science from Wallace&Hobbs in 10.1.3 - The temperature range is largest over the the Himalayas because they are very high and therefore the pressure decreases leading to colder temperatures than the rest of the zonal average. (Also on the southpole there is a large temperature range but I don't know why.)
Part 2 - Precipitation climatology¶
Open the precipitation file and explore it. The units of monthly precipitation are wrongly labeled (unfortunately). They should read: m per day.
dc = xr.open_dataset('ERA5_LowRes_Monthly_tp.nc')
dc
<xarray.Dataset> Dimensions: (longitude: 480, latitude: 241, time: 480) Coordinates: * longitude (longitude) float32 -179.6 -178.9 -178.1 ... 178.1 178.9 179.6 * latitude (latitude) float32 90.0 89.25 88.5 87.75 ... -88.5 -89.25 -90.0 * time (time) datetime64[ns] 1979-01-01 1979-02-01 ... 2018-12-01 Data variables: tp (time, latitude, longitude) float32 ... Attributes: Conventions: CF-1.6 history: 2019-11-18 09:30:18 GMT by grib_to_netcdf-2.14.0: /opt/ecmw...
Using .groupby()
, compute the average daily precipitation for each month of the year (I expect a variable of dimensions (month: 12, latitude: 241, longitude: 480)). Convert the units to mm per day. Plot a map of average daily precipitation in January and in August with the levels [0.5, 1, 2, 3, 4, 5, 7, 10, 15, 20, 40]
and the colormap `YlGnBu'
Questions:
- Describe the location of the ITCZ in January and August. Without going into the details, explain (in one or two sentences)
- Describe the precipitation seasonality in West Africa and in India. Name the phenomenon at play.
tp_m=(dc.tp.groupby('time.month').mean())*1000
ax = plt.axes(projection=ccrs.Robinson())
tp_m[1].plot(ax=ax, transform=ccrs.PlateCarree(), cmap='YlGnBu', levels=[0.5, 1, 2, 3, 4, 5, 7, 10, 15, 20, 40], cbar_kwargs={'label': 'mm'})
ax.set_title('Average precipitation January, ERA5 1979-2018')
ax.coastlines(); ax.gridlines();
ax = plt.axes(projection=ccrs.Robinson())
tp_m[8].plot(ax=ax, transform=ccrs.PlateCarree(), cmap='YlGnBu', levels=[0.5, 1, 2, 3, 4, 5, 7, 10, 15, 20, 40], cbar_kwargs={'label': 'mm'})
ax.set_title('Average precipitation August, ERA5 1979-2018')
ax.coastlines(); ax.gridlines();
Questions:
- Describe the location of the ITCZ in January and August. Without going into the details, explain (in one or two sentences)
- Describe the precipitation seasonality in West Africa and in India. Name the phenomenon at play.
Answers:
- In January it is closer southwards, in August it's more to the north.
- On the plots the rainy seasons in a few countries in the asian region, the phenomenon is called monsoon.
Part 3: sea-level pressure and surface winds¶
Open the file containing the surface winds (u10
and v10
) and sea-level pressure (msl
).
dd = xr.open_dataset('ERA5_LowRes_Monthly_uvslp.nc')
dd
<xarray.Dataset> Dimensions: (longitude: 480, latitude: 241, time: 480) Coordinates: * longitude (longitude) float32 -179.6 -178.9 -178.1 ... 178.1 178.9 179.6 * latitude (latitude) float32 90.0 89.25 88.5 87.75 ... -88.5 -89.25 -90.0 * time (time) datetime64[ns] 1979-01-01 1979-02-01 ... 2018-12-01 Data variables: u10 (time, latitude, longitude) float32 ... v10 (time, latitude, longitude) float32 ... msl (time, latitude, longitude) float32 ... Attributes: Conventions: CF-1.6 history: 2019-11-24 19:42:05 GMT by grib_to_netcdf-2.14.0: /opt/ecmw...
Compute [¯SLP] (the temporal and zonal average of sea-level pressure). Convert it to hPa, and plot it (line plot). With the help of plt.axhline, add the standard atmosphere pressure line to the plot to emphasize high and low pressure regions. Repeat with [¯u10] and [¯v10] (in m s−1) and add the 0 horizontal line to the plot (to detect surface westerlies from easterlies for example).
slp_mean=(dd.msl.mean(dim='time').mean(dim='longitude'))/100
slp_mean.plot()
plt.title('Temporal and zonal average of sea-level pressure')
plt.axhline(y=1013.25)
<matplotlib.lines.Line2D at 0x29169b880>
slp_mean=(dd.u10.mean(dim='time').mean(dim='longitude'))
slp_mean.plot()
plt.title('Temporal and zonal average of the u-component')
plt.axhline(y=0)
<matplotlib.lines.Line2D at 0x2916d08b0>
slp_mean=(dd.v10.mean(dim='time').mean(dim='longitude'))
slp_mean.plot()
plt.title('Temporal and zonal average of the v-component')
plt.axhline(y=0)
<matplotlib.lines.Line2D at 0x291727790>
slp_mean = (dd.msl.mean(dim='time').mean(dim='longitude'))/100 - 1013.25
slp_mean.plot(label='MSL')
slp_mean = dd.u10.mean(dim='time').mean(dim='longitude')
slp_mean.plot(label='U')
slp_mean = dd.v10.mean(dim='time').mean(dim='longitude')
slp_mean.plot(label='V')
plt.legend()
plt.axhline(y=0, color='black')
plt.savefig('part3')
Questions:
- Based on your knowledge about the general circulation of the atmosphere, explain the latitude location of the climatological high and low pressure systems of Earth.
- Similarly, explain the direction and strength of the zonal and meridional winds on earth (tip: the sea-level pressure plot helps)
Answers:
- What can be seen in the pressure is the low pressure system around the equator -> the ITCZ (intense solar heating -> warm air rises). What we also know is the polar lows the most intense low is at around latitude -60 until -70 degrees. At around 30 degrees north and south we can see a higher pressure as the average: here are the subtropical highs where air is descending.
- About the zonal winds: Starting from the equator until +30 and -30 degrees we know there are trade winds present (u-component below zero meaning going from east to west). Above 30 degrees (NH and SH) we have the westerlies, which are also reflected in the plot (u-component above zero meaning going from west to east). About the meridional winds: Close to the equator we can see that the v-component is close to zero. Starting there going northwards the v-component is negative because of the south component of the trade winds. The same occurs vice versa going from the equator towards south, where we can see positive values for the v-component, meaning the winds go from south to north, which is also because of the trade winds. Above 30 (NH and SH) we have the westerlies which are better seen in the v-component on the southern hemisphere showing negative values again meaning going from south to north. (For the NH the westerlies have positive values but here they are barely visible.)
Part 4: temperature change and CO2 concentrations¶
Download the global average CO2 concentration timeseries data in the CSV format (source: NOAA). Here, let me help your read them using pandas:
df = pd.read_csv('co2_mm_gl.csv', skiprows=38, parse_dates={'date' : [0, 1]}, index_col='date')
#df[0] = pd.to_datetime(df[0])
df
/var/folders/zr/1g427gwn0hq1xlw59hblpbwr0000gn/T/ipykernel_43630/4110104413.py:1: UserWarning: Could not infer format, so each element will be parsed individually, falling back to `dateutil`. To ensure parsing is consistent and as-expected, please specify a format. df = pd.read_csv('co2_mm_gl.csv', skiprows=38, parse_dates={'date' : [0, 1]}, index_col='date')
decimal | average | average_unc | trend | trend_unc | |
---|---|---|---|---|---|
date | |||||
1979-01-01 | 1979.042 | 336.56 | 0.11 | 335.92 | 0.09 |
1979-02-01 | 1979.125 | 337.29 | 0.09 | 336.25 | 0.10 |
1979-03-01 | 1979.208 | 337.88 | 0.11 | 336.51 | 0.10 |
1979-04-01 | 1979.292 | 338.32 | 0.12 | 336.72 | 0.10 |
1979-05-01 | 1979.375 | 338.26 | 0.03 | 336.71 | 0.10 |
... | ... | ... | ... | ... | ... |
2023-05-01 | 2023.375 | 420.54 | 0.10 | 418.87 | 0.06 |
2023-06-01 | 2023.458 | 419.53 | 0.10 | 418.94 | 0.06 |
2023-07-01 | 2023.542 | 417.83 | 0.10 | 419.10 | 0.06 |
2023-08-01 | 2023.625 | 416.53 | 0.10 | 419.36 | 0.06 |
2023-09-01 | 2023.708 | 416.83 | 0.10 | 419.70 | 0.06 |
537 rows × 5 columns
Prepare three plots:
- plot the monthly global CO2 concentration as a function of time.
- plot the annual average timeseries of global CO2 concentration as a function of time.
- plot the annual average timeseries of global CO2 concentration and of global 2m temperature from ERA5 on the same plot (using a secondary y axis for temperature).
df["average"].plot()
plt.ylabel('CO2 concentration in ppm')
plt.xlabel('Year')
plt.title('Monthly global CO2 concentration')
Text(0.5, 1.0, 'Monthly global CO2 concentration')
dfy=df.resample('Y').mean()
dfy['average'].plot()
plt.ylabel('CO2 concentration in ppm')
plt.xlabel('Year')
plt.title('Annual average of CO2 concentration')
Text(0.5, 1.0, 'Annual average of CO2 concentration')
t2my=ds.t2m.groupby('time.year').mean()
t2my=t2my.mean(dim='longitude')
#weight = np.cos(np.deg2rad(ds.latitude))
#weight = weight / weight.sum()
#t2my = np.sum(t2my * weight)
t2my=t2my.mean(dim='latitude')#not weighted!!!
fig, ax = plt.subplots()
line1, = ax.plot(pd.to_datetime(t2my.year, format='%Y'), t2my.data, color='black', label='Global Temperature')
ax.set_ylabel('t2m [K]', color='black')
ax.set_xlabel('Year', color='black')
ax2 = ax.twinx()
line2, = ax2.plot(dfy['average'], color='blue', label='CO2 Concentration')
ax2.set_ylabel('CO2 [ppm]', color='blue')
lines = [line1, line2]
labels = [line.get_label() for line in lines]
ax.legend(lines, labels, loc='upper left')
plt.title('Annual average of CO2 concentration and global temperature')
plt.show()
df_1985 = df.loc['1985']
avg_1985 = df_1985['average'].mean()
df_1980 = df.loc['1980']
avg_1980 = df_1980['average'].mean()
df_2021 = df.loc['2021']
avg_2021 = df_2021['average'].mean()
df_2016 = df.loc['2016']
avg_2016 = df_2016['average'].mean()
annualincrease1980 = (avg_1985-avg_1980)/(1985-1980)
annualincrease2016 = (avg_2021-avg_2016)/(2021-2016)
print(annualincrease1980)
print(annualincrease2016)
1.3251666666666666 2.3273333333333426
Questions:
- Describe and explain the annual cycle of CO2 concentrations
- What was the CO2 concentration in the atmosphere in the pre-industrial era? Compute the annual increase in CO2 concentration (unit: ppm per year) between 1980 and 1985 and between 2016 and 2021.
- Describe the relationship between global temperatures and CO2 concentrations. Beside CO2, name three processes that can influence temperature variability and change at the global scale.
Answers:
- One can see that in the winter time on the NH there is a higher CO2 concentration than in the summer time.This is because of the additional combustion processes for heating in the winter time and the higher plant activities in summer.
- The annual CO2 increase between 1980 and 1985 was 1.33ppm and the increase between 2016 and 2021 was 2.33ppm.
- The relationship between the temperature and CO2 concentration is a positive one since CO2 is a greenhouse gas and therefore warming our earth. Besides CO2 there are of course other GHGs f.e. methane. 3 other processes that influence the temperature variability could be a) changes in the solar radiation, b) change in the albedo (f.e. when large areas of ice are melting, less light is being reflected and therefore has an impact on the earths temperature) and c) volcanic activity/aerosole which can also have an impact on the albedo but have as well other aspects that influence the temperature change.
Part 5: variability and ENSO (open research question)¶
As of November 2023, the world is currently experiencing El Niño conditions, with projections indicating its persistence through the upcoming spring (source). To understand the implications and compare with La Niña, we will utilize our available data.
Using your learned skills, you should create global anomalie maps of sea-surface temperature, precipitation, and air temperature, comparing one El Niño with one La Niña year. Describe the anomaly patterns you are seeing in your plots (e.g. where do we see an increase/decrease in precipitation).
We suggest to look for literature or a google search on strong ENSO events in the past 40 years, and select one good example for a positive and a negative phase. With citation or links, explain why you picked these years as examples.
Laut NOAA/CPC-Liste war das stärkste El Niño-Ereignis der letzten 40 Jahre in der Wintersaison 1997-1998 und das stärkste La Niña-Ereignis in der Wintersaison 1988-1989. Ausgewählt: 1988 für La Nina und 1997 für El Nino.
#2m Temperatur
t2_avg=ds.t2m.mean(dim='time')
ts_y=ds.t2m.groupby('time.year').mean()
t_an_88 = ts_y[9]-t2_avg
ax = plt.axes(projection=ccrs.Robinson())
t_an_88.plot.imshow(ax=ax, transform=ccrs.PlateCarree(),vmin=-4, vmax=4, levels=7,cmap='RdBu_r', cbar_kwargs={'label': 'Difference in degrees'})
ax.coastlines(); ax.gridlines();
plt.title('Air temperature anomaly for 1988')
Text(0.5, 1.0, 'Air temperature anomaly for 1988')
t_an_97 = ts_y[18]-t2_avg
ax = plt.axes(projection=ccrs.Robinson())
t_an_97.plot.imshow(ax=ax, transform=ccrs.PlateCarree(),vmin=-4, vmax=4, levels=7,cmap='RdBu_r', cbar_kwargs={'label': 'Difference in degrees'})
ax.coastlines(); ax.gridlines();
plt.title('Air temperature anomaly for 1997')
Text(0.5, 1.0, 'Air temperature anomaly for 1997')
#Precipitation
tp_avg=dc.tp.mean(dim='time')
tp_y=dc.tp.groupby('time.year').mean()
tp_an_88 = tp_y[9]-tp_avg
ax = plt.axes(projection=ccrs.Robinson())
tp_an_88.plot.imshow(ax=ax, transform=ccrs.PlateCarree(),vmin=-0.01, vmax=0.01, levels=7, cbar_kwargs={'label': 'Difference in mm'})
ax.coastlines(); ax.gridlines();
plt.title('Precipitation anomaly for 1988')
Text(0.5, 1.0, 'Precipitation anomaly for 1988')
tp_an_97 = tp_y[18]-tp_avg
ax = plt.axes(projection=ccrs.Robinson())
tp_an_97.plot.imshow(ax=ax, transform=ccrs.PlateCarree(),vmin=-0.01, vmax=0.01, levels=7, cbar_kwargs={'label': 'Difference in mm'})
ax.coastlines(); ax.gridlines();
plt.title('Precipitation anomaly for 1997')
Text(0.5, 1.0, 'Precipitation anomaly for 1997')
#SeaSurfaceTemp
de = xr.open_dataset('ERA5_LowRes_Monthly_sst.nc')
de
<xarray.Dataset> Dimensions: (longitude: 480, latitude: 241, time: 480) Coordinates: * longitude (longitude) float32 -179.6 -178.9 -178.1 ... 178.1 178.9 179.6 * latitude (latitude) float32 90.0 89.25 88.5 87.75 ... -88.5 -89.25 -90.0 * time (time) datetime64[ns] 1979-01-01 1979-02-01 ... 2018-12-01 Data variables: sst (time, latitude, longitude) float32 ... Attributes: Conventions: CF-1.6 history: 2019-12-08 20:53:30 GMT by grib_to_netcdf-2.14.0: /opt/ecmw...
sst_avg=de.sst.mean(dim='time')
ax = plt.axes(projection=ccrs.Robinson())
sst_avg.plot.imshow(ax=ax, transform=ccrs.PlateCarree(),cmap='RdBu_r', cbar_kwargs={'label': 'degrees K'})
ax.coastlines(); ax.gridlines();
plt.title('Sea-surface temperature average over time')
Text(0.5, 1.0, 'Sea-surface temperature average over time')
#SeaSurfaceTemp Anomalie 1988
sst_y=de.sst.groupby('time.year').mean()
sst_an_88=sst_y[9]-sst_avg
ax = plt.axes(projection=ccrs.Robinson())
sst_an_88.plot.imshow(ax=ax, transform=ccrs.PlateCarree(),vmin=-3, vmax=3, levels=7,cmap='RdBu_r', cbar_kwargs={'label': 'Difference in degrees'})
ax.coastlines(); ax.gridlines();
plt.title('Sea-surface temperature anomaly for 1988')
Text(0.5, 1.0, 'Sea-surface temperature anomaly for 1988')
#SeaSurfaceTemp Anomalie 1997
sst_an_97=sst_y[18]-sst_avg
ax = plt.axes(projection=ccrs.Robinson())
sst_an_97.plot.imshow(ax=ax, transform=ccrs.PlateCarree(),vmin=-3, vmax=3, levels=7,cmap='RdBu_r', cbar_kwargs={'label': 'Difference in degrees'})
ax.coastlines(); ax.gridlines();
plt.title('Sea-surface temperature anomaly for 1997')
Text(0.5, 1.0, 'Sea-surface temperature anomaly for 1997')
t_an_88_eu=t_an_88.sel(longitude=slice(-20, 40),latitude=slice(80,30))
t_an_97_eu=t_an_97.sel(longitude=slice(-20, 40),latitude=slice(80,30))
max = np.max(np.maximum(t_an_88_eu, t_an_97_eu))
min = np.min(np.minimum(t_an_88_eu, t_an_97_eu))
fig, (ax1, ax2) = plt.subplots(ncols=2, subplot_kw={'projection': ccrs.PlateCarree()})
t_an_88_eu.plot(ax=ax1, transform=ccrs.PlateCarree(), cmap='viridis', vmin=min, vmax=max, cbar_kwargs={'label': 'Temperature anomaly K'})
ax1.set_title('Temperature anomaly 1988')
ax1.add_feature(cfeature.BORDERS)
ax1.coastlines()
t_an_97_eu.plot(ax=ax2, transform=ccrs.PlateCarree(), cmap='viridis', vmin=min, vmax=max, cbar_kwargs={'label': 'Temperature anomaly K'})
ax2.set_title('Temperature anomaly 1997')
ax2.add_feature(cfeature.BORDERS)
ax2.coastlines()
plt.show()
tp_an_88_eu=tp_an_88.sel(longitude=slice(-20, 40),latitude=slice(80,30))
tp_an_97_eu=tp_an_97.sel(longitude=slice(-20, 40),latitude=slice(80,30))
max = np.max(np.maximum(tp_an_88_eu, tp_an_97_eu))
min = np.min(np.minimum(tp_an_88_eu, tp_an_97_eu))
fig, (ax1, ax2) = plt.subplots(ncols=2, subplot_kw={'projection': ccrs.PlateCarree()})
tp_an_88_eu.plot(ax=ax1, transform=ccrs.PlateCarree(), cmap='RdBu', vmin=min, vmax=max, cbar_kwargs={'label': 'percipitation anomaly mm'})
ax1.set_title('precipitation anomaly 1988')
ax1.add_feature(cfeature.BORDERS)
ax1.coastlines()
tp_an_97_eu.plot(ax=ax2, transform=ccrs.PlateCarree(), cmap='RdBu', vmin=min, vmax=max,cbar_kwargs={'label': 'percipitation anomaly mm'})
ax2.set_title('precipitation anomaly 1997')
ax2.add_feature(cfeature.BORDERS)
ax2.coastlines()
plt.show()
#snowcover
dg = xr.open_dataset('ERA5_LowRes_Monthly_snow.nc')
dg
<xarray.Dataset> Dimensions: (longitude: 480, latitude: 241, time: 480) Coordinates: * longitude (longitude) float32 -179.6 -178.9 -178.1 ... 178.1 178.9 179.6 * latitude (latitude) float32 90.0 89.25 88.5 87.75 ... -88.5 -89.25 -90.0 * time (time) datetime64[ns] 1979-01-01 1979-02-01 ... 2018-12-01 Data variables: rsn (time, latitude, longitude) float32 ... sd (time, latitude, longitude) float32 ... sf (time, latitude, longitude) float32 ... tsn (time, latitude, longitude) float32 ... Attributes: Conventions: CF-1.6 history: 2020-01-10 08:03:02 GMT by grib_to_netcdf-2.15.0: /opt/ecmw...
sf_avg=dg.sf.mean(dim='time')
sf_y=dg.sf.groupby('time.year').mean()
sf_an_88=sf_y[9]-sf_avg
sf_an_97=sf_y[18]-sf_avg
sf_an_88_eu=sf_an_88.sel(longitude=slice(-20, 40),latitude=slice(80,30))
sf_an_97_eu=sf_an_97.sel(longitude=slice(-20, 40),latitude=slice(80,30))
max = np.max(np.maximum(sf_an_88_eu, sf_an_97_eu))
min = np.min(np.minimum(sf_an_88_eu, sf_an_97_eu))
fig, (ax1, ax2) = plt.subplots(ncols=2, subplot_kw={'projection': ccrs.PlateCarree()})
sf_an_88_eu.plot(ax=ax1, transform=ccrs.PlateCarree(), cmap='RdBu', vmin=min, vmax=max, cbar_kwargs={'label': 'snowfall anomaly mm'})
ax1.set_title('Snowfall anomaly 1988')
ax1.add_feature(cfeature.BORDERS)
ax1.coastlines()
sf_an_97_eu.plot(ax=ax2, transform=ccrs.PlateCarree(), cmap='RdBu', vmin=min, vmax=max, cbar_kwargs={'label': 'snowfall anomaly mm'})
ax2.set_title('Snowfall anomaly 1997')
ax2.add_feature(cfeature.BORDERS)
ax2.coastlines()
plt.show()
Precipitation Anomaly description:
There was a decrease in precipitation over the arctic, parts of norway, and the mediteraenian in 1988; in 1997 however, there a stronger deficit over central europe as well as the mediteraenian region, but not in northern europe. The snowfall anomaly however was larger was more present in 1988 with a stronger deficit in the north; in 1997 the snowfall deficit mirrored the precipitation deficit, being present much more in central, with some new anomalies in the arctic.
On the global scale, we observe a strong anomaly deficit in 1997 a couple of degrees north from the equator in the pacific ocean, and in 1988 in the same spot there was a surge of precipitation.
These plots therefore correspond to the El Nino and El Nina years, since there was less precipitation deficit in 1997 which was El nino compared with the stronger deficit in the El Nina year of 1988.