Title: | Computation and Visualization of Adaptive Landscapes |
---|---|
Description: | Implements adaptive landscape methods first described by Polly et al. (2016) <doi:10.1080/02724634.2016.1111225> for the integration, analysis and visualization of biological trait data on a phenotypic morphospace - typically defined by shape metrics. |
Authors: | Blake Dickson [aut, cre] , Stephanie Pierce [aut] , Noah Greifer [aut] , Robert Brocklehurst [aut] |
Maintainer: | Blake Dickson <[email protected]> |
License: | GPL (>= 2) |
Version: | 1.0.2 |
Built: | 2024-10-09 05:17:05 UTC |
Source: | https://github.com/blakedickson/morphoscape |
fnc_df
as_fnc_df()
converts a data frame containing coordinates and functional charactertics in a morphological space to a fnc_df
object for use in later funcitons, most importantly krige_surf
.
as_fnc_df(x, func.names = NULL, scale = TRUE)
as_fnc_df(x, func.names = NULL, scale = TRUE)
x |
a data frame containing coordinates and functional characteristics (and possibly other variables, which are ignored). The first two columns must correspond to the x and y coordinates of the warps in morphological space. |
func.names |
the names of the variables in |
scale |
whether to scale the functional characteristics to have a minimum of 0 and a maximum of 1. This should generally be left at its default ( |
Input data can be from a sampled grid of locations in morphospace, measured specimen data, species or group means, or a mix.
A fnc_df
object, which is a data.frame
with the x and y coordinates in the first two columns and the functional characteristics in the other columns. The "func.names"
attribute contains the names of the functional characteristics.
krige_surf
for using an fnc_df
object to create a kriged surface.
data("warps") warps_fnc <- as_fnc_df(warps, func.names = c("hydro", "curve", "mech", "fea")) str(warps_fnc)
data("warps") warps_fnc <- as_fnc_df(warps, func.names = c("hydro", "curve", "mech", "fea")) str(warps_fnc)
calc_all_lscps()
calculates adaptive landscapes from a set of kriged surfaces of functional characteristics and sets of weights for those characteristics.
calc_all_lscps(kr_data, grid_weights, file = NULL)
calc_all_lscps(kr_data, grid_weights, file = NULL)
kr_data |
a |
grid_weights |
a |
file |
the path of a file to save the resulting output object, which may be quite large. The file path should contain an .rds or .rdata extension, which will be saved using |
calc_all_lscps()
computes a combined adaptive landscape for each of the supplied sets of weights. The optimal landscape overall or for certain subsets of the sample data can be found using calcGrpWprime
or calcWprimeBy
. calc_lscp
can be used to extract the surface of the weighted functional characteristics for each set of weights (see Examples).
Because the resulting objects are so large, it can be a good idea to save them after creation, which can be done automatically using the file
argument. If the supplied file extension is .rds
, saveRDS
will be used to save the object to the supplied file path, and the file can be loaded using readRDS
. If the supplied file extension is .RData
, save
will be used to save the object to the supplied file path, and the file can be loaded using load
.
An all_lscps
object containing the following components:
dataframe |
a list of the |
wtd_lscps |
a list containing the weightred fitness values for each set of weights for the |
grid_weights |
the |
calc_lscp
for computing a single weighted landscape or extracting the weighted surface of functional characteristics for a single set of weights.
generate_weights
for generating the required matrix of weights.
calcGrpWprime
and calcWprimeBy
for finding optimal sets of weights and adaptive landscapes for subgroups.
data("warps") data("turtles") warps_fnc <- as_fnc_df(warps, func.names = c("hydro", "fea")) kr_surf <- krige_surf(warps_fnc, new_data = turtles) grid_weights <- generate_weights(n = 20, data = kr_surf) all_lscps <- calc_all_lscps(kr_surf, grid_weights = grid_weights) all_lscps # Extract the weighted surface for a single set # of weights (here, the 6th set of weights) grid_weights[6,] wtd_lscp_6 <- calc_lscp(all_lscps, i = 6) wtd_lscp_6 # This aligns with the weighted fitness value: mean(all_lscps$wtd_lscps$new_data[,6])
data("warps") data("turtles") warps_fnc <- as_fnc_df(warps, func.names = c("hydro", "fea")) kr_surf <- krige_surf(warps_fnc, new_data = turtles) grid_weights <- generate_weights(n = 20, data = kr_surf) all_lscps <- calc_all_lscps(kr_surf, grid_weights = grid_weights) all_lscps # Extract the weighted surface for a single set # of weights (here, the 6th set of weights) grid_weights[6,] wtd_lscp_6 <- calc_lscp(all_lscps, i = 6) wtd_lscp_6 # This aligns with the weighted fitness value: mean(all_lscps$wtd_lscps$new_data[,6])
calc_lscp()
calculates a single weighted landscape from a set of kriged surfaces of functional characteristics and a set of weights for those characteristics. This landscape can then be plotted using plot.wtd_lscp
. Additionally computes the fitness values for a sample of additional coordinates.
calc_lscp(data, weights, ...) ## S3 method for class 'kriged_surfaces' calc_lscp(data, weights, ...) ## S3 method for class 'all_lscps' calc_lscp(data, weights, i, ...)
calc_lscp(data, weights, ...) ## S3 method for class 'kriged_surfaces' calc_lscp(data, weights, ...) ## S3 method for class 'all_lscps' calc_lscp(data, weights, i, ...)
data |
a |
weights |
a vector of weights, one for each functional characteristic. These weights should be nonnegative and sum to 1. |
i |
when |
... |
ignored. |
calc_lscp()
operates on the kriged surfaces stored in data
by multiplying the functional characteristic values of each point on the surface grid by the weights and computing the sum of those values to arrive at a "fitness" value that is represented by the maximum height of the combined adaptive landscape. When a new_data
component is present in data
(e.g., because a new_data
argument was supplied to krige_surf()
or data
is the output of a call to krige_new_data()
), the weighted fitness values will be computed for the coordinates in new_data
as well.
A wtd_lscp
object, which contains the following components:
W |
a named vector of the supplied weights |
Wprime |
a list containing the weighted |
plot.wtd_lscp
for plotting the resulting weighted landscape.
generate_weights
for generating a matrix of weights.
calc_all_lscps
for computing weighted landscapes for a matrix of weights (i.e., rather than the single set of weights that can be used with calc_lscp
). For finding an optimal set of weights, calc_all_lscps
should be used, though it only produces the weighted fitness values for each set of weightd and not the weighted functional characteristic surfaces.
data("warps") warps_fnc <- as_fnc_df(warps, func.names = c("hydro", "fea")) kr_surf <- krige_surf(warps_fnc) weights <- c(hydro = .5, fea = .5) w_lscp <- calc_lscp(kr_surf, weights = weights) plot(w_lscp) # Adding new_data data("turtles") kr_surf <- krige_new_data(kr_surf, new_data = turtles) w_lscp <- calc_lscp(kr_surf, weights = weights) w_lscp plot(w_lscp) ## See further use with calc_all_lscps() ## at help("calc_all_lscps")
data("warps") warps_fnc <- as_fnc_df(warps, func.names = c("hydro", "fea")) kr_surf <- krige_surf(warps_fnc) weights <- c(hydro = .5, fea = .5) w_lscp <- calc_lscp(kr_surf, weights = weights) plot(w_lscp) # Adding new_data data("turtles") kr_surf <- krige_new_data(kr_surf, new_data = turtles) w_lscp <- calc_lscp(kr_surf, weights = weights) w_lscp plot(w_lscp) ## See further use with calc_all_lscps() ## at help("calc_all_lscps")
Given a "by_Wprime" or "kriged_surfaces" object, this function returns the grid of x, y values and adds a unique grid cell identifier
calc_lscp_Pareto(x, n1, n2)
calc_lscp_Pareto(x, n1, n2)
x |
A "by_Wprime" or "kriged_surfaces" object |
n1 |
String, name of the first trait or group to be compared |
n2 |
String, name of the second trait or group to be compared |
A list that contains two elements: 1) A tibble containing the x,y grid of points across morphospace, the trait or landscape values Z being compared at each point and the associated Pareto optimality (Ri) values. 2) A character vector containing the names of the groups or traits that had their Pareto optimality compared
Function for calculating Pareto optimality, using the formula of Deakin et al
calc_Ri(x, n1, n2)
calc_Ri(x, n1, n2)
x |
The grid data from objects of class 'kriged_surface' or 'by_Wprime' |
n1 |
Name of the first trait/group to be compared |
n2 |
Name of the second trait/group to be compared |
Pareto optimality
calcGrpWprime()
computes the optimally weighted adaptive landscape by searching through the adaptive landscapes formed from sets of weights and performance surfaces, and finding the set of weights that yields the greatest overall (average) fitness value (Z) across a sample of data or a subset thereof.
calcGrpWprime(x, index, method = "chi-squared", quantile = 0.05) ## S3 method for class 'grp_Wprime' print(x, digits = max(3L, getOption("digits") - 3L), ...)
calcGrpWprime(x, index, method = "chi-squared", quantile = 0.05) ## S3 method for class 'grp_Wprime' print(x, digits = max(3L, getOption("digits") - 3L), ...)
x |
for for |
index |
an optional vector of indices indicating which subset of the |
method |
the method used to compute the optimal weights. Allowable options include |
quantile |
when |
digits |
the number of significant digits to print. |
... |
passed to |
calcGrpWprime()
calculates an overall fitness score for each set of weights based on the average weighted fitness values of the indexed subgroup. The set of weights that optimizes this score is then produced as the weights defining the optimal adaptive landscape for that subgroup. The way the final set of weights is computed depends on the argument to method
. When method = "max"
, the single best set of weights is used. However, often many of the upper sets of weights perform equally or nearly equally as well as the best set. It is instead recommended to use "quantile"
or "chi-squared"
methods. When method = "quantile"
, the top of weights are averaged to compute the optimal weights, where
corresponds to the value supplied to
quantile
. When method = "chi-square"
, the chi-squared value is computed for each set of weights
as
where is the largest
among the weights, and a p-value is computed for each
value using a
distribution with 2 d.f.; any set of weights with a p-value less than
quantile
is included to be averaged to compute the optimal set of weights.
A grp_Wprime
object, which contains the following components:
Zprime |
a list containing the optimal weights and the Z value they yield ( |
W |
a matrix containing all sets of weights (i.e., those supplied to the |
Wprime |
a |
Dickson, B. V., Clack, J. A., Smithson, T. R., & Pierce, S. E. (2021). Functional adaptive landscapes predict terrestrial capacity at the origin of limbs. Nature, 589(7841), 242-245.
Jones, K. E., Dickson, B. V., Angielczyk, K. D., & Pierce, S. E. (2021). Adaptive landscapes challenge the "lateral-to-sagittal"" paradigm for mammalian vertebral evolution. Current Biology, 31(9), 1883-1892.
calc_all_lscps
for computing the landscapes which are to be optimized.
calcWprimeBy
for finding optimal sets of weights for multiple subgroups defined by a subgrouping variable.
plot.grp_Wprime
for plotting the resulting adaptive landscape.
data("warps") data("turtles") warps_fnc <- as_fnc_df(warps, func.names = c("hydro", "fea")) kr_surf <- krige_surf(warps_fnc, new_data = turtles) grid_weights <- generate_weights(n = 3, data = kr_surf) all_lscps <- calc_all_lscps(kr_surf, grid_weights = grid_weights) wprime_S <- calcGrpWprime(all_lscps, index = Ecology == "S") wprime_S plot(wprime_S)
data("warps") data("turtles") warps_fnc <- as_fnc_df(warps, func.names = c("hydro", "fea")) kr_surf <- krige_surf(warps_fnc, new_data = turtles) grid_weights <- generate_weights(n = 3, data = kr_surf) all_lscps <- calc_all_lscps(kr_surf, grid_weights = grid_weights) wprime_S <- calcGrpWprime(all_lscps, index = Ecology == "S") wprime_S plot(wprime_S)
calcPoly
calls on the spatial
package to fit rectangular spatial polynomial surface models by least-squares, or GLS. These methods allow the user to test whether data have spatial trends in morphospace. Outputs are a polynomial trend surface, and ANOVA table for the model fit. multiPoly
applies calcPoly
to a fnc_df
with outputs for each trait. For more extensive documentation for model fitting see the spatial
package.
calcPoly(fnc, npoly = 3, fnc.name = NULL, gls.covmod = list(covmod = expcov, d = 0.7, alpha = 0, se = 1), pad = 1.2, resample = 100, range = NULL, verbose = FALSE) multiPoly(fnc_df, npoly = 3, ...)
calcPoly(fnc, npoly = 3, fnc.name = NULL, gls.covmod = list(covmod = expcov, d = 0.7, alpha = 0, se = 1), pad = 1.2, resample = 100, range = NULL, verbose = FALSE) multiPoly(fnc_df, npoly = 3, ...)
fnc |
an XYZ dataframe or matrix of a spatially distributed trait. |
fnc_df |
a functional dataframe from |
npoly |
singular numeric. Degree of polynomial to fit ragning from 1-4. For |
gls.covmod |
Optional list of arguments to pass to |
fnc.name |
Optional speficiation of the trait name. Defaults to |
pad |
Degree by which to extrapolate input data. Defaults to 1.2. |
resample |
Resampling density. Corresponds to the number of points calculated along both X and Y axes. Defaults to 100. If no resampling is desired, set |
range |
Optional. Manually set X and Y ranges. Input is a 2x2 matrix with rows corresponding to X and Y ranges respectively. |
verbose |
Optional. Logical. If |
... |
Arguments to pass onto |
Fits polynomial trend surfaces using the 'spatial' package. First, an npoly
polynomial trend surface is fit by least squares using surf.ls
or generalized least-squares by surf.gls
. GLS is fit by one of three covariance functions, exponential (expcov
), gaussian (gaucov
) or spherical (sphercov
) and requires additional parameters to be passed as a list through gls.covmod
(see examples). For a full description of arguments and usage see surf.gls
and expcov
documentation.
The surface is then evaluated using trmat
within limits set by input data, or manually using range
.
An object of class poly_surf
, or multi_surf
with the following components:
fnc.name |
name of trait |
poly |
Polynomial trend fit output from |
surface |
Evaluated trend surface output from |
grid |
Expanded surface in long XZY dataframe format |
peak |
Coordinates and height of the peak of the surface |
Blake V. Dickson
Dickson, B.V. and Pierce, S.E. (2019), Functional performance of turtle humerus shape across an ecological adaptive landscape. Evolution, 73: 1265-1277. https://doi.org/10.1111/evo.13747
surf.ls
,
surf.gls
,
expcov
,
trmat
,
require(spatial) data("warps") warps_fnc <- as_fnc_df(warps) # Make single trait dataframe hydro_fnc <- data.frame(warps_fnc[ ,1:2], warps_fnc[ ,"hydro"]) polysurf <- calcPoly(hydro_fnc) summary(polysurf) plot(polysurf) # Fit using gls polysurf <- calcPoly(hydro_fnc, gls.covmod = list(covmod = expcov, d = 0.7, alpha = 0, se = 1)) ## Not run: summary(polysurf) ## End(Not run) plot(polysurf) # Calculate multiple polynomial surfaces multi_poly <- multiPoly(warps_fnc) ## Not run: summary(multi_poly) ## End(Not run) plot(multi_poly) # Set manual range polysurf <- calcPoly(hydro_fnc, range = rbind(range(warps_fnc$x) * 1.2, range(warps_fnc$y) * 1.4)) polysurf <- calcPoly(hydro_fnc, range = rbind(c(-0.2, 0.12), c(-0.06, 0.1)) ) ## Not run: summary(polysurf) ## End(Not run) # # Adjust polynomial degree multiPoly(warps_fnc, npoly = 2) # Specify multiple degrees multi_poly <- multiPoly(warps_fnc, npoly = c(2,3,4,3)) ## Not run: summary(polysurf) ## End(Not run) plot(polysurf)
require(spatial) data("warps") warps_fnc <- as_fnc_df(warps) # Make single trait dataframe hydro_fnc <- data.frame(warps_fnc[ ,1:2], warps_fnc[ ,"hydro"]) polysurf <- calcPoly(hydro_fnc) summary(polysurf) plot(polysurf) # Fit using gls polysurf <- calcPoly(hydro_fnc, gls.covmod = list(covmod = expcov, d = 0.7, alpha = 0, se = 1)) ## Not run: summary(polysurf) ## End(Not run) plot(polysurf) # Calculate multiple polynomial surfaces multi_poly <- multiPoly(warps_fnc) ## Not run: summary(multi_poly) ## End(Not run) plot(multi_poly) # Set manual range polysurf <- calcPoly(hydro_fnc, range = rbind(range(warps_fnc$x) * 1.2, range(warps_fnc$y) * 1.4)) polysurf <- calcPoly(hydro_fnc, range = rbind(c(-0.2, 0.12), c(-0.06, 0.1)) ) ## Not run: summary(polysurf) ## End(Not run) # # Adjust polynomial degree multiPoly(warps_fnc, npoly = 2) # Specify multiple degrees multi_poly <- multiPoly(warps_fnc, npoly = c(2,3,4,3)) ## Not run: summary(polysurf) ## End(Not run) plot(polysurf)
calcWprimeBy()
computes the optimally weighted adaptive landscape by searching through the adaptive landscapes formed from sets of weights and performance surfaces, and finding the set of weights that yields the greatest overall (average) fitness value (Z) across subsets of a sample dataset.
calcWprimeBy(x, by, method = "chi-squared", quantile = 0.05) ## S3 method for class 'by_Wprime' print(x, digits = max(3L, getOption("digits") - 3L), ...) ## S3 method for class 'by_Wprime' summary(object, ...) ## S3 method for class 'summary.by_Wprime' print(x, digits = max(3L, getOption("digits") - 3L), ...)
calcWprimeBy(x, by, method = "chi-squared", quantile = 0.05) ## S3 method for class 'by_Wprime' print(x, digits = max(3L, getOption("digits") - 3L), ...) ## S3 method for class 'by_Wprime' summary(object, ...) ## S3 method for class 'summary.by_Wprime' print(x, digits = max(3L, getOption("digits") - 3L), ...)
x |
for for for |
by |
a one-sided formula containing the grouping variable on the right hand side (e.g., |
method |
the method used to compute the optimal weights. Allowable options include |
quantile |
when |
digits |
the number of significant digits to print. |
... |
passed to |
object |
a |
calcWprimeBy()
splits the sample data based on the by
variable and then calls calcGrpWprime
on each subset. The main benefit of using calcWprimeBy()
is that the subgrouping variable is part of the output object and therefore can be used in plotting using plot.by_Wprime
.
A by_Wprime
object contaning the following components:
by |
the subgrouping variable supplied to |
grp_Wprimes |
a list of |
calc_all_lscps
for computing the landscapes which are to be optimized.
calcGrpWprime
for finding optimal sets of weights for a single subgroup.
plot.by_Wprime
for plotting the resulting adaptive landscapes.
data("warps") data("turtles") warps_fnc <- as_fnc_df(warps, func.names = c("hydro", "fea")) kr_surf <- krige_surf(warps_fnc, new_data = turtles) grid_weights <- generate_weights(n = 3, data = kr_surf) all_lscps <- calc_all_lscps(kr_surf, grid_weights = grid_weights) wprime_Ecology <- calcWprimeBy(all_lscps, by = ~Ecology) wprime_Ecology summary(wprime_Ecology) plot(wprime_Ecology)
data("warps") data("turtles") warps_fnc <- as_fnc_df(warps, func.names = c("hydro", "fea")) kr_surf <- krige_surf(warps_fnc, new_data = turtles) grid_weights <- generate_weights(n = 3, data = kr_surf) all_lscps <- calc_all_lscps(kr_surf, grid_weights = grid_weights) wprime_Ecology <- calcWprimeBy(all_lscps, by = ~Ecology) wprime_Ecology summary(wprime_Ecology) plot(wprime_Ecology)
generate_weights()
generates a matrix containing weight combinations for a set of variables such that each set of weights sums to 1. This can be supplied to calc_all_lscps
to calculate fitness landscapes corresponding to a variety of possible sets of weights for weighting functional characteristics. The weights are generated by partitioning a weight of 1 across however many variables are requested in all possible ways.
generate_weights(step, n, data = NULL, nvar = NULL, varnames = NULL, verbose = TRUE)
generate_weights(step, n, data = NULL, nvar = NULL, varnames = NULL, verbose = TRUE)
step |
|
n |
|
data |
an optional |
nvar |
the number of variables across which to allocate the weights. Ignored if |
varnames |
the names of the variables across which to allocate the weights. Ignored if |
verbose |
whether to display a message noting the number of sets of weights created. |
generate_weights()
works by fining all possible allocations of n
objects into nvar
bins. When step
is supplied, n
is computed as round(1/step)
, so the resulting weight partitions may not be exactly equal to step
when its inverse is not an integer. The larger n
is (or the smaller step
) is, the more possible allocations will be produced (i.e., and the resulting object will have more rows). The output of generate_weights()
can quickly become very large with increasing number of variables, and will make subsequent analyses slow. It is recommended to start with a large step
size, or small n
, and increment up.
A grid_weights
object, which is a matrix with a row for each each set of weights and a column for each variable over which the weights are allocated. The weights in each row will sum to 1.
# Allocating 10 partitions of .1 across 3 variables wmat <- generate_weights(n = 10, nvar = 3) head(wmat) # Allocating 5 partitions of .2 across the 4 functional # characteristics in the warps dataset data("warps") warps_fnc <- as_fnc_df(warps) wmat <- generate_weights(n = 5, data = warps_fnc) head(wmat) # Using 'step' for the same result: wmat <- generate_weights(step = .2, data = warps_fnc) head(wmat)
# Allocating 10 partitions of .1 across 3 variables wmat <- generate_weights(n = 10, nvar = 3) head(wmat) # Allocating 5 partitions of .2 across the 4 functional # characteristics in the warps dataset data("warps") warps_fnc <- as_fnc_df(warps) wmat <- generate_weights(n = 5, data = warps_fnc) head(wmat) # Using 'step' for the same result: wmat <- generate_weights(step = .2, data = warps_fnc) head(wmat)
Given a "by_Wprime" or "kriged_surfaces" object, this function returns the grid of x, y values and adds a unique grid cell identifier
get_grid(x)
get_grid(x)
x |
A "by_Wprime" or "kriged_surfaces" object |
The grid of x, y values and other data, with the addition of a unique grid cell identifier, 'gridID', which is needed to correctly reorder the data following the ranking functions - see below.
krige_surf()
performs automatic or manual kriging (i.e., interpolation) of one or more functional characteristics that are spatially distributed over a morphospace to create a smoothly kriged surface. Interpolated values can also be produced for a new dataset given their coordinates in morphological space.
krige_surf(fnc_df, vgm = NULL, grid = NULL, resample = 100, padding = 1.2, hull = NULL, alpha = 1, new_data = NULL) krige_new_data(x, new_data)
krige_surf(fnc_df, vgm = NULL, grid = NULL, resample = 100, padding = 1.2, hull = NULL, alpha = 1, new_data = NULL) krige_new_data(x, new_data)
fnc_df |
a |
vgm |
a user supplied list of variogram models generated from |
grid |
a matrix or data frame containing the grid of points over which the surface is to be interpolated. Should be the output of a call to |
resample |
the number of points (or pixels) in the x and y dimensions over which to create the grid. Default is 100 for a kriged surface of 100x100=10,000 pixels. Passed to |
padding |
a number representing how much to expand the grid beyond the ranges of the x- and y-coordinates. For example, |
hull |
method to to restrict kriging to an alpha hull to prevent extrapolation beyond the coordinates present in |
alpha |
the alpha value used to create the alpha hull. Passed to |
new_data |
a dataset of coordinates for a new sample; the values of the functional characteristics for this sample will be interpolated using the kriged surface. |
debug |
shows all warnings called from autoKrige. Only used for debugging purposes |
x |
a |
krige_surf()
implements the automap::autoKrige
function on one or more spatially distributed traits to produce an interpolated (or extrapolated) surface of evenly spaced gridpoints. This is done by automatiically finding the best variogram fit for each of the non-corrdinate variables in fnc_df
. For details on automatic variogram fitting, see automap::autoKrige
.
Input data in fnc_df
can be unevenly distributed (direct from speciments), or gridded (determined from evenly distributed hypothetical shapes) in morphospace. Trait data inputted directly from specimen measurements will be subject to error based on the how unevenly points are distributed, with high resoultion gridded datapoints producing the least potential reconstruction error (see Smith et al 2021).
By default krige_surf
will create a hull
to strictly prevent any extrapolation beyond the provided data. This will produce the most conservative landscapes. If hull
is set to FALSE
, then the function will reconstruct a rectangle determined by the XY coordinate ranges supplied in fnc_df
. Padding will be applied by default (an extra 20%) as defined by padding
, to expand the rectangle beyond the supplied points. Reconstructions without a hull
would be most appropriate for trait data determined from evenely spaced hypothetical gridpoints. If grid
is provided the function will strictly interpolate at these gridded points.
krige_new_data()
adds a new data set to the supplied kriged_surfaces
object and interpolates the values of the functional characteristics on the suppllied sample. This should only be used to add a new dataset to a kriged_surfaces
object produced without new_data
supplied or to replace an existing new_data
component.
An object of class kriged_surfaces
containing the following components:
fnc_df |
the original data frame of functional characteristics passed to |
autoKrige |
a named list of the kriged surfaces, one for each functional characteristic. Each surface is of class |
dataframes |
a list of two data frames, |
For krige_new_data()
, the original kriged_surfaces
object, with the $dataframes$new_data
component containing the sample coordinates supplied to new_data
as well as the interpolated values of the functional characteristics for each sample.
Smith, S. M., Stayton, C. T., & Angielczyk, K. D. (2021). How many trees to see the forest? Assessing the effects of morphospace coverage and sample size in performance surface analysis. Methods in Ecology and Evolution, 12(8), 1411-1424.
plot.kriged_surfaces
for plotting the kriged surfaces.
as_fnc_df
for creating the input dataset.
resample_grid
for creating the grid over which the kriging occurs prior to using krige_surf
.
automap::autoKrige
for the function that does the kriging.
data("warps") warps_fnc <- as_fnc_df(warps) grid <- resample_grid(warps, hull = "concaveman", plot = TRUE) kr_surf <- krige_surf(warps_fnc, grid = grid) kr_surf # Add new data data("turtles") kr_surf <- krige_new_data(kr_surf, new_data = turtles) kr_surf plot(kr_surf) # Doing it all in one step: ## Not run: kr_surf <- krige_surf(warps_fnc, new_data = turtles, hull = "alphahull") kr_surf ## End(Not run) # No hull and padding kr_surf <- krige_surf(warps_fnc, new_data = turtles, hull = NULL, padding = 1.2) plot(kr_surf)
data("warps") warps_fnc <- as_fnc_df(warps) grid <- resample_grid(warps, hull = "concaveman", plot = TRUE) kr_surf <- krige_surf(warps_fnc, grid = grid) kr_surf # Add new data data("turtles") kr_surf <- krige_new_data(kr_surf, new_data = turtles) kr_surf plot(kr_surf) # Doing it all in one step: ## Not run: kr_surf <- krige_surf(warps_fnc, new_data = turtles, hull = "alphahull") kr_surf ## End(Not run) # No hull and padding kr_surf <- krige_surf(warps_fnc, new_data = turtles, hull = NULL, padding = 1.2) plot(kr_surf)
lands.grp.test()
performs a statistical test for whether the optimal adaptive landscape for two subgroups are significantly different from each other. The p-value of the test is the proportion of weight sets that are shared between the two subgroups among their respective top weight sets. multi.lands.grp.test()
performs this test for all pairs of subgroups.
lands.grp.test(grpa, grpb, method = "chi-squared", quantile = 0.05) multi.lands.grp.test(x, method = "chi-squared", quantile = 0.05) ## S3 method for class 'lands.grp.test' print(x, digits = max(3L, getOption("digits") - 3L), ...) ## S3 method for class 'multi.lands.grp.test' print(x, digits = max(3L, getOption("digits") - 3L), style = "matrix", ...)
lands.grp.test(grpa, grpb, method = "chi-squared", quantile = 0.05) multi.lands.grp.test(x, method = "chi-squared", quantile = 0.05) ## S3 method for class 'lands.grp.test' print(x, digits = max(3L, getOption("digits") - 3L), ...) ## S3 method for class 'multi.lands.grp.test' print(x, digits = max(3L, getOption("digits") - 3L), style = "matrix", ...)
grpa , grpb
|
for |
x |
for for |
method |
the method used to determine which sets of weights are in the "best" sets of weights that are to be comapred between the two groups. Allowable options include |
quantile |
the top quantile used to determine the best sets of weights to be included in the average to compute the optimal set of weights. Should be a number between 0 and 1, with a low value indicating that only the few top sets of weights will be used. See |
digits |
the number of significant digits to print. |
style |
how to display the results of the pairwise tests; allowable options include |
... |
passed to |
lands.grp.test()
performs pairwise comparisons between two adaptive groups by comparing the number of shared landscapes in the top percentile of each group with the total number of landscapes in this top percentile
. The probability
thus is calculated as:
If method = "quantile"
is used, then the top percentile is defined by quantile
. If method = "chi-squared"
is used, then the top percentile is calculated from the chi-squared value as:
where is the largest
among the weights, and a p-value is computed for each
value using a
distribution with 2 d.f.; any set of weights with a p-value less than
quantile
is included in the optimal set of weights.
multi.lands.grp.test()
is a wrapper for lands.grp.test()
, applying the function pairwise to all combinations of groups calculated by calcWprimeBy
.
For lands.grp.test()
, a lands.grp.test
object containing the following components:
n.match |
the number of sets of weights that match between the two supplied subgroups |
p.val |
the p-value of the test, computed as the number of sets of weights that match divided by the number of sets of weights compared |
matching |
a matrix containing the sets of weights that match between the two subgroups |
method |
the argument supplied to |
quantile |
the argument supplied to |
For multi.lands.grp.test()
, a multi.lands.grp.test
object containing the following components:
res |
a data frame containing the results of the tests, with the columns |
method |
the argument supplied to |
quantile |
the argument supplied to |
For print.multi.lands.grp.test()
, setting style = "table"
prints the res
component as-is; setting style = "matrix"
creates a matrix where the p-values of the test are below the diagonal and the number of matches of the test are above the diagonal.
Jones, K. E., Dickson, B. V., Angielczyk, K. D., & Pierce, S. E. (2021). Adaptive landscapes challenge the "lateral-to-sagittal"" paradigm for mammalian vertebral evolution. Current Biology, 31(9), 1883-1892.
calcGrpWprime
and calcWprimeBy
for creatign the objects used as inputs to these functions
data("warps") data("turtles") warps_fnc <- as_fnc_df(warps, func.names = c("hydro", "fea")) kr_surf <- krige_surf(warps_fnc, new_data = turtles) grid_weights <- generate_weights(n = 3, data = kr_surf) all_lscps <- calc_all_lscps(kr_surf, grid_weights = grid_weights) # Comparing adaptive landscapes of Ecology groups S and M wprime_S <- calcGrpWprime(all_lscps, index = Ecology == "S") wprime_M <- calcGrpWprime(all_lscps, index = Ecology == "M") lands.grp.test(wprime_S, wprime_M) # Comparing adaptive landscapes of all Group subgroups wprime_by_Group <- calcWprimeBy(all_lscps, by = ~Group) tests <- multi.lands.grp.test(wprime_by_Group) tests print(tests, style = "table")
data("warps") data("turtles") warps_fnc <- as_fnc_df(warps, func.names = c("hydro", "fea")) kr_surf <- krige_surf(warps_fnc, new_data = turtles) grid_weights <- generate_weights(n = 3, data = kr_surf) all_lscps <- calc_all_lscps(kr_surf, grid_weights = grid_weights) # Comparing adaptive landscapes of Ecology groups S and M wprime_S <- calcGrpWprime(all_lscps, index = Ecology == "S") wprime_M <- calcGrpWprime(all_lscps, index = Ecology == "M") lands.grp.test(wprime_S, wprime_M) # Comparing adaptive landscapes of all Group subgroups wprime_by_Group <- calcWprimeBy(all_lscps, by = ~Group) tests <- multi.lands.grp.test(wprime_by_Group) tests print(tests, style = "table")
Perform simple operations (sum, sub, mult, div) on one or multiple landscapes (see details for use cases)
sum_lscps(lscps, num = NULL, average = TRUE) mult_lscps(lscps, num = NULL) sub_lscps(lscps, binary = FALSE) div_lscps(lscps, binary = FALSE)
sum_lscps(lscps, num = NULL, average = TRUE) mult_lscps(lscps, num = NULL) sub_lscps(lscps, binary = FALSE) div_lscps(lscps, binary = FALSE)
lscps |
A named list containing datasets of spatial data to apply operations (see details). |
num |
Optional. Defaults to NULL. A vector containing a single numeric scalar or numeric vector with length = lscps to scale by when using |
binary |
If subracting or dividing landscapes, binarize result to obtain logical [0,1] result (see details for use case) |
average |
if summation is performed, should the result be averaged for the number of landscapes |
Simple operations are applied to one or more landscapes depending on use case. Spatial datasets can be supplied in an XYZ dataframe, or as any landscape output from Morphoscape.
sum - sum a single spatial dataset/landscape with a single scalar (lscp1 + num1
); sum two or more spatial datasets/landscapes together (lscp1 + lscp2 ... lscpN
); or sum multiple landscapes with multiple scalars ((lscp1, lscp2 ... lscpN) + (num1, num2, ..., numN)
)
mult - multiply a single spatial dataset/landscape with a single scalar (lscp1 * num1
); multiply two or more spatial datasets/landscapes together (lscp1 * lscp2 ... lscpN
); or multiply multiple landscapes with multiple scalars ((lscp1, lscp2 ... lscpN) * (num1, num2, ..., numN)
)
sub - substract one spatial dataset/landscape from another (lscp1 - lscp2
). If numeric subtraction is desired, use sum_lscps with negative num
values.
div - divide one spatial dataset by another (lscp1 / lscp2
).
sub_lscps()
and div_lscps
can be used to construct transition landscapes per (Dickson et al 2020) which can compare performance between two adaptive regimes. If binary = T is used, the result will be a spatial representation of which parent landscape dominates. However, it is recommended to use trans_lscps
or adpt_regions
to calculate transtional landscapes or adaptive regions (not yet implemented).
An object of class "combined.surface" containing XYZ spatial data.
Blake V. Dickson
krige_surf
, calcGrpWprime
, calc_lscp
, calcPoly
, trans_lscps
, adpt_regions
require("Morphoscape") data("turtles") data("warps") fnc_df <- as_fnc_df(warps, func.names = c("hydro", "curve", "mech", "fea")) kr_surf <- krige_surf(fnc_df, new_data = turtles) grid_weights <- generate_weights(n = 10, data = kr_surf) all_lscps <- calc_all_lscps(kr_surf, grid_weights = grid_weights) wprime_S <- calcGrpWprime(all_lscps, index = Ecology == "S") wprime_T <- calcGrpWprime(all_lscps, index = Ecology == "T") lscps <- list(wprimeS = wprime_S, wprime_T = wprime_T) # summing multiple landscapes together summed_surfs <- sum_lscps(lscps, average = TRUE) # summing landscapes by one or more numeric scalars summed_surfs <- sum_lscps(lscps, num = c(1.5, -1.15)) # multiple numeric, with subtraction # multiplying mutliple landscapes together mult_surfs <- mult_lscps(lscps) # multiply landscapes together # multiplying landscapes by one or more numeric scalars mult_surfs <- mult_lscps(lscps, num = 2) # apply numeric multiplier to all landscapes mult_surfs <- mult_lscps(lscps, num = c(1.2, 0.8)) # apply numeric elements to each landscape # substract or divide two landscapes sub_surf <- sub_lscps(lscps) div_surf <- div_lscps(lscps) # with binary result sub_surf <- sub_lscps(lscps, binary = TRUE) div_surf <- div_lscps(lscps, binary = TRUE)
require("Morphoscape") data("turtles") data("warps") fnc_df <- as_fnc_df(warps, func.names = c("hydro", "curve", "mech", "fea")) kr_surf <- krige_surf(fnc_df, new_data = turtles) grid_weights <- generate_weights(n = 10, data = kr_surf) all_lscps <- calc_all_lscps(kr_surf, grid_weights = grid_weights) wprime_S <- calcGrpWprime(all_lscps, index = Ecology == "S") wprime_T <- calcGrpWprime(all_lscps, index = Ecology == "T") lscps <- list(wprimeS = wprime_S, wprime_T = wprime_T) # summing multiple landscapes together summed_surfs <- sum_lscps(lscps, average = TRUE) # summing landscapes by one or more numeric scalars summed_surfs <- sum_lscps(lscps, num = c(1.5, -1.15)) # multiple numeric, with subtraction # multiplying mutliple landscapes together mult_surfs <- mult_lscps(lscps) # multiply landscapes together # multiplying landscapes by one or more numeric scalars mult_surfs <- mult_lscps(lscps, num = 2) # apply numeric multiplier to all landscapes mult_surfs <- mult_lscps(lscps, num = c(1.2, 0.8)) # apply numeric elements to each landscape # substract or divide two landscapes sub_surf <- sub_lscps(lscps) div_surf <- div_lscps(lscps) # with binary result sub_surf <- sub_lscps(lscps, binary = TRUE) div_surf <- div_lscps(lscps, binary = TRUE)
Helper function - plots Pareto optimality Ri across the grid. Contours are color coded according Ri score. Additionally, the Pareto front is drawn using geom_smooth on the subset of points whose Ri == maximum Ri
plot_ggPareto(x, n1 = NULL, n2 = NULL)
plot_ggPareto(x, n1 = NULL, n2 = NULL)
x |
PO_List object, result of calc_lscp_Pareto. Alternatively, a dataframe or tibble containing trait values |
n1 |
First variable to plot |
n2 |
Second variable to plot |
A ggplot object
Helper function - plots specific performance surface or landscape. Data must be in tabular format. Grid is color-coded according to trait value or Z score.
plot_ggsurf(x, n1 = NULL)
plot_ggsurf(x, n1 = NULL)
x |
PO_List object, result of calc_lscp_Pareto. Alternatively, a dataframe or tibble containing trait values |
n1 |
Name of the trait variable or group landscape being plotted |
A ggplot object
Helper function - plots trade-offs between different traits or landscape Z scores, as an x-y scatterplot. Points are color coded according to Pareto optimality Ri score.
plot_ggtrade(x, n1 = NULL, n2 = NULL)
plot_ggtrade(x, n1 = NULL, n2 = NULL)
x |
PO_List object, result of calc_lscp_Pareto. Alternatively, a dataframe or tibble containing trait values |
n1 |
First variable to plot |
n2 |
Second variable to plot |
A ggplot object
Plots Pareto optimality between two traits or landscapes Z values across morphospace.
plot_lscp_Pareto(x, n1 = NULL, n2 = NULL)
plot_lscp_Pareto(x, n1 = NULL, n2 = NULL)
x |
Output from calc_lscps_Pareto |
n1 |
First variable to plot |
n2 |
Second variable to plot |
A series of ggplot graphs, generated by a series of helper functions. These can be accessed and viewed individually, or plotted all at once using the 'patchwork' package
plot.kriged_surfaces()
produces spatial landscape plots of kriged surfaces produced by krige_surf
.
## S3 method for class 'kriged_surfaces' plot(x, alpha = 0.5, pt.col = "black", interpolate = TRUE, contour = TRUE, ...)
## S3 method for class 'kriged_surfaces' plot(x, alpha = 0.5, pt.col = "black", interpolate = TRUE, contour = TRUE, ...)
x |
a |
alpha , pt.col
|
when a |
interpolate |
|
contour |
|
... |
ignored. |
plot.kriged_surfaces()
is a wrapper for ggplot2 raster plotting functions. For more precise control of raster plotting see ggplot2::geom_raster
.
A ggplot
object, which can be further manipulated using ggplot2 functionality.
ggplot2::ggplot
, ggplot2::geom_raster
, and ggplot2::geom_contour
for the underlying plotting functions. See also sp::spplot
for alternative plotting functions.
krige_surf
for generating the kriged surfaces. krige_new_data
for adding a new_data
component to an existing kriged surface before plotting.
# See examples at help("krige_surf")
# See examples at help("krige_surf")
These plot
plot methods plot an adaptive landscape, a weighted combination of functional surfaces. These landscape arise from calls to calc_lscp
, calc_all_lscps
, calcGrpWprime
, and calcWprimeBy
.
## S3 method for class 'wtd_lscp' plot(x, alpha = 1, pt.col = "black", interpolate = TRUE, contour = TRUE, ...) ## S3 method for class 'grp_Wprime' plot(x, alpha = 1, pt.col = "black", interpolate = TRUE, contour = TRUE, ...) ## S3 method for class 'by_Wprime' plot(x, level, ncol = 1, alpha = 1, pt.col = "black", interpolate = TRUE, contour = TRUE, ...)
## S3 method for class 'wtd_lscp' plot(x, alpha = 1, pt.col = "black", interpolate = TRUE, contour = TRUE, ...) ## S3 method for class 'grp_Wprime' plot(x, alpha = 1, pt.col = "black", interpolate = TRUE, contour = TRUE, ...) ## S3 method for class 'by_Wprime' plot(x, level, ncol = 1, alpha = 1, pt.col = "black", interpolate = TRUE, contour = TRUE, ...)
x |
a |
alpha |
the transparency of the points for the data sample. A number between 0 (fully transparent) and 1 (fully opaque). Passed to |
pt.col |
the color of the points for the data sample. Passed to |
interpolate |
whether to interpolate across pixels in the grid. Passed to |
contour |
whether to display contours in the grid. |
level |
which level of the |
ncol |
when multiple subgroups are plotted, in how many columns should the plots be arranged. |
... |
ignored. |
These plotting functions are wrappers for ggplot2
raster plotting functions. For more precise control of raster plotting see ggplot2::geom_raster
.
A ggplot
object that can be further adjusted using functions from ggplot2.
calc_lscp
, calc_all_lscps
, calcGrpWprime
, and calcWprimeBy
for the functions used to create the objects that are plotted
plot.kriged_surfaces
for plotting functional surfaces prior to combining them into an adaptive landscape.
ggplot2::geom_raster
, ggplot2::geom_point
, and ggplot2::geom_contour
for the underlying plotting functions.
data("warps") data("turtles") warps_fnc <- as_fnc_df(warps, func.names = c("hydro", "fea")) kr_surf <- krige_surf(warps_fnc, new_data = turtles) weights <- c(hydro = .5, fea = .5) w_lscp <- calc_lscp(kr_surf, weights = weights) plot(w_lscp) plot(w_lscp, countour = FALSE, pt.col = "white") # See help("calc_lscp"), help("calcGrpWprime"), and # help("calcWprimeBy") for examples when used with # those functions
data("warps") data("turtles") warps_fnc <- as_fnc_df(warps, func.names = c("hydro", "fea")) kr_surf <- krige_surf(warps_fnc, new_data = turtles) weights <- c(hydro = .5, fea = .5) w_lscp <- calc_lscp(kr_surf, weights = weights) plot(w_lscp) plot(w_lscp, countour = FALSE, pt.col = "white") # See help("calc_lscp"), help("calcGrpWprime"), and # help("calcWprimeBy") for examples when used with # those functions
resample_grid()
creates a rectangular grid around supplied coordinates by resampling evenly spaced points between the minimum and maximum values of each coordinate dimension. The grid can optionally be reduced to a convex or concave hull around the supplied coordinates.
resample_grid(coords2D, resample = 100, padding = 1.2, hull = NULL, alpha = 1, plot = FALSE)
resample_grid(coords2D, resample = 100, padding = 1.2, hull = NULL, alpha = 1, plot = FALSE)
coords2D |
a 2-column matrix data frame of coordinates with the x-coordinates in the first column and the y-coordinates in the second column. The ranges of each column will be used to create the resampled grid. |
resample |
the number of points (or pixels) in the x and y dimensions over which to create the grid. Default is 100 for a kriged surface of 100x100=10,000 pixels. |
padding |
a number representing how much to expand the grid beyond the ranges of the x- and y-coordinates. For example, |
hull |
method to restrict the grid to an alpha hull using |
alpha |
when |
plot |
Logical. When |
A data frame with two columns, x
and y
, containing the resampled coordinate grid. When hull
is specified, any points not in the hull will be absent.
krige_surf
, which uses resample_grid
for kriging.
ahull
and inahull
, or concaveman
for creating the hull.
data("warps") warps_fnc <- as_fnc_df(warps) # hull with plot to see the hull grid <- resample_grid(warps_fnc[c("x", "y")], hull = "concaveman", plot = TRUE) str(grid) ## Not run: # Alpha hull with plot to see the hull grid <- resample_grid(warps_fnc[c("x", "y")], hull = "alphahull", plot = TRUE) ## End(Not run)
data("warps") warps_fnc <- as_fnc_df(warps) # hull with plot to see the hull grid <- resample_grid(warps_fnc[c("x", "y")], hull = "concaveman", plot = TRUE) str(grid) ## Not run: # Alpha hull with plot to see the hull grid <- resample_grid(warps_fnc[c("x", "y")], hull = "alphahull", plot = TRUE) ## End(Not run)
Function to get the heights on a landscape for a set of species points. For a given set of species coordinates in morphospace, this function finds the closest point on the landscape grid, and assigns the values associated to that grid point to that species.
sp_vals_from_grid(x, y)
sp_vals_from_grid(x, y)
x |
A 'by_Wprime' or 'PO_List' object - contains the functional adaptive landscapes or Pareto landscapes you want to extract heights from. |
y |
A dataframe containing species information morphospace. The coordinates columns must be labelled 'x' and 'y'. |
A dataframe containing the species information from y, with additional columns extracted from the landscape data
A dataset containing a sample of 40 turtle humeri used in Dickson and Pierce (2019). New names added by Robert Brocklehurst to make them consistent with prevailing taxonomy.
data("turtles")
data("turtles")
A data frame with 40 observations on the following 4 variables.
x
the first axis of shape variation as determiend by a between-groups principal components analysis
y
the second axis of shape variation as determiend by a between-groups principal components analysis
Group
the locomotor ecologies of the turtles
Ecology
the three ecological groups as determined by a Procrustes ANOVA; "M" (marine), "S" (semiaquatic), and "T" (terrestrial)
Dickson, B.V. and Pierce, S.E. (2019), Functional performance of turtle humerus shape across an ecological adaptive landscape. Evolution, 73: 1265-1277. doi:10.1111/evo.13747
A phylogeny of turtles from Dickson and Pierce (2019) downloaded from timetree.org
data("turtles_tree")
data("turtles_tree")
A phylo object that stores the turtle phylogeny.
Dickson, B.V. and Pierce, S.E. (2019), Functional performance of turtle humerus shape across an ecological adaptive landscape. Evolution, 73: 1265-1277. doi:10.1111/evo.13747
timetree.org
Trait data for simulated shape warps of turtle humeri used to study the morphological evolution of turtles in Dickson and Pierce (2019). The morphospace was defined by a geometric morphometric analyises of 1028 psuedolandmarks on 40 turtle humeri. Hypothetical shape warps were then produced on a 4x6 grid accross morphospace. For each shape warp, four functional traits were measured, corresponding to a locomotory performance trait: stress under simulated load (strength), bone curvature (stride length), muscular mechanical advantage (mechanical advantage), and frontal area (hydrodynamics).
data("warps")
data("warps")
A data frame with 24 observations on the following 6 variables.
x
the first axis of shape variation as determiend by a between-groups principal components analysis of the turtles
dataset
y
the second axis of shape variation as determiend by a between-groups principal components analysis of the turtles
dataset
hydro
hydrodynamics
curve
stride length
mech
mechanical advantage
fea
strength (assessed using finite element analysis)
Dickson, B.V. and Pierce, S.E. (2019), Functional performance of turtle humerus shape across an ecological adaptive landscape. Evolution, 73: 1265-1277. doi:10.1111/evo.13747