Title: | Parsing, Computation, and Diagnostics for Greenhouse Gas Measurements |
---|---|
Description: | Parse static-chamber greenhouse gas measurement files generated by a variety of instruments; compute flux rates using multi-observation metadata; and generate diagnostic metrics and plots. Designed to be easy to integrate into reproducible scientific workflows. |
Authors: | Stephanie Wilson [cre] , Ben Bond-Lamberty [aut] , Genevieve Noyce [ctb] , Roberta Bittencourt Peixoto [ctb] , Patrick Megonigal [ctb] , Smithsonian Institution [cph, fnd] |
Maintainer: | Stephanie Wilson <[email protected]> |
License: | MIT + file LICENSE |
Version: | 1.0.0 |
Built: | 2025-01-10 15:23:19 UTC |
Source: | https://github.com/cranhaven/cranhaven.r-universe.dev |
Compute fluxes for multiple groups (measurements)
ffi_compute_fluxes( data, group_column, time_column, gas_column, dead_band = 0, normalize_time = TRUE, fit_function = ffi_fit_models, ... )
ffi_compute_fluxes( data, group_column, time_column, gas_column, dead_band = 0, normalize_time = TRUE, fit_function = ffi_fit_models, ... )
data |
A |
group_column |
Name of the grouping column in |
time_column |
Name of the time column in |
gas_column |
Name of the gas (concentration or quantity) column in
|
dead_band |
Length of dead band, the equilibration period at the beginning of the time series during which data are ignore, in seconds (numeric) |
normalize_time |
Normalize the values so that first is zero? Logical |
fit_function |
Optional flux-fit function;
default is |
... |
Other parameters passed to |
A data.frame with one row per group_column
value. It will
always include the mean, minimum, and maximum values of time_column
for that group, but other
columns depend on what is returned by the fit_function
.
# No grouping ffi_compute_fluxes(cars, group_column = NULL, "speed", "dist") # With grouping cars$Plot <- c("A", "B") ffi_compute_fluxes(cars, "Plot", "speed", "dist") # See the introductory vignette for a fully-worked example with real data
# No grouping ffi_compute_fluxes(cars, group_column = NULL, "speed", "dist") # With grouping cars$Plot <- c("A", "B") ffi_compute_fluxes(cars, "Plot", "speed", "dist") # See the introductory vignette for a fully-worked example with real data
Fit various models to gas concentration data
ffi_fit_models(time, conc, area, volume)
ffi_fit_models(time, conc, area, volume)
time |
Relative time of observation (typically seconds), numeric |
conc |
Greenhouse gas concentration (typically ppm or ppb), numeric |
area |
Area covered by the measurement chamber (typically cm2), numeric |
volume |
Volume of the system (chamber + tubing + analyzer, typically cm3), numeric |
If a linear model cannot be fit, NULL is returned. If the robust
linear and/or polynomial models cannot be fit, then NA
is returned
for their particular statistics. The HM1981 approach is only valid for
saturating (exponential) data and NA
is returned otherwise.
A wide-form data.frame
with fit statistics for linear
("lin", lm
), robust linear ("rob", rlm
),
polynomial ("poly"), and H&M1981 ("HM81", ffi_hm1981
) models.
The latter is based on an exponential model drawn from one-dimensional
diffusion theory; see Hutchinson and Mosier (1981) and Nakano et al. (2004).
For each model type, the following columns are returned:
Model statistics AIC
, r.squared
, RMSE
,
and p.value
;
Flux (slope) statistics flux.estimate
and flux.std.error
;
Intercept statistics int.estimate
and int.std.error
;
For the robust linear regression model only,
a logical value converged
.
Normally this is not called directly by users,
but instead via ffi_compute_fluxes
.
Nakano, T., Sawamoto, T., Morishita, T., Inoue, G., and Hatano, R.: A comparison of regression methods for estimating soil–atmosphere diffusion gas fluxes by a closed-chamber technique, Soil Biol. Biochem., 36, 107–113, 2004. doi:10.1016/j.soilbio.2003.07.005
Hutchinson, G. L. and Mosier, A. R.: Improved soil cover method for field measurement of nitrous oxide fluxes, Soil Sci. Soc. Am. J., 45, 311-316, 1981. doi:10.2136/sssaj1981.03615995004500020017x
# Toy data - linear ffi_fit_models(cars$speed, cars$dist) # Toy data - nonlinear ffi_fit_models(Puromycin$conc, Puromycin$rate) # Real data f <- system.file("extdata/TG10-01087.data", package = "fluxfinder") dat <- ffi_read_LI7810(f)[1:75,] # isolate first observation dat$SECONDS <- dat$SECONDS - min(dat$SECONDS) # normalize time to start at 0 plot(dat$SECONDS, dat$CO2) ffi_fit_models(dat$SECONDS, dat$CO2)
# Toy data - linear ffi_fit_models(cars$speed, cars$dist) # Toy data - nonlinear ffi_fit_models(Puromycin$conc, Puromycin$rate) # Real data f <- system.file("extdata/TG10-01087.data", package = "fluxfinder") dat <- ffi_read_LI7810(f)[1:75,] # isolate first observation dat$SECONDS <- dat$SECONDS - min(dat$SECONDS) # normalize time to start at 0 plot(dat$SECONDS, dat$CO2) ffi_fit_models(dat$SECONDS, dat$CO2)
Compute flux using nonlinear Hutchinson and Mosier (1981) model
ffi_hm1981(time, conc, h = 1)
ffi_hm1981(time, conc, h = 1)
time |
Time values, numeric |
conc |
Gas concentration values, numeric |
h |
Effective chamber height |
Flux estimate; see references for more information.
Hutchinson, G. L. and Mosier, A. R.: Improved soil cover method for field measurement of nitrous oxide fluxes, Soil Sci. Soc. Am. J., 45, 311-316, 1981. doi:10.2136/sssaj1981.03615995004500020017x
# If data are approximately linear, then NA is returned ffi_hm1981(cars$speed, cars$dist) # If data are nonlinear (saturating) then flux based on gas diffusion theory ffi_hm1981(Puromycin$conc, Puromycin$rate)
# If data are approximately linear, then NA is returned ffi_hm1981(cars$speed, cars$dist) # If data are nonlinear (saturating) then flux based on gas diffusion theory ffi_hm1981(Puromycin$conc, Puromycin$rate)
Match metadata info with a vector of data timestamps
ffi_metadata_match(data_timestamps, start_dates, start_times, obs_lengths)
ffi_metadata_match(data_timestamps, start_dates, start_times, obs_lengths)
data_timestamps |
Data timestamps, either character (YYYY-MM-DD HH:MM:SS) or |
start_dates |
Metadata measurement dates, either character
(YYYY-MM-DD) or |
start_times |
Metadata measurement start time entries, either character (HH:MM:SS) or |
obs_lengths |
Observation lengths in seconds, numeric; must be same
length as |
A numeric vector equal in length to data_timestamps
, with
each entry indicating the metadata entry that should be used for that
observation. NA
is returned if a timestamp has no match in the metadata (i.e., does not
fall within any window defined by the start_dates
, start_times
,
and observation length parameters).
If data_timestamps
or start_dates
cannot be parsed as
YYYY-MM-DD, the preferred format, then MM/DD/YYYY (used by U.S. versions of
Microsoft Excel when saving CSV files, for example) will be tried.
# Data timestamps d_t <- c("2024-01-01 13:00:05", "2024-01-01 13:00:10", "2024-01-01 13:05:05", "2024-01-01 13:10:00") # Metadata start dates and times: two measurements, starting 5 minutes apart s_d <- c("2024-01-01", "2024-01-01") s_t <- c("13:00:00", "13:05:00") ol <- c(60, 60) # Observation lengths ffi_metadata_match(d_t, s_d, s_t, ol) # Returns {1, 1, 2, NA} indicating that the first and second data timestamps # correspond to metadata entry 1, the third to entry 2, and the fourth # has no match # This generates an error because of overlapping timestamps: ## Not run: s_t <- c("13:00:00", "13:01:00") ffi_metadata_match(d_t, s_d, s_t, ol) ## End(Not run)
# Data timestamps d_t <- c("2024-01-01 13:00:05", "2024-01-01 13:00:10", "2024-01-01 13:05:05", "2024-01-01 13:10:00") # Metadata start dates and times: two measurements, starting 5 minutes apart s_d <- c("2024-01-01", "2024-01-01") s_t <- c("13:00:00", "13:05:00") ol <- c(60, 60) # Observation lengths ffi_metadata_match(d_t, s_d, s_t, ol) # Returns {1, 1, 2, NA} indicating that the first and second data timestamps # correspond to metadata entry 1, the third to entry 2, and the fourth # has no match # This generates an error because of overlapping timestamps: ## Not run: s_t <- c("13:00:00", "13:01:00") ffi_metadata_match(d_t, s_d, s_t, ol) ## End(Not run)
Generate a QA/QC document
ffi_qaqc( flux_data, group_column, output_file = "qaqc.html", output_dir = getwd(), open_output = TRUE )
ffi_qaqc( flux_data, group_column, output_file = "qaqc.html", output_dir = getwd(), open_output = TRUE )
flux_data |
A data frame from |
group_column |
Name of the grouping label column in |
output_file |
Name of the output file |
output_dir |
Name of the output directory; default is current working directory |
open_output |
Automatically open the output HTML file? |
The path of the output file.
# Toy data cars$Plot <- c("A", "B") fd <- ffi_compute_fluxes(cars, "Plot", "speed", "dist") x <- ffi_qaqc(fd, group_column = "Plot") file.remove(x) # clean up # See the introductory vignette for a fully-worked example with real data
# Toy data cars$Plot <- c("A", "B") fd <- ffi_compute_fluxes(cars, "Plot", "speed", "dist") x <- ffi_qaqc(fd, group_column = "Plot") file.remove(x) # clean up # See the introductory vignette for a fully-worked example with real data
Read an EGM-4 data file
ffi_read_EGM4(file, year, tz = "UTC")
ffi_read_EGM4(file, year, tz = "UTC")
file |
Filename to read, character |
year |
Four-digit year of the data (EGM-4 output files have month, day, hour, and minute, but not year), numeric or character |
tz |
Time zone of the file's time data, character (optional) |
A data.frame
with the parsed data.
f <- system.file("extdata/EGM4-data.dat", package = "fluxfinder") dat <- ffi_read_EGM4(f, 2023) dat <- ffi_read_EGM4(f, 2023, tz = "EST") # specify time zone
f <- system.file("extdata/EGM4-data.dat", package = "fluxfinder") dat <- ffi_read_EGM4(f, 2023) dat <- ffi_read_EGM4(f, 2023, tz = "EST") # specify time zone
Read a LGR 915-0011 data file
ffi_read_LGR915(file, date_format = "DMY", tz = "UTC")
ffi_read_LGR915(file, date_format = "DMY", tz = "UTC")
file |
Filename to read, character |
date_format |
Date format, character: "MDY" (month-day-year) "DMY" (day-month-year), or "YMD" (year-month-day) |
tz |
Time zone of the file's time data, character (optional) |
The LGR 915-0011 was an Ultra-Portable Greenhouse Gas Analyzer made
by Los Gatos Research. The date in its output files can appear in different
formats, which is why the date_format
parameter is needed.
A data.frame
with the parsed data.
Some LGR 915 files can have a PGP block at the end; this is ignored.
f <- system.file("extdata/LGR-data.csv", package = "fluxfinder") dat <- ffi_read_LGR915(f, date_format = "MDY") dat <- ffi_read_LGR915(f, date_format = "MDY", tz = "EST") # specify time zone
f <- system.file("extdata/LGR-data.csv", package = "fluxfinder") dat <- ffi_read_LGR915(f, date_format = "MDY") dat <- ffi_read_LGR915(f, date_format = "MDY", tz = "EST") # specify time zone
Read a LI-7810 data file
ffi_read_LI7810(file)
ffi_read_LI7810(file)
file |
Filename to read, character |
Currently LI-7810 and LI-7820 files are handled identically.
A data.frame
with the parsed data.
f <- system.file("extdata/TG10-01087.data", package = "fluxfinder") dat <- ffi_read_LI7810(f)
f <- system.file("extdata/TG10-01087.data", package = "fluxfinder") dat <- ffi_read_LI7810(f)
Read a LI-7820 data file
ffi_read_LI7820(file)
ffi_read_LI7820(file)
file |
Filename to read, character |
Currently LI-7810 and LI-7820 files are handled identically.
A data.frame
with the parsed data.
f <- system.file("extdata/TG20-01182.data", package = "fluxfinder") dat <- ffi_read_LI7820(f)
f <- system.file("extdata/TG20-01182.data", package = "fluxfinder") dat <- ffi_read_LI7820(f)
Read a LI-850 data file
ffi_read_LI850(file, tz = "UTC")
ffi_read_LI850(file, tz = "UTC")
file |
Filename to read, character |
tz |
Time zone of the file's time data, character (optional) |
A data.frame
with the parsed data, including a
TIMESTAMP
column.
f <- system.file("extdata/LI850.txt", package = "fluxfinder") dat <- ffi_read_LI850(f) dat <- ffi_read_LI850(f, tz = "EST") # specify time zone
f <- system.file("extdata/LI850.txt", package = "fluxfinder") dat <- ffi_read_LI850(f) dat <- ffi_read_LI850(f, tz = "EST") # specify time zone
Read a LI-8200-01S (smart chamber) data file
ffi_read_LIsmartchamber(file, concentrations = TRUE)
ffi_read_LIsmartchamber(file, concentrations = TRUE)
file |
Filename to read, character |
concentrations |
Return concentration data (the default), or just summary information? Logical |
A data.frame
with the parsed data.
These files are in JSON format. See also https://www.licor.com/env/products/soil-flux/smart-chamber.
Ben Bond-Lamberty
f <- system.file("extdata/LI8200-01S.json", package = "fluxfinder") dat <- ffi_read_LIsmartchamber(f) # returns 240 rows ffi_read_LIsmartchamber(f, concentrations = FALSE) # only 4 rows
f <- system.file("extdata/LI8200-01S.json", package = "fluxfinder") dat <- ffi_read_LIsmartchamber(f) # returns 240 rows ffi_read_LIsmartchamber(f, concentrations = FALSE) # only 4 rows
Read a Picarro G2301 data file
ffi_read_PicarroG2301(file, tz = "UTC")
ffi_read_PicarroG2301(file, tz = "UTC")
file |
Filename to read, character |
tz |
Time zone of the file's time data, character (optional) |
A data.frame
with the parsed data.
https://www.picarro.com/environmental/products/g2301_gas_concentration_analyzer
f <- system.file("extdata/PicarroG2301-data.dat", package = "fluxfinder") dat <- ffi_read_PicarroG2301(f) dat <- ffi_read_PicarroG2301(f, tz = "EST") # specify time zone
f <- system.file("extdata/PicarroG2301-data.dat", package = "fluxfinder") dat <- ffi_read_PicarroG2301(f) dat <- ffi_read_PicarroG2301(f, tz = "EST") # specify time zone
Convert gas concentration to quantity using the Ideal Gas Law
ffi_ppm_to_umol(ppm, volume, temp, atm) ffi_ppb_to_nmol(ppb, volume, temp, atm)
ffi_ppm_to_umol(ppm, volume, temp, atm) ffi_ppb_to_nmol(ppb, volume, temp, atm)
ppm |
Gas concentration (ppmv), numeric |
volume |
System volume (chamber + tubing + analyzer, m3), numeric |
temp |
Optional chamber temperature (degrees C), numeric |
atm |
Optional atmospheric pressure (Pa), numeric |
ppb |
Gas concentration (ppbv), numeric |
The quantity value, in micromoles (for ffi_ppm_to_umol
)
or nanomoles (for ffi_ppb_to_nmol
).
If temp
and/or atm
are not provided, the defaults
are NIST normal temperature and pressure.
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. doi:10.1016/S0168-1923(02)00023-0
ffi_ppm_to_umol(400, 0.1) ffi_ppb_to_nmol(400, 0.1)
ffi_ppm_to_umol(400, 0.1) ffi_ppb_to_nmol(400, 0.1)