{ "cells": [ { "cell_type": "markdown", "metadata": { "execution": {} }, "source": [ "[![Open In Colab](https://colab.research.google.com/assets/colab-badge.svg)](https://colab.research.google.com/github/ClimateMatchAcademy/course-content/blob/main/tutorials/W1D2_StateoftheClimateOceanandAtmosphereReanalysis/student/W1D2_Tutorial1.ipynb)   \"Open\n" ] }, { "cell_type": "markdown", "metadata": { "execution": {}, "tags": [] }, "source": [ "# Tutorial 1: Calculating ENSO with Xarray\n", "\n", "**Week 1, Day 2, Ocean-Atmosphere Reanalysis**\n", "\n", "**Content creators:** Abigail Bodner, Momme Hell, Aurora Basinski\n", "\n", "**Content reviewers:** Yosemley Bermúdez, Katrina Dobson, Danika Gupta, Maria Gonzalez, Will Gregory, Nahid Hasan, Sherry Mi, Beatriz Cosenza Muralles, Jenna Pearson, Chi Zhang, Ohad Zivan\n", "\n", "**Content editors:** Jenna Pearson, Chi Zhang, Ohad Zivan\n", "\n", "**Production editors:** Wesley Banfield, Jenna Pearson, Chi Zhang, Ohad Zivan\n", "\n", "**Our 2023 Sponsors:** NASA TOPS and Google DeepMind\n" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## ![project pythia](https://projectpythia.org/_static/images/logos/pythia_logo-blue-rtext.svg)\n", "\n", "Pythia credit: Rose, B. E. J., Kent, J., Tyle, K., Clyne, J., Banihirwe, A., Camron, D., May, R., Grover, M., Ford, R. R., Paul, K., Morley, J., Eroglu, O., Kailyn, L., & Zacharias, A. (2023). Pythia Foundations (Version v2023.05.01) https://zenodo.org/record/8065851\n", "\n", "## ![CMIP.png](https://github.com/ClimateMatchAcademy/course-content/blob/main/tutorials/Art/CMIP.png?raw=true)\n" ] }, { "cell_type": "markdown", "metadata": { "execution": {} }, "source": [ "# Tutorial Objectives\n", "\n", "In this notebook (adapted from [Project Pythia](https://foundations.projectpythia.org/core/xarray/enso-xarray.html)), you will practice using multiple tools to examine sea surface temperature (SST) and explore variations in the climate system that occur during El Nino and La Nina events. You will learn to:\n", "\n", "1. Load Sea Surface Temprature data from the CESM2 model\n", "2. Mask data using `.where()`\n", "3. Compute climatologies and anomalies using `.groupby()`\n", "4. Use `.rolling()` to compute moving average\n", "5. Compute, normalize, and plot the Oceanic Niño Index\n", "\n", "After completing the tasks above, you should be able to plot [Oceanic Niño Index](https://climatedataguide.ucar.edu/climate-data/nino-sst-indices-nino-12-3-34-4-oni-and-tni) that looks similar to the figure below. The red and blue regions correspond to the phases of El Niño and La Niña respectively.\n", "\n", "![ONI index plot from NCAR Climate Data Guide](https://climatedataguide.ucar.edu/sites/default/files/styles/extra_large/public/2022-03/indices_oni_2_2_lg.png)\n", "\n", "Credit: [NCAR](https://climatedataguide.ucar.edu/sites/default/files/styles/extra_large/public/2022-03/indices_oni_2_2_lg.png)\n", "\n", "Pythia credit: Rose, B. E. J., Kent, J., Tyle, K., Clyne, J., Banihirwe, A., Camron, D., May, R., Grover, M., Ford, R. R., Paul, K., Morley, J., Eroglu, O., Kailyn, L., & Zacharias, A. (2023). Pythia Foundations (Version v2023.05.01) https://zenodo.org/record/8065851\n" ] }, { "cell_type": "markdown", "metadata": { "execution": {}, "tags": [] }, "source": [ "# Setup\n" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "tags": [ "colab" ] }, "outputs": [], "source": [ "# installations ( uncomment and run this cell ONLY when using google colab or kaggle )\n", "\n", "# !pip install --upgrade --force-reinstall pythia_datasets cartopy matplotlib geoviews xarray cftime nc-time-axis\n", "# !pip install --no-binary shapely shapely --force\n", "# # note you will need to restart the kernel after this - there should be a small button at the end of the output.\n" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "# imports\n", "import cartopy.crs as ccrs\n", "import matplotlib.pyplot as plt\n", "import xarray as xr\n", "from pythia_datasets import DATASETS\n", "import cartopy.io.shapereader as shapereader\n", "import pandas as pd\n", "import matplotlib.dates as mdates\n", "import geoviews as gv\n", "import geoviews.feature as gf\n" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Video 1: El Niño Southern Oscillation\n" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "cellView": "form", "tags": [ "remove-input" ] }, "outputs": [], "source": [ "# @title Video 1: El Niño Southern Oscillation\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(\n", " id=video_ids[i][1], width=W, height=H, fs=fs, rel=0\n", " )\n", " print(f\"Video available at https://youtube.com/watch?v={video.id}\")\n", " else:\n", " video = PlayVideo(\n", " id=video_ids[i][1],\n", " source=video_ids[i][0],\n", " width=W,\n", " height=H,\n", " fs=fs,\n", " autoplay=False,\n", " )\n", " if video_ids[i][0] == \"Bilibili\":\n", " print(\n", " f\"Video available at https://www.bilibili.com/video/{video.id}\"\n", " )\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\", \"pkvy9KJUAsA\"), (\"Bilibili\", \"BV1p94y1B7d1\")]\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": "code", "execution_count": null, "metadata": { "cellView": "form", "pycharm": { "name": "#%%\n" }, "tags": [ "remove-input" ] }, "outputs": [], "source": [ "# @markdown\n", "from ipywidgets import widgets\n", "from IPython.display import IFrame\n", "\n", "link_id = \"t65v8\"\n", "\n", "download_link = f\"https://osf.io/download/{link_id}/\"\n", "render_link = f\"https://mfr.ca-1.osf.io/render?url=https://osf.io/{link_id}/?direct%26mode=render%26action=download%26mode=render\"\n", "# @markdown\n", "out = widgets.Output()\n", "with out:\n", " print(f\"If you want to download the slides: {download_link}\")\n", " display(IFrame(src=f\"{render_link}\", width=730, height=410))\n", "display(out)" ] }, { "cell_type": "markdown", "metadata": { "execution": {} }, "source": [ "# Section 1: Introduction to El Niño Southern Oscillation (ENSO)\n", "\n", "In W1D1 you practiced using `Xarray` to calculate a monthly climatology, climate anomalies, and a running average on monthly global Sea Surface Temperature (SST) data from the Community Earth System Model v2 (CESM2). You also used the `.where()` method to isolate SST data between **5ºN-5ºS and 190ºE-240ºE (or 170ºW-120ºW)**. This geographic region, known as the **Niño 3.4 region**, is in the tropical Pacific Ocean and is commonly used as a metric for determining the phase of the El Niño-Southern Oscillation (ENSO). ENSO is a recurring climate pattern involving changes in SST in the central and eastern tropical Pacific Ocean, which has two alternating phases:\n", "\n", "- **El Niño:** the phase of ENSO characterized by warmer than average SSTs in the central and eastern tropical Pacific Ocean, weakened east to west equatorial winds and increased rainfall in the eastern tropical Pacific.\n", "- **La Niña:** the phase of ENSO which is characterized by cooler than average SSTs in the central and eastern tropical Pacific Ocean, stronger east to west equatorial winds and decreased rainfall in the eastern tropical Pacific.\n", "\n", "## Section 1.1: Tropical Pacific Climate Processes\n", "\n", "To better understand the climate system processes that result in El Niño and La Niña events, let's first consider typical climate conditions in the tropical Pacific Ocean. Recall from W1D1, **trade winds** are winds that blow east to west just north and south of the equator (these are sometimes referred to as \"easterly\" winds since the winds are originating from the east and blowing toward the west). And as we discussed yesterday, the reason that the trade winds blow from east to west is related to Earth's rotation, which causes the winds in the Northern Hemisphere to curve to the right and winds in the Southern Hemisphere to curve to the left. This is known as the **Coriolis effect**.\n", "\n", "If Earth's rotation affects air movement, do you think it also influences surface ocean water movement? It does! As trade winds blow across the tropical Pacific Ocean, they move water because of friction at the ocean surface. But because of the Coriolis effect, surface water moves to the right of the wind direction in the Northern Hemisphere and to the left of the wind direction in the Southern Hemisphere. However, the speed and direction of water movement changes with depth. Ocean surface water moves at an angle to the wind, and the water under the surface water moves at a slightly larger angle, and the water below that turns at an even larger angle. The average direction of all this turning water is about a right angle from the wind direction. This average is known as **Ekman transport**. Since this process is driven by the trade winds, the strength of this ocean water transport varies in response to changes in the strength of the trade winds.\n", "\n", "## Section 1.2: Ocean-Atmosphere Interactions During El Niño and La Niña\n", "\n", "So, how does all of this relate to El Niño and La Niña? Changes in the strength of Pacific Ocean trade winds and the resulting impact on Ekman transport create variations in the tropical Pacific Ocean SST, which further results in changes to atmospheric circulation patterns and rainfall.\n", "\n", "During an El Niño event, **_easterly trade winds are weaker_**. As a result, less warm surface water is transported to the west via Ekman transport, which causes a build-up of warm surface water in the eastern equatorial Pacific. This creates warmer than average SSTs in the eastern equatorial Pacific Ocean. The atmosphere responds to this warming with increased rising air motion and above-average rainfall in the eastern Pacific. In contrast, during a La Niña event, **_easterly trade winds are stronger_**. As a result, more warm surface water is transported to the west via Ekman transport, and cool water from deeper in the ocean rises up in the eastern Pacific during a process known as upwelling. This creates cooler than average SSTs in the eastern equatorial Pacific Ocean. This cooling decreases rising air movement in the eastern Pacific, resulting in drier than average conditions.\n", "\n", "In this tutorial, we'll examine SST temperatures to explore variations in the climate system that occur during El Niño and La Niña events. Specifically, we will plot and interpret CESM2 SST data from the Niño 3.4 region.\n" ] }, { "cell_type": "markdown", "metadata": { "execution": {} }, "source": [ "# Section 2: Calculate the Oceanic Niño Index\n" ] }, { "cell_type": "markdown", "metadata": { "execution": {} }, "source": [ "In this notebook, we are going to combine several topics and methods you've covered so far to compute the [Oceanic Niño Index](https://climatedataguide.ucar.edu/climate-data/nino-sst-indices-nino-12-3-34-4-oni-and-tni) using SST from the CESM2 submission to the [CMIP6 project](https://esgf-node.llnl.gov/projects/cmip6/).\n", "\n", "You will be working with CMIP6 data later in the week, particularly during W2D1. You can also learn more about CMIP, including additional methods to access CMIP data, please see our [CMIP Resource Bank](https://github.com/ClimateMatchAcademy/course-content/blob/main/tutorials/CMIP/CMIP_resource_bank.md) and the [CMIP website](https://wcrp-cmip.org/).\n", "\n", "To calculate the Oceanic Niño Index you will:\n", "\n", "1. Select SST data from Niño 3.4 region of 5ºN-5ºS and 190ºE-240ºE (or 170ºW-120ºW) shown in the figure below.\n", "\n", "![](https://www.ncdc.noaa.gov/monitoring-content/teleconnections/nino-regions.gif)\n", "\n", "2. Compute the climatology (here from 2000-2014) for the Niño 3.4 region.\n", "3. Compute the monthly anomaly for the Niño 3.4 region.\n", "4. Compute the area-weighted mean of the anomalies for the Niño 3.4 region to obtain a time series.\n", "5. Smooth the time series of anomalies with a 3-month running mean.\n", "\n", "Here we will briefly move through each of these steps, and tomorrow you will learn about them in more detail.\n" ] }, { "cell_type": "markdown", "metadata": { "execution": {} }, "source": [ "## Section 2.1: Open the SST Data\n" ] }, { "cell_type": "markdown", "metadata": { "execution": {}, "tags": [] }, "source": [ "First, open the SST and areacello datasets, and use Xarray's `merge` method to combine them into a single dataset:\n" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "executionInfo": { "elapsed": 5921, "status": "ok", "timestamp": 1682537726774, "user": { "displayName": "Sloane Garelick", "userId": "04706287370408131987" }, "user_tz": 240 } }, "outputs": [], "source": [ "# retrive (fetch) the SST data we are going to be working on\n", "SST_path = DATASETS.fetch(\"CESM2_sst_data.nc\")\n", "\n", "# open the file we acquired with xarray\n", "SST_data = xr.open_dataset(SST_path)\n", "\n", "# remember that one degree spatial cell is not constant around the globe, each is a different size in square km.\n", "# we need to account for this when taking averages for example\n", "\n", "# fetch the weight for each grid cell\n", "gridvars_path = DATASETS.fetch(\"CESM2_grid_variables.nc\")\n", "\n", "# open and save only the gridcell weights whose variable name is 'areacello'\n", "# here the 'o' at the end refers to the area cells of the 'ocean' grid\n", "areacello_data = xr.open_dataset(gridvars_path).areacello\n", "\n", "# merge the SST and weights into one easy to use dataset - ds stands for dataset\n", "ds_SST = xr.merge([SST_data, areacello_data])\n", "ds_SST\n" ] }, { "cell_type": "markdown", "metadata": { "execution": {} }, "source": [ "Visualize the first time point in the early 2000s. You can check this on the indexes of the variable 'time' from the ds_SST above. Note that using the `plot` function of our dataarray will automatically include this as a title when we select just the first time index.\n" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "executionInfo": { "elapsed": 5137, "status": "ok", "timestamp": 1682537741323, "user": { "displayName": "Sloane Garelick", "userId": "04706287370408131987" }, "user_tz": 240 } }, "outputs": [], "source": [ "# define the plot size\n", "fig = plt.figure(figsize=(12, 6))\n", "\n", "# asssign axis and define the projection - for a round plot\n", "ax = plt.axes(projection=ccrs.Robinson(central_longitude=180))\n", "\n", "# add coastlines - this will issue a download warning but that is ok\n", "ax.coastlines()\n", "\n", "# add gridlines (lon and lat)\n", "ax.gridlines()\n", "\n", "# plots the first time index (0) of SST (variable name 'tos') at the first time\n", "ds_SST.tos.isel(time=0).plot(\n", " ax=ax,\n", " transform=ccrs.PlateCarree(), # give our axis a map projection\n", " vmin=-2,\n", " vmax=30, # define the temp range of the colorbarfrom -2 to 30C\n", " cmap=\"coolwarm\", # choose a colormap\n", ")\n" ] }, { "cell_type": "markdown", "metadata": { "execution": {} }, "source": [ "### Interactive Demo 2.1\n" ] }, { "cell_type": "markdown", "metadata": { "execution": {} }, "source": [ "You can visualize what the next few times look like in the model by using the interactive sliderbar below.\n" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "# a bit more complicated code that allows interactive plots\n", "gv.extension(\"bokeh\") # load Bokeh\n", "dataset_plot = gv.Dataset(\n", " ds_SST.isel(time=slice(0, 10))\n", ") # slice only the first 10 timepoint, as it is a time consuming task\n", "images = dataset_plot.to(gv.Image, [\"longitude\", \"latitude\"], \"tos\", \"time\")\n", "images.opts(\n", " cmap=\"coolwarm\",\n", " colorbar=True,\n", " width=600,\n", " height=400,\n", " projection=ccrs.Robinson(),\n", " clabel=\"Sea Surface Temperature [˚C]\",\n", ") * gf.coastline\n" ] }, { "cell_type": "markdown", "metadata": { "execution": {} }, "source": [ "## Section 2.2: Select the Niño 3.4 Region\n", "\n", "You may have noticed that the `lon` for the SST data is organized between 0°–360°E.\n" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "tags": [] }, "outputs": [], "source": [ "ds_SST.lon\n" ] }, { "cell_type": "markdown", "metadata": { "execution": {} }, "source": [ "This is different from how we typically use `longitude` (-180°–180°). How do we covert the value of longitude between two systems (0-360° v.s. -180°–180°)?\n", "\n", "Let's use `lon2` refer to the longitude system of `0°-360°` while `lon` refers to the system of `-180°–180°`. `0°-360°` is equivalent to `0–180°, -180°–0°`.\n", "\n", "In other words, `lon2=181°` is same as `lon=-179°`. Hence, in the western hemisphere, `lon2=lon+360`.\n", "\n", "Therefore, the Niño 3.4 region should be (-5°–5°, 190–240°) using the `lon2` system.\n", "\n", "Now that we have identified the longitude values we need to select, there are a couple ways to select the Niño 3.4 region. We will demonstrate how to use both below.\n", "\n", "1. `sel()`\n" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "executionInfo": { "elapsed": 842, "status": "ok", "timestamp": 1682539230855, "user": { "displayName": "Sloane Garelick", "userId": "04706287370408131987" }, "user_tz": 240 } }, "outputs": [], "source": [ "# select just the Nino 3.4 region (note our longitude values are in degrees east) by slicing\n", "tos_nino34_op1 = ds_SST.sel(lat=slice(-5, 5), lon=slice(190, 240))\n", "tos_nino34_op1\n" ] }, { "cell_type": "markdown", "metadata": { "execution": {} }, "source": [ "2. Use `where()` and select all values within the bounds of interest\n" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "executionInfo": { "elapsed": 492, "status": "ok", "timestamp": 1682539239230, "user": { "displayName": "Sloane Garelick", "userId": "04706287370408131987" }, "user_tz": 240 } }, "outputs": [], "source": [ "# select just the Nino 3.4 region (note our longitude values are in degrees east) by boolean conditioning\n", "tos_nino34_op2 = ds_SST.where(\n", " (ds_SST.lat < 5) & (ds_SST.lat > -5) & (ds_SST.lon > 190) & (ds_SST.lon < 240),\n", " drop=True,\n", ") # use dataset where function. use boolean commands\n", "tos_nino34_op2\n" ] }, { "cell_type": "markdown", "metadata": { "execution": {} }, "source": [ "You can verify that `tos_nino34_op1` and `tos_nino34_op2` are the same by comparing the lat and lon indexes.\n", "\n", "We only need one of these, so let us choose the second option and set that to the variable we will use moving forward.\n" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "# SST in just the Nino 3.4 region\n", "tos_nino34 = tos_nino34_op2\n" ] }, { "cell_type": "markdown", "metadata": { "execution": {} }, "source": [ "Let's utilize the same code we used to plot the entire Earth, but this time focusing on the Niño 3.4 region slice only.\n" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "executionInfo": { "elapsed": 797, "status": "ok", "timestamp": 1682539250576, "user": { "displayName": "Sloane Garelick", "userId": "04706287370408131987" }, "user_tz": 240 } }, "outputs": [], "source": [ "# define the figure size\n", "fig = plt.figure(figsize=(12, 6))\n", "\n", "# assign axis and projection\n", "ax = plt.axes(projection=ccrs.Robinson(central_longitude=180))\n", "\n", "# add coastlines\n", "ax.coastlines()\n", "\n", "# add gridlines (lon and lat)\n", "ax.gridlines()\n", "\n", "# plot as above\n", "tos_nino34.tos.isel(time=0).plot(\n", " ax=ax, transform=ccrs.PlateCarree(), vmin=-2, vmax=30, cmap=\"coolwarm\"\n", ")\n", "\n", "# make sure we see more areas of the earth and not only the square around Niño 3.4\n", "ax.set_extent((120, 300, 10, -10))\n" ] }, { "cell_type": "markdown", "metadata": { "execution": {} }, "source": [ "## Section 2.3: Compute the Climatology and Anomalies\n", "\n", "Now that we have selected our area, we can compute the monthly anomaly by first grouping all the data by month, then substracting the monthly climatology from each month.\n" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "# group the dataset by month\n", "tos_nino34_mon = tos_nino34.tos.groupby(\"time.month\")\n", "\n", "# find the monthly climatology in the Nino 3.4 region\n", "tos_nino34_clim = tos_nino34_mon.mean(dim=\"time\")\n", "\n", "# find the monthly anomaly in the Nino 3.4 region\n", "tos_nino34_anom = tos_nino34_mon - tos_nino34_clim\n", "\n", "# take the area weighted average of anomalies in the Nino 3.4 region\n", "tos_nino34_anom_mean = tos_nino34_anom.weighted(tos_nino34.areacello).mean(\n", " dim=[\"lat\", \"lon\"]\n", ")\n", "tos_nino34_anom_mean\n" ] }, { "cell_type": "markdown", "metadata": { "execution": {} }, "source": [ "## Section 2.4: Smooth the Anomaly Time Series\n" ] }, { "cell_type": "markdown", "metadata": { "execution": {} }, "source": [ "ENSO occurs on interannual timescales (a few years or more). To isolate the variability of this longer-term phenomenon on the Niño 3.4 region, we can smooth out the fluctuations due to variability on shorter timescales. To achieve this, we will apply a 3-month running mean to our time series of SST anomalies.\n" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "# smooth using a centered 3 month running mean\n", "oni_index = tos_nino34_anom_mean.rolling(time=3, center=True).mean()\n" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "executionInfo": { "elapsed": 975, "status": "ok", "timestamp": 1682539376867, "user": { "displayName": "Sloane Garelick", "userId": "04706287370408131987" }, "user_tz": 240 } }, "outputs": [], "source": [ "# define the plot size\n", "fig = plt.figure(figsize=(12, 6))\n", "\n", "# assign axis\n", "ax = plt.axes()\n", "\n", "# plot the monhtly data on the assigned axis\n", "tos_nino34_anom_mean.plot(ax=ax)\n", "\n", "# plot the smoothed data on the assigned axis\n", "oni_index.plot(ax=ax)\n", "\n", "# add legend\n", "ax.legend([\"monthly\", \"3-month running mean\"])\n", "\n", "# add ylabel\n", "ax.set_ylabel(\"temprature anomalies\")\n", "\n", "# add xlabel\n", "ax.set_xlabel(\"Year\")\n" ] }, { "cell_type": "markdown", "metadata": { "execution": {} }, "source": [ "# Section 3: Identify El Niño and La Niña Events\n" ] }, { "cell_type": "markdown", "metadata": { "execution": {} }, "source": [ "We will highlight values in excess of $\\pm$0.5, roughly corresponding to El Niño (warm) and La Niña (cold) events.\n" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "executionInfo": { "elapsed": 1326, "status": "ok", "timestamp": 1682539414434, "user": { "displayName": "Sloane Garelick", "userId": "04706287370408131987" }, "user_tz": 240 } }, "outputs": [], "source": [ "fig = plt.figure(figsize=(12, 6)) # assing figure size\n", "\n", "plt.fill_between( # plot with color in between\n", " oni_index.time.data, # x values\n", " # top boundary - y values above 0.5\n", " oni_index.where(oni_index >= 0.5).data,\n", " 0.5, # bottom boundary - 0.5\n", " color=\"red\", # color\n", " alpha=0.9, # transparency value\n", ")\n", "plt.fill_between(\n", " oni_index.time.data,\n", " oni_index.where(oni_index <= -0.5).data,\n", " -0.5,\n", " color=\"blue\",\n", " alpha=0.9,\n", ")\n", "\n", "oni_index.plot(color=\"black\") # plot the smoothed data\n", "plt.axhline(0, color=\"black\", lw=0.5) # add a black line at x=0\n", "plt.axhline(\n", " 0.5, color=\"black\", linewidth=0.5, linestyle=\"dotted\"\n", ") # add a black line at x=0.5\n", "plt.axhline(\n", " -0.5, color=\"black\", linewidth=0.5, linestyle=\"dotted\"\n", ") # add a black line at x=-0.5\n", "plt.title(\"Oceanic Niño Index (ONI)\")\n" ] }, { "cell_type": "markdown", "metadata": { "execution": {} }, "source": [ "### Questions 3:\n", "\n", "\n", "\n", "Now that we've normalized the data and highlighted SST anomalies that correspond to El Niño (warm) and La Niña (cold) events, consider the following questions:\n", "\n", "1. How frequently do El Niño and La Niña events occur over the period of time studied here?\n", "2. When were the strongest El Niño and La Niña events over this time period?\n", "3. Considering the ocean-atmosphere interactions that cause El Niño and La Niña events, can you hypothesize potential reasons one El Niño or La Niña event may be stronger than others?\n" ] }, { "cell_type": "markdown", "metadata": { "execution": {} }, "source": [ "# Summary\n", "\n", "In this tutorial, we have learned to utilize a variety of Xarray tools to examine variations in SST during El Niño and La Niña events. We've practiced loading SST data from the CESM2 model, and masking data using the `.where()` function for focused analysis. We have also computed climatologies and anomalies using the `.groupby()` function, and learned to compute moving averages using the `.rolling()` function. Finally, we have calculated, normalized, and plotted the Oceanic Niño Index (ONI), enhancing our understanding of the El Niño Southern Oscillation (ENSO) and its impacts on global climate patterns.\n" ] }, { "cell_type": "markdown", "metadata": { "execution": {} }, "source": [ "# Resources\n", "\n", "Data from this tutorial can be accessed [here](https://github.com/ProjectPythia/pythia-datasets).\n" ] } ], "metadata": { "colab": { "collapsed_sections": [], "include_colab_link": true, "name": "W1D2_Tutorial1", "provenance": [ { "file_id": "1WxQZGZjRjPv2YkhwRdEG4PGrU0tHGq9t", "timestamp": 1680102521421 } ], "toc_visible": true }, "kernel": { "display_name": "Python 3", "language": "python", "name": "python3" }, "kernelspec": { "display_name": "climatematch", "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.10.11" }, "toc-autonumbering": false, "toc-showcode": false, "toc-showmarkdowntxt": false, "toc-showtags": false }, "nbformat": 4, "nbformat_minor": 4 }