├── .Rbuildignore ├── .github └── workflows │ ├── R-CMD-check.yaml │ └── collect_metadata.yml ├── DESCRIPTION ├── LICENSE ├── NAMESPACE ├── NEWS.md ├── R ├── data.R ├── getters.R ├── helpers.R ├── imports.R ├── metrics.R ├── sfn_data_classes.R ├── sfn_data_generics.R ├── sfn_data_methods.R ├── sfn_dplyr.R └── visualizations.R ├── README.Rmd ├── README.md ├── _pkgdown.yml ├── benchmarking ├── benchmarking_splitting_sites.R └── benchmarking_tests.R ├── cran-comments.md ├── data-raw └── FOO_BAR_BAZ_creation.R ├── data ├── ARG_MAZ.rda ├── ARG_TRE.rda ├── AUS_CAN_ST2_MIX.rda └── sfn_metadata_ex.rda ├── man ├── ARG_MAZ.Rd ├── ARG_TRE.Rd ├── AUS_CAN_ST2_MIX.Rd ├── as_sfn_data_multi.Rd ├── data_coverage.Rd ├── describe_md_variable.Rd ├── diurnal_centroid.Rd ├── dot-accumulated_posix_aware.Rd ├── dot-assert_that_period_is_valid.Rd ├── dot-collapse_timestamp.Rd ├── dot-env_vars_names.Rd ├── dot-fixed_metrics_funs.Rd ├── dot-flag.Rd ├── dot-metadata_architecture.Rd ├── dot-nightly_daily_cf.Rd ├── dot-parse_period.Rd ├── dot-period_to_minutes.Rd ├── dot-sapflow_tidy.Rd ├── dot-timezone_dic.Rd ├── dot-write_metadata_cache.Rd ├── figures │ ├── README-example_multi-1.png │ ├── README-example_multi-2.png │ ├── README-example_single-1.png │ └── README-example_single-2.png ├── filter_sites_by_md.Rd ├── get_timezone.Rd ├── initialize-sfn_data-method.Rd ├── initialize-sfn_data_multi-method.Rd ├── metrics.Rd ├── metrics_tidyfier.Rd ├── norm_diurnal_centroid.Rd ├── pipe.Rd ├── read_sfn_data.Rd ├── read_sfn_metadata.Rd ├── sfn_data-class.Rd ├── sfn_data_multi-class.Rd ├── sfn_data_multi_validity.Rd ├── sfn_data_validity.Rd ├── sfn_filter.Rd ├── sfn_get_generics.Rd ├── sfn_get_methods.Rd ├── sfn_metadata_ex.Rd ├── sfn_metrics.Rd ├── sfn_multi_get_methods.Rd ├── sfn_mutate.Rd ├── sfn_mutate_at.Rd ├── sfn_plot.Rd ├── sfn_replacement_generics.Rd ├── sfn_replacement_methods.Rd ├── sfn_sites_in_folder.Rd ├── sfn_vars_to_filter.Rd ├── show-sfn_data-method.Rd ├── show-sfn_data_multi-method.Rd ├── summarise_by_period.Rd └── time_at_events.Rd ├── metadata.yml ├── pkgdown └── extra.css ├── tests ├── testthat.R └── testthat │ ├── ARG_MAZ.RData │ ├── ARG_TRE.RData │ ├── AUS_CAN_ST2_MIX.RData │ ├── Data │ ├── ARG_MAZ.RData │ ├── ARG_TRE.RData │ └── AUS_CAN_ST2_MIX.RData │ ├── test-getters.R │ ├── test-helpers.R │ ├── test-metrics.R │ ├── test-sfn_data_classes.R │ ├── test-sfn_dplyr_methods.R │ └── test-visualizations.R ├── tic.R └── vignettes ├── custom-aggregation.Rmd ├── data-flags.Rmd ├── memory-and-parallelization.Rmd ├── metadata-and-data-units.Rmd ├── resources ├── ARG_MAZ.RData ├── ARG_TRE.RData ├── AUS_CAN_ST2_MIX.RData ├── schematics.odg ├── schematics.svg └── schematics.svg.png ├── sapfluxnetr-quick-guide.Rmd └── sfn-data-classes.Rmd /.Rbuildignore: -------------------------------------------------------------------------------- 1 | ^CRAN-RELEASE$ 2 | ^cran-comments\.md$ 3 | ^\.travis\.yml$ 4 | ^docs$ 5 | ^_pkgdown\.yml$ 6 | ^.*\.Rproj$ 7 | ^\.Rproj\.user$ 8 | 9 | tests/testthat/Data/.metadata_cache.RData 10 | tests/testthat/big_test/ 11 | ^benchmarking$ 12 | ^data-raw$ 13 | ^README\.Rmd$ 14 | ^README-.*\.png$ 15 | ^pkgdown$ 16 | ^README_files$ 17 | ^tic\.R$ 18 | ^\.github$ 19 | ^metadata\.yml$ 20 | -------------------------------------------------------------------------------- /.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 | branches: [main, master] 8 | 9 | name: R-CMD-check 10 | 11 | jobs: 12 | R-CMD-check: 13 | runs-on: ${{ matrix.config.os }} 14 | 15 | name: ${{ matrix.config.os }} (${{ matrix.config.r }}) 16 | 17 | strategy: 18 | fail-fast: false 19 | max-parallel: 5 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 | R_REMOTES_NO_ERRORS_FROM_WARNINGS: true 32 | NOT_CRAN: true 33 | R_KEYRING_BACKEND: env 34 | 35 | steps: 36 | - uses: actions/checkout@v3 37 | 38 | - uses: r-lib/actions/setup-pandoc@v2 39 | 40 | - uses: r-lib/actions/setup-r@v2 41 | with: 42 | r-version: ${{ matrix.config.r }} 43 | http-user-agent: ${{ matrix.config.http-user-agent }} 44 | use-public-rspm: true 45 | 46 | - uses: r-lib/actions/setup-r-dependencies@v2 47 | with: 48 | extra-packages: any::rcmdcheck 49 | needs: check 50 | 51 | - uses: r-lib/actions/check-r-package@v2 52 | with: 53 | upload-snapshots: true 54 | -------------------------------------------------------------------------------- /.github/workflows/collect_metadata.yml: -------------------------------------------------------------------------------- 1 | on: 2 | push: 3 | branches: 4 | - main 5 | - master 6 | pull_request: 7 | branches: 8 | - main 9 | - master 10 | 11 | name: collect_metadata 12 | 13 | jobs: 14 | collect: 15 | runs-on: ubuntu-latest 16 | 17 | env: 18 | GITHUB_PAT: ${{ secrets.GITHUB_TOKEN }} 19 | EMF_DATABASE_HOST: ${{ secrets.EMF_DATABASE_HOST }} 20 | EMF_DATABASE_USER: ${{ secrets.EMF_DATABASE_USER}} 21 | EMF_DATABASE_PASS: ${{ secrets.EMF_DATABASE_PASS}} 22 | EMF_DATABASE: ${{ secrets.EMF_DATABASE}} 23 | 24 | steps: 25 | - uses: actions/checkout@v3 26 | 27 | - uses: r-lib/actions/setup-r@v2 28 | 29 | - name: Install system dependencies 30 | run: | 31 | sudo apt-get install -y make libicu-dev pandoc libcurl4-openssl-dev libssl-dev git libgit2-dev libpq-dev libfontconfig1-dev libfreetype6-dev libfribidi-dev libharfbuzz-dev libjpeg-dev libpng-dev libtiff-dev libxml2-dev libssh-dev 32 | 33 | - name: Cache keys dependencies 34 | run: | 35 | install.packages('pkgdepends') 36 | saveRDS(pkgdepends::new_pkg_deps('https://github.com/emf-creaf/EMFtoolbox')$resolve()$get_resolution(), ".github/depends.Rds", version = 2) 37 | writeLines(sprintf("R-%i.%i", getRversion()$major, getRversion()$minor), ".github/R-version") 38 | shell: Rscript {0} 39 | 40 | - name: Restore R package cache 41 | uses: actions/cache@v3 42 | with: 43 | path: ${{ env.R_LIBS_USER }} 44 | key: ${{ runner.os }}-${{ hashFiles('.github/R-version') }}-1-${{ hashFiles('.github/depends.Rds') }} 45 | restore-keys: ${{ runner.os }}-${{ hashFiles('.github/R-version') }}-1- 46 | 47 | - name: Install packages 48 | run: | 49 | R -e 'install.packages("remotes")' 50 | R -e 'remotes::install_github("emf-creaf/EMFtoolbox")' 51 | 52 | - name: Collect metadata and update db 53 | run: | 54 | R -e 'EMFtoolbox::collect_metadata(.dry = FALSE)' 55 | -------------------------------------------------------------------------------- /DESCRIPTION: -------------------------------------------------------------------------------- 1 | Package: sapfluxnetr 2 | Title: Working with 'Sapfluxnet' Project Data 3 | Version: 0.1.4 4 | Authors@R: c( 5 | person("Victor", "Granda", email = "victorgrandagarcia@gmail.com", role = c("aut", "cre"), comment = c(ORCID = "0000-0002-0469-1991")), 6 | person("Rafael", "Poyatos", email = "r.poyatos@creaf.uab.cat", role = "aut", comment = c(ORCID = "0000-0003-0521-2523")), 7 | person("Victor", "Flo", email = "v.flo@creaf.uab.cat", role = "aut", comment = c(ORCID = "0000-0003-1908-4577")), 8 | person("Jacob", "Nelson", email = "", role = 'ctb', comment = c(ORCID = "0000-0002-4663-2420")), 9 | person("Sapfluxnet Core Team", email = "sapfluxnet@creaf.uab.cat", role = 'cph') 10 | ) 11 | Description: Access, modify, aggregate and plot data from the 'Sapfluxnet' project 12 | (), the first global database of sap flow measurements. 13 | Depends: R (>= 3.5.0) 14 | License: MIT + file LICENSE 15 | Encoding: UTF-8 16 | LazyData: true 17 | Imports: 18 | assertthat, 19 | dplyr, 20 | furrr, 21 | ggplot2, 22 | glue, 23 | lubridate, 24 | magrittr, 25 | methods, 26 | purrr, 27 | rlang, 28 | stats, 29 | stringr, 30 | tibble, 31 | tidyr 32 | RoxygenNote: 7.2.3 33 | Collate: 34 | 'data.R' 35 | 'getters.R' 36 | 'helpers.R' 37 | 'imports.R' 38 | 'metrics.R' 39 | 'sfn_data_classes.R' 40 | 'sfn_data_generics.R' 41 | 'sfn_data_methods.R' 42 | 'sfn_dplyr.R' 43 | 'visualizations.R' 44 | Suggests: 45 | future, 46 | knitr, 47 | remotes, 48 | rmarkdown, 49 | testthat, 50 | xtable 51 | Config/testthat/edition: 3 52 | Config/testthat/parallel: true 53 | VignetteBuilder: knitr 54 | URL: https://github.com/sapfluxnet/sapfluxnetr 55 | BugReports: https://github.com/sapfluxnet/sapfluxnetr/issues 56 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | YEAR: 2018-2020 2 | COPYRIGHT HOLDER: Sapfluxnet Core Team -------------------------------------------------------------------------------- /NAMESPACE: -------------------------------------------------------------------------------- 1 | # Generated by roxygen2: do not edit by hand 2 | 3 | export("%>%") 4 | export("get_env_data<-") 5 | export("get_env_flags<-") 6 | export("get_env_md<-") 7 | export("get_plant_md<-") 8 | export("get_sapf_data<-") 9 | export("get_sapf_flags<-") 10 | export("get_si_code<-") 11 | export("get_site_md<-") 12 | export("get_solar_timestamp<-") 13 | export("get_species_md<-") 14 | export("get_stand_md<-") 15 | export("get_timestamp<-") 16 | export(daily_metrics) 17 | export(data_coverage) 18 | export(daylight_metrics) 19 | export(describe_md_variable) 20 | export(diurnal_centroid) 21 | export(filter_sites_by_md) 22 | export(get_env_data) 23 | export(get_env_flags) 24 | export(get_env_md) 25 | export(get_plant_md) 26 | export(get_sapf_data) 27 | export(get_sapf_flags) 28 | export(get_si_code) 29 | export(get_site_md) 30 | export(get_solar_timestamp) 31 | export(get_species_md) 32 | export(get_stand_md) 33 | export(get_timestamp) 34 | export(get_timezone) 35 | export(metrics_tidyfier) 36 | export(midday_metrics) 37 | export(monthly_metrics) 38 | export(nightly_metrics) 39 | export(predawn_metrics) 40 | export(read_sfn_data) 41 | export(read_sfn_metadata) 42 | export(sfn_data) 43 | export(sfn_data_multi) 44 | export(sfn_filter) 45 | export(sfn_metrics) 46 | export(sfn_mutate) 47 | export(sfn_mutate_at) 48 | export(sfn_plot) 49 | export(sfn_sites_in_folder) 50 | export(sfn_vars_to_filter) 51 | export(summarise_by_period) 52 | exportClasses(sfn_data) 53 | exportClasses(sfn_data_multi) 54 | exportMethods("get_env_data<-") 55 | exportMethods("get_env_flags<-") 56 | exportMethods("get_env_md<-") 57 | exportMethods("get_plant_md<-") 58 | exportMethods("get_sapf_flags<-") 59 | exportMethods("get_si_code<-") 60 | exportMethods("get_site_md<-") 61 | exportMethods("get_solar_timestamp<-") 62 | exportMethods("get_species_md<-") 63 | exportMethods("get_stand_md<-") 64 | exportMethods("get_timestamp<-") 65 | exportMethods(get_env_data) 66 | exportMethods(get_env_flags) 67 | exportMethods(get_env_md) 68 | exportMethods(get_plant_md) 69 | exportMethods(get_sapf_data) 70 | exportMethods(get_sapf_flags) 71 | exportMethods(get_si_code) 72 | exportMethods(get_site_md) 73 | exportMethods(get_solar_timestamp) 74 | exportMethods(get_species_md) 75 | exportMethods(get_stand_md) 76 | exportMethods(get_timestamp) 77 | exportMethods(initialize) 78 | exportMethods(show) 79 | import(ggplot2) 80 | import(methods) 81 | importFrom(dplyr,n) 82 | importFrom(magrittr,"%>%") 83 | importFrom(rlang,.data) 84 | importFrom(stats,quantile) 85 | importFrom(stats,sd) 86 | -------------------------------------------------------------------------------- /NEWS.md: -------------------------------------------------------------------------------- 1 | # sapfluxnetr 0.1.4 2 | 3 | * Fixed warnings due to changes in dependencies `purrr`, `tidyselect` and `ggplot2` 4 | * Fixed problem in .timezones_dic which gives some timezones as NULL due to 5 | ASCII characters in env_time_zone metadata variable 6 | 7 | # sapfluxnetr 0.1.3 8 | 9 | * Fixed tests to comply with next version of dplyr dependency (1.0.8) 10 | 11 | # sapfluxnetr 0.1.2 12 | 13 | * Improved docs (sub-daily aggregations, default metrics...) 14 | * Fix use of `setdiff` to check differences between data frames, not working on devel R versions 15 | 16 | # sapfluxnetr 0.1.1 17 | 18 | * Remove `tidyr::gather` and `tidyr::spread` calls, replacing them with the now 19 | recommended `tidyr::pivot_longer` and `tidyr::pivot_wide` calls. 20 | * Following the new database available, *"Mediterranean"* biome is replaced 21 | by *"Woodland/Shrubland"* in all vignettes and function examples where it was 22 | used. 23 | 24 | # sapfluxnetr 0.1.0 25 | 26 | * Removed `tidyverse` dependency from *suggests*. 27 | * Updated internal `.fixed_metrics_funs` to use formulas instead of quosures 28 | on quantile metrics in the functions list, as the use of quosures here is 29 | deprecated by newer dplyr versions. 30 | * First minor version, open data released 31 | 32 | # sapfluxnetr 0.0.7 33 | 34 | * Replaced calls of dplyr::funs with list (or rlang::list2 if splicing is needed) 35 | as the former is soft deprecated in dplyr 0.8.0 36 | * One word periods ('daily', 'monthly'...) in `sfn_metrics` function are 37 | **soft deprecated**. Please use '1 day', '1 month'... instead. 38 | * Removed all dependencies on 'tibbletime' package 39 | * Added utils internal functions: .collapse_timestamp and .parse_period 40 | * Added installation from CRAN to vignette and readme 41 | 42 | # sapfluxnetr 0.0.6 43 | 44 | * Improved examples in the functions help 45 | * Updated license file to comply with CRAN policy 46 | * Cleaning to comply with CRAN checks in windows builds and travis CI 47 | * Added .accumulated_posix_aware helper function to avoid summing posix objects 48 | * Added pkgdown support 49 | * Added Travis CI support 50 | * Updated sapfluxnetr Not So Quick Guide vignette and README file 51 | 52 | # sapfluxnetr 0.0.5 53 | 54 | * Cleaning to comply with CRAN checks. 55 | * Added the *"Metadata and data units"* vignette. 56 | * Fixes for the new `purrr` version. 57 | * Exported the pipe operator (`%>%`) from `magrittr` package. Now loading 58 | `sapfluxnetr` the pipe can be used. 59 | * Added `acummulated_precip` as new metric for the default `*_metrics` functions. 60 | * Fixed `data_coverage` function. Now it returns the real coverage based on the 61 | timestep, the period to summarise for and the timestamp values. This only will 62 | work within the wrapper metrics functions (using internally the 63 | `.fixed_metrics_funtions` function). 64 | * Fixed a bug in sfn_metrics that for special intervals (md, pd, daylight) the 65 | filtering step was collecting timestamps above the int_end 66 | * Fixed bug in metrics function that created min and max time variables as double 67 | instead of POSIXct in sites with NAs in the first day of measures 68 | * Now species metadata variables are returned individually instead of a list 69 | * Added helper function `sfn_sites_in_folder` to list the site codes in a folder 70 | * Deprecated `filter_by_var`, substituted by `filter_sites_by_md` 71 | * **Implementation of furrr::future_map** in `sfn_metrics`. After some 72 | benchmarking, the benefits in time are solid, so now the user has the ability 73 | to perform the metrics in parallel. 74 | * New logic with performance improvements for metrics_tidyfier (introducing the 75 | .sapflow_tidy internal helper function) 76 | * Added get methods for sfn_data_multi class objects 77 | * Fixed bug in metrics function that created min and max time variables as double 78 | instead of POSIXct in sites with NAs in the first day of measures 79 | * Now species metadata variables are returned individually instead of in a list 80 | 81 | # sapfluxnetr 0.0.4 82 | 83 | * Added geom control to `sfn_plot` function. 84 | * Refactored `sfn_metrics` to uniformize interval start and interval end 85 | * Modified `nightly_metrics` to return only night interval 86 | * Created `predawn_metrics`, `midday_metrics` and `daylight_metrics` functions 87 | taking leverage in the refactored `sfn_metrics` functions. 88 | * Modified `daily_metrics` and `monthly_metrics` to return only the general 89 | interval metrics, avoiding this way the creation of very big objects. 90 | * Added `tidy` argument to *_metrics functions, to skip one step when creating 91 | tidy metrics. 92 | * Updated README file 93 | * Added bug report link to DESCRIPTION file 94 | * Updated documentation and vignettes accordingly with the changes made 95 | 96 | # sapfluxnetr 0.0.3 97 | 98 | * Added metrics_tidyfier function to convert to tidy the metrics results. 99 | * Added sfn_metadata_ex to Data. 100 | * Changed all example data names to the original site name. 101 | * Improved install explanation in quick guide vignette. 102 | * Added a `NEWS.md` file to track changes to the package. 103 | * Added `README.md` file for new users. 104 | 105 | # sapfluxnetr 0.0.2 106 | 107 | * Code and Docs cleaning. 108 | * Added vignettes for flags, classes, quick guide and custom aggregation . 109 | * Updated big-tests for dplyr-like functions. 110 | * Refactored metadata cache. 111 | * Modification of sfn_data show method to include site paper. 112 | * Added documentation for dplyr-like methods sfn_filter, sfn_mutate and 113 | sfn_mutate_at. 114 | * Added .flag internal function to flag mutated sfn_data objects. 115 | 116 | # sapfluxnetr 0.0.1 117 | 118 | * Initial version of the package. 119 | -------------------------------------------------------------------------------- /R/data.R: -------------------------------------------------------------------------------- 1 | #' ARG_TRE sapfluxnet site 2 | #' 3 | #' Example site for package usage demonstration based on ARG_TRE 4 | #' 5 | #' @examples 6 | #' data('ARG_TRE', package = 'sapfluxnetr') 7 | #' ARG_TRE 8 | #' 9 | #' @format An sfn_data class object with the data and metadata for ARG_TRE site 10 | "ARG_TRE" 11 | 12 | #' ARG_MAZ sapfluxnet site 13 | #' 14 | #' Example site for package usage demonstration based on ARG_MAZ 15 | #' 16 | #' @examples 17 | #' data('ARG_MAZ', package = 'sapfluxnetr') 18 | #' ARG_MAZ 19 | #' 20 | #' @format An sfn_data class object with the data and metadata for ARG_MAZ site 21 | "ARG_MAZ" 22 | 23 | #' AUS_CAN_ST2_MIX sapfluxnet site 24 | #' 25 | #' Example site for package usage demonstration based on AUS_CAN_ST2_MIX 26 | #' 27 | #' @examples 28 | #' data('AUS_CAN_ST2_MIX', package = 'sapfluxnetr') 29 | #' AUS_CAN_ST2_MIX 30 | #' 31 | #' @format An sfn_data class object with the data and metadata for AUS_CAN_ST2_MIX site 32 | "AUS_CAN_ST2_MIX" 33 | 34 | #' sfn_metadata cache file for example data (ARG_MAZ, ARG_TRE and AUS_CAN_ST2_MIX) 35 | #' 36 | #' Example metadata cache file content for package usage demonstration 37 | #' 38 | #' @examples 39 | #' data('sfn_metadata_ex', package = 'sapfluxnetr') 40 | #' sfn_metadata_ex 41 | #' 42 | #' @format A list with five elements, each of one a metadata type. 43 | "sfn_metadata_ex" 44 | -------------------------------------------------------------------------------- /R/getters.R: -------------------------------------------------------------------------------- 1 | ## This functions are related to get the info about the different datasets 2 | ## and list/copy/load the filtered datasets 3 | 4 | #' Read sfn_data from disk 5 | #' 6 | #' Given a site code and a route, \code{read_sfn_data} will return the selected 7 | #' sfn_data object 8 | #' 9 | #' @param site_codes A character vector with the site code/s 10 | #' 11 | #' @param folder Route to the folder containing the \code{.RData} file. Default 12 | #' to working directory. 13 | #' 14 | #' @return If \code{site_codes} is a vector of length 1, an sfn_data object with 15 | #' the selected site data. If \code{site_codes} is a vector of length > 1, then 16 | #' a sfn_data_multi object containing all selected sites. 17 | #' 18 | #' @examples 19 | #' # Let's access the data in "folder". This typically is the folder where the 20 | #' # sapflow data at the desired unit level is (i.e. "RData/plant"), but in this 21 | #' # example we will create a temporal folder with some data to test the function 22 | #' folder <- tempdir() 23 | #' save(ARG_TRE, file = file.path(folder, 'ARG_TRE.RData')) 24 | #' save(ARG_MAZ, file = file.path(folder, 'ARG_MAZ.RData')) 25 | #' 26 | #' # now we read a single site 27 | #' ARG_TRE_test <- read_sfn_data('ARG_TRE', folder) 28 | #' ARG_TRE_test 29 | #' 30 | #' # or we can read multiple sites at once 31 | #' multi_sfn <- read_sfn_data( 32 | #' c('ARG_TRE', 'ARG_MAZ'), folder 33 | #' ) 34 | #' multi_sfn 35 | #' 36 | #' @export 37 | 38 | read_sfn_data <- function(site_codes, folder = '.') { 39 | 40 | # if more than one site we need to map the call 41 | if (length(site_codes) > 1) { 42 | sites_multi <- purrr::map(site_codes, read_sfn_data, folder) %>% 43 | as_sfn_data_multi() 44 | 45 | return(sites_multi) 46 | } 47 | 48 | # one site, we need to find it and load it 49 | file_name <- file.path(folder, paste0(site_codes, '.RData')) 50 | 51 | if (!file.exists(file_name)) { 52 | stop(folder, ' folder does not contain any file called ', site_codes, '.RData') 53 | } else { 54 | load(file = file_name) 55 | 56 | # load will load in the function environment a SITE_CODE object, 57 | # we need to access to it to return it 58 | return(eval(as.name(site_codes))) 59 | } 60 | 61 | } 62 | 63 | #' Write metadata cache file to disk 64 | #' 65 | #' Load all sites, read the metadata and write it to disk to cache the 66 | #' info for easy and fast access 67 | #' 68 | #' Load all data in memory to collect metadata info can be resource limiting. 69 | #' For easy and quick access to metadata, this function stores an .RData file 70 | #' in the specified folder along the data with all the metadata preloaded. 71 | #' 72 | #' @param folder Route to the folder containing the data. Default to working 73 | #' directory 74 | #' 75 | #' @param .dry Dry run. Metadata is loaded and read, but no cache is written 76 | #' 77 | #' @examples 78 | #' # Let's access the data in "folder". This typically is the folder where the 79 | #' # sapflow data at the desired unit level is (i.e. "RData/plant"), but in this 80 | #' # example we will create a temporal folder with some data to test the function 81 | #' folder <- tempdir() 82 | #' save(ARG_TRE, file = file.path(folder, 'ARG_TRE.RData')) 83 | #' save(ARG_MAZ, file = file.path(folder, 'ARG_MAZ.RData')) 84 | #' 85 | #' # lets create the metadata cache file 86 | #' sapfluxnetr:::.write_metadata_cache(folder, .dry = FALSE)#' 87 | #' file.exists(file.path(folder, '.metadata_cache.RData')) # TRUE 88 | #' 89 | #' @return A list of tibbles with the five metadata classes (site, stand, 90 | #' species, plant and environmental) 91 | #' @keywords internal 92 | 93 | .write_metadata_cache <- function(folder, .dry = FALSE) { 94 | 95 | # In order to avoid loading all data objects at one time in memory (it could be 96 | # too much in a normal system we think), lets only store the metadata. To do 97 | # that, we load one site and store the metadata before to pass to the next. 98 | # If we simply map read_sfn_data %>% get_plant_md for example, that will 99 | # result in all objects in memory, so NO GOOD, we nned to circumvent that. 100 | sites_codes <- list.files(folder, recursive = TRUE, pattern = '.RData') %>% 101 | stringr::str_remove('.RData') 102 | 103 | sfn_metadata <- list( 104 | site_md = tibble::tibble(), 105 | stand_md = tibble::tibble(), 106 | species_md = tibble::tibble(), 107 | plant_md = tibble::tibble(), 108 | env_md = tibble::tibble() 109 | ) 110 | 111 | # we do a simple for loop instead of loading all sites and getting the 112 | # metadata because in the benchmarking it not presents any time adventage and 113 | # in this way the memory is liberated in each loop, so it's suitable for 114 | # low memory systems (more or less) 115 | for (i in 1:length(sites_codes)) { 116 | 117 | print(paste0( 118 | 'processing site ', sites_codes[i], ' (', i, ' of ', length(sites_codes), ')' 119 | ), width = 80) 120 | 121 | sfn_data <- read_sfn_data(sites_codes[i], folder) 122 | 123 | sfn_metadata[['site_md']] <- dplyr::bind_rows( 124 | sfn_metadata[['site_md']], get_site_md(sfn_data) 125 | ) 126 | sfn_metadata[['stand_md']] <- dplyr::bind_rows( 127 | sfn_metadata[['stand_md']], get_stand_md(sfn_data) 128 | ) 129 | sfn_metadata[['species_md']] <- dplyr::bind_rows( 130 | sfn_metadata[['species_md']], get_species_md(sfn_data) 131 | ) 132 | sfn_metadata[['plant_md']] <- dplyr::bind_rows( 133 | sfn_metadata[['plant_md']], get_plant_md(sfn_data) %>% 134 | # TODO remove this when the sites are corrected 135 | dplyr::mutate(pl_name = as.character(.data$pl_name)) 136 | ) 137 | sfn_metadata[['env_md']] <- dplyr::bind_rows( 138 | sfn_metadata[['env_md']], get_env_md(sfn_data) 139 | ) 140 | } 141 | 142 | # cache thing 143 | if (!.dry) { 144 | save(sfn_metadata, file = file.path(folder, '.metadata_cache.RData')) 145 | } 146 | 147 | return(sfn_metadata) 148 | 149 | } 150 | 151 | #' Read and combine all metadata 152 | #' 153 | #' Read metadata from all sites in folder and write it to disk to cache the 154 | #' info for easy and fast access 155 | #' 156 | #' Load all data in memory to collect metadata info can be resource limiting. 157 | #' For easy and quick access to metadata, this function stores an .RData file 158 | #' in the specified folder along the data with all the metadata preloaded. Also 159 | #' it return it as an object to use in filtering and selecting sites. 160 | #' 161 | #' @param folder Route to the folder containing the data. Default to working 162 | #' directory 163 | #' 164 | #' @param .write_cache Logical indicating if a cached copy of the metadata must 165 | #' be written in \code{folder}. 166 | #' 167 | #' @examples 168 | #' # Let's access the data in "folder". This typically is the folder where the 169 | #' # sapflow data at the desired unit level is (i.e. "RData/plant"), but in this 170 | #' # example we will create a temporal folder with some data to test the function 171 | #' folder <- tempdir() 172 | #' save(ARG_TRE, file = file.path(folder, 'ARG_TRE.RData')) 173 | #' save(ARG_MAZ, file = file.path(folder, 'ARG_MAZ.RData')) 174 | #' 175 | #' # create and load the metadata. The first time we use .write_cache = TRUE, 176 | #' # to ensure creating a file containing the metadata for speed the process 177 | #' # for the next times 178 | #' read_sfn_metadata( 179 | #' folder = folder, .write_cache = TRUE 180 | #' ) 181 | #' # a cached copy must have been written to "folder" 182 | #' file.exists(paste0(folder, '.metadata_cache.RData')) # TRUE 183 | #' 184 | #' # after that, we only need to especify the folder 185 | #' sites_metadata <- read_sfn_metadata(folder = folder) # quicker than before 186 | #' sites_metadata 187 | #' 188 | #' @return A list of tibbles with the five metadata classes (site, stand, 189 | #' species, plant and environmental) 190 | #' 191 | #' @export 192 | 193 | read_sfn_metadata <- function(folder = '.', .write_cache = FALSE) { 194 | 195 | if (.write_cache) { 196 | sfn_metadata <- .write_metadata_cache(folder = folder, .dry = FALSE) 197 | } else { 198 | file_name <- file.path(folder, '.metadata_cache.RData') 199 | 200 | if (!file.exists(file_name)) { 201 | stop('metadata cache file not found at ', folder, 202 | ' If you want to create one, please set .write_cache to TRUE') 203 | } else { 204 | load(file_name) 205 | } 206 | } 207 | 208 | return(sfn_metadata) 209 | 210 | } 211 | 212 | #' Filter the sites by metadata variable values 213 | #' 214 | #' \code{filter_sites_by_md} function takes logical expressions for the metadata 215 | #' variables (i.e. \code{pl_sens_meth == 'HR'}), and list the sites that met 216 | #' the criteria from those supplied 217 | #' 218 | #' \code{.join} argument indicates how sites must be filtered between metadata 219 | #' classes. \code{'and'} indicates only sites meeting all conditions for all 220 | #' metadata classes are returned. \code{'or'} indicates all sites meeting any 221 | #' condition between classes are returned. For two or more filters of the same 222 | #' metadata class, they are combined as 'and'. 223 | #' 224 | #' @param sites character vector with the sites codes to filter, generally the 225 | #' result of \code{\link{sfn_sites_in_folder}} 226 | #' 227 | #' @param metadata metadata tbl object, usually the result of 228 | #' \code{\link{read_sfn_metadata}} 229 | #' 230 | #' @param ... Logical expressions for the metadata variables, as in 231 | #' \code{\link[dplyr]{filter}}. 232 | #' 233 | #' @param .join Character indicating how to filter the sites, see details. 234 | #' 235 | #' @examples 236 | #' # Let's access the data in "folder". This typically is the folder where the 237 | #' # sapflow data at the desired unit level is (i.e. "RData/plant"), but in this 238 | #' # example we will create a temporal folder with some data to test the function 239 | #' folder <- tempdir() 240 | #' save(ARG_TRE, file = file.path(folder, 'ARG_TRE.RData')) 241 | #' save(ARG_MAZ, file = file.path(folder, 'ARG_MAZ.RData')) 242 | #' save(AUS_CAN_ST2_MIX, file = file.path(folder, 'AUS_CAN_ST2_MIX.RData')) 243 | #' 244 | #' # we need the metadata and the site names 245 | #' metadata <- read_sfn_metadata(folder = folder, .write_cache = TRUE) 246 | #' sites <- sfn_sites_in_folder(folder) 247 | #' 248 | #' # Filter by Heat Ratio method 249 | #' filter_sites_by_md( 250 | #' pl_sens_meth == 'HR', sites = sites, metadata = metadata 251 | #' ) 252 | #' 253 | #' # Both, Heat Ratio and Heat Dissipation 254 | #' filter_sites_by_md( 255 | #' pl_sens_meth %in% c('HR', 'HD'), 256 | #' sites = sites, metadata = metadata 257 | #' ) 258 | #' 259 | #' # more complex, Heat Ratio method AND Woodland/Shrubland biome 260 | #' filter_sites_by_md( 261 | #' pl_sens_meth == 'HR', 262 | #' si_biome == 'Woodland/Shrubland', 263 | #' sites = sites, metadata = metadata, 264 | #' .join = 'and' # default 265 | #' ) 266 | #' 267 | #' # join = 'or' returns sites that meet any condition 268 | #' filter_sites_by_md( 269 | #' pl_sens_meth == 'HR', 270 | #' si_biome == 'Woodland/Shrubland', 271 | #' sites = sites, metadata = metadata, 272 | #' .join = 'or' 273 | #' ) 274 | #' 275 | #' @return A character vector with the sites fulfilling the premises 276 | #' 277 | #' @export 278 | 279 | filter_sites_by_md <- function( 280 | sites, metadata, 281 | ..., 282 | .join = c('and', 'or') 283 | ) { 284 | 285 | # if we accept ... (expressions with logical result) we need to enquo them 286 | dots <- dplyr::quos(...) 287 | # metadata dic to distribute the dots arguments to their respective md 288 | metadata_dic <- c(site_md = 'si_', stand_md = 'st_', 289 | species_md = 'sp_', plant_md = 'pl_', env_md = 'env_') 290 | # empty res 291 | res_list <- vector(mode = 'list') 292 | 293 | # loop along all metadata classes to check if there is filters and apply them 294 | for (md in 1:5) { 295 | 296 | # dot dispatcher, distribute the dots in the corresponding metadata 297 | sel_dots <- dots %>% 298 | purrr::map(rlang::quo_get_expr) %>% 299 | purrr::map(as.character) %>% 300 | purrr::map(stringr::str_detect, pattern = metadata_dic[[md]]) %>% 301 | purrr::map_lgl(any) 302 | md_dots <- dots[sel_dots] 303 | 304 | # if there is filters, filter the corresponding metadata, pull the codes 305 | # and get the unique (in case of plant and species md, that can be repeated) 306 | if (length(md_dots) > 0) { 307 | md_sites_selected <- metadata[[names(metadata_dic)[md]]] %>% 308 | dplyr::filter( 309 | !!! md_dots 310 | ) %>% 311 | # pull the si_code variable 312 | dplyr::pull(.data$si_code) %>% 313 | unique() 314 | 315 | res_list[[md]] <- md_sites_selected 316 | names(res_list)[md] <- names(metadata_dic)[md] 317 | 318 | } else { 319 | # if there is no filter, return NULL to the list, we will remove it after 320 | res_list[[md]] <- NULL 321 | } 322 | } 323 | 324 | # remove the NULL elements, this way we can check for values in all elements 325 | # We do it with purrr::keep (compact removes also empty vectors, which is not 326 | # desirable in this situation) 327 | names_sites <- res_list %>% 328 | purrr::keep(~ !is.null(.x)) 329 | 330 | # get the join argument 331 | .join <- match.arg(.join) 332 | if (.join == 'or') { 333 | 334 | # 'or' indicates any site that meet any condition 335 | res_names <- purrr::flatten_chr(names_sites) %>% 336 | unique() 337 | # we return only those which fulfill the criteria but also are in the sites 338 | # provided 339 | return(res_names[res_names %in% sites]) 340 | 341 | } else { 342 | 343 | # 'and' indicates only sites that meet all conditions, we will do that with 344 | # Reduce and intersect 345 | res_names <- Reduce(intersect, names_sites) 346 | # we return only those which fulfill the criteria but also are in the sites 347 | # provided 348 | return(res_names[res_names %in% sites]) 349 | 350 | } 351 | 352 | } 353 | 354 | #' list available sites in a db folder 355 | #' 356 | #' Retrieves the site codes in the specified folder 357 | #' 358 | #' If folder 359 | #' 360 | #' @param folder Character vector of length 1 indicating the route to the 361 | #' db folder 362 | #' 363 | #' @examples 364 | #' # Let's access the data in "folder". This typically is the folder where the 365 | #' # sapflow data at the desired unit level is (i.e. "RData/plant"), but in this 366 | #' # example we will create a temporal folder with some data to test the function 367 | #' folder <- tempdir() 368 | #' save(ARG_TRE, file = file.path(folder, 'ARG_TRE.RData')) 369 | #' save(ARG_MAZ, file = file.path(folder, 'ARG_MAZ.RData')) 370 | #' save(AUS_CAN_ST2_MIX, file = file.path(folder, 'AUS_EUC_ST2_MIX.RData')) 371 | #' 372 | #' # lets see the sites 373 | #' sites <- sfn_sites_in_folder(folder) 374 | #' 375 | #' @return A character vector with the site codes present in the folder, an 376 | #' error if the folder is not valid or does not contain any site data file. 377 | #' 378 | #' @export 379 | sfn_sites_in_folder <- function(folder = '.') { 380 | 381 | # checks 382 | stopifnot( 383 | is.character(folder), # folder must be character 384 | dir.exists(folder) # folder must be a valid directory 385 | ) 386 | 387 | # get the files, if any 388 | res <- list.files(folder, pattern = '.RData') %>% 389 | stringr::str_remove('.RData') 390 | 391 | if (length(res) < 1) { 392 | # if no files were found, report it and stop 393 | stop(folder, ' does not contain any site data file') 394 | } 395 | 396 | # return res 397 | return(res) 398 | } 399 | -------------------------------------------------------------------------------- /R/imports.R: -------------------------------------------------------------------------------- 1 | #' Reexporting the pipe operator 2 | #' 3 | #' Imported from magrittr package 4 | #' 5 | #' @examples 6 | #' # piping sites 7 | #' ARG_TRE %>% daily_metrics() 8 | #' 9 | #' @importFrom magrittr %>% 10 | #' @name %>% 11 | #' @rdname pipe 12 | #' @export 13 | NULL -------------------------------------------------------------------------------- /R/sfn_data_classes.R: -------------------------------------------------------------------------------- 1 | #### sfn_data classes definitions #### 2 | 3 | ##### sfn_data ################################################################# 4 | # set old class for S$ to recognize tbl as data.frames 5 | setOldClass(c("tbl_df", "tbl", "data.frame")) 6 | 7 | 8 | #' S4 class for sapfluxnet site data 9 | #' 10 | #' Main class for storing sapfluxnet project site data and metadata 11 | #' 12 | #' This class allows to store all the data and metadata for a sapfluxnet site 13 | #' in one single object, to easily work with it. See 14 | #' \code{vignette('sfn-data-classes', package = 'sapfluxnetr')} for more info. 15 | #' 16 | #' @slot sapf_data A data frame with the sapf data 17 | #' 18 | #' @slot env_data A data frame with the env data 19 | #' 20 | #' @slot sapf_flags A data frame with the same dimensions of \code{sapf_data} 21 | #' with the flag info for each tree/TIMESTAMP combination 22 | #' 23 | #' @slot env_flags A data frame with the same dimensions of \code{env_data} with 24 | #' the flag info for each env_var/TIMESTAMP combination 25 | #' 26 | #' @slot si_code A character vector of length one indicating 27 | #' the site code 28 | #' 29 | #' @slot timestamp A POSIXct vector of length \code{nrow(sapf_data)} with the 30 | #' timestamp 31 | #' 32 | #' @slot solar_timestamp A POSIXct vector of length \code{nrow(sapf_data)} with 33 | #' the solar timestamp 34 | #' 35 | #' @slot site_md A data frame containing the site metadata 36 | #' 37 | #' @slot stand_md A data frame containing the stand metadata 38 | #' 39 | #' @slot species_md A data frame containing the species metadata 40 | #' 41 | #' @slot plant_md A data frame containing the plant metadata 42 | #' 43 | #' @slot env_md A data frame containing the env metadata 44 | #' 45 | #' @import methods 46 | #' @export sfn_data 47 | #' @exportClass sfn_data 48 | 49 | sfn_data <- setClass( 50 | 'sfn_data', 51 | slots = list( 52 | sapf_data = "data.frame", 53 | env_data = "data.frame", 54 | sapf_flags = "data.frame", 55 | env_flags = "data.frame", 56 | si_code = "character", 57 | timestamp = "POSIXt", 58 | solar_timestamp = "POSIXt", 59 | site_md = "data.frame", 60 | stand_md = "data.frame", 61 | species_md = "data.frame", 62 | plant_md = "data.frame", 63 | env_md = "data.frame" 64 | ) 65 | ) 66 | 67 | ##### sfn_data_multi ########################################################### 68 | #' S4 class for sapfluxnet multi-site data 69 | #' 70 | #' Multi sfn data class, derived from list 71 | #' 72 | #' This class inherits from \code{list}, but modified to contain sfn_data objects 73 | #' as elements. This will allow to work with several sites at the same time 74 | #' obtaining results for all of them combined or individually as elements of 75 | #' the resulting list (with \code{lapply} or \code{purrr::map}) 76 | #' 77 | #' @export sfn_data_multi 78 | #' @exportClass sfn_data_multi 79 | 80 | sfn_data_multi <- setClass( 81 | 'sfn_data_multi', 82 | contains = 'list' 83 | ) 84 | -------------------------------------------------------------------------------- /R/sfn_data_generics.R: -------------------------------------------------------------------------------- 1 | #' sfn_data custom get generics 2 | #' 3 | #' Generics for getting the info in the slots of SfnData 4 | #' 5 | #' see \code{\link{sfn_get_methods}} for detailed info about using the get 6 | #' methods in \code{sfn_data} class objects and 7 | #' \code{\link{sfn_multi_get_methods}} for detailed info about using the get 8 | #' methods in \code{sfn_data_multi} class objects. 9 | #' 10 | #' @param object Object to get data from 11 | #' 12 | #' @param ... Further arguments to pass to the corresponding get method 13 | #' 14 | #' @name sfn_get_generics 15 | #' @include sfn_data_classes.R 16 | NULL 17 | 18 | #' @rdname sfn_get_generics 19 | #' @export 20 | setGeneric( 21 | "get_sapf_data", 22 | function(object, ...) { 23 | standardGeneric("get_sapf_data") 24 | } 25 | ) 26 | 27 | #' @rdname sfn_get_generics 28 | #' @export 29 | setGeneric( 30 | "get_env_data", 31 | function(object, ...) { 32 | standardGeneric("get_env_data") 33 | } 34 | ) 35 | 36 | #' @rdname sfn_get_generics 37 | #' @export 38 | setGeneric( 39 | "get_sapf_flags", 40 | function(object, ...) { 41 | standardGeneric("get_sapf_flags") 42 | } 43 | ) 44 | 45 | #' @rdname sfn_get_generics 46 | #' @export 47 | setGeneric( 48 | "get_env_flags", 49 | function(object, ...) { 50 | standardGeneric("get_env_flags") 51 | } 52 | ) 53 | 54 | #' @rdname sfn_get_generics 55 | #' @export 56 | setGeneric( 57 | "get_timestamp", 58 | function(object, ...) { 59 | standardGeneric("get_timestamp") 60 | } 61 | ) 62 | 63 | #' @rdname sfn_get_generics 64 | #' @export 65 | setGeneric( 66 | "get_solar_timestamp", 67 | function(object, ...) { 68 | standardGeneric("get_solar_timestamp") 69 | } 70 | ) 71 | 72 | #' @rdname sfn_get_generics 73 | #' @export 74 | setGeneric( 75 | "get_si_code", 76 | function(object, ...) { 77 | standardGeneric("get_si_code") 78 | } 79 | ) 80 | 81 | #' @rdname sfn_get_generics 82 | #' @export 83 | setGeneric( 84 | "get_site_md", 85 | function(object, ...) { 86 | standardGeneric("get_site_md") 87 | } 88 | ) 89 | 90 | #' @rdname sfn_get_generics 91 | #' @export 92 | setGeneric( 93 | "get_stand_md", 94 | function(object, ...) { 95 | standardGeneric("get_stand_md") 96 | } 97 | ) 98 | 99 | #' @rdname sfn_get_generics 100 | #' @export 101 | setGeneric( 102 | "get_species_md", 103 | function(object, ...) { 104 | standardGeneric("get_species_md") 105 | } 106 | ) 107 | 108 | #' @rdname sfn_get_generics 109 | #' @export 110 | setGeneric( 111 | "get_plant_md", 112 | function(object, ...) { 113 | standardGeneric("get_plant_md") 114 | } 115 | ) 116 | 117 | #' @rdname sfn_get_generics 118 | #' @export 119 | setGeneric( 120 | "get_env_md", 121 | function(object, ...) { 122 | standardGeneric("get_env_md") 123 | } 124 | ) 125 | 126 | #' sfn_data replacement generics 127 | #' 128 | #' Generic functions for replacement functions for sfn_data 129 | #' 130 | #' see \code{\link{sfn_replacement_methods}} for more info about using the 131 | #' replacement methods in sfn_data objects 132 | #' 133 | #' @param object Object to replace 134 | #' 135 | #' @param value Object to replace with 136 | #' 137 | #' @name sfn_replacement_generics 138 | NULL 139 | 140 | #' @rdname sfn_replacement_generics 141 | #' @export 142 | setGeneric( 143 | "get_sapf_data<-", 144 | function(object, value) { 145 | standardGeneric("get_sapf_data<-") 146 | } 147 | ) 148 | 149 | #' @rdname sfn_replacement_generics 150 | #' @export 151 | setGeneric( 152 | "get_env_data<-", 153 | function(object, value) { 154 | standardGeneric("get_env_data<-") 155 | } 156 | ) 157 | 158 | #' @rdname sfn_replacement_generics 159 | #' @export 160 | setGeneric( 161 | "get_sapf_flags<-", 162 | function(object, value) { 163 | standardGeneric("get_sapf_flags<-") 164 | } 165 | ) 166 | 167 | #' @rdname sfn_replacement_generics 168 | #' @export 169 | setGeneric( 170 | "get_env_flags<-", 171 | function(object, value) { 172 | standardGeneric("get_env_flags<-") 173 | } 174 | ) 175 | 176 | #' @rdname sfn_replacement_generics 177 | #' @export 178 | setGeneric( 179 | "get_timestamp<-", 180 | function(object, value) { 181 | standardGeneric("get_timestamp<-") 182 | } 183 | ) 184 | 185 | #' @rdname sfn_replacement_generics 186 | #' @export 187 | setGeneric( 188 | "get_solar_timestamp<-", 189 | function(object, value) { 190 | standardGeneric("get_solar_timestamp<-") 191 | } 192 | ) 193 | 194 | #' @rdname sfn_replacement_generics 195 | #' @export 196 | setGeneric( 197 | "get_si_code<-", 198 | function(object, value) { 199 | standardGeneric("get_si_code<-") 200 | } 201 | ) 202 | 203 | #' @rdname sfn_replacement_generics 204 | #' @export 205 | setGeneric( 206 | "get_site_md<-", 207 | function(object, value) { 208 | standardGeneric("get_site_md<-") 209 | } 210 | ) 211 | 212 | #' @rdname sfn_replacement_generics 213 | #' @export 214 | setGeneric( 215 | "get_stand_md<-", 216 | function(object, value) { 217 | standardGeneric("get_stand_md<-") 218 | } 219 | ) 220 | 221 | #' @rdname sfn_replacement_generics 222 | #' @export 223 | setGeneric( 224 | "get_species_md<-", 225 | function(object, value) { 226 | standardGeneric("get_species_md<-") 227 | } 228 | ) 229 | 230 | #' @rdname sfn_replacement_generics 231 | #' @export 232 | setGeneric( 233 | "get_plant_md<-", 234 | function(object, value) { 235 | standardGeneric("get_plant_md<-") 236 | } 237 | ) 238 | 239 | #' @rdname sfn_replacement_generics 240 | #' @export 241 | setGeneric( 242 | "get_env_md<-", 243 | function(object, value) { 244 | standardGeneric("get_env_md<-") 245 | } 246 | ) 247 | -------------------------------------------------------------------------------- /R/visualizations.R: -------------------------------------------------------------------------------- 1 | #### Visualization functions #### 2 | 3 | #' plot method for sfn_data class 4 | #' 5 | #' Plot the desired data from a site object 6 | #' 7 | #' @section ggplot plotting system: 8 | #' \code{\link{plot}} is a base R function which uses the base R plotting system 9 | #' to show the plot. We prefer the ggplot plotting system, which allow for 10 | #' storing the plots in objects and can be subjected to further modifications. 11 | #' This allow the package users to generate rather simple plots that can be 12 | #' fine tuned afterwards to the user taste. Generating a \code{\link{plot}} 13 | #' method for the \code{sfn_data} class returning a ggplot object is not 14 | #' desired (it change the way plot works and can be misleading about the plot 15 | #' general usage). So, instead, we offer this function, \code{sfn_plot}. 16 | #' 17 | #' @section Type: 18 | #' \code{type} argument controls what is going to be plotted. It accepts 19 | #' the following: 20 | #' \itemize{ 21 | #' \item{"sapf": It will plot sapflow data vs. TIMESTAMP} 22 | #' \item{"env": It will plot environmental variables vs. TIMESTMAP} 23 | #' \item{"ta", "rh", "vpd", "ppfd_in", "netrad", "sw_in", "ext_rad", 24 | #' "ws", "precip", "swc_shallow" and "swc_deep": They will plot 25 | #' the corresponding variable vs. TIMESTAMP} 26 | #' } 27 | #' 28 | #' @section Formula: 29 | #' \code{formula} argument can be used to select an environmental variable to 30 | #' plot versus all the sapflow measurements. Any environmental variable is 31 | #' allowed, if it exist in the site provided. 32 | #' 33 | #' @section Geometry: 34 | #' By default \code{sfn_plot} generates plots using \code{\link{geom_point}} 35 | #' geometry, except in the case of \code{type = "ws"} and 36 | #' \code{type = "precip"} where \code{\link{geom_col}} is used. These 37 | #' geometries can be modified with the \code{...} argument. 38 | #' 39 | #' @param sfn_data sfn_data object to plot. It can be also an sfn_data_multi 40 | #' object. 41 | #' 42 | #' @param type Character indicating which data to plot. See Type section for 43 | #' detailed information about the available values. Ignored if formula is 44 | #' provided 45 | #' 46 | #' @param formula_env Right side formula indicating an environmental variable to 47 | #' plot vs. the sapflow values. If NULL (default), \code{sfn_plot} will use 48 | #' "type" to guess which plot show. 49 | #' 50 | #' @param solar Logical indicating if the solar timestamp must be used instead 51 | #' of the site timestamp 52 | #' 53 | #' @param ... Further arguments to be passed on \code{\link{geom_point}} or 54 | #' \code{\link{geom_col}} to modify geometry aesthetics. 55 | #' 56 | #' @examples 57 | #' library(ggplot2) 58 | #' 59 | #' # data 60 | #' data('ARG_TRE', package = 'sapfluxnetr') 61 | #' 62 | #' # plotting directly 63 | #' sfn_plot(ARG_TRE, type = 'sapf') 64 | #' 65 | #' # this could be noisy, you can facet by "Tree" (for sapflow) or by 66 | #' # "Variable" (for environmental data): 67 | #' sfn_plot(ARG_TRE, type = 'sapf') + 68 | #' facet_wrap(~ Tree) 69 | #' 70 | #' sfn_plot(ARG_TRE, type = 'env') + 71 | #' facet_wrap(~ Variable, scales = 'free_y') 72 | #' 73 | #' # saving and modifying: 74 | #' env_plot <- sfn_plot(ARG_TRE, type = 'env', solar = FALSE) + 75 | #' facet_wrap(~ Variable, scales = 'free_y') 76 | #' env_plot + labs(title = 'Environmental variables facet plot') 77 | #' 78 | #' # formula 79 | #' sfn_plot(ARG_TRE, formula_env = ~ vpd) 80 | #' 81 | #' @return A ggplot object that can be called to see the plot. If input is an 82 | #' sfn_data_multi object, a list with the plots 83 | #' 84 | #' @import ggplot2 85 | #' 86 | #' @export 87 | 88 | sfn_plot <- function( 89 | sfn_data, 90 | type = c( 91 | 'sapf', 'env', 92 | 'ta', 'rh', 'vpd', 'ppfd_in', 'netrad', 'sw_in', 'ext_rad', 93 | 'ws', 'precip', 'swc_shallow', 'swc_deep' 94 | ), 95 | formula_env = NULL, 96 | solar = TRUE, 97 | ... 98 | ) { 99 | 100 | # if sfn_data_multi, iterate over the elements 101 | if (inherits(sfn_data, "sfn_data_multi")) { 102 | plot_list <- purrr::map( 103 | sfn_data, 104 | sfn_plot, type = type, formula_env = formula_env, solar = solar, ... 105 | ) 106 | 107 | return(plot_list) 108 | } 109 | 110 | # if formula, lets do that plot 111 | if (rlang::is_formula(formula_env)) { 112 | data <- get_env_data(sfn_data, solar = solar) %>% 113 | dplyr::select("TIMESTAMP", !!rlang::get_expr(formula_env)) %>% 114 | dplyr::inner_join(get_sapf_data(sfn_data, solar = solar), by = 'TIMESTAMP') 115 | 116 | units_char <- paste0( 117 | unique( 118 | get_plant_md(sfn_data)[['pl_sap_units']] 119 | ), 120 | sep = ' ' 121 | ) 122 | 123 | res_plot <- data %>% 124 | # tidyr::gather( 125 | # key = 'Tree', value = 'Sapflow', 126 | # -.data$TIMESTAMP, -!!rlang::get_expr(formula_env) 127 | # ) %>% 128 | tidyr::pivot_longer( 129 | !dplyr::contains(rlang::get_expr(formula_env) %>% as.character) & 130 | !dplyr::contains('TIMESTAMP'), 131 | names_to = 'Tree', values_to = 'Sapflow' 132 | ) %>% 133 | ggplot(aes( 134 | x = .data[[rlang::get_expr(formula_env) %>% as.character]], 135 | y = .data$Sapflow, 136 | colour = .data$Tree 137 | )) + 138 | geom_point(...) + 139 | labs(y = paste0('Sapflow [', units_char, ']'), 140 | subtitle = paste0('Sap flow vs. ', rlang::get_expr(formula_env)), 141 | title = get_si_code(sfn_data)) 142 | } else { 143 | 144 | # We need to go type by type checking and plotting if type matchs 145 | type <- match.arg(type) 146 | 147 | # sapf 148 | if (type == 'sapf') { 149 | data <- get_sapf_data(sfn_data, solar = solar) 150 | units_char <- paste0( 151 | unique( 152 | get_plant_md(sfn_data)[['pl_sap_units']] 153 | ), 154 | sep = ' ' 155 | ) 156 | 157 | # actual plot 158 | res_plot <- data %>% 159 | # tidyr::gather(key = 'Tree', value = 'Sapflow', -.data$TIMESTAMP) %>% 160 | tidyr::pivot_longer( 161 | -"TIMESTAMP", names_to = 'Tree', values_to = 'Sapflow' 162 | ) %>% 163 | ggplot(aes(x = .data$TIMESTAMP, y = .data$Sapflow, colour = .data$Tree)) + 164 | geom_point(...) + 165 | labs(y = paste0('Sapflow [', units_char, ']')) + 166 | scale_x_datetime() 167 | } 168 | 169 | # env 170 | if (type == 'env') { 171 | data <- get_env_data(sfn_data, solar = solar) 172 | 173 | # actual plot 174 | res_plot <- data %>% 175 | # tidyr::gather(key = 'Variable', value = 'Value', -.data$TIMESTAMP) %>% 176 | tidyr::pivot_longer( 177 | -"TIMESTAMP", 178 | names_to = 'Variable', values_to = 'Value' 179 | ) %>% 180 | ggplot(aes(x = .data$TIMESTAMP, y = .data$Value, colour = .data$Variable)) + 181 | geom_point(...) + 182 | scale_x_datetime() 183 | } 184 | 185 | # ta 186 | if (type == 'ta') { 187 | data <- get_env_data(sfn_data, solar) 188 | 189 | # we need to check if environmental variable exists 190 | if (is.null(data[['ta']])) { 191 | stop('Site has not ta data') 192 | } 193 | 194 | # actual plot 195 | res_plot <- data %>% 196 | ggplot(aes(x = .data$TIMESTAMP, y = .data$ta)) + 197 | geom_point(...) + 198 | labs(y = 'Air Temperature [C]') + 199 | scale_x_datetime() 200 | } 201 | 202 | # rh 203 | if (type == 'rh') { 204 | data <- get_env_data(sfn_data, solar) 205 | 206 | if (is.null(data[['rh']])) { 207 | stop('Site has not rh data') 208 | } 209 | 210 | # actual plot 211 | res_plot <- data %>% 212 | ggplot(aes(x = .data$TIMESTAMP, y = .data$rh)) + 213 | geom_point(...) + 214 | labs(y = 'Relative Humidity [%]') + 215 | scale_x_datetime() 216 | } 217 | 218 | # vpd 219 | if (type == 'vpd') { 220 | data <- get_env_data(sfn_data, solar) 221 | 222 | if (is.null(data[['vpd']])) { 223 | stop('Site has not vpd data') 224 | } 225 | 226 | # actual plot 227 | res_plot <- data %>% 228 | ggplot(aes(x = .data$TIMESTAMP, y = .data$vpd)) + 229 | geom_point(...) + 230 | labs(y = 'VPD [kPa]') + 231 | scale_x_datetime() 232 | } 233 | 234 | # ppfd_in 235 | if (type == 'ppfd_in') { 236 | data <- get_env_data(sfn_data, solar) 237 | 238 | if (is.null(data[['ppfd_in']])) { 239 | stop('Site has not ppfd_in data') 240 | } 241 | 242 | # actual plot 243 | res_plot <- data %>% 244 | ggplot(aes(x = .data$TIMESTAMP, y = .data$ppfd_in)) + 245 | geom_point(...) + 246 | labs(y = 'PPFD [?]') + 247 | scale_x_datetime() 248 | } 249 | 250 | # sw_in 251 | if (type == 'sw_in') { 252 | data <- get_env_data(sfn_data, solar) 253 | 254 | if (is.null(data[['sw_in']])) { 255 | stop('Site has not sw_in data') 256 | } 257 | 258 | # actual plot 259 | res_plot <- data %>% 260 | ggplot(aes(x = .data$TIMESTAMP, y = .data$sw_in)) + 261 | geom_point(...) + 262 | labs(y = 'sw [?]') + 263 | scale_x_datetime() 264 | } 265 | 266 | # netrad 267 | if (type == 'netrad') { 268 | data <- get_env_data(sfn_data, solar) 269 | 270 | if (is.null(data[['netrad']])) { 271 | stop('Site has not netrad data') 272 | } 273 | 274 | # actual plot 275 | res_plot <- data %>% 276 | ggplot(aes(x = .data$TIMESTAMP, y = .data$netrad)) + 277 | geom_point(...) + 278 | labs(y = 'Net Radiation [?]') + 279 | scale_x_datetime() 280 | } 281 | 282 | # ext_rad 283 | if (type == 'ext_rad') { 284 | data <- get_env_data(sfn_data, solar) 285 | 286 | if (is.null(data[['ext_rad']])) { 287 | stop('Site has not ext_rad data') 288 | } 289 | 290 | # actual plot 291 | res_plot <- data %>% 292 | ggplot(aes(x = .data$TIMESTAMP, y = .data$ext_rad)) + 293 | geom_point(...) + 294 | labs(y = 'Extraterrestrial Radiation [?]') + 295 | scale_x_datetime() 296 | } 297 | 298 | # ws 299 | if (type == 'ws') { 300 | data <- get_env_data(sfn_data, solar) 301 | 302 | if (is.null(data[['ws']])) { 303 | stop('Site has not ws data') 304 | } 305 | 306 | # actual plot 307 | res_plot <- data %>% 308 | ggplot(aes(x = .data$TIMESTAMP, y = .data$ws)) + 309 | geom_col(...) + 310 | labs(y = 'Wind Speed [m/s]') + 311 | scale_x_datetime() 312 | } 313 | 314 | # precip 315 | if (type == 'precip') { 316 | data <- get_env_data(sfn_data, solar) 317 | 318 | if (is.null(data[['precip']])) { 319 | stop('Site has not precip data') 320 | } 321 | 322 | # actual plot 323 | res_plot <- data %>% 324 | ggplot(aes(x = .data$TIMESTAMP, y = .data$precip)) + 325 | geom_col(...) + 326 | labs(y = 'Precipitation [?]') + 327 | scale_x_datetime() 328 | } 329 | 330 | # swc_shallow 331 | if (type == 'swc_shallow') { 332 | data <- get_env_data(sfn_data, solar) 333 | 334 | if (is.null(data[['swc_shallow']])) { 335 | stop('Site has not swc_shallow data') 336 | } 337 | 338 | # actual plot 339 | res_plot <- data %>% 340 | ggplot(aes(x = .data$TIMESTAMP, y = .data$swc_shallow)) + 341 | geom_point(...) + 342 | labs(y = 'SWC Shallow [cm3/cm3]') + 343 | scale_x_datetime() 344 | } 345 | 346 | # swc_deep 347 | if (type == 'swc_deep') { 348 | data <- get_env_data(sfn_data, solar) 349 | 350 | if (is.null(data[['swc_deep']])) { 351 | stop('Site has not swc_deep data') 352 | } 353 | 354 | # actual plot 355 | res_plot <- data %>% 356 | ggplot(aes(x = .data$TIMESTAMP, y = .data$swc_deep)) + 357 | geom_point(...) + 358 | labs(y = 'SWC Deep [cm3/cm3]') + 359 | scale_x_datetime() 360 | } 361 | 362 | } 363 | 364 | return(res_plot) 365 | 366 | } 367 | 368 | # TODO add explanation for the formula argument in the function doc 369 | -------------------------------------------------------------------------------- /README.Rmd: -------------------------------------------------------------------------------- 1 | --- 2 | output: github_document 3 | --- 4 | 5 | ```{r setup, include = FALSE} 6 | knitr::opts_chunk$set( 7 | collapse = TRUE, 8 | comment = "#>", 9 | fig.path = "man/figures/README-", 10 | out.width = "100%" 11 | ) 12 | ``` 13 | # sapfluxnetr 14 | 15 | [![CRAN status](https://www.r-pkg.org/badges/version/sapfluxnetr)](https://CRAN.R-project.org/package=sapfluxnetr) 16 | [![CRAN RStudio mirror downloads](https://cranlogs.r-pkg.org/badges/grand-total/sapfluxnetr?color=blue)](https://r-pkg.org/pkg/sapfluxnetr) 17 | [![R build status](https://github.com/sapfluxnet/sapfluxnetr/workflows/R-CMD-check/badge.svg)](https://github.com/sapfluxnet/sapfluxnetr/actions) 18 | 19 | 20 | 21 | `sapfluxnetr` provides tools for a tidy data analysis for the first global 22 | database of sap flow measurements 23 | ([Sapfluxnet Project](http://sapfluxnet.creaf.cat)) 24 | 25 | ## Examples 26 | 27 | You can work with individual sites: 28 | 29 | ```{r example_single} 30 | # load packages 31 | library(sapfluxnetr) 32 | library(ggplot2) 33 | 34 | # ARG_MAZ example site data 35 | data('ARG_MAZ', package = 'sapfluxnetr') 36 | data('sfn_metadata_ex', package = 'sapfluxnetr') 37 | 38 | # plot site sapflow measurements versus vpd 39 | sfn_plot(ARG_MAZ, formula_env = ~ vpd) 40 | 41 | # daily sapflow and environmental metrics 42 | arg_maz_metrics <- daily_metrics( 43 | ARG_MAZ, tidy = TRUE, metadata = sfn_metadata_ex 44 | ) 45 | 46 | # plot daily aggregations 47 | ggplot(arg_maz_metrics, aes(x = vpd_q_95, y = sapflow_q_95, colour = pl_code)) + 48 | geom_point() 49 | ``` 50 | 51 | You can work with multiple sites also: 52 | 53 | ```{r example_multi} 54 | # ARG_TRE and AUS_CAN_ST2_MIX example sites 55 | data('ARG_TRE', package = 'sapfluxnetr') 56 | data('AUS_CAN_ST2_MIX', package = 'sapfluxnetr') 57 | multi_sfn <- sfn_data_multi(ARG_TRE, ARG_MAZ, AUS_CAN_ST2_MIX) 58 | 59 | # plotting the individual sites. It creates a list of plots 60 | plots_list <- sfn_plot(multi_sfn, formula_env = ~ vpd) 61 | plots_list[['AUS_CAN_ST2_MIX']] 62 | 63 | # daily sapflow standard metrics 64 | multi_metrics <- daily_metrics( 65 | multi_sfn, tidy = TRUE, metadata = sfn_metadata_ex 66 | ) 67 | 68 | # plot daily aggregations 69 | ggplot(multi_metrics, aes(x = vpd_q_95, y = sapflow_q_95, colour = si_code)) + 70 | geom_point(alpha = 0.2) 71 | ``` 72 | 73 | ## Installation 74 | 75 | You can install sapfluxnetr from CRAN: 76 | 77 | ```{r cran-installation, eval = FALSE} 78 | install.packages('sapfluxnetr') 79 | ``` 80 | 81 | Be advised, `sapfluxnetr` is in active development and can contain undiscovered 82 | bugs. If you find something not working as expected fill a bug at 83 | https://github.com/sapfluxnet/sapfluxnetr/issues 84 | 85 | ## Overview 86 | 87 | Please see `vignette('sapfluxnetr-quick-guide', package = 'sapfluxnetr')` for 88 | a detailed overview of the package capabilities. 89 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | 2 | # sapfluxnetr 3 | 4 | [![CRAN 5 | status](https://www.r-pkg.org/badges/version/sapfluxnetr)](https://CRAN.R-project.org/package=sapfluxnetr) 6 | [![CRAN RStudio mirror 7 | downloads](https://cranlogs.r-pkg.org/badges/grand-total/sapfluxnetr?color=blue)](https://r-pkg.org/pkg/sapfluxnetr) 8 | [![R build 9 | status](https://github.com/sapfluxnet/sapfluxnetr/workflows/R-CMD-check/badge.svg)](https://github.com/sapfluxnet/sapfluxnetr/actions) 10 | 11 | `sapfluxnetr` provides tools for a tidy data analysis for the first 12 | global database of sap flow measurements ([Sapfluxnet 13 | Project](http://sapfluxnet.creaf.cat)) 14 | 15 | ## Examples 16 | 17 | You can work with individual sites: 18 | 19 | ``` r 20 | # load packages 21 | library(sapfluxnetr) 22 | library(ggplot2) 23 | 24 | # ARG_MAZ example site data 25 | data('ARG_MAZ', package = 'sapfluxnetr') 26 | data('sfn_metadata_ex', package = 'sapfluxnetr') 27 | 28 | # plot site sapflow measurements versus vpd 29 | sfn_plot(ARG_MAZ, formula_env = ~ vpd) 30 | ``` 31 | 32 | 33 | 34 | ``` r 35 | # daily sapflow and environmental metrics 36 | arg_maz_metrics <- daily_metrics( 37 | ARG_MAZ, tidy = TRUE, metadata = sfn_metadata_ex 38 | ) 39 | #> [1] "Crunching data for ARG_MAZ. In large datasets this could take a while" 40 | #> [1] "General data for ARG_MAZ" 41 | 42 | # plot daily aggregations 43 | ggplot(arg_maz_metrics, aes(x = vpd_q_95, y = sapflow_q_95, colour = pl_code)) + 44 | geom_point() 45 | ``` 46 | 47 | 48 | 49 | You can work with multiple sites also: 50 | 51 | ``` r 52 | # ARG_TRE and AUS_CAN_ST2_MIX example sites 53 | data('ARG_TRE', package = 'sapfluxnetr') 54 | data('AUS_CAN_ST2_MIX', package = 'sapfluxnetr') 55 | multi_sfn <- sfn_data_multi(ARG_TRE, ARG_MAZ, AUS_CAN_ST2_MIX) 56 | 57 | # plotting the individual sites. It creates a list of plots 58 | plots_list <- sfn_plot(multi_sfn, formula_env = ~ vpd) 59 | plots_list[['AUS_CAN_ST2_MIX']] 60 | #> Warning: Removed 526066 rows containing missing values (geom_point). 61 | ``` 62 | 63 | 64 | 65 | ``` r 66 | # daily sapflow standard metrics 67 | multi_metrics <- daily_metrics( 68 | multi_sfn, tidy = TRUE, metadata = sfn_metadata_ex 69 | ) 70 | #> [1] "Crunching data for ARG_TRE. In large datasets this could take a while" 71 | #> [1] "General data for ARG_TRE" 72 | #> [1] "Crunching data for ARG_MAZ. In large datasets this could take a while" 73 | #> [1] "General data for ARG_MAZ" 74 | #> [1] "Crunching data for AUS_CAN_ST2_MIX. In large datasets this could take a while" 75 | #> [1] "General data for AUS_CAN_ST2_MIX" 76 | 77 | # plot daily aggregations 78 | ggplot(multi_metrics, aes(x = vpd_q_95, y = sapflow_q_95, colour = si_code)) + 79 | geom_point(alpha = 0.2) 80 | #> Warning: Removed 10966 rows containing missing values (geom_point). 81 | ``` 82 | 83 | 84 | 85 | ## Installation 86 | 87 | You can install sapfluxnetr from CRAN: 88 | 89 | ``` r 90 | install.packages('sapfluxnetr') 91 | ``` 92 | 93 | Be advised, `sapfluxnetr` is in active development and can contain 94 | undiscovered bugs. If you find something not working as expected fill a 95 | bug at 96 | 97 | ## Overview 98 | 99 | Please see 100 | `vignette('sapfluxnetr-quick-guide', package = 'sapfluxnetr')` for a 101 | detailed overview of the package capabilities. 102 | -------------------------------------------------------------------------------- /_pkgdown.yml: -------------------------------------------------------------------------------- 1 | development: 2 | mode: release 3 | 4 | navbar: 5 | type: inverse 6 | 7 | reference: 8 | - title: "Example datasets" 9 | desc: ~ 10 | contents: 11 | - '`ARG_MAZ`' 12 | - '`ARG_TRE`' 13 | - '`AUS_CAN_ST2_MIX`' 14 | - '`sfn_metadata_ex`' 15 | - title: "Data handling and visualization" 16 | desc: ~ 17 | contents: 18 | - '`read_sfn_data`' 19 | - '`sfn_filter`' 20 | - '`sfn_mutate`' 21 | - '`sfn_mutate_at`' 22 | - '`sfn_plot`' 23 | - title: "Metadata handling and utilities" 24 | desc: ~ 25 | contents: 26 | - '`read_sfn_metadata`' 27 | - '`describe_md_variable`' 28 | - '`filter_sites_by_md`' 29 | - '`get_timezone`' 30 | - '`sfn_sites_in_folder`' 31 | - '`sfn_vars_to_filter`' 32 | - title: "Metrics" 33 | desc: ~ 34 | contents: 35 | - '`sfn_metrics`' 36 | - '`metrics`' 37 | - '`metrics_tidyfier`' 38 | - '`summarise_by_period`' 39 | - '`data_coverage`' 40 | - '`diurnal_centroid`' 41 | - '`norm_diurnal_centroid`' 42 | - '`time_at_events`' 43 | - title: "sfn_data classes" 44 | desc: ~ 45 | contents: 46 | - '`as_sfn_data_multi`' 47 | - '`initialize,sfn_data-method`' 48 | - '`initialize,sfn_data_multi-method`' 49 | - '`sfn_data-class`' 50 | - '`sfn_data_multi-class`' 51 | - '`sfn_data_multi_validity`' 52 | - '`sfn_data_validity`' 53 | - '`sfn_get_generics`' 54 | - '`sfn_get_methods`' 55 | - '`sfn_multi_get_methods`' 56 | - '`sfn_replacement_generics`' 57 | - '`sfn_replacement_methods`' 58 | - '`show,sfn_data-method`' 59 | - '`show,sfn_data_multi-method`' 60 | - title: "Other" 61 | desc: ~ 62 | contents: 63 | - '`.accumulated_posix_aware`' 64 | - '`.collapse_timestamp`' 65 | - '`.env_vars_names`' 66 | - '`.fixed_metrics_funs`' 67 | - '`.flag`' 68 | - '`.metadata_architecture`' 69 | - '`.parse_period`' 70 | - '`.period_to_minutes`' 71 | - '`.sapflow_tidy`' 72 | - '`.timezone_dic`' 73 | - '`.write_metadata_cache`' 74 | - title: "Imported functions" 75 | desc: ~ 76 | contents: 77 | - '`%>%`' 78 | -------------------------------------------------------------------------------- /benchmarking/benchmarking_splitting_sites.R: -------------------------------------------------------------------------------- 1 | library(pryr) 2 | library(tidyverse) 3 | library(sapfluxnetr) 4 | library(profvis) 5 | library(future) 6 | 7 | options('future.globals.maxSize' = 2*1014*1024^2) 8 | 9 | init_mem <- mem_used() 10 | profvis({ 11 | # This will need at least 5GB of memory during the process 12 | folder <- '../sapfluxnet_db/0.0.3/sapwood' 13 | sfn_metadata <- read_sfn_metadata(folder) 14 | sites <- list.files(folder, '.RData') %>% 15 | str_remove('.RData') 16 | 17 | daily_results <- read_sfn_data(sites[1:100], folder) %>% 18 | daily_metrics(tidy = TRUE, metadata = sfn_metadata) 19 | }) %>% 20 | htmlwidgets::saveWidget('~/Descargas/pv_100_sites.html') 21 | browseURL('~/Descargas/pv_100_sites.html') 22 | end_mem <- mem_used() 23 | end_mem - init_mem 24 | 25 | init_mem <- mem_used() 26 | profvis({ 27 | folder <- '../sapfluxnet_db/0.0.3/sapwood' 28 | sfn_metadata <- read_sfn_metadata(folder) 29 | sites <- sites <- list.files(folder, '.RData') %>% 30 | str_remove('.RData') 31 | 32 | daily_results_1 <- read_sfn_data(sites[1:25], folder) %>% 33 | daily_metrics(tidy = TRUE, metadata = sfn_metadata) 34 | daily_results_2 <- read_sfn_data(sites[26:50], folder) %>% 35 | daily_metrics(tidy = TRUE, metadata = sfn_metadata) 36 | daily_results_3 <- read_sfn_data(sites[51:75], folder) %>% 37 | daily_metrics(tidy = TRUE, metadata = sfn_metadata) 38 | daily_results_4 <- read_sfn_data(sites[76:100], folder) %>% 39 | daily_metrics(tidy = TRUE, metadata = sfn_metadata) 40 | 41 | daily_results <- bind_rows( 42 | daily_results_1, daily_results_2, 43 | daily_results_3, daily_results_4 44 | ) 45 | 46 | rm(daily_results_1, daily_results_2, daily_results_3, daily_results_4) 47 | }) %>% 48 | htmlwidgets::saveWidget('~/Descargas/pv_100_sites_spl.html') 49 | browseURL('~/Descargas/pv_100_sites_spl.html') 50 | end_mem <- mem_used() 51 | end_mem - init_mem 52 | 53 | -------------------------------------------------------------------------------- /benchmarking/benchmarking_tests.R: -------------------------------------------------------------------------------- 1 | library(future) 2 | library(pryr) 3 | library(tidyverse) 4 | library(profvis) 5 | library(microbenchmark) 6 | library(sapfluxnetr) 7 | 8 | ##### 9 | # folder <- 'tests/testthat/big_test/plant/' 10 | # sites <- list.files(folder, pattern = '.RData')[1:10] %>% 11 | # stringr::str_remove('.RData') 12 | # metadata <- read_sfn_metadata(folder) 13 | # site_objects <- read_sfn_data(sites, folder) 14 | # metrics_res <- read_sfn_data(sites, folder) %>% 15 | # daily_metrics() 16 | # interval <- 'general' 17 | # 18 | # 19 | # 20 | # mbm <- microbenchmark( 21 | # tidyfier_default = metrics_tidyfier(metrics_res, metadata, interval), 22 | # tidyfier_alt = metrics_tidyfier_alt(metrics_res, metadata, interval), 23 | # check = function(values) {all_equal(values[[1]], values[[2]])}, 24 | # times = 10 25 | # ) 26 | # 27 | # mbm 28 | # autoplot.microbenchmark(mbm) 29 | # 30 | # pv_default <- profvis({ 31 | # metrics_tidyfier(metrics_res, sfn_metadata, interval) 32 | # }) 33 | # 34 | # 35 | # pv_sapf_alt <- profvis({ 36 | # metrics_tidyfier_alt(metrics_res, sfn_metadata, interval) 37 | # }) 38 | # 39 | # pv_daily_metrics <- profvis({ 40 | # daily_metrics(read_sfn_data(sites, folder)) 41 | # }) 42 | # 43 | # profvis({ 44 | # site_objects <- read_sfn_data(sites, folder) 45 | # pause(2) 46 | # tururu <- function(site_objects) { 47 | # inherits(site_objects, 'sfn_data_multi') 48 | # class(site_objects) == 'sfn_data_multi' 49 | # is(site_objects, 'sfn_data_multi') 50 | # class(sfn_data) %in% c('sfn_data', 'sfn_data_multi') 51 | # } 52 | # 53 | # tururu(site_objects) 54 | # }) 55 | ##### 56 | 57 | options('future.globals.maxSize' = 4*1014*1024^2) 58 | plan('sequential') 59 | profvis({ 60 | 61 | init_mem <- mem_used() 62 | init_mem 63 | 64 | folder <- '../sapfluxnet_db/0.0.3/sapwood/' 65 | sites <- list.files(folder, pattern = '.RData') %>% 66 | stringr::str_remove('.RData') 67 | metadata <- read_sfn_metadata(folder, .write_cache = FALSE) 68 | res <- read_sfn_data(sites, folder) %>% 69 | daily_metrics(tidy = TRUE, metadata = metadata) 70 | 71 | end_mem <- mem_used() 72 | end_mem 73 | print(end_mem - init_mem) 74 | 75 | }) %>% 76 | htmlwidgets::saveWidget('~/Descargas/pv_complete_seq.html') 77 | browseURL('~/Descargas/pv_complete_seq.html') 78 | 79 | options('future.globals.maxSize' = 1014*1024^2) 80 | plan('multicore') 81 | 82 | init_mem <- mem_used() 83 | init_mem 84 | 85 | tictoc::tic() 86 | folder <- '../sapfluxnet_db/0.0.3/sapwood/' 87 | sites <- list.files(folder, pattern = '.RData') %>% 88 | stringr::str_remove('.RData') 89 | metadata <- read_sfn_metadata(folder, .write_cache = FALSE) 90 | res <- read_sfn_data(sites, folder) %>% 91 | daily_metrics(tidy = TRUE, metadata = metadata) 92 | tictoc::toc() 93 | 94 | end_mem <- mem_used() 95 | end_mem 96 | print(end_mem - init_mem) 97 | ##### 98 | # .write_metadata_cache 99 | 100 | .write_metadata_cache_alt <- function( 101 | folder, .dry = FALSE 102 | ) { 103 | 104 | site_codes <- list.files(folder, recursive = TRUE, pattern = '.RData') %>% 105 | stringr::str_remove('.RData') 106 | 107 | sites_data <- site_codes %>% 108 | read_sfn_data(folder = folder) 109 | 110 | sfn_metadata <- list( 111 | site_md = get_site_md(sites_data, collapse = TRUE), 112 | stand_md = get_stand_md(sites_data, collapse = TRUE), 113 | species_md = get_species_md(sites_data, collapse = TRUE), 114 | plant_md = get_plant_md(sites_data, collapse = TRUE), 115 | env_md = get_env_md(sites_data, collapse = TRUE) 116 | ) 117 | 118 | # cache thing 119 | if (!.dry) { 120 | save(sfn_metadata, file = file.path(folder, '.metadata_cache.RData')) 121 | } 122 | 123 | return(sfn_metadata) 124 | } 125 | 126 | folder <- '../sapfluxnet_db/0.0.3/sapwood' 127 | 128 | profvis({ 129 | sapfluxnetr:::.write_metadata_cache(folder, .dry = TRUE) 130 | }) %>% 131 | htmlwidgets::saveWidget('~/Descargas/pv_write_metadata_cache_def.html') 132 | browseURL('~/Descargas/pv_write_metadata_cache_def.html') 133 | 134 | profvis({ 135 | sapfluxnetr:::.write_metadata_cache_alt(folder, .dry = TRUE) 136 | }) %>% 137 | htmlwidgets::saveWidget('~/Descargas/pv_write_metadata_cache_alt.html') 138 | browseURL('~/Descargas/pv_write_metadata_cache_alt.html') 139 | 140 | -------------------------------------------------------------------------------- /cran-comments.md: -------------------------------------------------------------------------------- 1 | ## Submission 2 | Updating package due to upcoming changes in depedencies (purrr, tidyselect, ggplot2) 3 | 4 | ## Test environments 5 | * local Arch Linux install, R 4.2.2 6 | * windows-latest (release) (on github actions) 7 | * macOS-latest (release) (on github actions) 8 | * ubuntu-latest (release) (on github actions) 9 | * ubuntu-latest (devel) (on github actions) 10 | * ubuntu-latest (oldrelease) (on github actions) 11 | * win-builder (release) 12 | * win-builder (devel) 13 | * win-builder (oldrelease) 14 | 15 | Results for all environments were: 16 | 17 | ## R CMD check local results 18 | There were no ERRORs or WARNINGs or NOTEs. 19 | 20 | ## Downstream dependencies 21 | There are currently no downstream dependencies for this package -------------------------------------------------------------------------------- /data-raw/FOO_BAR_BAZ_creation.R: -------------------------------------------------------------------------------- 1 | library(dplyr) 2 | library(sapfluxnetr) 3 | 4 | load(file = 'tests/testthat/big_test/plant/ARG_TRE.RData') 5 | 6 | # sapf 7 | ARG_TRE_sapf_data <- get_sapf_data(ARG_TRE)[,-1] 8 | 9 | # sapf_flags 10 | ARG_TRE_sapf_flags <- get_sapf_flags(ARG_TRE)[,-1] 11 | 12 | # env_data 13 | ARG_TRE_env_data <- get_env_data(ARG_TRE)[,-1] 14 | 15 | # env_flags 16 | ARG_TRE_env_flags <- get_env_flags(ARG_TRE)[,-1] 17 | 18 | # si code 19 | ARG_TRE_si_code <- 'ARG_TRE' 20 | 21 | # timestamps, nothing to see here 22 | ARG_TRE_solar_timestamp <- get_solar_timestamp(ARG_TRE) 23 | ARG_TRE_timestamp <- get_timestamp(ARG_TRE) 24 | 25 | # site md 26 | ARG_TRE_site_md <- get_site_md(ARG_TRE) %>% 27 | mutate_at(vars(contains('email')), 28 | list(~ if_else(is.character(.), NA_character_, NA_character_, NA_character_))) 29 | 30 | ARG_TRE_stand_md <- get_stand_md(ARG_TRE) 31 | ARG_TRE_species_md <- get_species_md(ARG_TRE) 32 | ARG_TRE_plant_md <- get_plant_md(ARG_TRE) 33 | ARG_TRE_env_md <- get_env_md(ARG_TRE) 34 | 35 | ARG_TRE_sapf_data_bad <- ARG_TRE_sapf_data[-1,] 36 | ARG_TRE_sapf_flags_bad <- ARG_TRE_sapf_flags[-1,] 37 | ARG_TRE_env_data_bad <- ARG_TRE_env_data[-1,] 38 | ARG_TRE_env_flags_bad <- ARG_TRE_env_flags[-1,] 39 | ARG_TRE_solar_timestamp_bad <- ARG_TRE_solar_timestamp[-1] 40 | ARG_TRE_timestamp_bad <- ARG_TRE_timestamp[-1] 41 | 42 | get_site_md(ARG_TRE) <- ARG_TRE_site_md 43 | 44 | 45 | save(ARG_TRE, file = 'tests/testthat/Data/ARG_TRE.RData') 46 | save(ARG_TRE, file = 'vignettes/resources/ARG_TRE.RData') 47 | usethis::use_data(ARG_TRE, overwrite = TRUE) 48 | rm(list = c('ARG_TRE')) 49 | save.image(file = 'tests/testthat/ARG_TRE.RData') 50 | 51 | ## REMOVE ALL 52 | rm(list = ls()) 53 | ## 54 | 55 | load(file = 'tests/testthat/big_test/plant/ARG_MAZ.RData') 56 | 57 | # sapf 58 | ARG_MAZ_sapf_data <- get_sapf_data(ARG_MAZ)[,-1] 59 | 60 | # sapf_flags 61 | ARG_MAZ_sapf_flags <- get_sapf_flags(ARG_MAZ)[,-1] 62 | 63 | # env_data 64 | ARG_MAZ_env_data <- get_env_data(ARG_MAZ)[,-1] 65 | 66 | # env_flags 67 | ARG_MAZ_env_flags <- get_env_flags(ARG_MAZ)[,-1] 68 | 69 | # si code 70 | ARG_MAZ_si_code <- 'ARG_MAZ' 71 | 72 | # timestamps, nothing to see here 73 | ARG_MAZ_solar_timestamp <- get_solar_timestamp(ARG_MAZ) 74 | ARG_MAZ_timestamp <- get_timestamp(ARG_MAZ) 75 | 76 | # site md 77 | ARG_MAZ_site_md <- get_site_md(ARG_MAZ) %>% 78 | mutate_at(vars(contains('email')), 79 | list(~ if_else(is.character(.), NA_character_, NA_character_, NA_character_))) 80 | 81 | ARG_MAZ_stand_md <- get_stand_md(ARG_MAZ) 82 | ARG_MAZ_species_md <- get_species_md(ARG_MAZ) 83 | ARG_MAZ_plant_md <- get_plant_md(ARG_MAZ) 84 | ARG_MAZ_env_md <- get_env_md(ARG_MAZ) 85 | 86 | ARG_MAZ_sapf_data_bad <- ARG_MAZ_sapf_data[-1,] 87 | ARG_MAZ_sapf_flags_bad <- ARG_MAZ_sapf_flags[-1,] 88 | ARG_MAZ_env_data_bad <- ARG_MAZ_env_data[-1,] 89 | ARG_MAZ_env_flags_bad <- ARG_MAZ_env_flags[-1,] 90 | ARG_MAZ_solar_timestamp_bad <- ARG_MAZ_solar_timestamp[-1] 91 | ARG_MAZ_timestamp_bad <- ARG_MAZ_timestamp[-1] 92 | 93 | get_site_md(ARG_MAZ) <- ARG_MAZ_site_md 94 | 95 | 96 | save(ARG_MAZ, file = 'tests/testthat/Data/ARG_MAZ.RData') 97 | save(ARG_MAZ, file = 'vignettes/resources/ARG_MAZ.RData') 98 | usethis::use_data(ARG_MAZ, overwrite = TRUE) 99 | rm(list = c('ARG_MAZ')) 100 | save.image(file = 'tests/testthat/ARG_MAZ.RData') 101 | 102 | ## REMOVE ALL 103 | rm(list = ls()) 104 | ## 105 | 106 | load(file = 'tests/testthat/big_test/plant/AUS_CAN_ST2_MIX.RData') 107 | 108 | # sapf 109 | AUS_CAN_ST2_MIX_sapf_data <- get_sapf_data(AUS_CAN_ST2_MIX)[,-1] 110 | 111 | # sapf_flags 112 | AUS_CAN_ST2_MIX_sapf_flags <- get_sapf_flags(AUS_CAN_ST2_MIX)[,-1] 113 | 114 | # env_data 115 | AUS_CAN_ST2_MIX_env_data <- get_env_data(AUS_CAN_ST2_MIX)[,-1] 116 | 117 | # env_flags 118 | AUS_CAN_ST2_MIX_env_flags <- get_env_flags(AUS_CAN_ST2_MIX)[,-1] 119 | 120 | # si code 121 | AUS_CAN_ST2_MIX_si_code <- 'AUS_CAN_ST2_MIX' 122 | 123 | # timestamps, nothing to see here 124 | AUS_CAN_ST2_MIX_solar_timestamp <- get_solar_timestamp(AUS_CAN_ST2_MIX) 125 | AUS_CAN_ST2_MIX_timestamp <- get_timestamp(AUS_CAN_ST2_MIX) 126 | 127 | # site md 128 | AUS_CAN_ST2_MIX_site_md <- get_site_md(AUS_CAN_ST2_MIX) %>% 129 | mutate_at(vars(contains('email')), 130 | list(~ if_else(is.character(.), NA_character_, NA_character_, NA_character_))) 131 | 132 | AUS_CAN_ST2_MIX_stand_md <- get_stand_md(AUS_CAN_ST2_MIX) 133 | AUS_CAN_ST2_MIX_species_md <- get_species_md(AUS_CAN_ST2_MIX) 134 | AUS_CAN_ST2_MIX_plant_md <- get_plant_md(AUS_CAN_ST2_MIX) 135 | AUS_CAN_ST2_MIX_env_md <- get_env_md(AUS_CAN_ST2_MIX) 136 | 137 | AUS_CAN_ST2_MIX_sapf_data_bad <- AUS_CAN_ST2_MIX_sapf_data[-1,] 138 | AUS_CAN_ST2_MIX_sapf_flags_bad <- AUS_CAN_ST2_MIX_sapf_flags[-1,] 139 | AUS_CAN_ST2_MIX_env_data_bad <- AUS_CAN_ST2_MIX_env_data[-1,] 140 | AUS_CAN_ST2_MIX_env_flags_bad <- AUS_CAN_ST2_MIX_env_flags[-1,] 141 | AUS_CAN_ST2_MIX_solar_timestamp_bad <- AUS_CAN_ST2_MIX_solar_timestamp[-1] 142 | AUS_CAN_ST2_MIX_timestamp_bad <- AUS_CAN_ST2_MIX_timestamp[-1] 143 | 144 | get_site_md(AUS_CAN_ST2_MIX) <- AUS_CAN_ST2_MIX_site_md 145 | 146 | 147 | save(AUS_CAN_ST2_MIX, file = 'tests/testthat/Data/AUS_CAN_ST2_MIX.RData') 148 | save(AUS_CAN_ST2_MIX, file = 'vignettes/resources/AUS_CAN_ST2_MIX.RData') 149 | usethis::use_data(AUS_CAN_ST2_MIX, overwrite = TRUE) 150 | rm(list = c('AUS_CAN_ST2_MIX')) 151 | save.image(file = 'tests/testthat/AUS_CAN_ST2_MIX.RData') 152 | 153 | ## REMOVE ALL 154 | rm(list = ls()) 155 | ## 156 | 157 | sfn_metadata_ex <- sapfluxnetr:::.write_metadata_cache('tests/testthat/Data', 158 | .dry = TRUE) 159 | 160 | usethis::use_data(sfn_metadata_ex, overwrite = TRUE) 161 | -------------------------------------------------------------------------------- /data/ARG_MAZ.rda: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sapfluxnet/sapfluxnetr/a09141f653f540728ea3474d975b63680ffc463f/data/ARG_MAZ.rda -------------------------------------------------------------------------------- /data/ARG_TRE.rda: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sapfluxnet/sapfluxnetr/a09141f653f540728ea3474d975b63680ffc463f/data/ARG_TRE.rda -------------------------------------------------------------------------------- /data/AUS_CAN_ST2_MIX.rda: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sapfluxnet/sapfluxnetr/a09141f653f540728ea3474d975b63680ffc463f/data/AUS_CAN_ST2_MIX.rda -------------------------------------------------------------------------------- /data/sfn_metadata_ex.rda: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sapfluxnet/sapfluxnetr/a09141f653f540728ea3474d975b63680ffc463f/data/sfn_metadata_ex.rda -------------------------------------------------------------------------------- /man/ARG_MAZ.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/data.R 3 | \docType{data} 4 | \name{ARG_MAZ} 5 | \alias{ARG_MAZ} 6 | \title{ARG_MAZ sapfluxnet site} 7 | \format{ 8 | An sfn_data class object with the data and metadata for ARG_MAZ site 9 | } 10 | \usage{ 11 | ARG_MAZ 12 | } 13 | \description{ 14 | Example site for package usage demonstration based on ARG_MAZ 15 | } 16 | \examples{ 17 | data('ARG_MAZ', package = 'sapfluxnetr') 18 | ARG_MAZ 19 | 20 | } 21 | \keyword{datasets} 22 | -------------------------------------------------------------------------------- /man/ARG_TRE.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/data.R 3 | \docType{data} 4 | \name{ARG_TRE} 5 | \alias{ARG_TRE} 6 | \title{ARG_TRE sapfluxnet site} 7 | \format{ 8 | An sfn_data class object with the data and metadata for ARG_TRE site 9 | } 10 | \usage{ 11 | ARG_TRE 12 | } 13 | \description{ 14 | Example site for package usage demonstration based on ARG_TRE 15 | } 16 | \examples{ 17 | data('ARG_TRE', package = 'sapfluxnetr') 18 | ARG_TRE 19 | 20 | } 21 | \keyword{datasets} 22 | -------------------------------------------------------------------------------- /man/AUS_CAN_ST2_MIX.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/data.R 3 | \docType{data} 4 | \name{AUS_CAN_ST2_MIX} 5 | \alias{AUS_CAN_ST2_MIX} 6 | \title{AUS_CAN_ST2_MIX sapfluxnet site} 7 | \format{ 8 | An sfn_data class object with the data and metadata for AUS_CAN_ST2_MIX site 9 | } 10 | \usage{ 11 | AUS_CAN_ST2_MIX 12 | } 13 | \description{ 14 | Example site for package usage demonstration based on AUS_CAN_ST2_MIX 15 | } 16 | \examples{ 17 | data('AUS_CAN_ST2_MIX', package = 'sapfluxnetr') 18 | AUS_CAN_ST2_MIX 19 | 20 | } 21 | \keyword{datasets} 22 | -------------------------------------------------------------------------------- /man/as_sfn_data_multi.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/helpers.R 3 | \name{as_sfn_data_multi} 4 | \alias{as_sfn_data_multi} 5 | \title{as_sfn_data_multi helper} 6 | \usage{ 7 | as_sfn_data_multi(x) 8 | } 9 | \arguments{ 10 | \item{x}{A list of sfn_data objects} 11 | } 12 | \value{ 13 | A sfn_data_multi object 14 | } 15 | \description{ 16 | Convert any list of sfn_data objects in a sfn_data_multi object 17 | } 18 | \examples{ 19 | sites_list <- list(ARG_TRE, ARG_MAZ) 20 | sapfluxnetr:::as_sfn_data_multi(sites_list) 21 | 22 | } 23 | \keyword{internal} 24 | -------------------------------------------------------------------------------- /man/data_coverage.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/helpers.R 3 | \name{data_coverage} 4 | \alias{data_coverage} 5 | \title{data coverage} 6 | \usage{ 7 | data_coverage(x, timestep, period_minutes) 8 | } 9 | \arguments{ 10 | \item{x}{a vector, usually a variable in the sapflow or environmental data.} 11 | 12 | \item{timestep}{numeric value with the timestep in minutes} 13 | 14 | \item{period_minutes}{numeric value with the period in minutes} 15 | } 16 | \value{ 17 | a single value (numeric) with the percentage of coverage for that 18 | variable 19 | } 20 | \description{ 21 | helper for sfn_metrics 22 | } 23 | \details{ 24 | This helper function calculates the coverage percentage in a vector, and is 25 | designed to be used inside a dplyr summarise statement. It calculates the 26 | coverage as the percentage of no NAs in the expected length of the summarising 27 | period stated by the timestep. 28 | } 29 | \examples{ 30 | # data for one day, 60 minutes timestep (24 values) with a 75\% of coberture 31 | x <- rep(c(1,2,3,NA), 6) 32 | data_coverage(x, 60, 1440) # 75 33 | 34 | } 35 | -------------------------------------------------------------------------------- /man/describe_md_variable.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/helpers.R 3 | \name{describe_md_variable} 4 | \alias{describe_md_variable} 5 | \title{Detailed description of metadata variables} 6 | \usage{ 7 | describe_md_variable(variable) 8 | } 9 | \arguments{ 10 | \item{variable}{A character with the name of the variable} 11 | } 12 | \value{ 13 | Nothing, prints information to console 14 | } 15 | \description{ 16 | \code{describe_md_variable} prints in console a detailed description for the 17 | requested variable. Useful to know which values to filter or in which units 18 | the variables are. 19 | } 20 | \examples{ 21 | # info about the method used to measure sapflow (pl_sens_meth) 22 | describe_md_variable('pl_sens_meth') 23 | } 24 | -------------------------------------------------------------------------------- /man/diurnal_centroid.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/helpers.R 3 | \name{diurnal_centroid} 4 | \alias{diurnal_centroid} 5 | \title{Diurnal centroid calculation} 6 | \usage{ 7 | diurnal_centroid(variable) 8 | } 9 | \arguments{ 10 | \item{variable}{A numeric vector containing the sapflow values for a day at a 11 | regular intervals. Missing values are allowed but not recommended} 12 | } 13 | \value{ 14 | A numeric value with the diurnal centroid value (0 to 24 h) 15 | } 16 | \description{ 17 | Calculate the diurnal centroid for sapflow variables 18 | } 19 | \details{ 20 | The code for this function has been kindly provided by Jacob Nelson in python 21 | (see https://github.com/jnelson18/FluxnetTools/blob/master/FileS3.py) and has 22 | been translated to a tidy data philosophy in R to be used inside a 23 | \code{\link[dplyr]{summarise}} statement. 24 | } 25 | \section{Diurnal centroid algorithm}{ 26 | 27 | Given a continuous subdaily sapflow values at regular intervals 28 | \eqn{V = {x_1, ..., x_n}} to obtain the diurnal centroid each value is 29 | multiplied by its interval index and summed up and divided 30 | by the sum of the values for the day and finally the value is normalized to 31 | 24h: 32 | 33 | \deqn{ 34 | \sum {x_1 * 1, x_2 * 2, ... , x_n * n} / \sum {x_1, x_2, ... , x_n} * (24/n) 35 | } 36 | 37 | With even values for all the intervals (i.e. 100 for all), centroid converges 38 | to 12h at more than 1000 intervals per day. With only 48 (half hourly 39 | measurements) centroid converges to 12.25h and with 24 intervals (hourly 40 | measurements) centroid converges to 12.5h. So, using diurnal centroid value 41 | in half hourly datasets or above can have a considerable error associated. 42 | } 43 | 44 | \examples{ 45 | # dplyr 46 | library(dplyr) 47 | 48 | # check convergence to 12h: 49 | diurnal_centroid(rep(1, 1000)) # 12.012 h 50 | diurnal_centroid(rep(10000, 1000)) # 12.012 h, variable scale not affects calculation 51 | 52 | # sapflow diurnal centroid 53 | data('ARG_TRE', package = 'sapfluxnetr') 54 | 55 | sfn_metrics( 56 | ARG_TRE, 57 | period = '1 day', 58 | .funs = list(~ diurnal_centroid(.), 59 | ~ data_coverage(., timestep, period_minutes)), 60 | solar = FALSE, 61 | interval = 'general' 62 | ) 63 | 64 | } 65 | \author{ 66 | Jacob Nelson & Víctor Granda 67 | } 68 | -------------------------------------------------------------------------------- /man/dot-accumulated_posix_aware.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/helpers.R 3 | \name{.accumulated_posix_aware} 4 | \alias{.accumulated_posix_aware} 5 | \title{accumulated function} 6 | \usage{ 7 | .accumulated_posix_aware(variable, na.rm = FALSE) 8 | } 9 | \arguments{ 10 | \item{variable}{the variable as it is passed to the .fixed_metrics function} 11 | 12 | \item{na.rm}{logical to pass to na.rm argument from sum} 13 | } 14 | \value{ 15 | the sum for any other variables, but the first for POSIXct variables 16 | } 17 | \description{ 18 | sum for summarise_all aware of POSIX objects 19 | } 20 | \examples{ 21 | sapfluxnetr:::.accumulated_posix_aware(c(50,20)) 22 | sapfluxnetr:::.accumulated_posix_aware(c(Sys.time(), Sys.time() -1)) 23 | 24 | } 25 | \keyword{internal} 26 | -------------------------------------------------------------------------------- /man/dot-assert_that_period_is_valid.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/metrics.R 3 | \name{.assert_that_period_is_valid} 4 | \alias{.assert_that_period_is_valid} 5 | \title{test for character period} 6 | \usage{ 7 | .assert_that_period_is_valid(period) 8 | } 9 | \arguments{ 10 | \item{period}{"frequency period"} 11 | } 12 | \value{ 13 | TRUE if is valid, informative error if not. 14 | } 15 | \description{ 16 | test for character period 17 | } 18 | \examples{ 19 | sapfluxnetr:::.assert_that_period_is_valid('1 day') # TRUE 20 | # not run 21 | # sapfluxnetr:::.assert_that_period_is_valid('1day') # error 22 | 23 | } 24 | \keyword{internal} 25 | -------------------------------------------------------------------------------- /man/dot-collapse_timestamp.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/metrics.R 3 | \name{.collapse_timestamp} 4 | \alias{.collapse_timestamp} 5 | \title{.collapse_timestamp helper} 6 | \usage{ 7 | .collapse_timestamp(timestamp, ..., period, side = "start") 8 | } 9 | \value{ 10 | A vector of the same length as TIMESTAMP, with the collapsed timestamp 11 | with the same tz as the original one. 12 | } 13 | \description{ 14 | Util to collapse the TIMESTAMP using lubridate::*_date functions 15 | } 16 | \section{Period}{ 17 | 18 | Periods accepted are in the "number period" format, as in 19 | \code{\link[lubridate]{floor_date}} or a custom function name without quotes: 20 | \itemize{ 21 | \item{hours (exs. "1 hour", "12 hours")} 22 | \item{days (exs. "1 day", "3 days")} 23 | \item{weeks (exs. "1 week", "4 weeks")} 24 | \item{months (exs. "1 month", "6 months")} 25 | \item{years (exs. "1 year", "7 years")} 26 | \item{Also a custom function can be supplied, one that transforms the 27 | TIMESTAMP variable to the collapsed timestamp desired. See 28 | \code{\link{sfn_metrics}} for details} 29 | } 30 | } 31 | 32 | \section{Side}{ 33 | 34 | Side indicates if using \code{\link[lubridate]{floor_date}} (side = "start) or 35 | \code{\link[lubridate]{ceiling_date}} (side = 'end'). Ceiling dates is not 36 | trivial, see \code{\link[lubridate]{ceiling_date}} for information on how 37 | the date will be ceiled. 38 | } 39 | 40 | \examples{ 41 | arg_tre_timestamp <- get_timestamp(ARG_TRE) 42 | sapfluxnetr:::.collapse_timestamp( 43 | arg_tre_timestamp, period = "1 day", side = 'start' 44 | ) 45 | } 46 | \keyword{internal} 47 | -------------------------------------------------------------------------------- /man/dot-env_vars_names.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/helpers.R 3 | \name{.env_vars_names} 4 | \alias{.env_vars_names} 5 | \title{helper to return all environmental variable names} 6 | \usage{ 7 | .env_vars_names() 8 | } 9 | \value{ 10 | a character vector with env vars names 11 | } 12 | \description{ 13 | helper to return all environmental variable names 14 | } 15 | \examples{ 16 | sapfluxnetr:::.env_vars_names() 17 | 18 | } 19 | \keyword{internal} 20 | -------------------------------------------------------------------------------- /man/dot-fixed_metrics_funs.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/metrics.R 3 | \name{.fixed_metrics_funs} 4 | \alias{.fixed_metrics_funs} 5 | \title{helper function to generate the fixed metrics} 6 | \usage{ 7 | .fixed_metrics_funs(probs, centroid) 8 | } 9 | \arguments{ 10 | \item{probs}{probs vector for quantile} 11 | 12 | \item{centroid}{logical indicating if centroid calculation must be made. 13 | (i.e. in monthly metrics, the centroid calculation is not needed)} 14 | } 15 | \description{ 16 | generates a call to list to capture the fixed metrics in a quosure lambda 17 | style 18 | } 19 | \section{Metrics}{ 20 | 21 | Calculated metrics are as follow: 22 | 23 | \itemize{ 24 | \item{mean: Mean value for the selected period} 25 | \item{sd: Standard deviation for the selected period} 26 | \item{coverage: Percentage of coverage as the percentage of no NAs in the 27 | expected length of the period, stated by the site timestep} 28 | \item{q*: q95 by default. Quantile value for the selected period. Quantiles to 29 | calculate are stated in the probs argument} 30 | \item{accumulated: Accumulated value on the selected period} 31 | \item{centroid: daily centroid value in the selected period, calculated 32 | only if centroid argument is TRUE} 33 | } 34 | } 35 | 36 | \examples{ 37 | sapfluxnetr:::.fixed_metrics_funs(0.95, FALSE) 38 | sapfluxnetr:::.fixed_metrics_funs(c(0.05, 0.95), TRUE) 39 | 40 | } 41 | \keyword{internal} 42 | -------------------------------------------------------------------------------- /man/dot-flag.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/helpers.R 3 | \name{.flag} 4 | \alias{.flag} 5 | \title{helper function to flag the mutated data in sfn_mutate and sfn_mutate_at} 6 | \usage{ 7 | .flag(x) 8 | } 9 | \arguments{ 10 | \item{x}{variable to flag} 11 | } 12 | \value{ 13 | A vector of the same length than x with the variable flags modified 14 | } 15 | \description{ 16 | This function will add the "USER_MODF" flag to the data point flags 17 | } 18 | \examples{ 19 | sapfluxnetr:::.flag('') 20 | sapfluxnetr:::.flag('OUT_WARNING') 21 | 22 | } 23 | \keyword{internal} 24 | -------------------------------------------------------------------------------- /man/dot-metadata_architecture.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/helpers.R 3 | \name{.metadata_architecture} 4 | \alias{.metadata_architecture} 5 | \title{Metadata variables architecture} 6 | \usage{ 7 | .metadata_architecture() 8 | } 9 | \value{ 10 | a list with the metadata architecture 11 | } 12 | \description{ 13 | This function returns a nested list with the metadata, the variable and the 14 | values, description , units and type for it use in describe_variable, 15 | sfn_vars_to_filter and sfn_values_for 16 | } 17 | \examples{ 18 | sapfluxnetr:::.metadata_architecture() 19 | 20 | } 21 | \keyword{internal} 22 | -------------------------------------------------------------------------------- /man/dot-nightly_daily_cf.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/metrics.R 3 | \name{.nightly_daily_cf} 4 | \alias{.nightly_daily_cf} 5 | \title{Period custom function} 6 | \usage{ 7 | .nightly_daily_cf(timestamp, night_data, int_start) 8 | } 9 | \arguments{ 10 | \item{timestamp}{TIMESTAMP} 11 | 12 | \item{night_data}{as it comes inside of sfn_metrics} 13 | 14 | \item{int_start}{interval start as supplied to sfn_metrics} 15 | } 16 | \value{ 17 | a vector of the same length as TIMESTAMP with the collapsed values. 18 | } 19 | \description{ 20 | nightly period custom function, to use with nightly_metrics 21 | } 22 | \details{ 23 | This function will be supplied as "period" argument to summarise_by_period 24 | when daily nightly metrics are requested. 25 | } 26 | \keyword{internal} 27 | -------------------------------------------------------------------------------- /man/dot-parse_period.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/metrics.R 3 | \name{.parse_period} 4 | \alias{.parse_period} 5 | \title{.parse_period} 6 | \usage{ 7 | .parse_period(period) 8 | } 9 | \arguments{ 10 | \item{period}{Period in the "number period" format} 11 | } 12 | \value{ 13 | a list, with the freq value as numeric and the period value as 14 | character 15 | } 16 | \description{ 17 | Util to parse the period supplied to the function call to 18 | create the collapsed timestamp 19 | } 20 | \examples{ 21 | sapfluxnetr:::.parse_period('1 day') 22 | 23 | } 24 | \keyword{internal} 25 | -------------------------------------------------------------------------------- /man/dot-period_to_minutes.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/helpers.R 3 | \name{.period_to_minutes} 4 | \alias{.period_to_minutes} 5 | \title{transform period to minutes} 6 | \usage{ 7 | .period_to_minutes(period, timestamp, timestep, ...) 8 | } 9 | \arguments{ 10 | \item{period}{character indicating the period to summarise or a custom 11 | function name (without quotes).} 12 | 13 | \item{timestamp}{timestamp vector obtained from data} 14 | 15 | \item{timestep}{numeric with the timestep in minutes, obtained from metadata} 16 | 17 | \item{...}{extra arguments for period if it is a function} 18 | } 19 | \value{ 20 | An integer with the period value in minutes 21 | } 22 | \description{ 23 | helper for data_coverage 24 | } 25 | \details{ 26 | This function converts the period supplied into minutes to use it in the 27 | coverage calculation. 28 | } 29 | \examples{ 30 | 31 | # daily period, expected 1440 minutes 32 | sapfluxnetr:::.period_to_minutes('1 day') 33 | 34 | # Using a custom function, we need timestamp and timestep 35 | sapfluxnetr:::.period_to_minutes( 36 | lubridate::as_date, get_timestamp(ARG_TRE), 30 37 | ) 38 | } 39 | \keyword{internal} 40 | -------------------------------------------------------------------------------- /man/dot-sapflow_tidy.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/helpers.R 3 | \name{.sapflow_tidy} 4 | \alias{.sapflow_tidy} 5 | \title{.sapflow_tidy helper} 6 | \usage{ 7 | .sapflow_tidy(data) 8 | } 9 | \arguments{ 10 | \item{data}{site sapflow metrics dataframe} 11 | } 12 | \description{ 13 | This helper is in charge of putting in shape the sapflow metrics, creating 14 | the pl_code column. 15 | } 16 | \keyword{internal} 17 | -------------------------------------------------------------------------------- /man/dot-timezone_dic.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/helpers.R 3 | \name{.timezone_dic} 4 | \alias{.timezone_dic} 5 | \title{Timezones dictionary} 6 | \usage{ 7 | .timezone_dic(tz) 8 | } 9 | \arguments{ 10 | \item{tz}{Character vector with the ISO code of the timezone as provided in 11 | \code{env_time_zone} variable in \code{environmental_md}} 12 | } 13 | \value{ 14 | A character vector with the timezone code compatible with lubridate 15 | and as.POSIXct 16 | } 17 | \description{ 18 | Transforms timezone ISO code to character vector compatible with lubridate and 19 | POSIXct 20 | } 21 | \details{ 22 | GMT time zones are used, as they are day saving light time (DST) agnostic, 23 | and in that way the DST can setted if the metadata says so. GMT are sign 24 | exchanged to be compatible with ISO. 25 | } 26 | \keyword{internal} 27 | -------------------------------------------------------------------------------- /man/dot-write_metadata_cache.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/getters.R 3 | \name{.write_metadata_cache} 4 | \alias{.write_metadata_cache} 5 | \title{Write metadata cache file to disk} 6 | \usage{ 7 | .write_metadata_cache(folder, .dry = FALSE) 8 | } 9 | \arguments{ 10 | \item{folder}{Route to the folder containing the data. Default to working 11 | directory} 12 | 13 | \item{.dry}{Dry run. Metadata is loaded and read, but no cache is written} 14 | } 15 | \value{ 16 | A list of tibbles with the five metadata classes (site, stand, 17 | species, plant and environmental) 18 | } 19 | \description{ 20 | Load all sites, read the metadata and write it to disk to cache the 21 | info for easy and fast access 22 | } 23 | \details{ 24 | Load all data in memory to collect metadata info can be resource limiting. 25 | For easy and quick access to metadata, this function stores an .RData file 26 | in the specified folder along the data with all the metadata preloaded. 27 | } 28 | \examples{ 29 | # Let's access the data in "folder". This typically is the folder where the 30 | # sapflow data at the desired unit level is (i.e. "RData/plant"), but in this 31 | # example we will create a temporal folder with some data to test the function 32 | folder <- tempdir() 33 | save(ARG_TRE, file = file.path(folder, 'ARG_TRE.RData')) 34 | save(ARG_MAZ, file = file.path(folder, 'ARG_MAZ.RData')) 35 | 36 | # lets create the metadata cache file 37 | sapfluxnetr:::.write_metadata_cache(folder, .dry = FALSE)#' 38 | file.exists(file.path(folder, '.metadata_cache.RData')) # TRUE 39 | 40 | } 41 | \keyword{internal} 42 | -------------------------------------------------------------------------------- /man/figures/README-example_multi-1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sapfluxnet/sapfluxnetr/a09141f653f540728ea3474d975b63680ffc463f/man/figures/README-example_multi-1.png -------------------------------------------------------------------------------- /man/figures/README-example_multi-2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sapfluxnet/sapfluxnetr/a09141f653f540728ea3474d975b63680ffc463f/man/figures/README-example_multi-2.png -------------------------------------------------------------------------------- /man/figures/README-example_single-1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sapfluxnet/sapfluxnetr/a09141f653f540728ea3474d975b63680ffc463f/man/figures/README-example_single-1.png -------------------------------------------------------------------------------- /man/figures/README-example_single-2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sapfluxnet/sapfluxnetr/a09141f653f540728ea3474d975b63680ffc463f/man/figures/README-example_single-2.png -------------------------------------------------------------------------------- /man/filter_sites_by_md.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/getters.R 3 | \name{filter_sites_by_md} 4 | \alias{filter_sites_by_md} 5 | \title{Filter the sites by metadata variable values} 6 | \usage{ 7 | filter_sites_by_md(sites, metadata, ..., .join = c("and", "or")) 8 | } 9 | \arguments{ 10 | \item{sites}{character vector with the sites codes to filter, generally the 11 | result of \code{\link{sfn_sites_in_folder}}} 12 | 13 | \item{metadata}{metadata tbl object, usually the result of 14 | \code{\link{read_sfn_metadata}}} 15 | 16 | \item{...}{Logical expressions for the metadata variables, as in 17 | \code{\link[dplyr]{filter}}.} 18 | 19 | \item{.join}{Character indicating how to filter the sites, see details.} 20 | } 21 | \value{ 22 | A character vector with the sites fulfilling the premises 23 | } 24 | \description{ 25 | \code{filter_sites_by_md} function takes logical expressions for the metadata 26 | variables (i.e. \code{pl_sens_meth == 'HR'}), and list the sites that met 27 | the criteria from those supplied 28 | } 29 | \details{ 30 | \code{.join} argument indicates how sites must be filtered between metadata 31 | classes. \code{'and'} indicates only sites meeting all conditions for all 32 | metadata classes are returned. \code{'or'} indicates all sites meeting any 33 | condition between classes are returned. For two or more filters of the same 34 | metadata class, they are combined as 'and'. 35 | } 36 | \examples{ 37 | # Let's access the data in "folder". This typically is the folder where the 38 | # sapflow data at the desired unit level is (i.e. "RData/plant"), but in this 39 | # example we will create a temporal folder with some data to test the function 40 | folder <- tempdir() 41 | save(ARG_TRE, file = file.path(folder, 'ARG_TRE.RData')) 42 | save(ARG_MAZ, file = file.path(folder, 'ARG_MAZ.RData')) 43 | save(AUS_CAN_ST2_MIX, file = file.path(folder, 'AUS_CAN_ST2_MIX.RData')) 44 | 45 | # we need the metadata and the site names 46 | metadata <- read_sfn_metadata(folder = folder, .write_cache = TRUE) 47 | sites <- sfn_sites_in_folder(folder) 48 | 49 | # Filter by Heat Ratio method 50 | filter_sites_by_md( 51 | pl_sens_meth == 'HR', sites = sites, metadata = metadata 52 | ) 53 | 54 | # Both, Heat Ratio and Heat Dissipation 55 | filter_sites_by_md( 56 | pl_sens_meth \%in\% c('HR', 'HD'), 57 | sites = sites, metadata = metadata 58 | ) 59 | 60 | # more complex, Heat Ratio method AND Woodland/Shrubland biome 61 | filter_sites_by_md( 62 | pl_sens_meth == 'HR', 63 | si_biome == 'Woodland/Shrubland', 64 | sites = sites, metadata = metadata, 65 | .join = 'and' # default 66 | ) 67 | 68 | # join = 'or' returns sites that meet any condition 69 | filter_sites_by_md( 70 | pl_sens_meth == 'HR', 71 | si_biome == 'Woodland/Shrubland', 72 | sites = sites, metadata = metadata, 73 | .join = 'or' 74 | ) 75 | 76 | } 77 | -------------------------------------------------------------------------------- /man/get_timezone.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/helpers.R 3 | \name{get_timezone} 4 | \alias{get_timezone} 5 | \title{get the timezone of the site} 6 | \usage{ 7 | get_timezone(sfn_data) 8 | } 9 | \arguments{ 10 | \item{sfn_data}{An sfn_data or sfn_data_multi object} 11 | } 12 | \value{ 13 | a character with the site timezone 14 | } 15 | \description{ 16 | Obtain the site timezone from a sfn_data/sfn_data_multi object 17 | } 18 | \examples{ 19 | # timezone of ARG_TRE site 20 | get_timezone(ARG_TRE) 21 | 22 | } 23 | -------------------------------------------------------------------------------- /man/initialize-sfn_data-method.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/sfn_data_methods.R 3 | \name{initialize,sfn_data-method} 4 | \alias{initialize,sfn_data-method} 5 | \title{Initialize method for sfn_data} 6 | \usage{ 7 | \S4method{initialize}{sfn_data}( 8 | .Object, 9 | sapf_data, 10 | env_data, 11 | sapf_flags, 12 | env_flags, 13 | si_code, 14 | timestamp, 15 | solar_timestamp, 16 | site_md, 17 | stand_md, 18 | species_md, 19 | plant_md, 20 | env_md 21 | ) 22 | } 23 | \arguments{ 24 | \item{.Object}{sfn_data object to create} 25 | 26 | \item{sapf_data}{A tibble (or any object coercible to one) with the sapf_data 27 | (without the TIMESTAMP variable)} 28 | 29 | \item{env_data}{A tibble (or any object coercible to one) with the env_data 30 | (without the TIMESTAMP variable)} 31 | 32 | \item{sapf_flags}{A tibble (or any object coercible to one) with the same 33 | dimensions of \code{sapf_data} with the flag info for each tree/TIMESTAMP 34 | combination} 35 | 36 | \item{env_flags}{A tibble (or any object coercible to one) with the same 37 | dimensions of \code{env_data} with the flag info for each env_var/TIMESTAMP 38 | combination} 39 | 40 | \item{si_code}{A character vector of length one indicating 41 | the site code} 42 | 43 | \item{timestamp}{A POSIXct vector of length \code{nrow(sapf_data)} with the 44 | timestamp} 45 | 46 | \item{solar_timestamp}{A POSIXct vector of length \code{nrow(sapf_data)} with 47 | the solar timestamp} 48 | 49 | \item{site_md}{A tibble (or any object coercible to one) containing the site 50 | metadata} 51 | 52 | \item{stand_md}{A tibble (or any object coercible to one) containing the stand 53 | metadata} 54 | 55 | \item{species_md}{A tibble (or any object coercible to one) containing the species 56 | metadata} 57 | 58 | \item{plant_md}{A tibble (or any object coercible to one) containing the plant 59 | metadata} 60 | 61 | \item{env_md}{A tibble (or any object coercible to one) containing the env 62 | metadata} 63 | } 64 | \description{ 65 | Initialize an sfn_data object 66 | } 67 | -------------------------------------------------------------------------------- /man/initialize-sfn_data_multi-method.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/sfn_data_methods.R 3 | \name{initialize,sfn_data_multi-method} 4 | \alias{initialize,sfn_data_multi-method} 5 | \title{Initialize method for sfn_data multi} 6 | \usage{ 7 | \S4method{initialize}{sfn_data_multi}(.Object, ...) 8 | } 9 | \arguments{ 10 | \item{.Object}{sfn_data_multi object to create} 11 | 12 | \item{...}{sfn_data elements} 13 | } 14 | \description{ 15 | Initialize an sfn_data_multi object 16 | } 17 | -------------------------------------------------------------------------------- /man/metrics.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/metrics.R 3 | \name{metrics} 4 | \alias{metrics} 5 | \alias{daily_metrics} 6 | \alias{monthly_metrics} 7 | \alias{nightly_metrics} 8 | \alias{daylight_metrics} 9 | \alias{predawn_metrics} 10 | \alias{midday_metrics} 11 | \title{Complete metrics wrappers} 12 | \usage{ 13 | daily_metrics( 14 | sfn_data, 15 | solar = TRUE, 16 | probs = c(0.95), 17 | tidy = FALSE, 18 | metadata = NULL, 19 | ... 20 | ) 21 | 22 | monthly_metrics( 23 | sfn_data, 24 | solar = TRUE, 25 | probs = c(0.95), 26 | tidy = FALSE, 27 | metadata = NULL, 28 | ... 29 | ) 30 | 31 | nightly_metrics( 32 | sfn_data, 33 | period = c("1 day", "1 month"), 34 | solar = TRUE, 35 | int_start = 20, 36 | int_end = 6, 37 | probs = c(0.95), 38 | tidy = FALSE, 39 | metadata = NULL, 40 | ... 41 | ) 42 | 43 | daylight_metrics( 44 | sfn_data, 45 | period = c("1 day", "1 month"), 46 | solar = TRUE, 47 | int_start = 6, 48 | int_end = 20, 49 | probs = c(0.95), 50 | tidy = FALSE, 51 | metadata = NULL, 52 | ... 53 | ) 54 | 55 | predawn_metrics( 56 | sfn_data, 57 | period = c("1 day", "1 month"), 58 | solar = TRUE, 59 | int_start = 4, 60 | int_end = 6, 61 | probs = c(0.95), 62 | tidy = FALSE, 63 | metadata = NULL, 64 | ... 65 | ) 66 | 67 | midday_metrics( 68 | sfn_data, 69 | period = c("1 day", "1 month"), 70 | solar = TRUE, 71 | int_start = 11, 72 | int_end = 13, 73 | probs = c(0.95), 74 | tidy = FALSE, 75 | metadata = NULL, 76 | ... 77 | ) 78 | } 79 | \arguments{ 80 | \item{sfn_data}{\code{\link{sfn_data}} or \code{\link{sfn_data_multi}} object 81 | to obtain the metrics from} 82 | 83 | \item{solar}{Logical indicating if the solarTIMESTAMP must be used instead of 84 | the site local TIMESTAMP. Default to TRUE (use solarTIMESTAMP).} 85 | 86 | \item{probs}{numeric vector of probabilities for 87 | \code{\link[stats]{quantile}}} 88 | 89 | \item{tidy}{Logical indicating if the metrics must be returned in a tidy 90 | format (a long tibble, each observation in its own row)} 91 | 92 | \item{metadata}{metadata object, usually the result of 93 | \code{\link{read_sfn_metadata}}. Only used if tidy is TRUE.} 94 | 95 | \item{...}{additional arguments to be passed to \code{\link{.collapse_timestamp}} 96 | or \code{\link[lubridate]{floor_date}} or \code{\link[lubridate]{ceiling_date}}.} 97 | 98 | \item{period}{Time period to aggregate data by. See period section for an 99 | explanation about the periods ('3 hours', '1 day', '1 month', '1 year', ...)} 100 | 101 | \item{int_start}{Integer value indicating the starting hour of the special 102 | interval in 24h format. See Interval section in details.} 103 | 104 | \item{int_end}{Integer value indicating the ending hour of the special 105 | interval in 24h format. See Interval section in details.} 106 | } 107 | \value{ 108 | If \code{tidy} is TRUE, a tibble with the metrics for 109 | sapflow and environmental data, with all the metadata included. If 110 | \code{tidy} is FALSE (default), a list of tibbles with the calculated 111 | metrics. 112 | } 113 | \description{ 114 | This set of functions returns a complete set of statistics for a site (using 115 | \code{\link{sfn_data}}) or several sites (using \code{\link{sfn_data_multi}}) 116 | } 117 | \details{ 118 | \code{*_metrics} functions are wrappers for \code{\link{sfn_metrics}} with a 119 | set of fixed arguments. 120 | 121 | \code{*_metrics} functions return all or some of the following statistics: 122 | \itemize{ 123 | \item{mean: mean of variable (tree or environmental variable) for the 124 | given period. NAs are removed} 125 | \item{sd: standard deviation of the variable for the given period. NAs are 126 | removed} 127 | \item{coverage: Data coverage percentage (percentage of measures without 128 | NAs)} 129 | \item{q_XX: 0.XX quantile value for the period} 130 | \item{centroid: Diurnal centroid value (hours passed until the half of 131 | the summed daily value was reached). Only returned for sapflow 132 | measures when period is '1 day'} 133 | \item{accumulated: Accumulated values for precipitation only} 134 | } 135 | } 136 | \section{daily_metrics}{ 137 | 138 | \code{daily_metrics} summarise daily data for all hours in the day 139 | } 140 | 141 | \section{monthly_metrics}{ 142 | 143 | \code{monthly_metrics} summarise monthly data for all hours in the day. 144 | } 145 | 146 | \section{nightly_metrics}{ 147 | 148 | \code{nightly_metrics} will return the metrics for night 149 | periods, summarised daily or monthly 150 | 151 | Night for daily period starts in DOY x and ends in DOY x+1 (i.e. if 152 | \code{night_start = 20, night_end = 6} values for the night starting at 153 | 2018-03-28 20:00:00 and ending at 2018-03-29 06:00:00 are summarised). 154 | 155 | Night for monthly period summarises all night periods in the month, that 156 | includes from 00:00:00 of the first month night to 23:59:59 of the last 157 | month night. 158 | } 159 | 160 | \section{daylight_metrics}{ 161 | 162 | \code{daylight_metrics} will return the metrics for daylight 163 | periods, summarised daily or monthly. Daylight interval is selected by start 164 | and end hours. 165 | } 166 | 167 | \section{predawn_metrics}{ 168 | 169 | \code{predawn_metrics} will always return the metrics for predawn 170 | period, summarised daily or monthly. Predawn interval is selected by start and 171 | end hours. 172 | 173 | Predawn metrics did not return the centroid metric. 174 | } 175 | 176 | \section{midday_metrics}{ 177 | 178 | \code{midday_metrics} will always return the metrics for midday 179 | period, summarised daily or monthly. midday interval is selected by start and 180 | end hours. 181 | 182 | Midday metrics did not return the centroid metric. 183 | } 184 | 185 | \examples{ 186 | ## daily_metrics 187 | # data load 188 | data('ARG_TRE', package = 'sapfluxnetr') 189 | data('sfn_metadata_ex', package = 'sapfluxnetr') 190 | 191 | # non tidy raw metrics (default) 192 | ARG_TRE_raw_daily <- daily_metrics(ARG_TRE) 193 | str(ARG_TRE_raw_daily) 194 | 195 | \donttest{ 196 | # tidy daily metrics 197 | ARG_TRE_daily <- daily_metrics( 198 | ARG_TRE, tidy = TRUE, metadata = sfn_metadata_ex 199 | ) 200 | ARG_TRE_daily 201 | } 202 | 203 | ## monthly_metrics 204 | # data load 205 | data('ARG_TRE', package = 'sapfluxnetr') 206 | data('sfn_metadata_ex', package = 'sapfluxnetr') 207 | 208 | # non tidy raw metrics (default) 209 | ARG_TRE_raw_monthly <- monthly_metrics(ARG_TRE) 210 | str(ARG_TRE_raw_monthly) 211 | 212 | \donttest{ 213 | # tidy monthly metrics 214 | ARG_TRE_monthly <- monthly_metrics( 215 | ARG_TRE, tidy = TRUE, metadata = sfn_metadata_ex 216 | ) 217 | ARG_TRE_monthly 218 | } 219 | 220 | \donttest{ 221 | ## nightly_metrics 222 | # data load 223 | data('AUS_CAN_ST2_MIX', package = 'sapfluxnetr') 224 | 225 | # non tidy daily night metrics (default) 226 | AUS_CAN_ST2_MIX_night <- nightly_metrics(AUS_CAN_ST2_MIX) 227 | 228 | str(AUS_CAN_ST2_MIX_night) 229 | AUS_CAN_ST2_MIX_night[['sapf']] 230 | AUS_CAN_ST2_MIX_night[['env']] 231 | 232 | # change the night interval 233 | AUS_CAN_ST2_MIX_night_short <- nightly_metrics( 234 | AUS_CAN_ST2_MIX, int_start = 21, int_end = 4 # night starting and ending hour 235 | ) 236 | AUS_CAN_ST2_MIX_night_short[['env']] 237 | 238 | # tidy nightly metrics 239 | data('sfn_metadata_ex', package = 'sapfluxnetr') 240 | AUS_CAN_ST2_MIX_night_tidy <- nightly_metrics( 241 | AUS_CAN_ST2_MIX, 242 | tidy = TRUE, metadata = sfn_metadata_ex 243 | ) 244 | AUS_CAN_ST2_MIX_night_tidy 245 | } 246 | 247 | \donttest{ 248 | ## daylight_metrics 249 | # data load 250 | data('AUS_CAN_ST2_MIX', package = 'sapfluxnetr') 251 | 252 | # non tidy daily daylight metrics (default) 253 | AUS_CAN_ST2_MIX_daylight <- daylight_metrics(AUS_CAN_ST2_MIX) 254 | 255 | str(AUS_CAN_ST2_MIX_daylight) 256 | AUS_CAN_ST2_MIX_daylight[['sapf']] 257 | AUS_CAN_ST2_MIX_daylight[['env']] 258 | 259 | # change the daylight interval 260 | AUS_CAN_ST2_MIX_daylight_short <- daylight_metrics( 261 | AUS_CAN_ST2_MIX, int_start = 8, int_end = 18 # night starting and ending hour 262 | ) 263 | AUS_CAN_ST2_MIX_daylight_short[['env']] 264 | 265 | # tidy daylight metrics 266 | data('sfn_metadata_ex', package = 'sapfluxnetr') 267 | AUS_CAN_ST2_MIX_daylight_tidy <- daylight_metrics( 268 | AUS_CAN_ST2_MIX, 269 | tidy = TRUE, metadata = sfn_metadata_ex 270 | ) 271 | AUS_CAN_ST2_MIX_daylight_tidy 272 | } 273 | 274 | \donttest{ 275 | ## predawn_metrics 276 | # data load 277 | data('AUS_CAN_ST2_MIX', package = 'sapfluxnetr') 278 | 279 | # non tidy daily predawn metrics (default) 280 | AUS_CAN_ST2_MIX_predawn <- predawn_metrics(AUS_CAN_ST2_MIX) 281 | 282 | str(AUS_CAN_ST2_MIX_predawn) 283 | AUS_CAN_ST2_MIX_predawn[['sapf']] 284 | AUS_CAN_ST2_MIX_predawn[['env']] 285 | 286 | # change the predawn interval 287 | AUS_CAN_ST2_MIX_predawn_short <- predawn_metrics( 288 | AUS_CAN_ST2_MIX, int_start = 8, int_end = 18 # night starting and ending hour 289 | ) 290 | AUS_CAN_ST2_MIX_predawn_short[['env']] 291 | 292 | # tidy daylight metrics 293 | data('sfn_metadata_ex', package = 'sapfluxnetr') 294 | AUS_CAN_ST2_MIX_predawn_tidy <- predawn_metrics( 295 | AUS_CAN_ST2_MIX, 296 | tidy = TRUE, metadata = sfn_metadata_ex 297 | ) 298 | AUS_CAN_ST2_MIX_predawn_tidy 299 | } 300 | 301 | \donttest{ 302 | ## midday_metrics 303 | # data load 304 | data('AUS_CAN_ST2_MIX', package = 'sapfluxnetr') 305 | 306 | # non tidy daily midday metrics (default) 307 | AUS_CAN_ST2_MIX_midday <- midday_metrics(AUS_CAN_ST2_MIX) 308 | 309 | str(AUS_CAN_ST2_MIX_midday) 310 | AUS_CAN_ST2_MIX_midday[['sapf']] 311 | AUS_CAN_ST2_MIX_midday[['env']] 312 | 313 | # change the midday interval 314 | AUS_CAN_ST2_MIX_midday_short <- midday_metrics( 315 | AUS_CAN_ST2_MIX, int_start = 8, int_end = 18 # night starting and ending hour 316 | ) 317 | AUS_CAN_ST2_MIX_midday_short[['env']] 318 | 319 | # tidy daylight metrics 320 | data('sfn_metadata_ex', package = 'sapfluxnetr') 321 | AUS_CAN_ST2_MIX_midday_tidy <- midday_metrics( 322 | AUS_CAN_ST2_MIX, 323 | tidy = TRUE, metadata = sfn_metadata_ex 324 | ) 325 | AUS_CAN_ST2_MIX_midday_tidy 326 | } 327 | 328 | } 329 | \seealso{ 330 | Other metrics: 331 | \code{\link{sfn_metrics}()} 332 | } 333 | \concept{metrics} 334 | -------------------------------------------------------------------------------- /man/metrics_tidyfier.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/metrics.R 3 | \name{metrics_tidyfier} 4 | \alias{metrics_tidyfier} 5 | \title{Build a tidy data frame from the metrics results nested list} 6 | \usage{ 7 | metrics_tidyfier( 8 | metrics_res, 9 | metadata, 10 | interval = c("general", "predawn", "midday", "night", "daylight") 11 | ) 12 | } 13 | \arguments{ 14 | \item{metrics_res}{Nested list containing the metrics results as obtained 15 | from \code{\link{metrics}}} 16 | 17 | \item{metadata}{List containing the metadata nested list, as obtained from 18 | \code{\link{read_sfn_metadata}}} 19 | 20 | \item{interval}{Interval to return, it depends on the \code{metrics_res} and 21 | can be \code{"gen"} for the general metrics, \code{"md"} for midday metrics, 22 | \code{"pd"} for predawn metrics, \code{"night"} for night metrics or 23 | \code{"day"} for diurnal metrics.} 24 | } 25 | \value{ 26 | a tibble with the following columns: 27 | \itemize{ 28 | \item{TIMESTAMP: POSIXct vector with the date-time of the observation} 29 | \item{si_code: Character vector with the site codes} 30 | \item{pl_code: Character vector with the plant codes} 31 | \item{sapflow_*: Variables containing the different metrics for the 32 | sapflow measurements (i.e. sapflow_mean, sapflow_q_95)} 33 | \item{ta_*; rh_*; vpd_*; ...: Variables containing the different metrics 34 | for environmental variables (i.e. ta_mean, ta_q_95)} 35 | \item{pl_*: plant metadata variables (i.e. pl_sapw_area, pl_sens_meth)} 36 | \item{si_*: site metadata variables (i.e. si_biome, si_contact_firstname)} 37 | \item{st_*: stand metadata variables (i.e. st_aspect, st_lai)} 38 | \item{sp_*: species metadata variables (i.e. sp_basal_area_perc)} 39 | \item{env_*: environmental metadata variables (i.e. env_timezone)} 40 | } 41 | } 42 | \description{ 43 | Transform the nested list of metrics in a tidy tibble where each observation 44 | has its own row 45 | } 46 | \examples{ 47 | \donttest{ 48 | # data 49 | multi_sfn <- sfn_data_multi(ARG_TRE, ARG_MAZ, AUS_CAN_ST2_MIX) 50 | data('sfn_metadata_ex', package = 'sapfluxnetr') 51 | 52 | # metrics 53 | multi_metrics <- daily_metrics(multi_sfn) 54 | 55 | # tidyfing 56 | multi_tidy <- metrics_tidyfier( 57 | multi_metrics, sfn_metadata_ex, interval = 'general' 58 | ) 59 | multi_tidy 60 | 61 | # A really easier way of doing the same 62 | multi_tidy_easy <- daily_metrics(multi_sfn, tidy = TRUE, metadata = sfn_metadata_ex) 63 | } 64 | 65 | } 66 | -------------------------------------------------------------------------------- /man/norm_diurnal_centroid.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/helpers.R 3 | \name{norm_diurnal_centroid} 4 | \alias{norm_diurnal_centroid} 5 | \title{Normalized diurnal centroid calculation} 6 | \usage{ 7 | norm_diurnal_centroid(sapf_var, rad_var) 8 | } 9 | \arguments{ 10 | \item{sapf_var}{A numeric vector containing the sapflow values for a day at a 11 | regular intervals. Missing values are allowed but not recommended.} 12 | 13 | \item{rad_var}{A numeric vector containing the incoming radiation for a day 14 | at a regular intervals. Missing values are allowed but not recommended. 15 | Must be the same length as sapf_var.} 16 | } 17 | \value{ 18 | A numeric value with the normalized diurnal centroid value 19 | } 20 | \description{ 21 | Calculate the normalized diurnal centroid for sapflow variables 22 | } 23 | \details{ 24 | The code for this function has been kindly provided by Jacob Nelson in python 25 | (see https://github.com/jnelson18/FluxnetTools/blob/master/FileS3.py) and has 26 | been translated to a tidy data philosophy in R to be used inside a 27 | \code{\link[dplyr]{summarise}} statement. 28 | } 29 | \section{Normalized diurnal centroid algorithm}{ 30 | 31 | This function calculates the diurnal centroid of sapflow measures 32 | \emph{relative} to the diurnal centroid of incoming radiation (in any units). 33 | For that the incoming radiation diurnal centroid is substracted from the 34 | sapflow diurnal centroid: 35 | 36 | \deqn{ 37 | Sapf_cent - IncomingRad_cent 38 | } 39 | } 40 | 41 | \author{ 42 | Jacob Nelson & Víctor Granda 43 | } 44 | -------------------------------------------------------------------------------- /man/pipe.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/imports.R 3 | \name{\%>\%} 4 | \alias{\%>\%} 5 | \title{Reexporting the pipe operator} 6 | \description{ 7 | Imported from magrittr package 8 | } 9 | \examples{ 10 | # piping sites 11 | ARG_TRE \%>\% daily_metrics() 12 | 13 | } 14 | -------------------------------------------------------------------------------- /man/read_sfn_data.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/getters.R 3 | \name{read_sfn_data} 4 | \alias{read_sfn_data} 5 | \title{Read sfn_data from disk} 6 | \usage{ 7 | read_sfn_data(site_codes, folder = ".") 8 | } 9 | \arguments{ 10 | \item{site_codes}{A character vector with the site code/s} 11 | 12 | \item{folder}{Route to the folder containing the \code{.RData} file. Default 13 | to working directory.} 14 | } 15 | \value{ 16 | If \code{site_codes} is a vector of length 1, an sfn_data object with 17 | the selected site data. If \code{site_codes} is a vector of length > 1, then 18 | a sfn_data_multi object containing all selected sites. 19 | } 20 | \description{ 21 | Given a site code and a route, \code{read_sfn_data} will return the selected 22 | sfn_data object 23 | } 24 | \examples{ 25 | # Let's access the data in "folder". This typically is the folder where the 26 | # sapflow data at the desired unit level is (i.e. "RData/plant"), but in this 27 | # example we will create a temporal folder with some data to test the function 28 | folder <- tempdir() 29 | save(ARG_TRE, file = file.path(folder, 'ARG_TRE.RData')) 30 | save(ARG_MAZ, file = file.path(folder, 'ARG_MAZ.RData')) 31 | 32 | # now we read a single site 33 | ARG_TRE_test <- read_sfn_data('ARG_TRE', folder) 34 | ARG_TRE_test 35 | 36 | # or we can read multiple sites at once 37 | multi_sfn <- read_sfn_data( 38 | c('ARG_TRE', 'ARG_MAZ'), folder 39 | ) 40 | multi_sfn 41 | 42 | } 43 | -------------------------------------------------------------------------------- /man/read_sfn_metadata.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/getters.R 3 | \name{read_sfn_metadata} 4 | \alias{read_sfn_metadata} 5 | \title{Read and combine all metadata} 6 | \usage{ 7 | read_sfn_metadata(folder = ".", .write_cache = FALSE) 8 | } 9 | \arguments{ 10 | \item{folder}{Route to the folder containing the data. Default to working 11 | directory} 12 | 13 | \item{.write_cache}{Logical indicating if a cached copy of the metadata must 14 | be written in \code{folder}.} 15 | } 16 | \value{ 17 | A list of tibbles with the five metadata classes (site, stand, 18 | species, plant and environmental) 19 | } 20 | \description{ 21 | Read metadata from all sites in folder and write it to disk to cache the 22 | info for easy and fast access 23 | } 24 | \details{ 25 | Load all data in memory to collect metadata info can be resource limiting. 26 | For easy and quick access to metadata, this function stores an .RData file 27 | in the specified folder along the data with all the metadata preloaded. Also 28 | it return it as an object to use in filtering and selecting sites. 29 | } 30 | \examples{ 31 | # Let's access the data in "folder". This typically is the folder where the 32 | # sapflow data at the desired unit level is (i.e. "RData/plant"), but in this 33 | # example we will create a temporal folder with some data to test the function 34 | folder <- tempdir() 35 | save(ARG_TRE, file = file.path(folder, 'ARG_TRE.RData')) 36 | save(ARG_MAZ, file = file.path(folder, 'ARG_MAZ.RData')) 37 | 38 | # create and load the metadata. The first time we use .write_cache = TRUE, 39 | # to ensure creating a file containing the metadata for speed the process 40 | # for the next times 41 | read_sfn_metadata( 42 | folder = folder, .write_cache = TRUE 43 | ) 44 | # a cached copy must have been written to "folder" 45 | file.exists(paste0(folder, '.metadata_cache.RData')) # TRUE 46 | 47 | # after that, we only need to especify the folder 48 | sites_metadata <- read_sfn_metadata(folder = folder) # quicker than before 49 | sites_metadata 50 | 51 | } 52 | -------------------------------------------------------------------------------- /man/sfn_data-class.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/sfn_data_classes.R 3 | \docType{class} 4 | \name{sfn_data-class} 5 | \alias{sfn_data-class} 6 | \alias{sfn_data} 7 | \title{S4 class for sapfluxnet site data} 8 | \description{ 9 | Main class for storing sapfluxnet project site data and metadata 10 | } 11 | \details{ 12 | This class allows to store all the data and metadata for a sapfluxnet site 13 | in one single object, to easily work with it. See 14 | \code{vignette('sfn-data-classes', package = 'sapfluxnetr')} for more info. 15 | } 16 | \section{Slots}{ 17 | 18 | \describe{ 19 | \item{\code{sapf_data}}{A data frame with the sapf data} 20 | 21 | \item{\code{env_data}}{A data frame with the env data} 22 | 23 | \item{\code{sapf_flags}}{A data frame with the same dimensions of \code{sapf_data} 24 | with the flag info for each tree/TIMESTAMP combination} 25 | 26 | \item{\code{env_flags}}{A data frame with the same dimensions of \code{env_data} with 27 | the flag info for each env_var/TIMESTAMP combination} 28 | 29 | \item{\code{si_code}}{A character vector of length one indicating 30 | the site code} 31 | 32 | \item{\code{timestamp}}{A POSIXct vector of length \code{nrow(sapf_data)} with the 33 | timestamp} 34 | 35 | \item{\code{solar_timestamp}}{A POSIXct vector of length \code{nrow(sapf_data)} with 36 | the solar timestamp} 37 | 38 | \item{\code{site_md}}{A data frame containing the site metadata} 39 | 40 | \item{\code{stand_md}}{A data frame containing the stand metadata} 41 | 42 | \item{\code{species_md}}{A data frame containing the species metadata} 43 | 44 | \item{\code{plant_md}}{A data frame containing the plant metadata} 45 | 46 | \item{\code{env_md}}{A data frame containing the env metadata} 47 | }} 48 | 49 | -------------------------------------------------------------------------------- /man/sfn_data_multi-class.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/sfn_data_classes.R 3 | \docType{class} 4 | \name{sfn_data_multi-class} 5 | \alias{sfn_data_multi-class} 6 | \alias{sfn_data_multi} 7 | \title{S4 class for sapfluxnet multi-site data} 8 | \description{ 9 | Multi sfn data class, derived from list 10 | } 11 | \details{ 12 | This class inherits from \code{list}, but modified to contain sfn_data objects 13 | as elements. This will allow to work with several sites at the same time 14 | obtaining results for all of them combined or individually as elements of 15 | the resulting list (with \code{lapply} or \code{purrr::map}) 16 | } 17 | -------------------------------------------------------------------------------- /man/sfn_data_multi_validity.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/sfn_data_methods.R 3 | \name{sfn_data_multi_validity} 4 | \alias{sfn_data_multi_validity} 5 | \title{Validity method for sfn_data_multi class} 6 | \description{ 7 | Validation checks for generating sfn_data_multi class objects 8 | } 9 | \details{ 10 | This method is used internally to ensure the correctness of the sfn_data_multi 11 | object. Basically ensures that the object returned is a list of sfn_data 12 | class objects 13 | } 14 | -------------------------------------------------------------------------------- /man/sfn_data_validity.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/sfn_data_methods.R 3 | \name{sfn_data_validity} 4 | \alias{sfn_data_validity} 5 | \title{Validity method for sfn_data class} 6 | \description{ 7 | Validation checks for generating sfn_data class objects 8 | } 9 | \details{ 10 | This method is used internally when creating and/or modifying sfn_data class 11 | objects to ensure that the object returned is correct in terms of content 12 | classes and dimensions (i.e. sapflow data and environmental data has the 13 | same length) 14 | } 15 | -------------------------------------------------------------------------------- /man/sfn_filter.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/sfn_dplyr.R 3 | \name{sfn_filter} 4 | \alias{sfn_filter} 5 | \title{Filter sfn_data by variable/s value} 6 | \usage{ 7 | sfn_filter(sfn_data, ..., solar = FALSE) 8 | } 9 | \arguments{ 10 | \item{sfn_data}{\code{sfn_data} or \code{sfn_data_multi} object to subset} 11 | 12 | \item{...}{expressions to pass to the \code{\link[dplyr]{filter}} function} 13 | 14 | \item{solar}{Logical indicating if solar timestamp must used to subset} 15 | } 16 | \value{ 17 | For \code{sfn_data} objects, a filtered \code{sfn_data} or NULL if 18 | no data meet the criteria. For \code{sfn_data_multi} another 19 | \code{sfn_data_multi} with the sites filtered, and an empty 20 | \code{sfn_data_multi} if any sites met the criteria 21 | } 22 | \description{ 23 | Port of \code{\link[dplyr]{filter}} for \code{sfn_data} and 24 | \code{sfn_data_multi} objects 25 | } 26 | \details{ 27 | `sfn_filter` will remove the rows not matching the logical expression/s 28 | provided. So, it will remove cases and will create TIMESTAMP gaps, so its use 29 | is not recommended except in the case of filtering by TIMESTAMP (i.e. to 30 | set several sites (sfn_data_multi) in the same time frame). For other 31 | scenarios (removing extreme environmental conditions values or strange 32 | sapflow measures patterns) see \code{\link{sfn_mutate}} and 33 | \code{\link{sfn_mutate_at}} 34 | } 35 | \examples{ 36 | library(dplyr) 37 | library(lubridate) 38 | 39 | # data 40 | data('ARG_TRE', package = 'sapfluxnetr') 41 | 42 | # by timestamp 43 | foo_timestamp <- get_timestamp(ARG_TRE) 44 | 45 | foo_timestamp_trimmed <- foo_timestamp[1:100] 46 | 47 | sfn_filter( 48 | ARG_TRE, 49 | TIMESTAMP \%in\% foo_timestamp_trimmed 50 | ) 51 | 52 | # by wind speed value 53 | ws_threshold <- 25 54 | 55 | sfn_filter( 56 | ARG_TRE, 57 | ws <= ws_threshold 58 | ) 59 | 60 | ## multi 61 | data('ARG_MAZ', package = 'sapfluxnetr') 62 | multi_sfn <- sfn_data_multi(ARG_TRE, ARG_MAZ) 63 | 64 | # by timestamp 65 | sfn_filter( 66 | multi_sfn, 67 | between(day(TIMESTAMP), 18, 22) 68 | ) 69 | 70 | # by wind speed value 71 | sfn_filter( 72 | multi_sfn, 73 | ws <= ws_threshold 74 | ) 75 | 76 | } 77 | -------------------------------------------------------------------------------- /man/sfn_get_generics.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/sfn_data_generics.R 3 | \name{sfn_get_generics} 4 | \alias{sfn_get_generics} 5 | \alias{get_sapf_data} 6 | \alias{get_env_data} 7 | \alias{get_sapf_flags} 8 | \alias{get_env_flags} 9 | \alias{get_timestamp} 10 | \alias{get_solar_timestamp} 11 | \alias{get_si_code} 12 | \alias{get_site_md} 13 | \alias{get_stand_md} 14 | \alias{get_species_md} 15 | \alias{get_plant_md} 16 | \alias{get_env_md} 17 | \title{sfn_data custom get generics} 18 | \usage{ 19 | get_sapf_data(object, ...) 20 | 21 | get_env_data(object, ...) 22 | 23 | get_sapf_flags(object, ...) 24 | 25 | get_env_flags(object, ...) 26 | 27 | get_timestamp(object, ...) 28 | 29 | get_solar_timestamp(object, ...) 30 | 31 | get_si_code(object, ...) 32 | 33 | get_site_md(object, ...) 34 | 35 | get_stand_md(object, ...) 36 | 37 | get_species_md(object, ...) 38 | 39 | get_plant_md(object, ...) 40 | 41 | get_env_md(object, ...) 42 | } 43 | \arguments{ 44 | \item{object}{Object to get data from} 45 | 46 | \item{...}{Further arguments to pass to the corresponding get method} 47 | } 48 | \description{ 49 | Generics for getting the info in the slots of SfnData 50 | } 51 | \details{ 52 | see \code{\link{sfn_get_methods}} for detailed info about using the get 53 | methods in \code{sfn_data} class objects and 54 | \code{\link{sfn_multi_get_methods}} for detailed info about using the get 55 | methods in \code{sfn_data_multi} class objects. 56 | } 57 | -------------------------------------------------------------------------------- /man/sfn_get_methods.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/sfn_data_methods.R 3 | \name{sfn_get_methods} 4 | \alias{sfn_get_methods} 5 | \alias{get_sapf_data,sfn_data-method} 6 | \alias{get_env_data,sfn_data-method} 7 | \alias{get_sapf_flags,sfn_data-method} 8 | \alias{get_env_flags,sfn_data-method} 9 | \alias{get_timestamp,sfn_data-method} 10 | \alias{get_solar_timestamp,sfn_data-method} 11 | \alias{get_si_code,sfn_data-method} 12 | \alias{get_site_md,sfn_data-method} 13 | \alias{get_stand_md,sfn_data-method} 14 | \alias{get_species_md,sfn_data-method} 15 | \alias{get_plant_md,sfn_data-method} 16 | \alias{get_env_md,sfn_data-method} 17 | \title{sfn_data get methods} 18 | \usage{ 19 | \S4method{get_sapf_data}{sfn_data}(object, solar = FALSE) 20 | 21 | \S4method{get_env_data}{sfn_data}(object, solar = FALSE) 22 | 23 | \S4method{get_sapf_flags}{sfn_data}(object, solar = FALSE) 24 | 25 | \S4method{get_env_flags}{sfn_data}(object, solar = FALSE) 26 | 27 | \S4method{get_timestamp}{sfn_data}(object) 28 | 29 | \S4method{get_solar_timestamp}{sfn_data}(object) 30 | 31 | \S4method{get_si_code}{sfn_data}(object) 32 | 33 | \S4method{get_site_md}{sfn_data}(object) 34 | 35 | \S4method{get_stand_md}{sfn_data}(object) 36 | 37 | \S4method{get_species_md}{sfn_data}(object) 38 | 39 | \S4method{get_plant_md}{sfn_data}(object) 40 | 41 | \S4method{get_env_md}{sfn_data}(object) 42 | } 43 | \arguments{ 44 | \item{object}{Object of class sfn_data from which data is retrieved} 45 | 46 | \item{solar}{Logical indicating if the timestamp to return in the \code{get_sapf_data}, 47 | \code{get_env_data}, \code{get_sapf_flags} and \code{get_env_flags} methods is 48 | the solarTIMESTAMP (TRUE) or the contributors provided TIMESTAMP (FALSE)} 49 | } 50 | \description{ 51 | Methods to get the data and metadata from the sfn_data class slots 52 | } 53 | \details{ 54 | \code{get_sapf_data} and \code{get_env_data} methods retrieve sapflow or environmental 55 | tibbles to create a functional dataset to work with. 56 | 57 | \code{get_sapf_flags} and \code{get_env_flags} methods retrieve sapflow or 58 | environmental flags as tibbles. 59 | 60 | \code{get_timestamp} and \code{get_solar_timestamp} methods retrieve only the 61 | timestamp as POSIXct vector. 62 | 63 | \code{get_si_code} method retrieve a character vector with length(timestamp) 64 | containing the site code. 65 | 66 | \code{get_site_md}, \code{get_stand_md}, \code{get_species_md}, 67 | \code{get_plant_md} and \code{get_env_md} methods retrieve the corresponding 68 | metadata. 69 | } 70 | \examples{ 71 | library(dplyr) 72 | 73 | data('ARG_TRE', package = 'sapfluxnetr') 74 | sapf_data <- get_sapf_data(ARG_TRE, solar = TRUE) 75 | env_data_no_solar <- get_env_data(ARG_TRE, solar = FALSE) 76 | plant_md <- get_plant_md(ARG_TRE) 77 | 78 | # dplyr pipe to get the mean dbh for a site 79 | ARG_TRE \%>\% 80 | get_plant_md() \%>\% 81 | summarise(dbh_mean = mean(pl_dbh, na.rm = TRUE)) \%>\% 82 | pull(dbh_mean) 83 | 84 | } 85 | -------------------------------------------------------------------------------- /man/sfn_metadata_ex.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/data.R 3 | \docType{data} 4 | \name{sfn_metadata_ex} 5 | \alias{sfn_metadata_ex} 6 | \title{sfn_metadata cache file for example data (ARG_MAZ, ARG_TRE and AUS_CAN_ST2_MIX)} 7 | \format{ 8 | A list with five elements, each of one a metadata type. 9 | } 10 | \usage{ 11 | sfn_metadata_ex 12 | } 13 | \description{ 14 | Example metadata cache file content for package usage demonstration 15 | } 16 | \examples{ 17 | data('sfn_metadata_ex', package = 'sapfluxnetr') 18 | sfn_metadata_ex 19 | 20 | } 21 | \keyword{datasets} 22 | -------------------------------------------------------------------------------- /man/sfn_metrics.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/metrics.R 3 | \name{sfn_metrics} 4 | \alias{sfn_metrics} 5 | \title{Metrics summary function} 6 | \usage{ 7 | sfn_metrics( 8 | sfn_data, 9 | period, 10 | .funs, 11 | solar, 12 | interval = c("general", "predawn", "midday", "night", "daylight"), 13 | int_start = NULL, 14 | int_end = NULL, 15 | ... 16 | ) 17 | } 18 | \arguments{ 19 | \item{sfn_data}{\code{\link{sfn_data}} or \code{\link{sfn_data_multi}} object 20 | to obtain the metrics from} 21 | 22 | \item{period}{Time period to aggregate data by. See period section for an 23 | explanation about the periods ('3 hours', '1 day', '1 month', '1 year', ...)} 24 | 25 | \item{.funs}{List of function calls to summarise the data by, see .funs 26 | section for more details.} 27 | 28 | \item{solar}{Logical indicating if the solarTIMESTAMP must be used instead of 29 | the site local TIMESTAMP. Default to TRUE (use solarTIMESTAMP).} 30 | 31 | \item{interval}{Character vector indicating if the metrics must be filtered 32 | by an special hour interval. See Interval section in details.} 33 | 34 | \item{int_start}{Integer value indicating the starting hour of the special 35 | interval in 24h format. See Interval section in details.} 36 | 37 | \item{int_end}{Integer value indicating the ending hour of the special 38 | interval in 24h format. See Interval section in details.} 39 | 40 | \item{...}{optional arguments to pass to methods used 41 | (i.e. .collapse_timestamp or summarise funs extra arguments)} 42 | } 43 | \value{ 44 | For \code{\link{sfn_data}} objects, a list of tbl_df objects 45 | with the following structure: 46 | \itemize{ 47 | \item{$sapf: metrics for the sapflow data} 48 | \item{$env: metrics for the environmental data} 49 | } 50 | 51 | For \code{\link{sfn_data_multi}} objects, a list of lists of tbl_df objects 52 | with the metrics for each site: 53 | \itemize{ 54 | \item{$SITE_CODE 55 | \itemize{ 56 | \item{$sapf: metrics for the sapflow data} 57 | \item{$env: metrics for the environmental data} 58 | } 59 | } 60 | \item{$NEXT_SITE_CODE...} 61 | } 62 | } 63 | \description{ 64 | Generate metrics from a site/s data for the period indicated 65 | } 66 | \section{Period}{ 67 | 68 | \code{period} argument is used by internal function 69 | \code{\link{.collapse_timestamp}} and it can be stated in two ways: 70 | \itemize{ 71 | \item{\emph{frequency period} format: "3 hours", "1 day", "7 days", "1 month"} 72 | \item{As a \emph{custom function}. This will be the name of a function, 73 | without quotes, that accepts as the first argument the timestamp to collapse. 74 | The result of the function must be a vector of collapsed TIMESTAMPs of the 75 | same length than the original TIMESTAMP which will be used to group by and 76 | summarise the data. Additional arguments to this function, if needed, can 77 | be passed in the \code{...} argument.} 78 | } 79 | \code{\link{.collapse_timestamp}} also accepts the \code{side} argument to 80 | collapse by the starting timestamp or the ending timestamp of each group. This 81 | can be supplied in the \code{...} argument. 82 | } 83 | 84 | \section{.funs}{ 85 | 86 | \code{.funs} argument uses the same method as the \code{.funs} argument in the 87 | \code{\link[dplyr]{summarise_all}} function of \code{dplyr} package. Basically 88 | it accepts a list of function calls generated by list(). If you want to pass 89 | on a custom function you can specify it here. See details in 90 | \code{\link{summarise_by_period}} for more complex summarising functions 91 | declaration. 92 | } 93 | 94 | \section{Interval}{ 95 | 96 | Previously to the metrics summary, data can be filtered by an special 97 | interval (i.e. predawn or nightly). This filtering can be specified with the 98 | \code{interval} argument as this: 99 | \itemize{ 100 | \item{\code{"general"} (default). No special interval is used, and metrics 101 | are performed with all the data}. 102 | \item{\code{"predawn"}. Data is filtered for predawn interval. In this case 103 | \code{int_start} and \code{int_end} must be specified as 24h value} 104 | \item{\code{"midday"}. Data is filtered for midday interval. In this case 105 | \code{int_start} and \code{int_end} must be specified as 24h value} 106 | \item{\code{"night"}. Data is filtered for night interval. In this case 107 | \code{int_start} and \code{int_end} must be specified as 24h value} 108 | \item{\code{"daylight"}. Data is filtered for daylight interval. In this case 109 | \code{int_start} and \code{int_end} must be specified as 24h value} 110 | } 111 | } 112 | 113 | \examples{ 114 | library(dplyr) 115 | 116 | ### general metrics 117 | ## sfn_data 118 | data('ARG_TRE', package = 'sapfluxnetr') 119 | ARG_TRE_metrics <- sfn_metrics( 120 | ARG_TRE, 121 | period = '7 days', 122 | .funs = list(~ mean(., na.rm = TRUE), ~ sd(., na.rm = TRUE), ~ n()), 123 | solar = FALSE, 124 | interval = 'general' 125 | ) 126 | 127 | str(ARG_TRE_metrics) 128 | ARG_TRE_metrics[['sapf']] 129 | ARG_TRE_metrics[['env']] 130 | 131 | ## sfn_data_multi 132 | \donttest{ 133 | data('ARG_MAZ', package = 'sapfluxnetr') 134 | data('AUS_CAN_ST2_MIX', package = 'sapfluxnetr') 135 | multi_sfn <- sfn_data_multi(ARG_TRE, ARG_MAZ, AUS_CAN_ST2_MIX) 136 | 137 | multi_metrics <- sfn_metrics( 138 | multi_sfn, 139 | period = '7 days', 140 | .funs = list(~ mean(., na.rm = TRUE), ~ sd(., na.rm = TRUE), ~ n()), 141 | solar = FALSE, 142 | interval = 'general' 143 | ) 144 | 145 | str(multi_metrics) 146 | 147 | multi_metrics[['ARG_TRE']][['sapf']] 148 | } 149 | 150 | ### midday metrics 151 | ARG_TRE_midday <- sfn_metrics( 152 | ARG_TRE, 153 | period = '1 day', 154 | .funs = list(~ mean(., na.rm = TRUE), ~ sd(., na.rm = TRUE), ~ n()), 155 | solar = TRUE, 156 | interval = 'midday', int_start = 11, int_end = 13 157 | ) 158 | 159 | str(ARG_TRE_midday) 160 | ARG_TRE_midday[['sapf']] 161 | 162 | } 163 | \seealso{ 164 | Other metrics: 165 | \code{\link{metrics}} 166 | } 167 | \concept{metrics} 168 | -------------------------------------------------------------------------------- /man/sfn_multi_get_methods.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/sfn_data_methods.R 3 | \name{sfn_multi_get_methods} 4 | \alias{sfn_multi_get_methods} 5 | \alias{get_sapf_data,sfn_data_multi-method} 6 | \alias{get_env_data,sfn_data_multi-method} 7 | \alias{get_sapf_flags,sfn_data_multi-method} 8 | \alias{get_env_flags,sfn_data_multi-method} 9 | \alias{get_timestamp,sfn_data_multi-method} 10 | \alias{get_solar_timestamp,sfn_data_multi-method} 11 | \alias{get_si_code,sfn_data_multi-method} 12 | \alias{get_site_md,sfn_data_multi-method} 13 | \alias{get_stand_md,sfn_data_multi-method} 14 | \alias{get_species_md,sfn_data_multi-method} 15 | \alias{get_plant_md,sfn_data_multi-method} 16 | \alias{get_env_md,sfn_data_multi-method} 17 | \title{sfn_data_multi get methods} 18 | \usage{ 19 | \S4method{get_sapf_data}{sfn_data_multi}(object, solar = FALSE) 20 | 21 | \S4method{get_env_data}{sfn_data_multi}(object, solar = FALSE) 22 | 23 | \S4method{get_sapf_flags}{sfn_data_multi}(object, solar = FALSE) 24 | 25 | \S4method{get_env_flags}{sfn_data_multi}(object, solar = FALSE) 26 | 27 | \S4method{get_timestamp}{sfn_data_multi}(object) 28 | 29 | \S4method{get_solar_timestamp}{sfn_data_multi}(object) 30 | 31 | \S4method{get_si_code}{sfn_data_multi}(object) 32 | 33 | \S4method{get_site_md}{sfn_data_multi}(object, collapse = FALSE) 34 | 35 | \S4method{get_stand_md}{sfn_data_multi}(object, collapse = FALSE) 36 | 37 | \S4method{get_species_md}{sfn_data_multi}(object, collapse = FALSE) 38 | 39 | \S4method{get_plant_md}{sfn_data_multi}(object, collapse = FALSE) 40 | 41 | \S4method{get_env_md}{sfn_data_multi}(object, collapse = FALSE) 42 | } 43 | \arguments{ 44 | \item{object}{Object of class sfn_data_multi from which data or metadata is 45 | retrieved} 46 | 47 | \item{solar}{Logical indicating if the timestamp to return in the \code{get_sapf_data}, 48 | \code{get_env_data}, \code{get_sapf_flags} and \code{get_env_flags} methods is 49 | the solarTIMESTAMP (TRUE) or the contributors provided TIMESTAMP (FALSE)} 50 | 51 | \item{collapse}{Logical indicating if the metadata get methods must collapse 52 | the returning list to a data frame with all sites} 53 | } 54 | \description{ 55 | Methods to get the data and metadata from the sfn_data class slots 56 | } 57 | \details{ 58 | \code{get_sapf_data} and \code{get_env_data} methods retrieve sapflow or 59 | environmental tibbles from the sfn_data objects contained in the 60 | sfn_data_multi and return them in a list. 61 | 62 | \code{get_sapf_flags} and \code{get_env_flags} methods retrieve sapflow or 63 | environmental flags tibbles from the sfn_data objects contained in the 64 | sfn_data_multi and return them in a list. 65 | 66 | \code{get_timestamp} and \code{get_solar_timestamp} methods retrieve only the 67 | timestamps as POSIXct vectors and return them as a list (each element 68 | corresponding to a site in the sfn_data_multi object). 69 | 70 | \code{get_si_code} method retrieve a character vector with length(timestamp) 71 | containing the site code for each site, returning them as a list. 72 | 73 | \code{get_site_md}, \code{get_stand_md}, \code{get_species_md}, 74 | \code{get_plant_md} and \code{get_env_md} methods retrieve the corresponding 75 | metadata objects for each site returning them as a list, unless collapse is 76 | TRUE, then the list collapses to a tibble. 77 | } 78 | \examples{ 79 | library(dplyr) 80 | 81 | } 82 | -------------------------------------------------------------------------------- /man/sfn_mutate.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/sfn_dplyr.R 3 | \name{sfn_mutate} 4 | \alias{sfn_mutate} 5 | \title{Mutate variables by function} 6 | \usage{ 7 | sfn_mutate(sfn_data, ..., solar = FALSE) 8 | } 9 | \arguments{ 10 | \item{sfn_data}{\code{sfn_data} or \code{sfn_data_multi} object to subset} 11 | 12 | \item{...}{Name-value pairs of expressions to pass to the 13 | \code{\link[dplyr]{mutate}} function.} 14 | 15 | \item{solar}{Logical indicating if solar timestamp must used to subset} 16 | } 17 | \value{ 18 | For \code{sfn_data} objects, a mutated \code{sfn_data}. For 19 | \code{sfn_data_multi} another \code{sfn_data_multi} with the sites mutated 20 | } 21 | \description{ 22 | Port of \code{\link[dplyr]{mutate}} for \code{sfn_data} and 23 | \code{sfn_data_multi} objects 24 | } 25 | \details{ 26 | `sfn_mutate` function will maintain the same number of rows before and after 27 | the modification, so it is well suited to modify variables without creating 28 | TIMESTAMP gaps (i.e. to change variable units). For mutating groups of 29 | variables at the same time see \code{\link{sfn_mutate_at}}. 30 | } 31 | \section{Sapflow and environmental variables}{ 32 | 33 | `sfn_mutate` internally joins the sapflow and environmental datasets by the 34 | TIMESTAMP, so it is possible to mutate variables conditionally between 35 | sapflow and environmental measures (i.e. mutate sapflow when wind is high or 36 | radiation is zero). Due to this, at the moment any new variable is dropped 37 | when building the final results, so this is ONLY intended to mutate 38 | existing variables without changing the names. 39 | } 40 | 41 | \examples{ 42 | library(dplyr) 43 | library(lubridate) 44 | 45 | # data 46 | data('ARG_TRE', package = 'sapfluxnetr') 47 | 48 | # transform to NAs any wind value above 25 49 | ws_threshold <- 25 50 | sfn_mutate(ARG_TRE, ws = if_else(ws > 25, NA_real_, ws)) 51 | 52 | ## multi 53 | data(ARG_MAZ, package = 'sapfluxnetr') 54 | data(AUS_CAN_ST2_MIX, package = 'sapfluxnetr') 55 | multi_sfn <- sfn_data_multi(ARG_TRE, ARG_MAZ, AUS_CAN_ST2_MIX) 56 | 57 | multi_sfn_mutated <- sfn_mutate( 58 | multi_sfn, ws = if_else(ws > 25, NA_real_, ws) 59 | ) 60 | 61 | multi_sfn_mutated[['ARG_TRE']] 62 | 63 | } 64 | -------------------------------------------------------------------------------- /man/sfn_mutate_at.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/sfn_dplyr.R 3 | \name{sfn_mutate_at} 4 | \alias{sfn_mutate_at} 5 | \title{Mutate selected columns by function} 6 | \usage{ 7 | sfn_mutate_at(sfn_data, .vars, .funs, ..., solar = FALSE) 8 | } 9 | \arguments{ 10 | \item{sfn_data}{\code{sfn_data} or \code{sfn_data_multi} object to subset} 11 | 12 | \item{.vars}{Variables to mutate. Passed to \code{\link[dplyr]{mutate_at}}} 13 | 14 | \item{.funs}{Function/s for mutate, passed to \code{\link[dplyr]{mutate_at}}} 15 | 16 | \item{...}{Extra arguments to pass to the functions in \code{.funs}, passed 17 | to \code{\link[dplyr]{mutate_at}}.} 18 | 19 | \item{solar}{Logical indicating if solar timestamp must used to subset} 20 | } 21 | \value{ 22 | For \code{sfn_data} objects, a mutated \code{sfn_data}. For 23 | \code{sfn_data_multi} another \code{sfn_data_multi} with the sites mutated 24 | } 25 | \description{ 26 | Port of \code{\link[dplyr]{mutate_at}} for \code{sfn_data} and 27 | \code{sfn_data_multi} objects 28 | } 29 | \details{ 30 | `sfn_mutate_at` function will maintain the same number of rows before and 31 | after the modification, so it is well suited to modify variables without 32 | creating TIMESTAMP gaps (i.e. to change variable units). For mutating 33 | individual variables see \code{\link{sfn_mutate}}. 34 | } 35 | \examples{ 36 | library(dplyr) 37 | library(lubridate) 38 | 39 | # data 40 | data('ARG_TRE', package = 'sapfluxnetr') 41 | 42 | # transform to NAs any sapflow value occured with wind speed above 25 43 | ws_threshold <- 25 44 | # get the names of the variables to mutate (tree names) 45 | vars_to_mutate <- names(get_sapf_data(ARG_TRE)[,-1]) # no TIMESTAMP 46 | 47 | sfn_mutate_at( 48 | ARG_TRE, 49 | .vars = vars(one_of(vars_to_mutate)), 50 | .funs = list( 51 | ~ case_when( 52 | ws > ws_threshold ~ NA_real_, 53 | TRUE ~ . 54 | ) 55 | ) 56 | ) 57 | 58 | ## multi 59 | data(ARG_MAZ, package = 'sapfluxnetr') 60 | data(AUS_CAN_ST2_MIX, package = 'sapfluxnetr') 61 | multi_sfn <- sfn_data_multi(ARG_TRE, ARG_MAZ, AUS_CAN_ST2_MIX) 62 | 63 | ## in multi it's better to discard the variables to not mutate: 64 | vars_to_not_mutate <- names(get_env_data(ARG_TRE)) # all the environmental 65 | 66 | multi_sfn_mutated <- sfn_mutate_at( 67 | multi_sfn, 68 | .vars = vars(-one_of(vars_to_not_mutate)), # we use - 69 | .funs = list( 70 | ~ case_when( 71 | ws > ws_threshold ~ NA_real_, 72 | TRUE ~ . 73 | ) 74 | ) 75 | ) 76 | 77 | multi_sfn_mutated[['ARG_TRE']] 78 | 79 | } 80 | -------------------------------------------------------------------------------- /man/sfn_plot.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/visualizations.R 3 | \name{sfn_plot} 4 | \alias{sfn_plot} 5 | \title{plot method for sfn_data class} 6 | \usage{ 7 | sfn_plot( 8 | sfn_data, 9 | type = c("sapf", "env", "ta", "rh", "vpd", "ppfd_in", "netrad", "sw_in", "ext_rad", 10 | "ws", "precip", "swc_shallow", "swc_deep"), 11 | formula_env = NULL, 12 | solar = TRUE, 13 | ... 14 | ) 15 | } 16 | \arguments{ 17 | \item{sfn_data}{sfn_data object to plot. It can be also an sfn_data_multi 18 | object.} 19 | 20 | \item{type}{Character indicating which data to plot. See Type section for 21 | detailed information about the available values. Ignored if formula is 22 | provided} 23 | 24 | \item{formula_env}{Right side formula indicating an environmental variable to 25 | plot vs. the sapflow values. If NULL (default), \code{sfn_plot} will use 26 | "type" to guess which plot show.} 27 | 28 | \item{solar}{Logical indicating if the solar timestamp must be used instead 29 | of the site timestamp} 30 | 31 | \item{...}{Further arguments to be passed on \code{\link{geom_point}} or 32 | \code{\link{geom_col}} to modify geometry aesthetics.} 33 | } 34 | \value{ 35 | A ggplot object that can be called to see the plot. If input is an 36 | sfn_data_multi object, a list with the plots 37 | } 38 | \description{ 39 | Plot the desired data from a site object 40 | } 41 | \section{ggplot plotting system}{ 42 | 43 | \code{\link{plot}} is a base R function which uses the base R plotting system 44 | to show the plot. We prefer the ggplot plotting system, which allow for 45 | storing the plots in objects and can be subjected to further modifications. 46 | This allow the package users to generate rather simple plots that can be 47 | fine tuned afterwards to the user taste. Generating a \code{\link{plot}} 48 | method for the \code{sfn_data} class returning a ggplot object is not 49 | desired (it change the way plot works and can be misleading about the plot 50 | general usage). So, instead, we offer this function, \code{sfn_plot}. 51 | } 52 | 53 | \section{Type}{ 54 | 55 | \code{type} argument controls what is going to be plotted. It accepts 56 | the following: 57 | \itemize{ 58 | \item{"sapf": It will plot sapflow data vs. TIMESTAMP} 59 | \item{"env": It will plot environmental variables vs. TIMESTMAP} 60 | \item{"ta", "rh", "vpd", "ppfd_in", "netrad", "sw_in", "ext_rad", 61 | "ws", "precip", "swc_shallow" and "swc_deep": They will plot 62 | the corresponding variable vs. TIMESTAMP} 63 | } 64 | } 65 | 66 | \section{Formula}{ 67 | 68 | \code{formula} argument can be used to select an environmental variable to 69 | plot versus all the sapflow measurements. Any environmental variable is 70 | allowed, if it exist in the site provided. 71 | } 72 | 73 | \section{Geometry}{ 74 | 75 | By default \code{sfn_plot} generates plots using \code{\link{geom_point}} 76 | geometry, except in the case of \code{type = "ws"} and 77 | \code{type = "precip"} where \code{\link{geom_col}} is used. These 78 | geometries can be modified with the \code{...} argument. 79 | } 80 | 81 | \examples{ 82 | library(ggplot2) 83 | 84 | # data 85 | data('ARG_TRE', package = 'sapfluxnetr') 86 | 87 | # plotting directly 88 | sfn_plot(ARG_TRE, type = 'sapf') 89 | 90 | # this could be noisy, you can facet by "Tree" (for sapflow) or by 91 | # "Variable" (for environmental data): 92 | sfn_plot(ARG_TRE, type = 'sapf') + 93 | facet_wrap(~ Tree) 94 | 95 | sfn_plot(ARG_TRE, type = 'env') + 96 | facet_wrap(~ Variable, scales = 'free_y') 97 | 98 | # saving and modifying: 99 | env_plot <- sfn_plot(ARG_TRE, type = 'env', solar = FALSE) + 100 | facet_wrap(~ Variable, scales = 'free_y') 101 | env_plot + labs(title = 'Environmental variables facet plot') 102 | 103 | # formula 104 | sfn_plot(ARG_TRE, formula_env = ~ vpd) 105 | 106 | } 107 | -------------------------------------------------------------------------------- /man/sfn_replacement_generics.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/sfn_data_generics.R 3 | \name{sfn_replacement_generics} 4 | \alias{sfn_replacement_generics} 5 | \alias{get_sapf_data<-} 6 | \alias{get_env_data<-} 7 | \alias{get_sapf_flags<-} 8 | \alias{get_env_flags<-} 9 | \alias{get_timestamp<-} 10 | \alias{get_solar_timestamp<-} 11 | \alias{get_si_code<-} 12 | \alias{get_site_md<-} 13 | \alias{get_stand_md<-} 14 | \alias{get_species_md<-} 15 | \alias{get_plant_md<-} 16 | \alias{get_env_md<-} 17 | \title{sfn_data replacement generics} 18 | \usage{ 19 | get_sapf_data(object) <- value 20 | 21 | get_env_data(object) <- value 22 | 23 | get_sapf_flags(object) <- value 24 | 25 | get_env_flags(object) <- value 26 | 27 | get_timestamp(object) <- value 28 | 29 | get_solar_timestamp(object) <- value 30 | 31 | get_si_code(object) <- value 32 | 33 | get_site_md(object) <- value 34 | 35 | get_stand_md(object) <- value 36 | 37 | get_species_md(object) <- value 38 | 39 | get_plant_md(object) <- value 40 | 41 | get_env_md(object) <- value 42 | } 43 | \arguments{ 44 | \item{object}{Object to replace} 45 | 46 | \item{value}{Object to replace with} 47 | } 48 | \description{ 49 | Generic functions for replacement functions for sfn_data 50 | } 51 | \details{ 52 | see \code{\link{sfn_replacement_methods}} for more info about using the 53 | replacement methods in sfn_data objects 54 | } 55 | -------------------------------------------------------------------------------- /man/sfn_replacement_methods.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/sfn_data_methods.R 3 | \name{sfn_replacement_methods} 4 | \alias{sfn_replacement_methods} 5 | \alias{get_sapf_data<-,sfn_data-method} 6 | \alias{get_env_data<-,sfn_data-method} 7 | \alias{get_sapf_flags<-,sfn_data-method} 8 | \alias{get_env_flags<-,sfn_data-method} 9 | \alias{get_timestamp<-,sfn_data-method} 10 | \alias{get_solar_timestamp<-,sfn_data-method} 11 | \alias{get_si_code<-,sfn_data-method} 12 | \alias{get_site_md<-,sfn_data-method} 13 | \alias{get_stand_md<-,sfn_data-method} 14 | \alias{get_species_md<-,sfn_data-method} 15 | \alias{get_plant_md<-,sfn_data-method} 16 | \alias{get_env_md<-,sfn_data-method} 17 | \title{sfn_data replacement methods} 18 | \usage{ 19 | \S4method{get_sapf_data}{sfn_data}(object) <- value 20 | 21 | \S4method{get_env_data}{sfn_data}(object) <- value 22 | 23 | \S4method{get_sapf_flags}{sfn_data}(object) <- value 24 | 25 | \S4method{get_env_flags}{sfn_data}(object) <- value 26 | 27 | \S4method{get_timestamp}{sfn_data}(object) <- value 28 | 29 | \S4method{get_solar_timestamp}{sfn_data}(object) <- value 30 | 31 | \S4method{get_si_code}{sfn_data}(object) <- value 32 | 33 | \S4method{get_site_md}{sfn_data}(object) <- value 34 | 35 | \S4method{get_stand_md}{sfn_data}(object) <- value 36 | 37 | \S4method{get_species_md}{sfn_data}(object) <- value 38 | 39 | \S4method{get_plant_md}{sfn_data}(object) <- value 40 | 41 | \S4method{get_env_md}{sfn_data}(object) <- value 42 | } 43 | \arguments{ 44 | \item{object}{sfn_data containing the slot to replace} 45 | 46 | \item{value}{object with the data to replace sfn_data slot with} 47 | } 48 | \description{ 49 | Methods to replace the data and metadata from the sfn_data class slots 50 | } 51 | \details{ 52 | The replacement object must be a valid object for that slot: 53 | \itemize{ 54 | \item{For \code{get_sapf_data}, \code{get_env_data}, \code{get_sapf_flags} and 55 | \code{get_env_flags} a data.frame or tibble without the TIMESTAMP 56 | variable} 57 | \item{For \code{get_*_md} a data.frame or tibble} 58 | \item{For \code{get_timestamp} and \code{get_solar_timestamp} a POSIXct 59 | vector of length == nrow(sapf/env_data)} 60 | \item{For \code{get_si_code} a character vector} 61 | } 62 | Validity is automatically checked before modifying the sfn_data object, and 63 | an error is raised if not valid 64 | } 65 | \examples{ 66 | # preparation 67 | data('ARG_TRE', package = 'sapfluxnetr') 68 | sapf_data <- get_sapf_data(ARG_TRE, solar = TRUE) 69 | 70 | # modifying the slot data 71 | sapf_data[1:10, 2] <- NA 72 | 73 | # replacement. Remember, the sfn_data slot does not contain a TIMESTAMP 74 | # variable, it must be removed 75 | get_sapf_data(ARG_TRE) <- sapf_data[,-1] 76 | 77 | } 78 | -------------------------------------------------------------------------------- /man/sfn_sites_in_folder.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/getters.R 3 | \name{sfn_sites_in_folder} 4 | \alias{sfn_sites_in_folder} 5 | \title{list available sites in a db folder} 6 | \usage{ 7 | sfn_sites_in_folder(folder = ".") 8 | } 9 | \arguments{ 10 | \item{folder}{Character vector of length 1 indicating the route to the 11 | db folder} 12 | } 13 | \value{ 14 | A character vector with the site codes present in the folder, an 15 | error if the folder is not valid or does not contain any site data file. 16 | } 17 | \description{ 18 | Retrieves the site codes in the specified folder 19 | } 20 | \details{ 21 | If folder 22 | } 23 | \examples{ 24 | # Let's access the data in "folder". This typically is the folder where the 25 | # sapflow data at the desired unit level is (i.e. "RData/plant"), but in this 26 | # example we will create a temporal folder with some data to test the function 27 | folder <- tempdir() 28 | save(ARG_TRE, file = file.path(folder, 'ARG_TRE.RData')) 29 | save(ARG_MAZ, file = file.path(folder, 'ARG_MAZ.RData')) 30 | save(AUS_CAN_ST2_MIX, file = file.path(folder, 'AUS_EUC_ST2_MIX.RData')) 31 | 32 | # lets see the sites 33 | sites <- sfn_sites_in_folder(folder) 34 | 35 | } 36 | -------------------------------------------------------------------------------- /man/sfn_vars_to_filter.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/helpers.R 3 | \name{sfn_vars_to_filter} 4 | \alias{sfn_vars_to_filter} 5 | \title{List all variables that can be used to filter sites} 6 | \usage{ 7 | sfn_vars_to_filter() 8 | } 9 | \value{ 10 | A list with five elements, \code{site_md}, \code{stand_md}, 11 | \code{species_md}, \code{plant_md} and \code{env_md} 12 | } 13 | \description{ 14 | \code{sfn_vars_to_filter()} returns a list with the variables for each 15 | kind of metadata that can be used to select and filter sites 16 | } 17 | \examples{ 18 | # all variables 19 | sfn_vars_to_filter() 20 | 21 | # by some metadata 22 | sfn_vars_to_filter()$site_md 23 | 24 | } 25 | -------------------------------------------------------------------------------- /man/show-sfn_data-method.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/sfn_data_methods.R 3 | \name{show,sfn_data-method} 4 | \alias{show,sfn_data-method} 5 | \title{Show method for sfn_data} 6 | \usage{ 7 | \S4method{show}{sfn_data}(object) 8 | } 9 | \arguments{ 10 | \item{object}{sfn_data object to show} 11 | } 12 | \description{ 13 | print a summary for sfn_data objects 14 | } 15 | -------------------------------------------------------------------------------- /man/show-sfn_data_multi-method.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/sfn_data_methods.R 3 | \name{show,sfn_data_multi-method} 4 | \alias{show,sfn_data_multi-method} 5 | \title{Show method for sfn_data_multi} 6 | \usage{ 7 | \S4method{show}{sfn_data_multi}(object) 8 | } 9 | \arguments{ 10 | \item{object}{sfn_data_multi object to show} 11 | } 12 | \description{ 13 | print a summary for sfn_data_multi objects 14 | } 15 | -------------------------------------------------------------------------------- /man/summarise_by_period.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/metrics.R 3 | \name{summarise_by_period} 4 | \alias{summarise_by_period} 5 | \title{Summaries by period} 6 | \usage{ 7 | summarise_by_period(data, period, .funs, ...) 8 | } 9 | \arguments{ 10 | \item{data}{sapflow or environmental data as obtained by \code{\link{get_sapf_data}} 11 | and \code{\link{get_env_data}}. Must have a column named TIMESTAMP} 12 | 13 | \item{period}{period to collapse by. See \code{\link{sfn_metrics}} for details.} 14 | 15 | \item{.funs}{funs to summarise the data. See details.} 16 | 17 | \item{...}{optional arguments. See details} 18 | } 19 | \value{ 20 | A `tbl_df` object with the metrics results. The names of the columns 21 | indicate the original variable (tree or environmental variable) and the 22 | metric calculated (i.e. `vpd_mean`), separated by underscore 23 | } 24 | \description{ 25 | This function collapse the TIMESTAMP to the desired period (day, month...) 26 | by setting the same value to all timestamps within the period. This modified 27 | TIMESTAMP is used to group by and summarise the data. 28 | } 29 | \details{ 30 | This function uses internally \code{\link{.collapse_timestamp}} and 31 | \code{\link[dplyr]{summarise_all}}. Arguments to control these functions 32 | can be passed as `...`. Arguments for each function are spliced and applied 33 | when needed. Be advised that all arguments passed to the summarise_all function 34 | will be applied to all the summarising functions used, so it will fail if any 35 | of that functions does not accept that argument. To complex function-argument 36 | relationships, indicate each summary function call within the \code{.funs} 37 | argument as explained here \code{\link[dplyr]{summarise_all}}: 38 | \preformatted{ 39 | # This will fail beacuse na.rm argument will be also passed to the n function, 40 | # which does not accept any argument: 41 | summarise_by_period( 42 | data = get_sapf_data(ARG_TRE), 43 | period = '7 days', 44 | .funs = list(mean, sd, n()), 45 | na.rm = TRUE 46 | ) 47 | 48 | # to solve this is better to use the .funs argument: 49 | summarise_by_period( 50 | data = get_sapf_data(ARG_TRE), 51 | period = '7 days', 52 | .funs = list(~ mean(., na.rm = TRUE), ~ sd(., na.rm = TRUE), ~ n()) 53 | ) 54 | } 55 | } 56 | \section{TIMESTAMP_coll}{ 57 | 58 | Previously to the collapsing step, a temporal variable called 59 | \code{TIMESTAMP_coll} is created to be able to catch the real timestamp when 60 | some events happens, for example to use the \code{min_time} function. If 61 | your custom summarise function needs to get the time at which some event 62 | happens, use TIMESTAMP_coll instead of TIMESTAMP for that: 63 | \preformatted{ 64 | min_time <- function(x, time) { 65 | time[which.min(x)] 66 | } 67 | 68 | summarise_by_period( 69 | data = get_sapf_data(ARG_TRE), 70 | period = '1 day', 71 | .funs = list(~ min_time(., time = TIMESTAMP_coll)) # Not TIMESTAMP 72 | ) 73 | } 74 | } 75 | 76 | \examples{ 77 | library(dplyr) 78 | 79 | # data 80 | data('ARG_TRE', package = 'sapfluxnetr') 81 | 82 | # simple summary 83 | summarise_by_period( 84 | data = get_sapf_data(ARG_TRE), 85 | period = '7 days', 86 | .funs = list(~ mean(., na.rm = TRUE), ~ sd(., na.rm = TRUE), ~ n()) 87 | ) 88 | 89 | } 90 | -------------------------------------------------------------------------------- /man/time_at_events.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/helpers.R 3 | \name{time_at_events} 4 | \alias{time_at_events} 5 | \alias{max_time} 6 | \alias{min_time} 7 | \title{time at maximum/minimum} 8 | \usage{ 9 | max_time(x, time) 10 | 11 | min_time(x, time) 12 | } 13 | \arguments{ 14 | \item{x}{a numeric vector, usually a variable in the sapflow or environmental 15 | data.} 16 | 17 | \item{time}{a POSIXct or character vector with the TIMESTAMP values} 18 | } 19 | \value{ 20 | a single value (POSIXct) with the TIMESTAMP value. 21 | } 22 | \description{ 23 | helpers for sfn_metrics 24 | } 25 | \details{ 26 | These helper functions return the TIMESTAMP value at which the maximum value 27 | for other variable occurs. It is designed to be used inside a dplyr summarise 28 | statement. 29 | } 30 | \section{Functions}{ 31 | \itemize{ 32 | \item \code{max_time()}: helper for sfn_metrics 33 | 34 | \item \code{min_time()}: helper for sfn_metrics 35 | 36 | }} 37 | \examples{ 38 | library(dplyr) 39 | storms \%>\% 40 | group_by(year) \%>\% 41 | summarise(wind_max = max(wind), 42 | hour_at_max = sapfluxnetr:::max_time(wind, time = hour), 43 | wind_min = min(wind), 44 | hour_at_min = sapfluxnetr:::min_time(wind, time = hour)) 45 | 46 | } 47 | \keyword{internal} 48 | -------------------------------------------------------------------------------- /metadata.yml: -------------------------------------------------------------------------------- 1 | id: sapfluxnetr 2 | emf_type: softwork 3 | emf_public: true 4 | emf_automatized: true 5 | emf_reproducible: false 6 | emf_draft: false 7 | emf_data_type: emf_data_product 8 | data_repository: '' 9 | model_repository: '' 10 | nodes: '' 11 | authors: 12 | - vgranda 13 | - rpoyatos 14 | - vflo 15 | tags: 16 | - R 17 | - data 18 | - sap flow 19 | - sap flux 20 | links: 21 | url_docs: 'http://sapfluxnet.creaf.cat/sapfluxnetr/' 22 | url_source: 'https://github.com/sapfluxnet/sapfluxnetr' 23 | requirements: R (>= 4.0.0) 24 | description: Access, modify, aggregate and plot data from the 'Sapfluxnet' project, the first global database of sap flow measurements. 25 | date: '2022-02-10' 26 | date_lastmod: '2022-02-10' 27 | title: sapfluxnetr 28 | 29 | -------------------------------------------------------------------------------- /pkgdown/extra.css: -------------------------------------------------------------------------------- 1 | /* from styles.css in academic theme ------*/ 2 | 3 | html, body { 4 | font-family: 'Roboto', sans-serif; 5 | font-size: 18px; 6 | color: rgba(0,0,0,0.8); 7 | background-color: #FFFFFF; 8 | } 9 | 10 | /* Hack to change the links color */ 11 | a, 12 | h3.article-title a:hover { 13 | color: hsl(339, 90%, 68%); 14 | text-decoration: none; 15 | transition: color 0.6s ease; 16 | } 17 | 18 | a:hover, 19 | a:focus { 20 | color: hsl(339, 90%, 68%); 21 | } 22 | /* Hack to avoid the blue in the toc navigator */ 23 | .nav-pills>li.active>a, .nav-pills>li.active>a:focus, .nav-pills>li.active>a:hover { 24 | background-color: hsl(339, 90%, 68%); 25 | } 26 | 27 | /* Hack to make bigger the navbar */ 28 | .navbar { 29 | background-color: #141622; 30 | min-height: 70px !important; 31 | padding-top: 8px; 32 | } 33 | 34 | /* Hack to make text smaler in the toc sidebar */ 35 | nav[data-toggle='toc'] .nav > li > a { 36 | font-size: 18px; 37 | } 38 | -------------------------------------------------------------------------------- /tests/testthat.R: -------------------------------------------------------------------------------- 1 | library(testthat) 2 | library(sapfluxnetr) 3 | 4 | test_check("sapfluxnetr") 5 | -------------------------------------------------------------------------------- /tests/testthat/ARG_MAZ.RData: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sapfluxnet/sapfluxnetr/a09141f653f540728ea3474d975b63680ffc463f/tests/testthat/ARG_MAZ.RData -------------------------------------------------------------------------------- /tests/testthat/ARG_TRE.RData: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sapfluxnet/sapfluxnetr/a09141f653f540728ea3474d975b63680ffc463f/tests/testthat/ARG_TRE.RData -------------------------------------------------------------------------------- /tests/testthat/AUS_CAN_ST2_MIX.RData: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sapfluxnet/sapfluxnetr/a09141f653f540728ea3474d975b63680ffc463f/tests/testthat/AUS_CAN_ST2_MIX.RData -------------------------------------------------------------------------------- /tests/testthat/Data/ARG_MAZ.RData: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sapfluxnet/sapfluxnetr/a09141f653f540728ea3474d975b63680ffc463f/tests/testthat/Data/ARG_MAZ.RData -------------------------------------------------------------------------------- /tests/testthat/Data/ARG_TRE.RData: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sapfluxnet/sapfluxnetr/a09141f653f540728ea3474d975b63680ffc463f/tests/testthat/Data/ARG_TRE.RData -------------------------------------------------------------------------------- /tests/testthat/Data/AUS_CAN_ST2_MIX.RData: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sapfluxnet/sapfluxnetr/a09141f653f540728ea3474d975b63680ffc463f/tests/testthat/Data/AUS_CAN_ST2_MIX.RData -------------------------------------------------------------------------------- /tests/testthat/test-getters.R: -------------------------------------------------------------------------------- 1 | #### read_sfn_data tests #### 2 | test_that('read_sfn_data load the objects correctly', { 3 | 4 | expect_s4_class( 5 | read_sfn_data('ARG_TRE', 'Data'), 'sfn_data' 6 | ) 7 | 8 | expect_s4_class( 9 | read_sfn_data('ARG_MAZ', 'Data'), 'sfn_data' 10 | ) 11 | 12 | expect_s4_class( 13 | read_sfn_data('AUS_CAN_ST2_MIX', 'Data'), 'sfn_data' 14 | ) 15 | 16 | expect_s4_class( 17 | read_sfn_data(c('ARG_TRE', 'ARG_MAZ', 'AUS_CAN_ST2_MIX'), 'Data'), 'sfn_data_multi' 18 | ) 19 | 20 | }) 21 | 22 | #### as_sfn_data_multi tests #### 23 | test_that('as_sfn_data_multi helper works as intended', { 24 | 25 | ARG_TRE <- read_sfn_data('ARG_TRE', 'Data') 26 | ARG_MAZ <- read_sfn_data('ARG_MAZ', 'Data') 27 | AUS_CAN_ST2_MIX <- read_sfn_data('AUS_CAN_ST2_MIX', 'Data') 28 | 29 | multi_list <- list(ARG_TRE, ARG_MAZ, AUS_CAN_ST2_MIX) 30 | 31 | expect_s4_class( 32 | sapfluxnetr:::as_sfn_data_multi(multi_list), 'sfn_data_multi' 33 | ) 34 | 35 | multi_sfn <- sapfluxnetr:::as_sfn_data_multi(multi_list) 36 | 37 | expect_identical( 38 | names(multi_sfn), c('ARG_TRE', 'ARG_MAZ', 'AUS_CAN_ST2_MIX') 39 | ) 40 | 41 | expect_s4_class( 42 | multi_sfn[[1]], 'sfn_data' 43 | ) 44 | 45 | expect_s4_class( 46 | multi_sfn[[2]], 'sfn_data' 47 | ) 48 | 49 | expect_s4_class( 50 | multi_sfn[['AUS_CAN_ST2_MIX']], 'sfn_data' 51 | ) 52 | }) 53 | 54 | #### read_sfn_metadata tests #### 55 | test_that('.write_sfn_metadata writes correctly the file', { 56 | 57 | #testthat::skip_on_cran() 58 | 59 | folder <- tempdir() 60 | save(ARG_TRE, file = file.path(folder, 'ARG_TRE.RData')) 61 | save(ARG_MAZ, file = file.path(folder, 'ARG_MAZ.RData')) 62 | save(AUS_CAN_ST2_MIX, file = file.path(folder, 'AUS_CAN_ST2_MIX.RData')) 63 | 64 | sfn_metadata <- sapfluxnetr:::.write_metadata_cache(folder, .dry = TRUE) 65 | 66 | expect_false(file.exists(file.path(folder, '.metadata_cache.RData'))) 67 | expect_true(is.list(sfn_metadata)) 68 | expect_length(sfn_metadata, 5) 69 | expect_equal(nrow(sfn_metadata[['site_md']]), 3) 70 | expect_s3_class(sfn_metadata[['site_md']], 'tbl') 71 | expect_s3_class(sfn_metadata[['stand_md']], 'tbl') 72 | expect_s3_class(sfn_metadata[['species_md']], 'tbl') 73 | expect_s3_class(sfn_metadata[['plant_md']], 'tbl') 74 | expect_s3_class(sfn_metadata[['env_md']], 'tbl') 75 | 76 | sfn_metadata_2 <- sapfluxnetr:::.write_metadata_cache(folder) 77 | expect_true(file.exists(file.path(folder, '.metadata_cache.RData'))) 78 | expect_identical(sfn_metadata, sfn_metadata_2) 79 | 80 | unlink(file.path(folder, '.metadata_cache.RData')) 81 | 82 | }) 83 | 84 | test_that('read_sfn_metadata works as intended', { 85 | 86 | folder <- tempdir() 87 | save(ARG_TRE, file = file.path(folder, 'ARG_TRE.RData')) 88 | save(ARG_MAZ, file = file.path(folder, 'ARG_MAZ.RData')) 89 | save(AUS_CAN_ST2_MIX, file = file.path(folder, 'AUS_CAN_ST2_MIX.RData')) 90 | 91 | expect_error( 92 | read_sfn_metadata(folder = folder), 'metadata cache file not found at' 93 | ) 94 | 95 | sfn_metadata <- read_sfn_metadata(folder, .write_cache = TRUE) 96 | 97 | expect_true(file.exists(file.path(folder, '.metadata_cache.RData'))) 98 | expect_true(is.list(sfn_metadata)) 99 | expect_length(sfn_metadata, 5) 100 | expect_equal(nrow(sfn_metadata[['site_md']]), 3) 101 | 102 | sfn_metadata_2 <- read_sfn_metadata(folder) 103 | expect_true(is.list(sfn_metadata)) 104 | expect_length(sfn_metadata, 5) 105 | expect_equal(nrow(sfn_metadata[['site_md']]), 3) 106 | expect_identical(sfn_metadata, sfn_metadata_2) 107 | 108 | unlink(file.path(folder, '.metadata_cache.RData')) 109 | 110 | }) 111 | 112 | #### filter_sites_by_md tests #### 113 | test_that('filter_sites_by_md combines all metadata correctly', { 114 | 115 | data('sfn_metadata_ex', package = 'sapfluxnetr') 116 | sites <- sfn_sites_in_folder('Data') 117 | filters <- list(dplyr::quo(pl_sens_meth == 'HR')) 118 | 119 | expect_true(is.character(filter_sites_by_md( 120 | sites, sfn_metadata_ex, !!!filters 121 | ))) 122 | 123 | expect_length( 124 | filter_sites_by_md(sites, sfn_metadata_ex, !!!filters), 2 125 | ) 126 | 127 | expect_identical( 128 | filter_sites_by_md(sites, sfn_metadata_ex, !!!filters), 129 | c('ARG_MAZ', 'ARG_TRE') 130 | ) 131 | 132 | filters <- list( 133 | dplyr::quo(pl_sens_meth == 'HD'), 134 | dplyr::quo(env_ta == 'Clearing') 135 | ) 136 | 137 | expect_length( 138 | filter_sites_by_md(sites, sfn_metadata_ex, !!!filters), 0 139 | ) 140 | 141 | filters <- list( 142 | dplyr::quo(pl_sens_meth == 'HR'), 143 | dplyr::quo(env_ta == 'Above canopy') 144 | ) 145 | 146 | expect_length( 147 | filter_sites_by_md(sites, sfn_metadata_ex, !!!filters), 0 148 | ) 149 | 150 | filters <- list( 151 | dplyr::quo(pl_sens_meth == 'HR'), 152 | dplyr::quo(env_nonexistentname == 'Above canopy') 153 | ) 154 | 155 | expect_error( 156 | filter_sites_by_md(sites, sfn_metadata_ex, !!!filters) 157 | # 'env_nonexistentname' 158 | ) 159 | 160 | # TODO tests con los diferentes metadatas por separado, tests con combinaciones 161 | 162 | }) 163 | 164 | #### sfn_sites_in_folder #### 165 | test_that('sfn_sites_in_folder returns the expected results', { 166 | 167 | expect_true(is.character(sfn_sites_in_folder('Data'))) 168 | expect_length(sfn_sites_in_folder('Data'), 3) 169 | expect_identical( 170 | sfn_sites_in_folder('Data'), c('ARG_MAZ', 'ARG_TRE', 'AUS_CAN_ST2_MIX') 171 | ) 172 | 173 | # errors 174 | expect_error(sfn_sites_in_folder('NonExistentFolder')) 175 | expect_error(sfn_sites_in_folder(53)) 176 | 177 | }) 178 | 179 | #### teardown 180 | # teardown(unlink(file.path('Data', '.metadata_cache.RData'))) 181 | -------------------------------------------------------------------------------- /tests/testthat/test-helpers.R: -------------------------------------------------------------------------------- 1 | test_that("describe_md_variable works", { 2 | expect_output(describe_md_variable('pl_sens_meth'), 'Type:') 3 | expect_output(describe_md_variable('st_age'), 'Values:') 4 | expect_output(describe_md_variable('si_lat'), 'Units:') 5 | expect_output(describe_md_variable('sp_leaf_habit'), 'Description:') 6 | expect_output(describe_md_variable('env_vpd'), 'Type:') 7 | }) 8 | 9 | test_that("accumulated metric helper function works", { 10 | 11 | # skip_on_cran() 12 | 13 | data <- get_env_data(ARG_TRE) %>% dplyr::select(TIMESTAMP, precip) 14 | 15 | expect_identical( 16 | sapfluxnetr:::.accumulated_posix_aware(data$TIMESTAMP), data$TIMESTAMP[1] 17 | ) 18 | expect_equal( 19 | sapfluxnetr:::.accumulated_posix_aware(data$precip), 38.5 20 | ) 21 | expect_identical( 22 | sapfluxnetr:::.accumulated_posix_aware(data$precip), sum(data$precip) 23 | ) 24 | 25 | data_summ <- data %>% dplyr::summarise_all(sapfluxnetr:::.accumulated_posix_aware) 26 | 27 | expect_s3_class(data_summ, 'tbl') 28 | expect_identical(names(data_summ), c('TIMESTAMP', 'precip')) 29 | expect_identical(data_summ[['TIMESTAMP']][1], data$TIMESTAMP[1]) 30 | expect_equal(data_summ[['precip']][1], 38.5) 31 | }) 32 | -------------------------------------------------------------------------------- /tests/testthat/test-sfn_dplyr_methods.R: -------------------------------------------------------------------------------- 1 | data('ARG_TRE', package = 'sapfluxnetr') 2 | data('ARG_MAZ', package = 'sapfluxnetr') 3 | data('AUS_CAN_ST2_MIX', package = 'sapfluxnetr') 4 | 5 | #### filter ##### 6 | test_that("sfn_filter returns correct results", { 7 | foo_timestamp <- get_timestamp(ARG_TRE) 8 | foo_timestamp_trimmed <- foo_timestamp[1:100] 9 | foo_solar_timestamp <- get_solar_timestamp(ARG_TRE) 10 | foo_solar_timestamp_trimmed <- foo_solar_timestamp[1:100] 11 | ws_threshold <- 25 12 | foo_subset <- sfn_filter(ARG_TRE, TIMESTAMP %in% foo_timestamp_trimmed) 13 | foo_subset_2 <- sfn_filter(ARG_TRE, ws <= ws_threshold) 14 | foo_subset_3 <- sfn_filter( 15 | ARG_TRE, TIMESTAMP %in% foo_solar_timestamp_trimmed, 16 | solar = TRUE 17 | ) 18 | multi_sfn <- sfn_data_multi(ARG_TRE, ARG_MAZ) 19 | multi_sfn_filter <- sfn_filter( 20 | multi_sfn, dplyr::between(lubridate::day(TIMESTAMP), 19, 23) 21 | ) 22 | multi_sfn_filter_2 <- sfn_filter(multi_sfn, ws <= ws_threshold) 23 | multi_sfn_2 <- sfn_data_multi(ARG_TRE, ARG_MAZ, AUS_CAN_ST2_MIX) 24 | suppressWarnings(multi_sfn_filter_3 <- sfn_filter( 25 | multi_sfn_2, dplyr::between(lubridate::year(TIMESTAMP), 1998, 1999) 26 | )) 27 | suppressWarnings(multi_sfn_filter_4 <- sfn_filter( 28 | multi_sfn_2, dplyr::between(lubridate::year(TIMESTAMP), 2008, 2009) 29 | )) 30 | suppressWarnings(multi_sfn_filter_5 <- sfn_filter( 31 | multi_sfn_2, dplyr::between(lubridate::year(TIMESTAMP), 2006, 2007) 32 | )) 33 | 34 | 35 | expect_s4_class(foo_subset, 'sfn_data') 36 | # only check one because the constructor checks the others 37 | expect_length(get_solar_timestamp(foo_subset), 100) 38 | 39 | expect_s4_class(foo_subset_2, 'sfn_data') 40 | expect_true(all(get_env_data(foo_subset_2)[['ws']] <= 25)) 41 | # only check one because the constructor checks the others 42 | expect_length(get_solar_timestamp(foo_subset_2), 212) 43 | 44 | expect_s4_class(foo_subset_3, 'sfn_data') 45 | # only check one because the constructor checks the others 46 | expect_length(get_solar_timestamp(foo_subset_3), 100) 47 | 48 | expect_identical(foo_subset, foo_subset_3) 49 | 50 | expect_s4_class(multi_sfn_filter, 'sfn_data_multi') 51 | expect_length(multi_sfn_filter, 2) 52 | expect_s4_class(multi_sfn_filter[[1]], 'sfn_data') 53 | expect_s4_class(multi_sfn_filter[[2]], 'sfn_data') 54 | expect_length(get_timestamp(multi_sfn_filter[[1]]), 24*5) 55 | expect_length(get_timestamp(multi_sfn_filter[[2]]), 24*5) 56 | 57 | expect_s4_class(multi_sfn_filter_2, 'sfn_data_multi') 58 | expect_length(multi_sfn_filter_2, 2) 59 | expect_s4_class(multi_sfn_filter_2[[1]], 'sfn_data') 60 | expect_s4_class(multi_sfn_filter_2[[2]], 'sfn_data') 61 | expect_length(get_solar_timestamp(multi_sfn_filter_2[[1]]), 212) 62 | expect_length(get_solar_timestamp(multi_sfn_filter_2[[2]]), 210) 63 | 64 | expect_s4_class(multi_sfn_filter_3, 'sfn_data_multi') 65 | expect_length(multi_sfn_filter_3, 0) 66 | # In this case there are 4 warnings, each site and the final one. Since new 67 | # versions of testthat (Config/testthat/edition: 3), all extra warnings are 68 | # not captured as before so we need to nest expectations of warnings 69 | expect_warning( 70 | expect_warning( 71 | expect_warning( 72 | expect_warning( 73 | sfn_filter( 74 | multi_sfn_2, dplyr::between(lubridate::year(TIMESTAMP), 1998, 1999) 75 | ), "Any sites met the criteria, returning empty results" 76 | ), 77 | "AUS_CAN_ST2_MIX" 78 | ), 79 | "ARG_MAZ" 80 | ), 81 | "ARG_TRE" 82 | ) 83 | 84 | expect_s4_class(multi_sfn_filter_4, 'sfn_data_multi') 85 | expect_length(multi_sfn_filter_4, 2) 86 | expect_warning( 87 | sfn_filter( 88 | multi_sfn_2, dplyr::between(lubridate::year(TIMESTAMP), 2008, 2009) 89 | ), 'AUS_CAN_ST2_MIX' 90 | ) 91 | 92 | expect_s4_class(multi_sfn_filter_5, 'sfn_data_multi') 93 | expect_length(multi_sfn_filter_5, 1) 94 | # In this case there are 2 warnings, each ARG_* site. Since new 95 | # versions of testthat (Config/testthat/edition: 3), all extra warnings are 96 | # not captured as before so we need to nest expectations of warnings 97 | expect_warning( 98 | expect_warning( 99 | sfn_filter( 100 | multi_sfn_2, dplyr::between(lubridate::year(TIMESTAMP), 2006, 2007) 101 | ), 'ARG_MAZ' 102 | ), 103 | 'ARG_TRE' 104 | ) 105 | 106 | }) 107 | 108 | #### mutate #### 109 | test_that('sfn_mutate returns correct results', { 110 | 111 | foo_mutated <- sfn_mutate(ARG_TRE, ws = dplyr::if_else(ws > 25, NA_real_, ws)) 112 | multi_sfn <- sfn_data_multi(ARG_TRE, ARG_MAZ, AUS_CAN_ST2_MIX) 113 | multi_mutated <- sfn_mutate( 114 | multi_sfn, ws = dplyr::if_else(ws > 25, NA_real_, ws) 115 | ) 116 | 117 | expect_s4_class(foo_mutated, 'sfn_data') 118 | expect_equal(sum(is.na(get_env_data(foo_mutated)[['ws']])), 100) 119 | expect_match(get_env_flags(foo_mutated)[['ws']], 'USER_MODF', all = TRUE) 120 | expect_match(get_env_flags(foo_mutated)[['ws']], 'RANGE_WARN', all = FALSE) 121 | expect_equal(sum(is.na(get_env_data(foo_mutated)[['ta']])), 0) 122 | expect_failure( 123 | expect_match(get_env_flags(foo_mutated)[['ta']], 'USER_MODF', all = TRUE) 124 | ) 125 | expect_identical(attr(get_timestamp(foo_mutated), 'tz'), 'Etc/GMT+3') 126 | expect_identical(attr(get_solar_timestamp(foo_mutated), 'tz'), 'UTC') 127 | 128 | expect_s4_class(multi_mutated, 'sfn_data_multi') 129 | expect_length(multi_mutated, 3) 130 | expect_s4_class(multi_mutated[[1]], 'sfn_data') 131 | expect_s4_class(multi_mutated[[2]], 'sfn_data') 132 | expect_s4_class(multi_mutated[[3]], 'sfn_data') 133 | expect_identical(attr(get_timestamp(multi_mutated[[1]]), 'tz'), 'Etc/GMT+3') 134 | expect_identical(attr(get_solar_timestamp(multi_mutated[[1]]), 'tz'), 'UTC') 135 | expect_identical(attr(get_timestamp(multi_mutated[[2]]), 'tz'), 'Etc/GMT+3') 136 | expect_identical(attr(get_solar_timestamp(multi_mutated[[2]]), 'tz'), 'UTC') 137 | expect_identical(attr(get_timestamp(multi_mutated[[3]]), 'tz'), 'Etc/GMT-10') 138 | expect_identical(attr(get_solar_timestamp(multi_mutated[[3]]), 'tz'), 'UTC') 139 | expect_equal(sum(is.na(get_env_data(multi_mutated[[1]])[['ws']])), 100) 140 | expect_match(get_env_flags(multi_mutated[[1]])[['ws']], 'USER_MODF', all = TRUE) 141 | expect_match(get_env_flags(multi_mutated[[1]])[['ws']], 'RANGE_WARN', all = FALSE) 142 | expect_equal(sum(is.na(get_env_data(multi_mutated[[2]])[['ws']])), 78) 143 | expect_match(get_env_flags(multi_mutated[[2]])[['ws']], 'USER_MODF', all = TRUE) 144 | expect_match(get_env_flags(multi_mutated[[2]])[['ws']], 'RANGE_WARN', all = FALSE) 145 | expect_failure( 146 | expect_match(get_env_flags(multi_mutated[[3]])[['ws']], 'USER_MODF', all = TRUE) 147 | ) 148 | expect_match(get_env_flags(multi_mutated[[3]])[['ws']], 'OUT_WARN', all = FALSE) 149 | expect_identical(multi_sfn[['AUS_CAN_ST2_MIX']], multi_mutated[['AUS_CAN_ST2_MIX']]) 150 | }) 151 | 152 | #### mutate_at #### 153 | test_that('sfn_mutate_at returns correct results', { 154 | 155 | vars_to_mutate <- names(get_sapf_data(ARG_TRE)[,-1]) 156 | foo_mutated <- sfn_mutate_at( 157 | ARG_TRE, 158 | .vars = dplyr::vars(dplyr::one_of(vars_to_mutate)), 159 | .funs = list( 160 | ~ dplyr::case_when( 161 | ws > 25 ~ NA_real_, 162 | TRUE ~ . 163 | ) 164 | ) 165 | ) 166 | 167 | vars_to_not_mutate <- names(get_env_data(ARG_TRE)) 168 | multi_sfn <- sfn_data_multi(ARG_TRE, ARG_MAZ, AUS_CAN_ST2_MIX) 169 | multi_mutated <- suppressWarnings(sfn_mutate_at( 170 | multi_sfn, 171 | .vars = dplyr::vars(-dplyr::one_of(vars_to_not_mutate)), # we use - 172 | .funs = list( 173 | ~ dplyr::case_when( 174 | ws > 25 ~ NA_real_, 175 | TRUE ~ . 176 | ) 177 | ) 178 | )) 179 | 180 | expect_s4_class(foo_mutated, 'sfn_data') 181 | expect_equal(sum(is.na(get_sapf_data(foo_mutated)[[2]])), 100) 182 | expect_equal(sum(is.na(get_sapf_data(foo_mutated)[[3]])), 100) 183 | expect_equal(sum(is.na(get_sapf_data(foo_mutated)[[4]])), 100) 184 | expect_equal(sum(is.na(get_sapf_data(foo_mutated)[[5]])), 100) 185 | expect_match(get_sapf_flags(foo_mutated)[[2]], 'USER_MODF', all = TRUE) 186 | expect_match(get_sapf_flags(foo_mutated)[[3]], 'USER_MODF', all = TRUE) 187 | expect_match(get_sapf_flags(foo_mutated)[[4]], 'USER_MODF', all = TRUE) 188 | expect_match(get_sapf_flags(foo_mutated)[[5]], 'USER_MODF', all = TRUE) 189 | 190 | expect_s4_class(multi_mutated, 'sfn_data_multi') 191 | expect_length(multi_mutated, 3) 192 | expect_s4_class(multi_mutated[[1]], 'sfn_data') 193 | expect_s4_class(multi_mutated[[2]], 'sfn_data') 194 | expect_s4_class(multi_mutated[[3]], 'sfn_data') 195 | expect_equal(sum(is.na(get_sapf_data(multi_mutated[[1]])[[2]])), 100) 196 | expect_equal(sum(is.na(get_sapf_data(multi_mutated[[1]])[[3]])), 100) 197 | expect_equal(sum(is.na(get_sapf_data(multi_mutated[[1]])[[4]])), 100) 198 | expect_equal(sum(is.na(get_sapf_data(multi_mutated[[1]])[[5]])), 100) 199 | expect_equal(sum(is.na(get_sapf_data(multi_mutated[[2]])[[2]])), 78) 200 | expect_equal(sum(is.na(get_sapf_data(multi_mutated[[2]])[[3]])), 78) 201 | expect_equal(sum(is.na(get_sapf_data(multi_mutated[[2]])[[4]])), 78) 202 | expect_equal(sum(is.na(get_sapf_data(multi_mutated[[2]])[[5]])), 78) 203 | expect_match(get_sapf_flags(multi_mutated[[1]])[[2]], 'USER_MODF', all = TRUE) 204 | expect_match(get_sapf_flags(multi_mutated[[1]])[[3]], 'USER_MODF', all = TRUE) 205 | expect_match(get_sapf_flags(multi_mutated[[1]])[[4]], 'USER_MODF', all = TRUE) 206 | expect_match(get_sapf_flags(multi_mutated[[1]])[[5]], 'USER_MODF', all = TRUE) 207 | expect_match(get_sapf_flags(multi_mutated[[2]])[[2]], 'USER_MODF', all = TRUE) 208 | expect_match(get_sapf_flags(multi_mutated[[2]])[[3]], 'USER_MODF', all = TRUE) 209 | expect_match(get_sapf_flags(multi_mutated[[2]])[[4]], 'USER_MODF', all = TRUE) 210 | expect_match(get_sapf_flags(multi_mutated[[2]])[[5]], 'USER_MODF', all = TRUE) 211 | expect_failure( 212 | expect_match(get_sapf_flags(multi_mutated[[3]])[[2]], 'USER_MODF', all = TRUE) 213 | ) 214 | expect_failure( 215 | expect_match(get_sapf_flags(multi_mutated[[3]])[[3]], 'USER_MODF', all = TRUE) 216 | ) 217 | expect_failure( 218 | expect_match(get_sapf_flags(multi_mutated[[3]])[[4]], 'USER_MODF', all = TRUE) 219 | ) 220 | expect_failure( 221 | expect_match(get_sapf_flags(multi_mutated[[3]])[[5]], 'USER_MODF', all = TRUE) 222 | ) 223 | expect_identical(multi_sfn[['AUS_CAN_ST2_MIX']], multi_mutated[['AUS_CAN_ST2_MIX']]) 224 | 225 | }) 226 | -------------------------------------------------------------------------------- /tests/testthat/test-visualizations.R: -------------------------------------------------------------------------------- 1 | data("ARG_TRE", package = 'sapfluxnetr') 2 | data("ARG_MAZ", package = 'sapfluxnetr') 3 | data("AUS_CAN_ST2_MIX", package = 'sapfluxnetr') 4 | multi_sfn <- sfn_data_multi(ARG_TRE, ARG_MAZ, AUS_CAN_ST2_MIX) 5 | 6 | test_that('sfn_plot returns the object correctly', { 7 | 8 | expect_s3_class(normal_plot <- sfn_plot(ARG_TRE), 'gg') 9 | expect_s3_class(solar_false_plot <- sfn_plot(ARG_TRE, solar = FALSE), 'gg') 10 | expect_s3_class(env_plot <- sfn_plot(ARG_TRE, type = 'env'), 'gg') 11 | expect_s3_class(ta_plot <- sfn_plot(ARG_TRE, type = 'ta'), 'gg') 12 | expect_s3_class(vpd_plot <- sfn_plot(ARG_TRE, type = 'vpd'), 'gg') 13 | expect_s3_class(sapf_vpd_plot <- sfn_plot(ARG_TRE, formula_env = ~vpd), 'gg') 14 | expect_s3_class(sapf_ext_rad_plot <- sfn_plot(ARG_TRE, formula_env = ~ext_rad), 'gg') 15 | 16 | # check the objects are plottable 17 | expect_no_error(normal_plot) 18 | expect_no_error(solar_false_plot) 19 | expect_no_error(env_plot) 20 | expect_no_error(ta_plot) 21 | expect_no_error(vpd_plot) 22 | expect_no_error(sapf_vpd_plot) 23 | expect_no_error(sapf_ext_rad_plot) 24 | 25 | }) 26 | 27 | test_that('sfn_plot returns the object correctly when multi', { 28 | 29 | multi_plot <- sfn_plot(multi_sfn) 30 | expect_true(is.list(multi_plot)) 31 | expect_s3_class(multi_plot[['ARG_TRE']], 'gg') 32 | expect_s3_class(multi_plot[['ARG_MAZ']], 'gg') 33 | expect_s3_class(multi_plot[['AUS_CAN_ST2_MIX']], 'gg') 34 | 35 | multi_plot_2 <- sfn_plot(multi_sfn, solar = FALSE) 36 | expect_true(is.list(multi_plot_2)) 37 | expect_s3_class(multi_plot_2[['ARG_TRE']], 'gg') 38 | expect_s3_class(multi_plot_2[['ARG_MAZ']], 'gg') 39 | expect_s3_class(multi_plot_2[['AUS_CAN_ST2_MIX']], 'gg') 40 | 41 | multi_plot_3 <- sfn_plot(multi_sfn, type = 'env') 42 | expect_true(is.list(multi_plot_3)) 43 | expect_s3_class(multi_plot_3[['ARG_TRE']], 'gg') 44 | expect_s3_class(multi_plot_3[['ARG_MAZ']], 'gg') 45 | expect_s3_class(multi_plot_3[['AUS_CAN_ST2_MIX']], 'gg') 46 | 47 | multi_plot_4 <- sfn_plot(multi_sfn, type = 'ta') 48 | expect_true(is.list(multi_plot_4)) 49 | expect_s3_class(multi_plot_4[['ARG_TRE']], 'gg') 50 | expect_s3_class(multi_plot_4[['ARG_MAZ']], 'gg') 51 | expect_s3_class(multi_plot_4[['AUS_CAN_ST2_MIX']], 'gg') 52 | 53 | multi_plot_5 <- sfn_plot(multi_sfn, type = 'vpd') 54 | expect_true(is.list(multi_plot_5)) 55 | expect_s3_class(multi_plot_5[['ARG_TRE']], 'gg') 56 | expect_s3_class(multi_plot_5[['ARG_MAZ']], 'gg') 57 | expect_s3_class(multi_plot_5[['AUS_CAN_ST2_MIX']], 'gg') 58 | 59 | multi_plot_6 <- sfn_plot(multi_sfn, formula_env = ~vpd) 60 | expect_true(is.list(multi_plot_6)) 61 | expect_s3_class(multi_plot_6[['ARG_TRE']], 'gg') 62 | expect_s3_class(multi_plot_6[['ARG_MAZ']], 'gg') 63 | expect_s3_class(multi_plot_6[['AUS_CAN_ST2_MIX']], 'gg') 64 | 65 | multi_plot_7 <- sfn_plot(multi_sfn, formula_env = ~ext_rad) 66 | expect_true(is.list(multi_plot_7)) 67 | expect_s3_class(multi_plot_7[['ARG_TRE']], 'gg') 68 | expect_s3_class(multi_plot_7[['ARG_MAZ']], 'gg') 69 | expect_s3_class(multi_plot_7[['AUS_CAN_ST2_MIX']], 'gg') 70 | 71 | # TODO 72 | # add tests for plottability as in the previous test 73 | 74 | }) 75 | -------------------------------------------------------------------------------- /tic.R: -------------------------------------------------------------------------------- 1 | # installs dependencies, runs R CMD check, runs covr::codecov() 2 | do_package_checks() 3 | -------------------------------------------------------------------------------- /vignettes/custom-aggregation.Rmd: -------------------------------------------------------------------------------- 1 | --- 2 | title: "Custom aggregation" 3 | author: "Victor Granda (Sapfluxnet Team)" 4 | date: "`r Sys.Date()`" 5 | output: rmarkdown::html_vignette 6 | vignette: > 7 | %\VignetteIndexEntry{Custom aggregation} 8 | %\VignetteEncoding{UTF-8} 9 | %\VignetteEngine{knitr::rmarkdown} 10 | editor_options: 11 | chunk_output_type: console 12 | --- 13 | 14 | ```{r setup, include = FALSE} 15 | knitr::opts_chunk$set( 16 | collapse = TRUE, 17 | comment = "#>" 18 | ) 19 | ``` 20 | 21 | `sapfluxnetr` package offers a very flexible but powerful API based on the 22 | `tidyverse` packages to aggregate and summarise the site/s data in the form 23 | of the `sfn_metrics` function. All the metrics family of functions (`?metrics`) 24 | make use of the `sfn_metrics` function under the hood. If you want full control 25 | to the statistics returned and aggregation periods, we recommend you to use this 26 | API. This vignette will show you how. 27 | 28 | ## Pre-fixed summarising functions 29 | 30 | 1. `daily_metrics` 31 | 1. `monthly_metrics` 32 | 1. `predawn_metrics` 33 | 1. `midday_metrics` 34 | 1. `nightly_metrics` 35 | 1. `daylight_metrics` 36 | 37 | See each function help for a detailed description and examples of use. 38 | 39 | ## Custom summarising functions 40 | 41 | `daily_metrics` and related functions return a complete set of metrics ready for 42 | use, but if you want different metrics you can supply your own summarising 43 | functions using the `.funs` argument. 44 | The correct way of specifying the functions to use is described in 45 | the `summarise_all` help (`?dplyr::summarise_all`). The recommended way is a 46 | list of formulas with the function call: 47 | 48 | ```{r custom_summ} 49 | # libraries 50 | library(sapfluxnetr) 51 | library(dplyr) 52 | 53 | ### only mean and sd at a daily scale 54 | # data 55 | data('ARG_TRE', package = 'sapfluxnetr') 56 | 57 | # summarising funs (as a list of formulas) 58 | custom_funs <- list(mean = ~ mean(., na.rm = TRUE), std_dev = ~ sd(., na.rm = TRUE)) 59 | 60 | # metrics 61 | foo_simpler_metrics <- sfn_metrics( 62 | ARG_TRE, 63 | period = '1 day', 64 | .funs = custom_funs, 65 | solar = TRUE, 66 | interval = 'general' 67 | ) 68 | 69 | foo_simpler_metrics[['sapf']] 70 | ``` 71 | 72 | > When supplying only one function to .funs, names of variables are not changed to 73 | contain the metric name at the end, as the summary function returns the 74 | same columns as the original data 75 | 76 | ## Special interest intervals 77 | 78 | You can also choose if the "special interest" intervals (predawn, midday, 79 | nighttime or daylight) are calculated or not. For example, if you are only 80 | interested in the midday interval you can use: 81 | 82 | ```{r special_intervals} 83 | foo_simpler_metrics_midday <- sfn_metrics( 84 | ARG_TRE, 85 | period = '1 day', 86 | .funs = custom_funs, 87 | solar = TRUE, 88 | interval = 'midday', int_start = 11, int_end = 13 89 | ) 90 | 91 | foo_simpler_metrics_midday[['sapf']] 92 | ``` 93 | 94 | ## Custom aggregation periods 95 | 96 | `period` argument in `sfn_metrics` is passed to `.collapse_timestamp` function, 97 | and so, it can use the same input: 98 | 99 | + "frequency period" format, where frequency is a number and period is an 100 | interval as character (i.e. "1 year", "7 days") 101 | 102 | ```{r custom_aggregation} 103 | # weekly 104 | foo_weekly <- sfn_metrics( 105 | ARG_TRE, 106 | period = '7 days', 107 | .funs = custom_funs, 108 | solar = TRUE, 109 | interval = 'general' 110 | ) 111 | 112 | foo_weekly[['env']] 113 | ``` 114 | 115 | + A custom function name (without quotes). This way you can build irregular 116 | or custom periods. 117 | This function first argument must always be the timestamp to be collapsed, and 118 | can have other arguments thet will be supplied in the dots (`...`) argument 119 | of `sfn_metrics`. Also, this function always must return a vector of timestamps 120 | of the same length as the original timestamp. 121 | For example, if you want to summarise by quarters we can use the `quarter` 122 | function from the lubridate package: 123 | 124 | ```{r custom_aggregation_2} 125 | foo_custom <- sfn_metrics( 126 | AUS_CAN_ST2_MIX, 127 | period = lubridate::quarter, 128 | .funs = custom_funs, 129 | solar = TRUE, 130 | interval = 'general', 131 | with_year = TRUE # argument for lubridate::quarter 132 | ) 133 | foo_custom['env'] 134 | ``` 135 | 136 | ## Extra parameters 137 | 138 | `sfn_metrics` has a `...` parameter intended to supply additional parameters to 139 | the internal functions used: 140 | 141 | 1. `.collapse_timestamp` accepts the following extra arguments: 142 | 143 | - `side` 144 | "start" by default in the sfn_metrics implementation 145 | 146 | 1. `dplyr::summarise_all` accepts extra arguments intended to be applied to 147 | the summarising functions provided (to **all**, so they all must have the 148 | argument provided or an error will be raised). That's the reason because we 149 | recommend to use the list way, as the arguments are specified for the 150 | individual functions. 151 | 152 | For example, if we want the TIMESTAMPs after aggregation to show the end of the 153 | period instead the beginning (default) we can do the following: 154 | 155 | ```{r extra_params} 156 | foo_simpler_metrics_end <- sfn_metrics( 157 | ARG_TRE, 158 | period = '1 day', 159 | .funs = custom_funs, 160 | solar = TRUE, 161 | interval = 'general', 162 | side = "end" 163 | ) 164 | 165 | foo_simpler_metrics_end[['sapf']] 166 | ``` 167 | 168 | If it is compared with the `foo_simpler_metrics` calculated before, now the 169 | period is identified in the TIMESTAMP by the ending of the period (daily in this 170 | case). 171 | 172 | > When supplying custom functions as "period" argument, the default coverage 173 | statistic is not reliable as there is no way of knowing beforehand the 174 | period/s in minutes. 175 | 176 | ## Temporary columns helpers 177 | 178 | The internal aggregation process in `sfn_metrics` generates some transitory 179 | columns which can be used in the summarising functions: 180 | 181 | ### `TIMESTAMP_coll` 182 | 183 | When aggregating by the declared period (i.e. `"daily"`), the TIMESTAMP column 184 | collapses to the period start/end value (meaning thet all the TIMESTAMP values 185 | for the same day becomes identical). 186 | This makes impossible to use any summarise functions thet obtain the 187 | time of the day at which one event happens (i.e. time of the day at which the 188 | maximum sap flow occurs) because all TIMESTAMP values are identical. 189 | For thet kind of summarising functions, a transitory column called 190 | `TIMESTAMP_coll` is created. So in this case we can create a function thet 191 | takes de variable values for the day, the TIMESTAMP_coll values for the day 192 | and return the TIMESTAMP at which the max sap flow occurs and use it with 193 | `sfn_metrics`: 194 | 195 | ```{r timestamp_coll} 196 | max_time <- function(x, time) { 197 | 198 | # x: vector of values for a day 199 | # time: TIMESTAMP for the day 200 | 201 | # if all the values in x are NAs (a daily summmarise of no measures day for 202 | # example) this will return a length 0 POSIXct vector, which will crash 203 | # dplyr summarise step. So, check if all NA and if true return NA as POSIXct 204 | if(all(is.na(x))) { 205 | return(as.POSIXct(NA, tz = attr(time, 'tz'), origin = lubridate::origin)) 206 | } else { 207 | time[which.max(x)] 208 | } 209 | } 210 | 211 | custom_funs <- list(max = ~ max(., na.rm = TRUE), ~ max_time(., TIMESTAMP_coll)) 212 | 213 | max_time_metrics <- sfn_metrics( 214 | ARG_TRE, 215 | period = '1 day', 216 | .funs = custom_funs, 217 | solar = TRUE, 218 | interval = 'general' 219 | ) 220 | 221 | max_time_metrics[['sapf']] 222 | ``` 223 | 224 | ## Sub-daily aggregations 225 | 226 | `sfn_metrics` allows to perform sub-daily aggregations, by means of the `period` 227 | parameter. Sapfluxnet datasets have sub-daily data usually in the range of 30 228 | minutes to 2 hours. This means thet data can be aggregated in periods above 2 229 | hours. We can aggregate to a 3 hours period easily: 230 | 231 | ```{r subdaily_periods} 232 | custom_funs <- list(max = ~ max(., na.rm = TRUE)) 233 | 234 | three_hours_agg <- sfn_metrics( 235 | ARG_TRE, 236 | period = '3 hours', 237 | .funs = custom_funs, 238 | solar = TRUE, 239 | interval = 'general' 240 | ) 241 | 242 | three_hours_agg[['sapf']] 243 | ``` 244 | 245 | -------------------------------------------------------------------------------- /vignettes/data-flags.Rmd: -------------------------------------------------------------------------------- 1 | --- 2 | title: "Data Flags" 3 | author: "Victor Granda (Sapfluxnet Team)" 4 | date: "`r Sys.Date()`" 5 | output: rmarkdown::html_vignette 6 | vignette: > 7 | %\VignetteIndexEntry{Data Flags} 8 | %\VignetteEngine{knitr::rmarkdown} 9 | %\VignetteEncoding{UTF-8} 10 | --- 11 | 12 | ```{r setup, include = FALSE} 13 | knitr::opts_chunk$set( 14 | collapse = TRUE, 15 | comment = "#>" 16 | ) 17 | ``` 18 | 19 | Data flags indicate comments on individual data points raised in the quality 20 | control assessment of site data. They are useful to understand the original 21 | data and to track analysis problems to their origins. 22 | 23 | Possible values for flags when data comes from Sapfluxnet project are as follow: 24 | 25 | + **"CALCULATED"** Indicates thet the value was originally missing and was 26 | calculated in the quality check step. 27 | 28 | + **"MANUAL_REMOVED"** Indicates thet the value was manually removed in the 29 | quality control step, due to curator decision. 30 | 31 | + **"NA_ADDED"** Indicates thet the value was originally non-existent and it 32 | was created and filled with NA. Usually the result of equalising the sap 33 | flow and environmental TIMESTAMPS. 34 | 35 | + **"NA_PRESENT"** Indicates thet the value was originally an NA 36 | 37 | + **"OUT_REMOVED"** Indicates thet the value was clearly an outlier and was 38 | removed and substituted by NA 39 | 40 | + **"OUT_WARN"** Indicates thet the value could be an outlier based on hampel 41 | filter algorithm. Not removed nor substituted 42 | 43 | + **"RANGE_REMOVED"** Indicates values thet were clearly out of the range of 44 | variable. Removed and converted to NA 45 | 46 | + **"RANGE_WARN"** Indicates that the value could be out of "usual" maximum 47 | value for the variable. Not removed. 48 | 49 | + **"USER_MODF"** Modified by the user. Added when sfn_mutate or sfn_mutate_at 50 | functions are used. 51 | 52 | Data points can have more than one flag. In that case flags are separated by 53 | `"; "` (i.e. `"OUT_WARN; OUT_REMOVED"`) 54 | -------------------------------------------------------------------------------- /vignettes/memory-and-parallelization.Rmd: -------------------------------------------------------------------------------- 1 | --- 2 | title: "Memory and Parallelization" 3 | author: "Victor Granda (Sapfluxnet Team)" 4 | date: "`r Sys.Date()`" 5 | output: rmarkdown::html_vignette 6 | vignette: > 7 | %\VignetteIndexEntry{Memory and Parallelization} 8 | %\VignetteEngine{knitr::rmarkdown} 9 | %\VignetteEncoding{UTF-8} 10 | --- 11 | 12 | ```{r setup, include = FALSE} 13 | knitr::opts_chunk$set( 14 | collapse = TRUE, 15 | comment = "#>" 16 | ) 17 | ``` 18 | 19 | ## Memory 20 | 21 | In order to be able to work with the whole database at the *sapwood* or *plant* 22 | level it is recommended at least $16GB$ of RAM memory. This is because loading 23 | all data objects already consumes $4GB$ and any operation like aggregation or 24 | metric calculation results in extra memory needed: 25 | 26 | ```{r memory_all, eval=FALSE} 27 | library(sapfluxnetr) 28 | 29 | # This will need at least 5GB of memory during the process 30 | folder <- 'RData/plant' 31 | sfn_metadata <- read_sfn_metadata(folder) 32 | 33 | daily_results <- sfn_sites_in_folder(folder) %>% 34 | filter_sites_by_md( 35 | si_biome %in% c("Temperate forest", 'Woodland/Shrubland'), 36 | sites = sites, metadata = sfn_metadata 37 | ) %>% 38 | read_sfn_data(folder) %>% 39 | daily_metrics(tidy = TRUE, metadata = sfn_metadata) 40 | 41 | # Important to save, this way you will have access to the object in the future 42 | save(daily_results, file = 'daily_results.RData') 43 | ``` 44 | 45 | To circumvent this in less powerful systems, we recommend to work in small 46 | subsets of sites (25-30) and join the tidy results afterwards: 47 | 48 | ```{r memory_steps, eval = FALSE} 49 | library(sapfluxnetr) 50 | 51 | folder <- 'RData/plant' 52 | metadata <- read_sfn_metadata(folder) 53 | sites <- sfn_sites_in_folder(folder) %>% 54 | filter_sites_by_md( 55 | si_biome %in% c("Temperate forest", 'Woodland/Shrubland'), 56 | sites = sites, metadata = sfn_metadata 57 | ) 58 | 59 | daily_results_1 <- read_sfn_data(sites[1:30], folder) %>% 60 | daily_metrics(tidy = TRUE, metadata = sfn_metadata) 61 | daily_results_2 <- read_sfn_data(sites[31:60], folder) %>% 62 | daily_metrics(tidy = TRUE, metadata = sfn_metadata) 63 | daily_results_3 <- read_sfn_data(sites[61:90], folder) %>% 64 | daily_metrics(tidy = TRUE, metadata = sfn_metadata) 65 | daily_results_4 <- read_sfn_data(sites[91:110], folder) %>% 66 | daily_metrics(tidy = TRUE, metadata = sfn_metadata) 67 | 68 | daily_results_steps <- bind_rows( 69 | daily_results_1, daily_results_2, 70 | daily_results_3, daily_results_4 71 | ) 72 | 73 | rm(daily_results_1, daily_results_2, daily_results_3, daily_results_4) 74 | save(daily_results_steps, file = 'daily_results_steps.RData') 75 | ``` 76 | 77 | ## Parallelization 78 | 79 | `sapfluxnetr` includes the capability to parallelize the metrics calculation 80 | when performed on a `sfn_data_multi` object. This is made thenks to the 81 | [furrr](https://github.com/DavisVaughan/furrr) package, which uses the 82 | [future](https://github.com/HenrikBengtsson/future) package behind the scenes. 83 | By default, the code will run in a sequential process, which is the usual way 84 | the R code runs. But setting the `future::plan` to `multicore` (in Linux), 85 | `multisession` (in Windows) or `multiprocess` (automatically choose between the 86 | previous plans depending on the system) will run the code in parallel, dividing 87 | the sites between the available cores. 88 | 89 | > Be advised, parallelization usually means more RAM used, so in systems 90 | with less then 16GB maybe is not a good idea. 91 | Also, the time benefits start to show when analysing 10 sites or more. 92 | 93 | ```{r parallelizations, eval = FALSE} 94 | # loading future package 95 | library(future) 96 | 97 | # setting the plan 98 | plan('multiprocess') 99 | 100 | # metrics!! 101 | daily_results_parallel <- sfn_sites_in_folder(folder) %>% 102 | filter_sites_by_md( 103 | si_biome %in% c("Temperate forest", 'Woodland/Shrubland'), 104 | sites = sites, metadata = sfn_metadata 105 | ) %>% 106 | read_sfn_data(folder) %>% 107 | daily_metrics(tidy = TRUE, metadata = sfn_metadata) 108 | 109 | # Important to save, this way you will have access to the object in the future 110 | save(daily_results_parallel, file = 'daily_results_parallel.RData') 111 | ``` 112 | 113 | 114 | ### Memory limit 115 | 116 | When using `furrr`, even in the `sequential` plan, the `future` package sets 117 | a limit of $500MB$ for each core. With sapfluxnet data this limit is easily 118 | exceeded, causing an error. To avoid this we may want to set the 119 | `future.globals.maxSize` limit to a higher value ($1GB$ for example, but the 120 | limit wanted really depend on the plan and the number of sites): 121 | 122 | ```{r max_limit, eval = FALSE} 123 | # future library 124 | library(future) 125 | 126 | # plan sequential, not really needed, as it is the default, but for the sake of 127 | # clarity 128 | plant('sequential') 129 | 130 | # up the limit to 1GB, this in bytes is 1014*1024^2 131 | options('future.globals.maxSize' = 1014*1024^2) 132 | 133 | # do the metrics 134 | daily_results_limit <- sfn_sites_in_folder(folder) %>% 135 | filter_sites_by_md( 136 | si_biome %in% c("Temperate forest", 'Woodland/Shrubland'), 137 | sites = sites, metadata = sfn_metadata 138 | ) %>% 139 | read_sfn_data(folder) %>% 140 | daily_metrics(tidy = TRUE, metadata = sfn_metadata) 141 | 142 | # Important to save, this way you will have access to the object in the future 143 | save(daily_results_limit, file = 'daily_results_limit.RData') 144 | ``` 145 | 146 | 147 | -------------------------------------------------------------------------------- /vignettes/metadata-and-data-units.Rmd: -------------------------------------------------------------------------------- 1 | --- 2 | title: "Metadata and Data units" 3 | author: "Victor Granda (Sapfluxnet Team)" 4 | date: "`r Sys.Date()`" 5 | output: rmarkdown::html_vignette 6 | vignette: > 7 | %\VignetteIndexEntry{Metadata and Data units} 8 | %\VignetteEncoding{UTF-8} 9 | %\VignetteEngine{knitr::rmarkdown} 10 | editor_options: 11 | chunk_output_type: console 12 | --- 13 | 14 | ```{r setup, include = FALSE} 15 | knitr::opts_chunk$set( 16 | collapse = TRUE, 17 | comment = "#>" 18 | ) 19 | ``` 20 | 21 | ## Metadata 22 | 23 | Metadata numeric variables come in different units depending on the variable. 24 | One easy way to check for a variable units is to use the `describe_md_variable` 25 | function: 26 | 27 | ```{r describe_md_variable} 28 | library(sapfluxnetr) 29 | describe_md_variable('si_elev') 30 | describe_md_variable('st_age') 31 | ``` 32 | 33 | As it can be seen, site elevation is in meters and stand age is in years. 34 | 35 | Nevertheless, and for the sake of completion, here you can find a complete list 36 | of the metadata variables and their units: 37 | 38 | ```{r md_vars_table, echo=FALSE, results='asis'} 39 | suppressMessages(library(dplyr)) 40 | library(magrittr) 41 | site_md_table <- sapfluxnetr:::.metadata_architecture() %>% 42 | magrittr::extract2(., 'site_md') %>% 43 | purrr::map_dfr(magrittr::extract, c('description', 'type', 'units')) %>% 44 | dplyr::mutate( 45 | variable = sapfluxnetr:::.metadata_architecture() %>% 46 | magrittr::extract2(., 'site_md') %>% 47 | names() 48 | ) %>% 49 | select(variable, everything()) 50 | 51 | stand_md_table <- sapfluxnetr:::.metadata_architecture() %>% 52 | magrittr::extract2(., 'stand_md') %>% 53 | purrr::map_dfr(magrittr::extract, c('description', 'type', 'units')) %>% 54 | dplyr::mutate( 55 | variable = sapfluxnetr:::.metadata_architecture() %>% 56 | magrittr::extract2(., 'stand_md') %>% 57 | names() 58 | ) %>% 59 | select(variable, everything()) 60 | 61 | species_md_table <- sapfluxnetr:::.metadata_architecture() %>% 62 | magrittr::extract2(., 'species_md') %>% 63 | purrr::map_dfr(magrittr::extract, c('description', 'type', 'units')) %>% 64 | dplyr::mutate( 65 | variable = sapfluxnetr:::.metadata_architecture() %>% 66 | magrittr::extract2(., 'species_md') %>% 67 | names() 68 | ) %>% 69 | select(variable, everything()) 70 | 71 | plant_md_table <- sapfluxnetr:::.metadata_architecture() %>% 72 | magrittr::extract2(., 'plant_md') %>% 73 | purrr::map_dfr(magrittr::extract, c('description', 'type', 'units')) %>% 74 | dplyr::mutate( 75 | variable = sapfluxnetr:::.metadata_architecture() %>% 76 | magrittr::extract2(., 'plant_md') %>% 77 | names() 78 | ) %>% 79 | select(variable, everything()) 80 | 81 | env_md_table <- sapfluxnetr:::.metadata_architecture() %>% 82 | magrittr::extract2(., 'env_md') %>% 83 | purrr::map_dfr(magrittr::extract, c('description', 'type', 'units')) %>% 84 | dplyr::mutate( 85 | variable = sapfluxnetr:::.metadata_architecture() %>% 86 | magrittr::extract2(., 'env_md') %>% 87 | names() 88 | ) %>% 89 | select(variable, everything()) 90 | 91 | bind_rows( 92 | site_md_table, stand_md_table, species_md_table, plant_md_table, env_md_table 93 | ) %>% 94 | xtable::xtable(align = c('lcccc')) %>% 95 | print(type = 'html') 96 | ``` 97 | 98 | ## Data 99 | 100 | ### Sap flow units 101 | 102 | Sap flow units depends on the database level chosen: 103 | 104 | $$Plant:~\frac{cm³}{h}$$ 105 | $$Sapwood:~\frac{cm³}{cm²_{sa}·h}$$ 106 | $$Leaf:~\frac{cm³}{cm²_{la}·h}$$ 107 | 108 | ### Environmental variables 109 | 110 | Environmental variables come in the following units: 111 | 112 | ```{r environmetal_vars_table, echo=FALSE, results='asis'} 113 | tibble::tibble( 114 | Variable = c( 115 | 'env_ta', 'env_rh', 'env_vpd', 'env_sw_in', 'env_ppfd', 'env_netrad', 116 | 'env_ws', 'env_precip', 'env_swc_shallow', 'env_swc_deep' 117 | ), 118 | Description = c( 119 | 'Air temperature', 'Air relative humidity', 120 | 'Vapour pressure deficit', 'Shortwave incoming radiation', 121 | 'Incoming photosynthetic photon flux density', 122 | 'Net radiation', 'Wind speed', 'Precipitation', 123 | 'Shallow soil water content', 124 | 'Deep soil water content' 125 | ), 126 | Units = c( 127 | 'ºC', '%', 'kPa', 'W m-2', 'micromols m-2 s-1', 'W m-2', 'm s-1', 'mm timestep-1', 128 | 'cm3 cm-3', 'cm3 cm-3' 129 | ) 130 | ) %>% 131 | xtable::xtable(align = c('lccc')) %>% 132 | print(type = 'html') 133 | ``` 134 | 135 | ## Timestamps 136 | 137 | ### TIMESTAMP 138 | 139 | `TIMESTAMP` variable comes as provided by the contributors and timezone is 140 | applied per the site metadata description: 141 | 142 | ```{r TIMESTAMP_var} 143 | library(dplyr) 144 | library(lubridate) 145 | 146 | # timezone provided by contributor 147 | get_env_md(ARG_TRE) %>% pull(env_time_zone) 148 | 149 | # timezone in the TIMESTAMP 150 | get_timestamp(ARG_TRE) %>% tz() 151 | ``` 152 | 153 | As you can see, the final timezone is in GMT format. 154 | 155 | ### Solar TIMESTAMP 156 | 157 | When inspecting the solar `TIMESTAMP` variable, timezone declared is UTC: 158 | 159 | ```{r solar_TIMESTAMP} 160 | get_solar_timestamp(ARG_TRE) %>% tz() 161 | ``` 162 | 163 | This is so because solar timestamp is only referred to the sun position in the 164 | sky, rendering the timezone useless in this case. So UTC was chosen as timezone 165 | to be able to join and compare global data. 166 | -------------------------------------------------------------------------------- /vignettes/resources/ARG_MAZ.RData: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sapfluxnet/sapfluxnetr/a09141f653f540728ea3474d975b63680ffc463f/vignettes/resources/ARG_MAZ.RData -------------------------------------------------------------------------------- /vignettes/resources/ARG_TRE.RData: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sapfluxnet/sapfluxnetr/a09141f653f540728ea3474d975b63680ffc463f/vignettes/resources/ARG_TRE.RData -------------------------------------------------------------------------------- /vignettes/resources/AUS_CAN_ST2_MIX.RData: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sapfluxnet/sapfluxnetr/a09141f653f540728ea3474d975b63680ffc463f/vignettes/resources/AUS_CAN_ST2_MIX.RData -------------------------------------------------------------------------------- /vignettes/resources/schematics.odg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sapfluxnet/sapfluxnetr/a09141f653f540728ea3474d975b63680ffc463f/vignettes/resources/schematics.odg -------------------------------------------------------------------------------- /vignettes/resources/schematics.svg.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sapfluxnet/sapfluxnetr/a09141f653f540728ea3474d975b63680ffc463f/vignettes/resources/schematics.svg.png -------------------------------------------------------------------------------- /vignettes/sfn-data-classes.Rmd: -------------------------------------------------------------------------------- 1 | --- 2 | title: "sfn_data classes" 3 | author: "Victor Granda (Sapfluxnet Team)" 4 | date: "`r Sys.Date()`" 5 | output: rmarkdown::html_vignette 6 | vignette: > 7 | %\VignetteIndexEntry{sfn_data classes} 8 | %\VignetteEncoding{UTF-8} 9 | %\VignetteEngine{knitr::rmarkdown} 10 | editor_options: 11 | chunk_output_type: console 12 | --- 13 | 14 | ```{r setup, include = FALSE} 15 | knitr::opts_chunk$set( 16 | collapse = TRUE, 17 | comment = "#>" 18 | ) 19 | ``` 20 | 21 | # `sfn_data` 22 | 23 | `sfn_data` is an S4 class designed for store and interact with sap flow data 24 | at individual plant level (not raw data), primarily from Sapfluxnet project 25 | sites data and metadata. 26 | 27 | ## S4 Slots 28 | 29 | `sfn_data` class has twelve different slots: 30 | 31 | 1. **sapf_data**: Tibble containing the sap flow data, each column representing 32 | an individual tree, **without** any TIMESTAMP variable. 33 | 34 | 2. **env_data**: Tibble containing the environmental data, each column an 35 | environmental variable, **without** any TIMESTAMP variable. It must have 36 | the same `nrow` thet `sapf_data`, in order to be able to combine both in 37 | further analyses or aggregations. 38 | 39 | 3. **sapf_flags**: Tibble with the same dimensions as `sapf_data`, containing 40 | the flags (special remarks indicating possible outliers or any annotation 41 | of interest) for each observation in `sapf_data`. 42 | 43 | 4. **env_flags**: Tibble with the same dimensions as `env_data`, containing 44 | the flags for each observation in `env_data`. 45 | 46 | 5. **si_code**: Character vector of length 1 with the site code. Useful for 47 | further analyses or aggregations in order to identify the site when working 48 | with more then one. 49 | 50 | 6. **timestamp**: POSIXct vector of length equal to `nrow(sapf_data)` with the 51 | timestamp values. 52 | 53 | 7. **solar_timestamp**: POSIXct vector of length equal to `nrow(sapf_data)` 54 | with the apparent solar timestamp. 55 | 56 | 8. **site_md**: Tibble with the site metadata. See `sfn_vars_to_filter()` for 57 | a list of possible metadata variables. This variables are not mandatory, 58 | and new ones can be added. 59 | 60 | 9. **stand_md**: Tibble with the stand metadata. See `sfn_vars_to_filter()` 61 | for a list of possible metadata variables. This variables are not 62 | mandatory, and new ones can be added. 63 | 64 | 10. **species_md**: Tibble with the species metadata. See 65 | `sfn_vars_to_filter()` for a list of possible metadata variables. This 66 | variables are not mandatory, and new ones can be added. 67 | 68 | 11. **plant_md**: Tibble with the plant metadata. See `sfn_vars_to_filter()` 69 | for a list of possible metadata variables. This variables are not 70 | mandatory, and new ones can be added. 71 | 72 | 12. **env_md**: Tibble with the environmental metadata. See 73 | `sfn_vars_to_filter()` for a list of possible metadata variables. This 74 | variables are not mandatory, and new ones can be added. 75 | 76 | ### `sfn_data` design 77 | 78 | The schematics of the class are summarised in Fig 1. 79 | 80 | ![sfn_data schematics](resources/schematics.svg.png) 81 | 82 | This design have some characteristics: 83 | 84 | + **Dimensions**: Dimensions must comply: 85 | 86 | `nrow(sapf_data) == nrow(env_data) == nrow(sapf_flags) == nrow(env_flags) == length(timestamp) == length(solar_timestamp)` 87 | 88 | `ncol(sapf_data) == ncol(sapf_flags)` 89 | 90 | `ncol(env_data) == ncol(env_flags)` 91 | 92 | In the case of differences in the dimensions between environmental and 93 | sap flow data, NAs must be added in the corresponding places when equalising 94 | both TIMESTAMPs (i.e. if env data is longer then sapf data, rows are added 95 | to the later with NAs to make them equal, and flags ("NA_ADDED") are raised 96 | to indicate the adding). 97 | 98 | + **si_code slot**: This slot indicates the site. This is useful for 99 | identifying the site in the metrics functions results. 100 | 101 | + **Compartmentalization**: `timestamp` and `solar_timestamp` are isolated 102 | from data (sapf and env) in their own slot. This made easier subsetting the 103 | object and open the possibility of working with the timestamps only. 104 | 105 | + **Flags**: Two slots are used for storing data flags. As the flag slots 106 | have the same dimensions as the corresponding dataset slot, selection of 107 | flagged data is straightforward: 108 | 109 | `sapf_data[flag_data == "flag", ]` 110 | 111 | 112 | ## Methods 113 | 114 | Some methods are included in the class: 115 | 116 | + `show`: calling a sfn_data object shows info about it 117 | 118 | ```{r show} 119 | library(sapfluxnetr) 120 | data('ARG_TRE', package = 'sapfluxnetr') 121 | ARG_TRE 122 | ``` 123 | 124 | + `get methods`: methods to get any slot outside the object. In the case 125 | of sapf and env data, TIMESTAMP is added (based on the `solar` argument) in 126 | order to obtain fully functional datasets. See `?sfn_get_methods` for more 127 | details. 128 | 129 | ```{r get_methods} 130 | get_sapf_data(ARG_TRE, solar = FALSE) 131 | get_sapf_data(ARG_TRE, solar = TRUE) 132 | get_env_data(ARG_TRE) # solar default is FALSE 133 | get_sapf_flags(ARG_TRE) # solar default is FALSE 134 | get_env_flags(ARG_TRE) # solar default is FALSE 135 | get_si_code(ARG_TRE) 136 | get_timestamp(ARG_TRE)[1:10] 137 | get_solar_timestamp(ARG_TRE)[1:10] 138 | get_site_md(ARG_TRE) 139 | get_stand_md(ARG_TRE) 140 | get_species_md(ARG_TRE) 141 | get_plant_md(ARG_TRE) 142 | get_env_md(ARG_TRE) 143 | ``` 144 | 145 | + `assignation`: methods for `"<-"` are implemented, allowing transformation 146 | of the slots. This is used internally in some functions but is not 147 | recommended except for updating metadata slots. In data slots this 148 | changes are not reflected in the flags, so the reproducibility and 149 | traceability will be lost if used without care. 150 | See `?sfn_replacement_methods` for more details. 151 | 152 | ```{r assignation} 153 | # extraction and modification 154 | foo_site_md <- get_site_md(ARG_TRE) 155 | foo_site_md[['si_biome']] 156 | foo_site_md[['si_biome']] <- 'Temperate forest' 157 | # assignation 158 | get_site_md(ARG_TRE) <- foo_site_md 159 | # check it worked 160 | get_site_md(ARG_TRE)[['si_biome']] 161 | ``` 162 | 163 | + `validation`: a validation method is implemented in order to avoid creation 164 | of invalid sfn_data objects (i.e objects with different data dimensions, 165 | objects without metadata...) 166 | 167 | ```{r validation, error=TRUE, purl=FALSE, collapse=FALSE} 168 | # get sap flow data 169 | foo_bad_sapf <- get_sapf_data(ARG_TRE) 170 | # pull a row, now it has diferent dimensions then 171 | foo_bad_sapf <- foo_bad_sapf[-1,] 172 | # try to assign the incorrect data fails 173 | get_sapf_data(ARG_TRE) <- foo_bad_sapf[,-1] # ERROR 174 | # try to build a new object also fails 175 | sfn_data( 176 | sapf_data = foo_bad_sapf[,-1], # remember to remove timestamp column 177 | env_data = get_env_data(ARG_TRE)[,-1], 178 | sapf_flags = get_env_flags(ARG_TRE)[,-1], 179 | env_flags = get_env_flags(ARG_TRE)[,-1], 180 | si_code = get_si_code(ARG_TRE), 181 | timestamp = get_timestamp(ARG_TRE), 182 | solar_timestamp = get_solar_timestamp(ARG_TRE), 183 | site_md = get_site_md(ARG_TRE), 184 | stand_md = get_stand_md(ARG_TRE), 185 | species_md = get_species_md(ARG_TRE), 186 | plant_md = get_plant_md(ARG_TRE), 187 | env_md = get_env_md(ARG_TRE) 188 | ) 189 | ``` 190 | 191 | ## Utilities 192 | 193 | `sapfluxnetr` package offers some utilities to visualize and work with sfn_data 194 | objects: 195 | 196 | ### `sfn_plot` 197 | 198 | This function allows to plot `sfn_data` objects. See `?sfn_plot` for more 199 | details. 200 | 201 | ```{r sfn_plot, fig.width=6} 202 | library(ggplot2) 203 | 204 | sfn_plot(ARG_TRE, type = 'env') + 205 | facet_wrap(~ Variable, ncol = 3, scales = 'free_y') + 206 | theme(legend.position = 'none') 207 | 208 | sfn_plot(ARG_TRE, formula_env = ~ vpd) + 209 | theme(legend.position = 'none') 210 | ``` 211 | 212 | ### `sfn_filter` 213 | 214 | This function emulates `filter` function from `dplyr` package for `sfn_data` 215 | objects. Useful to filter by some specific timestamp. Be advised, using this 216 | function to filter by sap flow or environmental variables can create TIMESTAMP 217 | gaps. See `sfn_filter` for more details. 218 | 219 | ```{r sfn_filter} 220 | library(lubridate) 221 | library(dplyr) 222 | 223 | # get only the values for november 224 | sfn_filter(ARG_TRE, month(TIMESTAMP) == 11) 225 | ``` 226 | 227 | ### `sfn_mutate` 228 | 229 | This function allows mutation of data variables inside the `sfn_data` object. 230 | Useful when you need to transform a variable to another units or similar. A flag 231 | ('USER_MODF') will be added to all values in the mutated variable. See 232 | `sfn_mutate` for more details. 233 | 234 | > At this moment, mutate does not allows creating new variables, only mutate 235 | existing variables 236 | 237 | ```{r sfn_mutate} 238 | # transform ws from m/s to km/h 239 | foo_mutated <- sfn_mutate(ARG_TRE, ws = ws * 3600/1000) 240 | get_env_data(foo_mutated)[['ws']][1:10] 241 | ``` 242 | 243 | ### `sfn_mutate_at` 244 | 245 | This function mutates all variables declared with the function provided. Useful 246 | when you need to conditionally transform the data, i.e. converting to NA sap flow 247 | values when an environmental variable exceeds some threshold. See 248 | `sfn_mutate_at` for more details. 249 | 250 | ```{r sfn_mutate_at} 251 | foo_mutated_2 <- sfn_mutate_at( 252 | ARG_TRE, 253 | vars(one_of(names(get_sapf_data(ARG_TRE)[,-1]))), 254 | list(~ case_when( 255 | ws > 25 ~ NA_real_, 256 | TRUE ~ . 257 | )) 258 | ) 259 | 260 | # see the difference between ARG_TRE and foo_mutated_2 261 | get_sapf_data(ARG_TRE) 262 | get_sapf_data(foo_mutated_2) 263 | ``` 264 | 265 | ### `*_metrics` functions 266 | 267 | Family of functions to aggregate and summarise the site data. See `?metrics` for 268 | more details. 269 | 270 | ```{r metrics} 271 | foo_daily <- daily_metrics(ARG_TRE) 272 | foo_daily[['sapf']][['sapf_gen']] 273 | ``` 274 | 275 | For full control of metrics and custom aggregations see 276 | `vignette('custom-aggregation', package = 'sapfluxnetr')` 277 | 278 | # `sfn_data_multi` 279 | 280 | `sfn_data_multi` is an S4 class designed to store multiple `sfn_data` objects. 281 | It inherits from list so, in a nutshell, `sfn_data_multi` is a list of 282 | `sfn_data` objects. 283 | 284 | ## Methods 285 | 286 | `sfn_data_multi` has the following methods declared. 287 | 288 | + `show`: it shows the number, codes and combined timestamp span of sites in the 289 | multi object. 290 | 291 | ```{r show_multi} 292 | # creating a sfn_data_multi object 293 | data(ARG_MAZ, package = 'sapfluxnetr') 294 | data(AUS_CAN_ST2_MIX, package = 'sapfluxnetr') 295 | multi_sfn <- sfn_data_multi(ARG_TRE, ARG_MAZ, AUS_CAN_ST2_MIX) 296 | 297 | # show method 298 | multi_sfn 299 | ``` 300 | 301 | + `get` methods: they work the same as in the `sfn_data` objects, 302 | except they return a list, with the corresponding data for the sites in the 303 | `sfn_data_multi` object as elements. 304 | 305 | ```{r get_multi} 306 | # get sap flow data 307 | get_sapf_data(multi_sfn) 308 | # get plant metadata 309 | get_plant_md(multi_sfn) 310 | # with metadata, we can collapse 311 | get_plant_md(multi_sfn, collapse = TRUE) 312 | ``` 313 | 314 | 315 | ## Utilities 316 | 317 | All the utilities thet exists for `sfn_data` work for `sfn_data_multi` objects, 318 | executing the function for all the sites contained in the `sfn_data_multi` 319 | object: 320 | 321 | ### `sfn_plot` 322 | 323 | ```{r plot_multi, fig.show='hold', fig.width=3.4} 324 | multi_plot <- sfn_plot(multi_sfn, formula = ~ vpd) 325 | multi_plot[['ARG_TRE']] + theme(legend.position = 'none') 326 | multi_plot[['AUS_CAN_ST2_MIX']] + theme(legend.position = 'none') 327 | ``` 328 | 329 | 330 | ### `sfn_filter` 331 | 332 | ```{r sfn_filter_multi} 333 | multi_filtered <- sfn_filter(multi_sfn, month(TIMESTAMP) == 11) 334 | get_timestamp(multi_filtered[['AUS_CAN_ST2_MIX']])[1:10] 335 | ``` 336 | 337 | ### `sfn_mutate` 338 | 339 | ```{r sfn_mutate_multi} 340 | multi_mutated <- sfn_mutate(multi_sfn, ws = ws * 3600/1000) 341 | get_env_data(multi_mutated[['AUS_CAN_ST2_MIX']])[['ws']][1:10] 342 | ``` 343 | 344 | ### `sfn_mutate_at` 345 | 346 | ```{r sfn_mutate_at_multi} 347 | vars_to_not_mutate <- c( 348 | "TIMESTAMP", "ta", "rh", "vpd", "sw_in", "ws", 349 | "precip", "swc_shallow", "ppfd_in", "ext_rad" 350 | ) 351 | 352 | multi_mutated_2 <- sfn_mutate_at( 353 | multi_sfn, 354 | vars(-one_of(vars_to_not_mutate)), 355 | list(~ case_when( 356 | ws > 25 ~ NA_real_, 357 | TRUE ~ . 358 | )) 359 | ) 360 | 361 | multi_mutated_2[['ARG_TRE']] 362 | ``` 363 | 364 | ### `*_metrics` 365 | 366 | ```{r metrics_multi} 367 | multi_metrics <- daily_metrics(multi_sfn) 368 | multi_metrics[['ARG_TRE']][['sapf']] 369 | ``` 370 | --------------------------------------------------------------------------------