Skip to content

Commit

Permalink
Add ppm to umol conversion utility; update vignette to use it (#29)
Browse files Browse the repository at this point in the history
  • Loading branch information
bpbond authored Feb 25, 2024
1 parent 0e61515 commit 2106123
Show file tree
Hide file tree
Showing 6 changed files with 122 additions and 6 deletions.
1 change: 1 addition & 0 deletions NAMESPACE
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ export(wtf_compute_fluxes)
export(wtf_fit_models)
export(wtf_metadata_match)
export(wtf_normalize_time)
export(wtf_ppm_to_umol)
export(wtf_read_LGR915)
export(wtf_read_LI7810)
export(wtf_read_LI7820)
Expand Down
42 changes: 40 additions & 2 deletions R/models.R
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,10 @@
#' Fit various models to gas concentration data
#'
#' @param time Relative time of observation (typically seconds), numeric
#' @param conc Greenhouse gas concentration, numeric
#' @param conc Greenhouse gas concentration (typically ppm or ppb), numeric
#' @param area Area covered by the measurement chamber (typically cm2), numeric
#' @param volume Volume of the system
#' (chamber + tubing + analyzer, typically cm3), numeric
#' @return A wide-form \code{\link{data.frame}} with fit statistics for linear,
#' robust linear, and polynomial models. By default, extensive details are
#' provided only for the linear fi; for robust linear and polynomial, only
Expand All @@ -24,7 +27,7 @@
#' dat$SECONDS <- dat$SECONDS - min(dat$SECONDS) # normalize time to start at 0
#' plot(dat$SECONDS, dat$CO2)
#' wtf_fit_models(dat$SECONDS, dat$CO2)
wtf_fit_models <- function(time, conc) {
wtf_fit_models <- function(time, conc, area, volume) {
# Basic linear model
try(mod <- lm(conc ~ time))
if(!exists("mod")) {
Expand Down Expand Up @@ -157,3 +160,38 @@ wtf_compute_fluxes <- function(data,
onleft <- c(group_column, time_column)
return(z[c(onleft, setdiff(names(z), onleft))])
}


#' Convert ppm to micromoles using the Ideal Gas Law
#'
#' @param ppm Gas concentration (ppmv), numeric
#' @param volume System volume (chamber + tubing + analyzer, m3), numeric
#' @param temp Optional chamber temperature (degrees C), numeric
#' @param atm Optional atmospheric pressure (Pa), numeric
#' @return The value(s) in micromoles.
#' @export
#' @references Steduto et al.:
#' Automated closed-system canopy-chamber for continuous field-crop monitoring
#' of CO2 and H2O fluxes, Agric. For. Meteorol., 111:171-186, 2002.
#' \url{http://dx.doi.org/10.1016/S0168-1923(02)00023-0}
#' @note If \code{temp} and/or \code{atm} are not provided, the defaults
#' are NIST normal temperature and pressure.
wtf_ppm_to_umol <- function(ppm, volume, temp, atm) {

if(missing(temp)) {
temp <- 20
wtf_message("Assuming temp = ", temp, " C")
}
if(missing(atm)) {
atm <- 101325
wtf_message("Assuming atm = ", atm, " Pa")
}

# Gas constant, from https://en.wikipedia.org/wiki/Gas_constant
R <- 8.31446261815324 # m3 Pa K−1 mol−1
wtf_message("Using R = ", R, " m3 Pa K-1 mol-1")
TEMP_K <- temp + 273.15

# Use ideal gas law to calculate micromoles: n = pV/RT
return(ppm * atm * volume / (R * TEMP_K))
}
9 changes: 7 additions & 2 deletions man/wtf_fit_models.Rd

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

33 changes: 33 additions & 0 deletions man/wtf_ppm_to_umol.Rd

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

18 changes: 18 additions & 0 deletions tests/testthat/test-models.R
Original file line number Diff line number Diff line change
Expand Up @@ -56,3 +56,21 @@ test_that("wtf_compute_fluxes works", {
expect_identical(out$time_min, rep(min(times), nrow(out))) # min of raw times
expect_identical(out$time_max, rep(max(times), nrow(out))) # max of raw times
})

test_that("wtf_ppm_to_umol works", {
withr::local_options(whattheflux.quiet = TRUE)

# Fixed-value test at STP, assuming our ideal gas law implementation is correct
# 0.18 is the slope (ppm CO2/s) of the TG10-01087 example data
x <- wtf_ppm_to_umol(0.18, volume = 0.1)
expect_equal(round(x, 4), 0.7483)

# Colder temperature means larger flux for a given concentration rise
expect_gt(wtf_ppm_to_umol(0.18, volume = 0.1, temp = 5), x)
# Lower pressure means smaller flux for a given concentration rise
expect_lt(wtf_ppm_to_umol(0.18, volume = 0.1, atm = 75000), x)
# Larger volume means larger flux for a given concentration rise
expect_gt(wtf_ppm_to_umol(0.18, volume = 1), x)

# Not sure what else to test
})
25 changes: 23 additions & 2 deletions vignettes/intro-to-whattheflux.Rmd
Original file line number Diff line number Diff line change
Expand Up @@ -112,6 +112,26 @@ p %+% dat

That looks better!

## Unit conversion

We'd like our final units to be in µmol/m2/s, and so need to do some unit
conversion. (This can happen either before or after flux computation, below.)
The package provides `wtf_ppm_to_umol()` that does this conversion using the
[Ideal Gas Law](https://en.wikipedia.org/wiki/Ideal_gas_law).

```{r units}
dat$CO2_umol <- wtf_ppm_to_umol(dat$CO2,
volume = 0.1, # m3
temp = 24) # degrees C
# Note that because we didn't provide the 'atm' parameter,
# wtf_ppm_to_umol assumed standard pressure.
# Also normalize by ground area (0.16 m2)
dat$CO2_umol_m2 <- dat$CO2_umol / 0.16
```


## Compute fluxes

The `wtf_compute_fluxes` function provides a general-purpose tool for
Expand All @@ -122,7 +142,7 @@ QA/QC information.
fluxes <- wtf_compute_fluxes(dat,
group_column = "Plot",
time_column = "TIMESTAMP",
conc_column = "CO2",
conc_column = "CO2_umol_m2",
dead_band = 10)
# By default, wtf_compute_fluxes returns a data.frame with one row per
Expand All @@ -141,7 +161,8 @@ fluxes[c(1:2, 4, 14, 15, 20)]
ggplot(fluxes, aes(Plot, slope_estimate, color = adj.r.squared)) +
geom_point() +
geom_linerange(aes(ymin = slope_estimate - slope_std.error,
ymax = slope_estimate + slope_std.error))
ymax = slope_estimate + slope_std.error)) +
ylab("CO2 flux (µmol/m2/s)")
```

We might want to check whether the robust-linear slope diverges from the
Expand Down

0 comments on commit 2106123

Please sign in to comment.