Getting Started with FluxSeparator

Overview

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)].

Installation

Install the development version from GitHub:

install.packages("FluxSeparator")

Loading example data

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")=<pointer: (nil)>

Calculating ebullitive flux

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>

Key parameters

  • 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.

Calculating diffusive flux

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>

Key parameters

  • 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).

Unit conversion

Convert from ppm per hour to µmol m⁻² h⁻¹ using the ideal gas law:

ppm_to_umol(
  pressure = 101325,     # Pa (standard atmospheric)
  concentration = 10,    # ppm/hr
  volume = 0.01,         # m³
  temperature_C = 20,    # °C
  area = 0.05            # m²
)
#> [1] 83.14702

Choosing the right runvar_cutoff

The most important parameter is runvar_cutoff. To find the best value:

  1. Run ebullitive_flux() with show_plots = TRUE
  2. Inspect the running variance plots
  3. Adjust runvar_cutoff until bubble events are correctly identified
  4. Use the same runvar_cutoff for both ebullitive_flux() and diffusive_flux()

Working with plots

Both functions can return plot objects as an attribute when show_plots = TRUE:

result <- ebullitive_flux(DIY_sensor_data, show_plots = TRUE)

# Access individual plots
plots <- attr(result, "plots")

Citing FluxSeparator

citation("FluxSeparator")
#> To cite package 'FluxSeparator' in publications use:
#> 
#>   Sø J, Sand-Jensen K, Kragh T (2026). _FluxSeparator: Separation of
#>   Diffusive and Ebullitive Fluxes_.
#>   doi:10.32614/CRAN.package.FluxSeparator
#>   <https://doi.org/10.32614/CRAN.package.FluxSeparator>.
#> 
#> A BibTeX entry for LaTeX users is
#> 
#>   @Manual{,
#>     title = {FluxSeparator: Separation of Diffusive and Ebullitive Fluxes},
#>     author = {Jonas Stage Sø and Kaj Sand-Jensen and Theis Kragh},
#>     year = {2026},
#>     doi = {10.32614/CRAN.package.FluxSeparator},
#>   }