Skip to content

Instantly share code, notes, and snippets.

@jslefche
Last active August 12, 2019 14:54
Show Gist options
  • Save jslefche/0efb557ff2f245f4d0cf to your computer and use it in GitHub Desktop.
Save jslefche/0efb557ff2f245f4d0cf to your computer and use it in GitHub Desktop.
Trichromatic equations

Calculation of chlorophyll concentration based on spectrophotometric equations

The function chlA uses the trichromatic equations to convert absorbance values (wavelengths, in nm) to estimates of chlorophyll concentration using the equations from:

Jeffrey, S. W., and G. F. Humphrey. 1975. New spectrophotometric equations for determining chlorophylls a, b, c1 and c2 in higher plants, algae and natural phytoplankton. Biochem Physiol Pflanz BPP:191–194.

The function takes a data.frame with the following values in the column names (corresponding to wavelengths in the equations in Jeffrey & Humphrey): "480", "510", "630", "647", "664", and "750." Additional arguments include extraction container volume (vol) and, optionally, area of extration (area, representing surface area for epiphytic algae).

The function returns the same data.frame with columns appending for chlorophyll-a, -b, and -c, and phaeopigment concentrations.

Examples

# Create fake absorbance data
set.seed(3)

fake.chla.data = data.frame(
  sample = letters[1:20],
  X480nm = sample(seq(0, 0.04, 0.001), 20, replace = TRUE), 
  X510nm = sample(seq(0, 0.02, 0.001), 20, replace = TRUE), 
  X630nm = sample(seq(0, 0.015, 0.001), 20, replace = TRUE), 
  X647nm = sample(seq(0, 0.02, 0.001), 20, replace = TRUE), 
  X664nm = sample(seq(0, 0.08, 0.001), 20, replace = TRUE), 
  X750nm = sample(seq(0, 0.01, 0.001), 20, replace = TRUE)
  )
  
# Run function
chlA(fake.chla.data)

# Run function with different volume
chlA(fake.chla.data, vol = 60)

# Run function but scale to area (in cm2)
chlA(fake.chla.data, area = 20)
#' `edgarMethod` an R function for estimating algal biomass using the trichromatic equations
#' Author: Jon Lefcheck
#' Last updated: 01 February 2017
#' @param x = a sample-by-wavelength matrix
#' @param volume = the volume (in mL) of the extraction vial
#' @param area = the area of the extraction vial (if reported)
#' @return a `data.frame` containing the original values, and estimated abundances of chlorophyll a, b, c, and phaeopigments
chlA = function(data, vol = 20, area = NULL) {
# Extract only numeric columns
data.sub = data[, sapply(data, is.numeric)]
# Set any negative absorbances to zero
data.sub[data.sub < 0] = 0
# Identify which columsn correspond to which absorbances
WL480 = data.sub[, grepl("480", colnames(data.sub))]
WL510 = data.sub[, grepl("510", colnames(data.sub))]
WL630 = data.sub[, grepl("630", colnames(data.sub))]
WL647 = data.sub[, grepl("647", colnames(data.sub))]
WL664 = data.sub[, grepl("664", colnames(data.sub))]
WL750 = data.sub[, grepl("750", colnames(data.sub))]
# Stop function if missing any absorbances
if(any(sapply(list(WL480, WL510, WL630, WL647, WL664, WL750), function(x) all(is.na(x))))) {
# Get missing wavelength
nm = which(sapply(list(WL480, WL510, WL630, WL647, WL664, WL750), function(x) all(is.na(x))))
stop(paste("Missing ", c("480", "510", "630", "647", "664", "750")[nm]," nm wavelength!", sep = ""))
}
# Use trichromatic equations to convert absorbances into ug mL-1
chla.data = data.frame(
chla = 11.85 * (WL664 - WL750) - 1.54 * (WL647 - WL750) - 0.08 * (WL630 - WL750),
chlb = 21.03 * (WL647 - WL750) - 5.43 * (WL664 - WL750) - 2.66 * (WL630 - WL750),
chlc = 24.52 * (WL630 - WL750) - 1.67 * (WL664 - WL750) - 7.60 * (WL647 - WL750),
chlp = 7.60 * ((WL480 - 3 * WL750) - 1.49 * (WL510 - 2 * WL750))
)
names(chla.data) = c("chla", "chlb", "chlc", "chlp")
#Multiply by volume of sample (default is 20 mL) to yield ug biomass
chla.data = chla.data * 20
# Standardize to area (if present)
if(!is.null(area)) chla.data = chla.data / area
# Return data
data.frame(data, chla.data)
}
@Rodgerthat787
Copy link

A few questions...

  1. Has anyone run into issues with certain absorbance values causing the error message
    "Error in seq.default(0.0084, 0.008, 0.017) : wrong sign in 'by' argument" ?
    This specific line in my data table will not compute, while other data tables have had no trouble:
    jul23run2.chla.data = data.frame(
    sample = letters[1:3],
    X480nm = sample(seq(0.0036, 0.0038, 0.0287), 3, replace = TRUE),
    X510nm = sample(seq(0.0024, 0.0034, 0.0146), 3, replace = TRUE),
    X630nm = sample(seq(0.0084, 0.0080, 0.0170), 3, replace = TRUE), ******
    X647nm = sample(seq(0.0089, 0.0090, 0.0195), 3, replace = TRUE),
    X664nm = sample(seq(), 3, replace = TRUE),
    X750nm = sample(seq(-0.0033, -0.0026, 0.0002), 3, replace = TRUE)
    )

  2. I have a data set that is missing the absorbance for wavelength 664nm, so I left the sequence blank since chlA formula accounts for missing wavelengths, and the computed table showed values of 1 for each sample at 664nm, so I'm wondering if that is what it is supposed to do versus computing values based on the other absorbances given.

Thanks!

@jslefche
Copy link
Author

jslefche commented Aug 12, 2019 via email

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment