knitr::opts_chunk$set( collapse = TRUE, comment = "#>", fig.path = "man/figures/README-", message = FALSE )
A better way of interpolating nutrient data in the lakes. Both for mass calculations and for data visualization.
We often linearly interpolate water quality observations between observation depths. This is typically fine if a lake is well mixed, but if it's stratified it introduces a lot of error around the thermocline. Here, I provide functions to interpolate water quality observations leveraging information on lake stratification from temperature data. Often there is more temperature data than water quality data, which results in better interpolation.
The functions in this package allow you to:
Why is it called lakeloads? Mass cacluations can be used to infer loading.
You can install NTLlakeloads from github using devtools:
install.packages("devtools") devtools::install_github("hdugan/NTLlakeloads") library(NTLlakeloads)
library(NTLlakeloads)
# Load NTL datasets LTERtemp = loadLTERtemp() # Download NTL LTER data from EDI LTERnutrients = loadLTERnutrients() # Download NTL LTER data from EDI LTERions = loadLTERions() # Download NTL LTER data from EDI LTERsecchi = loadLTERsecchi() # Download NTL LTER data from EDI
# Available variables availableVars() # Available variables that are not depth-discrete. Used with weeklyInterpolate.1D. availableVars.1D()
library(metR) # # Create interpolated dataframe. Uses simple linear temperature interpolation df.ME.temp = weeklyTempInterpolate(lakeAbr = 'ME', maxdepth = 24, dataset = LTERtemp) plotTimeseries.year(df.interpolated = df.ME.temp$weeklyInterpolated, var = 'wtemp', chooseYear = 2018, binsize = 1, legend.title = 'Temp (°C)') + metR::scale_fill_divergent_discretised(high = 'red4', mid = '#e8e3a7', low = 'lightblue4', midpoint = 15) + labs(title = 'Lake Mendota, water temperature 2018') # theme(legend.position = 'none') # removes legend if you want # For Sparkling also add sampled points df.SP.temp = weeklyTempInterpolate(lakeAbr = 'SP', maxdepth = 19, dataset = LTERtemp) plotTimeseries.year(df.interpolated = df.SP.temp$weeklyInterpolated, var = 'wtemp', chooseYear = 2018, binsize = 1, legend.title = 'Temp (°C)') + geom_point(data = df.SP.temp$observations, aes(x = sampledate, y = depth), size = 0.2) + # add sampling points # scale_fill_viridis_d(option = 'H') + metR::scale_fill_divergent_discretised(high = 'red4', mid = '#e8e3a7', low = 'lightblue4', midpoint = 15) + labs(title = 'Sparkling Lake, water temperature 2018')
If LTERtemp = loadLTERtemp()
has not been run, this function downloads the NTL temperature dataset.
This function works by joining the water quality dataset (e.g. nutrients) with the temperature dataset. It uses the temperature profile to fit a gam, which is used to vertically interpolate data to a 1-m depth increment. The idea here is that this method will pick up large changes around the thermocline better than linear interpolation.
# printFigs = TRUE to output series of interpolated profiles (but slower) # See help file for argument descriptions df.ME = weeklyInterpolate(lakeAbr = 'ME', var = 'totpuf_sloh', dataset = LTERnutrients, maxdepth = 24, constrainMethod = 'zero', setThreshold = 0.1, printFigs = F)
# See help file for available arguments plotTimeseries(df.interpolated = df.ME$weeklyInterpolated, var = 'totpuf_sloh')
# With observations plotTimeseries.year(df.interpolated = df.ME$weeklyInterpolated, observations = df.ME$observations, var = 'totpuf_sloh', chooseYear = 2008) # Without observations, but adding legend title and decreasing binsize plotTimeseries.year(df.interpolated = df.ME$weeklyInterpolated, var = 'totpuf_sloh', binsize = 0.06, chooseYear = 2016, legend.title = 'TP (mg/L)')
Since these functions return a ggplot, they can be additionally customized with ggplot options. For example:
library(MetBrewer) library(ggplot2) plotTimeseries.year(df.interpolated = df.ME$weeklyInterpolated, var = 'totpuf_sloh', chooseYear = 2015, binsize = 0.1, legend.title = 'TP (mg/L)') + scale_fill_manual(values=met.brewer("Hokusai2", 7)) + # override color default geom_point(data = df.ME$observations, aes(x = sampledate, y = depth), size = 1, fill = 'gold', shape = 22, stroke = 0.2) + # sampling observations labs(title = 'Lake Mendota, total phosphorus 2015', x = 'Date') + theme_minimal(base_size = 10)
# Conversion from g to kg df.mass.annual = calcMass(df.ME$weeklyInterpolated,lakeAbr = 'ME', time.res = 'annual', conversion = 1e3)
library(ggplot2) ggplot(df.mass.annual, aes(x = year, y = mass)) + geom_path() + geom_point() + ylab('TP (kg)') + labs(title = 'Lake Mendota mean annual TP mass', caption = 'Calculated from NTLlakeloads') + theme_bw(base_size = 10) + theme(axis.title.x = element_blank())
df.mass = calcMass(df.ME$weeklyInterpolated,lakeAbr = 'ME', time.res = 'weekly', conversion = 1e3) decomposeTS(df.mass, lakeAbr = 'ME', var = 'totpuf_sloh')
Add the following code to your website.
For more information on customizing the embed code, read Embedding Snippets.