ssdsims runs reproducible simulation studies for species sensitivity distribution (SSD) models built on the ssdtools package. You describe a study declaratively as a scenario; ssdsims expands it into per-step task tables, draws the data, fits the distributions, and estimates the hazard concentrations. The same scenario runs three ways over one execution core — an in-memory baseline, single-core Hive-partitioned Parquet shards, and a targets-based shard pipeline for running in parallel or on a cluster — with byte-identical, reproducible per-task results throughout.
New here? Start with vignette("ssdsims") for the overview and a recommended reading order.
Installation
Install the development version from GitHub with:
# install.packages("pak")
pak::pak("poissonconsulting/ssdsims")
# or
# install.packages("remotes")
remotes::install_github("poissonconsulting/ssdsims")Usage
Assemble the data, declare a scenario, and run the in-memory baseline:
library(ssdsims)
scenario <- ssd_define_scenario(
ssd_scenario_data(ssddata::ccme_boron),
nsim = 2L,
seed = 42L,
nrow = c(6L, 10L),
ci = TRUE,
nboot = 10L,
ci_method = c("multi_fixed", "weighted_samples")
)
scenario
#> <ssdsims_scenario>
#> seed: 42
#> nsim: 2
#> datasets: ccme_boron
#> nrow: 6, 10
#> replace: TRUE
#> nrow_max: 1000 (setting)
#> fit grid:
#> rescale: FALSE
#> computable: FALSE
#> at_boundary_ok: TRUE
#> min_pmix: ssd_min_pmix
#> range_shape1: {0.05, 20}
#> range_shape2: {0.05, 20}
#> dists: gamma, lgumbel, llogis, lnorm, lnorm_lnorm, weibull (setting)
#> hc grid:
#> est_method: multi (setting)
#> proportion: 0.05 (setting)
#> ci: TRUE (setting)
#> nboot: 10
#> ci_method: multi_fixed, weighted_samples
#> parametric: TRUE
#> samples: FALSE (setting)
#> distsets:
#> BCANZ: gamma, lgumbel, llogis, lnorm, lnorm_lnorm, weibull
#> partition_by:
#> sample: dataset, sim, replace
#> fit: dataset, sim, nrow, rescale
#> hc: dataset, sim
#> bundle:
#> sample:
#> fit: replace, computable, at_boundary_ok, min_pmix, range_shape1, range_shape2
#> hc: replace, nrow, rescale, computable, at_boundary_ok, min_pmix, range_shape1, range_shape2, nboot, ci_method, parametric, distset
ssd_run_scenario_baseline(scenario)
#> $sample
#> <ssdsims_tasks: sample>
#> axes: dataset, sim, replace
#> tasks: 2
#> # A tibble: 2 × 5
#> dataset sim replace sample_id sample
#> <chr> <int> <lgl> <chr> <named list>
#> 1 ccme_boron 1 TRUE dataset=ccme_boron/sim=1/replace=TRUE <tibble>
#> 2 ccme_boron 2 TRUE dataset=ccme_boron/sim=2/replace=TRUE <tibble>
#>
#> $fit
#> <ssdsims_tasks: fit>
#> axes: dataset, sim, replace, nrow, rescale, computable, at_boundary_ok, min_pmix, range_shape1, range_shape2
#> tasks: 4
#> # A tibble: 4 × 16
#> dataset sim replace nrow rescale computable at_boundary_ok min_pmix
#> <chr> <int> <lgl> <int> <lgl> <lgl> <lgl> <chr>
#> 1 ccme_boron 1 TRUE 6 FALSE FALSE TRUE ssd_min_pmix
#> 2 ccme_boron 1 TRUE 10 FALSE FALSE TRUE ssd_min_pmix
#> 3 ccme_boron 2 TRUE 6 FALSE FALSE TRUE ssd_min_pmix
#> 4 ccme_boron 2 TRUE 10 FALSE FALSE TRUE ssd_min_pmix
#> # ℹ 8 more variables: range_shape1 <list>, range_shape2 <list>, fit_id <chr>,
#> # sample_id <chr>, fits <list>, .start <dttm>, .end <dttm>, .host <chr>
#>
#> $hc
#> <ssdsims_tasks: hc>
#> axes: dataset, sim, replace, nrow, rescale, computable, at_boundary_ok, min_pmix, range_shape1, range_shape2, nboot, ci_method, parametric, distset
#> tasks: 8
#> # A tibble: 8 × 20
#> dataset sim replace nrow rescale computable at_boundary_ok min_pmix
#> <chr> <int> <lgl> <int> <lgl> <lgl> <lgl> <chr>
#> 1 ccme_boron 1 TRUE 6 FALSE FALSE TRUE ssd_min_pmix
#> 2 ccme_boron 1 TRUE 6 FALSE FALSE TRUE ssd_min_pmix
#> 3 ccme_boron 1 TRUE 10 FALSE FALSE TRUE ssd_min_pmix
#> 4 ccme_boron 1 TRUE 10 FALSE FALSE TRUE ssd_min_pmix
#> 5 ccme_boron 2 TRUE 6 FALSE FALSE TRUE ssd_min_pmix
#> 6 ccme_boron 2 TRUE 6 FALSE FALSE TRUE ssd_min_pmix
#> 7 ccme_boron 2 TRUE 10 FALSE FALSE TRUE ssd_min_pmix
#> 8 ccme_boron 2 TRUE 10 FALSE FALSE TRUE ssd_min_pmix
#> # ℹ 12 more variables: range_shape1 <list>, range_shape2 <list>, nboot <int>,
#> # ci_method <chr>, parametric <lgl>, distset <chr>, hc_id <chr>,
#> # fit_id <chr>, hc <list>, .start <dttm>, .end <dttm>, .host <chr>The scenario is purely declarative — it draws no random numbers and depends on no targets — so the same object drives every runner. See vignette("defining-a-scenario") for the scenario object and vignette("sharded-pipeline") for the shard and targets pipeline.
Capability map
| Area | Article |
|---|---|
Define a scenario and expand it into sample/fit/hc task tables |
vignette("defining-a-scenario") |
Run as Hive-partitioned Parquet shards and a targets pipeline |
vignette("sharded-pipeline") |
| Combine several scenarios into one ragged design | vignette("scenario-to-design") |
| Run on a SLURM (or other) cluster | vignette("cluster-pipeline") |
| Ship shards to cloud object storage | vignette("cloud-upload") |
| Estimate compute cost before a run | vignette("cost-estimation") |
| Analyse observed compute cost after a run | vignette("cost-analysis") |
Reproducible per-task RNG (the dqrng pcg64 backend with per-task primers) underpins all of the above; see task_primer().