Nothing
#' Adjust Classifications in Manual Annotations
#'
#' This function adjusts the classifications in manual annotation files based on a class2use file.
#' It loads a specified class2use file and applies the adjustments to all relevant files in the
#' specified manual folder. Optionally, it can also perform compression on the output files.
#' This is the R equivalent function of `start_mc_adjust_classes_user_training` from the
#' `ifcb-analysis` repository (Sosik and Olson 2007).
#'
#' @param class2use_file A character string representing the full path to the class2use file
#' (should be a .mat file).
#' @param manual_folder A character string representing the path to the folder containing manual
#' annotation files. The function will look for files starting with 'D' in this folder.
#' @param do_compression A logical value indicating whether to apply compression to the output files.
#' Defaults to TRUE.
#' @return None
#'
#' @details
#' The MAT files are read and written directly from R, producing output
#' identical to the MATLAB `ifcb-analysis` format.
#'
#' @examples
#' \dontrun{
#' ifcb_adjust_classes("data/config/class2use.mat",
#' "data/manual/2014/")
#' }
#'
#' @export
#'
#' @seealso \code{\link{ifcb_create_class2use}} \url{https://github.com/hsosik/ifcb-analysis}
#'
#' @references Sosik, H. M. and Olson, R. J. (2007), Automated taxonomic classification of phytoplankton sampled with imaging-in-flow cytometry. Limnol. Oceanogr: Methods 5, 204–216.
ifcb_adjust_classes <- function(class2use_file, manual_folder, do_compression = TRUE) {
# Check if file exists
if (!file.exists(class2use_file)) {
cli_abort("{.arg class2use_file} does not exist: {.file {class2use_file}}")
}
# Check if manual folder exists
if (!dir.exists(manual_folder)) {
cli_abort("{.arg manual_folder} does not exist: {.file {manual_folder}}")
}
# Ensure the class2use file has a .mat extension
if (!grepl("\\.mat$", class2use_file)) {
class2use_file <- paste0(class2use_file, ".mat")
}
# Read the class2use cell array (1 x N) from the config file. `[[` rather
# than `$`: partial matching would silently pick class2use_manual or
# class2use_auto from a manual file passed here by mistake.
class2use_vars <- read_mat_v5(class2use_file)
class2use <- class2use_vars[["class2use"]]$data
if (!is.character(class2use) || length(class2use) == 0) {
cli_abort(c(
"No usable {.field class2use} variable in {.file {basename(class2use_file)}}.",
"x" = "Expected a non-empty cell array of class names under the variable name {.field class2use}.",
"i" = "The file holds: {.field {names(class2use_vars)}}."
))
}
# Process every manual file (those starting with 'D') in the folder, in place
files <- list.files(manual_folder, pattern = "^D", full.names = TRUE)
for (file_path in files) {
# Skip empty files
if (file.size(file_path) == 0) {
cli_warn("The manual file {.file {basename(file_path)}} is empty or corrupted.")
next
}
manual_data <- tryCatch(read_mat_v5(file_path), error = function(e) e)
if (inherits(manual_data, "error")) {
# Keep the reader's own message: it names the variable and the reason
# (an unsupported struct, a truncated file, ...), which "empty or
# corrupted" would hide.
cli_warn(c(
"Skipping manual file {.file {basename(file_path)}}.",
"x" = conditionMessage(manual_data)
))
next
}
# Replace the manual class list; mirror it (transposed) into the auto list
# when that field is present, matching the ifcb-analysis behaviour
manual_data$class2use_manual <- mat_var_cell(class2use)
if ("class2use_auto" %in% names(manual_data)) {
manual_data$class2use_auto <- mat_var_cell(t(class2use))
}
write_mat_v5(file_path, manual_data, do_compression = do_compression)
}
}
Any scripts or data that you put into this service are public.
Add the following code to your website.
For more information on customizing the embed code, read Embedding Snippets.