stochLAB
A tool to run collision risk models for seabirds on offshore wind farms.
https://github.com/marinescotlandscience/stochlab
Category: Renewable Energy
Sub Category: Wind Energy
Keywords
collision-risk migratoryspecies offshore-wind seabirds
Keywords from Contributors
geocoding
Last synced: about 9 hours ago
JSON representation
Repository metadata
The stochastic collision risk model toolbox
- Host: GitHub
- URL: https://github.com/marinescotlandscience/stochlab
- Owner: MarineScotlandScience
- License: other
- Created: 2021-07-15T19:55:27.000Z (almost 4 years ago)
- Default Branch: master
- Last Pushed: 2024-01-29T15:05:58.000Z (about 1 year ago)
- Last Synced: 2025-04-25T00:02:25.095Z (3 days ago)
- Topics: collision-risk, migratoryspecies, offshore-wind, seabirds
- Language: R
- Homepage: https://hidef-aerial-surveying.github.io/stochLAB/
- Size: 33 MB
- Stars: 7
- Watchers: 7
- Forks: 2
- Open Issues: 13
- Releases: 9
-
Metadata Files:
- Readme: README.Rmd
- Contributing: CONTRIBUTING.md
- License: LICENSE
README.Rmd
--- output: github_document editor_options: markdown: wrap: 80 --- ```{r, include = FALSE} knitr::opts_chunk$set( collapse = TRUE, comment = "#>", fig.path = "man/figures/README-", out.width = "100%" ) ``` # stochLAB[](https://github.com/HiDef-Aerial-Surveying/stochLAB/actions/workflows/test-coverage.yaml) [](https://github.com/HiDef-Aerial-Surveying/stochLAB/actions/workflows/pkgdown.yaml) [](https://github.com/HiDef-Aerial-Surveying/stochLAB/actions/workflows/R-CMD-check.yaml) [](https://github.com/HiDef-Aerial-Surveying/stochLAB/actions/workflows/pkgcheck.yaml) [](https://github.com/ropensci/software-review/issues/551) `{stochLAB}` is a tool to run Collision Risk Models (CRMs) for seabirds on offshore wind farms. ## Overview The `{stochLAB}` package is an adaptation of the [R code](https://data.marine.gov.scot/dataset/developing-avian-collision-risk-model-incorporate-variability-and-uncertainty-r-code-0) developed by [Masden (2015)](https://data.marine.gov.scot/dataset/developing-avian-collision-risk-model-incorporate-variability-and-uncertainty) to incorporate variability and uncertainty in the avian collision risk model originally developed by [Band (2012)](https://www.bto.org/sites/default/files/u28/downloads/Projects/Final_Report_SOSS02_Band1ModelGuidance.pdf). The package is for use by individuals modelling collision risk of seabirds at offshore wind farms. The primary functions take input information on the morphology, behaviour and densities of seabirds as well data pertaining to the proposed wind farm (i.e., turbine dimensions, speed and number). These collision risk models are useful for marine ornithologists who are working in the offshore wind industry, particularly in UK waters. However, the package itself relies on generic biological and windfarm data and can be applied anywhere (i.e., in any marine environment) as long as the parameters are appropriate for the species and windfarms of interest. Code developed under `{stochLAB}` substantially re-factored and re-structured Masden's (heavily script-based) implementation into a user-friendly, streamlined, well documented and easily distributed tool. Furthermore, the package lays down the code infrastructure for easier incorporation of new functionality, e.g. extra parameter sampling features, model expansions, etc. In addition, previous code underpinning core calculations for the extended model has been replaced by an alternative approach, resulting in significant gains in computational speed over Masden's code. This optimization is particularly beneficial under a stochastic context, when core calculations are called repeatedly during simulations. For a more detailed overview type `?stochLAB`, once installed! ## Installation You can install the released version of stochLAB from [CRAN](https://CRAN.R-project.org) with: ``` r install.packages("stochLAB") ``` You can install the development version with: ``` r # install.packages("devtools") devtools::install_github("HiDef-Aerial-Surveying/stochLAB") ``` This package depends on the following packages, which should be installed automatically: `cli dplyr glue logr magrittr msm pracma purrr rlang stats tibble tidyr` ## Bug reports To report any bugs, please log an [ISSUE](https://github.com/HiDef-Aerial-Surveying/stochLAB/issues) ## Input parameters Many of the input parameters for the `stoch_crm()` function need to be obtained from developers (e.g., blade pitch, rotor radius, wind speed, etc...). However, there are many parameters around the morphology and biology of birds that are built into the `sCRM` package for UK seabirds, which can be found [HERE](https://github.com/dmpstats/sCRM). `sCRM` is an R Shiny application that wraps up the `stoch_crm()` and `band_crm()` functions. These biological parameters can be accessed by installing the `sCRM` package and running `sCRM::spp_dflts`, which will bring up a tibble object with all the relevant information. If performing a collision risk assessment in UK waters, default biological data for the following parameters can be obtained from the `sCRM` package: `flt_speed_pars, body_lt_pars, wing_span_pars, avoid_bsc_pars, avoid_ext_pars, noct_act_pars, flight_type, gen_fhd_boots` Other parameters around the species of interest need to be derived from site-based surveys: `prop_crh_pars, bird_dens_dt,` and `site_fhd_boots` All wind farm parameters need to be obtained by the wind farm developers: `n_blades, air_gap_pars, rtr_radius_pars, bld_width_pars, bld_pitch_pars, rtn_speed_pars, windspd_pars, trb_wind_avbl, trb_downtime_pars, wf_n_trbs, wf_width, wf_latitude, tidal_offset, season_specs, bld_chord_prf, lrg_arr_corr` The following parameters refer to the outputs: `out_format, out_sampled_pars, out_period, verbose, log_file` More information on input parameter specifics can be found in the vignettes for `stoch_crm` and `band_crm`. ## Outputs Once the collision risk model is run, the key outputs are presented as a table which contains the mean, standard deviation and median number of collisions summarised by month, season, or year. Quantiles of the bootstrapped collisions are also presented in the tables. These tables are accessed through calling from the model object. Run the [Examples] to view exemplar outputs. ``` r stochOUT <- stochLAB::stoch_crm(...) stochOUT$collisions$opt1 #For outputs from option 1 of the stochastic collision risk model stochOUT$collisions$opt2 #For outputs from option 2 of the stochastic collision risk model stochOUT$collisions$opt3 #For outputs from option 3 of the stochastic collision risk model ``` ## Examples ### Simple example This is a basic example of running the stochastic collision model for one seabird species and one turbine/wind-farm scenario, with fictional input parameter data. ``` {r} library(stochLAB) # ------------------------------------------------------ # Setting some of the required inputs upfront b_dens <- data.frame( month = month.abb, mean = runif(12, 0.8, 1.5), sd = runif(12, 0.2, 0.3)) # Generic FHD bootstraps for one species, from Johnson et al (2014) fhd_boots <- generic_fhd_bootstraps[[1]] # wind speed vs rotation speed vs pitch wind_rtn_ptch <- data.frame( wind_speed = seq_len(30), rtn_speed = 10/(30:1), bld_pitch = c(rep(90, 4), rep(0, 8), 5:22)) # wind availability windavb <- data.frame( month = month.abb, pctg = runif(12, 85, 98)) # maintenance downtime dwntm <- data.frame( month = month.abb, mean = runif(12, 6, 10), sd = rep(2, 12)) # seasons specification seas_dt <- data.frame( season_id = c("a", "b", "c"), start_month = c("Jan", "May", "Oct"), end_month = c("Apr", "Sep", "Dec")) # ---------------------------------------------------------- # Run stochastic CRM, treating rotor radius, air gap and # blade width as fixed parameters (i.e. not stochastic) stoch_crm( model_options = c(1, 2, 3), n_iter = 1000, flt_speed_pars = data.frame(mean = 7.26, sd = 1.5), body_lt_pars = data.frame(mean = 0.39, sd = 0.005), wing_span_pars = data.frame(mean = 1.08, sd = 0.04), avoid_bsc_pars = data.frame(mean = 0.99, sd = 0.001), avoid_ext_pars = data.frame(mean = 0.96, sd = 0.002), noct_act_pars = data.frame(mean = 0.033, sd = 0.005), prop_crh_pars = data.frame(mean = 0.06, sd = 0.009), bird_dens_opt = "tnorm", bird_dens_dt = b_dens, flight_type = "flapping", prop_upwind = 0.5, gen_fhd_boots = fhd_boots, n_blades = 3, rtr_radius_pars = data.frame(mean = 80, sd = 0), # sd = 0, rotor radius is fixed air_gap_pars = data.frame(mean = 36, sd = 0), # sd = 0, air gap is fixed bld_width_pars = data.frame(mean = 8, sd = 0), # sd = 0, blade width is fixed rtn_pitch_opt = "windSpeedReltn", windspd_pars = data.frame(mean = 7.74, sd = 3), rtn_pitch_windspd_dt = wind_rtn_ptch, trb_wind_avbl = windavb, trb_downtime_pars = dwntm, wf_n_trbs = 200, wf_width = 15, wf_latitude = 56.9, tidal_offset = 2.5, lrg_arr_corr = TRUE, verbose = TRUE, seed = 1234, out_format = "summaries", out_sampled_pars = TRUE, out_period = "seasons", season_specs = seas_dt, log_file = paste0(getwd(), "scrm_example.log") ) ``` ### Multiscenario example This is an example usage of `stoch_crm()` for multiple scenarios. The aim is two-fold: 1. Suggest how input parameter datasets used in the previous implementation can be reshaped to fit `stoch_crm()`'s interface. Suggested code is also relevant in the context of multiple scenarios applications, since the wide tabular structure of these datasets is likely the favoured format for users to compile input parameters under different scenarios. 2. Propose a functional programming framework to run `stoch_crm()` for multiple species and wind-farm/turbines features. Please note the example runs on fictional data. ``` {r} library(stochLAB) # --------------------------------------------------------- # # ---- Reshaping into list-column data frames ---- # --------------------------------------------------------- # # # --- bird features bird_pars <- bird_pars_wide_example %>% dplyr::relocate(Flight, .after = dplyr::last_col()) %>% tidyr::pivot_longer(AvoidanceBasic:Prop_CRH_ObsSD) %>% dplyr::mutate( par = dplyr::if_else(grepl("SD|sd|Sd", name), "sd", "mean"), feature = gsub("SD|sd|Sd","", name)) %>% dplyr::select(-name) %>% tidyr::pivot_wider(names_from = par, values_from = value) %>% tidyr::nest(pars = c(mean, sd)) %>% tidyr::pivot_wider(names_from = feature, values_from = pars) %>% tibble::add_column(prop_upwind = 0.5) # --- bird densities: provided as mean and sd Parameters for Truncated Normal lower # bounded at 0 dens_pars <- dens_tnorm_wide_example %>% tibble::add_column( dens_opt = rep("tnorm", nrow(.)), .after = 1) %>% tidyr::pivot_longer(Jan:DecSD) %>% dplyr::mutate( par = dplyr::if_else(grepl("SD|sd|Sd", name), "sd", "mean"), month = gsub("SD|sd|Sd","", name)) %>% dplyr::select(-name) %>% tidyr::pivot_wider(names_from = par, values_from = value) %>% tidyr::nest(mth_dens = c(month, mean, sd)) # --- FHD data from Johnson et al (2014) for the species under analysis gen_fhd_boots <- generic_fhd_bootstraps[bird_pars$Species] # --- seasons definitions (made up) season_dt <- list( Arctic_Tern = data.frame( season_id = c("breeding", "feeding", "migrating"), start_month = c("May", "Sep", "Jan"), end_month = c("Aug", "Dec", "Apr")), Black_headed_Gull = data.frame( season_id = c("breeding", "feeding", "migrating"), start_month = c("Jan", "May", "Oct"), end_month = c("Apr", "Sep", "Dec")), Black_legged_Kittiwake = data.frame( season_id = c("breeding", "feeding", "migrating"), start_month = c("Dec", "Mar", "Sep"), end_month = c("Feb", "Aug", "Nov"))) # --- turbine parameters ## address operation parameters first trb_opr_pars <- turb_pars_wide_example %>% dplyr::select(TurbineModel, JanOp:DecOpSD) %>% tidyr::pivot_longer(JanOp:DecOpSD) %>% dplyr::mutate( month = substr(name, 1, 3), par = dplyr::case_when( grepl("SD|sd|Sd", name) ~ "sd", grepl("Mean|MEAN|mean", name) ~ "mean", TRUE ~ "pctg" )) %>% dplyr::select(-name) %>% tidyr::pivot_wider(names_from = par, values_from = value) %>% tidyr::nest( wind_avbl = c(month, pctg), trb_dwntm = c(month, mean, sd)) ## address turbine features and subsequently merge operation parameters trb_pars <- turb_pars_wide_example %>% dplyr::select(TurbineModel:windSpeedSD ) %>% dplyr::relocate(RotorSpeedAndPitch_SimOption, .after = 1) %>% tidyr::pivot_longer(RotorRadius:windSpeedSD) %>% dplyr::mutate( par = dplyr::if_else(grepl("SD|sd|Sd", name), "sd", "mean"), feature = gsub("(SD|sd|Sd)|(Mean|MEAN|mean)","", name) ) %>% dplyr::select(-name) %>% tidyr::pivot_wider(names_from = par, values_from = value) %>% tidyr::nest(pars = c(mean, sd)) %>% tidyr::pivot_wider(names_from = feature, values_from = pars) %>% dplyr::left_join(., trb_opr_pars) # --- windspeed, rotation speed and blade pitch relationship wndspd_rtn_ptch_example # --- windfarm parameters wf_pars <- data.frame( wf_id = c("wf_1", "wf_2"), n_turbs = c(200, 400), wf_width = c(4, 10), wf_lat = c(55.8, 55.0), td_off = c(2.5, 2), large_array_corr = c(FALSE, TRUE) ) # -------------------------------------------------------------- # # ---- Run stoch_crm() for multiple scenarios ---- # -------------------------------------------------------------- # # --- Set up scenario combinations scenarios_specs <- tidyr::expand_grid( spp = bird_pars$Species, turb_id = trb_pars$TurbineModel, wf_id = wf_pars$wf_id) %>% tibble::add_column( scenario_id = paste0("scenario_", 1:nrow(.)), .before = 1) # --- Set up progress bar for the upcoming iterative mapping step pb <- progress::progress_bar$new( format = "Running Scenario: :what [:bar] :percent eta: :eta", width = 100, total = nrow(scenarios_specs)) # --- Map stoch_crm() to each scenario specification via purrr::pmap outputs <- scenarios_specs %>% purrr::pmap(function(scenario_id, spp, turb_id, wf_id, ...){ pb$tick(tokens = list(what = scenario_id)) # params for current species c_spec <- bird_pars %>% dplyr::filter(Species == {{spp}}) # density for current species c_dens <- dens_pars %>% dplyr::filter(Species == {{spp}}) # params for current turbine scenario c_turb <- trb_pars %>% dplyr::filter(TurbineModel == {{turb_id}}) # params for current windfarm scenario c_wf <- wf_pars %>% dplyr::filter(wf_id == {{wf_id}}) # inputs in list-columns need to be unlisted, either via `unlist()` or # indexing `[[1]]` # switching off `verbose`, otherwise console will be # cramped with log messages stoch_crm( model_options = c(1, 2, 3), n_iter = 1000, flt_speed_pars = c_spec$Flight_Speed[[1]], body_lt_pars = c_spec$Body_Length[[1]], wing_span_pars = c_spec$Wingspan[[1]], avoid_bsc_pars = c_spec$AvoidanceBasic[[1]], avoid_ext_pars = c_spec$AvoidanceExtended[[1]], noct_act_pars = c_spec$Nocturnal_Activity[[1]], prop_crh_pars = c_spec$Prop_CRH_Obs[[1]], bird_dens_opt = c_dens$dens_opt, bird_dens_dt = c_dens$mth_dens[[1]], flight_type = c_spec$Flight, prop_upwind = c_spec$prop_upwind, gen_fhd_boots = gen_fhd_boots[[spp]], n_blades = c_turb$Blades, rtr_radius_pars = c_turb$RotorRadius[[1]], air_gap_pars = c_turb$HubHeightAdd[[1]], bld_width_pars = c_turb$BladeWidth[[1]], rtn_pitch_opt = c_turb$RotorSpeedAndPitch_SimOption, bld_pitch_pars = c_turb$Pitch[[1]], rtn_speed_pars = c_turb$RotationSpeed[[1]], windspd_pars = c_turb$windSpeed[[1]], rtn_pitch_windspd_dt = wndspd_rtn_ptch_example, trb_wind_avbl = c_turb$wind_avbl[[1]], trb_downtime_pars = c_turb$trb_dwntm[[1]], wf_n_trbs = c_wf$n_turbs, wf_width = c_wf$wf_width, wf_latitude = c_wf$wf_lat, tidal_offset = c_wf$td_off, lrg_arr_corr = c_wf$large_array_corr, verbose = FALSE, seed = 1234, out_format = "summaries", out_sampled_pars = FALSE, out_period = "seasons", season_specs = season_dt[[spp]], log_file = NULL ) }) # --- close progress bar pb$terminate() # --- identify elements of output list names(outputs) <- scenarios_specs$scenario_id outputs ``` ### Band model example This is an example usage of `band_crm()`. This is for a single species and single set of turbine parameters. This replicates the Band (2012) worksheet. The `stoch_crm()` function wraps around this function, where `band_crm()` acts in essence as a single draw of `stoch_crm()`. Please note the example runs on fictional data. ``` {r} library(stochLAB) # ------------------------------------------------------ # Run with arbitrary parameter values, for illustration # ------------------------------------------------------ # Setting a dataframe of parameters to draw from params <- data.frame( flight_speed = 13.1, # Flight speed in m/s body_lt = 0.85, # Body length in m wing_span = 1.01, # Wing span in m flight_type = "flapping", # flapping or gliding flight avoid_rt_basic = 0.989, # avoidance rate for option 1 and 2 avoid_rt_ext = 0.981, # extended avoidance rate for option 3 and 4 noct_activity = 0.5, # proportion of day birds are inactive prop_crh_surv = 0.13, # proportion of birds at collision risk height (option 1 only) prop_upwind = 0.5, # proportion of flights that are upwind rotor_speed = 15, # rotor speed in m/s rotor_radius = 120, # radius of turbine in m blade_width = 5, # width of turbine blades at thickest point in m blade_pitch = 15, # mean radius pitch in Radians n_blades = 3, # total number of blades per turbine hub_height = 150, # height of hub in m above HAT n_turbines = 100, # number of turbines in the wind farm wf_width = 52, # width across longest section of wind farm wf_latitude = 56, # latitude of centroid of wind farm tidal_offset = 2.5, # mean tidal offset from HAT of the wind farm lrg_arr_corr = TRUE # apply a large array correction? ) # Monthly bird densities b_dens <- data.frame( month = month.abb, dens = runif(12, 0.8, 1.5) ) # flight height distribution from Johnston et al gen_fhd_dat <- Johnston_Flight_heights_SOSS %>% dplyr::filter(variable=="Gannet.est") %>% dplyr::select(height,prop) # monthly operational time of the wind farm turb_oper <- data.frame( month = month.abb, prop_oper = runif(12,0.5,0.8) ) stochLAB::band_crm( model_options = c(1,2,3), flight_speed = params$flight_speed, body_lt = params$body_lt, wing_span = params$wing_span, flight_type = params$flight_type, avoid_rt_basic = params$avoid_rt_basic, avoid_rt_ext = params$avoid_rt_ext, noct_activity = params$noct_activity, prop_crh_surv = params$prop_crh_surv, dens_month = b_dens, prop_upwind = params$prop_upwind, gen_fhd = gen_fhd_dat, site_fhd = NULL, # Option 4 only rotor_speed = params$rotor_speed, rotor_radius = params$rotor_radius, blade_width = params$blade_width, blade_pitch = params$blade_pitch, n_blades = params$n_blades, hub_height = params$hub_height, chord_prof = chord_prof_5MW, n_turbines = params$n_turbines, turb_oper_month = turb_oper, wf_width = params$wf_width, wf_latitude = params$wf_latitude, tidal_offset = params$tidal_offset, lrg_arr_corr = params$lrg_arr_corr ) ```
Owner metadata
- Name: Scottish Government Marine Directorate
- Login: MarineScotlandScience
- Email:
- Kind: organization
- Description: Repository for Marine Science and Data Projects
- Website: http://www.gov.scot/Topics/marine/science
- Location: Scotland
- Twitter:
- Company:
- Icon url: https://avatars.githubusercontent.com/u/13151918?v=4
- Repositories: 2
- Last ynced at: 2024-03-25T09:58:18.681Z
- Profile URL: https://github.com/MarineScotlandScience
GitHub Events
Total
Last Year
Committers metadata
Last synced: 3 days ago
Total Commits: 154
Total Committers: 4
Avg Commits per committer: 38.5
Development Distribution Score (DDS): 0.429
Commits in past year: 0
Committers in past year: 0
Avg Commits per committer in past year: 0.0
Development Distribution Score (DDS) in past year: 0.0
Name | Commits | |
---|---|---|
Grant_Test | g****s@h****k | 88 |
Grant | h****t@g****m | 50 |
Bruno Caneco | b****o@d****m | 12 |
Maëlle Salmon | m****n@y****e | 4 |
Committer domains:
Dependencies
- R >= 4.0 depends
- cli * imports
- data.table * imports
- dplyr * imports
- foreach * imports
- glue * imports
- logr * imports
- magrittr * imports
- msm * imports
- pracma * imports
- purrr * imports
- rlang * imports
- stats * imports
- tibble * imports
- tidyr * imports
- covr * suggests
- knitr * suggests
- rmarkdown * suggests
- spelling * suggests
- testthat >= 3.0.0 suggests
- actions/checkout v2 composite
- r-lib/actions/check-r-package v1 composite
- r-lib/actions/setup-r v2 composite
- r-lib/actions/setup-r-dependencies v2 composite
- ropensci-review-tools/pkgcheck-action main composite
- actions/checkout v2 composite
- r-lib/actions/setup-pandoc v2 composite
- r-lib/actions/setup-r v2 composite
- r-lib/actions/setup-r-dependencies v2 composite
- actions/checkout v2 composite
- r-lib/actions/setup-r v2 composite
- r-lib/actions/setup-r-dependencies v2 composite
Score: 4.382026634673881