{ "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/W1D2_Ocean-AtmosphereReanalysis/W1D2_Tutorial5.ipynb)   \"Open" ] }, { "cell_type": "markdown", "metadata": { "execution": {} }, "source": [ "# Tutorial 5: Thermohaline Circulation\n", "\n", "**Week 1, Day 2: Ocean and Atmospheric Reanalysis**\n", "\n", "**Content creators:** Aurora Basinski\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:** NFDI4Earth, CMIP" ] }, { "cell_type": "markdown", "metadata": { "execution": {} }, "source": [ "# Tutorial Objectives\n", "\n", "*Estimated timing of tutorial:* 30 mins\n", "\n", "In the previous tutorial, we discussed how the surface ocean's movement is driven by wind forcing. However, the ocean can also experience movement due to density differences. The large-scale ocean movement driven by these density differences is known as the **_thermohaline circulation_**. The density of ocean water is influenced by temperature (thermo) and salinity (haline), and fluid motion occurs in response to pressure gradients caused by these density variations.\n", "\n", "In this tutorial, we will use ocean surface data for 2014 to 2016 from the [Estimating the Circulation and Climate of the Ocean (ECCO)](https://www.ecco-group.org/) reanalysis dataset to \n", "- Plot sea surface salinity and temperature,\n", "- Understand the relationship between salinity, temperature, and ocean density,\n", "- Explore the difference between linear and non-linear *equations of state*." ] }, { "cell_type": "markdown", "metadata": { "execution": {} }, "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 seaborn\n", "# !pip install cmocean\n", "# !pip install cartopy\n", "# !pip install gsw" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "execution": {}, "executionInfo": { "elapsed": 2058, "status": "error", "timestamp": 1682626613201, "user": { "displayName": "Sloane Garelick", "userId": "04706287370408131987" }, "user_tz": 240 } }, "outputs": [], "source": [ "#import numpy as np\n", "import xarray as xr\n", "import matplotlib.pyplot as plt\n", "import seaborn as sns\n", "from cartopy import crs as ccrs, feature as cfeature\n", "from cartopy.mpl.ticker import LongitudeFormatter, LatitudeFormatter\n", "import cmocean as cmo\n", "import pooch\n", "import os\n", "import tempfile\n", "import gsw" ] }, { "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_T5\"" ] }, { "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: Thermohaline Circulation\n" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "cellView": "form", "execution": {}, "tags": [ "remove-input" ] }, "outputs": [], "source": [ "# @title Video 1: Thermohaline 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', 'cgh6bC2uj58'), ('Bilibili', 'BV1uh4y1j7wN')]\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}_Thermohaline_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 = \"vdeq6\"\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}_Thermohaline_Circulation_Slides\")" ] }, { "cell_type": "markdown", "metadata": { "execution": {} }, "source": [ "# Section 1: Plot Surface Temperature and Salinity\n", "In the slides, we discovered that ocean flows can be driven by density variations in addition to wind-driven circulation. One example of a density-driven flow is the thermohaline circulation. Density in the ocean is influenced by two main factors: \n", "1. Salinity (higher salinity leads to greater density) and \n", "2. Temperature (lower temperature generally results in higher density),\n", "3. Also, pressure affects density (higher pressure results in higher density), but it generally has a much smaller impact on ocean density than temperature and salinity. \n", "\n", "To develop a better understanding of how density varies across different regions, let's examine the average salinity and temperature at the ocean surface.\n", "\n", "First let's load the data." ] }, { "cell_type": "code", "execution_count": null, "metadata": { "execution": {} }, "outputs": [], "source": [ "# import preprocessed ecco data. This is surface data of monthly resolution over the period 2014 to 2016.\n", "# load potential temperature theta\n", "filename_theta = \"surface_theta.nc\"\n", "url_theta = \"https://osf.io/98ksr/download\"\n", "\n", "subset_theta = xr.open_dataset(pooch_load(url_theta, filename_theta))\n", "subset_theta" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "execution": {} }, "outputs": [], "source": [ "# load salinity\n", "filename_salt = \"surface_salt.nc\"\n", "url_salt = \"https://osf.io/aufs2/download\"\n", "\n", "subset_salt = xr.open_dataset(pooch_load(url_salt, filename_salt))\n", "subset_salt" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "execution": {} }, "outputs": [], "source": [ "# make land points NaN (not a number)\n", "subset_theta = subset_theta.where(\n", " subset_theta != 0\n", ") # change anywhere that the value is zero to NaN\n", "subset_salt = subset_salt.where(subset_salt != 0) # same\n", "subset_theta = subset_theta.THETA # choose the variable to remove the dimension\n", "subset_salt = subset_salt.SALT" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "execution": {} }, "outputs": [], "source": [ "# plot Sea Surface Temprature - similar to plots we used in tutorials 2+3\n", "fig, ax = plt.subplots(\n", " subplot_kw={\"projection\": ccrs.PlateCarree()}, dpi=100\n", ") # this is from cartopy https://rabernat.github.io/research_computing_2018/maps-with-cartopy.html\n", "p = subset_theta.plot(\n", " vmin=0,\n", " cmap=cmo.cm.thermal,\n", " cbar_kwargs={\n", " \"shrink\": 0.75,\n", " \"orientation\": \"horizontal\",\n", " \"extend\": \"both\",\n", " \"pad\": 0.185,\n", " \"label\": \"°C\",\n", " },\n", " ax=ax,\n", ")\n", "ax.coastlines(color=\"grey\", lw=0.5)\n", "ax.set_xticks([-180, -120, -60, 0, 60, 120, 180], crs=ccrs.PlateCarree())\n", "ax.set_yticks([-90, -60, -30, 0, 30, 60, 90], crs=ccrs.PlateCarree())\n", "lon_formatter = LongitudeFormatter(zero_direction_label=True)\n", "lat_formatter = LatitudeFormatter()\n", "ax.add_feature(cfeature.LAND, zorder=100, edgecolor=\"k\")\n", "ax.set_title(\"Sea Surface Temperature (2014 – 2016 mean)\")" ] }, { "cell_type": "markdown", "metadata": { "execution": {} }, "source": [ "
\n", "Click here for a description of the plot \n", "Sea surface temperature on average decreases with increasing latitude, so the tropics show temperatures of about $30°\\text{C}$. Along western coastlines, it is additionally decreased due to the upwelling of low-temperature water masses caused by Ekman pumping (see also previous Tutorial 4). Water masses in polar regions are below $0°\\text{C}$ as the salinity decreases the freezing point.\n", "\n", "*** \n", "\n", "
" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "execution": {} }, "outputs": [], "source": [ "# plot Sea Surface Salinity\n", "fig, ax = plt.subplots(\n", " subplot_kw={\"projection\": ccrs.PlateCarree()}, dpi=100\n", ") # this is from cartopy https://rabernat.github.io/research_computing_2018/maps-with-cartopy.html\n", "p = subset_salt.plot(\n", " cmap=cmo.cm.haline,\n", " robust=True,\n", " #vmin=30,\n", " cbar_kwargs={\n", " \"shrink\": 0.75,\n", " \"orientation\": \"horizontal\",\n", " \"extend\": \"both\",\n", " \"pad\": 0.175,\n", " \"label\": \"psu\",\n", " },\n", " ax=ax,\n", ")\n", "ax.coastlines(color=\"grey\", lw=0.5)\n", "ax.set_xticks([-180, -120, -60, 0, 60, 120, 180], crs=ccrs.PlateCarree())\n", "ax.set_yticks([-90, -60, -30, 0, 30, 60, 90], crs=ccrs.PlateCarree())\n", "lon_formatter = LongitudeFormatter(zero_direction_label=True)\n", "lat_formatter = LatitudeFormatter()\n", "ax.add_feature(cfeature.LAND, zorder=100, edgecolor=\"k\")\n", "ax.set_title(\"Sea Surface Salinity (2014 – 2016 mean)\")" ] }, { "cell_type": "markdown", "metadata": { "execution": {} }, "source": [ "
\n", "Click here for a description of the plot \n", "The mean sea surface salinity varies around the average of $35\\perthousand$ with high salinities in the subtropics, the regions of strongest evaporation and minimal precipitation. In contrast, less saline water masses can be found in the polar regions where the precipitation (and sea ice melting) induce a freshwater influx.\n", "\n", "*** \n", "\n", "
" ] }, { "cell_type": "markdown", "metadata": { "execution": {} }, "source": [ "# Section 2: Calculating Density from Salinity & Temperature\n", "The equation relating ocean water density to other water properties is called the ***equation of state***. It is a non-linear function of temperature, salinity, and pressure. This can be expressed as $\\rho=\\rho(T,S,p)$. Here we will show two ways to calculate the density.\n", "\n", "The first is a *linear approximation* to the equation of state. We will then show how to calculate the full, non-linear equation of state using the `gsw` package.\n", "\n", "Note that the [potential temperature](https://glossary.ametsoc.org/wiki/Potential_temperature) $\\theta$ is commonly used in oceanographic calculations, which is why our temperature file is called `surface_theta.nc` and the corresponding variable `THETA`. For the following linearization, we follow the probably more familiar $T$ convention and neglect their difference." ] }, { "cell_type": "markdown", "metadata": { "execution": {} }, "source": [ "## Section 2.1: Linearized Equation of State\n", "Here we take the linearized equation of state from equation 1.57 in Vallis' textbook [\"*Atmospheric and Oceanic Fluid Dynamics*\"](https://www.cambridge.org/core/books/atmospheric-and-oceanic-fluid-dynamics/41379BDDC4257CBE11143C466F6428A4) (not Open-access)\n", "\n", "$$ \\rho=\\rho_0[1-\\beta_T(T-T_0)+\\beta_S(S-S_0)+\\beta_p(p-p_0)] $$\n", "\n", "In this equation, $\\rho_0\\simeq 1027$ is a reference density, $\\beta_T \\simeq 2*10^{-4} /\\text{K} $ is the thermal expansion coefficient, $\\beta_S \\simeq 7.6*10^{-4}/\\text{ppt}$ is the haline contraction coefficient, and $\\beta_p \\simeq 4.4*10^{-10}/\\text{Pa}$ is the compressibility coefficient. The values with subscript $_0$ are reference values, and here we use $T_0 = 283 \\text{K}$ and $S_0=35$. Since surface pressure rarely changes by more than a few percent, let's assume that the pressure at the surface is equal to the reference pressure at every point ($\\beta_p(p-p_0)=0$). *The non-linearities in the full equation of state (which we will use later) arise because, in reality, the $\\beta$ terms themselves vary with pressure, salinity, and temperature.*\n", "\n", "Let's now calculate a global map of surface density using this linear equation of state. Note that since we are using temperature and salinity *datasets*, our result will also be a dataset." ] }, { "cell_type": "code", "execution_count": null, "metadata": { "execution": {} }, "outputs": [], "source": [ "rho_linear = 1027 * (\n", " 1 - 2e-4 * (subset_theta + 273.15 - 283) + 7.6e-4 * (subset_salt - 35)\n", ")\n", "rho_linear" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "execution": {} }, "outputs": [], "source": [ "# plot linearized density\n", "fig, ax = plt.subplots(\n", " subplot_kw={\"projection\": ccrs.PlateCarree()}, dpi=100\n", ") # this is from cartopy https://rabernat.github.io/research_computing_2018/maps-with-cartopy.html\n", "p = rho_linear.plot(\n", " cmap=cmo.cm.dense,\n", " vmin=1021,\n", " vmax=1029,\n", " cbar_kwargs={\n", " \"shrink\": 0.75,\n", " \"orientation\": \"horizontal\",\n", " \"extend\": \"both\",\n", " \"pad\": 0.15,\n", " \"label\": \"Density (kg/m$^3$)\",\n", " },\n", " ax=ax,\n", ")\n", "ax.coastlines(color=\"grey\", lw=0.5)\n", "ax.set_xticks([-180, -120, -60, 0, 60, 120, 180], crs=ccrs.PlateCarree())\n", "ax.set_yticks([-90, -60, -30, 0, 30, 60, 90], crs=ccrs.PlateCarree())\n", "lon_formatter = LongitudeFormatter(zero_direction_label=True)\n", "lat_formatter = LatitudeFormatter()\n", "ax.add_feature(cfeature.LAND, zorder=100, edgecolor=\"k\")\n", "ax.set_title(\"Surface density from linear equation (2014 – 2016 mean)\")" ] }, { "cell_type": "markdown", "metadata": { "execution": {} }, "source": [ "## Section 2.2: Full Nonlinear Equation of State\n", "The full, non-linear equation of state is more complicated than the linear equation we just used. It contains dozens of equations which are impractical to code in this tutorial. Fortunately packages exist to do this calculation!\n", "\n", "Here we will compute surface density from the full nonlinear equation in `python` using the `gsw` package which is a Python implementation of the [Thermodynamic Equation of Seawater 2010 (TEOS-10)](https://teos-10.github.io/GSW-Python/)" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "execution": {} }, "outputs": [], "source": [ "CT = gsw.CT_from_pt(\n", " subset_salt, subset_theta\n", ") # get conservative temperature from potential temperature\n", "rho_nonlinear = gsw.rho(subset_salt, CT, 0)" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "execution": {} }, "outputs": [], "source": [ "# plot density from full nonlinear equation\n", "fig, ax = plt.subplots(\n", " subplot_kw={\"projection\": ccrs.PlateCarree()}, figsize=(11, 12), dpi=100\n", ") # this is from cartopy https://rabernat.github.io/research_computing_2018/maps-with-cartopy.html\n", "p = rho_nonlinear.plot(\n", " cmap=cmo.cm.dense,\n", " vmin=1021,\n", " vmax=1029,\n", " cbar_kwargs={\n", " \"shrink\": 0.75,\n", " \"orientation\": \"horizontal\",\n", " \"extend\": \"both\",\n", " \"pad\": 0.05,\n", " \"label\": \"Density (kg/m$^3$)\",\n", " },\n", " ax=ax,\n", ")\n", "ax.coastlines(color=\"grey\", lw=0.5)\n", "ax.set_xticks([-180, -120, -60, 0, 60, 120, 180], crs=ccrs.PlateCarree())\n", "ax.set_yticks([-90, -60, -30, 0, 30, 60, 90], crs=ccrs.PlateCarree())\n", "lon_formatter = LongitudeFormatter(zero_direction_label=True)\n", "lat_formatter = LatitudeFormatter()\n", "ax.add_feature(cfeature.LAND, zorder=100, edgecolor=\"k\")\n", "ax.set_title(\"Surface density from nonlinear equation (2014-2016 mean)\")\n", "fig.tight_layout()" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "execution": {} }, "outputs": [], "source": [ "# plot difference between linear and non-linear equations of state\n", "fig, ax = plt.subplots(\n", " subplot_kw={\"projection\": ccrs.PlateCarree()}, figsize=(11, 12), dpi=100\n", ") # this is from cartopy https://rabernat.github.io/research_computing_2018/maps-with-cartopy.html\n", "p = (rho_linear - rho_nonlinear).plot(\n", " cmap=\"coolwarm\",\n", " vmin=-3,\n", " vmax=3,\n", " cbar_kwargs={\n", " \"shrink\": 0.75,\n", " \"orientation\": \"horizontal\",\n", " \"extend\": \"both\",\n", " \"pad\": 0.05,\n", " \"label\": \"Density difference (kg/m$^3$)\",\n", " },\n", " ax=ax,\n", ")\n", "ax.coastlines(color=\"grey\", lw=0.5)\n", "ax.set_xticks([-180, -120, -60, 0, 60, 120, 180], crs=ccrs.PlateCarree())\n", "ax.set_yticks([-90, -60, -30, 0, 30, 60, 90], crs=ccrs.PlateCarree())\n", "lon_formatter = LongitudeFormatter(zero_direction_label=True)\n", "lat_formatter = LatitudeFormatter()\n", "ax.add_feature(cfeature.LAND, zorder=100, edgecolor=\"k\")\n", "ax.set_title(\"Linear minus non-linear equation of state (2014-2016 mean)\")\n", "fig.tight_layout()" ] }, { "cell_type": "markdown", "metadata": { "execution": {} }, "source": [ "Upon comparing the two equations of state, we observe that they are generally similar, but certain differences arise. These differences stem from the nonlinearity of the equation of state, where the haline contraction coefficient and thermal expansion coefficient are not constant as assumed in our linear equation of state.\n", "\n", "Irrespective of the method used to calculate density, we notice the presence of horizontal density variations (gradients) at the ocean surface. For instance, seawater tends to be less dense in the subtropics and denser near the poles. These density differences play a crucial role in driving ocean currents, as we discussed in the slides.\n", "\n", "These findings emphasize the significant density gradients in the ocean, which shape oceanic circulation patterns. The nonlinearity in the equation of state contributes to these density variations, which in turn also influences the movement of water masses and the formation of currents." ] }, { "cell_type": "markdown", "metadata": { "execution": {} }, "source": [ "### Questions 2.2\n", "\n", "1. Considering the nonlinear equation of state and TEOS-10, how do changes in ocean salinity and temperature uniquely impact the haline contraction and thermal expansion coefficients, thereby affecting density and ocean currents?\n", "2. One place that deep convection, a critical component of thermohaline circulation occurs, is in the North Atlantic Ocean to the south of Greenland. Based on the density maps you made, does it make sense that this would be an ideal location for a deepwater mass to form?" ] }, { "cell_type": "markdown", "metadata": { "colab_type": "text", "execution": {} }, "source": [ "[*Click for solution*](https://github.com/neuromatch/climate-course-content/tree/main/tutorials/W1D2_Ocean-AtmosphereReanalysis/solutions/W1D2_Tutorial5_Solution_67b02b01.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_2\")" ] }, { "cell_type": "markdown", "metadata": { "execution": {} }, "source": [ "# Summary\n", "\n", "In this tutorial, you explored sea surface salinity and temperature data from 2014 to 2016, and how those contribute to surface density patterns through the equation of state. You also compared the linear and non-linear equation of state and analyzed their differences." ] }, { "cell_type": "markdown", "metadata": { "execution": {} }, "source": [ "# Resources\n", "\n", "Data for this tutorial can be accessed [here](https://www.ecco-group.org/)." ] } ], "metadata": { "colab": { "collapsed_sections": [], "include_colab_link": true, "name": "W1D2_Tutorial5", "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 }