Skip to content

Commit f8d204b

Browse files
authored
Merge pull request #79 from iiasa/dev
Merging 0.1 dev branch to main
2 parents 068ad37 + a4bbbcc commit f8d204b

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

46 files changed

+1522
-391
lines changed

CITATION.cff

+1-1
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ message: 'To cite package "ibis.iSDM" in publications use:'
88
type: software
99
license: CC-BY-4.0
1010
title: 'ibis.iSDM: Modelling framework for integrated biodiversity distribution scenarios'
11-
version: 0.0.9
11+
version: 0.1.0
1212
abstract: Integrated framework of modelling the distribution of species and ecosystems
1313
in a suitability framing. This package allows the estimation of integrated species
1414
distribution models (iSDM) based on several sources of evidence and provided presence-only

DESCRIPTION

+3-1
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
Package: ibis.iSDM
22
Type: Package
33
Title: Modelling framework for integrated biodiversity distribution scenarios
4-
Version: 0.0.9
4+
Version: 0.1.0
55
Authors@R:
66
c(person(given = "Martin",
77
family = "Jung",
@@ -99,6 +99,7 @@ Collate:
9999
'bdproto-predictors.R'
100100
'add_predictors.R'
101101
'add_predictors_globiom.R'
102+
'add_predictors_model.R'
102103
'identifier.R'
103104
'bdproto-distributionmodel.R'
104105
'bdproto-priorlist.R'
@@ -141,6 +142,7 @@ Collate:
141142
'pseudoabsence.R'
142143
'scenario.R'
143144
'similarity.R'
145+
'simulate_population_steps.R'
144146
'summary.R'
145147
'threshold.R'
146148
'train.R'

NAMESPACE

+4
Original file line numberDiff line numberDiff line change
@@ -83,6 +83,7 @@ export(add_predictor_elevationpref)
8383
export(add_predictor_range)
8484
export(add_predictors)
8585
export(add_predictors_globiom)
86+
export(add_predictors_model)
8687
export(add_priors)
8788
export(add_pseudoabsence)
8889
export(alignRasters)
@@ -138,6 +139,7 @@ export(sanitize_names)
138139
export(scenario)
139140
export(sel_predictors)
140141
export(similarity)
142+
export(simulate_population_steps)
141143
export(spartial)
142144
export(thin_observations)
143145
export(threshold)
@@ -182,6 +184,7 @@ exportMethods(add_predictor_elevationpref)
182184
exportMethods(add_predictor_range)
183185
exportMethods(add_predictors)
184186
exportMethods(add_predictors_globiom)
187+
exportMethods(add_predictors_model)
185188
exportMethods(add_priors)
186189
exportMethods(check)
187190
exportMethods(distribution)
@@ -201,6 +204,7 @@ exportMethods(rm_priors)
201204
exportMethods(scenario)
202205
exportMethods(sel_predictors)
203206
exportMethods(similarity)
207+
exportMethods(simulate_population_steps)
204208
exportMethods(threshold)
205209
exportMethods(train)
206210
exportMethods(validate)

NEWS.md

+25-1
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,26 @@
1-
# ibis.iSDM 0.0.9 (current dev branch)
1+
# ibis.iSDM 0.1.0 (current dev branch)
2+
3+
#### New features
4+
* Added a small convenience wrapper to add model outputs to another model `add_predictors_model()`
5+
* Started adding mechanistic SDM vignette #67
6+
* Wrapper for *steps* implemented via `simulate_population_steps()` #68
7+
8+
#### Minor improvements and bug fixes
9+
* Added R-universe installation option as alternative to github #38
10+
* Minor bug fixes in `scenario()` object, and MigClim and Kissmig wrappers.
11+
* Bug fix related to CRS classes of sp and sf
12+
* Bug fix related to blas.num.threads
13+
* Bug fix that crashed `write_summary()` outputs when no prediction was made.
14+
* Bug fix related to CRS in `engine_inla()`
15+
* Bug fix in `engine_stan()` related to background layer
16+
* Class of biodiversity data is identical for PO and PA
17+
* Bug fix in `built_formula_glmnet()` and response
18+
* Bug fix in `built_formula_gdb()` and response
19+
* Each model$biodiversity stores only predictors of current ID
20+
* Bug fix in `built_formula_inla()` for INLABRU
21+
22+
# ibis.iSDM 0.0.9
23+
224
#### New features
325
* Added new vignette on available functions for data preparation #67
426
* Addition of small `mask()` function that emulates the for `terra`.
@@ -13,6 +35,7 @@
1335
* Improved error messages and handling of formula's.
1436

1537
# ibis.iSDM 0.0.8
38+
1639
#### New features
1740
* Implemented min size constraint (`add_constraint_minsize()`) #56
1841
* Added a function for estimating partial effects of ensembles `ensemble_spartial()`.
@@ -26,6 +49,7 @@
2649
* Allow to specify location of biodiversity point records in `threshold()`.
2750

2851
# ibis.iSDM 0.0.7
52+
2953
#### New features
3054
* Added method proximity to `add_control_bias()` to place lower weights on points closer to another.
3155
* Added helper functions `get_data()` and the option to apply `threshold()` directly on BiodiversityScenarios.

R/add_constraint.R

+16-6
Original file line numberDiff line numberDiff line change
@@ -61,12 +61,16 @@ NULL
6161
#' can be particular useful to limit the influence of increasing marginal
6262
#' responses and avoid biologically unrealistic projections.
6363
#'
64-
#' **Boundary**:
64+
#' **Boundary and size**:
6565
#' * \code{boundary} - Applies a hard boundary constraint on the projection, thus disallowing an expansion of a range outside
6666
#' the provide layer. Similar as specifying projection limits (see
6767
#' [`distribution`]), but can be used to specifically constrain a projection
6868
#' within a certain area (e.g. a species range or an island).
6969
#'
70+
#' * \code{minsize} - Allows to specify a certain size that must be satisfied
71+
#' in order for a thresholded patch to be occupied. Can be thought of as a minimum
72+
#' size requirement. See `add_constraint_minsize()` for the required parameters.
73+
#'
7074
#' @returns Adds constraints data to a [`BiodiversityScenario`] object.
7175
#' @references
7276
#' * Bateman, B. L., Murphy, H. T., Reside, A. E., Mokany, K., & VanDerWal, J. (2013). Appropriateness of full‐, partial‐and no‐dispersal scenarios in climate change impact modelling. Diversity and Distributions, 19(10), 1224-1234.
@@ -106,7 +110,8 @@ methods::setMethod(
106110
# Match method
107111
method <- match.arg(arg = method,
108112
choices = c("sdd_fixed", "sdd_nexpkernel", "kissmig", "migclim",
109-
"hardbarrier","resistance", "boundary",
113+
"hardbarrier","resistance",
114+
"boundary", "minsize",
110115
"nichelimit"), several.ok = FALSE)
111116

112117
# Now call the respective functions individually
@@ -126,8 +131,10 @@ methods::setMethod(
126131
# --- #
127132
"nichelimit" = add_constraint_adaptability(mod, method = "nichelimit", ...),
128133
# --- #
129-
"boundary" = add_constraint_boundary(mod, ...)
130-
)
134+
"boundary" = add_constraint_boundary(mod, ...),
135+
# --- #
136+
"minsize" = add_constraint_minsize(mod, ...)
137+
)
131138
return(o)
132139
}
133140
)
@@ -352,7 +359,7 @@ methods::setMethod(
352359
is.vector(params) || is.list(params),
353360
is.null(resistance) || is.logical(resistance) || is.Raster(resistance),
354361
# Check that baseline threshold raster is binomial
355-
length(unique(baseline_threshold))==2
362+
length(unique(baseline_threshold)[,1])==2
356363
)
357364

358365
check_package('kissmig')
@@ -366,12 +373,15 @@ methods::setMethod(
366373
# Simulate kissmig for a given threshold and suitability raster
367374
km <- kissmig::kissmig(O = terra_to_raster( baseline_threshold ),
368375
# Rescale newsuit to 0-1
369-
S = predictor_transform(new_suit, 'norm'),
376+
S = predictor_transform(new_suit, 'norm') |>
377+
terra_to_raster(),
370378
it = as.numeric( params['iteration'] ),
371379
type = params['type'],
372380
pext = as.numeric(params['pext']),
373381
pcor = as.numeric(params['pcor'])
374382
)
383+
# Convert to terra again
384+
km <- terra::rast(km)
375385
if(is.factor(km)) km <- terra::as.int(km)
376386

377387
# Now multiply the net suitability projection with this mask Thus removing any

R/add_constraint_MigClim.R

+1-1
Original file line numberDiff line numberDiff line change
@@ -63,7 +63,7 @@ NULL
6363
#'
6464
#' @name add_constraint_MigClim
6565
#' @aliases add_constraint_MigClim
66-
#' @family constrain
66+
#' @family constraint
6767
#' @keywords scenario
6868
#' @exportMethod add_constraint_MigClim
6969
#' @export

R/add_predictors.R

+2
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,8 @@ NULL
99
#' the [distribution] object. This function furthermore allows to transform or
1010
#' create derivates of provided predictors.
1111
#'
12+
#' @details
13+
#'
1214
#' A transformation takes the provided rasters and for instance rescales them or
1315
#' transforms them through a principal component analysis ([prcomp]). In
1416
#' contrast, derivates leave the original provided predictors alone, but instead

R/add_predictors_model.R

+172
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,172 @@
1+
#' @include utils.R bdproto.R bdproto-biodiversitydistribution.R bdproto-predictors.R
2+
NULL
3+
4+
#' Add predictors from a fitted model to a Biodiversity distribution object
5+
#'
6+
#' @description This function is a convenience wrapper to add the output from a
7+
#' previous fitted [`DistributionModel`] to another [`BiodiversityDistribution-class`]
8+
#' object. Obviously only works if a prediction was fitted in the model. Options
9+
#' to instead add thresholds, or to transform / derivate the model outputs are
10+
#' also supported.
11+
#'
12+
#' @details
13+
#'
14+
#' A transformation takes the provided rasters and for instance rescales them or
15+
#' transforms them through a principal component analysis ([prcomp]). In
16+
#' contrast, derivates leave the original provided predictors alone, but instead
17+
#' create new ones, for instance by transforming their values through a
18+
#' quadratic or hinge transformation. Note that this effectively increases the
19+
#' number of predictors in the object, generally requiring stronger
20+
#' regularization by the used [`Engine`]. Both transformations and derivates can
21+
#' also be combined. Available options for transformation are:
22+
#' * \code{'none'} - Leaves the provided predictors in the original scale.
23+
#' * \code{'pca'} - Converts the predictors to principal components. Note that this
24+
#' results in a renaming of the variables to principal component axes!
25+
#' * \code{'scale'} - Transforms all predictors by applying [scale] on them.
26+
#' * \code{'norm'} - Normalizes all predictors by transforming them to a scale from 0 to 1.
27+
#' * \code{'windsor'} - Applies a windsorization to the target predictors. By default
28+
#' this effectively cuts the predictors to the 0.05 and 0.95, thus helping to
29+
#' remove extreme outliers.
30+
#'
31+
#' Available options for creating derivates are:
32+
#' * \code{'none'} - No additional predictor derivates are created.
33+
#' * \code{'quad'} - Adds quadratic transformed predictors.
34+
#' * \code{'interaction'} - Add interacting predictors. Interactions need to be specified (\code{"int_variables"})!
35+
#' * \code{'thresh'} - Add threshold transformed predictors.
36+
#' * \code{'hinge'} - Add hinge transformed predictors.
37+
#' * \code{'bin'} - Add predictors binned by their percentiles.
38+
#'
39+
#' @param x [distribution()] (i.e. [`BiodiversityDistribution-class`]) object.
40+
#' @param model A [`DistributionModel`] object.
41+
#' @param transform A [`vector`] stating whether predictors should be
42+
#' preprocessed in any way (Options: \code{'none'},\code{'pca'},
43+
#' \code{'scale'}, \code{'norm'})
44+
#' @param derivates A Boolean check whether derivate features should be
45+
#' considered (Options: \code{'none'}, \code{'thresh'}, \code{'hinge'},
46+
#' \code{'quad'}) )
47+
#' @param threshold_only A [`logical`] flag indicating whether to add thresholded
48+
#' layers from the fitted model (if existing) instead (Default: \code{FALSE}).
49+
#' @param priors A [`PriorList-class`] object. Default is set to \code{NULL}
50+
#' which uses default prior assumptions.
51+
#' @param ... Other parameters passed down
52+
#' @aliases add_predictors_model
53+
#' @examples
54+
#' \dontrun{
55+
#' # Fit first model
56+
#' fit <- distribution(background) |>
57+
#' add_predictors(covariates) |>
58+
#' add_biodiversity_poipa(species) |>
59+
#' engine_glmnet() |>
60+
#' train()
61+
#'
62+
#' # New model object
63+
#' obj <- distribution(background) |>
64+
#' add_predictors_model(fit)
65+
#' obj
66+
#' }
67+
#' @name add_predictors_model
68+
NULL
69+
70+
#' @name add_predictors_model
71+
#' @rdname add_predictors_model
72+
#' @exportMethod add_predictors_model
73+
#' @export
74+
methods::setGeneric(
75+
"add_predictors_model",
76+
signature = methods::signature("x", "model"),
77+
function(x, model, transform = 'scale', derivates = 'none',
78+
threshold_only = FALSE, priors = NULL, ...) standardGeneric("add_predictors_model"))
79+
80+
#' @name add_predictors_model
81+
#' @rdname add_predictors_model
82+
#' @usage
83+
#' \S4method{add_predictors_model}{BiodiversityDistribution,ANY,character,character,logical,ANY}(x,model,transform,derivates,threshold_only,priors,...)
84+
methods::setMethod(
85+
"add_predictors_model",
86+
methods::signature(x = "BiodiversityDistribution", model = "ANY"),
87+
function(x, model, transform = 'scale', derivates = 'none',
88+
threshold_only = FALSE, priors = NULL, ...) {
89+
# Try and match transform and derivatives arguments
90+
transform <- match.arg(transform, c('none','pca', 'scale', 'norm', 'windsor') , several.ok = TRUE)
91+
derivates <- match.arg(derivates, c('none','thresh', 'hinge', 'quadratic', 'bin', 'interaction') , several.ok = TRUE)
92+
93+
assertthat::assert_that(inherits(x, "BiodiversityDistribution"),
94+
inherits(model, "DistributionModel"),
95+
is.logical(threshold_only),
96+
all(transform == 'none') || all( transform %in% c('pca', 'scale', 'norm', 'windsor') ),
97+
all(derivates == 'none') || all( derivates %in% c('thresh', 'hinge', 'quadratic', 'bin', 'interaction') ),
98+
is.null(priors) || inherits(priors,'PriorList')
99+
)
100+
# Messenger
101+
if(getOption('ibis.setupmessages')) myLog('[Setup]','green','Adding predictors from fitted model...')
102+
103+
# If priors have been set, save them in the distribution object
104+
if(!is.null(priors)) {
105+
x <- x$set_priors(priors)
106+
}
107+
108+
# Get prediction from model object
109+
assertthat::assert_that(
110+
"prediction" %in% model$show_rasters(),
111+
msg = "No prediction found in model object!"
112+
)
113+
if(threshold_only){
114+
tr <- grep('threshold', model$show_rasters(),ignore.case = TRUE,value = TRUE)
115+
if(length(tr)==1){
116+
prediction <- model$get_data(tr)
117+
} else {
118+
if(getOption('ibis.setupmessages')) myLog('[Setup]','yellow','No threshold found in fitted model. Using prediction...')
119+
prediction <- model$get_data()
120+
}
121+
} else {
122+
prediction <- model$get_data()
123+
}
124+
assertthat::assert_that(is.Raster(prediction))
125+
# Set names
126+
names(prediction) <- paste0(make.names(model$model$runname),"__",names(prediction))
127+
128+
# Standardization and scaling
129+
if('none' %notin% transform){
130+
if(getOption('ibis.setupmessages')) myLog('[Setup]','green','Transforming prediction...')
131+
for(tt in transform) prediction <- predictor_transform(prediction, option = tt)
132+
}
133+
assertthat::assert_that(is.Raster(prediction))
134+
135+
# Calculate derivates if set
136+
if('none' %notin% derivates){
137+
if(getOption('ibis.setupmessages')) myLog('[Setup]','green','Creating prediction derivates...')
138+
# Specific condition for interaction
139+
new_prediction <- terra::rast()
140+
for(dd in derivates){
141+
suppressWarnings(
142+
new_prediction <- c(new_prediction, predictor_derivate(prediction,
143+
option = dd) )
144+
)
145+
}
146+
# Add
147+
prediction <- c(prediction, new_prediction)
148+
rm(new_prediction)
149+
}
150+
151+
# Assign an attribute to this object to keep track of it
152+
attr(prediction,'transform') <- transform
153+
154+
# Sanitize names if specified
155+
if(getOption('ibis.cleannames')) names(prediction) <- sanitize_names(names(prediction))
156+
157+
# Get existing predictors
158+
if(!is.Waiver(x$predictors)){
159+
env <- x$predictors$get_data()
160+
env <- c(env, prediction)
161+
}
162+
163+
# Finally set the data to the BiodiversityDistribution object
164+
x$set_predictors(
165+
bdproto(NULL, PredictorDataset,
166+
id = new_id(),
167+
data = env,
168+
...
169+
)
170+
)
171+
}
172+
)

0 commit comments

Comments
 (0)