{
"cells": [
{
"cell_type": "markdown",
"metadata": {
"execution": {}
},
"source": [
"[](https://colab.research.google.com/github/neuromatch/climate-course-content/blob/main/tutorials/W1D4_Paleoclimate/student/W1D4_Tutorial2.ipynb)
"
]
},
{
"cell_type": "markdown",
"metadata": {
"execution": {}
},
"source": [
"# Tutorial 2: Reconstructing Past Changes in Ocean Climate\n",
"**Week 1, Day 4, Paleoclimate**\n",
"\n",
"**Content creators:** Sloane Garelick\n",
"\n",
"**Content reviewers:** Yosmely Bermúdez, Dionessa Biton, Katrina Dobson, Maria Gonzalez, Will Gregory, Nahid Hasan, Paul Heubel, Sherry Mi, Beatriz Cosenza Muralles, Brodie Pearson, Jenna Pearson, Chi Zhang, Ohad Zivan \n",
"\n",
"**Content editors:** Yosmely Bermúdez, Paul Heubel, Zahra Khodakaramimaghsoud, Jenna Pearson, Agustina Pesce, 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"
]
},
{
"attachments": {},
"cell_type": "markdown",
"metadata": {
"execution": {}
},
"source": [
"# Tutorial Objectives\n",
"\n",
"*Estimated timing of tutorial:* 20 minutes\n",
"\n",
"In the previous days, you learned about the El Niño–Southern Oscillation (ENSO), and have explored how satellite data can be employed to track this phenomenon during the instrumental period. In this tutorial, you will explore how oxygen isotopes of corals can record temperature changes associated with the phase of ENSO even further back in time.\n",
"\n",
"By the end of this tutorial you will be able to:\n",
"\n",
"* Understand the types of marine proxies that are used to reconstruct past climate\n",
"* Create a stacked plot and warming stripes to visualize ENSO temperature reconstructions\n",
"\n",
"\n",
"\n",
"### An Overview of Isotopes in Paleoclimate\n",
"\n",
"In this tutorial, and many of the remaining tutorials on this day, you will be looking at data of hydrogen and oxygen isotopes (δD and δ18O). As you learned in the video, isotopes are forms of the same element that contain the same numbers of protons but different numbers of neutrons. The two oxygen isotopes that are most commonly used in paleoclimate are oxygen 16 (16O), which is the which is the **\"lighter\"** oxygen isotope, and oxygen 18 (18O), which is the **\"heavier\"** oxygen isotope. The two hydrogen isotopes that are most commonly used in paleoclimate are hydrogen (H), which is the **\"lighter\"** oxygen isotope, and deuterium (D), which is the **\"heavier\"** oxygen isotope. \n",
"\n",
"\n",
"\n",
"Credit: [NASA Climate Science Investigations](https://www.ces.fau.edu/nasa/module-3/how-is-temperature-measured/isotopes.php)\n",
"\n",
"\n",
"\n",
"Credit: [NASA Climate Science Investigations](https://www.ces.fau.edu/nasa/module-3/how-is-temperature-measured/isotopes.php)\n",
"\n",
"Changes in the ratio of the heavy to light isotope can reflect changes in different climate variables, depending on geographic location and the material being measured. The ratio is represented in delta notation (δ) and in units of per mille (‰), and is calculated using the equation below (the same applies to the ratio of the heavy and light hydrogen isotopes):\n",
"\n",
"\n",
"\n",
"\n",
"The terminology for discussing δ18O and δD can be a bit confusing and there are multiple ways to reference the same trends in the data. The most common terms used to describe isotopic compositions are **\"depleted\"** and **\"enriched\"**. These terms refer to the relative amount of the heavy isotopes. Therefore, a \"more depleted\" isotopic value is more depleted in the heavy isotope (i.e., there is less of the heavy isotope), whereas a \"more enriched\" isotopic value is more enriched in the heavy isotope (i.e., there is more of the heavy isotope). Other terms that are sometimes used to describe whether isotopes are depleted or enriched are **\"more negative\"** or **\"more positive\"**. Isotopic values can be both positive and negative, so using \"more negative\" and \"more positive\" can be a bit confusing. For example, if we have isotopic values of -15‰ and -9‰, the value of -9‰ is \"more enriched\" (i.e., has more of the heavy isotope) or \"more positive\" (i.e., is closer to zero and positive values) than -15‰. Finally, the terms **\"smaller\"** or **\"larger\"** isotopic values can also be used to reference isotopes.\n",
"\n",
"Additional information about the use of isotopes in paleoclimate can be found [here](https://earthobservatory.nasa.gov/features/Paleoclimatology_OxygenBalance).\n",
"\n"
]
},
{
"cell_type": "markdown",
"metadata": {
"execution": {}
},
"source": [
"# Setup\n"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"execution": {}
},
"outputs": [],
"source": [
"# installations ( uncomment and run this cell ONLY when using google colab or kaggle )\n",
"\n",
"# !pip install cartopy\n",
"# !pip install pyleoclim"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"execution": {}
},
"outputs": [],
"source": [
"# imports\n",
"import pandas as pd\n",
"import numpy as np\n",
"import pooch\n",
"import os\n",
"import tempfile\n",
"import pyleoclim as pyleo\n",
"import matplotlib.pyplot as plt\n",
"import cartopy.crs as ccrs\n",
"import cartopy.feature as cfeature\n",
"from matplotlib import patches"
]
},
{
"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 = \"W1D4_T2\""
]
},
{
"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",
"def pooch_load(filelocation=None, filename=None, processor=None):\n",
" shared_location = \"/home/jovyan/shared/Data/tutorials/W1D4_Paleoclimate\" # 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": [
"## Video 1: Ocean Climate Proxies\n"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"cellView": "form",
"execution": {},
"tags": [
"remove-input"
]
},
"outputs": [],
"source": [
"# @title Video 1: Ocean Climate Proxies\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', 'VChIvgdwZbQ'), ('Bilibili', 'BV1cm4y1E7RF')]\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}_Ocean_Climate_Proxies_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 = \"qtkbv\"\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}_Ocean_Climate_Proxies_Slides\")"
]
},
{
"cell_type": "markdown",
"metadata": {
"execution": {}
},
"source": [
"# Section 1: Assessing Variability Related to El Niño Using Pyleoclim Series\n",
"\n",
"ENSO is a recurring climate pattern involving changes in SST in the central and eastern tropical Pacific Ocean. As we learned in the introductory video, oxygen isotopes ([δ18O](https://en.wikipedia.org/wiki/Δ18O)) of corals are a commonly used proxy for reconstructing changes in tropical Pacific SST and ENSO. Long-lived corals are well-suited for studying paleo-ENSO variability because they store decades to centuries of sub-annually resolved proxy information in the tropical Pacific. The oxygen isotopes of corals are useful for studying ENSO because they record changes in sea-surface temperature (SST), with more positive values of δ18O corresponding to colder SSTs, and vice-versa.\n",
"\n",
"One approach for detecting ENSO from coral isotope data is applying a 2- to 7-year bandpass filter to the δ18O records to highlight ENSO-related variability and compare (quantitatively) the bandpassed coral records to the Oceanic Niño Index (ONI) you learned about in Day 2 and Day 3. While we won't be going into this amount of detail, you may utilize the methods sections of these papers as a guide: [Cobb et al.(2003)](https://www.nature.com/articles/nature01779), [Cobb et al.(2013)](https://www.science.org/doi/10.1126/science.1228246). In this tutorial, we will be looking at the δ18O records and comparing them to a plot of the ONI without this band-pass filtering, in part to highlight why the filtering is needed."
]
},
{
"cell_type": "markdown",
"metadata": {
"execution": {}
},
"source": [
"## Section 1.1: Load coral oxygen isotope proxy reconstructions\n",
"\n",
"The two coral records we'll look at are from [Palmyra Atoll](https://en.wikipedia.org/wiki/Palmyra_Atoll) and [Line Islands](https://en.wikipedia.org/wiki/Line_Islands), both of which are in the tropical central Pacific Ocean.\n",
"\n",
"Let's plot these approximate locations as well as the Niño 3.4 region you are familiar with from the first three days."
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"execution": {}
},
"outputs": [],
"source": [
"# select data for the month of interest\n",
"# data = precip.sel(time='1979-01-01', method='nearest')\n",
"\n",
"# initate plot\n",
"fig = plt.figure()\n",
"\n",
"# set base map projection\n",
"ax = plt.axes(projection=ccrs.Robinson(central_longitude=180))\n",
"\n",
"# add background image to show land and sea\n",
"ax.stock_img()\n",
"\n",
"# add coastlines\n",
"ax.add_feature(cfeature.COASTLINE)\n",
"\n",
"# add in rectangle showing Nino 3.4 region\n",
"rectangle = patches.Rectangle(\n",
" (170, -5),\n",
" 50,\n",
" 10,\n",
" transform=ccrs.Geodetic(),\n",
" edgecolor=\"k\",\n",
" facecolor=\"none\",\n",
" linewidth=3,\n",
")\n",
"ax.add_patch(rectangle)\n",
"\n",
"rx, ry = rectangle.get_xy()\n",
"cx = rx + rectangle.get_width() / 2.0\n",
"cy = ry + rectangle.get_height() / 2.0\n",
"\n",
"# add labels\n",
"ax.annotate(\n",
" \"Nino 3.4\",\n",
" (cx - 10, cy),\n",
" color=\"w\",\n",
" transform=ccrs.PlateCarree(),\n",
" weight=\"bold\",\n",
" fontsize=10,\n",
" ha=\"center\",\n",
" va=\"center\",\n",
")\n",
"\n",
"# add the proxy locations\n",
"ax.scatter(\n",
" [-162.078333], [5.883611], transform=ccrs.Geodetic(), s=50, marker=\"v\", color=\"w\"\n",
")\n",
"ax.scatter([-157.2], [1.7], transform=ccrs.Geodetic(), s=50, marker=\"v\", color=\"w\")\n",
"\n",
"# add labels\n",
"ax.annotate(\n",
" \"Palmyra Atoll\",\n",
" (-170, 10),\n",
" color=\"w\",\n",
" transform=ccrs.Geodetic(),\n",
" weight=\"bold\",\n",
" fontsize=10,\n",
" ha=\"center\",\n",
" va=\"center\",\n",
")\n",
"\n",
"ax.annotate(\n",
" \"Line Islands\",\n",
" (-144, -1),\n",
" color=\"w\",\n",
" transform=ccrs.Geodetic(),\n",
" weight=\"bold\",\n",
" fontsize=10,\n",
" ha=\"center\",\n",
" va=\"center\",\n",
")\n",
"\n",
"# change the map view to zoom in on central Pacific\n",
"ax.set_extent((120, 300, -25, 25), crs=ccrs.PlateCarree())"
]
},
{
"cell_type": "markdown",
"metadata": {
"execution": {}
},
"source": [
"To analyze and visualize paleoclimate proxy time series, we will be using [Pyleoclim](https://pyleoclim-util.readthedocs.io/en/latest/). Pycleoclim is specifically designed for the analysis of paleoclimate data. The package is designed around [objects](https://docs.python.org/3.9/tutorial/classes.html) called `Series`, which can be directly manipulated for plotting and time series-appropriate analysis and operation. \n",
"\n",
"The `Series` object describes the fundamentals of a time series. To create a Pyleoclim `Series`, we first need to load the data set, and then specify values for its various properties:\n",
"\n",
"* `time`: Time values for the time series\n",
"* `value`: Paleo values for the time series\n",
"* `time_name` (optional): Name of the time vector, (e.g., 'Time', 'Age'). This is used to label the x-axis on plots\n",
"* `time_unit` (optional): The units of the time axis (e.g., 'years')\n",
"* `value_name` (optional): The name of the paleo variable (e.g., 'Temperature')\n",
"* `value_unit` (optional): The units of the paleo variable (e.g., 'deg C')\n",
"* `label` (optional): Name of the time series (e.g., 'Nino 3.4')\n",
"* `clean_ts` (optional): If True (default), remove NaNs and set an increasing time axis\n",
"\n",
"A common data format for datasets downloaded from the *NOAA Paleoclimate Database* is a templated text file, which contains helpful data and metadata. \n",
"\n",
"Take a look at our two datasets [here](https://www.ncei.noaa.gov/pub/data/paleo/coral/east_pacific/palmyra_2003.txt) and [here](https://www.ncei.noaa.gov/pub/data/paleo/coral/east_pacific/cobb2013-fan-modsplice-noaa.txt).\n",
"\n",
"The functionality in python allows us to ignore all of the information at the beginning of the text files, and we can load the data directly into a `pandas.DataFrame` using `.read_csv()`.\n",
"\n",
"### Section 1.1.1: Load Palmyra coral data"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"execution": {},
"executionInfo": {
"elapsed": 1031,
"status": "ok",
"timestamp": 1681584691666,
"user": {
"displayName": "Sloane Garelick",
"userId": "04706287370408131987"
},
"user_tz": 240
}
},
"outputs": [],
"source": [
"# download the data using the url\n",
"filename_Palmyra = \"palmyra_2003.txt\"\n",
"url_Palmyra = (\n",
" \"https://www.ncei.noaa.gov/pub/data/paleo/coral/east_pacific/palmyra_2003.txt\"\n",
")\n",
"data_path = pooch_load(\n",
" filelocation=url_Palmyra, filename=filename_Palmyra\n",
") # open the file\n",
"\n",
"# from the data set, we only want the data related to Modern Living Coral.\n",
"# this data is between row 6190 and 7539 of the dataset\n",
"rows = [int(row) for row in np.linspace(6190, 7539, 7539 - 6190 + 1)]\n",
"\n",
"# use pandas to read in the csv file\n",
"palmyra = pd.read_csv(\n",
" data_path,\n",
" skiprows=lambda x: x\n",
" not in rows, # number of rows to skip based on definition of rows above\n",
" sep=\"\\s+\", # how the data values are seperated (delimited) : '\\s+' = space\n",
" encoding=\"ISO-8859-1\",\n",
" names=[\"CalendarDate\", \"d180\"],\n",
" header=None,\n",
")\n",
"# print first few rows of df\n",
"palmyra.head()"
]
},
{
"cell_type": "markdown",
"metadata": {
"execution": {}
},
"source": [
"Now that we have the data in a dataframe, we can pull the relevant columns of this datframe into a `Series` object in Pyleoclim, which will allow us to organize the relevant metadata so that we can get a well-labeled, publication-quality plot:"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"execution": {}
},
"outputs": [],
"source": [
"ts_palmyra = pyleo.Series(\n",
" time=palmyra[\"CalendarDate\"],\n",
" value=palmyra[\"d180\"],\n",
" time_name=\"Calendar date\",\n",
" time_unit=\"Years\",\n",
" value_name=r\"$d18O$\",\n",
" value_unit=\"per mille\",\n",
" label=\"Palmyra Coral\",\n",
")"
]
},
{
"cell_type": "markdown",
"metadata": {
"execution": {}
},
"source": [
"Since we want to compare datasets based on different measurements (coral δ18O and the ONI, i.e., a temperature anomaly), it's helpful to standardize the data by removing it's estimated mean and dividing by its estimated standard deviation. Thankfully Pyleoclim has a [function](https://pyleoclim-util.readthedocs.io/en/v0.7.4/core/ui.html#pyleoclim.core.ui.Series.standardize) to do that for us."
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"execution": {}
},
"outputs": [],
"source": [
"palmyra_stnd = ts_palmyra.standardize()\n",
"palmyra_stnd"
]
},
{
"cell_type": "markdown",
"metadata": {
"execution": {}
},
"source": [
"### Section 1.1.2: Load Line Island coral data\n",
"\n",
"We will repeat these steps for the other dataset."
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"execution": {}
},
"outputs": [],
"source": [
"# Download the data using the url\n",
"filename_cobb2013 = \"cobb2013-fan-modsplice-noaa.txt\"\n",
"url_cobb2013 = \"https://www.ncei.noaa.gov/pub/data/paleo/coral/east_pacific/cobb2013-fan-modsplice-noaa.txt\"\n",
"data_path2 = pooch_load(\n",
" filelocation=url_cobb2013, filename=filename_cobb2013\n",
") # open the file\n",
"\n",
"# From the data set, we only want the data related to Modern Living Coral.\n",
"# So this data is between row 6190 and 7539 of the dataset\n",
"rows = [int(row) for row in np.linspace(127, 800, 800 - 127 + 1)]\n",
"line = pd.read_csv(\n",
" data_path2,\n",
" skiprows=lambda x: x not in rows,\n",
" sep=\"\\s+\",\n",
" encoding=\"ISO-8859-1\",\n",
" names=[\"age\", \"d18O\"],\n",
" header=None,\n",
")\n",
"# print first few rows of df\n",
"line.head()"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"execution": {}
},
"outputs": [],
"source": [
"ts_line = pyleo.Series(\n",
" time=line[\"age\"],\n",
" value=line[\"d18O\"],\n",
" time_name=\"Calendar date\",\n",
" time_unit=\"Years\",\n",
" value_name=r\"$d18O$\",\n",
" value_unit=\"per mille\",\n",
" label=\"Line Island Coral\",\n",
")"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"execution": {}
},
"outputs": [],
"source": [
"line_stnd = ts_line.standardize()\n",
"line_stnd"
]
},
{
"cell_type": "markdown",
"metadata": {
"execution": {}
},
"source": [
"# Section 2: Plot the Data Using Multiseries\n",
"\n",
"We will utilize the built in features of a [multiseries](https://pyleoclim-util.readthedocs.io/en/latest/core/api.html#multipleseries-pyleoclim-multipleseries) object to plot our coral proxy data side by side. To create a `pyleo.MultipleSeries`, we first create a list with our `pyleo.Series` objects and then pass this into a `pyleo.MultipleSeries`."
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"execution": {}
},
"outputs": [],
"source": [
"# combine into a list\n",
"nino_comparison = [palmyra_stnd, line_stnd]"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"execution": {}
},
"outputs": [],
"source": [
"# create multiseries\n",
"nino = pyleo.MultipleSeries(nino_comparison, name=\"El Nino Comparison\")"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"execution": {},
"executionInfo": {
"elapsed": 942,
"status": "ok",
"timestamp": 1681584722114,
"user": {
"displayName": "Sloane Garelick",
"userId": "04706287370408131987"
},
"user_tz": 240
}
},
"outputs": [],
"source": [
"# plot the time series of both datasets\n",
"fig, ax = nino.stackplot(time_unit=\"year\", xlim=[1960, 2000], colors=[\"b\", \"g\"])"
]
},
{
"cell_type": "markdown",
"metadata": {
"execution": {}
},
"source": [
"## Questions 2: Climate Connection\n",
"\n",
"Recall that as SST becomes colder, δ18O becomes more positive, and vice versa. Compare the figure below of the ONI to the time series of coral δ18O you plotted above and answer the questions below.\n",
"\n",
"\n",
"\n",
"Credit: [UCAR](https://climatedataguide.ucar.edu/sites/default/files/styles/extra_large/public/2022-03/indices_oni_2_2_lg.png?itok=Zew3VK_4)\n",
"\n",
"1. Do the ENSO events recorded by the ONI agree with the coral data?\n",
"2. What are some considerations you can think of when comparing proxies such as this to the ONI?\n"
]
},
{
"cell_type": "markdown",
"metadata": {
"colab_type": "text",
"execution": {}
},
"source": [
"[*Click for solution*](https://github.com/neuromatch/climate-course-content/tree/main/tutorials/W1D4_Paleoclimate/solutions/W1D4_Tutorial2_Solution_8f319b78.py)\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}_Questions_2\")"
]
},
{
"cell_type": "markdown",
"metadata": {
"execution": {}
},
"source": [
"# Section 3: Make Warming Stripes Plot"
]
},
{
"cell_type": "markdown",
"metadata": {
"execution": {}
},
"source": [
"We can also make a warming stripe for this data `Series` using the [`.stripes()`](https://pyleoclim-util.readthedocs.io/en/latest/core/api.html#pyleoclim.core.multipleseries.MultipleSeries.stripes) method, where darker red stripes indicate a warmer eastern Pacific and possibly an El Niño phase, and darker blue stripes indicate a cooler eastern Pacific and possibly La Niña phase. Can you see the trend present in the data?"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"execution": {},
"executionInfo": {
"elapsed": 409,
"status": "ok",
"timestamp": 1681584728212,
"user": {
"displayName": "Sloane Garelick",
"userId": "04706287370408131987"
},
"user_tz": 240
}
},
"outputs": [],
"source": [
"fig, ax = nino.stripes(\n",
" ref_period=(1960, 1990), time_unit=\"year\", show_xaxis=True, cmap=\"RdBu\"\n",
")"
]
},
{
"cell_type": "markdown",
"metadata": {
"execution": {}
},
"source": [
"# Summary\n",
"In this tutorial, we discovered how oxygen isotopes within corals serve as a valuable archive, recording changes in temperature associated with ENSO phases.\n",
"\n",
"During our explorations, \n",
"- We ventured into the study of proxy-based coral δ18O records, gaining insights into the rich historical climate data encapsulated within these marine structures.\n",
"- We compared these records to noted ENSO events over a few decades, offering us a glimpse into the dynamic nature of this influential climate phenomenon."
]
},
{
"cell_type": "markdown",
"metadata": {
"execution": {}
},
"source": [
"# Resources\n",
"\n",
"The code for this tutorial is based on existing notebooks from LinkedEarth that uses the `Pyleoclim` package to [assess variability in El Nino](https://github.com/LinkedEarth/PyleoTutorials/blob/main/notebooks/L0_a_quickstart.ipynb). \n",
"\n",
"Data from the following sources are used in this tutorial:\n",
"\n",
"\n",
"* Cobb,K., et al., Highly Variable El Niño–Southern Oscillation Throughout the Holocene.Science 339, 67-70(2013). https://doi.org/10.1126/science.1228246 accessible [here]( https://www.ncei.noaa.gov/pub/data/paleo/coral/east_pacific/palmyra_2003.txt).\n",
"\n",
"* Cobb, K., Charles, C., Cheng, H. et al. El Niño/Southern Oscillation and tropical Pacific climate during the last millennium. Nature 424, 271–276 (2003). https://doi.org/10.1038/nature01779 accessible [here]( https://www.ncei.noaa.gov/pub/data/paleo/coral/east_pacific/cobb2013-fan-modsplice-noaa.txt)."
]
}
],
"metadata": {
"colab": {
"collapsed_sections": [
"WFp2yBJuVoRr",
"DZbqRlQKXhnc"
],
"include_colab_link": true,
"name": "W1D4_Tutorial2",
"provenance": [
{
"file_id": "1lHuVrVtAW4fQzc0dFdlZuwY0i71KWw_t",
"timestamp": 1677637469824
}
],
"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
}