Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
19 changes: 11 additions & 8 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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

Expand Down Expand Up @@ -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

Expand Down Expand Up @@ -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](img/export_junior_pam.png)

#### Return

Expand Down Expand Up @@ -963,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)

---

Expand All @@ -986,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))
Expand All @@ -1003,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)

---

Expand Down
2 changes: 1 addition & 1 deletion examples/Example_compare_models.R
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down
2 changes: 1 addition & 1 deletion examples/Example_multiple_data.R
Original file line number Diff line number Diff line change
Expand Up @@ -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")
Expand Down
Binary file added img/export_junior_pam.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
2 changes: 1 addition & 1 deletion src/R/compare_regression_models.R
Original file line number Diff line number Diff line change
Expand Up @@ -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(
{
Expand Down
170 changes: 170 additions & 0 deletions src/R/device_dual_pam.R
Original file line number Diff line number Diff line change
@@ -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'")
}
}
Loading
Loading