Integrating with the gasfluxes package"

knitr::opts_chunk$set(
  collapse = TRUE,
  comment = "#>"
)

As noted in the introductory vignette, there are many reasons why greenhouse gas concentration observations might not be well fit by a linear model: diffusion effects, saturation, mixing problems, etc.

The fluxfinder package provides extensive outputs based on linear model fits, and a few QA/QC indicators based on a polynomial model, but there are cases where we might want to take advantage of more sophisticated model-fitting routines.

Some problematic sample data

library(fluxfinder)

# Load the data
# Data from a LI-7810
f <- system.file("extdata/TG10-01087-curvature.data", package = "fluxfinder")
dat <- ffi_read_LI7810(f)

# Fit a linear flux and QA/QC it
flux <- ffi_compute_fluxes(dat, group_column = NULL, time_column = "TIMESTAMP", gas_column = "CO2")
print(flux$lin_flux.estimate)
print(flux$lin_r.squared)
print(flux$poly_r.squared)
print(flux$HM81_flux.estimate)

There's a fairly large jump from the R2 of the linear model (0.93) to that of a polynomial (0.99+), and the flux computed by the Hutchinson and Mosier (1981) nonlinear approach is numeric (i.e., non-NA).

This implies nonlinearity in our data:

library(ggplot2)
dat$SECONDS <- dat$SECONDS-min(dat$SECONDS)
ggplot(dat, aes(SECONDS, CO2)) + geom_point() + 
  # naive linear model
  geom_smooth(method = "lm", formula = 'y ~ x') +
  # HM1981 flux line 
  geom_abline(slope = flux$HM81_flux.estimate, intercept = min(dat$CO2), linetype = 2)

There's definitely a problem! Depending on what we think is happening here, one option would be to change the observation length so that the flux is computed based on only the first ~75 seconds, which looks linear. A second option would be to use the flux_HM1981 field as our flux.

A third option would be fit more sophisticated model(s).

Using the gasfluxes package

The gasfluxes package also provides routines to calculate greenhouse gas fluxes from chamber measurements, and includes code to fit the HMR model as well as several model-selection routines.

library(gasfluxes)

# Add some columns that gasfluxes expects
dat$ID <- "test"
dat$V <- 0.1
dat$A <- 0.16

gasfluxes(dat, .times = "SECONDS", .C = "CO2", plot = FALSE)

gasfluxes will compute on multiple groups (measurements) via its .id parameter, but we can also use use fluxfinder::ffi_compute_fluxes() to handle the grouping and let it call gasfluxes:

# Define a small wrapper function to put things into the format
# that gasfluxes expects
f <- function(time, conc) {
  d <- data.frame(time = time, C = conc, ID = 1, A = 1, V = 1)
  gasfluxes(d, plot = FALSE)
}

ffi_compute_fluxes(dat, NULL, "SECONDS", "CO2", fit_function = f)

Conclusion

This vignette covered how to integrate gasfluxes with fluxfinder, if you want to take advantage of the former package's HMR or NDFE routines. More information on these models can be found in:



Try the fluxfinder package in your browser

Any scripts or data that you put into this service are public.

fluxfinder documentation built on Sept. 9, 2025, 5:39 p.m.