Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Dev #19

Merged
merged 24 commits into from
Sep 27, 2024
Merged

Dev #19

Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
24 commits
Select commit Hold shift + click to select a range
85f41fb
Merge branch 'main' into dev
NiklasHohmann Sep 13, 2024
1065cd7
Merge remote-tracking branch 'origin/main' into dev
NiklasHohmann Sep 13, 2024
3788b53
sort index alphabetically
NiklasHohmann Sep 13, 2024
839e130
add available distances from shore to docs
NiklasHohmann Sep 13, 2024
058377a
expand documentation
NiklasHohmann Sep 26, 2024
65a094d
add stasis simulation for pre-paleoTS format
NiklasHohmann Sep 26, 2024
24673f7
stasis simulation for pre-palepTS format"
NiklasHohmann Sep 26, 2024
69f9a01
remove test bc of wrong naming
NiklasHohmann Sep 26, 2024
34bcc24
add reduction of pre-paleoTS to paleoTS
NiklasHohmann Sep 26, 2024
a4835e9
add paleoTS dependency
NiklasHohmann Sep 26, 2024
a85e3a0
expand docs
NiklasHohmann Sep 26, 2024
c0c86e1
add new functions to index
NiklasHohmann Sep 26, 2024
be239e3
introduce dispatch
NiklasHohmann Sep 26, 2024
239b1bd
start implmentation of niche modeling for pre-paleoTS
NiklasHohmann Sep 26, 2024
d37aa97
expand documentation
NiklasHohmann Sep 27, 2024
0730611
add docs
NiklasHohmann Sep 27, 2024
5fbf3b3
add tests
NiklasHohmann Sep 27, 2024
2587df3
add helper function for probabilistic removal of elements
NiklasHohmann Sep 27, 2024
a64bde0
niche modeling for pre_paleoTS objects
NiklasHohmann Sep 27, 2024
83e1882
add spellchecker
NiklasHohmann Sep 27, 2024
37f421d
more robust implementation
NiklasHohmann Sep 27, 2024
09c4dce
add taphonomy for S3 class pre_paleoTS
NiklasHohmann Sep 27, 2024
a915c8f
Increment version number to 0.1.1.9001
NiklasHohmann Sep 27, 2024
e371709
update news
NiklasHohmann Sep 27, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 5 additions & 2 deletions DESCRIPTION
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
Package: StratPal
Title: Stratigraphic Paleobiology Modeling Pipelines
Version: 0.1.1.9000
Version: 0.1.1.9001
Authors@R:
person("Niklas", "Hohmann", , "[email protected]", role = c("aut", "cre"),
comment = c(ORCID = "0000-0003-1559-1838"))
Expand All @@ -20,10 +20,12 @@ Encoding: UTF-8
Roxygen: list(markdown = TRUE)
RoxygenNote: 7.3.2
Imports:
admtools (>= 0.3.0)
admtools (>= 0.3.0),
paleoTS
Suggests:
knitr,
rmarkdown,
spelling,
testthat (>= 3.0.0)
VignetteBuilder: knitr
Depends:
Expand All @@ -32,3 +34,4 @@ LazyData: true
URL: https://mindthegap-erc.github.io/StratPal/ , https://github.com/MindTheGap-ERC/StratPal
BugReports: https://github.com/MindTheGap-ERC/StratPal/issues
Config/testthat/edition: 3
Language: en-US
8 changes: 8 additions & 0 deletions NAMESPACE
Original file line number Diff line number Diff line change
@@ -1,13 +1,21 @@
# Generated by roxygen2: do not edit by hand

S3method(apply_niche,numeric)
S3method(apply_niche,pre_paleoTS)
S3method(apply_taphonomy,numeric)
S3method(apply_taphonomy,pre_paleoTS)
S3method(reduce_to_paleoTS,pre_paleoTS)
export(apply_niche)
export(apply_taphonomy)
export(bounded_niche)
export(ornstein_uhlenbeck)
export(p3)
export(p3_var_rate)
export(prob_remove)
export(random_walk)
export(reduce_to_paleoTS)
export(rej_samp)
export(snd_niche)
export(stasis)
export(stasis_sl)
export(thin)
2 changes: 2 additions & 0 deletions NEWS.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
# StratPal (development version)

* introduce S3 class `pre_paleoTS` with simulation procedures, functions to reduce to `paleoTS` via `reduce_to_paleoTS`, and implementaions of niche models and taphonomy via `apply_niche` and `apply_taphonomy`

* add more tests

* add input checks
Expand Down
38 changes: 28 additions & 10 deletions R/apply_niche.R
Original file line number Diff line number Diff line change
@@ -1,20 +1,20 @@
apply_niche = function(x, niche_def, gc){
#' @export
#'
#' @title apply niche model to events
#' @title apply niche model
#'
#' @param x events, e.g. times/ages of fossil occurrences or their stratigraphic position.
#' @param niche_def function, specifying the niche along a gradient. Should return 0 when taxon is outside of niche, and 1 when inside niche. Values between 0 and 1 are interpreted as collection probabilities.
#' @param gc function, stands for "gradient change". Specifies how the gradient changes, e.g. with time
#' @param x events, e.g. times/ages of fossil occurrences or their stratigraphic position, or a `pre_paleoTS` object (e.g. produced by `stasis_sl`).
#' @param niche_def function, specifying the niche along a gradient. Should return 0 when taxon is outside of niche, and 1 when inside niche. Values between 0 and 1 are interpreted as collection probabilities. Must be vectorized, meaning if given a vector, it must return a vector of equal length.
#' @param gc function, stands for "gradient change". Specifies how the gradient changes, e.g. with time. Must be vectorized, meaning if given a vector, it must return a vector of equal length.
#'
#' @description
#' Models niches by removing events (fossil occurrences) when they are outside of their niche using the function `thin`.
#' Combines the functions `niche_def` and `gc` ("gradient change") to determine how the taxons' collection probability changes with time/position. This is done by composing `niche_def` and `gc`. The result is then used as a thinning on the events `x`.
#' Models niches by removing events (fossil occurrences) or specimens when they are outside of their niche. For event type data, this is done using the function `thin`, for `pre_paleoTS` this is done by applying the function `prob_remove` on the specimens.
#' Combines the functions `niche_def` and `gc` ("gradient change") to determine how the taxons' collection probability changes with time/position. This is done by composing `niche_def` and `gc`. The result is then used to remove events/specimens in `x`.
#'
#' @returns numeric vector, timing/location of events (e.g. fossil ages/locations) preserved after the niche model is applied
#' @returns for a numeric vector input, returns a numeric vector, timing/location of events (e.g. fossil ages/locations) preserved after the niche model is applied. For a `pre_paleoTS` object as input, returns a `pre_paleoTS` object with specimens removed according to the niche model.
#'
#' @examples
#'
#' ### example for event type data
#' ## setup
#' # using water depth as gradient
#' t = scenarioA$t_myr
Expand All @@ -41,15 +41,33 @@ apply_niche = function(x, niche_def, gc){
#'
#' # see also
#' #vignette("event_data")
#' # for a detailed example on niche modeling
#' # for a detailed example on niche modeling for event type data
#'
#'
#'
#' @seealso [apply_taphonomy()] to model taphonomic effects based on the same principle, [thin()] for the underlying mathematical procedure. Basic niche models available are [bounded_niche()] and [snd_niche()]
#' @seealso [apply_taphonomy()] to model taphonomic effects based on the same principle, [thin()] and [prob_remove()] for the underlying mathematical procedure. Basic niche models available are [bounded_niche()] and [snd_niche()]
UseMethod("apply_niche")

}

apply_niche.numeric = function(x, niche_def, gc){

#' @export
# function that returns collection probability as a function of y (typically time)
change_in_niche = function(y) niche_def(gc(y))
# thin events based on collection probability
r = thin(x, change_in_niche)
return(r)
}

apply_niche.pre_paleoTS = function(x, niche_def, gc){
#' @export
#'
change_in_niche = function(y) niche_def(gc(y))
thin_vals = change_in_niche(x$t)
for (i in seq_along(thin_vals)){
r = prob_remove(x$vals[[i]], prob = thin_vals[i])
x$vals[[i]] = x$vals[[i]][as.logical(r)]
}
return(x)
}
35 changes: 29 additions & 6 deletions R/apply_taphonomy.R
Original file line number Diff line number Diff line change
Expand Up @@ -3,17 +3,17 @@ apply_taphonomy = function(x, pres_potential, ctc){
#'
#' @title model taphonomic effects
#'
#' @param x events, e.g. times/ages of fossil occurrences or their stratigraphic position.
#' @param pres_potential function. Takes taphonomic conditions as input and returns the preservation potential (a number between 0 and 1)
#' @param ctc function, change in taphonomic conditions (ctc) with time or stratigraphic position.
#' @param x event type data, e.g. times/ages of fossil occurrences or their stratigraphic position, or a `pre_paleoTS` object.
#' @param pres_potential function. Takes taphonomic conditions as input and returns the preservation potential (a number between 0 and 1). Must be vectorized, meaning if given a vector, it must return a vector of equal length.
#' @param ctc function, change in taphonomic conditions (ctc) with time or stratigraphic position. . Must be vectorized, meaning if given a vector, it must return a vector of equal length.
#'
#' @description
#' Models taphonomy by combining the change in taphonomic conditions with the preservation potential as a function of taphonomic conditions to determine how preservation potential changes. This is then used to systematically remove (thin) the event data using `thin`.
#' Models taphonomy by combining the change in taphonomic conditions with the preservation potential as a function of taphonomic conditions to determine how preservation potential changes. This is then used to systematically remove (thin) the event data using `thin`/ remove specimens from the `pre_paleoTS` object using `prob_remove`.
#'
#'
#' @seealso [apply_niche()] for modeling niche preferences based on the same principle, [thin()] for the underlying mathematical procedure.
#' @seealso [apply_niche()] for modeling niche preferences based on the same principle, [thin()] and [prob_remove()] for the underlying mathematical procedure.
#'
#' @returns numeric vector, location/timing of events (e.g. fossil occurrences) after the taphonomic filter is applied
#' @returns if given event type data, a numeric vector, location/timing of events (e.g. fossil occurrences) after the taphonomic filter is applied. If given a `pre_paleoTS` object, returns another `pre_paleoTS` object with reduced number of specimens.
#'
#' @examples
#'
Expand All @@ -22,10 +22,33 @@ apply_taphonomy = function(x, pres_potential, ctc){
#' # for details on usage
#'
#'
UseMethod("apply_taphonomy")

}

apply_taphonomy.numeric = function(x, pres_potential, ctc){
#' @export
# function that returns preservation potential as a function of input (e.g. time or position)
change_pres_pot = function(y) pres_potential(ctc(y))
# thin events
r = thin(x, change_pres_pot)
return(r)
}

apply_taphonomy.pre_paleoTS = function(x, pres_potential, ctc){
#' @export
#'
# function that returns preservation potential as a function of input (e.g. time or position)
change_pres_pot = function(y) pres_potential(ctc(y))
if (inherits(x, "timelist")){
thin_vals = change_pres_pot(x$t)
}
if (inherits(x, "stratlist")){
thin_vals = change_pres_pot(x$h)
}
for (i in seq_along(thin_vals)){
r = prob_remove(x$vals[[i]], prob = thin_vals[i])
x$vals[[i]] = x$vals[[i]][as.logical(r)]
}
return(x)
}
2 changes: 1 addition & 1 deletion R/bounded_niche.R
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ bounded_niche = function(g_min, g_max){
#' @returns a function describing the niche for usage with `apply_niche`. The function returns 1 if the taxon is within its niche (the gradient is between `g_min` and `g_max`), and 0 otherwise
#'
#' @description
#' Defines a simple niche model where the niche defined is given by a lower limit (`g_min`) and an upper limie (`g_max`) of a gradient the taxon can tolerate
#' Defines a simple niche model where the niche defined is given by a lower limit (`g_min`) and an upper limit (`g_max`) of a gradient the taxon can tolerate
#'
#' @examples
#'
Expand Down
2 changes: 1 addition & 1 deletion R/p3_var_rate.R
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@ p3_var_rate = function(x, y = NULL, from = 0, to = 1, f_max = 1, n = NULL){
#'
#' @seealso [p3()] for the constant rate implementation, [rej_samp()] for the underlying random number generation.
#'
#' @returns numeric vector, timing/location of events. Depending on the modeling framework, tyese events can represent location/age of fossils, or first/last occurrences of a group of taxa.
#' @returns numeric vector, timing/location of events. Depending on the modeling framework, these events can represent location/age of fossils, or first/last occurrences of a group of taxa.

if (from >= to){
stop("\"from\" must be smaller than \"to\".")
Expand Down
22 changes: 22 additions & 0 deletions R/prob_remove.R
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
prob_remove = function(x, prob){
#' @export
#'
#' @title probabilistic removal of elements
#'
#' @param x vector
#' @param prob number between 0 and 1, probability to preserve elements
#'
#' @description
#' probabilistic removal of elements from x. For each element, the probability to be preserved is independent and specified by prob
#'
#' @returns a vector of the same type as x
#'
#' @examples
#' x = prob_remove(1:10, 0.5)
#' x
#' @seealso [apply_niche()] and [apply_taphonomy()] use this function for transformation of `pre_paleoTS` objects

r = stats::rbinom(length(x), size = 1, prob = prob)
x = x[as.logical(r)]
return(x)
}
46 changes: 46 additions & 0 deletions R/reduce_to_paleoTS.R
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
reduce_to_paleoTS = function(x, ...){
#' @export
#'
#' @title reduce pre-paleoTS format to paleoTS
#'
#' @description
#' paleoTS is a format for paleontological time series. It is a summary format where interpopulation variance is provided as a parameter. As a result, taphonomic and ecological effects that act on individual specimens can not be modeled for paleoTS objects. To resolve this, the pre_paleoTS format tracks each specimen individually. This function reduces the pre-paleoTS format into standard paleoTS object, which can be used by the paleoTS package.
#'
#' @param x a `pre_paleoTS` object
#' @param ... other options. currently unused
#'
#' @seealso [stasis_sl()] to simulate stasis on specimen level (sl), returning an object of call `pre_paleoTS`
#'
#' @returns a `paleoTS` object
#'
#' @examples
#' x = stasis_sl(t = 0:5) # create pre_paleoTS object representing stasis on specimen level
#' y = reduce_to_paleoTS(x) # reduce to standard paleoTS format
#' # now analyses using the paleoTS package can be applied to y
#'

UseMethod("reduce_to_paleoTS")
}

reduce_to_paleoTS.pre_paleoTS = function(x, ...){

#' @export
#'
if (inherits(x, "timelist")){
tt = x$t
}
if (inherits(x, "stratlist")){
tt = x$h
}
l = length(x$t)
mm = rep(NA, l)
vv = rep(NA, l)
nn = rep(NA, l)
for (i in seq_along(x$t)){
mm[i] = mean(x$vals[[i]])
vv[i] = stats::var(x$vals[[i]])
nn[i] = length(x$vals[[i]])
}
x = paleoTS::as.paleoTS(mm, vv, nn, tt)
return(x)
}
2 changes: 1 addition & 1 deletion R/scenarioA.R
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@
#'
#' * `t_myr` : numeric vector. timesteps of the simulation in Myr
#' * `sl_m` : numeric vector. eustatic sea level in m
#' * `dist_from_shore` : character vector. Distance from shore in km of locations at which the observations were made
#' * `dist_from_shore` : character vector. Distance from shore in km of locations at which the observations were made. Available distances are "2km", "4km", "6km", "8km", "10km", "12km".
#' * `h_m` : matrix of size length(t_myr) x length(dist_from_shore). Accumulated sediment height in m at examined locations
#' * `wd_m`: matrix of size length(t_myr) x length(dist_from_shore). Water depth in m at examined locations
#' * `strat_col`: list with length(dist_from shore) elements. Represents a stratigraphic column. Each element is a list with two elements:
Expand Down
8 changes: 5 additions & 3 deletions R/stasis.R
Original file line number Diff line number Diff line change
Expand Up @@ -4,11 +4,13 @@ stasis = function(t, mean = 0, sd = 1){
#' @title simulate phenotypic stasis
#'
#' @param t times at which the traits are determined
#' @param mean scalar, mean trait value
#' @param sd strictly positive scalar, standard deviation of traits
#' @param mean number, mean trait value
#' @param sd strictly positive number, standard deviation of traits
#'
#' @seealso [random_walk()] and [ornstein_uhlenbeck()] to simulate other modes of evolution, [stasis_sl()] to simulate stasis on specimen level
#'
#' @description
#' Simulates stasis as independent, normally distributed random variables with mean `mean` and standard deviation `sd`
#' Simulates stasis of mean trait values as independent, normally distributed random variables with mean `mean` and standard deviation `sd`
#'
#' @returns A list with two elements: `t` and `y`. `t` is a duplicate of the input `t`, `y` are the corresponding trait values. Output list is of S3 class `timelist` (inherits from `list`) and can thus be plotted directly using `plot`, see `?admtools::plot.timelist`
#' @examples
Expand Down
38 changes: 38 additions & 0 deletions R/stasis_sl.R
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
stasis_sl = function(t, mean = 0, sd = 1, interpop_var = 1, n_per_sample = 10){
#' @export
#'
#' @title simulate phenotypic stasis (pre-paleoTS format)
#'
#' @param t times at which the traits are determined
#' @param mean mean trait value
#' @param sd strictly positive number, standard deviation of traits around the mean
#' @param interpop_var interpopulation variance, determines how much specimens from the same population vary
#' @param n_per_sample integer, number of specimens sampled per population/sampling locality
#'
#' @description
#' simulated stasis as independent, normally distributed random variables with mean `mean` and standard deviation `sd`, draws `n_per_sample` samples from each sampling location (population) that have specified variance `interpop_var`
#'
#' @seealso [stasis()] for the version that simulates stasis of mean trait values.
#'
#' @returns an object of S3 class `pre_paleoTS`, inherits from `timelist` and `list`. The list has two elements: `t`, containing a vector of times of sampling, and `vals`, a list of trait values of the same length as `t`, with element containing trait values of individual specimens. This object can be transformed using `apply_taphonomy`, `apply_niche` or `time_to_strat`, and then reduced to a `paleoTS` object using `reduce_to_paleoTS`. This can then be used to test for different modes of evolution.
#'
#' @examples
#' x = stasis_sl(1:5, mean = 2, sd = 2)
#'

if (interpop_var <= 0){
stop("parameter \'interpop_var\' must me >0 ")
}
if (n_per_sample <1){
stop("parameter \'n_per_sample\' must be >=1")
}
x = stasis(t, mean, sd)
r = list(t = x$t)
vals = list()
for (i in seq_along(x$t)){
vals[[i]] = stats::rnorm(n = n_per_sample, mean = x$y[i], sd = sqrt(interpop_var))
}
r[["vals"]] = vals
class(r) = c("pre_paleoTS","timelist", "list")
return(r)
}
15 changes: 11 additions & 4 deletions _pkgdown.yml
Original file line number Diff line number Diff line change
Expand Up @@ -8,9 +8,10 @@ reference:
- subtitle: Trait evolution
desc: Simulate trait evolution
contents:
- stasis
- random_walk
- ornstein_uhlenbeck
- random_walk
- stasis
- stasis_sl

- subtitle: Event type data
desc: Simulate event type data (e.g., fossil location/ages, first/last occurrences)
Expand All @@ -22,13 +23,19 @@ reference:
- subtitle: Ecology and taphonomy
desc: Ecological niche models and taphonomic effects
contents:
- apply_niche
- snd_niche
- bounded_niche
- apply_niche
- apply_taphonomy
- snd_niche
- thin
- prob_remove

- subtitle: Example data
desc: Example data from stratigraphic forward models
contents:
- scenarioA

- subtitle: paleoTS functionality
desc: Tools for linkage with the paleoTS package
contents:
- reduce_to_paleoTS
Loading