{ "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/neuromatch/climate-course-content/blob/main/tutorials/W1D3_RemoteSensing/instructor/W1D3_Tutorial7.ipynb)   \"Open\n" ] }, { "cell_type": "markdown", "metadata": { "execution": {} }, "source": [ "# Tutorial 7: Impact of Climate Variability - Precipitation\n", "\n", "**Week 1, Day 3, Remote Sensing**\n", "\n", "**Content creators:** Douglas Rao\n", "\n", "**Content reviewers:** Katrina Dobson, Younkap Nina Duplex, Maria Gonzalez, Will Gregory, Nahid Hasan, Paul Heubel, Sherry Mi, Beatriz Cosenza Muralles, Jenna Pearson, Agustina Pesce, 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:* 25 minutes\n", "\n", "In this tutorial, the primary goal is to understand how to utilize satellite data to investigate the effects of large-scale climate variability on precipitation.\n", "\n", "Upon the completion of this tutorial, you will be able to:\n", "\n", "- Comprehend the influence of the El Niño-Southern Oscillation (ENSO) on precipitation and its geographical distribution.\n", "- Compute Pearson's correlation coefficient, a statistical measure used to determine the relationship between two time series.\n" ] }, { "cell_type": "markdown", "metadata": { "execution": {} }, "source": [ "# Setup\n" ] }, { "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", "# # properly install cartopy in colab to avoid session crash\n", "# !apt-get install libproj-dev proj-data proj-bin --quiet\n", "# !apt-get install libgeos-dev --quiet\n", "# !pip install cython --quiet\n", "# !pip install cartopy --quiet\n", "\n", "# !apt-get -qq install python-cartopy python3-cartopy --quiet\n", "# !pip uninstall -y shapely --quiet\n", "# !pip install shapely --no-binary shapely --quiet\n", "\n", "# !pip install boto3 --quiet\n", "\n", "# you may need to restart the runtime after running this cell and that is ok" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "execution": {}, "tags": [] }, "outputs": [], "source": [ "# imports\n", "import xarray as xr\n", "import matplotlib.pyplot as plt\n", "import cartopy.crs as ccrs\n", "import os\n", "import pooch\n", "import tempfile\n", "from scipy import stats" ] }, { "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 = \"W1D3_T7\"" ] }, { "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": [ "## Helper functions\n" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "cellView": "form", "execution": {}, "tags": [ "hide-input" ] }, "outputs": [], "source": [ "# @title Helper functions\n", "\n", "\n", "def pooch_load(filelocation=None, filename=None, processor=None):\n", " # this is different for each day\n", " shared_location = \"/home/jovyan/shared/data/tutorials/W1D3_RemoteSensing\"\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": [ "## Video 1: Impact of Climate Variability\n" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "cellView": "form", "execution": {}, "tags": [ "remove-input" ] }, "outputs": [], "source": [ "# @title Video 1: Impact of Climate Variability\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(\n", " 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\", \"TJr_nNP87Rg\"), (\"Bilibili\", \"BV1Th4y1j7sY\")]\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}_Impact_of_Climate_Variability_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 = \"tyjwu\"\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}_Impact_of_Climate_Variability_Slides\")" ] }, { "cell_type": "markdown", "metadata": { "execution": {} }, "source": [ "# Section 1: ENSO and Precipitation\n" ] }, { "cell_type": "markdown", "metadata": { "execution": {} }, "source": [ "As discussed in previous tutorials, ENSO oscillates irregularly between El Niño and La Niña phases every two to seven years. These shifts often prompt predictable changes in ocean surface temperature and disrupt wind and rainfall patterns across the tropics, leading to a cascade of global side effects.\n", "\n", "In this context, we will be utilizing satellite data to scrutinize the influence of ENSO on precipitation patterns.\n" ] }, { "cell_type": "markdown", "metadata": { "execution": {} }, "source": [ "## Section 1.1: Get ENSO Index Oceanic Niño Index (ONI)\n", "\n", "In Tutorial 6, we calculated the Oceanic Niño Index (ONI) using the OISST Climate Data Records that contain interpolated sea surface temperature (SST) data. Now we just read the ONI values using the climatology of 1982-2011.\n" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "execution": {}, "tags": [] }, "outputs": [], "source": [ "# download't6_oceanic-nino-index.nc'\n", "\n", "url_nino = \"https://osf.io/8rwxb/download/\"\n", "filename_nino = \"t6_oceanic-nino-index\"\n", "oni = xr.open_dataset(pooch_load(filelocation=url_nino, filename=filename_nino))\n", "oni" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "execution": {}, "tags": [] }, "outputs": [], "source": [ "# plot the ONI timeseries we just downloaded\n", "fig, ax = plt.subplots()\n", "oni.sst.plot(ax=ax)\n", "\n", "# aesthetics\n", "ax.set_xlabel(\"Time (months)\")\n", "ax.set_ylabel(\"Oceanic Niño Index\")\n", "ax.axhline(y=0, linestyle=\"dashed\", color=\"k\")\n", "ax.axhline(y=0.5, linestyle=\"dotted\", color=\"r\")\n", "ax.axhline(y=-0.5, linestyle=\"dotted\", color=\"b\")\n", "ax.grid(True)" ] }, { "cell_type": "markdown", "metadata": { "execution": {} }, "source": [ "## Section 1.2: Get Precipitation Anomaly Data\n", "\n", "In Tutorial 5, we created the monthly anomaly data of precipitation globally using the GPCP Monthly Precipitation Climate Data Records. Here, we read in the anomaly data and look at one specific month (e.g., 1998-01-01).\n" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "execution": {}, "tags": [] }, "outputs": [], "source": [ "# download file 't5_gpcp-monthly-anomaly_1981-2010.nc'\n", "url_precip = \"https://osf.io/vhdcg/download/\"\n", "filename_precip = \"t5_gpcp-monthly-anomaly_1981-2010.nc\"\n", "precip = xr.open_dataset(pooch_load(filelocation=url_precip, filename=filename_precip))\n", "precip" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "execution": {}, "tags": [] }, "outputs": [], "source": [ "# select just data from 1998\n", "data = precip.sel(time=\"1998-01-01\")\n", "\n", "# initiate plot\n", "fig = plt.figure()\n", "ax = plt.axes(projection=ccrs.Robinson(central_longitude=180))\n", "# add coast- and gridlines\n", "ax.coastlines()\n", "ax.gridlines()\n", "# draw precipitation data\n", "data.precip.plot(\n", " ax=ax,\n", " transform=ccrs.PlateCarree(),\n", " vmin=-10,\n", " vmax=10,\n", " #robust=True,\n", " cmap=\"BrBG\",\n", " cbar_kwargs=dict(shrink=0.5, label=\"Precipitation Anomaly\\n(mm/day)\"),\n", ")" ] }, { "cell_type": "markdown", "metadata": { "execution": {} }, "source": [ "## Section 1.3: Spatial Pattern\n", "\n", "Let's look at one specific ENSO event - the **1997/1998 El Niño** and see how the spatial pattern of the precipitation evolves. The 1997/1998 El Niño is one of the most significant ENSO events that started in May of 1997 and ended April of 1998.\n", "\n", "Let's examine the seasonal precipitation anomaly pattern during this time period.\n" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "execution": {}, "tags": [] }, "outputs": [], "source": [ "# define the figure and each axis for the 2 rows and 2 columns\n", "fig, axs = plt.subplots(\n", " nrows=2,\n", " ncols=2,\n", " subplot_kw={\"projection\": ccrs.Robinson(central_longitude=180)},\n", " figsize=(12, 7.5),\n", " sharex=True,\n", " sharey=True,\n", ")\n", "\n", "# axs is a 2-dimensional array of `GeoAxes`. We will flatten it into a 1-D array to loop over it\n", "axs = axs.flatten()\n", "\n", "# loop over selected months (Jan, Apr, Jul, Oct)\n", "for i, month in enumerate([\"1997-07-01\", \"1997-10-01\", \"1998-01-01\", \"1998-04-01\"]):\n", " # draw the coastines and major gridline for each subplot\n", " axs[i].coastlines()\n", " axs[i].gridlines()\n", "\n", " # draw the precipitation anomaly data\n", " precip.precip.sel(time=month).plot(\n", " ax=axs[i],\n", " transform=ccrs.PlateCarree(),\n", " vmin=-10,\n", " vmax=10, # use the same range of max and min value\n", " cmap=\"BrBG\",\n", " cbar_kwargs=dict(shrink=0.5, label=\"Precipitation anomaly\\n(mm/day)\"),\n", " )" ] }, { "cell_type": "markdown", "metadata": { "execution": {} }, "source": [ "In this series of four monthly maps, notice the shifts in precipitation patterns across the tropics and various land regions.\n", "\n", "In particular, there are large increases and decreases in precipitation over the tropical ocean, where ENSO is actively monitored. In the Niño3.4 region, the intensification of the El Niño phase (which is characterized by warmer SSTs over the central and eastern Pacific) occurs alongside an increase in rainfall shown here (more blue areas near the equator).\n", "\n", "In addition to these changes, there are also rainfall patterns in regions such as North and South America, with the Amazon as a notable example.\n" ] }, { "cell_type": "markdown", "metadata": { "execution": {} }, "source": [ "# Section 2: Correlation Analysis\n", "\n", "Beyond visual inspection, we can also quantify the correlation between the ENSO (ONI) and the precipitation anomaly for a region of our interest.\n", "\n", "Let's use the Niño3.4 region as an example to calculate the correlation berween precipitation and ONI.\n" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "execution": {}, "tags": [] }, "outputs": [], "source": [ "# extract precipitation data for the Niño 3.4 region & the same time period with ONI data\n", "precip_nino34 = precip.sel(\n", " latitude=slice(-5, 5),\n", " longitude=slice(190, 240),\n", " time=slice(\"1981-09-01\", \"2022-12-01\"),\n", ")\n", "precip_nino34" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "execution": {}, "tags": [] }, "outputs": [], "source": [ "# calculate regional mean of the precipitation anomaly\n", "precip_nino34_mean = precip_nino34.mean((\"latitude\", \"longitude\"))\n", "\n", "# extract ONI values for the common period (ending at 2022-12-01)\n", "nino34 = oni.sel(time=slice(\"1981-09-01\", \"2022-12-01\"))" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "execution": {}, "tags": [] }, "outputs": [], "source": [ "# set up two subplots that share the x-axis to compare precipitation anomaly and ONI index\n", "fig, axs = plt.subplots(2, sharex=True)\n", "\n", "# aesthetics upper plot\n", "fig.suptitle(\"GPCP Precipitation Anomaly v.s. Oceanic Niño Index\")\n", "axs[0].plot(precip_nino34_mean.time, precip_nino34_mean.precip)\n", "axs[0].set_ylabel(\"Precipitation\\n(mm/day)\")\n", "axs[0].axhline(y=0, color=\"k\", linestyle=\"dashed\")\n", "\n", "# draw ONI in lower plot\n", "axs[1].plot(nino34.time, nino34.sst)\n", "# aesthetics lower plot\n", "axs[1].set_ylabel(\"ONI (°C)\")\n", "axs[1].set_xlabel(\"Time (months)\")\n", "axs[1].axhline(y=0, color=\"k\", linestyle=\"dashed\")" ] }, { "cell_type": "markdown", "metadata": { "execution": {} }, "source": [ "From theses two time series, a pattern exists of a synchronized change in the precipitation anomaly and ONI. Now, we can generate a scatter plot to further examine this relationship.\n" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "execution": {}, "tags": [] }, "outputs": [], "source": [ "# set up a scatter plot\n", "fig, ax = plt.subplots()\n", "\n", "# scatter ONI index vs. precipitation\n", "ax.scatter(nino34.sst, precip_nino34_mean.precip, alpha=0.6)\n", "\n", "# add horizontal and vertical lines of 0 values\n", "ax.axhline(y=0, linestyle=\"dashed\", color=\"k\", alpha=0.6)\n", "ax.axvline(x=0, linestyle=\"dashed\", color=\"k\", alpha=0.6)\n", "ax.axvline(x=0.5, linestyle=\"dashed\", color=\"r\", alpha=0.6) # El Nino threshold\n", "ax.axvline(x=-0.5, linestyle=\"dashed\", color=\"b\", alpha=0.6) # La Nina threshold\n", "\n", "# aesthetics\n", "fig.suptitle(\"GPCP Precipitation Anomaly v.s. Oceanic Niño Index\")\n", "ax.set_xlabel(\"ONI (°C)\")\n", "ax.set_ylabel(\"Precipitation anomaly\\n(mm/day)\")\n", "\n", "# add La Niña and El Niño annotations for more accessibility\n", "ax.annotate('El Niño',\n", " xy = (1, 1),\n", " xycoords = 'axes fraction',\n", " xytext = (0.8, 0.75),\n", " textcoords = 'axes fraction',\n", " alpha = 0.5, color = 'r')\n", "ax.annotate('La Niña',\n", " xy=(1, 1),\n", " xycoords='axes fraction',\n", " xytext=(0.1, 0.75),\n", " textcoords='axes fraction',\n", " alpha = 0.5, color = 'darkblue')" ] }, { "cell_type": "markdown", "metadata": { "execution": {} }, "source": [ "The scatter plot unveils a nonlinear relationship between precipitation anomalies and the ONI across different ENSO phases:\n", "\n", "- During the La Niña phase (i.e., when ONI values fall below -0.5/ the blue line), the Niño 3.4 region typically experiences below-average precipitation.\n", "- In contrast, during the El Niño phase (i.e., when ONI values rise above 0.5/ the red line), the Nino 3.4 region is inclined towards above-average precipitation.\n", "\n", "Although the overall relationship is nonlinear, we are only interested in the data during different ENSO phases (ONI above and below 0.5). Looking at this data separately, visually a linear fit seems appropriate. For your projects, you should check this is so by looking at the distribution of the **residuals of the linear fit**. The residuals are the difference between a dataset predicted by the linear model you will find during the regression process and the true data. If the fit is good, there should be no relationship between these two (i.e. the distribution of residuals should have little to no correlation with your data. For simplicity, we skip this step here.\n", "\n", "After you separate the data, you can have a look at the correlation coefficient and the associated p-value. This tells us how strongly related changes in the ONI are related to changes in precipitation anomalies. It is a value between -1 and 1, where the sign indicates whether the relationship is positive or negative, and the absolute value quantifies the correlation strength. An absolute value of the correlation coefficient closer to 1 indicates a stronger correlation. A low p-value will then assure us that the likelihood of the correlation we find being purely due to chance is very low.\n", "\n", "First, let us separate our data into El Niño and La Niña phases by using the ONI as a threshold.\n" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "execution": {}, "tags": [] }, "outputs": [], "source": [ "# El Nino Data, logically index to keep ONI values above 0.5\n", "el_nino_sst = nino34.sst[nino34.sst > 0.5]\n", "el_nino_precip = precip_nino34_mean.precip[nino34.sst > 0.5]\n", "\n", "# La Nina Data, logically index to keep ONI values below -0.5\n", "la_nina_sst = nino34.sst[nino34.sst < -0.5]\n", "la_nina_precip = precip_nino34_mean.precip[nino34.sst < -0.5]" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "execution": {}, "tags": [] }, "outputs": [], "source": [ "# set up scatter plot for just El Nino and La Nina phases\n", "fig, ax = plt.subplots(figsize=(7, 7))\n", "\n", "ax.scatter(el_nino_sst, el_nino_precip, c=\"r\", alpha=0.6)\n", "ax.scatter(la_nina_sst, la_nina_precip, c=\"b\", alpha=0.6)\n", "\n", "# add horizontal and vertical lines of 0 values\n", "ax.axhline(y=0, linestyle=\"dashed\", color=\"k\", alpha=0.6)\n", "ax.axvline(x=0, linestyle=\"dashed\", color=\"k\", alpha=0.6)\n", "ax.axvline(x=0.5, linestyle=\"dashed\", color=\"r\", alpha=0.6) # El Nino threshold\n", "ax.axvline(x=-0.5, linestyle=\"dashed\", color=\"b\", alpha=0.6) # La Nina threshold\n", "# aesthetics\n", "fig.suptitle(\"GPCP Precipitation Anomaly v.s. Oceanic Nino Index\")\n", "ax.set_xlabel(\"ONI (°C)\")\n", "ax.set_ylabel(\"Precipitation anomaly\\n(mm/day)\")\n", "\n", "# add La Niña and El Niño annotations for more accessibility\n", "ax.annotate('El Niño',\n", " xy = (1, 1),\n", " xycoords = 'axes fraction',\n", " xytext = (0.8, 0.75),\n", " textcoords = 'axes fraction',\n", " alpha = 0.5, color = 'r')\n", "ax.annotate('La Niña',\n", " xy=(1, 1),\n", " xycoords='axes fraction',\n", " xytext=(0.1, 0.75),\n", " textcoords='axes fraction',\n", " alpha = 0.5, color = 'darkblue')" ] }, { "cell_type": "markdown", "metadata": { "execution": {} }, "source": [ "Now find the linear correlation coefficient by applying [`pearsonr()`](https://docs.scipy.org/doc/scipy/reference/generated/scipy.stats.pearsonr.html) from the [SciPy stats package](https://docs.scipy.org/doc/scipy/tutorial/stats.html).\n" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "execution": {}, "tags": [] }, "outputs": [], "source": [ "# correlation coeff for El Nino data\n", "el_nino_r, el_nino_p = stats.pearsonr(el_nino_sst, el_nino_precip)\n", "\n", "print(\"El Niño - Corr Coef: \" + str(el_nino_r) + \", p-val: \" + str(el_nino_p))\n", "\n", "# correlation coeff for La Nina data\n", "la_nina_r, la_nina_p = stats.pearsonr(la_nina_sst, la_nina_precip)\n", "\n", "print(\"La Niña - Corr Coef: \" + str(la_nina_r) + \", p-val: \" + str(la_nina_p))" ] }, { "cell_type": "markdown", "metadata": { "execution": {} }, "source": [ "## Questions 2: Climate Connection\n", "\n", "1. Note that the correlation during La Niña phases is low with a higher p-value (less significant) than the correlation coefficient during El Niño phases. Explain what this means.\n", "2. Do the differences in correlation coefficients between phases line up with the time series above? Explain why.\n" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "execution": {}, "tags": [] }, "outputs": [], "source": [ "# to_remove explanation\n", "\n", "\"\"\"\n", "1. The low correlation between the La Niña phase and precipitation suggests that there is not a strong relationship between the two. However, the stronger and more significant correlation between El Niño and precipitation anomalies suggests that there is a more robust relationship between the two. This aligns with our physical understanding of how atmospheric convection and therefore precipitation is affected which we learned about in Day 2.\n", "2. It does. In the time series, we note that when there are peaks in the ONI, indicating an El Niño phase, there are generally peaks in the precipitation anomaly as well. However, for La Niña events, when there are troughs in the ONI data, there is much less agreement with the precipitation anomalies.\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_2\")" ] }, { "cell_type": "markdown", "metadata": { "execution": {} }, "source": [ "## Coding Exercises 2\n", "\n", "1. Choose a region of your interest to examine the relationship between ENSO (using ONI data) and precipitation anomaly globally. It will be interesting to see if the figures you make line up with your expectations from the maps we have made in the beginning of the tutorial. Will they be more or less correlated that the Niño 3.4 region? In the example code we will use Italy, but you can change this to be whatever region you are interested in.\n" ] }, { "cell_type": "markdown", "metadata": { "colab_type": "text", "execution": {}, "tags": [] }, "source": [ "```python\n", "# define region of interest for the precipitation anomaly\n", "italy_lon = [...,...]\n", "italy_lat = [...,...]\n", "\n", "# calculate regional mean time series\n", "precip_nino34_italy = ...\n", "\n", "# plot the time series of precipitation anomaly and ONI for the same time period on different subplots\n", "fig, axs = plt.subplots(2, sharex=True)\n", "# set title\n", "fig.suptitle(\"GPCP Precipitation Anomaly v.s. Oceanic Niño Index\")\n", "\n", "# draw precipitation data\n", "_ = ...\n", "# upper plot aesthetics\n", "axs[0].set_ylabel(\"Precipitation\\n(mm/day)\")\n", "axs[0].axhline(y=0, color=\"k\", linestyle=\"dashed\")\n", "\n", "# draw ONI data\n", "_ = ...\n", "# lower plot aesthetics\n", "axs[1].set_ylabel(\"ONI (°C)\")\n", "axs[1].set_xlabel(\"Time (months)\")\n", "axs[1].axhline(y=0, color=\"k\", linestyle=\"dashed\")\n", "\n", "# El Nino Data, select ONI values above 0.5 via boolean indexing\n", "# (https://pandas.pydata.org/pandas-docs/stable/user_guide/indexing.html#boolean-indexing)\n", "italy_el_nino_sst = ...\n", "italy_el_nino_precip = ...\n", "# La Nina Data, select ONI values below 0.5 via boolean indexing\n", "italy_la_nina_sst = ...\n", "italy_la_nina_precip = ...\n", "\n", "# correlation for El Nino data\n", "italy_el_nino_r = ...\n", "italy_el_nino_p = ...\n", "print(\"El Niño - Corr Coef: \" + str(italy_el_nino_r) + \", p-val: \" + str(italy_el_nino_p))\n", "\n", "# correlation for La Nina data\n", "italy_la_nina_r = ...\n", "italy_la_nina_p = ...\n", "print(\"La Niña - Corr Coef: \" + str(italy_la_nina_r) + \", p-val: \" + str(italy_la_nina_p))\n", "\n", "# scatter plot: precipitation vs. ONI\n", "fig, ax = plt.subplots()\n", "fig.suptitle(\"GPCP Precipitation Anomaly v.s. Oceanic Nino Index\")\n", "_ = ...\n", "_ = ...\n", "\n", "# add horizontal and vertical lines of 0 values\n", "ax.axhline(y=0, linestyle=\"dashed\", color=\"k\", alpha=0.6)\n", "ax.axvline(x=0, linestyle=\"dashed\", color=\"k\", alpha=0.6)\n", "ax.axvline(x=0.5, linestyle=\"dashed\", color=\"r\", alpha=0.6) # El Nino threshold\n", "ax.axvline(x=-0.5, linestyle=\"dashed\", color=\"b\", alpha=0.6) # La Nina threshold\n", "# labels\n", "ax.set_xlabel(\"ONI (°C)\")\n", "ax.set_ylabel(\"Precipitation Anomaly\\n(mm/day)\")\n", "\n", "```" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "execution": {}, "tags": [] }, "outputs": [], "source": [ "# to_remove solution\n", "\n", "# define region of interest for the precipitation anomaly\n", "italy_lon = [6, 19]\n", "italy_lat = [36, 48]\n", "\n", "# calculate regional mean time series\n", "precip_nino34_italy = precip.sel(\n", " latitude=slice(italy_lat[0], italy_lat[1]),\n", " longitude=slice(italy_lon[0], italy_lon[1]),\n", " time=slice(\"1981-09-01\", \"2022-12-01\"),\n", ").mean(dim=(\"latitude\", \"longitude\"))\n", "\n", "# plot the time series of precipitation anomaly and ONI for the same time period on different subplots\n", "fig, axs = plt.subplots(2, sharex=True)\n", "# set title\n", "fig.suptitle(\"GPCP Precipitation Anomaly v.s. Oceanic Niño Index\")\n", "\n", "# draw precipitation data\n", "_ = axs[0].plot(precip_nino34_italy.time, precip_nino34_italy.precip)\n", "# upper plot aesthetics\n", "axs[0].set_ylabel(\"Precipitation\\n(mm/day)\")\n", "axs[0].axhline(y=0, color=\"k\", linestyle=\"dashed\")\n", "\n", "# draw ONI data\n", "_ = axs[1].plot(nino34.time, nino34.sst)\n", "# lower plot aesthetics\n", "axs[1].set_ylabel(\"ONI (°C)\")\n", "axs[1].set_xlabel(\"Time (months)\")\n", "axs[1].axhline(y=0, color=\"k\", linestyle=\"dashed\")\n", "\n", "# El Nino Data, select ONI values above 0.5 via boolean indexing\n", "# (https://pandas.pydata.org/pandas-docs/stable/user_guide/indexing.html#boolean-indexing)\n", "italy_el_nino_sst = nino34.sst[nino34.sst > 0.5]\n", "italy_el_nino_precip = precip_nino34_italy.precip[nino34.sst > 0.5]\n", "\n", "# La Nina Data, select ONI values below 0.5 via boolean indexing\n", "italy_la_nina_sst = nino34.sst[nino34.sst < -0.5]\n", "italy_la_nina_precip = precip_nino34_italy.precip[nino34.sst < -0.5]\n", "\n", "# correlation for El Nino data\n", "italy_el_nino_r = stats.pearsonr(italy_el_nino_sst, italy_el_nino_precip)[0]\n", "italy_el_nino_p = stats.pearsonr(italy_el_nino_sst, italy_el_nino_precip)[1]\n", "print(\"El Niño - Corr Coef: \" + str(italy_el_nino_r) + \", p-val: \" + str(italy_el_nino_p))\n", "\n", "# correlation for La Nina data\n", "italy_la_nina_r = stats.pearsonr(italy_la_nina_sst, italy_la_nina_precip)[0]\n", "italy_la_nina_p = stats.pearsonr(italy_la_nina_sst, italy_la_nina_precip)[1]\n", "print(\"La Niña - Corr Coef: \" + str(italy_la_nina_r) + \", p-val: \" + str(italy_la_nina_p))\n", "\n", "# scatter plot: precipitation vs. ONI\n", "fig, ax = plt.subplots()\n", "fig.suptitle(\"GPCP Precipitation Anomaly v.s. Oceanic Nino Index\")\n", "_ = ax.scatter(italy_el_nino_sst, italy_el_nino_precip, c=\"r\", alpha=0.6)\n", "_ = ax.scatter(italy_la_nina_sst, italy_la_nina_precip, c=\"b\", alpha=0.6)\n", "\n", "# add horizontal and vertical lines of 0 values\n", "ax.axhline(y=0, linestyle=\"dashed\", color=\"k\", alpha=0.6)\n", "ax.axvline(x=0, linestyle=\"dashed\", color=\"k\", alpha=0.6)\n", "ax.axvline(x=0.5, linestyle=\"dashed\", color=\"r\", alpha=0.6) # El Nino threshold\n", "ax.axvline(x=-0.5, linestyle=\"dashed\", color=\"b\", alpha=0.6) # La Nina threshold\n", "# labels\n", "ax.set_xlabel(\"ONI (°C)\")\n", "ax.set_ylabel(\"Precipitation Anomaly\\n(mm/day)\")" ] }, { "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_2\")" ] }, { "cell_type": "markdown", "metadata": { "execution": {} }, "source": [ "# Summary\n", "\n", "In this tutorial, you've acquired skills to evaluate the connection between precipitation and large-scale climate variability by analyzing the statistical correlation between the Oceanic Nino Index (ONI) and precipitation data.\n", "\n", "- You've discovered that during ENSO, precipitation patterns in the tropics are altered.\n", "- You have used Pearson's correlation coefficient to investigate potential correlations. However, it's critical to further scrutinize these correlations with physical explanations to ensure that any detected signals are valid.\n" ] }, { "cell_type": "markdown", "metadata": { "execution": {} }, "source": [ "# Resources\n" ] }, { "cell_type": "markdown", "metadata": { "execution": {} }, "source": [ "Data from this tutorial can be accessed for OISST [here](https://www.ncei.noaa.gov/products/optimum-interpolation-sst) and precipitation [here](https://noaa-cdr-precip-gpcp-monthly-pds.s3.amazonaws.com/index.html#data/).\n" ] } ], "metadata": { "colab": { "collapsed_sections": [], "include_colab_link": true, "name": "W1D3_Tutorial7", "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" } }, "nbformat": 4, "nbformat_minor": 4 }