{ "cells": [ { "cell_type": "markdown", "metadata": {}, "source": [ "# Lab 4-3: Snowpack temperature and density profiles - snowpit data\n", "Written by Daniel Hogan - April, 2023.\n", "\n", "Modified by Jessica Lundquist - April, 2023.\n", "\n", "Modified by Eli Schwat - January 2024." ] }, { "cell_type": "code", "execution_count": 103, "metadata": {}, "outputs": [], "source": [ "import xarray as xr\n", "import numpy as np\n", "import os \n", "import urllib\n", "import pandas as pd\n", "import datetime as dt\n", "import matplotlib.pyplot as plt" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### SOS Data" ] }, { "cell_type": "code", "execution_count": 104, "metadata": {}, "outputs": [], "source": [ "sos_file = \"../data/sos_full_dataset_30min.nc\"\n", "sos_dataset = xr.open_dataset(sos_file)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "# Replicate the steps from Lab 4-1 to create a dataset of in-snow temperature measurements (including snow surface temperatures)" ] }, { "cell_type": "code", "execution_count": 105, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "['SnowDepth_d'] ['Tsnow_0_4m_d', 'Tsnow_0_5m_d', 'Tsnow_0_6m_d', 'Tsnow_0_7m_d', 'Tsnow_0_8m_d', 'Tsnow_0_9m_d', 'Tsnow_1_0m_d', 'Tsnow_1_1m_d', 'Tsnow_1_2m_d', 'Tsnow_1_3m_d', 'Tsnow_1_4m_d', 'Tsnow_1_5m_d']\n" ] } ], "source": [ "tsnow_vars = [v for v in sos_dataset if 'Tsnow_' in v and v.endswith('_d')]\n", "snow_depth_vars = ['SnowDepth_d']\n", "print(snow_depth_vars, tsnow_vars)" ] }, { "cell_type": "code", "execution_count": 106, "metadata": {}, "outputs": [], "source": [ "# Transform the NetCDF dataset to be a \"tidy\" dataset of snow depths\n", "snow_temp_dataset = sos_dataset[\n", " tsnow_vars + snow_depth_vars\n", "].to_dataframe().reset_index().set_index(['time', 'SnowDepth_d']).melt(ignore_index=False)\n", "\n", "# Calculate the depth of the snow sensor (relative to the snow surface)\n", "# using the snow depth measurements and the known above-ground height\n", "# of the snow sensors\n", "snow_temp_dataset['height_agl'] = snow_temp_dataset['variable'].str[6:9].str.replace('_', '.').astype(float)\n", "snow_temp_dataset = snow_temp_dataset.reset_index().set_index('time')\n", "snow_temp_dataset['depth'] = snow_temp_dataset['height_agl'] - snow_temp_dataset['SnowDepth_d']" ] }, { "cell_type": "code", "execution_count": 107, "metadata": {}, "outputs": [ { "data": { "text/html": [ "
\n", "\n", "\n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", "
valuedepth
time
2022-11-01 00:00:00NaN0
2022-11-01 00:30:00NaN0
2022-11-01 01:00:00NaN0
2022-11-01 01:30:00NaN0
2022-11-01 02:00:00NaN0
.........
2023-06-19 15:30:0023.8380740
2023-06-19 16:00:0022.5957950
2023-06-19 16:30:0021.6812440
2023-06-19 17:00:0020.6452640
2023-06-19 17:30:00NaN0
\n", "

11074 rows × 2 columns

\n", "
" ], "text/plain": [ " value depth\n", "time \n", "2022-11-01 00:00:00 NaN 0\n", "2022-11-01 00:30:00 NaN 0\n", "2022-11-01 01:00:00 NaN 0\n", "2022-11-01 01:30:00 NaN 0\n", "2022-11-01 02:00:00 NaN 0\n", "... ... ...\n", "2023-06-19 15:30:00 23.838074 0\n", "2023-06-19 16:00:00 22.595795 0\n", "2023-06-19 16:30:00 21.681244 0\n", "2023-06-19 17:00:00 20.645264 0\n", "2023-06-19 17:30:00 NaN 0\n", "\n", "[11074 rows x 2 columns]" ] }, "execution_count": 107, "metadata": {}, "output_type": "execute_result" } ], "source": [ "# Add surface temperature data (depth=0)\n", "surface_temps_dataset = sos_dataset['Tsurf_d'].to_dataframe()\n", "surface_temps_dataset = surface_temps_dataset.rename(columns={'Tsurf_d': 'value'})\n", "surface_temps_dataset['depth'] = 0\n", "surface_temps_dataset" ] }, { "cell_type": "code", "execution_count": 108, "metadata": {}, "outputs": [], "source": [ "snow_temp_dataset = pd.concat([snow_temp_dataset, surface_temps_dataset])" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Make sure we don't have any measurements from above the snow surface" ] }, { "cell_type": "code", "execution_count": 109, "metadata": {}, "outputs": [], "source": [ "snow_temp_dataset = snow_temp_dataset.query(\"depth <= 0\")" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "# Snowpit Measurements - a first look" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Open up the snowpit data and look at data from just two snowpits - on February 6 and 7, 2023" ] }, { "cell_type": "code", "execution_count": 110, "metadata": {}, "outputs": [ { "data": { "text/html": [ "
\n", "\n", "\n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", "
depthtimetemperaturedensityidir_surface_tempthermometer_surface_temppit_total_snow_depth
00.002023-02-06 09:12:00-0.6NaNKP21-8.1-9.51.04
10.002023-02-07 10:01:00-0.6NaNKP22-7.3-9.31.03
20.022023-02-06 09:12:00NaNNaNKP21-8.1-9.51.04
30.022023-02-07 10:01:00NaNNaNKP22-7.3-9.31.03
40.032023-02-06 09:12:00NaNNaNKP21-8.1-9.51.04
...........................
2871.592023-02-07 10:01:00NaNNaNKP22-7.3-9.31.03
2881.612023-02-06 09:12:00NaNNaNKP21-8.1-9.51.04
2891.612023-02-07 10:01:00NaNNaNKP22-7.3-9.31.03
2901.652023-02-06 09:12:00NaNNaNKP21-8.1-9.51.04
2911.652023-02-07 10:01:00NaNNaNKP22-7.3-9.31.03
\n", "

292 rows × 8 columns

\n", "
" ], "text/plain": [ " depth time temperature density id ir_surface_temp \\\n", "0 0.00 2023-02-06 09:12:00 -0.6 NaN KP21 -8.1 \n", "1 0.00 2023-02-07 10:01:00 -0.6 NaN KP22 -7.3 \n", "2 0.02 2023-02-06 09:12:00 NaN NaN KP21 -8.1 \n", "3 0.02 2023-02-07 10:01:00 NaN NaN KP22 -7.3 \n", "4 0.03 2023-02-06 09:12:00 NaN NaN KP21 -8.1 \n", ".. ... ... ... ... ... ... \n", "287 1.59 2023-02-07 10:01:00 NaN NaN KP22 -7.3 \n", "288 1.61 2023-02-06 09:12:00 NaN NaN KP21 -8.1 \n", "289 1.61 2023-02-07 10:01:00 NaN NaN KP22 -7.3 \n", "290 1.65 2023-02-06 09:12:00 NaN NaN KP21 -8.1 \n", "291 1.65 2023-02-07 10:01:00 NaN NaN KP22 -7.3 \n", "\n", " thermometer_surface_temp pit_total_snow_depth \n", "0 -9.5 1.04 \n", "1 -9.3 1.03 \n", "2 -9.5 1.04 \n", "3 -9.3 1.03 \n", "4 -9.5 1.04 \n", ".. ... ... \n", "287 -9.3 1.03 \n", "288 -9.5 1.04 \n", "289 -9.3 1.03 \n", "290 -9.5 1.04 \n", "291 -9.3 1.03 \n", "\n", "[292 rows x 8 columns]" ] }, "execution_count": 110, "metadata": {}, "output_type": "execute_result" } ], "source": [ "snowpit_ds = xr.open_dataset(\"../data/KettlePondsSnowPits.nc\")\n", "\n", "snowpit_ds = snowpit_ds.sel(time = slice('20230206', '20230207'))\n", "snowpit_df = snowpit_ds.to_dataframe().reset_index()\n", "\n", "# The timestamps in this dataset are in UTC. Let's convert to US/Mountain time, which our other dataset is conveniently already in.\n", "# After we convert, we remove the timezone info by calling `tz_localize(None)`. \n", "snowpit_df.time = snowpit_df.time.dt.tz_localize('UTC').dt.tz_convert('US/Mountain').dt.tz_localize(None)\n", "\n", "# convert depth variables from cm to m\n", "snowpit_df['depth'] = snowpit_df['depth']/100\n", "snowpit_df['pit_total_snow_depth'] = snowpit_df['pit_total_snow_depth']/100\n", "snowpit_df" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Look at the times the snowpit data was collected" ] }, { "cell_type": "code", "execution_count": 111, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "\n", "['2023-02-06 09:12:00', '2023-02-07 10:01:00']\n", "Length: 2, dtype: datetime64[ns]" ] }, "execution_count": 111, "metadata": {}, "output_type": "execute_result" } ], "source": [ "snowpit_df.time.unique()" ] }, { "cell_type": "code", "execution_count": 112, "metadata": {}, "outputs": [], "source": [ "import altair as alt" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Plot density and temperature profiles from the two days" ] }, { "cell_type": "code", "execution_count": 113, "metadata": {}, "outputs": [ { "data": { "text/html": [ "\n", "\n", "
\n", "" ], "text/plain": [ "alt.VConcatChart(...)" ] }, "execution_count": 113, "metadata": {}, "output_type": "execute_result" } ], "source": [ "density_charts = (\n", " alt.Chart(snowpit_df).mark_circle().encode(\n", " alt.X('density:Q').title('Density (kg/m^3)'),\n", " alt.Y('depth:Q').title('Depth (m)'),\n", " \n", " ) + alt.Chart(snowpit_df).mark_rule().encode(\n", " alt.Y('pit_total_snow_depth:Q')\n", " ).properties(width=150, height=150)\n", ").facet(\n", " alt.Facet('time:T')\n", ")\n", "\n", "temp_charts = (\n", " alt.Chart(snowpit_df).mark_circle().encode(\n", " alt.X('temperature:Q').title('Temperature (˚C)'),\n", " alt.Y('depth:Q').title('Depth (m)'),\n", " \n", " ) + alt.Chart(snowpit_df).mark_rule().encode(\n", " alt.Y('pit_total_snow_depth:Q')\n", " ).properties(width=150, height=150)\n", ").facet(\n", " alt.Facet('time:T')\n", ")\n", "\n", "density_charts & temp_charts" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Combining temperature measurements from snowpit and in-situ thermistor measurements" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Let's compare the manual snowpit temperature data to the in-situ in-snow temperature data we have analyzed previously.\n", "\n", "\n", "This will involve some data wrangling, because notice that the manual snowpit data measures Depth relative to the soil-snow interface. With the in-snow temperature data used previously, we calculated depth relative to the snow-air interface." ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "First, isolate the in-situ snow temperature measurements to the 30-minute period overlapping when the snowpits were taken. \n", "\n", "We saw above that the snowpits were dug during:\n", "* 2023-02-06 0900 - 0930\n", "* 2023-02-07 1000 - 1030\n", "\n", "Let's grab those two 30minute averages from the snow temp dataset and combine them into one small dataset." ] }, { "cell_type": "code", "execution_count": 114, "metadata": {}, "outputs": [ { "data": { "text/html": [ "
\n", "\n", "\n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", "
timeSnowDepth_dvariablevalueheight_agldepth
02023-02-06 09:00:000.912619Tsnow_0_4m_d-3.4472970.4-0.512619
12023-02-06 09:00:000.912619Tsnow_0_5m_d-4.0415520.5-0.412619
22023-02-06 09:00:000.912619Tsnow_0_6m_d-4.6849700.6-0.312619
32023-02-06 09:00:000.912619Tsnow_0_7m_d-4.8257820.7-0.212619
42023-02-06 09:00:000.912619Tsnow_0_8m_d-4.8825230.8-0.112619
52023-02-06 09:00:000.912619Tsnow_0_9m_d-5.4381390.9-0.012619
62023-02-06 09:00:00NaNNaN-11.606720NaN0.000000
72023-02-07 10:00:000.890080Tsnow_0_4m_d-3.1880190.4-0.490080
82023-02-07 10:00:000.890080Tsnow_0_5m_d-3.7279440.5-0.390080
92023-02-07 10:00:000.890080Tsnow_0_6m_d-4.5720830.6-0.290080
102023-02-07 10:00:000.890080Tsnow_0_7m_d-5.4296980.7-0.190080
112023-02-07 10:00:000.890080Tsnow_0_8m_d-7.3195890.8-0.090080
122023-02-07 10:00:00NaNNaN-15.121002NaN0.000000
\n", "
" ], "text/plain": [ " time SnowDepth_d variable value height_agl \\\n", "0 2023-02-06 09:00:00 0.912619 Tsnow_0_4m_d -3.447297 0.4 \n", "1 2023-02-06 09:00:00 0.912619 Tsnow_0_5m_d -4.041552 0.5 \n", "2 2023-02-06 09:00:00 0.912619 Tsnow_0_6m_d -4.684970 0.6 \n", "3 2023-02-06 09:00:00 0.912619 Tsnow_0_7m_d -4.825782 0.7 \n", "4 2023-02-06 09:00:00 0.912619 Tsnow_0_8m_d -4.882523 0.8 \n", "5 2023-02-06 09:00:00 0.912619 Tsnow_0_9m_d -5.438139 0.9 \n", "6 2023-02-06 09:00:00 NaN NaN -11.606720 NaN \n", "7 2023-02-07 10:00:00 0.890080 Tsnow_0_4m_d -3.188019 0.4 \n", "8 2023-02-07 10:00:00 0.890080 Tsnow_0_5m_d -3.727944 0.5 \n", "9 2023-02-07 10:00:00 0.890080 Tsnow_0_6m_d -4.572083 0.6 \n", "10 2023-02-07 10:00:00 0.890080 Tsnow_0_7m_d -5.429698 0.7 \n", "11 2023-02-07 10:00:00 0.890080 Tsnow_0_8m_d -7.319589 0.8 \n", "12 2023-02-07 10:00:00 NaN NaN -15.121002 NaN \n", "\n", " depth \n", "0 -0.512619 \n", "1 -0.412619 \n", "2 -0.312619 \n", "3 -0.212619 \n", "4 -0.112619 \n", "5 -0.012619 \n", "6 0.000000 \n", "7 -0.490080 \n", "8 -0.390080 \n", "9 -0.290080 \n", "10 -0.190080 \n", "11 -0.090080 \n", "12 0.000000 " ] }, "execution_count": 114, "metadata": {}, "output_type": "execute_result" } ], "source": [ "snow_temp_dataset_4_comparison = pd.concat([\n", " snow_temp_dataset.loc['20230206 0900'], # this represents the average from 0900-0930\n", " snow_temp_dataset.loc['20230207 1000'] # this represents the average from 1000-1030\n", "]).reset_index()\n", "snow_temp_dataset_4_comparison" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Check those measurements out quickly to make sure we grabbed the right stuff" ] }, { "cell_type": "code", "execution_count": 115, "metadata": {}, "outputs": [ { "data": { "text/html": [ "\n", "\n", "
\n", "" ], "text/plain": [ "alt.FacetChart(...)" ] }, "execution_count": 115, "metadata": {}, "output_type": "execute_result" } ], "source": [ "(\n", " alt.Chart(snow_temp_dataset_4_comparison).mark_line().encode(\n", " alt.X('value:Q').title('Temperature (˚C)'),\n", " alt.Y('depth:Q').title('Depth (m)'),\n", " \n", " ).properties(width=150, height=150)\n", ").facet(\n", " alt.Facet('time:T')\n", ")" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "OK looks good." ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "The depth of the snow on the two days, according to the snowpits measurements, was" ] }, { "cell_type": "code", "execution_count": 116, "metadata": {}, "outputs": [ { "data": { "text/html": [ "
\n", "\n", "\n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", "
timepit_total_snow_depth
02023-02-06 09:12:001.04
12023-02-07 10:01:001.03
\n", "
" ], "text/plain": [ " time pit_total_snow_depth\n", "0 2023-02-06 09:12:00 1.04\n", "1 2023-02-07 10:01:00 1.03" ] }, "execution_count": 116, "metadata": {}, "output_type": "execute_result" } ], "source": [ "snowpit_df[['time', 'pit_total_snow_depth']].drop_duplicates()" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "We can adjust the in-site snow temperature measurements so that depth means the same thing across the datasets.\n", "We do this by adding the depth from the dataset `snow_temp_dataset_4_comparison` to the snow depth values according to the snow pit measurements (in the `snowpit_df` dataset)." ] }, { "cell_type": "code", "execution_count": 117, "metadata": {}, "outputs": [], "source": [ "snow_temp_dataset_4_comparison.loc[\n", " snow_temp_dataset_4_comparison['time'] == '2023-02-06 09:00:00',\n", " 'depth'\n", "] = snow_temp_dataset_4_comparison.loc[\n", " snow_temp_dataset_4_comparison['time'] == '2023-02-06 09:00:00',\n", " 'depth'\n", "] + 1.04 # in meters, the dataset had 104 (centimeters)\n", "\n", "snow_temp_dataset_4_comparison.loc[\n", " snow_temp_dataset_4_comparison['time'] == '2023-02-07 10:00:00',\n", " 'depth'\n", "] = snow_temp_dataset_4_comparison.loc[\n", " snow_temp_dataset_4_comparison['time'] == '2023-02-07 10:00:00',\n", " 'depth'\n", "] + 1.03 # in meters, the dataset had 104 (centimeters)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Now we can plot the datasets together and see if they line up.\n", "\n", "To plot the datasets together, we combine the datasets into one dataset. We follow the following steps to do this:\n", "1. Make sure the variable names across the two datasets are the same\n", "2. Add a variable to each of the separate datasets indicating their measurement type (i.e. snow pit or in-situ)\n", "3. Combine" ] }, { "cell_type": "code", "execution_count": 118, "metadata": {}, "outputs": [ { "data": { "text/html": [ "
\n", "\n", "\n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", "
timedepthtemperaturedata_type
02023-02-06 09:00:000.527381-3.447297thermistor array
12023-02-06 09:00:000.627381-4.041552thermistor array
22023-02-06 09:00:000.727381-4.684970thermistor array
32023-02-06 09:00:000.827381-4.825782thermistor array
42023-02-06 09:00:000.927381-4.882523thermistor array
52023-02-06 09:00:001.027381-5.438139thermistor array
62023-02-06 09:00:001.040000-11.606720thermistor array
72023-02-07 10:00:000.539920-3.188019thermistor array
82023-02-07 10:00:000.639920-3.727944thermistor array
92023-02-07 10:00:000.739920-4.572083thermistor array
102023-02-07 10:00:000.839920-5.429698thermistor array
112023-02-07 10:00:000.939920-7.319589thermistor array
122023-02-07 10:00:001.030000-15.121002thermistor array
\n", "
" ], "text/plain": [ " time depth temperature data_type\n", "0 2023-02-06 09:00:00 0.527381 -3.447297 thermistor array\n", "1 2023-02-06 09:00:00 0.627381 -4.041552 thermistor array\n", "2 2023-02-06 09:00:00 0.727381 -4.684970 thermistor array\n", "3 2023-02-06 09:00:00 0.827381 -4.825782 thermistor array\n", "4 2023-02-06 09:00:00 0.927381 -4.882523 thermistor array\n", "5 2023-02-06 09:00:00 1.027381 -5.438139 thermistor array\n", "6 2023-02-06 09:00:00 1.040000 -11.606720 thermistor array\n", "7 2023-02-07 10:00:00 0.539920 -3.188019 thermistor array\n", "8 2023-02-07 10:00:00 0.639920 -3.727944 thermistor array\n", "9 2023-02-07 10:00:00 0.739920 -4.572083 thermistor array\n", "10 2023-02-07 10:00:00 0.839920 -5.429698 thermistor array\n", "11 2023-02-07 10:00:00 0.939920 -7.319589 thermistor array\n", "12 2023-02-07 10:00:00 1.030000 -15.121002 thermistor array" ] }, "execution_count": 118, "metadata": {}, "output_type": "execute_result" } ], "source": [ "# Modifying the in situ measurements\n", "## Isolate the variables we want (timestemps, depth, and temperature)\n", "in_situ_data = snow_temp_dataset_4_comparison[['time', 'depth', 'value']]\n", "## Rename the \"value\" column, which has temperatures, to \"temperature\"\n", "in_situ_data = in_situ_data.rename(columns={'value': 'temperature'})\n", "## Create a new column to clarify which data this is\n", "in_situ_data['data_type'] = 'thermistor array'\n", "in_situ_data" ] }, { "cell_type": "code", "execution_count": 119, "metadata": {}, "outputs": [ { "data": { "text/html": [ "
\n", "\n", "\n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", "
timedepthtemperaturedata_type
02023-02-06 09:12:000.00-0.6snow pit
12023-02-07 10:01:000.00-0.6snow pit
252023-02-07 10:01:000.13-1.5snow pit
262023-02-06 09:12:000.14-1.4snow pit
452023-02-07 10:01:000.23-2.1snow pit
462023-02-06 09:12:000.24-2.9snow pit
652023-02-07 10:01:000.33-2.6snow pit
662023-02-06 09:12:000.34-3.2snow pit
852023-02-07 10:01:000.43-3.1snow pit
862023-02-06 09:12:000.44-3.6snow pit
1052023-02-07 10:01:000.53-3.6snow pit
1062023-02-06 09:12:000.54-4.2snow pit
1252023-02-07 10:01:000.63-4.4snow pit
1262023-02-06 09:12:000.64-4.9snow pit
1452023-02-07 10:01:000.73-5.7snow pit
1462023-02-06 09:12:000.74-5.4snow pit
1652023-02-07 10:01:000.83-7.6snow pit
1662023-02-06 09:12:000.84-6.0snow pit
1852023-02-07 10:01:000.93-11.7snow pit
1862023-02-06 09:12:000.94-6.4snow pit
2072023-02-07 10:01:001.03-9.3snow pit
2082023-02-06 09:12:001.04-8.1snow pit
\n", "
" ], "text/plain": [ " time depth temperature data_type\n", "0 2023-02-06 09:12:00 0.00 -0.6 snow pit\n", "1 2023-02-07 10:01:00 0.00 -0.6 snow pit\n", "25 2023-02-07 10:01:00 0.13 -1.5 snow pit\n", "26 2023-02-06 09:12:00 0.14 -1.4 snow pit\n", "45 2023-02-07 10:01:00 0.23 -2.1 snow pit\n", "46 2023-02-06 09:12:00 0.24 -2.9 snow pit\n", "65 2023-02-07 10:01:00 0.33 -2.6 snow pit\n", "66 2023-02-06 09:12:00 0.34 -3.2 snow pit\n", "85 2023-02-07 10:01:00 0.43 -3.1 snow pit\n", "86 2023-02-06 09:12:00 0.44 -3.6 snow pit\n", "105 2023-02-07 10:01:00 0.53 -3.6 snow pit\n", "106 2023-02-06 09:12:00 0.54 -4.2 snow pit\n", "125 2023-02-07 10:01:00 0.63 -4.4 snow pit\n", "126 2023-02-06 09:12:00 0.64 -4.9 snow pit\n", "145 2023-02-07 10:01:00 0.73 -5.7 snow pit\n", "146 2023-02-06 09:12:00 0.74 -5.4 snow pit\n", "165 2023-02-07 10:01:00 0.83 -7.6 snow pit\n", "166 2023-02-06 09:12:00 0.84 -6.0 snow pit\n", "185 2023-02-07 10:01:00 0.93 -11.7 snow pit\n", "186 2023-02-06 09:12:00 0.94 -6.4 snow pit\n", "207 2023-02-07 10:01:00 1.03 -9.3 snow pit\n", "208 2023-02-06 09:12:00 1.04 -8.1 snow pit" ] }, "execution_count": 119, "metadata": {}, "output_type": "execute_result" } ], "source": [ "# Modifying the snowpit measurements\n", "## Isolate the variables we want - this is the only step we need to do for this one\n", "snowpit_data = snowpit_df[['time', 'depth', 'temperature']].dropna()\n", "## Create a new column to clarify which data this is\n", "snowpit_data['data_type'] = 'snow pit'\n", "snowpit_data" ] }, { "cell_type": "code", "execution_count": 120, "metadata": {}, "outputs": [ { "data": { "text/html": [ "
\n", "\n", "\n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", "
timedepthtemperaturedata_type
02023-02-06 09:12:000.000000-0.600000snow pit
12023-02-07 10:01:000.000000-0.600000snow pit
252023-02-07 10:01:000.130000-1.500000snow pit
262023-02-06 09:12:000.140000-1.400000snow pit
452023-02-07 10:01:000.230000-2.100000snow pit
462023-02-06 09:12:000.240000-2.900000snow pit
652023-02-07 10:01:000.330000-2.600000snow pit
662023-02-06 09:12:000.340000-3.200000snow pit
852023-02-07 10:01:000.430000-3.100000snow pit
862023-02-06 09:12:000.440000-3.600000snow pit
1052023-02-07 10:01:000.530000-3.600000snow pit
1062023-02-06 09:12:000.540000-4.200000snow pit
1252023-02-07 10:01:000.630000-4.400000snow pit
1262023-02-06 09:12:000.640000-4.900000snow pit
1452023-02-07 10:01:000.730000-5.700000snow pit
1462023-02-06 09:12:000.740000-5.400000snow pit
1652023-02-07 10:01:000.830000-7.600000snow pit
1662023-02-06 09:12:000.840000-6.000000snow pit
1852023-02-07 10:01:000.930000-11.700000snow pit
1862023-02-06 09:12:000.940000-6.400000snow pit
2072023-02-07 10:01:001.030000-9.300000snow pit
2082023-02-06 09:12:001.040000-8.100000snow pit
02023-02-06 09:00:000.527381-3.447297thermistor array
12023-02-06 09:00:000.627381-4.041552thermistor array
22023-02-06 09:00:000.727381-4.684970thermistor array
32023-02-06 09:00:000.827381-4.825782thermistor array
42023-02-06 09:00:000.927381-4.882523thermistor array
52023-02-06 09:00:001.027381-5.438139thermistor array
62023-02-06 09:00:001.040000-11.606720thermistor array
72023-02-07 10:00:000.539920-3.188019thermistor array
82023-02-07 10:00:000.639920-3.727944thermistor array
92023-02-07 10:00:000.739920-4.572083thermistor array
102023-02-07 10:00:000.839920-5.429698thermistor array
112023-02-07 10:00:000.939920-7.319589thermistor array
122023-02-07 10:00:001.030000-15.121002thermistor array
\n", "
" ], "text/plain": [ " time depth temperature data_type\n", "0 2023-02-06 09:12:00 0.000000 -0.600000 snow pit\n", "1 2023-02-07 10:01:00 0.000000 -0.600000 snow pit\n", "25 2023-02-07 10:01:00 0.130000 -1.500000 snow pit\n", "26 2023-02-06 09:12:00 0.140000 -1.400000 snow pit\n", "45 2023-02-07 10:01:00 0.230000 -2.100000 snow pit\n", "46 2023-02-06 09:12:00 0.240000 -2.900000 snow pit\n", "65 2023-02-07 10:01:00 0.330000 -2.600000 snow pit\n", "66 2023-02-06 09:12:00 0.340000 -3.200000 snow pit\n", "85 2023-02-07 10:01:00 0.430000 -3.100000 snow pit\n", "86 2023-02-06 09:12:00 0.440000 -3.600000 snow pit\n", "105 2023-02-07 10:01:00 0.530000 -3.600000 snow pit\n", "106 2023-02-06 09:12:00 0.540000 -4.200000 snow pit\n", "125 2023-02-07 10:01:00 0.630000 -4.400000 snow pit\n", "126 2023-02-06 09:12:00 0.640000 -4.900000 snow pit\n", "145 2023-02-07 10:01:00 0.730000 -5.700000 snow pit\n", "146 2023-02-06 09:12:00 0.740000 -5.400000 snow pit\n", "165 2023-02-07 10:01:00 0.830000 -7.600000 snow pit\n", "166 2023-02-06 09:12:00 0.840000 -6.000000 snow pit\n", "185 2023-02-07 10:01:00 0.930000 -11.700000 snow pit\n", "186 2023-02-06 09:12:00 0.940000 -6.400000 snow pit\n", "207 2023-02-07 10:01:00 1.030000 -9.300000 snow pit\n", "208 2023-02-06 09:12:00 1.040000 -8.100000 snow pit\n", "0 2023-02-06 09:00:00 0.527381 -3.447297 thermistor array\n", "1 2023-02-06 09:00:00 0.627381 -4.041552 thermistor array\n", "2 2023-02-06 09:00:00 0.727381 -4.684970 thermistor array\n", "3 2023-02-06 09:00:00 0.827381 -4.825782 thermistor array\n", "4 2023-02-06 09:00:00 0.927381 -4.882523 thermistor array\n", "5 2023-02-06 09:00:00 1.027381 -5.438139 thermistor array\n", "6 2023-02-06 09:00:00 1.040000 -11.606720 thermistor array\n", "7 2023-02-07 10:00:00 0.539920 -3.188019 thermistor array\n", "8 2023-02-07 10:00:00 0.639920 -3.727944 thermistor array\n", "9 2023-02-07 10:00:00 0.739920 -4.572083 thermistor array\n", "10 2023-02-07 10:00:00 0.839920 -5.429698 thermistor array\n", "11 2023-02-07 10:00:00 0.939920 -7.319589 thermistor array\n", "12 2023-02-07 10:00:00 1.030000 -15.121002 thermistor array" ] }, "execution_count": 120, "metadata": {}, "output_type": "execute_result" } ], "source": [ "# Combine the datasets!\n", "temp_profile_comparison_dataset = pd.concat([snowpit_data, in_situ_data])\n", "temp_profile_comparison_dataset" ] }, { "cell_type": "code", "execution_count": 121, "metadata": {}, "outputs": [ { "data": { "text/html": [ "\n", "\n", "
\n", "" ], "text/plain": [ "alt.FacetChart(...)" ] }, "execution_count": 121, "metadata": {}, "output_type": "execute_result" } ], "source": [ "(\n", " alt.Chart(temp_profile_comparison_dataset.dropna()).mark_line(\n", " point=True\n", " ).encode(\n", " alt.X('temperature:Q').title('Temperature (˚C)'),\n", " alt.Y('depth:Q').title('Depth (m)'),\n", " alt.Color('data_type:N'),\n", " alt.Order('depth:Q') # this makes sure the lines are drawn, connecting dots vertically, in order of depth\n", " ).properties(width=150, height=150)\n", ").facet(\n", " alt.Facet('day(time):T')\n", ")" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "OK so the temperature profiles have some differences!\n", "The surface temperatures disagree pretty strongly.\n", "Their basic behavior underneath the snow surface is pretty similar though.\n", "Why do you think the surface temperature measurements might differ?\n", "Why might the temperature measurements within the snowpack (beneath the surface) differ?" ] }, { "cell_type": "code", "execution_count": 172, "metadata": {}, "outputs": [ { "data": { "text/html": [ "
\n", "\n", "\n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", "
depthtimetemperaturedensityidir_surface_tempthermometer_surface_temppit_total_snow_depth
00.02023-01-06 10:48:00-0.5NaNKP01-4.3-4.31.020
10.02023-01-07 10:06:00-0.9NaNKP02-6.3-6.31.160
20.02023-01-09 09:13:00-0.8NaNKP03-7.2-4.40.995
30.02023-01-10 11:10:00NaNNaNKP04-1.0-0.11.120
40.02023-01-11 11:05:00-0.7NaNKP05-5.3-5.11.120
...........................
7003165.02023-03-11 09:53:00NaNNaNKP44-4.3-1.11.590
7004165.02023-03-12 11:00:00NaNNaNKP45-2.30.41.610
7005165.02023-03-14 13:52:00NaNNaNKP46-0.70.81.530
7006165.02023-03-15 14:00:00NaNNaNKP470.21.41.520
7007165.02023-03-16 08:12:00-6.691.0KP48-8.9-6.61.650
\n", "

7008 rows × 8 columns

\n", "
" ], "text/plain": [ " depth time temperature density id ir_surface_temp \\\n", "0 0.0 2023-01-06 10:48:00 -0.5 NaN KP01 -4.3 \n", "1 0.0 2023-01-07 10:06:00 -0.9 NaN KP02 -6.3 \n", "2 0.0 2023-01-09 09:13:00 -0.8 NaN KP03 -7.2 \n", "3 0.0 2023-01-10 11:10:00 NaN NaN KP04 -1.0 \n", "4 0.0 2023-01-11 11:05:00 -0.7 NaN KP05 -5.3 \n", "... ... ... ... ... ... ... \n", "7003 165.0 2023-03-11 09:53:00 NaN NaN KP44 -4.3 \n", "7004 165.0 2023-03-12 11:00:00 NaN NaN KP45 -2.3 \n", "7005 165.0 2023-03-14 13:52:00 NaN NaN KP46 -0.7 \n", "7006 165.0 2023-03-15 14:00:00 NaN NaN KP47 0.2 \n", "7007 165.0 2023-03-16 08:12:00 -6.6 91.0 KP48 -8.9 \n", "\n", " thermometer_surface_temp pit_total_snow_depth \n", "0 -4.3 1.020 \n", "1 -6.3 1.160 \n", "2 -4.4 0.995 \n", "3 -0.1 1.120 \n", "4 -5.1 1.120 \n", "... ... ... \n", "7003 -1.1 1.590 \n", "7004 0.4 1.610 \n", "7005 0.8 1.530 \n", "7006 1.4 1.520 \n", "7007 -6.6 1.650 \n", "\n", "[7008 rows x 8 columns]" ] }, "execution_count": 172, "metadata": {}, "output_type": "execute_result" } ], "source": [ "snowpit_ds = xr.open_dataset(\"../data/KettlePondsSnowPits.nc\")\n", "snowpit_df = snowpit_ds.to_dataframe().reset_index()\n", "\n", "# The timestamps in this dataset are in UTC. Let's convert to US/Mountain time, which our other dataset is conveniently already in.\n", "# After we convert, we remove the timezone info by calling `tz_localize(None)`. \n", "snowpit_df.time = snowpit_df.time.dt.tz_localize('UTC').dt.tz_convert('US/Mountain').dt.tz_localize(None)\n", "\n", "# convert depth variables from cm to m\n", "snowpit_df['pit_total_snow_depth'] = snowpit_df['pit_total_snow_depth']/100\n", "snowpit_df" ] }, { "cell_type": "code", "execution_count": 173, "metadata": {}, "outputs": [], "source": [ "snowpit_df = snowpit_df.query(\"depth <= 30\")\n", "snowpit_df = snowpit_df.sort_values('time')[['time', 'depth', 'temperature']].dropna()" ] }, { "cell_type": "code", "execution_count": 175, "metadata": {}, "outputs": [ { "name": "stderr", "output_type": "stream", "text": [ "/var/folders/x_/2h52bcjx2px15bhmdpdd748h0000gn/T/ipykernel_81015/3371135051.py:1: DeprecationWarning: DataFrameGroupBy.apply operated on the grouping columns. This behavior is deprecated, and in a future version of pandas the grouping columns will be excluded from the operation. Either pass `include_groups=False` to exclude the groupings or explicitly select the grouping columns after groupby to silence this warning.\n", " snowpit_df.groupby('time').apply(\n" ] }, { "data": { "text/plain": [ "np.float64(-0.1)" ] }, "execution_count": 175, "metadata": {}, "output_type": "execute_result" } ], "source": [ "snowpit_df.groupby('time').apply(\n", " lambda df: \n", " (df.sort_values('depth').temperature.values[-1] - df.sort_values('depth').temperature.values[0])\n", " /\n", " (df.sort_values('depth').depth.values[-1] - df.sort_values('depth').depth.values[0])\n", ").min()" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [] } ], "metadata": { "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.10.13" } }, "nbformat": 4, "nbformat_minor": 4 }