From fa99dfcf8f5415c6e4d54311482af2881cc06317 Mon Sep 17 00:00:00 2001 From: Abhinav Pandey Date: Mon, 24 Jun 2024 08:17:56 +0530 Subject: [PATCH 01/16] Combine multiple DB calls into a singular call This is an example demonstration of how we may proceed with Refactor `convert_input.R` to Optimise Workflow #3307 Signed-off-by: Abhinav Pandey --- modules/data.atmosphere/R/read.register.R | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/modules/data.atmosphere/R/read.register.R b/modules/data.atmosphere/R/read.register.R index b7a7db708a0..4e809e84dd6 100644 --- a/modules/data.atmosphere/R/read.register.R +++ b/modules/data.atmosphere/R/read.register.R @@ -35,10 +35,14 @@ read.register <- function(register.xml, con) { } else if ((!is.null(register$format$id) & is.null(register$format$name)) | (!is.null(register$format$id) & is.null(register$format$mimetype))) { - register$format$name <- PEcAn.DB::db.query( - paste("SELECT name from formats where id = ", register$format$id), con)[[1]] - register$format$mimetype <- PEcAn.DB::db.query( - paste("SELECT mime_type from formats where id = ", register$format$id), con)[[1]] + # get name and mime_type from formats table in a singular dataframe + format.info <- PEcAn.DB::db.query( + paste("SELECT name, mime_type FROM formats WHERE id = ", register$format$id), con + ) + + # Assign the values from the data frame to the respective columns in register$format + register$format$name <- format.info$name + register$format$mimetype <- format.info$mime_type } else if (is.null(register$format$id) & !is.null(register$format$name) & !is.null(register$format$mimetype)) { register$format$id <- PEcAn.DB::db.query( paste0("SELECT id from formats where name = '", register$format$name, From 08887f4578b560b35bc8d420333471d342022aab Mon Sep 17 00:00:00 2001 From: Abhinav Pandey Date: Tue, 25 Jun 2024 00:03:19 +0530 Subject: [PATCH 02/16] Retrieve format name and mimetype from the database in read.register.R Signed-off-by: Abhinav Pandey --- modules/data.atmosphere/R/read.register.R | 9 +++------ 1 file changed, 3 insertions(+), 6 deletions(-) diff --git a/modules/data.atmosphere/R/read.register.R b/modules/data.atmosphere/R/read.register.R index 4e809e84dd6..dbdadf636a9 100644 --- a/modules/data.atmosphere/R/read.register.R +++ b/modules/data.atmosphere/R/read.register.R @@ -35,14 +35,11 @@ read.register <- function(register.xml, con) { } else if ((!is.null(register$format$id) & is.null(register$format$name)) | (!is.null(register$format$id) & is.null(register$format$mimetype))) { - # get name and mime_type from formats table in a singular dataframe - format.info <- PEcAn.DB::db.query( - paste("SELECT name, mime_type FROM formats WHERE id = ", register$format$id), con + # Retrieve format name and mimetype from the database + register$format <- PEcAn.DB::db.query( + paste("SELECT name, mime_type AS mimetype FROM formats WHERE id = ", register$format$id), con ) - # Assign the values from the data frame to the respective columns in register$format - register$format$name <- format.info$name - register$format$mimetype <- format.info$mime_type } else if (is.null(register$format$id) & !is.null(register$format$name) & !is.null(register$format$mimetype)) { register$format$id <- PEcAn.DB::db.query( paste0("SELECT id from formats where name = '", register$format$name, From 6d571c050b58950bfe8d6d3a4dea7c99b27213e1 Mon Sep 17 00:00:00 2001 From: Harunobu Ishii Date: Wed, 26 Jun 2024 15:53:42 -0400 Subject: [PATCH 03/16] Fixed possible arg discrepancy --- modules/assim.sequential/inst/covariates.R | 30 ++++++++++++++++------ 1 file changed, 22 insertions(+), 8 deletions(-) diff --git a/modules/assim.sequential/inst/covariates.R b/modules/assim.sequential/inst/covariates.R index 52e86ec88fd..f704f2a5b80 100644 --- a/modules/assim.sequential/inst/covariates.R +++ b/modules/assim.sequential/inst/covariates.R @@ -12,9 +12,10 @@ # Product is a zip file containing 12 .tif files, one for each month # Use code below to average the 12 files to obtain one map # 2023 REU project used 10 minute spatial resolution +prefix = "path/to/covariates_data/" ## Solar Radiation (kJ m-2 day-1) -srad <- terra::rast(list.files(path = "/projectnb/dietzelab/jploshay/pecan_copy/jploshay/10m_srad", +srad <- terra::rast(list.files(path = paste0(prefix, "10m_srad"), pattern='.tif$', all.files= T, full.names= T)) @@ -22,7 +23,7 @@ srad <- terra::app(srad, mean) ## Vapor Pressure (kPa) -vapr <- terra::rast(list.files(path = "/projectnb/dietzelab/jploshay/pecan_copy/jploshay/10m_vapr", +vapr <- terra::rast(list.files(path = paste0(prefix, "10m_vapr"), pattern='.tif$', all.files= T, full.names= T)) @@ -30,7 +31,7 @@ vapr <- terra::app(vapr, mean) ## Average Temperature (*C) -tavg <- terra::rast(list.files(path = "/projectnb/dietzelab/jploshay/pecan_copy/jploshay/avg_temp_prep/WorldClim", +tavg <- terra::rast(list.files(path = paste0(prefix, "WorldClim"), pattern='.tif$', all.files= T, full.names= T)) @@ -38,7 +39,7 @@ tavg <- terra::app(tavg, mean) ## Total Precipitation (mm) -prec <- terra::rast(list.files(path = "/projectnb/dietzelab/jploshay/pecan_copy/jploshay/total_prec", +prec <- terra::rast(list.files(path = paste0(prefix, "total_prec"), pattern='.tif$', all.files= T, full.names= T)) @@ -64,8 +65,8 @@ sand <- geodata::soil_world(var = "sand", depth = 5, stat = "mean", path = tempd #### Land Cover #### -GLanCE_extract <- function(pattern, path) { - files <- list.files(path = "/projectnb/dietzelab/dietze/glance2012/e4ftl01.cr.usgs.gov/MEASURES/GLanCE30.001/2012.07.01", #make this path default +GLanCE_extract <- function(pattern) { + files <- list.files(path = paste0(prefix,"GLanCE30.001/2012.07.01"), all.files = T, full.names = T, pattern) @@ -79,11 +80,24 @@ GLanCE_extract <- function(pattern, path) { # Integer identifier for class in the current year land_cover <- GLanCE_extract(pattern = "NA_LC.tif$") - #### Resample and Stack Maps #### # Define the extent to crop the covariates to North America NA_extent <- terra::ext(-178.19453125, -10, 7.22006835937502, 83.5996093750001) + +## Align CRS for all datasets +crs_target <- "EPSG:4326" +tavg <- terra::project(tavg, crs_target) +srad <- terra::project(srad, crs_target) +prec <- terra::project(prec, crs_target) +vapr <- terra::project(vapr, crs_target) + +phh2o <- terra::project(phh2o, crs_target) +nitrogen <- terra::project(nitrogen, crs_target) +soc <- terra::project(soc, crs_target) +sand <- terra::project(sand, crs_target) +land_cover <- terra::project(land_cover, crs_target) + # Stack WorldClim maps WorldClim <- c(tavg, srad, prec, vapr) @@ -99,7 +113,7 @@ NA_SoilGrids <- terra::crop(SoilGrids, NA_extent) names(NA_SoilGrids) <- c("phh2o", "nitrogen", "soc", "sand") # Resample SoilGrids to match WorldClim maps -NA_SoilGrids <- terra::resample(NA_WorldClim, NA_SoilGrids, method = 'bilinear') # made change +NA_SoilGrids <- terra::resample(NA_SoilGrids, NA_WorldClim, method = 'bilinear') # Resample land cover to match WorldClim maps (~25 min) land_cover <- terra::resample(land_cover, NA_WorldClim, method = 'near') From 0db7757a7239be7ffec5a9f741977a14c5c90cca Mon Sep 17 00:00:00 2001 From: Harunobu Ishii Date: Wed, 26 Jun 2024 16:01:23 -0400 Subject: [PATCH 04/16] Retrieved path --- modules/assim.sequential/inst/covariates.R | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/modules/assim.sequential/inst/covariates.R b/modules/assim.sequential/inst/covariates.R index f704f2a5b80..cb15ea892fa 100644 --- a/modules/assim.sequential/inst/covariates.R +++ b/modules/assim.sequential/inst/covariates.R @@ -15,7 +15,7 @@ prefix = "path/to/covariates_data/" ## Solar Radiation (kJ m-2 day-1) -srad <- terra::rast(list.files(path = paste0(prefix, "10m_srad"), +srad <- terra::rast(list.files(path = "/projectnb/dietzelab/jploshay/pecan_copy/jploshay/avg_temp_prep/10m_srad", pattern='.tif$', all.files= T, full.names= T)) @@ -23,7 +23,7 @@ srad <- terra::app(srad, mean) ## Vapor Pressure (kPa) -vapr <- terra::rast(list.files(path = paste0(prefix, "10m_vapr"), +vapr <- terra::rast(list.files(path = "/projectnb/dietzelab/jploshay/pecan_copy/jploshay/avg_temp_prep/10m_vapr", pattern='.tif$', all.files= T, full.names= T)) @@ -31,7 +31,7 @@ vapr <- terra::app(vapr, mean) ## Average Temperature (*C) -tavg <- terra::rast(list.files(path = paste0(prefix, "WorldClim"), +tavg <- terra::rast(list.files(path = "/projectnb/dietzelab/jploshay/pecan_copy/jploshay/avg_temp_prep/WorldClim", pattern='.tif$', all.files= T, full.names= T)) @@ -39,7 +39,7 @@ tavg <- terra::app(tavg, mean) ## Total Precipitation (mm) -prec <- terra::rast(list.files(path = paste0(prefix, "total_prec"), +prec <- terra::rast(list.files(path = "/projectnb/dietzelab/jploshay/pecan_copy/jploshay/avg_temp_prep/total_prec", pattern='.tif$', all.files= T, full.names= T)) @@ -66,7 +66,7 @@ sand <- geodata::soil_world(var = "sand", depth = 5, stat = "mean", path = tempd #### Land Cover #### GLanCE_extract <- function(pattern) { - files <- list.files(path = paste0(prefix,"GLanCE30.001/2012.07.01"), + files <- list.files(path = "/projectnb/dietzelab/dietze/glance2012/e4ftl01.cr.usgs.gov/MEASURES/GLanCE30.001/2012.07.01", #make this path default all.files = T, full.names = T, pattern) From c519cae09a15b8f6b87f8c4f085aed5501366155 Mon Sep 17 00:00:00 2001 From: Harunobu Ishii Date: Wed, 26 Jun 2024 16:02:05 -0400 Subject: [PATCH 05/16] Retrieved path --- modules/assim.sequential/inst/covariates.R | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/modules/assim.sequential/inst/covariates.R b/modules/assim.sequential/inst/covariates.R index cb15ea892fa..5c37ce916f1 100644 --- a/modules/assim.sequential/inst/covariates.R +++ b/modules/assim.sequential/inst/covariates.R @@ -12,10 +12,10 @@ # Product is a zip file containing 12 .tif files, one for each month # Use code below to average the 12 files to obtain one map # 2023 REU project used 10 minute spatial resolution -prefix = "path/to/covariates_data/" + ## Solar Radiation (kJ m-2 day-1) -srad <- terra::rast(list.files(path = "/projectnb/dietzelab/jploshay/pecan_copy/jploshay/avg_temp_prep/10m_srad", +srad <- terra::rast(list.files(path = "/projectnb/dietzelab/jploshay/pecan_copy/jploshay/10m_srad", pattern='.tif$', all.files= T, full.names= T)) @@ -23,7 +23,7 @@ srad <- terra::app(srad, mean) ## Vapor Pressure (kPa) -vapr <- terra::rast(list.files(path = "/projectnb/dietzelab/jploshay/pecan_copy/jploshay/avg_temp_prep/10m_vapr", +vapr <- terra::rast(list.files(path = "/projectnb/dietzelab/jploshay/pecan_copy/jploshay/10m_vapr", pattern='.tif$', all.files= T, full.names= T)) @@ -31,7 +31,7 @@ vapr <- terra::app(vapr, mean) ## Average Temperature (*C) -tavg <- terra::rast(list.files(path = "/projectnb/dietzelab/jploshay/pecan_copy/jploshay/avg_temp_prep/WorldClim", +tavg <- terra::rast(list.files(path = "/projectnb/dietzelab/jploshay/pecan_copy/jploshay/WorldClim", pattern='.tif$', all.files= T, full.names= T)) @@ -39,7 +39,7 @@ tavg <- terra::app(tavg, mean) ## Total Precipitation (mm) -prec <- terra::rast(list.files(path = "/projectnb/dietzelab/jploshay/pecan_copy/jploshay/avg_temp_prep/total_prec", +prec <- terra::rast(list.files(path = "/projectnb/dietzelab/jploshay/pecan_copy/jploshay/total_prec", pattern='.tif$', all.files= T, full.names= T)) From 835ae6cd349edc474a10d7bacefaa6e69b5aae8f Mon Sep 17 00:00:00 2001 From: Harunobu Ishii Date: Wed, 26 Jun 2024 16:02:26 -0400 Subject: [PATCH 06/16] Retrieved path --- modules/assim.sequential/inst/covariates.R | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/modules/assim.sequential/inst/covariates.R b/modules/assim.sequential/inst/covariates.R index 5c37ce916f1..691ed2f429d 100644 --- a/modules/assim.sequential/inst/covariates.R +++ b/modules/assim.sequential/inst/covariates.R @@ -31,7 +31,7 @@ vapr <- terra::app(vapr, mean) ## Average Temperature (*C) -tavg <- terra::rast(list.files(path = "/projectnb/dietzelab/jploshay/pecan_copy/jploshay/WorldClim", +tavg <- terra::rast(list.files(path = "/projectnb/dietzelab/jploshay/pecan_copy/jploshay/avg_temp_prep/WorldClim", pattern='.tif$', all.files= T, full.names= T)) From 31b148eba62fa74dd690c3b717b7dc917f2e481b Mon Sep 17 00:00:00 2001 From: Harunobu Ishii Date: Wed, 26 Jun 2024 16:02:50 -0400 Subject: [PATCH 07/16] Retrieved path --- modules/assim.sequential/inst/covariates.R | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/modules/assim.sequential/inst/covariates.R b/modules/assim.sequential/inst/covariates.R index 691ed2f429d..dcf9fc3a2fa 100644 --- a/modules/assim.sequential/inst/covariates.R +++ b/modules/assim.sequential/inst/covariates.R @@ -65,7 +65,7 @@ sand <- geodata::soil_world(var = "sand", depth = 5, stat = "mean", path = tempd #### Land Cover #### -GLanCE_extract <- function(pattern) { +GLanCE_extract <- function(pattern, path) { files <- list.files(path = "/projectnb/dietzelab/dietze/glance2012/e4ftl01.cr.usgs.gov/MEASURES/GLanCE30.001/2012.07.01", #make this path default all.files = T, full.names = T, From 7b203162b0b64f6e5cc988267a6742f5e9015e2a Mon Sep 17 00:00:00 2001 From: Harunobu Ishii Date: Wed, 26 Jun 2024 16:03:08 -0400 Subject: [PATCH 08/16] Retrieved path --- modules/assim.sequential/inst/covariates.R | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/modules/assim.sequential/inst/covariates.R b/modules/assim.sequential/inst/covariates.R index dcf9fc3a2fa..b1db1171d69 100644 --- a/modules/assim.sequential/inst/covariates.R +++ b/modules/assim.sequential/inst/covariates.R @@ -66,7 +66,7 @@ sand <- geodata::soil_world(var = "sand", depth = 5, stat = "mean", path = tempd #### Land Cover #### GLanCE_extract <- function(pattern, path) { - files <- list.files(path = "/projectnb/dietzelab/dietze/glance2012/e4ftl01.cr.usgs.gov/MEASURES/GLanCE30.001/2012.07.01", #make this path default + files <- list.files(path = "/projectnb/dietzelab/dietze/glance2012/e4ftl01.cr.usgs.gov/MEASURES/GLanCE30.001/2012.07.01", #make this path default all.files = T, full.names = T, pattern) From 85b083ec5c3b2a0f579ee87f82321b01a7aa866a Mon Sep 17 00:00:00 2001 From: Harunobu Ishii Date: Wed, 26 Jun 2024 16:03:35 -0400 Subject: [PATCH 09/16] Retrieved path --- modules/assim.sequential/inst/covariates.R | 14 -------------- 1 file changed, 14 deletions(-) diff --git a/modules/assim.sequential/inst/covariates.R b/modules/assim.sequential/inst/covariates.R index b1db1171d69..91db5a31b91 100644 --- a/modules/assim.sequential/inst/covariates.R +++ b/modules/assim.sequential/inst/covariates.R @@ -84,20 +84,6 @@ land_cover <- GLanCE_extract(pattern = "NA_LC.tif$") # Define the extent to crop the covariates to North America NA_extent <- terra::ext(-178.19453125, -10, 7.22006835937502, 83.5996093750001) - -## Align CRS for all datasets -crs_target <- "EPSG:4326" -tavg <- terra::project(tavg, crs_target) -srad <- terra::project(srad, crs_target) -prec <- terra::project(prec, crs_target) -vapr <- terra::project(vapr, crs_target) - -phh2o <- terra::project(phh2o, crs_target) -nitrogen <- terra::project(nitrogen, crs_target) -soc <- terra::project(soc, crs_target) -sand <- terra::project(sand, crs_target) -land_cover <- terra::project(land_cover, crs_target) - # Stack WorldClim maps WorldClim <- c(tavg, srad, prec, vapr) From 61baeaf7b7a41aa59b8fe40c7aa218de1e0a9878 Mon Sep 17 00:00:00 2001 From: Harunobu Ishii Date: Wed, 26 Jun 2024 16:04:05 -0400 Subject: [PATCH 10/16] Retrievd white space --- modules/assim.sequential/inst/covariates.R | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/modules/assim.sequential/inst/covariates.R b/modules/assim.sequential/inst/covariates.R index 91db5a31b91..99ea5ab585b 100644 --- a/modules/assim.sequential/inst/covariates.R +++ b/modules/assim.sequential/inst/covariates.R @@ -13,7 +13,6 @@ # Use code below to average the 12 files to obtain one map # 2023 REU project used 10 minute spatial resolution - ## Solar Radiation (kJ m-2 day-1) srad <- terra::rast(list.files(path = "/projectnb/dietzelab/jploshay/pecan_copy/jploshay/10m_srad", pattern='.tif$', @@ -80,6 +79,7 @@ GLanCE_extract <- function(pattern, path) { # Integer identifier for class in the current year land_cover <- GLanCE_extract(pattern = "NA_LC.tif$") + #### Resample and Stack Maps #### # Define the extent to crop the covariates to North America NA_extent <- terra::ext(-178.19453125, -10, 7.22006835937502, 83.5996093750001) From 0def2a201cd3c78a3b3380f8b0b81ac7d513cd00 Mon Sep 17 00:00:00 2001 From: Abhinav Pandey Date: Fri, 28 Jun 2024 16:33:20 +0530 Subject: [PATCH 11/16] Update read.register to extract name and id in a 'temp' variable. Change broken `mime_type` to `mimetype_id`. Suggested by @infotroph Signed-off-by: Abhinav Pandey --- modules/data.atmosphere/R/read.register.R | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/modules/data.atmosphere/R/read.register.R b/modules/data.atmosphere/R/read.register.R index dbdadf636a9..fc42f4c77c6 100644 --- a/modules/data.atmosphere/R/read.register.R +++ b/modules/data.atmosphere/R/read.register.R @@ -36,14 +36,17 @@ read.register <- function(register.xml, con) { | (!is.null(register$format$id) & is.null(register$format$mimetype))) { # Retrieve format name and mimetype from the database - register$format <- PEcAn.DB::db.query( - paste("SELECT name, mime_type AS mimetype FROM formats WHERE id = ", register$format$id), con + query.format.info <- PEcAn.DB::db.query( + paste("SELECT name, mimetype_id AS mimetype FROM formats WHERE id = ", register$format$id), con ) + + register$format$name <- query.format.info$name + register$format$mimetype <- query.format.info$mimetype } else if (is.null(register$format$id) & !is.null(register$format$name) & !is.null(register$format$mimetype)) { register$format$id <- PEcAn.DB::db.query( paste0("SELECT id from formats where name = '", register$format$name, - "' and mime_type = '", register$format$mimetype, "'"), con)[[1]] + "' and mimetype_id = '", register$format$mimetype, "'"), con)[[1]] } } return(invisible(register)) From 56b1c378f38818524e01ffcbd0e2e246a6f16f83 Mon Sep 17 00:00:00 2001 From: Chris Black Date: Sat, 29 Jun 2024 10:11:07 +0200 Subject: [PATCH 12/16] minor cleanup in uncertainty function Roxygen blocks Plus: redocumented data.mining with current Roxygen --- modules/data.mining/DESCRIPTION | 2 +- modules/uncertainty/R/sensitivity.analysis.R | 126 ++++++++++-------- modules/uncertainty/man/get.elasticity.Rd | 5 +- modules/uncertainty/man/get.sensitivity.Rd | 9 +- modules/uncertainty/man/kurtosis.Rd | 8 +- modules/uncertainty/man/sa.splinefun.Rd | 9 +- modules/uncertainty/man/sd.var.Rd | 5 +- .../uncertainty/man/sensitivity.analysis.Rd | 20 +-- modules/uncertainty/man/spline.truncate.Rd | 7 +- 9 files changed, 93 insertions(+), 98 deletions(-) diff --git a/modules/data.mining/DESCRIPTION b/modules/data.mining/DESCRIPTION index 7ac5389be56..0816ff34964 100644 --- a/modules/data.mining/DESCRIPTION +++ b/modules/data.mining/DESCRIPTION @@ -21,4 +21,4 @@ LazyLoad: yes LazyData: FALSE Collate: Encoding: UTF-8 -RoxygenNote: 7.1.2 +RoxygenNote: 7.3.1 diff --git a/modules/uncertainty/R/sensitivity.analysis.R b/modules/uncertainty/R/sensitivity.analysis.R index c66992b8623..69f162d970f 100644 --- a/modules/uncertainty/R/sensitivity.analysis.R +++ b/modules/uncertainty/R/sensitivity.analysis.R @@ -10,14 +10,13 @@ ##' Spline estimate of univariate relationship between parameter value and model output ##' ##' Creates a spline function using the splinefun function that estimates univariate response of parameter input to model output -##' @name sa.splinefun -##' @title Sensitivity spline function -##' @param quantiles.input -##' @param quantiles.output +##' +##' @param quantiles.input passed to `x` argument of `stats::splinefun` +##' @param quantiles.output passed to `y` argument of `stats::splinefun` ##' @export -##' @return function +##' @return function sa.splinefun <- function(quantiles.input, quantiles.output) { - return(stats::splinefun(quantiles.input, quantiles.output, method = "monoH.FC")) + return(stats::splinefun(x = quantiles.input, y = quantiles.output, method = "monoH.FC")) } # sa.splinefun @@ -25,8 +24,6 @@ sa.splinefun <- function(quantiles.input, quantiles.output) { ##' Calculates the standard deviation of the variance estimate ##' ##' Uses the equation \eqn{\sigma^4\left(\frac{2}{n-1}+\frac{\kappa}{n}\right)}{\sigma^4 (2/(n-1) + \kappa/n)} -##' @name sd.var -##' @title Standard deviation of sample variance ##' @param x sample ##' @return estimate of standard deviation of the sample variance ##' @export @@ -42,17 +39,15 @@ sd.var <- function(x) { ##' ##' Note that this calculates the 'excess kurtosis', which is defined as kurtosis - 3. ##' This statistic is used in the calculation of the standard deviation of sample variance -##' in the function \code{\link{sd.var}}. -##' Additional details -##' @name kurtosis -##' @title Calculate excess kurtosis from a vector +##' in the function \code{\link{sd.var}}. +##' ##' @param x vector of values ##' @return numeric value of kurtosis ##' @author David LeBauer ##' @references NIST/SEMATECH e-Handbook of Statistical Methods, \url{http://www.itl.nist.gov/div898/handbook/eda/section3/eda35b.htm}, 2011-06-20. kurtosis <- function(x) { - kappa <- sum((x - mean(x, na.rm = TRUE)) ^ 4) / - ((sum(!is.na(x)) - 1) * stats::sd(x, na.rm = TRUE) ^ 4) - 3 + kappa <- sum((x - mean(x, na.rm = TRUE))^4) / + ((sum(!is.na(x)) - 1) * stats::sd(x, na.rm = TRUE)^4) - 3 return(kappa) } # kurtosis # ==================================================================================================# @@ -64,10 +59,9 @@ kurtosis <- function(x) { ##' This function evaluates the sensitivity of a model to a parameter. ##' This is done by evaluating the first derivative of the univariate spline estimate ##' of the model response at the parameter median. -##' @name get.sensitivity -##' @title Calculate Sensitivity -##' @param trait.samples -##' @param sa.splinefun +##' +##' @param trait.samples parameter values to evaluate at their median +##' @param sa.splinefun fitted spline function. Must take two arguments. ##' @export ##' @return numeric estimate of model sensitivity to parameter get.sensitivity <- function(trait.samples, sa.splinefun) { @@ -77,10 +71,10 @@ get.sensitivity <- function(trait.samples, sa.splinefun) { #--------------------------------------------------------------------------------------------------# +##' Get coefficient of variance +##' ##' Given a set of numbers (a numeric vector), this returns the set's coefficient of variance. ##' -##' @name get.coef.var -##' @title Get coefficient of variance ##' @param set numeric vector of trait values ##' @export ##' @return coeficient of variance @@ -93,70 +87,90 @@ get.coef.var <- function(set) { ##' Generic function for the elasticity ##' ##' Given the sensitivity, samples, and outputs for a single trait, return elasticity -##' @name get.elasticity -##' @title Get Elasticity +##' ##' @param sensitivity univariate sensitivity of model to a parameter, can be calculated by \code{\link{get.sensitivity}} ##' @param samples samples from trait distribution ##' @param outputs model output from ensemble runs ##' @export -##' @return elasticity = normalized sensitivity +##' @return elasticity = normalized sensitivity get.elasticity <- function(sensitivity, samples, outputs) { return(sensitivity / (stats::median(outputs) / stats::median(samples))) } # get.elasticity #--------------------------------------------------------------------------------------------------# -##' Performs univariate sensitivity analysis and variance decomposition +##' Performs univariate sensitivity analysis and variance decomposition ##' -##' This function estimates the univariate responses of a model to a parameter for a set of traits, calculates the model sensitivity at the median, and performs a variance decomposition. This function results in a set of sensitivity plots (one per variable) and plot_variance_decomposition. -##' @name sensitivity.analysis -##' @title Sensitivity Analysis -##' @param trait.samples list of vectors, one per trait, representing samples of the trait value, with length equal to the mcmc chain length. Samples are taken from either the prior distribution or meta-analysis results -##' @param sa.samples data.frame with one column per trait and one row for the set of quantiles used in sensitivity analysis. Each cell contains the value of the trait at the given quantile. -##' @param sa.output list of data.frames, similar to sa.samples, except cells contain the results of a model run with that trait x quantile combination and all other traits held at their median value +##' This function estimates the univariate responses of a model to a parameter for a set of traits, calculates the model sensitivity at the median, +##' and performs a variance decomposition. This function results in a set of sensitivity plots (one per variable) and plot_variance_decomposition. +##' +##' @param trait.samples list of vectors, one per trait, representing samples of the trait value, with length equal to the mcmc chain length. +##' Samples are taken from either the prior distribution or meta-analysis results +##' @param sa.samples data.frame with one column per trait and one row for the set of quantiles used in sensitivity analysis. +## Each cell contains the value of the trait at the given quantile. +##' @param sa.output list of data.frames, similar to sa.samples, except cells contain the results of a model run +##' with that trait x quantile combination and all other traits held at their median value ##' @param outdir directory to which plots are written ##' @return results of sensitivity analysis ##' @export ##' @author David LeBauer ##' @examples ##' \dontrun{ -##'sensitivity.analysis( +##' sensitivity.analysis( ##' trait.samples[[pft$name]], -##' sa.samples[[pft$name]], -##' sa.agb[[pft$name]], +##' sa.samples[[pft$name]], +##' sa.agb[[pft$name]], ##' pft$outdir -##') +##' ) ##' } sensitivity.analysis <- function(trait.samples, sa.samples, sa.output, outdir) { traits <- names(trait.samples) - sa.splines <- sapply(traits, - function(trait) sa.splinefun(sa.samples[[trait]], sa.output[[trait]])) - - spline.estimates <- lapply(traits, - function(trait) spline.truncate(sa.splines[[trait]](trait.samples[[trait]]))) + sa.splines <- sapply( + traits, + function(trait) sa.splinefun(sa.samples[[trait]], sa.output[[trait]]) + ) + + spline.estimates <- lapply( + traits, + function(trait) spline.truncate(sa.splines[[trait]](trait.samples[[trait]])) + ) names(spline.estimates) <- traits - sensitivities <- sapply(traits, - function(trait) get.sensitivity(trait.samples[[trait]], sa.splines[[trait]])) - elasticities <- sapply(traits, - function(trait) get.elasticity(sensitivities[[trait]], - trait.samples[[trait]], - spline.estimates[[trait]])) + sensitivities <- sapply( + traits, + function(trait) get.sensitivity(trait.samples[[trait]], sa.splines[[trait]]) + ) + elasticities <- sapply( + traits, + function(trait) { + get.elasticity( + sensitivities[[trait]], + trait.samples[[trait]], + spline.estimates[[trait]] + ) + } + ) variances <- sapply(traits, function(trait) stats::var(spline.estimates[[trait]])) partial.variances <- variances / sum(variances) - + coef.vars <- sapply(trait.samples, get.coef.var) - outlist <- list(sensitivity.output = list(sa.samples = sa.samples, - sa.splines = sa.splines), - variance.decomposition.output = list(coef.vars = coef.vars, - elasticities = elasticities, - sensitivities = sensitivities, - variances = variances, - partial.variances = partial.variances)) + outlist <- list( + sensitivity.output = list( + sa.samples = sa.samples, + sa.splines = sa.splines + ), + variance.decomposition.output = list( + coef.vars = coef.vars, + elasticities = elasticities, + sensitivities = sensitivities, + variances = variances, + partial.variances = partial.variances + ) + ) return(outlist) } # sensitivity.analysis -##' Truncate spline at zero if.. +##' Truncate spline at zero if... ##' ##' Truncate spline at zero if P[x<0] < pnorm(-3) ##' pnorm(-3) chosen as default value for min quantile @@ -164,7 +178,7 @@ sensitivity.analysis <- function(trait.samples, sa.samples, sa.output, outdir) { ##' sensitivity analysis. ##' This parameter could be determined based on minimum value in ##' settings$sensitivity.analysis$quantiles -##' @title Truncate spline +##' ##' @param x vector ##' @param min.quantile threshold quantile for testing lower bound on variable ##' @return either x or a vector with values < 0 converted to zero @@ -172,7 +186,7 @@ sensitivity.analysis <- function(trait.samples, sa.samples, sa.output, outdir) { ##' @export ##' @examples ##' set.seed(0) -##' x <- c(rgamma(998,1,1), rnorm(10)) +##' x <- c(rgamma(998,1,1), rnorm(10)) ##' min(x) # -0.5238 ##' min(PEcAn.uncertainty::spline.truncate(x)) spline.truncate <- function(x, min.quantile = stats::pnorm(-3)) { diff --git a/modules/uncertainty/man/get.elasticity.Rd b/modules/uncertainty/man/get.elasticity.Rd index 54d7bbc4727..502a29a5245 100644 --- a/modules/uncertainty/man/get.elasticity.Rd +++ b/modules/uncertainty/man/get.elasticity.Rd @@ -2,7 +2,7 @@ % Please edit documentation in R/sensitivity.analysis.R \name{get.elasticity} \alias{get.elasticity} -\title{Get Elasticity} +\title{Generic function for the elasticity} \usage{ get.elasticity(sensitivity, samples, outputs) } @@ -17,8 +17,5 @@ get.elasticity(sensitivity, samples, outputs) elasticity = normalized sensitivity } \description{ -Generic function for the elasticity -} -\details{ Given the sensitivity, samples, and outputs for a single trait, return elasticity } diff --git a/modules/uncertainty/man/get.sensitivity.Rd b/modules/uncertainty/man/get.sensitivity.Rd index e2c136cef8f..0763edc5706 100644 --- a/modules/uncertainty/man/get.sensitivity.Rd +++ b/modules/uncertainty/man/get.sensitivity.Rd @@ -2,22 +2,19 @@ % Please edit documentation in R/sensitivity.analysis.R \name{get.sensitivity} \alias{get.sensitivity} -\title{Calculate Sensitivity} +\title{Calculate the sensitivity of a function at the median} \usage{ get.sensitivity(trait.samples, sa.splinefun) } \arguments{ -\item{trait.samples}{} +\item{trait.samples}{parameter values to evaluate at their median} -\item{sa.splinefun}{} +\item{sa.splinefun}{fitted spline function. Must take two arguments.} } \value{ numeric estimate of model sensitivity to parameter } \description{ -Calculate the sensitivity of a function at the median -} -\details{ This function evaluates the sensitivity of a model to a parameter. This is done by evaluating the first derivative of the univariate spline estimate of the model response at the parameter median. diff --git a/modules/uncertainty/man/kurtosis.Rd b/modules/uncertainty/man/kurtosis.Rd index 06b69f1bd50..ae913824d7f 100644 --- a/modules/uncertainty/man/kurtosis.Rd +++ b/modules/uncertainty/man/kurtosis.Rd @@ -2,7 +2,7 @@ % Please edit documentation in R/sensitivity.analysis.R \name{kurtosis} \alias{kurtosis} -\title{Calculate excess kurtosis from a vector} +\title{Calculates the excess kurtosis of a vector} \usage{ kurtosis(x) } @@ -13,13 +13,9 @@ kurtosis(x) numeric value of kurtosis } \description{ -Calculates the excess kurtosis of a vector -} -\details{ Note that this calculates the 'excess kurtosis', which is defined as kurtosis - 3. This statistic is used in the calculation of the standard deviation of sample variance -in the function \code{\link{sd.var}}. -Additional details +in the function \code{\link{sd.var}}. } \references{ NIST/SEMATECH e-Handbook of Statistical Methods, \url{http://www.itl.nist.gov/div898/handbook/eda/section3/eda35b.htm}, 2011-06-20. diff --git a/modules/uncertainty/man/sa.splinefun.Rd b/modules/uncertainty/man/sa.splinefun.Rd index b8d27f71f3e..5e9b788ec11 100644 --- a/modules/uncertainty/man/sa.splinefun.Rd +++ b/modules/uncertainty/man/sa.splinefun.Rd @@ -2,21 +2,18 @@ % Please edit documentation in R/sensitivity.analysis.R \name{sa.splinefun} \alias{sa.splinefun} -\title{Sensitivity spline function} +\title{Spline estimate of univariate relationship between parameter value and model output} \usage{ sa.splinefun(quantiles.input, quantiles.output) } \arguments{ -\item{quantiles.input}{} +\item{quantiles.input}{passed to `x` argument of `stats::splinefun`} -\item{quantiles.output}{} +\item{quantiles.output}{passed to `y` argument of `stats::splinefun`} } \value{ function } \description{ -Spline estimate of univariate relationship between parameter value and model output -} -\details{ Creates a spline function using the splinefun function that estimates univariate response of parameter input to model output } diff --git a/modules/uncertainty/man/sd.var.Rd b/modules/uncertainty/man/sd.var.Rd index fe6c570e436..a1f3845d1c6 100644 --- a/modules/uncertainty/man/sd.var.Rd +++ b/modules/uncertainty/man/sd.var.Rd @@ -2,7 +2,7 @@ % Please edit documentation in R/sensitivity.analysis.R \name{sd.var} \alias{sd.var} -\title{Standard deviation of sample variance} +\title{Calculates the standard deviation of the variance estimate} \usage{ sd.var(x) } @@ -13,9 +13,6 @@ sd.var(x) estimate of standard deviation of the sample variance } \description{ -Calculates the standard deviation of the variance estimate -} -\details{ Uses the equation \eqn{\sigma^4\left(\frac{2}{n-1}+\frac{\kappa}{n}\right)}{\sigma^4 (2/(n-1) + \kappa/n)} } \references{ diff --git a/modules/uncertainty/man/sensitivity.analysis.Rd b/modules/uncertainty/man/sensitivity.analysis.Rd index 4d1cffaf233..563ff528ceb 100644 --- a/modules/uncertainty/man/sensitivity.analysis.Rd +++ b/modules/uncertainty/man/sensitivity.analysis.Rd @@ -2,16 +2,18 @@ % Please edit documentation in R/sensitivity.analysis.R \name{sensitivity.analysis} \alias{sensitivity.analysis} -\title{Sensitivity Analysis} +\title{Performs univariate sensitivity analysis and variance decomposition} \usage{ sensitivity.analysis(trait.samples, sa.samples, sa.output, outdir) } \arguments{ -\item{trait.samples}{list of vectors, one per trait, representing samples of the trait value, with length equal to the mcmc chain length. Samples are taken from either the prior distribution or meta-analysis results} +\item{trait.samples}{list of vectors, one per trait, representing samples of the trait value, with length equal to the mcmc chain length. +Samples are taken from either the prior distribution or meta-analysis results} -\item{sa.samples}{data.frame with one column per trait and one row for the set of quantiles used in sensitivity analysis. Each cell contains the value of the trait at the given quantile.} +\item{sa.samples}{data.frame with one column per trait and one row for the set of quantiles used in sensitivity analysis.} -\item{sa.output}{list of data.frames, similar to sa.samples, except cells contain the results of a model run with that trait x quantile combination and all other traits held at their median value} +\item{sa.output}{list of data.frames, similar to sa.samples, except cells contain the results of a model run +with that trait x quantile combination and all other traits held at their median value} \item{outdir}{directory to which plots are written} } @@ -19,17 +21,15 @@ sensitivity.analysis(trait.samples, sa.samples, sa.output, outdir) results of sensitivity analysis } \description{ -Performs univariate sensitivity analysis and variance decomposition -} -\details{ -This function estimates the univariate responses of a model to a parameter for a set of traits, calculates the model sensitivity at the median, and performs a variance decomposition. This function results in a set of sensitivity plots (one per variable) and plot_variance_decomposition. +This function estimates the univariate responses of a model to a parameter for a set of traits, calculates the model sensitivity at the median, + and performs a variance decomposition. This function results in a set of sensitivity plots (one per variable) and plot_variance_decomposition. } \examples{ \dontrun{ sensitivity.analysis( trait.samples[[pft$name]], - sa.samples[[pft$name]], - sa.agb[[pft$name]], + sa.samples[[pft$name]], + sa.agb[[pft$name]], pft$outdir ) } diff --git a/modules/uncertainty/man/spline.truncate.Rd b/modules/uncertainty/man/spline.truncate.Rd index a1ee6b3518e..3e3dd08eea9 100644 --- a/modules/uncertainty/man/spline.truncate.Rd +++ b/modules/uncertainty/man/spline.truncate.Rd @@ -2,7 +2,7 @@ % Please edit documentation in R/sensitivity.analysis.R \name{spline.truncate} \alias{spline.truncate} -\title{Truncate spline} +\title{Truncate spline at zero if...} \usage{ spline.truncate(x, min.quantile = stats::pnorm(-3)) } @@ -15,9 +15,6 @@ spline.truncate(x, min.quantile = stats::pnorm(-3)) either x or a vector with values < 0 converted to zero } \description{ -Truncate spline at zero if.. -} -\details{ Truncate spline at zero if P[x<0] < pnorm(-3) pnorm(-3) chosen as default value for min quantile because this is the default low end of range for the @@ -27,7 +24,7 @@ settings$sensitivity.analysis$quantiles } \examples{ set.seed(0) -x <- c(rgamma(998,1,1), rnorm(10)) +x <- c(rgamma(998,1,1), rnorm(10)) min(x) # -0.5238 min(PEcAn.uncertainty::spline.truncate(x)) } From 9b6942894e590343709b8d65722e6a971a23592f Mon Sep 17 00:00:00 2001 From: Abhinav Pandey Date: Wed, 10 Jul 2024 11:46:12 +0530 Subject: [PATCH 13/16] Update modules/data.atmosphere/R/read.register.R Co-authored-by: Chris Black --- modules/data.atmosphere/R/read.register.R | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/modules/data.atmosphere/R/read.register.R b/modules/data.atmosphere/R/read.register.R index fc42f4c77c6..51c9f7ece31 100644 --- a/modules/data.atmosphere/R/read.register.R +++ b/modules/data.atmosphere/R/read.register.R @@ -46,7 +46,7 @@ read.register <- function(register.xml, con) { } else if (is.null(register$format$id) & !is.null(register$format$name) & !is.null(register$format$mimetype)) { register$format$id <- PEcAn.DB::db.query( paste0("SELECT id from formats where name = '", register$format$name, - "' and mimetype_id = '", register$format$mimetype, "'"), con)[[1]] + "' AND type_string = '", register$format$mimetype, "'"), con)[[1]] } } return(invisible(register)) From 0ac2c938ebcfc34d094e2d075f9bbd3a874b6fa6 Mon Sep 17 00:00:00 2001 From: Abhinav Pandey Date: Wed, 10 Jul 2024 11:46:31 +0530 Subject: [PATCH 14/16] Update modules/data.atmosphere/R/read.register.R Co-authored-by: Chris Black --- modules/data.atmosphere/R/read.register.R | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/modules/data.atmosphere/R/read.register.R b/modules/data.atmosphere/R/read.register.R index 51c9f7ece31..567dc216697 100644 --- a/modules/data.atmosphere/R/read.register.R +++ b/modules/data.atmosphere/R/read.register.R @@ -37,7 +37,11 @@ read.register <- function(register.xml, con) { (!is.null(register$format$id) & is.null(register$format$mimetype))) { # Retrieve format name and mimetype from the database query.format.info <- PEcAn.DB::db.query( - paste("SELECT name, mimetype_id AS mimetype FROM formats WHERE id = ", register$format$id), con + paste( + "SELECT name, type_string AS mimetype", + "FROM formats JOIN mimetypes ON formats.mimetype_id = mimetypes.id", + "WHERE formats.id = ", register$format$id), + con ) register$format$name <- query.format.info$name From d287192169c6e8736140543907cddb51426c3dc2 Mon Sep 17 00:00:00 2001 From: Abhinav Pandey Date: Wed, 10 Jul 2024 11:48:18 +0530 Subject: [PATCH 15/16] Update query to retrieve format.id Co-authored-by: Chris Black --- modules/data.atmosphere/R/read.register.R | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/modules/data.atmosphere/R/read.register.R b/modules/data.atmosphere/R/read.register.R index 567dc216697..01a999ded60 100644 --- a/modules/data.atmosphere/R/read.register.R +++ b/modules/data.atmosphere/R/read.register.R @@ -49,7 +49,9 @@ read.register <- function(register.xml, con) { } else if (is.null(register$format$id) & !is.null(register$format$name) & !is.null(register$format$mimetype)) { register$format$id <- PEcAn.DB::db.query( - paste0("SELECT id from formats where name = '", register$format$name, + paste0( + "SELECT formats.id FROM formats JOIN mimetypes ON formats.mimetype_id = mimetypes.id ", + "WHERE name = '", register$format$name, "' AND type_string = '", register$format$mimetype, "'"), con)[[1]] } } From b1b184668996e66dd25312e8ad6e4e03bb6f08fb Mon Sep 17 00:00:00 2001 From: Chris Black Date: Wed, 10 Jul 2024 12:29:04 -0700 Subject: [PATCH 16/16] relicense shiny/dbsync and shiny/Elicitation (all authors have approved this change) --- CHANGELOG.md | 13 +++++++++++++ shiny/Elicitation/LICENSE | 37 +++---------------------------------- shiny/dbsync/LICENSE | 37 +++---------------------------------- 3 files changed, 19 insertions(+), 68 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 8e69c58ee70..87242effa0d 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -7,6 +7,19 @@ For more information about this file see also [Keep a Changelog](http://keepacha ## [Unreleased] +### Added + +### Fixed + +### Changed +- The following components have changed their licensing. With approval of all their contributors, we now provide them under a BSD 3-clause license rather than the previously used NCSA Open Source license. As a reminder, we intend to relicense the entire system and this list will expand as we gather permission from the relevant copyright owners. + * Shiny apps `dbsync` and `Elicitation` + +### Removed + + +## [1.8.0] - 2024-07-12 + ### Added - Created a new soilgrids function to extract the mean soil organic carbon profile with associated undertainty values at each depth for any lat/long location (#3040). Function was created for the CMS SDA workflow diff --git a/shiny/Elicitation/LICENSE b/shiny/Elicitation/LICENSE index 5a9e44128f1..09ef35a60b4 100644 --- a/shiny/Elicitation/LICENSE +++ b/shiny/Elicitation/LICENSE @@ -1,34 +1,3 @@ -## This is the master copy of the PEcAn License - -University of Illinois/NCSA Open Source License - -Copyright (c) 2012, University of Illinois, NCSA. All rights reserved. - -PEcAn project -www.pecanproject.org - -Permission is hereby granted, free of charge, to any person obtaining -a copy of this software and associated documentation files (the -"Software"), to deal with the Software without restriction, including -without limitation the rights to use, copy, modify, merge, publish, -distribute, sublicense, and/or sell copies of the Software, and to -permit persons to whom the Software is furnished to do so, subject to -the following conditions: - -- Redistributions of source code must retain the above copyright - notice, this list of conditions and the following disclaimers. -- Redistributions in binary form must reproduce the above copyright - notice, this list of conditions and the following disclaimers in the - documentation and/or other materials provided with the distribution. -- Neither the names of University of Illinois, NCSA, nor the names - of its contributors may be used to endorse or promote products - derived from this Software without specific prior written permission. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. -IN NO EVENT SHALL THE CONTRIBUTORS OR COPYRIGHT HOLDERS BE LIABLE FOR -ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF -CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION -WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS WITH THE SOFTWARE. - +YEAR: 2024 +COPYRIGHT HOLDER: PEcAn Project +ORGANIZATION: PEcAn Project, authors affiliations diff --git a/shiny/dbsync/LICENSE b/shiny/dbsync/LICENSE index 26efbfea4dc..09ef35a60b4 100644 --- a/shiny/dbsync/LICENSE +++ b/shiny/dbsync/LICENSE @@ -1,34 +1,3 @@ -## This is the master copy of the PEcAn License - -University of Illinois/NCSA Open Source License - -Copyright (c) 2012, University of Illinois, NCSA. All rights reserved. - -PEcAn project -www.pecanproject.org - -Permission is hereby granted, free of charge, to any person obtaining -a copy of this software and associated documentation files (the - "Software"), to deal with the Software without restriction, including -without limitation the rights to use, copy, modify, merge, publish, -distribute, sublicense, and/or sell copies of the Software, and to -permit persons to whom the Software is furnished to do so, subject to -the following conditions: - - - Redistributions of source code must retain the above copyright -notice, this list of conditions and the following disclaimers. -- Redistributions in binary form must reproduce the above copyright -notice, this list of conditions and the following disclaimers in the -documentation and/or other materials provided with the distribution. -- Neither the names of University of Illinois, NCSA, nor the names -of its contributors may be used to endorse or promote products -derived from this Software without specific prior written permission. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. -IN NO EVENT SHALL THE CONTRIBUTORS OR COPYRIGHT HOLDERS BE LIABLE FOR -ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF -CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION -WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS WITH THE SOFTWARE. - +YEAR: 2024 +COPYRIGHT HOLDER: PEcAn Project +ORGANIZATION: PEcAn Project, authors affiliations