From f41142b2ec009462b45302e2919e62a3d8849033 Mon Sep 17 00:00:00 2001 From: George Chen <72078254+jiajic@users.noreply.github.com> Date: Wed, 16 Oct 2024 09:46:42 -0400 Subject: [PATCH 01/28] temp --- R/clustering.R | 30 +++++++++++++++++------------- man/labelTransfer.Rd | 9 +++++---- 2 files changed, 22 insertions(+), 17 deletions(-) diff --git a/R/clustering.R b/R/clustering.R index f57dd4f84..7ca8141e8 100644 --- a/R/clustering.R +++ b/R/clustering.R @@ -3321,19 +3321,23 @@ setGeneric("labelTransfer", #' @rdname labelTransfer #' @export -setMethod("labelTransfer", signature(x = "giotto", y = "giotto"), function(x, y, - spat_unit = NULL, - feat_type = NULL, - labels, - k = 10, - name = paste0("trnsfr_", labels), - prob = TRUE, - reduction = "cells", - reduction_method = "pca", - reduction_name = "pca", - dimensions_to_use = 1:10, - return_gobject = TRUE, - ...) { +setMethod("labelTransfer", signature(x = "giotto", y = "giotto"), function( + x, y, + spat_unit = NULL, + feat_type = NULL, + labels, + k = 10, + name = paste0("trnsfr_", labels), + prob = TRUE, + co_filter_params = list(), + co_norm_params = list(), + + reduction_name = NULL, + reduction_method = NULL, + dimensions_to_use = NULL, + return_gobject = TRUE, + ... +) { # NSE vars temp_name <- cell_ID <- temp_name_prob <- NULL diff --git a/man/labelTransfer.Rd b/man/labelTransfer.Rd index dbf876a0b..230768609 100644 --- a/man/labelTransfer.Rd +++ b/man/labelTransfer.Rd @@ -16,10 +16,11 @@ voting} k = 10, name = paste0("trnsfr_", labels), prob = TRUE, - reduction = "cells", - reduction_method = "pca", - reduction_name = "pca", - dimensions_to_use = 1:10, + co_filter_params = list(), + co_norm_params = list(), + reduction_name = NULL, + reduction_method = NULL, + dimensions_to_use = NULL, return_gobject = TRUE, ... ) From 3436f4934a090d6dcbe3031195769947f8576df0 Mon Sep 17 00:00:00 2001 From: George Chen <72078254+jiajic@users.noreply.github.com> Date: Wed, 30 Oct 2024 17:24:29 -0400 Subject: [PATCH 02/28] chore: bump version for dev and drop remotes --- DESCRIPTION | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/DESCRIPTION b/DESCRIPTION index 2f88d432a..37810e3f1 100644 --- a/DESCRIPTION +++ b/DESCRIPTION @@ -1,6 +1,6 @@ Package: Giotto Title: Spatial Single-Cell Transcriptomics Toolbox -Version: 4.1.4 +Version: 4.1.5 Authors@R: c( person("Ruben", "Dries", email = "rubendries@gmail.com", role = c("aut", "cre"), comment = c(ORCID = "0000-0001-7650-7754")), @@ -108,10 +108,6 @@ Suggests: trendsceek, testthat (>= 3.0.0), rmarkdown -Remotes: - drieslab/GiottoUtils, - drieslab/GiottoClass, - drieslab/GiottoVisuals Collate: 'ONTraC_wrapper.R' 'auxiliary_giotto.R' From 578f39ef3424daf351cb26c5908a9b5566a96406 Mon Sep 17 00:00:00 2001 From: George Chen <72078254+jiajic@users.noreply.github.com> Date: Wed, 6 Nov 2024 13:40:38 -0500 Subject: [PATCH 03/28] Update convenience_xenium.R --- R/convenience_xenium.R | 145 +++++++++++++++++++++++++++++------------ 1 file changed, 104 insertions(+), 41 deletions(-) diff --git a/R/convenience_xenium.R b/R/convenience_xenium.R index fa305be0b..d7e52dfe9 100644 --- a/R/convenience_xenium.R +++ b/R/convenience_xenium.R @@ -317,6 +317,7 @@ setMethod( # load image call img_fun <- function(path, name = "image", + output_dir, micron = obj@micron, negative_y = TRUE, flip_vertical = FALSE, @@ -325,6 +326,7 @@ setMethod( .xenium_image( path = path, name = name, + output_dir = output_dir, micron = micron, negative_y = negative_y, flip_vertical = flip_vertical, @@ -371,7 +373,7 @@ setMethod( "UnassignedCodeword", "NegControlCodeword" ), - load_images = NULL, + load_images = "focus", load_aligned_images = NULL, load_expression = FALSE, load_cellmeta = FALSE, @@ -483,10 +485,28 @@ setMethod( # images + load_images <- lapply(load_images, normalizePath) + img_focus_path <- normalizePath(img_focus_path) + + # [exception] handle focus image dir + is_focus <- load_images == "focus" | load_images == img_focus_path + # split the focus image dir away from other entries + focus_dir <- load_images[is_focus][[1]] + load_images <- load_images[!is_focus] + + # ignore any name the focus dir has + focus_dir <- as.character(focus_dir) + names(focus_dir) <- NULL + + focus_files <- list.files(focus_dir, full.names = TRUE) + nbound <- length(focus_files) - 1L + focus_names <- c("dapi", sprintf("bound%d", seq_len(nbound))) + names(focus_files) <- focus_names + + # append to rest of entries + load_images <- c(load_images, focus_files) + if (!is.null(load_images)) { - # replace convenient shortnames - load_images[load_images == "focus"] <- img_focus_path - imglist <- list() imnames <- names(load_images) for (impath_i in seq_along(load_images)) { @@ -500,7 +520,7 @@ setMethod( } # aligned images can be placed in random places and do not have - # a standardized naming scheme. + # a standardized naming scheme. Cannot load with expected default. if (!is.null(load_aligned_images)) { aimglist <- list() @@ -1041,9 +1061,10 @@ importXenium <- function(xenium_dir = NULL, qv_threshold = 20) { ## image #### + .xenium_image <- function(path, name, - # output_dir, + output_dir, micron, negative_y = TRUE, flip_vertical = FALSE, @@ -1055,37 +1076,39 @@ importXenium <- function(xenium_dir = NULL, qv_threshold = 20) { "No path to image file provided or auto-detected" ), call. = FALSE) } - - # # [directory input] -> load as individual .ome paths with defined names - # # intended for usage with single channel stain focus images - # if (checkmate::test_directory_exists(path)) { - # if (missing(output_dir)) output_dir <- file.path(path, "tif_exports") - # # find actual image paths in directory - # ome_paths <- list.files(path, full.names = TRUE, pattern = ".ome") - # # parse ome metadata for images names - # ome_xml <- ometif_metadata( - # ome_paths[[1]], node = "Channel", output = "data.frame" - # ) - # # update names with the channel names - # name <- ome_xml$Name - # - # # do conversion if file does not already exist in output_dir - # vmsg(.v = verbose, "> ometif to tif conversion") - # lapply(ome_paths, function(ome) { - # try(silent = TRUE, { # ignore fail when already written - # ometif_to_tif( - # # can pass overwrite = TRUE via ... if needed - # ome, output_dir = output_dir, ... - # ) - # }) - # }) - # # update path param - # path <- list.files(output_dir, pattern = ".tif", full.names = TRUE) - # } + + # *** whether .ome or not does not matter for this function *** # # set default if still missing if (missing(name)) name <- "image" + # [directory input] -> load as individual image paths + # these need to be expanded then appended to running named list of images + is_dir <- vapply(path, dir.exists, FUN.VALUE = logical(1L)) + dir_path <- path[is_dir] + dir_name <- name[is_dir] + path <- path[!is_dir] + name <- name[!is_dir] + + # expand directory inputs + if (length(dir_path) > 0L) { + for (dir_i in seq_along(dir_path)) { + dp_i <- dir_path[[dir_i]] # dir path + dn_i <- dir_name[[dir_i]] # dir name + vmsg(.is_debug = TRUE, "img dir input:", dp_i) + + # expand and update to per-image + dfp_i <- list.files(dp_i, full.names = TRUE) # dir file paths + dfn_i <- sprintf("%s_%d", dn_i, seq_along(dfp_i)) # dir file names + vmsg(.is_debug = TRUE, "* [img paths]:\n", paste(dfp_i, collapse = "\n")) + vmsg(.is_debug = TRUE, "* [img names]:\n", paste(dfn_i, collapse = "\n")) + + # append to single file lists + path <- c(path, dfp_i) + name <- c(name, dfn_i) + } + } + # [paths] # check files exist vapply(path, checkmate::assert_file_exists, FUN.VALUE = character(1L)) @@ -1105,9 +1128,11 @@ importXenium <- function(xenium_dir = NULL, qv_threshold = 20) { p <- pbar(along = path) gimg_list <- lapply(seq_along(path), function(img_i) { + # handle .ome conversion and image subobject creation gimg <- .xenium_image_single( path = path[[img_i]], name = name[[img_i]], + output_dir = output_dir, micron = micron, negative_y = negative_y, flip_vertical = flip_vertical, @@ -1121,12 +1146,19 @@ importXenium <- function(xenium_dir = NULL, qv_threshold = 20) { return(gimg_list) } +# per image... +# if .ome : check that converted output path file exists. +# if exists && if overwrite : remove converted image +# if still not exist : create converted image +# use image .xenium_image_single <- function(path, name = "image", + output_dir, micron, negative_y = TRUE, flip_vertical = FALSE, flip_horizontal = FALSE, + overwrite = FALSE, verbose = NULL) { vmsg(.v = verbose, sprintf("loading image as '%s'", name)) vmsg(.v = verbose, .is_debug = TRUE, path) @@ -1139,14 +1171,45 @@ importXenium <- function(xenium_dir = NULL, qv_threshold = 20) { .prefix = "" ) - # warning to for single channel .ome.tif images that terra::rast() and - # gdal still have difficulties with. May be related to JP2OpenJPEG driver - # but even loading this does not seem to fix it. - if (file_extension(path) %in% "ome") { - warning(wrap_txt( - ".ome.tif images not fully supported. - If reading fails, try converting to a basic tif `ometif_to_tif()`" - )) + # terra::rast() and gdal still have difficulties with 10x single channel + # .ome.tif images. May be related to JP2OpenJPEG driver but even loading + # this does not seem to fix it. + if ("ome" %in% file_extension(path)) { + if (missing(output_dir)) { + # default output dir is a new folder under the same directory + output_dir <- file.path(dirname(path), "tif_exports") + } + + # check for existence of converted tiff file in output dir + # fullpath of tiff to write + tiff_path <- file.path(output_dir, basename(path)) + if (checkmate::test_file_exists(tiff_path)) { + vmsg(.is_debug = TRUE, sprintf( + "converted tiff already present\n%s", tiff_path + )) + # if found AND overwrite, remove it to be regenerated downstream + if (isTRUE(overwrite)) { + unlink(tiff_path, force = TRUE) + } + # the convenience fun can be run multiple times on the dataset + # So, we allow directly using already converted imgs + } + + # check the fullpath again + if (!checkmate::test_file_exists(tiff_path)) { + vmsg(.is_debug = TRUE, sprintf( + "converting ome to tif\n%s", tiff_path + )) + # if missing, do conversion + # output is expected at `tiff_path` + ometif_to_tif( + input_file = path, + output_dir = output_dir, + overwrite = overwrite + ) + } + + path <- tiff_path } img <- createGiottoLargeImage(path, From ae212be87a5f55520080189d10611f9c897cb675 Mon Sep 17 00:00:00 2001 From: George Chen <72078254+jiajic@users.noreply.github.com> Date: Wed, 6 Nov 2024 13:41:37 -0500 Subject: [PATCH 04/28] Revert "temp" This reverts commit f41142b2ec009462b45302e2919e62a3d8849033. --- R/clustering.R | 30 +++++++++++++----------------- man/labelTransfer.Rd | 9 ++++----- 2 files changed, 17 insertions(+), 22 deletions(-) diff --git a/R/clustering.R b/R/clustering.R index 7ca8141e8..f57dd4f84 100644 --- a/R/clustering.R +++ b/R/clustering.R @@ -3321,23 +3321,19 @@ setGeneric("labelTransfer", #' @rdname labelTransfer #' @export -setMethod("labelTransfer", signature(x = "giotto", y = "giotto"), function( - x, y, - spat_unit = NULL, - feat_type = NULL, - labels, - k = 10, - name = paste0("trnsfr_", labels), - prob = TRUE, - co_filter_params = list(), - co_norm_params = list(), - - reduction_name = NULL, - reduction_method = NULL, - dimensions_to_use = NULL, - return_gobject = TRUE, - ... -) { +setMethod("labelTransfer", signature(x = "giotto", y = "giotto"), function(x, y, + spat_unit = NULL, + feat_type = NULL, + labels, + k = 10, + name = paste0("trnsfr_", labels), + prob = TRUE, + reduction = "cells", + reduction_method = "pca", + reduction_name = "pca", + dimensions_to_use = 1:10, + return_gobject = TRUE, + ...) { # NSE vars temp_name <- cell_ID <- temp_name_prob <- NULL diff --git a/man/labelTransfer.Rd b/man/labelTransfer.Rd index 230768609..dbf876a0b 100644 --- a/man/labelTransfer.Rd +++ b/man/labelTransfer.Rd @@ -16,11 +16,10 @@ voting} k = 10, name = paste0("trnsfr_", labels), prob = TRUE, - co_filter_params = list(), - co_norm_params = list(), - reduction_name = NULL, - reduction_method = NULL, - dimensions_to_use = NULL, + reduction = "cells", + reduction_method = "pca", + reduction_name = "pca", + dimensions_to_use = 1:10, return_gobject = TRUE, ... ) From f61dcfd1e1589eaf9a0a8a383a5e3a05babb3df6 Mon Sep 17 00:00:00 2001 From: George Chen <72078254+jiajic@users.noreply.github.com> Date: Wed, 6 Nov 2024 13:57:33 -0500 Subject: [PATCH 05/28] Update convenience_xenium.R --- R/convenience_xenium.R | 1 + 1 file changed, 1 insertion(+) diff --git a/R/convenience_xenium.R b/R/convenience_xenium.R index d7e52dfe9..c0d084621 100644 --- a/R/convenience_xenium.R +++ b/R/convenience_xenium.R @@ -1014,6 +1014,7 @@ importXenium <- function(xenium_dir = NULL, qv_threshold = 20) { fname <- "rna" if (length(names(ex_list)) > 1L) fname <- names(ex_list) fname[fname == "Gene Expression"] <- "rna" + fname <- gsub(" ", "_", fname) # replace " " with "_" characters # lapply to process more than one if present eo_list <- lapply(seq_along(ex_list), function(ex_i) { From 8b0950f6be5aea2b486634eb25a747bc5502b708 Mon Sep 17 00:00:00 2001 From: George Chen <72078254+jiajic@users.noreply.github.com> Date: Wed, 6 Nov 2024 14:15:19 -0500 Subject: [PATCH 06/28] temporarily lower R ver --- DESCRIPTION | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/DESCRIPTION b/DESCRIPTION index 4c3a03d74..9ed33d372 100644 --- a/DESCRIPTION +++ b/DESCRIPTION @@ -26,7 +26,7 @@ URL: https://drieslab.github.io/Giotto/, https://github.com/drieslab/Giotto BugReports: https://github.com/drieslab/Giotto/issues RoxygenNote: 7.3.2 Depends: - R (>= 4.4.1), + R (>= 4.4.0), methods, GiottoClass (>= 0.4.1) Imports: From ad9314f53eae2021bb018416829141ed4bba674d Mon Sep 17 00:00:00 2001 From: George Chen <72078254+jiajic@users.noreply.github.com> Date: Wed, 6 Nov 2024 16:33:13 -0500 Subject: [PATCH 07/28] Update convenience_xenium.R --- R/convenience_xenium.R | 24 +++++++++++++----------- 1 file changed, 13 insertions(+), 11 deletions(-) diff --git a/R/convenience_xenium.R b/R/convenience_xenium.R index c0d084621..065ec7b89 100644 --- a/R/convenience_xenium.R +++ b/R/convenience_xenium.R @@ -315,7 +315,7 @@ setMethod( obj@calls$load_expression <- expr_fun # load image call - img_fun <- function(path, + img_fun <- function(path = img_focus_path, name = "image", output_dir, micron = obj@micron, @@ -1082,6 +1082,16 @@ importXenium <- function(xenium_dir = NULL, qv_threshold = 20) { # set default if still missing if (missing(name)) name <- "image" + + # [names] + if (length(name) != length(path) && + length(name) != 1) { + stop("length of `name` should be same as length of `path`") + } + if (length(name) == 1 && + length(path) > 1) { + name <- sprintf("%s_%d", name, seq_along(path)) + } # [directory input] -> load as individual image paths # these need to be expanded then appended to running named list of images @@ -1109,19 +1119,11 @@ importXenium <- function(xenium_dir = NULL, qv_threshold = 20) { name <- c(name, dfn_i) } } - + # [paths] # check files exist vapply(path, checkmate::assert_file_exists, FUN.VALUE = character(1L)) - # names - if (length(name) != length(path) && - length(name) != 1) { - stop("length of `name` should be same as length of `path`") - } - if (length(name) == 1 && - length(path) > 1) { - name <- sprintf("%s_%d", name, seq_along(path)) - } + # micron checkmate::assert_numeric(micron) From f9818351145cdc5baa41662ed362de1d6aa52f72 Mon Sep 17 00:00:00 2001 From: George Chen <72078254+jiajic@users.noreply.github.com> Date: Wed, 6 Nov 2024 16:43:38 -0500 Subject: [PATCH 08/28] Update convenience_xenium.R --- R/convenience_xenium.R | 2 ++ 1 file changed, 2 insertions(+) diff --git a/R/convenience_xenium.R b/R/convenience_xenium.R index 065ec7b89..cdc8eaea9 100644 --- a/R/convenience_xenium.R +++ b/R/convenience_xenium.R @@ -1110,6 +1110,8 @@ importXenium <- function(xenium_dir = NULL, qv_threshold = 20) { # expand and update to per-image dfp_i <- list.files(dp_i, full.names = TRUE) # dir file paths + dfp_i <- dfp_i[!dir.exists(dfp_i)] # ignore dir matches + # (such as the export directory) dfn_i <- sprintf("%s_%d", dn_i, seq_along(dfp_i)) # dir file names vmsg(.is_debug = TRUE, "* [img paths]:\n", paste(dfp_i, collapse = "\n")) vmsg(.is_debug = TRUE, "* [img names]:\n", paste(dfn_i, collapse = "\n")) From eff1c71c8aa58000df61b32b90584ad0788ae4d9 Mon Sep 17 00:00:00 2001 From: George Chen <72078254+jiajic@users.noreply.github.com> Date: Wed, 6 Nov 2024 17:09:42 -0500 Subject: [PATCH 09/28] Update convenience_xenium.R --- R/convenience_xenium.R | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/R/convenience_xenium.R b/R/convenience_xenium.R index cdc8eaea9..0fc37ac20 100644 --- a/R/convenience_xenium.R +++ b/R/convenience_xenium.R @@ -1065,7 +1065,7 @@ importXenium <- function(xenium_dir = NULL, qv_threshold = 20) { .xenium_image <- function(path, name, - output_dir, + output_dir = "default", # new tif_exports folder one layer down micron, negative_y = TRUE, flip_vertical = FALSE, @@ -1180,7 +1180,7 @@ importXenium <- function(xenium_dir = NULL, qv_threshold = 20) { # .ome.tif images. May be related to JP2OpenJPEG driver but even loading # this does not seem to fix it. if ("ome" %in% file_extension(path)) { - if (missing(output_dir)) { + if (output_dir == "default") { # default output dir is a new folder under the same directory output_dir <- file.path(dirname(path), "tif_exports") } From 8bf5431fd570a542c39ec01ccfeddbdc3057733a Mon Sep 17 00:00:00 2001 From: George Chen <72078254+jiajic@users.noreply.github.com> Date: Wed, 6 Nov 2024 17:17:48 -0500 Subject: [PATCH 10/28] Update convenience_xenium.R --- R/convenience_xenium.R | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/R/convenience_xenium.R b/R/convenience_xenium.R index 0fc37ac20..5c8d0a50b 100644 --- a/R/convenience_xenium.R +++ b/R/convenience_xenium.R @@ -1065,7 +1065,7 @@ importXenium <- function(xenium_dir = NULL, qv_threshold = 20) { .xenium_image <- function(path, name, - output_dir = "default", # new tif_exports folder one layer down + output_dir, micron, negative_y = TRUE, flip_vertical = FALSE, @@ -1082,6 +1082,8 @@ importXenium <- function(xenium_dir = NULL, qv_threshold = 20) { # set default if still missing if (missing(name)) name <- "image" + # default = new tif_exports folder one layer down + if (missing(output_dir)) output_dir <- "default" # [names] if (length(name) != length(path) && From 0157ba8c54083addc5c253acf652b6c430d230c7 Mon Sep 17 00:00:00 2001 From: George Chen <72078254+jiajic@users.noreply.github.com> Date: Thu, 7 Nov 2024 08:30:47 -0500 Subject: [PATCH 11/28] fix tif path checking --- R/convenience_xenium.R | 1 + 1 file changed, 1 insertion(+) diff --git a/R/convenience_xenium.R b/R/convenience_xenium.R index 5c8d0a50b..57994a66e 100644 --- a/R/convenience_xenium.R +++ b/R/convenience_xenium.R @@ -1190,6 +1190,7 @@ importXenium <- function(xenium_dir = NULL, qv_threshold = 20) { # check for existence of converted tiff file in output dir # fullpath of tiff to write tiff_path <- file.path(output_dir, basename(path)) + tiff_path <- gsub(".ome.tif", ".tif", tiff_path) if (checkmate::test_file_exists(tiff_path)) { vmsg(.is_debug = TRUE, sprintf( "converted tiff already present\n%s", tiff_path From 2eb20b56ea77baa1de626c84f6cf2ee7288f91fb Mon Sep 17 00:00:00 2001 From: George Chen <72078254+jiajic@users.noreply.github.com> Date: Thu, 7 Nov 2024 09:19:24 -0500 Subject: [PATCH 12/28] Update convenience_xenium.R --- R/convenience_xenium.R | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) diff --git a/R/convenience_xenium.R b/R/convenience_xenium.R index 57994a66e..570edbf63 100644 --- a/R/convenience_xenium.R +++ b/R/convenience_xenium.R @@ -1013,8 +1013,19 @@ importXenium <- function(xenium_dir = NULL, qv_threshold = 20) { # set correct feature name fname <- "rna" if (length(names(ex_list)) > 1L) fname <- names(ex_list) + + # specific feat type naming updates fname[fname == "Gene Expression"] <- "rna" - fname <- gsub(" ", "_", fname) # replace " " with "_" characters + fname[fname == "Negative Control Codeword"] <- "NegControlCodeword" + fname[fname == "Negative Control Probe"] <- "NegControlProbe" + fname[fname == "Blank Codeword"] <- "UnassignedCodeword" # from legacy Xenium pipeline + fname[fname == "Genomic Control"] <- "GenomicControl" + fname[fname == "Unassigned Codeword"] <- "UnassignedCodeword" + fname[fname == "Deprecated Codeword"] <- "DeprecatedCodeword" + + # catch for " " characters in feat type + # (no major reason for doing this. spaces just make it harder to read) + fname <- gsub(" ", "_", fname) # lapply to process more than one if present eo_list <- lapply(seq_along(ex_list), function(ex_i) { From 57788f03f95f4929be22e3f346bb31392b0a041d Mon Sep 17 00:00:00 2001 From: George Chen <72078254+jiajic@users.noreply.github.com> Date: Thu, 7 Nov 2024 09:27:50 -0500 Subject: [PATCH 13/28] fix: allow overwrite passing though ... --- R/convenience_xenium.R | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/R/convenience_xenium.R b/R/convenience_xenium.R index 570edbf63..6c5fbd0a8 100644 --- a/R/convenience_xenium.R +++ b/R/convenience_xenium.R @@ -322,7 +322,8 @@ setMethod( negative_y = TRUE, flip_vertical = FALSE, flip_horizontal = FALSE, - verbose = NULL) { + verbose = NULL, + ...) { .xenium_image( path = path, name = name, @@ -331,7 +332,8 @@ setMethod( negative_y = negative_y, flip_vertical = flip_vertical, flip_horizontal = flip_horizontal, - verbose = verbose + verbose = verbose, + ... ) } obj@calls$load_image <- img_fun @@ -1156,6 +1158,7 @@ importXenium <- function(xenium_dir = NULL, qv_threshold = 20) { flip_vertical = flip_vertical, flip_horizontal = flip_horizontal, verbose = verbose + ... ) p() return(gimg) From 8555ccf5cc88704ac216848c78bdd8c483cd50a7 Mon Sep 17 00:00:00 2001 From: George Chen <72078254+jiajic@users.noreply.github.com> Date: Thu, 7 Nov 2024 10:10:43 -0500 Subject: [PATCH 14/28] fix: change when image input type is checked --- R/convenience_xenium.R | 54 +++++++++++++++++++++--------------------- 1 file changed, 27 insertions(+), 27 deletions(-) diff --git a/R/convenience_xenium.R b/R/convenience_xenium.R index 6c5fbd0a8..1a4f41188 100644 --- a/R/convenience_xenium.R +++ b/R/convenience_xenium.R @@ -384,12 +384,6 @@ setMethod( load_expression <- as.logical(load_expression) load_cellmeta <- as.logical(load_cellmeta) - if (!is.null(load_images)) { - checkmate::assert_list(load_images) - if (is.null(names(load_images))) { - stop("'load_images' must be a named list of filepaths\n") - } - } if (!is.null(load_aligned_images)) { checkmate::assert_list(load_aligned_images) if (is.null(names(load_aligned_images))) { @@ -487,28 +481,34 @@ setMethod( # images - load_images <- lapply(load_images, normalizePath) - img_focus_path <- normalizePath(img_focus_path) - - # [exception] handle focus image dir - is_focus <- load_images == "focus" | load_images == img_focus_path - # split the focus image dir away from other entries - focus_dir <- load_images[is_focus][[1]] - load_images <- load_images[!is_focus] - - # ignore any name the focus dir has - focus_dir <- as.character(focus_dir) - names(focus_dir) <- NULL - - focus_files <- list.files(focus_dir, full.names = TRUE) - nbound <- length(focus_files) - 1L - focus_names <- c("dapi", sprintf("bound%d", seq_len(nbound))) - names(focus_files) <- focus_names - - # append to rest of entries - load_images <- c(load_images, focus_files) - if (!is.null(load_images)) { + load_images <- lapply(load_images, normalizePath) + img_focus_path <- normalizePath(img_focus_path) + + # [exception] handle focus image dir + is_focus <- load_images == "focus" | load_images == img_focus_path + # split the focus image dir away from other entries + focus_dir <- load_images[is_focus][[1]] + load_images <- load_images[!is_focus] + + # ignore any name the focus dir has + focus_dir <- as.character(focus_dir) + names(focus_dir) <- NULL + + focus_files <- list.files(focus_dir, full.names = TRUE) + nbound <- length(focus_files) - 1L + focus_names <- c("dapi", sprintf("bound%d", seq_len(nbound))) + names(focus_files) <- focus_names + + # append to rest of entries + load_images <- c(load_images, focus_files) + + # ensure that input is list + checkmate::assert_list(load_images) + if (is.null(names(load_images))) { + stop("'load_images' must be a named list of filepaths\n") + } + imglist <- list() imnames <- names(load_images) for (impath_i in seq_along(load_images)) { From 52abd97749d1fa3947fdcfaf13c4c52b59d154a8 Mon Sep 17 00:00:00 2001 From: George Chen <72078254+jiajic@users.noreply.github.com> Date: Thu, 7 Nov 2024 10:12:43 -0500 Subject: [PATCH 15/28] fix: missing comma --- R/convenience_xenium.R | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/R/convenience_xenium.R b/R/convenience_xenium.R index 1a4f41188..ec5e14a69 100644 --- a/R/convenience_xenium.R +++ b/R/convenience_xenium.R @@ -1157,7 +1157,7 @@ importXenium <- function(xenium_dir = NULL, qv_threshold = 20) { negative_y = negative_y, flip_vertical = flip_vertical, flip_horizontal = flip_horizontal, - verbose = verbose + verbose = verbose, ... ) p() From 5359eb2831929459836d47648fc7b7bbdbfcb762 Mon Sep 17 00:00:00 2001 From: George Chen <72078254+jiajic@users.noreply.github.com> Date: Thu, 7 Nov 2024 10:32:20 -0500 Subject: [PATCH 16/28] fix: warning that the "focus" dir does not exist --- R/convenience_xenium.R | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/R/convenience_xenium.R b/R/convenience_xenium.R index ec5e14a69..a42a20e85 100644 --- a/R/convenience_xenium.R +++ b/R/convenience_xenium.R @@ -483,7 +483,7 @@ setMethod( # images if (!is.null(load_images)) { load_images <- lapply(load_images, normalizePath) - img_focus_path <- normalizePath(img_focus_path) + img_focus_path <- normalizePath(img_focus_path, mustWork = FALSE) # [exception] handle focus image dir is_focus <- load_images == "focus" | load_images == img_focus_path From 4d357502ec9820e3f0e187b89b4d7629fba26d8d Mon Sep 17 00:00:00 2001 From: George Chen <72078254+jiajic@users.noreply.github.com> Date: Thu, 7 Nov 2024 10:36:26 -0500 Subject: [PATCH 17/28] fix: focus img dir assignment --- R/convenience_xenium.R | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/R/convenience_xenium.R b/R/convenience_xenium.R index a42a20e85..46c82b214 100644 --- a/R/convenience_xenium.R +++ b/R/convenience_xenium.R @@ -488,12 +488,8 @@ setMethod( # [exception] handle focus image dir is_focus <- load_images == "focus" | load_images == img_focus_path # split the focus image dir away from other entries - focus_dir <- load_images[is_focus][[1]] load_images <- load_images[!is_focus] - - # ignore any name the focus dir has - focus_dir <- as.character(focus_dir) - names(focus_dir) <- NULL + focus_dir <- img_focus_path focus_files <- list.files(focus_dir, full.names = TRUE) nbound <- length(focus_files) - 1L From a23ca0e5ca48132a6bc8c2e81e027f7013a9c3f9 Mon Sep 17 00:00:00 2001 From: George Chen <72078254+jiajic@users.noreply.github.com> Date: Thu, 7 Nov 2024 11:25:43 -0500 Subject: [PATCH 18/28] Update convenience_xenium.R - make transcript loading optional in create_gobject - change featmeta loading to after possible expr matrix loading - silence verbosity when loading TX cols --- R/convenience_xenium.R | 54 ++++++++++++++++++++++++++---------------- 1 file changed, 33 insertions(+), 21 deletions(-) diff --git a/R/convenience_xenium.R b/R/convenience_xenium.R index 46c82b214..4bddb3975 100644 --- a/R/convenience_xenium.R +++ b/R/convenience_xenium.R @@ -377,12 +377,20 @@ setMethod( ), load_images = "focus", load_aligned_images = NULL, + load_transcripts = TRUE, load_expression = FALSE, load_cellmeta = FALSE, instructions = NULL, verbose = NULL) { + load_transcripts <- as.logical(load_transcripts) load_expression <- as.logical(load_expression) load_cellmeta <- as.logical(load_cellmeta) + + if (!load_transcripts && !load_expression) { + warning(wrap_txt( + "One of either transcripts or expression info should be loaded for a fully functioning object" + )) + } if (!is.null(load_aligned_images)) { checkmate::assert_list(load_aligned_images) @@ -418,14 +426,17 @@ setMethod( # transcripts - tx_list <- funs$load_transcripts( - path = transcript_path, - feat_type = feat_type, - split_keyword = split_keyword, - verbose = verbose - ) - g <- setGiotto(g, tx_list, verbose = FALSE) # lists are fine + if (load_transcripts) { + tx_list <- funs$load_transcripts( + path = transcript_path, + feat_type = feat_type, + split_keyword = split_keyword, + verbose = verbose + ) + g <- setGiotto(g, tx_list, verbose = FALSE) # lists are fine + } + # polys if (!is.null(load_bounds)) { # replace convenient shortnames @@ -444,19 +455,8 @@ setMethod( } g <- setGiotto(g, blist, verbose = FALSE) } - - - # feat metadata - fx <- funs$load_featmeta( - path = gene_panel_json_path, - # ID = symbols makes sense with the subcellular feat_IDs - gene_ids = "symbols", - # no dropcols - verbose = verbose - ) - g <- setGiotto(g, fx, verbose = FALSE) - - + + # expression if (load_expression) { ex <- funs$load_expression( @@ -470,6 +470,17 @@ setMethod( } + # feat metadata + fx <- funs$load_featmeta( + path = gene_panel_json_path, + # ID = symbols makes sense with the subcellular feat_IDs + gene_ids = "symbols", + # no dropcols + verbose = verbose + ) + g <- setGiotto(g, fx, verbose = FALSE) + + # cell metadata if (load_cellmeta) { cx <- funs$load_cellmeta( @@ -680,7 +691,8 @@ importXenium <- function(xenium_dir = NULL, qv_threshold = 20) { gpointslist <- createGiottoPoints( x = tx, feat_type = feat_type, - split_keyword = split_keyword + split_keyword = split_keyword, + verbose = FALSE ) if (inherits(gpointslist, "list")) { From 0559c448e47967d0f9bac692379aaf238b4b4069 Mon Sep 17 00:00:00 2001 From: George Chen <72078254+jiajic@users.noreply.github.com> Date: Thu, 7 Nov 2024 11:44:12 -0500 Subject: [PATCH 19/28] fix: ignore subdirectories within image focus dir --- R/convenience_xenium.R | 21 ++++++++++++--------- 1 file changed, 12 insertions(+), 9 deletions(-) diff --git a/R/convenience_xenium.R b/R/convenience_xenium.R index 4bddb3975..a05df423e 100644 --- a/R/convenience_xenium.R +++ b/R/convenience_xenium.R @@ -493,22 +493,25 @@ setMethod( # images if (!is.null(load_images)) { - load_images <- lapply(load_images, normalizePath) + load_images <- lapply(load_images, normalizePath, mustWork = FALSE) img_focus_path <- normalizePath(img_focus_path, mustWork = FALSE) # [exception] handle focus image dir is_focus <- load_images == "focus" | load_images == img_focus_path # split the focus image dir away from other entries load_images <- load_images[!is_focus] - focus_dir <- img_focus_path - focus_files <- list.files(focus_dir, full.names = TRUE) - nbound <- length(focus_files) - 1L - focus_names <- c("dapi", sprintf("bound%d", seq_len(nbound))) - names(focus_files) <- focus_names - - # append to rest of entries - load_images <- c(load_images, focus_files) + if (any(is_focus)) { + focus_dir <- img_focus_path + focus_files <- list.files(focus_dir, full.names = TRUE) + focus_files <- focus_files[!dir.exists(focus_files)] # ignore matches to export dir + nbound <- length(focus_files) - 1L + focus_names <- c("dapi", sprintf("bound%d", seq_len(nbound))) + names(focus_files) <- focus_names + + # append to rest of entries + load_images <- c(load_images, focus_files) + } # ensure that input is list checkmate::assert_list(load_images) From 4a9da54a0b0a942cad797c6162a2fbc3b2e09aaa Mon Sep 17 00:00:00 2001 From: George Chen <72078254+jiajic@users.noreply.github.com> Date: Thu, 7 Nov 2024 11:52:20 -0500 Subject: [PATCH 20/28] add centroid creation step --- R/convenience_xenium.R | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/R/convenience_xenium.R b/R/convenience_xenium.R index a05df423e..7d237a6f4 100644 --- a/R/convenience_xenium.R +++ b/R/convenience_xenium.R @@ -551,6 +551,11 @@ setMethod( } g <- setGiotto(g, aimglist) } + + # centroids + g <- addSpatialCentroidLocations( + g, poly_info = list_spatial_info_names(g)[[1]] + ) return(g) } From 84c9cd2f46adcb4374d8312099adace5e567283b Mon Sep 17 00:00:00 2001 From: George Chen <72078254+jiajic@users.noreply.github.com> Date: Thu, 7 Nov 2024 12:01:28 -0500 Subject: [PATCH 21/28] Update convenience_xenium.R --- R/convenience_xenium.R | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/R/convenience_xenium.R b/R/convenience_xenium.R index 7d237a6f4..c7449f9a6 100644 --- a/R/convenience_xenium.R +++ b/R/convenience_xenium.R @@ -553,8 +553,11 @@ setMethod( } # centroids - g <- addSpatialCentroidLocations( - g, poly_info = list_spatial_info_names(g)[[1]] + spat_units_to_calc <- list_spatial_info_names(g) + g <- addSpatialCentroidLocations(g, + poly_info = spat_units_to_calc, + provenance = as.list(spat_units_to_calc), + verbose = FALSE ) return(g) From 1e33aa1a720320f366443cda59b19fea9f62f39f Mon Sep 17 00:00:00 2001 From: George Chen <72078254+jiajic@users.noreply.github.com> Date: Thu, 7 Nov 2024 12:25:20 -0500 Subject: [PATCH 22/28] enh: update conv. fun - autoload focus images - auto load pre-agg data + metadata - skip tx by default --- R/convenience_xenium.R | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/R/convenience_xenium.R b/R/convenience_xenium.R index c7449f9a6..85f662acb 100644 --- a/R/convenience_xenium.R +++ b/R/convenience_xenium.R @@ -1383,10 +1383,11 @@ createGiottoXeniumObject <- function(xenium_dir, "NegControlCodeword" ), qv_threshold = 20, - load_images = NULL, + load_images = "focus", load_aligned_images = NULL, - load_expression = FALSE, - load_cellmeta = FALSE, + load_transcripts = FALSE, + load_expression = TRUE, + load_cellmeta = TRUE, instructions = NULL, verbose = NULL) { x <- importXenium(xenium_dir) @@ -1400,6 +1401,7 @@ createGiottoXeniumObject <- function(xenium_dir, split_keyword = split_keyword, load_images = load_images, load_aligned_images = load_aligned_images, + load_transcripts = load_transcripts, load_expression = load_expression, load_cellmeta = load_cellmeta, instructions = instructions, From 4e4e2dd9b6d80f69bdc0c11037fa46110b9c5490 Mon Sep 17 00:00:00 2001 From: George Chen <72078254+jiajic@users.noreply.github.com> Date: Thu, 7 Nov 2024 12:30:32 -0500 Subject: [PATCH 23/28] revert default changes --- R/convenience_xenium.R | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/R/convenience_xenium.R b/R/convenience_xenium.R index 85f662acb..6fb8bc4ad 100644 --- a/R/convenience_xenium.R +++ b/R/convenience_xenium.R @@ -1385,9 +1385,9 @@ createGiottoXeniumObject <- function(xenium_dir, qv_threshold = 20, load_images = "focus", load_aligned_images = NULL, - load_transcripts = FALSE, - load_expression = TRUE, - load_cellmeta = TRUE, + load_transcripts = TRUE, + load_expression = FALSE, + load_cellmeta = FALSE, instructions = NULL, verbose = NULL) { x <- importXenium(xenium_dir) From 7f70a924f2c94d382b5f019cad253297c2c8e4e5 Mon Sep 17 00:00:00 2001 From: George Chen <72078254+jiajic@users.noreply.github.com> Date: Thu, 7 Nov 2024 12:40:49 -0500 Subject: [PATCH 24/28] update prints and run docs --- R/convenience_xenium.R | 6 +++++- man/createGiottoXeniumObject.Rd | 3 ++- 2 files changed, 7 insertions(+), 2 deletions(-) diff --git a/R/convenience_xenium.R b/R/convenience_xenium.R index 6fb8bc4ad..931ce3fa0 100644 --- a/R/convenience_xenium.R +++ b/R/convenience_xenium.R @@ -487,7 +487,8 @@ setMethod( path = metadata_path, verbose = verbose ) - g <- setGiotto(g, cx) + # verbose = FALSE to silence warning that meta is already generated + g <- setGiotto(g, cx, verbose = FALSE) } @@ -553,12 +554,15 @@ setMethod( } # centroids + vmsg(.v = verbose, "calculating centroids") spat_units_to_calc <- list_spatial_info_names(g) g <- addSpatialCentroidLocations(g, poly_info = spat_units_to_calc, provenance = as.list(spat_units_to_calc), verbose = FALSE ) + + vmsg(.v = verbose, "done") return(g) } diff --git a/man/createGiottoXeniumObject.Rd b/man/createGiottoXeniumObject.Rd index f803aece8..5f41859b8 100644 --- a/man/createGiottoXeniumObject.Rd +++ b/man/createGiottoXeniumObject.Rd @@ -14,8 +14,9 @@ createGiottoXeniumObject( feat_type = c("rna", "NegControlProbe", "UnassignedCodeword", "NegControlCodeword"), split_keyword = list("NegControlProbe", "UnassignedCodeword", "NegControlCodeword"), qv_threshold = 20, - load_images = NULL, + load_images = "focus", load_aligned_images = NULL, + load_transcripts = TRUE, load_expression = FALSE, load_cellmeta = FALSE, instructions = NULL, From 34d10add36323ad36d7af3ffbc444a4cac7fbd14 Mon Sep 17 00:00:00 2001 From: George Chen <72078254+jiajic@users.noreply.github.com> Date: Thu, 7 Nov 2024 12:47:33 -0500 Subject: [PATCH 25/28] Revert "temporarily lower R ver" This reverts commit 8b0950f6be5aea2b486634eb25a747bc5502b708. --- DESCRIPTION | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/DESCRIPTION b/DESCRIPTION index 9ed33d372..4c3a03d74 100644 --- a/DESCRIPTION +++ b/DESCRIPTION @@ -26,7 +26,7 @@ URL: https://drieslab.github.io/Giotto/, https://github.com/drieslab/Giotto BugReports: https://github.com/drieslab/Giotto/issues RoxygenNote: 7.3.2 Depends: - R (>= 4.4.0), + R (>= 4.4.1), methods, GiottoClass (>= 0.4.1) Imports: From fbdb139348fcb9c401935b50f7dfa77ac1d3e17a Mon Sep 17 00:00:00 2001 From: George Chen <72078254+jiajic@users.noreply.github.com> Date: Thu, 7 Nov 2024 12:56:56 -0500 Subject: [PATCH 26/28] chore: update news --- NEWS.md | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/NEWS.md b/NEWS.md index 9ecdd4e72..fc9051371 100644 --- a/NEWS.md +++ b/NEWS.md @@ -1,4 +1,10 @@ +# Giotto 4.1.5 + +## Enhancements +* `createGiottoXeniumObject()` auto loading for morphology focus images, image directory loading, auto centroid calculation, allow skipping transcript loading + + # Giotto 4.1.4 (2024/10/30) ## Changes From 4613aa8ece7f3d6a66a3e5a7a463d5ea97a135da Mon Sep 17 00:00:00 2001 From: George Chen <72078254+jiajic@users.noreply.github.com> Date: Fri, 8 Nov 2024 10:07:55 -0500 Subject: [PATCH 27/28] chore: update news --- NEWS.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/NEWS.md b/NEWS.md index fc9051371..146e88ee4 100644 --- a/NEWS.md +++ b/NEWS.md @@ -1,5 +1,5 @@ -# Giotto 4.1.5 +# Giotto 4.1.5 (2024/11/08) ## Enhancements * `createGiottoXeniumObject()` auto loading for morphology focus images, image directory loading, auto centroid calculation, allow skipping transcript loading From 89a031a9203c9275cb8406ac006fdb4a683d6a12 Mon Sep 17 00:00:00 2001 From: George Chen <72078254+jiajic@users.noreply.github.com> Date: Fri, 8 Nov 2024 10:09:15 -0500 Subject: [PATCH 28/28] chore: add back remotes --- DESCRIPTION | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/DESCRIPTION b/DESCRIPTION index 4c3a03d74..fccb7569a 100644 --- a/DESCRIPTION +++ b/DESCRIPTION @@ -108,6 +108,10 @@ Suggests: trendsceek, testthat (>= 3.0.0), rmarkdown +Remotes: + drieslab/GiottoUtils, + drieslab/GiottoClass, + drieslab/GiottoVisuals Collate: 'ONTraC_wrapper.R' 'auxiliary_giotto.R'