├── .Rbuildignore ├── .github ├── .gitignore └── workflows │ └── R-CMD-check.yaml ├── .gitignore ├── DESCRIPTION ├── LICENSE.md ├── NAMESPACE ├── NEWS.md ├── R ├── check_raster.R ├── classes.R ├── data.R ├── func_checks.R ├── generate_points.R ├── generate_points_checks.R ├── globals.R ├── methods.R ├── metrics_bind.R ├── metrics_corr.R ├── metrics_corr_checks.R ├── metrics_filter.R ├── metrics_filter_checks.R ├── metrics_gradient.R ├── metrics_gradient_checks.R ├── metrics_list.R ├── metrics_plots.R ├── metrics_scalogram.R ├── metrics_scalogram_checks.R ├── mland.R ├── mland_checks.R ├── mland_export_gis.R ├── mland_load.R ├── mland_metrics.R ├── mland_metrics_checks.R ├── mland_overlap.R ├── mland_overlap_checks.R ├── mland_plot.R ├── mland_plot_checks.R ├── mland_save.R └── utils.R ├── README.Rmd ├── README.md ├── cran-comments.md ├── data ├── ed_metrics.rda └── otf_metrics.rda ├── inst ├── CITATION └── extdata │ ├── ed_metrics.rds │ ├── elchaco.tif │ ├── elchaco2.tif │ ├── elchaco_ndvi.tif │ ├── elchaco_sites.gpkg │ ├── ernesdesign.zip │ └── otf_sites.gpkg ├── man ├── MultiLand-class.Rd ├── MultiLandMetrics-class.Rd ├── check_raster.Rd ├── conditions.Rd ├── ed_metrics.Rd ├── figures │ ├── logo.png │ └── plot_peje.png ├── generate_points.Rd ├── metrics_bind.Rd ├── metrics_corr.Rd ├── metrics_filter.Rd ├── metrics_gradient.Rd ├── metrics_list.Rd ├── metrics_plots.Rd ├── metrics_scalogram.Rd ├── mland.Rd ├── mland_export_gis.Rd ├── mland_load.Rd ├── mland_metrics.Rd ├── mland_overlap.Rd ├── mland_plot.Rd ├── mland_save.Rd ├── otf_metrics.Rd ├── show-MultiLand-method.Rd └── show-MultiLandMetrics-method.Rd ├── manual.pdf ├── multilandr.Rproj ├── tests ├── testthat.R └── testthat │ ├── test-mland.R │ └── test-mland_metrics.R └── vignettes ├── .gitignore └── Introduction.Rmd /.Rbuildignore: -------------------------------------------------------------------------------- 1 | ^multilandr\.Rproj$ 2 | ^\.Rproj\.user$ 3 | ^app\.R$ 4 | ^scroll_script\.js$ 5 | ^rsconnect$ 6 | ^dev_files$ 7 | ^README\.Rmd$ 8 | ^manual\.pdf$ 9 | ^cran-comments\.md$ 10 | ^\.github$ 11 | ^CRAN-SUBMISSION$ 12 | ^LICENSE\.md$ 13 | -------------------------------------------------------------------------------- /.github/.gitignore: -------------------------------------------------------------------------------- 1 | *.html 2 | -------------------------------------------------------------------------------- /.github/workflows/R-CMD-check.yaml: -------------------------------------------------------------------------------- 1 | # Workflow derived from https://github.com/r-lib/actions/tree/v2/examples 2 | # Need help debugging build failures? Start at https://github.com/r-lib/actions#where-to-find-help 3 | on: 4 | push: 5 | branches: [main, master] 6 | pull_request: 7 | 8 | name: R-CMD-check.yaml 9 | 10 | permissions: read-all 11 | 12 | jobs: 13 | R-CMD-check: 14 | runs-on: ${{ matrix.config.os }} 15 | 16 | name: ${{ matrix.config.os }} (${{ matrix.config.r }}) 17 | 18 | strategy: 19 | fail-fast: false 20 | matrix: 21 | config: 22 | - {os: macos-latest, r: 'release'} 23 | - {os: windows-latest, r: 'release'} 24 | - {os: ubuntu-latest, r: 'devel', http-user-agent: 'release'} 25 | - {os: ubuntu-latest, r: 'release'} 26 | - {os: ubuntu-latest, r: 'oldrel-1'} 27 | 28 | env: 29 | GITHUB_PAT: ${{ secrets.GITHUB_TOKEN }} 30 | R_KEEP_PKG_SOURCE: yes 31 | 32 | steps: 33 | - uses: actions/checkout@v4 34 | 35 | - uses: r-lib/actions/setup-pandoc@v2 36 | 37 | - uses: r-lib/actions/setup-r@v2 38 | with: 39 | r-version: ${{ matrix.config.r }} 40 | http-user-agent: ${{ matrix.config.http-user-agent }} 41 | use-public-rspm: true 42 | 43 | - uses: r-lib/actions/setup-r-dependencies@v2 44 | with: 45 | extra-packages: any::rcmdcheck 46 | needs: check 47 | 48 | - uses: r-lib/actions/check-r-package@v2 49 | with: 50 | upload-snapshots: true 51 | build_args: 'c("--no-manual","--compact-vignettes=gs+qpdf")' 52 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | .Rproj.user 2 | .Rproj 3 | .Rhistory 4 | .Rdata 5 | .httr-oauth 6 | .DS_Store 7 | dev_files/ 8 | R/rsconnect/ 9 | inst/doc 10 | -------------------------------------------------------------------------------- /DESCRIPTION: -------------------------------------------------------------------------------- 1 | Package: multilandr 2 | Title: Landscape Analysis at Multiple Spatial Scales 3 | Version: 1.0.0.9000 4 | Authors@R: 5 | person("Pablo Yair", "Huais", , "pablo.huais@unc.edu.ar", role = c("aut", "cre", "cph"), 6 | comment = c(ORCID = "0000-0002-4062-0779")) 7 | Maintainer: Pablo Yair Huais 8 | Description: Provides a tidy workflow for landscape-scale analysis. 'multilandr' offers tools to generate landscapes at multiple spatial scales and compute landscape metrics, primarily using the 'landscapemetrics' package. It also features utility functions for plotting and analyzing multi-scale landscapes, exploring correlations between metrics, filtering landscapes based on specific conditions, generating landscape gradients for a given metric, and preparing datasets for further statistical analysis. Documentation about 'multilandr' is provided in an introductory vignette included in this package and in the paper by Huais (2024) ; see citation("multilandr") for details. 9 | License: GPL (>= 3) 10 | Encoding: UTF-8 11 | Roxygen: list(markdown = TRUE) 12 | RoxygenNote: 7.3.1 13 | Imports: 14 | terra (>= 1.7-71), 15 | GGally (>= 2.2.1), 16 | ggplot2 (>= 3.5.1), 17 | tidyterra (>= 0.6.0), 18 | gridExtra (>= 2.3), 19 | landscapemetrics (>= 2.1.1), 20 | sf (>= 1.0-16), 21 | methods (>= 4.3.0) 22 | Depends: 23 | R (>= 4.3.0) 24 | LazyData: true 25 | Suggests: 26 | knitr, 27 | parallel (>= 4.1.0), 28 | rmarkdown, 29 | testthat (>= 3.0.0) 30 | Collate: 31 | 'check_raster.R' 32 | 'classes.R' 33 | 'data.R' 34 | 'func_checks.R' 35 | 'generate_points.R' 36 | 'generate_points_checks.R' 37 | 'globals.R' 38 | 'methods.R' 39 | 'metrics_bind.R' 40 | 'metrics_corr.R' 41 | 'metrics_corr_checks.R' 42 | 'metrics_filter.R' 43 | 'metrics_filter_checks.R' 44 | 'metrics_gradient.R' 45 | 'metrics_gradient_checks.R' 46 | 'metrics_list.R' 47 | 'metrics_plots.R' 48 | 'metrics_scalogram.R' 49 | 'metrics_scalogram_checks.R' 50 | 'mland.R' 51 | 'mland_checks.R' 52 | 'mland_export_gis.R' 53 | 'mland_load.R' 54 | 'mland_metrics.R' 55 | 'mland_metrics_checks.R' 56 | 'mland_overlap.R' 57 | 'mland_overlap_checks.R' 58 | 'mland_plot.R' 59 | 'mland_plot_checks.R' 60 | 'mland_save.R' 61 | 'utils.R' 62 | Config/testthat/edition: 3 63 | VignetteBuilder: knitr 64 | URL: https://github.com/phuais/multilandr 65 | BugReports: https://github.com/phuais/multilandr/issues 66 | -------------------------------------------------------------------------------- /NAMESPACE: -------------------------------------------------------------------------------- 1 | # Generated by roxygen2: do not edit by hand 2 | 3 | export(check_raster) 4 | export(conditions) 5 | export(generate_points) 6 | export(metrics_bind) 7 | export(metrics_corr) 8 | export(metrics_filter) 9 | export(metrics_gradient) 10 | export(metrics_list) 11 | export(metrics_plots) 12 | export(metrics_scalogram) 13 | export(mland) 14 | export(mland_export_gis) 15 | export(mland_load) 16 | export(mland_metrics) 17 | export(mland_overlap) 18 | export(mland_plot) 19 | export(mland_save) 20 | exportClasses(MultiLand) 21 | exportClasses(MultiLandMetrics) 22 | exportMethods(show) 23 | importClassesFrom(terra,SpatVector) 24 | importFrom(methods,is) 25 | importFrom(methods,show) 26 | -------------------------------------------------------------------------------- /NEWS.md: -------------------------------------------------------------------------------- 1 | # multilandr (development version) 2 | 3 | # multilandr 1.0.0 4 | 5 | * Initial CRAN submission. 6 | -------------------------------------------------------------------------------- /R/check_raster.R: -------------------------------------------------------------------------------- 1 | #' Check input raster 2 | #' 3 | #' Checks the validity of raster layers to be inputted in [mland()], intended to represent land cover. The function directly calls 4 | #' [landscapemetrics::check_landscape()]. 5 | #' 6 | #' @param raster An object of class 'RasterLayer', 'RasterStack', 'RasterBrick', 'SpatRaster', 7 | #' or a list of raster objects (one of 'RasterLayer' or 'SpatRaster'). 8 | #' @param verbose Print warning messages in the console? Default is TRUE. 9 | #' 10 | #' @details Extracts basic information about the inputted raster: coordinate reference system (crs) - either "geographic", 11 | #' "projected", or NA, units of the 12 | #' coordinate reference system, class for the values of the inputted raster and the number of classes 13 | #' found in the raster. 14 | #' 15 | #' @return A data frame with relevant information about the inputted raster. 16 | #' 17 | #' @export 18 | check_raster <- function(raster, 19 | verbose = TRUE){ 20 | as.data.frame(landscapemetrics::check_landscape(raster, verbose)) 21 | } 22 | -------------------------------------------------------------------------------- /R/classes.R: -------------------------------------------------------------------------------- 1 | #' @importFrom methods is show 2 | #' @importClassesFrom terra SpatVector 3 | 4 | setClassUnion("null_chr", c("NULL", "character")) 5 | 6 | #' Class "MultiLand" 7 | #' 8 | #' Objects of class 'MultiLand' are created with the function [mland()], and holds 9 | #' relevant objects and information to be passed to other functions of the package. The slot 10 | #' `@buffers` holds an object of class 'SpatVector' with the buffers for each point 11 | #' contained in the slot `@points` and each radius defined in slot `@radii`. The slot 12 | #' `@buffers@data` holds a data.frame with the identification of each buffer (individualized by a 13 | #' point id and a radius value). 14 | #' 15 | #' If the slot `@on_the_fly` equals `FALSE`, the slot `@landscapes` holds the intersections (objects of class 'SpatRaster') between 16 | #' buffers and the raster layers inputted by the user when running [mland()]. Intersections 17 | #' between buffers and raster layers with discrete values (inputted in argument `raster` in [mland()]) are 18 | #' contained inside a list named 'lsm_rasters', whereas intersections between extra raster layers 19 | #' (inputted in argument `ext_rast_layer` in [mland()]) and buffers 20 | #' are contained inside a list named 'ext_rasters'. Each list ('lsm_rasters' and 'ext_rasters') contains a 21 | #' list with as many elements as previously inputted raster layers. Additionally, each element of 22 | #' this latter list holds an additional internal list, with as many elements as intersections (i.e. rasters generated by the intersections between buffers defined 23 | #' by each point and radius, and the raster layer). The name of each element of each internal list 24 | #' reveals the information related to a given intersection, with the following coding: "RasterLayerL-P-R" or 25 | #' "ExtRasterLayerL-P-R", where L is the 26 | #' given raster layer, P is the id of the point and R is the radius. For example, a plausible 27 | #' intersection may be named as "RasterLayer1-5-1500", indicating that this element holds a raster 28 | #' layer which is the result of the intersection between RasterLayer1 and the buffer around point 5 and 29 | #' radius 1500 m. 30 | #' 31 | #' If slot `@on_the_fly` equals `FALSE`, the slot `@landscapes` holds a list containing two named lists 32 | #' as 'lsm_rasters' and 'ext_rasters'. Each one contains a list with as many raster layers were initially 33 | #' inputted by the user when running [mland()] in arguments `rast_layer` and `ext_rast_layer`. 34 | #' This means that no intersections were 35 | #' made when creating the 'MultiLand' object. Intersections will be created "on the fly" when other functions of 36 | #' the package requires them. 37 | #' 38 | #' @slot call The call when function [mland()] was called. 39 | #' @slot idkey A unique identification id for the 'MultiLand' object. 40 | #' @slot crs_proj A string depicting the CRS of points layer. 41 | #' @slot points An object of class 'SpatVector'. Holds the points inputted by the user. 42 | #' @slot buffers An object of class 'SpatVector'. Holds the buffers layers. 43 | #' @slot site_ref String holding the name of the attribute that the user defined as 44 | #' the one that identifies individual points and is contained inside the layer of points. 45 | #' @slot radii Vector of numbers containing the radii that defined the creation of buffers. 46 | #' @slot n_layers Number of raster layers (defined in argument `raster` in [mland()]) from which i 47 | #' ntersections between were created (or will be if slot `@on_the_fly = TRUE`). 48 | #' @slot n_classes A numeric vector depicting the number of classes (raster values) per raster 49 | #' layer (defined in argument `raster` in [mland()]). 50 | #' @slot classes A data.frame depicting the classes (and classes names) for each rasterlayer 51 | #' (defined in argument `raster` in [mland()]). 52 | #' @slot on_the_fly A logical value indicating whether intersections between buffers and raster layers 53 | #' were created (FALSE) or not (TRUE). 54 | #' @slot landscapes If `on_the_fly = FALSE`, this slot holds the intersections between buffers and 55 | #' raster layers. Otherwise, if `on_the_fly = TRUE`, it holds the raw raster layers. 56 | #' @slot l_ref A data.frame relating each point and radius with a "row_id", equal to the position of 57 | #' its buffer in the slot `@buffers` and to the position of the intersection for each point/radius in 58 | #' the slot `@landscapes` (if `on_the_fly = TRUE`). 59 | #' @slot rast_names A list containing two data.frame with the names assigned by the user for the main raster layers 60 | #' and extra raster layers defined in argument `rast_layer` and `ext_rast_layer` in [mland()]. 61 | #' 62 | #' @examples 63 | #' # Shows information of object 'MultiLand' 64 | #' ernesdesign <- system.file("extdata", "ernesdesign.zip", package = "multilandr") 65 | #' ernesdesign <- mland_load(ernesdesign) 66 | #' ernesdesign 67 | #' @export 68 | setClass("MultiLand", 69 | 70 | slots = c( 71 | # call 72 | call = "call", 73 | 74 | # MultiLand id 75 | idkey = "numeric", 76 | 77 | # CRS proj 78 | crs_proj = "character", 79 | 80 | # number of layers 81 | n_layers = "numeric", 82 | 83 | # number of classes per layer, 84 | n_classes = "numeric", 85 | 86 | # classes per layer, 87 | classes = "data.frame", 88 | 89 | # points 90 | points = "SpatVector", 91 | 92 | # buffers 93 | buffers = "SpatVector", 94 | 95 | # on the fly? 96 | on_the_fly = "logical", 97 | 98 | # landscapes 99 | landscapes = "list", 100 | 101 | # main rasters and extra rasters names 102 | rast_names = "list", 103 | 104 | # data.frame reference 105 | l_ref = "data.frame", 106 | 107 | # sites reference 108 | site_ref = "null_chr", 109 | 110 | # radii 111 | radii = "numeric") 112 | ) 113 | 114 | #' Class 'MultiLandMetrics' 115 | #' 116 | #' Objects of class `MultiLandMetrics` are returned by [mland_metrics()]. It holds all the information 117 | #' relative to the metrics that were calculated by the parameters inputted by the user. This object 118 | #' class can be passed to functions [metrics_corr()], [metrics_plots()], [metrics_filter()], [metrics_gradient()] and 119 | #' [metrics_bind()] for further analyses. 120 | #' 121 | #' @slot call The call when function [mland_metrics()] was called. 122 | #' @slot idkey A unique identification id for the 'MultiLandMetrics' object. 123 | #' @slot crs_proj A string depicting the CRS of points layer. 124 | #' @slot n_layers Number of raster layers from which metrics were calculated. 125 | #' @slot rast_names A list with dataframes containing the names of the raster layers of the 126 | #' 'MultiLand' object the function [mland_metrics()] worked with. 127 | #' @slot classes A data.frame depicting the raster layers, classes and classes names from which 128 | #' metrics were calculated. 129 | #' @slot n_classes Numeric vector depicting the number of distinct classes per raster layer 130 | #' from which metrics were calculated. 131 | #' @slot points A data.frame containing points coordinates and other attributes. 132 | #' @slot n_points Number of points from which metrics were calculated. 133 | #' @slot site_names Logical. Whether points have associated site names or not. 134 | #' @slot radii Distinct radii from which metrics were calculated. 135 | #' @slot metrics A data.frame depicting the metrics that were calculated, classified by level. 136 | #' @slot data Main data.frame with the values of the metrics that were calculated for each 137 | #' point, radius, raster layers and other parameters pre-defined by the user. 138 | #' @slot ext_calcs A data.frame depicting the extra calculations that were made in given extra 139 | #' raster layers. 140 | #' 141 | #' @export 142 | #' 143 | #' @examples 144 | #' # Shows information of object 'MultiLandMetrics' 145 | #' ed_metrics 146 | #' otf_metrics 147 | setClass("MultiLandMetrics", 148 | 149 | slots = c( 150 | # call 151 | call = "call", 152 | 153 | # Multilandmetrics id 154 | idkey = "numeric", 155 | 156 | # CRS proj 157 | crs_proj = "character", 158 | 159 | # number of raster layers 160 | n_layers = "numeric", 161 | 162 | # raster layers names 163 | rast_names = "list", 164 | 165 | # classes 166 | classes = "data.frame", 167 | 168 | # number of classes per layer, 169 | n_classes = "numeric", 170 | 171 | # points 172 | points = "data.frame", 173 | 174 | # number of points 175 | n_points = "numeric", 176 | 177 | # site names 178 | site_names = "logical", 179 | 180 | # radii 181 | radii = "numeric", 182 | 183 | # metrics 184 | metrics = "data.frame", 185 | 186 | # extra calculations for extra rasters 187 | ext_calcs = "data.frame", 188 | 189 | # data frame of metric values 190 | data = "data.frame") 191 | ) 192 | -------------------------------------------------------------------------------- /R/data.R: -------------------------------------------------------------------------------- 1 | #' 'MultiLandMetrics' object 2 | #' 3 | #' An object of class 'MultiLandMetrics' generated with [mland_metrics()], for the purposes of package 4 | #' examples of the following functions: [metrics_filter()], [metrics_gradient()], 5 | #' [metrics_corr()], [metrics_plots()] and [metrics_bind()]. See 'MultiLand-class' 6 | #' for general information about these objects. 7 | #' 8 | #' The main internal object is a data.frame (accesible through `ed_metrics@data`) with information 9 | #' about the values of two landscape metrics: "pland" (percentage of landscape) and "ed" (edge density). 10 | #' 11 | #' The object was created from the MultiLand object named "ernesdesign", which 12 | #' received two raster layers from a small portion of the ecoregion "El Chaco" as main inputs. The main rasterlayer 13 | #' was provided by the project "MapBiomas Chaco" for the year 2000. 14 | #' The extra rasterlayer contained the NDVI values of cells within the same extent of the main rasterlayer, and was provided by Landsat. 15 | #' 16 | #' @seealso See the examples sections of [mland_metrics()] and [mland()] 17 | #' for more context. 18 | #' 19 | #' @references 20 | #' Project MapBiomas Chaco – Collection 4.0 of annual land cover and land use maps, 21 | #' accessed during July 2022 through the following link: \href{https://chaco.mapbiomas.org/}{MapBiomas Chaco} 22 | #' 23 | #' Landsat-5 image courtesy of the U.S. Geological Survey 24 | #' 25 | "ed_metrics" 26 | 27 | #' 'MultiLandMetrics' object 28 | #' 29 | #' An object of class 'MultiLandMetrics' generated with [mland_metrics()], for the purposes of package 30 | #' examples of the following functions: [metrics_filter()], [metrics_gradient()], 31 | #' [metrics_corr()], [metrics_plots()] and [metrics_bind()]. See 'MultiLand-class' for general 32 | #' information about these objects. 33 | #' 34 | #' The main internal object is a data.frame (accesible through `otf_metrics@data`) with information about the values of two landscape metrics: 35 | #' "pland" (percentage of landscape) and "np" (number of patches). 36 | #' 37 | #' The object was created from the MultiLand object named "otf_design", which 38 | #' received a raster layer from a small portion of the ecoregion "El Chaco" as main input. 39 | #' The rasterlayer was provided by the project "MapBiomas Chaco" for the year 2000. 40 | #' 41 | #' @seealso See the examples sections of [mland_metrics()] and [mland()] 42 | #' for more context. 43 | #' 44 | #' #' @references 45 | #' Project MapBiomas Chaco – Collection 4.0 of annual land cover and land use maps, 46 | #' accessed during July 2022 through the following link: \href{https://chaco.mapbiomas.org/}{MapBiomas Chaco} 47 | "otf_metrics" 48 | -------------------------------------------------------------------------------- /R/func_checks.R: -------------------------------------------------------------------------------- 1 | .chk_site_ref <- function(messages, what, x, site_ref, points){ 2 | # site_ref 3 | if(!is.logical(site_ref)){ 4 | messages <- append(messages, 5 | "- argument 'site_ref' must be logical. The argument was ignored.") 6 | what <- append(what, 1) 7 | site_ref <- FALSE 8 | } else { 9 | if(site_ref){ 10 | if(is.null(x@site_ref)){ 11 | messages <- append(messages, 12 | "- argument 'site_ref' was TRUE, but x does not declare the same. Set site_ref to FALSE or get an x object with site_ref equal to TRUE.") 13 | what <- append(what, 2) 14 | } else { 15 | if(!is.null(points)){ 16 | if(!all(unique(points) %in% x@points[, x@site_ref])){ 17 | messages <- append(messages, 18 | "- one or more required points were not found in x. Mispelled?") 19 | what <- append(what, 2) 20 | } 21 | } 22 | } 23 | } else { 24 | if(!is.null(points)){ 25 | if(!all(unique(points) %in% 1:length(x@points))){ 26 | messages <- append(messages, 27 | "- one or more required points were not found in x. Mispelled?") 28 | what <- append(what, 2) 29 | } 30 | } 31 | } 32 | } 33 | 34 | out <- list(messages, what, site_ref) 35 | return(out) 36 | } 37 | 38 | .chk_raster <- function(messages, what, raster, arg_name){ 39 | if(!is.null(raster)){ 40 | if(!class(raster) %in% c("RasterLayer", "RasterStack", "RasterBrick", "SpatRaster", "list")){ 41 | messages <- append(messages, paste0("- argument '", arg_name, "' must be a rasterlayer or a 42 | list of raster layers. See ?mland")) 43 | what <- append(what, 2) 44 | } 45 | if(is(raster, "list")){ 46 | cl <- vector("logical", length(raster)) 47 | for(i in 1:length(raster)){ cl[i] <- class(raster[[i]]) %in% c("RasterLayer", "SpatRaster") } 48 | if(!all(cl)){ 49 | messages <- append(messages, paste0("- if provided a list in argument '", arg_name, "', this must be a 50 | list of objects of raster layers. See ?mland")) 51 | what <- append(what, 2) 52 | } 53 | } 54 | } else { 55 | raster <- vector("list") 56 | } 57 | 58 | out <- list(messages, what, raster) 59 | return(out) 60 | } 61 | 62 | .chk_radii <- function(messages, what, x, radii){ 63 | if(!is.null(radii)){ 64 | if(!is.numeric(radii) | !all(radii > 0)){ 65 | messages <- append(messages, "- argument 'radii' must be a vector of positive numbers.") 66 | what <- append(what, 2) 67 | } else { 68 | if(!all(radii %in% x@radii)){ 69 | messages <- append(messages, "- one or more defined radii were not found in x definition.") 70 | what <- append(what, 2) 71 | } 72 | } 73 | } 74 | 75 | out <- list(messages, what) 76 | return(out) 77 | } 78 | 79 | .chk_points <- function(messages, what, x, points){ 80 | force_sitename <- F 81 | if(!is.null(points)){ 82 | for(i in 1:length(points)){ 83 | if(is.numeric(points[i])){ 84 | if(!points[i] %in% terra::values(x@points)[, "id"]){ 85 | messages <- append(messages, 86 | paste0("- could not found point ", points[i], " in x points data 87 | definition. Mispelled?")) 88 | what <- append(what, 2) 89 | } 90 | } else { 91 | if(is.character(points[i])){ 92 | if(!is.null(x@site_ref)){ 93 | if(!points[i] %in% terra::values(x@points)[, x@site_ref]){ 94 | messages <- append(messages, 95 | paste0("- could not found site \"", points[i], "\" in x points data 96 | definition. Mispelled?")) 97 | what <- append(what, 2) 98 | } else { 99 | points[i] <- terra::values(x@points)[terra::values(x@points)[, x@site_ref] == points[i], "id"] 100 | force_sitename <- T 101 | } 102 | } else { 103 | messages <- append(messages, 104 | "- site names were declared in argument 'points' but no names were 105 | found in 'x'. Declare point ids or generate an 'x' object that 106 | includes site names.") 107 | what <- append(what, 2) 108 | break 109 | } 110 | } else { 111 | messages <- append(messages, 112 | "- If not NULL, argument 'points' must be a numeric or a character 113 | vector.") 114 | what <- append(what, 2) 115 | break 116 | } 117 | } 118 | } 119 | } 120 | 121 | out <- list(messages, what, points, force_sitename) 122 | return(out) 123 | } 124 | 125 | .chk_points2 <- function(messages, what, x, points){ 126 | if(!is.null(points)){ 127 | for(i in 1:length(points)){ 128 | if(is.numeric(points[i])){ 129 | if(!points[i] %in% x@points$id){ 130 | messages <- append(messages, 131 | paste0("- could not found point ", points[i], " in x. Mispelled?")) 132 | what <- append(what, 2) 133 | } 134 | } else { 135 | if(is.character(points[i])){ 136 | if(x@site_names){ 137 | if(!points[i] %in% x@points$name){ 138 | messages <- append(messages, 139 | paste0("- could not found site \"", points[i], "\" in x. Mispelled?")) 140 | what <- append(what, 2) 141 | } else { 142 | points[i] <- x@points[x@points$name == points[i], ]$id 143 | } 144 | } else { 145 | messages <- append(messages, 146 | "- site names were declared in argument 'points' but no names were 147 | found in 'x'.") 148 | what <- append(what, 2) 149 | break 150 | } 151 | } else { 152 | messages <- append(messages, 153 | "- if not NULL, argument 'points' must be a numeric or a character 154 | vector.") 155 | what <- append(what, 2) 156 | break 157 | } 158 | } 159 | } 160 | } 161 | 162 | out <- list(messages, what, points) 163 | return(out) 164 | } 165 | 166 | .chk_title <- function(messages, what, x, title){ 167 | # title 168 | if(!title %in% c("id", "sitename")){ 169 | messages <- append(messages, 170 | "- argument 'title' must be one of the following: \"id\" or \"sitename\". Default 171 | \"id\" was taken.") 172 | what <- append(what, 1) 173 | title <- "id" 174 | } else { 175 | if(title == "sitename"){ 176 | if(is.null(x@site_ref)){ 177 | messages <- append(messages, 178 | "- if argument 'title' equals \"sitename\", x@site_ref must be TRUE. Default 179 | \"id\" was taken.") 180 | what <- append(what, 1) 181 | title <- "id" 182 | } 183 | } 184 | } 185 | 186 | out <- list(messages, what, title) 187 | return(out) 188 | } 189 | 190 | .chk_classnames <- function(messages, what, show_class_names){ 191 | 192 | if(!is.logical(show_class_names)){ 193 | messages <- append(messages, 194 | "- argument 'show_class_names' must be logical. Default FALSE was taken.") 195 | what <- append(what, 1) 196 | show_class_names <- FALSE 197 | } 198 | 199 | out <- list(messages, what, show_class_names) 200 | return(out) 201 | } 202 | 203 | .chk_progress <- function(messages, what, progress){ 204 | if(!is.logical(progress)){ 205 | messages <- append(messages, "- argument 'progress' was taken as TRUE.") 206 | what <- append(what, 1) 207 | progress <- TRUE 208 | } 209 | 210 | out <- list(messages, what, progress) 211 | return(out) 212 | } 213 | 214 | -------------------------------------------------------------------------------- /R/generate_points_checks.R: -------------------------------------------------------------------------------- 1 | .generate_points_chk_args <- function(){ 2 | 3 | messages <- NULL 4 | what <- NULL 5 | 6 | # Raster 7 | if(!class(raster) %in% c("RasterLayer", "RasterStack", "RasterBrick", "SpatRaster")){ 8 | messages <- append(messages, 9 | "- argument 'raster' must be a rasterlayer. See ?generate_coods") 10 | what <- append(what, 2) 11 | } 12 | 13 | # Padding 14 | if(any(!is.numeric(padding), padding < 0)){ 15 | messages <- append(messages, 16 | "- argument 'padding' must a positive number. See ?generate_coods") 17 | what <- append(what, 2) 18 | } 19 | 20 | # approach 21 | if(!approach %in% c("grid", "random", "patch")){ 22 | messages <- append(messages, 23 | "- argument 'approach' must be \"grid\", \"random\" or \"patch\".") 24 | what <- append(what, 2) 25 | } else { 26 | if(approach == "random"){ 27 | # n 28 | if(!is.null(n)){ 29 | if(!is.positive.wholenumber(n)){ 30 | messages <- append(messages, 31 | "- argument 'n' must be a positive whole number.") 32 | what <- append(what, 2) 33 | } 34 | } else { 35 | messages <- append(messages, 36 | "- argument 'n' must be a positive whole number.") 37 | what <- append(what, 2) 38 | } 39 | 40 | # try 41 | if(!is.null(try)){ 42 | if(!is.positive.wholenumber(try)){ 43 | messages <- append(messages, 44 | "- argument 'try' must be a positive integer.") 45 | what <- append(what, 2) 46 | } 47 | } 48 | 49 | # values 50 | if(!is.null(values)){ 51 | if(!is.numeric(values)){ 52 | messages <- append(messages, 53 | "- argument 'values' must be a numeric vector.") 54 | what <- append(what, 2) 55 | } 56 | if(class(raster) %in% c("RasterStack", "RasterBrick")){ 57 | messages <- append(messages, 58 | "- if specific values are defined, the input cannot be an object of class 59 | 'RasterStack' or 'RasterBrick'.") 60 | what <- append(what, 2) 61 | } 62 | } 63 | 64 | # trim 65 | if(!is.logical(trim)){ 66 | messages <- append(messages, 67 | "- argument 'trim' must be logical. Default TRUE was taken.") 68 | what <- append(what, 1) 69 | trim <- TRUE 70 | } 71 | 72 | # attempts 73 | if(!is.positive.wholenumber(attempts)){ 74 | messages <- append(messages, 75 | "- argument 'attempts' must a postive whole number. Default 10 was taken.") 76 | what <- append(what, 1) 77 | attempts <- 10 78 | } 79 | 80 | # offset 81 | if(!is.logical(offset)){ 82 | messages <- append(messages, 83 | "- argument 'offset' must be logical. Default FALSE was taken.") 84 | what <- append(what, 1) 85 | offset <- FALSE 86 | } 87 | } 88 | 89 | if(approach == "patch"){ 90 | # patch_conditions 91 | if(!is.list(patch_conditions)){ 92 | messages <- append(messages, 93 | "- argument 'patch_conditions' must be a list.") 94 | what <- append(what, 2) 95 | } else { 96 | for(i in 1:length(patch_conditions)){ 97 | if(!is.list(patch_conditions[[i]])){ 98 | messages <- append(messages, 99 | paste0("- patch condition number ", i, " is not a list. Each condition must 100 | be a list. See ?generate_points")) 101 | what <- append(what, 2) 102 | } else { 103 | if(length(patch_conditions[[i]]) != 4){ 104 | messages <- append(messages, 105 | paste0("- patch_condition number ", i, " must be a list with four elements: 106 | c(class, metric, min. value, max. value). 107 | More details in ?generate_points")) 108 | what <- append(what, 2) 109 | } else { 110 | 111 | # Metric 112 | if(length(patch_conditions[[i]][[2]]) > 1){ 113 | messages <- append(messages, 114 | "- only one metric can be defined per patch condition.") 115 | what <- append(what, 2) 116 | } else { 117 | met <- metrics_list(level = "patch")$metric 118 | if(!patch_conditions[[i]][[2]] %in% met){ 119 | messages <- append(messages, 120 | paste0("- metric \"", patch_conditions[[i]][[2]], "\" from 121 | patch condition ", i, " was not found as an available 122 | metric to be calculated. See metrics_list(level = \"patch\"). 123 | Mispelled?")) 124 | what <- append(what, 2) 125 | } 126 | } 127 | 128 | # Min. value 129 | if(is.na(suppressWarnings(as.numeric(patch_conditions[[i]][[3]])))){ 130 | messages <- append(messages, 131 | paste0("- min. value (3rd element) from patch condition ", i, 132 | " must be numeric.")) 133 | what <- append(what, 2) 134 | } 135 | # Max. value 136 | if(is.na(suppressWarnings(as.numeric(patch_conditions[[i]][[4]])))){ 137 | messages <- append(messages, 138 | paste0("- max. value (4th element) from patch condition ", i, 139 | " must be numeric.")) 140 | what <- append(what, 2) 141 | } 142 | } 143 | } 144 | } 145 | } 146 | } else { 147 | if(!is.null(patch_conditions)){ 148 | messages <- append(messages,"- patch conditions were ignored.") 149 | what <- append(what, 2) 150 | } 151 | } 152 | } 153 | 154 | # distance 155 | if(!is.null(distance)){ 156 | if(!is.positive.numeric(distance)){ 157 | messages <- append(messages, 158 | "- argument 'distance' must a postive number.") 159 | what <- append(what, 2) 160 | } 161 | } else { 162 | if(approach == "grid"){ 163 | messages <- append(messages, 164 | "- if approach = 'grid', argument 'distance' must a postive number.") 165 | what <- append(what, 2) 166 | } else { 167 | distance <- 0 168 | } 169 | } 170 | 171 | # parallel 172 | if(!is.logical(parallel)){ 173 | messages <- append(messages, 174 | "- argument 'parallel' must be logical. Default FALSE was taken.") 175 | what <- append(what, 1) 176 | parallel <- FALSE 177 | } 178 | 179 | # closest cell 180 | if(!is.logical(closest_cell)){ 181 | messages <- append(messages, 182 | "- argument 'closest_cell' must be logical. Default FALSE was taken.") 183 | what <- append(what, 1) 184 | closest_cell <- FALSE 185 | } 186 | 187 | # Progress 188 | chk_progress <- .chk_progress(messages, what, progress) 189 | messages <- chk_progress[[1]] 190 | what <- chk_progress[[2]] 191 | 192 | warnings <- messages[which(what == 1)] 193 | errors <- messages[which(what == 2)] 194 | 195 | out <- list(warnings = warnings, 196 | errors = errors, 197 | trim = trim, 198 | attempts = attempts, 199 | offset = offset, 200 | parallel = parallel, 201 | closest_cell = closest_cell, 202 | distance = distance, 203 | progress = progress) 204 | return(out) 205 | } 206 | -------------------------------------------------------------------------------- /R/globals.R: -------------------------------------------------------------------------------- 1 | utils::globalVariables(c("x", "class_metrics", "points", "total_rows_pp", "radii", "n_classes", 2 | "classes_tmp", "df_reference", "absence_values", "values", "raster", 3 | "approach", "n", "patch_conditions", "lay", "row_id", "r", "data", 4 | "na.exclude", "level", "name", "type", "metric", "ext_calc", "on_the_fly", 5 | "ext_raster", "hcl.colors", "method", "class_names", "c_level", "l_level", 6 | "reshape", "y", "ext_calc_ref", "txtProgressBar", "runif", "res", "dist", 7 | "setTxtProgressBar", "aggregate", "unzip", "new", "rasters_classes_tab", 8 | "askYesNo", "arg_name", "classes", "value", "progress", "update", 9 | "cutpoints", "breaks", "points_layer", "rast_layer", "ext_rast_layer", 10 | "padding", "random", "show_class_names", "radius", "rasterlayer", 11 | "site", "towide")) 12 | -------------------------------------------------------------------------------- /R/methods.R: -------------------------------------------------------------------------------- 1 | #' @include classes.R 2 | #NULL 3 | 4 | if(!isGeneric("show")) 5 | methods::setGeneric("show", function(object) standardGeneric("show")) 6 | 7 | #' Show 'MultiLand' object 8 | #' 9 | #' @param object Prints relevant information about a 'MultiLand' object. 10 | #' 11 | #' @return No return value, called for side effects. 12 | #' 13 | #' @export 14 | methods::setMethod(f = "show", signature = "MultiLand", 15 | definition = 16 | function(object){ 17 | cat("class : MultiLand\n") 18 | cat("On the fly :", object@on_the_fly, "\n") 19 | cat("Raster layers :", object@n_layers, "\n") 20 | if(length(object@n_classes) > 0){ 21 | cat(" n classes :", object@n_classes, "\n") 22 | } else { 23 | cat(" n classes : -\n") 24 | } 25 | cat("Ext. raster layers:", length(object@landscapes[[2]]), "\n") 26 | cat("n points :", nrow(object@points), "\n") 27 | if(!is.null(object@site_ref)){ 28 | cat("Site reference : \"", object@site_ref, "\"\n", sep = "") 29 | } else { 30 | cat("Site reference : -\n") 31 | } 32 | if(length(object@radii) > 6){ 33 | cat("Radii (m) :", object@radii[1:5], "...", object@radii[length(object@radii)], "\n") 34 | } else { 35 | cat("Radii (m) :", object@radii, "\n") 36 | } 37 | } 38 | ) 39 | 40 | #' Show 'MultiLandMetrics' object 41 | #' 42 | #' @param object Prints relevant information about a 'MultiLandMetrics' object. 43 | #' 44 | #' @return No return value, called for side effects. 45 | #' 46 | #' @export 47 | methods::setMethod(f = "show", signature = "MultiLandMetrics", 48 | definition = 49 | function(object){ 50 | cat("class : MultiLandMetrics\n") 51 | cat("Number of layers :", object@n_layers, "\n") 52 | cat("Number of classes:", object@n_classes, "\n") 53 | cat("Number of points :", object@n_points, "\n") 54 | cat("Radii (m) :", show_sample(object@radii, limit = 5), "\n") 55 | cat("Metrics\n Landscape-level:", 56 | show_sample(unique(object@metrics[object@metrics$level == "landscape", "metric"]), 57 | limit = 5), 58 | "\n Class-level :", 59 | show_sample(unique(object@metrics[object@metrics$level == "class", "metric"]), 60 | limit = 5), 61 | "\n Patch-level :", 62 | show_sample(unique(object@metrics[object@metrics$level == "patch", "metric"]), 63 | limit = 5), "\n") 64 | cat("Extra calcs. :", show_sample(unique(object@ext_calcs$fun), limit = 5), "\n") 65 | } 66 | ) 67 | -------------------------------------------------------------------------------- /R/metrics_bind.R: -------------------------------------------------------------------------------- 1 | .metrics_bind_chk_args <- function(){ 2 | 3 | messages <- NULL 4 | what <- NULL 5 | 6 | # Data frame 7 | if(!is.data.frame(data)){ 8 | messages <- append(messages, 9 | "- argument 'data' must be a data.frame.") 10 | what <- append(what, 2) 11 | } else { 12 | if(!any(c("point_id", "site") %in% colnames(data))){ 13 | messages <- append(messages, 14 | "- argument 'data' must be a data.frame with at least one of the following 15 | column names as unique identifiers for distinct sites: \"site\" or \"point_id\".") 16 | what <- append(what, 2) 17 | } else { 18 | if("point_id" %in% colnames(data)){ 19 | if(!all(sort(unique(data$point_id)) == sort(unique(x@data$point_id)))){ 20 | messages <- append(messages, 21 | "- unique values for column \"point_id\" do not match the corresponding 22 | values in x@data$point_id. These site identifiers should match. 23 | See ?metrics_bind") 24 | what <- append(what, 2) 25 | } 26 | } 27 | if("site" %in% colnames(data)){ 28 | if(!all(sort(unique(data$site)) == sort(unique(x@data$site)))){ 29 | messages <- append(messages, 30 | "- unique values for column \"site\" do not match the corresponding 31 | values in x@data$site. These site identifiers should match. 32 | See ?metrics_bind") 33 | what <- append(what, 2) 34 | } 35 | } 36 | } 37 | } 38 | 39 | # Class names 40 | chk_classnames <- .chk_classnames(messages, what, show_class_names) 41 | messages <- chk_classnames[[1]] 42 | what <- chk_classnames[[2]] 43 | show_class_names <- chk_classnames[[3]] 44 | 45 | warnings <- messages[which(what == 1)] 46 | errors <- messages[which(what == 2)] 47 | 48 | out <- list(warnings = warnings, 49 | errors = errors, 50 | show_class_names = show_class_names) 51 | 52 | return(out) 53 | } 54 | 55 | #' Metric's data preparation 56 | #' 57 | #' Merge data.frame with metric's values with a data.frame with other data. 58 | #' 59 | #' @inheritParams metrics_corr 60 | #' @param data A data.frame with data from each sampling point/site. See Details. 61 | #' @param raster,ext_raster,classes,radii,l_level,c_level Parameters to subset data.frame containing the 62 | #' metrics values. See Details. 63 | #' @param show_class_names Logical. If TRUE, classes names will be returned as the names of the classes 64 | #' previously provided (if so) when `x` was generated. Default FALSE. 65 | #' 66 | #' @details Merges data.frame with metrics values, contained in an object of 67 | #' class 'MultiLandMetrics' (returned by [mland_metrics()]) with a data.frame with other data for each 68 | #' site. In this way, the returned data.frame will be prepared for later statistical or 69 | #' visual analyses. The data.frame provided in `data` must have a column named "site" or "point_id", 70 | #' containing unique identifiers for each sampling site, which must match with the identifiers 71 | #' present in the data.frame contained in `x` (i.e. data.frame with metrics values for each site). 72 | #' If "site", the function will assume that the site names are provided as identifiers. If "point_id", 73 | #' the function will assume that point ids are being provided. In any case, these identifiers must 74 | #' match the site identifiers in `x`. 75 | #' 76 | #' Argument `raster`, `ext_raster`, `classes`, `radii`, `l_level` and `c_level` can be defined to 77 | #' subset the data.frame contained in `x`. In each one of these, an all-positive or an 78 | #' all-negative vector can be passed, whether to include (all-postive) or exclude (all-negative) 79 | #' the elements to be taken into account for the subsetting: 80 | #' * rasterlayers: a numeric vector with the number of the raster layers to be included/excluded. 81 | #' For example: `c(1, 2, 4)` to include raster layers 1, 2 and 4; `c(-2, -3)` to exclude raster layers 2 82 | #' and 3. 83 | #' * classes: must be a list with as many elements as defined raster layers in argument 84 | #' `rasterlayers`. Each element of the list must be a numeric vector (classes identities) with the 85 | #' classes to be included/excluded. If provided a character vector, [metrics_bind()] assumes that 86 | #' classes names are provided. For example, for the case with 2 raster layers: 87 | #' `list(c(3, 20, 35), c("Forest", "Crops"))` would include classes 3, 20 and 35 from rasterl ayer 1 88 | #' and classes "Forest" and "Crops" for raster layer 2. For the case of a unique rasterlayer, there 89 | #' is no need to input a list. For example, for the case of a unique raster layer and the 90 | #' exclusion of some classes: `c(-5, -10, -15)` to exclude classes 5, 10 and 15 of 91 | #' the unique raster layer; `c("-Forest", "-Grassland")` to exclude classes "Forest" and "Grassland". 92 | #' Note the "-" before each class name to indicate the exclusion of the classes. 93 | #' * radii: a numeric vector to include/exclude particular radii. For example: `c(1000, 2000)` to 94 | #' include only radii of 1000 and 2000 m; `c(-500, -1500)` to exclude radii of 500 and 1500 m. 95 | #' * c_level: character vector with the class-level metrics to be included/excluded from 96 | #' the analysis. For example: `c("np", "pland")` will include only the metrics "number of patches" 97 | #' ("np") and "percentage of the landscape" ("pland") in the analysis, whereas `c("-np", "-pland")` 98 | #' will exclude them. Note the "-" before each metric name to indicate the exclusion of the 99 | #' metrics. 100 | #' * l_level: character vector with the landscape-level metrics to be included/excluded from 101 | #' the analysis. Extra calculations for extra raster layers are considered as landscape-level metrics, 102 | #' and must be provided as "fun_" + the name of the function. 103 | #' 104 | #' @return A data.frame equal to sampling data provided in `data` but with additional columns 105 | #' containing the values of the metrics for each sampling site. 106 | #' 107 | #' @seealso [mland_metrics()] 108 | #' 109 | #' @export 110 | #' 111 | #' @examples 112 | #' # Get sites names from ed_metrics and creates ad-hoc data.frame with random values of 113 | #' # "richness" (the response variable). Only for the purpose of this example 114 | #' sites <- ed_metrics@points$name 115 | #' sampling_data <- data.frame(site = rep(sites, each = 10), 116 | #' richness = sample(1:500, 150)) 117 | #' 118 | #' # With no filters, all columns with all metrics at all spatial scales are added to 119 | #' # the sampling data 120 | #' new_data <- metrics_bind(ed_metrics, sampling_data) 121 | #' 122 | #' # Subset for metrics of class "Forest", radius 5000 and metric "pland" 123 | #' new_data <- metrics_bind(ed_metrics, sampling_data, show_class_names = TRUE, 124 | #' classes = "Forest", radii = 3000, c_level = "pland") 125 | #' 126 | #' # In this format, the data.frame can be passed to a fitting model 127 | #' fit <- lm(richness ~ r1_Forest_pland_3000, data = new_data) 128 | metrics_bind <- function(x, 129 | data, 130 | raster = NULL, 131 | classes = NULL, 132 | radii = NULL, 133 | c_level = NULL, 134 | l_level = NULL, 135 | ext_raster = NULL, 136 | show_class_names = FALSE){ 137 | 138 | if(!is(x, "MultiLandMetrics")) stop("x must be an object of class 'MultiLandMetrics'.") 139 | environment(.metrics_bind_chk_args) <- environment() 140 | chk <- .metrics_bind_chk_args() 141 | if(length(chk[[1]]) > 0) 142 | for(w in 1:length(chk[[1]])){ 143 | warning(strwrap(chk[[1]], prefix = "\n", initial = ""), call. = FALSE) 144 | } 145 | if(length(chk[[2]]) > 0){ 146 | errors <- chk[[2]] 147 | stop(strwrap(errors, prefix = "\n", initial = "\n")) 148 | } else { 149 | objs <- names(chk) 150 | for(i in 3:length(chk)){ assign(objs[i], chk[[i]]) } 151 | } 152 | 153 | towide <- T 154 | environment(.pair_subsets) <- environment() 155 | df <- .pair_subsets() 156 | new_df_wide <- df[[1]] 157 | out <- merge(data, new_df_wide) 158 | cols <- colnames(out)[!colnames(out) %in% c("point_id", "site")] 159 | out <- out[, c("point_id", "site", cols)] 160 | return(out) 161 | } 162 | -------------------------------------------------------------------------------- /R/metrics_corr_checks.R: -------------------------------------------------------------------------------- 1 | .metrics_corr_chk_args <- function(...){ 2 | 3 | messages <- NULL 4 | what <- NULL 5 | 6 | if(!method %in% c("pearson", "spearman", "kendall")){ 7 | messages <- append(messages, 8 | "- argument 'method' must be one of the following: \"pearson\", \"spearman\" or 9 | \"kendall\".") 10 | what <- append(what, 2) 11 | } else { 12 | if(!is.null(fun)){ 13 | if(!exists(fun)){ 14 | messages <- append(messages, 15 | paste0("- could not find a function named \"", fun, "\" in the current 16 | environment. Mispelled?")) 17 | what <- append(what, 2) 18 | fun <- NULL 19 | } else { 20 | args <- list(1:5, 1:5, ...) 21 | cor_test <- tryCatch(do.call(fun, args), 22 | error = c) 23 | bad <- F 24 | if(is.list(cor_test)) bad <- T 25 | if(is.numeric(cor_test)){ 26 | if(length(cor_test) != 1) bad <- T 27 | } else { 28 | bad <- T 29 | } 30 | if(bad){ 31 | messages <- append(messages, 32 | "- function provided in argument 'fun' was not defined properly. 33 | See ?metrics_corr") 34 | what <- append(what, 2) 35 | fun <- NULL 36 | } 37 | } 38 | } 39 | if(!is.null(fun)){ 40 | message(strwrap("- a user-defined function was provided through argument 'fun'. 41 | Argument 'method' was ignored.", prefix = "\n", initial = "\n")) 42 | } 43 | } 44 | 45 | if(!is.logical(show_class_names)){ 46 | messages <- append(messages, 47 | "- argument 'show_class_names' must be logical. Default FALSE was taken.") 48 | what <- append(what, 1) 49 | show_class_names <- FALSE 50 | } 51 | 52 | # Class names 53 | chk_classnames <- .chk_classnames(messages, what, show_class_names) 54 | messages <- chk_classnames[[1]] 55 | what <- chk_classnames[[2]] 56 | show_class_names <- chk_classnames[[3]] 57 | 58 | if(!display %in% c("radii", "rl", "both")){ 59 | messages <- append(messages, 60 | "- argument 'display' must be one of the following: \"radii\", \"rl\" or \"both\". 61 | Default \"radii\" was taken.") 62 | what <- append(what, 1) 63 | display <- "radii" 64 | } 65 | 66 | warnings <- messages[which(what == 1)] 67 | errors <- messages[which(what == 2)] 68 | 69 | out <- list(warnings = warnings, 70 | errors = errors, 71 | fun = fun, 72 | show_class_names = show_class_names, 73 | display = display) 74 | 75 | return(out) 76 | } 77 | 78 | .metrics_plots_chk_args <- function(){ 79 | 80 | messages <- NULL 81 | what <- NULL 82 | 83 | if(!is.logical(upper)){ 84 | messages <- append(messages, 85 | "- argument 'upper' must be logical. Default TRUE was taken.") 86 | what <- append(what, 1) 87 | upper <- TRUE 88 | } 89 | 90 | if(!is.logical(diag)){ 91 | messages <- append(messages, 92 | "- argument 'diag' must be logical. Default TRUE was taken.") 93 | what <- append(what, 1) 94 | diag <- TRUE 95 | } 96 | 97 | if(!is.logical(smooth)){ 98 | messages <- append(messages, 99 | "- argument 'smooth' must be logical. Default TRUE was taken.") 100 | what <- append(what, 1) 101 | smooth <- TRUE 102 | } 103 | 104 | # points style 105 | args <- list(shape = 21, size = 2, col = "black", fill = "white", alpha = 1) 106 | if(!all(names(args) %in% names(st_points))){ 107 | for(i in 1:5){ 108 | if(!names(args)[i] %in% names(st_points)){ 109 | st_points <- append(st_points, args[i]) 110 | names(st_points)[length(st_points)] <- names(args)[i] 111 | } 112 | } 113 | } 114 | 115 | # buffers style 116 | args <- list(lty = 1, lwd = 1, col = "black", alpha = 1) 117 | if(!all(names(args) %in% names(st_lines))){ 118 | for(i in 1:5){ 119 | if(!names(args)[i] %in% names(st_lines)){ 120 | st_lines <- append(st_lines, args[i]) 121 | names(st_lines)[length(st_lines)] <- names(args)[i] 122 | } 123 | } 124 | } 125 | 126 | warnings <- messages[which(what == 1)] 127 | errors <- messages[which(what == 2)] 128 | 129 | out <- list(warnings = warnings, 130 | errors = errors, 131 | upper = upper, 132 | diag = diag, 133 | smooth = smooth, 134 | st_points = st_points, 135 | st_lines = st_lines) 136 | 137 | return(out) 138 | } 139 | -------------------------------------------------------------------------------- /R/metrics_gradient.R: -------------------------------------------------------------------------------- 1 | #' Generates optimized metrics gradient 2 | #' 3 | #' Selects a set of points whose associated landscapes comprise an optimized gradient for a given landscape metric. 4 | #' 5 | #' @param x An object of class 'MultiLandMetrics' generated with [mland_metrics()]. 6 | #' @param rasterlayer The raster layer to be considered. If 7 | #' an extra raster layer must be specified, the string "ext" must precede the raster layer number 8 | #' (e.g. "ext1", "ext2") 9 | #' @param class The class to be considered, as a number or as a string with the name of the class. 10 | #' @param radius The radius to be considered. 11 | #' @param metric The metric to be considered. Metrics as extra calculations for extra raster layers must be 12 | #' provided as "fun_" + the name of the function. 13 | #' @param n The number of points that will comprise the gradient. See Details. 14 | #' @param cutpoints A sequence of numbers that will serve as numeric approximations to select the 15 | #' points that will comprise the gradient. See Details. 16 | #' @param breaks A unique number with the number of breaks that will generate the cutpoints for the 17 | #' specified metric values. Default is 10. See Details. 18 | #' @param random Logical. If TRUE, random points will be selected. 19 | #' @param output One of the following: "MLM" to return an updated version of the 'MultiLandMetrics' object provided in `x` (default), 20 | #' "spatial" to return a 'SpatVector' with the points 21 | #' of the selected landscapes, "data" to return a data.frame with the metric values information or "coords" 22 | #' to return a data.frame with geographical information of the selected points. 23 | #' 24 | #' @details Selects a subset of landscapes that overall will 25 | #' generate an optimized gradient of values for a given landscape metric of a specified raster layer, 26 | #' class and radius. One can define a gradient as optimized if 27 | #' its values fulfill to cover a good range of values between a minimum and a maximum value. The 28 | #' final gradient will comprise the number of points specified in argument `n`. Note that 29 | #' only one landscape metric can be specified at a time. 30 | #' 31 | #' The algorithm will select those points whose associated landscapes present values for the specified landscape metric that are 32 | #' the most close to the specified `cutpoints`. Alternatively, the user can provide a number of 33 | #' `breaks` from which the sequence of cutpoints will be generated. If both arguments are specified, 34 | #' the function will consider the values inputted in `cutpoints`. If both arguments are NULL, the 35 | #' algorithm will simply select `n` random points. 36 | #' 37 | #' @return 38 | #' A 'MultiLandMetrics' if `output = "MLM"`, a 'SpatVector' if `output = "spatial"`, 39 | #' a data.frame if `output = "data"` or a data.frame with geographical information of the points if `output = "coords"`. 40 | #' 41 | #' @seealso [metrics_filter()] 42 | #' 43 | #' @export 44 | #' 45 | #' @examples 46 | #' # Generates an optimized gradient for the landscape metric "pland", for the class "Forest". 47 | #' pland_gradient <- metrics_gradient(otf_metrics, rasterlayer = 1, class = "Forest", 48 | #' radius = 2000, metric = "pland", n = 15, breaks = 10) 49 | #' # Note that, in this case, specifications for the rasterlayer and the radius are 50 | #' # redundant, and could be simply ignored and left as default, asthe object otf_metrics 51 | #' # only comprises a unique rasterlayer and radius. 52 | #' 53 | #' # By default, the output is an updated version of the object otf_metrics. In order to 54 | #' # inspect the returned values, let's select only the dataframe containing the 55 | #' # metric's values. 56 | #' foo <- subset(pland_gradient@data, metric == "pland" & classname == "Forest", 57 | #' select = value) 58 | #' 59 | #' # Next, we output the range of values we have obtained, note there are 15 points, as 60 | #' # previously specified in the function definition in the argument 'n' 61 | #' round(sort(foo$value), digits = 2) 62 | #' 63 | #' # 1.15 1.57 8.17 8.19 15.24 22.32 29.27 36.32 43.17 43.20 49.79 50.25 55.44 57.62 64.53 64 | #' 65 | #' # Alternatively, we can define specific cutpoints around the landscapes will be selected 66 | #' # in termsof its numeric closeness. 67 | #' pland_gradient <- metrics_gradient(otf_metrics, rasterlayer = 1, class = "Forest", 68 | #' radius = 2000,metric = "pland", n = 15, 69 | #' cutpoints = seq(1, 60, 5)) 70 | #' 71 | #' # Again, we inspect the dataframe with the metric values to see our results. 72 | #' foo <- subset(pland_gradient@data, metric == "pland" & classname == "Forest", 73 | #' select = value) 74 | #' 75 | #' round(sort(foo$value), digits = 2) 76 | #' 77 | #' # 1.15 6.02 6.03 10.99 15.97 20.99 26.01 31.02 35.95 41.14 41.34 45.93 51.41 54.56 55.44 78 | #' 79 | #' # Both alternatives generated a wide-ranged gradient of values for the forest metric "pland" 80 | metrics_gradient <- function(x, 81 | rasterlayer = NULL, 82 | class = NULL, 83 | radius = NULL, 84 | metric = NULL, 85 | n, 86 | cutpoints = NULL, 87 | breaks = NULL, 88 | random = FALSE, 89 | output = "MLM"){ 90 | 91 | if(!is(x, "MultiLandMetrics")) stop("x must be an object of class 'MultiLandMetrics'.") 92 | 93 | environment(.metrics_gradient_chk_args) <- environment() 94 | chk <- .metrics_gradient_chk_args() 95 | if(length(chk[[1]]) > 0) 96 | for(w in 1:length(chk[[1]])){ 97 | warning(strwrap(chk[[1]], prefix = "\n", initial = ""), call. = FALSE) 98 | } 99 | if(length(chk[[2]]) > 0){ 100 | errors <- chk[[2]] 101 | stop(strwrap(errors, prefix = "\n", initial = "\n")) 102 | } else { 103 | objs <- names(chk) 104 | for(i in 3:length(chk)){ assign(objs[i], chk[[i]]) } 105 | } 106 | 107 | dat <- x@data[x@data$rasterlayer == rasterlayer & 108 | x@data$class == class & 109 | x@data$radius == radius & 110 | x@data$metric == metric, ] 111 | 112 | if(random){ 113 | pp <- sample(1:nrow(dat), n) 114 | message("As random = TRUE, arguments \"cutpoints\" or \"breaks\" were not considered. Random points were selected.") 115 | } else { 116 | if(is.null(cutpoints) & is.null(breaks)){ 117 | breaks <- n 118 | } 119 | if(!is.null(cutpoints) & !is.null(breaks)){ 120 | message("Argument \"breaks\" was discarded.") 121 | breaks <- length(cutpoints) 122 | } 123 | if(is.null(cutpoints) & !is.null(breaks)){ 124 | cutpoints <- seq(min(dat$value), max(dat$value), length.out = breaks) 125 | } 126 | if(!is.null(cutpoints)){ 127 | breaks <- length(cutpoints) 128 | } 129 | 130 | points_assign <- rep(0, breaks) 131 | # Pseudo-Random assignment of the points 132 | tandas <- floor(n/breaks) 133 | for(i in 1:tandas){ points_assign <- points_assign + 1 } 134 | rest <- n - sum(points_assign) 135 | if(rest > 0){ 136 | foo <- sample(1:breaks, rest) 137 | points_assign[foo] <- points_assign[foo] + 1 138 | } 139 | 140 | pp <- vector("numeric") 141 | dat2 <- dat 142 | for(i in 1:breaks){ 143 | for(j in 1:points_assign[i]){ 144 | min_diff_id <- which.min(abs(cutpoints[i] - dat2$value)) 145 | rownames(dat2[min_diff_id, ]) 146 | pp <- c(pp, rownames(dat2[min_diff_id, ])) 147 | dat2 <- dat2[-min_diff_id, ] 148 | } 149 | } 150 | } 151 | 152 | # Output MultiLandMetrics, updated 153 | df_tmp <- x@data[x@data$point_id %in% dat[pp, ]$point_id, ] 154 | if(output == "MLM"){ 155 | out <- x 156 | # Update object 157 | out@points <- out@points[out@points$id %in% unique(df_tmp$point_id), ] 158 | out@n_points <- length(unique(df_tmp$point_id)) 159 | out@n_layers <- sum(!grepl("ext", unique(out@data$rasterlayer))) 160 | out@classes <- na.exclude(unique(out@data[, c("rasterlayer", "class", "classname")])) 161 | out@classes <- out@classes[order(out@classes$rasterlayer, out@classes$class, out@classes$classname), ] 162 | out@metrics <- na.exclude(unique(out@data[, c("level", "metric")])) 163 | # Updating ext_calcs 164 | foo <- unique(out@data[, c("rasterlayer", "layer_name", "metric")]) 165 | foo <- foo[grepl("ext", foo$rasterlayer), ] 166 | foo$rasterlayer <- as.numeric(gsub("ext", "", foo$rasterlayer)) 167 | foo$metric <- gsub("fun_", "", foo$metric) 168 | colnames(foo)[2] <- "name" 169 | if(nrow(foo) > 0) rownames(foo) <- 1:nrow(foo) 170 | out@ext_calcs <- foo 171 | out@data <- df_tmp 172 | } else { 173 | points_vec <- terra::vect(cbind(x = x@points$x, y = x@points$y), 174 | atts = x@points[3:ncol(x@points)], 175 | crs = terra::crs(x@crs_proj)) 176 | # output vector 177 | if(output == "spatial"){ 178 | out <- points_vec[unique(df_tmp$point_id), ] 179 | } else { 180 | # output points dataframe 181 | if(output == "coords" & nrow(df_tmp) > 0){ 182 | out <- aggregate(point_id ~ site, df_tmp, unique) 183 | } else { 184 | # output metrics dataframe 185 | out <- df_tmp 186 | } 187 | 188 | # add points coordinates 189 | coordinates <- as.data.frame(terra::crds(points_vec)) 190 | coordinates$point_id <- 1:length(points_vec) 191 | out <- merge(out, coordinates, "point_id", all.x = TRUE) 192 | 193 | # order columns 194 | if(output == "data"){ 195 | out <- out[, c("rasterlayer", "point_id", "site", "x", "y", 196 | "radius", "level", "class", "classname", "patch_id", 197 | "metric", "value")] 198 | } 199 | } 200 | } 201 | 202 | invisible(out) 203 | } 204 | 205 | -------------------------------------------------------------------------------- /R/metrics_gradient_checks.R: -------------------------------------------------------------------------------- 1 | .metrics_gradient_chk_args <- function(){ 2 | 3 | messages <- NULL 4 | what <- NULL 5 | 6 | # Rasterlayer 7 | if(is.null(rasterlayer)){ 8 | rasterlayer <- unique(x@data$rasterlayer) 9 | } 10 | if(!is.numberinchar(rasterlayer)){ 11 | if(substr(rasterlayer, 1, 3) != "ext"){ 12 | foo <- rbind(x@rast_names$lsm, x@rast_names$ext) 13 | if(nrow(x@rast_names$ext) > 0){ 14 | foo[(nrow(x@rast_names$lsm)+1):nrow(foo), "rasterlayer"] <- 15 | paste0("ext", foo[(nrow(x@rast_names$lsm)+1):nrow(foo), "rasterlayer"]) 16 | } 17 | if(rasterlayer %in% foo$name){ 18 | rasterlayer <- foo[foo$name == rasterlayer, "rasterlayer"] 19 | } else { 20 | rasterlayer <- NA 21 | } 22 | } 23 | } 24 | if(!rasterlayer %in% unique(x@data$rasterlayer)){ 25 | messages <- append(messages, 26 | paste0("- specified rasterlayer was not found as a defined layer in 27 | 'x'. Mispelled?")) 28 | what <- append(what, 2) 29 | } else { 30 | # Class 31 | if(!is.null(class)){ 32 | if(!grepl("ext", rasterlayer)){ 33 | foo <- x@classes[x@classes$rasterlayer %in% rasterlayer, ] 34 | if(is.numeric(class)){ 35 | if(!class %in% foo$class){ 36 | messages <- append(messages, 37 | paste0("- specified class was not found as a defined 38 | class of rasterlayer ", rasterlayer, " in 'x'. Mispelled?")) 39 | what <- append(what, 2) 40 | } 41 | } else { 42 | if(is.character(class)){ 43 | if(!class %in% foo$classname){ 44 | messages <- append(messages, 45 | paste0("- specified class was not found as a defined 46 | class of rasterlayer ", rasterlayer, 47 | " in 'x'. Mispelled?")) 48 | what <- append(what, 2) 49 | } else { 50 | class <- foo[foo$classname == class, "class"] 51 | } 52 | } 53 | } 54 | } 55 | } else { 56 | class <- x@classes[x@classes$rasterlayer %in% rasterlayer, ]$class 57 | } 58 | } 59 | 60 | # Radius 61 | if(!is.null(radius)){ 62 | if(!radius %in% x@radii){ 63 | messages <- append(messages, 64 | paste0("- specified radius was not found as a defined radius in 65 | 'x'. Mispelled?")) 66 | what <- append(what, 2) 67 | } 68 | } else { 69 | radius <- unique(x@data$radius) 70 | } 71 | 72 | # Metric 73 | if(!is.null(metric)){ 74 | if(!all(metric %in% unique(x@data$metric))){ 75 | messages <- append(messages, 76 | paste0("- specified metric was not found as a defined metric in 77 | 'x'. Mispelled?")) 78 | what <- append(what, 2) 79 | } 80 | } else { 81 | metric <- unique(x@data$metric) 82 | } 83 | 84 | foo <- x@data[x@data$rasterlayer %in% rasterlayer & 85 | x@data$class %in% class & 86 | x@data$radius %in% radius & 87 | x@data$metric %in% metric, ] 88 | if(nrow(foo) == 0){ 89 | messages <- append(messages, 90 | paste0("- no metric values where found in 'x' given the specified 91 | parameters.")) 92 | what <- append(what, 2) 93 | } else { 94 | if(nrow(unique(foo[, c("rasterlayer", "class", "radius", "metric")])) != 1){ 95 | messages <- append(messages, 96 | paste0("- only one gradient for a unique metric of a given rasterlayer, 97 | class and radius can be generated at a time.")) 98 | what <- append(what, 2) 99 | } 100 | } 101 | 102 | if(is.numeric(n)){ 103 | if(length(n) != 1){ 104 | messages <- append(messages, 105 | paste0("- argument 'n' must be a unique number.")) 106 | what <- append(what, 2) 107 | } else { 108 | if(!2 %in% what){ 109 | if(n > nrow(foo)){ 110 | messages <- append(messages, 111 | paste0("- The number of required points (", n, ") is higher than the total number 112 | of points where to pick from (", nrow(foo), "), given the specified parameters. 113 | All points were selected, nothing has changed.")) 114 | what <- append(what, 2) 115 | n <- nrow(foo) 116 | } 117 | } 118 | } 119 | } else { 120 | messages <- append(messages, 121 | paste0("- argument 'n' must be numeric.")) 122 | what <- append(what, 2) 123 | } 124 | 125 | if(!is.null(cutpoints)){ 126 | if(!is.null(cutpoints)){ 127 | if(!is.numeric(cutpoints)){ 128 | messages <- append(messages, 129 | paste0("- argument 'cutpoints' must be numeric.")) 130 | what <- append(what, 2) 131 | } else { 132 | if(length(cutpoints) > n){ 133 | messages <- append(messages, 134 | paste0("- number of cutpoints cannot be higher than the number of required points.")) 135 | what <- append(what, 2) 136 | } 137 | } 138 | } 139 | } 140 | 141 | if(!is.null(breaks)){ 142 | if(is.numeric(breaks)){ 143 | if(length(breaks) != 1){ 144 | messages <- append(messages, 145 | paste0("- argument 'breaks' must be a unique number.")) 146 | what <- append(what, 2) 147 | } 148 | } else { 149 | messages <- append(messages, 150 | paste0("- argument 'breaks' must be numeric.")) 151 | what <- append(what, 2) 152 | } 153 | } 154 | 155 | if(!is.logical(random)){ 156 | messages <- append(messages, 157 | paste0("- argument 'random' must be logical.")) 158 | what <- append(what, 2) 159 | } 160 | 161 | if(!output %in% c("MLM", "spatial", "data", "coords")){ 162 | messages <- append(messages, 163 | "- argument 'output' must be \"MLM\", \"spatial\", \"data\" or \"coords\". Default 164 | \"MLM\" was taken. See ?metrics_filter") 165 | what <- append(what, 1) 166 | output <- "MLM" 167 | } 168 | 169 | warnings <- messages[which(what == 1)] 170 | errors <- messages[which(what == 2)] 171 | 172 | out <- list(warnings = warnings, 173 | errors = errors, 174 | n = n, 175 | class = class, 176 | output = output) 177 | return(out) 178 | } 179 | -------------------------------------------------------------------------------- /R/metrics_list.R: -------------------------------------------------------------------------------- 1 | #' Metrics list 2 | #' 3 | #' List of available landscape metrics provided by package `landscapemetrics` to be calculated with 4 | #' [mland_metrics()]. It simply calls [landscapemetrics::list_lsm()]. For more information regarding the 5 | #' definition and equations of metrics, please check the user manual of `landscapemetrics`. 6 | #' 7 | #' @param type Character vector. Type according to FRAGSTATS grouping. One or more of the following: 8 | #' "area and edge", "core area", "shape", "aggregation", "complexity", and or "diversity". Default 9 | #' NULL considers all types. 10 | #' @param level Character vector. Level of metrics. Either "patch", "class" or "landscape" 11 | #' (or a vector with a combination of these). Default NULL considers all levels. 12 | #' @param metric Abbreviation of metrics (e.g. "area"). 13 | #' @param name Full name of metrics (e.g. "core area"). 14 | #' @param what Selected level of metrics: either "patch", "class" or "landscape". It is also 15 | #' possible to specify functions as a vector of strings, e.g. what = c("lsm_c_ca", "lsm_l_ta"). 16 | #' 17 | #' @return A data.frame with the list of available landscape metrics, including information 18 | #' regarding the level, type, metric, name and function name provided by package `landscapemetrics`. 19 | #' @export 20 | #' 21 | #' @references 22 | #' Hesselbarth, M.H.K., Sciaini, M., With, K.A., Wiegand, K., Nowosad, J. 2019. landscapemetrics: 23 | #' an open-source R tool to calculate landscape metrics. - Ecography 42:1648-1657(ver. 0). 24 | #' 25 | #' McGarigal, K., SA Cushman, and E Ene. 2012. FRAGSTATS v4: Spatial Pattern Analysis Program for 26 | #' Categorical and Continuous Maps. Computer software program produced by the authors at the 27 | #' University of Massachusetts, Amherst. \cr 28 | #' Available at the following web site: https://www.umass.edu/landeco/ 29 | metrics_list <- function(level = NULL, 30 | metric = NULL, 31 | name = NULL, 32 | type = NULL, 33 | what = NULL){ 34 | 35 | tab <- tryCatch.W.E(landscapemetrics::list_lsm(level = level, 36 | metric = metric, 37 | name = name, 38 | type = type, 39 | what = what)) 40 | 41 | if(length(class(tab$value)) >= 2){ 42 | if(any(class(tab$value)[1:2] %in% c("simpleError", "error"))){ 43 | stop(strwrap("Selected metrics do not exist. Run metrics_list() to see all 44 | available metrics.", prefix = "\n", initial = "")) 45 | } else { tab <- tab$value } 46 | } 47 | tab <- as.data.frame(tab) 48 | 49 | return(tab) 50 | } 51 | -------------------------------------------------------------------------------- /R/metrics_plots.R: -------------------------------------------------------------------------------- 1 | #' Pairwise metric plots 2 | #' 3 | #' Plots pair of metric values in two-dimensional plots. 4 | #' 5 | #' @inheritParams mland_metrics 6 | #' @param raster,ext_raster,classes,radii,l_level,c_level Parameters to subset plots. See Details. 7 | #' @param show_class_names logical. Whether to show classes with its previously defined names (if defined) 8 | #' when generating the 'MultiLand' object (TRUE), or not (FALSE, default). 9 | #' @param smooth logical. If TRUE (default) a pattern between the pair of metric values 10 | #' is plotted, with a smoothing method as defined in `method`. 11 | #' @param method Smoothing method (function) to use, as in [ggplot2::geom_smooth()]. It accepts 12 | #' "loess" (default), "lm", "gam", among others. See ?ggplot2::geom_smooth() for more details. 13 | #' @param se logical. Whether to show (TRUE) or not (FALSE) confidence intervals when `smooth = TRUE`. 14 | #' @param ... Other parameters to be passed to [ggplot2::geom_smooth()], if `smooth = TRUE`. 15 | #' @param upper logical. Whether to plot upper-diagonal plots or not. Default TRUE 16 | #' @param diag logical. Whether to plot diagonal density plots or not. Default TRUE. 17 | #' @param st_points List of aesthetic arguments for points plotting: 18 | #' \code{shape} for points shape, \code{size} for points size, \code{col} for 19 | #' points border color, \code{fill} for points fill color and \code{alpha} for point transparency. 20 | #' @param st_lines List of aesthetic arguments for lines plotting (if `smooth = TRUE`): 21 | #' \code{lty} for linetype, \code{lwd} for linewidth, 22 | #' \code{col} for line color and \code{alpha} for line transparency. 23 | #' 24 | #' @details [metrics_plots()] mainly relies on [GGally::ggpairs()] to generate pair plots 25 | #' between metrics values. Arguments `upper` and `diag` are specific arguments of 26 | #' [GGally::ggpairs()], here adapted to the context of continuous values only. 27 | #' 28 | #' Argument `raster`, `classes`, `radii`, `l_level` and `c_level` can be defined to 29 | #' subset the plots. In each one of these, an all-positive or an 30 | #' all-negative vector can be passed, whether to include (all-positive) or exclude (all-negative) 31 | #' the elements to be taken into account for the subsetting: 32 | #' * rasterlayers: a numeric vector with the number of the raster layers to be included/excluded. 33 | #' For example: `c(1, 2, 4)` to include raster layers 1, 2 and 4; `c(-2, -3)` to exclude raster layers 2 34 | #' and 3. 35 | #' * classes: must be a list with as many elements as defined raster layers in argument 36 | #' `raster`. Each element of the list must be a numeric vector (classes identities) with the 37 | #' classes to be included/excluded. If provided a character vector, [metrics_corr()] assumes that 38 | #' classes names are provided. For example, for the case with 2 raster layers: 39 | #' `list(c(3, 20, 35), c("Forest", "Crops"))` would include classes 3, 20 and 35 from raster layer 1 40 | #' and classes "Forest" and "Crops" for raster layer 2. For the case of a unique raster layer, there 41 | #' is no need to input a list. For example, for the case of a unique raster layer and the 42 | #' exclusion of some classes: `c(-5, -10, -15)` to exclude classes 5, 10 and 15 of 43 | #' the unique raster layer; `c("-Forest", "-Grassland")` to exclude classes "Forest" and "Grassland". 44 | #' Note the "-" before each class name to indicate the exclusion of the classes. 45 | #' * radii: a numeric vector to include/exclude particular radii. For example: c(1000, 2000) to 46 | #' include only radii of 1000 and 2000 m; c(-500, -1500) to exclude radii of 500 and 1500 m. 47 | #' * c_level: character vector with the class-level metrics to be included/excluded from 48 | #' the analysis. For example: `c("np", "pland")` will include only the metrics "number of patches" 49 | #' ("np") and "percentage of the landscape" ("pland") in the analysis, whereas `c("-np", "-pland")` 50 | #' will exclude them. Note the "-" before each metric name to indicate the exclusion of the 51 | #' metrics. 52 | #' * l_level: character vector with the landscape-level metrics to be included/excluded from 53 | #' the analysis. Other calculations for extra raster layers are considered as landscape-level metrics, 54 | #' and must be provided as "fun_" + the name of the function (e.g. "fun_mean"). 55 | #' 56 | #' Names of the available metrics of the 'MultiLandMetrics' object provided in `x` can 57 | #' be accessed with `x@metrics` and `x@ext_calc`. 58 | #' 59 | #' Note that patch-level metrics, if exists in `x` metric's data.frame, are excluded from 60 | #' calculations, as this function works at a landscape scale. 61 | #' 62 | #' @return A panel with several plots returned by [GGally::ggpairs()] relating pair of metrics 63 | #' values. Metrics 64 | #' names are presented at the top and right of the panel (strips), with the following format: 65 | #' "level"_"metric_name"_"radius". For a landscape-level metric, a plausible metric name could be 66 | #' "l_np_1500" indicating a landscape-level metric, which is "np" ("number of patches") at a scale 67 | #' (radius) of 1500 m. For a class-level metric a plausible metric name could be "c4_pland_1000", 68 | #' indicating a class-level metric of class 4 (the value of the raster), which is "pland" 69 | #' ("percentage of landscape") at a scale (radius) of 1000 m. If more that one rasterlayer is 70 | #' being analyzed, the prefix "r1", "r2", "r3", ..., "rn" (referring to rasterlayer 1, 2, 3, ..., n) is 71 | #' added to the metric name. 72 | #' 73 | #' @seealso [mland_metrics()], [metrics_corr()] 74 | #' 75 | #' @export 76 | #' 77 | #' @examples 78 | #' # Pair plots between metrics "pland" of classes 1 to 4, for radius 3000 m 79 | #' metrics_plots(ed_metrics, classes = 1:4, radii = 3000, show_class_names = TRUE, 80 | #' c_level = "pland") 81 | #' 82 | #' # Without smooth pattern 83 | #' metrics_plots(ed_metrics, classes = 1:4, radii = 3000, show_class_names = TRUE, 84 | #' c_level = "pland", smooth = FALSE) 85 | #' 86 | #' \donttest{ 87 | #' # Changing aesthetics 88 | #' metrics_plots(ed_metrics, classes = 1:4, radii = 3000, show_class_names = TRUE, 89 | #' c_level = "pland", smooth = FALSE, size = 1.5, shape = 21, 90 | #' fill = "red", alpha = 0.4) 91 | #' 92 | #' # Assessing two radii values at the same time 93 | #' metrics_plots(ed_metrics, classes = 1:4, radii = c(1000, 5000), 94 | #' show_class_names = TRUE, c_level = "pland", smooth = FALSE, 95 | #' size = 1.5, shape = 21, fill = "red", alpha = 0.4) 96 | #' 97 | #' # An example with hundreds of points 98 | #' metrics_plots(otf_metrics, classes = c("Forest", "Crops")) 99 | #' 100 | #' # Plots can be combined with ggplot2::theme 101 | #' metrics_plots(otf_metrics, classes = c("Forest", "Crops")) + 102 | #' ggplot2::theme_bw() 103 | #' } 104 | metrics_plots <- function(x, 105 | raster = NULL, 106 | classes = NULL, 107 | radii = NULL, 108 | c_level = NULL, 109 | l_level = NULL, 110 | ext_raster = NULL, 111 | show_class_names = FALSE, 112 | upper = TRUE, 113 | diag = TRUE, 114 | smooth = TRUE, 115 | method = "loess", 116 | se = FALSE, 117 | st_points = list(shape = 21, 118 | size = 2, 119 | col = "black", 120 | fill = "white", 121 | alpha = 1), 122 | st_lines = list(lty = 1, 123 | lwd = 1, 124 | col = "black", 125 | alpha = 0.6), 126 | ...){ 127 | 128 | if(!is(x, "MultiLandMetrics")) stop("x must be an object of class 'MultiLandMetrics'.") 129 | environment(.metrics_plots_chk_args) <- environment() 130 | chk <- .metrics_plots_chk_args() 131 | if(length(chk[[1]]) > 0) 132 | for(w in 1:length(chk[[1]])){ 133 | warning(strwrap(chk[[1]], prefix = "\n", initial = ""), call. = FALSE) 134 | } 135 | if(length(chk[[2]]) > 0){ 136 | errors <- chk[[2]] 137 | stop(strwrap(errors, prefix = "\n", initial = "\n")) 138 | } else { 139 | objs <- names(chk) 140 | for(i in 3:length(chk)){ assign(objs[i], chk[[i]]) } 141 | } 142 | 143 | towide <- T 144 | environment(.pair_subsets) <- environment() 145 | df <- tryCatch(.pair_subsets(), 146 | error = function(e){ 147 | message("") 148 | stop(e)}) 149 | new_df_wide <- df[[1]] 150 | 151 | # asks if it is okay to plot so many plots 152 | if(length(4:ncol(new_df_wide)) > 10){ 153 | ask <- askYesNo("You are attempting to plot more than one hundred plots. Are you sure?") 154 | if(is.na(ask) | !ask) stop("Operation cancelled") 155 | } 156 | 157 | # plotting function, combining points with geom_smooth 158 | # Credit to user20650 from stackoverflow 159 | my_fn <- function(data, mapping, meth = method, ...){ 160 | p <- ggplot2::ggplot(data = data, mapping = mapping) + 161 | ggplot2::geom_point(shape = st_points$shape, fill = st_points$fill, 162 | col = st_points$col, alpha = st_points$alpha, 163 | size = st_points$size, na.rm = T) 164 | 165 | if(smooth){ 166 | p <- p + ggplot2::geom_smooth(method = meth, formula = y ~ x, se = se, na.rm = T, 167 | lty = st_lines$lty, lwd = st_lines$lwd, 168 | col = ggplot2::alpha(st_lines$col, st_lines$alpha), ...) 169 | } 170 | p 171 | } 172 | 173 | # Pair scatterplots 174 | if(upper) upper <- list(continuous = my_fn) else upper = "blank" 175 | if(diag) diag <- list(continuous = "densityDiag") else diag = list(continuous = "blankDiag") 176 | suppressWarnings(GGally::ggpairs(new_df_wide[3:ncol(new_df_wide)], 177 | lower = list(continuous = my_fn), 178 | upper = upper, diag = diag, progress = F)) 179 | } 180 | 181 | -------------------------------------------------------------------------------- /R/metrics_scalogram_checks.R: -------------------------------------------------------------------------------- 1 | .metrics_scalogram_chk_args <- function(){ 2 | 3 | messages <- NULL 4 | what <- NULL 5 | 6 | # Points 7 | chk_points <- .chk_points2(messages, what, x, points) 8 | messages <- chk_points[[1]] 9 | what <- chk_points[[2]] 10 | points <- chk_points[[3]] 11 | 12 | # Show class names 13 | if(!is.logical(show_class_names)){ 14 | messages <- append(messages, 15 | "- argument 'show_class_names' must be logical. Default FALSE was taken.") 16 | what <- append(what, 1) 17 | show_class_names <- FALSE 18 | } 19 | 20 | # Class names 21 | chk_classnames <- .chk_classnames(messages, what, show_class_names) 22 | messages <- chk_classnames[[1]] 23 | what <- chk_classnames[[2]] 24 | show_class_names <- chk_classnames[[3]] 25 | 26 | # Aggregation 27 | if(!is.logical(aggregation)){ 28 | messages <- append(messages, 29 | "- argument 'aggregation' must be logical. Default FALSE was taken.") 30 | what <- append(what, 1) 31 | aggregation <- FALSE 32 | } 33 | 34 | # Aggregation function 35 | if(fun != "mean"){ 36 | if(!exists(fun)){ 37 | messages <- append(messages, 38 | paste0("- could not find a function named \"", fun, "\" in the current 39 | environment. Mispelled?")) 40 | what <- append(what, 2) 41 | fun <- "mean" 42 | } else { 43 | args <- list(1:5) 44 | val_test <- tryCatch(do.call(fun, args), 45 | error = c) 46 | bad <- FALSE 47 | if(is.list(val_test)) bad <- TRUE 48 | if(is.numeric(val_test)){ 49 | if(length(val_test) != 1) bad <- TRUE 50 | } else { 51 | bad <- TRUE 52 | } 53 | if(bad){ 54 | messages <- append(messages, 55 | "- function provided in argument 'fun' does not make sense in this context. 56 | See ?metrics_scalogram") 57 | what <- append(what, 2) 58 | fun <- "mean" 59 | } 60 | } 61 | } 62 | 63 | warnings <- messages[which(what == 1)] 64 | errors <- messages[which(what == 2)] 65 | 66 | out <- list(warnings = warnings, 67 | errors = errors, 68 | points = points, 69 | show_class_names = show_class_names, 70 | fun = fun) 71 | 72 | return(out) 73 | } 74 | -------------------------------------------------------------------------------- /R/mland_checks.R: -------------------------------------------------------------------------------- 1 | # mland argument checking 2 | .mland_chk_args <- function() { 3 | 4 | messages <- NULL 5 | what <- NULL 6 | 7 | # Points 8 | if(!class(points_layer) %in% c("character", "SpatVector", "SpatialPointsDataFrame", "SpatialPoints")){ 9 | messages <- append(messages, 10 | "- argument 'points_layer' must be a filename (string) or an object of class 11 | 'SpatVector', 'SpatialPointsDataFrame' or 'SpatialPoints'.") 12 | what <- append(what, 2) 13 | } else { 14 | if(!class(points_layer) %in% c("SpatVector", "SpatialPointsDataFrame", "SpatialPoints")){ 15 | if(!file.exists(points_layer)){ 16 | messages <- append(messages, paste("- could not find points layer file: ", points_layer, ".")) 17 | what <- append(what, 2) 18 | } 19 | } 20 | } 21 | 22 | # Rasters 23 | if(is.null(rast_layer) & is.null(ext_rast_layer)){ 24 | messages <- append(messages, "- at least one rasterlayer must be specified in 'rast_layer' 25 | and/or 'ext_rast_layer'.") 26 | what <- append(what, 2) 27 | } else { 28 | # Raster 29 | chk_raster <- .chk_raster(messages, what, rast_layer, arg_name = "rast_layer") 30 | messages <- chk_raster[[1]] 31 | what <- chk_raster[[2]] 32 | rast_layer <- chk_raster[[3]] 33 | 34 | # Extra Raster 35 | chk_ext_raster <- .chk_raster(messages, what, ext_rast_layer, arg_name = "ext_rast_layer") 36 | messages <- chk_ext_raster[[1]] 37 | what <- chk_ext_raster[[2]] 38 | ext_rast_layer <- chk_ext_raster[[3]] 39 | } 40 | 41 | # On the fly 42 | if(!is.logical(on_the_fly)){ 43 | messages <- append(messages, "- argument 'on_the_fly' must be logical.") 44 | what <- append(what, 2) 45 | } 46 | 47 | # Class names 48 | if(!is.null(class_names)){ 49 | if(is.list(class_names)){ 50 | if(length(class_names) > 0){ 51 | for(i in 1:length(class_names)){ 52 | if(is.character(class_names[[i]])){ 53 | cl <- seq(1, length(class_names[[i]]), 2) 54 | if((length(class_names[[i]]) %% 2) != 0 | 55 | !all(!is.na(suppressWarnings(as.numeric(class_names[[i]][cl]))))){ 56 | messages <- append(messages, "- argument 'class_names' was not defined properly. See ?mland.") 57 | what <- append(what, 2) 58 | class_names <- list() 59 | break 60 | } else { 61 | if(!is.character(class_names[[i]])){ 62 | messages <- append(messages, "- argument 'class_names' must be a list with vector of 63 | strings in even elements. See ?mland") 64 | what <- append(what, 2) 65 | class_names <- list() 66 | break 67 | } 68 | } 69 | if("landscape" %in% class_names[[i]]){ 70 | messages <- append(messages, "- the string \"landscape\" must be 71 | avoided to name a raster class. Please use another one.") 72 | what <- append(what, 2) 73 | class_names <- list() 74 | break 75 | } 76 | } else { 77 | messages <- append(messages, "- argument 'class_names' was not defined properly. See ?mland.") 78 | what <- append(what, 2) 79 | class_names <- list() 80 | break 81 | } 82 | } 83 | } 84 | } else { 85 | messages <- append(messages, "- argument 'class_names' must be a list. The argument was 86 | ignored.") 87 | what <- append(what, 1) 88 | class_names <- list() 89 | } 90 | } else { class_names <- list() } 91 | 92 | # Raster names 93 | if(!is.null(rast_names)){ 94 | if(!is.character(rast_names)){ 95 | messages <- append("- argument 'rast_names' must be a character vector. 96 | Argument was discarded.") 97 | what <- append(what, 1) 98 | rast_names <- vector("character") 99 | } else { 100 | if(any(duplicated(rast_names))){ 101 | messages <- append("- argument 'rast_names' contains duplicated string. Raster layer 102 | names should be unique to avoid ambiguites. Argument was discarded.") 103 | what <- append(what, 1) 104 | rast_names <- vector("character") 105 | } else { 106 | if(any(substr(rast_names, 1, 3) == "ext")){ 107 | messages <- append("- The names for the raster layers cannot start with the 108 | substring \"ext\".") 109 | what <- append(what, 2) 110 | rast_names <- vector("character") 111 | } 112 | } 113 | } 114 | } else { rast_names <- vector("character") } 115 | 116 | # Site reference 117 | if(!is.null(site_ref)){ 118 | if(!is.character(site_ref) | length(site_ref) > 1){ 119 | messages <- append(messages, "- argument 'site_ref' must be a string. The argument was 120 | ignored.") 121 | what <- append(what, 1) 122 | site_ref <- NULL 123 | } 124 | } 125 | 126 | # Radii 127 | if(!is.numeric(radii) | !all(radii > 0)){ 128 | messages <- append(messages, "- argument 'radii' must be a vector of positive numbers.") 129 | what <- append(what, 2) 130 | } 131 | 132 | # Type of buffer 133 | if(length(bufftype) > 1 | !is.character(bufftype) | 134 | !tolower(bufftype[1]) %in% c("round", "square")){ 135 | messages <- append(messages, "- argument 'bufftype' must be \"round\" or \"square\". Default \"round\" 136 | was taken.") 137 | what <- append(what, 1) 138 | bufftype <- "round" 139 | } 140 | 141 | # Segs of buffers 142 | if(!is.numeric(segs) | length(segs) > 1 | segs[1] < 0){ 143 | messages <- append(messages, "- argument 'segs' must be a positive integer. Default 20 was 144 | taken.") 145 | what <- append(what, 1) 146 | segs <- 20 147 | } 148 | 149 | # Progress 150 | chk_progress <- .chk_progress(messages, what, progress) 151 | messages <- chk_progress[[1]] 152 | what <- chk_progress[[2]] 153 | 154 | warnings <- messages[which(what == 1)] 155 | errors <- messages[which(what == 2)] 156 | 157 | out <- list(warnings = warnings, 158 | errors = errors, 159 | class_names = class_names, 160 | site_ref = site_ref, 161 | bufftype = bufftype, 162 | segs = segs, 163 | rast_layer = rast_layer, 164 | ext_rast_layer = ext_rast_layer, 165 | rast_names = rast_names, 166 | progress = progress) 167 | return(out) 168 | } 169 | 170 | .check_pointsCRS <- function(points_layer){ 171 | mess <- FALSE 172 | if(terra::crs(points_layer) == ""){ 173 | mess <- "- points layer must be projected in a crs with meters unit." } 174 | return(mess) 175 | } 176 | 177 | .check_classCRS <- function(points_layer, class, ex_p, rad){ 178 | mess <- if(!terra::same.crs(points_layer, class)) 1 else 0 179 | 180 | # Check extent non-overlapping 181 | if(mess == 0){ 182 | ex_cl <- terra::ext(class) 183 | if(ex_p[1] < ex_cl[1] | 184 | ex_p[2] > ex_cl[2] | 185 | ex_p[3] < ex_cl[3] | 186 | ex_p[4] > ex_cl[4]){ 187 | mess <- 2 188 | } else { 189 | if((ex_p[1] - ex_cl[1]) < rad | 190 | (ex_cl[2] - ex_p[2]) < rad | 191 | (ex_p[3] - ex_cl[3]) < rad | 192 | (ex_cl[4] - ex_p[4]) < rad){ 193 | mess <- 3 194 | } 195 | } 196 | } 197 | return(mess) 198 | } 199 | 200 | .check_pointsref <- function(points_layer, site_ref){ 201 | mess <- 0 202 | if(!site_ref %in% names(points_layer)){ 203 | mess <- 1 204 | } else { 205 | if(anyDuplicated(terra::as.list(points_layer)[[site_ref]]) != 0){ 206 | mess <- 2 ; return(mess) 207 | } 208 | if(any(is.na(terra::as.list(points_layer)[[site_ref]]))){ 209 | mess <- 3 ; return(mess) 210 | } 211 | } 212 | return(mess) 213 | } 214 | -------------------------------------------------------------------------------- /R/mland_load.R: -------------------------------------------------------------------------------- 1 | #' Load 'MultiLand' or 'MultiLandMetrics' object 2 | #' 3 | #' Imports a zip file into an object of class 'MultiLand' that was previously 4 | #' saved with [mland_save()]. Alternatively, loads to the environment an RDS object depicting a 5 | #' 'MultiLandMetrics' object. 6 | #' 7 | #' @param path A string depicting the path to a zip file, to load objects of class 8 | #' 'MultiLand', or to a RDS file to load objects of class 'MultiLandMetrics'. 9 | #' @param ... Other parameters passed to [readRDS()] when trying to load an object of class 10 | #' 'MultiLandMetrics'. 11 | #' 12 | #' @return A 'MultiLand' or a 'MultiLandMetrics' object. 13 | #' 14 | #' @seealso [mland_save()], [mland()], [mland_metrics()] 15 | #' 16 | #' @export 17 | #' 18 | #' @examples 19 | #' # Loads mland object from a zip file, previously created with mland_save() 20 | #' mland_obj <- system.file("extdata", "ernesdesign.zip", package = "multilandr") 21 | #' ernesdesign <- mland_load(mland_obj) 22 | #' 23 | #' # Loads a MultiLandMetrics object previously generated with mland_metrics() and 24 | #' # exported as a RDS object with mland_save() or saveRDS() 25 | #' 26 | #' mlm_obj <- system.file("extdata", "ed_metrics.rds", package = "multilandr") 27 | #' ed_metrics <- mland_load(mlm_obj) 28 | mland_load <- function(path, 29 | ...){ 30 | if(is.character(path)){ 31 | if(substr(path, (nchar(path) + 1) - 4, nchar(path)) == ".zip"){ 32 | if(!file.exists(path)) 33 | stop("Could not find required zip file.") 34 | tmp <- tempdir() 35 | objs <- utils::unzip(path, exdir = tmp) 36 | } else { 37 | if(substr(path, (nchar(path) + 1) - 4, nchar(path)) == tolower(".rds")){ 38 | if(!file.exists(path)) 39 | stop("Could not find required .rds file.") 40 | 41 | out <- readRDS(file = path, ...) 42 | if(!is(out, "MultiLandMetrics")){ 43 | stop("The provided file is not an object of class 'MultiLandMetrics'.") 44 | } 45 | return(out) 46 | } else { 47 | stop("- argument 'path' must be a string with the path to a zip file (for 'MultiLand' objects), 48 | or to a RDS file (for 'MultiLandMetrics' objects).") 49 | } 50 | objs <- paste0(path, "/", list.files(path)) 51 | } 52 | } else { 53 | stop("- argument 'path' must be a string with the path to a zip file (for 'MultiLand' objects), 54 | or to a RDS file (for 'MultiLandMetrics' objects).") 55 | } 56 | 57 | if(!all(any(grepl("info.rds", objs)), 58 | any(grepl("/buffers/", objs)), 59 | any(grepl("/points/", objs)), 60 | any(grepl("README.txt", objs)), 61 | any(grepl("/landscapes/", objs)))){ 62 | stop("- directory content is corrupted or was not generated via mland_save().") 63 | } 64 | 65 | # Loads mland info 66 | info <- readRDS(grep("info.rds", objs, value = T)) 67 | 68 | # Loads points and buffers 69 | info@points <- terra::vect(grep("points.gpkg", objs, value = T)) 70 | info@buffers <- terra::vect(grep("buffers.gpkg", objs, value = T)) 71 | 72 | ff <- function(x, objs){ 73 | terra::rast(grep(x, objs, value = T)) 74 | } 75 | 76 | # Loads main rasters 77 | if(length(info@landscapes$lsm_rasters) > 0){ 78 | for(i in 1:info@n_layers){ 79 | if(!info@on_the_fly){ 80 | names <- as.list(paste0("/", names(info@landscapes$lsm_rasters[[i]]))) 81 | info@landscapes$lsm_rasters[[i]] <- lapply(names, ff, objs) 82 | names(info@landscapes$lsm_rasters[[i]]) <- substring(names, 2) 83 | } else { 84 | info@landscapes$lsm_rasters[[i]] <- terra::rast(grep(paste0("landscapes/lsm_rasters/raster_", i), 85 | objs, value = T)) 86 | } 87 | } 88 | } 89 | 90 | # Loads extra rasters 91 | if(length(info@landscapes$ext_rasters) > 0){ 92 | for(i in 1:length(info@landscapes$ext_rasters)){ 93 | if(!info@on_the_fly){ 94 | names <- as.list(names(info@landscapes$ext_rasters[[i]])) 95 | info@landscapes$ext_rasters[[i]] <- lapply(names, ff, objs) 96 | names(info@landscapes$ext_rasters[[i]]) <- names 97 | } else { 98 | info@landscapes$ext_rasters[[i]] <- terra::rast(grep(paste0("landscapes/ext_rasters/raster_", i), 99 | objs, value = T)) 100 | } 101 | } 102 | } 103 | 104 | unlink(gsub("info.RDS", "", grep("info.RDS", objs, value = T))) 105 | message("'MultiLand' object was loaded successfully.") 106 | return(info) 107 | } 108 | -------------------------------------------------------------------------------- /R/mland_overlap.R: -------------------------------------------------------------------------------- 1 | #' Buffers overlapping 2 | #' 3 | #' Returns matrices informing the degree of overlapped area 4 | #' between buffers of a 'MultiLand' object. 5 | #' 6 | #' @inheritParams mland_metrics 7 | #' @param points Numeric or character vector depicting the points to be considered. If NULL, all 8 | #' points will be taken into account. See Details. 9 | #' @param radii Numeric vector depicting the radii to be considered. If NULL, all radii will be taken 10 | #' into account. 11 | #' @param digits Numeric. Number of digits for the values of overlapped areas. Default is 2. 12 | #' @param title One of the following: "id" to output each point with its id (default), or "sitename" to 13 | #' output each point with its pre-defined point name in `x`. 14 | #' @param perc Logical. If TRUE (default) the degree of overlapped areas will be 15 | #' presented as percentages. If FALSE, proportions will be outputted. 16 | #' 17 | #' @details 18 | #' If argument `points` is a character vector, 19 | #' [mland_overlap()] will assume that the 'MultiLand' object inputted in argument `x` was created with 20 | #' `site_ref = TRUE`. This is, there is a column/attribute in the points layer with the names for 21 | #' each distinct point. Therefore, the inputted values in argument `points` will be taken as these 22 | #' identification names. Otherwise, if a numeric vector is declared, the inputted values 23 | #' will be taken as the automatically generated point ids (created when executing [mland()]). 24 | #' 25 | #' @return A list with as many elements as different radius in `x`. Each element contains a 26 | #' matrix with the percentages (or proportions if `perc = FALSE`) of overlapping of buffer areas. 27 | #' 28 | #' @export 29 | #' 30 | #' @examples 31 | #' \donttest{ 32 | #' # Loads a 'MultiLand' object 33 | #' ernesdesign <- system.file("extdata", "ernesdesign.zip", package = "multilandr") 34 | #' ernesdesign <- mland_load(ernesdesign) 35 | #' 36 | #' # Returns a matrix with the percentage of overlapping between buffers of each radii 37 | #' mland_overlap(ernesdesign) 38 | #' 39 | #' # Selects only one radius and return the site names rather than the ids 40 | #' mland_overlap(ernesdesign, radii = 5000, title = "sitename") 41 | #' } 42 | mland_overlap <- function(x, 43 | points = NULL, 44 | radii = NULL, 45 | digits = 2, 46 | perc = TRUE, 47 | title = "id"){ 48 | 49 | # Check arguments 50 | if(!is(x, "MultiLand")) stop("- argument 'x' must be an object of class 'MultiLand'.") 51 | environment(.mland_overlap_check_args) <- environment() 52 | chk <- .mland_overlap_check_args() 53 | if(length(chk[[1]]) > 0) 54 | for(w in 1:length(chk[[1]])){ 55 | warning(strwrap(chk[[1]], prefix = "\n", initial = ""), call. = FALSE) 56 | } 57 | if(length(chk[[2]]) > 0){ 58 | errors <- chk[[2]] 59 | stop(strwrap(errors, prefix = "\n", initial = "\n")) 60 | } else { 61 | objs <- names(chk) 62 | for(i in 3:length(chk)){ assign(objs[i], chk[[i]]) } 63 | } 64 | 65 | if(is.null(points)){ 66 | points <- 1:length(x@points) 67 | } else { points <- as.numeric(points) } 68 | if(is.null(radii)) radii <- x@radii 69 | 70 | df_reference <- x@l_ref 71 | 72 | # filter df_reference by site id or point id, and radii 73 | df_reference <- df_reference[df_reference$point_id %in% points & 74 | df_reference$radius %in% radii, ] 75 | 76 | # final number of radii and points to be evaluated 77 | n_radii <- length(radii) 78 | n_points <- length(points) 79 | 80 | summary_list <- vector("list", n_radii) 81 | summary <- matrix(data = rep(0, n_points^2), nrow = n_points, ncol = n_points) 82 | # Generating matrix 83 | for(k in 1:n_radii){ 84 | for(j in 1:n_points){ 85 | p1 <- points[j] 86 | for(i in 1:n_points){ 87 | if(j <= i){ 88 | if(j != i){ 89 | p2 <- points[i] 90 | buff1 <- x@buffers[df_reference[df_reference$radius == radii[k] & 91 | df_reference$point_id == p1, "row_id"], ] 92 | buff2 <- x@buffers[df_reference[df_reference$radius == radii[k] & 93 | df_reference$point_id == p2, "row_id"], ] 94 | buffarea <- terra::expanse(buff1) 95 | inter <- suppressWarnings(terra::intersect(buff1, buff2)) 96 | if(length(inter) > 0){ 97 | inter_area <- terra::expanse(inter) 98 | overlap <- round(inter_area/buffarea) 99 | if(perc){ 100 | overlap <- round(inter_area/buffarea, digits = digits + 2)*100 101 | } else { 102 | overlap <- round(inter_area/buffarea, digits = digits) 103 | } 104 | } else { 105 | overlap <- 0 106 | } 107 | summary[i, j] <- overlap 108 | } else { 109 | summary[i, j] <- if(perc) 100 else 1 110 | } 111 | } else { 112 | summary[i, j] <- NA 113 | } 114 | } 115 | } 116 | if(title == "id"){ 117 | point_ids_col <- "point_id" 118 | } else { 119 | point_ids_col <- "site" 120 | } 121 | rownames(summary) <- colnames(summary) <- df_reference[df_reference$radius == radii[k], 122 | point_ids_col] 123 | summary_list[[k]] <- summary 124 | names(summary_list)[[k]] <- as.character(radii[k]) 125 | } 126 | 127 | return(summary_list) 128 | } 129 | -------------------------------------------------------------------------------- /R/mland_overlap_checks.R: -------------------------------------------------------------------------------- 1 | .mland_overlap_check_args <- function(){ 2 | 3 | messages <- NULL 4 | what <- NULL 5 | 6 | # Points 7 | chk_points <- .chk_points(messages, what, x, points) 8 | messages <- chk_points[[1]] 9 | what <- chk_points[[2]] 10 | points <- chk_points[[3]] 11 | 12 | # Radii 13 | chk_radii <- .chk_radii(messages, what, x, radii) 14 | messages <- chk_radii[[1]] 15 | what <- chk_radii[[2]] 16 | 17 | # title 18 | chk_title <- .chk_title(messages, what, x, title) 19 | messages <- chk_title[[1]] 20 | what <- chk_title[[2]] 21 | title <- chk_title[[3]] 22 | if(chk_points[[4]]) title <- "sitename" 23 | 24 | # digits 25 | if(!is.positive.wholenumber(digits)){ 26 | messages <- append(messages, 27 | "- argument 'digits' must be a positive wholenumber. Default 2 was taken.") 28 | what <- append(what, 1) 29 | digits <- 2 30 | } 31 | 32 | # Percentage? 33 | if(!is.logical(perc)){ 34 | messages <- append(messages, 35 | "- argument 'perc' must be logical. Default TRUE was taken.") 36 | what <- append(what, 1) 37 | perc <- TRUE 38 | } 39 | 40 | errors <- messages[which(what == 2)] 41 | warnings <- messages[which(what == 1)] 42 | 43 | out <- list(warnings = warnings, 44 | errors = errors, 45 | points = points, 46 | title = title, 47 | digits = digits, 48 | perc = perc) 49 | return(out) 50 | } 51 | -------------------------------------------------------------------------------- /R/mland_plot_checks.R: -------------------------------------------------------------------------------- 1 | # mland_plot() arguments checking 2 | .mland_plot_check_args <- function(){ 3 | 4 | messages <- NULL 5 | what <- NULL 6 | 7 | # Rasterlayer 8 | arg_name <- "raster" 9 | raster_isok <- T 10 | if(is.null(raster) & is.null(ext_raster)){ 11 | raster <- 1 12 | if(x@n_layers == 0){ 13 | arg_name <- "ext_raster" 14 | message("- argument 'ext_raster' was taken as equal to 1.") 15 | } else { 16 | message("- argument 'raster' was taken as equal to 1.") 17 | } 18 | } else { 19 | if(all(!is.null(raster), !is.null(ext_raster))){ 20 | messages <- append(messages, "- only one rasterlayer can be plotted, which can be specified 21 | either in arguments 'raster' or 'ext_raster'.") 22 | what <- append(what, 2) 23 | raster_isok <- F 24 | } else { 25 | if(!is.null(ext_raster)){ 26 | raster <- ext_raster 27 | arg_name <- "ext_raster" 28 | if(length(x@landscapes$ext_rasters) > 0){ 29 | rast_search <- x@rast_names[[2]] 30 | } else { 31 | rast_search <- F 32 | } 33 | } else { 34 | if(length(x@landscapes$lsm_rasters) > 0){ 35 | rast_search <- x@rast_names[[1]] 36 | } else { 37 | rast_search <- F 38 | } 39 | } 40 | if(is.logical(rast_search)){ 41 | messages <- append(messages, 42 | paste0("- in argument '", arg_name, 43 | "': required rasterlayer was not found in x.")) 44 | what <- append(what, 2) 45 | raster_isok <- F 46 | } else { 47 | if(length(raster) > 1){ 48 | messages <- append(messages, 49 | paste0("- in argument '", arg_name, 50 | "': only one rasterlayer can be selected.")) 51 | what <- append(what, 2) 52 | raster_isok <- F 53 | } else { 54 | if(is.character(raster)){ 55 | raster <- rast_search[rast_search$name == raster, "rasterlayer"] 56 | if(length(raster) == 0) raster <- max(rast_search$rasterlayer) + 1 57 | if(is.na(raster)) raster <- max(rast_search$rasterlayer) + 1 58 | } 59 | if(!is.positive.wholenumber(raster)){ 60 | messages <- append(messages, 61 | paste0("- argument '", arg_name, "' must be a positive wholenumber 62 | depicting the rasterlayer number, or a string depicting the 63 | rasterlayer name.")) 64 | what <- append(what, 2) 65 | raster_isok <- F 66 | } else { 67 | if(!raster %in% rast_search$rasterlayer){ 68 | messages <- append(messages, 69 | paste0("- in argument '", arg_name, 70 | "': required rasterlayer was not found in x.")) 71 | what <- append(what, 2) 72 | raster_isok <- F 73 | } 74 | } 75 | } 76 | } 77 | } 78 | } 79 | 80 | # Points 81 | chk_points <- .chk_points(messages, what, x, points) 82 | messages <- chk_points[[1]] 83 | what <- chk_points[[2]] 84 | points <- chk_points[[3]] 85 | 86 | # Radii 87 | chk_radii <- .chk_radii(messages, what, x, radii) 88 | messages <- chk_radii[[1]] 89 | what <- chk_radii[[2]] 90 | 91 | # title 92 | chk_title <- .chk_title(messages, what, x, title) 93 | messages <- chk_title[[1]] 94 | what <- chk_title[[2]] 95 | title <- chk_title[[3]] 96 | if(chk_points[[4]]) title <- "sitename" 97 | 98 | # nrow and ncol 99 | if(!is.null(nrow)){ 100 | if(!is.positive.wholenumber(nrow)){ 101 | messages <- append(messages, 102 | "- if not NULL, argument 'nrow' must be a positive wholenumber. Default 103 | NULL was taken.") 104 | what <- append(what, 1) 105 | nrow <- NULL 106 | } 107 | } 108 | if(!is.null(ncol)){ 109 | if(!is.positive.wholenumber(ncol)){ 110 | messages <- append(messages, 111 | "- if not NULL, argument 'ncol' must be a positive wholenumber. Default 112 | NULL was taken.") 113 | what <- append(what, 1) 114 | ncol <- NULL 115 | } 116 | } 117 | 118 | # points style 119 | args <- list(shape = 21, size = 2, col = "black", fill = "white", alpha = 1) 120 | if(!all(names(args) %in% names(st_points))){ 121 | for(i in 1:5){ 122 | if(!names(args)[i] %in% names(st_points)){ 123 | st_points <- append(st_points, args[i]) 124 | names(st_points)[length(st_points)] <- names(args)[i] 125 | } 126 | } 127 | } 128 | 129 | # buffers style 130 | args <- list(lty = 1, lwd = 1, col = "black", alpha = 1) 131 | if(!all(names(args) %in% names(st_buffers))){ 132 | for(i in 1:5){ 133 | if(!names(args)[i] %in% names(st_buffers)){ 134 | st_buffers <- append(st_buffers, args[i]) 135 | names(st_buffers)[length(st_buffers)] <- names(args)[i] 136 | } 137 | } 138 | } 139 | 140 | # classes style 141 | args <- list(palette = "Spectral", fill = NULL, alpha = NULL, na_value = c("white", 1)) 142 | if(!all(names(args) %in% names(st_classes))){ 143 | for(i in 1:4){ 144 | if(!names(args)[i] %in% names(st_classes)){ 145 | st_classes <- append(st_classes, args[i]) 146 | names(st_classes)[length(st_classes)] <- names(args)[i] 147 | } 148 | } 149 | } 150 | 151 | if(raster_isok){ 152 | if(arg_name == "raster"){ 153 | # check fill parameters 154 | cl_vals <- x@classes[x@classes$rasterlayer == raster, "class"] 155 | cl_names <- x@classes[x@classes$rasterlayer == raster, "classname"] 156 | orig_cl <- c(cl_vals, cl_names) 157 | if(!is.null(st_classes$fill)){ 158 | if(length(st_classes$fill)/2 != length(cl_vals)){ 159 | warning(strwrap("- number of colors defined in st_classes$fill differ with the number of 160 | potential classes to plot. Default NULL was taken.", 161 | prefix = "\n", initial = ""), call. = FALSE) 162 | st_classes$fill <- c(rbind(cl_vals, 163 | hcl.colors(length(cl_vals), palette = st_classes$palette))) 164 | } else { 165 | ok <- T 166 | for(i in seq(1, length(st_classes$fill), 2)){ 167 | if(!st_classes$fill[i] %in% orig_cl){ 168 | warning(paste0("- in st_classes$fill: class '", st_classes$fill[i], 169 | "' is not a defined class in 'x'. Default NULL was taken."), 170 | call. = FALSE) 171 | ok <- F 172 | break 173 | } 174 | } 175 | if(!ok){ 176 | st_classes$fill <- c(rbind(cl_vals, 177 | hcl.colors(length(cl_vals), palette = st_classes$palette))) 178 | } 179 | } 180 | } else { 181 | st_classes$fill <- c(rbind(cl_vals, 182 | hcl.colors(length(cl_vals), palette = st_classes$palette))) 183 | } 184 | 185 | for(i in seq(1, length(st_classes$fill), 2)){ 186 | if(is.na(suppressWarnings(as.numeric(st_classes$fill[i])))){ 187 | st_classes$fill[i] <- x@classes[x@classes$classname == st_classes$fill[i], "class"] 188 | } 189 | } 190 | 191 | if(any(duplicated(st_classes$fill[seq(1, length(st_classes$fill), 2)]))){ 192 | warning("- in st_classes$fill: duplicated classes were found. Default NULL was taken.", 193 | call. = FALSE) 194 | st_classes$fill <- c(rbind(cl_vals, 195 | hcl.colors(length(cl_vals), palette = st_classes$palette))) 196 | } 197 | 198 | # check alpha parameters 199 | if(!is.null(st_classes$alpha)){ 200 | if(length(st_classes$alpha)/2 != length(cl_vals)){ 201 | warning(strwrap("- number of alpha values defined in st_classes$alpha differ with the number of 202 | potential classes to plot. Default NULL was taken.", 203 | prefix = "\n", initial = ""), call. = FALSE) 204 | st_classes$alpha <- c(rbind(cl_vals, rep(1, length(cl_vals)))) 205 | } else { 206 | ok <- T 207 | for(i in seq(1, length(st_classes$alpha), 2)){ 208 | if(!st_classes$alpha[i] %in% orig_cl){ 209 | warning(paste0("- in st_classes$alpha: class '", st_classes$alpha[i], 210 | "' is not a defined class in 'x'. Default NULL was taken."), 211 | call. = FALSE) 212 | ok <- F 213 | break 214 | } 215 | } 216 | if(!ok){ 217 | st_classes$alpha <- c(rbind(cl_vals, rep(1, length(cl_vals)))) 218 | } 219 | } 220 | } else { 221 | st_classes$alpha <- c(rbind(cl_vals, rep(1, length(cl_vals)))) 222 | } 223 | 224 | for(i in seq(1, length(st_classes$alpha), 2)){ 225 | if(is.na(suppressWarnings(as.numeric(st_classes$alpha[i])))){ 226 | st_classes$alpha[i] <- x@classes[x@classes$classname == st_classes$alpha[i], "class"] 227 | } 228 | } 229 | 230 | if(any(duplicated(st_classes$alpha[seq(1, length(st_classes$alpha), 2)]))){ 231 | warning("- in st_classes$fill: duplicated classes were found. Default NULL was taken.", 232 | call. = FALSE) 233 | st_classes$alpha <- c(rbind(cl_vals, rep(1, length(cl_vals)))) 234 | } 235 | } else { 236 | if(any(length(st_ext) != 2, !is.character(st_ext))){ 237 | messages <- append(messages, "- argument 'st_ext' must be a character vector with the name 238 | of two colors. Default options were taken.") 239 | what <- append(what, 1) 240 | st_ext <- c("chartreuse", "firebrick1") 241 | } 242 | } 243 | } 244 | 245 | errors <- messages[which(what == 2)] 246 | warnings <- messages[which(what == 1)] 247 | 248 | out <- list(warnings = warnings, 249 | errors = errors, 250 | arg_name = arg_name, 251 | raster = raster, 252 | points = points, 253 | title = title, 254 | ncol = ncol, 255 | nrow = nrow, 256 | st_points = st_points, 257 | st_buffers = st_buffers, 258 | st_classes = st_classes, 259 | st_ext = st_ext) 260 | return(out) 261 | } 262 | -------------------------------------------------------------------------------- /R/mland_save.R: -------------------------------------------------------------------------------- 1 | save_rasts <- function(tmp, rast_dir, x_obj, gdal, ...){ 2 | if(length(x_obj) > 0){ 3 | for(i in 1:length(x_obj)){ 4 | r_dir <- paste0("raster_", i) 5 | dir.create(file.path(tmp, "MultiLand", rast_dir[1], rast_dir[2], r_dir)) 6 | if(is.list(x_obj[[i]])){ 7 | r_names <- as.list(names(x_obj[[i]])) 8 | for(j in 1:length(x_obj[[i]])){ 9 | terra::writeRaster(x_obj[[i]][[j]], file.path(tmp, "MultiLand", 10 | rast_dir[1], rast_dir[2], r_dir, 11 | paste0(r_names[j], ".tif")), 12 | gdal = gdal, ...) 13 | } 14 | } else { 15 | terra::writeRaster(x_obj[[i]], file.path(tmp, "MultiLand", 16 | rast_dir[1], rast_dir[2], r_dir, 17 | paste0("/raster_", i, ".tif")), 18 | gdal = gdal, ...) 19 | } 20 | } 21 | } 22 | } 23 | 24 | #' Saves a 'MultiLand' or 'MultiLandMetrics' object 25 | #' 26 | #' Exports an object of class 'MultiLand' to be read in the future with [mland_load()], or 27 | #' an object of class 'MultiLandMetrics' as if it was saved with [saveRDS()]. 28 | #' 29 | #' @param x Object of class 'MultiLand' or 'MultiLandMetrics'. 30 | #' @param name If `x` is an object of class 'MultiLand', the name of the zip file where 31 | #' files will be saved (without the '.zip'). If `x` is an object of class 'MultiLandMetrics', the name of the R file (.rds). If NULL (default), 32 | #' the name will be 'mland_' or 'mlandmetrics_' + a large random number. 33 | #' @param gdal GeoTiff creation options for rasters (\href{https://gdal.org/en/stable/drivers/raster/gtiff.html}{GeoTiff file format}). 34 | #' [mland_save()] uses the following compression options: c("COMPRESS=DEFLATE", "PREDICTOR=2", "ZLEVEL=9"). Only relevant 35 | #' if `x` is an object of class 'MultiLand'. 36 | #' @param dir Path to the export directory. This must be specified explicitly. 37 | #' To export to the current directory, use `dir = getwd()`. Otherwise, provide 38 | #' a valid path to an existing directory, ensuring it does not end with "/". 39 | #' @param verbose Print messages in the console? Default is TRUE. 40 | #' @param ... If `x` is an object of class 'MultiLand', `...` should depict other arguments passed to 41 | #' [terra::writeRaster], the function to write raster layers (from intersections and plain raster layers). 42 | #' Otherwise, if `x` is an object of class 'MultiLandMetrics', `...` should depict other arguments passed 43 | #' to [save()]. See Details. 44 | #' 45 | #' @details 'MultiLand' objects should be exported with this function rather than exporting as an 46 | #' external representation of R objects with [saveRDS()]. This is because objects of classes 47 | #' 'SpatVector' and 'SpatRaster' (from package terra) contained inside a 'MultiLand' 48 | #' object cannot be exported as regular R objects. The exported object will be a zip file, 49 | #' and can be loaded again into an R session with [mland_load()]. 50 | #' 51 | #' Relevant arguments can be passed to the function [terra::writeRaster], which is used to write 52 | #' raster layers from a 'MultiLand' object. Particularly, in the argument `gdal` one can specify 53 | #' relevant options regarding raster compression. This may reduce raster sizes significantly. Definition 54 | #' of some other arguments inside [terra::writeRaster] may affect exportation of raster layer 55 | #' objects, in the context of a 'MultiLand' object. 56 | #' 57 | #' Objects of class 'MultiLandMetrics', instead, do not contain 'SpatVector' or 'SpatRaster' objects 58 | #' and can be exported as regular R objects with [saveRDS()]. The user may use [saveRDS()] or 59 | #' [mland_save()], and the outcome will be identical. 60 | #' 61 | #' @return If `x` is an object of class 'MultiLand', a zip file or a directory containing all 62 | #' information regarding the 'MultiLand' object provided in 'x'. Otherwise, if `x` is an object of 63 | #' class 'MultiLandMetrics', the function will export the R object as if it was exported as a 64 | #' regular R object with [saveRDS()]. 65 | #' @export 66 | #' 67 | #' @seealso [mland_load()], [mland()], [mland_metrics()] 68 | #' 69 | #' @examples 70 | #' \donttest{ 71 | #' # Load MultiLand object 72 | #' mland_obj <- system.file("extdata", "ernesdesign.zip", package = "multilandr") 73 | #' ernesdesign2 <- mland_load(mland_obj) 74 | #' 75 | #' # Save it again, in temporary directory for this example and with a given name 76 | #' mland_save(ernesdesign2, name = "mland_example", dir = tempdir()) 77 | #' 78 | #' # Remove file for this example 79 | #' unlink(file.path(tempdir(), "mland_example.zip")) 80 | #' 81 | #' # Save it again but defining a higher compression for raster layers 82 | #' mland_save(ernesdesign2, gdal = "COMPRESS=DEFLATE", name = "mland_example", dir = tempdir()) 83 | #' 84 | #' # Remove file for this example 85 | #' unlink(file.path(tempdir(), "mland_example.zip")) 86 | #' 87 | #' # Loads a MultiLandMetrics object previously generated with mland_metrics() 88 | #' mlm_obj <- system.file("extdata", "ed_metrics.rds", package = "multilandr") 89 | #' ed_metrics2 <- mland_load(mlm_obj) 90 | #' 91 | #' # Save it again. In this case, mland_save() is the same as using saveRDS() 92 | #' mland_save(ed_metrics2, dir = tempdir(), name = "mlandmetrics_example") 93 | #' 94 | #' unlink(file.path(tempdir(), "mlandmetrics_example.rds")) 95 | #' } 96 | mland_save <- function(x, 97 | name = NULL, 98 | gdal = c("COMPRESS=DEFLATE", "PREDICTOR=2", "ZLEVEL=9"), 99 | dir = NULL, 100 | verbose = TRUE, 101 | ...){ 102 | 103 | if(!is(x, "MultiLand") & !is(x, "MultiLandMetrics")) 104 | stop("- argument 'x' must be an object of class 'MultiLand' or 'MultiLandMetrics'.") 105 | 106 | if(!is.null(name)){ 107 | if(!is.character(name)) 108 | stop("- if not NULL, argument 'name' must be a string with the name of the file.") 109 | } else { 110 | name <- keygen() 111 | if(is(x, "MultiLandMetrics")){ 112 | name <- paste0("mlandmetrics_", name) 113 | } else { 114 | name <- paste0("mland_", name) 115 | } 116 | } 117 | 118 | if(is(x, "MultiLandMetrics")){ 119 | #if(!substr(name, (nchar(name) + 1) - 4, nchar(name)) == ".rds"){ 120 | name <- paste0(dir, "/", name, ".rds") 121 | #} 122 | saveRDS(x, file = name, ...) 123 | return(invisible()) 124 | } 125 | 126 | if(file.exists(paste0(name, ".zip"))) 127 | stop("name: a file with the same name for the zip file already exist. Please choose another one.") 128 | 129 | if(is.null(dir)){ 130 | stop("dir: exporting directory must be defined explicitly. To set the working directory use dir = getwd()") 131 | } else { 132 | if(!dir.exists(dir)) 133 | stop("dir: could not find the provided directory.") 134 | } 135 | 136 | if(!is.logical(verbose)) 137 | warning("- argument 'verbose' must be logical. Default TRUE was taken.") 138 | 139 | dir.create(tmp <- tempfile()) 140 | dir.create(file.path(tmp, "MultiLand")) 141 | dir.create(file.path(tmp, "MultiLand", "points")) 142 | dir.create(file.path(tmp, "MultiLand", "buffers")) 143 | dir.create(file.path(tmp, "MultiLand", "/landscapes/lsm_rasters/"), recursive = T) 144 | dir.create(file.path(tmp, "MultiLand", "/landscapes/ext_rasters/"), recursive = T) 145 | 146 | # Save points and buffers 147 | suppressWarnings(terra::writeVector(x@points, file.path(tmp, "MultiLand", "points", "points.gpkg"), 148 | options = NULL)) 149 | suppressWarnings(terra::writeVector(x@buffers, file.path(tmp, "MultiLand", "buffers", "buffers.gpkg"), 150 | options = NULL)) 151 | 152 | # Save landscapes of main and rasters 153 | save_rasts(tmp, c("landscapes", "lsm_rasters"), x@landscapes$lsm_rasters, gdal, ...) 154 | save_rasts(tmp, c("landscapes", "ext_rasters"), x@landscapes$ext_rasters, gdal, ...) 155 | 156 | # Save object info 157 | info <- x 158 | info@points <- info@buffers <- terra::vect() 159 | if(length(info@landscapes$lsm_rasters) > 0){ 160 | for(i in 1:length(info@landscapes$lsm_rasters)){ 161 | info@landscapes$lsm_rasters[[i]] <- lapply(info@landscapes$lsm_rasters[[i]], function(x) NA) 162 | } 163 | } 164 | if(length(info@landscapes$ext_rasters) > 0){ 165 | for(i in 1:length(info@landscapes$ext_rasters)){ 166 | info@landscapes$ext_rasters[[i]] <- lapply(info@landscapes$ext_rasters[[i]], function(x) NA) 167 | } 168 | } 169 | saveRDS(info, file = file.path(tmp, "MultiLand", "info.rds")) 170 | 171 | if(verbose){ 172 | cat(strwrap("MultiLand\n\n 173 | This directory was created by R package multilandr.\n 174 | No modifications of folders or files should be made by hand.\n 175 | This folder, as a zip file, may be loaded into an R session as a 'MultiLand' object with function 176 | mland_load().", 177 | prefix = "\n", initial = ""), file = file.path(tmp, "MultiLand", "README.txt")) 178 | } 179 | 180 | # Generates zip file 181 | last_wd <- getwd() 182 | zipfile <- paste0(dir, "/", name, ".zip") 183 | setwd(tmp) 184 | utils::zip(zipfile, ".") 185 | setwd(last_wd) 186 | unlink(file.path(tmp), recursive = T) 187 | message(paste0("'MultiLand' object successfully exported as '", name, ".zip'.")) 188 | } 189 | -------------------------------------------------------------------------------- /R/utils.R: -------------------------------------------------------------------------------- 1 | # Copyright (C) 2010-2012 The R Core Team 2 | tryCatch.W.E <- function(expr) 3 | { 4 | W <- NULL 5 | w.handler <- function(w){ # warning handler 6 | W <<- w 7 | invokeRestart("muffleWarning") 8 | } 9 | out <- list(value = withCallingHandlers(tryCatch(expr, error = function(e) e), 10 | warning = w.handler), warning = W) 11 | if(!is.null(out$warning)){ 12 | message("landscapemetrics warnings:") 13 | message(paste0(out$warning)) 14 | } 15 | return(out) 16 | } 17 | 18 | is.wholenumber <- function(x, tol = .Machine$double.eps^0.5) abs(x - round(x)) < tol 19 | 20 | is.positive.wholenumber <- function(x){ 21 | if(!is.na(x)){ 22 | if(all(is.wholenumber(x), x > 0)) T else F 23 | } else { 24 | F 25 | } 26 | } 27 | 28 | is.positive.numeric <- function(x){ 29 | if(all(is.numeric(x), x > 0)) T else F 30 | } 31 | 32 | is.numberinchar <- function(x){ 33 | if(is.na(suppressWarnings(as.numeric(x)))) F else T 34 | } 35 | 36 | # Obtains legend from plot 37 | # Credits to Luciano Selzer: 38 | # https://stackoverflow.com/questions/11883844/inserting-a-table-under-the-legend-in-a-ggplot2-histogram 39 | .g_legend <- function(a.gplot){ 40 | tmp <- ggplot2::ggplot_gtable(ggplot2::ggplot_build(a.gplot)) 41 | leg <- which(sapply(tmp$grobs, function(x) x$name) == "guide-box") 42 | if(length(leg) > 0){ 43 | legend <- tmp$grobs[[leg]] 44 | } else { 45 | legend <- NULL 46 | } 47 | return(legend) 48 | } 49 | 50 | length_unique <- function(x){ length(unique(x)) } 51 | 52 | mmerge <- function(x){ 53 | merged_raster <- terra::merge(x[[1]], x[[2]]) 54 | if(length(x) > 2){ 55 | for(i in 3:length(x)){ 56 | merged_raster <- terra::merge(merged_raster, x[[i]]) 57 | } 58 | } 59 | merged_raster 60 | } 61 | 62 | keygen <- function(){ 63 | id <- "" 64 | for(i in 1:9){ id <- paste0(id, sample(1:9, 1)) } 65 | id 66 | } 67 | 68 | rbind_and_remove <- function(x, y, cols){ 69 | x <- rbind(x, y) 70 | index <- rownames(unique(x[, cols])) 71 | x 72 | } 73 | 74 | rbind_and_replace <- function(x, y, cols){ 75 | y <- rbind(y, x) 76 | y <- y[!duplicated(y[, cols], fromLast = T), ] 77 | y 78 | } 79 | 80 | show_sample <- function(x, limit = 6){ 81 | if(length(x) > limit){ 82 | x <- c(x[1:limit], "...") 83 | } 84 | x 85 | } 86 | -------------------------------------------------------------------------------- /cran-comments.md: -------------------------------------------------------------------------------- 1 | ## R CMD check results 2 | 3 | 0 errors | 0 warnings | 1 note 4 | 5 | * This is a new release. 6 | 7 | * checking CRAN incoming feasibility ... [6s/22s] NOTE 8 | Maintainer: ‘Pablo Yair Huais ’ 9 | 10 | New submission 11 | 12 | Possibly misspelled words in DESCRIPTION: 13 | Huais (8:627) 14 | multilandr (8:688) 15 | -------------------------------------------------------------------------------- /data/ed_metrics.rda: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/phuais/multilandr/3b1d7fa40858c26a72186480a3b7a7aabfa13021/data/ed_metrics.rda -------------------------------------------------------------------------------- /data/otf_metrics.rda: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/phuais/multilandr/3b1d7fa40858c26a72186480a3b7a7aabfa13021/data/otf_metrics.rda -------------------------------------------------------------------------------- /inst/CITATION: -------------------------------------------------------------------------------- 1 | citHeader("To cite multilandr or acknowledge its use, please cite the following paper:") 2 | 3 | bibentry( 4 | bibtype = "Article", 5 | title = {"multilandr: An R package for multi-scale landscape analysis"}, 6 | author = as.person("Pablo Yair Huais"), 7 | journal = {"Landscape Ecology"}, 8 | volume = {"39"}, 9 | number = {"140"}, 10 | year = {"2024"}, 11 | doi = {"10.1007/s10980-024-01930-z"}, 12 | textVersion = "Huais, P.Y. multilandr: an R package for multi-scale landscape analysis. Landscape Ecology 39, 140 (2024). https://doi.org/10.1007/s10980-024-01930-z") 13 | -------------------------------------------------------------------------------- /inst/extdata/ed_metrics.rds: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/phuais/multilandr/3b1d7fa40858c26a72186480a3b7a7aabfa13021/inst/extdata/ed_metrics.rds -------------------------------------------------------------------------------- /inst/extdata/elchaco.tif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/phuais/multilandr/3b1d7fa40858c26a72186480a3b7a7aabfa13021/inst/extdata/elchaco.tif -------------------------------------------------------------------------------- /inst/extdata/elchaco2.tif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/phuais/multilandr/3b1d7fa40858c26a72186480a3b7a7aabfa13021/inst/extdata/elchaco2.tif -------------------------------------------------------------------------------- /inst/extdata/elchaco_ndvi.tif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/phuais/multilandr/3b1d7fa40858c26a72186480a3b7a7aabfa13021/inst/extdata/elchaco_ndvi.tif -------------------------------------------------------------------------------- /inst/extdata/elchaco_sites.gpkg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/phuais/multilandr/3b1d7fa40858c26a72186480a3b7a7aabfa13021/inst/extdata/elchaco_sites.gpkg -------------------------------------------------------------------------------- /inst/extdata/ernesdesign.zip: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/phuais/multilandr/3b1d7fa40858c26a72186480a3b7a7aabfa13021/inst/extdata/ernesdesign.zip -------------------------------------------------------------------------------- /inst/extdata/otf_sites.gpkg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/phuais/multilandr/3b1d7fa40858c26a72186480a3b7a7aabfa13021/inst/extdata/otf_sites.gpkg -------------------------------------------------------------------------------- /man/MultiLand-class.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/classes.R 3 | \docType{class} 4 | \name{MultiLand-class} 5 | \alias{MultiLand-class} 6 | \title{Class "MultiLand"} 7 | \description{ 8 | Objects of class 'MultiLand' are created with the function \code{\link[=mland]{mland()}}, and holds 9 | relevant objects and information to be passed to other functions of the package. The slot 10 | \verb{@buffers} holds an object of class 'SpatVector' with the buffers for each point 11 | contained in the slot \verb{@points} and each radius defined in slot \verb{@radii}. The slot 12 | \verb{@buffers@data} holds a data.frame with the identification of each buffer (individualized by a 13 | point id and a radius value). 14 | } 15 | \details{ 16 | If the slot \verb{@on_the_fly} equals \code{FALSE}, the slot \verb{@landscapes} holds the intersections (objects of class 'SpatRaster') between 17 | buffers and the raster layers inputted by the user when running \code{\link[=mland]{mland()}}. Intersections 18 | between buffers and raster layers with discrete values (inputted in argument \code{raster} in \code{\link[=mland]{mland()}}) are 19 | contained inside a list named 'lsm_rasters', whereas intersections between extra raster layers 20 | (inputted in argument \code{ext_rast_layer} in \code{\link[=mland]{mland()}}) and buffers 21 | are contained inside a list named 'ext_rasters'. Each list ('lsm_rasters' and 'ext_rasters') contains a 22 | list with as many elements as previously inputted raster layers. Additionally, each element of 23 | this latter list holds an additional internal list, with as many elements as intersections (i.e. rasters generated by the intersections between buffers defined 24 | by each point and radius, and the raster layer). The name of each element of each internal list 25 | reveals the information related to a given intersection, with the following coding: "RasterLayerL-P-R" or 26 | "ExtRasterLayerL-P-R", where L is the 27 | given raster layer, P is the id of the point and R is the radius. For example, a plausible 28 | intersection may be named as "RasterLayer1-5-1500", indicating that this element holds a raster 29 | layer which is the result of the intersection between RasterLayer1 and the buffer around point 5 and 30 | radius 1500 m. 31 | 32 | If slot \verb{@on_the_fly} equals \code{FALSE}, the slot \verb{@landscapes} holds a list containing two named lists 33 | as 'lsm_rasters' and 'ext_rasters'. Each one contains a list with as many raster layers were initially 34 | inputted by the user when running \code{\link[=mland]{mland()}} in arguments \code{rast_layer} and \code{ext_rast_layer}. 35 | This means that no intersections were 36 | made when creating the 'MultiLand' object. Intersections will be created "on the fly" when other functions of 37 | the package requires them. 38 | } 39 | \section{Slots}{ 40 | 41 | \describe{ 42 | \item{\code{call}}{The call when function \code{\link[=mland]{mland()}} was called.} 43 | 44 | \item{\code{idkey}}{A unique identification id for the 'MultiLand' object.} 45 | 46 | \item{\code{crs_proj}}{A string depicting the CRS of points layer.} 47 | 48 | \item{\code{points}}{An object of class 'SpatVector'. Holds the points inputted by the user.} 49 | 50 | \item{\code{buffers}}{An object of class 'SpatVector'. Holds the buffers layers.} 51 | 52 | \item{\code{site_ref}}{String holding the name of the attribute that the user defined as 53 | the one that identifies individual points and is contained inside the layer of points.} 54 | 55 | \item{\code{radii}}{Vector of numbers containing the radii that defined the creation of buffers.} 56 | 57 | \item{\code{n_layers}}{Number of raster layers (defined in argument \code{raster} in \code{\link[=mland]{mland()}}) from which i 58 | ntersections between were created (or will be if slot \verb{@on_the_fly = TRUE}).} 59 | 60 | \item{\code{n_classes}}{A numeric vector depicting the number of classes (raster values) per raster 61 | layer (defined in argument \code{raster} in \code{\link[=mland]{mland()}}).} 62 | 63 | \item{\code{classes}}{A data.frame depicting the classes (and classes names) for each rasterlayer 64 | (defined in argument \code{raster} in \code{\link[=mland]{mland()}}).} 65 | 66 | \item{\code{on_the_fly}}{A logical value indicating whether intersections between buffers and raster layers 67 | were created (FALSE) or not (TRUE).} 68 | 69 | \item{\code{landscapes}}{If \code{on_the_fly = FALSE}, this slot holds the intersections between buffers and 70 | raster layers. Otherwise, if \code{on_the_fly = TRUE}, it holds the raw raster layers.} 71 | 72 | \item{\code{l_ref}}{A data.frame relating each point and radius with a "row_id", equal to the position of 73 | its buffer in the slot \verb{@buffers} and to the position of the intersection for each point/radius in 74 | the slot \verb{@landscapes} (if \code{on_the_fly = TRUE}).} 75 | 76 | \item{\code{rast_names}}{A list containing two data.frame with the names assigned by the user for the main raster layers 77 | and extra raster layers defined in argument \code{rast_layer} and \code{ext_rast_layer} in \code{\link[=mland]{mland()}}.} 78 | }} 79 | 80 | \examples{ 81 | # Shows information of object 'MultiLand' 82 | ernesdesign <- system.file("extdata", "ernesdesign.zip", package = "multilandr") 83 | ernesdesign <- mland_load(ernesdesign) 84 | ernesdesign 85 | } 86 | -------------------------------------------------------------------------------- /man/MultiLandMetrics-class.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/classes.R 3 | \docType{class} 4 | \name{MultiLandMetrics-class} 5 | \alias{MultiLandMetrics-class} 6 | \title{Class 'MultiLandMetrics'} 7 | \description{ 8 | Objects of class \code{MultiLandMetrics} are returned by \code{\link[=mland_metrics]{mland_metrics()}}. It holds all the information 9 | relative to the metrics that were calculated by the parameters inputted by the user. This object 10 | class can be passed to functions \code{\link[=metrics_corr]{metrics_corr()}}, \code{\link[=metrics_plots]{metrics_plots()}}, \code{\link[=metrics_filter]{metrics_filter()}}, \code{\link[=metrics_gradient]{metrics_gradient()}} and 11 | \code{\link[=metrics_bind]{metrics_bind()}} for further analyses. 12 | } 13 | \section{Slots}{ 14 | 15 | \describe{ 16 | \item{\code{call}}{The call when function \code{\link[=mland_metrics]{mland_metrics()}} was called.} 17 | 18 | \item{\code{idkey}}{A unique identification id for the 'MultiLandMetrics' object.} 19 | 20 | \item{\code{crs_proj}}{A string depicting the CRS of points layer.} 21 | 22 | \item{\code{n_layers}}{Number of raster layers from which metrics were calculated.} 23 | 24 | \item{\code{rast_names}}{A list with dataframes containing the names of the raster layers of the 25 | 'MultiLand' object the function \code{\link[=mland_metrics]{mland_metrics()}} worked with.} 26 | 27 | \item{\code{classes}}{A data.frame depicting the raster layers, classes and classes names from which 28 | metrics were calculated.} 29 | 30 | \item{\code{n_classes}}{Numeric vector depicting the number of distinct classes per raster layer 31 | from which metrics were calculated.} 32 | 33 | \item{\code{points}}{A data.frame containing points coordinates and other attributes.} 34 | 35 | \item{\code{n_points}}{Number of points from which metrics were calculated.} 36 | 37 | \item{\code{site_names}}{Logical. Whether points have associated site names or not.} 38 | 39 | \item{\code{radii}}{Distinct radii from which metrics were calculated.} 40 | 41 | \item{\code{metrics}}{A data.frame depicting the metrics that were calculated, classified by level.} 42 | 43 | \item{\code{data}}{Main data.frame with the values of the metrics that were calculated for each 44 | point, radius, raster layers and other parameters pre-defined by the user.} 45 | 46 | \item{\code{ext_calcs}}{A data.frame depicting the extra calculations that were made in given extra 47 | raster layers.} 48 | }} 49 | 50 | \examples{ 51 | # Shows information of object 'MultiLandMetrics' 52 | ed_metrics 53 | otf_metrics 54 | } 55 | -------------------------------------------------------------------------------- /man/check_raster.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/check_raster.R 3 | \name{check_raster} 4 | \alias{check_raster} 5 | \title{Check input raster} 6 | \usage{ 7 | check_raster(raster, verbose = TRUE) 8 | } 9 | \arguments{ 10 | \item{raster}{An object of class 'RasterLayer', 'RasterStack', 'RasterBrick', 'SpatRaster', 11 | or a list of raster objects (one of 'RasterLayer' or 'SpatRaster').} 12 | 13 | \item{verbose}{Print warning messages in the console? Default is TRUE.} 14 | } 15 | \value{ 16 | A data frame with relevant information about the inputted raster. 17 | } 18 | \description{ 19 | Checks the validity of raster layers to be inputted in \code{\link[=mland]{mland()}}, intended to represent land cover. The function directly calls 20 | \code{\link[landscapemetrics:check_landscape]{landscapemetrics::check_landscape()}}. 21 | } 22 | \details{ 23 | Extracts basic information about the inputted raster: coordinate reference system (crs) - either "geographic", 24 | "projected", or NA, units of the 25 | coordinate reference system, class for the values of the inputted raster and the number of classes 26 | found in the raster. 27 | } 28 | -------------------------------------------------------------------------------- /man/conditions.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/metrics_filter.R 3 | \name{conditions} 4 | \alias{conditions} 5 | \title{Define metric conditions} 6 | \usage{ 7 | conditions(...) 8 | } 9 | \arguments{ 10 | \item{...}{Patch or metric conditions in the form of lists. See Details.} 11 | } 12 | \value{ 13 | A list to be inputted within the argument \code{patch_conditions} in \code{\link[=generate_points]{generate_points()}} or 14 | the argument \code{conditions} in \code{\link[=metrics_filter]{metrics_filter()}}. 15 | } 16 | \description{ 17 | Helper function to define patch conditions within \code{\link[=generate_points]{generate_points()}} or 18 | metric conditions within \code{\link[=metrics_filter]{metrics_filter()}}. 19 | } 20 | \details{ 21 | Conditions must be defined as lists (one or more). 22 | 23 | For patch conditions, within 24 | the environment of \code{\link[=generate_points]{generate_points()}}, each element within the list defines the condition 25 | that the patch must meet in relation to the value of certain patch-level metric, as follows: 26 | 27 | \preformatted{ 28 | list(class, metric, minimum value, maximum value) 29 | } 30 | \itemize{ 31 | \item class: the class (raster value) of the patch that must meet the defined conditions. More than one class can 32 | be specified. 33 | \item metric: the patch-level metric whose values must meet the defined conditions. Only one metric 34 | per condition can be defined. Available patch-level metrics can be found in \code{\link[=metrics_list]{metrics_list()}} and in 35 | documentation of the package \code{landscapemetrics}. 36 | \item minimum value: the minimum value that the metric must have for the retained patches. If equal 37 | to -Inf, and a maximum value is defined, patches whose values in the defined metric are equal 38 | or lower to the maximum value will be retained. 39 | \item maximum value: the maximum value that the metric must have in the retained patches. If equal 40 | to Inf, and a minimum value is defined, patches whose values in the defined metric are equal 41 | or higher to the minimum value will be retained. 42 | } 43 | 44 | For metric conditions, within 45 | the environment of \code{\link[=metrics_filter]{metrics_filter()}}, each element within the list defines the required 46 | metric conditions, as follows: 47 | 48 | \preformatted{ 49 | list(rasterlayers, class, radii, metric, minimum value, maximum value) 50 | } 51 | \itemize{ 52 | \item rasterlayers: the raster layers to be considered. If NA, all raster layers will be considered. If 53 | an extra raster layer must be specified, the string "ext" must precede the raster layer number 54 | (e.g. "ext1", "ext2"). 55 | \item class: the classes to be considered, as numbers or strings with the names of the classes. If NA, all classes of required raster layers will be 56 | considered. If NULL, the function will assume that the metric to be considered is a landscape-level metric. 57 | Take into account that metrics from extra calculations are considered as landscape-level metrics. 58 | \item radii: the radii to be considered. If NA, all radii will be considered. 59 | \item metrics: the name of the metric to be considered (as defined with its abbreviation by column "metric" in \code{\link[=metrics_list]{metrics_list()}}). 60 | Only one metric per condition can be defined. Metrics as extra calculations for extra raster layers must be 61 | provided as "fun_" + the name of the function (e.g. "fun_mean"). 62 | \item minimum value: the minimum value that the metric must have in the filtered landscapes. If equal 63 | to -Inf, and a maximum value is defined, landscapes whose values in the defined metric are equal 64 | or lower to the maximum value will be retained. 65 | \item maximum value: the maximum value that the metric must have in the filtered landscapes. If equal 66 | to Inf, and a minimum value is defined, landscapes whose values in the defined metric are equal 67 | or higher to the minimum value will be retained. 68 | } 69 | 70 | See the example sections of functions \code{\link[=generate_points]{generate_points()}} and 71 | \code{\link[=metrics_filter]{metrics_filter()}} for more details. 72 | } 73 | -------------------------------------------------------------------------------- /man/ed_metrics.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/data.R 3 | \docType{data} 4 | \name{ed_metrics} 5 | \alias{ed_metrics} 6 | \title{'MultiLandMetrics' object} 7 | \format{ 8 | An object of class \code{MultiLandMetrics} of length 1. 9 | } 10 | \usage{ 11 | ed_metrics 12 | } 13 | \description{ 14 | An object of class 'MultiLandMetrics' generated with \code{\link[=mland_metrics]{mland_metrics()}}, for the purposes of package 15 | examples of the following functions: \code{\link[=metrics_filter]{metrics_filter()}}, \code{\link[=metrics_gradient]{metrics_gradient()}}, 16 | \code{\link[=metrics_corr]{metrics_corr()}}, \code{\link[=metrics_plots]{metrics_plots()}} and \code{\link[=metrics_bind]{metrics_bind()}}. See 'MultiLand-class' 17 | for general information about these objects. 18 | } 19 | \details{ 20 | The main internal object is a data.frame (accesible through \code{ed_metrics@data}) with information 21 | about the values of two landscape metrics: "pland" (percentage of landscape) and "ed" (edge density). 22 | 23 | The object was created from the MultiLand object named "ernesdesign", which 24 | received two raster layers from a small portion of the ecoregion "El Chaco" as main inputs. The main rasterlayer 25 | was provided by the project "MapBiomas Chaco" for the year 2000. 26 | The extra rasterlayer contained the NDVI values of cells within the same extent of the main rasterlayer, and was provided by Landsat. 27 | } 28 | \references{ 29 | Project MapBiomas Chaco – Collection 4.0 of annual land cover and land use maps, 30 | accessed during July 2022 through the following link: \href{https://chaco.mapbiomas.org/}{MapBiomas Chaco} 31 | 32 | Landsat-5 image courtesy of the U.S. Geological Survey 33 | } 34 | \seealso{ 35 | See the examples sections of \code{\link[=mland_metrics]{mland_metrics()}} and \code{\link[=mland]{mland()}} 36 | for more context. 37 | } 38 | \keyword{datasets} 39 | -------------------------------------------------------------------------------- /man/figures/logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/phuais/multilandr/3b1d7fa40858c26a72186480a3b7a7aabfa13021/man/figures/logo.png -------------------------------------------------------------------------------- /man/figures/plot_peje.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/phuais/multilandr/3b1d7fa40858c26a72186480a3b7a7aabfa13021/man/figures/plot_peje.png -------------------------------------------------------------------------------- /man/generate_points.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/generate_points.R 3 | \name{generate_points} 4 | \alias{generate_points} 5 | \title{Generates point coordinates} 6 | \usage{ 7 | generate_points( 8 | raster, 9 | approach = "grid", 10 | n = NULL, 11 | padding = 0, 12 | try = NULL, 13 | values = NULL, 14 | patch_conditions = NULL, 15 | trim = TRUE, 16 | attempts = 10, 17 | distance = NULL, 18 | offset = FALSE, 19 | closest_cell = FALSE, 20 | parallel = FALSE, 21 | cores = 1, 22 | progress = TRUE 23 | ) 24 | } 25 | \arguments{ 26 | \item{raster}{An object of class 'SpatRaster', 'RasterLayer', 'RasterStack' or 'RasterBrick'.} 27 | 28 | \item{approach}{One of the following: "grid" to generate points through a grid, "random" to 29 | generate points at random locations, or "patch" to generate points inside patches that meet 30 | pre-defined conditions. See Details.} 31 | 32 | \item{n}{Number of point to generate.} 33 | 34 | \item{padding}{Numeric. Width (in meters) of the internal margin around the raster that will be 35 | discarded from the analysis. See Details.} 36 | 37 | \item{try}{Number of points to be generated in 38 | each turn. Only applies if \code{approach = "random"}. See Details.} 39 | 40 | \item{values}{The values of the rasterlayer where points should be placed. Only applies if 41 | \code{approach = "random"}.} 42 | 43 | \item{patch_conditions}{The conditions that patches must meet to be included as the 44 | patches from which points will be generated. Only applies if \code{approach = "patch"}. See Details.} 45 | 46 | \item{trim}{Logical. If TRUE (default) the number of final points will be trimmed to the value 47 | defined in \code{n}.} 48 | 49 | \item{attempts}{Number of attempts to generate new random points given the total required 50 | points (\code{n}) and the minimum distance required in \code{distance}. Only applies if 51 | \code{approach = "random"}. See Details.} 52 | 53 | \item{distance}{Distance between points of the grid (if \code{approach = "grid"}) or minimum distance 54 | between generated points (if \code{approach = "random"}).} 55 | 56 | \item{offset}{Logical. If TRUE, each point coordinates will be randomly displaced around the area 57 | occupied by the raster cell size. If FALSE (default), each point will be located at the center of 58 | a given raster cell. Only applies if \code{approach = "random"}.} 59 | 60 | \item{closest_cell}{Logical. If \code{approach = "patch"}, whether to return the coordinates of each patch centroid even if 61 | they fall outside the patch (FALSE, default) or to move the point to the 62 | closest cell of the patch if this happens (TRUE).} 63 | 64 | \item{parallel}{Logical. If TRUE, part of the processes will be parallelized. See Details.} 65 | 66 | \item{cores}{Number of cores to use if \code{parallel = TRUE}.} 67 | 68 | \item{progress}{Logical. If TRUE (default), progress of the analysis will be printed.} 69 | } 70 | \value{ 71 | An object of class 'SpatVector' containing the coordinates of the generated points. 72 | } 73 | \description{ 74 | Generates point coordinates over a rasterlayer extent. 75 | } 76 | \details{ 77 | If \code{approach = "random"}, the user can restrict the locations of new generated points 78 | inside raster cells with certain value or values, by defining them in \code{values}. Also a minimum distance 79 | between the generated points can be defined in \code{distance} (also applies for the resolution of 80 | the grid if \code{approach = "grid"}). 81 | 82 | If \code{approach = "random"} and a minimum distance was defined, the function will generate new 83 | "random" points in sequential passes. In each pass, the function will try to generate new points 84 | taking into account the minimum distance between points, by randomly generating a number of points as 85 | defined in \code{try}. The function will perform this task until the new generated points is equal or 86 | higher than \code{n}. If \code{try = NULL} (default), \code{try} will equals \code{n}. If in each turn no new points 87 | were added (i.e. new points were located at less than the minimum distance to other previously 88 | generated points), the function will record this event. If this event happens more than the 89 | number of times defined in \code{attempts} before the total generated points equals \code{n}, the function will 90 | terminate, and return the points that were successfully generated given the required parameters. 91 | The user may try different values for \code{n}, \code{try} and \code{attempts} to get a desirable result. 92 | 93 | If \code{approach = "patch"}, the function will return as many points as patches that meet certain 94 | conditions in relation to pre-defined metric values. Conditions can be defined in 95 | argument \code{patch_conditions}, for which the helper function \code{\link[=conditions]{conditions()}} is available: 96 | 97 | \preformatted{ 98 | conditions(list(class, metric, minimum value, maximum value), 99 | list(class, metric, minimum value, maximum value), ...) 100 | } 101 | \itemize{ 102 | \item class: the class (raster value) of the patch that must meet the defined conditions. More than one class can 103 | be specified. 104 | \item metric: the patch-level metric whose values must meet the defined conditions. Only one metric 105 | per condition can be defined. Available patch-level metrics can be found in \code{\link[=metrics_list]{metrics_list()}} and in 106 | documentation of the package \code{landscapemetrics}. 107 | \item minimum value: the minimum value that the metric must have for the retained patches. If equal 108 | to -Inf, and a maximum value is defined, patches whose values in the defined metric are equal 109 | or lower to the maximum value will be retained. 110 | \item maximum value: the maximum value that the metric must have in the retained patches. If equal 111 | to Inf, and a minimum value is defined, patches whose values in the defined metric are equal 112 | or higher to the minimum value will be retained. 113 | } 114 | 115 | Retained patches will be those patches that meet all patch conditions at the same time. Returned 116 | point's coordinates will equal the centroid of each patch. If \code{closest_cell = TRUE}, the point's coordinates of the 117 | centroids that did not fall inside the patch will be moved to the closest cell belonging to that 118 | patch. 119 | 120 | To avoid generating points to close to the boundaries of the raster, the outer borders of the 121 | raster can be discarded from the analysis, by considering the width inputted in \code{padding}. 122 | 123 | If \code{parallel = TRUE} the function will parallelize part of the processes. Parallelization 124 | is done to obtain the coordinates of the patches if \code{approach = "patch"}. The number of 125 | cores must be declared in \code{cores} (parallelization requires at least two cores). To use this 126 | functionality, package \code{parallel} must be installed. So far, parallelization will run 127 | in LINUX and MAC, but not in Windows. 128 | } 129 | \examples{ 130 | \donttest{ 131 | # Loads raster 132 | elchaco <- terra::rast(system.file("extdata", "elchaco.tif", package = "multilandr")) 133 | 134 | # Returns points at "random" locations, but inside cells of value equals to 1. 135 | chaco_coords <- generate_points(elchaco, approach = "random", values = 1, n = 500) 136 | 137 | # The same but points must be separated by at least 300 m between each other. Also, each point 138 | # is randomly displaced inside the raster cell. 139 | chaco_coords2 <- generate_points(elchaco, approach = "random", values = 1, n = 500, 140 | try = 100, distance = 300, offset = TRUE) 141 | 142 | # Returns as many points as patches that meet the defined condition. This is 143 | # all patches of value equal to 1 of area between 9 and 11 hectares. 144 | patch_sites <- generate_points(elchaco, approach = "patch", 145 | patch_conditions = conditions(list(1, "area", 8, 12)), 146 | padding = 2000) 147 | } 148 | } 149 | \seealso{ 150 | \code{\link[=mland]{mland()}} 151 | } 152 | -------------------------------------------------------------------------------- /man/metrics_bind.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/metrics_bind.R 3 | \name{metrics_bind} 4 | \alias{metrics_bind} 5 | \title{Metric's data preparation} 6 | \usage{ 7 | metrics_bind( 8 | x, 9 | data, 10 | raster = NULL, 11 | classes = NULL, 12 | radii = NULL, 13 | c_level = NULL, 14 | l_level = NULL, 15 | ext_raster = NULL, 16 | show_class_names = FALSE 17 | ) 18 | } 19 | \arguments{ 20 | \item{x}{An object of class 'MultiLandMetrics' generated with \code{\link[=mland_metrics]{mland_metrics()}}.} 21 | 22 | \item{data}{A data.frame with data from each sampling point/site. See Details.} 23 | 24 | \item{raster, ext_raster, classes, radii, l_level, c_level}{Parameters to subset data.frame containing the 25 | metrics values. See Details.} 26 | 27 | \item{show_class_names}{Logical. If TRUE, classes names will be returned as the names of the classes 28 | previously provided (if so) when \code{x} was generated. Default FALSE.} 29 | } 30 | \value{ 31 | A data.frame equal to sampling data provided in \code{data} but with additional columns 32 | containing the values of the metrics for each sampling site. 33 | } 34 | \description{ 35 | Merge data.frame with metric's values with a data.frame with other data. 36 | } 37 | \details{ 38 | Merges data.frame with metrics values, contained in an object of 39 | class 'MultiLandMetrics' (returned by \code{\link[=mland_metrics]{mland_metrics()}}) with a data.frame with other data for each 40 | site. In this way, the returned data.frame will be prepared for later statistical or 41 | visual analyses. The data.frame provided in \code{data} must have a column named "site" or "point_id", 42 | containing unique identifiers for each sampling site, which must match with the identifiers 43 | present in the data.frame contained in \code{x} (i.e. data.frame with metrics values for each site). 44 | If "site", the function will assume that the site names are provided as identifiers. If "point_id", 45 | the function will assume that point ids are being provided. In any case, these identifiers must 46 | match the site identifiers in \code{x}. 47 | 48 | Argument \code{raster}, \code{ext_raster}, \code{classes}, \code{radii}, \code{l_level} and \code{c_level} can be defined to 49 | subset the data.frame contained in \code{x}. In each one of these, an all-positive or an 50 | all-negative vector can be passed, whether to include (all-postive) or exclude (all-negative) 51 | the elements to be taken into account for the subsetting: 52 | \itemize{ 53 | \item rasterlayers: a numeric vector with the number of the raster layers to be included/excluded. 54 | For example: \code{c(1, 2, 4)} to include raster layers 1, 2 and 4; \code{c(-2, -3)} to exclude raster layers 2 55 | and 3. 56 | \item classes: must be a list with as many elements as defined raster layers in argument 57 | \code{rasterlayers}. Each element of the list must be a numeric vector (classes identities) with the 58 | classes to be included/excluded. If provided a character vector, \code{\link[=metrics_bind]{metrics_bind()}} assumes that 59 | classes names are provided. For example, for the case with 2 raster layers: 60 | \code{list(c(3, 20, 35), c("Forest", "Crops"))} would include classes 3, 20 and 35 from rasterl ayer 1 61 | and classes "Forest" and "Crops" for raster layer 2. For the case of a unique rasterlayer, there 62 | is no need to input a list. For example, for the case of a unique raster layer and the 63 | exclusion of some classes: \code{c(-5, -10, -15)} to exclude classes 5, 10 and 15 of 64 | the unique raster layer; \code{c("-Forest", "-Grassland")} to exclude classes "Forest" and "Grassland". 65 | Note the "-" before each class name to indicate the exclusion of the classes. 66 | \item radii: a numeric vector to include/exclude particular radii. For example: \code{c(1000, 2000)} to 67 | include only radii of 1000 and 2000 m; \code{c(-500, -1500)} to exclude radii of 500 and 1500 m. 68 | \item c_level: character vector with the class-level metrics to be included/excluded from 69 | the analysis. For example: \code{c("np", "pland")} will include only the metrics "number of patches" 70 | ("np") and "percentage of the landscape" ("pland") in the analysis, whereas \code{c("-np", "-pland")} 71 | will exclude them. Note the "-" before each metric name to indicate the exclusion of the 72 | metrics. 73 | \item l_level: character vector with the landscape-level metrics to be included/excluded from 74 | the analysis. Extra calculations for extra raster layers are considered as landscape-level metrics, 75 | and must be provided as "fun_" + the name of the function. 76 | } 77 | } 78 | \examples{ 79 | # Get sites names from ed_metrics and creates ad-hoc data.frame with random values of 80 | # "richness" (the response variable). Only for the purpose of this example 81 | sites <- ed_metrics@points$name 82 | sampling_data <- data.frame(site = rep(sites, each = 10), 83 | richness = sample(1:500, 150)) 84 | 85 | # With no filters, all columns with all metrics at all spatial scales are added to 86 | # the sampling data 87 | new_data <- metrics_bind(ed_metrics, sampling_data) 88 | 89 | # Subset for metrics of class "Forest", radius 5000 and metric "pland" 90 | new_data <- metrics_bind(ed_metrics, sampling_data, show_class_names = TRUE, 91 | classes = "Forest", radii = 3000, c_level = "pland") 92 | 93 | # In this format, the data.frame can be passed to a fitting model 94 | fit <- lm(richness ~ r1_Forest_pland_3000, data = new_data) 95 | } 96 | \seealso{ 97 | \code{\link[=mland_metrics]{mland_metrics()}} 98 | } 99 | -------------------------------------------------------------------------------- /man/metrics_corr.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/metrics_corr.R 3 | \name{metrics_corr} 4 | \alias{metrics_corr} 5 | \title{Pairwise metric correlations} 6 | \usage{ 7 | metrics_corr( 8 | x, 9 | method = "pearson", 10 | fun = NULL, 11 | raster = NULL, 12 | classes = NULL, 13 | radii = NULL, 14 | c_level = NULL, 15 | l_level = NULL, 16 | ext_raster = NULL, 17 | show_class_names = FALSE, 18 | display = "radii", 19 | ... 20 | ) 21 | } 22 | \arguments{ 23 | \item{x}{An object of class 'MultiLandMetrics' generated with \code{\link[=mland_metrics]{mland_metrics()}}.} 24 | 25 | \item{method}{The method to be used to calculate pair correlations: "pearson" (default), 26 | "spearman" or "kendall".} 27 | 28 | \item{fun}{A user-defined function to calculate correlations. See Details.} 29 | 30 | \item{raster, ext_raster, classes, radii, l_level, c_level}{Parameters to subset calculations of 31 | correlations. See Details.} 32 | 33 | \item{show_class_names}{Logical. If TRUE, row and column of returned matrices will be identified 34 | with the names of the classes, if available in \code{x}. Default FALSE.} 35 | 36 | \item{display}{Defines how correlations are presented: "radii" (default), "rl" or "both". 37 | See Details.} 38 | 39 | \item{...}{Other arguments passed to function \code{\link[=cor]{cor()}} or to the user-defined function provided 40 | in \code{fun}.} 41 | } 42 | \value{ 43 | A list with matrices containing correlation values between pair of metrics. Matrices 44 | are disaggregated by radius if \code{display = "radii"}, by rasterlayer if \code{display = "rl"} or by 45 | rasterlayer and radii if \code{display = "both"}. Metrics 46 | names are presented as row and column names of the matrices, with the following format: 47 | "level"\emph{"metric_name"}"radius". For a landscape-level metric, a plausible metric name could be 48 | "l_np_1500" indicating a landscape-level metric, which is "np" ("number of patches") at a scale 49 | (radius) of 1500 m. For a class-level metric a plausible metric name could be "c4_pland_1000", 50 | indicating a class-level metric of class 4 (the value of the raster), which is "pland" 51 | ("percentage of landscape") at a scale (radius) of 1000 m. If more that one raster layer is 52 | being analyzed, the prefix "r1", "r2", "r3", ..., "rn" (referring to raster layer 1, 2, 3, ..., n) is 53 | added to the metric name. 54 | } 55 | \description{ 56 | Calculates pairwise correlations between landscape metrics. 57 | } 58 | \details{ 59 | Correlations are calculated, by default, through the function \code{\link[=cor]{cor()}}, by specifying 60 | the method through the argument \code{method}. Alternatively, a user-defined function can be provided 61 | in the argument \code{fun}. If not NULL, the function will assume that a user-defined function 62 | have been provided. This must be a function already loaded in the environment, and 63 | must take at least two arguments. These initial pair of arguments should be capable of receiving 64 | two numeric vectors (one in each argument), process them in some way, and return a numeric 65 | value (i.e. the supposed correlation). 66 | 67 | Arguments \code{raster}, \code{ext_raster}, \code{classes}, \code{radii}, \code{c_level} and \code{l_level} can be defined to 68 | subset the calculations of pair correlations. In each one of these, an all-positive or an 69 | all-negative vector can be passed, whether to include (all-positive) or exclude (all-negative) 70 | the elements to be taken into account for the subsetting: 71 | \itemize{ 72 | \item raster: a numeric vector with the number of the raster layers to be included/excluded. 73 | For example: \code{c(1, 2, 4)} to include raster layers 1, 2 and 4; \code{c(-2, -3)} to exclude raster layers 2 74 | and 3. 75 | \item ext_raster: a numeric vector with the number of the extra raster layers to be included/excluded, 76 | as in the raster slot. 77 | \item classes: must be a list with as many elements as defined raster layers in argument 78 | \code{raster}. Each element of the list must be a numeric vector (classes identities) with the 79 | classes to be included/excluded. If provided a character vector, \code{\link[=metrics_corr]{metrics_corr()}} assumes that 80 | classes names are provided. For example, for the case with 2 raster layers: 81 | \code{list(c(3, 20, 35), c("Forest", "Crops"))} would include classes 3, 20 and 35 from raster layer 1 82 | and classes "Forest" and "Crops" for raster layer 2. For the case of a unique raster layer, there 83 | is no need to input a list. For example, for the case of a unique raster layer and the 84 | exclusion of some classes: \code{c(-5, -10, -15)} to exclude classes 5, 10 and 15 of 85 | the unique raster layer; \code{c("-Forest", "-Grassland")} to exclude classes "Forest" and "Grassland". 86 | Note the "-" before each class name to indicate the exclusion of the classes. 87 | \item radii: a numeric vector to include/exclude particular radii. For example: \code{c(1000, 2000)} to 88 | include only radii of 1000 and 2000 m; \code{c(-500, -1500)} to exclude radii of 500 and 1500 m. 89 | \item c_level: character vector with the class-level metrics to be included/excluded from 90 | the analysis. For example: \code{c("np", "pland")} will include only the metrics "number of patches" 91 | ("np") and "percentage of the landscape" ("pland") in the analysis, whereas \code{c("-np", "-pland")} 92 | will exclude them. Note the "-" before each metric name to indicate the exclusion of the 93 | metrics. 94 | \item l_level: character vector with the landscape-level metrics to be included/excluded from 95 | the analysis. Other calculations for extra raster layers are considered as landscape-level metrics, 96 | and must be provided as "fun_" + the name of the function (e.g. "fun_mean"). 97 | } 98 | 99 | Names of the available metrics of the 'MultiLandMetrics' object provided in \code{x} can 100 | be accessed with \code{x@metrics} and \code{x@ext_calc}. 101 | 102 | Note that patch-level metrics, if exists in \code{x} metric's data.frame, are excluded from 103 | calculations, as this function works at a landscape scale. 104 | 105 | Argument \code{display} defines how correlation values will be presented. If equals to "radii" 106 | (default), correlation values are disaggregated by radii. If "rl", correlation values are 107 | disaggregated by rasterlayer: correlations between different radii will be presented. 108 | If "both", correlation values are firstly disaggregated by rasterlayer, and by radii secondly. 109 | Disaggregations by raster layers only make sense for 'MultiLandMetrics' objects with more than one raster layer. 110 | } 111 | \examples{ 112 | # Calculates pearson correlations between metrics of a MultiLandMetrics object 113 | metrics_corr(ed_metrics) 114 | 115 | # Only for radius 5000 m and with classes names rather than classes values 116 | metrics_corr(ed_metrics, radii = 5000, show_class_names = TRUE) 117 | 118 | # Only selecting the metric "pland" 119 | metrics_corr(ed_metrics, radii = 5000, show_class_names = TRUE, c_level = "pland") 120 | 121 | # Excluding the metric "pland" 122 | metrics_corr(ed_metrics, radii = 5000, show_class_names = TRUE, c_level = "-pland") 123 | 124 | # Excluding the metric radii of 4000 and 5000 m 125 | metrics_corr(ed_metrics, radii = c(-4000, -5000), show_class_names = TRUE) 126 | 127 | # Correlations of metric "pland" between classes 1 to 3, and between radii 128 | # 1000 and 5000 m, disaggregating by rasterlayer. 129 | metrics_corr(ed_metrics, radii = c(1000, 5000), classes = 1:3, 130 | c_level = "pland", display = "rl") 131 | } 132 | \seealso{ 133 | \code{\link[=mland_metrics]{mland_metrics()}}, \code{\link[=metrics_plots]{metrics_plots()}} 134 | } 135 | -------------------------------------------------------------------------------- /man/metrics_filter.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/metrics_filter.R 3 | \name{metrics_filter} 4 | \alias{metrics_filter} 5 | \title{Filters metrics} 6 | \usage{ 7 | metrics_filter(x, conditions, output = "MLM") 8 | } 9 | \arguments{ 10 | \item{x}{An object of class 'MultiLandMetrics' generated with \code{\link[=mland_metrics]{mland_metrics()}}.} 11 | 12 | \item{conditions}{List. Conditions to be met by the landscapes. See Details.} 13 | 14 | \item{output}{One of the following: "MLM" to return an updated version of the 'MultiLandMetrics' object provided in \code{x} (default), 15 | "spatial" to return a 'SpatVector' with the points 16 | of the selected landscapes, "data" to return a data.frame with the metric values information or "coords" 17 | to return a data.frame with geographical information of the filtered points.} 18 | } 19 | \value{ 20 | A 'MultiLandMetrics' if \code{output = "MLM"}, a 'SpatVector' if \code{output = "spatial"}, 21 | a data.frame if \code{output = "data"} or a data.frame with geographical information of the points if \code{output = "coords"}. 22 | } 23 | \description{ 24 | Selects landscapes that meet certain pre-defined conditions in relation to its metrics from 25 | a 'MultiLandMetrics' object. 26 | } 27 | \details{ 28 | Selects landscapes that meet certain conditions in relation to the values of 29 | their landscape metrics. The function will retain those points associated with the landscapes 30 | that meet all the defined conditions at the same time. Conditions must be provided through a list, 31 | for which the helper function \code{\link[=conditions]{conditions()}} is available: 32 | 33 | \preformatted{ 34 | conditions(list(rasterlayers, class, radii, metric, minimum value, maximum value), 35 | list(rasterlayers, class, radii, metric, minimum value, maximum value), 36 | ...) 37 | } 38 | \itemize{ 39 | \item rasterlayers: the raster layers to be considered. If NA, all raster layers will be considered. If 40 | an extra raster layer must be specified, the string "ext" must precede the raster layer number 41 | (e.g. "ext1", "ext2"). 42 | \item class: the classes to be considered, as numbers or strings with the names of the classes. If NA, all classes of required raster layers will be 43 | considered. If NULL, the function will assume that the metric to be considered is a landscape-level metric. 44 | Take into account that metrics from extra calculations are considered as landscape-level metrics. 45 | \item radii: the radii to be considered. If NA, all radii will be considered. 46 | \item metrics: the name of the metric to be considered (as defined with its abbreviation by column "metric" in \code{\link[=metrics_list]{metrics_list()}}). 47 | Only one metric per condition can be defined. Metrics as extra calculations for extra raster layers must be 48 | provided as "fun_" + the name of the function (e.g. "fun_mean"). 49 | \item minimum value: the minimum value that the metric must have in the filtered landscapes. If equal 50 | to -Inf, and a maximum value is defined, landscapes whose values in the defined metric are equal 51 | or lower to the maximum value will be retained. 52 | \item maximum value: the maximum value that the metric must have in the filtered landscapes. If equal 53 | to Inf, and a minimum value is defined, landscapes whose values in the defined metric are equal 54 | or higher to the minimum value will be retained. 55 | } 56 | 57 | A plausible list of conditions could be the following: 58 | 59 | \preformatted{ 60 | conditions(list(1, 2, 1000, "pland", 20, 30), 61 | list(1, 4, 1000, "np", 1, 15), 62 | list("ext1", NULL, 1000, "fun_mean", 70, 80)) 63 | } 64 | 65 | And it would indicate that landscapes of radius equal to 1000 m should present values of "pland" 66 | (percentage of the landscape) for class 2 from raster layer 1, between 20 and 30\%. At the same time, landscapes of radius 67 | equal to 1000 m should present values of "np" (number of patches) for class 4 from rasterlayer 1, 68 | between 1 and 15 patches. Finally, all selected landscapes of radius equal to 1000 m should 69 | present values for "fun_mean" (applied to extra raster layer "ext1") between 70 and 80. Note that the 70 | slot for "class" is NULL, as extra raster layers do not hold classes. 71 | } 72 | \examples{ 73 | # Filter landscapes that have between 20 and 30\% of forest at a radius of 2000 m 74 | # and output the data.frame with metrics values 75 | conds <- conditions(list(NA, "Forest", 2000, "pland", 20, 30)) 76 | otf_subset <- metrics_filter(otf_metrics, 77 | conditions = conds, 78 | output = "data") 79 | 80 | # The same but returning a data.frame with information of the retained points 81 | conds <- conditions(list(NA, "Forest", 2000, "pland", 20, 30)) 82 | otf_subset_points <- metrics_filter(otf_metrics, 83 | conditions = conds, 84 | output = "coords") 85 | 86 | # Filter landscapes that have between 20 and 30\% of forest at a radius of 2000 m 87 | # and a maximum of 60\% of Crops. 88 | conds <- conditions(list(NA, "Forest", 2000, "pland", 20, 30), 89 | list(NA, "Crops", 2000, "pland", -Inf, 60)) 90 | otf_subset2 <- metrics_filter(otf_metrics, 91 | conditions = conds, 92 | output = "data") 93 | } 94 | \seealso{ 95 | \code{\link[=metrics_gradient]{metrics_gradient()}} 96 | } 97 | -------------------------------------------------------------------------------- /man/metrics_gradient.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/metrics_gradient.R 3 | \name{metrics_gradient} 4 | \alias{metrics_gradient} 5 | \title{Generates optimized metrics gradient} 6 | \usage{ 7 | metrics_gradient( 8 | x, 9 | rasterlayer = NULL, 10 | class = NULL, 11 | radius = NULL, 12 | metric = NULL, 13 | n, 14 | cutpoints = NULL, 15 | breaks = NULL, 16 | random = FALSE, 17 | output = "MLM" 18 | ) 19 | } 20 | \arguments{ 21 | \item{x}{An object of class 'MultiLandMetrics' generated with \code{\link[=mland_metrics]{mland_metrics()}}.} 22 | 23 | \item{rasterlayer}{The raster layer to be considered. If 24 | an extra raster layer must be specified, the string "ext" must precede the raster layer number 25 | (e.g. "ext1", "ext2")} 26 | 27 | \item{class}{The class to be considered, as a number or as a string with the name of the class.} 28 | 29 | \item{radius}{The radius to be considered.} 30 | 31 | \item{metric}{The metric to be considered. Metrics as extra calculations for extra raster layers must be 32 | provided as "fun_" + the name of the function.} 33 | 34 | \item{n}{The number of points that will comprise the gradient. See Details.} 35 | 36 | \item{cutpoints}{A sequence of numbers that will serve as numeric approximations to select the 37 | points that will comprise the gradient. See Details.} 38 | 39 | \item{breaks}{A unique number with the number of breaks that will generate the cutpoints for the 40 | specified metric values. Default is 10. See Details.} 41 | 42 | \item{random}{Logical. If TRUE, random points will be selected.} 43 | 44 | \item{output}{One of the following: "MLM" to return an updated version of the 'MultiLandMetrics' object provided in \code{x} (default), 45 | "spatial" to return a 'SpatVector' with the points 46 | of the selected landscapes, "data" to return a data.frame with the metric values information or "coords" 47 | to return a data.frame with geographical information of the selected points.} 48 | } 49 | \value{ 50 | A 'MultiLandMetrics' if \code{output = "MLM"}, a 'SpatVector' if \code{output = "spatial"}, 51 | a data.frame if \code{output = "data"} or a data.frame with geographical information of the points if \code{output = "coords"}. 52 | } 53 | \description{ 54 | Selects a set of points whose associated landscapes comprise an optimized gradient for a given landscape metric. 55 | } 56 | \details{ 57 | Selects a subset of landscapes that overall will 58 | generate an optimized gradient of values for a given landscape metric of a specified raster layer, 59 | class and radius. One can define a gradient as optimized if 60 | its values fulfill to cover a good range of values between a minimum and a maximum value. The 61 | final gradient will comprise the number of points specified in argument \code{n}. Note that 62 | only one landscape metric can be specified at a time. 63 | 64 | The algorithm will select those points whose associated landscapes present values for the specified landscape metric that are 65 | the most close to the specified \code{cutpoints}. Alternatively, the user can provide a number of 66 | \code{breaks} from which the sequence of cutpoints will be generated. If both arguments are specified, 67 | the function will consider the values inputted in \code{cutpoints}. If both arguments are NULL, the 68 | algorithm will simply select \code{n} random points. 69 | } 70 | \examples{ 71 | # Generates an optimized gradient for the landscape metric "pland", for the class "Forest". 72 | pland_gradient <- metrics_gradient(otf_metrics, rasterlayer = 1, class = "Forest", 73 | radius = 2000, metric = "pland", n = 15, breaks = 10) 74 | # Note that, in this case, specifications for the rasterlayer and the radius are 75 | # redundant, and could be simply ignored and left as default, asthe object otf_metrics 76 | # only comprises a unique rasterlayer and radius. 77 | 78 | # By default, the output is an updated version of the object otf_metrics. In order to 79 | # inspect the returned values, let's select only the dataframe containing the 80 | # metric's values. 81 | foo <- subset(pland_gradient@data, metric == "pland" & classname == "Forest", 82 | select = value) 83 | 84 | # Next, we output the range of values we have obtained, note there are 15 points, as 85 | # previously specified in the function definition in the argument 'n' 86 | round(sort(foo$value), digits = 2) 87 | 88 | # 1.15 1.57 8.17 8.19 15.24 22.32 29.27 36.32 43.17 43.20 49.79 50.25 55.44 57.62 64.53 89 | 90 | # Alternatively, we can define specific cutpoints around the landscapes will be selected 91 | # in termsof its numeric closeness. 92 | pland_gradient <- metrics_gradient(otf_metrics, rasterlayer = 1, class = "Forest", 93 | radius = 2000,metric = "pland", n = 15, 94 | cutpoints = seq(1, 60, 5)) 95 | 96 | # Again, we inspect the dataframe with the metric values to see our results. 97 | foo <- subset(pland_gradient@data, metric == "pland" & classname == "Forest", 98 | select = value) 99 | 100 | round(sort(foo$value), digits = 2) 101 | 102 | # 1.15 6.02 6.03 10.99 15.97 20.99 26.01 31.02 35.95 41.14 41.34 45.93 51.41 54.56 55.44 103 | 104 | # Both alternatives generated a wide-ranged gradient of values for the forest metric "pland" 105 | } 106 | \seealso{ 107 | \code{\link[=metrics_filter]{metrics_filter()}} 108 | } 109 | -------------------------------------------------------------------------------- /man/metrics_list.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/metrics_list.R 3 | \name{metrics_list} 4 | \alias{metrics_list} 5 | \title{Metrics list} 6 | \usage{ 7 | metrics_list( 8 | level = NULL, 9 | metric = NULL, 10 | name = NULL, 11 | type = NULL, 12 | what = NULL 13 | ) 14 | } 15 | \arguments{ 16 | \item{level}{Character vector. Level of metrics. Either "patch", "class" or "landscape" 17 | (or a vector with a combination of these). Default NULL considers all levels.} 18 | 19 | \item{metric}{Abbreviation of metrics (e.g. "area").} 20 | 21 | \item{name}{Full name of metrics (e.g. "core area").} 22 | 23 | \item{type}{Character vector. Type according to FRAGSTATS grouping. One or more of the following: 24 | "area and edge", "core area", "shape", "aggregation", "complexity", and or "diversity". Default 25 | NULL considers all types.} 26 | 27 | \item{what}{Selected level of metrics: either "patch", "class" or "landscape". It is also 28 | possible to specify functions as a vector of strings, e.g. what = c("lsm_c_ca", "lsm_l_ta").} 29 | } 30 | \value{ 31 | A data.frame with the list of available landscape metrics, including information 32 | regarding the level, type, metric, name and function name provided by package \code{landscapemetrics}. 33 | } 34 | \description{ 35 | List of available landscape metrics provided by package \code{landscapemetrics} to be calculated with 36 | \code{\link[=mland_metrics]{mland_metrics()}}. It simply calls \code{\link[landscapemetrics:list_lsm]{landscapemetrics::list_lsm()}}. For more information regarding the 37 | definition and equations of metrics, please check the user manual of \code{landscapemetrics}. 38 | } 39 | \references{ 40 | Hesselbarth, M.H.K., Sciaini, M., With, K.A., Wiegand, K., Nowosad, J. 2019. landscapemetrics: 41 | an open-source R tool to calculate landscape metrics. - Ecography 42:1648-1657(ver. 0). 42 | 43 | McGarigal, K., SA Cushman, and E Ene. 2012. FRAGSTATS v4: Spatial Pattern Analysis Program for 44 | Categorical and Continuous Maps. Computer software program produced by the authors at the 45 | University of Massachusetts, Amherst. \cr 46 | Available at the following web site: https://www.umass.edu/landeco/ 47 | } 48 | -------------------------------------------------------------------------------- /man/metrics_plots.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/metrics_plots.R 3 | \name{metrics_plots} 4 | \alias{metrics_plots} 5 | \title{Pairwise metric plots} 6 | \usage{ 7 | metrics_plots( 8 | x, 9 | raster = NULL, 10 | classes = NULL, 11 | radii = NULL, 12 | c_level = NULL, 13 | l_level = NULL, 14 | ext_raster = NULL, 15 | show_class_names = FALSE, 16 | upper = TRUE, 17 | diag = TRUE, 18 | smooth = TRUE, 19 | method = "loess", 20 | se = FALSE, 21 | st_points = list(shape = 21, size = 2, col = "black", fill = "white", alpha = 1), 22 | st_lines = list(lty = 1, lwd = 1, col = "black", alpha = 0.6), 23 | ... 24 | ) 25 | } 26 | \arguments{ 27 | \item{x}{An object of class 'Multiland' generated with \code{\link[=mland]{mland()}}.} 28 | 29 | \item{raster, ext_raster, classes, radii, l_level, c_level}{Parameters to subset plots. See Details.} 30 | 31 | \item{show_class_names}{logical. Whether to show classes with its previously defined names (if defined) 32 | when generating the 'MultiLand' object (TRUE), or not (FALSE, default).} 33 | 34 | \item{upper}{logical. Whether to plot upper-diagonal plots or not. Default TRUE} 35 | 36 | \item{diag}{logical. Whether to plot diagonal density plots or not. Default TRUE.} 37 | 38 | \item{smooth}{logical. If TRUE (default) a pattern between the pair of metric values 39 | is plotted, with a smoothing method as defined in \code{method}.} 40 | 41 | \item{method}{Smoothing method (function) to use, as in \code{\link[ggplot2:geom_smooth]{ggplot2::geom_smooth()}}. It accepts 42 | "loess" (default), "lm", "gam", among others. See ?ggplot2::geom_smooth() for more details.} 43 | 44 | \item{se}{logical. Whether to show (TRUE) or not (FALSE) confidence intervals when \code{smooth = TRUE}.} 45 | 46 | \item{st_points}{List of aesthetic arguments for points plotting: 47 | \code{shape} for points shape, \code{size} for points size, \code{col} for 48 | points border color, \code{fill} for points fill color and \code{alpha} for point transparency.} 49 | 50 | \item{st_lines}{List of aesthetic arguments for lines plotting (if \code{smooth = TRUE}): 51 | \code{lty} for linetype, \code{lwd} for linewidth, 52 | \code{col} for line color and \code{alpha} for line transparency.} 53 | 54 | \item{...}{Other parameters to be passed to \code{\link[ggplot2:geom_smooth]{ggplot2::geom_smooth()}}, if \code{smooth = TRUE}.} 55 | } 56 | \value{ 57 | A panel with several plots returned by \code{\link[GGally:ggpairs]{GGally::ggpairs()}} relating pair of metrics 58 | values. Metrics 59 | names are presented at the top and right of the panel (strips), with the following format: 60 | "level"\emph{"metric_name"}"radius". For a landscape-level metric, a plausible metric name could be 61 | "l_np_1500" indicating a landscape-level metric, which is "np" ("number of patches") at a scale 62 | (radius) of 1500 m. For a class-level metric a plausible metric name could be "c4_pland_1000", 63 | indicating a class-level metric of class 4 (the value of the raster), which is "pland" 64 | ("percentage of landscape") at a scale (radius) of 1000 m. If more that one rasterlayer is 65 | being analyzed, the prefix "r1", "r2", "r3", ..., "rn" (referring to rasterlayer 1, 2, 3, ..., n) is 66 | added to the metric name. 67 | } 68 | \description{ 69 | Plots pair of metric values in two-dimensional plots. 70 | } 71 | \details{ 72 | \code{\link[=metrics_plots]{metrics_plots()}} mainly relies on \code{\link[GGally:ggpairs]{GGally::ggpairs()}} to generate pair plots 73 | between metrics values. Arguments \code{upper} and \code{diag} are specific arguments of 74 | \code{\link[GGally:ggpairs]{GGally::ggpairs()}}, here adapted to the context of continuous values only. 75 | 76 | Argument \code{raster}, \code{classes}, \code{radii}, \code{l_level} and \code{c_level} can be defined to 77 | subset the plots. In each one of these, an all-positive or an 78 | all-negative vector can be passed, whether to include (all-positive) or exclude (all-negative) 79 | the elements to be taken into account for the subsetting: 80 | \itemize{ 81 | \item rasterlayers: a numeric vector with the number of the raster layers to be included/excluded. 82 | For example: \code{c(1, 2, 4)} to include raster layers 1, 2 and 4; \code{c(-2, -3)} to exclude raster layers 2 83 | and 3. 84 | \item classes: must be a list with as many elements as defined raster layers in argument 85 | \code{raster}. Each element of the list must be a numeric vector (classes identities) with the 86 | classes to be included/excluded. If provided a character vector, \code{\link[=metrics_corr]{metrics_corr()}} assumes that 87 | classes names are provided. For example, for the case with 2 raster layers: 88 | \code{list(c(3, 20, 35), c("Forest", "Crops"))} would include classes 3, 20 and 35 from raster layer 1 89 | and classes "Forest" and "Crops" for raster layer 2. For the case of a unique raster layer, there 90 | is no need to input a list. For example, for the case of a unique raster layer and the 91 | exclusion of some classes: \code{c(-5, -10, -15)} to exclude classes 5, 10 and 15 of 92 | the unique raster layer; \code{c("-Forest", "-Grassland")} to exclude classes "Forest" and "Grassland". 93 | Note the "-" before each class name to indicate the exclusion of the classes. 94 | \item radii: a numeric vector to include/exclude particular radii. For example: c(1000, 2000) to 95 | include only radii of 1000 and 2000 m; c(-500, -1500) to exclude radii of 500 and 1500 m. 96 | \item c_level: character vector with the class-level metrics to be included/excluded from 97 | the analysis. For example: \code{c("np", "pland")} will include only the metrics "number of patches" 98 | ("np") and "percentage of the landscape" ("pland") in the analysis, whereas \code{c("-np", "-pland")} 99 | will exclude them. Note the "-" before each metric name to indicate the exclusion of the 100 | metrics. 101 | \item l_level: character vector with the landscape-level metrics to be included/excluded from 102 | the analysis. Other calculations for extra raster layers are considered as landscape-level metrics, 103 | and must be provided as "fun_" + the name of the function (e.g. "fun_mean"). 104 | } 105 | 106 | Names of the available metrics of the 'MultiLandMetrics' object provided in \code{x} can 107 | be accessed with \code{x@metrics} and \code{x@ext_calc}. 108 | 109 | Note that patch-level metrics, if exists in \code{x} metric's data.frame, are excluded from 110 | calculations, as this function works at a landscape scale. 111 | } 112 | \examples{ 113 | # Pair plots between metrics "pland" of classes 1 to 4, for radius 3000 m 114 | metrics_plots(ed_metrics, classes = 1:4, radii = 3000, show_class_names = TRUE, 115 | c_level = "pland") 116 | 117 | # Without smooth pattern 118 | metrics_plots(ed_metrics, classes = 1:4, radii = 3000, show_class_names = TRUE, 119 | c_level = "pland", smooth = FALSE) 120 | 121 | \donttest{ 122 | # Changing aesthetics 123 | metrics_plots(ed_metrics, classes = 1:4, radii = 3000, show_class_names = TRUE, 124 | c_level = "pland", smooth = FALSE, size = 1.5, shape = 21, 125 | fill = "red", alpha = 0.4) 126 | 127 | # Assessing two radii values at the same time 128 | metrics_plots(ed_metrics, classes = 1:4, radii = c(1000, 5000), 129 | show_class_names = TRUE, c_level = "pland", smooth = FALSE, 130 | size = 1.5, shape = 21, fill = "red", alpha = 0.4) 131 | 132 | # An example with hundreds of points 133 | metrics_plots(otf_metrics, classes = c("Forest", "Crops")) 134 | 135 | # Plots can be combined with ggplot2::theme 136 | metrics_plots(otf_metrics, classes = c("Forest", "Crops")) + 137 | ggplot2::theme_bw() 138 | } 139 | } 140 | \seealso{ 141 | \code{\link[=mland_metrics]{mland_metrics()}}, \code{\link[=metrics_corr]{metrics_corr()}} 142 | } 143 | -------------------------------------------------------------------------------- /man/metrics_scalogram.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/metrics_scalogram.R 3 | \name{metrics_scalogram} 4 | \alias{metrics_scalogram} 5 | \title{Scalograms} 6 | \usage{ 7 | metrics_scalogram( 8 | x, 9 | raster = NULL, 10 | points = NULL, 11 | classes = NULL, 12 | radii = NULL, 13 | c_level = NULL, 14 | l_level = NULL, 15 | ext_raster = NULL, 16 | show_class_names = FALSE, 17 | aggregation = FALSE, 18 | fun = "mean", 19 | ... 20 | ) 21 | } 22 | \arguments{ 23 | \item{x}{An object of class 'MultiLandMetrics' generated with \code{\link[=mland_metrics]{mland_metrics()}}.} 24 | 25 | \item{raster, ext_raster, classes, radii, l_level, c_level}{Parameters to select 26 | what to plot. See Details.} 27 | 28 | \item{points}{Numeric or character vector of points to be considered. See Details.} 29 | 30 | \item{show_class_names}{Logical. If TRUE, raster classes will be identified 31 | with the names of the classes, if available in \code{x}. Default FALSE.} 32 | 33 | \item{aggregation}{Logical. Should data be aggregated by site? See Details.} 34 | 35 | \item{fun}{Function to apply during aggregation. Default is "mean". See Details.} 36 | 37 | \item{...}{Parameters passed to ggplot2::geom_line().} 38 | } 39 | \value{ 40 | A panel with ggplot2 facet plots relating the value of the provided 41 | metrics and the radii. Plots are 42 | } 43 | \description{ 44 | Plots the value of metrics across different spatial scales (radius) 45 | } 46 | \details{ 47 | \code{\link[=metrics_scalogram]{metrics_scalogram()}} generates scalograms. In these plots, the value 48 | of a landscape metric is plotted in relation to different spatial scales (which 49 | in this context are defined by the radii of buffers) (Wu, 2004). Curves are disaggregated by 50 | raster classes (if applies), and a label named "landscape" is provided for those landscape-level 51 | metrics. 52 | 53 | If argument \code{points} is a character vector, 54 | \code{\link[=metrics_scalogram]{metrics_scalogram()}} will assume that the 'MultiLandMetrics' object inputted in argument \code{x} contains 55 | the identification names of each site/point. Therefore, the inputted values in argument \code{points} will be taken as these 56 | identification names. Otherwise, if a numeric vector is inputted, these values 57 | will be taken as point ids. 58 | 59 | Arguments \code{raster}, \code{ext_raster}, \code{classes}, \code{radii}, \code{c_level} and \code{l_level} 60 | can be defined to select what metrics, classes, raster layers and radii will 61 | be considered for plotting. In each one of these, an all-positive or an 62 | all-negative vector can be passed, whether to include (all-positive) or 63 | exclude (all-negative) the elements to be taken into account for the 64 | selection: 65 | \itemize{ 66 | \item raster: a numeric vector with the number of the raster layers to be included/excluded. 67 | For example: \code{c(1, 2, 4)} to include raster layers 1, 2 and 4; \code{c(-2, -3)} to exclude raster layers 2 68 | and 3. 69 | \item ext_raster: a numeric vector with the number of the extra raster layers to be included/excluded, 70 | as in the raster slot. 71 | \item classes: must be a list with as many elements as defined raster layers in argument 72 | \code{raster}. Each element of the list must be a numeric vector (classes identities) with the 73 | classes to be included/excluded. If provided a character vector, \code{\link[=metrics_scalogram]{metrics_scalogram()}} assumes that 74 | classes names are provided. For example, for the case with 2 raster layers: 75 | \code{list(c(3, 20, 35), c("Forest", "Crops"))} would include classes 3, 20 and 35 from raster layer 1 76 | and classes "Forest" and "Crops" for raster layer 2. For the case of a unique raster layer, there 77 | is no need to input a list. For example, for the case of a unique raster layer and the 78 | exclusion of some classes: \code{c(-5, -10, -15)} to exclude classes 5, 10 and 15 of 79 | the unique raster layer; \code{c("-Forest", "-Grassland")} to exclude classes "Forest" and "Grassland". 80 | Note the "-" before each class name to indicate the exclusion of the classes. 81 | \item radii: a numeric vector to include/exclude particular radii. For example: \code{c(1000, 2000)} to 82 | include only radii of 1000 and 2000 m; \code{c(-500, -1500)} to exclude radii of 500 and 1500 m. 83 | \item c_level: character vector with the class-level metrics to be included/excluded from 84 | the analysis. For example: \code{c("np", "pland")} will include only the metrics "number of patches" 85 | ("np") and "percentage of the landscape" ("pland") in the analysis, whereas \code{c("-np", "-pland")} 86 | will exclude them. Note the "-" before each metric name to indicate the exclusion of the 87 | metrics. 88 | \item l_level: character vector with the landscape-level metrics to be included/excluded from 89 | the analysis. Other calculations for extra raster layers are considered as landscape-level metrics, 90 | and must be provided as "fun_" + the name of the function (e.g. "fun_mean"). 91 | } 92 | 93 | Names of the available metrics of the 'MultiLandMetrics' object provided in \code{x} can 94 | be accessed with \code{x@metrics} and \code{x@ext_calc}. 95 | 96 | Note that patch-level metrics, if exists in \code{x} metric's data.frame, are excluded from 97 | calculations, as this function works at a landscape scale. 98 | 99 | If \code{aggregation} is TRUE, the values of the selected metrics for different sites will be aggregated. 100 | By default, for each spatial scale and raster layer, \code{\link[=metrics_scalogram]{metrics_scalogram()}} will 101 | calculate the mean value from the values of all available sites/points. A different 102 | function (could be user-defined) can be provided in argument \code{fun}. 103 | } 104 | \examples{ 105 | \donttest{ 106 | # We will generate a 'MultiLand' obejct with several radii. The objective is 107 | # evaluate metrics across a wide range of spatial scales 108 | 109 | # Loads main raster with land covers 110 | elchaco <- terra::rast(system.file("extdata", "elchaco.tif", package = "multilandr")) 111 | 112 | # Loads extra raster with NDVI values 113 | elchaco_ndvi <- terra::rast(system.file("extdata", "elchaco_ndvi.tif", package = "multilandr")) 114 | 115 | # Classes names 116 | cl_names <- c(1, "Forest", 117 | 2, "Grassland", 118 | 3, "Crops", 119 | 4, "Pastures", 120 | 5, "Water", 121 | 6, "Urban") 122 | 123 | # Loads points 124 | elchaco_sites <- terra::vect(system.file("extdata", "elchaco_sites.gpkg", package = "multilandr")) 125 | 126 | # Creates 'MultiLand' object by loading main raster, an extra raster and points. 127 | ernesdesign1 <- mland(points_layer = elchaco_sites, 128 | rast_layer = elchaco, 129 | radii = seq(500, 5000, 100), 130 | class_names = list(cl_names), 131 | site_ref = "name", 132 | ext_rast_layer = elchaco_ndvi, 133 | rast_names = c("landcover", "NDVI"), 134 | segs = 20) 135 | 136 | # Now, we calculate two metrics: the number of patches for each class 137 | # and the total edge considering all classes (i.e. a landscape-level class) 138 | ed_metrics5 <- mland_metrics(ernesdesign1, 139 | what = c("lsm_c_np", "lsm_l_te"), 140 | ext_calc = list(c(1, "mean"))) 141 | 142 | # Plots scalogram for 3 different sites/landscapes, for raster layer "landcover" 143 | # and metric "np" 144 | metrics_scalogram(ed_metrics5, points = c("Algarrobo", "Peje", "Itin"), 145 | raster = "landcover", c_level = "np", 146 | aggregation = FALSE, show_class_names = TRUE) 147 | 148 | # Scalogram with aggregation across sites. By default, a mean value among all 149 | # considered sites is calculated. 150 | metrics_scalogram(ed_metrics5, raster = 1, 151 | aggregation = TRUE, show_class_names = TRUE) 152 | 153 | # Here, we only plot those metrics calculated for the extra raster layer 154 | # named "NDVI", which in this case is only one metric 155 | metrics_scalogram(ed_metrics5, points = c("Algarrobo", "Peje", "Itin"), 156 | ext_raster = "NDVI", 157 | aggregation = FALSE, show_class_names = TRUE) 158 | 159 | # Scalogram with aggregation across three sites. By default, a mean value among 160 | # the three considered sites is calculated. 161 | metrics_scalogram(ed_metrics5, ext_raster = 1, 162 | points = c("Yuchan", "Coco", "Tala"), 163 | aggregation = FALSE, show_class_names = TRUE) 164 | 165 | # The output can be customized as every ggplot object 166 | library(ggplot2) 167 | metrics_scalogram(ed_metrics5, points = c("Algarrobo", "Peje", "Itin"), raster = 1, 168 | c_level = "np", 169 | aggregation = FALSE, show_class_names = TRUE, lwd = 1) + 170 | scale_color_brewer(type = "div", palette = 1) + 171 | theme_bw() + 172 | theme(aspect.ratio = 1, legend.title = element_blank()) 173 | } 174 | } 175 | \references{ 176 | Wu, J. (2004). Effects of changing scale on landscape pattern analysis: scaling relations. Landscape ecology, 19, 125-138. 177 | } 178 | -------------------------------------------------------------------------------- /man/mland_export_gis.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/mland_export_gis.R 3 | \name{mland_export_gis} 4 | \alias{mland_export_gis} 5 | \title{Exports a 'MultiLand' object as GIS data} 6 | \usage{ 7 | mland_export_gis( 8 | x, 9 | raster = NULL, 10 | points = NULL, 11 | radii = NULL, 12 | ext_raster = NULL, 13 | name = NULL, 14 | gdal = c("COMPRESS=DEFLATE", "PREDICTOR=2", "ZLEVEL=9"), 15 | dir = NULL, 16 | verbose = TRUE, 17 | ... 18 | ) 19 | } 20 | \arguments{ 21 | \item{x}{An object of class 'MultiLand' generated with \code{\link[=mland]{mland()}}.} 22 | 23 | \item{raster, ext_raster}{Numeric. The raster layers to be exported.} 24 | 25 | \item{points}{Numeric or character vector of points to be processed. See Details.} 26 | 27 | \item{radii}{Numeric vector of radii to be processed.} 28 | 29 | \item{name}{Character. Name of the zip file where files will be exported.} 30 | 31 | \item{gdal}{GeoTiff creation options for rasters (\href{https://gdal.org/en/stable/drivers/raster/gtiff.html}{GeoTiff file format}). 32 | \code{\link[=mland_export_gis]{mland_export_gis()}} uses the following compression options: 33 | c("COMPRESS=DEFLATE", "PREDICTOR=2", "ZLEVEL=9").} 34 | 35 | \item{dir}{Path to the export directory. This must be specified explicitly. 36 | To export to the current directory, use \code{dir = getwd()}. Otherwise, provide 37 | a valid path to an existing directory, ensuring it does not end with "/".} 38 | 39 | \item{verbose}{Print messages in the console? Default is TRUE.} 40 | 41 | \item{...}{Other arguments passed to \link[terra:writeRaster]{terra::writeRaster}.} 42 | } 43 | \value{ 44 | GIS data from a 'MultiLand' object is exported through a zip file. 45 | } 46 | \description{ 47 | Exports points, buffers and intersections between buffers and raster layers, as vector and raster 48 | files. 49 | } 50 | \details{ 51 | If argument \code{points} is a character vector, 52 | \code{\link[=mland_export_gis]{mland_export_gis()}} will assume that the 'MultiLand' object inputted in argument \code{x} was created with 53 | \code{site_ref = TRUE}. This is, there is an attribute in points layer data with the names for 54 | each individual point. Therefore, the inputted values in argument \code{points} will be taken as these 55 | identification names. Otherwise, if a numeric vector is declared, the inputted values 56 | will be taken as the automatically generated point ids (created when running \code{\link[=mland]{mland()}}). 57 | } 58 | \examples{ 59 | \donttest{ 60 | # Loads a 'MultiLand' object 61 | ernesdesign <- system.file("extdata", "ernesdesign.zip", package = "multilandr") 62 | ernesdesign <- mland_load(ernesdesign) 63 | 64 | # Exports as GIS data, in temporary directory for this example and with a given name 65 | mland_export_gis(ernesdesign, dir = tempdir(), name = "mland-GIS_example") 66 | 67 | # Remove file for this example 68 | unlink(file.path(tempdir(), "mland-GIS_example.zip")) 69 | } 70 | } 71 | \seealso{ 72 | \code{\link[=mland]{mland()}}, \code{\link[=mland_save]{mland_save()}}, \code{\link[=mland_load]{mland_load()}} 73 | } 74 | -------------------------------------------------------------------------------- /man/mland_load.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/mland_load.R 3 | \name{mland_load} 4 | \alias{mland_load} 5 | \title{Load 'MultiLand' or 'MultiLandMetrics' object} 6 | \usage{ 7 | mland_load(path, ...) 8 | } 9 | \arguments{ 10 | \item{path}{A string depicting the path to a zip file, to load objects of class 11 | 'MultiLand', or to a RDS file to load objects of class 'MultiLandMetrics'.} 12 | 13 | \item{...}{Other parameters passed to \code{\link[=readRDS]{readRDS()}} when trying to load an object of class 14 | 'MultiLandMetrics'.} 15 | } 16 | \value{ 17 | A 'MultiLand' or a 'MultiLandMetrics' object. 18 | } 19 | \description{ 20 | Imports a zip file into an object of class 'MultiLand' that was previously 21 | saved with \code{\link[=mland_save]{mland_save()}}. Alternatively, loads to the environment an RDS object depicting a 22 | 'MultiLandMetrics' object. 23 | } 24 | \examples{ 25 | # Loads mland object from a zip file, previously created with mland_save() 26 | mland_obj <- system.file("extdata", "ernesdesign.zip", package = "multilandr") 27 | ernesdesign <- mland_load(mland_obj) 28 | 29 | # Loads a MultiLandMetrics object previously generated with mland_metrics() and 30 | # exported as a RDS object with mland_save() or saveRDS() 31 | 32 | mlm_obj <- system.file("extdata", "ed_metrics.rds", package = "multilandr") 33 | ed_metrics <- mland_load(mlm_obj) 34 | } 35 | \seealso{ 36 | \code{\link[=mland_save]{mland_save()}}, \code{\link[=mland]{mland()}}, \code{\link[=mland_metrics]{mland_metrics()}} 37 | } 38 | -------------------------------------------------------------------------------- /man/mland_overlap.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/mland_overlap.R 3 | \name{mland_overlap} 4 | \alias{mland_overlap} 5 | \title{Buffers overlapping} 6 | \usage{ 7 | mland_overlap( 8 | x, 9 | points = NULL, 10 | radii = NULL, 11 | digits = 2, 12 | perc = TRUE, 13 | title = "id" 14 | ) 15 | } 16 | \arguments{ 17 | \item{x}{An object of class 'Multiland' generated with \code{\link[=mland]{mland()}}.} 18 | 19 | \item{points}{Numeric or character vector depicting the points to be considered. If NULL, all 20 | points will be taken into account. See Details.} 21 | 22 | \item{radii}{Numeric vector depicting the radii to be considered. If NULL, all radii will be taken 23 | into account.} 24 | 25 | \item{digits}{Numeric. Number of digits for the values of overlapped areas. Default is 2.} 26 | 27 | \item{perc}{Logical. If TRUE (default) the degree of overlapped areas will be 28 | presented as percentages. If FALSE, proportions will be outputted.} 29 | 30 | \item{title}{One of the following: "id" to output each point with its id (default), or "sitename" to 31 | output each point with its pre-defined point name in \code{x}.} 32 | } 33 | \value{ 34 | A list with as many elements as different radius in \code{x}. Each element contains a 35 | matrix with the percentages (or proportions if \code{perc = FALSE}) of overlapping of buffer areas. 36 | } 37 | \description{ 38 | Returns matrices informing the degree of overlapped area 39 | between buffers of a 'MultiLand' object. 40 | } 41 | \details{ 42 | If argument \code{points} is a character vector, 43 | \code{\link[=mland_overlap]{mland_overlap()}} will assume that the 'MultiLand' object inputted in argument \code{x} was created with 44 | \code{site_ref = TRUE}. This is, there is a column/attribute in the points layer with the names for 45 | each distinct point. Therefore, the inputted values in argument \code{points} will be taken as these 46 | identification names. Otherwise, if a numeric vector is declared, the inputted values 47 | will be taken as the automatically generated point ids (created when executing \code{\link[=mland]{mland()}}). 48 | } 49 | \examples{ 50 | \donttest{ 51 | # Loads a 'MultiLand' object 52 | ernesdesign <- system.file("extdata", "ernesdesign.zip", package = "multilandr") 53 | ernesdesign <- mland_load(ernesdesign) 54 | 55 | # Returns a matrix with the percentage of overlapping between buffers of each radii 56 | mland_overlap(ernesdesign) 57 | 58 | # Selects only one radius and return the site names rather than the ids 59 | mland_overlap(ernesdesign, radii = 5000, title = "sitename") 60 | } 61 | } 62 | -------------------------------------------------------------------------------- /man/mland_plot.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/mland_plot.R 3 | \name{mland_plot} 4 | \alias{mland_plot} 5 | \title{Plots landscapes from 'MultiLand' objects} 6 | \usage{ 7 | mland_plot( 8 | x, 9 | raster = NULL, 10 | points = NULL, 11 | radii = NULL, 12 | ext_raster = NULL, 13 | title = "id", 14 | ncol = NULL, 15 | nrow = NULL, 16 | st_points = list(shape = 21, size = 2, col = "black", fill = "white", alpha = 1), 17 | st_buffers = list(lty = 1, lwd = 1, col = "black", alpha = 0.6), 18 | st_classes = list(palette = "Spectral", fill = NULL, alpha = NULL, na_value = 19 | c("white", 1)), 20 | st_ext = c("chartreuse", "firebrick1") 21 | ) 22 | } 23 | \arguments{ 24 | \item{x}{An object of class 'MultiLand' generated with \code{\link[=mland]{mland()}}.} 25 | 26 | \item{raster, ext_raster}{Numeric. The rasterlayer to be plotted. Only one rasterlayer can be 27 | plotted at the same time, either defined in \code{raster} or \code{ext_raster}.} 28 | 29 | \item{points}{Numeric or character vector of points to be plotted. See Details.} 30 | 31 | \item{radii}{Numeric vector of radii to be plotted.} 32 | 33 | \item{title}{One of the following: "id" to plot titles as each point id (default), or "sitename" to 34 | plot titles as each pre-defined point name in \code{x}. See Details.} 35 | 36 | \item{ncol, nrow}{Number of columns and rows wherein individual plots will be arranged.} 37 | 38 | \item{st_points}{List of aesthetic arguments for points plotting: 39 | \code{shape} for points shape, \code{size} for points size, \code{col} for 40 | points border color, \code{fill} for points fill color and \code{alpha} for point transparency.} 41 | 42 | \item{st_buffers}{List of aesthetic arguments for buffers plotting: 43 | \code{lty} for buffers linetype, \code{lwd} for buffers linewidth, 44 | \code{col} for buffers border color and \code{alpha} for border transparency.} 45 | 46 | \item{st_classes}{List of aesthetic arguments for classes plotting: 47 | \code{palette}, for classes color palette, \code{fill} a vector of fill colors for classes, \code{alpha}, a vector of 48 | alpha values for classes, and \code{na_value} for the color of NA values. See Details.} 49 | 50 | \item{st_ext}{Character vector of length 2, depicting the color for the minimum and maximum values 51 | of the raster defined in \code{ext_raster}.} 52 | } 53 | \value{ 54 | Multiple plots (in a unique plotting device) of landscapes around 55 | defined points, radii and classes of a MultiLand object. 56 | } 57 | \description{ 58 | Returns multiple plots for each landscape generated from each point and buffer, with their radii and classes, 59 | defined by the user through a 'MultiLand' object (generated by \code{\link[=mland]{mland()}}). 60 | Aesthetic parameters of plots can be customized. 61 | } 62 | \details{ 63 | If argument \code{points} is a character vector, 64 | \code{\link[=mland_plot]{mland_plot()}} will assume that the 'MultiLand' object inputted in argument \code{x} was created with 65 | \code{site_ref = TRUE}. This is, there is a column/attribute in points layer data with the names for 66 | each distinct point. Therefore, the inputted values in argument \code{points} will be taken as these 67 | identification names. Otherwise, if a numeric vector is inputted, these values 68 | will be taken as the automatically generated point ids (created when running \code{\link[=mland]{mland()}}). 69 | 70 | If \code{title = "sitename"}, the title of individual plots will be the names of each point. For this, 71 | the names of the points in \code{x} must had been defined when the object was created with \code{\link[=mland]{mland()}} 72 | (i.e. \code{x@site_ref = TRUE}). Otherwise, the argument will be ignored and the titles will be the 73 | ids of the points. 74 | 75 | A pre-defined palette can be chosen to differentiate classes inside \code{palette = "palette_name"}, 76 | inside the list defined in \code{st_classes}. Any palette from \code{\link[=hcl.pals]{hcl.pals()}} can be chosen. Otherwise, 77 | the user can define specific colors for each class, inside \code{fill}. This must be a vector built 78 | with concatenated pair of values, the first value being the class (or class name, if defined 79 | during \code{x} generation), and the second value the color (either the name of the color or the hex 80 | code of the color). For example, in the case the rasterlayer has four unique values: (1, 2, 3 and 4), a plausible color definition 81 | could be the following: 82 | 83 | \preformatted{ 84 | list(c(1, "green", 2, "red", 3, "black", 4, "yellow")) 85 | } 86 | } 87 | \examples{ 88 | \donttest{ 89 | # Loads a 'MultiLand' object 90 | ernesdesign <- system.file("extdata", "ernesdesign.zip", package = "multilandr") 91 | ernesdesign <- mland_load(ernesdesign) 92 | 93 | # Plots all points and radii 94 | mland_plot(ernesdesign) 95 | 96 | # Plots points 1 to 3 and only radius 3000 m 97 | mland_plot(ernesdesign, points = 1:3, radii = 3000) 98 | 99 | # Plot with pre-defined colors, and specifying other arguments 100 | cols <- c(1, "forestgreen", 101 | 2, "darkolivegreen2", 102 | 3, "firebrick3", 103 | 4, "goldenrod1", 104 | 5, "deepskyblue3", 105 | 6, "black") 106 | 107 | mland_plot(ernesdesign, points = 9:11, radii = c(1000, 2000, 3000), 108 | title = "sitename", nrow = 1, 109 | st_points = list(shape = 9), 110 | st_buffers = list(lty = "dashed"), 111 | st_classes = list(fill = cols)) 112 | 113 | # Plot a unique landscape by calling it with its name 114 | mland_plot(ernesdesign, points = "Peje", title = "sitename", 115 | st_points = list(shape = 15, col = "red"), 116 | st_classes = list(palette = "Hawaii")) 117 | 118 | # Plot extra rasterlaer 119 | mland_plot(ernesdesign, radii = 3000, ext_raster = 1, title = "sitename") 120 | 121 | # Plot extra rasterlater with customized colors 122 | mland_plot(ernesdesign, radii = 3000, ext_raster = 1, title = "sitename", 123 | st_ext = c("blue", "red")) 124 | } 125 | } 126 | -------------------------------------------------------------------------------- /man/mland_save.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/mland_save.R 3 | \name{mland_save} 4 | \alias{mland_save} 5 | \title{Saves a 'MultiLand' or 'MultiLandMetrics' object} 6 | \usage{ 7 | mland_save( 8 | x, 9 | name = NULL, 10 | gdal = c("COMPRESS=DEFLATE", "PREDICTOR=2", "ZLEVEL=9"), 11 | dir = NULL, 12 | verbose = TRUE, 13 | ... 14 | ) 15 | } 16 | \arguments{ 17 | \item{x}{Object of class 'MultiLand' or 'MultiLandMetrics'.} 18 | 19 | \item{name}{If \code{x} is an object of class 'MultiLand', the name of the zip file where 20 | files will be saved (without the '.zip'). If \code{x} is an object of class 'MultiLandMetrics', the name of the R file (.rds). If NULL (default), 21 | the name will be 'mland_' or 'mlandmetrics_' + a large random number.} 22 | 23 | \item{gdal}{GeoTiff creation options for rasters (\href{https://gdal.org/en/stable/drivers/raster/gtiff.html}{GeoTiff file format}). 24 | \code{\link[=mland_save]{mland_save()}} uses the following compression options: c("COMPRESS=DEFLATE", "PREDICTOR=2", "ZLEVEL=9"). Only relevant 25 | if \code{x} is an object of class 'MultiLand'.} 26 | 27 | \item{dir}{Path to the export directory. This must be specified explicitly. 28 | To export to the current directory, use \code{dir = getwd()}. Otherwise, provide 29 | a valid path to an existing directory, ensuring it does not end with "/".} 30 | 31 | \item{verbose}{Print messages in the console? Default is TRUE.} 32 | 33 | \item{...}{If \code{x} is an object of class 'MultiLand', \code{...} should depict other arguments passed to 34 | \link[terra:writeRaster]{terra::writeRaster}, the function to write raster layers (from intersections and plain raster layers). 35 | Otherwise, if \code{x} is an object of class 'MultiLandMetrics', \code{...} should depict other arguments passed 36 | to \code{\link[=save]{save()}}. See Details.} 37 | } 38 | \value{ 39 | If \code{x} is an object of class 'MultiLand', a zip file or a directory containing all 40 | information regarding the 'MultiLand' object provided in 'x'. Otherwise, if \code{x} is an object of 41 | class 'MultiLandMetrics', the function will export the R object as if it was exported as a 42 | regular R object with \code{\link[=saveRDS]{saveRDS()}}. 43 | } 44 | \description{ 45 | Exports an object of class 'MultiLand' to be read in the future with \code{\link[=mland_load]{mland_load()}}, or 46 | an object of class 'MultiLandMetrics' as if it was saved with \code{\link[=saveRDS]{saveRDS()}}. 47 | } 48 | \details{ 49 | 'MultiLand' objects should be exported with this function rather than exporting as an 50 | external representation of R objects with \code{\link[=saveRDS]{saveRDS()}}. This is because objects of classes 51 | 'SpatVector' and 'SpatRaster' (from package terra) contained inside a 'MultiLand' 52 | object cannot be exported as regular R objects. The exported object will be a zip file, 53 | and can be loaded again into an R session with \code{\link[=mland_load]{mland_load()}}. 54 | 55 | Relevant arguments can be passed to the function \link[terra:writeRaster]{terra::writeRaster}, which is used to write 56 | raster layers from a 'MultiLand' object. Particularly, in the argument \code{gdal} one can specify 57 | relevant options regarding raster compression. This may reduce raster sizes significantly. Definition 58 | of some other arguments inside \link[terra:writeRaster]{terra::writeRaster} may affect exportation of raster layer 59 | objects, in the context of a 'MultiLand' object. 60 | 61 | Objects of class 'MultiLandMetrics', instead, do not contain 'SpatVector' or 'SpatRaster' objects 62 | and can be exported as regular R objects with \code{\link[=saveRDS]{saveRDS()}}. The user may use \code{\link[=saveRDS]{saveRDS()}} or 63 | \code{\link[=mland_save]{mland_save()}}, and the outcome will be identical. 64 | } 65 | \examples{ 66 | \donttest{ 67 | # Load MultiLand object 68 | mland_obj <- system.file("extdata", "ernesdesign.zip", package = "multilandr") 69 | ernesdesign2 <- mland_load(mland_obj) 70 | 71 | # Save it again, in temporary directory for this example and with a given name 72 | mland_save(ernesdesign2, name = "mland_example", dir = tempdir()) 73 | 74 | # Remove file for this example 75 | unlink(file.path(tempdir(), "mland_example.zip")) 76 | 77 | # Save it again but defining a higher compression for raster layers 78 | mland_save(ernesdesign2, gdal = "COMPRESS=DEFLATE", name = "mland_example", dir = tempdir()) 79 | 80 | # Remove file for this example 81 | unlink(file.path(tempdir(), "mland_example.zip")) 82 | 83 | # Loads a MultiLandMetrics object previously generated with mland_metrics() 84 | mlm_obj <- system.file("extdata", "ed_metrics.rds", package = "multilandr") 85 | ed_metrics2 <- mland_load(mlm_obj) 86 | 87 | # Save it again. In this case, mland_save() is the same as using saveRDS() 88 | mland_save(ed_metrics2, dir = tempdir(), name = "mlandmetrics_example") 89 | 90 | unlink(file.path(tempdir(), "mlandmetrics_example.rds")) 91 | } 92 | } 93 | \seealso{ 94 | \code{\link[=mland_load]{mland_load()}}, \code{\link[=mland]{mland()}}, \code{\link[=mland_metrics]{mland_metrics()}} 95 | } 96 | -------------------------------------------------------------------------------- /man/otf_metrics.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/data.R 3 | \docType{data} 4 | \name{otf_metrics} 5 | \alias{otf_metrics} 6 | \title{'MultiLandMetrics' object} 7 | \format{ 8 | An object of class \code{MultiLandMetrics} of length 1. 9 | } 10 | \usage{ 11 | otf_metrics 12 | } 13 | \description{ 14 | An object of class 'MultiLandMetrics' generated with \code{\link[=mland_metrics]{mland_metrics()}}, for the purposes of package 15 | examples of the following functions: \code{\link[=metrics_filter]{metrics_filter()}}, \code{\link[=metrics_gradient]{metrics_gradient()}}, 16 | \code{\link[=metrics_corr]{metrics_corr()}}, \code{\link[=metrics_plots]{metrics_plots()}} and \code{\link[=metrics_bind]{metrics_bind()}}. See 'MultiLand-class' for general 17 | information about these objects. 18 | } 19 | \details{ 20 | The main internal object is a data.frame (accesible through \code{otf_metrics@data}) with information about the values of two landscape metrics: 21 | "pland" (percentage of landscape) and "np" (number of patches). 22 | 23 | The object was created from the MultiLand object named "otf_design", which 24 | received a raster layer from a small portion of the ecoregion "El Chaco" as main input. 25 | The rasterlayer was provided by the project "MapBiomas Chaco" for the year 2000. 26 | } 27 | \seealso{ 28 | See the examples sections of \code{\link[=mland_metrics]{mland_metrics()}} and \code{\link[=mland]{mland()}} 29 | for more context. 30 | 31 | #' @references 32 | Project MapBiomas Chaco – Collection 4.0 of annual land cover and land use maps, 33 | accessed during July 2022 through the following link: \href{https://chaco.mapbiomas.org/}{MapBiomas Chaco} 34 | } 35 | \keyword{datasets} 36 | -------------------------------------------------------------------------------- /man/show-MultiLand-method.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/methods.R 3 | \name{show,MultiLand-method} 4 | \alias{show,MultiLand-method} 5 | \title{Show 'MultiLand' object} 6 | \usage{ 7 | \S4method{show}{MultiLand}(object) 8 | } 9 | \arguments{ 10 | \item{object}{Prints relevant information about a 'MultiLand' object.} 11 | } 12 | \value{ 13 | No return value, called for side effects. 14 | } 15 | \description{ 16 | Show 'MultiLand' object 17 | } 18 | -------------------------------------------------------------------------------- /man/show-MultiLandMetrics-method.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/methods.R 3 | \name{show,MultiLandMetrics-method} 4 | \alias{show,MultiLandMetrics-method} 5 | \title{Show 'MultiLandMetrics' object} 6 | \usage{ 7 | \S4method{show}{MultiLandMetrics}(object) 8 | } 9 | \arguments{ 10 | \item{object}{Prints relevant information about a 'MultiLandMetrics' object.} 11 | } 12 | \value{ 13 | No return value, called for side effects. 14 | } 15 | \description{ 16 | Show 'MultiLandMetrics' object 17 | } 18 | -------------------------------------------------------------------------------- /manual.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/phuais/multilandr/3b1d7fa40858c26a72186480a3b7a7aabfa13021/manual.pdf -------------------------------------------------------------------------------- /multilandr.Rproj: -------------------------------------------------------------------------------- 1 | Version: 1.0 2 | 3 | RestoreWorkspace: No 4 | SaveWorkspace: No 5 | AlwaysSaveHistory: Default 6 | 7 | EnableCodeIndexing: Yes 8 | UseSpacesForTab: Yes 9 | NumSpacesForTab: 2 10 | Encoding: UTF-8 11 | 12 | RnwWeave: Sweave 13 | LaTeX: pdfLaTeX 14 | 15 | AutoAppendNewline: Yes 16 | StripTrailingWhitespace: Yes 17 | LineEndingConversion: Posix 18 | 19 | BuildType: Package 20 | PackageUseDevtools: Yes 21 | PackageInstallArgs: --no-multiarch --with-keep.source 22 | PackageRoxygenize: rd,collate,namespace 23 | -------------------------------------------------------------------------------- /tests/testthat.R: -------------------------------------------------------------------------------- 1 | # This file is part of the standard setup for testthat. 2 | # It is recommended that you do not modify it. 3 | # 4 | # Where should you do additional test configuration? 5 | # Learn more about the roles of various files in: 6 | # * https://r-pkgs.org/tests.html 7 | # * https://testthat.r-lib.org/reference/test_package.html#special-files 8 | 9 | library(testthat) 10 | library(multilandr) 11 | 12 | test_check("multilandr") 13 | -------------------------------------------------------------------------------- /tests/testthat/test-mland.R: -------------------------------------------------------------------------------- 1 | # Test: mland() arguments 2 | 3 | test_that("loads MultiLand successfully", { 4 | expect_s4_class({ 5 | elchaco <- terra::rast(system.file("extdata", "elchaco.tif", package = "multilandr")) 6 | elchaco_sites <- terra::vect(system.file("extdata", "elchaco_sites.gpkg", package = "multilandr")) 7 | mm <- mland(points_layer = elchaco_sites, 8 | rast_layer = elchaco, 9 | radii = seq(1000, 5000, 1000), 10 | site_ref = "name", 11 | rast_names = "landcover", 12 | segs = 20, 13 | progress = F) 14 | }, "MultiLand") 15 | 16 | expect_error({ 17 | elchaco <- terra::rast(system.file("extdata", "elchaco.tif", package = "multilandr")) 18 | elchaco_sites <- terra::vect(system.file("extdata", "elchaco_sites.gpkg", package = "multilandr")) 19 | mland(points_layer = elchaco_sites2, 20 | rast_layer = elchaco, 21 | radii = seq(1000, 5000, 1000), 22 | site_ref = "name", 23 | rast_names = "landcover", 24 | segs = 20, 25 | progress = F) 26 | }) 27 | 28 | expect_error({ 29 | elchaco <- terra::rast(system.file("extdata", "elchaco.tif", package = "multilandr")) 30 | elchaco_sites <- terra::vect(system.file("extdata", "elchaco_sites.gpkg", package = "multilandr")) 31 | mland(points_layer = elchaco_sites, 32 | rast_layer = elchaco, 33 | radii = c("a", "b", "c"), 34 | site_ref = "name", 35 | rast_names = "landcover", 36 | segs = 20, 37 | progress = F) 38 | }, "- argument 'radii' must be a vector of positive numbers.") 39 | 40 | expect_warning({ 41 | elchaco <- terra::rast(system.file("extdata", "elchaco.tif", package = "multilandr")) 42 | elchaco_sites <- terra::vect(system.file("extdata", "elchaco_sites.gpkg", package = "multilandr")) 43 | mland(points_layer = elchaco_sites, 44 | rast_layer = elchaco, 45 | radii = seq(1000, 5000, 1000), 46 | site_ref = "site", 47 | rast_names = "landcover", 48 | segs = 20, 49 | progress = F) 50 | }) 51 | 52 | expect_warning({ 53 | elchaco <- terra::rast(system.file("extdata", "elchaco.tif", package = "multilandr")) 54 | elchaco_sites <- terra::vect(system.file("extdata", "elchaco_sites.gpkg", package = "multilandr")) 55 | mland(points_layer = elchaco_sites, 56 | rast_layer = elchaco, 57 | radii = seq(1000, 5000, 1000), 58 | site_ref = "name", 59 | class_names = c(1, "Forest", 60 | 2, "Grassland", 61 | 3, "Crops", 62 | 4, "Pastures", 63 | 5, "Water", 64 | 6, "Urban"), 65 | rast_names = "landcover", 66 | segs = 20, 67 | progress = F) 68 | }) 69 | 70 | expect_warning({ 71 | elchaco <- terra::rast(system.file("extdata", "elchaco.tif", package = "multilandr")) 72 | elchaco_sites <- terra::vect(system.file("extdata", "elchaco_sites.gpkg", package = "multilandr")) 73 | mland(points_layer = elchaco_sites, 74 | rast_layer = elchaco, 75 | radii = seq(1000, 5000, 1000), 76 | site_ref = "name", 77 | class_names = list(c(1, "Forest", 78 | 2, "Grassland", 79 | 3, "Crops")), 80 | rast_names = "landcover", 81 | segs = 20, 82 | progress = F) 83 | }) 84 | 85 | }) 86 | 87 | # Test: mland_overlap() 88 | 89 | ernesdesign <- system.file("extdata", "ernesdesign.zip", package = "multilandr") 90 | ernesdesign <- suppressMessages(mland_load(ernesdesign)) 91 | 92 | test_that("perform overlapping calculations", { 93 | expect_error({ 94 | mland_overlap(ernesdesign, points = 17:20) 95 | }) 96 | expect_warning({ 97 | mland_overlap(ernesdesign, points = 1:2, title = "site") 98 | }) 99 | }) 100 | 101 | # Test: generate_points 102 | 103 | test_that("generation of points is going fine", { 104 | elchaco <- terra::rast(system.file("extdata", "elchaco.tif", package = "multilandr")) 105 | expect_s4_class({ 106 | generate_points(elchaco, approach = "random", values = 1, n = 500, progress = F)}, 107 | "SpatVector") 108 | expect_equal({ 109 | pp <- generate_points(elchaco, approach = "patch", 110 | patch_conditions = conditions(list(1, "area", 8, 8.1)), progress = F) 111 | length(pp) 112 | }, 35) 113 | }) 114 | -------------------------------------------------------------------------------- /tests/testthat/test-mland_metrics.R: -------------------------------------------------------------------------------- 1 | # Test: mland_metrics() 2 | 3 | ernesdesign <- system.file("extdata", "ernesdesign.zip", package = "multilandr") 4 | ernesdesign <- suppressMessages(mland_load(ernesdesign)) 5 | ed_metrics_test <- mland_metrics(ernesdesign, level = "class", metric = c("pland", "ed"), 6 | absence_values = list("pland" = 0), 7 | points = 1, radii = 1000, progress = F) 8 | mean_sd <- function(x){ mean(x)/sd(x) } 9 | 10 | test_that("colnames of metric dataframe have not changed", { 11 | expect_equal({ 12 | colnames(ed_metrics_test@data) 13 | }, c("rasterlayer", "layer_name", "point_id", "site", "radius", "level", 14 | "class", "classname", "patch_id", "metric", "value")) 15 | }) 16 | 17 | test_that("metrics calculation are ok", { 18 | expect_equal({ 19 | round(ed_metrics_test@data$value, digits = 2) 20 | }, c(13.83, 5.94, 16.24, 3.71, NA, NA, 26.56, 1.09, 71.46, 0.89, 0.00, 0.00)) 21 | expect_equal({ 22 | ed_metrics2 <- mland_metrics(ernesdesign, level = "class", metric = c("pland", "ed"), 23 | absence_values = list("pland" = 0), 24 | ext_calc = list(c(1, "mean")), 25 | points = 1, radii = 1000, progress = F) 26 | round(ed_metrics2@data$value, digits = 2) 27 | }, c(13.83, 5.94, 16.24, 3.71, NA, NA, 26.56, 1.09, 71.46, 0.89, 0.00, 0.00, 0.40)) 28 | }) 29 | 30 | # Test: metrics_filter() 31 | 32 | test_that("metric filtering is ok", { 33 | expect_equal({ 34 | otf_subset <- metrics_filter(otf_metrics, 35 | conditions = conditions(list(NA, "Forest", 2000, "pland", 20, 30)), 36 | output = "MLM") 37 | otf_subset@n_points 38 | }, 140) 39 | 40 | expect_equal({ 41 | otf_subset2 <- metrics_filter(otf_metrics, 42 | conditions = conditions(list(NA, "Forest", 2000, "pland", 20, 30), 43 | list(NA, "Crops", 2000, "pland", -Inf, 60)), 44 | output = "MLM") 45 | otf_subset2@n_points 46 | }, 67) 47 | }) 48 | 49 | # Test: metrics_corr and metrics_plots 50 | test_that("metrics correlations and plots going silently", { 51 | expect_silent({ 52 | metrics_corr(ed_metrics, radii = 5000, show_class_names = TRUE)}) 53 | expect_silent({ 54 | metrics_plots(ed_metrics, classes = 1:4, radii = 3000, show_class_names = TRUE, c_level = "pland")}) 55 | }) 56 | 57 | # Test: metrics_bind 58 | test_that("metric binding is going fine", { 59 | sites <- ed_metrics@points$name 60 | sampling_data <- data.frame(site = rep(sites, each = 10), richness = sample(1:500, 150)) 61 | expect_silent({ 62 | metrics_bind(ed_metrics, sampling_data)}) 63 | expect_equal({ 64 | new_data <- metrics_bind(ed_metrics, sampling_data) 65 | dim(new_data)} 66 | , c(150, 68)) 67 | }) 68 | 69 | -------------------------------------------------------------------------------- /vignettes/.gitignore: -------------------------------------------------------------------------------- 1 | *.html 2 | *.R 3 | --------------------------------------------------------------------------------