Group project: the Climate System¶
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 12 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 my 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. I 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
I 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)
1 2 3 4 5 6 7 8 9 | # 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 # Some defaults: plt.rcParams['figure.figsize'] = (12, 5) # Default plot size |
Part 1 - temperature climatology¶
Open the ERA5 temperature data:
1 | dt = xr.open_dataset('data/ERA5_LowRes_Monthly_t2m.nc') |
Plot three global maps:
- Compute and plot the temporal mean temperature $\overline{T}$ for the entire period (unit °C)
- Compute and plot $\overline{T^{*}}$ (see lesson), the zonal anomaly map of average temperature.
- Compute the monthly average temperature for each month $\overline{T_M}$ (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. $\overline{T_M}max$ - $\overline{T_M}min$ on a map.
Plot 1:
- Compute and plot the temporal mean temperature $\overline{T}$ for the entire period (unit °C)
1 2 3 4 5 6 7 | t2_tavg = dt.t2m.mean(dim='time') #mean temperature in Celsius t2c_tavg = t2_tavg-273.15 ax = plt.axes(projection=ccrs.Robinson()) t2c_tavg.plot(ax=ax, transform=ccrs.PlateCarree(), cbar_kwargs={'label': '°C'}); ax.coastlines() ax.gridlines() ax.set_title('Average 2m air temperature, ERA5 1979-2018') |
Text(0.5, 1.0, 'Average 2m air temperature, ERA5 1979-2018')
Plot 2:
- Compute and plot $\overline{T^{*}}$ (see lesson), the zonal anomaly map of average temperature. (zonal anomaly of the temporal mean of the temperature field)
1 2 3 4 5 6 7 8 9 10 | #Computing Zonal mean t2c_lon = t2c_tavg.mean(dim = 'longitude') #zonal mean t2m t2_anomaly = t2c_tavg- t2c_lon # mean at gridpoint- zonal mean #------------------------------------------------------------------------- #plot ax = plt.axes(projection=ccrs.Robinson()) t2_anomaly.plot(ax=ax, transform=ccrs.PlateCarree(), cbar_kwargs={'label': '°C'}, vmin=-32, vmax=20, cmap = 'jet'); #changed limits so one can better see the max/min cause we only are intereseted into the qualitaive ax.coastlines() ax.gridlines() ax.set_title('Anomaly of 2m air temperature from zonal mean , ERA5 1979-2018') |
Text(0.5, 1.0, 'Anomaly of 2m air temperature from zonal mean , ERA5 1979-2018')
Plot 3: $\newline$
Compute the monthly average temperature for each month $\overline{T_M}$ (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. $\overline{T_M}max$ - $\overline{T_M}min$ on a map.
1 2 3 4 5 6 7 8 9 10 | #compute mean yearly cycle t2m_mavg = dt.t2m.groupby('time.month').mean() #------------------------------------------------------------------------- # #plot t2m_yrange= t2m_mavg.max(dim = 'month')-t2m_mavg.min(dim = 'month') ax = plt.axes(projection=ccrs.Robinson()) t2m_yrange.plot(ax=ax, transform=ccrs.PlateCarree(), cmap = 'viridis'); #changed limits so one can better see the max/min cause we only are intereseted into the qualitaive ax.coastlines() ax.gridlines() ax.set_title('$\overline{T_M}max$ - $\overline{T_M}min$ , ERA5 1979-2018') |
Text(0.5, 1.0, '$\\overline{T_M}max$ - $\\overline{T_M}min$ , 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. $\newline$ It is warmer because of the gulf stream and the north atlantic drift. This brings warm water from the gulf of mexico to the cost of western Europe. $\newline$
- Explain why the Northern Pacific Ocean does not have a similar pattern.
Source: 01_ClimateSystems_ComponentsProcesses $\newline$ 2. Look at the average monthly temperature range map. $\newline$ - Explain why the temperature range is smaller in the tropics than at higher latitudes $\newline$ The temperature range in the tropics is smaller than at higher latitudes because the tropics receive more direct solar radiation throughout the year.. This results in a more constant temperature and little to none variation between summer and winter. At higher latitudes there is less direct solar radiation and therefore greater temperature range. $\newline$ - Explain why the temperature range is smaller over oceans than over land?$\newline$ The temperature range is smaller because water has a high heat capacity and therefore the see-surface temperature is not changing as much as the land surface temperature, when there is a change in the solar imput. And because the air temperature at 2m is almost the same as the sea surface temperature the range is smaller over oceans. $\newline$ - Where is the temperature range largest? Explain why. $\newline$ The biggest difference is in eastern russia. There is a strong continetal climate. Key facts for the great difference are that there is land mass (im comparrison to SH) and no sea which could keeep the temperature less variable as well as the big differnce in solar heating.
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.
1 | dp = xr.open_dataset('data/ERA5_LowRes_Monthly_tp.nc') |
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: \newline
- Describe the location of the ITCZ in January and February. Without going into the details, explain (in one or two sentences)
- close to equator or a bit south in Jannuary and February
- shiftet to the north in August
- due to the location of the highest solar radiation (N in summer, S in winter)
- Describe the precipitation seasonality in West Africa and in India. Name the phenomenon at play.
- it is called Monsun and results from the shift of the ITC as well as the Temperture differnce of land mass and see.
source: https://www.dwd.de/DE/service/lexikon/Functions/glossar.html?nn=103346&lv2=101640&lv3=101800
1 2 | dp_avg_month = dp.tp.groupby('time.month').mean() dp_avg_mm = dp_avg_month*1000 #convert to mm |
1 2 3 4 5 6 7 | #Plot ax = plt.axes(projection=ccrs.Robinson()) dp_avg_mm_jan = dp_avg_mm.sel(month= 1) dp_avg_mm_jan.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/day'}); ax.coastlines() ax.gridlines() ax.set_title('Mean daily precepitaion in January , ERA5 1979-2018') |
Text(0.5, 1.0, 'Mean daily precepitaion in January , ERA5 1979-2018')
1 2 3 4 5 6 7 | #plot for Qeustion (February) ax = plt.axes(projection=ccrs.Robinson()) dp_avg_mm_jan = dp_avg_mm.sel(month= 2) dp_avg_mm_jan.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/day'}); ax.coastlines() ax.gridlines() ax.set_title('Mean daily precepitaion in February , ERA5 1979-2018') |
Text(0.5, 1.0, 'Mean daily precepitaion in February , ERA5 1979-2018')
1 2 3 4 5 6 7 | #August ax = plt.axes(projection=ccrs.Robinson()) dp_avg_mm_aug = dp_avg_mm.sel(month= 8) dp_avg_mm_aug.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/day'}); ax.coastlines() ax.gridlines() ax.set_title('Mean daily precepitaion in August , ERA5 1979-2018') |
Text(0.5, 1.0, 'Mean daily precepitaion in August , ERA5 1979-2018')
Part 3: sea-level pressure and surface winds¶
Open the file containing the surface winds (u10
and v10
) and sea-level pressure (msl
).
1 | dv = xr.open_dataset('data/ERA5_LowRes_Monthly_uvslp.nc') |
Compute $\left[ \overline{SLP} \right]$ (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 $\left[ \overline{u_{10}} \right]$ and $\left[ \overline{v_{10}} \right]$ (in m s$^{-1}$) and add the 0 horizontal line to the plot (to detect surface westerlies from easterlies for example).
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)
Questions:
1. 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.
The low at the equator is due to the rising air of the hadley cells and the rising air of the ferell and polar cells cause the lows at 60° north and south, respectively.
Similarly, the sinking air of the hadley and ferell cells cause the highs at 30° north and south, repectively, and the highs at the poles are due to the sinking air of the polar cells.
2. Similarly, explain the direction and strength of the zonal and meridional winds on earth (tip: the sea-level pressure plot helps)
The meridional winds are caused by the low and high pressure systems of question 1. They occure because the air masses are transported from the highs to the lows to compensate the pressure differences. That is why we have a positiv (v) wind component in the southern poral and hadley cell and in the northern ferell cell. Similarly we have negative (v) wind component in the sothern ferell cell and in the northern hadley and polar cell.
The zonal winds (u) are caused by the meridional winds and the coriolis force. The coriolis force deflects the meridional winds to the right on the northern hemisphere and to the left on the southern hemisphere. Thus we have west winds in the ferell cells and east winds in the polar and hadley cells.
The strenght of the winds in the southern hemisphere are higher due to the higher pressure differences compared to the northern hemisphere.
1 2 3 4 5 | SLP_temp_zonal = dv.msl.mean(dim='time').mean(dim='longitude')/100 SLP_temp_zonal.plot() plt.axhline(y=1013.15, color='g') plt.ylabel('Mean Sea Level Pressure [hPa]') plt.title('Temporal zonal average of mean sea level pressure'); |
1 2 3 4 5 | u10_temp_zonal = dv.u10.mean(dim='time').mean(dim='longitude') u10_temp_zonal.plot() plt.axhline(y=0, color='g') plt.ylabel('wind speed [m/s]') plt.title('Temporal Zonal average of (u) wind speed'); |
1 2 3 4 5 | v10_temp_zonal = dv.v10.mean(dim='time').mean(dim='longitude') v10_temp_zonal.plot() plt.axhline(y=0, color='g') plt.ylabel('wind speed [m/s]') plt.title('Temporal Zonal average of (v) wind speed'); |
Part 4: temperature change and CO$_2$ concentrations¶
Download the global average CO$_2$ concentration timeseries data in the CSV format (source: NOAA). Here, let me help your read them using pandas:
1 | df = pd.read_csv('data/co2_mm_gl.csv', skiprows=55, parse_dates={'date' : [0, 1]}, index_col='date') |
Prepare three plots:
- plot the monthly global CO$_2$ concentration as a function of time.
- plot the annual average timeseries of global CO$_2$ concentration as a function of time.
- plot the annual average timeseries of global CO$_2$ concentration and of global 2m temperature from ERA5 on the same plot (using a secondary y axis for temperature).
Questions:
- Describe and explain the annual cycle of CO$_2$ concentrations
- What was the CO$_2$ concentration in the atmosphere in the pre-industrial era? Compute the annual increase in CO$_2$ concentration (unit: ppm per year) between 1980 and 1985 and between 2016 and 2021.
- Describe the relationship between global temperatures and CO$_2$ concentrations. Beside CO$_2$, name three processes that can influence temperature variability and change at the global scale.
1.
Due to photosynthesis and respiration, plants cause the concentration of CO$_2$ to fall during spring and summer. In fall and winter they release some of the CO$_2$ to the atmosphere which leads to an increase of the CO$_2$ concentration.
2.
As we calculated in the next cell, we can see that the annual increase in CO$_2$ concentration is increasing aswell.
annual increase in CO2 concentration (1980-1985): 1.1043 ppm/year
annual increase in CO2 concentration (2016-2021): 1.9414 ppm/year
3. Eventhough the global temperature has some fluctuations, we can clealy see that the CO$_2$ concentration and the global temperature are both rising. This relationship can be explained by the greenhouse effect which says that the infrared radiation emitted by the earth, gets reflected by the greenhouse gases in the atmosphere causing a temperature rise.
Beside CO$_2$, there are some other processes that can influence temperature variability. Variations in solar activity, changes in the earth's orbit and rotation and changes in earth's reflectivity are examples for that.
1 | df.average.plot(title = 'average timeseries of global $CO_2$ ', ylabel = '$CO_2$ in ppm', xlabel = 'time', legend = True); |
1 2 | anual_avg_co2 = df.average.resample("y").mean() anual_avg_co2.plot(title = 'annual average timeseries of global $CO_2$ ', ylabel = '$CO_2$ in ppm', xlabel = 'year'); |
1 2 3 4 5 6 7 8 9 | # Meridional weights weight = np.cos(np.deg2rad(dt.latitude)) weight = weight / weight.sum() zonal_mean_t2_c = dt.t2m.mean(dim='longitude') - 273.15 weighted_zonal_mean_t2_c = zonal_mean_t2_c * weight weighted_ts_t2_c = weighted_zonal_mean_t2_c.sum(dim='latitude') t2_a_av = weighted_ts_t2_c.resample(time= 'A').mean() T = t2_a_av.to_pandas() |
1 2 3 4 5 6 7 8 9 10 | #plot fig,ax = plt.subplots() ax.plot(T, color="red") ax.set_xlabel("year", fontsize = 14) ax.set_ylabel("2m temperature", color="red", fontsize=14) ax.set_title("CO2 Concentration and 2m Temperature") ax2=ax.twinx() ax2.plot(anual_avg_co2,color="blue") ax2.set_ylabel("CO2 in ppm",color="blue",fontsize=14) plt.show() |
Part 5: variability and ENSO (open research question)¶
Using the available data, describe the global effect of an El Niño year and a La Niña year on sea-surface temperature, precipitation, and air temperature. I 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. Then use annual or seasonal anomaly maps to show the patterns of SST, temperature and precipitation anomalies during these events. With citation or links, explain why you picked these years as examples.
1 2 | #Sea_Surface temperature difference dsst = xr.open_dataset('data/ERA5_LowRes_Monthly_sst.nc') |
1 2 3 4 5 6 | sst_avg_el = dsst.sst.sel(time= '1987').mean(dim = 'time') sst_avg = dsst.sst.mean(dim = 'time') sst_an_el = sst_avg_el - sst_avg ax = plt.axes(projection=ccrs.Robinson(central_longitude=180)) sst_an_el.plot(ax=ax, transform=ccrs.PlateCarree()); ax.coastlines(), ax.set_title('Sea Surface Temperatur anomaly during an el Niño year (1987)'), ax.gridlines() |
(<cartopy.mpl.feature_artist.FeatureArtist at 0x1d231c895d0>, Text(0.5, 1.0, 'Sea Surface Temperatur anomaly during an el Niño year (1987)'), <cartopy.mpl.gridliner.Gridliner at 0x1d23c0363b0>)
1 2 3 4 5 6 7 | #sea surface temperature anomaly la Ninia sst_avg_la = dsst.sst.sel(time= '1985').mean(dim = 'time') sst_avg = dsst.sst.mean(dim = 'time') sst_an_la = sst_avg_la - sst_avg ax = plt.axes(projection=ccrs.Robinson(central_longitude=180)) sst_an_la.plot(ax=ax, transform=ccrs.PlateCarree()); ax.coastlines(), ax.gridlines(), ax.set_title('Sea Surface Temperatur anomaly during a la Niña year (1985)') |
(<cartopy.mpl.feature_artist.FeatureArtist at 0x1d23c9f1870>, <cartopy.mpl.gridliner.Gridliner at 0x1d23ca408e0>, Text(0.5, 1.0, 'Sea Surface Temperatur anomaly during a la Niña year (1985)'))
El Niño
- If we look at the SST we can se that during an el Niño event easter Pacific is very warm due to cut of of cold water from the deep.
- In the western pacific in frint of SE Asia we can se slightly cooler water than normal.
- Very cold water in northern Pacific
la Niña
- very cold water in front of Peru.
- Some warmer water in NE Pacific but no other strong signals.
1 2 3 4 5 6 7 8 | #Temperature El t2_avg_el = dt.t2m.sel(time= '1987').mean(dim = 'time') t2c_an_el = t2_avg_el - t2_tavg ax = plt.axes(projection=ccrs.Robinson(central_longitude=180)) t2c_an_el.plot(ax=ax, transform=ccrs.PlateCarree(), levels=[-2, -1.5, -1, -0.5, 0, 0.5, 1, 1.5, 2]); ax.coastlines() ax.set_title('Surface Temperatur anomaly during an el Niño year (1987)'), ax.gridlines() #ax.set_extent([135, 295, -20, 20]) |
(Text(0.5, 1.0, 'Surface Temperatur anomaly during an el Niño year (1987)'), <cartopy.mpl.gridliner.Gridliner at 0x1d23cee5690>)
1 2 3 4 5 6 7 | #Temperature la t2_avg_la = dt.t2m.sel(time= '1985').mean(dim = 'time') t2c_an_la = t2_avg_la - t2_tavg ax = plt.axes(projection=ccrs.Robinson(central_longitude=180)) t2c_an_la.plot(ax=ax, transform=ccrs.PlateCarree(), levels=[-2, -1.5, -1, -0.5, 0, 0.5, 1, 1.5, 2]); ax.coastlines() ax.set_title('Surface Temperatur anomaly during a la Niña year year (1985)'), ax.gridlines() |
(Text(0.5, 1.0, 'Surface Temperatur anomaly during a la Niña year year (1985)'), <cartopy.mpl.gridliner.Gridliner at 0x1d23d33a2c0>)
El Niño
- warmer on South American coast
- colder in Mexico and SW USA
- extreamly warm in Canada and the mid West in the USA. Not only from ENSO.
la Niña
- colder in middle and south America
- colder in Australia
- not much difference in SE Asia probably can seen better in seasonal anomalies
1 2 3 4 5 6 7 8 9 10 | #precipitation anomalies lev = np.arange(-200, 200, 10) tp_sum_el = dp.tp.sel(time= '1987').sum(dim = 'time')*1000 #convert to mm tp_avg = dp.tp.mean(dim = 'time')*1000 tp_sum_el = tp_sum_el-tp_avg ax = plt.axes(projection=ccrs.Robinson(central_longitude=180)) tp_sum_el.plot(ax=ax, transform=ccrs.PlateCarree(), cmap = 'RdYlBu', cbar_kwargs={'label': 'mm'}, levels = lev); ax.coastlines() ax.set_title('cumulative precipitation anomaly during an el Niño year year (1987)') #ax.set_extent([135, 295, -20, 20]) |
Text(0.5, 1.0, 'cumulative precipitation anomaly during an el Niño year year (1987)')
1 2 3 4 5 6 7 8 9 | #precipitation anomalies tp_sum_el = dp.tp.sel(time= '1985').sum(dim = 'time')*1000 #convert to mm tp_avg = dp.tp.mean(dim = 'time')*1000 tp_sum_el = (tp_sum_el-tp_avg) ax = plt.axes(projection=ccrs.Robinson(central_longitude=180)) tp_sum_el.plot(ax=ax, transform=ccrs.PlateCarree(), cmap = 'RdYlBu', cbar_kwargs={'label': 'mm'}, levels = lev); ax.coastlines() ax.set_title('cumulative precipitation anomaly during an la Niña year year (1985)') #ax.set_extent([135, 295, -20, 20]) |
Text(0.5, 1.0, 'cumulative precipitation anomaly during an la Niña year year (1985)')
El Niño
- see positive anomaly although shoud be negative in SE Asia
- more precepitaion in south America $\newline$ la Niña
- dry in SE South America
- a lot of rain in South Asia which fit to the event.
Sources: $\newline$
https://origin.cpc.ncep.noaa.gov/products/analysis_monitoring/ensostuff/ONI_v5.php $\newline$
https://www.metoffice.gov.uk/research/climate/seasonal-to-decadal/gpc-outlooks/el-nino-la-nina/enso-impacts#:~:text=ENSO%20events%20have%20widespread%20effects,Ni%C3%B1o%20and%20La%20Ni%C3%B1a%20events. $\newline$
Why did we choose these Events?
We tried it with differnt years and it came down to the 1998/1999 or the chossen event. After ploting both we disediet to go with the el Niño in 1987 and the la Niña in 1985 because these where quit long and consistent phases, resulting in the biggest anomalies in the plots.