Group project: the Climate System¶
Anna Buchhauser and Marie Kaucher
# 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 pandas as pd
# Some defaults:
plt.rcParams['figure.figsize'] = (12, 5) # Default plot size
Part 1 - temperature climatology¶
#read data
ds1= xr.open_dataset(r'ERA5_LowRes_Monthly_t2m.nc')
ds1
<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)
#The temporal mean temperature for the entire period (unit °C)
t2m_tavg = ds1.t2m.mean(dim='time')
t2mC_tavg=t2m_tavg-272.15 #changing in Celsius
ax = plt.axes(projection=ccrs.Robinson())
t2mC_tavg.plot(ax=ax, transform=ccrs.PlateCarree(), cmap='plasma', center=False,
vmin=-40, vmax=30, levels=30, cbar_kwargs={'label': '°C'})
ax.set_title('Average annual 2m air temperature for 1979 to 2018, ERA5')
ax.coastlines(); ax.gridlines();
- Compute and plot ¯T∗ (see lesson), the zonal anomaly map of average temperature.
#the zonal anomaly map of average temperature
# Meridional weights
weight = np.cos(np.deg2rad(ds1.latitude))
weight = weight / weight.sum()
# Meridionally weighted zonal mean to get right answers about anomalies
zonal_mean_t2m_c = ds1.t2m.mean(dim='longitude') - 273.15
weighted_zonal_mean_t2m_c = zonal_mean_t2m_c * weight
weighted_ts_t2m_c = weighted_zonal_mean_t2m_c.sum(dim='latitude')
t_avg_dep = t2m_tavg - t2m_tavg.mean(dim='longitude')
# Creating a plot
ax = plt.axes(projection=ccrs.Robinson())
t_avg_dep.plot(ax=ax, transform=ccrs.PlateCarree(), cmap='coolwarm', center=True,
cbar_kwargs={'label': 'anomaly in °C'})
ax.set_title('Zonal anomaly in average annual 2m air temperature for 1979 to 2018, ERA5')
ax.coastlines(); ax.gridlines();
- 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.
#the monthly average temperature for each month (annual cycle)
tavgerage_c=ds1.t2m.groupby('time.month').mean()- 273.15
tavgerage_range=tavgerage_c.max(dim='month')-tavgerage_c.min(dim='month')
tavgerage_range
<xarray.DataArray 't2m' (latitude: 241, longitude: 480)> array([[26.397247, 26.397247, 26.397247, ..., 26.397247, 26.397247, 26.397247], [26.618607, 26.62648 , 26.634842, ..., 26.610596, 26.611755, 26.613388], [26.734756, 26.73616 , 26.744843, ..., 26.73143 , 26.731567, 26.73317 ], ..., [24.638016, 24.648285, 24.642487, ..., 24.62149 , 24.620026, 24.628891], [26.135895, 26.140427, 26.14563 , ..., 26.15451 , 26.14328 , 26.134079], [26.673813, 26.673813, 26.673813, ..., 26.673813, 26.673813, 26.673813]], dtype=float32) 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
#plot temperature range
ax = plt.axes(projection=ccrs.Robinson())
tavgerage_range.plot(ax=ax, transform=ccrs.PlateCarree(), levels=60, cbar_kwargs={'label': 'Range of average air temperature in °C'})
ax.coastlines(); ax.gridlines();
plt.title('Average monthly temperature range, ERA5 1979-2018');
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:
- In the North Atlantic we have a ocean circulation called the gulf stream, that transports warmer air from the Caribbean to northern Europe. This is warming the surface level air and causes the temperature difference with North America or Russia, where there is no such effect. In the Northern Pacific on the other hand cold water is transported northwards as we can see in this picture:
(source: https://www.ces.fau.edu/nasa/resources/global-ocean-conveyor.php ) - The change in temperature over the year is caused by the tilt of the earths axis. Because of this the angle with witch sunlight hits the earth at a certain point changes over the year, causing different temperatures. This change is smallest in the equator region, what causes a daytime climate meaning, that the temperature changes more during a day, than over the year.
Water has a higher heat capacity than land. This means it takes more energy to encrease the temperature of water, but also that it is better in storing heat. Therefore it doesn't cool down or heat up as fast as land.
The temperature range is largest in northwestern Russia dew to its continental climate. This means that there are no larger water masses nearby, that can store the heat and therefore regulate the temperature, what causes the land surface to heat up/cool down more. Because of this there are very high temperatures in the summer and very low ones in the winter and therefore a large temperature range. Another effect that plays along are the cold winds coming from the poles, since there are no large mountain ranges in the north preventing this.
references: Lecture sildes, https://www.ruseducation.in/climate-in-russia/#
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.
ds2 = xr.open_dataset(r'ERA5_LowRes_Monthly_tp.nc')
ds2
<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'
#compute the average daily precipitation for each month of the year and calculate it in mmm per day
pre_avg_mon = ds2.tp.groupby('time.month').mean() * 1000
pre_avg_mon
<xarray.DataArray 'tp' (month: 12, latitude: 241, longitude: 480)> array([[[0.46101883, 0.46101883, 0.46101883, ..., 0.46101883, 0.46101883, 0.46101883], [0.43445352, 0.4340633 , 0.43381488, ..., 0.4358723 , 0.43530464, 0.43484366], [0.42448688, 0.4241676 , 0.4239195 , ..., 0.4255508 , 0.4248062 , 0.42477092], ..., [0.10928027, 0.11186972, 0.11350112, ..., 0.10282509, 0.10431492, 0.10683304], [0.14439403, 0.14549373, 0.14634468, ..., 0.14180495, 0.14290428, 0.14403927], [0.11853771, 0.11853771, 0.11853771, ..., 0.11853771, 0.11853771, 0.11853771]], [[0.39777923, 0.39777923, 0.39777923, ..., 0.39777923, 0.39777923, 0.39777923], [0.38057715, 0.38022232, 0.379832 , ..., 0.381393 , 0.38100296, 0.38057715], [0.37330613, 0.37319958, 0.37312898, ..., 0.37390924, 0.37351903, 0.37355432], ... [0.1421948 , 0.14528054, 0.14765728, ..., 0.13499466, 0.13666181, 0.13949908], [0.19483007, 0.19607171, 0.19720598, ..., 0.19117697, 0.19280845, 0.1942982 ], [0.15581465, 0.15581465, 0.15581465, ..., 0.15581465, 0.15581465, 0.15581465]], [[0.48095238, 0.48095238, 0.48095238, ..., 0.48095238, 0.48095238, 0.48095238], [0.46825466, 0.46811283, 0.46797088, ..., 0.46868047, 0.468574 , 0.4683611 ], [0.46048725, 0.46091294, 0.46116143, ..., 0.45928127, 0.4594232 , 0.4598489 ], ..., [0.095696 , 0.09814343, 0.10037785, ..., 0.08899234, 0.09065913, 0.09324849], [0.12272279, 0.12350287, 0.12428332, ..., 0.12038155, 0.12141028, 0.12233267], [0.09392229, 0.09392229, 0.09392229, ..., 0.09392229, 0.09392229, 0.09392229]]], dtype=float32) 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 * month (month) int64 1 2 3 4 5 6 7 8 9 10 11 12
#plot average daily precipitation january
#select january
pre_avg_jan = pre_avg_mon.sel(month=1)
# Creating a plot for January
ax = plt.axes(projection=ccrs.Robinson())
pre_avg_jan.plot(ax=ax, transform=ccrs.PlateCarree(), cmap='YlGnBu', center=True, levels=[0.5, 1, 2, 3, 4, 5, 7, 10, 15, 20, 40],
cbar_kwargs={'label': 'Precipitation in mm'})
ax.set_title('Average precipitation in January, 1979 to 2018, ERA5')
ax.coastlines(); ax.gridlines();
#plot average daily precipitation February for the Question, I am not sur if it is a mistake in the task
#select february
pre_avg_jan = pre_avg_mon.sel(month=2)
# Creating a plot for February
ax = plt.axes(projection=ccrs.Robinson())
pre_avg_jan.plot(ax=ax, transform=ccrs.PlateCarree(), cmap='YlGnBu', center=True, levels=[0.5, 1, 2, 3, 4, 5, 7, 10, 15, 20, 40],
cbar_kwargs={'label': 'Precipitation in mm'})
ax.set_title('Average precipitation in February, 1979 to 2018, ERA5')
ax.coastlines(); ax.gridlines();
#plot average daily precipitation August
#select August
pre_avg_aug = pre_avg_mon.sel(month=8)
# Creating a plot for January
ax = plt.axes(projection=ccrs.Robinson())
pre_avg_aug.plot(ax=ax, transform=ccrs.PlateCarree(), cmap='YlGnBu', center=True, levels=[0.5, 1, 2, 3, 4, 5, 7, 10, 15, 20, 40],
cbar_kwargs={'label': 'Precipitation in mm'})
ax.set_title('Average precipitation in August, 1979 to 2018, ERA5')
ax.coastlines(); ax.gridlines();
Questions:¶
Describe the location of the ITCZ in January and February. Without going into the details, explain (in one or two sentences)¶
The location of the Innertropical Convergence Zone is in January and in February (I am not sur if this is a writing mistake in the task) is a line following a few latitutes over North South-America (app. Guyana), middle to south of Africa (app. above the Kongo Becken) and the islands around Sumatra and Indonesia. In North Hemisphere Summer the zone is higher in the North over the Caribic, Sahel, India and Bangladesh.
Describe the precipitation seasonality in West Africa and in India. Name the phenomenon at play.¶
In India is in summer time extreme high values of precipitation while there is nearly no precipitation through Northern Hemispheric winter. In West Africa we have a similar pattern north of the Gulf of Gunniea (precipitation in summer and nearly no precipiation in winter). The phenomen is called Monsun Precipiation, depending on the annual circle winds (Passat winds) over the Gulf of Guinea, Gulf of Bangladesh and Indic Ocean.
references:
- class slides of annuale climate patterns
- good short explanation: https://www.eskp.de/grundlagen/klimawandel/monsun-935719/ (29.12.2023, 9:03)
Part 3: sea-level pressure and surface winds¶
Open the file containing the surface winds (u10
and v10
) and sea-level pressure (msl
).
ds3 = xr.open_dataset(r'ERA5_LowRes_Monthly_uvslp.nc')
ds3
<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).
# temporal and zonal average of sea-level pressure
#compute average
msl_avg = ds3.msl.mean(dim=['time','longitude'])
slp = msl_avg / 100 #convert to hpa
std_p = 1013.25 #standard atmosphere pressure
#create plot
slp.plot(label='sea-level pressure')
plt.axhline(std_p, color='black', label='standard atmosphere pressure')
plt.legend()
plt.ylabel('sea-level pressure [hpa]')
plt.title('temporal and zonal average of sea-level pressure, ERA5 1979-2018');
# temporal and zonal average of U wind component
#compute average
u10_avg = ds3.u10.mean(dim=['time','longitude'])
#create plot
u10_avg.plot(label='10 meter u wind component')
plt.axhline(0, color='black', label='horizontal line')
plt.legend()
plt.ylabel('wind speed [m/s]')
plt.title('temporal and zonal average of 10 meter u wind component, ERA5 1979-2018');
# temporal and zonal average of v wind component
#compute average
v10_avg = ds3.v10.mean(dim=['time','longitude'])
#create plot
v10_avg.plot(label='10 meter v wind component')
plt.axhline(0, color='black', label='horizontal line')
plt.legend()
plt.ylabel('wind speed [m/s]')
plt.title('temporal and zonal average of 10 meter v wind component, ERA5 1979-2018');
# temporal and zonal average of v and u wind component in one plot
#create plot
u10_avg.plot(label='10 meter u wind component', color='green')
v10_avg.plot(label='10 meter v wind component')
plt.axhline(0, color='black', label='horizontal line')
plt.legend()
plt.ylabel('wind speed [m/s]')
plt.title('temporal and zonal average of 10 meter u and v wind component, ERA5 1979-2018');
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:
- Around 0°, the equator region, we can see that the pressure is lower than the atmosoheric standard pressure. This is because of the inner tropical convergence zone (ITCZ). Here the passsat winds, that are coming from south and north, converge and create a low pressure belt. This is part of the Hadley cell.
At 30° N/S a high pressure band is located, it is called the subtropical high caused by north and south diverging winds. While the winds blowing towards the equator are part of the Hadley Cell, the airmasses going polewards form the Ferrel Cell, a atmospheric circulation cell driven by friction. Dew to the coriolis force the winds are deflected and from the strong westerlies, that are characteristic for the northern hemisphere mid latitudes.
At around 60° N/S the warmer air hits the cold polar air and rises again forming the subpolar low. As we can see clearly in the plot, the mean latitudinal pressure is way lower than on the northern hemisphere. This is caused by the different land-sea distribution. While there is almost only ocean at this latitude in the southern hemisphere, what makes it possible for a continuous trough that completely encircles the globe, to form, on the northern hemisphere landsurface disrupts the atmospheric circulations and only regional lows are abel to form, for example the Icelandic low over the North Atlantic.
The last and weakest of the cells is the polar cell. Here some of the air, that rises at the subpolar low pressure belt, travels northwards (on the NH) and sinks down over the poles creating the polar high, which we can see in the plot mostly at the north pole.
The following picture shows the global circulations with all three cells. (source: https://www.britannica.com/science/atmospheric-circulation )
2. The u component of the wind shows the wind speed in the east-west direction and is positive towards the east. In the plot we can see that from ca. -25° to 25° we have easterlies, which are weakest at the equator. Looking at the v-component, wich is positive towards the north, we can see that on the southern hemisphere the wind is going towards the north and an the northern hemisphere towards the south. This causes wind from the NE on the NH and from the SE on the SH, called trade winds that blow towards the low pressure belt at the equator, but are deflected due to coriolis force.
In the mid latitudes, the Ferrel cell, we can see the winds are blowing polewards, where at 60° N/S the subpolar low is located, as we know from the pressure plot. They are again deflected by the coriolis force (to the right on the NH to the left on the SH) causing strong westerlies. But we can see that on the SH the windspeeds are higher, since there is not as much land mass that slows the wind down due to higher friction.
In the polar cell we again have wind blowing towards the subpolar low and away from the poles, which results due to the deflection in easterlies on both hemispheres. But again on the NH the wind is significantly slowed dwon by the land surface.
references: https://www.noaa.gov/jetstream/global/global-atmospheric-circulations, lecture slides, Atmospheric Science - An Introductory Survey (Wallace & Hobbs)
Part 4: temperature change and CO concentrations<¶
ds4 = pd.read_csv('co2_mm_gl.csv', skiprows=55, parse_dates={'date' : [0, 1]}, index_col='date')
ds4=ds4.set_axis(["decimal","average","average_unc","trend","trend_unc"], axis='columns')
ds4
--------------------------------------------------------------------------- FileNotFoundError Traceback (most recent call last) Cell In[6], line 1 ----> 1 ds4 = pd.read_csv('co2_mm_gl.csv', skiprows=55, parse_dates={'date' : [0, 1]}, index_col='date') 2 ds4=ds4.set_axis(["decimal","average","average_unc","trend","trend_unc"], axis='columns') 3 ds4 File ~\miniforge3\envs\climate\lib\site-packages\pandas\io\parsers\readers.py:948, in read_csv(filepath_or_buffer, sep, delimiter, header, names, index_col, usecols, dtype, engine, converters, true_values, false_values, skipinitialspace, skiprows, skipfooter, nrows, na_values, keep_default_na, na_filter, verbose, skip_blank_lines, parse_dates, infer_datetime_format, keep_date_col, date_parser, date_format, dayfirst, cache_dates, iterator, chunksize, compression, thousands, decimal, lineterminator, quotechar, quoting, doublequote, escapechar, comment, encoding, encoding_errors, dialect, on_bad_lines, delim_whitespace, low_memory, memory_map, float_precision, storage_options, dtype_backend) 935 kwds_defaults = _refine_defaults_read( 936 dialect, 937 delimiter, (...) 944 dtype_backend=dtype_backend, 945 ) 946 kwds.update(kwds_defaults) --> 948 return _read(filepath_or_buffer, kwds) File ~\miniforge3\envs\climate\lib\site-packages\pandas\io\parsers\readers.py:611, in _read(filepath_or_buffer, kwds) 608 _validate_names(kwds.get("names", None)) 610 # Create the parser. --> 611 parser = TextFileReader(filepath_or_buffer, **kwds) 613 if chunksize or iterator: 614 return parser File ~\miniforge3\envs\climate\lib\site-packages\pandas\io\parsers\readers.py:1448, in TextFileReader.__init__(self, f, engine, **kwds) 1445 self.options["has_index_names"] = kwds["has_index_names"] 1447 self.handles: IOHandles | None = None -> 1448 self._engine = self._make_engine(f, self.engine) File ~\miniforge3\envs\climate\lib\site-packages\pandas\io\parsers\readers.py:1705, in TextFileReader._make_engine(self, f, engine) 1703 if "b" not in mode: 1704 mode += "b" -> 1705 self.handles = get_handle( 1706 f, 1707 mode, 1708 encoding=self.options.get("encoding", None), 1709 compression=self.options.get("compression", None), 1710 memory_map=self.options.get("memory_map", False), 1711 is_text=is_text, 1712 errors=self.options.get("encoding_errors", "strict"), 1713 storage_options=self.options.get("storage_options", None), 1714 ) 1715 assert self.handles is not None 1716 f = self.handles.handle File ~\miniforge3\envs\climate\lib\site-packages\pandas\io\common.py:863, in get_handle(path_or_buf, mode, encoding, compression, memory_map, is_text, errors, storage_options) 858 elif isinstance(handle, str): 859 # Check whether the filename is to be opened in binary mode. 860 # Binary mode does not support 'encoding' and 'newline'. 861 if ioargs.encoding and "b" not in ioargs.mode: 862 # Encoding --> 863 handle = open( 864 handle, 865 ioargs.mode, 866 encoding=ioargs.encoding, 867 errors=errors, 868 newline="", 869 ) 870 else: 871 # Binary mode 872 handle = open(handle, ioargs.mode) FileNotFoundError: [Errno 2] No such file or directory: 'co2_mm_gl.csv'
Prepare three plots:
- plot the monthly global CO2 concentration as a function of time.
co2_monthy_av=ds4.resample('M').mean()
# plot the monthly global CO2 oncentration as a function of time.
co2_monthy_av.average.plot(label='CO2 concentration 1980-2018')
plt.legend()
plt.ylabel('Co2 in ppm')
plt.title('Monthly average in global CO$_2$ concentration, ERA5 1979-2018');
- plot the annual average timeseries of global CO2 concentration as a function of time.
#plot the annual average timeseries of global CO2 concentration as a function of time.
co2_year_av=ds4.resample('Y').mean()
# plot the monthly global CO2 oncentration as a function of time.
co2_year_av.average.plot(label='CO2 concentration 1980-2018')
plt.legend()
plt.ylabel('Co2 in ppm')
plt.title('Annual avearge in global CO$_2$ concentration, ERA5 1979-2018');
- 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).
# Define Data
x = np.arange(1979,2018,40)
co2_year_av=ds4.resample('Y').mean()
ds1year=ds1.groupby('time.year').mean()
# Meridionally weighted and zonal weighted
weight = np.cos(np.deg2rad(ds1year.latitude))
weight = weight / weight.sum()
# Meridionally weighted zonal mean
zonal_mean_t2_c =ds1year.t2m.mean(dim='longitude') - 273.15 # convert into Celsius
weighted_zonal_mean_t2_c = zonal_mean_t2_c * weight
weighted_ts_t2_c = weighted_zonal_mean_t2_c.sum(dim='latitude')
# Create Plot
fig, ax1 = plt.subplots()
weighted_ts_t2_c.plot(label="global yearly average air temperature")
ax1.plot(ds1year.year, weighted_ts_t2_c,label="global yearly average air temperature")
ax1.set_ylabel('global 2m temperature °C', color = 'red')
# Adding Twin Axes
ax2 = ax1.twinx()
ax2.plot(co2_year_av.decimal, co2_year_av.average,label="CO2 concentration 1980-2018")
ax2.set_ylabel('CO2 Concentration in ppm', color = 'blue')
# Show plot
plt.show
plt.title('Annual avearge in global CO$_2$ concentration and air temperature, ERA5 1979-2018');
#Compute the annual increase in COconcentration (unit: ppm per year) between 1980 and 1985 and between 2016 and 2021
eightties_increase=(345.537500-338.444286)/5
twenties_increase=(414.703333-397.345000)/5
print(eightties_increase,twenties_increase)
1.418642800000009 3.471666599999992
Questions:¶
Describe and explain the annual cycle of CO concentrations¶
The concentration of CO2 have higher values in the spring. (Easier to see on a plot for one year: https://gml.noaa.gov/ccgg/trends/weekly.html 29.12.23) and lower values in the autuum/winter. However, the values in November, December are higher than in January through the general increasing.
In winter plants in Northern hemisphere are less photosynthetic active, less CO2 is used for it and more CO2 stays in Atmosphere. That is why, the values are the highest their and the lowest after the season of strong photosynthesis.
refernces: https://www.mpg.de/9862783/kohlendioxid-schwankung-vegetation-erderwaermung (29.12.2023,11:30)
What was the CO concentration in the atmosphere in the pre-industrial era? Compute the annual increase in COconcentration (unit: ppm per year) between 1980 and 1985 and between 2016 and 2021.¶
The pre-industrial niveau is refering to the NASA Observation 278ppm
(reference: https://svs.gsfc.nasa.gov/4962).
1980 to 1985: from 338.444ppm to 345.538ppm: an annual increase of 1.419ppm per year
2016 to 2021: from 397.345ppm to 414.703ppm: an annual incrase of 3.472ppm per year
Describe the relationship between global temperatures and CO concentrations. Beside CO, name three processes that can influence temperature variability and change at the global scale.¶
The global temperature raise is parallel to increasing CO2 consentration in the atmosphere, which is logical due to the fact the Concentration of CO2 is forcing global warming.
Other drivers of the climate systems are:
on the one hand external forces...
- concentration of greenhouse gases in the atmosphere (in addition to CO2, methane and water vapor)
- orbital variations (Milankovitch circle)
- variations in sun constant
on the other hand internal forces...
- strength of internal circulation as for example Ocean circulation
- big changings in biosphere
- vulcanos
The third factor which is mainly responsible for the increasing Co2 is anthropogenic emission.
(reference lecture "Driver of the climate system")
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.
#opening the missing data
ds5=xr.open_dataset(r'ERA5_LowRes_Monthly_sst.nc')
#ds2 is the precipiation
#ds1 the air temperature
ds5
<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...
El Nino years in our time period have been: 1980, 1983, 1987, 1988, 1992, 1995, 1998, 2003, 2007, 2010, 2016
La Nina yaers in our time period: 1989, 1999, 2000, 2008, 2011, 2012, 2021, 2022
neutral years:1975, 1977, 1979, 1981-1982, 1984-1986, 1990-1991, 1993-1994, 1996-1997, 2001-2002, 2004, 2006, 2009, 2013-2015, 2017-2020
(source: https://psl.noaa.gov/enso/past_events.html)
We picked 1999 for a La Nina event and 1997 for El Nino due the fact both where strong anomalies and very close together so there is no big differnce in the measurments through other factors like global warming.
Here an index is used to calculate the strongest El Nino years:
https://psl.noaa.gov/enso/climaterisks/years/top24enso.html (29.12.23)
https://ggweather.com/enso/oni.htm (29.12.23)
Additionally we use 2001 as a neutral year, to make anomaly plots for only one case.
# picking two periods in time
# computing the sea surface temperature
nino_seatemp = ds5.isel(time=(ds5.time.dt.year == 1997))
nina_seatemp = ds5.isel(time=(ds5.time.dt.year == 1999))
neutral_seatemp = ds5.isel(time=(ds5.time.dt.year == 2001))
# computing the precipiation
nino_pre = ds2.isel(time=(ds2.time.dt.year == 1997))
nina_pre = ds2.isel(time=(ds2.time.dt.year == 1999))
neutral_pre = ds2.isel(time=(ds2.time.dt.year == 2001))
# computing the temperature
nino_temp = ds1.isel(time=(ds1.time.dt.year == 1997))
nina_temp = ds1.isel(time=(ds1.time.dt.year == 1999))
neutral_temp = ds1.isel(time=(ds1.time.dt.year == 2001))
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).
#sea-surface temperature
# calculating the anomaly
nino_av_sea = nino_seatemp.mean(dim='time')
nina_av_sea = nina_seatemp.mean(dim='time')
neutral_av_sea=neutral_seatemp.mean(dim='time')
seatemp_anomal = nino_av_sea - nina_av_sea
seatemp_anomal_nino=nino_av_sea - neutral_av_sea
seatemp_anomal_nina=nina_av_sea - neutral_av_sea
# creating a plot
ax = plt.axes(projection=ccrs.Robinson(central_longitude=180.0))
seatemp_anomal.sst.plot(ax=ax, transform=ccrs.PlateCarree(), cmap='coolwarm', center=True, vmin=-4, vmax=5, levels=30,
cbar_kwargs={'label': 'anomaly in °C'})
ax.set_title('Zonal anomaly in average annual 2m air temperature El Nino with La Nina, ERA5')
ax.coastlines(); ax.gridlines();
# creating a plot
ax = plt.axes(projection=ccrs.Robinson(central_longitude=180.0))
seatemp_anomal_nino.sst.plot(ax=ax, transform=ccrs.PlateCarree(), cmap='coolwarm', center=True, vmin=-4, vmax=5, levels=10,
cbar_kwargs={'label': 'anomaly in °C'})
ax.set_title('Zonal anomaly in average annual 2m air temperature El Nino compared to a neutral year, ERA5')
ax.coastlines(); ax.gridlines();
# creating a plot for la Nina
ax = plt.axes(projection=ccrs.Robinson(central_longitude=180.0))
seatemp_anomal_nina.sst.plot(ax=ax, transform=ccrs.PlateCarree(), cmap='coolwarm', center=True,vmin=-4, vmax=4, levels=10,
cbar_kwargs={'label': 'anomaly in °C'})
ax.set_title('Zonal anomaly in average annual 2m air temperature La Nina compared to a neutral year, ERA5')
ax.coastlines(); ax.gridlines();
During a "normal" year sea-level pressure is higher on the eastern side of the pacific than on the western side resulting in easterly trade winds. But during an El Nino event the sea-level pressure at the western side (Indonesia, Australia) is higher than normal. This causes a weakening in the pressure gradient and therefore a weakening of the easterly winds. (reference: Introductry Survey)
Pattern in the sea-surface temperature
El Nino: warmer sea temperature in the west of South America
La Nina:low temperature values in the west of South America
These patterns can be explained with the situation above. Weaker trade winds cause a reduced upwelling in the equatorial region. The correlation between upwelling and the trade winds is explained here: https://glossary.ametsoc.org/wiki/Equatorial_upwelling
Since we have less cold water from deeper layers the sea surface temperature rises.
During a La Nina event, the opposite is the case. The pressure gradient over the pacific ocean is stronger than normal causing stronger surface winds, stronger upwelling and therefore colder sea-surface temperatures.
#precipiation
# calculating the anomaly
nino_av_pre = nino_pre.mean(dim='time')*1000
nina_av_pre = nina_pre.mean(dim='time')*1000
neutral_av_pre=neutral_pre.mean(dim='time')*1000
pre_anomal = nino_av_pre - nina_av_pre
pre_anomal_nino= nino_av_pre-neutral_av_pre
pre_anomal_nina=nina_av_pre-neutral_av_pre
#precipiation
# creating a plot
ax = plt.axes(projection=ccrs.Robinson(central_longitude=180.0))
pre_anomal.tp.plot(ax=ax, transform=ccrs.PlateCarree(), cmap='RdBu', center=True, vmin=-10, vmax=10, levels=30,
cbar_kwargs={'label': 'anomaly in mm'})
ax.set_title('Zonal anomaly in precipitation El Nino with La Nina, ERA5')
ax.coastlines(); ax.gridlines();
# creating a plot El Nino
ax = plt.axes(projection=ccrs.Robinson(central_longitude=180.0))
pre_anomal_nino.tp.plot(ax=ax, transform=ccrs.PlateCarree(), cmap='RdBu', center=True, vmin=-10, vmax=10, levels=30,
cbar_kwargs={'label': 'anomaly in mm'})
ax.set_title('Zonal anomaly in precipitation El Nino compared to a neutral year, ERA5')
ax.coastlines(); ax.gridlines();
# creating a plot La Nina
ax = plt.axes(projection=ccrs.Robinson(central_longitude=180.0))
pre_anomal_nina.tp.plot(ax=ax, transform=ccrs.PlateCarree(), cmap='RdBu', center=True, vmin=-10, vmax=10, levels=30,
cbar_kwargs={'label': 'anomaly in mm'})
ax.set_title('Zonal anomaly in precipitation La Nina compared to a neutral year, ERA5')
ax.coastlines(); ax.gridlines();
Pattern in the precipitation:
El Nino: precipiation more in the east of the pacific, droughts in the west
La Nina: precipiation more in west, often droughts in the South of the US, high precipiation in Australia and Indonesia
During an El Nino event we have an eastwards shift in the warm pool as explained above this means we have more condesation in these regions resulting in more precipitation.
#air temperature
# calculating the anomaly
nino_av_air = nino_temp.mean(dim='time')
nina_av_air = nina_temp.mean(dim='time')
neutral_av_air = neutral_temp.mean(dim='time')
#anomalies
t_air_anomal = nino_av_air - nina_av_air
t_air_anomal_nino = nino_av_air - neutral_av_air
t_air_anomal_nina = nina_av_air - neutral_av_air
# creating a plot
ax = plt.axes(projection=ccrs.Robinson(central_longitude=180.0))
t_air_anomal.t2m.plot(ax=ax, transform=ccrs.PlateCarree(), cmap='coolwarm', center=True,vmin=-10, vmax=10, levels=10,
cbar_kwargs={'label': 'anomaly in °C'})
ax.set_title('Zonal anomaly in average annual 2m air temperature El Nino with La Nina, ERA5')
ax.coastlines(); ax.gridlines();
# creating a plot
ax = plt.axes(projection=ccrs.Robinson(central_longitude=180.0))
t_air_anomal_nino.t2m.plot(ax=ax, transform=ccrs.PlateCarree(), cmap='coolwarm', center=True,vmin=-5, vmax=5, levels=10,
cbar_kwargs={'label': 'anomaly in °C'})
ax.set_title('Zonal anomaly in average annual 2m air temperature El Nino compared with a neutral year, ERA5')
ax.coastlines(); ax.gridlines();
# creating a plot
ax = plt.axes(projection=ccrs.Robinson(central_longitude=180.0))
t_air_anomal_nina.t2m.plot(ax=ax, transform=ccrs.PlateCarree(), cmap='coolwarm', center=True,vmin=-10, vmax=10, levels=10,
cbar_kwargs={'label': 'anomaly in °C'})
ax.set_title('Zonal anomaly in average annual 2m air temperature El Nina compared with a neutral year, ERA5')
ax.coastlines(); ax.gridlines();
Pattern in air temperature:
We can see some resamblance between the air temperature and the sea-surface temperature anomalies. For example do we have higher temperatures west of south africa during the El Nino event just like in the plot for the sea-surface temperature. This is only normal since the sea-surface and air temperature are connected closely.
The picture shows the schematic pattern of El Nino and La Nina events: