FluxSeparator separates diffusive and ebullitive (bubble) methane fluxes from continuous concentration measurements. It uses a running variance approach to identify sudden concentration increases caused by ebullition, then calculates diffusive flux from the remaining data using linear regression.
For methodological details, see Sø et al. (2024).
Install the development version from GitHub:
The package includes a small dataset from Lake Lyng with two pump cycles: one with only diffusive flux and one with an ebullitive event.
library(FluxSeparator)
data(DIY_sensor_data)
str(DIY_sensor_data)
#> spc_tbl_ [2,400 × 12] (S3: spec_tbl_df/tbl_df/tbl/data.frame)
#> $ datetime : POSIXct[1:2400], format: "2021-09-28 03:11:35" "2021-09-28 03:11:37" ...
#> $ RH : num [1:2400] 73.3 73.4 73.3 73.3 73.3 73.3 73.3 73.4 73.4 73.5 ...
#> $ tempC : num [1:2400] 19.8 18 17.9 17.9 17.9 17.9 17.9 17.9 17.9 17.9 ...
#> $ CH4smV : num [1:2400] 493 493 493 493 493 ...
#> $ K33_RH : num [1:2400] 44.2 44.2 44.2 44.2 44.2 ...
#> $ K33_Temp : num [1:2400] 28.4 28.4 28.4 28.4 28.4 ...
#> $ K33_CO2 : num [1:2400] 387 387 387 387 387 387 387 387 387 387 ...
#> $ SampleNumber: num [1:2400] 1 2 3 4 5 6 7 8 9 10 ...
#> $ PumpCycle : num [1:2400] 1 1 1 1 1 1 1 1 1 1 ...
#> $ pred_CH4 : num [1:2400] 0.786 2.149 2.243 2.243 2.243 ...
#> $ station : num [1:2400] 1 1 1 1 1 1 1 1 1 1 ...
#> $ sensor : num [1:2400] 1 1 1 1 1 1 1 1 1 1 ...
#> - attr(*, "spec")=
#> .. cols(
#> .. datetime = col_datetime(format = ""),
#> .. `RH%` = col_double(),
#> .. tempC = col_double(),
#> .. CH4smV = col_double(),
#> .. K33_RH = col_double(),
#> .. K33_Temp = col_double(),
#> .. K33_CO2 = col_double(),
#> .. SampleNumber = col_double(),
#> .. PumpCycle = col_double(),
#> .. pred_CH4 = col_double(),
#> .. station = col_double(),
#> .. sensor = col_double()
#> .. )
#> - attr(*, "problems")=<externalptr>The ebullitive_flux() function identifies bubble events
using a running variance threshold. When the running variance exceeds
runvar_cutoff, the data is flagged as an ebullitive
event.
ebul_flux <- ebullitive_flux(DIY_sensor_data, show_plots = FALSE)
ebul_flux
#> # A tibble: 2 × 10
#> # Groups: station [1]
#> station PumpCycle datetime_start datetime_end
#> <dbl> <dbl> <dttm> <dttm>
#> 1 1 1 2021-09-28 03:11:35 2021-09-28 03:51:37
#> 2 1 2 2021-09-28 04:11:35 2021-09-28 04:51:36
#> # ℹ 6 more variables: sum_bubbles_concentration <dbl>, n_bubbles <dbl>,
#> # pumpcycle_duration_hr <dbl>, temp <dbl>, bubbles_per_time <dbl>,
#> # concentration_per_time <dbl>runvar_cutoff (default: 0.5): Lower
values detect more bubbles. Start high and decrease until you capture
the events you see in the data.IndexSpan (default: 30): How many
observations to include before/after each detected event.top_selection: Use "last"
(default) or "max" to determine the peak concentration of
each bubble.show_plots: Set to TRUE
for interactive visual inspection.The diffusive_flux() function first removes ebullitive
events (unless look_for_bubbles = FALSE), then fits a
linear model to the remaining concentration data to estimate the
diffusive flux.
diff_flux <- diffusive_flux(DIY_sensor_data,
cutoff_start_value = 5,
show_plots = FALSE)
#> Adding missing grouping variables: `PumpCycle`
diff_flux
#> # A tibble: 1 × 9
#> # Groups: PumpCycle, station [1]
#> PumpCycle station datetime_start datetime_end
#> <dbl> <dbl> <dttm> <dttm>
#> 1 1 1 2021-09-28 03:18:16 2021-09-28 03:31:37
#> # ℹ 5 more variables: slope_concentration_hr <dbl>, slope_standard_error <dbl>,
#> # n_obs_included_in_lm <int>, r2 <dbl>, temp <dbl>cutoff_start_value: Maximum starting
concentration for a cycle to be included. Use Inf (default)
to include all cycles.remove_observations_prior (default:
200): Skip the first N observations to allow the chamber to
equilibrate.number_of_observations_used (default:
400): Number of observations for the linear regression.look_for_bubbles (default:
TRUE): Set to FALSE for gases where ebullition
is unlikely (e.g., CO2).Convert from ppm per hour to µmol m⁻² h⁻¹ using the ideal gas law:
runvar_cutoffThe most important parameter is runvar_cutoff. To find
the best value:
ebullitive_flux() with
show_plots = TRUErunvar_cutoff until bubble events are correctly
identifiedrunvar_cutoff for both
ebullitive_flux() and diffusive_flux()Both functions can return plot objects as an attribute when
show_plots = TRUE:
citation("FluxSeparator")
#> To cite package 'FluxSeparator' in publications use:
#>
#> Sø J, Sand-Jensen K, Kragh T (2024). "Self-Made Equipment for
#> Automatic Methane Diffusion and Ebullition Measurements From Aquatic
#> Environments." _Journal of Geophysical Research: Biogeosciences_.
#> doi:10.1029/2024JG008035 <https://doi.org/10.1029/2024JG008035>.
#>
#> A BibTeX entry for LaTeX users is
#>
#> @Article{,
#> title = {Self-Made Equipment for Automatic Methane Diffusion and Ebullition Measurements From Aquatic Environments},
#> author = {Jonas Stage Sø and Kaj Sand-Jensen and Theis Kragh},
#> journal = {Journal of Geophysical Research: Biogeosciences},
#> year = {2024},
#> doi = {10.1029/2024JG008035},
#> }