{ "nbformat": 4, "nbformat_minor": 0, "metadata": { "colab": { "provenance": [], "collapsed_sections": [ "tYzchKpM7DlA", "i4UTa6PqGjn4", "7jf1Ar-fKD64" ] }, "kernelspec": { "name": "python3", "display_name": "Python 3" }, "language_info": { "name": "python" } }, "cells": [ { "cell_type": "markdown", "source": [ "# **MATE Floats! Coding Notebook** - Day 4\n", "\n", "Created by Ethan C. Campbell for NCAT/MATE/GO-BGC Marine Technology Summer Program\n", "\n", "Thursday, August 24, 2023" ], "metadata": { "id": "OxvLAQ1SWpeR" } }, { "cell_type": "code", "source": [ "import numpy as np # NumPy is an array and math library\n", "import matplotlib.pyplot as plt # Matplotlib is a visualization (plotting) library\n", "import pandas as pd # Pandas lets us work with spreadsheet (.csv) data\n", "from datetime import datetime, timedelta # Datetime helps us work with dates and times" ], "metadata": { "id": "oMjc5MqnJrgv" }, "execution_count": null, "outputs": [] }, { "cell_type": "markdown", "source": [ "## Part 1: Loading and plotting R/V Rachel Carson CTD casts" ], "metadata": { "id": "tYzchKpM7DlA" } }, { "cell_type": "markdown", "source": [ "First, let's download three `.csv` data files from Google Drive here: https://drive.google.com/drive/folders/1Am6XdlB-APQ3ccOvLeGK8DFPQ2OnPeJD?usp=sharing. Two of the files are CTD casts that were collected from the R/V Rachel Carson off of Carkeek Park near Seattle. ***Save these two files to your computer.***\n", "\n", "Let's first take a look at the raw files, including their headers.\n", "\n", "Next, we can upload the files to this Google Colab notebook. ***Click the sidebar folder icon on the left, then use the page-with-arrow icon at the top to select the files and upload them.*** NOTE: uploaded files will be deleted from Google Colab when you refresh this notebook!\n", "\n", "We will specify each **filepath** using string variables:" ], "metadata": { "id": "czGyp7MTAc5T" } }, { "cell_type": "code", "source": [ "filepath_0 = '/content/2023051001001_Carkeek.csv'\n", "filepath_1 = '/content/2023051101001_Carkeek.csv'" ], "metadata": { "id": "gnrD640dB5ds" }, "execution_count": null, "outputs": [] }, { "cell_type": "markdown", "source": [ "Now, we can load the files using `pandas`:\n", "\n", "> **`pd.read_csv(FILEPATH, ARGUMENTS...)`**\n", "\n", "This function is very customizable using the many optional `ARGUMENTS`, which allow it to handle almost any file. You can find documentation about the arguments [at this link](https://pandas.pydata.org/docs/reference/api/pandas.read_csv.html).\n", "\n", "***Let's first take a look at the data file using a simple text editor. Notice the long header. What argument can we use to exclude the header from being loaded?***\n", "\n", "Below, we'll load each data file using ``pd.read_csv()`` and store each file into a new variable.\n", "\n", "We can look at the data using **`display()`** (which is a fancy version of `print()` for DataFrames):" ], "metadata": { "id": "XaUCH7ikB6Sy" } }, { "cell_type": "code", "source": [ "data_0 = pd.read_csv(filepath_0,comment='#')\n", "data_1 = pd.read_csv(filepath_1,comment='#')\n", "\n", "display(data_0)" ], "metadata": { "id": "4boQwvSg7R5J" }, "execution_count": null, "outputs": [] }, { "cell_type": "markdown", "source": [ "The data in a `pandas` DataFrame is similar to a NumPy 2-D array, except we use **column labels** to refer to columns and **index** values to refer to rows.\n", "\n", "To retrieve a specific column, we use bracket notation: **`data_frame[COLUMN_LABEL]`**." ], "metadata": { "id": "HYem5ZznDUfk" } }, { "cell_type": "code", "source": [ "# For example:\n", "data_0['density00']" ], "metadata": { "id": "-k030Au_Dyd_" }, "execution_count": null, "outputs": [] }, { "cell_type": "markdown", "source": [ "With these tools, we can make line plots of temperature vs. depth that include both CTD casts.\n", "\n", "***Can you try plotting another parameter vs. depth? Note: the file contains salinity, oxygen, fluorescence, and pH data.***\n", "\n", "The following line of code flips the y-axis so the surface is at the top: **`plt.gca().invert_yaxis()`**." ], "metadata": { "id": "TDLpAjCnELuY" } }, { "cell_type": "code", "source": [ "# Temperature vs. depth profile\n", "plt.plot(data_0['t090C'],data_0['depSM'],label='R/V Carson cast #1 (5/10/23)')\n", "plt.plot(data_1['t090C'],data_1['depSM'],label='R/V Carson cast #2 (5/11/23)')\n", "plt.legend()\n", "plt.gca().invert_yaxis() # This reverses the y-axis\n", "plt.xlabel('Temperature (°C)')\n", "plt.ylabel('Depth (m)');\n", "\n", "# Write your code here:\n" ], "metadata": { "id": "dh6QZ2Np9gXs" }, "execution_count": null, "outputs": [] }, { "cell_type": "markdown", "source": [ "***How do the casts look similar and how do they look different? What could be some causes of the differences?***\n", "\n", "***What do you observe in the other parameter(s) that you plotted?***" ], "metadata": { "id": "w0ZA-UHrGB1c" } }, { "cell_type": "markdown", "source": [ "## Part 2: Loading and plotting seaglider data" ], "metadata": { "id": "i4UTa6PqGjn4" } }, { "cell_type": "markdown", "source": [ "At this link is a file with a **seaglider** (or just **\"glider\"**) profile from the same cruise, one day after the second R/V Carson cast.\n", "\n", "If you haven't already, ***download*** the glider `.csv` data file from Google Drive here: https://drive.google.com/drive/folders/1Am6XdlB-APQ3ccOvLeGK8DFPQ2OnPeJD?usp=sharing. ***Save the file to your computer, then load it into Google Colab.***\n", "\n", "Let's load and display the data using `pandas`:" ], "metadata": { "id": "VkvUEcToGo4U" } }, { "cell_type": "code", "source": [ "filepath_2 = '/content/20230512_glider.csv'\n", "\n", "data_2 = pd.read_csv(filepath_2,parse_dates=['time'])\n", "\n", "display(data_2)" ], "metadata": { "id": "-F0ldgmxttkL" }, "execution_count": null, "outputs": [] }, { "cell_type": "markdown", "source": [ "***What data parameters do you see, and what do you expect each parameter represents?***\n", "\n", "As a first step, let's see whether the glider was sampling the same region as the R/V Rachel Carson. We can plot each of their tracks using latitude and longitude:" ], "metadata": { "id": "brNjCdRzHjk-" } }, { "cell_type": "code", "source": [ "plt.plot(data_0['longitude'],data_0['latitude'],label='R/V Rachel Carson cast #1')\n", "plt.plot(data_1['longitude'],data_1['latitude'],label='R/V Rachel Carson cast #2')\n", "plt.plot(data_2['longitude'],data_2['latitude'],label='Glider')\n", "plt.legend()\n", "plt.xlabel('Longitude (°E)')\n", "plt.ylabel('Latitude (°N)')\n", "plt.title('Ship and glider tracks');" ], "metadata": { "id": "wQFYa8SYHZYH" }, "execution_count": null, "outputs": [] }, { "cell_type": "markdown", "source": [ "One way to visualize glider data is in **time-depth space**. In other words, time is on the x-axis and depth is on the y-axis. If we use a scatter plot (`plt.scatter()`), we can color the points by another quantity, like temperature or buoyancy.\n", "\n", "***Try changing the `c` (color) argument below to plot different quantities in time-depth space. What do you notice?***" ], "metadata": { "id": "4XlsqUInIb-P" } }, { "cell_type": "code", "source": [ "plt.scatter(data_2['time'],data_2['depth'],c=data_2['buoyancy'])\n", "plt.colorbar(label='Buoyancy (g)') # This adds the color bar and color label on the right\n", "plt.gca().invert_yaxis() # This reverses the y-axis\n", "plt.xlabel('Time')\n", "plt.ylabel('Depth (m)');" ], "metadata": { "id": "a9nA2EAtH_Ye" }, "execution_count": null, "outputs": [] }, { "cell_type": "markdown", "source": [ "Of course, we can also plot parameter vs. **depth profiles**.\n", "\n", "***Copy the code from above, where you plotted temperature profiles from the R/V Carson ship CTD casts. Then add the glider temperature data.***" ], "metadata": { "id": "mI9_9HJoJFxK" } }, { "cell_type": "code", "source": [ "# Write your code here:\n" ], "metadata": { "id": "A_jUPcj3Ikyu" }, "execution_count": null, "outputs": [] }, { "cell_type": "markdown", "source": [ "We can zoom in to certain depths by changing the y-axis scale using:\n", "\n", "> **`plt.ylim([LOWER,UPPER])`**\n", "\n", "***By `plt.ylim()` to the plot above, what can we observe about the differences between the casts near the surface and near the bottom? Why do these differences exist?***\n", "\n", "***If we wanted to calibrate a glider sensor to the R/V Carson's sensor, what depths would we want to use?***" ], "metadata": { "id": "adHqnEBNJjI0" } }, { "cell_type": "markdown", "source": [ "## Part 3: Exploring Argo float data" ], "metadata": { "id": "7jf1Ar-fKD64" } }, { "cell_type": "markdown", "source": [ "**Links:**\n", "* Earth Nullschool map: http://data.scripps.earth/argoviz/\n", "* Argovis – get your API key here: https://argovis-keygen.colorado.edu/\n", "* Argovis: https://argovis.colorado.edu/\n", "* Google Slides for your plots: https://docs.google.com/presentation/d/1MqYfkOHBv9KWO41ZgK0MMnfQ8E9zah3AntKlZkrWrgU/edit?usp=sharing" ], "metadata": { "id": "sqrpf-KeKLq-" } } ] }