From 9f23ac898e968279506f69149ac07eb2557c67fe Mon Sep 17 00:00:00 2001 From: JulienBoehm <180776296+JulienBoehm@users.noreply.github.com> Date: Wed, 15 Apr 2026 17:44:16 +0200 Subject: [PATCH 01/32] added read_pam_2500_data() function --- src/NAMESPACE | 1 + src/R/read_pam_data.R | 112 +++++++++++++++++- src/R/validation.R | 39 ++++++ .../extdata/pam_2500_data/20260311_1(2).CSV | 18 +++ src/man/read_junior_pam_data.Rd | 2 +- src/man/read_pam_2500_data.Rd | 55 +++++++++ .../testthat/data/20260311_1(2)_pam_2500.CSV | 18 +++ src/tests/testthat/test-read_pam_2500_data.R | 74 ++++++++++++ 8 files changed, 317 insertions(+), 2 deletions(-) create mode 100644 src/inst/extdata/pam_2500_data/20260311_1(2).CSV create mode 100644 src/man/read_pam_2500_data.Rd create mode 100644 src/tests/testthat/data/20260311_1(2)_pam_2500.CSV create mode 100644 src/tests/testthat/test-read_pam_2500_data.R diff --git a/src/NAMESPACE b/src/NAMESPACE index e66c609..f12344a 100644 --- a/src/NAMESPACE +++ b/src/NAMESPACE @@ -18,6 +18,7 @@ export(platt_modified) export(plot_control) export(read_dual_pam_data) export(read_junior_pam_data) +export(read_pam_2500_data) export(read_universal_data) export(vollenweider_default_start_value_a) export(vollenweider_default_start_value_alpha) diff --git a/src/R/read_pam_data.R b/src/R/read_pam_data.R index 8651931..c8b4a22 100644 --- a/src/R/read_pam_data.R +++ b/src/R/read_pam_data.R @@ -236,7 +236,7 @@ calc_etr <- function(yield, par, etr_factor, p_ratio) { #' Read and Process Junior PAM Data #' -#' Reads raw CSV files generated by Junior PAM software, calculates electron transport rate (ETR) values, and returns a cleaned dataset. Customization may be needed for non-DualPAM devices. +#' Reads raw CSV files generated by Junior PAM software, calculates electron transport rate (ETR) values, and returns a cleaned dataset. #' #' @param csv_path File path to the CSV file. #' @param remove_recovery Logical. Removes recovery measurements if \code{TRUE}. Default is \code{TRUE}. @@ -352,3 +352,113 @@ read_junior_pam_data <- function( } ) } + +#' Read and Process PAM 2500 Data +#' +#' Reads raw CSV files generated by PAM 2500 software, calculates electron transport rate (ETR) values, and returns a cleaned dataset. +#' +#' @param csv_path File path to the CSV file. +#' @param remove_recovery Logical. Removes recovery measurements if \code{TRUE}. Default is \code{TRUE}. +#' @param etr_factor Numeric. Factor for ETR calculation. Default is \code{0.84}. +#' @param fraction_photosystem_I Numeric. Relative distribution of absorbed PAR to photosystem I. Default is \code{0.5}. +#' @param fraction_photosystem_II Numeric. Relative distribution of absorbed PAR to photosystem II. Default is \code{0.5}. +#' +#' @details +#' Calculates ETR II using: +#' \deqn{\text{ETR II} = \text{PAR} \cdot \text{ETR-Factor} \cdot \text{Fraction of Photosystem (II)} \cdot \text{Yield (II)}} +#' +#' A detailed documentation can be found under \url{https://github.com/biotoolbox/pam?tab=readme-ov-file} +#' +#' @return A \code{data.table} containing: +#' \itemize{ +#' \item \code{par}: Photosynthetically active radiation. +#' \item \code{yield_1}: Yield for photosystem I. +#' \item \code{yield_2}: Yield for photosystem II. +#' \item \code{etr_1}: Calculated ETR for photosystem I. +#' \item \code{etr_2}: Calculated ETR for photosystem II. +#' } +#' +#' @references{ +#' Heinz Walz GmbH. (2024). \emph{DUAL-PAM-100 DUAL-PAM/F MANUAL, 5th Edition, April 2024, Chapter 7 (pp. 162-172).} +#' Heinz Walz GmbH, Effeltrich, Germany. +#' Available at: \url{https://www.walz.com/files/downloads/dualpamed05.pdf} +#' } +#' @examples +#' path <- file.path(system.file("extdata/pam_2500_data", package = "pam"), "20260311_1(2).CSV") +#' data <- read_pam_2500_data(path) +#' @export +read_pam_2500_data <- function( + csv_path, + remove_recovery = TRUE, + etr_factor = 0.84, + fraction_photosystem_I = 0.5, + fraction_photosystem_II = 0.5) { + if (fraction_photosystem_I + fraction_photosystem_II != 1) { + stop("The sum of fraction_photosystem_I and fraction_photosystem_II must be equal 1.") + } + + tryCatch( + { + data <- utils::read.csv(csv_path, sep = ";", dec = ".") + data <- data.table::as.data.table(data) + + validate_pam_2500_data(data) + data <- data[grepl("^\\d+$", data$`No.`), ] + + date_time_col_values <- c() + for (i in seq_len(nrow(data))) { + row <- data[i, ] + + date_time_row_value <- as.POSIXct( + paste(row$Date, row$Time, sep = " "), + tz = "GMT", "%d.%m.%y %H:%M:%S" + ) + date_time_col_values <- c(date_time_col_values, date_time_row_value) + } + + data$DateTime <- date_time_col_values + data <- data[order(data$DateTime), ] + + + result <- data.table::data.table( + par = numeric(), + yield_1 = numeric(), + yield_2 = numeric(), + etr_1 = numeric(), + etr_2 = numeric() + ) + last_par <- as.numeric(0) + for (i in seq_len(nrow(data))) { + row <- data[i, ] + current_par <- row$PAR + + if (remove_recovery && last_par != 0 && current_par < last_par) { + break + } + + yield_2 <- row$Y.II. + recalc_etr_2 <- calc_etr(yield_2, current_par, etr_factor, fraction_photosystem_II) + + new_row <- list( + par = current_par, + yield_1 = NA_real_, + yield_2 = yield_2, + etr_1 = NA_real_, + etr_2 = recalc_etr_2 + ) + result <- rbind(result, new_row) + + last_par <- current_par + } + + return(result) + }, + warning = function(w) { + stop("Warning in file: ", csv_path, " Warning: ", w) + }, + error = function(e) { + stop("Error in file: ", csv_path, " Error: ", e) + } + ) +} + diff --git a/src/R/validation.R b/src/R/validation.R index d47d394..bee93c9 100644 --- a/src/R/validation.R +++ b/src/R/validation.R @@ -130,6 +130,45 @@ validate_junior_pam_data <- function(data) { } } +validate_pam_2500_data <- function(data) { + if (is.null(data)) { + stop("data is null") + } + + if (!data.table::is.data.table(data)) { + stop("data is not a valid data.table") + } + + if (nrow(data) < 2) { + stop("no data rows") + } + + if (ncol(data) == 0) { + stop("no cols in data") + } + + if (!"No." %in% colnames(data)) { + stop("required col 'No.' not found") + } + + if (!"PAR" %in% colnames(data)) { + stop("required col 'PAR' not found") + } + + if (!"Date" %in% colnames(data)) { + stop("required col 'Date' not found") + } + + if (!"Time" %in% colnames(data)) { + stop("required col 'Time' not found") + } + + if (!"Y.II." %in% colnames(data)) { + stop("required col 'Y(II)' not found") + } + +} + validate_etr_regression_data <- function(regression_data) { if (is.null(regression_data)) { stop("is null") diff --git a/src/inst/extdata/pam_2500_data/20260311_1(2).CSV b/src/inst/extdata/pam_2500_data/20260311_1(2).CSV new file mode 100644 index 0000000..6868c88 --- /dev/null +++ b/src/inst/extdata/pam_2500_data/20260311_1(2).CSV @@ -0,0 +1,18 @@ + +"t";"Date";"Time";"No.";"ML";"Temp.";"PAR";"F";"Fo'";"Fm'";"~Fo'";"Y(II)";"Y(NPQ)";"Y(NO)";"NPQ";"qN";"qP";"qL";"ETR";"Y4S";""; + 2;11.03.26;14:16:47;Type: LC + 4;11.03.26;14:16:48;default_60.par + 2;11.03.26;14:16:47;;1; 0.0;0;0.166;Fo: 0.166;Fm: 0.744 + 2;11.03.26;14:16:47;1;1; 0.0;0; 0.166; 0.000; 0.744; 0.166;0.777;0.000;0.223;0.000;0.000;1.000;1.000; 0.0;0.777 + 12;11.03.26;14:16:57;2;1; 0.0;5; 0.208; 0.194; 0.708; 0.164;0.706;0.014;0.280;0.051;0.111;0.973;0.907; 1.5;0.706 + 42;11.03.26;14:17:27;3;1; 0.0;9; 0.238; 0.184; 0.474; 0.147;0.498;0.182;0.320;0.570;0.498;0.814;0.629; 1.9;0.498 + 72;11.03.26;14:17:57;4;1; 0.0;34; 0.246; 0.180; 0.423; 0.142;0.418;0.251;0.331;0.759;0.580;0.728;0.533; 6.0;0.418 + 102;11.03.26;14:18:27;5;1; 0.0;67; 0.259; 0.174; 0.412; 0.141;0.371;0.281;0.348;0.806;0.588;0.643;0.432; 10.5;0.371 + 132;11.03.26;14:18:57;6;1; 0.0;104; 0.270; 0.168; 0.397; 0.139;0.320;0.317;0.363;0.874;0.604;0.555;0.345; 14.0;0.320 + 162;11.03.26;14:19:27;7;1; 0.0;144; 0.277; 0.177; 0.383; 0.137;0.277;0.351;0.372;0.943;0.644;0.515;0.329; 16.7;0.277 + 192;11.03.26;14:19:57;8;1; 0.0;201; 0.285; 0.172; 0.371; 0.136;0.232;0.385;0.383;1.005;0.656;0.432;0.261; 19.6;0.232 + 222;11.03.26;14:20:27;9;1; 0.0;274; 0.294; 0.169; 0.361; 0.134;0.186;0.419;0.395;1.061;0.668;0.349;0.201; 21.4;0.186 + 252;11.03.26;14:20:57;10;1; 0.0;366; 0.299; 0.171; 0.351; 0.133;0.148;0.450;0.402;1.120;0.689;0.289;0.165; 22.8;0.148 + 282;11.03.26;14:21:27;11;1; 0.0;477; 0.303; 0.170; 0.344; 0.132;0.119;0.474;0.407;1.163;0.699;0.236;0.132; 23.9;0.119 + 312;11.03.26;14:21:57;12;1; 0.0;622; 0.304; 0.169; 0.337; 0.131;0.098;0.493;0.409;1.208;0.709;0.196;0.109; 25.6;0.098 + 329;11.03.26;14:22:14;File: L_260311_141645.PWS diff --git a/src/man/read_junior_pam_data.Rd b/src/man/read_junior_pam_data.Rd index 9a435d3..d33e45c 100644 --- a/src/man/read_junior_pam_data.Rd +++ b/src/man/read_junior_pam_data.Rd @@ -34,7 +34,7 @@ A \code{data.table} containing: } } \description{ -Reads raw CSV files generated by Junior PAM software, calculates electron transport rate (ETR) values, and returns a cleaned dataset. Customization may be needed for non-DualPAM devices. +Reads raw CSV files generated by Junior PAM software, calculates electron transport rate (ETR) values, and returns a cleaned dataset. } \details{ Calculates ETR II using: diff --git a/src/man/read_pam_2500_data.Rd b/src/man/read_pam_2500_data.Rd new file mode 100644 index 0000000..7199f92 --- /dev/null +++ b/src/man/read_pam_2500_data.Rd @@ -0,0 +1,55 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/read_pam_data.R +\name{read_pam_2500_data} +\alias{read_pam_2500_data} +\title{Read and Process PAM 2500 Data} +\usage{ +read_pam_2500_data( + csv_path, + remove_recovery = TRUE, + etr_factor = 0.84, + fraction_photosystem_I = 0.5, + fraction_photosystem_II = 0.5 +) +} +\arguments{ +\item{csv_path}{File path to the CSV file.} + +\item{remove_recovery}{Logical. Removes recovery measurements if \code{TRUE}. Default is \code{TRUE}.} + +\item{etr_factor}{Numeric. Factor for ETR calculation. Default is \code{0.84}.} + +\item{fraction_photosystem_I}{Numeric. Relative distribution of absorbed PAR to photosystem I. Default is \code{0.5}.} + +\item{fraction_photosystem_II}{Numeric. Relative distribution of absorbed PAR to photosystem II. Default is \code{0.5}.} +} +\value{ +A \code{data.table} containing: +\itemize{ + \item \code{par}: Photosynthetically active radiation. + \item \code{yield_1}: Yield for photosystem I. + \item \code{yield_2}: Yield for photosystem II. + \item \code{etr_1}: Calculated ETR for photosystem I. + \item \code{etr_2}: Calculated ETR for photosystem II. +} +} +\description{ +Reads raw CSV files generated by PAM 2500 software, calculates electron transport rate (ETR) values, and returns a cleaned dataset. +} +\details{ +Calculates ETR II using: +\deqn{\text{ETR II} = \text{PAR} \cdot \text{ETR-Factor} \cdot \text{Fraction of Photosystem (II)} \cdot \text{Yield (II)}} + +A detailed documentation can be found under \url{https://github.com/biotoolbox/pam?tab=readme-ov-file} +} +\examples{ +path <- file.path(system.file("extdata/pam_2500_data", package = "pam"), "20260311_1(2).CSV") +data <- read_pam_2500_data(path) +} +\references{ +{ + Heinz Walz GmbH. (2024). \emph{DUAL-PAM-100 DUAL-PAM/F MANUAL, 5th Edition, April 2024, Chapter 7 (pp. 162-172).} + Heinz Walz GmbH, Effeltrich, Germany. + Available at: \url{https://www.walz.com/files/downloads/dualpamed05.pdf} +} +} diff --git a/src/tests/testthat/data/20260311_1(2)_pam_2500.CSV b/src/tests/testthat/data/20260311_1(2)_pam_2500.CSV new file mode 100644 index 0000000..6868c88 --- /dev/null +++ b/src/tests/testthat/data/20260311_1(2)_pam_2500.CSV @@ -0,0 +1,18 @@ + +"t";"Date";"Time";"No.";"ML";"Temp.";"PAR";"F";"Fo'";"Fm'";"~Fo'";"Y(II)";"Y(NPQ)";"Y(NO)";"NPQ";"qN";"qP";"qL";"ETR";"Y4S";""; + 2;11.03.26;14:16:47;Type: LC + 4;11.03.26;14:16:48;default_60.par + 2;11.03.26;14:16:47;;1; 0.0;0;0.166;Fo: 0.166;Fm: 0.744 + 2;11.03.26;14:16:47;1;1; 0.0;0; 0.166; 0.000; 0.744; 0.166;0.777;0.000;0.223;0.000;0.000;1.000;1.000; 0.0;0.777 + 12;11.03.26;14:16:57;2;1; 0.0;5; 0.208; 0.194; 0.708; 0.164;0.706;0.014;0.280;0.051;0.111;0.973;0.907; 1.5;0.706 + 42;11.03.26;14:17:27;3;1; 0.0;9; 0.238; 0.184; 0.474; 0.147;0.498;0.182;0.320;0.570;0.498;0.814;0.629; 1.9;0.498 + 72;11.03.26;14:17:57;4;1; 0.0;34; 0.246; 0.180; 0.423; 0.142;0.418;0.251;0.331;0.759;0.580;0.728;0.533; 6.0;0.418 + 102;11.03.26;14:18:27;5;1; 0.0;67; 0.259; 0.174; 0.412; 0.141;0.371;0.281;0.348;0.806;0.588;0.643;0.432; 10.5;0.371 + 132;11.03.26;14:18:57;6;1; 0.0;104; 0.270; 0.168; 0.397; 0.139;0.320;0.317;0.363;0.874;0.604;0.555;0.345; 14.0;0.320 + 162;11.03.26;14:19:27;7;1; 0.0;144; 0.277; 0.177; 0.383; 0.137;0.277;0.351;0.372;0.943;0.644;0.515;0.329; 16.7;0.277 + 192;11.03.26;14:19:57;8;1; 0.0;201; 0.285; 0.172; 0.371; 0.136;0.232;0.385;0.383;1.005;0.656;0.432;0.261; 19.6;0.232 + 222;11.03.26;14:20:27;9;1; 0.0;274; 0.294; 0.169; 0.361; 0.134;0.186;0.419;0.395;1.061;0.668;0.349;0.201; 21.4;0.186 + 252;11.03.26;14:20:57;10;1; 0.0;366; 0.299; 0.171; 0.351; 0.133;0.148;0.450;0.402;1.120;0.689;0.289;0.165; 22.8;0.148 + 282;11.03.26;14:21:27;11;1; 0.0;477; 0.303; 0.170; 0.344; 0.132;0.119;0.474;0.407;1.163;0.699;0.236;0.132; 23.9;0.119 + 312;11.03.26;14:21:57;12;1; 0.0;622; 0.304; 0.169; 0.337; 0.131;0.098;0.493;0.409;1.208;0.709;0.196;0.109; 25.6;0.098 + 329;11.03.26;14:22:14;File: L_260311_141645.PWS diff --git a/src/tests/testthat/test-read_pam_2500_data.R b/src/tests/testthat/test-read_pam_2500_data.R new file mode 100644 index 0000000..7e1e3ff --- /dev/null +++ b/src/tests/testthat/test-read_pam_2500_data.R @@ -0,0 +1,74 @@ +test_that("read_pam_2500_data 20260311_1(2)_pam_2500.CSV - default", { + test_data_file <- testthat::test_path("data", "20260311_1(2)_pam_2500.CSV") + data <- read_pam_2500_data(test_data_file) + + par <- data$par + expect_equal(par[1], 0) + expect_equal(par[2], 5) + expect_equal(par[3], 9) + expect_equal(par[4], 34) + expect_equal(par[5], 67) + expect_equal(par[6], 104) + expect_equal(par[7], 144) + expect_equal(par[8], 201) + expect_equal(par[9], 274) + expect_equal(par[10], 366) + expect_equal(par[11], 477) + expect_equal(par[12], 622) + + yield_1 <- data$yield_1 + expect_equal(yield_1[1], NA_real_) + expect_equal(yield_1[2], NA_real_) + expect_equal(yield_1[3], NA_real_) + expect_equal(yield_1[4], NA_real_) + expect_equal(yield_1[5], NA_real_) + expect_equal(yield_1[6], NA_real_) + expect_equal(yield_1[7], NA_real_) + expect_equal(yield_1[8], NA_real_) + expect_equal(yield_1[9], NA_real_) + expect_equal(yield_1[10], NA_real_) + expect_equal(yield_1[11], NA_real_) + expect_equal(yield_1[12], NA_real_) + + yield_2 <- data$yield_2 + expect_equal(yield_2[1], 0.777) + expect_equal(yield_2[2], 0.706) + expect_equal(yield_2[3], 0.498) + expect_equal(yield_2[4], 0.418) + expect_equal(yield_2[5], 0.371) + expect_equal(yield_2[6], 0.320) + expect_equal(yield_2[7], 0.277) + expect_equal(yield_2[8], 0.232) + expect_equal(yield_2[9], 0.186) + expect_equal(yield_2[10], 0.148) + expect_equal(yield_2[11], 0.119) + expect_equal(yield_2[12], 0.098) + + etr_1 <- data$etr_1 + expect_equal(etr_1[1], NA_real_) + expect_equal(etr_1[2], NA_real_) + expect_equal(etr_1[3], NA_real_) + expect_equal(etr_1[4], NA_real_) + expect_equal(etr_1[5], NA_real_) + expect_equal(etr_1[6], NA_real_) + expect_equal(etr_1[7], NA_real_) + expect_equal(etr_1[8], NA_real_) + expect_equal(etr_1[9], NA_real_) + expect_equal(etr_1[10], NA_real_) + expect_equal(etr_1[11], NA_real_) + expect_equal(etr_1[12], NA_real_) + + etr_2 <- data$etr_2 + expect_equal(etr_2[1], 0) + expect_equal(etr_2[2], 1.48260) + expect_equal(etr_2[3], 1.88244) + expect_equal(etr_2[4], 5.969040) + expect_equal(etr_2[5], 10.439940) + expect_equal(etr_2[6], 13.97760) + expect_equal(etr_2[7], 16.752960) + expect_equal(etr_2[8], 19.58544) + expect_equal(etr_2[9], 21.404880) + expect_equal(etr_2[10], 22.75056) + expect_equal(etr_2[11], 23.84046) + expect_equal(etr_2[12], 25.601520) +}) \ No newline at end of file From 1897ea21927b73d6df5b43e8f4e1cf059dad8564 Mon Sep 17 00:00:00 2001 From: JulienBoehm <180776296+JulienBoehm@users.noreply.github.com> Date: Thu, 16 Apr 2026 13:30:12 +0200 Subject: [PATCH 02/32] Add tests for read_pam_2500_data with etr_factor and fraction_photosystem parameters --- src/tests/testthat/test-read_pam_2500_data.R | 158 ++++++++++++++++++- 1 file changed, 157 insertions(+), 1 deletion(-) diff --git a/src/tests/testthat/test-read_pam_2500_data.R b/src/tests/testthat/test-read_pam_2500_data.R index 7e1e3ff..5ef4f14 100644 --- a/src/tests/testthat/test-read_pam_2500_data.R +++ b/src/tests/testthat/test-read_pam_2500_data.R @@ -71,4 +71,160 @@ test_that("read_pam_2500_data 20260311_1(2)_pam_2500.CSV - default", { expect_equal(etr_2[10], 22.75056) expect_equal(etr_2[11], 23.84046) expect_equal(etr_2[12], 25.601520) -}) \ No newline at end of file +}) + +test_that("read_pam_2500_data 20260311_1(2)_pam_2500.CSV - etr-factor 0.5", { + test_data_file <- testthat::test_path("data", "20260311_1(2)_pam_2500.CSV") + data <- read_pam_2500_data(test_data_file, etr_factor = 0.5) + + par <- data$par + expect_equal(par[1], 0) + expect_equal(par[2], 5) + expect_equal(par[3], 9) + expect_equal(par[4], 34) + expect_equal(par[5], 67) + expect_equal(par[6], 104) + expect_equal(par[7], 144) + expect_equal(par[8], 201) + expect_equal(par[9], 274) + expect_equal(par[10], 366) + expect_equal(par[11], 477) + expect_equal(par[12], 622) + + yield_1 <- data$yield_1 + expect_equal(yield_1[1], NA_real_) + expect_equal(yield_1[2], NA_real_) + expect_equal(yield_1[3], NA_real_) + expect_equal(yield_1[4], NA_real_) + expect_equal(yield_1[5], NA_real_) + expect_equal(yield_1[6], NA_real_) + expect_equal(yield_1[7], NA_real_) + expect_equal(yield_1[8], NA_real_) + expect_equal(yield_1[9], NA_real_) + expect_equal(yield_1[10], NA_real_) + expect_equal(yield_1[11], NA_real_) + expect_equal(yield_1[12], NA_real_) + + yield_2 <- data$yield_2 + expect_equal(yield_2[1], 0.777) + expect_equal(yield_2[2], 0.706) + expect_equal(yield_2[3], 0.498) + expect_equal(yield_2[4], 0.418) + expect_equal(yield_2[5], 0.371) + expect_equal(yield_2[6], 0.320) + expect_equal(yield_2[7], 0.277) + expect_equal(yield_2[8], 0.232) + expect_equal(yield_2[9], 0.186) + expect_equal(yield_2[10], 0.148) + expect_equal(yield_2[11], 0.119) + expect_equal(yield_2[12], 0.098) + + etr_1 <- data$etr_1 + expect_equal(etr_1[1], NA_real_) + expect_equal(etr_1[2], NA_real_) + expect_equal(etr_1[3], NA_real_) + expect_equal(etr_1[4], NA_real_) + expect_equal(etr_1[5], NA_real_) + expect_equal(etr_1[6], NA_real_) + expect_equal(etr_1[7], NA_real_) + expect_equal(etr_1[8], NA_real_) + expect_equal(etr_1[9], NA_real_) + expect_equal(etr_1[10], NA_real_) + expect_equal(etr_1[11], NA_real_) + expect_equal(etr_1[12], NA_real_) + + etr_2 <- data$etr_2 + expect_equal(etr_2[1], 0) + expect_equal(etr_2[2], 0.8825) + expect_equal(etr_2[3], 1.12050) + expect_equal(etr_2[4], 3.553) + expect_equal(etr_2[5], 6.21425) + expect_equal(etr_2[6], 8.320) + expect_equal(etr_2[7], 9.972) + expect_equal(etr_2[8], 11.658) + expect_equal(etr_2[9], 12.741) + expect_equal(etr_2[10], 13.542) + expect_equal(etr_2[11], 14.190750) + expect_equal(etr_2[12], 15.239) +}) + +test_that("read_pam_2500_data 20260311_1(2)_pam_2500.CSV - - fraction_photosystem_I = 0.2, fraction_photosystem_II = 0.8", { + test_data_file <- testthat::test_path("data", "20260311_1(2)_pam_2500.CSV") + data <- read_pam_2500_data(test_data_file, etr_factor = 0.5) + expect_error(read_pam_2000_data(test_data_file, fraction_photosystem_I = 0.9, fraction_photosystem_II = 0.2)) +}) + +test_that("read_pam_2500_data 20260311_1(2)_pam_2500.CSV - fraction_photosystem_I = 0.2, fraction_photosystem_II = 0.8", { + test_data_file <- testthat::test_path("data", "20260311_1(2)_pam_2500.CSV") + data <- read_pam_2500_data(test_data_file, fraction_photosystem_I = 0.2, fraction_photosystem_II = 0.8) + + par <- data$par + expect_equal(par[1], 0) + expect_equal(par[2], 5) + expect_equal(par[3], 9) + expect_equal(par[4], 34) + expect_equal(par[5], 67) + expect_equal(par[6], 104) + expect_equal(par[7], 144) + expect_equal(par[8], 201) + expect_equal(par[9], 274) + expect_equal(par[10], 366) + expect_equal(par[11], 477) + expect_equal(par[12], 622) + + yield_1 <- data$yield_1 + expect_equal(yield_1[1], NA_real_) + expect_equal(yield_1[2], NA_real_) + expect_equal(yield_1[3], NA_real_) + expect_equal(yield_1[4], NA_real_) + expect_equal(yield_1[5], NA_real_) + expect_equal(yield_1[6], NA_real_) + expect_equal(yield_1[7], NA_real_) + expect_equal(yield_1[8], NA_real_) + expect_equal(yield_1[9], NA_real_) + expect_equal(yield_1[10], NA_real_) + expect_equal(yield_1[11], NA_real_) + expect_equal(yield_1[12], NA_real_) + + yield_2 <- data$yield_2 + expect_equal(yield_2[1], 0.777) + expect_equal(yield_2[2], 0.706) + expect_equal(yield_2[3], 0.498) + expect_equal(yield_2[4], 0.418) + expect_equal(yield_2[5], 0.371) + expect_equal(yield_2[6], 0.320) + expect_equal(yield_2[7], 0.277) + expect_equal(yield_2[8], 0.232) + expect_equal(yield_2[9], 0.186) + expect_equal(yield_2[10], 0.148) + expect_equal(yield_2[11], 0.119) + expect_equal(yield_2[12], 0.098) + + etr_1 <- data$etr_1 + expect_equal(etr_1[1], NA_real_) + expect_equal(etr_1[2], NA_real_) + expect_equal(etr_1[3], NA_real_) + expect_equal(etr_1[4], NA_real_) + expect_equal(etr_1[5], NA_real_) + expect_equal(etr_1[6], NA_real_) + expect_equal(etr_1[7], NA_real_) + expect_equal(etr_1[8], NA_real_) + expect_equal(etr_1[9], NA_real_) + expect_equal(etr_1[10], NA_real_) + expect_equal(etr_1[11], NA_real_) + expect_equal(etr_1[12], NA_real_) + + etr_2 <- data$etr_2 + expect_equal(etr_2[1], 0) + expect_equal(etr_2[2], 2.37216) + expect_equal(etr_2[3], 3.011904) + expect_equal(etr_2[4], 9.5504640) + expect_equal(etr_2[5], 16.7039040) + expect_equal(etr_2[6], 22.36416) + expect_equal(etr_2[7], 26.804736) + expect_equal(etr_2[8], 31.3367040) + expect_equal(etr_2[9], 34.2478080) + expect_equal(etr_2[10], 36.4008960) + expect_equal(etr_2[11], 38.1447360) + expect_equal(etr_2[12], 40.9624320) +}) From b5d4d709a45895842ebb59d3cdb2ca8692ce7607 Mon Sep 17 00:00:00 2001 From: JulienBoehm <180776296+JulienBoehm@users.noreply.github.com> Date: Thu, 16 Apr 2026 15:31:03 +0200 Subject: [PATCH 03/32] Update README to include details for read_pam_2500_data function and its parameters --- README.md | 75 ++++++++++++++++++++++++++++++++++++++++++++++++++----- 1 file changed, 69 insertions(+), 6 deletions(-) diff --git a/README.md b/README.md index 8e3e7cd..1323bb5 100644 --- a/README.md +++ b/README.md @@ -96,9 +96,7 @@ fraction_photosystem_II = 0.5) #### Description -This function reads the original CSV file as created by the DualPAM software, processes it by calculating $$ETR$$ values, and returns a cleaned dataset. -Functionality with raw data from other PAM devices cannot be guaranteed. -Individual customisation may be necessary when reading data. +This function reads the original CSV file as created by the [DUAL-PAM-100](https://www.walz.com/products/dual-pam-100/) software, processes it by calculating $$ETR$$ values, and returns a cleaned dataset. #### Parameters @@ -149,9 +147,7 @@ fraction_photosystem_II = 0.5) #### Description -This function reads the original CSV file as created by the WinControl software, processes it by calculating $$ETR$$ values, and returns a cleaned dataset. -Functionality with raw data from other PAM devices cannot be guaranteed. -Individual customisation may be necessary when reading data. +This function reads the original CSV file from [JUNIOR-PAM](https://www.walz.com/products/junior-pam/) as created by the WinControl software, processes it by calculating $$ETR$$ values, and returns a cleaned dataset. #### Parameters @@ -197,6 +193,73 @@ fraction_photosystem_II = 0.5) - Heinz Walz GmbH. (2024). *DUAL-PAM-100 DUAL-PAM/F MANUAL, 5th Edition, April 2024, Chapter 7 (pp. 162-172).* Heinz Walz GmbH, Effeltrich, Germany. Available at: [DUAL-PAM-100 Manual](https://www.walz.com/files/downloads/dualpamed05.pdf) +### read_pam_2500_data() + +#### Description + +This function reads the original CSV file generated by the [PAM-2500](https://www.walz.com/products/pam-2500/) software, processes it by calculating $$ETR$$ values for Photosystem II, and returns a cleaned dataset. + +#### Parameters + +- **csv_path**: A string representing the file path to the CSV file. +- **remove_recovery**: Logical value indicating whether recovery measurements after the actual Pi curve should be removed. Default is `TRUE`. +- **etr_factor**: A numeric value used as a factor for calculating ETR. Default is `0.84`. +- **fraction_photosystem_I**: A numeric value representing the relative distribution of absorbed PAR to photosystem I. Default is `0.5`. + Calculated as: $$\textit{Fraction of Photosystem I} = \frac{PPS 1}{PPS 1+2}$$ +- **fraction_photosystem_II**: A numeric value representing the relative distribution of absorbed PAR to photosystem II. Default is `0.5`. + Calculated as: $$\textit{Fraction of Photosystem II} = \frac{PPS 2}{PPS 1+2}$$ + +--- + +#### Details + +ETR values are calculated using the following formula: + +$$ \textit{ETR (II)} = PAR \cdot \textit{ETR–Factor} \cdot \textit{Fraction of Photosystem II} \cdot \textit{Yield (II)} $$ + +The function processes the provided CSV file by: + +- Reading the CSV file using `read.csv()` with `;` as separator and converting it to a `data.table`. +- Validating the dataset using `validate_pam_2500_data()`. +- Filtering rows where the column `No.` contains numeric entries only. +- Combining the `Date` and `Time` columns into a `DateTime` column and sorting the dataset chronologically. +- Iterating through all rows to: + - Extract `PAR` and `Y.II.` values. + - Calculate ETR for Photosystem II using `calc_etr()`. +- Optionally stopping at the recovery phase if `remove_recovery = TRUE`, defined as a decrease in PAR values. +- Constructing a result table with calculated values. + +--- + +#### Return + +- A `data.table` containing the following columns: + + - `par`: Photosynthetically active radiation + - `yield_1`: Placeholder column (`NA`) + - `yield_2`: Effective quantum yield of Photosystem II + - `etr_1`: Placeholder column (`NA`) + - `etr_2`: Calculated electron transport rate for Photosystem II + +--- + +#### Example + +```r +data <- read_pam_2500_data( + "path/to/data.csv", + remove_recovery = TRUE, + etr_factor = 0.84, + fraction_photosystem_I = 0.5, + fraction_photosystem_II = 0.5 +) +``` + +#### References + +- Heinz Walz GmbH. (2024). *DUAL-PAM-100 DUAL-PAM/F MANUAL, 5th Edition, April 2024, Chapter 7 (pp. 162-172).* Heinz Walz GmbH, Effeltrich, Germany. Available at: [DUAL-PAM-100 Manual](https://www.walz.com/files/downloads/dualpamed05.pdf) + + ### vollenweider_generate_regression_ETR_I() and vollenweider_generate_regression_ETR_II() This function generates a regression model based on Vollenweider (1965). Original naming conventions from the publication are used. From b350fd589b08ab6eb15a2796e01d634799f80a6e Mon Sep 17 00:00:00 2001 From: JulienBoehm <180776296+JulienBoehm@users.noreply.github.com> Date: Thu, 16 Apr 2026 15:38:55 +0200 Subject: [PATCH 04/32] README cleanup --- README.md | 35 ++++++++++++++++++++++++++++++++--- 1 file changed, 32 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index 1323bb5..759f62a 100644 --- a/README.md +++ b/README.md @@ -44,6 +44,8 @@ install.packages("pam") Examples of usage can be found in the `examples` directory. +--- + ## Functions ### read_universal_data() @@ -91,6 +93,7 @@ fraction_photosystem_II = 0.5) - Heinz Walz GmbH. (2024). *DUAL-PAM-100 DUAL-PAM/F MANUAL, 5th Edition, April 2024, Chapter 7 (pp. 162-172).* Heinz Walz GmbH, Effeltrich, Germany. Available at: [DUAL-PAM-100 Manual](https://www.walz.com/files/downloads/dualpamed05.pdf) +--- ### read_dual_pam_data() @@ -143,6 +146,8 @@ fraction_photosystem_II = 0.5) - Heinz Walz GmbH. (2024). *DUAL-PAM-100 DUAL-PAM/F MANUAL, 5th Edition, April 2024, Chapter 7 (pp. 162-172).* Heinz Walz GmbH, Effeltrich, Germany. Available at: [DUAL-PAM-100 Manual](https://www.walz.com/files/downloads/dualpamed05.pdf) +--- + ### read_junior_pam_data() #### Description @@ -193,6 +198,8 @@ fraction_photosystem_II = 0.5) - Heinz Walz GmbH. (2024). *DUAL-PAM-100 DUAL-PAM/F MANUAL, 5th Edition, April 2024, Chapter 7 (pp. 162-172).* Heinz Walz GmbH, Effeltrich, Germany. Available at: [DUAL-PAM-100 Manual](https://www.walz.com/files/downloads/dualpamed05.pdf) +--- + ### read_pam_2500_data() #### Description @@ -209,7 +216,6 @@ This function reads the original CSV file generated by the [PAM-2500](https://ww - **fraction_photosystem_II**: A numeric value representing the relative distribution of absorbed PAR to photosystem II. Default is `0.5`. Calculated as: $$\textit{Fraction of Photosystem II} = \frac{PPS 2}{PPS 1+2}$$ ---- #### Details @@ -229,7 +235,6 @@ The function processes the provided CSV file by: - Optionally stopping at the recovery phase if `remove_recovery = TRUE`, defined as a decrease in PAR values. - Constructing a result table with calculated values. ---- #### Return @@ -241,7 +246,6 @@ The function processes the provided CSV file by: - `etr_1`: Placeholder column (`NA`) - `etr_2`: Calculated electron transport rate for Photosystem II ---- #### Example @@ -259,6 +263,7 @@ data <- read_pam_2500_data( - Heinz Walz GmbH. (2024). *DUAL-PAM-100 DUAL-PAM/F MANUAL, 5th Edition, April 2024, Chapter 7 (pp. 162-172).* Heinz Walz GmbH, Effeltrich, Germany. Available at: [DUAL-PAM-100 Manual](https://www.walz.com/files/downloads/dualpamed05.pdf) +--- ### vollenweider_generate_regression_ETR_I() and vollenweider_generate_regression_ETR_II() @@ -340,6 +345,8 @@ result_vollenweider_ETR_II <- vollenweider_generate_regression_ETR_II(data, Vollenweider, R. A. (1965). *Calculation models of photosynthesis-depth curves and some implications regarding day rate estimates in primary production measurements*, p. 427-457. In C. R. Goldman [ed.], *Primary Productivity in Aquatic Environments*. Mem. Ist. Ital. Idrobiol., 18 Suppl., University of California Press, Berkeley. +--- + ### platt_generate_regression_ETR_I() and platt_generate_regression_ETR_II() This function generates a regression model based on Platt (1980). Original naming conventions from the publication are used. @@ -403,6 +410,8 @@ result_platt_ETR_II <- platt_generate_regression_ETR_II(data, Platt, T., Gallegos, C. L., & Harrison, W. G. (1980). *Photoinhibition of photosynthesis in natural assemblages of marine phytoplankton*. Journal of Marine Research, 38(4). Retrieved from . +--- + ### eilers_peeters_generate_regression_ETR_I() and eilers_peeters_generate_regression_ETR_II() This function generates a regression model based on Eilers-Peeters (1988). Original naming conventions from the publication are used. All parameters are calculated taking photoinhibition into account. @@ -466,6 +475,8 @@ c_start_value = 5) Eilers, P. H. C., & Peeters, J. C. H. (1988). *A model for the relationship between light intensity and the rate of photosynthesis in phytoplankton.* Ecological Modelling, 42(3-4), 199-215. [doi:10.1016/0304-3800(88)90057-9](https://doi.org/10.1016/0304-3800(88)90057-9). +--- + ### walsby_generate_regression_ETR_I() and walsby_generate_regression_ETR_II() This function generates a regression model based on Walsby (1997) in a modified version without the respiration term. Naming conventions from Romoth (2019) are used. ETRmax is calculated without taking photoinhibition into account. @@ -503,6 +514,8 @@ Walsby, A. E. (1997). Numerical integration of phytoplankton photosynthesis thro Romoth, K., Nowak, P., Kempke, D., Dietrich, A., Porsche, C., & Schubert, H. (2019). Acclimation limits of *Fucus evanescens* along the salinity gradient of the southwestern Baltic Sea. *Botanica Marina*, 62(1), 1-12. +--- + ### vollenweider_modified() This function adds parameters that were not originally included in the Vollenweider (1965) model, but were introduced by other models and renames the parameters to a standardised one for all models. See the table below. @@ -553,6 +566,7 @@ This function validates the `model_result` input and processes relevant paramete ```r modified_result_vollenweider <- vollenweider_modified(model_result_vollenweider) ``` +--- ### platt_modified() @@ -598,6 +612,8 @@ This function validates the `model_result` input and processes relevant paramete modified_result_platt <- platt_modified(model_result_platt) ``` +--- + ### eilers_peeters_modified() This function adds parameters that were not originally included in the Eilers and Peeters (1988) model, but were introduced by other models and renames the parameters to a standardised one for all models. See the table below. @@ -640,6 +656,7 @@ This function validates the `model_result` input, extracts relevant parameters f # Example usage for eilers_peeters_modified modified_result <- eilers_peeters_modified(model_result_eilers_peeters) ``` +--- ### walsby_modified() @@ -704,6 +721,7 @@ This function validates the `model_result` input and processes relevant paramete ```r modified_result <- walsby_modified(model_result_walsby) ``` +--- ### Naming overview @@ -729,6 +747,8 @@ modified |Eilers and Peeters |Platt |Walsby |Vollenweider |ib |NA |ib |NA |NA | |etrmax_without_with_ratio |NA |NA |NA |pmax_popt_and_ik_iik_ratio | +--- + #### Publication-accurate naming and the respective modified naming with additional calculations not included in the original publication |modified |Eilers and Peeters |Platt |Walsby |Vollenweider | @@ -751,6 +771,8 @@ modified |Eilers and Peeters |Platt |Walsby |Vollenweider |ib |NA |ib |NA |NA | |etrmax_without_with_ratio |NA |etrmax_without_with_ratio |etrmax_without_with_ratio |pmax_popt_and_ik_iik_ratio | +--- + ### compare_regression_models_ETR_I() and compare_regression_models_ETR_II() This function compares different regression models. @@ -796,6 +818,8 @@ Vollenweider, R. A. (1965). *Calculation models of photosynthesis-depth curves a Walsby, A. E. (1997). Numerical integration of phytoplankton photosynthesis through time and depth in a water column. *New Phytologist*, 136(2), 189-209. +--- + ### plot_control() This function creates a control plot for the used model based on the provided data and model results. @@ -825,6 +849,8 @@ print(plot_control_eilers_peeters_ETR_II) ![Plot](test-eilers_peeters_etr_II_modified_control_plot_20240925.jpg) +--- + ### combo_plot_control() The `combo_plot_control()` function generates a combined plot of electron transport rate (ETR) data and regression model predictions, along with a customized table summarizing the parameters for each model. @@ -863,6 +889,8 @@ test_data_file <- file.path(getwd(), "data", "20240925.csv") ![combo Plot](test_combo_plot_control_etr_II.jpg) +--- + ### write_model_result_csv() This function exports the raw input data, regression data, and model parameters into separate CSV files for easy access and further analysis. @@ -894,6 +922,7 @@ write_model_result_csv( model_result = model_result_eilers_peeters ) ``` +--- ### known issues From a9fad9aebe839c513d76bf2c6132ffafe83eaad8 Mon Sep 17 00:00:00 2001 From: JulienBoehm <180776296+JulienBoehm@users.noreply.github.com> Date: Thu, 16 Apr 2026 16:40:20 +0200 Subject: [PATCH 05/32] Add read_dual_pam_data_single_channel_II function, and tests --- src/NAMESPACE | 1 + src/R/read_pam_data.R | 127 ++++++++++++++++++ src/R/validation.R | 46 +++++++ .../20260130_efeutute_dual_pam_only_ps_2.csv | 16 +++ .../read_dual_pam_data_single_channel_II.Rd | 55 ++++++++ ...est-read_dual_pam_data_single_channel_II.R | 69 ++++++++++ 6 files changed, 314 insertions(+) create mode 100644 src/inst/extdata/20260130_efeutute_dual_pam_only_ps_2.csv create mode 100644 src/man/read_dual_pam_data_single_channel_II.Rd create mode 100644 src/tests/testthat/test-read_dual_pam_data_single_channel_II.R diff --git a/src/NAMESPACE b/src/NAMESPACE index f12344a..5ee9989 100644 --- a/src/NAMESPACE +++ b/src/NAMESPACE @@ -17,6 +17,7 @@ export(platt_generate_regression_ETR_II) export(platt_modified) export(plot_control) export(read_dual_pam_data) +export(read_dual_pam_data_single_channel_II) export(read_junior_pam_data) export(read_pam_2500_data) export(read_universal_data) diff --git a/src/R/read_pam_data.R b/src/R/read_pam_data.R index c8b4a22..100ed79 100644 --- a/src/R/read_pam_data.R +++ b/src/R/read_pam_data.R @@ -210,6 +210,133 @@ read_dual_pam_data <- function( ) } +#' Read and Process DualPAM Data Single Chanel Mode Photosystem II +#' +#' Reads raw CSV files generated by DualPAM software, calculates electron transport rate (ETR) values for Photosystem II, and returns a universal dataset. +#' +#' @param csv_path File path to the CSV file. +#' @param remove_recovery Logical. Removes recovery measurements if \code{TRUE}. Default is \code{TRUE}. +#' @param etr_factor Numeric. Factor for ETR calculation. Default is \code{0.84}. +#' @param fraction_photosystem_I Numeric. Relative distribution of absorbed PAR to photosystem I. Default is \code{0.5}. +#' @param fraction_photosystem_II Numeric. Relative distribution of absorbed PAR to photosystem II. Default is \code{0.5}. +#' +#' @details +#' Calculates ETR using: +#' \deqn{\text{ETR} = \text{PAR} \cdot \text{ETR-Factor} \cdot \text{Fraction of Photosystem (II)} \cdot \text{Yield (II)}} +#' +#' A detailed documentation can be found under \url{https://github.com/biotoolbox/pam?tab=readme-ov-file#read_dual_pam_data} +#' +#' @return A \code{data.table} containing: +#' \itemize{ +#' \item \code{par}: Photosynthetically active radiation. +#' \item \code{yield_1}: NA +#' \item \code{yield_2}: Yield for photosystem II. +#' \item \code{etr_1}: NA +#' \item \code{etr_2}: Calculated ETR for photosystem II. +#' } +#' +#' @references{ +#' Heinz Walz GmbH. (2024). \emph{DUAL-PAM-100 DUAL-PAM/F MANUAL, 5th Edition, April 2024, Chapter 7 (pp. 162-172).} +#' Heinz Walz GmbH, Effeltrich, Germany. +#' Available at: \url{https://www.walz.com/files/downloads/dualpamed05.pdf} +#' } +#' @examples +#' path <- file.path(system.file("extdata", package = "pam"), "20260130_efeutute_dual_pam_only_ps_2.csv") +#' data <- read_dual_pam_data_single_channel_II(path) +#' @export +read_dual_pam_data_single_channel_II <- function( + csv_path, + remove_recovery = TRUE, + etr_factor = 0.84, + fraction_photosystem_I = 0.5, + fraction_photosystem_II = 0.5) { + if (fraction_photosystem_I + fraction_photosystem_II != 1) { + stop("The sum of fraction_photosystem_I and fraction_photosystem_II must be equal 1.") + } + + tryCatch( + { + data <- utils::read.csv(csv_path, sep = ";", dec = ".") + data <- data.table::as.data.table(data) + + validate_dual_pam_data_single_channel_II(data) + data <- data[data$ID == "SP", ] + + date_time_col_values <- c() + for (i in seq_len(nrow(data))) { + row <- data[i, ] + + date_time_row_value <- as.POSIXct( + paste(row$Date, row$Time, sep = " "), + tz = "GMT", "%d.%m.%y %H:%M:%S" + ) + date_time_col_values <- c(date_time_col_values, date_time_row_value) + } + + data$DateTime <- date_time_col_values + data <- data[order(data$DateTime), ] + + fm_det_row <- subset(data, data$PAR == 0 & data$Action == "Fm-Det.") + yield_2_first <- fm_det_row$Y.II. + recalc_etr_2 <- calc_etr(yield_2_first, 0, etr_factor, fraction_photosystem_II) + + + result <- data.table::data.table( + par = numeric(), + yield_1 = numeric(), + yield_2 = numeric(), + etr_1 = numeric(), + etr_2 = numeric() + ) + new_row <- list( + par = 0, + yield_1 = NA_real_, + yield_2 = yield_2_first, + etr_1 = NA_real_, + etr_2 = recalc_etr_2 + ) + result <- rbind(result, new_row) + + last_par <- as.numeric(0) + for (i in seq_len(nrow(data))) { + row <- data[i, ] + current_par <- row$PAR + + if (row$Action != "Fluo. SP") { + next + } + + if (remove_recovery && last_par != 0 && current_par < last_par) { + break + } + + yield_2 <- row$Y.II. + recalc_etr_2 <- calc_etr(yield_2, current_par, etr_factor, fraction_photosystem_II) + + new_row <- list( + par = current_par, + yield_1 = NA_real_, + yield_2 = yield_2, + etr_1 = NA_real_, + etr_2 = recalc_etr_2 + ) + result <- rbind(result, new_row) + + last_par <- current_par + } + + validate_data(result) + return(result) + }, + warning = function(w) { + stop("Warning in file: ", csv_path, " Warning: ", w) + }, + error = function(e) { + stop("Error in file: ", csv_path, " Error: ", e) + } + ) +} + calc_etr <- function(yield, par, etr_factor, p_ratio) { if (is.na(yield)) { return(NA_real_) diff --git a/src/R/validation.R b/src/R/validation.R index bee93c9..cafb252 100644 --- a/src/R/validation.R +++ b/src/R/validation.R @@ -100,6 +100,52 @@ validate_dual_pam_data <- function(data) { } } +validate_dual_pam_data_single_channel_II <- function(data) { + if (is.null(data)) { + stop("data is null") + } + + if (!data.table::is.data.table(data)) { + stop("data is not a valid data.table") + } + + if (nrow(data) < 2) { + stop("no data rows") + } + + if (ncol(data) == 0) { + stop("no cols in data") + } + + if (!"ID" %in% colnames(data)) { + stop("required col 'ID' not found") + } + + if (!"PAR" %in% colnames(data)) { + stop("required col 'PAR' not found") + } + + if (!"Y.II." %in% colnames(data)) { + stop("required col 'Y(II)' not found") + } + + if (!"Action" %in% colnames(data)) { + stop("required col 'Action' not found") + } + + if (!"Date" %in% colnames(data)) { + stop("required col 'Date' not found") + } + + if (!"Time" %in% colnames(data)) { + stop("required col 'Time' not found") + } + + if (!"Fm-Det." %in% data[["Action"]]) { + stop("required value 'Fm' not found in column 'Action'") + } +} + validate_junior_pam_data <- function(data) { if (is.null(data)) { stop("data is null") diff --git a/src/inst/extdata/20260130_efeutute_dual_pam_only_ps_2.csv b/src/inst/extdata/20260130_efeutute_dual_pam_only_ps_2.csv new file mode 100644 index 0000000..4427b93 --- /dev/null +++ b/src/inst/extdata/20260130_efeutute_dual_pam_only_ps_2.csv @@ -0,0 +1,16 @@ +"Date";"Time";"Action";"ID";"Name";"Temp";"PAR";"F(I)/Fo calc";"F(I)";"Fo,Fo'";"Fm,Fm'";"FMTm";"F";"Y(II)";"Y(4S)";"k/ocs";"ETR(II)";"Y(NO)";"Y(NPQ)";"NPQ";"qN";"qP";"qL";"F/Fm";"Fm'/Fm";"P700ox";"P700m,P700m'";"Y(I)";"Y(ND)";"Y(NA)";"ETR(I)"; +30.01.26;10:49:51;LC-Start;LCB;LC1;;;;;;;;;;;;;;;;;;;;;;;;;;; +30.01.26;10:49:51;Manual;SK;S_260130_104951; 0.0;0;;;;;;;;;;;;;;;;;;;;;;;;; +30.01.26;10:49:52;Fo-Det.;Fo;;n.c.;0;;0.0000;0.4025;;;;;;;;;;;;;;;;;;;;;; +30.01.26;10:49:53;Fm-Det.;SP;F_260130_104953_0;n.c.;0;;0.0000;0.4025;1.7295;;0.4001;0.767;;;0.000;0.233;0.000;0.000;0.000;1.000;1.000;0.231;1.000;;;;;;; +30.01.26;10:50:26;Fluo. SP;SP;F_260130_105026_0;n.c.;39;;0.0000;0.3414;0.9772;;0.6443;0.341;;;5.580;0.373;0.287;0.770;0.521;0.524;0.277;0.373;0.565;;;;;;; +30.01.26;10:50:56;Fluo. SP;SP;F_260130_105056_0;n.c.;49;;0.0000;0.3222;0.8350;;0.5725;0.314;;;6.471;0.331;0.355;1.071;0.614;0.512;0.288;0.331;0.483;;;;;;; +30.01.26;10:51:26;Fluo. SP;SP;F_260130_105126_0;n.c.;62;;0.0000;0.3092;0.7531;;0.5378;0.286;;;7.445;0.311;0.403;1.296;0.665;0.485;0.279;0.311;0.435;;;;;;; +30.01.26;10:51:56;Fluo. SP;SP;F_260130_105156_0;n.c.;113;;0.0000;0.2986;0.6930;;0.5534;0.201;;;9.560;0.320;0.479;1.496;0.703;0.354;0.191;0.320;0.401;;;;;;; +30.01.26;10:52:26;Fluo. SP;SP;F_260130_105226_0;n.c.;185;;0.0000;0.2934;0.6657;;0.5730;0.139;;;10.828;0.331;0.529;1.598;0.719;0.249;0.128;0.331;0.385;;;;;;; +30.01.26;10:52:56;Fluo. SP;SP;F_260130_105256_0;n.c.;241;;0.0000;0.2909;0.6528;;0.5795;0.112;;;11.368;0.335;0.553;1.649;0.727;0.203;0.102;0.335;0.377;;;;;;; +30.01.26;10:53:26;Fluo. SP;SP;F_260130_105326_0;n.c.;397;;0.0000;0.2892;0.6444;;0.5983;0.072;;;11.924;0.346;0.583;1.684;0.732;0.130;0.063;0.346;0.373;;;;;;; +30.01.26;10:53:56;Fluo. SP;SP;F_260130_105356_0;n.c.;614;;0.0000;0.2883;0.6401;;0.6092;0.048;;;12.431;0.352;0.600;1.702;0.735;0.088;0.042;0.352;0.370;;;;;;; +30.01.26;10:54:26;Fluo. SP;SP;F_260130_105426_0;n.c.;946;;0.0000;0.2877;0.6371;;0.6167;0.032;;;12.665;0.357;0.612;1.715;0.737;0.058;0.027;0.357;0.368;;;;;;; +30.01.26;10:54:56;Fluo. SP;SP;F_260130_105456_0;n.c.;1453;;0.0000;0.2872;0.6348;;0.6220;0.020;;;12.317;0.360;0.620;1.724;0.738;0.037;0.017;0.360;0.367;;;;;;; +30.01.26;10:54:59;LC-Stop;LCE;LC1;;;;;;;;;;;;;;;;;;;;;;;;;;; diff --git a/src/man/read_dual_pam_data_single_channel_II.Rd b/src/man/read_dual_pam_data_single_channel_II.Rd new file mode 100644 index 0000000..6f5cf63 --- /dev/null +++ b/src/man/read_dual_pam_data_single_channel_II.Rd @@ -0,0 +1,55 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/read_pam_data.R +\name{read_dual_pam_data_single_channel_II} +\alias{read_dual_pam_data_single_channel_II} +\title{Read and Process DualPAM Data Single Chanel Mode Photosystem II} +\usage{ +read_dual_pam_data_single_channel_II( + csv_path, + remove_recovery = TRUE, + etr_factor = 0.84, + fraction_photosystem_I = 0.5, + fraction_photosystem_II = 0.5 +) +} +\arguments{ +\item{csv_path}{File path to the CSV file.} + +\item{remove_recovery}{Logical. Removes recovery measurements if \code{TRUE}. Default is \code{TRUE}.} + +\item{etr_factor}{Numeric. Factor for ETR calculation. Default is \code{0.84}.} + +\item{fraction_photosystem_I}{Numeric. Relative distribution of absorbed PAR to photosystem I. Default is \code{0.5}.} + +\item{fraction_photosystem_II}{Numeric. Relative distribution of absorbed PAR to photosystem II. Default is \code{0.5}.} +} +\value{ +A \code{data.table} containing: +\itemize{ + \item \code{par}: Photosynthetically active radiation. + \item \code{yield_1}: NA + \item \code{yield_2}: Yield for photosystem II. + \item \code{etr_1}: NA + \item \code{etr_2}: Calculated ETR for photosystem II. +} +} +\description{ +Reads raw CSV files generated by DualPAM software, calculates electron transport rate (ETR) values for Photosystem II, and returns a universal dataset. +} +\details{ +Calculates ETR using: +\deqn{\text{ETR} = \text{PAR} \cdot \text{ETR-Factor} \cdot \text{Fraction of Photosystem (II)} \cdot \text{Yield (II)}} + +A detailed documentation can be found under \url{https://github.com/biotoolbox/pam?tab=readme-ov-file#read_dual_pam_data} +} +\examples{ +path <- file.path(system.file("extdata", package = "pam"), "20260130_efeutute_dual_pam_only_ps_2.csv") +data <- read_dual_pam_data_single_channel_II(path) +} +\references{ +{ + Heinz Walz GmbH. (2024). \emph{DUAL-PAM-100 DUAL-PAM/F MANUAL, 5th Edition, April 2024, Chapter 7 (pp. 162-172).} + Heinz Walz GmbH, Effeltrich, Germany. + Available at: \url{https://www.walz.com/files/downloads/dualpamed05.pdf} +} +} diff --git a/src/tests/testthat/test-read_dual_pam_data_single_channel_II.R b/src/tests/testthat/test-read_dual_pam_data_single_channel_II.R new file mode 100644 index 0000000..7890bb5 --- /dev/null +++ b/src/tests/testthat/test-read_dual_pam_data_single_channel_II.R @@ -0,0 +1,69 @@ +test_that("read_dual_pam_data 20260130_efeutute_dual_pam_only_ps_2 - default", { + test_data_file <- testthat::test_path("data", "20260130_efeutute_dual_pam_only_ps_2.csv") + data <- read_dual_pam_data_single_channel_II(test_data_file) + + par <- data$par + expect_equal(par[1], 0) + expect_equal(par[2], 39) + expect_equal(par[3], 49) + expect_equal(par[4], 62) + expect_equal(par[5], 113) + expect_equal(par[6], 185) + expect_equal(par[7], 241) + expect_equal(par[8], 397) + expect_equal(par[9], 614) + expect_equal(par[10], 946) + expect_equal(par[11], 1453) + + yield_1 <- data$yield_1 + expect_equal(yield_1[1], NA_real_) + expect_equal(yield_1[2], NA_real_) + expect_equal(yield_1[3], NA_real_) + expect_equal(yield_1[4], NA_real_) + expect_equal(yield_1[5], NA_real_) + expect_equal(yield_1[6], NA_real_) + expect_equal(yield_1[7], NA_real_) + expect_equal(yield_1[8], NA_real_) + expect_equal(yield_1[9], NA_real_) + expect_equal(yield_1[10], NA_real_) + expect_equal(yield_1[11], NA_real_) + + yield_2 <- data$yield_2 + expect_equal(yield_2[1], 0.7670) + expect_equal(yield_2[2], 0.3410) + expect_equal(yield_2[3], 0.3140) + expect_equal(yield_2[4], 0.2860) + expect_equal(yield_2[5], 0.2010) + expect_equal(yield_2[6], 0.139) + expect_equal(yield_2[7], 0.112) + expect_equal(yield_2[8], 0.0720) + expect_equal(yield_2[9], 0.0480) + expect_equal(yield_2[10], 0.0320) + expect_equal(yield_2[11], 0.02) + + etr_1 <- data$etr_1 + expect_equal(etr_1[1], NA_real_) + expect_equal(etr_1[2], NA_real_) + expect_equal(etr_1[3], NA_real_) + expect_equal(etr_1[4], NA_real_) + expect_equal(etr_1[5], NA_real_) + expect_equal(etr_1[6], NA_real_) + expect_equal(etr_1[7], NA_real_) + expect_equal(etr_1[8], NA_real_) + expect_equal(etr_1[9], NA_real_) + expect_equal(etr_1[10], NA_real_) + expect_equal(etr_1[11], NA_real_) + + etr_2 <- data$etr_2 + expect_equal(etr_2[1], 0) + expect_equal(etr_2[2], 5.585580) + expect_equal(etr_2[3], 6.462120) + expect_equal(etr_2[4], 7.44744) + expect_equal(etr_2[5], 9.53946) + expect_equal(etr_2[6], 10.80030) + expect_equal(etr_2[7], 11.33664) + expect_equal(etr_2[8], 12.005280) + expect_equal(etr_2[9], 12.37824) + expect_equal(etr_2[10], 12.71424) + expect_equal(etr_2[11], 12.2052) +}) \ No newline at end of file From 17dab876b52774ed27b033ec9513ad593261ea9d Mon Sep 17 00:00:00 2001 From: JulienBoehm <180776296+JulienBoehm@users.noreply.github.com> Date: Fri, 17 Apr 2026 10:20:42 +0200 Subject: [PATCH 06/32] updated file paths in documentation and examples --- src/R/combo_plot_control.R | 2 +- src/R/compare_regression_models.R | 4 ++-- src/R/eilers_peeters.R | 6 +++--- src/R/platt.R | 6 +++--- src/R/read_pam_data.R | 6 +++--- src/R/util.R | 4 ++-- src/R/vollenweider.R | 6 +++--- src/R/walsby.R | 6 +++--- src/inst/extdata/{ => dual_pam_data}/20231122_01.csv | 0 src/inst/extdata/{ => dual_pam_data}/20240925.csv | 0 .../20260130_efeutute_dual_pam_only_ps_2.csv | 0 .../{junior_pam => junior_pam_data}/junior_pam_20250613.csv | 0 src/man/combo_plot_control.Rd | 2 +- src/man/compare_regression_models_ETR_I.Rd | 2 +- src/man/compare_regression_models_ETR_II.Rd | 2 +- src/man/eilers_peeters_generate_regression_ETR_I.Rd | 2 +- src/man/eilers_peeters_generate_regression_ETR_II.Rd | 2 +- src/man/eilers_peeters_modified.Rd | 2 +- src/man/platt_generate_regression_ETR_I.Rd | 2 +- src/man/platt_generate_regression_ETR_II.Rd | 2 +- src/man/platt_modified.Rd | 2 +- src/man/plot_control.Rd | 2 +- src/man/read_dual_pam_data.Rd | 2 +- src/man/read_dual_pam_data_single_channel_II.Rd | 2 +- src/man/read_junior_pam_data.Rd | 2 +- src/man/vollenweider_generate_regression_ETR_I.Rd | 2 +- src/man/vollenweider_generate_regression_ETR_II.Rd | 2 +- src/man/vollenweider_modified.Rd | 2 +- src/man/walsby_generate_regression_ETR_I.Rd | 2 +- src/man/walsby_generate_regression_ETR_II.Rd | 2 +- src/man/walsby_modified.Rd | 2 +- src/man/write_model_result_csv.Rd | 2 +- 32 files changed, 40 insertions(+), 40 deletions(-) rename src/inst/extdata/{ => dual_pam_data}/20231122_01.csv (100%) rename src/inst/extdata/{ => dual_pam_data}/20240925.csv (100%) rename src/inst/extdata/{ => dual_pam_single_channel_II_data}/20260130_efeutute_dual_pam_only_ps_2.csv (100%) rename src/inst/extdata/{junior_pam => junior_pam_data}/junior_pam_20250613.csv (100%) diff --git a/src/R/combo_plot_control.R b/src/R/combo_plot_control.R index 145afc3..6cec8d5 100644 --- a/src/R/combo_plot_control.R +++ b/src/R/combo_plot_control.R @@ -14,7 +14,7 @@ #' @return A plot with ETR data, regression results, and a summary table. #' #' @examples -#' path <- file.path(system.file("extdata", package = "pam"), "20240925.csv") +#' path <- file.path(system.file("extdata/dual_pam_data", package = "pam"), "20240925.csv") #' data <- read_dual_pam_data(path) #' #' model_results_eilers_peeters <- eilers_peeters_generate_regression_ETR_II(data) diff --git a/src/R/compare_regression_models.R b/src/R/compare_regression_models.R index 793767f..dd27f1c 100644 --- a/src/R/compare_regression_models.R +++ b/src/R/compare_regression_models.R @@ -42,7 +42,7 @@ #' New Phytologist, 136(2), 189-209. Available at: \doi{10.1046/j.1469-8137.1997.00736.x}. #' } #' @examples -#' path <- file.path(system.file("extdata", package = "pam")) +#' path <- file.path(system.file("extdata/dual_pam_data", package = "pam")) #' points <- compare_regression_models_ETR_I(path, read_dual_pam_data) #' #' @export @@ -95,7 +95,7 @@ compare_regression_models_ETR_I <- function(data_dir, read_func) { #' New Phytologist, 136(2), 189-209. Available at: \doi{10.1046/j.1469-8137.1997.00736.x}. #' } #' @examples -#' path <- file.path(system.file("extdata", package = "pam")) +#' path <- file.path(system.file("extdata/dual_pam_data", package = "pam")) #' points <- compare_regression_models_ETR_II(path, read_dual_pam_data) #' #' @export diff --git a/src/R/eilers_peeters.R b/src/R/eilers_peeters.R index 83e3310..7b88880 100644 --- a/src/R/eilers_peeters.R +++ b/src/R/eilers_peeters.R @@ -42,7 +42,7 @@ eilers_peeters_default_start_value_c <- 7.012012 #' } #' #' @examples -#' path <- file.path(system.file("extdata", package = "pam"), "20240925.csv") +#' path <- file.path(system.file("extdata/dual_pam_data", package = "pam"), "20240925.csv") #' data <- read_dual_pam_data(path) #' #' result <- eilers_peeters_generate_regression_ETR_I(data) @@ -93,7 +93,7 @@ eilers_peeters_generate_regression_ETR_I <- function( #' Ecological Modelling, 42(3-4), 199-215. Available at: \doi{10.1016/0304-3800(88)90057-9} #' } #' @examples -#' path <- file.path(system.file("extdata", package = "pam"), "20240925.csv") +#' path <- file.path(system.file("extdata/dual_pam_data", package = "pam"), "20240925.csv") #' data <- read_dual_pam_data(path) #' #' result <- eilers_peeters_generate_regression_ETR_II(data) @@ -298,7 +298,7 @@ eilers_peeters_generate_regression_internal <- function( #' A detailed documentation can be found under \url{https://github.com/biotoolbox/pam?tab=readme-ov-file#eilers_peeters_modified} #' #' @examples -#' path <- file.path(system.file("extdata", package = "pam"), "20240925.csv") +#' path <- file.path(system.file("extdata/dual_pam_data", package = "pam"), "20240925.csv") #' data <- read_dual_pam_data(path) #' #' result <- eilers_peeters_generate_regression_ETR_II(data) diff --git a/src/R/platt.R b/src/R/platt.R index c992518..ab2961d 100644 --- a/src/R/platt.R +++ b/src/R/platt.R @@ -44,7 +44,7 @@ platt_default_start_value_ps <- 49.76112 #' #' } #' @examples -#' path <- file.path(system.file("extdata", package = "pam"), "20240925.csv") +#' path <- file.path(system.file("extdata/dual_pam_data", package = "pam"), "20240925.csv") #' data <- read_dual_pam_data(path) #' #' result <- platt_generate_regression_ETR_I(data) @@ -98,7 +98,7 @@ platt_generate_regression_ETR_I <- function( #' #' } #' @examples -#' path <- file.path(system.file("extdata", package = "pam"), "20240925.csv") +#' path <- file.path(system.file("extdata/dual_pam_data", package = "pam"), "20240925.csv") #' data <- read_dual_pam_data(path) #' #' result <- platt_generate_regression_ETR_II(data) @@ -306,7 +306,7 @@ platt_generate_regression_internal <- function( #' A detailed documentation can be found under \url{https://github.com/biotoolbox/pam?tab=readme-ov-file#platt_modified} #' #' @examples -#' path <- file.path(system.file("extdata", package = "pam"), "20240925.csv") +#' path <- file.path(system.file("extdata/dual_pam_data", package = "pam"), "20240925.csv") #' data <- read_dual_pam_data(path) #' #' result <- platt_generate_regression_ETR_II(data) diff --git a/src/R/read_pam_data.R b/src/R/read_pam_data.R index 100ed79..aeb4bfe 100644 --- a/src/R/read_pam_data.R +++ b/src/R/read_pam_data.R @@ -107,7 +107,7 @@ read_universal_data <- function(csv_path, #' Available at: \url{https://www.walz.com/files/downloads/dualpamed05.pdf} #' } #' @examples -#' path <- file.path(system.file("extdata", package = "pam"), "20240925.csv") +#' path <- file.path(system.file("extdata/dual_pam_data", package = "pam"), "20240925.csv") #' data <- read_dual_pam_data(path) #' @export read_dual_pam_data <- function( @@ -241,7 +241,7 @@ read_dual_pam_data <- function( #' Available at: \url{https://www.walz.com/files/downloads/dualpamed05.pdf} #' } #' @examples -#' path <- file.path(system.file("extdata", package = "pam"), "20260130_efeutute_dual_pam_only_ps_2.csv") +#' path <- file.path(system.file("extdata/dual_pam_single_channel_II_data", package = "pam"), "20260130_efeutute_dual_pam_only_ps_2.csv") #' data <- read_dual_pam_data_single_channel_II(path) #' @export read_dual_pam_data_single_channel_II <- function( @@ -392,7 +392,7 @@ calc_etr <- function(yield, par, etr_factor, p_ratio) { #' Available at: \url{https://www.walz.com/files/downloads/dualpamed05.pdf} #' } #' @examples -#' path <- file.path(system.file("extdata/junior_pam", package = "pam"), "junior_pam_20250613.csv") +#' path <- file.path(system.file("extdata/junior_pam_data", package = "pam"), "junior_pam_20250613.csv") #' data <- read_junior_pam_data(path) #' @export read_junior_pam_data <- function( diff --git a/src/R/util.R b/src/R/util.R index 931a7b6..0d8f2d8 100644 --- a/src/R/util.R +++ b/src/R/util.R @@ -125,7 +125,7 @@ plot_table <- function(model_result, entries_per_row) { #' @return A plot displaying the original ETR and Yield values and the regression data. A table below the plot shows the calculated data. #' #' @examples -#' path <- file.path(system.file("extdata", package = "pam"), "20240925.csv") +#' path <- file.path(system.file("extdata/dual_pam_data", package = "pam"), "20240925.csv") #' data <- read_dual_pam_data(path) #' #' result <- eilers_peeters_generate_regression_ETR_I(data) @@ -259,7 +259,7 @@ create_modified_model_result <- function( #' @return No return value, called for side effects #' #' @examples -#' path <- file.path(system.file("extdata", package = "pam"), "20240925.csv") +#' path <- file.path(system.file("extdata/dual_pam_data", package = "pam"), "20240925.csv") #' data <- read_dual_pam_data(path) #' #' result <- eilers_peeters_generate_regression_ETR_I(data) diff --git a/src/R/vollenweider.R b/src/R/vollenweider.R index 62ed785..9abc648 100644 --- a/src/R/vollenweider.R +++ b/src/R/vollenweider.R @@ -50,7 +50,7 @@ vollenweider_default_start_value_n <- 100 #' } #' #' @examples -#' path <- file.path(system.file("extdata", package = "pam"), "20240925.csv") +#' path <- file.path(system.file("extdata/dual_pam_data", package = "pam"), "20240925.csv") #' data <- read_dual_pam_data(path) #' #' result <- vollenweider_generate_regression_ETR_I(data) @@ -107,7 +107,7 @@ vollenweider_generate_regression_ETR_I <- function( #' } #' #' @examples -#' path <- file.path(system.file("extdata", package = "pam"), "20240925.csv") +#' path <- file.path(system.file("extdata/dual_pam_data", package = "pam"), "20240925.csv") #' data <- read_dual_pam_data(path) #' #' result <- vollenweider_generate_regression_ETR_II(data) @@ -308,7 +308,7 @@ vollenweider_generate_regression_internal <- function( #' A detailed documentation can be found under \url{https://github.com/biotoolbox/pam?tab=readme-ov-file#vollenweider_modified} #' #' @examples -#' path <- file.path(system.file("extdata", package = "pam"), "20240925.csv") +#' path <- file.path(system.file("extdata/dual_pam_data", package = "pam"), "20240925.csv") #' data <- read_dual_pam_data(path) #' #' result <- vollenweider_generate_regression_ETR_II(data) diff --git a/src/R/walsby.R b/src/R/walsby.R index 4908e0d..9016530 100644 --- a/src/R/walsby.R +++ b/src/R/walsby.R @@ -44,7 +44,7 @@ walsby_default_start_value_beta <- -0.0008944076 #' } #' #' @examples -#' path <- file.path(system.file("extdata", package = "pam"), "20240925.csv") +#' path <- file.path(system.file("extdata/dual_pam_data", package = "pam"), "20240925.csv") #' data <- read_dual_pam_data(path) #' #' result <- walsby_generate_regression_ETR_I(data) @@ -100,7 +100,7 @@ walsby_generate_regression_ETR_I <- function( #' } #' #' @examples -#' path <- file.path(system.file("extdata", package = "pam"), "20240925.csv") +#' path <- file.path(system.file("extdata/dual_pam_data", package = "pam"), "20240925.csv") #' data <- read_dual_pam_data(path) #' #' result <- walsby_generate_regression_ETR_II(data) @@ -239,7 +239,7 @@ walsby_generate_regression_internal <- function( #' A detailed documentation can be found under \url{https://github.com/biotoolbox/pam?tab=readme-ov-file#walsby_modified} #' #' @examples -#' path <- file.path(system.file("extdata", package = "pam"), "20240925.csv") +#' path <- file.path(system.file("extdata/dual_pam_data", package = "pam"), "20240925.csv") #' data <- read_dual_pam_data(path) #' #' result <- walsby_generate_regression_ETR_II(data) diff --git a/src/inst/extdata/20231122_01.csv b/src/inst/extdata/dual_pam_data/20231122_01.csv similarity index 100% rename from src/inst/extdata/20231122_01.csv rename to src/inst/extdata/dual_pam_data/20231122_01.csv diff --git a/src/inst/extdata/20240925.csv b/src/inst/extdata/dual_pam_data/20240925.csv similarity index 100% rename from src/inst/extdata/20240925.csv rename to src/inst/extdata/dual_pam_data/20240925.csv diff --git a/src/inst/extdata/20260130_efeutute_dual_pam_only_ps_2.csv b/src/inst/extdata/dual_pam_single_channel_II_data/20260130_efeutute_dual_pam_only_ps_2.csv similarity index 100% rename from src/inst/extdata/20260130_efeutute_dual_pam_only_ps_2.csv rename to src/inst/extdata/dual_pam_single_channel_II_data/20260130_efeutute_dual_pam_only_ps_2.csv diff --git a/src/inst/extdata/junior_pam/junior_pam_20250613.csv b/src/inst/extdata/junior_pam_data/junior_pam_20250613.csv similarity index 100% rename from src/inst/extdata/junior_pam/junior_pam_20250613.csv rename to src/inst/extdata/junior_pam_data/junior_pam_20250613.csv diff --git a/src/man/combo_plot_control.Rd b/src/man/combo_plot_control.Rd index 260691a..4833f14 100644 --- a/src/man/combo_plot_control.Rd +++ b/src/man/combo_plot_control.Rd @@ -27,7 +27,7 @@ Generates a plot of ETR data with different regression model predictions and a s A detailed documentation can be found under \url{https://github.com/biotoolbox/pam?tab=readme-ov-file#combo_control_plot}. } \examples{ -path <- file.path(system.file("extdata", package = "pam"), "20240925.csv") +path <- file.path(system.file("extdata/dual_pam_data", package = "pam"), "20240925.csv") data <- read_dual_pam_data(path) model_results_eilers_peeters <- eilers_peeters_generate_regression_ETR_II(data) diff --git a/src/man/compare_regression_models_ETR_I.Rd b/src/man/compare_regression_models_ETR_I.Rd index de6cd96..579d0b6 100644 --- a/src/man/compare_regression_models_ETR_I.Rd +++ b/src/man/compare_regression_models_ETR_I.Rd @@ -36,7 +36,7 @@ Models are ranked based on the deviation between observed and predicted values. A detailed documentation can be found under \url{https://github.com/biotoolbox/pam?tab=readme-ov-file#walsby_modified} } \examples{ -path <- file.path(system.file("extdata", package = "pam")) +path <- file.path(system.file("extdata/dual_pam_data", package = "pam")) points <- compare_regression_models_ETR_I(path, read_dual_pam_data) } diff --git a/src/man/compare_regression_models_ETR_II.Rd b/src/man/compare_regression_models_ETR_II.Rd index adaaa75..37fe621 100644 --- a/src/man/compare_regression_models_ETR_II.Rd +++ b/src/man/compare_regression_models_ETR_II.Rd @@ -36,7 +36,7 @@ Models are ranked based on the deviation between observed and predicted values. A detailed documentation can be found in the README. } \examples{ -path <- file.path(system.file("extdata", package = "pam")) +path <- file.path(system.file("extdata/dual_pam_data", package = "pam")) points <- compare_regression_models_ETR_II(path, read_dual_pam_data) } diff --git a/src/man/eilers_peeters_generate_regression_ETR_I.Rd b/src/man/eilers_peeters_generate_regression_ETR_I.Rd index 8809c7e..a48a6d3 100644 --- a/src/man/eilers_peeters_generate_regression_ETR_I.Rd +++ b/src/man/eilers_peeters_generate_regression_ETR_I.Rd @@ -42,7 +42,7 @@ Fits a regression model for ETR I based on Eilers-Peeters (1988), considering ph A detailed documentation can be found under \url{https://github.com/biotoolbox/pam?tab=readme-ov-file#eilers_peeters_generate_regression_etr_i-and-eilers_peeters_generate_regression_etr_ii}. } \examples{ -path <- file.path(system.file("extdata", package = "pam"), "20240925.csv") +path <- file.path(system.file("extdata/dual_pam_data", package = "pam"), "20240925.csv") data <- read_dual_pam_data(path) result <- eilers_peeters_generate_regression_ETR_I(data) diff --git a/src/man/eilers_peeters_generate_regression_ETR_II.Rd b/src/man/eilers_peeters_generate_regression_ETR_II.Rd index 238079c..4c08182 100644 --- a/src/man/eilers_peeters_generate_regression_ETR_II.Rd +++ b/src/man/eilers_peeters_generate_regression_ETR_II.Rd @@ -42,7 +42,7 @@ Fits a regression model for ETR II based on Eilers-Peeters (1988), considering p A detailed documentation can be found under \url{https://github.com/biotoolbox/pam?tab=readme-ov-file#eilers_peeters_generate_regression_etr_i-and-eilers_peeters_generate_regression_etr_ii}. } \examples{ -path <- file.path(system.file("extdata", package = "pam"), "20240925.csv") +path <- file.path(system.file("extdata/dual_pam_data", package = "pam"), "20240925.csv") data <- read_dual_pam_data(path) result <- eilers_peeters_generate_regression_ETR_II(data) diff --git a/src/man/eilers_peeters_modified.Rd b/src/man/eilers_peeters_modified.Rd index 8e18b1d..9a6fd2f 100644 --- a/src/man/eilers_peeters_modified.Rd +++ b/src/man/eilers_peeters_modified.Rd @@ -40,7 +40,7 @@ This function enhances the Eilers and Peeters (1988) model by adding parameters A detailed documentation can be found under \url{https://github.com/biotoolbox/pam?tab=readme-ov-file#eilers_peeters_modified} } \examples{ -path <- file.path(system.file("extdata", package = "pam"), "20240925.csv") +path <- file.path(system.file("extdata/dual_pam_data", package = "pam"), "20240925.csv") data <- read_dual_pam_data(path) result <- eilers_peeters_generate_regression_ETR_II(data) diff --git a/src/man/platt_generate_regression_ETR_I.Rd b/src/man/platt_generate_regression_ETR_I.Rd index 13940ea..1f5092e 100644 --- a/src/man/platt_generate_regression_ETR_I.Rd +++ b/src/man/platt_generate_regression_ETR_I.Rd @@ -44,7 +44,7 @@ Fits the Platt (1980) regression model using original naming conventions. A detailed documentation can be found under \url{https://github.com/biotoolbox/pam?tab=readme-ov-file#platt_generate_regression_etr_i-and-platt_generate_regression_etr_ii} . } \examples{ -path <- file.path(system.file("extdata", package = "pam"), "20240925.csv") +path <- file.path(system.file("extdata/dual_pam_data", package = "pam"), "20240925.csv") data <- read_dual_pam_data(path) result <- platt_generate_regression_ETR_I(data) diff --git a/src/man/platt_generate_regression_ETR_II.Rd b/src/man/platt_generate_regression_ETR_II.Rd index 404e842..3166a75 100644 --- a/src/man/platt_generate_regression_ETR_II.Rd +++ b/src/man/platt_generate_regression_ETR_II.Rd @@ -44,7 +44,7 @@ Fits the Platt (1980) regression model using original naming conventions. A detailed documentation can be found under \url{https://github.com/biotoolbox/pam?tab=readme-ov-file#platt_generate_regression_etr_i-and-platt_generate_regression_etr_ii}. } \examples{ -path <- file.path(system.file("extdata", package = "pam"), "20240925.csv") +path <- file.path(system.file("extdata/dual_pam_data", package = "pam"), "20240925.csv") data <- read_dual_pam_data(path) result <- platt_generate_regression_ETR_II(data) diff --git a/src/man/platt_modified.Rd b/src/man/platt_modified.Rd index baaf582..e383ddd 100644 --- a/src/man/platt_modified.Rd +++ b/src/man/platt_modified.Rd @@ -40,7 +40,7 @@ This function enhances the Platt (1980) model by adding parameters not originall A detailed documentation can be found under \url{https://github.com/biotoolbox/pam?tab=readme-ov-file#platt_modified} } \examples{ -path <- file.path(system.file("extdata", package = "pam"), "20240925.csv") +path <- file.path(system.file("extdata/dual_pam_data", package = "pam"), "20240925.csv") data <- read_dual_pam_data(path) result <- platt_generate_regression_ETR_II(data) diff --git a/src/man/plot_control.Rd b/src/man/plot_control.Rd index bd04867..4423a9c 100644 --- a/src/man/plot_control.Rd +++ b/src/man/plot_control.Rd @@ -25,7 +25,7 @@ This function creates a control plot for the used model based on the provided da A detailed documentation can be found under \url{https://github.com/biotoolbox/pam?tab=readme-ov-file#plot_control} } \examples{ -path <- file.path(system.file("extdata", package = "pam"), "20240925.csv") +path <- file.path(system.file("extdata/dual_pam_data", package = "pam"), "20240925.csv") data <- read_dual_pam_data(path) result <- eilers_peeters_generate_regression_ETR_I(data) diff --git a/src/man/read_dual_pam_data.Rd b/src/man/read_dual_pam_data.Rd index c8c1e6e..c25aa42 100644 --- a/src/man/read_dual_pam_data.Rd +++ b/src/man/read_dual_pam_data.Rd @@ -43,7 +43,7 @@ Calculates ETR using: A detailed documentation can be found under \url{https://github.com/biotoolbox/pam?tab=readme-ov-file#read_dual_pam_data} } \examples{ -path <- file.path(system.file("extdata", package = "pam"), "20240925.csv") +path <- file.path(system.file("extdata/dual_pam_data", package = "pam"), "20240925.csv") data <- read_dual_pam_data(path) } \references{ diff --git a/src/man/read_dual_pam_data_single_channel_II.Rd b/src/man/read_dual_pam_data_single_channel_II.Rd index 6f5cf63..f5a006f 100644 --- a/src/man/read_dual_pam_data_single_channel_II.Rd +++ b/src/man/read_dual_pam_data_single_channel_II.Rd @@ -43,7 +43,7 @@ Calculates ETR using: A detailed documentation can be found under \url{https://github.com/biotoolbox/pam?tab=readme-ov-file#read_dual_pam_data} } \examples{ -path <- file.path(system.file("extdata", package = "pam"), "20260130_efeutute_dual_pam_only_ps_2.csv") +path <- file.path(system.file("extdata/dual_pam_single_channel_II_data", package = "pam"), "20260130_efeutute_dual_pam_only_ps_2.csv") data <- read_dual_pam_data_single_channel_II(path) } \references{ diff --git a/src/man/read_junior_pam_data.Rd b/src/man/read_junior_pam_data.Rd index d33e45c..67523f7 100644 --- a/src/man/read_junior_pam_data.Rd +++ b/src/man/read_junior_pam_data.Rd @@ -43,7 +43,7 @@ Calculates ETR II using: A detailed documentation can be found under \url{https://github.com/biotoolbox/pam?tab=readme-ov-file} } \examples{ -path <- file.path(system.file("extdata/junior_pam", package = "pam"), "junior_pam_20250613.csv") +path <- file.path(system.file("extdata/junior_pam_data", package = "pam"), "junior_pam_20250613.csv") data <- read_junior_pam_data(path) } \references{ diff --git a/src/man/vollenweider_generate_regression_ETR_I.Rd b/src/man/vollenweider_generate_regression_ETR_I.Rd index e23950e..aa5b47c 100644 --- a/src/man/vollenweider_generate_regression_ETR_I.Rd +++ b/src/man/vollenweider_generate_regression_ETR_I.Rd @@ -47,7 +47,7 @@ Fits the Vollenweider (1965) regression model using original naming conventions A detailed documentation can be found under \url{https://github.com/biotoolbox/pam?tab=readme-ov-file#vollenweider_generate_regression_etr_i-and-vollenweider_generate_regression_etr_ii}. } \examples{ -path <- file.path(system.file("extdata", package = "pam"), "20240925.csv") +path <- file.path(system.file("extdata/dual_pam_data", package = "pam"), "20240925.csv") data <- read_dual_pam_data(path) result <- vollenweider_generate_regression_ETR_I(data) diff --git a/src/man/vollenweider_generate_regression_ETR_II.Rd b/src/man/vollenweider_generate_regression_ETR_II.Rd index 87a0caa..0cd386c 100644 --- a/src/man/vollenweider_generate_regression_ETR_II.Rd +++ b/src/man/vollenweider_generate_regression_ETR_II.Rd @@ -47,7 +47,7 @@ Fits the Vollenweider (1965) regression model using original naming conventions A detailed documentation can be found under \url{https://github.com/biotoolbox/pam?tab=readme-ov-file#vollenweider_generate_regression_etr_i-and-vollenweider_generate_regression_etr_ii}. } \examples{ -path <- file.path(system.file("extdata", package = "pam"), "20240925.csv") +path <- file.path(system.file("extdata/dual_pam_data", package = "pam"), "20240925.csv") data <- read_dual_pam_data(path) result <- vollenweider_generate_regression_ETR_II(data) diff --git a/src/man/vollenweider_modified.Rd b/src/man/vollenweider_modified.Rd index 4335ab9..5747da4 100644 --- a/src/man/vollenweider_modified.Rd +++ b/src/man/vollenweider_modified.Rd @@ -40,7 +40,7 @@ This function adds parameters that were not originally included in the Vollenwei A detailed documentation can be found under \url{https://github.com/biotoolbox/pam?tab=readme-ov-file#vollenweider_modified} } \examples{ -path <- file.path(system.file("extdata", package = "pam"), "20240925.csv") +path <- file.path(system.file("extdata/dual_pam_data", package = "pam"), "20240925.csv") data <- read_dual_pam_data(path) result <- vollenweider_generate_regression_ETR_II(data) diff --git a/src/man/walsby_generate_regression_ETR_I.Rd b/src/man/walsby_generate_regression_ETR_I.Rd index a17b1ed..6d7222d 100644 --- a/src/man/walsby_generate_regression_ETR_I.Rd +++ b/src/man/walsby_generate_regression_ETR_I.Rd @@ -40,7 +40,7 @@ Calculates \eqn{ETR_{max}} without accounting for photoinhibition. A detailed documentation can be found under \url{https://github.com/biotoolbox/pam?tab=readme-ov-file#walsby_generate_regression_etr_i-and-walsby_generate_regression_etr_ii}. } \examples{ -path <- file.path(system.file("extdata", package = "pam"), "20240925.csv") +path <- file.path(system.file("extdata/dual_pam_data", package = "pam"), "20240925.csv") data <- read_dual_pam_data(path) result <- walsby_generate_regression_ETR_I(data) diff --git a/src/man/walsby_generate_regression_ETR_II.Rd b/src/man/walsby_generate_regression_ETR_II.Rd index 30ae1e4..0767416 100644 --- a/src/man/walsby_generate_regression_ETR_II.Rd +++ b/src/man/walsby_generate_regression_ETR_II.Rd @@ -40,7 +40,7 @@ Calculates \eqn{ETR_{max}} without accounting for photoinhibition. A detailed documentation can be found under \url{https://github.com/biotoolbox/pam?tab=readme-ov-file#walsby_generate_regression_etr_i-and-walsby_generate_regression_etr_ii}. } \examples{ -path <- file.path(system.file("extdata", package = "pam"), "20240925.csv") +path <- file.path(system.file("extdata/dual_pam_data", package = "pam"), "20240925.csv") data <- read_dual_pam_data(path) result <- walsby_generate_regression_ETR_II(data) diff --git a/src/man/walsby_modified.Rd b/src/man/walsby_modified.Rd index fe176e6..8b40c68 100644 --- a/src/man/walsby_modified.Rd +++ b/src/man/walsby_modified.Rd @@ -40,7 +40,7 @@ Enhances the Walsby (1997) model by adding parameters from other models and stan A detailed documentation can be found under \url{https://github.com/biotoolbox/pam?tab=readme-ov-file#walsby_modified} } \examples{ -path <- file.path(system.file("extdata", package = "pam"), "20240925.csv") +path <- file.path(system.file("extdata/dual_pam_data", package = "pam"), "20240925.csv") data <- read_dual_pam_data(path) result <- walsby_generate_regression_ETR_II(data) diff --git a/src/man/write_model_result_csv.Rd b/src/man/write_model_result_csv.Rd index 0be05ed..75c3281 100644 --- a/src/man/write_model_result_csv.Rd +++ b/src/man/write_model_result_csv.Rd @@ -32,7 +32,7 @@ The `name` parameter serves as a prefix for each file, ensuring clarity and orga A detailed documentation can be found under \url{https://github.com/biotoolbox/pam?tab=readme-ov-file#write_model_result_csv} } \examples{ -path <- file.path(system.file("extdata", package = "pam"), "20240925.csv") +path <- file.path(system.file("extdata/dual_pam_data", package = "pam"), "20240925.csv") data <- read_dual_pam_data(path) result <- eilers_peeters_generate_regression_ETR_I(data) From 00412344cb09ded2b101bb711b44aa11c654f0d1 Mon Sep 17 00:00:00 2001 From: JulienBoehm <180776296+JulienBoehm@users.noreply.github.com> Date: Fri, 17 Apr 2026 10:31:08 +0200 Subject: [PATCH 07/32] Rename read_dual_pam_data_single_channel_II to read_dual_pam_single_channel_II_data --- src/NAMESPACE | 2 +- src/R/read_pam_data.R | 4 ++-- ...nnel_II.Rd => read_dual_pam_single_channel_II_data.Rd} | 8 ++++---- .../testthat/test-read_dual_pam_data_single_channel_II.R | 2 +- 4 files changed, 8 insertions(+), 8 deletions(-) rename src/man/{read_dual_pam_data_single_channel_II.Rd => read_dual_pam_single_channel_II_data.Rd} (91%) diff --git a/src/NAMESPACE b/src/NAMESPACE index 5ee9989..a00e4e2 100644 --- a/src/NAMESPACE +++ b/src/NAMESPACE @@ -17,7 +17,7 @@ export(platt_generate_regression_ETR_II) export(platt_modified) export(plot_control) export(read_dual_pam_data) -export(read_dual_pam_data_single_channel_II) +export(read_dual_pam_single_channel_II_data) export(read_junior_pam_data) export(read_pam_2500_data) export(read_universal_data) diff --git a/src/R/read_pam_data.R b/src/R/read_pam_data.R index aeb4bfe..2d4859b 100644 --- a/src/R/read_pam_data.R +++ b/src/R/read_pam_data.R @@ -242,9 +242,9 @@ read_dual_pam_data <- function( #' } #' @examples #' path <- file.path(system.file("extdata/dual_pam_single_channel_II_data", package = "pam"), "20260130_efeutute_dual_pam_only_ps_2.csv") -#' data <- read_dual_pam_data_single_channel_II(path) +#' data <- read_dual_pam_single_channel_II_data(path) #' @export -read_dual_pam_data_single_channel_II <- function( +read_dual_pam_single_channel_II_data <- function( csv_path, remove_recovery = TRUE, etr_factor = 0.84, diff --git a/src/man/read_dual_pam_data_single_channel_II.Rd b/src/man/read_dual_pam_single_channel_II_data.Rd similarity index 91% rename from src/man/read_dual_pam_data_single_channel_II.Rd rename to src/man/read_dual_pam_single_channel_II_data.Rd index f5a006f..45ab597 100644 --- a/src/man/read_dual_pam_data_single_channel_II.Rd +++ b/src/man/read_dual_pam_single_channel_II_data.Rd @@ -1,10 +1,10 @@ % Generated by roxygen2: do not edit by hand % Please edit documentation in R/read_pam_data.R -\name{read_dual_pam_data_single_channel_II} -\alias{read_dual_pam_data_single_channel_II} +\name{read_dual_pam_single_channel_II_data} +\alias{read_dual_pam_single_channel_II_data} \title{Read and Process DualPAM Data Single Chanel Mode Photosystem II} \usage{ -read_dual_pam_data_single_channel_II( +read_dual_pam_single_channel_II_data( csv_path, remove_recovery = TRUE, etr_factor = 0.84, @@ -44,7 +44,7 @@ A detailed documentation can be found under \url{https://github.com/biotoolbox/p } \examples{ path <- file.path(system.file("extdata/dual_pam_single_channel_II_data", package = "pam"), "20260130_efeutute_dual_pam_only_ps_2.csv") -data <- read_dual_pam_data_single_channel_II(path) +data <- read_dual_pam_single_channel_II_data(path) } \references{ { diff --git a/src/tests/testthat/test-read_dual_pam_data_single_channel_II.R b/src/tests/testthat/test-read_dual_pam_data_single_channel_II.R index 7890bb5..8b2bc31 100644 --- a/src/tests/testthat/test-read_dual_pam_data_single_channel_II.R +++ b/src/tests/testthat/test-read_dual_pam_data_single_channel_II.R @@ -1,6 +1,6 @@ test_that("read_dual_pam_data 20260130_efeutute_dual_pam_only_ps_2 - default", { test_data_file <- testthat::test_path("data", "20260130_efeutute_dual_pam_only_ps_2.csv") - data <- read_dual_pam_data_single_channel_II(test_data_file) + data <- read_dual_pam_single_channel_II_data(test_data_file) par <- data$par expect_equal(par[1], 0) From 70f6f8979de38bded6951b94b5e4fe587002adc7 Mon Sep 17 00:00:00 2001 From: JulienBoehm <180776296+JulienBoehm@users.noreply.github.com> Date: Fri, 17 Apr 2026 13:25:19 +0200 Subject: [PATCH 08/32] Added additional tests for read_dual_pam_single_channel_I_data function --- src/NAMESPACE | 1 + src/R/read_pam_data.R | 134 ++++++++- src/R/validation.R | 118 +++++++- ...0260130_01_efeutute_dual_pam_only_ps_1.csv | 21 ++ .../read_dual_pam_single_channel_I_data.Rd | 55 ++++ ...st-read_dual_pam_single_channel_II_data.R} | 2 +- ...test-read_dual_pam_single_channel_I_data.R | 274 ++++++++++++++++++ 7 files changed, 600 insertions(+), 5 deletions(-) create mode 100644 src/inst/extdata/dual_pam_single_channel_I_data/20260130_01_efeutute_dual_pam_only_ps_1.csv create mode 100644 src/man/read_dual_pam_single_channel_I_data.Rd rename src/tests/testthat/{test-read_dual_pam_data_single_channel_II.R => test-read_dual_pam_single_channel_II_data.R} (95%) create mode 100644 src/tests/testthat/test-read_dual_pam_single_channel_I_data.R diff --git a/src/NAMESPACE b/src/NAMESPACE index a00e4e2..7dea862 100644 --- a/src/NAMESPACE +++ b/src/NAMESPACE @@ -18,6 +18,7 @@ export(platt_modified) export(plot_control) export(read_dual_pam_data) export(read_dual_pam_single_channel_II_data) +export(read_dual_pam_single_channel_I_data) export(read_junior_pam_data) export(read_pam_2500_data) export(read_universal_data) diff --git a/src/R/read_pam_data.R b/src/R/read_pam_data.R index 2d4859b..19eb1d3 100644 --- a/src/R/read_pam_data.R +++ b/src/R/read_pam_data.R @@ -210,6 +210,133 @@ read_dual_pam_data <- function( ) } +#' Read and Process DualPAM Data Single Chanel Mode Photosystem I +#' +#' Reads raw CSV files generated by DualPAM software, calculates electron transport rate (ETR) values for Photosystem I, and returns a universal dataset. +#' +#' @param csv_path File path to the CSV file. +#' @param remove_recovery Logical. Removes recovery measurements if \code{TRUE}. Default is \code{TRUE}. +#' @param etr_factor Numeric. Factor for ETR calculation. Default is \code{0.84}. +#' @param fraction_photosystem_I Numeric. Relative distribution of absorbed PAR to photosystem I. Default is \code{0.5}. +#' @param fraction_photosystem_II Numeric. Relative distribution of absorbed PAR to photosystem II. Default is \code{0.5}. +#' +#' @details +#' Calculates ETR using: +#' \deqn{\text{ETR} = \text{PAR} \cdot \text{ETR-Factor} \cdot \text{Fraction of Photosystem (I)} \cdot \text{Yield (I)}} +#' +#' A detailed documentation can be found under \url{https://github.com/biotoolbox/pam?tab=readme-ov-file#read_dual_pam_data} +#' +#' @return A \code{data.table} containing: +#' \itemize{ +#' \item \code{par}: Photosynthetically active radiation. +#' \item \code{yield_1}: NA +#' \item \code{yield_2}: Yield for photosystem II. +#' \item \code{etr_1}: NA +#' \item \code{etr_2}: Calculated ETR for photosystem II. +#' } +#' +#' @references{ +#' Heinz Walz GmbH. (2024). \emph{DUAL-PAM-100 DUAL-PAM/F MANUAL, 5th Edition, April 2024, Chapter 7 (pp. 162-172).} +#' Heinz Walz GmbH, Effeltrich, Germany. +#' Available at: \url{https://www.walz.com/files/downloads/dualpamed05.pdf} +#' } +#' @examples +#' path <- file.path(system.file("extdata/dual_pam_single_channel_I_data", package = "pam"), "20260130_01_efeutute_dual_pam_only_ps_1.csv") +#' data <- read_dual_pam_single_channel_I_data(path) +#' @export +read_dual_pam_single_channel_I_data <- function( + csv_path, + remove_recovery = TRUE, + etr_factor = 0.84, + fraction_photosystem_I = 0.5, + fraction_photosystem_II = 0.5) { + if (fraction_photosystem_I + fraction_photosystem_II != 1) { + stop("The sum of fraction_photosystem_I and fraction_photosystem_II must be equal 1.") + } + + tryCatch( + { + data <- utils::read.csv(csv_path, sep = ";", dec = ".") + data <- data.table::as.data.table(data) + + validate_dual_pam_single_channel_I_data(data) + data <- data[data$ID == "SP", ] + + date_time_col_values <- c() + for (i in seq_len(nrow(data))) { + row <- data[i, ] + + date_time_row_value <- as.POSIXct( + paste(row$Date, row$Time, sep = " "), + tz = "GMT", "%d.%m.%y %H:%M:%S" + ) + date_time_col_values <- c(date_time_col_values, date_time_row_value) + } + + data$DateTime <- date_time_col_values + data <- data[order(data$DateTime), ] + + pm_det_row <- subset(data, data$PAR == 0 & data$Action == "Pm.-Det.") + yield_1_first <- pm_det_row$Y.I. + recalc_etr_1 <- calc_etr(yield_1_first, 0, etr_factor, fraction_photosystem_I) + + + result <- data.table::data.table( + par = numeric(), + yield_1 = numeric(), + yield_2 = numeric(), + etr_1 = numeric(), + etr_2 = numeric() + ) + new_row <- list( + par = 0, + yield_1 = yield_1_first, + yield_2 = NA_real_, + etr_1 = recalc_etr_1, + etr_2 = NA_real_ + ) + result <- rbind(result, new_row) + + last_par <- as.numeric(0) + for (i in seq_len(nrow(data))) { + row <- data[i, ] + current_par <- row$PAR + + if (row$Action != "P700 SP") { + next + } + + if (remove_recovery && last_par != 0 && current_par < last_par) { + break + } + + yield_1 <- row$Y.I. + recalc_etr_1 <- calc_etr(yield_1, current_par, etr_factor, fraction_photosystem_I) + + new_row <- list( + par = current_par, + yield_1 = yield_1, + yield_2 = NA_real_, + etr_1 = recalc_etr_1, + etr_2 = NA_real_ + ) + result <- rbind(result, new_row) + + last_par <- current_par + } + + validate_data(result) + return(result) + }, + warning = function(w) { + stop("Warning in file: ", csv_path, " Warning: ", w) + }, + error = function(e) { + stop("Error in file: ", csv_path, " Error: ", e) + } + ) +} + #' Read and Process DualPAM Data Single Chanel Mode Photosystem II #' #' Reads raw CSV files generated by DualPAM software, calculates electron transport rate (ETR) values for Photosystem II, and returns a universal dataset. @@ -259,7 +386,7 @@ read_dual_pam_single_channel_II_data <- function( data <- utils::read.csv(csv_path, sep = ";", dec = ".") data <- data.table::as.data.table(data) - validate_dual_pam_data_single_channel_II(data) + validate_dual_pam_single_channel_II_data(data) data <- data[data$ID == "SP", ] date_time_col_values <- c() @@ -278,7 +405,9 @@ read_dual_pam_single_channel_II_data <- function( fm_det_row <- subset(data, data$PAR == 0 & data$Action == "Fm-Det.") yield_2_first <- fm_det_row$Y.II. - recalc_etr_2 <- calc_etr(yield_2_first, 0, etr_factor, fraction_photosystem_II) + recalc_etr_2 <- calc_etr( + yield_2_first, 0, etr_factor, fraction_photosystem_II + ) result <- data.table::data.table( @@ -588,4 +717,3 @@ read_pam_2500_data <- function( } ) } - diff --git a/src/R/validation.R b/src/R/validation.R index cafb252..d1eeb0e 100644 --- a/src/R/validation.R +++ b/src/R/validation.R @@ -100,7 +100,7 @@ validate_dual_pam_data <- function(data) { } } -validate_dual_pam_data_single_channel_II <- function(data) { +validate_dual_pam_single_channel_II_data <- function(data) { if (is.null(data)) { stop("data is null") } @@ -215,6 +215,122 @@ validate_pam_2500_data <- function(data) { } + +validate_dual_pam_single_channel_I_data <- function(data) { + if (is.null(data)) { + stop("data is null") + } + + if (!data.table::is.data.table(data)) { + stop("data is not a valid data.table") + } + + if (nrow(data) < 2) { + stop("no data rows") + } + + if (ncol(data) == 0) { + stop("no cols in data") + } + + if (!"ID" %in% colnames(data)) { + stop("required col 'ID' not found") + } + + if (!"PAR" %in% colnames(data)) { + stop("required col 'PAR' not found") + } + + if (!"Y.I." %in% colnames(data)) { + stop("required col 'Y(I)' not found") + } + + if (!"Action" %in% colnames(data)) { + stop("required col 'Action' not found") + } + + if (!"Date" %in% colnames(data)) { + stop("required col 'Date' not found") + } + + if (!"Time" %in% colnames(data)) { + stop("required col 'Time' not found") + } + + if (!"Pm.-Det." %in% data[["Action"]]) { + stop("required value 'Pm.-Det.' not found in column 'Action'") + } +} + +validate_junior_pam_data <- function(data) { + if (is.null(data)) { + stop("data is null") + } + + if (!data.table::is.data.table(data)) { + stop("data is not a valid data.table") + } + + if (nrow(data) < 2) { + stop("no data rows") + } + + if (ncol(data) == 0) { + stop("no cols in data") + } + + if (!any(grepl("PAR", colnames(data)))) { + stop("required col 'PAR' not found") + } + + if (!any(grepl("Y..II.", colnames(data)))) { + stop("required col 'Y..II.' not found") + } + + if (!"Datetime" %in% colnames(data)) { + stop("required col 'Datetime' not found") + } +} + +validate_pam_2500_data <- function(data) { + if (is.null(data)) { + stop("data is null") + } + + if (!data.table::is.data.table(data)) { + stop("data is not a valid data.table") + } + + if (nrow(data) < 2) { + stop("no data rows") + } + + if (ncol(data) == 0) { + stop("no cols in data") + } + + if (!"No." %in% colnames(data)) { + stop("required col 'No.' not found") + } + + if (!"PAR" %in% colnames(data)) { + stop("required col 'PAR' not found") + } + + if (!"Date" %in% colnames(data)) { + stop("required col 'Date' not found") + } + + if (!"Time" %in% colnames(data)) { + stop("required col 'Time' not found") + } + + if (!"Y.II." %in% colnames(data)) { + stop("required col 'Y(II)' not found") + } + +} + validate_etr_regression_data <- function(regression_data) { if (is.null(regression_data)) { stop("is null") diff --git a/src/inst/extdata/dual_pam_single_channel_I_data/20260130_01_efeutute_dual_pam_only_ps_1.csv b/src/inst/extdata/dual_pam_single_channel_I_data/20260130_01_efeutute_dual_pam_only_ps_1.csv new file mode 100644 index 0000000..7b94de9 --- /dev/null +++ b/src/inst/extdata/dual_pam_single_channel_I_data/20260130_01_efeutute_dual_pam_only_ps_1.csv @@ -0,0 +1,21 @@ +"Date";"Time";"Action";"ID";"Name";"Temp";"PAR";"F(I)/Fo calc";"F(I)";"Fo,Fo'";"Fm,Fm'";"FMTm";"F";"Y(II)";"Y(4S)";"k/ocs";"ETR(II)";"Y(NO)";"Y(NPQ)";"NPQ";"qN";"qP";"qL";"F/Fm";"Fm'/Fm";"P700ox";"P700m,P700m'";"Y(I)";"Y(ND)";"Y(NA)";"ETR(I)"; +30.01.26;11:15:27;New Report;NR;MR1;;;;;;;;;;;;;;;;;;;;;;;;;;; +30.01.26;11:15:33;P700-Cal.;SK;S_260130_111533; 0.0;0;;;;;;;;;;;;;;;;;;;;;;;;; +30.01.26;11:15:40;LC-Start;LCB;LC1;;;;;;;;;;;;;;;;;;;;;;;;;;; +30.01.26;11:15:40;Manual;SK;S_260130_111540; 0.0;0;;;;;;;;;;;;;;;;;;;;;;;;; +30.01.26;11:15:49;Pm.-Det.;SP;F_260130_111549_0;n.c.;0;;;;;;;;;;;;;;;;;;;3.499;4.012;0.128;0.872;-0.000;0.000; +30.01.26;11:16:23;P700 SP;SP;F_260130_111623_0;n.c.;6;;;;;;;;;;;;;;;;;;;0.164;3.581;0.852;0.041;0.107;2.146; +30.01.26;11:16:53;P700 SP;SP;F_260130_111653_0;n.c.;16;;;;;;;;;;;;;;;;;;;0.227;3.631;0.848;0.057;0.095;5.702; +30.01.26;11:17:23;P700 SP;SP;F_260130_111723_0;n.c.;29;;;;;;;;;;;;;;;;;;;0.082;3.247;0.789;0.020;0.191;9.610; +30.01.26;11:17:53;P700 SP;SP;F_260130_111753_0;n.c.;80;;;;;;;;;;;;;;;;;;;0.564;3.490;0.729;0.141;0.130;24.505; +30.01.26;11:18:23;P700 SP;SP;F_260130_111823_0;n.c.;152;;;;;;;;;;;;;;;;;;;1.695;3.764;0.516;0.423;0.062;32.927; +30.01.26;11:18:53;P700 SP;SP;F_260130_111853_0;n.c.;208;;;;;;;;;;;;;;;;;;;2.205;3.761;0.388;0.550;0.063;33.887; +30.01.26;11:19:23;P700 SP;SP;F_260130_111923_0;n.c.;364;;;;;;;;;;;;;;;;;;;2.151;3.428;0.318;0.536;0.145;48.659; +30.01.26;11:19:53;P700 SP;SP;F_260130_111953_0;n.c.;581;;;;;;;;;;;;;;;;;;;1.985;3.145;0.289;0.495;0.216;70.546; +30.01.26;11:20:23;P700 SP;SP;F_260130_112023_0;n.c.;913;;;;;;;;;;;;;;;;;;;2.126;3.064;0.234;0.530;0.236;89.628; +30.01.26;11:20:53;P700 SP;SP;F_260130_112053_0;n.c.;1420;;;;;;;;;;;;;;;;;;;2.382;3.104;0.180;0.594;0.226;107.245; +30.01.26;11:21:23;P700 SP;SP;F_260130_112123_0;n.c.;1763;;;;;;;;;;;;;;;;;;;2.557;3.178;0.155;0.637;0.208;114.562; +30.01.26;11:21:53;P700 SP;SP;F_260130_112153_0;n.c.;2199;;;;;;;;;;;;;;;;;;;2.711;3.232;0.130;0.676;0.194;119.883; +30.01.26;11:22:23;P700 SP;SP;F_260130_112223_0;n.c.;2717;;;;;;;;;;;;;;;;;;;2.863;3.276;0.103;0.714;0.183;117.269; +30.01.26;11:22:53;P700 SP;SP;F_260130_112253_0;n.c.;3315;;;;;;;;;;;;;;;;;;;2.983;3.291;0.077;0.744;0.180;106.912; +30.01.26;11:22:56;LC-Stop;LCE;LC1;;;;;;;;;;;;;;;;;;;;;;;;;;; diff --git a/src/man/read_dual_pam_single_channel_I_data.Rd b/src/man/read_dual_pam_single_channel_I_data.Rd new file mode 100644 index 0000000..f4440af --- /dev/null +++ b/src/man/read_dual_pam_single_channel_I_data.Rd @@ -0,0 +1,55 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/read_pam_data.R +\name{read_dual_pam_single_channel_I_data} +\alias{read_dual_pam_single_channel_I_data} +\title{Read and Process DualPAM Data Single Chanel Mode Photosystem I} +\usage{ +read_dual_pam_single_channel_I_data( + csv_path, + remove_recovery = TRUE, + etr_factor = 0.84, + fraction_photosystem_I = 0.5, + fraction_photosystem_II = 0.5 +) +} +\arguments{ +\item{csv_path}{File path to the CSV file.} + +\item{remove_recovery}{Logical. Removes recovery measurements if \code{TRUE}. Default is \code{TRUE}.} + +\item{etr_factor}{Numeric. Factor for ETR calculation. Default is \code{0.84}.} + +\item{fraction_photosystem_I}{Numeric. Relative distribution of absorbed PAR to photosystem I. Default is \code{0.5}.} + +\item{fraction_photosystem_II}{Numeric. Relative distribution of absorbed PAR to photosystem II. Default is \code{0.5}.} +} +\value{ +A \code{data.table} containing: +\itemize{ + \item \code{par}: Photosynthetically active radiation. + \item \code{yield_1}: NA + \item \code{yield_2}: Yield for photosystem II. + \item \code{etr_1}: NA + \item \code{etr_2}: Calculated ETR for photosystem II. +} +} +\description{ +Reads raw CSV files generated by DualPAM software, calculates electron transport rate (ETR) values for Photosystem I, and returns a universal dataset. +} +\details{ +Calculates ETR using: +\deqn{\text{ETR} = \text{PAR} \cdot \text{ETR-Factor} \cdot \text{Fraction of Photosystem (I)} \cdot \text{Yield (I)}} + +A detailed documentation can be found under \url{https://github.com/biotoolbox/pam?tab=readme-ov-file#read_dual_pam_data} +} +\examples{ +path <- file.path(system.file("extdata/dual_pam_single_channel_I_data", package = "pam"), "20260130_01_efeutute_dual_pam_only_ps_1.csv") +data <- read_dual_pam_single_channel_I_data(path) +} +\references{ +{ + Heinz Walz GmbH. (2024). \emph{DUAL-PAM-100 DUAL-PAM/F MANUAL, 5th Edition, April 2024, Chapter 7 (pp. 162-172).} + Heinz Walz GmbH, Effeltrich, Germany. + Available at: \url{https://www.walz.com/files/downloads/dualpamed05.pdf} +} +} diff --git a/src/tests/testthat/test-read_dual_pam_data_single_channel_II.R b/src/tests/testthat/test-read_dual_pam_single_channel_II_data.R similarity index 95% rename from src/tests/testthat/test-read_dual_pam_data_single_channel_II.R rename to src/tests/testthat/test-read_dual_pam_single_channel_II_data.R index 8b2bc31..40c352b 100644 --- a/src/tests/testthat/test-read_dual_pam_data_single_channel_II.R +++ b/src/tests/testthat/test-read_dual_pam_single_channel_II_data.R @@ -1,4 +1,4 @@ -test_that("read_dual_pam_data 20260130_efeutute_dual_pam_only_ps_2 - default", { +test_that("read_dual_pam_single_channel_II_data 20260130_efeutute_dual_pam_only_ps_2 - default", { test_data_file <- testthat::test_path("data", "20260130_efeutute_dual_pam_only_ps_2.csv") data <- read_dual_pam_single_channel_II_data(test_data_file) diff --git a/src/tests/testthat/test-read_dual_pam_single_channel_I_data.R b/src/tests/testthat/test-read_dual_pam_single_channel_I_data.R new file mode 100644 index 0000000..9b40ad8 --- /dev/null +++ b/src/tests/testthat/test-read_dual_pam_single_channel_I_data.R @@ -0,0 +1,274 @@ +test_that("read_dual_pam_single_channel_I_data 20260130_01_efeutute_dual_pam_only_ps_1 - default", { + test_data_file <- testthat::test_path("data", "20260130_01_efeutute_dual_pam_only_ps_1.csv") + data <- read_dual_pam_single_channel_I_data(test_data_file) + + par <- data$par + expect_equal(par[1], 0) + expect_equal(par[2], 6) + expect_equal(par[3], 16) + expect_equal(par[4], 29) + expect_equal(par[5], 80) + expect_equal(par[6], 152) + expect_equal(par[7], 208) + expect_equal(par[8], 364) + expect_equal(par[9], 581) + expect_equal(par[10], 913) + expect_equal(par[11], 1420) + expect_equal(par[12], 1763) + expect_equal(par[13], 2199) + expect_equal(par[14], 2717) + expect_equal(par[15], 3315) + + yield_1 <- data$yield_1 + expect_equal(yield_1[1], 0.128) + expect_equal(yield_1[2], 0.852) + expect_equal(yield_1[3], 0.848) + expect_equal(yield_1[4], 0.789) + expect_equal(yield_1[5], 0.729) + expect_equal(yield_1[6], 0.516) + expect_equal(yield_1[7], 0.388) + expect_equal(yield_1[8], 0.318) + expect_equal(yield_1[9], 0.289) + expect_equal(yield_1[10], 0.234) + expect_equal(yield_1[11], 0.180) + expect_equal(yield_1[12], 0.155) + expect_equal(yield_1[13], 0.130) + expect_equal(yield_1[14], 0.103) + expect_equal(yield_1[15], 0.077) + + yield_2 <- data$yield_2 + expect_equal(yield_2[1], NA_real_) + expect_equal(yield_2[2], NA_real_) + expect_equal(yield_2[3], NA_real_) + expect_equal(yield_2[4], NA_real_) + expect_equal(yield_2[5], NA_real_) + expect_equal(yield_2[6], NA_real_) + expect_equal(yield_2[7], NA_real_) + expect_equal(yield_2[8], NA_real_) + expect_equal(yield_2[9], NA_real_) + expect_equal(yield_2[10], NA_real_) + expect_equal(yield_2[11], NA_real_) + expect_equal(yield_2[12], NA_real_) + expect_equal(yield_2[13], NA_real_) + expect_equal(yield_2[14], NA_real_) + expect_equal(yield_2[15], NA_real_) + + etr_1 <- data$etr_1 + expect_equal(etr_1[1], 0.0) + expect_equal(etr_1[2], 2.147040) + expect_equal(etr_1[3], 5.698560) + expect_equal(etr_1[4], 9.610020) + expect_equal(etr_1[5], 24.4944) + expect_equal(etr_1[6], 32.94144) + expect_equal(etr_1[7], 33.895680) + expect_equal(etr_1[8], 48.61584) + expect_equal(etr_1[9], 70.52178) + expect_equal(etr_1[10], 89.72964) + expect_equal(etr_1[11], 107.352) + expect_equal(etr_1[12], 114.77130) + expect_equal(etr_1[13], 120.06540) + expect_equal(etr_1[14], 117.53742) + expect_equal(etr_1[15], 107.2071) + + etr_2 <- data$etr_2 + expect_equal(etr_2[1], NA_real_) + expect_equal(etr_2[2], NA_real_) + expect_equal(etr_2[3], NA_real_) + expect_equal(etr_2[4], NA_real_) + expect_equal(etr_2[5], NA_real_) + expect_equal(etr_2[6], NA_real_) + expect_equal(etr_2[7], NA_real_) + expect_equal(etr_2[8], NA_real_) + expect_equal(etr_2[9], NA_real_) + expect_equal(etr_2[10], NA_real_) + expect_equal(etr_2[11], NA_real_) + expect_equal(etr_2[12], NA_real_) + expect_equal(etr_2[13], NA_real_) + expect_equal(etr_2[14], NA_real_) + expect_equal(etr_2[15], NA_real_) +}) + +test_that("read_dual_pam_single_channel_I_data 20260130_01_efeutute_dual_pam_only_ps_1 - etr_factor 0.5", { + test_data_file <- testthat::test_path("data", "20260130_01_efeutute_dual_pam_only_ps_1.csv") + data <- read_dual_pam_single_channel_I_data(test_data_file, etr_factor = 0.5) + + par <- data$par + expect_equal(par[1], 0) + expect_equal(par[2], 6) + expect_equal(par[3], 16) + expect_equal(par[4], 29) + expect_equal(par[5], 80) + expect_equal(par[6], 152) + expect_equal(par[7], 208) + expect_equal(par[8], 364) + expect_equal(par[9], 581) + expect_equal(par[10], 913) + expect_equal(par[11], 1420) + expect_equal(par[12], 1763) + expect_equal(par[13], 2199) + expect_equal(par[14], 2717) + expect_equal(par[15], 3315) + + yield_1 <- data$yield_1 + expect_equal(yield_1[1], 0.128) + expect_equal(yield_1[2], 0.852) + expect_equal(yield_1[3], 0.848) + expect_equal(yield_1[4], 0.789) + expect_equal(yield_1[5], 0.729) + expect_equal(yield_1[6], 0.516) + expect_equal(yield_1[7], 0.388) + expect_equal(yield_1[8], 0.318) + expect_equal(yield_1[9], 0.289) + expect_equal(yield_1[10], 0.234) + expect_equal(yield_1[11], 0.180) + expect_equal(yield_1[12], 0.155) + expect_equal(yield_1[13], 0.130) + expect_equal(yield_1[14], 0.103) + expect_equal(yield_1[15], 0.077) + + yield_2 <- data$yield_2 + expect_equal(yield_2[1], NA_real_) + expect_equal(yield_2[2], NA_real_) + expect_equal(yield_2[3], NA_real_) + expect_equal(yield_2[4], NA_real_) + expect_equal(yield_2[5], NA_real_) + expect_equal(yield_2[6], NA_real_) + expect_equal(yield_2[7], NA_real_) + expect_equal(yield_2[8], NA_real_) + expect_equal(yield_2[9], NA_real_) + expect_equal(yield_2[10], NA_real_) + expect_equal(yield_2[11], NA_real_) + expect_equal(yield_2[12], NA_real_) + expect_equal(yield_2[13], NA_real_) + expect_equal(yield_2[14], NA_real_) + expect_equal(yield_2[15], NA_real_) + + etr_1 <- data$etr_1 + expect_equal(etr_1[1], 0.0) + expect_equal(etr_1[2], 1.2780) + expect_equal(etr_1[3], 3.3920) + expect_equal(etr_1[4], 5.72025) + expect_equal(etr_1[5], 14.580) + expect_equal(etr_1[6], 19.6080) + expect_equal(etr_1[7], 20.176) + expect_equal(etr_1[8], 28.938) + expect_equal(etr_1[9], 41.97725) + expect_equal(etr_1[10], 53.41050) + expect_equal(etr_1[11], 63.9) + expect_equal(etr_1[12], 68.31625) + expect_equal(etr_1[13], 71.46750) + expect_equal(etr_1[14], 69.96275) + expect_equal(etr_1[15], 63.81375) + + etr_2 <- data$etr_2 + expect_equal(etr_2[1], NA_real_) + expect_equal(etr_2[2], NA_real_) + expect_equal(etr_2[3], NA_real_) + expect_equal(etr_2[4], NA_real_) + expect_equal(etr_2[5], NA_real_) + expect_equal(etr_2[6], NA_real_) + expect_equal(etr_2[7], NA_real_) + expect_equal(etr_2[8], NA_real_) + expect_equal(etr_2[9], NA_real_) + expect_equal(etr_2[10], NA_real_) + expect_equal(etr_2[11], NA_real_) + expect_equal(etr_2[12], NA_real_) + expect_equal(etr_2[13], NA_real_) + expect_equal(etr_2[14], NA_real_) + expect_equal(etr_2[15], NA_real_) +}) + +test_that("read_dual_pam_single_channel_I_data 20260130_01_efeutute_dual_pam_only_ps_1 - fraction_photosystem > 1", { + test_data_file <- testthat::test_path("data", "20260130_01_efeutute_dual_pam_only_ps_1.csv") + expect_error(read_dual_pam_single_cannel_I_data(test_data_file, fraction_photosystem_I = 0.9, fraction_photosystem_II = 0.2)) +}) + +test_that("read_dual_pam_single_channel_I_data 20260130_01_efeutute_dual_pam_only_ps_1 - fraction_photosystem_I = 0.2, fraction_photosystem_II = 0.8", { + test_data_file <- testthat::test_path("data", "20260130_01_efeutute_dual_pam_only_ps_1.csv") + data <- read_dual_pam_single_channel_I_data(test_data_file, fraction_photosystem_I = 0.2, fraction_photosystem_II = 0.8) + + par <- data$par + expect_equal(par[1], 0) + expect_equal(par[2], 6) + expect_equal(par[3], 16) + expect_equal(par[4], 29) + expect_equal(par[5], 80) + expect_equal(par[6], 152) + expect_equal(par[7], 208) + expect_equal(par[8], 364) + expect_equal(par[9], 581) + expect_equal(par[10], 913) + expect_equal(par[11], 1420) + expect_equal(par[12], 1763) + expect_equal(par[13], 2199) + expect_equal(par[14], 2717) + expect_equal(par[15], 3315) + + yield_1 <- data$yield_1 + expect_equal(yield_1[1], 0.128) + expect_equal(yield_1[2], 0.852) + expect_equal(yield_1[3], 0.848) + expect_equal(yield_1[4], 0.789) + expect_equal(yield_1[5], 0.729) + expect_equal(yield_1[6], 0.516) + expect_equal(yield_1[7], 0.388) + expect_equal(yield_1[8], 0.318) + expect_equal(yield_1[9], 0.289) + expect_equal(yield_1[10], 0.234) + expect_equal(yield_1[11], 0.180) + expect_equal(yield_1[12], 0.155) + expect_equal(yield_1[13], 0.130) + expect_equal(yield_1[14], 0.103) + expect_equal(yield_1[15], 0.077) + + yield_2 <- data$yield_2 + expect_equal(yield_2[1], NA_real_) + expect_equal(yield_2[2], NA_real_) + expect_equal(yield_2[3], NA_real_) + expect_equal(yield_2[4], NA_real_) + expect_equal(yield_2[5], NA_real_) + expect_equal(yield_2[6], NA_real_) + expect_equal(yield_2[7], NA_real_) + expect_equal(yield_2[8], NA_real_) + expect_equal(yield_2[9], NA_real_) + expect_equal(yield_2[10], NA_real_) + expect_equal(yield_2[11], NA_real_) + expect_equal(yield_2[12], NA_real_) + expect_equal(yield_2[13], NA_real_) + expect_equal(yield_2[14], NA_real_) + expect_equal(yield_2[15], NA_real_) + + etr_1 <- data$etr_1 + expect_equal(etr_1[1], 0.0) + expect_equal(etr_1[2], 0.858816) + expect_equal(etr_1[3], 2.2794240) + expect_equal(etr_1[4], 3.8440080) + expect_equal(etr_1[5], 9.797760) + expect_equal(etr_1[6], 13.1765760) + expect_equal(etr_1[7], 13.5582720) + expect_equal(etr_1[8], 19.4463360) + expect_equal(etr_1[9], 28.208712) + expect_equal(etr_1[10], 35.891856) + expect_equal(etr_1[11], 42.94080) + expect_equal(etr_1[12], 45.908520) + expect_equal(etr_1[13], 48.02616) + expect_equal(etr_1[14], 47.014968) + expect_equal(etr_1[15], 42.88284) + + etr_2 <- data$etr_2 + expect_equal(etr_2[1], NA_real_) + expect_equal(etr_2[2], NA_real_) + expect_equal(etr_2[3], NA_real_) + expect_equal(etr_2[4], NA_real_) + expect_equal(etr_2[5], NA_real_) + expect_equal(etr_2[6], NA_real_) + expect_equal(etr_2[7], NA_real_) + expect_equal(etr_2[8], NA_real_) + expect_equal(etr_2[9], NA_real_) + expect_equal(etr_2[10], NA_real_) + expect_equal(etr_2[11], NA_real_) + expect_equal(etr_2[12], NA_real_) + expect_equal(etr_2[13], NA_real_) + expect_equal(etr_2[14], NA_real_) + expect_equal(etr_2[15], NA_real_) +}) \ No newline at end of file From cfe20486202811ab613c6f12a5d0d8d23be77daa Mon Sep 17 00:00:00 2001 From: JulienBoehm <180776296+JulienBoehm@users.noreply.github.com> Date: Fri, 17 Apr 2026 13:39:39 +0200 Subject: [PATCH 09/32] added link to researchgate in readme --- README.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/README.md b/README.md index 759f62a..582f5bb 100644 --- a/README.md +++ b/README.md @@ -18,6 +18,8 @@ Generated control plots make it possible to check each individual regression fit - J. Böhm, I. Blindow, N. Gyllenstrand, W. Diewald, and H. Schubert, ‘*Sphaerochara canadensis* (Charophyceae): A circumpolar species with a high temperature optimum’, Journal of Phycology, vol. 61, no. 6, pp. 1863–1873, Dec. 2025, doi: [10.1111/jpy.70111]( https://doi.org/10.1111/jpy.70111). +- A continuously updated overview of studies using this package can be accessed at [Researchgate](https://www.researchgate.net/publication/395536281_pam_Fast_and_Efficient_Processing_of_PAM_Data/citations) + ## Test coverage ```r From d92315ef4ce501a2d28771693e0552b04193c3c6 Mon Sep 17 00:00:00 2001 From: JulienBoehm <180776296+JulienBoehm@users.noreply.github.com> Date: Fri, 17 Apr 2026 14:39:50 +0200 Subject: [PATCH 10/32] added further tests for read_dual_pam_single_channel_II_data --- src/R/read_pam_data.R | 9 +- .../read_dual_pam_single_channel_II_data.Rd | 3 +- .../read_dual_pam_single_channel_I_data.Rd | 3 +- src/man/read_junior_pam_data.Rd | 3 +- ...est-read_dual_pam_single_channel_II_data.R | 145 ++++++++++++++++++ ...test-read_dual_pam_single_channel_I_data.R | 2 +- 6 files changed, 158 insertions(+), 7 deletions(-) diff --git a/src/R/read_pam_data.R b/src/R/read_pam_data.R index 19eb1d3..48dfd5c 100644 --- a/src/R/read_pam_data.R +++ b/src/R/read_pam_data.R @@ -241,7 +241,8 @@ read_dual_pam_data <- function( #' Available at: \url{https://www.walz.com/files/downloads/dualpamed05.pdf} #' } #' @examples -#' path <- file.path(system.file("extdata/dual_pam_single_channel_I_data", package = "pam"), "20260130_01_efeutute_dual_pam_only_ps_1.csv") +#' path <- file.path(system.file("extdata/dual_pam_single_channel_I_data", package = "pam"), +#' "20260130_01_efeutute_dual_pam_only_ps_1.csv") #' data <- read_dual_pam_single_channel_I_data(path) #' @export read_dual_pam_single_channel_I_data <- function( @@ -368,7 +369,8 @@ read_dual_pam_single_channel_I_data <- function( #' Available at: \url{https://www.walz.com/files/downloads/dualpamed05.pdf} #' } #' @examples -#' path <- file.path(system.file("extdata/dual_pam_single_channel_II_data", package = "pam"), "20260130_efeutute_dual_pam_only_ps_2.csv") +#' path <- file.path(system.file("extdata/dual_pam_single_channel_II_data", package = "pam"), +#' "20260130_efeutute_dual_pam_only_ps_2.csv") #' data <- read_dual_pam_single_channel_II_data(path) #' @export read_dual_pam_single_channel_II_data <- function( @@ -521,7 +523,8 @@ calc_etr <- function(yield, par, etr_factor, p_ratio) { #' Available at: \url{https://www.walz.com/files/downloads/dualpamed05.pdf} #' } #' @examples -#' path <- file.path(system.file("extdata/junior_pam_data", package = "pam"), "junior_pam_20250613.csv") +#' path <- file.path(system.file("extdata/junior_pam_data", package = "pam"), +#' "junior_pam_20250613.csv") #' data <- read_junior_pam_data(path) #' @export read_junior_pam_data <- function( diff --git a/src/man/read_dual_pam_single_channel_II_data.Rd b/src/man/read_dual_pam_single_channel_II_data.Rd index 45ab597..8c6887c 100644 --- a/src/man/read_dual_pam_single_channel_II_data.Rd +++ b/src/man/read_dual_pam_single_channel_II_data.Rd @@ -43,7 +43,8 @@ Calculates ETR using: A detailed documentation can be found under \url{https://github.com/biotoolbox/pam?tab=readme-ov-file#read_dual_pam_data} } \examples{ -path <- file.path(system.file("extdata/dual_pam_single_channel_II_data", package = "pam"), "20260130_efeutute_dual_pam_only_ps_2.csv") +path <- file.path(system.file("extdata/dual_pam_single_channel_II_data", package = "pam"), +"20260130_efeutute_dual_pam_only_ps_2.csv") data <- read_dual_pam_single_channel_II_data(path) } \references{ diff --git a/src/man/read_dual_pam_single_channel_I_data.Rd b/src/man/read_dual_pam_single_channel_I_data.Rd index f4440af..60d5331 100644 --- a/src/man/read_dual_pam_single_channel_I_data.Rd +++ b/src/man/read_dual_pam_single_channel_I_data.Rd @@ -43,7 +43,8 @@ Calculates ETR using: A detailed documentation can be found under \url{https://github.com/biotoolbox/pam?tab=readme-ov-file#read_dual_pam_data} } \examples{ -path <- file.path(system.file("extdata/dual_pam_single_channel_I_data", package = "pam"), "20260130_01_efeutute_dual_pam_only_ps_1.csv") +path <- file.path(system.file("extdata/dual_pam_single_channel_I_data", package = "pam"), +"20260130_01_efeutute_dual_pam_only_ps_1.csv") data <- read_dual_pam_single_channel_I_data(path) } \references{ diff --git a/src/man/read_junior_pam_data.Rd b/src/man/read_junior_pam_data.Rd index 67523f7..96663d0 100644 --- a/src/man/read_junior_pam_data.Rd +++ b/src/man/read_junior_pam_data.Rd @@ -43,7 +43,8 @@ Calculates ETR II using: A detailed documentation can be found under \url{https://github.com/biotoolbox/pam?tab=readme-ov-file} } \examples{ -path <- file.path(system.file("extdata/junior_pam_data", package = "pam"), "junior_pam_20250613.csv") +path <- file.path(system.file("extdata/junior_pam_data", package = "pam"), +"junior_pam_20250613.csv") data <- read_junior_pam_data(path) } \references{ diff --git a/src/tests/testthat/test-read_dual_pam_single_channel_II_data.R b/src/tests/testthat/test-read_dual_pam_single_channel_II_data.R index 40c352b..bbba415 100644 --- a/src/tests/testthat/test-read_dual_pam_single_channel_II_data.R +++ b/src/tests/testthat/test-read_dual_pam_single_channel_II_data.R @@ -66,4 +66,149 @@ test_that("read_dual_pam_single_channel_II_data 20260130_efeutute_dual_pam_only_ expect_equal(etr_2[9], 12.37824) expect_equal(etr_2[10], 12.71424) expect_equal(etr_2[11], 12.2052) +}) + +test_that("read_dual_pam_single_channel_II_data 20260130_efeutute_dual_pam_only_ps_2 - etr_factor 0.5", { + test_data_file <- testthat::test_path("data", "20260130_efeutute_dual_pam_only_ps_2.csv") + data <- read_dual_pam_single_channel_II_data(test_data_file, etr_factor = 0.5) + + par <- data$par + expect_equal(par[1], 0) + expect_equal(par[2], 39) + expect_equal(par[3], 49) + expect_equal(par[4], 62) + expect_equal(par[5], 113) + expect_equal(par[6], 185) + expect_equal(par[7], 241) + expect_equal(par[8], 397) + expect_equal(par[9], 614) + expect_equal(par[10], 946) + expect_equal(par[11], 1453) + + yield_1 <- data$yield_1 + expect_equal(yield_1[1], NA_real_) + expect_equal(yield_1[2], NA_real_) + expect_equal(yield_1[3], NA_real_) + expect_equal(yield_1[4], NA_real_) + expect_equal(yield_1[5], NA_real_) + expect_equal(yield_1[6], NA_real_) + expect_equal(yield_1[7], NA_real_) + expect_equal(yield_1[8], NA_real_) + expect_equal(yield_1[9], NA_real_) + expect_equal(yield_1[10], NA_real_) + expect_equal(yield_1[11], NA_real_) + + yield_2 <- data$yield_2 + expect_equal(yield_2[1], 0.7670) + expect_equal(yield_2[2], 0.3410) + expect_equal(yield_2[3], 0.3140) + expect_equal(yield_2[4], 0.2860) + expect_equal(yield_2[5], 0.2010) + expect_equal(yield_2[6], 0.139) + expect_equal(yield_2[7], 0.112) + expect_equal(yield_2[8], 0.0720) + expect_equal(yield_2[9], 0.0480) + expect_equal(yield_2[10], 0.0320) + expect_equal(yield_2[11], 0.02) + + etr_1 <- data$etr_1 + expect_equal(etr_1[1], NA_real_) + expect_equal(etr_1[2], NA_real_) + expect_equal(etr_1[3], NA_real_) + expect_equal(etr_1[4], NA_real_) + expect_equal(etr_1[5], NA_real_) + expect_equal(etr_1[6], NA_real_) + expect_equal(etr_1[7], NA_real_) + expect_equal(etr_1[8], NA_real_) + expect_equal(etr_1[9], NA_real_) + expect_equal(etr_1[10], NA_real_) + expect_equal(etr_1[11], NA_real_) + + etr_2 <- data$etr_2 + expect_equal(etr_2[1], 0) + expect_equal(etr_2[2], 3.32475) + expect_equal(etr_2[3], 3.84650) + expect_equal(etr_2[4], 4.433) + expect_equal(etr_2[5], 5.67825) + expect_equal(etr_2[6], 6.42875) + expect_equal(etr_2[7], 6.748) + expect_equal(etr_2[8], 7.146) + expect_equal(etr_2[9], 7.368) + expect_equal(etr_2[10], 7.568) + expect_equal(etr_2[11], 7.265) +}) + +test_that("read_dual_pam_single_channel_II_data 20260130_efeutute_dual_pam_only_ps_2 - fraction_photosystem > 1", { + test_data_file <- testthat::test_path("data", "20260130_efeutute_dual_pam_only_ps_2.csv") + expect_error(read_dual_pam_single_channel_II_data(test_data_file, fraction_photosystem_I = 0.9, fraction_photosystem_II = 0.2)) +}) + +test_that("read_dual_pam_single_channel_II_data 20260130_efeutute_dual_pam_only_ps_2 - fraction_photosystem_I = 0.2, fraction_photosystem_II = 0.8", { + test_data_file <- testthat::test_path("data", "20260130_efeutute_dual_pam_only_ps_2.csv") + data <- read_dual_pam_single_channel_II_data(test_data_file, fraction_photosystem_I = 0.2, fraction_photosystem_II = 0.8) + + par <- data$par + expect_equal(par[1], 0) + expect_equal(par[2], 39) + expect_equal(par[3], 49) + expect_equal(par[4], 62) + expect_equal(par[5], 113) + expect_equal(par[6], 185) + expect_equal(par[7], 241) + expect_equal(par[8], 397) + expect_equal(par[9], 614) + expect_equal(par[10], 946) + expect_equal(par[11], 1453) + + yield_1 <- data$yield_1 + expect_equal(yield_1[1], NA_real_) + expect_equal(yield_1[2], NA_real_) + expect_equal(yield_1[3], NA_real_) + expect_equal(yield_1[4], NA_real_) + expect_equal(yield_1[5], NA_real_) + expect_equal(yield_1[6], NA_real_) + expect_equal(yield_1[7], NA_real_) + expect_equal(yield_1[8], NA_real_) + expect_equal(yield_1[9], NA_real_) + expect_equal(yield_1[10], NA_real_) + expect_equal(yield_1[11], NA_real_) + + yield_2 <- data$yield_2 + expect_equal(yield_2[1], 0.7670) + expect_equal(yield_2[2], 0.3410) + expect_equal(yield_2[3], 0.3140) + expect_equal(yield_2[4], 0.2860) + expect_equal(yield_2[5], 0.2010) + expect_equal(yield_2[6], 0.139) + expect_equal(yield_2[7], 0.112) + expect_equal(yield_2[8], 0.0720) + expect_equal(yield_2[9], 0.0480) + expect_equal(yield_2[10], 0.0320) + expect_equal(yield_2[11], 0.02) + + etr_1 <- data$etr_1 + expect_equal(etr_1[1], NA_real_) + expect_equal(etr_1[2], NA_real_) + expect_equal(etr_1[3], NA_real_) + expect_equal(etr_1[4], NA_real_) + expect_equal(etr_1[5], NA_real_) + expect_equal(etr_1[6], NA_real_) + expect_equal(etr_1[7], NA_real_) + expect_equal(etr_1[8], NA_real_) + expect_equal(etr_1[9], NA_real_) + expect_equal(etr_1[10], NA_real_) + expect_equal(etr_1[11], NA_real_) + + etr_2 <- data$etr_2 + expect_equal(etr_2[1], 0.0) + expect_equal(etr_2[2], 8.936928) + expect_equal(etr_2[3], 10.3393920) + expect_equal(etr_2[4], 11.915904) + expect_equal(etr_2[5], 15.2631360) + expect_equal(etr_2[6], 17.28048) + expect_equal(etr_2[7], 18.1386240) + expect_equal(etr_2[8], 19.208448) + expect_equal(etr_2[9], 19.805184) + expect_equal(etr_2[10], 20.3427840) + expect_equal(etr_2[11], 19.52832) }) \ No newline at end of file diff --git a/src/tests/testthat/test-read_dual_pam_single_channel_I_data.R b/src/tests/testthat/test-read_dual_pam_single_channel_I_data.R index 9b40ad8..24a0eed 100644 --- a/src/tests/testthat/test-read_dual_pam_single_channel_I_data.R +++ b/src/tests/testthat/test-read_dual_pam_single_channel_I_data.R @@ -180,7 +180,7 @@ test_that("read_dual_pam_single_channel_I_data 20260130_01_efeutute_dual_pam_onl test_that("read_dual_pam_single_channel_I_data 20260130_01_efeutute_dual_pam_only_ps_1 - fraction_photosystem > 1", { test_data_file <- testthat::test_path("data", "20260130_01_efeutute_dual_pam_only_ps_1.csv") - expect_error(read_dual_pam_single_cannel_I_data(test_data_file, fraction_photosystem_I = 0.9, fraction_photosystem_II = 0.2)) + expect_error(read_dual_pam_single_channel_I_data(test_data_file, fraction_photosystem_I = 0.9, fraction_photosystem_II = 0.2)) }) test_that("read_dual_pam_single_channel_I_data 20260130_01_efeutute_dual_pam_only_ps_1 - fraction_photosystem_I = 0.2, fraction_photosystem_II = 0.8", { From feaa1aec03e5bd24d11e8332bbbdd8d6965bc0e6 Mon Sep 17 00:00:00 2001 From: JulienBoehm <180776296+JulienBoehm@users.noreply.github.com> Date: Fri, 17 Apr 2026 15:40:07 +0200 Subject: [PATCH 11/32] added read_dual_pam_single_chanel functions to Readme --- README.md | 119 +++++++++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 117 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 582f5bb..8d31838 100644 --- a/README.md +++ b/README.md @@ -14,9 +14,9 @@ Generated control plots make it possible to check each individual regression fit ## Publications using this package -- J. Böhm, J. Trossen, I. Blindow, and H. Schubert, ‘Impact of temperature and light on the physiology and morphology of *Chara hispida* L. (Charophyceae)’, Aquatic Botany, vol. 206, p. 104022, Sep. 2026, doi: [10.1016/j.aquabot.2026.104022]( https://doi.org/10.1016/j.aquabot.2026.104022). +- J. Böhm, J. Trossen, I. Blindow, and H. Schubert, ‘Impact of temperature and light on the physiology and morphology of *Chara hispida* L. (Charophyceae)’, Aquatic Botany, vol. 206, p. 104022, Sep. 2026, doi: [10.1016/j.aquabot.2026.104022](https://www.researchgate.net/publication/402846331_Impact_of_temperature_and_light_on_the_physiology_and_morphology_of_Chara_hispida_L_Charophyceae). -- J. Böhm, I. Blindow, N. Gyllenstrand, W. Diewald, and H. Schubert, ‘*Sphaerochara canadensis* (Charophyceae): A circumpolar species with a high temperature optimum’, Journal of Phycology, vol. 61, no. 6, pp. 1863–1873, Dec. 2025, doi: [10.1111/jpy.70111]( https://doi.org/10.1111/jpy.70111). +- J. Böhm, I. Blindow, N. Gyllenstrand, W. Diewald, and H. Schubert, ‘*Sphaerochara canadensis* (Charophyceae): A circumpolar species with a high temperature optimum’, Journal of Phycology, vol. 61, no. 6, pp. 1863–1873, Dec. 2025, doi: [10.1111/jpy.70111](https://www.researchgate.net/publication/398295400_Sphaerochara_canadensis_Charophyceae_A_circumpolar_species_with_a_high_temperature_optimum). - A continuously updated overview of studies using this package can be accessed at [Researchgate](https://www.researchgate.net/publication/395536281_pam_Fast_and_Efficient_Processing_of_PAM_Data/citations) @@ -150,6 +150,121 @@ fraction_photosystem_II = 0.5) --- +### read_dual_pam_single_channel_I_data() + +#### Description + +This function reads the original CSV file as created by the [DUAL-PAM-100](https://www.walz.com/products/dual-pam-100/) software in single channel mode (Photosystem I), processes it by calculating $$ETR$$ values for Photosystem I, and returns a cleaned dataset. + +#### Parameters + +- **csv_path**: A string representing the file path to the CSV file. +- **remove_recovery**: Automatic removal of recovery measurements after the actual Pi curve for an accurate regression. Default is `TRUE`. +- **etr_factor**: A numeric value used as a factor for calculating ETR. Default is `0.84`. +- **fraction_photosystem_I**: A numeric value representing the relative distribution of absorbed PAR to Photosystem I used in the ETR calculation formula. Default is `0.5`. + Calculated as: $$\textit{Fraction of Photosystem I} = \frac{PPS 1}{PPS 1+2}$$ +- **fraction_photosystem_II**: A numeric value representing the relative distribution of absorbed PAR to Photosystem II. Default is `0.5`. + (Must sum with Photosystem I fraction to 1.) + +#### Details + +ETR values for **Photosystem I** are calculated using the following formula: + +$$ \textit{ETR (I)} = PAR \cdot \textit{ETR–Factor} \cdot \textit{Fraction of Photosystem I} \cdot \textit{Yield (I)} $$ + +The function processes the provided CSV file by: + +- Reading the CSV data using `read.csv()` and converting it to a `data.table`. +- Validating the raw Dual-PAM data with `validate_dual_pam_single_channel_I_data()`. +- Filtering rows where the column `ID` equals `SP`. +- Combining the `Date` and `Time` columns to create a `DateTime` column and ordering the data chronologically. +- Extracting the initial Pm.-Det. measurement at `PAR = 0` to calculate the first ETR value. +- Iterating through all rows with `Action == "P700 SP"` to calculate ETR values for Photosystem I (`Y.I.`). +- Optionally stopping at the recovery period if `remove_recovery = TRUE`. + +#### Return + +- Returning a table containing: + - `par`: Photosynthetically active radiation. + - `yield_1`: Yield of Photosystem I. + - `yield_2`: `NA` (not available in single channel PS I mode). + - `etr_1`: Calculated ETR for Photosystem I. + - `etr_2`: `NA` (not available in single channel PS I mode). + +#### Example + +```r +data <- read_dual_pam_single_channel_I_data( + "path/to/data.csv", + remove_recovery = TRUE, + etr_factor = 0.84, + fraction_photosystem_I = 0.5, + fraction_photosystem_II = 0.5 +) +``` + +#### References + +- Heinz Walz GmbH. (2024). *DUAL-PAM-100 DUAL-PAM/F MANUAL, 5th Edition, April 2024, Chapter 7 (pp. 162-172).* Heinz Walz GmbH, Effeltrich, Germany. Available at: [DUAL-PAM-100 Manual](https://www.walz.com/files/downloads/dualpamed05.pdf) +--- + +### read_dual_pam_single_channel_II_data() + +#### Description + +This function reads the original CSV file as created by the [DUAL-PAM-100](https://www.walz.com/products/dual-pam-100/) software in single channel mode (Photosystem II), processes it by calculating $$ETR$$ values for Photosystem II, and returns a cleaned dataset. + +#### Parameters + +- **csv_path**: A string representing the file path to the CSV file. +- **remove_recovery**: Automatic removal of recovery measurements after the actual Pi curve for an accurate regression. Default is `TRUE`. +- **etr_factor**: A numeric value used as a factor for calculating ETR. Default is `0.84`. +- **fraction_photosystem_I**: A numeric value representing the relative distribution of absorbed PAR to Photosystem I. Default is `0.5`. +- **fraction_photosystem_II**: A numeric value representing the relative distribution of absorbed PAR to Photosystem II used in the ETR calculation formula. Default is `0.5`. + Calculated as: $$\textit{Fraction of Photosystem II} = \frac{PPS 2}{PPS 1+2}$$ + +#### Details + +ETR values for Photosystem II are calculated using the following formula: + +$$ \textit{ETR (II)} = PAR \cdot \textit{ETR–Factor} \cdot \textit{Fraction of Photosystem II} \cdot \textit{Yield (II)} $$ + +The function processes the provided CSV file by: + +- Reading the CSV data using `read.csv()` and converting it to a `data.table`. +- Validating the raw Dual-PAM data with `validate_dual_pam_single_channel_II_data()`. +- Filtering rows where the column `ID` equals `SP`. +- Combining the `Date` and `Time` columns to create a `DateTime` column and ordering the data chronologically. +- Extracting the initial **Fm-Det.** measurement at `PAR = 0` to calculate the first ETR value. +- Iterating through all rows with `Action == "Fluo. SP"` to calculate ETR values for Photosystem II (`Y.II.`). +- Optionally stopping at the recovery period if `remove_recovery = TRUE`. + +#### Return + +- Returning a table containing: + - `par`: Photosynthetically active radiation. + - `yield_1`: `NA` (not available in single channel Photosystem II mode). + - `yield_2`: Yield of Photosystem II. + - `etr_1`: `NA` (not available in single channel Photosystem II mode). + - `etr_2`: Calculated ETR for Photosystem II. + +#### Example + +```r +data <- read_dual_pam_single_channel_II_data( + "path/to/data.csv", + remove_recovery = TRUE, + etr_factor = 0.84, + fraction_photosystem_I = 0.5, + fraction_photosystem_II = 0.5 +) +``` + +#### References + +- Heinz Walz GmbH. (2024). *DUAL-PAM-100 DUAL-PAM/F MANUAL, 5th Edition, April 2024, Chapter 7 (pp. 162-172).* Heinz Walz GmbH, Effeltrich, Germany. Available at: [DUAL-PAM-100 Manual](https://www.walz.com/files/downloads/dualpamed05.pdf) +--- + ### read_junior_pam_data() #### Description From c3c3a6cc003c26a11ff6f97a92130902b799d254 Mon Sep 17 00:00:00 2001 From: Phi-S <926151+Phi-S@users.noreply.github.com> Date: Mon, 20 Apr 2026 12:16:35 +0200 Subject: [PATCH 12/32] Fix error handling messages in Eilers-Peeters regression and update numeric checks in compare_regression_models --- src/R/compare_regression_models.R | 6 +++--- src/R/eilers_peeters.R | 10 +++++----- src/R/platt.R | 4 ++-- src/R/read_pam_data.R | 2 +- 4 files changed, 11 insertions(+), 11 deletions(-) diff --git a/src/R/compare_regression_models.R b/src/R/compare_regression_models.R index 793767f..4e7c9b3 100644 --- a/src/R/compare_regression_models.R +++ b/src/R/compare_regression_models.R @@ -132,7 +132,7 @@ compare_regression_models <- function(data_dir, etr_type, read_func) { platt <- platt_generate_regression_internal(data, etr_type) platt_sdiff <- platt[["residual_sum_of_squares"]] - if (!is.numeric(eilers_peeters_sdiff)) { + if (!is.numeric(platt_sdiff)) { stop("platt residual_sum_of_squares result is not numeric") } if (is.na(platt_sdiff)) { @@ -141,7 +141,7 @@ compare_regression_models <- function(data_dir, etr_type, read_func) { vollenweider <- vollenweider_generate_regression_internal(data, etr_type) vollenweider_sdiff <- vollenweider[["residual_sum_of_squares"]] - if (!is.numeric(eilers_peeters_sdiff)) { + if (!is.numeric(vollenweider_sdiff)) { stop("vollenweider residual_sum_of_squares result is not numeric") } if (is.na(vollenweider_sdiff)) { @@ -150,7 +150,7 @@ compare_regression_models <- function(data_dir, etr_type, read_func) { walsby <- walsby_generate_regression_internal(data, etr_type) walsby_sdiff <- walsby[["residual_sum_of_squares"]] - if (!is.numeric(eilers_peeters_sdiff)) { + if (!is.numeric(walsby_sdiff)) { stop("walsby residual_sum_of_squares result is not numeric") } if (is.na(walsby_sdiff)) { diff --git a/src/R/eilers_peeters.R b/src/R/eilers_peeters.R index 83e3310..8ee471a 100644 --- a/src/R/eilers_peeters.R +++ b/src/R/eilers_peeters.R @@ -167,7 +167,7 @@ eilers_peeters_generate_regression_internal <- function( eilers_peeters_message(paste("failed to calculate pm: warning:", w)) }, error = function(e) { - eilers_peeters_message(paste("failed to calculate pm: error:", w)) + eilers_peeters_message(paste("failed to calculate pm: error:", e)) } ) @@ -180,7 +180,7 @@ eilers_peeters_generate_regression_internal <- function( eilers_peeters_message(paste("failed to calculate s: warning:", w)) }, error = function(e) { - eilers_peeters_message(paste("failed to calculate s: error:", w)) + eilers_peeters_message(paste("failed to calculate s: error:", e)) } ) @@ -193,7 +193,7 @@ eilers_peeters_generate_regression_internal <- function( eilers_peeters_message(paste("failed to calculate ik: warning:", w)) }, error = function(e) { - eilers_peeters_message(paste("failed to calculate ik: error:", w)) + eilers_peeters_message(paste("failed to calculate ik: error:", e)) } ) @@ -206,7 +206,7 @@ eilers_peeters_generate_regression_internal <- function( eilers_peeters_message(paste("failed to calculate im: warning:", w)) }, error = function(e) { - eilers_peeters_message(paste("failed to calculate im: error:", w)) + eilers_peeters_message(paste("failed to calculate im: error:", e)) } ) @@ -219,7 +219,7 @@ eilers_peeters_generate_regression_internal <- function( eilers_peeters_message(paste("failed to calculate w: warning:", w)) }, error = function(e) { - eilers_peeters_message(paste("failed to calculate w: error:", w)) + eilers_peeters_message(paste("failed to calculate w: error:", e)) } ) diff --git a/src/R/platt.R b/src/R/platt.R index c992518..b68845d 100644 --- a/src/R/platt.R +++ b/src/R/platt.R @@ -319,8 +319,8 @@ platt_modified <- function(model_result) { etr_type = get_etr_type_from_model_result(model_result), etr_regression_data = get_etr_regression_data_from_model_result(model_result), residual_sum_of_squares = get_sdiff_from_model_result(model_result), - model_result[["root_mean_squared_error"]], - model_result[["relative_root_mean_squared_error"]], + root_mean_squared_error = model_result[["root_mean_squared_error"]], + relative_root_mean_squared_error = model_result[["relative_root_mean_squared_error"]], a = model_result[["ps"]], b = model_result[["alpha"]], c = model_result[["beta"]], diff --git a/src/R/read_pam_data.R b/src/R/read_pam_data.R index 8651931..d70b255 100644 --- a/src/R/read_pam_data.R +++ b/src/R/read_pam_data.R @@ -142,7 +142,7 @@ read_dual_pam_data <- function( data$DateTime <- date_time_col_values data <- data[order(data$DateTime), ] - pm_det_row <- pm_det_row <- subset(data, data$PAR == 0 & data$Action == "Pm.-Det.") + pm_det_row <- subset(data, data$PAR == 0 & data$Action == "Pm.-Det.") yield_1_first <- pm_det_row$Y.I. recalc_etr_1 <- calc_etr(yield_1_first, 0, etr_factor, fraction_photosystem_I) From 3985a78cd81aaded483ea1a39271374df75ebeb7 Mon Sep 17 00:00:00 2001 From: JulienBoehm <180776296+JulienBoehm@users.noreply.github.com> Date: Mon, 20 Apr 2026 13:21:25 +0200 Subject: [PATCH 13/32] changed variable name from sdiff to residual_sum_of_squares --- src/R/compare_regression_models.R | 32 +++++++++++++++---------------- src/R/eilers_peeters.R | 2 +- src/R/platt.R | 2 +- src/R/util.R | 2 +- src/R/vollenweider.R | 2 +- src/R/walsby.R | 2 +- 6 files changed, 21 insertions(+), 21 deletions(-) diff --git a/src/R/compare_regression_models.R b/src/R/compare_regression_models.R index 4e7c9b3..b3bd470 100644 --- a/src/R/compare_regression_models.R +++ b/src/R/compare_regression_models.R @@ -122,45 +122,45 @@ compare_regression_models <- function(data_dir, etr_type, read_func) { tryCatch( { eilers_peeters <- eilers_peeters_generate_regression_internal(data, etr_type) - eilers_peeters_sdiff <- eilers_peeters[["residual_sum_of_squares"]] - if (!is.numeric(eilers_peeters_sdiff)) { + eilers_peeters_residual_sum_of_squares <- eilers_peeters[["residual_sum_of_squares"]] + if (!is.numeric(eilers_peeters_residual_sum_of_squares)) { stop("eilers_peeters residual_sum_of_squares result is not numeric") } - if (is.na(eilers_peeters_sdiff)) { + if (is.na(eilers_peeters_residual_sum_of_squares)) { stop("failed to calculate residual_sum_of_squares with eilers_peeters") } platt <- platt_generate_regression_internal(data, etr_type) - platt_sdiff <- platt[["residual_sum_of_squares"]] - if (!is.numeric(platt_sdiff)) { + platt_residual_sum_of_squares <- platt[["residual_sum_of_squares"]] + if (!is.numeric(platt_residual_sum_of_squares)) { stop("platt residual_sum_of_squares result is not numeric") } - if (is.na(platt_sdiff)) { + if (is.na(platt_residual_sum_of_squares)) { stop("failed to calculate residual_sum_of_squares with platt") } vollenweider <- vollenweider_generate_regression_internal(data, etr_type) - vollenweider_sdiff <- vollenweider[["residual_sum_of_squares"]] - if (!is.numeric(vollenweider_sdiff)) { + vollenweider_residual_sum_of_squares <- vollenweider[["residual_sum_of_squares"]] + if (!is.numeric(vollenweider_residual_sum_of_squares)) { stop("vollenweider residual_sum_of_squares result is not numeric") } - if (is.na(vollenweider_sdiff)) { + if (is.na(vollenweider_residual_sum_of_squares)) { stop("failed to calculate residual_sum_of_squares with vollenweider") } walsby <- walsby_generate_regression_internal(data, etr_type) - walsby_sdiff <- walsby[["residual_sum_of_squares"]] - if (!is.numeric(walsby_sdiff)) { + walsby_residual_sum_of_squares <- walsby[["residual_sum_of_squares"]] + if (!is.numeric(walsby_residual_sum_of_squares)) { stop("walsby residual_sum_of_squares result is not numeric") } - if (is.na(walsby_sdiff)) { + if (is.na(walsby_residual_sum_of_squares)) { stop("failed to calculate residual_sum_of_squares with walsby") } - data1 <- data.table::data.table(group = "eilers_peeters", value = eilers_peeters_sdiff) - data2 <- data.table::data.table(group = "platt", value = platt_sdiff) - data3 <- data.table::data.table(group = "vollenweider", value = vollenweider_sdiff) - data4 <- data.table::data.table(group = "walsby", value = walsby_sdiff) + data1 <- data.table::data.table(group = "eilers_peeters", value = eilers_peeters_residual_sum_of_squares) + data2 <- data.table::data.table(group = "platt", value = platt_residual_sum_of_squares) + data3 <- data.table::data.table(group = "vollenweider", value = vollenweider_residual_sum_of_squares) + data4 <- data.table::data.table(group = "walsby", value = walsby_residual_sum_of_squares) combined_data <- rbind(data1, data2, data3, data4) combined_data <- combined_data[order(combined_data$value), ] diff --git a/src/R/eilers_peeters.R b/src/R/eilers_peeters.R index 8ee471a..6ec37b1 100644 --- a/src/R/eilers_peeters.R +++ b/src/R/eilers_peeters.R @@ -310,7 +310,7 @@ eilers_peeters_modified <- function(model_result) { result <- create_modified_model_result( get_etr_type_from_model_result(model_result), get_etr_regression_data_from_model_result(model_result), - get_sdiff_from_model_result(model_result), + get_residual_sum_of_squares_from_model_result(model_result), model_result[["root_mean_squared_error"]], model_result[["relative_root_mean_squared_error"]], model_result[["a"]], diff --git a/src/R/platt.R b/src/R/platt.R index b68845d..f04318c 100644 --- a/src/R/platt.R +++ b/src/R/platt.R @@ -318,7 +318,7 @@ platt_modified <- function(model_result) { result <- create_modified_model_result( etr_type = get_etr_type_from_model_result(model_result), etr_regression_data = get_etr_regression_data_from_model_result(model_result), - residual_sum_of_squares = get_sdiff_from_model_result(model_result), + residual_sum_of_squares = get_residual_sum_of_squares_from_model_result(model_result), root_mean_squared_error = model_result[["root_mean_squared_error"]], relative_root_mean_squared_error = model_result[["relative_root_mean_squared_error"]], a = model_result[["ps"]], diff --git a/src/R/util.R b/src/R/util.R index 931a7b6..44336d6 100644 --- a/src/R/util.R +++ b/src/R/util.R @@ -26,7 +26,7 @@ get_etr_regression_data_from_model_result <- function(model_result) { return(model_result[["etr_regression_data"]]) } -get_sdiff_from_model_result <- function(model_result) { +get_residual_sum_of_squares_from_model_result <- function(model_result) { return(model_result[["residual_sum_of_squares"]]) } diff --git a/src/R/vollenweider.R b/src/R/vollenweider.R index 62ed785..ae3282a 100644 --- a/src/R/vollenweider.R +++ b/src/R/vollenweider.R @@ -324,7 +324,7 @@ vollenweider_modified <- function(model_result) { result <- create_modified_model_result( etr_type = get_etr_type_from_model_result(model_result), etr_regression_data = get_etr_regression_data_from_model_result(model_result), - residual_sum_of_squares = get_sdiff_from_model_result(model_result), + residual_sum_of_squares = get_residual_sum_of_squares_from_model_result(model_result), model_result[["root_mean_squared_error"]], model_result[["relative_root_mean_squared_error"]], a = model_result[["pmax"]], diff --git a/src/R/walsby.R b/src/R/walsby.R index 4908e0d..f5aac8b 100644 --- a/src/R/walsby.R +++ b/src/R/walsby.R @@ -257,7 +257,7 @@ walsby_modified <- function(model_result) { result <- create_modified_model_result( etr_type = get_etr_type_from_model_result(model_result), etr_regression_data = get_etr_regression_data_from_model_result(model_result), - residual_sum_of_squares = get_sdiff_from_model_result(model_result), + residual_sum_of_squares = get_residual_sum_of_squares_from_model_result(model_result), model_result[["root_mean_squared_error"]], model_result[["relative_root_mean_squared_error"]], a = model_result[["etr_max"]], From 49c79c1171d2cc9959ffa281ea7787e93ef1c944 Mon Sep 17 00:00:00 2001 From: Phi-S <926151+Phi-S@users.noreply.github.com> Date: Mon, 20 Apr 2026 14:07:52 +0200 Subject: [PATCH 14/32] formatting and fix test case for read_pam_2500_data --- src/R/read_pam_data.R | 35 ++++++++++---------- src/R/validation.R | 3 +- src/tests/testthat/test-read_pam_2500_data.R | 2 +- 3 files changed, 20 insertions(+), 20 deletions(-) diff --git a/src/R/read_pam_data.R b/src/R/read_pam_data.R index fe6cfc5..05e79cf 100644 --- a/src/R/read_pam_data.R +++ b/src/R/read_pam_data.R @@ -111,11 +111,12 @@ read_universal_data <- function(csv_path, #' data <- read_dual_pam_data(path) #' @export read_dual_pam_data <- function( - csv_path, - remove_recovery = TRUE, - etr_factor = 0.84, - fraction_photosystem_I = 0.5, - fraction_photosystem_II = 0.5) { + csv_path, + remove_recovery = TRUE, + etr_factor = 0.84, + fraction_photosystem_I = 0.5, + fraction_photosystem_II = 0.5 +) { if (fraction_photosystem_I + fraction_photosystem_II != 1) { stop("The sum of fraction_photosystem_I and fraction_photosystem_II must be equal 1.") } @@ -269,11 +270,12 @@ calc_etr <- function(yield, par, etr_factor, p_ratio) { #' data <- read_junior_pam_data(path) #' @export read_junior_pam_data <- function( - csv_path, - remove_recovery = TRUE, - etr_factor = 0.84, - fraction_photosystem_I = 0.5, - fraction_photosystem_II = 0.5) { + csv_path, + remove_recovery = TRUE, + etr_factor = 0.84, + fraction_photosystem_I = 0.5, + fraction_photosystem_II = 0.5 +) { if (fraction_photosystem_I + fraction_photosystem_II != 1) { stop("The sum of fraction_photosystem_I and fraction_photosystem_II must be equal 1.") } @@ -388,11 +390,12 @@ read_junior_pam_data <- function( #' data <- read_pam_2500_data(path) #' @export read_pam_2500_data <- function( - csv_path, - remove_recovery = TRUE, - etr_factor = 0.84, - fraction_photosystem_I = 0.5, - fraction_photosystem_II = 0.5) { + csv_path, + remove_recovery = TRUE, + etr_factor = 0.84, + fraction_photosystem_I = 0.5, + fraction_photosystem_II = 0.5 +) { if (fraction_photosystem_I + fraction_photosystem_II != 1) { stop("The sum of fraction_photosystem_I and fraction_photosystem_II must be equal 1.") } @@ -419,7 +422,6 @@ read_pam_2500_data <- function( data$DateTime <- date_time_col_values data <- data[order(data$DateTime), ] - result <- data.table::data.table( par = numeric(), yield_1 = numeric(), @@ -461,4 +463,3 @@ read_pam_2500_data <- function( } ) } - diff --git a/src/R/validation.R b/src/R/validation.R index bee93c9..967052c 100644 --- a/src/R/validation.R +++ b/src/R/validation.R @@ -163,10 +163,9 @@ validate_pam_2500_data <- function(data) { stop("required col 'Time' not found") } - if (!"Y.II." %in% colnames(data)) { + if (!"Y.II." %in% colnames(data)) { stop("required col 'Y(II)' not found") } - } validate_etr_regression_data <- function(regression_data) { diff --git a/src/tests/testthat/test-read_pam_2500_data.R b/src/tests/testthat/test-read_pam_2500_data.R index 5ef4f14..bdbb3bd 100644 --- a/src/tests/testthat/test-read_pam_2500_data.R +++ b/src/tests/testthat/test-read_pam_2500_data.R @@ -151,7 +151,7 @@ test_that("read_pam_2500_data 20260311_1(2)_pam_2500.CSV - etr-factor 0.5", { test_that("read_pam_2500_data 20260311_1(2)_pam_2500.CSV - - fraction_photosystem_I = 0.2, fraction_photosystem_II = 0.8", { test_data_file <- testthat::test_path("data", "20260311_1(2)_pam_2500.CSV") data <- read_pam_2500_data(test_data_file, etr_factor = 0.5) - expect_error(read_pam_2000_data(test_data_file, fraction_photosystem_I = 0.9, fraction_photosystem_II = 0.2)) + expect_error(read_pam_2500_data(test_data_file, fraction_photosystem_I = 0.9, fraction_photosystem_II = 0.2)) }) test_that("read_pam_2500_data 20260311_1(2)_pam_2500.CSV - fraction_photosystem_I = 0.2, fraction_photosystem_II = 0.8", { From 81c77f4427fd92264f0aa242130addae439b76ea Mon Sep 17 00:00:00 2001 From: Phi-S <926151+Phi-S@users.noreply.github.com> Date: Mon, 20 Apr 2026 14:25:30 +0200 Subject: [PATCH 15/32] Remove unnecessary data loading in test for fraction photosystem parameters --- src/tests/testthat/test-read_pam_2500_data.R | 1 - 1 file changed, 1 deletion(-) diff --git a/src/tests/testthat/test-read_pam_2500_data.R b/src/tests/testthat/test-read_pam_2500_data.R index bdbb3bd..97c31c8 100644 --- a/src/tests/testthat/test-read_pam_2500_data.R +++ b/src/tests/testthat/test-read_pam_2500_data.R @@ -150,7 +150,6 @@ test_that("read_pam_2500_data 20260311_1(2)_pam_2500.CSV - etr-factor 0.5", { test_that("read_pam_2500_data 20260311_1(2)_pam_2500.CSV - - fraction_photosystem_I = 0.2, fraction_photosystem_II = 0.8", { test_data_file <- testthat::test_path("data", "20260311_1(2)_pam_2500.CSV") - data <- read_pam_2500_data(test_data_file, etr_factor = 0.5) expect_error(read_pam_2500_data(test_data_file, fraction_photosystem_I = 0.9, fraction_photosystem_II = 0.2)) }) From 907b3ff89ab5485781eadfd34ebbcd6cf9aa57e1 Mon Sep 17 00:00:00 2001 From: PhiS <926151+Phi-S@users.noreply.github.com> Date: Mon, 20 Apr 2026 14:28:10 +0200 Subject: [PATCH 16/32] Update rcmdcheck.yml --- .github/workflows/rcmdcheck.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/rcmdcheck.yml b/.github/workflows/rcmdcheck.yml index cf8fd69..55d1efa 100644 --- a/.github/workflows/rcmdcheck.yml +++ b/.github/workflows/rcmdcheck.yml @@ -10,9 +10,9 @@ name: rcmdcheck on: push: - branches: [ "main" ] + branches: [ "main", "dev" ] pull_request: - branches: [ "main" ] + branches: [ "main", "dev" ] permissions: contents: read From 03440aa248a27aae0a5a4bf5042110c749fb6027 Mon Sep 17 00:00:00 2001 From: Phi-S <926151+Phi-S@users.noreply.github.com> Date: Mon, 20 Apr 2026 15:26:07 +0200 Subject: [PATCH 17/32] used walz names for channels fluo and p700 --- README.md | 18 ++-- src/NAMESPACE | 4 +- src/R/combo_plot_control.R | 11 ++- src/R/compare_regression_models.R | 1 - src/R/eilers_peeters.R | 29 +++--- src/R/platt.R | 35 ++++--- src/R/read_pam_data.R | 97 +++++++++++-------- src/R/validation.R | 81 ++++++++-------- .../20260130_efeutute_dual_pam_only_fluo.csv} | 0 ...260130_01_efeutute_dual_pam_only_p700.csv} | 0 ...read_dual_pam_single_channel_fluo_data.Rd} | 16 +-- ...read_dual_pam_single_channel_p700_data.Rd} | 24 ++--- src/man/read_junior_pam_data.Rd | 6 +- ...260130_01_efeutute_dual_pam_only_p700.csv} | 0 ... 20260130_efeutute_dual_pam_only_fluo.csv} | 0 src/tests/testthat/test-read_dual_pam_data.R | 8 +- ...-read_dual_pam_single_channel_fluo_data.R} | 26 ++--- ...-read_dual_pam_single_channel_p700_data.R} | 26 ++--- 18 files changed, 201 insertions(+), 181 deletions(-) rename src/inst/extdata/{dual_pam_single_channel_II_data/20260130_efeutute_dual_pam_only_ps_2.csv => dual_pam_single_channel_fluo_data/20260130_efeutute_dual_pam_only_fluo.csv} (100%) rename src/inst/extdata/{dual_pam_single_channel_I_data/20260130_01_efeutute_dual_pam_only_ps_1.csv => dual_pam_single_channel_p700_data/20260130_01_efeutute_dual_pam_only_p700.csv} (100%) rename src/man/{read_dual_pam_single_channel_II_data.Rd => read_dual_pam_single_channel_fluo_data.Rd} (81%) rename src/man/{read_dual_pam_single_channel_I_data.Rd => read_dual_pam_single_channel_p700_data.Rd} (73%) rename src/tests/testthat/data/{20260130_01_efeutute_dual_pam_only_ps_1.csv => 20260130_01_efeutute_dual_pam_only_p700.csv} (100%) rename src/tests/testthat/data/{20260130_efeutute_dual_pam_only_ps_2.csv => 20260130_efeutute_dual_pam_only_fluo.csv} (100%) rename src/tests/testthat/{test-read_dual_pam_single_channel_II_data.R => test-read_dual_pam_single_channel_fluo_data.R} (86%) rename src/tests/testthat/{test-read_dual_pam_single_channel_I_data.R => test-read_dual_pam_single_channel_p700_data.R} (89%) diff --git a/README.md b/README.md index 8d31838..92bb9da 100644 --- a/README.md +++ b/README.md @@ -150,11 +150,11 @@ fraction_photosystem_II = 0.5) --- -### read_dual_pam_single_channel_I_data() +### read_dual_pam_single_channel_p700_data() #### Description -This function reads the original CSV file as created by the [DUAL-PAM-100](https://www.walz.com/products/dual-pam-100/) software in single channel mode (Photosystem I), processes it by calculating $$ETR$$ values for Photosystem I, and returns a cleaned dataset. +This function reads the original CSV file as created by the [DUAL-PAM-100](https://www.walz.com/products/dual-pam-100/) software in single channel mode (P700), processes it by calculating $$ETR$$ values for Photosystem I, and returns a cleaned dataset. #### Parameters @@ -168,14 +168,14 @@ This function reads the original CSV file as created by the [DUAL-PAM-100](https #### Details -ETR values for **Photosystem I** are calculated using the following formula: +ETR values for Photosystem I are calculated using the following formula: $$ \textit{ETR (I)} = PAR \cdot \textit{ETR–Factor} \cdot \textit{Fraction of Photosystem I} \cdot \textit{Yield (I)} $$ The function processes the provided CSV file by: - Reading the CSV data using `read.csv()` and converting it to a `data.table`. -- Validating the raw Dual-PAM data with `validate_dual_pam_single_channel_I_data()`. +- Validating the raw Dual-PAM data with `validate_dual_pam_single_channel_p700_data()`. - Filtering rows where the column `ID` equals `SP`. - Combining the `Date` and `Time` columns to create a `DateTime` column and ordering the data chronologically. - Extracting the initial Pm.-Det. measurement at `PAR = 0` to calculate the first ETR value. @@ -194,7 +194,7 @@ The function processes the provided CSV file by: #### Example ```r -data <- read_dual_pam_single_channel_I_data( +data <- read_dual_pam_single_channel_p700_data( "path/to/data.csv", remove_recovery = TRUE, etr_factor = 0.84, @@ -208,11 +208,11 @@ data <- read_dual_pam_single_channel_I_data( - Heinz Walz GmbH. (2024). *DUAL-PAM-100 DUAL-PAM/F MANUAL, 5th Edition, April 2024, Chapter 7 (pp. 162-172).* Heinz Walz GmbH, Effeltrich, Germany. Available at: [DUAL-PAM-100 Manual](https://www.walz.com/files/downloads/dualpamed05.pdf) --- -### read_dual_pam_single_channel_II_data() +### read_dual_pam_single_channel_fluo_data() #### Description -This function reads the original CSV file as created by the [DUAL-PAM-100](https://www.walz.com/products/dual-pam-100/) software in single channel mode (Photosystem II), processes it by calculating $$ETR$$ values for Photosystem II, and returns a cleaned dataset. +This function reads the original CSV file as created by the [DUAL-PAM-100](https://www.walz.com/products/dual-pam-100/) software in single channel mode (Fluo), processes it by calculating $$ETR$$ values for Photosystem II, and returns a cleaned dataset. #### Parameters @@ -232,7 +232,7 @@ $$ \textit{ETR (II)} = PAR \cdot \textit{ETR–Factor} \cdot \textit{Fraction of The function processes the provided CSV file by: - Reading the CSV data using `read.csv()` and converting it to a `data.table`. -- Validating the raw Dual-PAM data with `validate_dual_pam_single_channel_II_data()`. +- Validating the raw Dual-PAM data with `validate_dual_pam_single_channel_fluo_data()`. - Filtering rows where the column `ID` equals `SP`. - Combining the `Date` and `Time` columns to create a `DateTime` column and ordering the data chronologically. - Extracting the initial **Fm-Det.** measurement at `PAR = 0` to calculate the first ETR value. @@ -251,7 +251,7 @@ The function processes the provided CSV file by: #### Example ```r -data <- read_dual_pam_single_channel_II_data( +data <- read_dual_pam_single_channel_fluo_data( "path/to/data.csv", remove_recovery = TRUE, etr_factor = 0.84, diff --git a/src/NAMESPACE b/src/NAMESPACE index 7dea862..ead7307 100644 --- a/src/NAMESPACE +++ b/src/NAMESPACE @@ -17,8 +17,8 @@ export(platt_generate_regression_ETR_II) export(platt_modified) export(plot_control) export(read_dual_pam_data) -export(read_dual_pam_single_channel_II_data) -export(read_dual_pam_single_channel_I_data) +export(read_dual_pam_single_channel_fluo_data) +export(read_dual_pam_single_channel_p700_data) export(read_junior_pam_data) export(read_pam_2500_data) export(read_universal_data) diff --git a/src/R/combo_plot_control.R b/src/R/combo_plot_control.R index 6cec8d5..c2c12ea 100644 --- a/src/R/combo_plot_control.R +++ b/src/R/combo_plot_control.R @@ -30,11 +30,12 @@ #' #' @export combo_plot_control <- function( - title, - data, - model_results, - name_list, - color_list) { + title, + data, + model_results, + name_list, + color_list +) { validate_data(data) if (length(model_results) <= 0) { diff --git a/src/R/compare_regression_models.R b/src/R/compare_regression_models.R index dd27f1c..0fb7782 100644 --- a/src/R/compare_regression_models.R +++ b/src/R/compare_regression_models.R @@ -50,7 +50,6 @@ compare_regression_models_ETR_I <- function(data_dir, read_func) { return(compare_regression_models(data_dir, etr_1_type, read_func)) } - #' Compare Regression Models for ETR II #' #' Compares multiple regression models for electron transport rate (ETR) data using predefined performance metrics. diff --git a/src/R/eilers_peeters.R b/src/R/eilers_peeters.R index 7b88880..7c0df21 100644 --- a/src/R/eilers_peeters.R +++ b/src/R/eilers_peeters.R @@ -49,10 +49,11 @@ eilers_peeters_default_start_value_c <- 7.012012 #' #' @export eilers_peeters_generate_regression_ETR_I <- function( - data, - a_start_value = eilers_peeters_default_start_value_a, - b_start_value = eilers_peeters_default_start_value_b, - c_start_value = eilers_peeters_default_start_value_c) { + data, + a_start_value = eilers_peeters_default_start_value_a, + b_start_value = eilers_peeters_default_start_value_b, + c_start_value = eilers_peeters_default_start_value_c +) { return(eilers_peeters_generate_regression_internal( data, etr_1_type, @@ -100,10 +101,11 @@ eilers_peeters_generate_regression_ETR_I <- function( #' #' @export eilers_peeters_generate_regression_ETR_II <- function( - data, - a_start_value = eilers_peeters_default_start_value_a, - b_start_value = eilers_peeters_default_start_value_b, - c_start_value = eilers_peeters_default_start_value_c) { + data, + a_start_value = eilers_peeters_default_start_value_a, + b_start_value = eilers_peeters_default_start_value_b, + c_start_value = eilers_peeters_default_start_value_c +) { return(eilers_peeters_generate_regression_internal( data, etr_2_type, @@ -122,11 +124,12 @@ eilers_peeters_message <- function(msg) { } eilers_peeters_generate_regression_internal <- function( - data, - etr_type, - a_start_value = eilers_peeters_default_start_value_a, - b_start_value = eilers_peeters_default_start_value_b, - c_start_value = eilers_peeters_default_start_value_c) { + data, + etr_type, + a_start_value = eilers_peeters_default_start_value_a, + b_start_value = eilers_peeters_default_start_value_b, + c_start_value = eilers_peeters_default_start_value_c +) { tryCatch( { validate_data(data) diff --git a/src/R/platt.R b/src/R/platt.R index ab2961d..41d66ca 100644 --- a/src/R/platt.R +++ b/src/R/platt.R @@ -51,10 +51,11 @@ platt_default_start_value_ps <- 49.76112 #' #' @export platt_generate_regression_ETR_I <- function( - data, - alpha_start_value = platt_default_start_value_alpha, - beta_start_value = platt_default_start_value_beta, - ps_start_value = platt_default_start_value_ps) { + data, + alpha_start_value = platt_default_start_value_alpha, + beta_start_value = platt_default_start_value_beta, + ps_start_value = platt_default_start_value_ps +) { return(platt_generate_regression_internal( data, etr_1_type, @@ -105,10 +106,11 @@ platt_generate_regression_ETR_I <- function( #' #' @export platt_generate_regression_ETR_II <- function( - data, - alpha_start_value = platt_default_start_value_alpha, - beta_start_value = platt_default_start_value_beta, - ps_start_value = platt_default_start_value_ps) { + data, + alpha_start_value = platt_default_start_value_alpha, + beta_start_value = platt_default_start_value_beta, + ps_start_value = platt_default_start_value_ps +) { return(platt_generate_regression_internal( data, etr_2_type, @@ -127,11 +129,12 @@ platt_message <- function(msg) { } platt_generate_regression_internal <- function( - data, - etr_type, - alpha_start_value = platt_default_start_value_alpha, - beta_start_value = platt_default_start_value_beta, - ps_start_value = platt_default_start_value_ps) { + data, + etr_type, + alpha_start_value = platt_default_start_value_alpha, + beta_start_value = platt_default_start_value_beta, + ps_start_value = platt_default_start_value_ps +) { tryCatch( { validate_data(data) @@ -240,7 +243,7 @@ platt_generate_regression_internal <- function( } etr_regression_data <- create_regression_data(pars, predictions) - measured_predicted_etr_par_data <- get_etr_data_for_par_values(data, etr_regression_data, etr_type) + measured_predicted_etr_par_data <- get_etr_data_for_par_values(data, etr_regression_data, etr_type) root_mean_squared_error <- root_mean_squared_error(measured_predicted_etr_par_data) @@ -250,7 +253,7 @@ platt_generate_regression_internal <- function( etr_type = etr_type, etr_regression_data = etr_regression_data, residual_sum_of_squares = residual_sum_of_squares, - root_mean_squared_error = root_mean_squared_error, + root_mean_squared_error = root_mean_squared_error, relative_root_mean_squared_error = relative_root_mean_squared_error, alpha = alpha, beta = beta, @@ -319,7 +322,7 @@ platt_modified <- function(model_result) { etr_type = get_etr_type_from_model_result(model_result), etr_regression_data = get_etr_regression_data_from_model_result(model_result), residual_sum_of_squares = get_sdiff_from_model_result(model_result), - model_result[["root_mean_squared_error"]], + model_result[["root_mean_squared_error"]], model_result[["relative_root_mean_squared_error"]], a = model_result[["ps"]], b = model_result[["alpha"]], diff --git a/src/R/read_pam_data.R b/src/R/read_pam_data.R index 48dfd5c..dfd0814 100644 --- a/src/R/read_pam_data.R +++ b/src/R/read_pam_data.R @@ -111,11 +111,12 @@ read_universal_data <- function(csv_path, #' data <- read_dual_pam_data(path) #' @export read_dual_pam_data <- function( - csv_path, - remove_recovery = TRUE, - etr_factor = 0.84, - fraction_photosystem_I = 0.5, - fraction_photosystem_II = 0.5) { + csv_path, + remove_recovery = TRUE, + etr_factor = 0.84, + fraction_photosystem_I = 0.5, + fraction_photosystem_II = 0.5 +) { if (fraction_photosystem_I + fraction_photosystem_II != 1) { stop("The sum of fraction_photosystem_I and fraction_photosystem_II must be equal 1.") } @@ -210,7 +211,7 @@ read_dual_pam_data <- function( ) } -#' Read and Process DualPAM Data Single Chanel Mode Photosystem I +#' Read and Process DualPAM Data Single Chanel Mode P700 #' #' Reads raw CSV files generated by DualPAM software, calculates electron transport rate (ETR) values for Photosystem I, and returns a universal dataset. #' @@ -229,10 +230,10 @@ read_dual_pam_data <- function( #' @return A \code{data.table} containing: #' \itemize{ #' \item \code{par}: Photosynthetically active radiation. -#' \item \code{yield_1}: NA -#' \item \code{yield_2}: Yield for photosystem II. -#' \item \code{etr_1}: NA -#' \item \code{etr_2}: Calculated ETR for photosystem II. +#' \item \code{yield_1}: Yield for photosystem I +#' \item \code{yield_2}: NA +#' \item \code{etr_1}: Calculated ETR for photosystem I +#' \item \code{etr_2}: NA #' } #' #' @references{ @@ -241,16 +242,19 @@ read_dual_pam_data <- function( #' Available at: \url{https://www.walz.com/files/downloads/dualpamed05.pdf} #' } #' @examples -#' path <- file.path(system.file("extdata/dual_pam_single_channel_I_data", package = "pam"), -#' "20260130_01_efeutute_dual_pam_only_ps_1.csv") -#' data <- read_dual_pam_single_channel_I_data(path) +#' path <- file.path( +#' system.file("extdata/dual_pam_single_channel_p700_data", package = "pam"), +#' "20260130_01_efeutute_dual_pam_only_p700.csv" +#' ) +#' data <- read_dual_pam_single_channel_p700_data(path) #' @export -read_dual_pam_single_channel_I_data <- function( - csv_path, - remove_recovery = TRUE, - etr_factor = 0.84, - fraction_photosystem_I = 0.5, - fraction_photosystem_II = 0.5) { +read_dual_pam_single_channel_p700_data <- function( + csv_path, + remove_recovery = TRUE, + etr_factor = 0.84, + fraction_photosystem_I = 0.5, + fraction_photosystem_II = 0.5 +) { if (fraction_photosystem_I + fraction_photosystem_II != 1) { stop("The sum of fraction_photosystem_I and fraction_photosystem_II must be equal 1.") } @@ -260,7 +264,7 @@ read_dual_pam_single_channel_I_data <- function( data <- utils::read.csv(csv_path, sep = ";", dec = ".") data <- data.table::as.data.table(data) - validate_dual_pam_single_channel_I_data(data) + validate_dual_pam_single_channel_p700_data(data) data <- data[data$ID == "SP", ] date_time_col_values <- c() @@ -338,7 +342,7 @@ read_dual_pam_single_channel_I_data <- function( ) } -#' Read and Process DualPAM Data Single Chanel Mode Photosystem II +#' Read and Process DualPAM Data Single Chanel Mode Fluo #' #' Reads raw CSV files generated by DualPAM software, calculates electron transport rate (ETR) values for Photosystem II, and returns a universal dataset. #' @@ -369,16 +373,19 @@ read_dual_pam_single_channel_I_data <- function( #' Available at: \url{https://www.walz.com/files/downloads/dualpamed05.pdf} #' } #' @examples -#' path <- file.path(system.file("extdata/dual_pam_single_channel_II_data", package = "pam"), -#' "20260130_efeutute_dual_pam_only_ps_2.csv") -#' data <- read_dual_pam_single_channel_II_data(path) +#' path <- file.path( +#' system.file("extdata/dual_pam_single_channel_fluo_data", package = "pam"), +#' "20260130_efeutute_dual_pam_only_fluo.csv" +#' ) +#' data <- read_dual_pam_single_channel_fluo_data(path) #' @export -read_dual_pam_single_channel_II_data <- function( - csv_path, - remove_recovery = TRUE, - etr_factor = 0.84, - fraction_photosystem_I = 0.5, - fraction_photosystem_II = 0.5) { +read_dual_pam_single_channel_fluo_data <- function( + csv_path, + remove_recovery = TRUE, + etr_factor = 0.84, + fraction_photosystem_I = 0.5, + fraction_photosystem_II = 0.5 +) { if (fraction_photosystem_I + fraction_photosystem_II != 1) { stop("The sum of fraction_photosystem_I and fraction_photosystem_II must be equal 1.") } @@ -388,7 +395,7 @@ read_dual_pam_single_channel_II_data <- function( data <- utils::read.csv(csv_path, sep = ";", dec = ".") data <- data.table::as.data.table(data) - validate_dual_pam_single_channel_II_data(data) + validate_dual_pam_single_channel_fluo_data(data) data <- data[data$ID == "SP", ] date_time_col_values <- c() @@ -523,16 +530,19 @@ calc_etr <- function(yield, par, etr_factor, p_ratio) { #' Available at: \url{https://www.walz.com/files/downloads/dualpamed05.pdf} #' } #' @examples -#' path <- file.path(system.file("extdata/junior_pam_data", package = "pam"), -#' "junior_pam_20250613.csv") +#' path <- file.path( +#' system.file("extdata/junior_pam_data", package = "pam"), +#' "junior_pam_20250613.csv" +#' ) #' data <- read_junior_pam_data(path) #' @export read_junior_pam_data <- function( - csv_path, - remove_recovery = TRUE, - etr_factor = 0.84, - fraction_photosystem_I = 0.5, - fraction_photosystem_II = 0.5) { + csv_path, + remove_recovery = TRUE, + etr_factor = 0.84, + fraction_photosystem_I = 0.5, + fraction_photosystem_II = 0.5 +) { if (fraction_photosystem_I + fraction_photosystem_II != 1) { stop("The sum of fraction_photosystem_I and fraction_photosystem_II must be equal 1.") } @@ -647,11 +657,12 @@ read_junior_pam_data <- function( #' data <- read_pam_2500_data(path) #' @export read_pam_2500_data <- function( - csv_path, - remove_recovery = TRUE, - etr_factor = 0.84, - fraction_photosystem_I = 0.5, - fraction_photosystem_II = 0.5) { + csv_path, + remove_recovery = TRUE, + etr_factor = 0.84, + fraction_photosystem_I = 0.5, + fraction_photosystem_II = 0.5 +) { if (fraction_photosystem_I + fraction_photosystem_II != 1) { stop("The sum of fraction_photosystem_I and fraction_photosystem_II must be equal 1.") } diff --git a/src/R/validation.R b/src/R/validation.R index d1eeb0e..404ade2 100644 --- a/src/R/validation.R +++ b/src/R/validation.R @@ -100,7 +100,7 @@ validate_dual_pam_data <- function(data) { } } -validate_dual_pam_single_channel_II_data <- function(data) { +validate_dual_pam_single_channel_p700_data <- function(data) { if (is.null(data)) { stop("data is null") } @@ -125,8 +125,8 @@ validate_dual_pam_single_channel_II_data <- function(data) { stop("required col 'PAR' not found") } - if (!"Y.II." %in% colnames(data)) { - stop("required col 'Y(II)' not found") + if (!"Y.I." %in% colnames(data)) { + stop("required col 'Y(I)' not found") } if (!"Action" %in% colnames(data)) { @@ -141,12 +141,12 @@ validate_dual_pam_single_channel_II_data <- function(data) { stop("required col 'Time' not found") } - if (!"Fm-Det." %in% data[["Action"]]) { - stop("required value 'Fm' not found in column 'Action'") + if (!"Pm.-Det." %in% data[["Action"]]) { + stop("required value 'Pm.-Det.' not found in column 'Action'") } } -validate_junior_pam_data <- function(data) { +validate_dual_pam_single_channel_fluo_data <- function(data) { if (is.null(data)) { stop("data is null") } @@ -163,20 +163,36 @@ validate_junior_pam_data <- function(data) { stop("no cols in data") } - if (!any(grepl("PAR", colnames(data)))) { + if (!"ID" %in% colnames(data)) { + stop("required col 'ID' not found") + } + + if (!"PAR" %in% colnames(data)) { stop("required col 'PAR' not found") } - if (!any(grepl("Y..II.", colnames(data)))) { - stop("required col 'Y..II.' not found") + if (!"Y.II." %in% colnames(data)) { + stop("required col 'Y(II)' not found") } - if (!"Datetime" %in% colnames(data)) { - stop("required col 'Datetime' not found") + if (!"Action" %in% colnames(data)) { + stop("required col 'Action' not found") + } + + if (!"Date" %in% colnames(data)) { + stop("required col 'Date' not found") + } + + if (!"Time" %in% colnames(data)) { + stop("required col 'Time' not found") + } + + if (!"Fm-Det." %in% data[["Action"]]) { + stop("required value 'Fm' not found in column 'Action'") } } -validate_pam_2500_data <- function(data) { +validate_junior_pam_data <- function(data) { if (is.null(data)) { stop("data is null") } @@ -193,30 +209,20 @@ validate_pam_2500_data <- function(data) { stop("no cols in data") } - if (!"No." %in% colnames(data)) { - stop("required col 'No.' not found") - } - - if (!"PAR" %in% colnames(data)) { + if (!any(grepl("PAR", colnames(data)))) { stop("required col 'PAR' not found") } - if (!"Date" %in% colnames(data)) { - stop("required col 'Date' not found") - } - - if (!"Time" %in% colnames(data)) { - stop("required col 'Time' not found") + if (!any(grepl("Y..II.", colnames(data)))) { + stop("required col 'Y..II.' not found") } - if (!"Y.II." %in% colnames(data)) { - stop("required col 'Y(II)' not found") + if (!"Datetime" %in% colnames(data)) { + stop("required col 'Datetime' not found") } - } - -validate_dual_pam_single_channel_I_data <- function(data) { +validate_pam_2500_data <- function(data) { if (is.null(data)) { stop("data is null") } @@ -233,22 +239,14 @@ validate_dual_pam_single_channel_I_data <- function(data) { stop("no cols in data") } - if (!"ID" %in% colnames(data)) { - stop("required col 'ID' not found") + if (!"No." %in% colnames(data)) { + stop("required col 'No.' not found") } if (!"PAR" %in% colnames(data)) { stop("required col 'PAR' not found") } - if (!"Y.I." %in% colnames(data)) { - stop("required col 'Y(I)' not found") - } - - if (!"Action" %in% colnames(data)) { - stop("required col 'Action' not found") - } - if (!"Date" %in% colnames(data)) { stop("required col 'Date' not found") } @@ -257,8 +255,8 @@ validate_dual_pam_single_channel_I_data <- function(data) { stop("required col 'Time' not found") } - if (!"Pm.-Det." %in% data[["Action"]]) { - stop("required value 'Pm.-Det.' not found in column 'Action'") + if (!"Y.II." %in% colnames(data)) { + stop("required col 'Y(II)' not found") } } @@ -325,10 +323,9 @@ validate_pam_2500_data <- function(data) { stop("required col 'Time' not found") } - if (!"Y.II." %in% colnames(data)) { + if (!"Y.II." %in% colnames(data)) { stop("required col 'Y(II)' not found") } - } validate_etr_regression_data <- function(regression_data) { diff --git a/src/inst/extdata/dual_pam_single_channel_II_data/20260130_efeutute_dual_pam_only_ps_2.csv b/src/inst/extdata/dual_pam_single_channel_fluo_data/20260130_efeutute_dual_pam_only_fluo.csv similarity index 100% rename from src/inst/extdata/dual_pam_single_channel_II_data/20260130_efeutute_dual_pam_only_ps_2.csv rename to src/inst/extdata/dual_pam_single_channel_fluo_data/20260130_efeutute_dual_pam_only_fluo.csv diff --git a/src/inst/extdata/dual_pam_single_channel_I_data/20260130_01_efeutute_dual_pam_only_ps_1.csv b/src/inst/extdata/dual_pam_single_channel_p700_data/20260130_01_efeutute_dual_pam_only_p700.csv similarity index 100% rename from src/inst/extdata/dual_pam_single_channel_I_data/20260130_01_efeutute_dual_pam_only_ps_1.csv rename to src/inst/extdata/dual_pam_single_channel_p700_data/20260130_01_efeutute_dual_pam_only_p700.csv diff --git a/src/man/read_dual_pam_single_channel_II_data.Rd b/src/man/read_dual_pam_single_channel_fluo_data.Rd similarity index 81% rename from src/man/read_dual_pam_single_channel_II_data.Rd rename to src/man/read_dual_pam_single_channel_fluo_data.Rd index 8c6887c..2567b81 100644 --- a/src/man/read_dual_pam_single_channel_II_data.Rd +++ b/src/man/read_dual_pam_single_channel_fluo_data.Rd @@ -1,10 +1,10 @@ % Generated by roxygen2: do not edit by hand % Please edit documentation in R/read_pam_data.R -\name{read_dual_pam_single_channel_II_data} -\alias{read_dual_pam_single_channel_II_data} -\title{Read and Process DualPAM Data Single Chanel Mode Photosystem II} +\name{read_dual_pam_single_channel_fluo_data} +\alias{read_dual_pam_single_channel_fluo_data} +\title{Read and Process DualPAM Data Single Chanel Mode Fluo} \usage{ -read_dual_pam_single_channel_II_data( +read_dual_pam_single_channel_fluo_data( csv_path, remove_recovery = TRUE, etr_factor = 0.84, @@ -43,9 +43,11 @@ Calculates ETR using: A detailed documentation can be found under \url{https://github.com/biotoolbox/pam?tab=readme-ov-file#read_dual_pam_data} } \examples{ -path <- file.path(system.file("extdata/dual_pam_single_channel_II_data", package = "pam"), -"20260130_efeutute_dual_pam_only_ps_2.csv") -data <- read_dual_pam_single_channel_II_data(path) +path <- file.path( + system.file("extdata/dual_pam_single_channel_fluo_data", package = "pam"), + "20260130_efeutute_dual_pam_only_fluo.csv" +) +data <- read_dual_pam_single_channel_fluo_data(path) } \references{ { diff --git a/src/man/read_dual_pam_single_channel_I_data.Rd b/src/man/read_dual_pam_single_channel_p700_data.Rd similarity index 73% rename from src/man/read_dual_pam_single_channel_I_data.Rd rename to src/man/read_dual_pam_single_channel_p700_data.Rd index 60d5331..7d766bb 100644 --- a/src/man/read_dual_pam_single_channel_I_data.Rd +++ b/src/man/read_dual_pam_single_channel_p700_data.Rd @@ -1,10 +1,10 @@ % Generated by roxygen2: do not edit by hand % Please edit documentation in R/read_pam_data.R -\name{read_dual_pam_single_channel_I_data} -\alias{read_dual_pam_single_channel_I_data} -\title{Read and Process DualPAM Data Single Chanel Mode Photosystem I} +\name{read_dual_pam_single_channel_p700_data} +\alias{read_dual_pam_single_channel_p700_data} +\title{Read and Process DualPAM Data Single Chanel Mode P700} \usage{ -read_dual_pam_single_channel_I_data( +read_dual_pam_single_channel_p700_data( csv_path, remove_recovery = TRUE, etr_factor = 0.84, @@ -27,10 +27,10 @@ read_dual_pam_single_channel_I_data( A \code{data.table} containing: \itemize{ \item \code{par}: Photosynthetically active radiation. - \item \code{yield_1}: NA - \item \code{yield_2}: Yield for photosystem II. - \item \code{etr_1}: NA - \item \code{etr_2}: Calculated ETR for photosystem II. + \item \code{yield_1}: Yield for photosystem I + \item \code{yield_2}: NA + \item \code{etr_1}: Calculated ETR for photosystem I + \item \code{etr_2}: NA } } \description{ @@ -43,9 +43,11 @@ Calculates ETR using: A detailed documentation can be found under \url{https://github.com/biotoolbox/pam?tab=readme-ov-file#read_dual_pam_data} } \examples{ -path <- file.path(system.file("extdata/dual_pam_single_channel_I_data", package = "pam"), -"20260130_01_efeutute_dual_pam_only_ps_1.csv") -data <- read_dual_pam_single_channel_I_data(path) +path <- file.path( + system.file("extdata/dual_pam_single_channel_p700_data", package = "pam"), + "20260130_01_efeutute_dual_pam_only_p700.csv" +) +data <- read_dual_pam_single_channel_p700_data(path) } \references{ { diff --git a/src/man/read_junior_pam_data.Rd b/src/man/read_junior_pam_data.Rd index 96663d0..180872a 100644 --- a/src/man/read_junior_pam_data.Rd +++ b/src/man/read_junior_pam_data.Rd @@ -43,8 +43,10 @@ Calculates ETR II using: A detailed documentation can be found under \url{https://github.com/biotoolbox/pam?tab=readme-ov-file} } \examples{ -path <- file.path(system.file("extdata/junior_pam_data", package = "pam"), -"junior_pam_20250613.csv") +path <- file.path( + system.file("extdata/junior_pam_data", package = "pam"), + "junior_pam_20250613.csv" +) data <- read_junior_pam_data(path) } \references{ diff --git a/src/tests/testthat/data/20260130_01_efeutute_dual_pam_only_ps_1.csv b/src/tests/testthat/data/20260130_01_efeutute_dual_pam_only_p700.csv similarity index 100% rename from src/tests/testthat/data/20260130_01_efeutute_dual_pam_only_ps_1.csv rename to src/tests/testthat/data/20260130_01_efeutute_dual_pam_only_p700.csv diff --git a/src/tests/testthat/data/20260130_efeutute_dual_pam_only_ps_2.csv b/src/tests/testthat/data/20260130_efeutute_dual_pam_only_fluo.csv similarity index 100% rename from src/tests/testthat/data/20260130_efeutute_dual_pam_only_ps_2.csv rename to src/tests/testthat/data/20260130_efeutute_dual_pam_only_fluo.csv diff --git a/src/tests/testthat/test-read_dual_pam_data.R b/src/tests/testthat/test-read_dual_pam_data.R index 925428c..bcb9dc1 100644 --- a/src/tests/testthat/test-read_dual_pam_data.R +++ b/src/tests/testthat/test-read_dual_pam_data.R @@ -303,12 +303,12 @@ test_that("read_dual_pam_data 20240925.csv - fraction_photosystem_I = 0.2, fract expect_equal(etr_2[17], 62.0256) }) -test_that("20260130_01_efeutute_dual_pam_only_ps_1.csv - expect fm missing", { - test_data_file <- testthat::test_path("data", "20260130_01_efeutute_dual_pam_only_ps_1.csv") +test_that("20260130_01_efeutute_dual_pam_only_p700.csv - expect fm missing", { + test_data_file <- testthat::test_path("data", "20260130_01_efeutute_dual_pam_only_p700.csv") expect_error(read_dual_pam_data(test_data_file)) }) -test_that("20260130_efeutute_dual_pam_only_ps_2.csv - expect pm missing", { - test_data_file <- testthat::test_path("data", "20260130_efeutute_dual_pam_only_ps_2.csv") +test_that("20260130_efeutute_dual_pam_only_fluo.csv - expect pm missing", { + test_data_file <- testthat::test_path("data", "20260130_efeutute_dual_pam_only_fluo.csv") expect_error(read_dual_pam_data(test_data_file)) }) diff --git a/src/tests/testthat/test-read_dual_pam_single_channel_II_data.R b/src/tests/testthat/test-read_dual_pam_single_channel_fluo_data.R similarity index 86% rename from src/tests/testthat/test-read_dual_pam_single_channel_II_data.R rename to src/tests/testthat/test-read_dual_pam_single_channel_fluo_data.R index bbba415..fda729a 100644 --- a/src/tests/testthat/test-read_dual_pam_single_channel_II_data.R +++ b/src/tests/testthat/test-read_dual_pam_single_channel_fluo_data.R @@ -1,6 +1,6 @@ -test_that("read_dual_pam_single_channel_II_data 20260130_efeutute_dual_pam_only_ps_2 - default", { - test_data_file <- testthat::test_path("data", "20260130_efeutute_dual_pam_only_ps_2.csv") - data <- read_dual_pam_single_channel_II_data(test_data_file) +test_that("read_dual_pam_single_channel_fluo_data 20260130_efeutute_dual_pam_only_fluo - default", { + test_data_file <- testthat::test_path("data", "20260130_efeutute_dual_pam_only_fluo.csv") + data <- read_dual_pam_single_channel_fluo_data(test_data_file) par <- data$par expect_equal(par[1], 0) @@ -68,9 +68,9 @@ test_that("read_dual_pam_single_channel_II_data 20260130_efeutute_dual_pam_only_ expect_equal(etr_2[11], 12.2052) }) -test_that("read_dual_pam_single_channel_II_data 20260130_efeutute_dual_pam_only_ps_2 - etr_factor 0.5", { - test_data_file <- testthat::test_path("data", "20260130_efeutute_dual_pam_only_ps_2.csv") - data <- read_dual_pam_single_channel_II_data(test_data_file, etr_factor = 0.5) +test_that("read_dual_pam_single_channel_fluo_data 20260130_efeutute_dual_pam_only_fluo - etr_factor 0.5", { + test_data_file <- testthat::test_path("data", "20260130_efeutute_dual_pam_only_fluo.csv") + data <- read_dual_pam_single_channel_fluo_data(test_data_file, etr_factor = 0.5) par <- data$par expect_equal(par[1], 0) @@ -138,14 +138,14 @@ test_that("read_dual_pam_single_channel_II_data 20260130_efeutute_dual_pam_only_ expect_equal(etr_2[11], 7.265) }) -test_that("read_dual_pam_single_channel_II_data 20260130_efeutute_dual_pam_only_ps_2 - fraction_photosystem > 1", { - test_data_file <- testthat::test_path("data", "20260130_efeutute_dual_pam_only_ps_2.csv") - expect_error(read_dual_pam_single_channel_II_data(test_data_file, fraction_photosystem_I = 0.9, fraction_photosystem_II = 0.2)) +test_that("read_dual_pam_single_channel_fluo_data 20260130_efeutute_dual_pam_only_fluo - fraction_photosystem > 1", { + test_data_file <- testthat::test_path("data", "20260130_efeutute_dual_pam_only_fluo.csv") + expect_error(read_dual_pam_single_channel_fluo_data(test_data_file, fraction_photosystem_I = 0.9, fraction_photosystem_II = 0.2)) }) -test_that("read_dual_pam_single_channel_II_data 20260130_efeutute_dual_pam_only_ps_2 - fraction_photosystem_I = 0.2, fraction_photosystem_II = 0.8", { - test_data_file <- testthat::test_path("data", "20260130_efeutute_dual_pam_only_ps_2.csv") - data <- read_dual_pam_single_channel_II_data(test_data_file, fraction_photosystem_I = 0.2, fraction_photosystem_II = 0.8) +test_that("read_dual_pam_single_channel_fluo_data 20260130_efeutute_dual_pam_only_fluo - fraction_photosystem_I = 0.2, fraction_photosystem_II = 0.8", { + test_data_file <- testthat::test_path("data", "20260130_efeutute_dual_pam_only_fluo.csv") + data <- read_dual_pam_single_channel_fluo_data(test_data_file, fraction_photosystem_I = 0.2, fraction_photosystem_II = 0.8) par <- data$par expect_equal(par[1], 0) @@ -211,4 +211,4 @@ test_that("read_dual_pam_single_channel_II_data 20260130_efeutute_dual_pam_only_ expect_equal(etr_2[9], 19.805184) expect_equal(etr_2[10], 20.3427840) expect_equal(etr_2[11], 19.52832) -}) \ No newline at end of file +}) diff --git a/src/tests/testthat/test-read_dual_pam_single_channel_I_data.R b/src/tests/testthat/test-read_dual_pam_single_channel_p700_data.R similarity index 89% rename from src/tests/testthat/test-read_dual_pam_single_channel_I_data.R rename to src/tests/testthat/test-read_dual_pam_single_channel_p700_data.R index 24a0eed..d486edf 100644 --- a/src/tests/testthat/test-read_dual_pam_single_channel_I_data.R +++ b/src/tests/testthat/test-read_dual_pam_single_channel_p700_data.R @@ -1,6 +1,6 @@ -test_that("read_dual_pam_single_channel_I_data 20260130_01_efeutute_dual_pam_only_ps_1 - default", { - test_data_file <- testthat::test_path("data", "20260130_01_efeutute_dual_pam_only_ps_1.csv") - data <- read_dual_pam_single_channel_I_data(test_data_file) +test_that("read_dual_pam_single_channel_p700_data 20260130_01_efeutute_dual_pam_only_p700 - default", { + test_data_file <- testthat::test_path("data", "20260130_01_efeutute_dual_pam_only_p700.csv") + data <- read_dual_pam_single_channel_p700_data(test_data_file) par <- data$par expect_equal(par[1], 0) @@ -88,9 +88,9 @@ test_that("read_dual_pam_single_channel_I_data 20260130_01_efeutute_dual_pam_onl expect_equal(etr_2[15], NA_real_) }) -test_that("read_dual_pam_single_channel_I_data 20260130_01_efeutute_dual_pam_only_ps_1 - etr_factor 0.5", { - test_data_file <- testthat::test_path("data", "20260130_01_efeutute_dual_pam_only_ps_1.csv") - data <- read_dual_pam_single_channel_I_data(test_data_file, etr_factor = 0.5) +test_that("read_dual_pam_single_channel_p700_data 20260130_01_efeutute_dual_pam_only_p700 - etr_factor 0.5", { + test_data_file <- testthat::test_path("data", "20260130_01_efeutute_dual_pam_only_p700.csv") + data <- read_dual_pam_single_channel_p700_data(test_data_file, etr_factor = 0.5) par <- data$par expect_equal(par[1], 0) @@ -178,14 +178,14 @@ test_that("read_dual_pam_single_channel_I_data 20260130_01_efeutute_dual_pam_onl expect_equal(etr_2[15], NA_real_) }) -test_that("read_dual_pam_single_channel_I_data 20260130_01_efeutute_dual_pam_only_ps_1 - fraction_photosystem > 1", { - test_data_file <- testthat::test_path("data", "20260130_01_efeutute_dual_pam_only_ps_1.csv") - expect_error(read_dual_pam_single_channel_I_data(test_data_file, fraction_photosystem_I = 0.9, fraction_photosystem_II = 0.2)) +test_that("read_dual_pam_single_channel_p700_data 20260130_01_efeutute_dual_pam_only_p700 - fraction_photosystem > 1", { + test_data_file <- testthat::test_path("data", "20260130_01_efeutute_dual_pam_only_p700.csv") + expect_error(read_dual_pam_single_channel_p700_data(test_data_file, fraction_photosystem_I = 0.9, fraction_photosystem_II = 0.2)) }) -test_that("read_dual_pam_single_channel_I_data 20260130_01_efeutute_dual_pam_only_ps_1 - fraction_photosystem_I = 0.2, fraction_photosystem_II = 0.8", { - test_data_file <- testthat::test_path("data", "20260130_01_efeutute_dual_pam_only_ps_1.csv") - data <- read_dual_pam_single_channel_I_data(test_data_file, fraction_photosystem_I = 0.2, fraction_photosystem_II = 0.8) +test_that("read_dual_pam_single_channel_p700_data 20260130_01_efeutute_dual_pam_only_p700 - fraction_photosystem_I = 0.2, fraction_photosystem_II = 0.8", { + test_data_file <- testthat::test_path("data", "20260130_01_efeutute_dual_pam_only_p700.csv") + data <- read_dual_pam_single_channel_p700_data(test_data_file, fraction_photosystem_I = 0.2, fraction_photosystem_II = 0.8) par <- data$par expect_equal(par[1], 0) @@ -271,4 +271,4 @@ test_that("read_dual_pam_single_channel_I_data 20260130_01_efeutute_dual_pam_onl expect_equal(etr_2[13], NA_real_) expect_equal(etr_2[14], NA_real_) expect_equal(etr_2[15], NA_real_) -}) \ No newline at end of file +}) From 5a29e4c60b79990eb05f16ab6d726c42b28185b7 Mon Sep 17 00:00:00 2001 From: Phi-S <926151+Phi-S@users.noreply.github.com> Date: Mon, 20 Apr 2026 12:16:35 +0200 Subject: [PATCH 18/32] Fix error handling messages in Eilers-Peeters regression and update numeric checks in compare_regression_models --- src/R/compare_regression_models.R | 6 +++--- src/R/eilers_peeters.R | 10 +++++----- src/R/platt.R | 4 ++-- src/R/read_pam_data.R | 2 +- 4 files changed, 11 insertions(+), 11 deletions(-) diff --git a/src/R/compare_regression_models.R b/src/R/compare_regression_models.R index 0fb7782..904e4cd 100644 --- a/src/R/compare_regression_models.R +++ b/src/R/compare_regression_models.R @@ -131,7 +131,7 @@ compare_regression_models <- function(data_dir, etr_type, read_func) { platt <- platt_generate_regression_internal(data, etr_type) platt_sdiff <- platt[["residual_sum_of_squares"]] - if (!is.numeric(eilers_peeters_sdiff)) { + if (!is.numeric(platt_sdiff)) { stop("platt residual_sum_of_squares result is not numeric") } if (is.na(platt_sdiff)) { @@ -140,7 +140,7 @@ compare_regression_models <- function(data_dir, etr_type, read_func) { vollenweider <- vollenweider_generate_regression_internal(data, etr_type) vollenweider_sdiff <- vollenweider[["residual_sum_of_squares"]] - if (!is.numeric(eilers_peeters_sdiff)) { + if (!is.numeric(vollenweider_sdiff)) { stop("vollenweider residual_sum_of_squares result is not numeric") } if (is.na(vollenweider_sdiff)) { @@ -149,7 +149,7 @@ compare_regression_models <- function(data_dir, etr_type, read_func) { walsby <- walsby_generate_regression_internal(data, etr_type) walsby_sdiff <- walsby[["residual_sum_of_squares"]] - if (!is.numeric(eilers_peeters_sdiff)) { + if (!is.numeric(walsby_sdiff)) { stop("walsby residual_sum_of_squares result is not numeric") } if (is.na(walsby_sdiff)) { diff --git a/src/R/eilers_peeters.R b/src/R/eilers_peeters.R index 7c0df21..c79048b 100644 --- a/src/R/eilers_peeters.R +++ b/src/R/eilers_peeters.R @@ -170,7 +170,7 @@ eilers_peeters_generate_regression_internal <- function( eilers_peeters_message(paste("failed to calculate pm: warning:", w)) }, error = function(e) { - eilers_peeters_message(paste("failed to calculate pm: error:", w)) + eilers_peeters_message(paste("failed to calculate pm: error:", e)) } ) @@ -183,7 +183,7 @@ eilers_peeters_generate_regression_internal <- function( eilers_peeters_message(paste("failed to calculate s: warning:", w)) }, error = function(e) { - eilers_peeters_message(paste("failed to calculate s: error:", w)) + eilers_peeters_message(paste("failed to calculate s: error:", e)) } ) @@ -196,7 +196,7 @@ eilers_peeters_generate_regression_internal <- function( eilers_peeters_message(paste("failed to calculate ik: warning:", w)) }, error = function(e) { - eilers_peeters_message(paste("failed to calculate ik: error:", w)) + eilers_peeters_message(paste("failed to calculate ik: error:", e)) } ) @@ -209,7 +209,7 @@ eilers_peeters_generate_regression_internal <- function( eilers_peeters_message(paste("failed to calculate im: warning:", w)) }, error = function(e) { - eilers_peeters_message(paste("failed to calculate im: error:", w)) + eilers_peeters_message(paste("failed to calculate im: error:", e)) } ) @@ -222,7 +222,7 @@ eilers_peeters_generate_regression_internal <- function( eilers_peeters_message(paste("failed to calculate w: warning:", w)) }, error = function(e) { - eilers_peeters_message(paste("failed to calculate w: error:", w)) + eilers_peeters_message(paste("failed to calculate w: error:", e)) } ) diff --git a/src/R/platt.R b/src/R/platt.R index 41d66ca..38d1387 100644 --- a/src/R/platt.R +++ b/src/R/platt.R @@ -322,8 +322,8 @@ platt_modified <- function(model_result) { etr_type = get_etr_type_from_model_result(model_result), etr_regression_data = get_etr_regression_data_from_model_result(model_result), residual_sum_of_squares = get_sdiff_from_model_result(model_result), - model_result[["root_mean_squared_error"]], - model_result[["relative_root_mean_squared_error"]], + root_mean_squared_error = model_result[["root_mean_squared_error"]], + relative_root_mean_squared_error = model_result[["relative_root_mean_squared_error"]], a = model_result[["ps"]], b = model_result[["alpha"]], c = model_result[["beta"]], diff --git a/src/R/read_pam_data.R b/src/R/read_pam_data.R index dfd0814..90af9f1 100644 --- a/src/R/read_pam_data.R +++ b/src/R/read_pam_data.R @@ -143,7 +143,7 @@ read_dual_pam_data <- function( data$DateTime <- date_time_col_values data <- data[order(data$DateTime), ] - pm_det_row <- pm_det_row <- subset(data, data$PAR == 0 & data$Action == "Pm.-Det.") + pm_det_row <- subset(data, data$PAR == 0 & data$Action == "Pm.-Det.") yield_1_first <- pm_det_row$Y.I. recalc_etr_1 <- calc_etr(yield_1_first, 0, etr_factor, fraction_photosystem_I) From e81eecdcef152574d6f063faaa7785e9a592a4e1 Mon Sep 17 00:00:00 2001 From: JulienBoehm <180776296+JulienBoehm@users.noreply.github.com> Date: Mon, 20 Apr 2026 13:21:25 +0200 Subject: [PATCH 19/32] changed variable name from sdiff to residual_sum_of_squares --- src/R/compare_regression_models.R | 32 +++++++++++++++---------------- src/R/eilers_peeters.R | 2 +- src/R/platt.R | 2 +- src/R/util.R | 2 +- src/R/vollenweider.R | 2 +- src/R/walsby.R | 2 +- 6 files changed, 21 insertions(+), 21 deletions(-) diff --git a/src/R/compare_regression_models.R b/src/R/compare_regression_models.R index 904e4cd..facb739 100644 --- a/src/R/compare_regression_models.R +++ b/src/R/compare_regression_models.R @@ -121,45 +121,45 @@ compare_regression_models <- function(data_dir, etr_type, read_func) { tryCatch( { eilers_peeters <- eilers_peeters_generate_regression_internal(data, etr_type) - eilers_peeters_sdiff <- eilers_peeters[["residual_sum_of_squares"]] - if (!is.numeric(eilers_peeters_sdiff)) { + eilers_peeters_residual_sum_of_squares <- eilers_peeters[["residual_sum_of_squares"]] + if (!is.numeric(eilers_peeters_residual_sum_of_squares)) { stop("eilers_peeters residual_sum_of_squares result is not numeric") } - if (is.na(eilers_peeters_sdiff)) { + if (is.na(eilers_peeters_residual_sum_of_squares)) { stop("failed to calculate residual_sum_of_squares with eilers_peeters") } platt <- platt_generate_regression_internal(data, etr_type) - platt_sdiff <- platt[["residual_sum_of_squares"]] - if (!is.numeric(platt_sdiff)) { + platt_residual_sum_of_squares <- platt[["residual_sum_of_squares"]] + if (!is.numeric(platt_residual_sum_of_squares)) { stop("platt residual_sum_of_squares result is not numeric") } - if (is.na(platt_sdiff)) { + if (is.na(platt_residual_sum_of_squares)) { stop("failed to calculate residual_sum_of_squares with platt") } vollenweider <- vollenweider_generate_regression_internal(data, etr_type) - vollenweider_sdiff <- vollenweider[["residual_sum_of_squares"]] - if (!is.numeric(vollenweider_sdiff)) { + vollenweider_residual_sum_of_squares <- vollenweider[["residual_sum_of_squares"]] + if (!is.numeric(vollenweider_residual_sum_of_squares)) { stop("vollenweider residual_sum_of_squares result is not numeric") } - if (is.na(vollenweider_sdiff)) { + if (is.na(vollenweider_residual_sum_of_squares)) { stop("failed to calculate residual_sum_of_squares with vollenweider") } walsby <- walsby_generate_regression_internal(data, etr_type) - walsby_sdiff <- walsby[["residual_sum_of_squares"]] - if (!is.numeric(walsby_sdiff)) { + walsby_residual_sum_of_squares <- walsby[["residual_sum_of_squares"]] + if (!is.numeric(walsby_residual_sum_of_squares)) { stop("walsby residual_sum_of_squares result is not numeric") } - if (is.na(walsby_sdiff)) { + if (is.na(walsby_residual_sum_of_squares)) { stop("failed to calculate residual_sum_of_squares with walsby") } - data1 <- data.table::data.table(group = "eilers_peeters", value = eilers_peeters_sdiff) - data2 <- data.table::data.table(group = "platt", value = platt_sdiff) - data3 <- data.table::data.table(group = "vollenweider", value = vollenweider_sdiff) - data4 <- data.table::data.table(group = "walsby", value = walsby_sdiff) + data1 <- data.table::data.table(group = "eilers_peeters", value = eilers_peeters_residual_sum_of_squares) + data2 <- data.table::data.table(group = "platt", value = platt_residual_sum_of_squares) + data3 <- data.table::data.table(group = "vollenweider", value = vollenweider_residual_sum_of_squares) + data4 <- data.table::data.table(group = "walsby", value = walsby_residual_sum_of_squares) combined_data <- rbind(data1, data2, data3, data4) combined_data <- combined_data[order(combined_data$value), ] diff --git a/src/R/eilers_peeters.R b/src/R/eilers_peeters.R index c79048b..d122966 100644 --- a/src/R/eilers_peeters.R +++ b/src/R/eilers_peeters.R @@ -313,7 +313,7 @@ eilers_peeters_modified <- function(model_result) { result <- create_modified_model_result( get_etr_type_from_model_result(model_result), get_etr_regression_data_from_model_result(model_result), - get_sdiff_from_model_result(model_result), + get_residual_sum_of_squares_from_model_result(model_result), model_result[["root_mean_squared_error"]], model_result[["relative_root_mean_squared_error"]], model_result[["a"]], diff --git a/src/R/platt.R b/src/R/platt.R index 38d1387..19435ab 100644 --- a/src/R/platt.R +++ b/src/R/platt.R @@ -321,7 +321,7 @@ platt_modified <- function(model_result) { result <- create_modified_model_result( etr_type = get_etr_type_from_model_result(model_result), etr_regression_data = get_etr_regression_data_from_model_result(model_result), - residual_sum_of_squares = get_sdiff_from_model_result(model_result), + residual_sum_of_squares = get_residual_sum_of_squares_from_model_result(model_result), root_mean_squared_error = model_result[["root_mean_squared_error"]], relative_root_mean_squared_error = model_result[["relative_root_mean_squared_error"]], a = model_result[["ps"]], diff --git a/src/R/util.R b/src/R/util.R index 0d8f2d8..1afb041 100644 --- a/src/R/util.R +++ b/src/R/util.R @@ -26,7 +26,7 @@ get_etr_regression_data_from_model_result <- function(model_result) { return(model_result[["etr_regression_data"]]) } -get_sdiff_from_model_result <- function(model_result) { +get_residual_sum_of_squares_from_model_result <- function(model_result) { return(model_result[["residual_sum_of_squares"]]) } diff --git a/src/R/vollenweider.R b/src/R/vollenweider.R index 9abc648..aae0ece 100644 --- a/src/R/vollenweider.R +++ b/src/R/vollenweider.R @@ -324,7 +324,7 @@ vollenweider_modified <- function(model_result) { result <- create_modified_model_result( etr_type = get_etr_type_from_model_result(model_result), etr_regression_data = get_etr_regression_data_from_model_result(model_result), - residual_sum_of_squares = get_sdiff_from_model_result(model_result), + residual_sum_of_squares = get_residual_sum_of_squares_from_model_result(model_result), model_result[["root_mean_squared_error"]], model_result[["relative_root_mean_squared_error"]], a = model_result[["pmax"]], diff --git a/src/R/walsby.R b/src/R/walsby.R index 9016530..341d0f2 100644 --- a/src/R/walsby.R +++ b/src/R/walsby.R @@ -257,7 +257,7 @@ walsby_modified <- function(model_result) { result <- create_modified_model_result( etr_type = get_etr_type_from_model_result(model_result), etr_regression_data = get_etr_regression_data_from_model_result(model_result), - residual_sum_of_squares = get_sdiff_from_model_result(model_result), + residual_sum_of_squares = get_residual_sum_of_squares_from_model_result(model_result), model_result[["root_mean_squared_error"]], model_result[["relative_root_mean_squared_error"]], a = model_result[["etr_max"]], From 0425d128cf0fbdd3a96e5890587795e916f2f7c2 Mon Sep 17 00:00:00 2001 From: Phi-S <926151+Phi-S@users.noreply.github.com> Date: Mon, 20 Apr 2026 14:07:52 +0200 Subject: [PATCH 20/32] formatting and fix test case for read_pam_2500_data --- src/R/read_pam_data.R | 1 - src/R/validation.R | 67 -------------------- src/tests/testthat/test-read_pam_2500_data.R | 2 +- 3 files changed, 1 insertion(+), 69 deletions(-) diff --git a/src/R/read_pam_data.R b/src/R/read_pam_data.R index 90af9f1..5b76d2c 100644 --- a/src/R/read_pam_data.R +++ b/src/R/read_pam_data.R @@ -689,7 +689,6 @@ read_pam_2500_data <- function( data$DateTime <- date_time_col_values data <- data[order(data$DateTime), ] - result <- data.table::data.table( par = numeric(), yield_1 = numeric(), diff --git a/src/R/validation.R b/src/R/validation.R index 404ade2..99541ec 100644 --- a/src/R/validation.R +++ b/src/R/validation.R @@ -258,74 +258,7 @@ validate_pam_2500_data <- function(data) { if (!"Y.II." %in% colnames(data)) { stop("required col 'Y(II)' not found") } -} - -validate_junior_pam_data <- function(data) { - if (is.null(data)) { - stop("data is null") - } - - if (!data.table::is.data.table(data)) { - stop("data is not a valid data.table") - } - - if (nrow(data) < 2) { - stop("no data rows") - } - - if (ncol(data) == 0) { - stop("no cols in data") - } - - if (!any(grepl("PAR", colnames(data)))) { - stop("required col 'PAR' not found") - } - - if (!any(grepl("Y..II.", colnames(data)))) { - stop("required col 'Y..II.' not found") - } - if (!"Datetime" %in% colnames(data)) { - stop("required col 'Datetime' not found") - } -} - -validate_pam_2500_data <- function(data) { - if (is.null(data)) { - stop("data is null") - } - - if (!data.table::is.data.table(data)) { - stop("data is not a valid data.table") - } - - if (nrow(data) < 2) { - stop("no data rows") - } - - if (ncol(data) == 0) { - stop("no cols in data") - } - - if (!"No." %in% colnames(data)) { - stop("required col 'No.' not found") - } - - if (!"PAR" %in% colnames(data)) { - stop("required col 'PAR' not found") - } - - if (!"Date" %in% colnames(data)) { - stop("required col 'Date' not found") - } - - if (!"Time" %in% colnames(data)) { - stop("required col 'Time' not found") - } - - if (!"Y.II." %in% colnames(data)) { - stop("required col 'Y(II)' not found") - } } validate_etr_regression_data <- function(regression_data) { diff --git a/src/tests/testthat/test-read_pam_2500_data.R b/src/tests/testthat/test-read_pam_2500_data.R index 5ef4f14..bdbb3bd 100644 --- a/src/tests/testthat/test-read_pam_2500_data.R +++ b/src/tests/testthat/test-read_pam_2500_data.R @@ -151,7 +151,7 @@ test_that("read_pam_2500_data 20260311_1(2)_pam_2500.CSV - etr-factor 0.5", { test_that("read_pam_2500_data 20260311_1(2)_pam_2500.CSV - - fraction_photosystem_I = 0.2, fraction_photosystem_II = 0.8", { test_data_file <- testthat::test_path("data", "20260311_1(2)_pam_2500.CSV") data <- read_pam_2500_data(test_data_file, etr_factor = 0.5) - expect_error(read_pam_2000_data(test_data_file, fraction_photosystem_I = 0.9, fraction_photosystem_II = 0.2)) + expect_error(read_pam_2500_data(test_data_file, fraction_photosystem_I = 0.9, fraction_photosystem_II = 0.2)) }) test_that("read_pam_2500_data 20260311_1(2)_pam_2500.CSV - fraction_photosystem_I = 0.2, fraction_photosystem_II = 0.8", { From c1619152670d93ef7c442a74d19762f2a89c3420 Mon Sep 17 00:00:00 2001 From: Phi-S <926151+Phi-S@users.noreply.github.com> Date: Mon, 20 Apr 2026 14:25:30 +0200 Subject: [PATCH 21/32] Remove unnecessary data loading in test for fraction photosystem parameters --- src/tests/testthat/test-read_pam_2500_data.R | 1 - 1 file changed, 1 deletion(-) diff --git a/src/tests/testthat/test-read_pam_2500_data.R b/src/tests/testthat/test-read_pam_2500_data.R index bdbb3bd..97c31c8 100644 --- a/src/tests/testthat/test-read_pam_2500_data.R +++ b/src/tests/testthat/test-read_pam_2500_data.R @@ -150,7 +150,6 @@ test_that("read_pam_2500_data 20260311_1(2)_pam_2500.CSV - etr-factor 0.5", { test_that("read_pam_2500_data 20260311_1(2)_pam_2500.CSV - - fraction_photosystem_I = 0.2, fraction_photosystem_II = 0.8", { test_data_file <- testthat::test_path("data", "20260311_1(2)_pam_2500.CSV") - data <- read_pam_2500_data(test_data_file, etr_factor = 0.5) expect_error(read_pam_2500_data(test_data_file, fraction_photosystem_I = 0.9, fraction_photosystem_II = 0.2)) }) From a2eb1dffe2f21ccd99c5c31d77d717a5f3e840ca Mon Sep 17 00:00:00 2001 From: PhiS <926151+Phi-S@users.noreply.github.com> Date: Mon, 20 Apr 2026 14:28:10 +0200 Subject: [PATCH 22/32] Update rcmdcheck.yml --- .github/workflows/rcmdcheck.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/rcmdcheck.yml b/.github/workflows/rcmdcheck.yml index cf8fd69..55d1efa 100644 --- a/.github/workflows/rcmdcheck.yml +++ b/.github/workflows/rcmdcheck.yml @@ -10,9 +10,9 @@ name: rcmdcheck on: push: - branches: [ "main" ] + branches: [ "main", "dev" ] pull_request: - branches: [ "main" ] + branches: [ "main", "dev" ] permissions: contents: read From f67be2b632cd1211119f178289b702684b579032 Mon Sep 17 00:00:00 2001 From: JulienBoehm <180776296+JulienBoehm@users.noreply.github.com> Date: Tue, 21 Apr 2026 19:11:24 +0200 Subject: [PATCH 23/32] updated citation and readme --- CITATION.cff | 18 ++++++++++++++++-- README.md | 7 +++---- src/inst/CITATION | 13 ++++++++----- 3 files changed, 27 insertions(+), 11 deletions(-) diff --git a/CITATION.cff b/CITATION.cff index c807543..c41435b 100644 --- a/CITATION.cff +++ b/CITATION.cff @@ -8,7 +8,21 @@ authors: given-names: "Philipp" orcid: "https://orcid.org/0009-0002-7697-5536" title: "pam" -version: 2.1.1 -date-released: 2026-04-11 url: "https://github.com/biotoolbox/pam" doi: "10.32614/CRAN.package.pam" + +preferred-citation: + type: article + authors: + - family-names: "Böhm" + given-names: "Julien" + - family-names: "Schrag" + given-names: "Philipp" + title: "pam: An R Package for Fast and Efficient Processing of Pulse-Amplitude Modulation Data" + journal: "Ecology and Evolution" + year: 2026 + volume: 16 + issue: 4 + start: e73400 + doi: "10.1002/ece3.73400" + url: "https://onlinelibrary.wiley.com/doi/abs/10.1002/ece3.73400" diff --git a/README.md b/README.md index 92bb9da..daee3b2 100644 --- a/README.md +++ b/README.md @@ -7,10 +7,9 @@ ## Introduction -The library ‘pam’ was developed to process PAM raw data (chlorophyll fluorometry to analyze photosystem II and dual wavelength absorbance spectrometry to analyze photosystem I). For this purpose, both device-specific read functions (e.g., for the WALZ Dual-PAM) and a universal read function for processing generic datasets are provided. -Four different models are provided for the regression of the light curve (Vollenweider (1965), Platt (1980), Eilers and Peeters (1988) and Walsby (1997)). -To select the most suitable model for the respective data set, the models can be compared with each other. To avoid confusion in the naming of the variables and calculated factors such as $$ETR_{max}$$, it is possible to output both with publication-compliant naming and with homogenised naming. -Generated control plots make it possible to check each individual regression fit and calculated data. +Rapid light curves recorded via the pulse‐amplitude modulation (PAM) technique are widely used to characterize photosynthesis, enabling the determination of key photosynthetic parameters. However, deriving these kinetic parameters from raw data requires fitting to regression models, a process traditionally involving laborious and error‐prone manual steps. Our R package pam streamlines this process by automating regression analysis, enabling fast and reproducible processing of large datasets. It provides the models of Vollenweider (1965), Platt et al. (1980), Eilers and Peeters (1988) and Walsby (1997). + +- J. Böhm and P. Schrag, ‘pam: An R Package for Fast and Efficient Processing of Pulse‐Amplitude Modulation Data’, Ecology and Evolution, vol. 16, no. 4, p. e73400, Apr. 2026, doi: [10.1002/ece3.73400](https://www.researchgate.net/publication/404020183_pam_An_R_Package_for_Fast_and_Efficient_Processing_of_Pulse-Amplitude_Modulation_Data). ## Publications using this package diff --git a/src/inst/CITATION b/src/inst/CITATION index a3fb634..ad0cae4 100644 --- a/src/inst/CITATION +++ b/src/inst/CITATION @@ -1,9 +1,12 @@ citation <- bibentry( - bibtype = "Manual", - title = "pam: Fast and Efficient Processing of PAM Data", + bibtype = "Article", + title = "pam: An R Package for Fast and Efficient Processing of Pulse-Amplitude Modulation Data", author = c(person("Julien", "Böhm"), person("Philipp", "Schrag")), + journal = "Ecology and Evolution", year = 2026, - note = "R package version 2.1.1", - url = "https://CRAN.R-project.org/package=pam", - doi = "10.32614/CRAN.package.pam" + volume = "16", + number = "4", + pages = "e73400", + doi = "10.1002/ece3.73400", + url = "https://onlinelibrary.wiley.com/doi/abs/10.1002/ece3.73400" ) From 9d83544be3e8eeae46cb1e25c251b5e8fd4e4aeb Mon Sep 17 00:00:00 2001 From: JulienBoehm <180776296+JulienBoehm@users.noreply.github.com> Date: Wed, 22 Apr 2026 09:38:00 +0200 Subject: [PATCH 24/32] updated links in readme --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index daee3b2..02e37fc 100644 --- a/README.md +++ b/README.md @@ -17,7 +17,7 @@ Rapid light curves recorded via the pulse‐amplitude modulation (PAM) technique - J. Böhm, I. Blindow, N. Gyllenstrand, W. Diewald, and H. Schubert, ‘*Sphaerochara canadensis* (Charophyceae): A circumpolar species with a high temperature optimum’, Journal of Phycology, vol. 61, no. 6, pp. 1863–1873, Dec. 2025, doi: [10.1111/jpy.70111](https://www.researchgate.net/publication/398295400_Sphaerochara_canadensis_Charophyceae_A_circumpolar_species_with_a_high_temperature_optimum). -- A continuously updated overview of studies using this package can be accessed at [Researchgate](https://www.researchgate.net/publication/395536281_pam_Fast_and_Efficient_Processing_of_PAM_Data/citations) +- A continuously updated overview of studies using this package can be accessed via ResearchGate ([publication](https://www.researchgate.net/publication/404020183_pam_An_R_Package_for_Fast_and_Efficient_Processing_of_Pulse-Amplitude_Modulation_Data/citations), [package](https://www.researchgate.net/publication/395536281_pam_Fast_and_Efficient_Processing_of_PAM_Data/citations)) ## Test coverage From d529933dc90c3c5a24005e4789c82a5e07447923 Mon Sep 17 00:00:00 2001 From: JulienBoehm <180776296+JulienBoehm@users.noreply.github.com> Date: Wed, 22 Apr 2026 13:46:45 +0200 Subject: [PATCH 25/32] updated read_junior_pam --- README.md | 13 +- src/R/read_pam_data.R | 72 +++----- src/R/validation.R | 4 +- .../junior_pam_data/2026_04_22_junior_pam.csv | 20 +++ .../junior_pam_data/junior_pam_20250613.csv | 20 --- src/man/read_junior_pam_data.Rd | 2 +- .../testthat/data/2026_04_22_junior_pam.csv | 20 +++ .../testthat/data/junior_pam_20250613.csv | 20 --- .../test-eilers_peeters_junior_pam_etr_II.R | 79 --------- .../testthat/test-read_junior_pam_data.R | 166 +++++++++--------- texport_junior_pam.png | Bin 0 -> 42974 bytes 11 files changed, 161 insertions(+), 255 deletions(-) create mode 100644 src/inst/extdata/junior_pam_data/2026_04_22_junior_pam.csv delete mode 100644 src/inst/extdata/junior_pam_data/junior_pam_20250613.csv create mode 100644 src/tests/testthat/data/2026_04_22_junior_pam.csv delete mode 100644 src/tests/testthat/data/junior_pam_20250613.csv delete mode 100644 src/tests/testthat/test-eilers_peeters_junior_pam_etr_II.R create mode 100644 texport_junior_pam.png diff --git a/README.md b/README.md index 02e37fc..f15e965 100644 --- a/README.md +++ b/README.md @@ -126,7 +126,7 @@ The function processes the provided CSV file by: - Combining the `Date` and `Time` columns to create a `DateTime` column and ordering the data chronologically. - Calculating initial ETR values from `Pm.-Det.` and `Fm-Det.` rows using `calc_etr()`. - Iterating through all rows with `Action == "P.+F. SP"` to calculate ETR values for both `Y.I.` and `Y.II.` -- Optionally stopping at the recovery period if `remove_recovery = TRUE`. +- Stopping at the recovery period if `remove_recovery = TRUE`. #### Return @@ -179,7 +179,7 @@ The function processes the provided CSV file by: - Combining the `Date` and `Time` columns to create a `DateTime` column and ordering the data chronologically. - Extracting the initial Pm.-Det. measurement at `PAR = 0` to calculate the first ETR value. - Iterating through all rows with `Action == "P700 SP"` to calculate ETR values for Photosystem I (`Y.I.`). -- Optionally stopping at the recovery period if `remove_recovery = TRUE`. +- Stopping at the recovery period if `remove_recovery = TRUE`. #### Return @@ -236,7 +236,7 @@ The function processes the provided CSV file by: - Combining the `Date` and `Time` columns to create a `DateTime` column and ordering the data chronologically. - Extracting the initial **Fm-Det.** measurement at `PAR = 0` to calculate the first ETR value. - Iterating through all rows with `Action == "Fluo. SP"` to calculate ETR values for Photosystem II (`Y.II.`). -- Optionally stopping at the recovery period if `remove_recovery = TRUE`. +- Stopping at the recovery period if `remove_recovery = TRUE`. #### Return @@ -292,9 +292,12 @@ The function processes the provided CSV file by: - Validating the raw Junior-PAM data with `validate_junior_pam_data()`. - Renaming columns to standard names (`PAR`, `Y.II`.) if necessary. - Filtering rows where Type equals `"FO"` or `"F"`. -- Converting and ordering the `DateTime` column. +- Ordering by `Time (rel/ms)` column. - Iterating through all rows to calculate ETR values for `Y.II.` using `calc_etr()`. -- Optionally stopping at the recovery period if `remove_recovery = TRUE`. +- Stopping at the recovery period if `remove_recovery = TRUE`. + +To ensure the file is imported correctly, please export the CSV file using the default settings: +![Plot](texport_junior_pam.png) #### Return diff --git a/src/R/read_pam_data.R b/src/R/read_pam_data.R index 5b76d2c..189b901 100644 --- a/src/R/read_pam_data.R +++ b/src/R/read_pam_data.R @@ -111,12 +111,11 @@ read_universal_data <- function(csv_path, #' data <- read_dual_pam_data(path) #' @export read_dual_pam_data <- function( - csv_path, - remove_recovery = TRUE, - etr_factor = 0.84, - fraction_photosystem_I = 0.5, - fraction_photosystem_II = 0.5 -) { + csv_path, + remove_recovery = TRUE, + etr_factor = 0.84, + fraction_photosystem_I = 0.5, + fraction_photosystem_II = 0.5) { if (fraction_photosystem_I + fraction_photosystem_II != 1) { stop("The sum of fraction_photosystem_I and fraction_photosystem_II must be equal 1.") } @@ -249,12 +248,11 @@ read_dual_pam_data <- function( #' data <- read_dual_pam_single_channel_p700_data(path) #' @export read_dual_pam_single_channel_p700_data <- function( - csv_path, - remove_recovery = TRUE, - etr_factor = 0.84, - fraction_photosystem_I = 0.5, - fraction_photosystem_II = 0.5 -) { + csv_path, + remove_recovery = TRUE, + etr_factor = 0.84, + fraction_photosystem_I = 0.5, + fraction_photosystem_II = 0.5) { if (fraction_photosystem_I + fraction_photosystem_II != 1) { stop("The sum of fraction_photosystem_I and fraction_photosystem_II must be equal 1.") } @@ -380,12 +378,11 @@ read_dual_pam_single_channel_p700_data <- function( #' data <- read_dual_pam_single_channel_fluo_data(path) #' @export read_dual_pam_single_channel_fluo_data <- function( - csv_path, - remove_recovery = TRUE, - etr_factor = 0.84, - fraction_photosystem_I = 0.5, - fraction_photosystem_II = 0.5 -) { + csv_path, + remove_recovery = TRUE, + etr_factor = 0.84, + fraction_photosystem_I = 0.5, + fraction_photosystem_II = 0.5) { if (fraction_photosystem_I + fraction_photosystem_II != 1) { stop("The sum of fraction_photosystem_I and fraction_photosystem_II must be equal 1.") } @@ -532,17 +529,16 @@ calc_etr <- function(yield, par, etr_factor, p_ratio) { #' @examples #' path <- file.path( #' system.file("extdata/junior_pam_data", package = "pam"), -#' "junior_pam_20250613.csv" +#' "2026_04_22_junior_pam.csv" #' ) #' data <- read_junior_pam_data(path) #' @export read_junior_pam_data <- function( - csv_path, - remove_recovery = TRUE, - etr_factor = 0.84, - fraction_photosystem_I = 0.5, - fraction_photosystem_II = 0.5 -) { + csv_path, + remove_recovery = TRUE, + etr_factor = 0.84, + fraction_photosystem_I = 0.5, + fraction_photosystem_II = 0.5) { if (fraction_photosystem_I + fraction_photosystem_II != 1) { stop("The sum of fraction_photosystem_I and fraction_photosystem_II must be equal 1.") } @@ -565,20 +561,7 @@ read_junior_pam_data <- function( } data <- data[data$Type == "FO" | data$Type == "F", ] - data$Datetime <- as.POSIXct(data$Datetime, format = "%Y-%m-%d %H:%M:%OS", tz = "GMT") - - date_time_col_values <- c() - for (i in seq_len(nrow(data))) { - row <- data[i, ] - - date_time_row_value <- as.POSIXct( - paste(row$Date, row$Time, sep = " "), - tz = "GMT", "%d.%m.%y %H:%M:%S" - ) - date_time_col_values <- c(date_time_col_values, date_time_row_value) - } - data$DateTime <- date_time_col_values - data <- data[order(data$Datetime), ] + data <- data[order(data$"Time..rel.ms."), ] result <- data.table::data.table( par = numeric(), @@ -657,12 +640,11 @@ read_junior_pam_data <- function( #' data <- read_pam_2500_data(path) #' @export read_pam_2500_data <- function( - csv_path, - remove_recovery = TRUE, - etr_factor = 0.84, - fraction_photosystem_I = 0.5, - fraction_photosystem_II = 0.5 -) { + csv_path, + remove_recovery = TRUE, + etr_factor = 0.84, + fraction_photosystem_I = 0.5, + fraction_photosystem_II = 0.5) { if (fraction_photosystem_I + fraction_photosystem_II != 1) { stop("The sum of fraction_photosystem_I and fraction_photosystem_II must be equal 1.") } diff --git a/src/R/validation.R b/src/R/validation.R index 85a7639..69d5d40 100644 --- a/src/R/validation.R +++ b/src/R/validation.R @@ -217,8 +217,8 @@ validate_junior_pam_data <- function(data) { stop("required col 'Y..II.' not found") } - if (!"Datetime" %in% colnames(data)) { - stop("required col 'Datetime' not found") + if (!"Time..rel.ms." %in% colnames(data)) { + stop("required col 'Time (rel/ms)' not found") } } diff --git a/src/inst/extdata/junior_pam_data/2026_04_22_junior_pam.csv b/src/inst/extdata/junior_pam_data/2026_04_22_junior_pam.csv new file mode 100644 index 0000000..3f4f810 --- /dev/null +++ b/src/inst/extdata/junior_pam_data/2026_04_22_junior_pam.csv @@ -0,0 +1,20 @@ +26-04-22;10:44:04.000;WinControl (rev1255) report file +Time (rel/ms);Type;No.;2:F;2:Fm';2:PAR;2:Y (II);2:ETR +0;D;;Device Nr: #2, JUNIOR-PAM-III (CFMG0711B); +0;SLCS;;Light Curve start; +0;REG1;;#2: alpha: - , ETRm: - , Ik: - ( beta: - 0.001, ETRmPot: 76.798 ) (Platt et al. 1980); +0;REG2;;#2: alpha: 0.188, ETRm: 77.953, Ik: 414.611 (Jassby and Platt 1976); +1393;FO;1;130;506;0;0.743;0 +51389;F;2;278;489;50;0.431;9.1 +101375;F;3;317;472;90;0.328;12.4 +151366;F;4;211;342;130;0.383;20.9 +201357;F;5;178;304;180;0.414;31.3 +251347;F;6;164;284;250;0.423;44.4 +301335;F;7;159;248;380;0.359;57.3 +351325;F;8;148;210;570;0.295;70.6 +401305;F;9;144;183;840;0.213;75.1 +451323;F;10;140;164;1250;0.146;76.7 +501306;F;11;135;150;1640;0.1;68.9 +551299;F;12;131;143;2300;0.084;81.1 +601286;F;13;127;136;3000;0.066;83.2 +605163;SLCE;;Light Curve end; diff --git a/src/inst/extdata/junior_pam_data/junior_pam_20250613.csv b/src/inst/extdata/junior_pam_data/junior_pam_20250613.csv deleted file mode 100644 index 94e369e..0000000 --- a/src/inst/extdata/junior_pam_data/junior_pam_20250613.csv +++ /dev/null @@ -1,20 +0,0 @@ -25-06-13;10:50:28.000;WinControl (rev1242) report file -Datetime;Time (abs/ms);Time (rel/ms);Type;No.;1:F;1:Fm';1:PAR;1:Y (II);1:ETR -;0;D;;Device Nr: #1, JUNIOR-PAM-III (CFMG0710B); -2025-06-13 10:38:54.217;1749803934217;0;SLCS;;Light Curve start; -2025-06-13 10:38:54.217;1749803934217;0;REG1;;#1: alpha: 0.303, ETRm: 59.733, Ik: 197.268 ( beta: 0.001, ETRmPot: 61.486 ) (Platt et al. 1980); -2025-06-13 10:38:54.217;1749803934217;0;REG2;;#1: alpha: 0.238, ETRm: 58.397, Ik: 245.332 (Jassby and Platt 1976); -2025-06-13 10:38:55.603;1.7498e+012;1386;FO;1;124;584;0;0.788;0 -2025-06-13 10:39:35.598;1.7498e+012;41381;F;2;207;549;50;0.623;13.1 -2025-06-13 10:40:15.588;1.7498e+012;81371;F;3;207;512;90;0.596;22.5 -2025-06-13 10:40:55.576;1.7498e+012;121359;F;4;214;472;130;0.547;29.9 -2025-06-13 10:41:35.555;1.7498e+012;161338;F;5;204;396;180;0.485;36.7 -2025-06-13 10:42:15.549;1.7498e+012;201332;F;6;198;336;250;0.411;43.2 -2025-06-13 10:42:55.538;1.7498e+012;241321;F;7;196;286;380;0.315;50.3 -2025-06-13 10:43:35.534;1.7498e+012;281317;F;8;193;252;570;0.234;56 -2025-06-13 10:44:15.514;1.7498e+012;321297;F;9;189;226;840;0.164;57.9 -2025-06-13 10:44:55.507;1.7498e+012;361290;F;10;185;209;1250;0.115;60.4 -2025-06-13 10:45:35.495;1.7498e+012;401278;F;11;178;196;1640;0.092;63.4 -2025-06-13 10:46:15.491;1.7498e+012;441274;F;12;174;185;2300;0.059;57 -2025-06-13 10:46:55.496;1.7498e+012;481279;F;13;168;176;3000;0.045;56.7 -2025-06-13 10:46:58.974;1749804418974;484757;SLCE;;Light Curve end; diff --git a/src/man/read_junior_pam_data.Rd b/src/man/read_junior_pam_data.Rd index 180872a..f233dff 100644 --- a/src/man/read_junior_pam_data.Rd +++ b/src/man/read_junior_pam_data.Rd @@ -45,7 +45,7 @@ A detailed documentation can be found under \url{https://github.com/biotoolbox/p \examples{ path <- file.path( system.file("extdata/junior_pam_data", package = "pam"), - "junior_pam_20250613.csv" + "2026_04_22_junior_pam.csv" ) data <- read_junior_pam_data(path) } diff --git a/src/tests/testthat/data/2026_04_22_junior_pam.csv b/src/tests/testthat/data/2026_04_22_junior_pam.csv new file mode 100644 index 0000000..3f4f810 --- /dev/null +++ b/src/tests/testthat/data/2026_04_22_junior_pam.csv @@ -0,0 +1,20 @@ +26-04-22;10:44:04.000;WinControl (rev1255) report file +Time (rel/ms);Type;No.;2:F;2:Fm';2:PAR;2:Y (II);2:ETR +0;D;;Device Nr: #2, JUNIOR-PAM-III (CFMG0711B); +0;SLCS;;Light Curve start; +0;REG1;;#2: alpha: - , ETRm: - , Ik: - ( beta: - 0.001, ETRmPot: 76.798 ) (Platt et al. 1980); +0;REG2;;#2: alpha: 0.188, ETRm: 77.953, Ik: 414.611 (Jassby and Platt 1976); +1393;FO;1;130;506;0;0.743;0 +51389;F;2;278;489;50;0.431;9.1 +101375;F;3;317;472;90;0.328;12.4 +151366;F;4;211;342;130;0.383;20.9 +201357;F;5;178;304;180;0.414;31.3 +251347;F;6;164;284;250;0.423;44.4 +301335;F;7;159;248;380;0.359;57.3 +351325;F;8;148;210;570;0.295;70.6 +401305;F;9;144;183;840;0.213;75.1 +451323;F;10;140;164;1250;0.146;76.7 +501306;F;11;135;150;1640;0.1;68.9 +551299;F;12;131;143;2300;0.084;81.1 +601286;F;13;127;136;3000;0.066;83.2 +605163;SLCE;;Light Curve end; diff --git a/src/tests/testthat/data/junior_pam_20250613.csv b/src/tests/testthat/data/junior_pam_20250613.csv deleted file mode 100644 index 94e369e..0000000 --- a/src/tests/testthat/data/junior_pam_20250613.csv +++ /dev/null @@ -1,20 +0,0 @@ -25-06-13;10:50:28.000;WinControl (rev1242) report file -Datetime;Time (abs/ms);Time (rel/ms);Type;No.;1:F;1:Fm';1:PAR;1:Y (II);1:ETR -;0;D;;Device Nr: #1, JUNIOR-PAM-III (CFMG0710B); -2025-06-13 10:38:54.217;1749803934217;0;SLCS;;Light Curve start; -2025-06-13 10:38:54.217;1749803934217;0;REG1;;#1: alpha: 0.303, ETRm: 59.733, Ik: 197.268 ( beta: 0.001, ETRmPot: 61.486 ) (Platt et al. 1980); -2025-06-13 10:38:54.217;1749803934217;0;REG2;;#1: alpha: 0.238, ETRm: 58.397, Ik: 245.332 (Jassby and Platt 1976); -2025-06-13 10:38:55.603;1.7498e+012;1386;FO;1;124;584;0;0.788;0 -2025-06-13 10:39:35.598;1.7498e+012;41381;F;2;207;549;50;0.623;13.1 -2025-06-13 10:40:15.588;1.7498e+012;81371;F;3;207;512;90;0.596;22.5 -2025-06-13 10:40:55.576;1.7498e+012;121359;F;4;214;472;130;0.547;29.9 -2025-06-13 10:41:35.555;1.7498e+012;161338;F;5;204;396;180;0.485;36.7 -2025-06-13 10:42:15.549;1.7498e+012;201332;F;6;198;336;250;0.411;43.2 -2025-06-13 10:42:55.538;1.7498e+012;241321;F;7;196;286;380;0.315;50.3 -2025-06-13 10:43:35.534;1.7498e+012;281317;F;8;193;252;570;0.234;56 -2025-06-13 10:44:15.514;1.7498e+012;321297;F;9;189;226;840;0.164;57.9 -2025-06-13 10:44:55.507;1.7498e+012;361290;F;10;185;209;1250;0.115;60.4 -2025-06-13 10:45:35.495;1.7498e+012;401278;F;11;178;196;1640;0.092;63.4 -2025-06-13 10:46:15.491;1.7498e+012;441274;F;12;174;185;2300;0.059;57 -2025-06-13 10:46:55.496;1.7498e+012;481279;F;13;168;176;3000;0.045;56.7 -2025-06-13 10:46:58.974;1749804418974;484757;SLCE;;Light Curve end; diff --git a/src/tests/testthat/test-eilers_peeters_junior_pam_etr_II.R b/src/tests/testthat/test-eilers_peeters_junior_pam_etr_II.R deleted file mode 100644 index f5143e8..0000000 --- a/src/tests/testthat/test-eilers_peeters_junior_pam_etr_II.R +++ /dev/null @@ -1,79 +0,0 @@ -test_that("test-eilers_peeters_etr_II junior_pam_20250613.csv.csv - linux", { - skip_if_not(is_debian_or_ubuntu()) - - test_data_file <- testthat::test_path("data", "junior_pam_20250613.csv") - data <- read_junior_pam_data(test_data_file) - model_result <- eilers_peeters_generate_regression_ETR_II(data) - - expect_equal(model_result[["residual_sum_of_squares"]], 18.5975058) - # expect_equal(model_result[["a"]], 0.000001594) - expect_equal(model_result[["b"]], 0.01213671) - expect_equal(model_result[["c"]], 2.77837046) - expect_equal(model_result[["pm"]], 61.1793644) - expect_equal(model_result[["s"]], 0.35992320) - expect_equal(model_result[["ik"]], 169.978939) - expect_equal(model_result[["im"]], 1320.307821) - expect_equal(model_result[["w"]], 5.7674788) -}) - -test_that("test-eilers_peeters_etr_II junior_pam_20250613.csv.csv", { - test_data_file <- testthat::test_path("data", "junior_pam_20250613.csv") - data <- read_junior_pam_data(test_data_file) - model_result <- eilers_peeters_generate_regression_ETR_II(data) - expect_no_error(validate_model_result(model_result)) -}) - -test_that("test-eilers_peeters_etr_II modified junior_pam_20250613.csv.csv - linux", { - skip_if_not(is_debian_or_ubuntu()) - test_data_file <- testthat::test_path("data", "junior_pam_20250613.csv") - data <- read_junior_pam_data(test_data_file) - model_result <- eilers_peeters_generate_regression_ETR_II(data) - model_result <- eilers_peeters_modified(model_result) - - expect_equal(model_result[["residual_sum_of_squares"]], 18.5975058) - # expect_equal(model_result[["a"]], 0.000001594) - expect_equal(model_result[["b"]], 0.01213671) - expect_equal(model_result[["c"]], 2.77837046) - expect_equal(model_result[["d"]], NA_real_) - expect_equal(model_result[["alpha"]], 0.35992320) - expect_equal(model_result[["beta"]], NA_real_) - expect_equal(model_result[["etrmax_with_photoinhibition"]], 61.1793644) - expect_equal(model_result[["etrmax_without_photoinhibition"]], NA_real_) - expect_equal(model_result[["ik_with_photoinhibition"]], 169.978939) - expect_equal(model_result[["ik_without_photoinhibition"]], NA_real_) - expect_equal(model_result[["im_with_photoinhibition"]], 1320.307821) - expect_equal(model_result[["w"]], 5.7674788) - expect_equal(model_result[["ib"]], NA_real_) - expect_equal(model_result[["etrmax_without_with_ratio"]], NA_real_) -}) - -test_that("test-eilers_peeters_etr_II modified junior_pam_20250613.csv.csv", { - test_data_file <- testthat::test_path("data", "junior_pam_20250613.csv") - data <- read_junior_pam_data(test_data_file) - - model_result <- eilers_peeters_generate_regression_ETR_II(data) - expect_no_error(validate_model_result(model_result)) - - model_result <- eilers_peeters_modified(model_result) - expect_no_error(validate_modified_model_result(model_result)) -}) - -test_that("test-eilers_peeters_etr_II modified control plot junior_pam_20250613.csv", { - test_data_file <- testthat::test_path("data", "junior_pam_20250613.csv") - data <- read_junior_pam_data(test_data_file) - model_result <- eilers_peeters_generate_regression_ETR_II(data) - model_result <- model_result <- eilers_peeters_modified(model_result) - - plot <- plot_control( - data, - model_result, - "eilers_peeters ETR II modified junior_pam_20250613.csv", - color_eilers_peeters - ) - expect_s3_class(plot, "ggplot") - expect_gt(length(plot$layers), 0) - - out <- file.path("results", "test-eilers_peeters_etr_II modified control plot junior_pam_20250613.jpg") - ggplot2::ggsave(out, create.dir = TRUE, plot = plot, units = "px", width = 1000, height = 1000, dpi = 100, limitsize = FALSE) - expect_true(file.exists(out)) -}) diff --git a/src/tests/testthat/test-read_junior_pam_data.R b/src/tests/testthat/test-read_junior_pam_data.R index 8290928..30c8982 100644 --- a/src/tests/testthat/test-read_junior_pam_data.R +++ b/src/tests/testthat/test-read_junior_pam_data.R @@ -1,5 +1,5 @@ -test_that("read_junior_pam_data junior_pam_20250613.csv - default", { - test_data_file <- testthat::test_path("data", "junior_pam_20250613.csv") +test_that("read_junior_pam_data 2026_04_22_junior_pam.csv - default", { + test_data_file <- testthat::test_path("data", "2026_04_22_junior_pam.csv") data <- read_junior_pam_data(test_data_file) par <- data$par @@ -33,19 +33,19 @@ test_that("read_junior_pam_data junior_pam_20250613.csv - default", { expect_equal(yield_1[13], NA_real_) yield_2 <- data$yield_2 - expect_equal(yield_2[1], 0.788) - expect_equal(yield_2[2], 0.623) - expect_equal(yield_2[3], 0.596) - expect_equal(yield_2[4], 0.547) - expect_equal(yield_2[5], 0.485) - expect_equal(yield_2[6], 0.411) - expect_equal(yield_2[7], 0.315) - expect_equal(yield_2[8], 0.234) - expect_equal(yield_2[9], 0.164) - expect_equal(yield_2[10], 0.115) - expect_equal(yield_2[11], 0.092) - expect_equal(yield_2[12], 0.059) - expect_equal(yield_2[13], 0.045) + expect_equal(yield_2[1], 0.743) + expect_equal(yield_2[2], 0.4310) + expect_equal(yield_2[3], 0.3280) + expect_equal(yield_2[4], 0.3830) + expect_equal(yield_2[5], 0.414) + expect_equal(yield_2[6], 0.423) + expect_equal(yield_2[7], 0.359) + expect_equal(yield_2[8], 0.295) + expect_equal(yield_2[9], 0.213) + expect_equal(yield_2[10], 0.146) + expect_equal(yield_2[11], 0.1000) + expect_equal(yield_2[12], 0.084) + expect_equal(yield_2[13], 0.066) etr_1 <- data$etr_1 expect_equal(etr_1[1], NA_real_) @@ -64,22 +64,22 @@ test_that("read_junior_pam_data junior_pam_20250613.csv - default", { etr_2 <- data$etr_2 expect_equal(etr_2[1], 0) - expect_equal(etr_2[2], 13.083) - expect_equal(etr_2[3], 22.5288) - expect_equal(etr_2[4], 29.8662) - expect_equal(etr_2[5], 36.666) - expect_equal(etr_2[6], 43.155) - expect_equal(etr_2[7], 50.274) - expect_equal(etr_2[8], 56.0196) - expect_equal(etr_2[9], 57.8592) - expect_equal(etr_2[10], 60.375) - expect_equal(etr_2[11], 63.3696) - expect_equal(etr_2[12], 56.994) - expect_equal(etr_2[13], 56.7) + expect_equal(etr_2[2], 9.0510) + expect_equal(etr_2[3], 12.3984) + expect_equal(etr_2[4], 20.9118) + expect_equal(etr_2[5], 31.2984) + expect_equal(etr_2[6], 44.4150) + expect_equal(etr_2[7], 57.2964) + expect_equal(etr_2[8], 70.6230) + expect_equal(etr_2[9], 75.1464) + expect_equal(etr_2[10], 76.6500) + expect_equal(etr_2[11], 68.8800) + expect_equal(etr_2[12], 81.1440) + expect_equal(etr_2[13], 83.1600) }) -test_that("read_junior_pam_data junior_pam_20250613.csv - etr_factor 0.5", { - test_data_file <- testthat::test_path("data", "junior_pam_20250613.csv") +test_that("read_junior_pam_data 2026_04_22_junior_pam.csv - etr_factor 0.5", { + test_data_file <- testthat::test_path("data", "2026_04_22_junior_pam.csv") data <- read_junior_pam_data(test_data_file, etr_factor = 0.5) par <- data$par @@ -113,19 +113,19 @@ test_that("read_junior_pam_data junior_pam_20250613.csv - etr_factor 0.5", { expect_equal(yield_1[13], NA_real_) yield_2 <- data$yield_2 - expect_equal(yield_2[1], 0.788) - expect_equal(yield_2[2], 0.623) - expect_equal(yield_2[3], 0.596) - expect_equal(yield_2[4], 0.547) - expect_equal(yield_2[5], 0.485) - expect_equal(yield_2[6], 0.411) - expect_equal(yield_2[7], 0.315) - expect_equal(yield_2[8], 0.234) - expect_equal(yield_2[9], 0.164) - expect_equal(yield_2[10], 0.115) - expect_equal(yield_2[11], 0.092) - expect_equal(yield_2[12], 0.059) - expect_equal(yield_2[13], 0.045) + expect_equal(yield_2[1], 0.743) + expect_equal(yield_2[2], 0.4310) + expect_equal(yield_2[3], 0.3280) + expect_equal(yield_2[4], 0.3830) + expect_equal(yield_2[5], 0.414) + expect_equal(yield_2[6], 0.423) + expect_equal(yield_2[7], 0.359) + expect_equal(yield_2[8], 0.295) + expect_equal(yield_2[9], 0.213) + expect_equal(yield_2[10], 0.146) + expect_equal(yield_2[11], 0.1000) + expect_equal(yield_2[12], 0.084) + expect_equal(yield_2[13], 0.066) etr_1 <- data$etr_1 expect_equal(etr_1[1], NA_real_) @@ -144,27 +144,27 @@ test_that("read_junior_pam_data junior_pam_20250613.csv - etr_factor 0.5", { etr_2 <- data$etr_2 expect_equal(etr_2[1], 0) - expect_equal(etr_2[2], 7.7875) - expect_equal(etr_2[3], 13.41) - expect_equal(etr_2[4], 17.7775) - expect_equal(etr_2[5], 21.825) - expect_equal(etr_2[6], 25.6875) - expect_equal(etr_2[7], 29.925) - expect_equal(etr_2[8], 33.345) - expect_equal(etr_2[9], 34.44) - expect_equal(etr_2[10], 35.9375) - expect_equal(etr_2[11], 37.72) - expect_equal(etr_2[12], 33.925) - expect_equal(etr_2[13], 33.75) + expect_equal(etr_2[2], 5.3875) + expect_equal(etr_2[3], 7.3800) + expect_equal(etr_2[4], 12.4475) + expect_equal(etr_2[5], 18.6300) + expect_equal(etr_2[6], 26.4375) + expect_equal(etr_2[7], 34.1050) + expect_equal(etr_2[8], 42.0375) + expect_equal(etr_2[9], 44.7300) + expect_equal(etr_2[10], 45.6250) + expect_equal(etr_2[11], 41.0000) + expect_equal(etr_2[12], 48.3000) + expect_equal(etr_2[13], 49.5000) }) -test_that("read_junior_pam_data junior_pam_20250613.csv - fraction_photosystem > 1", { - test_data_file <- testthat::test_path("data", "junior_pam_20250613.csv") +test_that("read_junior_pam_data 2026_04_22_junior_pam.csv - fraction_photosystem > 1", { + test_data_file <- testthat::test_path("data", "2026_04_22_junior_pam.csv") expect_error(read_junior_pam_data(test_data_file, fraction_photosystem_I = 0.9, fraction_photosystem_II = 0.2)) }) -test_that("read_junior_pam_data junior_pam_20250613.csv - fraction_photosystem_I = 0.2, fraction_photosystem_II = 0.8", { - test_data_file <- testthat::test_path("data", "junior_pam_20250613.csv") +test_that("read_junior_pam_data 2026_04_22_junior_pam.csv - fraction_photosystem_I = 0.2, fraction_photosystem_II = 0.8", { + test_data_file <- testthat::test_path("data", "2026_04_22_junior_pam.csv") data <- read_junior_pam_data(test_data_file, fraction_photosystem_I = 0.2, fraction_photosystem_II = 0.8) par <- data$par @@ -198,19 +198,19 @@ test_that("read_junior_pam_data junior_pam_20250613.csv - fraction_photosystem_I expect_equal(yield_1[13], NA_real_) yield_2 <- data$yield_2 - expect_equal(yield_2[1], 0.788) - expect_equal(yield_2[2], 0.623) - expect_equal(yield_2[3], 0.596) - expect_equal(yield_2[4], 0.547) - expect_equal(yield_2[5], 0.485) - expect_equal(yield_2[6], 0.411) - expect_equal(yield_2[7], 0.315) - expect_equal(yield_2[8], 0.234) - expect_equal(yield_2[9], 0.164) - expect_equal(yield_2[10], 0.115) - expect_equal(yield_2[11], 0.092) - expect_equal(yield_2[12], 0.059) - expect_equal(yield_2[13], 0.045) + expect_equal(yield_2[1], 0.743) + expect_equal(yield_2[2], 0.4310) + expect_equal(yield_2[3], 0.3280) + expect_equal(yield_2[4], 0.3830) + expect_equal(yield_2[5], 0.414) + expect_equal(yield_2[6], 0.423) + expect_equal(yield_2[7], 0.359) + expect_equal(yield_2[8], 0.295) + expect_equal(yield_2[9], 0.213) + expect_equal(yield_2[10], 0.146) + expect_equal(yield_2[11], 0.1000) + expect_equal(yield_2[12], 0.084) + expect_equal(yield_2[13], 0.066) etr_1 <- data$etr_1 expect_equal(etr_1[1], NA_real_) @@ -229,16 +229,16 @@ test_that("read_junior_pam_data junior_pam_20250613.csv - fraction_photosystem_I etr_2 <- data$etr_2 expect_equal(etr_2[1], 0) - expect_equal(etr_2[2], 20.9328) - expect_equal(etr_2[3], 36.04608) - expect_equal(etr_2[4], 47.78592) - expect_equal(etr_2[5], 58.6656) - expect_equal(etr_2[6], 69.048) - expect_equal(etr_2[7], 80.4384) - expect_equal(etr_2[8], 89.63136) - expect_equal(etr_2[9], 92.57472) - expect_equal(etr_2[10], 96.6) - expect_equal(etr_2[11], 101.39136) - expect_equal(etr_2[12], 91.1904) - expect_equal(etr_2[13], 90.72) + expect_equal(etr_2[2], 14.48160) + expect_equal(etr_2[3], 19.83744) + expect_equal(etr_2[4], 33.45888) + expect_equal(etr_2[5], 50.07744) + expect_equal(etr_2[6], 71.06400) + expect_equal(etr_2[7], 91.67424) + expect_equal(etr_2[8], 112.99680) + expect_equal(etr_2[9], 120.23424) + expect_equal(etr_2[10], 122.64000) + expect_equal(etr_2[11], 110.20800) + expect_equal(etr_2[12], 129.83040) + expect_equal(etr_2[13], 133.05600) }) diff --git a/texport_junior_pam.png b/texport_junior_pam.png new file mode 100644 index 0000000000000000000000000000000000000000..28ffa71140da507f6820eb6217cc9043b7d03e5e GIT binary patch literal 42974 zcmd42cRZVK|2`bmRwthhwdp{WqH5LFYPGi7Gqh?%gldf1S}iR_Yj28ByLOGBRZ=Ul zW2=$`5i25go-2Ca_v`+Cf4}FS=dZ_$SLDi-^E$6{9Pi^e-tX(ZzV5@br#Mf6K%lc4 zkM0|QK#Xx9(2=ea$AKfE$vsoR3j^HX;XP0(ntK6wbJX#!&Rr0wJo@zBlVia9lg}TS z!$F`+0`xxy4FmpF5GWt6asRH-OYqWuP?Du%0D;!5c(i}!VK%#4knQsekr!4_-=!XN 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 literal 0 HcmV?d00001 From 159883df93b2accfe3d2d962b756cb67f736ad39 Mon Sep 17 00:00:00 2001 From: JulienBoehm <180776296+JulienBoehm@users.noreply.github.com> Date: Wed, 22 Apr 2026 14:22:34 +0200 Subject: [PATCH 26/32] updated test data set for read_pam_2500_data --- src/R/read_pam_data.R | 4 +- .../extdata/pam_2500_data/20260311_1(2).CSV | 18 -- .../pam_2500_data/20260422_pam_2500.CSV | 18 ++ src/man/read_pam_2500_data.Rd | 2 +- .../testthat/data/20260311_1(2)_pam_2500.CSV | 18 -- src/tests/testthat/data/20260422_pam_2500.CSV | 18 ++ src/tests/testthat/test-read_pam_2500_data.R | 216 ++++++++---------- 7 files changed, 132 insertions(+), 162 deletions(-) delete mode 100644 src/inst/extdata/pam_2500_data/20260311_1(2).CSV create mode 100644 src/inst/extdata/pam_2500_data/20260422_pam_2500.CSV delete mode 100644 src/tests/testthat/data/20260311_1(2)_pam_2500.CSV create mode 100644 src/tests/testthat/data/20260422_pam_2500.CSV diff --git a/src/R/read_pam_data.R b/src/R/read_pam_data.R index 189b901..f284218 100644 --- a/src/R/read_pam_data.R +++ b/src/R/read_pam_data.R @@ -636,7 +636,7 @@ read_junior_pam_data <- function( #' Available at: \url{https://www.walz.com/files/downloads/dualpamed05.pdf} #' } #' @examples -#' path <- file.path(system.file("extdata/pam_2500_data", package = "pam"), "20260311_1(2).CSV") +#' path <- file.path(system.file("extdata/pam_2500_data", package = "pam"), "20260422_pam_2500.CSV") #' data <- read_pam_2500_data(path) #' @export read_pam_2500_data <- function( @@ -701,7 +701,7 @@ read_pam_2500_data <- function( last_par <- current_par } - + print(result) return(result) }, warning = function(w) { diff --git a/src/inst/extdata/pam_2500_data/20260311_1(2).CSV b/src/inst/extdata/pam_2500_data/20260311_1(2).CSV deleted file mode 100644 index 6868c88..0000000 --- a/src/inst/extdata/pam_2500_data/20260311_1(2).CSV +++ /dev/null @@ -1,18 +0,0 @@ - -"t";"Date";"Time";"No.";"ML";"Temp.";"PAR";"F";"Fo'";"Fm'";"~Fo'";"Y(II)";"Y(NPQ)";"Y(NO)";"NPQ";"qN";"qP";"qL";"ETR";"Y4S";""; - 2;11.03.26;14:16:47;Type: LC - 4;11.03.26;14:16:48;default_60.par - 2;11.03.26;14:16:47;;1; 0.0;0;0.166;Fo: 0.166;Fm: 0.744 - 2;11.03.26;14:16:47;1;1; 0.0;0; 0.166; 0.000; 0.744; 0.166;0.777;0.000;0.223;0.000;0.000;1.000;1.000; 0.0;0.777 - 12;11.03.26;14:16:57;2;1; 0.0;5; 0.208; 0.194; 0.708; 0.164;0.706;0.014;0.280;0.051;0.111;0.973;0.907; 1.5;0.706 - 42;11.03.26;14:17:27;3;1; 0.0;9; 0.238; 0.184; 0.474; 0.147;0.498;0.182;0.320;0.570;0.498;0.814;0.629; 1.9;0.498 - 72;11.03.26;14:17:57;4;1; 0.0;34; 0.246; 0.180; 0.423; 0.142;0.418;0.251;0.331;0.759;0.580;0.728;0.533; 6.0;0.418 - 102;11.03.26;14:18:27;5;1; 0.0;67; 0.259; 0.174; 0.412; 0.141;0.371;0.281;0.348;0.806;0.588;0.643;0.432; 10.5;0.371 - 132;11.03.26;14:18:57;6;1; 0.0;104; 0.270; 0.168; 0.397; 0.139;0.320;0.317;0.363;0.874;0.604;0.555;0.345; 14.0;0.320 - 162;11.03.26;14:19:27;7;1; 0.0;144; 0.277; 0.177; 0.383; 0.137;0.277;0.351;0.372;0.943;0.644;0.515;0.329; 16.7;0.277 - 192;11.03.26;14:19:57;8;1; 0.0;201; 0.285; 0.172; 0.371; 0.136;0.232;0.385;0.383;1.005;0.656;0.432;0.261; 19.6;0.232 - 222;11.03.26;14:20:27;9;1; 0.0;274; 0.294; 0.169; 0.361; 0.134;0.186;0.419;0.395;1.061;0.668;0.349;0.201; 21.4;0.186 - 252;11.03.26;14:20:57;10;1; 0.0;366; 0.299; 0.171; 0.351; 0.133;0.148;0.450;0.402;1.120;0.689;0.289;0.165; 22.8;0.148 - 282;11.03.26;14:21:27;11;1; 0.0;477; 0.303; 0.170; 0.344; 0.132;0.119;0.474;0.407;1.163;0.699;0.236;0.132; 23.9;0.119 - 312;11.03.26;14:21:57;12;1; 0.0;622; 0.304; 0.169; 0.337; 0.131;0.098;0.493;0.409;1.208;0.709;0.196;0.109; 25.6;0.098 - 329;11.03.26;14:22:14;File: L_260311_141645.PWS diff --git a/src/inst/extdata/pam_2500_data/20260422_pam_2500.CSV b/src/inst/extdata/pam_2500_data/20260422_pam_2500.CSV new file mode 100644 index 0000000..663240e --- /dev/null +++ b/src/inst/extdata/pam_2500_data/20260422_pam_2500.CSV @@ -0,0 +1,18 @@ + +"t";"Date";"Time";"No.";"ML";"Temp.";"PAR";"F";"Fo'";"Fm'";"~Fo'";"Y(II)";"Y(NPQ)";"Y(NO)";"NPQ";"qN";"qP";"qL";"ETR";""; + 12;22.04.26;11:20:13;Type: LC + 14;22.04.26;11:20:14;default_60.par + 12;22.04.26;11:20:13;;2; 0.0;0;0.389;Fo: 0.389;Fm: 1.960 + 12;22.04.26;11:20:13;1;2; 0.0;0; 0.389; 0.000; 1.960; 0.389;0.802;0.000;0.198;0.000;0.000;1.000;1.000; 0.0 + 42;22.04.26;11:20:43;2;2; 0.0;7; 0.921; 0.000; 1.726; 0.379;0.466;0.064;0.470;0.136;0.142;0.598;0.246; 1.4 + 72;22.04.26;11:21:13;3;2; 0.0;36; 0.783; 0.000; 1.379; 0.359;0.432;0.168;0.399;0.421;0.351;0.584;0.268; 6.5 + 102;22.04.26;11:21:43;4;2; 0.0;106; 0.644; 0.000; 1.082; 0.335;0.405;0.267;0.329;0.811;0.525;0.586;0.305; 18.0 + 132;22.04.26;11:22:13;5;2; 0.0;203; 0.595; 0.000; 0.899; 0.315;0.338;0.358;0.304;1.180;0.628;0.521;0.276; 28.8 + 162;22.04.26;11:22:43;6;2; 0.0;368; 0.584; 0.000; 0.780; 0.299;0.251;0.451;0.298;1.513;0.694;0.408;0.209; 38.8 + 192;22.04.26;11:23:13;7;2; 0.0;624; 0.585; 0.000; 0.712; 0.289;0.178;0.523;0.298;1.753;0.730;0.300;0.148; 46.7 + 222;22.04.26;11:23:43;8;2; 0.0;986; 0.588; 0.000; 0.673; 0.282;0.126;0.574;0.300;1.912;0.751;0.217;0.104; 52.3 + 252;22.04.26;11:24:13;9;2; 0.0;1391; 0.588; 0.000; 0.651; 0.278;0.097;0.603;0.300;2.011;0.763;0.169;0.080; 56.5 + 282;22.04.26;11:24:43;10;2; 0.0;2020; 0.592; 0.000; 0.636; 0.275;0.069;0.629;0.302;2.082;0.770;0.122;0.057; 58.7 + 312;22.04.26;11:25:13;11;2; 0.0;7; 0.449; 0.000; 1.011; 0.328;0.556;0.215;0.229;0.939;0.565;0.823;0.601; 1.6 + 342;22.04.26;11:25:43;12;2; 0.0;69; 0.507; 0.000; 1.065; 0.333;0.524;0.217;0.259;0.840;0.534;0.763;0.502; 15.2 + 355;22.04.26;11:25:55;File: L_260422_112001.PWS diff --git a/src/man/read_pam_2500_data.Rd b/src/man/read_pam_2500_data.Rd index 7199f92..5fdd444 100644 --- a/src/man/read_pam_2500_data.Rd +++ b/src/man/read_pam_2500_data.Rd @@ -43,7 +43,7 @@ Calculates ETR II using: A detailed documentation can be found under \url{https://github.com/biotoolbox/pam?tab=readme-ov-file} } \examples{ -path <- file.path(system.file("extdata/pam_2500_data", package = "pam"), "20260311_1(2).CSV") +path <- file.path(system.file("extdata/pam_2500_data", package = "pam"), "20260422_pam_2500.CSV") data <- read_pam_2500_data(path) } \references{ diff --git a/src/tests/testthat/data/20260311_1(2)_pam_2500.CSV b/src/tests/testthat/data/20260311_1(2)_pam_2500.CSV deleted file mode 100644 index 6868c88..0000000 --- a/src/tests/testthat/data/20260311_1(2)_pam_2500.CSV +++ /dev/null @@ -1,18 +0,0 @@ - -"t";"Date";"Time";"No.";"ML";"Temp.";"PAR";"F";"Fo'";"Fm'";"~Fo'";"Y(II)";"Y(NPQ)";"Y(NO)";"NPQ";"qN";"qP";"qL";"ETR";"Y4S";""; - 2;11.03.26;14:16:47;Type: LC - 4;11.03.26;14:16:48;default_60.par - 2;11.03.26;14:16:47;;1; 0.0;0;0.166;Fo: 0.166;Fm: 0.744 - 2;11.03.26;14:16:47;1;1; 0.0;0; 0.166; 0.000; 0.744; 0.166;0.777;0.000;0.223;0.000;0.000;1.000;1.000; 0.0;0.777 - 12;11.03.26;14:16:57;2;1; 0.0;5; 0.208; 0.194; 0.708; 0.164;0.706;0.014;0.280;0.051;0.111;0.973;0.907; 1.5;0.706 - 42;11.03.26;14:17:27;3;1; 0.0;9; 0.238; 0.184; 0.474; 0.147;0.498;0.182;0.320;0.570;0.498;0.814;0.629; 1.9;0.498 - 72;11.03.26;14:17:57;4;1; 0.0;34; 0.246; 0.180; 0.423; 0.142;0.418;0.251;0.331;0.759;0.580;0.728;0.533; 6.0;0.418 - 102;11.03.26;14:18:27;5;1; 0.0;67; 0.259; 0.174; 0.412; 0.141;0.371;0.281;0.348;0.806;0.588;0.643;0.432; 10.5;0.371 - 132;11.03.26;14:18:57;6;1; 0.0;104; 0.270; 0.168; 0.397; 0.139;0.320;0.317;0.363;0.874;0.604;0.555;0.345; 14.0;0.320 - 162;11.03.26;14:19:27;7;1; 0.0;144; 0.277; 0.177; 0.383; 0.137;0.277;0.351;0.372;0.943;0.644;0.515;0.329; 16.7;0.277 - 192;11.03.26;14:19:57;8;1; 0.0;201; 0.285; 0.172; 0.371; 0.136;0.232;0.385;0.383;1.005;0.656;0.432;0.261; 19.6;0.232 - 222;11.03.26;14:20:27;9;1; 0.0;274; 0.294; 0.169; 0.361; 0.134;0.186;0.419;0.395;1.061;0.668;0.349;0.201; 21.4;0.186 - 252;11.03.26;14:20:57;10;1; 0.0;366; 0.299; 0.171; 0.351; 0.133;0.148;0.450;0.402;1.120;0.689;0.289;0.165; 22.8;0.148 - 282;11.03.26;14:21:27;11;1; 0.0;477; 0.303; 0.170; 0.344; 0.132;0.119;0.474;0.407;1.163;0.699;0.236;0.132; 23.9;0.119 - 312;11.03.26;14:21:57;12;1; 0.0;622; 0.304; 0.169; 0.337; 0.131;0.098;0.493;0.409;1.208;0.709;0.196;0.109; 25.6;0.098 - 329;11.03.26;14:22:14;File: L_260311_141645.PWS diff --git a/src/tests/testthat/data/20260422_pam_2500.CSV b/src/tests/testthat/data/20260422_pam_2500.CSV new file mode 100644 index 0000000..663240e --- /dev/null +++ b/src/tests/testthat/data/20260422_pam_2500.CSV @@ -0,0 +1,18 @@ + +"t";"Date";"Time";"No.";"ML";"Temp.";"PAR";"F";"Fo'";"Fm'";"~Fo'";"Y(II)";"Y(NPQ)";"Y(NO)";"NPQ";"qN";"qP";"qL";"ETR";""; + 12;22.04.26;11:20:13;Type: LC + 14;22.04.26;11:20:14;default_60.par + 12;22.04.26;11:20:13;;2; 0.0;0;0.389;Fo: 0.389;Fm: 1.960 + 12;22.04.26;11:20:13;1;2; 0.0;0; 0.389; 0.000; 1.960; 0.389;0.802;0.000;0.198;0.000;0.000;1.000;1.000; 0.0 + 42;22.04.26;11:20:43;2;2; 0.0;7; 0.921; 0.000; 1.726; 0.379;0.466;0.064;0.470;0.136;0.142;0.598;0.246; 1.4 + 72;22.04.26;11:21:13;3;2; 0.0;36; 0.783; 0.000; 1.379; 0.359;0.432;0.168;0.399;0.421;0.351;0.584;0.268; 6.5 + 102;22.04.26;11:21:43;4;2; 0.0;106; 0.644; 0.000; 1.082; 0.335;0.405;0.267;0.329;0.811;0.525;0.586;0.305; 18.0 + 132;22.04.26;11:22:13;5;2; 0.0;203; 0.595; 0.000; 0.899; 0.315;0.338;0.358;0.304;1.180;0.628;0.521;0.276; 28.8 + 162;22.04.26;11:22:43;6;2; 0.0;368; 0.584; 0.000; 0.780; 0.299;0.251;0.451;0.298;1.513;0.694;0.408;0.209; 38.8 + 192;22.04.26;11:23:13;7;2; 0.0;624; 0.585; 0.000; 0.712; 0.289;0.178;0.523;0.298;1.753;0.730;0.300;0.148; 46.7 + 222;22.04.26;11:23:43;8;2; 0.0;986; 0.588; 0.000; 0.673; 0.282;0.126;0.574;0.300;1.912;0.751;0.217;0.104; 52.3 + 252;22.04.26;11:24:13;9;2; 0.0;1391; 0.588; 0.000; 0.651; 0.278;0.097;0.603;0.300;2.011;0.763;0.169;0.080; 56.5 + 282;22.04.26;11:24:43;10;2; 0.0;2020; 0.592; 0.000; 0.636; 0.275;0.069;0.629;0.302;2.082;0.770;0.122;0.057; 58.7 + 312;22.04.26;11:25:13;11;2; 0.0;7; 0.449; 0.000; 1.011; 0.328;0.556;0.215;0.229;0.939;0.565;0.823;0.601; 1.6 + 342;22.04.26;11:25:43;12;2; 0.0;69; 0.507; 0.000; 1.065; 0.333;0.524;0.217;0.259;0.840;0.534;0.763;0.502; 15.2 + 355;22.04.26;11:25:55;File: L_260422_112001.PWS diff --git a/src/tests/testthat/test-read_pam_2500_data.R b/src/tests/testthat/test-read_pam_2500_data.R index 97c31c8..d288fb4 100644 --- a/src/tests/testthat/test-read_pam_2500_data.R +++ b/src/tests/testthat/test-read_pam_2500_data.R @@ -1,20 +1,18 @@ -test_that("read_pam_2500_data 20260311_1(2)_pam_2500.CSV - default", { - test_data_file <- testthat::test_path("data", "20260311_1(2)_pam_2500.CSV") +test_that("read_pam_2500_data 20260422_pam_2500.CSV - default", { + test_data_file <- testthat::test_path("data", "20260422_pam_2500.CSV") data <- read_pam_2500_data(test_data_file) par <- data$par expect_equal(par[1], 0) - expect_equal(par[2], 5) - expect_equal(par[3], 9) - expect_equal(par[4], 34) - expect_equal(par[5], 67) - expect_equal(par[6], 104) - expect_equal(par[7], 144) - expect_equal(par[8], 201) - expect_equal(par[9], 274) - expect_equal(par[10], 366) - expect_equal(par[11], 477) - expect_equal(par[12], 622) + expect_equal(par[2], 7) + expect_equal(par[3], 36) + expect_equal(par[4], 106) + expect_equal(par[5], 203) + expect_equal(par[6], 368) + expect_equal(par[7], 624) + expect_equal(par[8], 986) + expect_equal(par[9], 1391) + expect_equal(par[10], 2020) yield_1 <- data$yield_1 expect_equal(yield_1[1], NA_real_) @@ -27,22 +25,18 @@ test_that("read_pam_2500_data 20260311_1(2)_pam_2500.CSV - default", { expect_equal(yield_1[8], NA_real_) expect_equal(yield_1[9], NA_real_) expect_equal(yield_1[10], NA_real_) - expect_equal(yield_1[11], NA_real_) - expect_equal(yield_1[12], NA_real_) yield_2 <- data$yield_2 - expect_equal(yield_2[1], 0.777) - expect_equal(yield_2[2], 0.706) - expect_equal(yield_2[3], 0.498) - expect_equal(yield_2[4], 0.418) - expect_equal(yield_2[5], 0.371) - expect_equal(yield_2[6], 0.320) - expect_equal(yield_2[7], 0.277) - expect_equal(yield_2[8], 0.232) - expect_equal(yield_2[9], 0.186) - expect_equal(yield_2[10], 0.148) - expect_equal(yield_2[11], 0.119) - expect_equal(yield_2[12], 0.098) + expect_equal(yield_2[1], 0.802) + expect_equal(yield_2[2], 0.466) + expect_equal(yield_2[3], 0.432) + expect_equal(yield_2[4], 0.405) + expect_equal(yield_2[5], 0.338) + expect_equal(yield_2[6], 0.251) + expect_equal(yield_2[7], 0.178) + expect_equal(yield_2[8], 0.126) + expect_equal(yield_2[9], 0.097) + expect_equal(yield_2[10], 0.069) etr_1 <- data$etr_1 expect_equal(etr_1[1], NA_real_) @@ -55,41 +49,35 @@ test_that("read_pam_2500_data 20260311_1(2)_pam_2500.CSV - default", { expect_equal(etr_1[8], NA_real_) expect_equal(etr_1[9], NA_real_) expect_equal(etr_1[10], NA_real_) - expect_equal(etr_1[11], NA_real_) - expect_equal(etr_1[12], NA_real_) etr_2 <- data$etr_2 expect_equal(etr_2[1], 0) - expect_equal(etr_2[2], 1.48260) - expect_equal(etr_2[3], 1.88244) - expect_equal(etr_2[4], 5.969040) - expect_equal(etr_2[5], 10.439940) - expect_equal(etr_2[6], 13.97760) - expect_equal(etr_2[7], 16.752960) - expect_equal(etr_2[8], 19.58544) - expect_equal(etr_2[9], 21.404880) - expect_equal(etr_2[10], 22.75056) - expect_equal(etr_2[11], 23.84046) - expect_equal(etr_2[12], 25.601520) + expect_equal(etr_2[2], 1.37004) + expect_equal(etr_2[3], 6.53184) + expect_equal(etr_2[4], 18.03060) + expect_equal(etr_2[5], 28.81788) + expect_equal(etr_2[6], 38.79456) + expect_equal(etr_2[7], 46.65024) + expect_equal(etr_2[8], 52.17912) + expect_equal(etr_2[9], 56.66934) + expect_equal(etr_2[10], 58.53960) }) -test_that("read_pam_2500_data 20260311_1(2)_pam_2500.CSV - etr-factor 0.5", { - test_data_file <- testthat::test_path("data", "20260311_1(2)_pam_2500.CSV") +test_that("read_pam_2500_data 20260422_pam_2500.CSV - etr-factor 0.5", { + test_data_file <- testthat::test_path("data", "20260422_pam_2500.CSV") data <- read_pam_2500_data(test_data_file, etr_factor = 0.5) par <- data$par - expect_equal(par[1], 0) - expect_equal(par[2], 5) - expect_equal(par[3], 9) - expect_equal(par[4], 34) - expect_equal(par[5], 67) - expect_equal(par[6], 104) - expect_equal(par[7], 144) - expect_equal(par[8], 201) - expect_equal(par[9], 274) - expect_equal(par[10], 366) - expect_equal(par[11], 477) - expect_equal(par[12], 622) + expect_equal(par[1], 0) + expect_equal(par[2], 7) + expect_equal(par[3], 36) + expect_equal(par[4], 106) + expect_equal(par[5], 203) + expect_equal(par[6], 368) + expect_equal(par[7], 624) + expect_equal(par[8], 986) + expect_equal(par[9], 1391) + expect_equal(par[10], 2020) yield_1 <- data$yield_1 expect_equal(yield_1[1], NA_real_) @@ -102,22 +90,18 @@ test_that("read_pam_2500_data 20260311_1(2)_pam_2500.CSV - etr-factor 0.5", { expect_equal(yield_1[8], NA_real_) expect_equal(yield_1[9], NA_real_) expect_equal(yield_1[10], NA_real_) - expect_equal(yield_1[11], NA_real_) - expect_equal(yield_1[12], NA_real_) yield_2 <- data$yield_2 - expect_equal(yield_2[1], 0.777) - expect_equal(yield_2[2], 0.706) - expect_equal(yield_2[3], 0.498) - expect_equal(yield_2[4], 0.418) - expect_equal(yield_2[5], 0.371) - expect_equal(yield_2[6], 0.320) - expect_equal(yield_2[7], 0.277) - expect_equal(yield_2[8], 0.232) - expect_equal(yield_2[9], 0.186) - expect_equal(yield_2[10], 0.148) - expect_equal(yield_2[11], 0.119) - expect_equal(yield_2[12], 0.098) + expect_equal(yield_2[1], 0.802) + expect_equal(yield_2[2], 0.466) + expect_equal(yield_2[3], 0.432) + expect_equal(yield_2[4], 0.405) + expect_equal(yield_2[5], 0.338) + expect_equal(yield_2[6], 0.251) + expect_equal(yield_2[7], 0.178) + expect_equal(yield_2[8], 0.126) + expect_equal(yield_2[9], 0.097) + expect_equal(yield_2[10], 0.069) etr_1 <- data$etr_1 expect_equal(etr_1[1], NA_real_) @@ -130,46 +114,40 @@ test_that("read_pam_2500_data 20260311_1(2)_pam_2500.CSV - etr-factor 0.5", { expect_equal(etr_1[8], NA_real_) expect_equal(etr_1[9], NA_real_) expect_equal(etr_1[10], NA_real_) - expect_equal(etr_1[11], NA_real_) - expect_equal(etr_1[12], NA_real_) etr_2 <- data$etr_2 expect_equal(etr_2[1], 0) - expect_equal(etr_2[2], 0.8825) - expect_equal(etr_2[3], 1.12050) - expect_equal(etr_2[4], 3.553) - expect_equal(etr_2[5], 6.21425) - expect_equal(etr_2[6], 8.320) - expect_equal(etr_2[7], 9.972) - expect_equal(etr_2[8], 11.658) - expect_equal(etr_2[9], 12.741) - expect_equal(etr_2[10], 13.542) - expect_equal(etr_2[11], 14.190750) - expect_equal(etr_2[12], 15.239) + expect_equal(etr_2[2], 0.81550) + expect_equal(etr_2[3], 3.88800) + expect_equal(etr_2[4], 10.73250) + expect_equal(etr_2[5], 17.15350) + expect_equal(etr_2[6], 23.09200) + expect_equal(etr_2[7], 27.76800) + expect_equal(etr_2[8], 31.05900) + expect_equal(etr_2[9], 33.73175) + expect_equal(etr_2[10], 34.84500) }) -test_that("read_pam_2500_data 20260311_1(2)_pam_2500.CSV - - fraction_photosystem_I = 0.2, fraction_photosystem_II = 0.8", { - test_data_file <- testthat::test_path("data", "20260311_1(2)_pam_2500.CSV") +test_that("read_pam_2500_data 20260422_pam_2500.CSV - fraction_photosystem_I = 0.2, fraction_photosystem_II = 0.8", { + test_data_file <- testthat::test_path("data", "20260422_pam_2500.CSV") expect_error(read_pam_2500_data(test_data_file, fraction_photosystem_I = 0.9, fraction_photosystem_II = 0.2)) }) -test_that("read_pam_2500_data 20260311_1(2)_pam_2500.CSV - fraction_photosystem_I = 0.2, fraction_photosystem_II = 0.8", { - test_data_file <- testthat::test_path("data", "20260311_1(2)_pam_2500.CSV") +test_that("read_pam_2500_data 20260422_pam_2500.CSV - fraction_photosystem_I = 0.2, fraction_photosystem_II = 0.8", { + test_data_file <- testthat::test_path("data", "20260422_pam_2500.CSV") data <- read_pam_2500_data(test_data_file, fraction_photosystem_I = 0.2, fraction_photosystem_II = 0.8) par <- data$par expect_equal(par[1], 0) - expect_equal(par[2], 5) - expect_equal(par[3], 9) - expect_equal(par[4], 34) - expect_equal(par[5], 67) - expect_equal(par[6], 104) - expect_equal(par[7], 144) - expect_equal(par[8], 201) - expect_equal(par[9], 274) - expect_equal(par[10], 366) - expect_equal(par[11], 477) - expect_equal(par[12], 622) + expect_equal(par[2], 7) + expect_equal(par[3], 36) + expect_equal(par[4], 106) + expect_equal(par[5], 203) + expect_equal(par[6], 368) + expect_equal(par[7], 624) + expect_equal(par[8], 986) + expect_equal(par[9], 1391) + expect_equal(par[10], 2020) yield_1 <- data$yield_1 expect_equal(yield_1[1], NA_real_) @@ -182,22 +160,18 @@ test_that("read_pam_2500_data 20260311_1(2)_pam_2500.CSV - fraction_photosystem_ expect_equal(yield_1[8], NA_real_) expect_equal(yield_1[9], NA_real_) expect_equal(yield_1[10], NA_real_) - expect_equal(yield_1[11], NA_real_) - expect_equal(yield_1[12], NA_real_) yield_2 <- data$yield_2 - expect_equal(yield_2[1], 0.777) - expect_equal(yield_2[2], 0.706) - expect_equal(yield_2[3], 0.498) - expect_equal(yield_2[4], 0.418) - expect_equal(yield_2[5], 0.371) - expect_equal(yield_2[6], 0.320) - expect_equal(yield_2[7], 0.277) - expect_equal(yield_2[8], 0.232) - expect_equal(yield_2[9], 0.186) - expect_equal(yield_2[10], 0.148) - expect_equal(yield_2[11], 0.119) - expect_equal(yield_2[12], 0.098) + expect_equal(yield_2[1], 0.802) + expect_equal(yield_2[2], 0.466) + expect_equal(yield_2[3], 0.432) + expect_equal(yield_2[4], 0.405) + expect_equal(yield_2[5], 0.338) + expect_equal(yield_2[6], 0.251) + expect_equal(yield_2[7], 0.178) + expect_equal(yield_2[8], 0.126) + expect_equal(yield_2[9], 0.097) + expect_equal(yield_2[10], 0.069) etr_1 <- data$etr_1 expect_equal(etr_1[1], NA_real_) @@ -210,20 +184,16 @@ test_that("read_pam_2500_data 20260311_1(2)_pam_2500.CSV - fraction_photosystem_ expect_equal(etr_1[8], NA_real_) expect_equal(etr_1[9], NA_real_) expect_equal(etr_1[10], NA_real_) - expect_equal(etr_1[11], NA_real_) - expect_equal(etr_1[12], NA_real_) etr_2 <- data$etr_2 expect_equal(etr_2[1], 0) - expect_equal(etr_2[2], 2.37216) - expect_equal(etr_2[3], 3.011904) - expect_equal(etr_2[4], 9.5504640) - expect_equal(etr_2[5], 16.7039040) - expect_equal(etr_2[6], 22.36416) - expect_equal(etr_2[7], 26.804736) - expect_equal(etr_2[8], 31.3367040) - expect_equal(etr_2[9], 34.2478080) - expect_equal(etr_2[10], 36.4008960) - expect_equal(etr_2[11], 38.1447360) - expect_equal(etr_2[12], 40.9624320) + expect_equal(etr_2[2], 2.192064) + expect_equal(etr_2[3], 10.450944) + expect_equal(etr_2[4], 28.848960) + expect_equal(etr_2[5], 46.108608) + expect_equal(etr_2[6], 62.071296) + expect_equal(etr_2[7], 74.640384) + expect_equal(etr_2[8], 83.486592) + expect_equal(etr_2[9], 90.670944) + expect_equal(etr_2[10], 93.663360) }) From 239c563f340d625d00c797ac6fb48dc91501c45c Mon Sep 17 00:00:00 2001 From: Phi-S <926151+Phi-S@users.noreply.github.com> Date: Thu, 23 Apr 2026 10:26:32 +0200 Subject: [PATCH 27/32] mprove column validation in junior PAM data functions --- src/R/read_pam_data.R | 71 +++++++++++++++++++++---------------------- src/R/validation.R | 12 ++++++-- 2 files changed, 43 insertions(+), 40 deletions(-) diff --git a/src/R/read_pam_data.R b/src/R/read_pam_data.R index f284218..139288b 100644 --- a/src/R/read_pam_data.R +++ b/src/R/read_pam_data.R @@ -111,11 +111,12 @@ read_universal_data <- function(csv_path, #' data <- read_dual_pam_data(path) #' @export read_dual_pam_data <- function( - csv_path, - remove_recovery = TRUE, - etr_factor = 0.84, - fraction_photosystem_I = 0.5, - fraction_photosystem_II = 0.5) { + csv_path, + remove_recovery = TRUE, + etr_factor = 0.84, + fraction_photosystem_I = 0.5, + fraction_photosystem_II = 0.5 +) { if (fraction_photosystem_I + fraction_photosystem_II != 1) { stop("The sum of fraction_photosystem_I and fraction_photosystem_II must be equal 1.") } @@ -248,11 +249,12 @@ read_dual_pam_data <- function( #' data <- read_dual_pam_single_channel_p700_data(path) #' @export read_dual_pam_single_channel_p700_data <- function( - csv_path, - remove_recovery = TRUE, - etr_factor = 0.84, - fraction_photosystem_I = 0.5, - fraction_photosystem_II = 0.5) { + csv_path, + remove_recovery = TRUE, + etr_factor = 0.84, + fraction_photosystem_I = 0.5, + fraction_photosystem_II = 0.5 +) { if (fraction_photosystem_I + fraction_photosystem_II != 1) { stop("The sum of fraction_photosystem_I and fraction_photosystem_II must be equal 1.") } @@ -378,11 +380,12 @@ read_dual_pam_single_channel_p700_data <- function( #' data <- read_dual_pam_single_channel_fluo_data(path) #' @export read_dual_pam_single_channel_fluo_data <- function( - csv_path, - remove_recovery = TRUE, - etr_factor = 0.84, - fraction_photosystem_I = 0.5, - fraction_photosystem_II = 0.5) { + csv_path, + remove_recovery = TRUE, + etr_factor = 0.84, + fraction_photosystem_I = 0.5, + fraction_photosystem_II = 0.5 +) { if (fraction_photosystem_I + fraction_photosystem_II != 1) { stop("The sum of fraction_photosystem_I and fraction_photosystem_II must be equal 1.") } @@ -534,11 +537,12 @@ calc_etr <- function(yield, par, etr_factor, p_ratio) { #' data <- read_junior_pam_data(path) #' @export read_junior_pam_data <- function( - csv_path, - remove_recovery = TRUE, - etr_factor = 0.84, - fraction_photosystem_I = 0.5, - fraction_photosystem_II = 0.5) { + csv_path, + remove_recovery = TRUE, + etr_factor = 0.84, + fraction_photosystem_I = 0.5, + fraction_photosystem_II = 0.5 +) { if (fraction_photosystem_I + fraction_photosystem_II != 1) { stop("The sum of fraction_photosystem_I and fraction_photosystem_II must be equal 1.") } @@ -550,15 +554,8 @@ read_junior_pam_data <- function( validate_junior_pam_data(data) - par_col <- grep("PAR", names(data), value = TRUE) - if (length(par_col) == 1 && par_col != "PAR") { - data.table::setnames(data, old = par_col, new = "PAR") - } - - yield_2_col <- grep("Y..II.", names(data), value = TRUE) - if (length(yield_2_col) == 1 && yield_2_col != "Y..II.") { - data.table::setnames(data, old = yield_2_col, new = "Y.II.") - } + par_col <- grep("^.+\\.PAR$", names(data), value = TRUE)[1] + yield_2_col <- grep("^.+\\.Y\\.\\.II\\.$", names(data), value = TRUE)[1] data <- data[data$Type == "FO" | data$Type == "F", ] data <- data[order(data$"Time..rel.ms."), ] @@ -573,13 +570,13 @@ read_junior_pam_data <- function( last_par <- as.numeric(0) for (i in seq_len(nrow(data))) { row <- data[i, ] - current_par <- row$PAR + current_par <- row[[par_col]] if (remove_recovery && last_par != 0 && current_par < last_par) { break } - yield_2 <- row$Y.II. + yield_2 <- row[[yield_2_col]] recalc_etr_2 <- calc_etr(yield_2, current_par, etr_factor, fraction_photosystem_II) new_row <- list( @@ -640,11 +637,12 @@ read_junior_pam_data <- function( #' data <- read_pam_2500_data(path) #' @export read_pam_2500_data <- function( - csv_path, - remove_recovery = TRUE, - etr_factor = 0.84, - fraction_photosystem_I = 0.5, - fraction_photosystem_II = 0.5) { + csv_path, + remove_recovery = TRUE, + etr_factor = 0.84, + fraction_photosystem_I = 0.5, + fraction_photosystem_II = 0.5 +) { if (fraction_photosystem_I + fraction_photosystem_II != 1) { stop("The sum of fraction_photosystem_I and fraction_photosystem_II must be equal 1.") } @@ -701,7 +699,6 @@ read_pam_2500_data <- function( last_par <- current_par } - print(result) return(result) }, warning = function(w) { diff --git a/src/R/validation.R b/src/R/validation.R index 69d5d40..8fdce1a 100644 --- a/src/R/validation.R +++ b/src/R/validation.R @@ -209,12 +209,18 @@ validate_junior_pam_data <- function(data) { stop("no cols in data") } - if (!any(grepl("PAR", colnames(data)))) { + par_cols <- grep("^.+\\.PAR$", names(data), value = TRUE) + if (length(par_cols) == 0) { stop("required col 'PAR' not found") + } else if (length(par_cols) > 1) { + stop(paste(length(par_cols), " 'PAR' cols found. Only supporting one 'PAR' column")) } - if (!any(grepl("Y..II.", colnames(data)))) { - stop("required col 'Y..II.' not found") + yield_cols <- grep("^.+\\.Y\\.\\.II\\.$", names(data), value = TRUE) + if (length(yield_cols) == 0) { + stop("required col 'Y (II)' not found") + } else if (length(yield_cols) > 1) { + stop(paste(length(yield_cols), " 'Y (II)' cols found. Only supporting one 'Y (II)' column")) } if (!"Time..rel.ms." %in% colnames(data)) { From aab70e2f7718defdaed9378e10ca631fadf5a220 Mon Sep 17 00:00:00 2001 From: Phi-S <926151+Phi-S@users.noreply.github.com> Date: Thu, 23 Apr 2026 10:32:19 +0200 Subject: [PATCH 28/32] updated folder structure for test data and images used in the README --- README.md | 8 ++++---- examples/Example_compare_models.R | 2 +- examples/Example_multiple_data.R | 2 +- texport_junior_pam.png => img/export_junior_pam.png | Bin ...eeters_etr_II_modified_control_plot_20240925.jpg | Bin .../test_combo_plot_control_etr_II.jpg | Bin .../data/{ => dual_pam_data}/20231122_01.csv | 0 .../testthat/data/{ => dual_pam_data}/20240925.csv | 0 .../data/{ => dual_pam_data}/bulk/20231123_02.csv | 0 .../data/{ => dual_pam_data}/bulk/20231123_03.csv | 0 .../data/{ => dual_pam_data}/bulk/20231123_04.csv | 0 .../data/{ => dual_pam_data}/bulk/20231123_05.csv | 0 .../data/{ => dual_pam_data}/bulk/20231123_06.csv | 0 .../data/{ => dual_pam_data}/bulk/20231123_07.csv | 0 .../data/{ => dual_pam_data}/bulk/20231214.csv | 0 .../data/{ => dual_pam_data}/bulk/20231214_08.csv | 0 .../data/{ => dual_pam_data}/bulk/20231214_09.csv | 0 .../data/{ => dual_pam_data}/bulk/20231214_10.csv | 0 .../data/{ => dual_pam_data}/bulk/20231214_11.csv | 0 .../data/{ => dual_pam_data}/bulk/20231214_12.csv | 0 .../data/{ => dual_pam_data}/bulk/20231214_13.csv | 0 .../data/{ => dual_pam_data}/bulk/20231214_14.csv | 0 .../data/{ => dual_pam_data}/bulk/20231214_15.csv | 0 .../data/{ => dual_pam_data}/bulk/20231214_16.csv | 0 .../data/{ => dual_pam_data}/bulk/20231214_17.csv | 0 .../data/{ => dual_pam_data}/bulk/20231214_18.csv | 0 .../data/{ => dual_pam_data}/bulk/20231214_19.csv | 0 .../20260130_efeutute_dual_pam_only_fluo.csv | 0 .../20260130_01_efeutute_dual_pam_only_p700.csv | 0 .../{ => junior_pam_data}/2026_04_22_junior_pam.csv | 0 .../data/{ => pam_2500_data}/20260422_pam_2500.CSV | 0 .../data/{ => universal_data}/universal_data.csv | 0 src/tests/testthat/test-combo_plot_control_etr_I.R | 2 +- src/tests/testthat/test-combo_plot_control_etr_II.R | 2 +- .../testthat/test-compare_regression_models_etr_I.R | 4 ++-- .../test-compare_regression_models_etr_II.R | 4 ++-- .../testthat/test-compare_regression_models_total.R | 4 ++-- src/tests/testthat/test-eilers_peeters_etr_I.R | 12 ++++++------ src/tests/testthat/test-eilers_peeters_etr_II.R | 10 +++++----- .../testthat/test-get_etr_data_for_par_values.R | 2 +- src/tests/testthat/test-platt_etr_I.R | 10 +++++----- src/tests/testthat/test-platt_etr_II.R | 12 ++++++------ src/tests/testthat/test-read_dual_pam_data.R | 12 ++++++------ .../test-read_dual_pam_single_channel_fluo_data.R | 8 ++++---- .../test-read_dual_pam_single_channel_p700_data.R | 8 ++++---- src/tests/testthat/test-read_junior_pam_data.R | 8 ++++---- src/tests/testthat/test-read_pam_2500_data.R | 8 ++++---- src/tests/testthat/test-read_universal_data.R | 8 ++++---- .../test-relative_root_mean_squared_error.R | 4 ++-- src/tests/testthat/test-root_mean_squared_error.R | 4 ++-- src/tests/testthat/test-universal_data_etr_I.R | 6 +++--- src/tests/testthat/test-vollenweider_etr_I.R | 12 ++++++------ src/tests/testthat/test-vollenweider_etr_II.R | 12 ++++++------ src/tests/testthat/test-walsby_etr_I.R | 12 ++++++------ src/tests/testthat/test-walsby_etr_II.R | 12 ++++++------ src/tests/testthat/test-write_model_result_csv.R | 4 ++-- 56 files changed, 96 insertions(+), 96 deletions(-) rename texport_junior_pam.png => img/export_junior_pam.png (100%) rename test-eilers_peeters_etr_II_modified_control_plot_20240925.jpg => img/test-eilers_peeters_etr_II_modified_control_plot_20240925.jpg (100%) rename test_combo_plot_control_etr_II.jpg => img/test_combo_plot_control_etr_II.jpg (100%) rename src/tests/testthat/data/{ => dual_pam_data}/20231122_01.csv (100%) rename src/tests/testthat/data/{ => dual_pam_data}/20240925.csv (100%) rename src/tests/testthat/data/{ => dual_pam_data}/bulk/20231123_02.csv (100%) rename src/tests/testthat/data/{ => dual_pam_data}/bulk/20231123_03.csv (100%) rename src/tests/testthat/data/{ => dual_pam_data}/bulk/20231123_04.csv (100%) rename src/tests/testthat/data/{ => dual_pam_data}/bulk/20231123_05.csv (100%) rename src/tests/testthat/data/{ => dual_pam_data}/bulk/20231123_06.csv (100%) rename src/tests/testthat/data/{ => dual_pam_data}/bulk/20231123_07.csv (100%) rename src/tests/testthat/data/{ => dual_pam_data}/bulk/20231214.csv (100%) rename src/tests/testthat/data/{ => dual_pam_data}/bulk/20231214_08.csv (100%) rename src/tests/testthat/data/{ => dual_pam_data}/bulk/20231214_09.csv (100%) rename src/tests/testthat/data/{ => dual_pam_data}/bulk/20231214_10.csv (100%) rename src/tests/testthat/data/{ => dual_pam_data}/bulk/20231214_11.csv (100%) rename src/tests/testthat/data/{ => dual_pam_data}/bulk/20231214_12.csv (100%) rename src/tests/testthat/data/{ => dual_pam_data}/bulk/20231214_13.csv (100%) rename src/tests/testthat/data/{ => dual_pam_data}/bulk/20231214_14.csv (100%) rename src/tests/testthat/data/{ => dual_pam_data}/bulk/20231214_15.csv (100%) rename src/tests/testthat/data/{ => dual_pam_data}/bulk/20231214_16.csv (100%) rename src/tests/testthat/data/{ => dual_pam_data}/bulk/20231214_17.csv (100%) rename src/tests/testthat/data/{ => dual_pam_data}/bulk/20231214_18.csv (100%) rename src/tests/testthat/data/{ => dual_pam_data}/bulk/20231214_19.csv (100%) rename src/tests/testthat/data/{ => dual_pam_single_channel_fluo_data}/20260130_efeutute_dual_pam_only_fluo.csv (100%) rename src/tests/testthat/data/{ => dual_pam_single_channel_p700_data}/20260130_01_efeutute_dual_pam_only_p700.csv (100%) rename src/tests/testthat/data/{ => junior_pam_data}/2026_04_22_junior_pam.csv (100%) rename src/tests/testthat/data/{ => pam_2500_data}/20260422_pam_2500.CSV (100%) rename src/tests/testthat/data/{ => universal_data}/universal_data.csv (100%) diff --git a/README.md b/README.md index f15e965..5625986 100644 --- a/README.md +++ b/README.md @@ -297,7 +297,7 @@ The function processes the provided CSV file by: - Stopping at the recovery period if `remove_recovery = TRUE`. To ensure the file is imported correctly, please export the CSV file using the default settings: -![Plot](texport_junior_pam.png) +![Plot](img/export_junior_pam.png) #### Return @@ -966,7 +966,7 @@ plot_control_eilers_peeters_ETR_II <- plot_control( print(plot_control_eilers_peeters_ETR_II) ``` -![Plot](test-eilers_peeters_etr_II_modified_control_plot_20240925.jpg) +![Plot](img/test-eilers_peeters_etr_II_modified_control_plot_20240925.jpg) --- @@ -989,7 +989,7 @@ A plot displaying the original ETR and Yield values and the regression data from #### Examples ```r -test_data_file <- file.path(getwd(), "data", "20240925.csv") +test_data_file <- file.path(getwd(), "data", "dual_pam_data", "20240925.csv") data <- read_dual_pam_data(test_data_file) eilers_peeters <- eilers_peeters_modified(eilers_peeters_generate_regression_ETR_II(data)) @@ -1006,7 +1006,7 @@ test_data_file <- file.path(getwd(), "data", "20240925.csv") ) ``` -![combo Plot](test_combo_plot_control_etr_II.jpg) +![combo Plot](img/test_combo_plot_control_etr_II.jpg) --- diff --git a/examples/Example_compare_models.R b/examples/Example_compare_models.R index e65a9a0..04a6a54 100644 --- a/examples/Example_compare_models.R +++ b/examples/Example_compare_models.R @@ -7,7 +7,7 @@ library("pam") #### read_dual_pam_data()#### # raw data file directory script_dir <- dirname(sys.frame(1)$ofile) -data_dir <- file.path(script_dir, "data", "bulk") +data_dir <- file.path(script_dir, "data", "dual_pam_data", "bulk") #### compare_regression_models_ETR_II#### compare_regression_models_ETR_II_result <- compare_regression_models_ETR_II(data_dir, read_dual_pam_data) diff --git a/examples/Example_multiple_data.R b/examples/Example_multiple_data.R index fc69ef3..e3d8c41 100644 --- a/examples/Example_multiple_data.R +++ b/examples/Example_multiple_data.R @@ -6,7 +6,7 @@ library("pam") #### raw data file directory#### script_dir <- dirname(sys.frame(1)$ofile) -data_dir <- file.path(script_dir, "data", "bulk") +data_dir <- file.path(script_dir, "data", "dual_pam_data", "bulk") output_dir <- file.path(script_dir, "output") dir.create(output_dir, showWarnings = FALSE) output_path_pdf <- file.path(output_dir, "eilers_peters_plot_control.pdf") diff --git a/texport_junior_pam.png b/img/export_junior_pam.png similarity index 100% rename from texport_junior_pam.png rename to img/export_junior_pam.png diff --git a/test-eilers_peeters_etr_II_modified_control_plot_20240925.jpg b/img/test-eilers_peeters_etr_II_modified_control_plot_20240925.jpg similarity index 100% rename from test-eilers_peeters_etr_II_modified_control_plot_20240925.jpg rename to img/test-eilers_peeters_etr_II_modified_control_plot_20240925.jpg diff --git a/test_combo_plot_control_etr_II.jpg b/img/test_combo_plot_control_etr_II.jpg similarity index 100% rename from test_combo_plot_control_etr_II.jpg rename to img/test_combo_plot_control_etr_II.jpg diff --git a/src/tests/testthat/data/20231122_01.csv b/src/tests/testthat/data/dual_pam_data/20231122_01.csv similarity index 100% rename from src/tests/testthat/data/20231122_01.csv rename to src/tests/testthat/data/dual_pam_data/20231122_01.csv diff --git a/src/tests/testthat/data/20240925.csv b/src/tests/testthat/data/dual_pam_data/20240925.csv similarity index 100% rename from src/tests/testthat/data/20240925.csv rename to src/tests/testthat/data/dual_pam_data/20240925.csv diff --git a/src/tests/testthat/data/bulk/20231123_02.csv b/src/tests/testthat/data/dual_pam_data/bulk/20231123_02.csv similarity index 100% rename from src/tests/testthat/data/bulk/20231123_02.csv rename to src/tests/testthat/data/dual_pam_data/bulk/20231123_02.csv diff --git a/src/tests/testthat/data/bulk/20231123_03.csv b/src/tests/testthat/data/dual_pam_data/bulk/20231123_03.csv similarity index 100% rename from src/tests/testthat/data/bulk/20231123_03.csv rename to src/tests/testthat/data/dual_pam_data/bulk/20231123_03.csv diff --git a/src/tests/testthat/data/bulk/20231123_04.csv b/src/tests/testthat/data/dual_pam_data/bulk/20231123_04.csv similarity index 100% rename from src/tests/testthat/data/bulk/20231123_04.csv rename to src/tests/testthat/data/dual_pam_data/bulk/20231123_04.csv diff --git a/src/tests/testthat/data/bulk/20231123_05.csv b/src/tests/testthat/data/dual_pam_data/bulk/20231123_05.csv similarity index 100% rename from src/tests/testthat/data/bulk/20231123_05.csv rename to src/tests/testthat/data/dual_pam_data/bulk/20231123_05.csv diff --git a/src/tests/testthat/data/bulk/20231123_06.csv b/src/tests/testthat/data/dual_pam_data/bulk/20231123_06.csv similarity index 100% rename from src/tests/testthat/data/bulk/20231123_06.csv rename to src/tests/testthat/data/dual_pam_data/bulk/20231123_06.csv diff --git a/src/tests/testthat/data/bulk/20231123_07.csv b/src/tests/testthat/data/dual_pam_data/bulk/20231123_07.csv similarity index 100% rename from src/tests/testthat/data/bulk/20231123_07.csv rename to src/tests/testthat/data/dual_pam_data/bulk/20231123_07.csv diff --git a/src/tests/testthat/data/bulk/20231214.csv b/src/tests/testthat/data/dual_pam_data/bulk/20231214.csv similarity index 100% rename from src/tests/testthat/data/bulk/20231214.csv rename to src/tests/testthat/data/dual_pam_data/bulk/20231214.csv diff --git a/src/tests/testthat/data/bulk/20231214_08.csv b/src/tests/testthat/data/dual_pam_data/bulk/20231214_08.csv similarity index 100% rename from src/tests/testthat/data/bulk/20231214_08.csv rename to src/tests/testthat/data/dual_pam_data/bulk/20231214_08.csv diff --git a/src/tests/testthat/data/bulk/20231214_09.csv b/src/tests/testthat/data/dual_pam_data/bulk/20231214_09.csv similarity index 100% rename from src/tests/testthat/data/bulk/20231214_09.csv rename to src/tests/testthat/data/dual_pam_data/bulk/20231214_09.csv diff --git a/src/tests/testthat/data/bulk/20231214_10.csv b/src/tests/testthat/data/dual_pam_data/bulk/20231214_10.csv similarity index 100% rename from src/tests/testthat/data/bulk/20231214_10.csv rename to src/tests/testthat/data/dual_pam_data/bulk/20231214_10.csv diff --git a/src/tests/testthat/data/bulk/20231214_11.csv b/src/tests/testthat/data/dual_pam_data/bulk/20231214_11.csv similarity index 100% rename from src/tests/testthat/data/bulk/20231214_11.csv rename to src/tests/testthat/data/dual_pam_data/bulk/20231214_11.csv diff --git a/src/tests/testthat/data/bulk/20231214_12.csv b/src/tests/testthat/data/dual_pam_data/bulk/20231214_12.csv similarity index 100% rename from src/tests/testthat/data/bulk/20231214_12.csv rename to src/tests/testthat/data/dual_pam_data/bulk/20231214_12.csv diff --git a/src/tests/testthat/data/bulk/20231214_13.csv b/src/tests/testthat/data/dual_pam_data/bulk/20231214_13.csv similarity index 100% rename from src/tests/testthat/data/bulk/20231214_13.csv rename to src/tests/testthat/data/dual_pam_data/bulk/20231214_13.csv diff --git a/src/tests/testthat/data/bulk/20231214_14.csv b/src/tests/testthat/data/dual_pam_data/bulk/20231214_14.csv similarity index 100% rename from src/tests/testthat/data/bulk/20231214_14.csv rename to src/tests/testthat/data/dual_pam_data/bulk/20231214_14.csv diff --git a/src/tests/testthat/data/bulk/20231214_15.csv b/src/tests/testthat/data/dual_pam_data/bulk/20231214_15.csv similarity index 100% rename from src/tests/testthat/data/bulk/20231214_15.csv rename to src/tests/testthat/data/dual_pam_data/bulk/20231214_15.csv diff --git a/src/tests/testthat/data/bulk/20231214_16.csv b/src/tests/testthat/data/dual_pam_data/bulk/20231214_16.csv similarity index 100% rename from src/tests/testthat/data/bulk/20231214_16.csv rename to src/tests/testthat/data/dual_pam_data/bulk/20231214_16.csv diff --git a/src/tests/testthat/data/bulk/20231214_17.csv b/src/tests/testthat/data/dual_pam_data/bulk/20231214_17.csv similarity index 100% rename from src/tests/testthat/data/bulk/20231214_17.csv rename to src/tests/testthat/data/dual_pam_data/bulk/20231214_17.csv diff --git a/src/tests/testthat/data/bulk/20231214_18.csv b/src/tests/testthat/data/dual_pam_data/bulk/20231214_18.csv similarity index 100% rename from src/tests/testthat/data/bulk/20231214_18.csv rename to src/tests/testthat/data/dual_pam_data/bulk/20231214_18.csv diff --git a/src/tests/testthat/data/bulk/20231214_19.csv b/src/tests/testthat/data/dual_pam_data/bulk/20231214_19.csv similarity index 100% rename from src/tests/testthat/data/bulk/20231214_19.csv rename to src/tests/testthat/data/dual_pam_data/bulk/20231214_19.csv diff --git a/src/tests/testthat/data/20260130_efeutute_dual_pam_only_fluo.csv b/src/tests/testthat/data/dual_pam_single_channel_fluo_data/20260130_efeutute_dual_pam_only_fluo.csv similarity index 100% rename from src/tests/testthat/data/20260130_efeutute_dual_pam_only_fluo.csv rename to src/tests/testthat/data/dual_pam_single_channel_fluo_data/20260130_efeutute_dual_pam_only_fluo.csv diff --git a/src/tests/testthat/data/20260130_01_efeutute_dual_pam_only_p700.csv b/src/tests/testthat/data/dual_pam_single_channel_p700_data/20260130_01_efeutute_dual_pam_only_p700.csv similarity index 100% rename from src/tests/testthat/data/20260130_01_efeutute_dual_pam_only_p700.csv rename to src/tests/testthat/data/dual_pam_single_channel_p700_data/20260130_01_efeutute_dual_pam_only_p700.csv diff --git a/src/tests/testthat/data/2026_04_22_junior_pam.csv b/src/tests/testthat/data/junior_pam_data/2026_04_22_junior_pam.csv similarity index 100% rename from src/tests/testthat/data/2026_04_22_junior_pam.csv rename to src/tests/testthat/data/junior_pam_data/2026_04_22_junior_pam.csv diff --git a/src/tests/testthat/data/20260422_pam_2500.CSV b/src/tests/testthat/data/pam_2500_data/20260422_pam_2500.CSV similarity index 100% rename from src/tests/testthat/data/20260422_pam_2500.CSV rename to src/tests/testthat/data/pam_2500_data/20260422_pam_2500.CSV diff --git a/src/tests/testthat/data/universal_data.csv b/src/tests/testthat/data/universal_data/universal_data.csv similarity index 100% rename from src/tests/testthat/data/universal_data.csv rename to src/tests/testthat/data/universal_data/universal_data.csv diff --git a/src/tests/testthat/test-combo_plot_control_etr_I.R b/src/tests/testthat/test-combo_plot_control_etr_I.R index cf29b08..87c882a 100644 --- a/src/tests/testthat/test-combo_plot_control_etr_I.R +++ b/src/tests/testthat/test-combo_plot_control_etr_I.R @@ -1,5 +1,5 @@ test_that("test-combo_plot_control 20240925.csv", { - test_data_file <- testthat::test_path("data", "20240925.csv") + test_data_file <- testthat::test_path("data", "dual_pam_data", "20240925.csv") data <- read_dual_pam_data(test_data_file) eilers_peeters <- eilers_peeters_modified(eilers_peeters_generate_regression_ETR_I(data)) diff --git a/src/tests/testthat/test-combo_plot_control_etr_II.R b/src/tests/testthat/test-combo_plot_control_etr_II.R index 798f8cd..47457e1 100644 --- a/src/tests/testthat/test-combo_plot_control_etr_II.R +++ b/src/tests/testthat/test-combo_plot_control_etr_II.R @@ -1,5 +1,5 @@ test_that("test-combo_plot_control 20240925.csv", { - test_data_file <- testthat::test_path("data", "20240925.csv") + test_data_file <- testthat::test_path("data", "dual_pam_data", "20240925.csv") data <- read_dual_pam_data(test_data_file) eilers_peeters <- eilers_peeters_modified(eilers_peeters_generate_regression_ETR_II(data)) diff --git a/src/tests/testthat/test-compare_regression_models_etr_I.R b/src/tests/testthat/test-compare_regression_models_etr_I.R index 5e54236..f8076a4 100644 --- a/src/tests/testthat/test-compare_regression_models_etr_I.R +++ b/src/tests/testthat/test-compare_regression_models_etr_I.R @@ -1,6 +1,6 @@ test_that("compare_regression_models etr I - linux", { skip_if_not(is_debian_or_ubuntu()) - test_data_dir <- testthat::test_path("data", "bulk") + test_data_dir <- testthat::test_path("data", "dual_pam_data", "bulk") result <- compare_regression_models_ETR_I(test_data_dir, read_dual_pam_data) expect_equal(result[["eilers_peeters"]], 13) @@ -10,7 +10,7 @@ test_that("compare_regression_models etr I - linux", { }) test_that("compare_regression_models etr I", { - test_data_dir <- testthat::test_path("data", "bulk") + test_data_dir <- testthat::test_path("data", "dual_pam_data", "bulk") result <- compare_regression_models_ETR_I(test_data_dir, read_dual_pam_data) expect_named(result, c("eilers_peeters", "platt", "vollenweider", "walsby"), ignore.order = TRUE) }) diff --git a/src/tests/testthat/test-compare_regression_models_etr_II.R b/src/tests/testthat/test-compare_regression_models_etr_II.R index 919d238..ea84675 100644 --- a/src/tests/testthat/test-compare_regression_models_etr_II.R +++ b/src/tests/testthat/test-compare_regression_models_etr_II.R @@ -1,7 +1,7 @@ test_that("compare_regression_models etr II - linux", { skip_if_not(is_debian_or_ubuntu()) - test_data_dir <- testthat::test_path("data", "bulk") + test_data_dir <- testthat::test_path("data", "dual_pam_data", "bulk") result <- compare_regression_models_ETR_II(test_data_dir, read_dual_pam_data) expect_equal(result[["eilers_peeters"]], 37) @@ -11,7 +11,7 @@ test_that("compare_regression_models etr II - linux", { }) test_that("compare_regression_models etr II", { - test_data_dir <- testthat::test_path("data", "bulk") + test_data_dir <- testthat::test_path("data", "dual_pam_data", "bulk") result <- compare_regression_models_ETR_II(test_data_dir, read_dual_pam_data) expect_named(result, c("eilers_peeters", "platt", "vollenweider", "walsby"), ignore.order = TRUE) }) diff --git a/src/tests/testthat/test-compare_regression_models_total.R b/src/tests/testthat/test-compare_regression_models_total.R index 3c6f43a..21adb47 100644 --- a/src/tests/testthat/test-compare_regression_models_total.R +++ b/src/tests/testthat/test-compare_regression_models_total.R @@ -1,6 +1,6 @@ test_that("compare_regression_models etr I + II - linux", { skip_if_not(is_debian_or_ubuntu()) - test_data_dir <- testthat::test_path("data", "bulk") + test_data_dir <- testthat::test_path("data", "dual_pam_data", "bulk") model_points_etr_I <- compare_regression_models_ETR_I(test_data_dir, read_dual_pam_data) model_points_etr_II <- compare_regression_models_ETR_II(test_data_dir, read_dual_pam_data) @@ -16,7 +16,7 @@ test_that("compare_regression_models etr I + II - linux", { }) test_that("compare_regression_models etr I + II", { - test_data_dir <- testthat::test_path("data", "bulk") + test_data_dir <- testthat::test_path("data", "dual_pam_data", "bulk") model_points_etr_I <- compare_regression_models_ETR_I(test_data_dir, read_dual_pam_data) expect_named(model_points_etr_I, c("eilers_peeters", "platt", "vollenweider", "walsby"), ignore.order = TRUE) diff --git a/src/tests/testthat/test-eilers_peeters_etr_I.R b/src/tests/testthat/test-eilers_peeters_etr_I.R index b8d0fe2..d4e0275 100644 --- a/src/tests/testthat/test-eilers_peeters_etr_I.R +++ b/src/tests/testthat/test-eilers_peeters_etr_I.R @@ -1,6 +1,6 @@ test_that("test-eilers_peeters_etr_I generate regression 20240925.csv - linux", { skip_if_not(is_debian_or_ubuntu()) - test_data_file <- testthat::test_path("data", "20240925.csv") + test_data_file <- testthat::test_path("data", "dual_pam_data", "20240925.csv") data <- read_dual_pam_data(test_data_file) model_result <- eilers_peeters_generate_regression_ETR_I(data) @@ -16,14 +16,14 @@ test_that("test-eilers_peeters_etr_I generate regression 20240925.csv - linux", }) test_that("test-eilers_peeters_etr_I generate regression 20240925.csv", { - test_data_file <- testthat::test_path("data", "20240925.csv") + test_data_file <- testthat::test_path("data", "dual_pam_data", "20240925.csv") data <- read_dual_pam_data(test_data_file) model_result <- eilers_peeters_generate_regression_ETR_I(data) expect_no_error(validate_model_result(model_result)) }) test_that("test-eilers_peeters_etr_I control plot 20240925.csv", { - test_data_file <- testthat::test_path("data", "20240925.csv") + test_data_file <- testthat::test_path("data", "dual_pam_data", "20240925.csv") data <- read_dual_pam_data(test_data_file) model_result <- eilers_peeters_generate_regression_ETR_I(data) @@ -44,7 +44,7 @@ test_that("test-eilers_peeters_etr_I control plot 20240925.csv", { test_that("test-eilers_peeters_etr_I generate regression modified 20240925.csv - linux", { skip_if_not(is_debian_or_ubuntu()) - test_data_file <- testthat::test_path("data", "20240925.csv") + test_data_file <- testthat::test_path("data", "dual_pam_data", "20240925.csv") data <- read_dual_pam_data(test_data_file) model_result <- eilers_peeters_generate_regression_ETR_I(data) model_result <- eilers_peeters_modified(model_result) @@ -67,7 +67,7 @@ test_that("test-eilers_peeters_etr_I generate regression modified 20240925.csv - }) test_that("test-eilers_peeters_etr_I generate regression modified 20240925.csv", { - test_data_file <- testthat::test_path("data", "20240925.csv") + test_data_file <- testthat::test_path("data", "dual_pam_data", "20240925.csv") data <- read_dual_pam_data(test_data_file) model_result <- eilers_peeters_generate_regression_ETR_I(data) @@ -78,7 +78,7 @@ test_that("test-eilers_peeters_etr_I generate regression modified 20240925.csv", }) test_that("test-eilers_peeters_etr_I modified control plot 20240925.csv", { - test_data_file <- testthat::test_path("data", "20240925.csv") + test_data_file <- testthat::test_path("data", "dual_pam_data", "20240925.csv") data <- read_dual_pam_data(test_data_file) model_result <- eilers_peeters_generate_regression_ETR_I(data) model_result <- eilers_peeters_modified(model_result) diff --git a/src/tests/testthat/test-eilers_peeters_etr_II.R b/src/tests/testthat/test-eilers_peeters_etr_II.R index 0dc92b6..f9210fb 100644 --- a/src/tests/testthat/test-eilers_peeters_etr_II.R +++ b/src/tests/testthat/test-eilers_peeters_etr_II.R @@ -1,6 +1,6 @@ test_that("test-eilers_peeters_etr_II generate regression 20240925.csv - linux", { skip_if_not(is_debian_or_ubuntu()) - test_data_file <- testthat::test_path("data", "20240925.csv") + test_data_file <- testthat::test_path("data", "dual_pam_data", "20240925.csv") data <- read_dual_pam_data(test_data_file) model_result <- eilers_peeters_generate_regression_ETR_II(data) @@ -16,7 +16,7 @@ test_that("test-eilers_peeters_etr_II generate regression 20240925.csv - linux", }) test_that("test-eilers_peeters_etr_II generate regression 20240925.csv", { - test_data_file <- testthat::test_path("data", "20240925.csv") + test_data_file <- testthat::test_path("data", "dual_pam_data", "20240925.csv") data <- read_dual_pam_data(test_data_file) model_result <- eilers_peeters_generate_regression_ETR_II(data) expect_no_error(validate_model_result(model_result)) @@ -25,7 +25,7 @@ test_that("test-eilers_peeters_etr_II generate regression 20240925.csv", { test_that("test-eilers_peeters_etr_II modified 20240925.csv - linux", { skip_if_not(is_debian_or_ubuntu()) - test_data_file <- testthat::test_path("data", "20240925.csv") + test_data_file <- testthat::test_path("data", "dual_pam_data", "20240925.csv") data <- read_dual_pam_data(test_data_file) model_result <- eilers_peeters_generate_regression_ETR_II(data) model_result <- eilers_peeters_modified(model_result) @@ -48,7 +48,7 @@ test_that("test-eilers_peeters_etr_II modified 20240925.csv - linux", { }) test_that("test-eilers_peeters_etr_II modified 20240925.csv", { - test_data_file <- testthat::test_path("data", "20240925.csv") + test_data_file <- testthat::test_path("data", "dual_pam_data", "20240925.csv") data <- read_dual_pam_data(test_data_file) model_result <- eilers_peeters_generate_regression_ETR_II(data) expect_no_error(validate_model_result(model_result)) @@ -58,7 +58,7 @@ test_that("test-eilers_peeters_etr_II modified 20240925.csv", { }) test_that("test-eilers_peeters_etr_II modified control plot 20240925.csv", { - test_data_file <- testthat::test_path("data", "20240925.csv") + test_data_file <- testthat::test_path("data", "dual_pam_data", "20240925.csv") data <- read_dual_pam_data(test_data_file) model_result <- eilers_peeters_generate_regression_ETR_II(data) model_result <- model_result <- eilers_peeters_modified(model_result) diff --git a/src/tests/testthat/test-get_etr_data_for_par_values.R b/src/tests/testthat/test-get_etr_data_for_par_values.R index 7e8022a..2705898 100644 --- a/src/tests/testthat/test-get_etr_data_for_par_values.R +++ b/src/tests/testthat/test-get_etr_data_for_par_values.R @@ -1,5 +1,5 @@ test_that("test-get_etr_data_for_par_values.R", { - test_data_file <- testthat::test_path("data", "20240925.csv") + test_data_file <- testthat::test_path("data", "dual_pam_data", "20240925.csv") data <- read_dual_pam_data(test_data_file) model_result <- walsby_generate_regression_ETR_II(data) etr_regression_data <- get_etr_regression_data_from_model_result(model_result) diff --git a/src/tests/testthat/test-platt_etr_I.R b/src/tests/testthat/test-platt_etr_I.R index dded5b9..419101e 100644 --- a/src/tests/testthat/test-platt_etr_I.R +++ b/src/tests/testthat/test-platt_etr_I.R @@ -1,7 +1,7 @@ test_that("test-platt_etr_I generate regression 20240925.csv - linux", { skip_if_not(is_debian_or_ubuntu()) - test_data_file <- testthat::test_path("data", "20240925.csv") + test_data_file <- testthat::test_path("data", "dual_pam_data", "20240925.csv") data <- read_dual_pam_data(test_data_file) model_result <- platt_generate_regression_ETR_I(data) @@ -17,7 +17,7 @@ test_that("test-platt_etr_I generate regression 20240925.csv - linux", { }) test_that("test-platt_etr_I generate regression 20240925.csv", { - test_data_file <- testthat::test_path("data", "20240925.csv") + test_data_file <- testthat::test_path("data", "dual_pam_data", "20240925.csv") data <- read_dual_pam_data(test_data_file) model_result <- platt_generate_regression_ETR_I(data) expect_no_error(validate_model_result(model_result)) @@ -26,7 +26,7 @@ test_that("test-platt_etr_I generate regression 20240925.csv", { test_that("test-platt_etr_I generate regression modified 20240925.csv - linux", { skip_if_not(is_debian_or_ubuntu()) - test_data_file <- testthat::test_path("data", "20240925.csv") + test_data_file <- testthat::test_path("data", "dual_pam_data", "20240925.csv") data <- read_dual_pam_data(test_data_file) model_result <- platt_generate_regression_ETR_I(data) model_result <- platt_modified(model_result) @@ -49,7 +49,7 @@ test_that("test-platt_etr_I generate regression modified 20240925.csv - linux", }) test_that("test-platt_etr_I generate regression modified 20240925.csv", { - test_data_file <- testthat::test_path("data", "20240925.csv") + test_data_file <- testthat::test_path("data", "dual_pam_data", "20240925.csv") data <- read_dual_pam_data(test_data_file) model_result <- platt_generate_regression_ETR_I(data) @@ -60,7 +60,7 @@ test_that("test-platt_etr_I generate regression modified 20240925.csv", { }) test_that("test-platt_etr_I modified control plot 20240925.csv", { - test_data_file <- testthat::test_path("data", "20240925.csv") + test_data_file <- testthat::test_path("data", "dual_pam_data", "20240925.csv") data <- read_dual_pam_data(test_data_file) model_result <- platt_generate_regression_ETR_I(data) model_result <- platt_modified(model_result) diff --git a/src/tests/testthat/test-platt_etr_II.R b/src/tests/testthat/test-platt_etr_II.R index f5d7c93..c8b0db6 100644 --- a/src/tests/testthat/test-platt_etr_II.R +++ b/src/tests/testthat/test-platt_etr_II.R @@ -1,7 +1,7 @@ test_that("test-platt_etr_II generate regression 20240925.csv - linux", { skip_if_not(is_debian_or_ubuntu()) - test_data_file <- testthat::test_path("data", "20240925.csv") + test_data_file <- testthat::test_path("data", "dual_pam_data", "20240925.csv") data <- read_dual_pam_data(test_data_file) model_result <- platt_generate_regression_ETR_II(data) @@ -17,14 +17,14 @@ test_that("test-platt_etr_II generate regression 20240925.csv - linux", { }) test_that("test-platt_etr_II generate regression 20240925.csv", { - test_data_file <- testthat::test_path("data", "20240925.csv") + test_data_file <- testthat::test_path("data", "dual_pam_data", "20240925.csv") data <- read_dual_pam_data(test_data_file) model_result <- platt_generate_regression_ETR_II(data) expect_no_error(validate_model_result(model_result)) }) test_that("test-platt_etr_II control plot 20240925.csv", { - test_data_file <- testthat::test_path("data", "20240925.csv") + test_data_file <- testthat::test_path("data", "dual_pam_data", "20240925.csv") data <- read_dual_pam_data(test_data_file) model_result <- platt_generate_regression_ETR_II(data) @@ -45,7 +45,7 @@ test_that("test-platt_etr_II control plot 20240925.csv", { test_that("test-platt_etr_II generate regression modified 20240925.csv - linux", { skip_if_not(is_debian_or_ubuntu()) - test_data_file <- testthat::test_path("data", "20240925.csv") + test_data_file <- testthat::test_path("data", "dual_pam_data", "20240925.csv") data <- read_dual_pam_data(test_data_file) model_result <- platt_generate_regression_ETR_II(data) model_result <- platt_modified(model_result) @@ -68,7 +68,7 @@ test_that("test-platt_etr_II generate regression modified 20240925.csv - linux", }) test_that("test-platt_etr_II generate regression modified 20240925.csv", { - test_data_file <- testthat::test_path("data", "20240925.csv") + test_data_file <- testthat::test_path("data", "dual_pam_data", "20240925.csv") data <- read_dual_pam_data(test_data_file) model_result <- platt_generate_regression_ETR_II(data) expect_no_error(validate_model_result(model_result)) @@ -78,7 +78,7 @@ test_that("test-platt_etr_II generate regression modified 20240925.csv", { }) test_that("test-platt_etr_II modified control plot 20240925.csv", { - test_data_file <- testthat::test_path("data", "20240925.csv") + test_data_file <- testthat::test_path("data", "dual_pam_data", "20240925.csv") data <- read_dual_pam_data(test_data_file) model_result <- platt_generate_regression_ETR_II(data) diff --git a/src/tests/testthat/test-read_dual_pam_data.R b/src/tests/testthat/test-read_dual_pam_data.R index bcb9dc1..1f556d4 100644 --- a/src/tests/testthat/test-read_dual_pam_data.R +++ b/src/tests/testthat/test-read_dual_pam_data.R @@ -1,5 +1,5 @@ test_that("read_dual_pam_data 20240925.csv - default", { - test_data_file <- testthat::test_path("data", "20240925.csv") + test_data_file <- testthat::test_path("data", "dual_pam_data", "20240925.csv") data <- read_dual_pam_data(test_data_file) par <- data$par @@ -99,7 +99,7 @@ test_that("read_dual_pam_data 20240925.csv - default", { }) test_that("read_dual_pam_data 20240925.csv - etr_factor 0.5", { - test_data_file <- testthat::test_path("data", "20240925.csv") + test_data_file <- testthat::test_path("data", "dual_pam_data", "20240925.csv") data <- read_dual_pam_data(test_data_file, etr_factor = 0.5) par <- data$par @@ -199,12 +199,12 @@ test_that("read_dual_pam_data 20240925.csv - etr_factor 0.5", { }) test_that("read_dual_pam_data 20240925.csv - fraction_photosystem > 1", { - test_data_file <- testthat::test_path("data", "20240925.csv") + test_data_file <- testthat::test_path("data", "dual_pam_data", "20240925.csv") expect_error(read_dual_pam_data(test_data_file, fraction_photosystem_I = 0.9, fraction_photosystem_II = 0.2)) }) test_that("read_dual_pam_data 20240925.csv - fraction_photosystem_I = 0.2, fraction_photosystem_II = 0.8", { - test_data_file <- testthat::test_path("data", "20240925.csv") + test_data_file <- testthat::test_path("data", "dual_pam_data", "20240925.csv") data <- read_dual_pam_data(test_data_file, fraction_photosystem_I = 0.2, fraction_photosystem_II = 0.8) par <- data$par @@ -304,11 +304,11 @@ test_that("read_dual_pam_data 20240925.csv - fraction_photosystem_I = 0.2, fract }) test_that("20260130_01_efeutute_dual_pam_only_p700.csv - expect fm missing", { - test_data_file <- testthat::test_path("data", "20260130_01_efeutute_dual_pam_only_p700.csv") + test_data_file <- testthat::test_path("data", "dual_pam_single_channel_p700_data", "20260130_01_efeutute_dual_pam_only_p700.csv") expect_error(read_dual_pam_data(test_data_file)) }) test_that("20260130_efeutute_dual_pam_only_fluo.csv - expect pm missing", { - test_data_file <- testthat::test_path("data", "20260130_efeutute_dual_pam_only_fluo.csv") + test_data_file <- testthat::test_path("data", "dual_pam_single_channel_fluo_data", "20260130_efeutute_dual_pam_only_fluo.csv") expect_error(read_dual_pam_data(test_data_file)) }) diff --git a/src/tests/testthat/test-read_dual_pam_single_channel_fluo_data.R b/src/tests/testthat/test-read_dual_pam_single_channel_fluo_data.R index fda729a..61cd47a 100644 --- a/src/tests/testthat/test-read_dual_pam_single_channel_fluo_data.R +++ b/src/tests/testthat/test-read_dual_pam_single_channel_fluo_data.R @@ -1,5 +1,5 @@ test_that("read_dual_pam_single_channel_fluo_data 20260130_efeutute_dual_pam_only_fluo - default", { - test_data_file <- testthat::test_path("data", "20260130_efeutute_dual_pam_only_fluo.csv") + test_data_file <- testthat::test_path("data", "dual_pam_single_channel_fluo_data", "20260130_efeutute_dual_pam_only_fluo.csv") data <- read_dual_pam_single_channel_fluo_data(test_data_file) par <- data$par @@ -69,7 +69,7 @@ test_that("read_dual_pam_single_channel_fluo_data 20260130_efeutute_dual_pam_onl }) test_that("read_dual_pam_single_channel_fluo_data 20260130_efeutute_dual_pam_only_fluo - etr_factor 0.5", { - test_data_file <- testthat::test_path("data", "20260130_efeutute_dual_pam_only_fluo.csv") + test_data_file <- testthat::test_path("data", "dual_pam_single_channel_fluo_data", "20260130_efeutute_dual_pam_only_fluo.csv") data <- read_dual_pam_single_channel_fluo_data(test_data_file, etr_factor = 0.5) par <- data$par @@ -139,12 +139,12 @@ test_that("read_dual_pam_single_channel_fluo_data 20260130_efeutute_dual_pam_onl }) test_that("read_dual_pam_single_channel_fluo_data 20260130_efeutute_dual_pam_only_fluo - fraction_photosystem > 1", { - test_data_file <- testthat::test_path("data", "20260130_efeutute_dual_pam_only_fluo.csv") + test_data_file <- testthat::test_path("data", "dual_pam_single_channel_fluo_data", "20260130_efeutute_dual_pam_only_fluo.csv") expect_error(read_dual_pam_single_channel_fluo_data(test_data_file, fraction_photosystem_I = 0.9, fraction_photosystem_II = 0.2)) }) test_that("read_dual_pam_single_channel_fluo_data 20260130_efeutute_dual_pam_only_fluo - fraction_photosystem_I = 0.2, fraction_photosystem_II = 0.8", { - test_data_file <- testthat::test_path("data", "20260130_efeutute_dual_pam_only_fluo.csv") + test_data_file <- testthat::test_path("data", "dual_pam_single_channel_fluo_data", "20260130_efeutute_dual_pam_only_fluo.csv") data <- read_dual_pam_single_channel_fluo_data(test_data_file, fraction_photosystem_I = 0.2, fraction_photosystem_II = 0.8) par <- data$par diff --git a/src/tests/testthat/test-read_dual_pam_single_channel_p700_data.R b/src/tests/testthat/test-read_dual_pam_single_channel_p700_data.R index d486edf..4a5fdb8 100644 --- a/src/tests/testthat/test-read_dual_pam_single_channel_p700_data.R +++ b/src/tests/testthat/test-read_dual_pam_single_channel_p700_data.R @@ -1,5 +1,5 @@ test_that("read_dual_pam_single_channel_p700_data 20260130_01_efeutute_dual_pam_only_p700 - default", { - test_data_file <- testthat::test_path("data", "20260130_01_efeutute_dual_pam_only_p700.csv") + test_data_file <- testthat::test_path("data", "dual_pam_single_channel_p700_data", "20260130_01_efeutute_dual_pam_only_p700.csv") data <- read_dual_pam_single_channel_p700_data(test_data_file) par <- data$par @@ -89,7 +89,7 @@ test_that("read_dual_pam_single_channel_p700_data 20260130_01_efeutute_dual_pam_ }) test_that("read_dual_pam_single_channel_p700_data 20260130_01_efeutute_dual_pam_only_p700 - etr_factor 0.5", { - test_data_file <- testthat::test_path("data", "20260130_01_efeutute_dual_pam_only_p700.csv") + test_data_file <- testthat::test_path("data", "dual_pam_single_channel_p700_data", "20260130_01_efeutute_dual_pam_only_p700.csv") data <- read_dual_pam_single_channel_p700_data(test_data_file, etr_factor = 0.5) par <- data$par @@ -179,12 +179,12 @@ test_that("read_dual_pam_single_channel_p700_data 20260130_01_efeutute_dual_pam_ }) test_that("read_dual_pam_single_channel_p700_data 20260130_01_efeutute_dual_pam_only_p700 - fraction_photosystem > 1", { - test_data_file <- testthat::test_path("data", "20260130_01_efeutute_dual_pam_only_p700.csv") + test_data_file <- testthat::test_path("data", "dual_pam_single_channel_p700_data", "20260130_01_efeutute_dual_pam_only_p700.csv") expect_error(read_dual_pam_single_channel_p700_data(test_data_file, fraction_photosystem_I = 0.9, fraction_photosystem_II = 0.2)) }) test_that("read_dual_pam_single_channel_p700_data 20260130_01_efeutute_dual_pam_only_p700 - fraction_photosystem_I = 0.2, fraction_photosystem_II = 0.8", { - test_data_file <- testthat::test_path("data", "20260130_01_efeutute_dual_pam_only_p700.csv") + test_data_file <- testthat::test_path("data", "dual_pam_single_channel_p700_data", "20260130_01_efeutute_dual_pam_only_p700.csv") data <- read_dual_pam_single_channel_p700_data(test_data_file, fraction_photosystem_I = 0.2, fraction_photosystem_II = 0.8) par <- data$par diff --git a/src/tests/testthat/test-read_junior_pam_data.R b/src/tests/testthat/test-read_junior_pam_data.R index 30c8982..0286f22 100644 --- a/src/tests/testthat/test-read_junior_pam_data.R +++ b/src/tests/testthat/test-read_junior_pam_data.R @@ -1,5 +1,5 @@ test_that("read_junior_pam_data 2026_04_22_junior_pam.csv - default", { - test_data_file <- testthat::test_path("data", "2026_04_22_junior_pam.csv") + test_data_file <- testthat::test_path("data", "junior_pam_data", "2026_04_22_junior_pam.csv") data <- read_junior_pam_data(test_data_file) par <- data$par @@ -79,7 +79,7 @@ test_that("read_junior_pam_data 2026_04_22_junior_pam.csv - default", { }) test_that("read_junior_pam_data 2026_04_22_junior_pam.csv - etr_factor 0.5", { - test_data_file <- testthat::test_path("data", "2026_04_22_junior_pam.csv") + test_data_file <- testthat::test_path("data", "junior_pam_data", "2026_04_22_junior_pam.csv") data <- read_junior_pam_data(test_data_file, etr_factor = 0.5) par <- data$par @@ -159,12 +159,12 @@ test_that("read_junior_pam_data 2026_04_22_junior_pam.csv - etr_factor 0.5", { }) test_that("read_junior_pam_data 2026_04_22_junior_pam.csv - fraction_photosystem > 1", { - test_data_file <- testthat::test_path("data", "2026_04_22_junior_pam.csv") + test_data_file <- testthat::test_path("data", "junior_pam_data", "2026_04_22_junior_pam.csv") expect_error(read_junior_pam_data(test_data_file, fraction_photosystem_I = 0.9, fraction_photosystem_II = 0.2)) }) test_that("read_junior_pam_data 2026_04_22_junior_pam.csv - fraction_photosystem_I = 0.2, fraction_photosystem_II = 0.8", { - test_data_file <- testthat::test_path("data", "2026_04_22_junior_pam.csv") + test_data_file <- testthat::test_path("data", "junior_pam_data", "2026_04_22_junior_pam.csv") data <- read_junior_pam_data(test_data_file, fraction_photosystem_I = 0.2, fraction_photosystem_II = 0.8) par <- data$par diff --git a/src/tests/testthat/test-read_pam_2500_data.R b/src/tests/testthat/test-read_pam_2500_data.R index d288fb4..d916676 100644 --- a/src/tests/testthat/test-read_pam_2500_data.R +++ b/src/tests/testthat/test-read_pam_2500_data.R @@ -1,5 +1,5 @@ test_that("read_pam_2500_data 20260422_pam_2500.CSV - default", { - test_data_file <- testthat::test_path("data", "20260422_pam_2500.CSV") + test_data_file <- testthat::test_path("data", "pam_2500_data", "20260422_pam_2500.CSV") data <- read_pam_2500_data(test_data_file) par <- data$par @@ -64,7 +64,7 @@ test_that("read_pam_2500_data 20260422_pam_2500.CSV - default", { }) test_that("read_pam_2500_data 20260422_pam_2500.CSV - etr-factor 0.5", { - test_data_file <- testthat::test_path("data", "20260422_pam_2500.CSV") + test_data_file <- testthat::test_path("data", "pam_2500_data", "20260422_pam_2500.CSV") data <- read_pam_2500_data(test_data_file, etr_factor = 0.5) par <- data$par @@ -129,12 +129,12 @@ test_that("read_pam_2500_data 20260422_pam_2500.CSV - etr-factor 0.5", { }) test_that("read_pam_2500_data 20260422_pam_2500.CSV - fraction_photosystem_I = 0.2, fraction_photosystem_II = 0.8", { - test_data_file <- testthat::test_path("data", "20260422_pam_2500.CSV") + test_data_file <- testthat::test_path("data", "pam_2500_data", "20260422_pam_2500.CSV") expect_error(read_pam_2500_data(test_data_file, fraction_photosystem_I = 0.9, fraction_photosystem_II = 0.2)) }) test_that("read_pam_2500_data 20260422_pam_2500.CSV - fraction_photosystem_I = 0.2, fraction_photosystem_II = 0.8", { - test_data_file <- testthat::test_path("data", "20260422_pam_2500.CSV") + test_data_file <- testthat::test_path("data", "pam_2500_data", "20260422_pam_2500.CSV") data <- read_pam_2500_data(test_data_file, fraction_photosystem_I = 0.2, fraction_photosystem_II = 0.8) par <- data$par diff --git a/src/tests/testthat/test-read_universal_data.R b/src/tests/testthat/test-read_universal_data.R index e07470e..ba3d7fb 100644 --- a/src/tests/testthat/test-read_universal_data.R +++ b/src/tests/testthat/test-read_universal_data.R @@ -1,5 +1,5 @@ test_that("read_universal_data universal_data.csv - default", { - test_data_file <- testthat::test_path("data", "universal_data.csv") + test_data_file <- testthat::test_path("data", "universal_data", "universal_data.csv") data <- read_universal_data(test_data_file) par <- data$par @@ -99,7 +99,7 @@ test_that("read_universal_data universal_data.csv - default", { }) test_that("read_universal_data universal_data.csv - etr_factor 0.5", { - test_data_file <- testthat::test_path("data", "universal_data.csv") + test_data_file <- testthat::test_path("data", "universal_data", "universal_data.csv") data <- read_universal_data(test_data_file, etr_factor = 0.5) par <- data$par @@ -199,12 +199,12 @@ test_that("read_universal_data universal_data.csv - etr_factor 0.5", { }) test_that("read_universal_data universal_data.csv - fraction_photosystem > 1", { - test_data_file <- testthat::test_path("data", "universal_data.csv") + test_data_file <- testthat::test_path("data", "universal_data", "universal_data.csv") expect_error(read_universal_data(test_data_file, fraction_photosystem_I = 0.9, fraction_photosystem_II = 0.2)) }) test_that("read_universal_data universal_data.csv - fraction_photosystem_I = 0.2, fraction_photosystem_II = 0.8", { - test_data_file <- testthat::test_path("data", "universal_data.csv") + test_data_file <- testthat::test_path("data", "universal_data", "universal_data.csv") data <- read_universal_data(test_data_file, fraction_photosystem_I = 0.2, fraction_photosystem_II = 0.8) par <- data$par diff --git a/src/tests/testthat/test-relative_root_mean_squared_error.R b/src/tests/testthat/test-relative_root_mean_squared_error.R index 026f461..938371b 100644 --- a/src/tests/testthat/test-relative_root_mean_squared_error.R +++ b/src/tests/testthat/test-relative_root_mean_squared_error.R @@ -1,7 +1,7 @@ test_that("test-relative_root_mean_squared_error - linux", { skip_if_not(is_debian_or_ubuntu()) - test_data_file <- testthat::test_path("data", "20240925.csv") + test_data_file <- testthat::test_path("data", "dual_pam_data", "20240925.csv") data <- read_dual_pam_data(test_data_file) model_result <- walsby_generate_regression_ETR_II(data) etr_regression_data <- get_etr_regression_data_from_model_result(model_result) @@ -13,7 +13,7 @@ test_that("test-relative_root_mean_squared_error - linux", { }) test_that("test-relative_root_mean_squared_error", { - test_data_file <- testthat::test_path("data", "20240925.csv") + test_data_file <- testthat::test_path("data", "dual_pam_data", "20240925.csv") data <- read_dual_pam_data(test_data_file) model_result <- walsby_generate_regression_ETR_II(data) etr_regression_data <- get_etr_regression_data_from_model_result(model_result) diff --git a/src/tests/testthat/test-root_mean_squared_error.R b/src/tests/testthat/test-root_mean_squared_error.R index 8606069..f29912d 100644 --- a/src/tests/testthat/test-root_mean_squared_error.R +++ b/src/tests/testthat/test-root_mean_squared_error.R @@ -1,7 +1,7 @@ test_that("test-root_mean_squared_error - linux", { skip_if_not(is_debian_or_ubuntu()) - test_data_file <- testthat::test_path("data", "20240925.csv") + test_data_file <- testthat::test_path("data", "dual_pam_data", "20240925.csv") data <- read_dual_pam_data(test_data_file) model_result <- walsby_generate_regression_ETR_II(data) etr_regression_data <- get_etr_regression_data_from_model_result(model_result) @@ -12,7 +12,7 @@ test_that("test-root_mean_squared_error - linux", { }) test_that("test-root_mean_squared_error", { - test_data_file <- testthat::test_path("data", "20240925.csv") + test_data_file <- testthat::test_path("data", "dual_pam_data", "20240925.csv") data <- read_dual_pam_data(test_data_file) model_result <- walsby_generate_regression_ETR_II(data) etr_regression_data <- get_etr_regression_data_from_model_result(model_result) diff --git a/src/tests/testthat/test-universal_data_etr_I.R b/src/tests/testthat/test-universal_data_etr_I.R index e1ac1e3..a2c9986 100644 --- a/src/tests/testthat/test-universal_data_etr_I.R +++ b/src/tests/testthat/test-universal_data_etr_I.R @@ -1,7 +1,7 @@ test_that("test-universal_data_etr_I - linux", { skip_if_not(is_debian_or_ubuntu()) - test_data_file <- testthat::test_path("data", "universal_data.csv") + test_data_file <- testthat::test_path("data", "universal_data", "universal_data.csv") data <- read_universal_data(test_data_file) eilers_peeters <- eilers_peeters_modified(eilers_peeters_generate_regression_ETR_I(data)) @@ -75,7 +75,7 @@ test_that("test-universal_data_etr_I - linux", { }) test_that("test-universal_data_etr_I", { - test_data_file <- testthat::test_path("data", "universal_data.csv") + test_data_file <- testthat::test_path("data", "universal_data", "universal_data.csv") data <- read_universal_data(test_data_file) eilers_peeters <- eilers_peeters_modified(eilers_peeters_generate_regression_ETR_I(data)) @@ -92,7 +92,7 @@ test_that("test-universal_data_etr_I", { }) test_that("test-universal_data_etr_I plot", { - test_data_file <- testthat::test_path("data", "universal_data.csv") + test_data_file <- testthat::test_path("data", "universal_data", "universal_data.csv") data <- read_universal_data(test_data_file) eilers_peeters <- eilers_peeters_modified(eilers_peeters_generate_regression_ETR_I(data)) diff --git a/src/tests/testthat/test-vollenweider_etr_I.R b/src/tests/testthat/test-vollenweider_etr_I.R index 0c7bda5..e1c7772 100644 --- a/src/tests/testthat/test-vollenweider_etr_I.R +++ b/src/tests/testthat/test-vollenweider_etr_I.R @@ -1,7 +1,7 @@ test_that("test-vollenweider_etr_I generate regression 20240925.csv - linux", { skip_if_not(is_debian_or_ubuntu()) - test_data_file <- testthat::test_path("data", "20240925.csv") + test_data_file <- testthat::test_path("data", "dual_pam_data", "20240925.csv") data <- read_dual_pam_data(test_data_file) model_result <- vollenweider_generate_regression_ETR_I(data) @@ -17,14 +17,14 @@ test_that("test-vollenweider_etr_I generate regression 20240925.csv - linux", { }) test_that("test-vollenweider_etr_I generate regression 20240925.csv", { - test_data_file <- testthat::test_path("data", "20240925.csv") + test_data_file <- testthat::test_path("data", "dual_pam_data", "20240925.csv") data <- read_dual_pam_data(test_data_file) model_result <- vollenweider_generate_regression_ETR_I(data) expect_no_error(validate_model_result(model_result)) }) test_that("test-vollenweider_etr_I control plot 20240925.csv", { - test_data_file <- testthat::test_path("data", "20240925.csv") + test_data_file <- testthat::test_path("data", "dual_pam_data", "20240925.csv") data <- read_dual_pam_data(test_data_file) model_result <- vollenweider_generate_regression_ETR_I(data) @@ -45,7 +45,7 @@ test_that("test-vollenweider_etr_I control plot 20240925.csv", { test_that("test-vollenweider_etr_I generate regression modified 20240925.csv - linux", { skip_if_not(is_debian_or_ubuntu()) - test_data_file <- testthat::test_path("data", "20240925.csv") + test_data_file <- testthat::test_path("data", "dual_pam_data", "20240925.csv") data <- read_dual_pam_data(test_data_file) model_result <- vollenweider_generate_regression_ETR_I(data) model_result <- vollenweider_modified(model_result) @@ -68,7 +68,7 @@ test_that("test-vollenweider_etr_I generate regression modified 20240925.csv - l }) test_that("test-vollenweider_etr_I generate regression modified 20240925.csv", { - test_data_file <- testthat::test_path("data", "20240925.csv") + test_data_file <- testthat::test_path("data", "dual_pam_data", "20240925.csv") data <- read_dual_pam_data(test_data_file) model_result <- vollenweider_generate_regression_ETR_I(data) expect_no_error(validate_model_result(model_result)) @@ -78,7 +78,7 @@ test_that("test-vollenweider_etr_I generate regression modified 20240925.csv", { }) test_that("test-vollenweider_etr_I modified control plot 20240925.csv", { - test_data_file <- testthat::test_path("data", "20240925.csv") + test_data_file <- testthat::test_path("data", "dual_pam_data", "20240925.csv") data <- read_dual_pam_data(test_data_file) model_result <- vollenweider_generate_regression_ETR_I(data) model_result <- vollenweider_modified(model_result) diff --git a/src/tests/testthat/test-vollenweider_etr_II.R b/src/tests/testthat/test-vollenweider_etr_II.R index ad71827..a892144 100644 --- a/src/tests/testthat/test-vollenweider_etr_II.R +++ b/src/tests/testthat/test-vollenweider_etr_II.R @@ -1,7 +1,7 @@ test_that("test-vollenweider_etr_II generate regression 20240925.csv - linux", { skip_if_not(is_debian_or_ubuntu()) - test_data_file <- testthat::test_path("data", "20240925.csv") + test_data_file <- testthat::test_path("data", "dual_pam_data", "20240925.csv") data <- read_dual_pam_data(test_data_file) model_result <- vollenweider_generate_regression_ETR_II(data) @@ -17,14 +17,14 @@ test_that("test-vollenweider_etr_II generate regression 20240925.csv - linux", { }) test_that("test-vollenweider_etr_II generate regression 20240925.csv", { - test_data_file <- testthat::test_path("data", "20240925.csv") + test_data_file <- testthat::test_path("data", "dual_pam_data", "20240925.csv") data <- read_dual_pam_data(test_data_file) model_result <- vollenweider_generate_regression_ETR_II(data) expect_no_error(validate_model_result(model_result)) }) test_that("test-vollenweider_etr_II control plot 20240925.csv", { - test_data_file <- testthat::test_path("data", "20240925.csv") + test_data_file <- testthat::test_path("data", "dual_pam_data", "20240925.csv") data <- read_dual_pam_data(test_data_file) model_result <- vollenweider_generate_regression_ETR_II(data) @@ -45,7 +45,7 @@ test_that("test-vollenweider_etr_II control plot 20240925.csv", { test_that("test-vollenweider_etr_II generate regression modified 20240925.csv - linux", { skip_if_not(is_debian_or_ubuntu()) - test_data_file <- testthat::test_path("data", "20240925.csv") + test_data_file <- testthat::test_path("data", "dual_pam_data", "20240925.csv") data <- read_dual_pam_data(test_data_file) model_result <- vollenweider_generate_regression_ETR_II(data) model_result <- vollenweider_modified(model_result) @@ -68,7 +68,7 @@ test_that("test-vollenweider_etr_II generate regression modified 20240925.csv - }) test_that("test-vollenweider_etr_II generate regression modified 20240925.csv", { - test_data_file <- testthat::test_path("data", "20240925.csv") + test_data_file <- testthat::test_path("data", "dual_pam_data", "20240925.csv") data <- read_dual_pam_data(test_data_file) model_result <- vollenweider_generate_regression_ETR_II(data) @@ -79,7 +79,7 @@ test_that("test-vollenweider_etr_II generate regression modified 20240925.csv", }) test_that("test-vollenweider_etr_II modified control plot 20240925.csv", { - test_data_file <- testthat::test_path("data", "20240925.csv") + test_data_file <- testthat::test_path("data", "dual_pam_data", "20240925.csv") data <- read_dual_pam_data(test_data_file) model_result <- vollenweider_generate_regression_ETR_II(data) model_result <- vollenweider_modified(model_result) diff --git a/src/tests/testthat/test-walsby_etr_I.R b/src/tests/testthat/test-walsby_etr_I.R index 6da7dad..319fa25 100644 --- a/src/tests/testthat/test-walsby_etr_I.R +++ b/src/tests/testthat/test-walsby_etr_I.R @@ -1,7 +1,7 @@ test_that("test-walsby_etr_I generate regression 20240925.csv - linux", { skip_if_not(is_debian_or_ubuntu()) - test_data_file <- testthat::test_path("data", "20240925.csv") + test_data_file <- testthat::test_path("data", "dual_pam_data", "20240925.csv") data <- read_dual_pam_data(test_data_file) model_result <- walsby_generate_regression_ETR_I(data) @@ -12,14 +12,14 @@ test_that("test-walsby_etr_I generate regression 20240925.csv - linux", { }) test_that("test-walsby_etr_I generate regression 20240925.csv", { - test_data_file <- testthat::test_path("data", "20240925.csv") + test_data_file <- testthat::test_path("data", "dual_pam_data", "20240925.csv") data <- read_dual_pam_data(test_data_file) model_result <- walsby_generate_regression_ETR_I(data) expect_no_error(validate_model_result(model_result)) }) test_that("test-walsby_etr_I control plot 20240925.csv", { - test_data_file <- testthat::test_path("data", "20240925.csv") + test_data_file <- testthat::test_path("data", "dual_pam_data", "20240925.csv") data <- read_dual_pam_data(test_data_file) model_result <- walsby_generate_regression_ETR_I(data) @@ -40,7 +40,7 @@ test_that("test-walsby_etr_I control plot 20240925.csv", { test_that("test-walsby_etr_I generate regression modified 20240925.csv - linux", { skip_if_not(is_debian_or_ubuntu()) - test_data_file <- testthat::test_path("data", "20240925.csv") + test_data_file <- testthat::test_path("data", "dual_pam_data", "20240925.csv") data <- read_dual_pam_data(test_data_file) model_result <- walsby_generate_regression_ETR_I(data) model_result <- walsby_modified(model_result) @@ -63,7 +63,7 @@ test_that("test-walsby_etr_I generate regression modified 20240925.csv - linux", }) test_that("test-walsby_etr_I generate regression modified 20240925.csv", { - test_data_file <- testthat::test_path("data", "20240925.csv") + test_data_file <- testthat::test_path("data", "dual_pam_data", "20240925.csv") data <- read_dual_pam_data(test_data_file) model_result <- walsby_generate_regression_ETR_I(data) @@ -74,7 +74,7 @@ test_that("test-walsby_etr_I generate regression modified 20240925.csv", { }) test_that("test-walsby_etr_I modified control plot 20240925.csv", { - test_data_file <- testthat::test_path("data", "20240925.csv") + test_data_file <- testthat::test_path("data", "dual_pam_data", "20240925.csv") data <- read_dual_pam_data(test_data_file) model_result <- walsby_generate_regression_ETR_I(data) model_result <- walsby_modified(model_result) diff --git a/src/tests/testthat/test-walsby_etr_II.R b/src/tests/testthat/test-walsby_etr_II.R index 55d94c5..f2dfda3 100644 --- a/src/tests/testthat/test-walsby_etr_II.R +++ b/src/tests/testthat/test-walsby_etr_II.R @@ -1,7 +1,7 @@ test_that("test-walsby_etr_II generate regression 20240925.csv - linux", { skip_if_not(is_debian_or_ubuntu()) - test_data_file <- testthat::test_path("data", "20240925.csv") + test_data_file <- testthat::test_path("data", "dual_pam_data", "20240925.csv") data <- read_dual_pam_data(test_data_file) model_result <- walsby_generate_regression_ETR_II(data) @@ -12,14 +12,14 @@ test_that("test-walsby_etr_II generate regression 20240925.csv - linux", { }) test_that("test-walsby_etr_II generate regression 20240925.csv", { - test_data_file <- testthat::test_path("data", "20240925.csv") + test_data_file <- testthat::test_path("data", "dual_pam_data", "20240925.csv") data <- read_dual_pam_data(test_data_file) model_result <- walsby_generate_regression_ETR_II(data) expect_no_error(validate_model_result(model_result)) }) test_that("test-walsby_etr_II control plot 20240925.csv", { - test_data_file <- testthat::test_path("data", "20240925.csv") + test_data_file <- testthat::test_path("data", "dual_pam_data", "20240925.csv") data <- read_dual_pam_data(test_data_file) model_result <- walsby_generate_regression_ETR_II(data) @@ -40,7 +40,7 @@ test_that("test-walsby_etr_II control plot 20240925.csv", { test_that("test-walsby_etr_II generate regression modified 20240925.csv - linux", { skip_if_not(is_debian_or_ubuntu()) - test_data_file <- testthat::test_path("data", "20240925.csv") + test_data_file <- testthat::test_path("data", "dual_pam_data", "20240925.csv") data <- read_dual_pam_data(test_data_file) model_result <- walsby_generate_regression_ETR_II(data) model_result <- walsby_modified(model_result) @@ -63,7 +63,7 @@ test_that("test-walsby_etr_II generate regression modified 20240925.csv - linux" }) test_that("test-walsby_etr_II generate regression modified 20240925.csv", { - test_data_file <- testthat::test_path("data", "20240925.csv") + test_data_file <- testthat::test_path("data", "dual_pam_data", "20240925.csv") data <- read_dual_pam_data(test_data_file) model_result <- walsby_generate_regression_ETR_II(data) @@ -74,7 +74,7 @@ test_that("test-walsby_etr_II generate regression modified 20240925.csv", { }) test_that("test-walsby_etr_II modified control plot 20240925.csv", { - test_data_file <- testthat::test_path("data", "20240925.csv") + test_data_file <- testthat::test_path("data", "dual_pam_data", "20240925.csv") data <- read_dual_pam_data(test_data_file) model_result <- walsby_generate_regression_ETR_II(data) model_result <- walsby_modified(model_result) diff --git a/src/tests/testthat/test-write_model_result_csv.R b/src/tests/testthat/test-write_model_result_csv.R index a968478..2e51656 100644 --- a/src/tests/testthat/test-write_model_result_csv.R +++ b/src/tests/testthat/test-write_model_result_csv.R @@ -1,5 +1,5 @@ test_that("test-write_model_result_csv - walsby_modified - 20240925.csv", { - test_data_file <- testthat::test_path("data", "20240925.csv") + test_data_file <- testthat::test_path("data", "dual_pam_data", "20240925.csv") data <- read_dual_pam_data(test_data_file) model_result <- walsby_generate_regression_ETR_II(data) model_result <- walsby_modified(model_result) @@ -52,7 +52,7 @@ test_that("test-write_model_result_csv - walsby_modified - 20240925.csv", { }) test_that("test-write_model_result_csv - walsby - 20240925.csv", { - test_data_file <- testthat::test_path("data", "20240925.csv") + test_data_file <- testthat::test_path("data", "dual_pam_data", "20240925.csv") data <- read_dual_pam_data(test_data_file) model_result <- walsby_generate_regression_ETR_II(data) From b123237f9575b96f7c8869c53b1be773553579f0 Mon Sep 17 00:00:00 2001 From: Phi-S <926151+Phi-S@users.noreply.github.com> Date: Thu, 23 Apr 2026 11:46:36 +0200 Subject: [PATCH 29/32] updated read function and validate structure --- src/R/compare_regression_models.R | 2 +- src/R/device_dual_pam.R | 170 +++++ src/R/device_dual_pam_single_channel_fluo.R | 164 ++++ src/R/device_dual_pam_single_channel_p700.R | 162 ++++ src/R/device_junior_pam.R | 125 +++ src/R/device_pam_2500.R | 133 ++++ src/R/device_universal_data.R | 93 +++ ...ilers_peeters.R => model_eilers_peeters.R} | 2 +- src/R/{platt.R => model_platt.R} | 2 +- .../{vollenweider.R => model_vollenweider.R} | 2 +- src/R/{walsby.R => model_walsby.R} | 2 +- src/R/{combo_plot_control.R => plot.R} | 212 +++++- src/R/read_pam_data.R | 711 ------------------ src/R/util.R | 309 +------- src/R/validation.R | 228 +----- src/R/write_model_result_csv.R | 75 ++ ...uo.csv => 20260130_dual_pam_only_fluo.csv} | 0 ...csv => 20260130_01_dual_pam_only_p700.csv} | 0 src/man/combo_plot_control.Rd | 2 +- .../eilers_peeters_default_start_value_a.Rd | 2 +- .../eilers_peeters_default_start_value_b.Rd | 2 +- .../eilers_peeters_default_start_value_c.Rd | 2 +- ...ilers_peeters_generate_regression_ETR_I.Rd | 2 +- ...lers_peeters_generate_regression_ETR_II.Rd | 2 +- src/man/eilers_peeters_modified.Rd | 2 +- src/man/platt_default_start_value_alpha.Rd | 2 +- src/man/platt_default_start_value_beta.Rd | 2 +- src/man/platt_default_start_value_ps.Rd | 2 +- src/man/platt_generate_regression_ETR_I.Rd | 2 +- src/man/platt_generate_regression_ETR_II.Rd | 2 +- src/man/platt_modified.Rd | 2 +- src/man/plot_control.Rd | 2 +- src/man/read_dual_pam_data.Rd | 110 +-- .../read_dual_pam_single_channel_fluo_data.Rd | 4 +- .../read_dual_pam_single_channel_p700_data.Rd | 4 +- src/man/read_junior_pam_data.Rd | 2 +- src/man/read_pam_2500_data.Rd | 2 +- src/man/read_universal_data.Rd | 2 +- src/man/vollenweider_default_start_value_a.Rd | 2 +- .../vollenweider_default_start_value_alpha.Rd | 2 +- src/man/vollenweider_default_start_value_n.Rd | 2 +- .../vollenweider_default_start_value_pmax.Rd | 2 +- .../vollenweider_generate_regression_ETR_I.Rd | 2 +- ...vollenweider_generate_regression_ETR_II.Rd | 2 +- src/man/vollenweider_modified.Rd | 2 +- src/man/walsby_default_start_value_alpha.Rd | 2 +- src/man/walsby_default_start_value_beta.Rd | 2 +- src/man/walsby_default_start_value_etr_max.Rd | 2 +- src/man/walsby_generate_regression_ETR_I.Rd | 2 +- src/man/walsby_generate_regression_ETR_II.Rd | 2 +- src/man/walsby_modified.Rd | 2 +- src/man/write_model_result_csv.Rd | 2 +- ...uo.csv => 20260130_dual_pam_only_fluo.csv} | 0 ...csv => 20260130_01_dual_pam_only_p700.csv} | 0 src/tests/testthat/test-read_dual_pam_data.R | 8 +- ...t-read_dual_pam_single_channel_fluo_data.R | 8 +- ...t-read_dual_pam_single_channel_p700_data.R | 8 +- 57 files changed, 1269 insertions(+), 1327 deletions(-) create mode 100644 src/R/device_dual_pam.R create mode 100644 src/R/device_dual_pam_single_channel_fluo.R create mode 100644 src/R/device_dual_pam_single_channel_p700.R create mode 100644 src/R/device_junior_pam.R create mode 100644 src/R/device_pam_2500.R create mode 100644 src/R/device_universal_data.R rename src/R/{eilers_peeters.R => model_eilers_peeters.R} (99%) rename src/R/{platt.R => model_platt.R} (99%) rename src/R/{vollenweider.R => model_vollenweider.R} (99%) rename src/R/{walsby.R => model_walsby.R} (99%) rename src/R/{combo_plot_control.R => plot.R} (52%) delete mode 100644 src/R/read_pam_data.R create mode 100644 src/R/write_model_result_csv.R rename src/inst/extdata/dual_pam_single_channel_fluo_data/{20260130_efeutute_dual_pam_only_fluo.csv => 20260130_dual_pam_only_fluo.csv} (100%) rename src/inst/extdata/dual_pam_single_channel_p700_data/{20260130_01_efeutute_dual_pam_only_p700.csv => 20260130_01_dual_pam_only_p700.csv} (100%) rename src/tests/testthat/data/dual_pam_single_channel_fluo_data/{20260130_efeutute_dual_pam_only_fluo.csv => 20260130_dual_pam_only_fluo.csv} (100%) rename src/tests/testthat/data/dual_pam_single_channel_p700_data/{20260130_01_efeutute_dual_pam_only_p700.csv => 20260130_01_dual_pam_only_p700.csv} (100%) diff --git a/src/R/compare_regression_models.R b/src/R/compare_regression_models.R index facb739..59832d2 100644 --- a/src/R/compare_regression_models.R +++ b/src/R/compare_regression_models.R @@ -116,7 +116,7 @@ compare_regression_models <- function(data_dir, etr_type, read_func) { for (file in csv_files) { title <- basename(file) data <- do.call(read_func, list(csv_path = file)) - validate_data(data) + validate_intermediate_data(data) tryCatch( { diff --git a/src/R/device_dual_pam.R b/src/R/device_dual_pam.R new file mode 100644 index 0000000..57d7677 --- /dev/null +++ b/src/R/device_dual_pam.R @@ -0,0 +1,170 @@ +#' Read and Process DualPAM Data +#' +#' Reads raw CSV files generated by DualPAM software, calculates electron transport rate (ETR) values, and returns a universal dataset. +#' +#' @param csv_path File path to the CSV file. +#' @param remove_recovery Logical. Removes recovery measurements if \code{TRUE}. Default is \code{TRUE}. +#' @param etr_factor Numeric. Factor for ETR calculation. Default is \code{0.84}. +#' @param fraction_photosystem_I Numeric. Relative distribution of absorbed PAR to photosystem I. Default is \code{0.5}. +#' @param fraction_photosystem_II Numeric. Relative distribution of absorbed PAR to photosystem II. Default is \code{0.5}. +#' +#' @details +#' Calculates ETR using: +#' \deqn{\text{ETR} = \text{PAR} \cdot \text{ETR-Factor} \cdot \text{Fraction of Photosystem (I or II)} \cdot \text{Yield (I or II)}} +#' +#' A detailed documentation can be found under \url{https://github.com/biotoolbox/pam?tab=readme-ov-file#read_dual_pam_data} +#' +#' @return A \code{data.table} containing: +#' \itemize{ +#' \item \code{par}: Photosynthetically active radiation. +#' \item \code{yield_1}: Yield for photosystem I. +#' \item \code{yield_2}: Yield for photosystem II. +#' \item \code{etr_1}: Calculated ETR for photosystem I. +#' \item \code{etr_2}: Calculated ETR for photosystem II. +#' } +#' +#' @references{ +#' Heinz Walz GmbH. (2024). \emph{DUAL-PAM-100 DUAL-PAM/F MANUAL, 5th Edition, April 2024, Chapter 7 (pp. 162-172).} +#' Heinz Walz GmbH, Effeltrich, Germany. +#' Available at: \url{https://www.walz.com/files/downloads/dualpamed05.pdf} +#' } +#' @examples +#' path <- file.path(system.file("extdata/dual_pam_data", package = "pam"), "20240925.csv") +#' data <- read_dual_pam_data(path) +#' @export +read_dual_pam_data <- function( + csv_path, + remove_recovery = TRUE, + etr_factor = 0.84, + fraction_photosystem_I = 0.5, + fraction_photosystem_II = 0.5 +) { + if (fraction_photosystem_I + fraction_photosystem_II != 1) { + stop("The sum of fraction_photosystem_I and fraction_photosystem_II must be equal 1.") + } + + tryCatch( + { + data <- utils::read.csv(csv_path, sep = ";", dec = ".") + data <- data.table::as.data.table(data) + + validate_dual_pam_data(data) + data <- data[data$ID == "SP", ] + + date_time_col_values <- c() + for (i in seq_len(nrow(data))) { + row <- data[i, ] + + date_time_row_value <- as.POSIXct( + paste(row$Date, row$Time, sep = " "), + tz = "GMT", "%d.%m.%y %H:%M:%S" + ) + date_time_col_values <- c(date_time_col_values, date_time_row_value) + } + + data$DateTime <- date_time_col_values + data <- data[order(data$DateTime), ] + + pm_det_row <- subset(data, data$PAR == 0 & data$Action == "Pm.-Det.") + yield_1_first <- pm_det_row$Y.I. + recalc_etr_1 <- calc_etr(yield_1_first, 0, etr_factor, fraction_photosystem_I) + + fm_det_row <- subset(data, data$PAR == 0 & data$Action == "Fm-Det.") + yield_2_first <- fm_det_row$Y.II. + recalc_etr_2 <- calc_etr(yield_2_first, 0, etr_factor, fraction_photosystem_II) + + + result <- data.table::data.table( + par = numeric(), + yield_1 = numeric(), + yield_2 = numeric(), + etr_1 = numeric(), + etr_2 = numeric() + ) + new_row <- list( + par = 0, + yield_1 = yield_1_first, + yield_2 = yield_2_first, + etr_1 = recalc_etr_1, + etr_2 = recalc_etr_2 + ) + result <- rbind(result, new_row) + + last_par <- as.numeric(0) + for (i in seq_len(nrow(data))) { + row <- data[i, ] + current_par <- row$PAR + + if (row$Action != "P.+F. SP") { + next + } + + if (remove_recovery && last_par != 0 && current_par < last_par) { + break + } + + yield_1 <- row$Y.I. + recalc_etr_1 <- calc_etr(yield_1, current_par, etr_factor, fraction_photosystem_I) + + yield_2 <- row$Y.II. + recalc_etr_2 <- calc_etr(yield_2, current_par, etr_factor, fraction_photosystem_II) + + new_row <- list( + par = current_par, + yield_1 = yield_1, + yield_2 = yield_2, + etr_1 = recalc_etr_1, + etr_2 = recalc_etr_2 + ) + result <- rbind(result, new_row) + + last_par <- current_par + } + + validate_intermediate_data(result) + return(result) + }, + warning = function(w) { + stop("Warning in file: ", csv_path, " Warning: ", w) + }, + error = function(e) { + stop("Error in file: ", csv_path, " Error: ", e) + } + ) +} + +validate_dual_pam_data <- function(data) { + validate_data_not_empty(data) + + if (!"ID" %in% colnames(data)) { + stop("required col 'ID' not found") + } + + if (!"PAR" %in% colnames(data)) { + stop("required col 'PAR' not found") + } + + if (!"Y.I." %in% colnames(data) && !"Y.II." %in% colnames(data)) { + stop("required col 'Y(I)' and 'Y(II)' not found") + } + + if (!"Action" %in% colnames(data)) { + stop("required col 'Action' not found") + } + + if (!"Date" %in% colnames(data)) { + stop("required col 'Date' not found") + } + + if (!"Time" %in% colnames(data)) { + stop("required col 'Time' not found") + } + + if (!"Pm.-Det." %in% data[["Action"]]) { + stop("required value 'Pm' not found in column 'Action'") + } + + if (!"Fm-Det." %in% data[["Action"]]) { + stop("required value 'Fm' not found in column 'Action'") + } +} diff --git a/src/R/device_dual_pam_single_channel_fluo.R b/src/R/device_dual_pam_single_channel_fluo.R new file mode 100644 index 0000000..176c3e4 --- /dev/null +++ b/src/R/device_dual_pam_single_channel_fluo.R @@ -0,0 +1,164 @@ +#' Read and Process DualPAM Data Single Chanel Mode Fluo +#' +#' Reads raw CSV files generated by DualPAM software, calculates electron transport rate (ETR) values for Photosystem II, and returns a universal dataset. +#' +#' @param csv_path File path to the CSV file. +#' @param remove_recovery Logical. Removes recovery measurements if \code{TRUE}. Default is \code{TRUE}. +#' @param etr_factor Numeric. Factor for ETR calculation. Default is \code{0.84}. +#' @param fraction_photosystem_I Numeric. Relative distribution of absorbed PAR to photosystem I. Default is \code{0.5}. +#' @param fraction_photosystem_II Numeric. Relative distribution of absorbed PAR to photosystem II. Default is \code{0.5}. +#' +#' @details +#' Calculates ETR using: +#' \deqn{\text{ETR} = \text{PAR} \cdot \text{ETR-Factor} \cdot \text{Fraction of Photosystem (II)} \cdot \text{Yield (II)}} +#' +#' A detailed documentation can be found under \url{https://github.com/biotoolbox/pam?tab=readme-ov-file#read_dual_pam_data} +#' +#' @return A \code{data.table} containing: +#' \itemize{ +#' \item \code{par}: Photosynthetically active radiation. +#' \item \code{yield_1}: NA +#' \item \code{yield_2}: Yield for photosystem II. +#' \item \code{etr_1}: NA +#' \item \code{etr_2}: Calculated ETR for photosystem II. +#' } +#' +#' @references{ +#' Heinz Walz GmbH. (2024). \emph{DUAL-PAM-100 DUAL-PAM/F MANUAL, 5th Edition, April 2024, Chapter 7 (pp. 162-172).} +#' Heinz Walz GmbH, Effeltrich, Germany. +#' Available at: \url{https://www.walz.com/files/downloads/dualpamed05.pdf} +#' } +#' @examples +#' path <- file.path( +#' system.file("extdata/dual_pam_single_channel_fluo_data", package = "pam"), +#' "20260130_dual_pam_only_fluo.csv" +#' ) +#' data <- read_dual_pam_single_channel_fluo_data(path) +#' @export +read_dual_pam_single_channel_fluo_data <- function( + csv_path, + remove_recovery = TRUE, + etr_factor = 0.84, + fraction_photosystem_I = 0.5, + fraction_photosystem_II = 0.5 +) { + if (fraction_photosystem_I + fraction_photosystem_II != 1) { + stop("The sum of fraction_photosystem_I and fraction_photosystem_II must be equal 1.") + } + + tryCatch( + { + data <- utils::read.csv(csv_path, sep = ";", dec = ".") + data <- data.table::as.data.table(data) + + validate_dual_pam_single_channel_fluo_data(data) + data <- data[data$ID == "SP", ] + + date_time_col_values <- c() + for (i in seq_len(nrow(data))) { + row <- data[i, ] + + date_time_row_value <- as.POSIXct( + paste(row$Date, row$Time, sep = " "), + tz = "GMT", "%d.%m.%y %H:%M:%S" + ) + date_time_col_values <- c(date_time_col_values, date_time_row_value) + } + + data$DateTime <- date_time_col_values + data <- data[order(data$DateTime), ] + + fm_det_row <- subset(data, data$PAR == 0 & data$Action == "Fm-Det.") + yield_2_first <- fm_det_row$Y.II. + recalc_etr_2 <- calc_etr( + yield_2_first, 0, etr_factor, fraction_photosystem_II + ) + + + result <- data.table::data.table( + par = numeric(), + yield_1 = numeric(), + yield_2 = numeric(), + etr_1 = numeric(), + etr_2 = numeric() + ) + new_row <- list( + par = 0, + yield_1 = NA_real_, + yield_2 = yield_2_first, + etr_1 = NA_real_, + etr_2 = recalc_etr_2 + ) + result <- rbind(result, new_row) + + last_par <- as.numeric(0) + for (i in seq_len(nrow(data))) { + row <- data[i, ] + current_par <- row$PAR + + if (row$Action != "Fluo. SP") { + next + } + + if (remove_recovery && last_par != 0 && current_par < last_par) { + break + } + + yield_2 <- row$Y.II. + recalc_etr_2 <- calc_etr(yield_2, current_par, etr_factor, fraction_photosystem_II) + + new_row <- list( + par = current_par, + yield_1 = NA_real_, + yield_2 = yield_2, + etr_1 = NA_real_, + etr_2 = recalc_etr_2 + ) + result <- rbind(result, new_row) + + last_par <- current_par + } + + validate_intermediate_data(result) + return(result) + }, + warning = function(w) { + stop("Warning in file: ", csv_path, " Warning: ", w) + }, + error = function(e) { + stop("Error in file: ", csv_path, " Error: ", e) + } + ) +} + +validate_dual_pam_single_channel_fluo_data <- function(data) { + validate_data_not_empty(data) + + if (!"ID" %in% colnames(data)) { + stop("required col 'ID' not found") + } + + if (!"PAR" %in% colnames(data)) { + stop("required col 'PAR' not found") + } + + if (!"Y.II." %in% colnames(data)) { + stop("required col 'Y(II)' not found") + } + + if (!"Action" %in% colnames(data)) { + stop("required col 'Action' not found") + } + + if (!"Date" %in% colnames(data)) { + stop("required col 'Date' not found") + } + + if (!"Time" %in% colnames(data)) { + stop("required col 'Time' not found") + } + + if (!"Fm-Det." %in% data[["Action"]]) { + stop("required value 'Fm' not found in column 'Action'") + } +} diff --git a/src/R/device_dual_pam_single_channel_p700.R b/src/R/device_dual_pam_single_channel_p700.R new file mode 100644 index 0000000..0f6ff75 --- /dev/null +++ b/src/R/device_dual_pam_single_channel_p700.R @@ -0,0 +1,162 @@ +#' Read and Process DualPAM Data Single Chanel Mode P700 +#' +#' Reads raw CSV files generated by DualPAM software, calculates electron transport rate (ETR) values for Photosystem I, and returns a universal dataset. +#' +#' @param csv_path File path to the CSV file. +#' @param remove_recovery Logical. Removes recovery measurements if \code{TRUE}. Default is \code{TRUE}. +#' @param etr_factor Numeric. Factor for ETR calculation. Default is \code{0.84}. +#' @param fraction_photosystem_I Numeric. Relative distribution of absorbed PAR to photosystem I. Default is \code{0.5}. +#' @param fraction_photosystem_II Numeric. Relative distribution of absorbed PAR to photosystem II. Default is \code{0.5}. +#' +#' @details +#' Calculates ETR using: +#' \deqn{\text{ETR} = \text{PAR} \cdot \text{ETR-Factor} \cdot \text{Fraction of Photosystem (I)} \cdot \text{Yield (I)}} +#' +#' A detailed documentation can be found under \url{https://github.com/biotoolbox/pam?tab=readme-ov-file#read_dual_pam_data} +#' +#' @return A \code{data.table} containing: +#' \itemize{ +#' \item \code{par}: Photosynthetically active radiation. +#' \item \code{yield_1}: Yield for photosystem I +#' \item \code{yield_2}: NA +#' \item \code{etr_1}: Calculated ETR for photosystem I +#' \item \code{etr_2}: NA +#' } +#' +#' @references{ +#' Heinz Walz GmbH. (2024). \emph{DUAL-PAM-100 DUAL-PAM/F MANUAL, 5th Edition, April 2024, Chapter 7 (pp. 162-172).} +#' Heinz Walz GmbH, Effeltrich, Germany. +#' Available at: \url{https://www.walz.com/files/downloads/dualpamed05.pdf} +#' } +#' @examples +#' path <- file.path( +#' system.file("extdata/dual_pam_single_channel_p700_data", package = "pam"), +#' "20260130_01_dual_pam_only_p700.csv" +#' ) +#' data <- read_dual_pam_single_channel_p700_data(path) +#' @export +read_dual_pam_single_channel_p700_data <- function( + csv_path, + remove_recovery = TRUE, + etr_factor = 0.84, + fraction_photosystem_I = 0.5, + fraction_photosystem_II = 0.5 +) { + if (fraction_photosystem_I + fraction_photosystem_II != 1) { + stop("The sum of fraction_photosystem_I and fraction_photosystem_II must be equal 1.") + } + + tryCatch( + { + data <- utils::read.csv(csv_path, sep = ";", dec = ".") + data <- data.table::as.data.table(data) + + validate_dual_pam_single_channel_p700_data(data) + data <- data[data$ID == "SP", ] + + date_time_col_values <- c() + for (i in seq_len(nrow(data))) { + row <- data[i, ] + + date_time_row_value <- as.POSIXct( + paste(row$Date, row$Time, sep = " "), + tz = "GMT", "%d.%m.%y %H:%M:%S" + ) + date_time_col_values <- c(date_time_col_values, date_time_row_value) + } + + data$DateTime <- date_time_col_values + data <- data[order(data$DateTime), ] + + pm_det_row <- subset(data, data$PAR == 0 & data$Action == "Pm.-Det.") + yield_1_first <- pm_det_row$Y.I. + recalc_etr_1 <- calc_etr(yield_1_first, 0, etr_factor, fraction_photosystem_I) + + + result <- data.table::data.table( + par = numeric(), + yield_1 = numeric(), + yield_2 = numeric(), + etr_1 = numeric(), + etr_2 = numeric() + ) + new_row <- list( + par = 0, + yield_1 = yield_1_first, + yield_2 = NA_real_, + etr_1 = recalc_etr_1, + etr_2 = NA_real_ + ) + result <- rbind(result, new_row) + + last_par <- as.numeric(0) + for (i in seq_len(nrow(data))) { + row <- data[i, ] + current_par <- row$PAR + + if (row$Action != "P700 SP") { + next + } + + if (remove_recovery && last_par != 0 && current_par < last_par) { + break + } + + yield_1 <- row$Y.I. + recalc_etr_1 <- calc_etr(yield_1, current_par, etr_factor, fraction_photosystem_I) + + new_row <- list( + par = current_par, + yield_1 = yield_1, + yield_2 = NA_real_, + etr_1 = recalc_etr_1, + etr_2 = NA_real_ + ) + result <- rbind(result, new_row) + + last_par <- current_par + } + + validate_intermediate_data(result) + return(result) + }, + warning = function(w) { + stop("Warning in file: ", csv_path, " Warning: ", w) + }, + error = function(e) { + stop("Error in file: ", csv_path, " Error: ", e) + } + ) +} + +validate_dual_pam_single_channel_p700_data <- function(data) { + validate_data_not_empty(data) + + if (!"ID" %in% colnames(data)) { + stop("required col 'ID' not found") + } + + if (!"PAR" %in% colnames(data)) { + stop("required col 'PAR' not found") + } + + if (!"Y.I." %in% colnames(data)) { + stop("required col 'Y(I)' not found") + } + + if (!"Action" %in% colnames(data)) { + stop("required col 'Action' not found") + } + + if (!"Date" %in% colnames(data)) { + stop("required col 'Date' not found") + } + + if (!"Time" %in% colnames(data)) { + stop("required col 'Time' not found") + } + + if (!"Pm.-Det." %in% data[["Action"]]) { + stop("required value 'Pm.-Det.' not found in column 'Action'") + } +} diff --git a/src/R/device_junior_pam.R b/src/R/device_junior_pam.R new file mode 100644 index 0000000..92e8a5b --- /dev/null +++ b/src/R/device_junior_pam.R @@ -0,0 +1,125 @@ +#' Read and Process Junior PAM Data +#' +#' Reads raw CSV files generated by Junior PAM software, calculates electron transport rate (ETR) values, and returns a cleaned dataset. +#' +#' @param csv_path File path to the CSV file. +#' @param remove_recovery Logical. Removes recovery measurements if \code{TRUE}. Default is \code{TRUE}. +#' @param etr_factor Numeric. Factor for ETR calculation. Default is \code{0.84}. +#' @param fraction_photosystem_I Numeric. Relative distribution of absorbed PAR to photosystem I. Default is \code{0.5}. +#' @param fraction_photosystem_II Numeric. Relative distribution of absorbed PAR to photosystem II. Default is \code{0.5}. +#' +#' @details +#' Calculates ETR II using: +#' \deqn{\text{ETR II} = \text{PAR} \cdot \text{ETR-Factor} \cdot \text{Fraction of Photosystem (II)} \cdot \text{Yield (II)}} +#' +#' A detailed documentation can be found under \url{https://github.com/biotoolbox/pam?tab=readme-ov-file} +#' +#' @return A \code{data.table} containing: +#' \itemize{ +#' \item \code{par}: Photosynthetically active radiation. +#' \item \code{yield_1}: Yield for photosystem I. +#' \item \code{yield_2}: Yield for photosystem II. +#' \item \code{etr_1}: Calculated ETR for photosystem I. +#' \item \code{etr_2}: Calculated ETR for photosystem II. +#' } +#' +#' @references{ +#' Heinz Walz GmbH. (2024). \emph{DUAL-PAM-100 DUAL-PAM/F MANUAL, 5th Edition, April 2024, Chapter 7 (pp. 162-172).} +#' Heinz Walz GmbH, Effeltrich, Germany. +#' Available at: \url{https://www.walz.com/files/downloads/dualpamed05.pdf} +#' } +#' @examples +#' path <- file.path( +#' system.file("extdata/junior_pam_data", package = "pam"), +#' "2026_04_22_junior_pam.csv" +#' ) +#' data <- read_junior_pam_data(path) +#' @export +read_junior_pam_data <- function( + csv_path, + remove_recovery = TRUE, + etr_factor = 0.84, + fraction_photosystem_I = 0.5, + fraction_photosystem_II = 0.5 +) { + if (fraction_photosystem_I + fraction_photosystem_II != 1) { + stop("The sum of fraction_photosystem_I and fraction_photosystem_II must be equal 1.") + } + + tryCatch( + { + data <- utils::read.csv(csv_path, sep = ";", dec = ".", skip = 1, header = TRUE) + data <- data.table::as.data.table(data) + + validate_junior_pam_data(data) + + par_col <- grep("^.+\\.PAR$", names(data), value = TRUE)[1] + yield_2_col <- grep("^.+\\.Y\\.\\.II\\.$", names(data), value = TRUE)[1] + + data <- data[data$Type == "FO" | data$Type == "F", ] + data <- data[order(data$"Time..rel.ms."), ] + + result <- data.table::data.table( + par = numeric(), + yield_1 = numeric(), + yield_2 = numeric(), + etr_1 = numeric(), + etr_2 = numeric() + ) + last_par <- as.numeric(0) + for (i in seq_len(nrow(data))) { + row <- data[i, ] + current_par <- row[[par_col]] + + if (remove_recovery && last_par != 0 && current_par < last_par) { + break + } + + yield_2 <- row[[yield_2_col]] + recalc_etr_2 <- calc_etr(yield_2, current_par, etr_factor, fraction_photosystem_II) + + new_row <- list( + par = current_par, + yield_1 = NA_real_, + yield_2 = yield_2, + etr_1 = NA_real_, + etr_2 = recalc_etr_2 + ) + result <- rbind(result, new_row) + + last_par <- current_par + } + + validate_intermediate_data(result) + return(result) + }, + warning = function(w) { + stop("Warning in file: ", csv_path, " Warning: ", w) + }, + error = function(e) { + stop("Error in file: ", csv_path, " Error: ", e) + } + ) +} + +validate_junior_pam_data <- function(data) { + validate_data_not_empty(data) + + par_cols <- grep("^.+\\.PAR$", names(data), value = TRUE) + if (length(par_cols) == 0) { + stop("required col 'PAR' not found") + } else if (length(par_cols) > 1) { + stop(paste(length(par_cols), " 'PAR' cols found. Only supporting one 'PAR' column")) + } + + yield_cols <- grep("^.+\\.Y\\.\\.II\\.$", names(data), value = TRUE) + if (length(yield_cols) == 0) { + stop("required col 'Y (II)' not found") + } else if (length(yield_cols) > 1) { + stop(paste(length(yield_cols), " 'Y (II)' cols found. Only supporting one 'Y (II)' column")) + } + + if (!"Time..rel.ms." %in% colnames(data)) { + stop("required col 'Time (rel/ms)' not found") + } +} diff --git a/src/R/device_pam_2500.R b/src/R/device_pam_2500.R new file mode 100644 index 0000000..0389338 --- /dev/null +++ b/src/R/device_pam_2500.R @@ -0,0 +1,133 @@ +#' Read and Process PAM 2500 Data +#' +#' Reads raw CSV files generated by PAM 2500 software, calculates electron transport rate (ETR) values, and returns a cleaned dataset. +#' +#' @param csv_path File path to the CSV file. +#' @param remove_recovery Logical. Removes recovery measurements if \code{TRUE}. Default is \code{TRUE}. +#' @param etr_factor Numeric. Factor for ETR calculation. Default is \code{0.84}. +#' @param fraction_photosystem_I Numeric. Relative distribution of absorbed PAR to photosystem I. Default is \code{0.5}. +#' @param fraction_photosystem_II Numeric. Relative distribution of absorbed PAR to photosystem II. Default is \code{0.5}. +#' +#' @details +#' Calculates ETR II using: +#' \deqn{\text{ETR II} = \text{PAR} \cdot \text{ETR-Factor} \cdot \text{Fraction of Photosystem (II)} \cdot \text{Yield (II)}} +#' +#' A detailed documentation can be found under \url{https://github.com/biotoolbox/pam?tab=readme-ov-file} +#' +#' @return A \code{data.table} containing: +#' \itemize{ +#' \item \code{par}: Photosynthetically active radiation. +#' \item \code{yield_1}: Yield for photosystem I. +#' \item \code{yield_2}: Yield for photosystem II. +#' \item \code{etr_1}: Calculated ETR for photosystem I. +#' \item \code{etr_2}: Calculated ETR for photosystem II. +#' } +#' +#' @references{ +#' Heinz Walz GmbH. (2024). \emph{DUAL-PAM-100 DUAL-PAM/F MANUAL, 5th Edition, April 2024, Chapter 7 (pp. 162-172).} +#' Heinz Walz GmbH, Effeltrich, Germany. +#' Available at: \url{https://www.walz.com/files/downloads/dualpamed05.pdf} +#' } +#' @examples +#' path <- file.path(system.file("extdata/pam_2500_data", package = "pam"), "20260422_pam_2500.CSV") +#' data <- read_pam_2500_data(path) +#' @export +read_pam_2500_data <- function( + csv_path, + remove_recovery = TRUE, + etr_factor = 0.84, + fraction_photosystem_I = 0.5, + fraction_photosystem_II = 0.5 +) { + if (fraction_photosystem_I + fraction_photosystem_II != 1) { + stop("The sum of fraction_photosystem_I and fraction_photosystem_II must be equal 1.") + } + + tryCatch( + { + data <- utils::read.csv(csv_path, sep = ";", dec = ".") + data <- data.table::as.data.table(data) + + validate_pam_2500_data(data) + data <- data[grepl("^\\d+$", data$`No.`), ] + + date_time_col_values <- c() + for (i in seq_len(nrow(data))) { + row <- data[i, ] + + date_time_row_value <- as.POSIXct( + paste(row$Date, row$Time, sep = " "), + tz = "GMT", "%d.%m.%y %H:%M:%S" + ) + date_time_col_values <- c(date_time_col_values, date_time_row_value) + } + + data$DateTime <- date_time_col_values + data <- data[order(data$DateTime), ] + + result <- data.table::data.table( + par = numeric(), + yield_1 = numeric(), + yield_2 = numeric(), + etr_1 = numeric(), + etr_2 = numeric() + ) + last_par <- as.numeric(0) + for (i in seq_len(nrow(data))) { + row <- data[i, ] + current_par <- row$PAR + + if (remove_recovery && last_par != 0 && current_par < last_par) { + break + } + + yield_2 <- row$Y.II. + recalc_etr_2 <- calc_etr(yield_2, current_par, etr_factor, fraction_photosystem_II) + + new_row <- list( + par = current_par, + yield_1 = NA_real_, + yield_2 = yield_2, + etr_1 = NA_real_, + etr_2 = recalc_etr_2 + ) + result <- rbind(result, new_row) + + last_par <- current_par + } + + validate_intermediate_data(result) + return(result) + }, + warning = function(w) { + stop("Warning in file: ", csv_path, " Warning: ", w) + }, + error = function(e) { + stop("Error in file: ", csv_path, " Error: ", e) + } + ) +} + +validate_pam_2500_data <- function(data) { + validate_data_not_empty(data) + + if (!"No." %in% colnames(data)) { + stop("required col 'No.' not found") + } + + if (!"PAR" %in% colnames(data)) { + stop("required col 'PAR' not found") + } + + if (!"Date" %in% colnames(data)) { + stop("required col 'Date' not found") + } + + if (!"Time" %in% colnames(data)) { + stop("required col 'Time' not found") + } + + if (!"Y.II." %in% colnames(data)) { + stop("required col 'Y(II)' not found") + } +} diff --git a/src/R/device_universal_data.R b/src/R/device_universal_data.R new file mode 100644 index 0000000..ddc6941 --- /dev/null +++ b/src/R/device_universal_data.R @@ -0,0 +1,93 @@ +#' Read and Process Universal PAM Data +#' +#' Reads a standardized CSV file containing PAR and yield data for photosystem I and/or II, calculates electron transport rates (ETR), and returns a cleaned and validated dataset. The function is device-agnostic but requires a predefined column structure. +#' +#' @param csv_path File path to the CSV file. +#' @param etr_factor Numeric. Factor for ETR calculation. Default is \code{0.84}. +#' @param fraction_photosystem_I Numeric. Relative distribution of absorbed PAR +#' to photosystem I. Default is \code{0.5}. +#' @param fraction_photosystem_II Numeric. Relative distribution of absorbed PAR +#' to photosystem II. Default is \code{0.5}. +#' +#' @details +#' Calculates ETR using: +#' \deqn{\text{ETR} = \text{PAR} \cdot \text{ETR-Factor} \cdot \text{Fraction of Photosystem (I or II)} \cdot \text{Yield (I or II)}} +#' +#' A detailed documentation can be found under \url{https://github.com/biotoolbox/pam?tab=readme-ov-file#read_universal_data} +#' +#' @return A \code{data.table} containing: +#' \itemize{ +#' \item \code{par}: Photosynthetically active radiation. +#' \item \code{yield_1}: Yield for photosystem I. +#' \item \code{yield_2}: Yield for photosystem II. +#' \item \code{etr_1}: Calculated ETR for photosystem I. +#' \item \code{etr_2}: Calculated ETR for photosystem II. +#' } +#' +#' @references{ +#' Heinz Walz GmbH. (2024). \emph{DUAL-PAM-100 DUAL-PAM/F MANUAL, 5th Edition, April 2024, Chapter 7 (pp. 162-172).} +#' Heinz Walz GmbH, Effeltrich, Germany. +#' Available at: \url{https://www.walz.com/files/downloads/dualpamed05.pdf} +#' } +#' @examples +#' path <- file.path(system.file("extdata", package = "pam"), "universal_data", "universal_data.csv") +#' data <- read_universal_data(path) +#' @export +read_universal_data <- function(csv_path, + etr_factor = 0.84, + fraction_photosystem_I = 0.5, + fraction_photosystem_II = 0.5) { + if (fraction_photosystem_I + fraction_photosystem_II != 1) { + stop("The sum of fraction_photosystem_I and fraction_photosystem_II must be equal 1.") + } + + data <- utils::read.csv(csv_path, sep = ";", dec = ".") + data <- data.table::as.data.table(data) + validate_universal_data(data) + + result <- data.table::data.table( + par = numeric(), + yield_1 = numeric(), + yield_2 = numeric(), + etr_1 = numeric(), + etr_2 = numeric() + ) + for (i in seq_len(nrow(data))) { + row <- data[i, ] + current_par <- row$par + + yield_1 <- row$yield_1 + recalc_etr_1 <- calc_etr(yield_1, current_par, etr_factor, fraction_photosystem_I) + + yield_2 <- row$yield_2 + recalc_etr_2 <- calc_etr(yield_2, current_par, etr_factor, fraction_photosystem_II) + + new_row <- list( + par = current_par, + yield_1 = yield_1, + yield_2 = yield_2, + etr_1 = recalc_etr_1, + etr_2 = recalc_etr_2 + ) + result <- rbind(result, new_row) + } + + validate_intermediate_data(result) + return(result) +} + +validate_universal_data <- function(data) { + validate_data_not_empty(data) + + if (!"par" %in% colnames(data)) { + stop("required col 'par' not found") + } + + if (!"yield_1" %in% colnames(data)) { + stop("required col 'yield_1' not found") + } + + if (!"yield_2" %in% colnames(data)) { + stop("required col 'yield_2' not found") + } +} diff --git a/src/R/eilers_peeters.R b/src/R/model_eilers_peeters.R similarity index 99% rename from src/R/eilers_peeters.R rename to src/R/model_eilers_peeters.R index d122966..db50ac0 100644 --- a/src/R/eilers_peeters.R +++ b/src/R/model_eilers_peeters.R @@ -132,7 +132,7 @@ eilers_peeters_generate_regression_internal <- function( ) { tryCatch( { - validate_data(data) + validate_intermediate_data(data) validate_etr_type(etr_type) if (!is.numeric(a_start_value)) { diff --git a/src/R/platt.R b/src/R/model_platt.R similarity index 99% rename from src/R/platt.R rename to src/R/model_platt.R index 19435ab..9fab2ed 100644 --- a/src/R/platt.R +++ b/src/R/model_platt.R @@ -137,7 +137,7 @@ platt_generate_regression_internal <- function( ) { tryCatch( { - validate_data(data) + validate_intermediate_data(data) validate_etr_type(etr_type) if (!is.numeric(alpha_start_value)) { diff --git a/src/R/vollenweider.R b/src/R/model_vollenweider.R similarity index 99% rename from src/R/vollenweider.R rename to src/R/model_vollenweider.R index aae0ece..485a3e8 100644 --- a/src/R/vollenweider.R +++ b/src/R/model_vollenweider.R @@ -147,7 +147,7 @@ vollenweider_generate_regression_internal <- function( tryCatch( { validate_etr_type(etr_type) - validate_data(data) + validate_intermediate_data(data) if (!is.numeric(pmax_start_value)) { stop("pmax start value is not a valid number") diff --git a/src/R/walsby.R b/src/R/model_walsby.R similarity index 99% rename from src/R/walsby.R rename to src/R/model_walsby.R index 341d0f2..b321458 100644 --- a/src/R/walsby.R +++ b/src/R/model_walsby.R @@ -136,7 +136,7 @@ walsby_generate_regression_internal <- function( beta_start_value = walsby_default_start_value_beta) { tryCatch( { - validate_data(data) + validate_intermediate_data(data) validate_etr_type(etr_type) if (!is.numeric(etr_max_start_value)) { diff --git a/src/R/combo_plot_control.R b/src/R/plot.R similarity index 52% rename from src/R/combo_plot_control.R rename to src/R/plot.R index c2c12ea..a3a88e3 100644 --- a/src/R/combo_plot_control.R +++ b/src/R/plot.R @@ -36,7 +36,7 @@ combo_plot_control <- function( name_list, color_list ) { - validate_data(data) + validate_intermediate_data(data) if (length(model_results) <= 0) { stop("empty model_results") @@ -228,3 +228,213 @@ combo_plot_control <- function( return(plot) } + + +plot_table <- function(model_result, entries_per_row) { + validate_model_result(model_result) + + custom_theme <- gridExtra::ttheme_minimal( + core = list( + fg_params = list( + cex = 0.7, + fontface = 3 + ), + bg_params = list( + fill = "lightgray", + col = "black" + ) + ), # font size for cell text + colhead = list( + fg_params = list(cex = 0.7), + bg_params = list( + fill = "lightgray", + col = "black" + ) + ), # font size for column headers + rowhead = list( + fg_params = list(cex = 0.7), + bg_params = list( + fill = "lightgray", + col = "black" + ) + ), # font size for row headers + ) + + tbl_list <- list() + row <- NULL + + row_count <- 1 + count <- 1 + + for (i in names(model_result)) { + if (i == "etr_type" || i == "etr_regression_data") { + next() + } + + value <- model_result[[i]] + + if (is.null(row)) { + row <- data.frame(tmp = NA) + } + + row[[i]] <- c(value) + + if (count == entries_per_row) { + row$tmp <- NULL + tbl_list[[row_count]] <- gridExtra::tableGrob( + row, + rows = NULL, + theme = custom_theme + ) + + row <- NULL + row_count <- row_count + 1 + count <- 1 + } else { + count <- count + 1 + } + } + + if (is.null(row) == FALSE) { + row$tmp <- NULL + tbl_list[[row_count]] <- gridExtra::tableGrob( + row, + rows = NULL, + theme = custom_theme + ) + } + + tbl <- cowplot::plot_grid( + plotlist = tbl_list, + ncol = 1 + ) + return(tbl) +} + +#' @title Plot Control +#' @description This function creates a control plot for the used model based on the provided data and model results. +#' +#' @param data A `data.table` containing the original ETR and yield data for the plot. +#' @param model_result A list containing the fitting results of the used model and the calculated parameters. +#' @param title A character string that specifies the title of the plot. +#' @param color A color specification for the regression line in the plot. +#' +#' @details +#' A detailed documentation can be found under \url{https://github.com/biotoolbox/pam?tab=readme-ov-file#plot_control} +#' +#' @return A plot displaying the original ETR and Yield values and the regression data. A table below the plot shows the calculated data. +#' +#' @examples +#' path <- file.path(system.file("extdata/dual_pam_data", package = "pam"), "20240925.csv") +#' data <- read_dual_pam_data(path) +#' +#' result <- eilers_peeters_generate_regression_ETR_I(data) +#' plot_control(data, result, "Control Plot") +#' +#' @export +plot_control <- function( + data, + model_result, + title, + color = "black" +) { + validate_intermediate_data(data) + validate_model_result(model_result) + + etr_type <- get_etr_type_from_model_result(model_result) + validate_etr_type(etr_type) + + yield <- NA_real_ + yield_name <- "" + if (etr_type == etr_1_type) { + yield <- "yield_1" + yield_name <- "Y(I)" + } else { + yield <- "yield_2" + yield_name <- "Y(II)" + } + + etr_regression_data <- get_etr_regression_data_from_model_result(model_result) + validate_etr_regression_data(etr_regression_data) + + max_etr <- max(etr_regression_data$prediction) + + plot <- ggplot2::ggplot(data, ggplot2::aes(x = data$par, y = get(etr_type))) + + ggplot2::geom_point() + + ggplot2::geom_line( + data = etr_regression_data, + ggplot2::aes( + x = etr_regression_data$par, + y = etr_regression_data$prediction + ), + color = color + ) + + ggplot2::geom_point(data = data, shape = 17, ggplot2::aes(y = get(yield) * max_etr)) + + ggplot2::geom_line(data = data, ggplot2::aes(y = get(yield) * max_etr)) + + ggplot2::labs(x = par_label, y = etr_label, title = eval(title)) + + ggplot2::scale_y_continuous( + sec.axis = ggplot2::sec_axis(~ . / max_etr, name = yield_name) + ) + + ggthemes::theme_base() + + ggplot2::theme( + plot.background = ggplot2::element_rect(fill = "white", color = NA), + panel.background = ggplot2::element_rect(fill = "white", color = NA) + ) + + + tbl <- plot_table(model_result, 4) + + plot <- cowplot::plot_grid( + plot, + tbl, + ncol = 1, + rel_heights = c(0.7, 0.3) + ) + return(plot) +} + +create_modified_model_result <- function( + etr_type, + etr_regression_data, + residual_sum_of_squares, + root_mean_squared_error, + relative_root_mean_squared_error, + a, + b, + c, + d, + alpha, + beta, + etrmax_with_photoinhibition, + etrmax_without_photoinhibition, + ik_with_photoinhibition, + ik_without_photoinhibition, + im_with_photoinhibition, + w, + ib, + etrmax_without_with_ratio +) { + result <- list( + etr_type = etr_type, + etr_regression_data = etr_regression_data, + residual_sum_of_squares = residual_sum_of_squares, + root_mean_squared_error = root_mean_squared_error, + relative_root_mean_squared_error = relative_root_mean_squared_error, + a = a, + b = b, + c = c, + d = d, + alpha = alpha, + beta = beta, + etrmax_with_photoinhibition = etrmax_with_photoinhibition, + etrmax_without_photoinhibition = etrmax_without_photoinhibition, + ik_with_photoinhibition = ik_with_photoinhibition, + ik_without_photoinhibition = ik_without_photoinhibition, + im_with_photoinhibition = im_with_photoinhibition, + w = w, + ib = ib, + etrmax_without_with_ratio = etrmax_without_with_ratio + ) + validate_modified_model_result(result) + return(result) +} diff --git a/src/R/read_pam_data.R b/src/R/read_pam_data.R deleted file mode 100644 index 139288b..0000000 --- a/src/R/read_pam_data.R +++ /dev/null @@ -1,711 +0,0 @@ -#' Read and Process Universal PAM Data -#' -#' Reads a standardized CSV file containing PAR and yield data for photosystem I and/or II, calculates electron transport rates (ETR), and returns a cleaned and validated dataset. The function is device-agnostic but requires a predefined column structure. -#' -#' @param csv_path File path to the CSV file. -#' @param etr_factor Numeric. Factor for ETR calculation. Default is \code{0.84}. -#' @param fraction_photosystem_I Numeric. Relative distribution of absorbed PAR -#' to photosystem I. Default is \code{0.5}. -#' @param fraction_photosystem_II Numeric. Relative distribution of absorbed PAR -#' to photosystem II. Default is \code{0.5}. -#' -#' @details -#' Calculates ETR using: -#' \deqn{\text{ETR} = \text{PAR} \cdot \text{ETR-Factor} \cdot \text{Fraction of Photosystem (I or II)} \cdot \text{Yield (I or II)}} -#' -#' A detailed documentation can be found under \url{https://github.com/biotoolbox/pam?tab=readme-ov-file#read_universal_data} -#' -#' @return A \code{data.table} containing: -#' \itemize{ -#' \item \code{par}: Photosynthetically active radiation. -#' \item \code{yield_1}: Yield for photosystem I. -#' \item \code{yield_2}: Yield for photosystem II. -#' \item \code{etr_1}: Calculated ETR for photosystem I. -#' \item \code{etr_2}: Calculated ETR for photosystem II. -#' } -#' -#' @references{ -#' Heinz Walz GmbH. (2024). \emph{DUAL-PAM-100 DUAL-PAM/F MANUAL, 5th Edition, April 2024, Chapter 7 (pp. 162-172).} -#' Heinz Walz GmbH, Effeltrich, Germany. -#' Available at: \url{https://www.walz.com/files/downloads/dualpamed05.pdf} -#' } -#' @examples -#' path <- file.path(system.file("extdata", package = "pam"), "universal_data", "universal_data.csv") -#' data <- read_universal_data(path) -#' @export -read_universal_data <- function(csv_path, - etr_factor = 0.84, - fraction_photosystem_I = 0.5, - fraction_photosystem_II = 0.5) { - if (fraction_photosystem_I + fraction_photosystem_II != 1) { - stop("The sum of fraction_photosystem_I and fraction_photosystem_II must be equal 1.") - } - - data <- utils::read.csv(csv_path, sep = ";", dec = ".") - data <- data.table::as.data.table(data) - validate_raw_intermediate_csv(data) - - result <- data.table::data.table( - par = numeric(), - yield_1 = numeric(), - yield_2 = numeric(), - etr_1 = numeric(), - etr_2 = numeric() - ) - for (i in seq_len(nrow(data))) { - row <- data[i, ] - current_par <- row$par - - yield_1 <- row$yield_1 - recalc_etr_1 <- calc_etr(yield_1, current_par, etr_factor, fraction_photosystem_I) - - yield_2 <- row$yield_2 - recalc_etr_2 <- calc_etr(yield_2, current_par, etr_factor, fraction_photosystem_II) - - new_row <- list( - par = current_par, - yield_1 = yield_1, - yield_2 = yield_2, - etr_1 = recalc_etr_1, - etr_2 = recalc_etr_2 - ) - result <- rbind(result, new_row) - } - - validate_data(result) - return(result) -} - -#' Read and Process DualPAM Data -#' -#' Reads raw CSV files generated by DualPAM software, calculates electron transport rate (ETR) values, and returns a universal dataset. -#' -#' @param csv_path File path to the CSV file. -#' @param remove_recovery Logical. Removes recovery measurements if \code{TRUE}. Default is \code{TRUE}. -#' @param etr_factor Numeric. Factor for ETR calculation. Default is \code{0.84}. -#' @param fraction_photosystem_I Numeric. Relative distribution of absorbed PAR to photosystem I. Default is \code{0.5}. -#' @param fraction_photosystem_II Numeric. Relative distribution of absorbed PAR to photosystem II. Default is \code{0.5}. -#' -#' @details -#' Calculates ETR using: -#' \deqn{\text{ETR} = \text{PAR} \cdot \text{ETR-Factor} \cdot \text{Fraction of Photosystem (I or II)} \cdot \text{Yield (I or II)}} -#' -#' A detailed documentation can be found under \url{https://github.com/biotoolbox/pam?tab=readme-ov-file#read_dual_pam_data} -#' -#' @return A \code{data.table} containing: -#' \itemize{ -#' \item \code{par}: Photosynthetically active radiation. -#' \item \code{yield_1}: Yield for photosystem I. -#' \item \code{yield_2}: Yield for photosystem II. -#' \item \code{etr_1}: Calculated ETR for photosystem I. -#' \item \code{etr_2}: Calculated ETR for photosystem II. -#' } -#' -#' @references{ -#' Heinz Walz GmbH. (2024). \emph{DUAL-PAM-100 DUAL-PAM/F MANUAL, 5th Edition, April 2024, Chapter 7 (pp. 162-172).} -#' Heinz Walz GmbH, Effeltrich, Germany. -#' Available at: \url{https://www.walz.com/files/downloads/dualpamed05.pdf} -#' } -#' @examples -#' path <- file.path(system.file("extdata/dual_pam_data", package = "pam"), "20240925.csv") -#' data <- read_dual_pam_data(path) -#' @export -read_dual_pam_data <- function( - csv_path, - remove_recovery = TRUE, - etr_factor = 0.84, - fraction_photosystem_I = 0.5, - fraction_photosystem_II = 0.5 -) { - if (fraction_photosystem_I + fraction_photosystem_II != 1) { - stop("The sum of fraction_photosystem_I and fraction_photosystem_II must be equal 1.") - } - - tryCatch( - { - data <- utils::read.csv(csv_path, sep = ";", dec = ".") - data <- data.table::as.data.table(data) - - validate_dual_pam_data(data) - data <- data[data$ID == "SP", ] - - date_time_col_values <- c() - for (i in seq_len(nrow(data))) { - row <- data[i, ] - - date_time_row_value <- as.POSIXct( - paste(row$Date, row$Time, sep = " "), - tz = "GMT", "%d.%m.%y %H:%M:%S" - ) - date_time_col_values <- c(date_time_col_values, date_time_row_value) - } - - data$DateTime <- date_time_col_values - data <- data[order(data$DateTime), ] - - pm_det_row <- subset(data, data$PAR == 0 & data$Action == "Pm.-Det.") - yield_1_first <- pm_det_row$Y.I. - recalc_etr_1 <- calc_etr(yield_1_first, 0, etr_factor, fraction_photosystem_I) - - fm_det_row <- subset(data, data$PAR == 0 & data$Action == "Fm-Det.") - yield_2_first <- fm_det_row$Y.II. - recalc_etr_2 <- calc_etr(yield_2_first, 0, etr_factor, fraction_photosystem_II) - - - result <- data.table::data.table( - par = numeric(), - yield_1 = numeric(), - yield_2 = numeric(), - etr_1 = numeric(), - etr_2 = numeric() - ) - new_row <- list( - par = 0, - yield_1 = yield_1_first, - yield_2 = yield_2_first, - etr_1 = recalc_etr_1, - etr_2 = recalc_etr_2 - ) - result <- rbind(result, new_row) - - last_par <- as.numeric(0) - for (i in seq_len(nrow(data))) { - row <- data[i, ] - current_par <- row$PAR - - if (row$Action != "P.+F. SP") { - next - } - - if (remove_recovery && last_par != 0 && current_par < last_par) { - break - } - - yield_1 <- row$Y.I. - recalc_etr_1 <- calc_etr(yield_1, current_par, etr_factor, fraction_photosystem_I) - - yield_2 <- row$Y.II. - recalc_etr_2 <- calc_etr(yield_2, current_par, etr_factor, fraction_photosystem_II) - - new_row <- list( - par = current_par, - yield_1 = yield_1, - yield_2 = yield_2, - etr_1 = recalc_etr_1, - etr_2 = recalc_etr_2 - ) - result <- rbind(result, new_row) - - last_par <- current_par - } - - validate_data(result) - return(result) - }, - warning = function(w) { - stop("Warning in file: ", csv_path, " Warning: ", w) - }, - error = function(e) { - stop("Error in file: ", csv_path, " Error: ", e) - } - ) -} - -#' Read and Process DualPAM Data Single Chanel Mode P700 -#' -#' Reads raw CSV files generated by DualPAM software, calculates electron transport rate (ETR) values for Photosystem I, and returns a universal dataset. -#' -#' @param csv_path File path to the CSV file. -#' @param remove_recovery Logical. Removes recovery measurements if \code{TRUE}. Default is \code{TRUE}. -#' @param etr_factor Numeric. Factor for ETR calculation. Default is \code{0.84}. -#' @param fraction_photosystem_I Numeric. Relative distribution of absorbed PAR to photosystem I. Default is \code{0.5}. -#' @param fraction_photosystem_II Numeric. Relative distribution of absorbed PAR to photosystem II. Default is \code{0.5}. -#' -#' @details -#' Calculates ETR using: -#' \deqn{\text{ETR} = \text{PAR} \cdot \text{ETR-Factor} \cdot \text{Fraction of Photosystem (I)} \cdot \text{Yield (I)}} -#' -#' A detailed documentation can be found under \url{https://github.com/biotoolbox/pam?tab=readme-ov-file#read_dual_pam_data} -#' -#' @return A \code{data.table} containing: -#' \itemize{ -#' \item \code{par}: Photosynthetically active radiation. -#' \item \code{yield_1}: Yield for photosystem I -#' \item \code{yield_2}: NA -#' \item \code{etr_1}: Calculated ETR for photosystem I -#' \item \code{etr_2}: NA -#' } -#' -#' @references{ -#' Heinz Walz GmbH. (2024). \emph{DUAL-PAM-100 DUAL-PAM/F MANUAL, 5th Edition, April 2024, Chapter 7 (pp. 162-172).} -#' Heinz Walz GmbH, Effeltrich, Germany. -#' Available at: \url{https://www.walz.com/files/downloads/dualpamed05.pdf} -#' } -#' @examples -#' path <- file.path( -#' system.file("extdata/dual_pam_single_channel_p700_data", package = "pam"), -#' "20260130_01_efeutute_dual_pam_only_p700.csv" -#' ) -#' data <- read_dual_pam_single_channel_p700_data(path) -#' @export -read_dual_pam_single_channel_p700_data <- function( - csv_path, - remove_recovery = TRUE, - etr_factor = 0.84, - fraction_photosystem_I = 0.5, - fraction_photosystem_II = 0.5 -) { - if (fraction_photosystem_I + fraction_photosystem_II != 1) { - stop("The sum of fraction_photosystem_I and fraction_photosystem_II must be equal 1.") - } - - tryCatch( - { - data <- utils::read.csv(csv_path, sep = ";", dec = ".") - data <- data.table::as.data.table(data) - - validate_dual_pam_single_channel_p700_data(data) - data <- data[data$ID == "SP", ] - - date_time_col_values <- c() - for (i in seq_len(nrow(data))) { - row <- data[i, ] - - date_time_row_value <- as.POSIXct( - paste(row$Date, row$Time, sep = " "), - tz = "GMT", "%d.%m.%y %H:%M:%S" - ) - date_time_col_values <- c(date_time_col_values, date_time_row_value) - } - - data$DateTime <- date_time_col_values - data <- data[order(data$DateTime), ] - - pm_det_row <- subset(data, data$PAR == 0 & data$Action == "Pm.-Det.") - yield_1_first <- pm_det_row$Y.I. - recalc_etr_1 <- calc_etr(yield_1_first, 0, etr_factor, fraction_photosystem_I) - - - result <- data.table::data.table( - par = numeric(), - yield_1 = numeric(), - yield_2 = numeric(), - etr_1 = numeric(), - etr_2 = numeric() - ) - new_row <- list( - par = 0, - yield_1 = yield_1_first, - yield_2 = NA_real_, - etr_1 = recalc_etr_1, - etr_2 = NA_real_ - ) - result <- rbind(result, new_row) - - last_par <- as.numeric(0) - for (i in seq_len(nrow(data))) { - row <- data[i, ] - current_par <- row$PAR - - if (row$Action != "P700 SP") { - next - } - - if (remove_recovery && last_par != 0 && current_par < last_par) { - break - } - - yield_1 <- row$Y.I. - recalc_etr_1 <- calc_etr(yield_1, current_par, etr_factor, fraction_photosystem_I) - - new_row <- list( - par = current_par, - yield_1 = yield_1, - yield_2 = NA_real_, - etr_1 = recalc_etr_1, - etr_2 = NA_real_ - ) - result <- rbind(result, new_row) - - last_par <- current_par - } - - validate_data(result) - return(result) - }, - warning = function(w) { - stop("Warning in file: ", csv_path, " Warning: ", w) - }, - error = function(e) { - stop("Error in file: ", csv_path, " Error: ", e) - } - ) -} - -#' Read and Process DualPAM Data Single Chanel Mode Fluo -#' -#' Reads raw CSV files generated by DualPAM software, calculates electron transport rate (ETR) values for Photosystem II, and returns a universal dataset. -#' -#' @param csv_path File path to the CSV file. -#' @param remove_recovery Logical. Removes recovery measurements if \code{TRUE}. Default is \code{TRUE}. -#' @param etr_factor Numeric. Factor for ETR calculation. Default is \code{0.84}. -#' @param fraction_photosystem_I Numeric. Relative distribution of absorbed PAR to photosystem I. Default is \code{0.5}. -#' @param fraction_photosystem_II Numeric. Relative distribution of absorbed PAR to photosystem II. Default is \code{0.5}. -#' -#' @details -#' Calculates ETR using: -#' \deqn{\text{ETR} = \text{PAR} \cdot \text{ETR-Factor} \cdot \text{Fraction of Photosystem (II)} \cdot \text{Yield (II)}} -#' -#' A detailed documentation can be found under \url{https://github.com/biotoolbox/pam?tab=readme-ov-file#read_dual_pam_data} -#' -#' @return A \code{data.table} containing: -#' \itemize{ -#' \item \code{par}: Photosynthetically active radiation. -#' \item \code{yield_1}: NA -#' \item \code{yield_2}: Yield for photosystem II. -#' \item \code{etr_1}: NA -#' \item \code{etr_2}: Calculated ETR for photosystem II. -#' } -#' -#' @references{ -#' Heinz Walz GmbH. (2024). \emph{DUAL-PAM-100 DUAL-PAM/F MANUAL, 5th Edition, April 2024, Chapter 7 (pp. 162-172).} -#' Heinz Walz GmbH, Effeltrich, Germany. -#' Available at: \url{https://www.walz.com/files/downloads/dualpamed05.pdf} -#' } -#' @examples -#' path <- file.path( -#' system.file("extdata/dual_pam_single_channel_fluo_data", package = "pam"), -#' "20260130_efeutute_dual_pam_only_fluo.csv" -#' ) -#' data <- read_dual_pam_single_channel_fluo_data(path) -#' @export -read_dual_pam_single_channel_fluo_data <- function( - csv_path, - remove_recovery = TRUE, - etr_factor = 0.84, - fraction_photosystem_I = 0.5, - fraction_photosystem_II = 0.5 -) { - if (fraction_photosystem_I + fraction_photosystem_II != 1) { - stop("The sum of fraction_photosystem_I and fraction_photosystem_II must be equal 1.") - } - - tryCatch( - { - data <- utils::read.csv(csv_path, sep = ";", dec = ".") - data <- data.table::as.data.table(data) - - validate_dual_pam_single_channel_fluo_data(data) - data <- data[data$ID == "SP", ] - - date_time_col_values <- c() - for (i in seq_len(nrow(data))) { - row <- data[i, ] - - date_time_row_value <- as.POSIXct( - paste(row$Date, row$Time, sep = " "), - tz = "GMT", "%d.%m.%y %H:%M:%S" - ) - date_time_col_values <- c(date_time_col_values, date_time_row_value) - } - - data$DateTime <- date_time_col_values - data <- data[order(data$DateTime), ] - - fm_det_row <- subset(data, data$PAR == 0 & data$Action == "Fm-Det.") - yield_2_first <- fm_det_row$Y.II. - recalc_etr_2 <- calc_etr( - yield_2_first, 0, etr_factor, fraction_photosystem_II - ) - - - result <- data.table::data.table( - par = numeric(), - yield_1 = numeric(), - yield_2 = numeric(), - etr_1 = numeric(), - etr_2 = numeric() - ) - new_row <- list( - par = 0, - yield_1 = NA_real_, - yield_2 = yield_2_first, - etr_1 = NA_real_, - etr_2 = recalc_etr_2 - ) - result <- rbind(result, new_row) - - last_par <- as.numeric(0) - for (i in seq_len(nrow(data))) { - row <- data[i, ] - current_par <- row$PAR - - if (row$Action != "Fluo. SP") { - next - } - - if (remove_recovery && last_par != 0 && current_par < last_par) { - break - } - - yield_2 <- row$Y.II. - recalc_etr_2 <- calc_etr(yield_2, current_par, etr_factor, fraction_photosystem_II) - - new_row <- list( - par = current_par, - yield_1 = NA_real_, - yield_2 = yield_2, - etr_1 = NA_real_, - etr_2 = recalc_etr_2 - ) - result <- rbind(result, new_row) - - last_par <- current_par - } - - validate_data(result) - return(result) - }, - warning = function(w) { - stop("Warning in file: ", csv_path, " Warning: ", w) - }, - error = function(e) { - stop("Error in file: ", csv_path, " Error: ", e) - } - ) -} - -calc_etr <- function(yield, par, etr_factor, p_ratio) { - if (is.na(yield)) { - return(NA_real_) - } - - if (!is.numeric(yield)) { - stop("yield is not numeric") - } - - if (!is.numeric(par)) { - stop("par is not numeric") - } - - if (!is.numeric(etr_factor)) { - stop("etr_factor is not numeric") - } - - if (!is.numeric(p_ratio)) { - stop("p_ratio is not numeric") - } - - return(yield * par * etr_factor * p_ratio) -} - -#' Read and Process Junior PAM Data -#' -#' Reads raw CSV files generated by Junior PAM software, calculates electron transport rate (ETR) values, and returns a cleaned dataset. -#' -#' @param csv_path File path to the CSV file. -#' @param remove_recovery Logical. Removes recovery measurements if \code{TRUE}. Default is \code{TRUE}. -#' @param etr_factor Numeric. Factor for ETR calculation. Default is \code{0.84}. -#' @param fraction_photosystem_I Numeric. Relative distribution of absorbed PAR to photosystem I. Default is \code{0.5}. -#' @param fraction_photosystem_II Numeric. Relative distribution of absorbed PAR to photosystem II. Default is \code{0.5}. -#' -#' @details -#' Calculates ETR II using: -#' \deqn{\text{ETR II} = \text{PAR} \cdot \text{ETR-Factor} \cdot \text{Fraction of Photosystem (II)} \cdot \text{Yield (II)}} -#' -#' A detailed documentation can be found under \url{https://github.com/biotoolbox/pam?tab=readme-ov-file} -#' -#' @return A \code{data.table} containing: -#' \itemize{ -#' \item \code{par}: Photosynthetically active radiation. -#' \item \code{yield_1}: Yield for photosystem I. -#' \item \code{yield_2}: Yield for photosystem II. -#' \item \code{etr_1}: Calculated ETR for photosystem I. -#' \item \code{etr_2}: Calculated ETR for photosystem II. -#' } -#' -#' @references{ -#' Heinz Walz GmbH. (2024). \emph{DUAL-PAM-100 DUAL-PAM/F MANUAL, 5th Edition, April 2024, Chapter 7 (pp. 162-172).} -#' Heinz Walz GmbH, Effeltrich, Germany. -#' Available at: \url{https://www.walz.com/files/downloads/dualpamed05.pdf} -#' } -#' @examples -#' path <- file.path( -#' system.file("extdata/junior_pam_data", package = "pam"), -#' "2026_04_22_junior_pam.csv" -#' ) -#' data <- read_junior_pam_data(path) -#' @export -read_junior_pam_data <- function( - csv_path, - remove_recovery = TRUE, - etr_factor = 0.84, - fraction_photosystem_I = 0.5, - fraction_photosystem_II = 0.5 -) { - if (fraction_photosystem_I + fraction_photosystem_II != 1) { - stop("The sum of fraction_photosystem_I and fraction_photosystem_II must be equal 1.") - } - - tryCatch( - { - data <- utils::read.csv(csv_path, sep = ";", dec = ".", skip = 1, header = TRUE) - data <- data.table::as.data.table(data) - - validate_junior_pam_data(data) - - par_col <- grep("^.+\\.PAR$", names(data), value = TRUE)[1] - yield_2_col <- grep("^.+\\.Y\\.\\.II\\.$", names(data), value = TRUE)[1] - - data <- data[data$Type == "FO" | data$Type == "F", ] - data <- data[order(data$"Time..rel.ms."), ] - - result <- data.table::data.table( - par = numeric(), - yield_1 = numeric(), - yield_2 = numeric(), - etr_1 = numeric(), - etr_2 = numeric() - ) - last_par <- as.numeric(0) - for (i in seq_len(nrow(data))) { - row <- data[i, ] - current_par <- row[[par_col]] - - if (remove_recovery && last_par != 0 && current_par < last_par) { - break - } - - yield_2 <- row[[yield_2_col]] - recalc_etr_2 <- calc_etr(yield_2, current_par, etr_factor, fraction_photosystem_II) - - new_row <- list( - par = current_par, - yield_1 = NA_real_, - yield_2 = yield_2, - etr_1 = NA_real_, - etr_2 = recalc_etr_2 - ) - result <- rbind(result, new_row) - - last_par <- current_par - } - - return(result) - }, - warning = function(w) { - stop("Warning in file: ", csv_path, " Warning: ", w) - }, - error = function(e) { - stop("Error in file: ", csv_path, " Error: ", e) - } - ) -} - -#' Read and Process PAM 2500 Data -#' -#' Reads raw CSV files generated by PAM 2500 software, calculates electron transport rate (ETR) values, and returns a cleaned dataset. -#' -#' @param csv_path File path to the CSV file. -#' @param remove_recovery Logical. Removes recovery measurements if \code{TRUE}. Default is \code{TRUE}. -#' @param etr_factor Numeric. Factor for ETR calculation. Default is \code{0.84}. -#' @param fraction_photosystem_I Numeric. Relative distribution of absorbed PAR to photosystem I. Default is \code{0.5}. -#' @param fraction_photosystem_II Numeric. Relative distribution of absorbed PAR to photosystem II. Default is \code{0.5}. -#' -#' @details -#' Calculates ETR II using: -#' \deqn{\text{ETR II} = \text{PAR} \cdot \text{ETR-Factor} \cdot \text{Fraction of Photosystem (II)} \cdot \text{Yield (II)}} -#' -#' A detailed documentation can be found under \url{https://github.com/biotoolbox/pam?tab=readme-ov-file} -#' -#' @return A \code{data.table} containing: -#' \itemize{ -#' \item \code{par}: Photosynthetically active radiation. -#' \item \code{yield_1}: Yield for photosystem I. -#' \item \code{yield_2}: Yield for photosystem II. -#' \item \code{etr_1}: Calculated ETR for photosystem I. -#' \item \code{etr_2}: Calculated ETR for photosystem II. -#' } -#' -#' @references{ -#' Heinz Walz GmbH. (2024). \emph{DUAL-PAM-100 DUAL-PAM/F MANUAL, 5th Edition, April 2024, Chapter 7 (pp. 162-172).} -#' Heinz Walz GmbH, Effeltrich, Germany. -#' Available at: \url{https://www.walz.com/files/downloads/dualpamed05.pdf} -#' } -#' @examples -#' path <- file.path(system.file("extdata/pam_2500_data", package = "pam"), "20260422_pam_2500.CSV") -#' data <- read_pam_2500_data(path) -#' @export -read_pam_2500_data <- function( - csv_path, - remove_recovery = TRUE, - etr_factor = 0.84, - fraction_photosystem_I = 0.5, - fraction_photosystem_II = 0.5 -) { - if (fraction_photosystem_I + fraction_photosystem_II != 1) { - stop("The sum of fraction_photosystem_I and fraction_photosystem_II must be equal 1.") - } - - tryCatch( - { - data <- utils::read.csv(csv_path, sep = ";", dec = ".") - data <- data.table::as.data.table(data) - - validate_pam_2500_data(data) - data <- data[grepl("^\\d+$", data$`No.`), ] - - date_time_col_values <- c() - for (i in seq_len(nrow(data))) { - row <- data[i, ] - - date_time_row_value <- as.POSIXct( - paste(row$Date, row$Time, sep = " "), - tz = "GMT", "%d.%m.%y %H:%M:%S" - ) - date_time_col_values <- c(date_time_col_values, date_time_row_value) - } - - data$DateTime <- date_time_col_values - data <- data[order(data$DateTime), ] - - result <- data.table::data.table( - par = numeric(), - yield_1 = numeric(), - yield_2 = numeric(), - etr_1 = numeric(), - etr_2 = numeric() - ) - last_par <- as.numeric(0) - for (i in seq_len(nrow(data))) { - row <- data[i, ] - current_par <- row$PAR - - if (remove_recovery && last_par != 0 && current_par < last_par) { - break - } - - yield_2 <- row$Y.II. - recalc_etr_2 <- calc_etr(yield_2, current_par, etr_factor, fraction_photosystem_II) - - new_row <- list( - par = current_par, - yield_1 = NA_real_, - yield_2 = yield_2, - etr_1 = NA_real_, - etr_2 = recalc_etr_2 - ) - result <- rbind(result, new_row) - - last_par <- current_par - } - return(result) - }, - warning = function(w) { - stop("Warning in file: ", csv_path, " Warning: ", w) - }, - error = function(e) { - stop("Error in file: ", csv_path, " Error: ", e) - } - ) -} diff --git a/src/R/util.R b/src/R/util.R index 1afb041..852dc93 100644 --- a/src/R/util.R +++ b/src/R/util.R @@ -30,291 +30,8 @@ get_residual_sum_of_squares_from_model_result <- function(model_result) { return(model_result[["residual_sum_of_squares"]]) } -plot_table <- function(model_result, entries_per_row) { - validate_model_result(model_result) - - custom_theme <- gridExtra::ttheme_minimal( - core = list( - fg_params = list( - cex = 0.7, - fontface = 3 - ), - bg_params = list( - fill = "lightgray", - col = "black" - ) - ), # font size for cell text - colhead = list( - fg_params = list(cex = 0.7), - bg_params = list( - fill = "lightgray", - col = "black" - ) - ), # font size for column headers - rowhead = list( - fg_params = list(cex = 0.7), - bg_params = list( - fill = "lightgray", - col = "black" - ) - ), # font size for row headers - ) - - tbl_list <- list() - row <- NULL - - row_count <- 1 - count <- 1 - - for (i in names(model_result)) { - if (i == "etr_type" || i == "etr_regression_data") { - next() - } - - value <- model_result[[i]] - - if (is.null(row)) { - row <- data.frame(tmp = NA) - } - - row[[i]] <- c(value) - - if (count == entries_per_row) { - row$tmp <- NULL - tbl_list[[row_count]] <- gridExtra::tableGrob( - row, - rows = NULL, - theme = custom_theme - ) - - row <- NULL - row_count <- row_count + 1 - count <- 1 - } else { - count <- count + 1 - } - } - - if (is.null(row) == FALSE) { - row$tmp <- NULL - tbl_list[[row_count]] <- gridExtra::tableGrob( - row, - rows = NULL, - theme = custom_theme - ) - } - - tbl <- cowplot::plot_grid( - plotlist = tbl_list, - ncol = 1 - ) - return(tbl) -} - -#' @title Plot Control -#' @description This function creates a control plot for the used model based on the provided data and model results. -#' -#' @param data A `data.table` containing the original ETR and yield data for the plot. -#' @param model_result A list containing the fitting results of the used model and the calculated parameters. -#' @param title A character string that specifies the title of the plot. -#' @param color A color specification for the regression line in the plot. -#' -#' @details -#' A detailed documentation can be found under \url{https://github.com/biotoolbox/pam?tab=readme-ov-file#plot_control} -#' -#' @return A plot displaying the original ETR and Yield values and the regression data. A table below the plot shows the calculated data. -#' -#' @examples -#' path <- file.path(system.file("extdata/dual_pam_data", package = "pam"), "20240925.csv") -#' data <- read_dual_pam_data(path) -#' -#' result <- eilers_peeters_generate_regression_ETR_I(data) -#' plot_control(data, result, "Control Plot") -#' -#' @export -plot_control <- function( - data, - model_result, - title, - color = "black") { - validate_data(data) - validate_model_result(model_result) - - etr_type <- get_etr_type_from_model_result(model_result) - validate_etr_type(etr_type) - - yield <- NA_real_ - yield_name <- "" - if (etr_type == etr_1_type) { - yield <- "yield_1" - yield_name <- "Y(I)" - } else { - yield <- "yield_2" - yield_name <- "Y(II)" - } - - etr_regression_data <- get_etr_regression_data_from_model_result(model_result) - validate_etr_regression_data(etr_regression_data) - - max_etr <- max(etr_regression_data$prediction) - - plot <- ggplot2::ggplot(data, ggplot2::aes(x = data$par, y = get(etr_type))) + - ggplot2::geom_point() + - ggplot2::geom_line( - data = etr_regression_data, - ggplot2::aes( - x = etr_regression_data$par, - y = etr_regression_data$prediction - ), - color = color - ) + - ggplot2::geom_point(data = data, shape = 17, ggplot2::aes(y = get(yield) * max_etr)) + - ggplot2::geom_line(data = data, ggplot2::aes(y = get(yield) * max_etr)) + - ggplot2::labs(x = par_label, y = etr_label, title = eval(title)) + - ggplot2::scale_y_continuous( - sec.axis = ggplot2::sec_axis(~ . / max_etr, name = yield_name) - ) + - ggthemes::theme_base() + - ggplot2::theme( - plot.background = ggplot2::element_rect(fill = "white", color = NA), - panel.background = ggplot2::element_rect(fill = "white", color = NA) - ) - - - tbl <- plot_table(model_result, 4) - - plot <- cowplot::plot_grid( - plot, - tbl, - ncol = 1, - rel_heights = c(0.7, 0.3) - ) - return(plot) -} - -create_modified_model_result <- function( - etr_type, - etr_regression_data, - residual_sum_of_squares, - root_mean_squared_error, - relative_root_mean_squared_error, - a, - b, - c, - d, - alpha, - beta, - etrmax_with_photoinhibition, - etrmax_without_photoinhibition, - ik_with_photoinhibition, - ik_without_photoinhibition, - im_with_photoinhibition, - w, - ib, - etrmax_without_with_ratio) { - result <- list( - etr_type = etr_type, - etr_regression_data = etr_regression_data, - residual_sum_of_squares = residual_sum_of_squares, - root_mean_squared_error = root_mean_squared_error, - relative_root_mean_squared_error = relative_root_mean_squared_error, - a = a, - b = b, - c = c, - d = d, - alpha = alpha, - beta = beta, - etrmax_with_photoinhibition = etrmax_with_photoinhibition, - etrmax_without_photoinhibition = etrmax_without_photoinhibition, - ik_with_photoinhibition = ik_with_photoinhibition, - ik_without_photoinhibition = ik_without_photoinhibition, - im_with_photoinhibition = im_with_photoinhibition, - w = w, - ib = ib, - etrmax_without_with_ratio = etrmax_without_with_ratio - ) - validate_modified_model_result(result) - return(result) -} - -#' Write Model Result CSV -#' @description -#' This function exports the intermediate data table, regression data, and model parameters into separate CSV files for easy access and further analysis. -#' -#' @param dest_dir A character string specifying the directory where the CSV files will be saved. -#' @param name A character string specifying the base name for the output files. -#' @param data A data.table containing the intermediate data used in the model. -#' @param model_result A list containing the model results, including parameter values and regression data. -#' -#' @details -#' This function generates three CSV files: -#' \enumerate{ -#' \item \strong{raw_data.csv:} Contains the original raw data used in the model. -#' \item \strong{regression_data.csv:} Includes the regression data with predicted electron transport rate (ETR) values. -#' \item \strong{model_result.csv:} Summarizes the parameter values derived from the model results (excluding regression data), such as \code{alpha} or \code{beta}. -#' } -#' The `name` parameter serves as a prefix for each file, ensuring clarity and organization in the output directory. -#' A detailed documentation can be found under \url{https://github.com/biotoolbox/pam?tab=readme-ov-file#write_model_result_csv} -#' -#' @return No return value, called for side effects -#' -#' @examples -#' path <- file.path(system.file("extdata/dual_pam_data", package = "pam"), "20240925.csv") -#' data <- read_dual_pam_data(path) -#' -#' result <- eilers_peeters_generate_regression_ETR_I(data) -#' write_model_result_csv(tempdir(), "20240925", data, result) -#' -#' @export -write_model_result_csv <- function(dest_dir, name, data, model_result) { - data_dest <- file.path(dest_dir, paste(name, "_raw_data.csv", sep = "")) - regression_data_dest <- file.path(dest_dir, paste(name, "_regression_data.csv", sep = "")) - model_result_dest <- file.path(dest_dir, paste(name, "_model_result.csv", sep = "")) - - utils::write.csv( - data, - file = data_dest, - quote = TRUE, - row.names = FALSE - ) - - utils::write.csv( - get_etr_regression_data_from_model_result(model_result), - file = regression_data_dest, - quote = TRUE, - row.names = FALSE - ) - - df <- data.frame() - df[1, ] <- NA - - for (n in names(model_result)) { - if (n == "etr_regression_data" || n == "etr_type") { - next() - } - - entry <- data.frame( - stats::setNames( - list( - c(model_result[[n]]) - ), - c(n) - ) - ) - - df <- cbind(df, NewCol = entry) - } - - utils::write.csv( - df, - file = model_result_dest, - quote = TRUE, - row.names = FALSE - ) -} - get_etr_data_for_par_values <- function(data, etr_regression_data, etr_type) { - validate_data(data) + validate_intermediate_data(data) validate_etr_regression_data(etr_regression_data) validate_etr_type(etr_type) @@ -345,3 +62,27 @@ relative_root_mean_squared_error <- function(measured_predicted_etr_data) { relative_root_mean_squared_error <- root_mean_squared_error / mean(predicted_etr) return(relative_root_mean_squared_error) } + +calc_etr <- function(yield, par, etr_factor, p_ratio) { + if (is.na(yield)) { + return(NA_real_) + } + + if (!is.numeric(yield)) { + stop("yield is not numeric") + } + + if (!is.numeric(par)) { + stop("par is not numeric") + } + + if (!is.numeric(etr_factor)) { + stop("etr_factor is not numeric") + } + + if (!is.numeric(p_ratio)) { + stop("p_ratio is not numeric") + } + + return(yield * par * etr_factor * p_ratio) +} diff --git a/src/R/validation.R b/src/R/validation.R index 8fdce1a..cd45ac3 100644 --- a/src/R/validation.R +++ b/src/R/validation.R @@ -1,4 +1,4 @@ -validate_data <- function(data) { +validate_intermediate_data <- function(data) { if (is.null(data)) { stop("data is null") } @@ -28,7 +28,7 @@ validate_data <- function(data) { } } -validate_raw_intermediate_csv <- function(data) { +validate_data_not_empty <- function(data) { if (is.null(data)) { stop("data is null") } @@ -37,233 +37,13 @@ validate_raw_intermediate_csv <- function(data) { stop("data is not a valid data.table") } - if (!"par" %in% colnames(data)) { - stop("required col 'par' not found") - } - - if (!"yield_1" %in% colnames(data)) { - stop("required col 'yield_1' not found") - } - - if (!"yield_2" %in% colnames(data)) { - stop("required col 'yield_2' not found") - } -} - -validate_dual_pam_data <- function(data) { - if (is.null(data)) { - stop("data is null") - } - - if (!data.table::is.data.table(data)) { - stop("data is not a valid data.table") - } - - if (nrow(data) < 2) { - stop("no data rows") + if (nrow(data) == 0) { + stop("no rows in data") } if (ncol(data) == 0) { stop("no cols in data") } - - if (!"ID" %in% colnames(data)) { - stop("required col 'ID' not found") - } - - if (!"PAR" %in% colnames(data)) { - stop("required col 'PAR' not found") - } - - if (!"Y.I." %in% colnames(data) && !"Y.II." %in% colnames(data)) { - stop("required col 'Y(I)' and 'Y(II)' not found") - } - - if (!"Action" %in% colnames(data)) { - stop("required col 'Action' not found") - } - - if (!"Date" %in% colnames(data)) { - stop("required col 'Date' not found") - } - - if (!"Time" %in% colnames(data)) { - stop("required col 'Time' not found") - } - - if (!"Pm.-Det." %in% data[["Action"]]) { - stop("required value 'Pm' not found in column 'Action'") - } - - if (!"Fm-Det." %in% data[["Action"]]) { - stop("required value 'Fm' not found in column 'Action'") - } -} - -validate_dual_pam_single_channel_p700_data <- function(data) { - if (is.null(data)) { - stop("data is null") - } - - if (!data.table::is.data.table(data)) { - stop("data is not a valid data.table") - } - - if (nrow(data) < 2) { - stop("no data rows") - } - - if (ncol(data) == 0) { - stop("no cols in data") - } - - if (!"ID" %in% colnames(data)) { - stop("required col 'ID' not found") - } - - if (!"PAR" %in% colnames(data)) { - stop("required col 'PAR' not found") - } - - if (!"Y.I." %in% colnames(data)) { - stop("required col 'Y(I)' not found") - } - - if (!"Action" %in% colnames(data)) { - stop("required col 'Action' not found") - } - - if (!"Date" %in% colnames(data)) { - stop("required col 'Date' not found") - } - - if (!"Time" %in% colnames(data)) { - stop("required col 'Time' not found") - } - - if (!"Pm.-Det." %in% data[["Action"]]) { - stop("required value 'Pm.-Det.' not found in column 'Action'") - } -} - -validate_dual_pam_single_channel_fluo_data <- function(data) { - if (is.null(data)) { - stop("data is null") - } - - if (!data.table::is.data.table(data)) { - stop("data is not a valid data.table") - } - - if (nrow(data) < 2) { - stop("no data rows") - } - - if (ncol(data) == 0) { - stop("no cols in data") - } - - if (!"ID" %in% colnames(data)) { - stop("required col 'ID' not found") - } - - if (!"PAR" %in% colnames(data)) { - stop("required col 'PAR' not found") - } - - if (!"Y.II." %in% colnames(data)) { - stop("required col 'Y(II)' not found") - } - - if (!"Action" %in% colnames(data)) { - stop("required col 'Action' not found") - } - - if (!"Date" %in% colnames(data)) { - stop("required col 'Date' not found") - } - - if (!"Time" %in% colnames(data)) { - stop("required col 'Time' not found") - } - - if (!"Fm-Det." %in% data[["Action"]]) { - stop("required value 'Fm' not found in column 'Action'") - } -} - -validate_junior_pam_data <- function(data) { - if (is.null(data)) { - stop("data is null") - } - - if (!data.table::is.data.table(data)) { - stop("data is not a valid data.table") - } - - if (nrow(data) < 2) { - stop("no data rows") - } - - if (ncol(data) == 0) { - stop("no cols in data") - } - - par_cols <- grep("^.+\\.PAR$", names(data), value = TRUE) - if (length(par_cols) == 0) { - stop("required col 'PAR' not found") - } else if (length(par_cols) > 1) { - stop(paste(length(par_cols), " 'PAR' cols found. Only supporting one 'PAR' column")) - } - - yield_cols <- grep("^.+\\.Y\\.\\.II\\.$", names(data), value = TRUE) - if (length(yield_cols) == 0) { - stop("required col 'Y (II)' not found") - } else if (length(yield_cols) > 1) { - stop(paste(length(yield_cols), " 'Y (II)' cols found. Only supporting one 'Y (II)' column")) - } - - if (!"Time..rel.ms." %in% colnames(data)) { - stop("required col 'Time (rel/ms)' not found") - } -} - -validate_pam_2500_data <- function(data) { - if (is.null(data)) { - stop("data is null") - } - - if (!data.table::is.data.table(data)) { - stop("data is not a valid data.table") - } - - if (nrow(data) < 2) { - stop("no data rows") - } - - if (ncol(data) == 0) { - stop("no cols in data") - } - - if (!"No." %in% colnames(data)) { - stop("required col 'No.' not found") - } - - if (!"PAR" %in% colnames(data)) { - stop("required col 'PAR' not found") - } - - if (!"Date" %in% colnames(data)) { - stop("required col 'Date' not found") - } - - if (!"Time" %in% colnames(data)) { - stop("required col 'Time' not found") - } - - if (!"Y.II." %in% colnames(data)) { - stop("required col 'Y(II)' not found") - } } validate_etr_regression_data <- function(regression_data) { diff --git a/src/R/write_model_result_csv.R b/src/R/write_model_result_csv.R new file mode 100644 index 0000000..9331646 --- /dev/null +++ b/src/R/write_model_result_csv.R @@ -0,0 +1,75 @@ +#' Write Model Result CSV +#' @description +#' This function exports the intermediate data table, regression data, and model parameters into separate CSV files for easy access and further analysis. +#' +#' @param dest_dir A character string specifying the directory where the CSV files will be saved. +#' @param name A character string specifying the base name for the output files. +#' @param data A data.table containing the intermediate data used in the model. +#' @param model_result A list containing the model results, including parameter values and regression data. +#' +#' @details +#' This function generates three CSV files: +#' \enumerate{ +#' \item \strong{raw_data.csv:} Contains the original raw data used in the model. +#' \item \strong{regression_data.csv:} Includes the regression data with predicted electron transport rate (ETR) values. +#' \item \strong{model_result.csv:} Summarizes the parameter values derived from the model results (excluding regression data), such as \code{alpha} or \code{beta}. +#' } +#' The `name` parameter serves as a prefix for each file, ensuring clarity and organization in the output directory. +#' A detailed documentation can be found under \url{https://github.com/biotoolbox/pam?tab=readme-ov-file#write_model_result_csv} +#' +#' @return No return value, called for side effects +#' +#' @examples +#' path <- file.path(system.file("extdata/dual_pam_data", package = "pam"), "20240925.csv") +#' data <- read_dual_pam_data(path) +#' +#' result <- eilers_peeters_generate_regression_ETR_I(data) +#' write_model_result_csv(tempdir(), "20240925", data, result) +#' +#' @export +write_model_result_csv <- function(dest_dir, name, data, model_result) { + data_dest <- file.path(dest_dir, paste(name, "_raw_data.csv", sep = "")) + regression_data_dest <- file.path(dest_dir, paste(name, "_regression_data.csv", sep = "")) + model_result_dest <- file.path(dest_dir, paste(name, "_model_result.csv", sep = "")) + + utils::write.csv( + data, + file = data_dest, + quote = TRUE, + row.names = FALSE + ) + + utils::write.csv( + get_etr_regression_data_from_model_result(model_result), + file = regression_data_dest, + quote = TRUE, + row.names = FALSE + ) + + df <- data.frame() + df[1, ] <- NA + + for (n in names(model_result)) { + if (n == "etr_regression_data" || n == "etr_type") { + next() + } + + entry <- data.frame( + stats::setNames( + list( + c(model_result[[n]]) + ), + c(n) + ) + ) + + df <- cbind(df, NewCol = entry) + } + + utils::write.csv( + df, + file = model_result_dest, + quote = TRUE, + row.names = FALSE + ) +} diff --git a/src/inst/extdata/dual_pam_single_channel_fluo_data/20260130_efeutute_dual_pam_only_fluo.csv b/src/inst/extdata/dual_pam_single_channel_fluo_data/20260130_dual_pam_only_fluo.csv similarity index 100% rename from src/inst/extdata/dual_pam_single_channel_fluo_data/20260130_efeutute_dual_pam_only_fluo.csv rename to src/inst/extdata/dual_pam_single_channel_fluo_data/20260130_dual_pam_only_fluo.csv diff --git a/src/inst/extdata/dual_pam_single_channel_p700_data/20260130_01_efeutute_dual_pam_only_p700.csv b/src/inst/extdata/dual_pam_single_channel_p700_data/20260130_01_dual_pam_only_p700.csv similarity index 100% rename from src/inst/extdata/dual_pam_single_channel_p700_data/20260130_01_efeutute_dual_pam_only_p700.csv rename to src/inst/extdata/dual_pam_single_channel_p700_data/20260130_01_dual_pam_only_p700.csv diff --git a/src/man/combo_plot_control.Rd b/src/man/combo_plot_control.Rd index 4833f14..fba2468 100644 --- a/src/man/combo_plot_control.Rd +++ b/src/man/combo_plot_control.Rd @@ -1,5 +1,5 @@ % Generated by roxygen2: do not edit by hand -% Please edit documentation in R/combo_plot_control.R +% Please edit documentation in R/plot.R \name{combo_plot_control} \alias{combo_plot_control} \title{Combined ETR Plot and Summary Table} diff --git a/src/man/eilers_peeters_default_start_value_a.Rd b/src/man/eilers_peeters_default_start_value_a.Rd index 749d6b3..b90840f 100644 --- a/src/man/eilers_peeters_default_start_value_a.Rd +++ b/src/man/eilers_peeters_default_start_value_a.Rd @@ -1,5 +1,5 @@ % Generated by roxygen2: do not edit by hand -% Please edit documentation in R/eilers_peeters.R +% Please edit documentation in R/model_eilers_peeters.R \docType{data} \name{eilers_peeters_default_start_value_a} \alias{eilers_peeters_default_start_value_a} diff --git a/src/man/eilers_peeters_default_start_value_b.Rd b/src/man/eilers_peeters_default_start_value_b.Rd index d4fd0ac..8ddf54f 100644 --- a/src/man/eilers_peeters_default_start_value_b.Rd +++ b/src/man/eilers_peeters_default_start_value_b.Rd @@ -1,5 +1,5 @@ % Generated by roxygen2: do not edit by hand -% Please edit documentation in R/eilers_peeters.R +% Please edit documentation in R/model_eilers_peeters.R \docType{data} \name{eilers_peeters_default_start_value_b} \alias{eilers_peeters_default_start_value_b} diff --git a/src/man/eilers_peeters_default_start_value_c.Rd b/src/man/eilers_peeters_default_start_value_c.Rd index 87e74db..3bbd431 100644 --- a/src/man/eilers_peeters_default_start_value_c.Rd +++ b/src/man/eilers_peeters_default_start_value_c.Rd @@ -1,5 +1,5 @@ % Generated by roxygen2: do not edit by hand -% Please edit documentation in R/eilers_peeters.R +% Please edit documentation in R/model_eilers_peeters.R \docType{data} \name{eilers_peeters_default_start_value_c} \alias{eilers_peeters_default_start_value_c} diff --git a/src/man/eilers_peeters_generate_regression_ETR_I.Rd b/src/man/eilers_peeters_generate_regression_ETR_I.Rd index a48a6d3..3981037 100644 --- a/src/man/eilers_peeters_generate_regression_ETR_I.Rd +++ b/src/man/eilers_peeters_generate_regression_ETR_I.Rd @@ -1,5 +1,5 @@ % Generated by roxygen2: do not edit by hand -% Please edit documentation in R/eilers_peeters.R +% Please edit documentation in R/model_eilers_peeters.R \name{eilers_peeters_generate_regression_ETR_I} \alias{eilers_peeters_generate_regression_ETR_I} \title{Eilers-Peeters Regression for ETR I} diff --git a/src/man/eilers_peeters_generate_regression_ETR_II.Rd b/src/man/eilers_peeters_generate_regression_ETR_II.Rd index 4c08182..7ebaca4 100644 --- a/src/man/eilers_peeters_generate_regression_ETR_II.Rd +++ b/src/man/eilers_peeters_generate_regression_ETR_II.Rd @@ -1,5 +1,5 @@ % Generated by roxygen2: do not edit by hand -% Please edit documentation in R/eilers_peeters.R +% Please edit documentation in R/model_eilers_peeters.R \name{eilers_peeters_generate_regression_ETR_II} \alias{eilers_peeters_generate_regression_ETR_II} \title{Eilers-Peeters Regression for ETR II} diff --git a/src/man/eilers_peeters_modified.Rd b/src/man/eilers_peeters_modified.Rd index 9a6fd2f..f2a25fc 100644 --- a/src/man/eilers_peeters_modified.Rd +++ b/src/man/eilers_peeters_modified.Rd @@ -1,5 +1,5 @@ % Generated by roxygen2: do not edit by hand -% Please edit documentation in R/eilers_peeters.R +% Please edit documentation in R/model_eilers_peeters.R \name{eilers_peeters_modified} \alias{eilers_peeters_modified} \title{Eilers & Peeters Model Modification} diff --git a/src/man/platt_default_start_value_alpha.Rd b/src/man/platt_default_start_value_alpha.Rd index 15cb9e9..c6cb1c9 100644 --- a/src/man/platt_default_start_value_alpha.Rd +++ b/src/man/platt_default_start_value_alpha.Rd @@ -1,5 +1,5 @@ % Generated by roxygen2: do not edit by hand -% Please edit documentation in R/platt.R +% Please edit documentation in R/model_platt.R \docType{data} \name{platt_default_start_value_alpha} \alias{platt_default_start_value_alpha} diff --git a/src/man/platt_default_start_value_beta.Rd b/src/man/platt_default_start_value_beta.Rd index 0acd762..20c3104 100644 --- a/src/man/platt_default_start_value_beta.Rd +++ b/src/man/platt_default_start_value_beta.Rd @@ -1,5 +1,5 @@ % Generated by roxygen2: do not edit by hand -% Please edit documentation in R/platt.R +% Please edit documentation in R/model_platt.R \docType{data} \name{platt_default_start_value_beta} \alias{platt_default_start_value_beta} diff --git a/src/man/platt_default_start_value_ps.Rd b/src/man/platt_default_start_value_ps.Rd index f6f4dc2..402c3a2 100644 --- a/src/man/platt_default_start_value_ps.Rd +++ b/src/man/platt_default_start_value_ps.Rd @@ -1,5 +1,5 @@ % Generated by roxygen2: do not edit by hand -% Please edit documentation in R/platt.R +% Please edit documentation in R/model_platt.R \docType{data} \name{platt_default_start_value_ps} \alias{platt_default_start_value_ps} diff --git a/src/man/platt_generate_regression_ETR_I.Rd b/src/man/platt_generate_regression_ETR_I.Rd index 1f5092e..8087ac7 100644 --- a/src/man/platt_generate_regression_ETR_I.Rd +++ b/src/man/platt_generate_regression_ETR_I.Rd @@ -1,5 +1,5 @@ % Generated by roxygen2: do not edit by hand -% Please edit documentation in R/platt.R +% Please edit documentation in R/model_platt.R \name{platt_generate_regression_ETR_I} \alias{platt_generate_regression_ETR_I} \title{Platt Regression for ETR I} diff --git a/src/man/platt_generate_regression_ETR_II.Rd b/src/man/platt_generate_regression_ETR_II.Rd index 3166a75..32951e4 100644 --- a/src/man/platt_generate_regression_ETR_II.Rd +++ b/src/man/platt_generate_regression_ETR_II.Rd @@ -1,5 +1,5 @@ % Generated by roxygen2: do not edit by hand -% Please edit documentation in R/platt.R +% Please edit documentation in R/model_platt.R \name{platt_generate_regression_ETR_II} \alias{platt_generate_regression_ETR_II} \title{Platt Regression for ETR II} diff --git a/src/man/platt_modified.Rd b/src/man/platt_modified.Rd index e383ddd..353f616 100644 --- a/src/man/platt_modified.Rd +++ b/src/man/platt_modified.Rd @@ -1,5 +1,5 @@ % Generated by roxygen2: do not edit by hand -% Please edit documentation in R/platt.R +% Please edit documentation in R/model_platt.R \name{platt_modified} \alias{platt_modified} \title{Platt Model Modification} diff --git a/src/man/plot_control.Rd b/src/man/plot_control.Rd index 4423a9c..6441fbe 100644 --- a/src/man/plot_control.Rd +++ b/src/man/plot_control.Rd @@ -1,5 +1,5 @@ % Generated by roxygen2: do not edit by hand -% Please edit documentation in R/util.R +% Please edit documentation in R/plot.R \name{plot_control} \alias{plot_control} \title{Plot Control} diff --git a/src/man/read_dual_pam_data.Rd b/src/man/read_dual_pam_data.Rd index c25aa42..70a36ef 100644 --- a/src/man/read_dual_pam_data.Rd +++ b/src/man/read_dual_pam_data.Rd @@ -1,55 +1,55 @@ -% Generated by roxygen2: do not edit by hand -% Please edit documentation in R/read_pam_data.R -\name{read_dual_pam_data} -\alias{read_dual_pam_data} -\title{Read and Process DualPAM Data} -\usage{ -read_dual_pam_data( - csv_path, - remove_recovery = TRUE, - etr_factor = 0.84, - fraction_photosystem_I = 0.5, - fraction_photosystem_II = 0.5 -) -} -\arguments{ -\item{csv_path}{File path to the CSV file.} - -\item{remove_recovery}{Logical. Removes recovery measurements if \code{TRUE}. Default is \code{TRUE}.} - -\item{etr_factor}{Numeric. Factor for ETR calculation. Default is \code{0.84}.} - -\item{fraction_photosystem_I}{Numeric. Relative distribution of absorbed PAR to photosystem I. Default is \code{0.5}.} - -\item{fraction_photosystem_II}{Numeric. Relative distribution of absorbed PAR to photosystem II. Default is \code{0.5}.} -} -\value{ -A \code{data.table} containing: -\itemize{ - \item \code{par}: Photosynthetically active radiation. - \item \code{yield_1}: Yield for photosystem I. - \item \code{yield_2}: Yield for photosystem II. - \item \code{etr_1}: Calculated ETR for photosystem I. - \item \code{etr_2}: Calculated ETR for photosystem II. -} -} -\description{ -Reads raw CSV files generated by DualPAM software, calculates electron transport rate (ETR) values, and returns a universal dataset. -} -\details{ -Calculates ETR using: -\deqn{\text{ETR} = \text{PAR} \cdot \text{ETR-Factor} \cdot \text{Fraction of Photosystem (I or II)} \cdot \text{Yield (I or II)}} - -A detailed documentation can be found under \url{https://github.com/biotoolbox/pam?tab=readme-ov-file#read_dual_pam_data} -} -\examples{ -path <- file.path(system.file("extdata/dual_pam_data", package = "pam"), "20240925.csv") -data <- read_dual_pam_data(path) -} -\references{ -{ - Heinz Walz GmbH. (2024). \emph{DUAL-PAM-100 DUAL-PAM/F MANUAL, 5th Edition, April 2024, Chapter 7 (pp. 162-172).} - Heinz Walz GmbH, Effeltrich, Germany. - Available at: \url{https://www.walz.com/files/downloads/dualpamed05.pdf} -} -} +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/device_dual_pam.R +\name{read_dual_pam_data} +\alias{read_dual_pam_data} +\title{Read and Process DualPAM Data} +\usage{ +read_dual_pam_data( + csv_path, + remove_recovery = TRUE, + etr_factor = 0.84, + fraction_photosystem_I = 0.5, + fraction_photosystem_II = 0.5 +) +} +\arguments{ +\item{csv_path}{File path to the CSV file.} + +\item{remove_recovery}{Logical. Removes recovery measurements if \code{TRUE}. Default is \code{TRUE}.} + +\item{etr_factor}{Numeric. Factor for ETR calculation. Default is \code{0.84}.} + +\item{fraction_photosystem_I}{Numeric. Relative distribution of absorbed PAR to photosystem I. Default is \code{0.5}.} + +\item{fraction_photosystem_II}{Numeric. Relative distribution of absorbed PAR to photosystem II. Default is \code{0.5}.} +} +\value{ +A \code{data.table} containing: +\itemize{ + \item \code{par}: Photosynthetically active radiation. + \item \code{yield_1}: Yield for photosystem I. + \item \code{yield_2}: Yield for photosystem II. + \item \code{etr_1}: Calculated ETR for photosystem I. + \item \code{etr_2}: Calculated ETR for photosystem II. +} +} +\description{ +Reads raw CSV files generated by DualPAM software, calculates electron transport rate (ETR) values, and returns a universal dataset. +} +\details{ +Calculates ETR using: +\deqn{\text{ETR} = \text{PAR} \cdot \text{ETR-Factor} \cdot \text{Fraction of Photosystem (I or II)} \cdot \text{Yield (I or II)}} + +A detailed documentation can be found under \url{https://github.com/biotoolbox/pam?tab=readme-ov-file#read_dual_pam_data} +} +\examples{ +path <- file.path(system.file("extdata/dual_pam_data", package = "pam"), "20240925.csv") +data <- read_dual_pam_data(path) +} +\references{ +{ + Heinz Walz GmbH. (2024). \emph{DUAL-PAM-100 DUAL-PAM/F MANUAL, 5th Edition, April 2024, Chapter 7 (pp. 162-172).} + Heinz Walz GmbH, Effeltrich, Germany. + Available at: \url{https://www.walz.com/files/downloads/dualpamed05.pdf} +} +} diff --git a/src/man/read_dual_pam_single_channel_fluo_data.Rd b/src/man/read_dual_pam_single_channel_fluo_data.Rd index 2567b81..d9f6fe0 100644 --- a/src/man/read_dual_pam_single_channel_fluo_data.Rd +++ b/src/man/read_dual_pam_single_channel_fluo_data.Rd @@ -1,5 +1,5 @@ % Generated by roxygen2: do not edit by hand -% Please edit documentation in R/read_pam_data.R +% Please edit documentation in R/device_dual_pam_single_channel_fluo.R \name{read_dual_pam_single_channel_fluo_data} \alias{read_dual_pam_single_channel_fluo_data} \title{Read and Process DualPAM Data Single Chanel Mode Fluo} @@ -45,7 +45,7 @@ A detailed documentation can be found under \url{https://github.com/biotoolbox/p \examples{ path <- file.path( system.file("extdata/dual_pam_single_channel_fluo_data", package = "pam"), - "20260130_efeutute_dual_pam_only_fluo.csv" + "20260130_dual_pam_only_fluo.csv" ) data <- read_dual_pam_single_channel_fluo_data(path) } diff --git a/src/man/read_dual_pam_single_channel_p700_data.Rd b/src/man/read_dual_pam_single_channel_p700_data.Rd index 7d766bb..be58956 100644 --- a/src/man/read_dual_pam_single_channel_p700_data.Rd +++ b/src/man/read_dual_pam_single_channel_p700_data.Rd @@ -1,5 +1,5 @@ % Generated by roxygen2: do not edit by hand -% Please edit documentation in R/read_pam_data.R +% Please edit documentation in R/device_dual_pam_single_channel_p700.R \name{read_dual_pam_single_channel_p700_data} \alias{read_dual_pam_single_channel_p700_data} \title{Read and Process DualPAM Data Single Chanel Mode P700} @@ -45,7 +45,7 @@ A detailed documentation can be found under \url{https://github.com/biotoolbox/p \examples{ path <- file.path( system.file("extdata/dual_pam_single_channel_p700_data", package = "pam"), - "20260130_01_efeutute_dual_pam_only_p700.csv" + "20260130_01_dual_pam_only_p700.csv" ) data <- read_dual_pam_single_channel_p700_data(path) } diff --git a/src/man/read_junior_pam_data.Rd b/src/man/read_junior_pam_data.Rd index f233dff..c4d1e3d 100644 --- a/src/man/read_junior_pam_data.Rd +++ b/src/man/read_junior_pam_data.Rd @@ -1,5 +1,5 @@ % Generated by roxygen2: do not edit by hand -% Please edit documentation in R/read_pam_data.R +% Please edit documentation in R/device_junior_pam.R \name{read_junior_pam_data} \alias{read_junior_pam_data} \title{Read and Process Junior PAM Data} diff --git a/src/man/read_pam_2500_data.Rd b/src/man/read_pam_2500_data.Rd index 5fdd444..ce8e5b6 100644 --- a/src/man/read_pam_2500_data.Rd +++ b/src/man/read_pam_2500_data.Rd @@ -1,5 +1,5 @@ % Generated by roxygen2: do not edit by hand -% Please edit documentation in R/read_pam_data.R +% Please edit documentation in R/device_pam_2500.R \name{read_pam_2500_data} \alias{read_pam_2500_data} \title{Read and Process PAM 2500 Data} diff --git a/src/man/read_universal_data.Rd b/src/man/read_universal_data.Rd index ba63970..f877222 100644 --- a/src/man/read_universal_data.Rd +++ b/src/man/read_universal_data.Rd @@ -1,5 +1,5 @@ % Generated by roxygen2: do not edit by hand -% Please edit documentation in R/read_pam_data.R +% Please edit documentation in R/device_universal_data.R \name{read_universal_data} \alias{read_universal_data} \title{Read and Process Universal PAM Data} diff --git a/src/man/vollenweider_default_start_value_a.Rd b/src/man/vollenweider_default_start_value_a.Rd index c3a2479..0f9e605 100644 --- a/src/man/vollenweider_default_start_value_a.Rd +++ b/src/man/vollenweider_default_start_value_a.Rd @@ -1,5 +1,5 @@ % Generated by roxygen2: do not edit by hand -% Please edit documentation in R/vollenweider.R +% Please edit documentation in R/model_vollenweider.R \docType{data} \name{vollenweider_default_start_value_a} \alias{vollenweider_default_start_value_a} diff --git a/src/man/vollenweider_default_start_value_alpha.Rd b/src/man/vollenweider_default_start_value_alpha.Rd index 698faa7..f896c6d 100644 --- a/src/man/vollenweider_default_start_value_alpha.Rd +++ b/src/man/vollenweider_default_start_value_alpha.Rd @@ -1,5 +1,5 @@ % Generated by roxygen2: do not edit by hand -% Please edit documentation in R/vollenweider.R +% Please edit documentation in R/model_vollenweider.R \docType{data} \name{vollenweider_default_start_value_alpha} \alias{vollenweider_default_start_value_alpha} diff --git a/src/man/vollenweider_default_start_value_n.Rd b/src/man/vollenweider_default_start_value_n.Rd index 9cb6ba8..ad79912 100644 --- a/src/man/vollenweider_default_start_value_n.Rd +++ b/src/man/vollenweider_default_start_value_n.Rd @@ -1,5 +1,5 @@ % Generated by roxygen2: do not edit by hand -% Please edit documentation in R/vollenweider.R +% Please edit documentation in R/model_vollenweider.R \docType{data} \name{vollenweider_default_start_value_n} \alias{vollenweider_default_start_value_n} diff --git a/src/man/vollenweider_default_start_value_pmax.Rd b/src/man/vollenweider_default_start_value_pmax.Rd index acf98e1..b10dfb6 100644 --- a/src/man/vollenweider_default_start_value_pmax.Rd +++ b/src/man/vollenweider_default_start_value_pmax.Rd @@ -1,5 +1,5 @@ % Generated by roxygen2: do not edit by hand -% Please edit documentation in R/vollenweider.R +% Please edit documentation in R/model_vollenweider.R \docType{data} \name{vollenweider_default_start_value_pmax} \alias{vollenweider_default_start_value_pmax} diff --git a/src/man/vollenweider_generate_regression_ETR_I.Rd b/src/man/vollenweider_generate_regression_ETR_I.Rd index aa5b47c..224e1d5 100644 --- a/src/man/vollenweider_generate_regression_ETR_I.Rd +++ b/src/man/vollenweider_generate_regression_ETR_I.Rd @@ -1,5 +1,5 @@ % Generated by roxygen2: do not edit by hand -% Please edit documentation in R/vollenweider.R +% Please edit documentation in R/model_vollenweider.R \name{vollenweider_generate_regression_ETR_I} \alias{vollenweider_generate_regression_ETR_I} \title{Vollenweider Regression for ETR I} diff --git a/src/man/vollenweider_generate_regression_ETR_II.Rd b/src/man/vollenweider_generate_regression_ETR_II.Rd index 0cd386c..c1c0bde 100644 --- a/src/man/vollenweider_generate_regression_ETR_II.Rd +++ b/src/man/vollenweider_generate_regression_ETR_II.Rd @@ -1,5 +1,5 @@ % Generated by roxygen2: do not edit by hand -% Please edit documentation in R/vollenweider.R +% Please edit documentation in R/model_vollenweider.R \name{vollenweider_generate_regression_ETR_II} \alias{vollenweider_generate_regression_ETR_II} \title{Vollenweider Regression for ETR II} diff --git a/src/man/vollenweider_modified.Rd b/src/man/vollenweider_modified.Rd index 5747da4..8fde27b 100644 --- a/src/man/vollenweider_modified.Rd +++ b/src/man/vollenweider_modified.Rd @@ -1,5 +1,5 @@ % Generated by roxygen2: do not edit by hand -% Please edit documentation in R/vollenweider.R +% Please edit documentation in R/model_vollenweider.R \name{vollenweider_modified} \alias{vollenweider_modified} \title{Vollenweider Model Modification} diff --git a/src/man/walsby_default_start_value_alpha.Rd b/src/man/walsby_default_start_value_alpha.Rd index 0756ff4..43bcffc 100644 --- a/src/man/walsby_default_start_value_alpha.Rd +++ b/src/man/walsby_default_start_value_alpha.Rd @@ -1,5 +1,5 @@ % Generated by roxygen2: do not edit by hand -% Please edit documentation in R/walsby.R +% Please edit documentation in R/model_walsby.R \docType{data} \name{walsby_default_start_value_alpha} \alias{walsby_default_start_value_alpha} diff --git a/src/man/walsby_default_start_value_beta.Rd b/src/man/walsby_default_start_value_beta.Rd index 9885fe7..95e0360 100644 --- a/src/man/walsby_default_start_value_beta.Rd +++ b/src/man/walsby_default_start_value_beta.Rd @@ -1,5 +1,5 @@ % Generated by roxygen2: do not edit by hand -% Please edit documentation in R/walsby.R +% Please edit documentation in R/model_walsby.R \docType{data} \name{walsby_default_start_value_beta} \alias{walsby_default_start_value_beta} diff --git a/src/man/walsby_default_start_value_etr_max.Rd b/src/man/walsby_default_start_value_etr_max.Rd index def9308..3754373 100644 --- a/src/man/walsby_default_start_value_etr_max.Rd +++ b/src/man/walsby_default_start_value_etr_max.Rd @@ -1,5 +1,5 @@ % Generated by roxygen2: do not edit by hand -% Please edit documentation in R/walsby.R +% Please edit documentation in R/model_walsby.R \docType{data} \name{walsby_default_start_value_etr_max} \alias{walsby_default_start_value_etr_max} diff --git a/src/man/walsby_generate_regression_ETR_I.Rd b/src/man/walsby_generate_regression_ETR_I.Rd index 6d7222d..560e7af 100644 --- a/src/man/walsby_generate_regression_ETR_I.Rd +++ b/src/man/walsby_generate_regression_ETR_I.Rd @@ -1,5 +1,5 @@ % Generated by roxygen2: do not edit by hand -% Please edit documentation in R/walsby.R +% Please edit documentation in R/model_walsby.R \name{walsby_generate_regression_ETR_I} \alias{walsby_generate_regression_ETR_I} \title{Walsby Regression for ETR I} diff --git a/src/man/walsby_generate_regression_ETR_II.Rd b/src/man/walsby_generate_regression_ETR_II.Rd index 0767416..4549376 100644 --- a/src/man/walsby_generate_regression_ETR_II.Rd +++ b/src/man/walsby_generate_regression_ETR_II.Rd @@ -1,5 +1,5 @@ % Generated by roxygen2: do not edit by hand -% Please edit documentation in R/walsby.R +% Please edit documentation in R/model_walsby.R \name{walsby_generate_regression_ETR_II} \alias{walsby_generate_regression_ETR_II} \title{Walsby Regression for ETR II} diff --git a/src/man/walsby_modified.Rd b/src/man/walsby_modified.Rd index 8b40c68..cad11c3 100644 --- a/src/man/walsby_modified.Rd +++ b/src/man/walsby_modified.Rd @@ -1,5 +1,5 @@ % Generated by roxygen2: do not edit by hand -% Please edit documentation in R/walsby.R +% Please edit documentation in R/model_walsby.R \name{walsby_modified} \alias{walsby_modified} \title{Walsby Model Modification} diff --git a/src/man/write_model_result_csv.Rd b/src/man/write_model_result_csv.Rd index 75c3281..bc6a2d2 100644 --- a/src/man/write_model_result_csv.Rd +++ b/src/man/write_model_result_csv.Rd @@ -1,5 +1,5 @@ % Generated by roxygen2: do not edit by hand -% Please edit documentation in R/util.R +% Please edit documentation in R/write_model_result_csv.R \name{write_model_result_csv} \alias{write_model_result_csv} \title{Write Model Result CSV} diff --git a/src/tests/testthat/data/dual_pam_single_channel_fluo_data/20260130_efeutute_dual_pam_only_fluo.csv b/src/tests/testthat/data/dual_pam_single_channel_fluo_data/20260130_dual_pam_only_fluo.csv similarity index 100% rename from src/tests/testthat/data/dual_pam_single_channel_fluo_data/20260130_efeutute_dual_pam_only_fluo.csv rename to src/tests/testthat/data/dual_pam_single_channel_fluo_data/20260130_dual_pam_only_fluo.csv diff --git a/src/tests/testthat/data/dual_pam_single_channel_p700_data/20260130_01_efeutute_dual_pam_only_p700.csv b/src/tests/testthat/data/dual_pam_single_channel_p700_data/20260130_01_dual_pam_only_p700.csv similarity index 100% rename from src/tests/testthat/data/dual_pam_single_channel_p700_data/20260130_01_efeutute_dual_pam_only_p700.csv rename to src/tests/testthat/data/dual_pam_single_channel_p700_data/20260130_01_dual_pam_only_p700.csv diff --git a/src/tests/testthat/test-read_dual_pam_data.R b/src/tests/testthat/test-read_dual_pam_data.R index 1f556d4..61c12c8 100644 --- a/src/tests/testthat/test-read_dual_pam_data.R +++ b/src/tests/testthat/test-read_dual_pam_data.R @@ -303,12 +303,12 @@ test_that("read_dual_pam_data 20240925.csv - fraction_photosystem_I = 0.2, fract expect_equal(etr_2[17], 62.0256) }) -test_that("20260130_01_efeutute_dual_pam_only_p700.csv - expect fm missing", { - test_data_file <- testthat::test_path("data", "dual_pam_single_channel_p700_data", "20260130_01_efeutute_dual_pam_only_p700.csv") +test_that("20260130_01_dual_pam_only_p700.csv - expect fm missing", { + test_data_file <- testthat::test_path("data", "dual_pam_single_channel_p700_data", "20260130_01_dual_pam_only_p700.csv") expect_error(read_dual_pam_data(test_data_file)) }) -test_that("20260130_efeutute_dual_pam_only_fluo.csv - expect pm missing", { - test_data_file <- testthat::test_path("data", "dual_pam_single_channel_fluo_data", "20260130_efeutute_dual_pam_only_fluo.csv") +test_that("20260130_dual_pam_only_fluo.csv - expect pm missing", { + test_data_file <- testthat::test_path("data", "dual_pam_single_channel_fluo_data", "20260130_dual_pam_only_fluo.csv") expect_error(read_dual_pam_data(test_data_file)) }) diff --git a/src/tests/testthat/test-read_dual_pam_single_channel_fluo_data.R b/src/tests/testthat/test-read_dual_pam_single_channel_fluo_data.R index 61cd47a..2c865b1 100644 --- a/src/tests/testthat/test-read_dual_pam_single_channel_fluo_data.R +++ b/src/tests/testthat/test-read_dual_pam_single_channel_fluo_data.R @@ -1,5 +1,5 @@ test_that("read_dual_pam_single_channel_fluo_data 20260130_efeutute_dual_pam_only_fluo - default", { - test_data_file <- testthat::test_path("data", "dual_pam_single_channel_fluo_data", "20260130_efeutute_dual_pam_only_fluo.csv") + test_data_file <- testthat::test_path("data", "dual_pam_single_channel_fluo_data", "20260130_dual_pam_only_fluo.csv") data <- read_dual_pam_single_channel_fluo_data(test_data_file) par <- data$par @@ -69,7 +69,7 @@ test_that("read_dual_pam_single_channel_fluo_data 20260130_efeutute_dual_pam_onl }) test_that("read_dual_pam_single_channel_fluo_data 20260130_efeutute_dual_pam_only_fluo - etr_factor 0.5", { - test_data_file <- testthat::test_path("data", "dual_pam_single_channel_fluo_data", "20260130_efeutute_dual_pam_only_fluo.csv") + test_data_file <- testthat::test_path("data", "dual_pam_single_channel_fluo_data", "20260130_dual_pam_only_fluo.csv") data <- read_dual_pam_single_channel_fluo_data(test_data_file, etr_factor = 0.5) par <- data$par @@ -139,12 +139,12 @@ test_that("read_dual_pam_single_channel_fluo_data 20260130_efeutute_dual_pam_onl }) test_that("read_dual_pam_single_channel_fluo_data 20260130_efeutute_dual_pam_only_fluo - fraction_photosystem > 1", { - test_data_file <- testthat::test_path("data", "dual_pam_single_channel_fluo_data", "20260130_efeutute_dual_pam_only_fluo.csv") + test_data_file <- testthat::test_path("data", "dual_pam_single_channel_fluo_data", "20260130_dual_pam_only_fluo.csv") expect_error(read_dual_pam_single_channel_fluo_data(test_data_file, fraction_photosystem_I = 0.9, fraction_photosystem_II = 0.2)) }) test_that("read_dual_pam_single_channel_fluo_data 20260130_efeutute_dual_pam_only_fluo - fraction_photosystem_I = 0.2, fraction_photosystem_II = 0.8", { - test_data_file <- testthat::test_path("data", "dual_pam_single_channel_fluo_data", "20260130_efeutute_dual_pam_only_fluo.csv") + test_data_file <- testthat::test_path("data", "dual_pam_single_channel_fluo_data", "20260130_dual_pam_only_fluo.csv") data <- read_dual_pam_single_channel_fluo_data(test_data_file, fraction_photosystem_I = 0.2, fraction_photosystem_II = 0.8) par <- data$par diff --git a/src/tests/testthat/test-read_dual_pam_single_channel_p700_data.R b/src/tests/testthat/test-read_dual_pam_single_channel_p700_data.R index 4a5fdb8..5b38fa3 100644 --- a/src/tests/testthat/test-read_dual_pam_single_channel_p700_data.R +++ b/src/tests/testthat/test-read_dual_pam_single_channel_p700_data.R @@ -1,5 +1,5 @@ test_that("read_dual_pam_single_channel_p700_data 20260130_01_efeutute_dual_pam_only_p700 - default", { - test_data_file <- testthat::test_path("data", "dual_pam_single_channel_p700_data", "20260130_01_efeutute_dual_pam_only_p700.csv") + test_data_file <- testthat::test_path("data", "dual_pam_single_channel_p700_data", "20260130_01_dual_pam_only_p700.csv") data <- read_dual_pam_single_channel_p700_data(test_data_file) par <- data$par @@ -89,7 +89,7 @@ test_that("read_dual_pam_single_channel_p700_data 20260130_01_efeutute_dual_pam_ }) test_that("read_dual_pam_single_channel_p700_data 20260130_01_efeutute_dual_pam_only_p700 - etr_factor 0.5", { - test_data_file <- testthat::test_path("data", "dual_pam_single_channel_p700_data", "20260130_01_efeutute_dual_pam_only_p700.csv") + test_data_file <- testthat::test_path("data", "dual_pam_single_channel_p700_data", "20260130_01_dual_pam_only_p700.csv") data <- read_dual_pam_single_channel_p700_data(test_data_file, etr_factor = 0.5) par <- data$par @@ -179,12 +179,12 @@ test_that("read_dual_pam_single_channel_p700_data 20260130_01_efeutute_dual_pam_ }) test_that("read_dual_pam_single_channel_p700_data 20260130_01_efeutute_dual_pam_only_p700 - fraction_photosystem > 1", { - test_data_file <- testthat::test_path("data", "dual_pam_single_channel_p700_data", "20260130_01_efeutute_dual_pam_only_p700.csv") + test_data_file <- testthat::test_path("data", "dual_pam_single_channel_p700_data", "20260130_01_dual_pam_only_p700.csv") expect_error(read_dual_pam_single_channel_p700_data(test_data_file, fraction_photosystem_I = 0.9, fraction_photosystem_II = 0.2)) }) test_that("read_dual_pam_single_channel_p700_data 20260130_01_efeutute_dual_pam_only_p700 - fraction_photosystem_I = 0.2, fraction_photosystem_II = 0.8", { - test_data_file <- testthat::test_path("data", "dual_pam_single_channel_p700_data", "20260130_01_efeutute_dual_pam_only_p700.csv") + test_data_file <- testthat::test_path("data", "dual_pam_single_channel_p700_data", "20260130_01_dual_pam_only_p700.csv") data <- read_dual_pam_single_channel_p700_data(test_data_file, fraction_photosystem_I = 0.2, fraction_photosystem_II = 0.8) par <- data$par From 95402a8b5480bb4546f8a46aa9f192d6c555f9f7 Mon Sep 17 00:00:00 2001 From: Phi-S <926151+Phi-S@users.noreply.github.com> Date: Thu, 23 Apr 2026 12:27:55 +0200 Subject: [PATCH 30/32] refactor OS detection functions and update test cases to use is_reference_platform --- src/tests/testthat/helper-os-detection.R | 61 +++++++------------ .../test-compare_regression_models_etr_I.R | 2 +- .../test-compare_regression_models_etr_II.R | 2 +- .../test-compare_regression_models_total.R | 2 +- .../testthat/test-eilers_peeters_etr_I.R | 4 +- .../testthat/test-eilers_peeters_etr_II.R | 4 +- src/tests/testthat/test-platt_etr_I.R | 4 +- src/tests/testthat/test-platt_etr_II.R | 4 +- .../test-relative_root_mean_squared_error.R | 2 +- .../testthat/test-root_mean_squared_error.R | 2 +- .../testthat/test-universal_data_etr_I.R | 2 +- src/tests/testthat/test-vollenweider_etr_I.R | 4 +- src/tests/testthat/test-vollenweider_etr_II.R | 4 +- src/tests/testthat/test-walsby_etr_I.R | 4 +- src/tests/testthat/test-walsby_etr_II.R | 4 +- 15 files changed, 45 insertions(+), 60 deletions(-) diff --git a/src/tests/testthat/helper-os-detection.R b/src/tests/testthat/helper-os-detection.R index d143fbc..95b89a7 100644 --- a/src/tests/testthat/helper-os-detection.R +++ b/src/tests/testthat/helper-os-detection.R @@ -1,51 +1,36 @@ -# Returns a string identifying the OS or distro -get_os_distro <- function() { +get_os_id <- function() { sys_name <- Sys.info()[["sysname"]] if (sys_name == "Linux") { - # If the file doesn't exist, we can't determine distro if (!file.exists("/etc/os-release")) { - return("unknown") + return(NA) } - - # Try reading the file safely - os_release <- tryCatch( - readLines("/etc/os-release"), - error = function(e) NULL - ) - - if (is.null(os_release)) { - return("unknown") + os_release <- readLines("/etc/os-release") + id_line <- grep("^ID=", os_release, value = TRUE) + if (length(id_line) == 0) { + return(NA) } + return(id_line) + } - # Extract ID_LIKE and ID - distro_id_like <- grep("^ID_LIKE=", os_release, value = TRUE) - distro_id_like <- if (length(distro_id_like) > 0) { - sub("^ID_LIKE=", "", distro_id_like) - } else { - "" - } + return(tolower(sys_name)) +} - distro_id <- grep("^ID=", os_release, value = TRUE) - distro_id <- if (length(distro_id) > 0) { - sub("^ID=", "", distro_id) - } else { - "" - } +is_reference_platform <- function() { + os <- get_os_id() + if (is.na(os) || !grepl("\\b(debian|ubuntu)\\b", os, ignore.case = TRUE)) { + return(FALSE) + } - distro_names <- paste(distro_id_like, distro_id, collapse = " ") - if (nchar(trimws(distro_names)) == 0) { - return("unknown") - } else { - return(distro_names) - } + blas <- tolower(extSoftVersion()[["BLAS"]]) + if (!grepl("openblas|mkl|atlas|flexiblas|accelerate", blas)) { + return(FALSE) } - # For non-Linux, just return the system name (e.g. "Windows", "Darwin") - return(tolower(sys_name)) -} + arch <- tolower(Sys.info()[["machine"]]) + if (!(arch %in% c("x86_64", "amd64", "i386", "i686"))) { + return(FALSE) + } -is_debian_or_ubuntu <- function() { - os <- get_os_distro() - grepl("\\b(debian|ubuntu)\\b", os, ignore.case = TRUE) + return(TRUE) } diff --git a/src/tests/testthat/test-compare_regression_models_etr_I.R b/src/tests/testthat/test-compare_regression_models_etr_I.R index f8076a4..5789053 100644 --- a/src/tests/testthat/test-compare_regression_models_etr_I.R +++ b/src/tests/testthat/test-compare_regression_models_etr_I.R @@ -1,5 +1,5 @@ test_that("compare_regression_models etr I - linux", { - skip_if_not(is_debian_or_ubuntu()) + skip_if_not(is_reference_platform()) test_data_dir <- testthat::test_path("data", "dual_pam_data", "bulk") result <- compare_regression_models_ETR_I(test_data_dir, read_dual_pam_data) diff --git a/src/tests/testthat/test-compare_regression_models_etr_II.R b/src/tests/testthat/test-compare_regression_models_etr_II.R index ea84675..5c12d66 100644 --- a/src/tests/testthat/test-compare_regression_models_etr_II.R +++ b/src/tests/testthat/test-compare_regression_models_etr_II.R @@ -1,5 +1,5 @@ test_that("compare_regression_models etr II - linux", { - skip_if_not(is_debian_or_ubuntu()) + skip_if_not(is_reference_platform()) test_data_dir <- testthat::test_path("data", "dual_pam_data", "bulk") result <- compare_regression_models_ETR_II(test_data_dir, read_dual_pam_data) diff --git a/src/tests/testthat/test-compare_regression_models_total.R b/src/tests/testthat/test-compare_regression_models_total.R index 21adb47..69d59c1 100644 --- a/src/tests/testthat/test-compare_regression_models_total.R +++ b/src/tests/testthat/test-compare_regression_models_total.R @@ -1,5 +1,5 @@ test_that("compare_regression_models etr I + II - linux", { - skip_if_not(is_debian_or_ubuntu()) + skip_if_not(is_reference_platform()) test_data_dir <- testthat::test_path("data", "dual_pam_data", "bulk") model_points_etr_I <- compare_regression_models_ETR_I(test_data_dir, read_dual_pam_data) model_points_etr_II <- compare_regression_models_ETR_II(test_data_dir, read_dual_pam_data) diff --git a/src/tests/testthat/test-eilers_peeters_etr_I.R b/src/tests/testthat/test-eilers_peeters_etr_I.R index d4e0275..f9f1851 100644 --- a/src/tests/testthat/test-eilers_peeters_etr_I.R +++ b/src/tests/testthat/test-eilers_peeters_etr_I.R @@ -1,5 +1,5 @@ test_that("test-eilers_peeters_etr_I generate regression 20240925.csv - linux", { - skip_if_not(is_debian_or_ubuntu()) + skip_if_not(is_reference_platform()) test_data_file <- testthat::test_path("data", "dual_pam_data", "20240925.csv") data <- read_dual_pam_data(test_data_file) model_result <- eilers_peeters_generate_regression_ETR_I(data) @@ -42,7 +42,7 @@ test_that("test-eilers_peeters_etr_I control plot 20240925.csv", { }) test_that("test-eilers_peeters_etr_I generate regression modified 20240925.csv - linux", { - skip_if_not(is_debian_or_ubuntu()) + skip_if_not(is_reference_platform()) test_data_file <- testthat::test_path("data", "dual_pam_data", "20240925.csv") data <- read_dual_pam_data(test_data_file) diff --git a/src/tests/testthat/test-eilers_peeters_etr_II.R b/src/tests/testthat/test-eilers_peeters_etr_II.R index f9210fb..70f79d0 100644 --- a/src/tests/testthat/test-eilers_peeters_etr_II.R +++ b/src/tests/testthat/test-eilers_peeters_etr_II.R @@ -1,5 +1,5 @@ test_that("test-eilers_peeters_etr_II generate regression 20240925.csv - linux", { - skip_if_not(is_debian_or_ubuntu()) + skip_if_not(is_reference_platform()) test_data_file <- testthat::test_path("data", "dual_pam_data", "20240925.csv") data <- read_dual_pam_data(test_data_file) model_result <- eilers_peeters_generate_regression_ETR_II(data) @@ -23,7 +23,7 @@ test_that("test-eilers_peeters_etr_II generate regression 20240925.csv", { }) test_that("test-eilers_peeters_etr_II modified 20240925.csv - linux", { - skip_if_not(is_debian_or_ubuntu()) + skip_if_not(is_reference_platform()) test_data_file <- testthat::test_path("data", "dual_pam_data", "20240925.csv") data <- read_dual_pam_data(test_data_file) diff --git a/src/tests/testthat/test-platt_etr_I.R b/src/tests/testthat/test-platt_etr_I.R index 419101e..4cd675d 100644 --- a/src/tests/testthat/test-platt_etr_I.R +++ b/src/tests/testthat/test-platt_etr_I.R @@ -1,5 +1,5 @@ test_that("test-platt_etr_I generate regression 20240925.csv - linux", { - skip_if_not(is_debian_or_ubuntu()) + skip_if_not(is_reference_platform()) test_data_file <- testthat::test_path("data", "dual_pam_data", "20240925.csv") data <- read_dual_pam_data(test_data_file) @@ -24,7 +24,7 @@ test_that("test-platt_etr_I generate regression 20240925.csv", { }) test_that("test-platt_etr_I generate regression modified 20240925.csv - linux", { - skip_if_not(is_debian_or_ubuntu()) + skip_if_not(is_reference_platform()) test_data_file <- testthat::test_path("data", "dual_pam_data", "20240925.csv") data <- read_dual_pam_data(test_data_file) diff --git a/src/tests/testthat/test-platt_etr_II.R b/src/tests/testthat/test-platt_etr_II.R index c8b0db6..ff45605 100644 --- a/src/tests/testthat/test-platt_etr_II.R +++ b/src/tests/testthat/test-platt_etr_II.R @@ -1,5 +1,5 @@ test_that("test-platt_etr_II generate regression 20240925.csv - linux", { - skip_if_not(is_debian_or_ubuntu()) + skip_if_not(is_reference_platform()) test_data_file <- testthat::test_path("data", "dual_pam_data", "20240925.csv") data <- read_dual_pam_data(test_data_file) @@ -43,7 +43,7 @@ test_that("test-platt_etr_II control plot 20240925.csv", { }) test_that("test-platt_etr_II generate regression modified 20240925.csv - linux", { - skip_if_not(is_debian_or_ubuntu()) + skip_if_not(is_reference_platform()) test_data_file <- testthat::test_path("data", "dual_pam_data", "20240925.csv") data <- read_dual_pam_data(test_data_file) diff --git a/src/tests/testthat/test-relative_root_mean_squared_error.R b/src/tests/testthat/test-relative_root_mean_squared_error.R index 938371b..430a398 100644 --- a/src/tests/testthat/test-relative_root_mean_squared_error.R +++ b/src/tests/testthat/test-relative_root_mean_squared_error.R @@ -1,5 +1,5 @@ test_that("test-relative_root_mean_squared_error - linux", { - skip_if_not(is_debian_or_ubuntu()) + skip_if_not(is_reference_platform()) test_data_file <- testthat::test_path("data", "dual_pam_data", "20240925.csv") data <- read_dual_pam_data(test_data_file) diff --git a/src/tests/testthat/test-root_mean_squared_error.R b/src/tests/testthat/test-root_mean_squared_error.R index f29912d..a6066dc 100644 --- a/src/tests/testthat/test-root_mean_squared_error.R +++ b/src/tests/testthat/test-root_mean_squared_error.R @@ -1,5 +1,5 @@ test_that("test-root_mean_squared_error - linux", { - skip_if_not(is_debian_or_ubuntu()) + skip_if_not(is_reference_platform()) test_data_file <- testthat::test_path("data", "dual_pam_data", "20240925.csv") data <- read_dual_pam_data(test_data_file) diff --git a/src/tests/testthat/test-universal_data_etr_I.R b/src/tests/testthat/test-universal_data_etr_I.R index a2c9986..d2592c3 100644 --- a/src/tests/testthat/test-universal_data_etr_I.R +++ b/src/tests/testthat/test-universal_data_etr_I.R @@ -1,5 +1,5 @@ test_that("test-universal_data_etr_I - linux", { - skip_if_not(is_debian_or_ubuntu()) + skip_if_not(is_reference_platform()) test_data_file <- testthat::test_path("data", "universal_data", "universal_data.csv") data <- read_universal_data(test_data_file) diff --git a/src/tests/testthat/test-vollenweider_etr_I.R b/src/tests/testthat/test-vollenweider_etr_I.R index e1c7772..ac1fb8d 100644 --- a/src/tests/testthat/test-vollenweider_etr_I.R +++ b/src/tests/testthat/test-vollenweider_etr_I.R @@ -1,5 +1,5 @@ test_that("test-vollenweider_etr_I generate regression 20240925.csv - linux", { - skip_if_not(is_debian_or_ubuntu()) + skip_if_not(is_reference_platform()) test_data_file <- testthat::test_path("data", "dual_pam_data", "20240925.csv") data <- read_dual_pam_data(test_data_file) @@ -43,7 +43,7 @@ test_that("test-vollenweider_etr_I control plot 20240925.csv", { }) test_that("test-vollenweider_etr_I generate regression modified 20240925.csv - linux", { - skip_if_not(is_debian_or_ubuntu()) + skip_if_not(is_reference_platform()) test_data_file <- testthat::test_path("data", "dual_pam_data", "20240925.csv") data <- read_dual_pam_data(test_data_file) diff --git a/src/tests/testthat/test-vollenweider_etr_II.R b/src/tests/testthat/test-vollenweider_etr_II.R index a892144..3aac649 100644 --- a/src/tests/testthat/test-vollenweider_etr_II.R +++ b/src/tests/testthat/test-vollenweider_etr_II.R @@ -1,5 +1,5 @@ test_that("test-vollenweider_etr_II generate regression 20240925.csv - linux", { - skip_if_not(is_debian_or_ubuntu()) + skip_if_not(is_reference_platform()) test_data_file <- testthat::test_path("data", "dual_pam_data", "20240925.csv") data <- read_dual_pam_data(test_data_file) @@ -43,7 +43,7 @@ test_that("test-vollenweider_etr_II control plot 20240925.csv", { }) test_that("test-vollenweider_etr_II generate regression modified 20240925.csv - linux", { - skip_if_not(is_debian_or_ubuntu()) + skip_if_not(is_reference_platform()) test_data_file <- testthat::test_path("data", "dual_pam_data", "20240925.csv") data <- read_dual_pam_data(test_data_file) diff --git a/src/tests/testthat/test-walsby_etr_I.R b/src/tests/testthat/test-walsby_etr_I.R index 319fa25..f5b383c 100644 --- a/src/tests/testthat/test-walsby_etr_I.R +++ b/src/tests/testthat/test-walsby_etr_I.R @@ -1,5 +1,5 @@ test_that("test-walsby_etr_I generate regression 20240925.csv - linux", { - skip_if_not(is_debian_or_ubuntu()) + skip_if_not(is_reference_platform()) test_data_file <- testthat::test_path("data", "dual_pam_data", "20240925.csv") data <- read_dual_pam_data(test_data_file) @@ -38,7 +38,7 @@ test_that("test-walsby_etr_I control plot 20240925.csv", { }) test_that("test-walsby_etr_I generate regression modified 20240925.csv - linux", { - skip_if_not(is_debian_or_ubuntu()) + skip_if_not(is_reference_platform()) test_data_file <- testthat::test_path("data", "dual_pam_data", "20240925.csv") data <- read_dual_pam_data(test_data_file) diff --git a/src/tests/testthat/test-walsby_etr_II.R b/src/tests/testthat/test-walsby_etr_II.R index f2dfda3..e3b28fb 100644 --- a/src/tests/testthat/test-walsby_etr_II.R +++ b/src/tests/testthat/test-walsby_etr_II.R @@ -1,5 +1,5 @@ test_that("test-walsby_etr_II generate regression 20240925.csv - linux", { - skip_if_not(is_debian_or_ubuntu()) + skip_if_not(is_reference_platform()) test_data_file <- testthat::test_path("data", "dual_pam_data", "20240925.csv") data <- read_dual_pam_data(test_data_file) @@ -38,7 +38,7 @@ test_that("test-walsby_etr_II control plot 20240925.csv", { }) test_that("test-walsby_etr_II generate regression modified 20240925.csv - linux", { - skip_if_not(is_debian_or_ubuntu()) + skip_if_not(is_reference_platform()) test_data_file <- testthat::test_path("data", "dual_pam_data", "20240925.csv") data <- read_dual_pam_data(test_data_file) From 7a3096cbc9800799299715972eef2c14587b83dc Mon Sep 17 00:00:00 2001 From: JulienBoehm <180776296+JulienBoehm@users.noreply.github.com> Date: Thu, 23 Apr 2026 12:49:57 +0200 Subject: [PATCH 31/32] update BLAS validation in is_reference_platform function to check for specific library path --- src/tests/testthat/helper-os-detection.R | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/tests/testthat/helper-os-detection.R b/src/tests/testthat/helper-os-detection.R index 95b89a7..eb95289 100644 --- a/src/tests/testthat/helper-os-detection.R +++ b/src/tests/testthat/helper-os-detection.R @@ -23,7 +23,7 @@ is_reference_platform <- function() { } blas <- tolower(extSoftVersion()[["BLAS"]]) - if (!grepl("openblas|mkl|atlas|flexiblas|accelerate", blas)) { + if (!grepl("^/usr/lib/.*/blas/libblas\\.so", blas)) { return(FALSE) } From 53f5f135ae2fdd1f679ffc1d9a3b0efcfc60ee79 Mon Sep 17 00:00:00 2001 From: JulienBoehm <180776296+JulienBoehm@users.noreply.github.com> Date: Thu, 23 Apr 2026 12:54:05 +0200 Subject: [PATCH 32/32] bump version to 2.2.0 --- Makefile | 4 ++-- src/DESCRIPTION | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/Makefile b/Makefile index 076f791..f104278 100644 --- a/Makefile +++ b/Makefile @@ -20,9 +20,9 @@ build: buildtest: rm -rf src/tests/testthat/results make build - R CMD check pam_2.1.1.tar.gz + R CMD check pam_2.2.0.tar.gz buildtestcran: rm -rf src/tests/testthat/results make build - R CMD check --as-cran pam_2.1.1.tar.gz \ No newline at end of file + R CMD check --as-cran pam_2.2.0.tar.gz \ No newline at end of file diff --git a/src/DESCRIPTION b/src/DESCRIPTION index f85927c..d5f8cef 100644 --- a/src/DESCRIPTION +++ b/src/DESCRIPTION @@ -1,7 +1,7 @@ Package: pam Type: Package Title: Fast and Efficient Processing of PAM Data -Version: 2.1.1 +Version: 2.2.0 Authors@R: c( person( "Julien",