Skip to contents

Applies a state machine to a univariate flow time series to detect regime changes (e.g. baseflow, rising limb, peak, recession) based on estimated signal derivatives. Only state transitions are returned.

Usage

run_state_machine(
  time,
  flow,
  params,
  kernel_l = 60,
  time_units = "mins",
  derivative_units = "per_minute"
)

Arguments

time

A vector of timestamps (POSIXct or convertible), representing the time of each observation.

flow

Numeric vector of flow (or discharge) values. Must be the same length as `time`.

params

A list of parameters controlling state transitions. Passed to update_state_no_forecast().

kernel_l

Numeric. Length scale of the smoothing kernel used in state estimation. Default is `60`.

time_units

Character string specifying the time units of the input series (e.g. `"mins"`, `"hours"`). Passed to estimate_state().

derivative_units

Character string specifying the units of the estimated derivatives (e.g. `"per_minute"`). Passed to estimate_state().

Value

A data frame containing only state transitions with columns:

  • `time`: timestamp at which a state change occurs

  • `state`: the new state entered at that time

Details

The function first estimates a smoothed version of the flow signal and its first and second derivatives using estimate_state().

A baseline flow (`baseflow_Q`) is computed as the median of the input flow series. This is used as a reference level in state transitions.

The state machine is initialised in the `"BASEFLOW"` state and updated sequentially using update_state_no_forecast(), which determines the next state based on:

  • current flow (`Q`)

  • first derivative (`dQ`)

  • second derivative (`ddQ`)

  • baseline flow (`baseflow_Q`)

  • user-defined parameters (`params`)

Only points where the state changes are recorded, resulting in a compact representation of regime transitions rather than a full time series.

See also

estimate_state, update_state_no_forecast

Examples

# Simulated example
if (FALSE) { # \dontrun{
set.seed(1)
time <- seq.POSIXt(Sys.time(), by = "min", length.out = 200)
flow <- cumsum(rnorm(200))

params <- list(
  rise_threshold = 0.1,
  fall_threshold = -0.1
)

transitions <- run_state_machine(
  time = time,
  flow = flow,
  params = params
)

head(transitions)
} # }