Skip to contents

FL Operating model & Sampling Simulator

Guide and documentation: https://henning-winker.github.io/FLOSS/ (How it works · User guide · Teaching scenarios · Functions)

FLOSS builds multi-fleet, multi-species age-structured operating models and the data such fisheries produce: catch and effort by fleet, CPUE, survey indices, length frequencies and biological samples (length, age, weight, maturity) with realistic sampling error. It is made for training (trainees analyse data from a fishery whose truth is known) and for trainers (generate example datasets in a few clicks, with an answer key).

It builds on FLR (FLCore, FLBRP, FLasher, FLife) and FLRef.

Concept

1 FISHERY        ->  2 SPECIES           ->  3 OM                 ->  4 SAMPLING      ->  5 EXPORT
fleets, years,       life history, MSY,      calibrate to MSY,        catch, effort,      pick species
nominal effort,      selectivity and         nsim iterations,         CPUE, survey,       and iterations
effort creep         catchability by fleet   truth + refpts           LFD, bio samples    -> csv/xlsx/rds
  • Shared effort. Fleets have nominal effort trends with process noise that is common to all species, so species caught by the same fleet share effort anomalies. Apical F of species s and fleet f is F[s,f,y] = relq[s,f] * Fmsy[s] * efficiency[f,y] * effort[f,y].
  • Effort creep. An annual efficiency increase raises F but is not visible in the nominal effort index, which produces hyperstable CPUE.
  • Species library. Four example reef species (Siganus sutor, Lethrinus mahsena, Lutjanus bohar, Carcharhinus melanopterus); users can copy, edit and save their own as plain YAML.
  • Engine first. Everything runs from R scripts; the Shiny app (run_app()) only collects inputs and calls the same functions.

The app

install.packages(c("shiny", "shinydashboard", "commonmark"))
FLOSS::run_app()

The app has the layout of the FLicc app: numbered steps in the left panel, sub-tabs on each page, a Before you run checklist with the Build operating model and Sample data buttons, and a status pill at the top.

Step Sub-tabs
Guide Start here, How it works, Sampling and size data, Warning flags, Truth and export, Settings explained
1 Fishery Fleets and effort (reef, one gear, or a new fishery: add gears one by one), Effort creep, Effort realisation
2 Species Library (choose, add, save), Life history, Selectivity, Exploitation
3 Operating model Settings, Stock trends, Fleets, Equilibrium, Spawners vs vulnerable, Stock and recruitment
4 Treatments Build, Predict, Reveal (prediction vs what happened, true response, length data)
5 Sampling Overview, Catch, Effort, CPUE, Survey, Length frequencies, Biological samples
6 Export Datasets (zip of csv/xlsx with optional answer key), Settings (YAML)
7 True status Status, Trajectories, Kobe plot, Downloads (only when Hide truth is unticked)

Installation

Install the FLR packages from r-universe only, then FLOSS from GitHub:

install.packages(c("FLCore", "ggplotFL", "FLBRP", "FLasher", "FLife", "FLRef"),
                 repos = "https://flr.r-universe.dev")
remotes::install_github("Henning-Winker/FLOSS", build_vignettes = TRUE)
install.packages(c("shiny", "shinydashboard", "commonmark"))   # for the app

Guides

vignette("floss-02-user-guide", "FLOSS")          # if installed with build_vignettes = TRUE
FLOSS::floss_guide("user-guide")                  # copy the guide (.Rmd and .R) to your folder
FLOSS::floss_guide("all", dir = "guides", render = TRUE)   # copy and render all guides

The guide sources live in inst/guide/ (always installed); the vignettes in vignettes/ include them. Fully commented R-script versions, as in JABBA3: inst/guide/FLOSS_user_guide.R and inst/guide/FLOSS_teaching.R (file.edit(system.file("guide", "FLOSS_user_guide.R", package = "FLOSS"))).

Quick start

library(FLOSS)

# 1-3: fishery, species and operating models (4 reef species, 3 fleets)
fy  <- load_fishery("reef_3fleets")
oms <- build_oms(species_library()$id, fy, nsim = 100)
plot_om(oms)

# 4-5: sampling settings and data (CPUE/length/bio: last 5, 10, 15 years)
oem <- reef_oem()
dat <- sample_data(oms, oem, iters = 1:10)
plot_availability(dat, "Lutjanus bohar")
plot_obs(dat, "Lutjanus bohar", what = "index", truth = TRUE)
plot_lfd(dat, "Lutjanus bohar")
plot_bio(dat, "Lutjanus bohar", what = "alk")
plot_caa(caa_obs(dat, "Lutjanus bohar", "linefish"))

# 6: save one dataset per iteration + answer key
export_data(dat, "reef_course", format = c("csv", "xlsx"), zip = TRUE)

Vignettes:

Teaching: treatments with common random numbers

sp <- one_gear_species(load_species("lutjanus_bohar"))   # handline; effort = F/Fmsy
rt <- run_treatment(sp, one_gear_fishery(1),
        list(pulse   = treatment("strong 2012 year class",
                         recruitment = list(type = "pulse", years = 2012, mult = 8)),
             decline = treatment("recruitment -10%/yr",
                         recruitment = list(type = "trend", from = 2005, rate = -0.1))),
        nsim = 10, oem = oem_settings(one_gear_fishery(1), tail = 30), iters = 1:5)
plot_treatment(rt)
plot_length_indicators(length_indicators(rt, "Lutjanus bohar"))

Main functions

Step Functions
Fishery fishery(), effort_trend(), reef_fishery(), load_fishery(), plot_effort()
Species species(), selectivity(), species_library(), load_species(), save_species()
Operating model build_om(), build_oms(), catch_fleet(), plot_om(), plot_fleets()
Sampling oem_settings(), survey_settings(), season_design(), reef_oem(), sample_data(), lfd_annual(), plot_seasons() (CPUE with AR1 residuals, FLRef two-stage length samples, biological samples with random or length-stratified ageing)
Aggregation (teaching) catch_table(), effort_table(), nominal_cpue(), plot_aggregate(), lfd_aggregate(), plot_bio(by =)
FLR export as_flr(), export_data(format = "rds"): FLQuants, FLIndices and FLPar for JABBA3 and FLicc
Colours FLOSS muted palette by default; floss.r4col() (r4ss palette, as in JABBA) if preferred
Observations plot_availability(), plot_obs(), plot_lfd(), plot_bio(), alk_obs(), caa_obs(), plot_caa() – observations only, nothing fitted
Treatments treatment(), run_treatment(), plot_treatment(), one_gear_fishery(), one_gear_species() – baseline and treatment share all random numbers
Dynamics plot_eq() (equilibrium curves with the realised path), plot_srr(), plot_eq_selectivity() (growth overfishing), plot_ssb_vb() (spawners vs what each gear sees)
Size data and flags length_indicators(), plot_length_indicators(), plot_lfd(cohorts = TRUE), plot_indicators() (dashboard), planted artefacts (cpue_q_step, catch_bias_from, bio_age_bias, survey q_step) with planted_artefacts()
Basic fits (optional) fit_growth(), fit_lw(), fit_maturity(), catch_curve(), catch_curve_length(), M_empirical(), cpue_check(), plot_fit()
Truth (trainers) status_table(), plot_truth(), plot_kobe(), export_truth()
Save export_data(), read_dataset(), simulate_fishery() (all in one call)

Roadmap

Version Content
0.1 Specs (fishery, species) with YAML library; OM engine reproducing the multi-gear reef example; shared effort and effort creep
0.2 Sampling: catch, effort, CPUE (AR1 residuals), survey, two-stage length samples (FLRef lfd.sim()), biological samples (random or length-stratified ageing); observed ALK and catch-at-age; export with answer key; user guide
0.3 Treatments with common random numbers; dynamics plots; length indicators, cohort lines, indicator dashboard; plantable artefacts with hidden answer key; optional basic fits; guide and teaching vignette
0.4 Shiny app run_app() in the FLicc layout: Guide, Fishery, Species, OM, Treatments (predict, reveal), Sampling, Export, True status; info tooltips (floss_tip()), Hide truth switch
0.4.1 Seasonal sampling by default (season_design(): balanced, fixed imbalance, shift, opportunistic, per fleet), lfd_annual(), plot_seasons(), Seasons tab in the app
0.4.2 Gradual sampling shifts, change in sampling intensity (e.g. funding cut), randomly missing sampling years
0.5.7 Appendix: methods and equations (effort, F by gear and species, MSY calibration, age-structured dynamics, treatments, sampling incl. two-stage length sampling and autocorrelated CPUE); Kobe trajectories; fix for JABBA3 masking
0.5.5 Length frequencies by season (plot_lfd(by_season = TRUE); app: By season) to show imbalanced seasonal sampling; histogram, ridge and bubble views; survey off by default
0.5.1 New fishery in the app (add gears by name); guides in inst/guide with floss_guide() and fully commented R scripts (as in JABBA3)
0.5.0 Effort in fishing days; naive aggregation for teaching (catch, effort and nominal CPUE by fleet, all fleets, all species; length samples pooled or raised to the catch; biological samples by fleet, all fleets or season); FLR export for JABBA3 and FLicc
0.5 Trainee data viewer for exported datasets
0.6 Project save/load, more survey designs, seasonal effort
later sex-structured and spatial stocks, link to mse via sampling.lfd.oem()

Acknowledgement

The progression of the teaching material (simple population dynamics, then data, then models) is inspired by Haddon, M. (2021) Using R for Modelling and Quantitative Methods in Fisheries, Chapman & Hall/CRC.

License

GPL (>= 3)