{
"cells": [
{
"cell_type": "markdown",
"metadata": {
"execution": {}
},
"source": [
"[](https://colab.research.google.com/github/neuromatch/climate-course-content/blob/main/tutorials/W1D2_Ocean-AtmosphereReanalysis/W1D2_Tutorial3.ipynb)
"
]
},
{
"cell_type": "markdown",
"metadata": {
"execution": {}
},
"source": [
"# Tutorial 3: Atmospheric Circulation\n",
"\n",
"**Week 1, Day 2, Ocean-Atmosphere Reanalysis**\n",
"\n",
"**Content creators:** Momme Hell\n",
"\n",
"**Content reviewers:** Katrina Dobson, Danika Gupta, Maria Gonzalez, Will Gregory, Nahid Hasan, Paul Heubel, Sherry Mi, Beatriz Cosenza Muralles, Jenna Pearson, Chi Zhang, Ohad Zivan\n",
"\n",
"**Content editors:** Paul Heubel, Jenna Pearson, Chi Zhang, Ohad Zivan\n",
"\n",
"**Production editors:** Wesley Banfield, Paul Heubel, Jenna Pearson, Konstantine Tsafatinos, Chi Zhang, Ohad Zivan\n",
"\n",
"**Our 2024 Sponsors:** CMIP, NFDI4Earth\n"
]
},
{
"cell_type": "markdown",
"metadata": {
"execution": {}
},
"source": [
"# Tutorial Objectives\n",
"\n",
"*Estimated timing of tutorial:* 30-40 mins\n",
"\n",
"In the previous tutorial, you examined atmospheric surface temperatures. Spatial variations in surface temperature created by uneven solar radiation (e.g., between the equator and poles), are one of the main drivers of global-scale air movement. Other processes such as the Earth's rotation, storm tracks, and surface topography can also influence global wind patterns. \n",
"\n",
"By the end of this tutorial, you will be able to:\n",
"\n",
"- Describe the seasonal variations in surface winds.\n",
"- Calculate seasonal climatologies and create global maps.\n",
"- Compare statistics derived from these climatologies.\n",
"\n",
"In this tutorial, you will again utilize the monthly mean surface wind fields from ERA5 over a 30-year period."
]
},
{
"cell_type": "markdown",
"metadata": {
"execution": {},
"tags": []
},
"source": [
"# Setup"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"execution": {},
"tags": [
"colab"
]
},
"outputs": [],
"source": [
"# installations ( uncomment and run this cell ONLY when using google colab or kaggle )\n",
"\n",
"# !pip install cartopy"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"execution": {}
},
"outputs": [],
"source": [
"import matplotlib.pyplot as plt\n",
"import matplotlib.ticker as ticker\n",
"import os\n",
"import pooch\n",
"import tempfile\n",
"import numpy as np\n",
"import xarray as xr\n",
"import warnings\n",
"from cartopy import crs as ccrs, feature as cfeature\n",
"\n",
"# Suppress warnings issued by Cartopy when downloading data files\n",
"warnings.filterwarnings(\"ignore\")"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## Install and import feedback gadget\n"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"cellView": "form",
"execution": {},
"tags": [
"hide-input"
]
},
"outputs": [],
"source": [
"# @title Install and import feedback gadget\n",
"\n",
"!pip3 install vibecheck datatops --quiet\n",
"\n",
"from vibecheck import DatatopsContentReviewContainer\n",
"def content_review(notebook_section: str):\n",
" return DatatopsContentReviewContainer(\n",
" \"\", # No text prompt\n",
" notebook_section,\n",
" {\n",
" \"url\": \"https://pmyvdlilci.execute-api.us-east-1.amazonaws.com/klab\",\n",
" \"name\": \"comptools_4clim\",\n",
" \"user_key\": \"l5jpxuee\",\n",
" },\n",
" ).render()\n",
"\n",
"\n",
"feedback_prefix = \"W1D2_T3\""
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## Plotting Functions\n"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"cellView": "form",
"execution": {},
"tags": [
"hide-input"
]
},
"outputs": [],
"source": [
"# @title Plotting Functions\n",
"\n",
"\n",
"def set_projection_figure(projection=ccrs.PlateCarree(), figsize=plt.rcParams['figure.figsize']):\n",
" # source:https://foundations.projectpythia.org/core/cartopy/cartopy.html\n",
" # edit by PH: figsize defined by cma.mplstyle in Figure Settings section\n",
"\n",
" projLccNY = projection # ccrs.LambertConformal(central_longitude=cLon, central_latitude=cLat)\n",
"\n",
" fig = plt.figure(figsize=figsize)\n",
" ax = plt.subplot(1, 1, 1, projection=projLccNY)\n",
"\n",
" format_axes(ax)\n",
" # ax.add_feature(cfeature.STATES)\n",
" # ax.add_feature(cfeature.RIVERS)\n",
" return fig, ax\n",
"\n",
"\n",
"def format_axes(ax):\n",
" ax.add_feature(cfeature.COASTLINE)\n",
" ax.add_feature(cfeature.LAKES, edgecolor=\"black\", facecolor=\"None\", alpha=0.3)\n",
" gl = ax.gridlines(\n",
" draw_labels=True, linewidth=1, color=\"black\", alpha=0.5, linestyle=\"--\"\n",
" )\n",
" gl.xlocator = ticker.MaxNLocator(7)\n",
" gl.ylocator = ticker.MaxNLocator(5)\n",
" gl.xlabels_top = False\n",
" gl.ylabels_left = False\n",
" # gl.xlines = False\n",
"\n",
"\n",
"# helping functions:\n",
"def geographic_lon_to_360(lon):\n",
" return 360 + lon\n",
"\n",
"\n",
"def inverted_geographic_lon_to_360(lon):\n",
" return lon - 180\n",
"\n",
"\n",
"def cbar_label(DD):\n",
" return DD.attrs[\"long_name\"] + \" [\" + DD.attrs[\"units\"] + \"]\""
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## Helper functions\n"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"cellView": "form",
"execution": {},
"tags": [
"hide-input"
]
},
"outputs": [],
"source": [
"# @title Helper functions\n",
"\n",
"def pooch_load(filelocation=None, filename=None, processor=None):\n",
" shared_location = \"/home/jovyan/shared/Data/tutorials/W1D2_Ocean-AtmosphereReanalysis\" # this is different for each day\n",
" user_temp_cache = tempfile.gettempdir()\n",
"\n",
" if os.path.exists(os.path.join(shared_location, filename)):\n",
" file = os.path.join(shared_location, filename)\n",
" else:\n",
" file = pooch.retrieve(\n",
" filelocation,\n",
" known_hash=None,\n",
" fname=os.path.join(user_temp_cache, filename),\n",
" processor=processor,\n",
" )\n",
"\n",
" return file"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## Figure Settings\n"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"cellView": "form",
"execution": {},
"tags": [
"hide-input"
]
},
"outputs": [],
"source": [
"# @title Figure Settings\n",
"import ipywidgets as widgets # interactive display\n",
"\n",
"%config InlineBackend.figure_format = 'retina'\n",
"plt.style.use(\n",
" \"https://raw.githubusercontent.com/neuromatch/climate-course-content/main/cma.mplstyle\"\n",
")"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## Video 1: The Wind Driven Circulation\n"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"cellView": "form",
"execution": {},
"tags": [
"remove-input"
]
},
"outputs": [],
"source": [
"# @title Video 1: The Wind Driven Circulation\n",
"\n",
"from ipywidgets import widgets\n",
"from IPython.display import YouTubeVideo\n",
"from IPython.display import IFrame\n",
"from IPython.display import display\n",
"\n",
"\n",
"class PlayVideo(IFrame):\n",
" def __init__(self, id, source, page=1, width=400, height=300, **kwargs):\n",
" self.id = id\n",
" if source == 'Bilibili':\n",
" src = f'https://player.bilibili.com/player.html?bvid={id}&page={page}'\n",
" elif source == 'Osf':\n",
" src = f'https://mfr.ca-1.osf.io/render?url=https://osf.io/download/{id}/?direct%26mode=render'\n",
" super(PlayVideo, self).__init__(src, width, height, **kwargs)\n",
"\n",
"\n",
"def display_videos(video_ids, W=400, H=300, fs=1):\n",
" tab_contents = []\n",
" for i, video_id in enumerate(video_ids):\n",
" out = widgets.Output()\n",
" with out:\n",
" if video_ids[i][0] == 'Youtube':\n",
" video = YouTubeVideo(id=video_ids[i][1], width=W,\n",
" height=H, fs=fs, rel=0)\n",
" print(f'Video available at https://youtube.com/watch?v={video.id}')\n",
" else:\n",
" video = PlayVideo(id=video_ids[i][1], source=video_ids[i][0], width=W,\n",
" height=H, fs=fs, autoplay=False)\n",
" if video_ids[i][0] == 'Bilibili':\n",
" print(f'Video available at https://www.bilibili.com/video/{video.id}')\n",
" elif video_ids[i][0] == 'Osf':\n",
" print(f'Video available at https://osf.io/{video.id}')\n",
" display(video)\n",
" tab_contents.append(out)\n",
" return tab_contents\n",
"\n",
"\n",
"video_ids = [('Youtube', 'zgwShu0xXYA'), ('Bilibili', 'BV1NN411U7Eb')]\n",
"tab_contents = display_videos(video_ids, W=730, H=410)\n",
"tabs = widgets.Tab()\n",
"tabs.children = tab_contents\n",
"for i in range(len(tab_contents)):\n",
" tabs.set_title(i, video_ids[i][0])\n",
"display(tabs)"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## Submit your feedback\n"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"cellView": "form",
"execution": {},
"tags": [
"hide-input"
]
},
"outputs": [],
"source": [
"# @title Submit your feedback\n",
"content_review(f\"{feedback_prefix}_Wind_Driven_Circulation_Video\")"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"\n"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"cellView": "form",
"execution": {},
"pycharm": {
"name": "#%%\n"
},
"tags": [
"remove-input"
]
},
"outputs": [],
"source": [
"# @markdown\n",
"from ipywidgets import widgets\n",
"from IPython.display import IFrame\n",
"\n",
"link_id = \"t6c78\"\n",
"\n",
"print(f\"If you want to download the slides: https://osf.io/download/{link_id}/\")\n",
"IFrame(src=f\"https://mfr.ca-1.osf.io/render?url=https://osf.io/{link_id}/?direct%26mode=render%26action=download%26mode=render\", width=854, height=480)"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## Submit your feedback\n"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"cellView": "form",
"execution": {},
"tags": [
"hide-input"
]
},
"outputs": [],
"source": [
"# @title Submit your feedback\n",
"content_review(f\"{feedback_prefix}_Wind_Driven_Circulation_Slides\")"
]
},
{
"cell_type": "markdown",
"metadata": {
"execution": {}
},
"source": [
"# Section 1: Surface Winds\n"
]
},
{
"cell_type": "markdown",
"metadata": {
"execution": {}
},
"source": [
"The large-scale atmospheric circulation significantly influences the climate we experience at different latitudes. The global atmospheric circulation is often depicted as a three-cell structure, as visualized [in this figure showing the surface winds](https://commons.wikimedia.org/wiki/File:Earth_Global_Circulation_-_en.svg):\n",
"\n",
".\n",
"\n",
"\n",
"This schematic of atmospheric circulation cells reveal meridional (north-south) and zonal (east-west) components of the large-scale surface winds. \n",
"\n",
"Let's see if you are able to detect these large-scale patterns in reanalysis data! \n",
"For this, you will load ERA5 wind data, which we pre-processed after retrieving it from the [Pangeo catalog](https://pangeo.io/catalog.html).\n"
]
},
{
"cell_type": "markdown",
"metadata": {
"execution": {}
},
"source": [
"## Section 1.1: Annual Mean Wind Speed\n",
"\n",
"You should start investigating this data by examining the global surface winds. These winds are represented as vectors, consisting of a zonal component denoted as `u10` and a meridional component denoted as `v10`. \n",
"\n",
"Recall from the previous tutorial that the magnitude of the wind vector represents the wind speed you will use later in the tutorial, given by:\n",
"\n",
"\\begin{align}\n",
"||u|| = \\sqrt{u^2 + v^2}\n",
"\\end{align}\n",
"\n",
"To examine long-term changes in the wind field you should visualize the zonal wind component $u$ and the meridional wind component $v$ with monthly mean data. With the help of `xarray`, you can derive monthly means from higher-resolution data (such as those used in tutorial 2) using the `xr.resample('1M').mean('time')` function.\n",
"\n",
"For your convenience, we have already performed this step, and you can load the data using the following instructions:\n",
"\n",
"- The variable `si10` represents the wind speed in this dataset.\n",
"- To calculate the long-term mean, we selected 30 years of data ranging from 1980 to 2010.\n",
"\n",
"Let's grab the reanalysis data from before that we have preprocessed (noting naming convention changes):"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"execution": {}
},
"outputs": [],
"source": [
"# note this can take a few minutes to download\n",
"filename_era5_mm = \"ERA5_surface_winds_mm.nc\"\n",
"url_era5_mm = \"https://osf.io/3q4vs/download\"\n",
"\n",
"ERA5_mm = xr.open_dataset(pooch_load(url_era5_mm, filename_era5_mm)).sel(\n",
" time=slice(\"1980\", \"2006\")\n",
") # select the timeslice during loading\n",
"ERA5_mm"
]
},
{
"cell_type": "markdown",
"metadata": {
"execution": {}
},
"source": [
"Now calculate the temporal mean of the surface wind speed."
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"execution": {}
},
"outputs": [],
"source": [
"# take the temporal mean over 26 years (Jan 1980 - Dec 2005)\n",
"ERA5_mean = ERA5_mm.mean(\"time\")"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"execution": {}
},
"outputs": [],
"source": [
"ERA5_mean"
]
},
{
"cell_type": "markdown",
"metadata": {
"execution": {}
},
"source": [
"To visualize this data, we will be using some helper functions defined in the beginning of the tutorial just to set the map features and aesthetics. Please take a look at them if you are interested in seeing how they work."
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"execution": {},
"tags": []
},
"outputs": [],
"source": [
"# adjust color levels to weaker amplitudes\n",
"colorlevels_clim = np.arange(-10, 11, 1)\n",
"\n",
"var = \"u10\" # select our variable\n",
"fig, ax = set_projection_figure(\n",
" projection=ccrs.PlateCarree()\n",
") # same plot function as Part I\n",
"ax.set_title(\"Mean \" + var + \" – (1980-2005)\", loc=\"left\")\n",
"dataplot = ax.contourf(\n",
" ERA5_mean.longitude,\n",
" ERA5_mean.latitude,\n",
" ERA5_mean[var],\n",
" levels=colorlevels_clim,\n",
" transform=ccrs.PlateCarree(),\n",
" cmap=plt.cm.coolwarm,\n",
")\n",
"fig.colorbar(dataplot, orientation=\"vertical\", label=\"Wind Speed (m/s)\",\n",
" shrink=0.55, pad=0.11\n",
" )"
]
},
{
"cell_type": "markdown",
"metadata": {
"execution": {}
},
"source": [
"\n",
"Click here for a description of the plot
\n",
"In the zonal wind speed figure you created, two distinct wind bands between 35° to 65° both north and south of the equator blow from west to east (red, positive wind speeds). These mid-latitude wind bands are known as the westerlies. Additionally, you can see that winds predominantly blow from the east to the west (blue, negative wind speeds) in the tropics (less than 30° N/S), and are referred to as the easterlies.\n",
"\n",
"*** \n",
"\n",
" "
]
},
{
"cell_type": "markdown",
"metadata": {
"execution": {}
},
"source": [
"### Coding Exercise 1.1: Mean Meridional Wind\n",
"Reproduce the previous figure, but modify it to plot the **meridional wind** rather than the **zonal wind** component."
]
},
{
"cell_type": "markdown",
"metadata": {
"colab_type": "text",
"execution": {}
},
"source": [
"```python\n",
"#################################################\n",
"## TODO for students: add the variable of interest to be plotted. ##\n",
"# Remove the following line of code once you have completed the exercise:\n",
"raise NotImplementedError(\"Student exercise: Add the variable of interest to be plotted.\")\n",
"#################################################\n",
"var = ...\n",
"fig, ax = set_projection_figure(projection=ccrs.PlateCarree())\n",
"ax.set_title(\"Mean \" + str(var) + \" – (1980-2005)\", loc=\"left\")\n",
"dataplot = ax.contourf(\n",
" ERA5_mean.longitude,\n",
" ERA5_mean.latitude,\n",
" ERA5_mean[var],\n",
" levels=colorlevels_clim,\n",
" transform=ccrs.PlateCarree(),\n",
" cmap=plt.cm.coolwarm,\n",
")\n",
"fig.colorbar(dataplot, orientation=\"vertical\", label=\"Wind Speed (m/s)\", shrink=0.55, pad=0.11)\n",
"\n",
"```"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"execution": {}
},
"outputs": [],
"source": [
"# to_remove solution\n",
"var = \"v10\"\n",
"fig, ax = set_projection_figure(projection=ccrs.PlateCarree())\n",
"ax.set_title(\"Mean \" + str(var) + \" – (1980-2005)\", loc=\"left\")\n",
"dataplot = ax.contourf(\n",
" ERA5_mean.longitude,\n",
" ERA5_mean.latitude,\n",
" ERA5_mean[var],\n",
" levels=colorlevels_clim,\n",
" transform=ccrs.PlateCarree(),\n",
" cmap=plt.cm.coolwarm,\n",
")\n",
"fig.colorbar(dataplot, orientation=\"vertical\", label=\"Wind Speed (m/s)\", shrink=0.55, pad=0.11)"
]
},
{
"cell_type": "markdown",
"metadata": {
"execution": {}
},
"source": [
"\n",
"Click here for a description of the plot
\n",
"There are strong southward winds in the subtropics of the Northern Hemisphere (blue, negative wind speed), and northward winds in the subtropics of the Southern Hemisphere (red, positive wind speed). The meridional winds are strongest on the western side of the continents. \n",
"\n",
"*** \n",
"\n",
" "
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"#### Submit your feedback\n"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"cellView": "form",
"execution": {},
"tags": [
"hide-input"
]
},
"outputs": [],
"source": [
"# @title Submit your feedback\n",
"content_review(f\"{feedback_prefix}_Coding_Exercise_1_1\")"
]
},
{
"cell_type": "markdown",
"metadata": {
"execution": {}
},
"source": [
"### Questions 1.1\n",
"1. Among the three atmospheric \"cells\" (the Hadley Cell, Ferrel Cell, and Polar Cell) depicted in the figure from Section 1 above, which ones correspond to the zonal wind bands that we visualized in the first plot above? \n",
"2. How do the zonal and meridional winds compare in magnitude, longitude, and latitude?"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"execution": {}
},
"outputs": [],
"source": [
"# to_remove explanation\n",
"'''\n",
"1. The Hadley Cell is the tropical region containing the easterlies (a.k.a. trade winds), and the Ferrel Cell is the mid-latitude region containing the westerlies.\n",
"2. Meridional winds are typically weaker and less variable than zonal winds. This is due to the general circulation of the atmosphere, which primarily moves air in the east-west direction rather than north-south.\n",
"'''"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"#### Submit your feedback\n"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"cellView": "form",
"execution": {},
"tags": [
"hide-input"
]
},
"outputs": [],
"source": [
"# @title Submit your feedback\n",
"content_review(f\"{feedback_prefix}_Questions_1_1\")"
]
},
{
"cell_type": "markdown",
"metadata": {
"execution": {}
},
"source": [
"## Section 1.2: Zonal-mean Wind Speed\n",
"\n",
"To examine the latitudinal variation in the surface winds, you can plot the zonal mean of the annual mean zonal and meridional winds:\n"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"execution": {}
},
"outputs": [],
"source": [
"fig, ax = plt.subplots()\n",
"\n",
"# calculate zonal mean over all longitudes\n",
"ERA5_mean_zmean = ERA5_mean.mean(\"longitude\")\n",
"\n",
"# select the u10 & v10 variable and plot it\n",
"ERA5_mean_zmean[\"u10\"].plot( label=\"Zonal wind\", ax = ax )\n",
"ERA5_mean_zmean[\"v10\"].plot( label=\"Meridional wind\", ax = ax )\n",
"\n",
"# aesthetics\n",
"ax.legend() # add legend\n",
"ax.set_title(\"Mean wind components, zonally averaged\", loc=\"left\") # add title\n",
"ax.set_xlabel(\"Latitudes (°N)\") # axis labels\n",
"ax.set_ylabel(\"Wind speed (m/s)\")\n",
"ax.axhline(0, color=\"black\", alpha=0.3) # add a black line at x = 0\n",
"#ax.grid(True)\n",
"\n",
"# Add annotations to the plot for improved readability\n",
"# arrow & annot. to emphasize wind direction of meridional wind (positive speed)\n",
"ax.annotate(\"Northward\", xy=(-15, 1.8), xytext= (-15, 4), xycoords='data', size=9,\n",
" arrowprops=dict(arrowstyle=\"->\"))\n",
"# arrow & annot. to emphasize wind direction of zonal wind (positive speed)\n",
"ax.annotate(\"Eastward\", xy=(50, 1.8), xytext= (50, 4), xycoords='data', fontsize=9,\n",
" arrowprops=dict(arrowstyle=\"->\"))\n",
"# annotate N hemisphere/ pole\n",
"ax.annotate('N', xy=(1, 0), xycoords='axes fraction',\n",
" xytext=(-20, 20), textcoords='offset pixels',\n",
" horizontalalignment='right',\n",
" verticalalignment='bottom', color='darkgray')\n",
"# annotate S hemisphere/ pole\n",
"ax.annotate('S', xy=(0, 0), xycoords='axes fraction',\n",
" xytext=(30, 20), textcoords='offset pixels',\n",
" horizontalalignment='left',\n",
" verticalalignment='bottom', color='darkgray')"
]
},
{
"cell_type": "markdown",
"metadata": {
"execution": {}
},
"source": [
"### Questions 1.2\n",
"1. Considering the zonal-mean wind speed figure provided, what factors contribute to the noticeable disparities between the Northern and Southern Hemispheres in terms of wind patterns?"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"execution": {}
},
"outputs": [],
"source": [
"# to_remove explanation\n",
"\n",
"\"\"\"\n",
"1. The continents influence the strength of the winds, and since the continents are so unevenly distributed on the planet, the winds are weaker in the North than in the South. The strongest winds occur in the Southern Ocean, where there is little land, and must become very strong to create the same drag as over the large land masses of the Northern Hemisphere.\n",
"\"\"\""
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"#### Submit your feedback\n"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"cellView": "form",
"execution": {},
"tags": [
"hide-input"
]
},
"outputs": [],
"source": [
"# @title Submit your feedback\n",
"content_review(f\"{feedback_prefix}_Questions_1_2\")"
]
},
{
"cell_type": "markdown",
"metadata": {
"execution": {}
},
"source": [
"# Section 2: Monthly Climatology\n",
"\n",
"Now, you should examine how the zonal mean winds vary throughout the seasons. You will focus on the zonal wind component and create a special type of diagram called a Hovmöller diagram. In this diagram, the horizontal axis represents latitude, while the vertical axis represents time.\n",
"\n",
"By using the [Hovmöller diagram](https://en.wikipedia.org/wiki/Hovm%C3%B6ller_diagram), you can visualize how the average east-west winds change over the annual cycle.\n",
"\n",
"At first, we average our original dataset over all longitudes to get the zonal mean of all variables. We then temporally average it with respect to all months, resulting in a data set with twelve time steps which represent the mean of every month over the whole period of January 1980 to December 2005 for all three variables (`u10`, `v10` and `si10`)."
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"execution": {}
},
"outputs": [],
"source": [
"# Note how we use several commands in one line.\n",
"# Python performs them in order. First, calculate the zonal mean, then group by month, and lastly calculate the mean.\n",
"# The groupby method hereby regroups the data by month, such that all Januarys, all Februaries, .. can be averaged.\n",
"\n",
"ERA5_zmean_mmean = ERA5_mm.mean(\"longitude\").groupby(\"time.month\").mean()"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"execution": {}
},
"outputs": [],
"source": [
"# Have a look at our new dataset, which incorporates the zonal mean and the temporal mean of every month\n",
"ERA5_zmean_mmean"
]
},
{
"cell_type": "markdown",
"metadata": {
"execution": {}
},
"source": [
"We plot the zonal wind component `u10` of the wind vector versus month and latitude, i.e. the aforementioned Hovmöller diagram, which is a special type of [heatmap](https://en.wikipedia.org/wiki/Heat_map) and might remind you of the [Warming Stripes](https://en.wikipedia.org/wiki/Warming_stripes).\n",
"\n",
"It allows us to recognize both spatial (abscissa/ x-axis) and temporal changes (ordinate/ y-axis) in our variables. \n",
"\n",
"Note that xarray uses the metadata of the dataset to label the axes, hence it does not look as pretty and insightful as our previous plots. If you have difficulties to interpret the output, perhaps it helps to look at the previous blue line plot, to compare the axes and to try to understand how the shown extrema translate into colors of the Hovmöller diagram."
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"execution": {}
},
"outputs": [],
"source": [
"# plot the zonal wind component of the wind vector\n",
"_ = ERA5_zmean_mmean.u10.plot()"
]
},
{
"cell_type": "markdown",
"metadata": {
"execution": {}
},
"source": [
"\n",
"Click here for a description of the plot
\n",
"This Hovmöller diagram shows the zonal wind vector component $u$ for every month and latitude (in °N) after being averaged over 26 years (1980 - 2005) and all longitudes. The wind bands are almost symmetrical in width with regard to the hemispheres, but not in magnitude. The zonal wind is way stronger in the Southern Hemisphere (negative latitude range). Over time the east-west and vice versa winds shift to the north in boreal summer (i.e. summer in the Northern Hemisphere). Furthermore, wind bands of westerly winds arise around the equator and the northern high latitudes in boreal summer, while less changes in the southern high latitudes. The easterlies (negative wind speed) around the equator seasonally oscillate in magnitude. In other words, in the respective summer of the hemisphere winds weaken, while they increase in winter.\n",
"\n",
"*** \n",
"\n",
" "
]
},
{
"cell_type": "markdown",
"metadata": {
"execution": {}
},
"source": [
"### Coding Exercises 2\n",
"\n",
"Extend the above analysis to create a Hovmöller diagram of the meridional winds. "
]
},
{
"cell_type": "markdown",
"metadata": {
"colab_type": "text",
"execution": {}
},
"source": [
"```python\n",
"# select the variable of interest and plot it with xarray's plotting method\n",
"_ = ...\n",
"\n",
"```"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"execution": {}
},
"outputs": [],
"source": [
"# to_remove solution\n",
"\n",
"# select the variable of interest and plot it with xarray's plotting method\n",
"_ = ERA5_zmean_mmean.v10.plot()"
]
},
{
"cell_type": "markdown",
"metadata": {
"execution": {}
},
"source": [
"\n",
"Click here for a description of the plot
\n",
"This Hovmöller diagram shows the meridional wind vector component $v$ for every month and latitude (in °N) after being averaged over 26 years (1980 - 2005) and all longitudes. The meridional wind is way stronger in the Southern Hemisphere (negative latitude range). Over time the north-south and vice versa wind bands that blow towards the equator shift to the north in boreal summer (i.e. summer in the Northern Hemisphere). There are strong winds in northern direction but less changes in the southern high latitudes. The south winds (blue, negative wind speed) and north winds (red, positive wind speed) around the equator seasonally oscillate in magnitude. In other words, in the respective summer of the hemisphere, meridional winds weaken, while they increase in winter.\n",
"\n",
"*** \n",
"\n",
" "
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"#### Submit your feedback\n"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"cellView": "form",
"execution": {},
"tags": [
"hide-input"
]
},
"outputs": [],
"source": [
"# @title Submit your feedback\n",
"content_review(f\"{feedback_prefix}_Coding_Exercises_2\")"
]
},
{
"cell_type": "markdown",
"metadata": {
"execution": {}
},
"source": [
"*In summary:*\n",
"- The winds in the Southern Hemisphere appear to be generally stronger compared to the Northern Hemisphere.\n",
"- The period between June and September shows strong meridional winds. These winds result from the seasonal variation of the Hadley cell. During the winter in each respective hemisphere, the Hadley cell becomes much stronger, leading to the intensification of meridional winds."
]
},
{
"cell_type": "markdown",
"metadata": {
"execution": {}
},
"source": [
"# Bonus Section 3: Seasonal differences of the zonal wind\n",
"\n",
"The solar insulation leads to varying circulation patterns within the seasons. To explore this seasonality you can proceed as follows:\n",
"\n",
"- Plot the global map for the seasons December to February (DJF) and June to August (JJA) of the zonal wind. What do you see when you compare the mid-latitudes? (You can also plot their difference!)\n",
"\n",
"- Plot the trend of the zonally averaged zonal wind vector component in DJF.\n",
"\n",
"You can find out more in [Global Physical Climatology](https://www.atmos.washington.edu/~dennis/gpc.html), \n",
"[The Atmospheric General Circulation](https://www.cambridge.org/us/academic/subjects/earth-and-environmental-science/atmospheric-science-and-meteorology/atmospheric-general-circulation?format=HB&isbn=9781108474245)\n",
"or the first few chapters of this evolving draft [Physics of Earth's Climate](https://climate-dynamics.org/wp-content/uploads/2017/04/Climate_Book.pdf)\n"
]
},
{
"cell_type": "markdown",
"metadata": {
"colab_type": "text",
"execution": {}
},
"source": [
"```python\n",
"# select the variable of interest, group the data by season, and average over all seasons.\n",
"# note, this code takes a while to run,\n",
"# to test your solution and to reduce the duration select a smaller period\n",
"ERA5_season_u10 = ...\n",
"\n",
"```"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"execution": {}
},
"outputs": [],
"source": [
"# to_remove solution\n",
"# select the variable of interest, group the data by season, and average over all seasons.\n",
"# note, this code takes a while to run,\n",
"# to test your solution and to reduce the duration select a smaller period\n",
"ERA5_season_u10 = ERA5_mm.u10.sel(time=slice('2000','2005')).groupby('time.season').mean()"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## Submit your feedback\n"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"cellView": "form",
"execution": {},
"tags": [
"hide-input"
]
},
"outputs": [],
"source": [
"# @title Submit your feedback\n",
"content_review(f\"{feedback_prefix}_Bonus_Coding_Exercise_3_1\")"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"execution": {}
},
"outputs": [],
"source": [
"ERA5_season_u10"
]
},
{
"cell_type": "markdown",
"metadata": {
"colab_type": "text",
"execution": {}
},
"source": [
"```python\n",
"var='u10'\n",
"season='DJF'\n",
"F, ax = set_projection_figure(projection = ccrs.PlateCarree())\n",
"ax.set_title('Zonal Wind DJF mean | '+ var , loc ='left')\n",
"dataplot = ...\n",
"_ = ... # colorbar\n",
"plt.show()\n",
"\n",
"season='JJA'\n",
"F, ax = set_projection_figure(projection = ccrs.PlateCarree())\n",
"ax.set_title('Zonal Wind DJF mean | '+ var , loc ='left')\n",
"dataplot = ...\n",
"_ = ... # colorbar\n",
"plt.show()\n",
"\n",
"# difference:\n",
"pdata = ...\n",
"\n",
"F, ax = set_projection_figure(projection = ccrs.PlateCarree())\n",
"ax.set_title(... , loc ='left')\n",
"dataplot = ...\n",
"_ = ... # colorbar\n",
"plt.show()\n",
"\n",
"```"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"execution": {}
},
"outputs": [],
"source": [
"# to_remove solution\n",
"var='u10'\n",
"season='DJF'\n",
"F, ax = set_projection_figure(projection = ccrs.PlateCarree())\n",
"ax.set_title('Zonal Wind DJF mean | '+ var , loc ='left')\n",
"dataplot = ax.contourf(ERA5_season_u10.longitude, ERA5_season_u10.latitude, ERA5_season_u10.sel(season=season),\n",
" levels = colorlevels_clim,\n",
" transform=ccrs.PlateCarree(), cmap= plt.cm.coolwarm)\n",
"_ = plt.colorbar(dataplot, orientation='vertical', label = 'Wind speed (m/s)', shrink= 0.55 , pad = 0.11) # colorbar\n",
"plt.show()\n",
"\n",
"season='JJA'\n",
"F, ax = set_projection_figure(projection = ccrs.PlateCarree())\n",
"ax.set_title('Zonal Wind DJF mean | '+ var , loc ='left')\n",
"dataplot = ax.contourf(ERA5_season_u10.longitude, ERA5_season_u10.latitude, ERA5_season_u10.sel(season=season),\n",
" levels = colorlevels_clim,\n",
" transform=ccrs.PlateCarree(), cmap= plt.cm.coolwarm)\n",
"_ = plt.colorbar(dataplot, orientation='vertical', label = 'Wind speed (m/s)', shrink= 0.55 , pad = 0.11) # colorbar\n",
"plt.show()\n",
"\n",
"# difference:\n",
"pdata = ERA5_season_u10.sel(season='DJF') - ERA5_season_u10.sel(season='JJA')\n",
"\n",
"F, ax = set_projection_figure(projection = ccrs.PlateCarree())\n",
"ax.set_title('Zonal Wind DJF mean - JJA mean | '+ var , loc ='left')\n",
"dataplot = ax.contourf(ERA5_season_u10.longitude, ERA5_season_u10.latitude,pdata ,\n",
" levels = colorlevels_clim,\n",
" transform=ccrs.PlateCarree(), cmap= plt.cm.coolwarm)\n",
"_ = plt.colorbar(dataplot, orientation='vertical', label = 'Wind speed (m/s)', shrink= 0.55 , pad = 0.11) # colorbar\n",
"plt.show()"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## Submit your feedback\n"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"cellView": "form",
"execution": {},
"tags": [
"hide-input"
]
},
"outputs": [],
"source": [
"# @title Submit your feedback\n",
"content_review(f\"{feedback_prefix}_Bonus_Coding_Exercise_3_2\")"
]
},
{
"cell_type": "markdown",
"metadata": {
"execution": {}
},
"source": [
"## Additional Reading: Extra-tropical Storms\n",
"\n",
"In the wind speed figure, you can notice areas of strong winds over the Southern Ocean, North Pacific, and North Atlantic. These powerful winds are caused by weather systems known as extratropical storms or mid-latitude cyclones. These storms occur in the middle latitudes, between 30° and 60° north or south of the equator. During winter, they are particularly strong over the Southern Ocean and the oceans in the Northern Hemisphere.\n",
"\n",
"Extratropical storms form when warm and cold air masses interact. They have a low-pressure center and produce winds that circulate counterclockwise in the Northern Hemisphere and clockwise in the Southern Hemisphere. These storms can be intense, bringing strong winds, heavy rain, snow, and sleet. They often lead to problems like flooding, power outages, and disruptions in transportation.\n",
"\n",
"The strength of these storms depends on factors such as the temperature difference between air masses, the speed of the jet stream, and the amount of moisture in the air. If you want to learn more about extratropical storms, you can refer to basic meteorology and atmospheric dynamics resources, or you can explore online sources such as the following:\n",
"\n",
"- Wikipedia: [Extratropical Cyclone](https://en.wikipedia.org/wiki/Extratropical_cyclone)\n",
"- Pressbooks: [Chapter 13 - Extratropical Cyclones](http://pressbooks-dev.oer.hawaii.edu/atmo/chapter/chapter-13-extratropical-cyclones/)\n",
"\n",
"Although an individual storm may last only a few days and doesn't create significant ocean currents, the continuous winds and the occurrence of multiple storms over a year can influence the development of ocean currents. These currents are a response to the persistent wind patterns."
]
},
{
"cell_type": "markdown",
"metadata": {
"execution": {}
},
"source": [
"# Summary\n",
"\n",
"Within this tutorial, you analysed the global atmospheric circulation by using ERA5 reanalysis data. You explored the distribution of westerlies and easterlies across the globe, observed their seasonal variations. You observed that the strongest winds were found to occur over the Southern Ocean."
]
},
{
"cell_type": "markdown",
"metadata": {
"execution": {}
},
"source": [
"# Resources\n",
"\n",
"Data from this tutorial can be accessed [here](https://registry.opendata.aws/ecmwf-era5/)."
]
}
],
"metadata": {
"colab": {
"collapsed_sections": [],
"include_colab_link": true,
"name": "W1D2_Tutorial3",
"provenance": [],
"toc_visible": true
},
"kernel": {
"display_name": "Python 3",
"language": "python",
"name": "python3"
},
"kernelspec": {
"display_name": "Python 3 (ipykernel)",
"language": "python",
"name": "python3"
},
"language_info": {
"codemirror_mode": {
"name": "ipython",
"version": 3
},
"file_extension": ".py",
"mimetype": "text/x-python",
"name": "python",
"nbconvert_exporter": "python",
"pygments_lexer": "ipython3",
"version": "3.9.19"
},
"toc-autonumbering": true
},
"nbformat": 4,
"nbformat_minor": 4
}