From e03c52b35527b4a12217490b3560e8ef99ff0f08 Mon Sep 17 00:00:00 2001 From: George Chen <72078254+jiajic@users.noreply.github.com> Date: Wed, 5 Feb 2025 10:00:11 -0500 Subject: [PATCH 01/11] chore: setup dev --- DESCRIPTION | 4 ++-- NEWS.md | 4 ++++ 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/DESCRIPTION b/DESCRIPTION index 2b41c464c..adffc612b 100644 --- a/DESCRIPTION +++ b/DESCRIPTION @@ -1,6 +1,6 @@ Package: Giotto Title: Spatial Single-Cell Transcriptomics Toolbox -Version: 4.2.1 +Version: 4.2.2 Authors@R: c( person("Ruben", "Dries", email = "rubendries@gmail.com", role = c("aut", "cre"), comment = c(ORCID = "0000-0001-7650-7754")), @@ -37,7 +37,7 @@ Imports: dbscan (>= 1.1-3), ggraph, ggplot2 (>= 3.1.1), - GiottoUtils (>= 0.2.3), + GiottoUtils (>= 0.2.4), GiottoVisuals (>= 0.2.10), igraph (>= 1.2.4.1), Matrix (>= 1.6-2), diff --git a/NEWS.md b/NEWS.md index 97f6f5f5f..bf890e35c 100644 --- a/NEWS.md +++ b/NEWS.md @@ -1,3 +1,7 @@ +# Giotto 4.2.2 + + + # Giotto 4.2.1 (2025/02/04) ## Bug fixes From 960a5aa827dbe611c830b484ec6e90aa38729e6e Mon Sep 17 00:00:00 2001 From: George Chen <72078254+jiajic@users.noreply.github.com> Date: Wed, 5 Feb 2025 10:01:11 -0500 Subject: [PATCH 02/11] chore: switch `abbrev_path()` to functionality now exported from GiottoUtils --- R/convenience_cosmx.R | 2 +- R/convenience_general.R | 9 --------- R/convenience_visiumHD.R | 2 +- R/convenience_xenium.R | 2 +- 4 files changed, 3 insertions(+), 12 deletions(-) diff --git a/R/convenience_cosmx.R b/R/convenience_cosmx.R index fba38d090..6ac08e488 100644 --- a/R/convenience_cosmx.R +++ b/R/convenience_cosmx.R @@ -37,7 +37,7 @@ setMethod("show", signature("CosmxReader"), function(object) { d <- object@cosmx_dir if (length(d) > 0L) { nch <- nchar(d) - d <- abbrev_path(d) + d <- GiottoUtils::str_abbreviate(d) cat(pre["dir"], d, "\n") } else { cat(pre["dir"], "\n") diff --git a/R/convenience_general.R b/R/convenience_general.R index 1bbe1d513..ac3877977 100644 --- a/R/convenience_general.R +++ b/R/convenience_general.R @@ -187,15 +187,6 @@ NULL -abbrev_path <- function(path, head = 15, tail = 35L) { - nch <- nchar(path) - if (nch > 60L) { - p1 <- substring(path, first = 0L, last = head) - p2 <- substring(path, first = nch - tail, last = nch) - path <- paste0(p1, "[...]", p2) - } - return(path) -} .reader_fun_prints <- function(x, pre) { nfun <- length(x@calls) diff --git a/R/convenience_visiumHD.R b/R/convenience_visiumHD.R index fca2fd695..b5cdb946d 100644 --- a/R/convenience_visiumHD.R +++ b/R/convenience_visiumHD.R @@ -45,7 +45,7 @@ setMethod("show", signature("VisiumHDReader"), function(object) { d <- object@visiumHD_dir if (length(d) > 0L) { nch <- nchar(d) - d <- abbrev_path(d) + d <- GiottoUtils::str_abbreviate(d) cat(pre["dir"], d, "\n") } else { cat(pre["dir"], "\n") diff --git a/R/convenience_xenium.R b/R/convenience_xenium.R index 506410479..37e3abd50 100644 --- a/R/convenience_xenium.R +++ b/R/convenience_xenium.R @@ -59,7 +59,7 @@ setMethod("show", signature("XeniumReader"), function(object) { # dir d <- object@xenium_dir if (length(d) > 0L) { - d <- abbrev_path(d) + d <- GiottoUtils::str_abbreviate(d) cat(pre["dir"], d, "\n") } else { cat(pre["dir"], "\n") From 53072ab1b5f9974daa9ddf061fb1801478f7a01c Mon Sep 17 00:00:00 2001 From: George Chen <72078254+jiajic@users.noreply.github.com> Date: Wed, 5 Feb 2025 10:08:16 -0500 Subject: [PATCH 03/11] Update NEWS.md --- NEWS.md | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/NEWS.md b/NEWS.md index bf890e35c..f5407a36f 100644 --- a/NEWS.md +++ b/NEWS.md @@ -1,6 +1,7 @@ # Giotto 4.2.2 - +## Changes +* GiottoUtils req raised to 0.2.4 # Giotto 4.2.1 (2025/02/04) From 8f0a5b5955bacd0da502c6ed4754d708e91a317e Mon Sep 17 00:00:00 2001 From: George Chen <72078254+jiajic@users.noreply.github.com> Date: Wed, 5 Feb 2025 10:25:29 -0500 Subject: [PATCH 04/11] Update DESCRIPTION --- DESCRIPTION | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/DESCRIPTION b/DESCRIPTION index adffc612b..461030963 100644 --- a/DESCRIPTION +++ b/DESCRIPTION @@ -28,7 +28,7 @@ RoxygenNote: 7.3.2 Depends: R (>= 4.4.1), methods, - GiottoClass (>= 0.4.5) + GiottoClass (>= 0.4.7) Imports: BiocParallel, BiocSingular, From 0b560524979e69ac126de34f24a4b5165d1af4fd Mon Sep 17 00:00:00 2001 From: George Chen <72078254+jiajic@users.noreply.github.com> Date: Wed, 12 Feb 2025 12:16:52 -0500 Subject: [PATCH 05/11] chore: bump GiottoVisuals dep --- DESCRIPTION | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/DESCRIPTION b/DESCRIPTION index 461030963..e792c985c 100644 --- a/DESCRIPTION +++ b/DESCRIPTION @@ -38,7 +38,7 @@ Imports: ggraph, ggplot2 (>= 3.1.1), GiottoUtils (>= 0.2.4), - GiottoVisuals (>= 0.2.10), + GiottoVisuals (>= 0.2.12), igraph (>= 1.2.4.1), Matrix (>= 1.6-2), MatrixGenerics, From 9268c8ac2663b86cfafb83e67472caa5de4d4859 Mon Sep 17 00:00:00 2001 From: George Chen <72078254+jiajic@users.noreply.github.com> Date: Tue, 25 Feb 2025 17:00:05 -0500 Subject: [PATCH 06/11] hotfix: cosmx convenience ## Bug fixes: * fix `createGiottoCosMxObject()` not passing `load_expression`, `load_cellmeta`, `load_transcripts` params to `importCosMx()` ## Enhancements * `poly_pref` param for `createGiottoCosMxObject()` and `importCosMx()` to select between loading the mask images or the `polygons.csv` as polygon info. * `image_negative_y` param for `createGiottoCosMxObject()` for toggling how images and polygons from mask images should be spatially mapped * `slide` param made more prominent in `createGiottoCosMxObject()` * docs --- DESCRIPTION | 2 +- NEWS.md | 10 +- R/convenience_cosmx.R | 311 +++++++++++++++++++++++++++------ man/createGiottoCosMxObject.Rd | 68 ++++++- man/importCosMx.Rd | 9 +- man/reexports.Rd | 2 +- 6 files changed, 334 insertions(+), 68 deletions(-) diff --git a/DESCRIPTION b/DESCRIPTION index e792c985c..74033633e 100644 --- a/DESCRIPTION +++ b/DESCRIPTION @@ -1,6 +1,6 @@ Package: Giotto Title: Spatial Single-Cell Transcriptomics Toolbox -Version: 4.2.2 +Version: 4.2.1 Authors@R: c( person("Ruben", "Dries", email = "rubendries@gmail.com", role = c("aut", "cre"), comment = c(ORCID = "0000-0001-7650-7754")), diff --git a/NEWS.md b/NEWS.md index f5407a36f..62042ef54 100644 --- a/NEWS.md +++ b/NEWS.md @@ -1,12 +1,16 @@ -# Giotto 4.2.2 +# Giotto 4.2.1 (2025/02/04) ## Changes * GiottoUtils req raised to 0.2.4 -# Giotto 4.2.1 (2025/02/04) - ## Bug fixes * fix `identifyTMAcores()` when no overlap relations are found and an `rbind` error is thrown +* fix `createGiottoCosMxObject()` not passing `load_expression`, `load_cellmeta`, `load_transcripts` params to `importCosMx()` + +## Enhancements +* `poly_pref` param for `createGiottoCosMxObject()` and `importCosMx()` to select between loading the mask images or the `polygons.csv` as polygon info. +* `image_negative_y` param for `createGiottoCosMxObject()` for toggling how images and polygons from mask images should be spatially mapped +* `slide` param made more prominent in `createGiottoCosMxObject()` # Giotto 4.2.0 (2025/01/17) diff --git a/R/convenience_cosmx.R b/R/convenience_cosmx.R index 6ac08e488..83b90dd8a 100644 --- a/R/convenience_cosmx.R +++ b/R/convenience_cosmx.R @@ -10,6 +10,7 @@ setClass( fovs = "numeric", micron = "logical", px2um = "numeric", + poly_pref = "character", offsets = "ANY", calls = "list" ), @@ -18,6 +19,7 @@ setClass( slide = 1, micron = FALSE, px2um = 0.12028, # from cosmx output help files + poly_pref = "mask", offsets = NULL, calls = list() ) @@ -27,7 +29,7 @@ setClass( setMethod("show", signature("CosmxReader"), function(object) { cat(sprintf("Giotto <%s>\n", "CosmxReader")) print_slots <- c("version", "dir", "slide", "fovs", - "micron", "offsets", "funs") + "micron", "poly_pref", "offsets", "funs") pre <- sprintf( "%s :", format(print_slots) ) @@ -58,6 +60,10 @@ setMethod("show", signature("CosmxReader"), function(object) { # micron scaling micron <- ifelse(object@micron, object@px2um, FALSE) cat(pre["micron"], micron, "\n") + + # poly preference + ppref <- object@poly_pref + cat(pre["poly_pref"], ppref, "\n") # offsets offs_status <- ifelse(nrow(object@offsets) > 0L, "found", "none") @@ -89,7 +95,17 @@ setMethod( } plot(y ~ x, data = dat, asp = 1L, type = "n", ...) - text(y ~ x, data = dat, labels = dat$fov, cex = cex, ...) + if (length(x@fovs) == 0) { + text(y ~ x, data = dat, labels = dat$fov, cex = cex, ...) + } else { + fov_sel <- dat$fov %in% x@fovs + dat_grey <- dat[!fov_sel] + dat_black <- dat[fov_sel] + text(y ~ x, data = dat_grey, labels = dat_grey$fov, + cex = cex, col = "grey", ...) + text(y ~ x, data = dat_black, labels = dat_black$fov, + cex = cex, col = "black", ...) + } } ) @@ -114,7 +130,10 @@ setMethod( #' @param micron logical. Whether to scale spatial information as micron #' instead of the default pixels #' @param px2um numeric. Scalefactor from pixels to micron. Defaults to 0.12028 -#' based on `CosMx-ReadMe.html` info +#' based on `CosMx-ReadMe.html` info. May be different depending on dataset. +#' @param poly_pref character. Either "csv" (default) or "mask". Which format of +#' data to load as polygon info. "csv" will use vector polygons from the +#' `polygons.csv`. "mask" will load the mask images from `CellLabels` directory. #' @details #' Loading functions are generated after the `cosmx_dir` is added. #' Transcripts, expression, and metadata loading are all expected to be done @@ -147,7 +166,7 @@ setMethod( #' } #' @export importCosMx <- function(cosmx_dir = NULL, slide = 1, fovs = NULL, - micron = FALSE, px2um = 0.12028) { + micron = FALSE, px2um = 0.12028, poly_pref = "mask") { # get params a <- list(Class = "CosmxReader") if (!is.null(cosmx_dir)) { @@ -159,6 +178,7 @@ importCosMx <- function(cosmx_dir = NULL, slide = 1, fovs = NULL, a$slide <- slide a$micron <- micron a$px2um <- px2um + a$poly_pref <- poly_pref do.call(new, args = a) } @@ -166,7 +186,7 @@ importCosMx <- function(cosmx_dir = NULL, slide = 1, fovs = NULL, # * init #### setMethod( "initialize", signature("CosmxReader"), - function(.Object, cosmx_dir, version, slide, fovs, micron, px2um) { + function(.Object, cosmx_dir, version, slide, fovs, micron, px2um, poly_pref) { # provided params (if any) if (!missing(cosmx_dir)) { checkmate::assert_directory_exists(cosmx_dir) @@ -190,6 +210,9 @@ setMethod( if (!missing(px2um)) { .Object@px2um <- px2um } + if (!missing(poly_pref)) { + .Object@poly_pref <- poly_pref + } # NULL case if (length(.Object@cosmx_dir) == 0) { @@ -210,6 +233,7 @@ setMethod( meta_path <- .cosmx_detect("metadata_file") tx_path <- .cosmx_detect("tx_file") mask_dir <- .cosmx_detect("CellLabels") + poly_path <- .cosmx_detect("polygons") expr_path <- .cosmx_detect("exprMat_file") composite_img_dir <- .cosmx_detect("CellComposite") overlay_img_dir <- .cosmx_detect("CellOverlay") @@ -291,8 +315,19 @@ setMethod( "legacy" = 1 ) - mask_fun <- function( - path = mask_dir, + if (!is.null(mask_dir) && !is.null(poly_path)) { + poly_use_path <- switch(.Object@poly_pref, + "csv" = poly_path, + "mask" = mask_dir + ) + } else if (!is.null(poly_path)) { + poly_use_path <- poly_path + } else if (!is.null(mask_dir)) { + poly_use_path <- mask_dir + } + + poly_fun <- function( + path = poly_use_path, # VERTICAL FLIP + NO VERTICAL SHIFT flip_vertical = TRUE, flip_horizontal = FALSE, @@ -314,7 +349,7 @@ setMethod( verbose = verbose ) } - .Object@calls$load_polys <- mask_fun + .Object@calls$load_polys <- poly_fun # expression load call @@ -400,13 +435,16 @@ setMethod( composite = "composite", overlay = "overlay" ), + image_negative_y = NULL, load_expression = FALSE, load_cellmeta = TRUE, + load_transcripts = TRUE, instructions = NULL, cores = determine_cores(), verbose = NULL) { load_expression <- as.logical(load_expression) load_cellmeta <- as.logical(load_cellmeta) + load_transcripts <- as.logical(load_transcripts) if (!is.null(load_images)) { checkmate::assert_list(load_images) @@ -425,22 +463,33 @@ setMethod( } # transcripts - tx_list <- funs$load_transcripts( - path = transcript_path, - feat_type = feat_type, - split_keyword = split_keyword, - cores = cores, - verbose = verbose - ) - for (tx in tx_list) { - g <- setGiotto(g, tx) + if (isTRUE(load_transcripts)) { + tx_list <- funs$load_transcripts( + path = transcript_path, + feat_type = feat_type, + split_keyword = split_keyword, + cores = cores, + verbose = verbose + ) + for (tx in tx_list) { + g <- setGiotto(g, tx) + } } # polys - polys <- funs$load_polys( + poly_args <- list( path = cell_labels_dir, verbose = FALSE ) + if (!is.null(image_negative_y)) { + # negative_y override + if (isTRUE(image_negative_y)) { + poly_args$shift_vertical_step <- FALSE + } else { + poly_args$shift_vertical_step <- 1 + } + } + polys <- do.call(funs$load_polys, poly_args) g <- setGiotto(g, polys, verbose = verbose) # images @@ -452,11 +501,16 @@ setMethod( imglist <- list() dirnames <- names(load_images) for (imdir_i in seq_along(load_images)) { - dir_imgs <- funs$load_images( + img_args <- list( path = load_images[[imdir_i]], img_type = dirnames[[imdir_i]], verbose = verbose ) + if (!is.null(image_negative_y)) { + # negative_y override + img_args$negative_y <- image_negative_y + } + dir_imgs <- do.call(funs$load_images, img_args) imglist <- c(imglist, dir_imgs) } g <- addGiottoLargeImage(g, largeImages = imglist, @@ -516,7 +570,7 @@ setMethod( #' @export setMethod("$", signature("CosmxReader"), function(x, name) { basic_info <- c("cosmx_dir", "version", "slide", "fovs", - "micron", "px2um", "offsets") + "micron", "px2um", "poly_pref", "offsets") if (name %in% basic_info) { return(methods::slot(x, name)) } @@ -526,7 +580,9 @@ setMethod("$", signature("CosmxReader"), function(x, name) { #' @export setMethod("$<-", signature("CosmxReader"), function(x, name, value) { - basic_info <- c("cosmx_dir", "version", "slide", "fovs", "micron", "px2um") + basic_info <- c( + "cosmx_dir", "version", "slide", "fovs", "micron", "px2um", "poly_pref" + ) if (name %in% basic_info) { methods::slot(x, name) <- value return(initialize(x)) @@ -548,7 +604,7 @@ setMethod("$<-", signature("CosmxReader"), function(x, name, value) { #' @export `.DollarNames.CosmxReader` <- function(x, pattern) { dn <- c("cosmx_dir", "version", "slide", "fovs", - "micron", "px2um", "offsets") + "micron", "px2um", "poly_pref", "offsets") if (length(methods::slot(x, "calls")) > 0) { dn <- c(dn, paste0(names(methods::slot(x, "calls")), "()")) } @@ -609,11 +665,17 @@ setMethod("$<-", signature("CosmxReader"), function(x, name, value) { vmsg(.v = verbose, "loading feature detections...") vmsg(.v = verbose, .is_debug = TRUE, path) - - tx <- data.table::fread(input = path, nThread = cores, drop = dropcols) - if (!is.null(fovs)) { - # subset to only needed FOVs - tx <- tx[fov %in% as.numeric(fovs), ] + + if (is.null(fovs)) { + tx <- data.table::fread(input = path, nThread = cores, drop = dropcols) + } else { + tx <- read_colmatch( + file = path, + col = "fov", + sep = ",", + values_to_match = fovs, + drop = dropcols + ) } # micron scaling if desired @@ -741,30 +803,24 @@ setMethod("$<-", signature("CosmxReader"), function(x, name, value) { return(fovs) } -.cosmx_poly <- function( - path, - slide = 1, - fovs = NULL, - name = "cell", - # VERTICAL FLIP + NO SHIFTS - flip_vertical = TRUE, - flip_horizontal = FALSE, - shift_vertical_step = FALSE, - shift_horizontal_step = FALSE, - remove_background_polygon = TRUE, - micron = FALSE, - px2um = 0.12028, - offsets, - verbose = NULL) { +.cosmx_poly_maskimage <- function(path, + slide = 1, + fovs = NULL, + name = "cell", + # VERTICAL FLIP + NO SHIFTS + flip_vertical = TRUE, + flip_horizontal = FALSE, + shift_vertical_step = FALSE, + shift_horizontal_step = FALSE, + remove_background_polygon = TRUE, + micron = FALSE, + px2um = 0.12028, + offsets, + verbose = NULL, + ...) { # NSE params f <- x <- y <- NULL - - if (missing(path)) { - stop(wrap_txt( - "No path to polys subdirectory provided or auto-detected" - ), call. = FALSE) - } - + GiottoUtils::vmsg(.v = verbose, "loading segmentation masks...") vmsg(.v = verbose, .is_debug = TRUE, path) @@ -825,6 +881,82 @@ setMethod("$<-", signature("CosmxReader"), function(x, name, value) { if (length(gpolys) > 1L) { gpolys <- do.call(rbind, args = gpolys) } + + return(gpolys) +} + +.cosmx_poly_csv <- function( + path, + slide = 1, + fovs = NULL, + name = "cell", + micron = FALSE, + px2um = 0.12028, + make_valid = TRUE, + # cellID is an integer identifier per FOV + # x_local_px and y_local_px are local xy coords per FOV + dropcols = c("x_local_px", "y_local_px"), + verbose = NULL, + ...) { + + GiottoUtils::vmsg(.v = verbose, "loading segmentation polygons...") + vmsg(.v = verbose, .is_debug = TRUE, path) + + checkmate::assert_file_exists(path) + + if (is.null(fovs)) { + dt <- data.table::fread(path, drop = dropcols) + } else { + fovs <- as.integer(fovs) + dt <- GiottoUtils::read_colmatch( + file = path, + col = "fov", + values_to_match = fovs, + verbose = verbose, + drop = dropcols + ) + } + + dt[, cell := sprintf("c_%d_%d_%d", as.integer(slide), fov, cellID)] + dt[, cellID := NULL] + + data.table::setcolorder(dt, c("x_global_px", "y_global_px", "cell", "fov")) + createGiottoPolygon(dt, make_valid = make_valid, verbose = FALSE) +} + +.cosmx_poly <- function( + path, + slide = 1, + fovs = NULL, + name = "cell", + # VERTICAL FLIP + NO SHIFTS + flip_vertical = TRUE, + flip_horizontal = FALSE, + shift_vertical_step = FALSE, + shift_horizontal_step = FALSE, + remove_background_polygon = TRUE, + micron = FALSE, + px2um = 0.12028, + offsets, + verbose = NULL, + ...) { + + a <- GiottoUtils::get_args_list(...) + + if (missing(path)) { + c("No path to mask image subdirectory or polygons csv", + "provided or auto-detected") %>% + wrap_txt() %>% + stop(call. = FALSE) + } + + if (dir.exists(path)) { + gpolys <- do.call(.cosmx_poly_maskimage, args = a) + } else if ("csv" %in% GiottoUtils::file_extension(path)) { + gpolys <- do.call(.cosmx_poly_csv, args = a) + } else { + "importCosMx - load_polys(): unrecognized path input" + } # never return lists. Only the single merged gpoly return(gpolys) @@ -993,14 +1125,19 @@ setMethod("$<-", signature("CosmxReader"), function(x, name, value) { imgfile <- Sys.glob(paths = sprintf("%s/*F%03d*", path, f)) img_name <- sprintf(img_name_fmt, f) - gimg <- createGiottoLargeImage( + gimg <- try(createGiottoLargeImage( raster_object = imgfile, name = img_name, negative_y = negative_y, flip_vertical = flip_vertical, flip_horizontal = flip_horizontal, verbose = verbose - ) + ), silent = TRUE) + # catch stray metadata files like thumbnails + if (inherits(gimg, "try-error")) { + warning(sprintf("[load_image] unreadable image: %s", imgfile), + call. = FALSE) + } xshift <- offsets[fov == f, x] yshift <- offsets[fov == f, y] @@ -1038,11 +1175,13 @@ setMethod("$<-", signature("CosmxReader"), function(x, name, value) { #' @title Create Nanostring CosMx Giotto Object #' @name createGiottoCosMxObject #' @description Given the path to a CosMx experiment directory, creates a Giotto -#' object. +#' object. For lower level control over loading, please see [importCosMx()] #' @param cosmx_dir full path to the exported cosmx directory #' @param version character. Version of CosMx output. Current selections are #' either "default", "v6", and "legacy" (for the NSCLC dataset). -#' @param FOVs field of views to load (only affects subcellular data and images) +#' @param FOVs field of views to load. +#' @param slide numeric. Slide number. Defaults to 1. This must be correct so +#' that cell_IDs will match across polygons and (if loaded) expression matrix. #' @param feat_type character. feature type. Provide more than one value if #' using the `split_keyword` param. For each set of keywords to split by, an #' additional feat_type should be provided in the same order. Affects how @@ -1057,6 +1196,14 @@ setMethod("$<-", signature("CosmxReader"), function(x, name, value) { #' expression matrix #' @param load_cellmeta logical. (Default = TRUE) whether to load provided #' cell metadata +#' @param load_transcripts logical. (Default = TRUE) whether to load provided +#' transcript detections +#' @param poly_pref character. "mask" or "csv". Determines whether to load in +#' the polygons from the mask images (default) or the csv polygons file. +#' @param image_negative_y Optional logical. Whether images are assumed to map +#' to positive or negative y values before fov shifts are applied. Affects +#' images (and polygons generated from masks). This overrides any settings from +#' selecting `version`. #' @param fov_shifts_path Optional. Filepath to fov_positions_file #' @param transcript_path Optional. Filepath to desired transcripts file to #' load. @@ -1070,7 +1217,7 @@ setMethod("$<-", signature("CosmxReader"), function(x, name, value) { #' @param background_algo deprecated. Not used #' @param remove_unvalid_polygons deprecated. Now always done #' @inheritParams GiottoClass::createGiottoObjectSubcellular -#' @inheritDotParams importCosMx -cosmx_dir -fovs +#' @inheritDotParams importCosMx -cosmx_dir -fovs -slide #' @returns a giotto object #' @details #' \[**Expected Directory**\] This function generates a giotto object when @@ -1086,7 +1233,11 @@ setMethod("$<-", signature("CosmxReader"), function(x, name, value) { #' \item{experimentname_\strong{fov_positions_file}.csv (file)} #' \item{experimentname_\strong{metadata_file}.csv (file)} #' \item{experimentname_\strong{tx_file}.csv (file)} +#' \item{experimentname-\strong{polygons}.csv (file)} #' } +#' +#' The subdirectories should contain only the image files in order to be loaded +#' correctly. #' #' \[**feat_type and split_keyword**\] #' Additional QC probe information is in the subcellular feature detections @@ -1103,19 +1254,59 @@ setMethod("$<-", signature("CosmxReader"), function(x, name, value) { #' #' \[**Images**\] Images in the expected CellComposite and CellOverlay #' folders will be loaded as giotto largeImage objects by default. +#' +#' \[**Polygons**\] Some outputs provide both the mask images and the +#' `polygons.csv`. Giotto uses the mask images by default to convert to polygons +#' info. However, if only the `polygons.csv` file is present or +#' `poly_pref = csv` is set, then the csv file will be used instead. One thing +#' to watch out for when loading from the `csv` is that in some datasets, the +#' polygons preferably should not overlap each other. Giotto is not fully +#' compatible with overlapping annotations. It also opens up the possibility +#' of double counting transcripts. Polygon overlaps do not appear to be an +#' issue in the most recent outputs. +#' +#' \[**Spatial Alignment Issues**\] Different versions of the CosMx output have +#' changed how images (and polygons generated from masks) should be aligned +#' relative to the vector information (transcript detections). The `version` +#' param affects how the images are mapped by default. `image_negative_y` is +#' a toggle that overrides the image mapping style when an appropriate `version` +#' is difficult to determine. #' \code{\link{showGiottoImageNames}} can be used to see the available images. #' @md +#' @examples +#' \dontrun{ +#' f <- "file path to cosmx flatfile output directory" +#' createGiottoCosMxObject(f) +#' +#' # load older CosMx format +#' createGiottoCosMxObject(f, version = "legacy") +#' +#' # force images and mask image polygons to shift up one image height +#' createGiottoCosMxObject(f, image_negative_y = FALSE) +#' +#' # load only aggregated data +#' createGiottoCosMxObject(f, +#' load_cellmeta = TRUE, +#' load_expression = TRUE, +#' load_transcripts = FALSE +#' # data filepaths not needed unless they are not in expected locations +#' ) +#' } #' @export createGiottoCosMxObject <- function( cosmx_dir, version = "default", FOVs = NULL, + slide = 1, feat_type = c("rna", "negprobes"), split_keyword = list("NegPrb"), load_images = list(composite = "composite", overlay = "overlay"), load_expression = FALSE, - load_cellmeta = FALSE, + load_cellmeta = TRUE, + load_transcripts = TRUE, + poly_pref = "mask", + image_negative_y = NULL, # optional filepaths fov_shifts_path = NULL, @@ -1154,7 +1345,11 @@ createGiottoCosMxObject <- function( # setup importer - x <- importCosMx(cosmx_dir = cosmx_dir, fovs = FOVs, ...) + x <- importCosMx(cosmx_dir, + fovs = FOVs, + slide = slide, + poly_pref = poly_pref, + ...) x$version <- version if (!is.null(fov_shifts_path)) { checkmate::assert_file_exists(fov_shifts_path) @@ -1166,6 +1361,10 @@ createGiottoCosMxObject <- function( feat_type = feat_type, split_keyword = split_keyword, load_images = load_images, + load_expression = load_expression, + load_cellmeta = load_cellmeta, + load_transcripts = load_transcripts, + image_negative_y = image_negative_y, instructions = instructions, cores = cores, verbose = verbose diff --git a/man/createGiottoCosMxObject.Rd b/man/createGiottoCosMxObject.Rd index c9351e724..cd0424392 100644 --- a/man/createGiottoCosMxObject.Rd +++ b/man/createGiottoCosMxObject.Rd @@ -8,11 +8,15 @@ createGiottoCosMxObject( cosmx_dir, version = "default", FOVs = NULL, + slide = 1, feat_type = c("rna", "negprobes"), split_keyword = list("NegPrb"), load_images = list(composite = "composite", overlay = "overlay"), load_expression = FALSE, - load_cellmeta = FALSE, + load_cellmeta = TRUE, + load_transcripts = TRUE, + poly_pref = "mask", + image_negative_y = NULL, fov_shifts_path = NULL, transcript_path = NULL, cell_labels_dir = NULL, @@ -34,7 +38,10 @@ createGiottoCosMxObject( \item{version}{character. Version of CosMx output. Current selections are either "default", "v6", and "legacy" (for the NSCLC dataset).} -\item{FOVs}{field of views to load (only affects subcellular data and images)} +\item{FOVs}{field of views to load.} + +\item{slide}{numeric. Slide number. Defaults to 1. This must be correct so +that cell_IDs will match across polygons and (if loaded) expression matrix.} \item{feat_type}{character. feature type. Provide more than one value if using the \code{split_keyword} param. For each set of keywords to split by, an @@ -55,6 +62,17 @@ expression matrix} \item{load_cellmeta}{logical. (Default = TRUE) whether to load provided cell metadata} +\item{load_transcripts}{logical. (Default = TRUE) whether to load provided +transcript detections} + +\item{poly_pref}{character. "mask" or "csv". Determines whether to load in +the polygons from the mask images (default) or the csv polygons file.} + +\item{image_negative_y}{Optional logical. Whether images are assumed to map +to positive or negative y values before fov shifts are applied. Affects +images (and polygons generated from masks). This overrides any settings from +selecting \code{version}.} + \item{fov_shifts_path}{Optional. Filepath to fov_positions_file} \item{transcript_path}{Optional. Filepath to desired transcripts file to @@ -85,11 +103,10 @@ from \code{\link[GiottoClass]{createGiottoInstructions}}} \item{...}{ Arguments passed on to \code{\link[=importCosMx]{importCosMx}} \describe{ - \item{\code{slide}}{numeric. Slide number. Defaults to 1} \item{\code{micron}}{logical. Whether to scale spatial information as micron instead of the default pixels} \item{\code{px2um}}{numeric. Scalefactor from pixels to micron. Defaults to 0.12028 -based on `CosMx-ReadMe.html` info} +based on `CosMx-ReadMe.html` info. May be different depending on dataset.} }} } \value{ @@ -97,7 +114,7 @@ a giotto object } \description{ Given the path to a CosMx experiment directory, creates a Giotto -object. +object. For lower level control over loading, please see \code{\link[=importCosMx]{importCosMx()}} } \details{ [\strong{Expected Directory}] This function generates a giotto object when @@ -113,8 +130,12 @@ function matches against: \item{experimentname_\strong{fov_positions_file}.csv (file)} \item{experimentname_\strong{metadata_file}.csv (file)} \item{experimentname_\strong{tx_file}.csv (file)} +\item{experimentname-\strong{polygons}.csv (file)} } +The subdirectories should contain only the image files in order to be loaded +correctly. + [\strong{feat_type and split_keyword}] Additional QC probe information is in the subcellular feature detections information and must be separated from the gene expression information @@ -130,5 +151,42 @@ feat_IDs that do not get matched to any of the \code{split_keywords}. [\strong{Images}] Images in the expected CellComposite and CellOverlay folders will be loaded as giotto largeImage objects by default. + +[\strong{Polygons}] Some outputs provide both the mask images and the +\code{polygons.csv}. Giotto uses the mask images by default to convert to polygons +info. However, if only the \code{polygons.csv} file is present or +\code{poly_pref = csv} is set, then the csv file will be used instead. One thing +to watch out for when loading from the \code{csv} is that in some datasets, the +polygons preferably should not overlap each other. Giotto is not fully +compatible with overlapping annotations. It also opens up the possibility +of double counting transcripts. Polygon overlaps do not appear to be an +issue in the most recent outputs. + +[\strong{Spatial Alignment Issues}] Different versions of the CosMx output have +changed how images (and polygons generated from masks) should be aligned +relative to the vector information (transcript detections). The \code{version} +param affects how the images are mapped by default. \code{image_negative_y} is +a toggle that overrides the image mapping style when an appropriate \code{version} +is difficult to determine. \code{\link{showGiottoImageNames}} can be used to see the available images. } +\examples{ +\dontrun{ +f <- "file path to cosmx flatfile output directory" +createGiottoCosMxObject(f) + +# load older CosMx format +createGiottoCosMxObject(f, version = "legacy") + +# force images and mask image polygons to shift up one image height +createGiottoCosMxObject(f, image_negative_y = FALSE) + +# load only aggregated data +createGiottoCosMxObject(f, + load_cellmeta = TRUE, + load_expression = TRUE, + load_transcripts = FALSE + # data filepaths not needed unless they are not in expected locations +) +} +} diff --git a/man/importCosMx.Rd b/man/importCosMx.Rd index fbfd0f8df..edf8e8701 100644 --- a/man/importCosMx.Rd +++ b/man/importCosMx.Rd @@ -9,7 +9,8 @@ importCosMx( slide = 1, fovs = NULL, micron = FALSE, - px2um = 0.12028 + px2um = 0.12028, + poly_pref = "mask" ) } \arguments{ @@ -24,7 +25,11 @@ Otherwise, all FOVs will be loaded} instead of the default pixels} \item{px2um}{numeric. Scalefactor from pixels to micron. Defaults to 0.12028 -based on `CosMx-ReadMe.html` info} +based on `CosMx-ReadMe.html` info. May be different depending on dataset.} + +\item{poly_pref}{character. Either "csv" (default) or "mask". Which format of +data to load as polygon info. "csv" will use vector polygons from the +`polygons.csv`. "mask" will load the mask images from `CellLabels` directory.} } \value{ CosmxReader object diff --git a/man/reexports.Rd b/man/reexports.Rd index 688279922..a139653a4 100644 --- a/man/reexports.Rd +++ b/man/reexports.Rd @@ -298,7 +298,7 @@ These objects are imported from other packages. Follow the links below to see their documentation. \describe{ - \item{GiottoClass}{\code{\link[GiottoClass:activeFeatType-generic]{activeFeatType}}, \code{\link[GiottoClass:activeFeatType-generic]{activeFeatType<-}}, \code{\link[GiottoClass:activeSpatUnit-generic]{activeSpatUnit}}, \code{\link[GiottoClass:activeSpatUnit-generic]{activeSpatUnit<-}}, \code{\link[GiottoClass]{addCellMetadata}}, \code{\link[GiottoClass]{addFeatMetadata}}, \code{\link[GiottoClass]{addGiottoImage}}, \code{\link[GiottoClass]{addGiottoImageMG}}, \code{\link[GiottoClass]{addGiottoLargeImage}}, \code{\link[GiottoClass]{addGiottoPoints}}, \code{\link[GiottoClass:addGiottoPoints]{addGiottoPoints3D}}, \code{\link[GiottoClass]{addGiottoPolygons}}, \code{\link[GiottoClass]{addNetworkLayout}}, \code{\link[GiottoClass]{addSpatialCentroidLocations}}, \code{\link[GiottoClass]{addSpatialCentroidLocationsLayer}}, \code{\link[GiottoClass]{aggregateStacks}}, \code{\link[GiottoClass]{aggregateStacksExpression}}, \code{\link[GiottoClass]{aggregateStacksLocations}}, \code{\link[GiottoClass]{aggregateStacksPolygonOverlaps}}, \code{\link[GiottoClass]{aggregateStacksPolygons}}, \code{\link[GiottoClass]{anndataToGiotto}}, \code{\link[GiottoClass]{annotateGiotto}}, \code{\link[GiottoClass]{annotateSpatialGrid}}, \code{\link[GiottoClass]{annotateSpatialNetwork}}, \code{\link[GiottoClass]{as.points}}, \code{\link[GiottoClass]{as.polygons}}, \code{\link[GiottoClass:r_spatial_conversions]{as.sf}}, \code{\link[GiottoClass:r_spatial_conversions]{as.sp}}, \code{\link[GiottoClass:r_spatial_conversions]{as.stars}}, \code{\link[GiottoClass:r_spatial_conversions]{as.terra}}, \code{\link[GiottoClass]{calculateMetaTable}}, \code{\link[GiottoClass]{calculateMetaTableCells}}, \code{\link[GiottoClass]{calculateOverlap}}, \code{\link[GiottoClass]{calculateOverlapParallel}}, \code{\link[GiottoClass]{calculateOverlapPolygonImages}}, \code{\link[GiottoClass]{calculateOverlapRaster}}, \code{\link[GiottoClass]{calculateOverlapSerial}}, \code{\link[GiottoClass]{calculateSpatCellMetadataProportions}}, \code{\link[GiottoClass:centroids-generic]{centroids}}, \code{\link[GiottoClass]{changeGiottoInstructions}}, \code{\link[GiottoClass]{changeImageBg}}, \code{\link[GiottoClass:giotto_python]{checkGiottoEnvironment}}, \code{\link[GiottoClass]{circleVertices}}, \code{\link[GiottoClass]{combineCellData}}, \code{\link[GiottoClass]{combineFeatureData}}, \code{\link[GiottoClass]{combineFeatureOverlapData}}, \code{\link[GiottoClass]{combineMetadata}}, \code{\link[GiottoClass]{combineSpatialCellMetadataInfo}}, \code{\link[GiottoClass]{combineToMultiPolygon}}, \code{\link[GiottoClass]{convertGiottoLargeImageToMG}}, \code{\link[GiottoClass]{copy}}, \code{\link[GiottoClass]{createBentoAdata}}, \code{\link[GiottoClass]{createCellMetaObj}}, \code{\link[GiottoClass]{createDimObj}}, \code{\link[GiottoClass]{createExprObj}}, \code{\link[GiottoClass]{createFeatMetaObj}}, \code{\link[GiottoClass]{createGiottoImage}}, \code{\link[GiottoClass:giotto_instructions]{createGiottoInstructions}}, \code{\link[GiottoClass]{createGiottoLargeImage}}, \code{\link[GiottoClass]{createGiottoLargeImageList}}, \code{\link[GiottoClass]{createGiottoObject}}, \code{\link[GiottoClass]{createGiottoObjectSubcellular}}, \code{\link[GiottoClass]{createGiottoPoints}}, \code{\link[GiottoClass]{createGiottoPolygon}}, \code{\link[GiottoClass:createGiottoPolygon]{createGiottoPolygonsFromDfr}}, \code{\link[GiottoClass:createGiottoPolygon]{createGiottoPolygonsFromGeoJSON}}, \code{\link[GiottoClass:createGiottoPolygon]{createGiottoPolygonsFromMask}}, \code{\link[GiottoClass]{createMetafeats}}, \code{\link[GiottoClass]{createNearestNetObj}}, \code{\link[GiottoClass]{createNearestNetwork}}, \code{\link[GiottoClass]{createSpatEnrObj}}, \code{\link[GiottoClass]{createSpatialDefaultGrid}}, \code{\link[GiottoClass]{createSpatialDelaunayNetwork}}, \code{\link[GiottoClass]{createSpatialFeaturesKNNnetwork}}, \code{\link[GiottoClass]{createSpatialGrid}}, \code{\link[GiottoClass]{createSpatialKNNnetwork}}, \code{\link[GiottoClass]{createSpatialNetwork}}, \code{\link[GiottoClass]{createSpatialWeightMatrix}}, \code{\link[GiottoClass]{createSpatLocsObj}}, \code{\link[GiottoClass]{createSpatNetObj}}, \code{\link[GiottoClass]{crop}}, \code{\link[GiottoClass]{cropGiottoLargeImage}}, \code{\link[GiottoClass]{density}}, \code{\link[GiottoClass]{distGiottoImage}}, \code{\link[GiottoClass]{estimateImageBg}}, \code{\link[GiottoClass]{ext}}, \code{\link[GiottoClass:ext]{ext<-}}, \code{\link[GiottoClass]{fDataDT}}, \code{\link[GiottoClass:spatIDs-generic]{featIDs}}, \code{\link[GiottoClass:giotto_schema]{featType}}, \code{\link[GiottoClass:giotto_schema]{featType<-}}, \code{\link[GiottoClass:featureNetwork-class]{featureNetwork}}, \code{\link[GiottoClass]{flip}}, \code{\link[GiottoClass]{gefToGiotto}}, \code{\link[GiottoClass]{getCellMetadata}}, \code{\link[GiottoClass]{getDimReduction}}, \code{\link[GiottoClass]{getExpression}}, \code{\link[GiottoClass]{getFeatureInfo}}, \code{\link[GiottoClass]{getFeatureMetadata}}, \code{\link[GiottoClass]{getGiottoImage}}, \code{\link[GiottoClass]{getMultiomics}}, \code{\link[GiottoClass]{getNearestNetwork}}, \code{\link[GiottoClass]{getPolygonInfo}}, \code{\link[GiottoClass]{getSpatialEnrichment}}, \code{\link[GiottoClass]{getSpatialEnrichment}}, \code{\link[GiottoClass]{getSpatialGrid}}, \code{\link[GiottoClass]{getSpatialGrid}}, \code{\link[GiottoClass]{getSpatialLocations}}, \code{\link[GiottoClass]{getSpatialLocations}}, \code{\link[GiottoClass]{getSpatialNetwork}}, \code{\link[GiottoClass]{getSpatialNetwork}}, \code{\link[GiottoClass:giotto-class]{giotto}}, \code{\link[GiottoClass:giottoImage-class]{giottoImage}}, \code{\link[GiottoClass:giottoLargeImage-class]{giottoLargeImage}}, \code{\link[GiottoClass]{giottoMasterToSuite}}, \code{\link[GiottoClass:giottoPoints-class]{giottoPoints}}, \code{\link[GiottoClass:giottoPolygon-class]{giottoPolygon}}, \code{\link[GiottoClass]{giottoToAnnData}}, \code{\link[GiottoClass]{giottoToSeurat}}, \code{\link[GiottoClass]{giottoToSeuratV4}}, \code{\link[GiottoClass]{giottoToSeuratV5}}, \code{\link[GiottoClass]{giottoToSpatialExperiment}}, \code{\link[GiottoClass]{hexVertices}}, \code{\link[GiottoClass]{hist}}, \code{\link[GiottoClass:giotto_python]{installGiottoEnvironment}}, \code{\link[GiottoClass:giotto_instructions]{instructions}}, \code{\link[GiottoClass:giotto_instructions]{instructions<-}}, \code{\link[GiottoClass]{joinGiottoObjects}}, \code{\link[GiottoClass]{loadGiotto}}, \code{\link[GiottoClass]{makePseudoVisium}}, \code{\link[GiottoClass]{objHistory}}, \code{\link[GiottoClass:giotto_schema]{objName}}, \code{\link[GiottoClass:giotto_schema]{objName<-}}, \code{\link[GiottoClass:generate_grid]{orthoGrid}}, \code{\link[GiottoClass]{overlapImagesToMatrix}}, \code{\link[GiottoClass:overlaps-generic]{overlaps}}, \code{\link[GiottoClass]{overlapToMatrix}}, \code{\link[GiottoClass]{overlapToMatrixMultiPoly}}, \code{\link[GiottoClass]{pDataDT}}, \code{\link[GiottoClass]{plotGiottoImage}}, \code{\link[GiottoClass]{polyStamp}}, \code{\link[GiottoClass:giotto_schema]{prov}}, \code{\link[GiottoClass:giotto_schema]{prov<-}}, \code{\link[GiottoClass]{readCellMetadata}}, \code{\link[GiottoClass]{readDimReducData}}, \code{\link[GiottoClass]{readExprData}}, \code{\link[GiottoClass]{readExprMatrix}}, \code{\link[GiottoClass]{readFeatData}}, \code{\link[GiottoClass]{readFeatMetadata}}, \code{\link[GiottoClass]{readGiottoInstructions}}, \code{\link[GiottoClass]{readNearestNetData}}, \code{\link[GiottoClass]{readPolygonData}}, \code{\link[GiottoClass]{readSpatEnrichData}}, \code{\link[GiottoClass]{readSpatLocsData}}, \code{\link[GiottoClass]{readSpatNetData}}, \code{\link[GiottoClass]{reconnectGiottoImage}}, \code{\link[GiottoClass]{rectVertices}}, \code{\link[GiottoClass]{removeCellAnnotation}}, \code{\link[GiottoClass]{removeFeatAnnotation}}, \code{\link[GiottoClass:giotto_python]{removeGiottoEnvironment}}, \code{\link[GiottoClass]{replaceGiottoInstructions}}, \code{\link[GiottoClass]{rescale}}, \code{\link[GiottoClass]{rescalePolygons}}, \code{\link[GiottoClass]{saveGiotto}}, \code{\link[GiottoClass]{setCellMetadata}}, \code{\link[GiottoClass]{setDimReduction}}, \code{\link[GiottoClass]{setExpression}}, \code{\link[GiottoClass]{setFeatureInfo}}, \code{\link[GiottoClass]{setFeatureMetadata}}, \code{\link[GiottoClass]{setGiotto}}, \code{\link[GiottoClass]{setGiottoImage}}, \code{\link[GiottoClass]{setMultiomics}}, \code{\link[GiottoClass]{setNearestNetwork}}, \code{\link[GiottoClass]{setPolygonInfo}}, \code{\link[GiottoClass]{setSpatialEnrichment}}, \code{\link[GiottoClass]{setSpatialGrid}}, \code{\link[GiottoClass]{setSpatialLocations}}, \code{\link[GiottoClass]{setSpatialNetwork}}, \code{\link[GiottoClass]{seuratToGiotto}}, \code{\link[GiottoClass]{seuratToGiottoV4}}, \code{\link[GiottoClass]{seuratToGiottoV5}}, \code{\link[GiottoClass]{showGiottoCellMetadata}}, \code{\link[GiottoClass]{showGiottoDimRed}}, \code{\link[GiottoClass]{showGiottoExpression}}, \code{\link[GiottoClass]{showGiottoFeatInfo}}, \code{\link[GiottoClass]{showGiottoFeatMetadata}}, \code{\link[GiottoClass]{showGiottoImageNames}}, \code{\link[GiottoClass]{showGiottoInstructions}}, \code{\link[GiottoClass]{showGiottoNearestNetworks}}, \code{\link[GiottoClass]{showGiottoSpatEnrichments}}, \code{\link[GiottoClass]{showGiottoSpatGrids}}, \code{\link[GiottoClass]{showGiottoSpatialInfo}}, \code{\link[GiottoClass]{showGiottoSpatLocs}}, \code{\link[GiottoClass]{showGiottoSpatNetworks}}, \code{\link[GiottoClass]{showProcessingSteps}}, \code{\link[GiottoClass]{smoothGiottoPolygons}}, \code{\link[GiottoClass]{spatialExperimentToGiotto}}, \code{\link[GiottoClass:spatIDs-generic]{spatIDs}}, \code{\link[GiottoClass]{spatQueryGiottoPolygons}}, \code{\link[GiottoClass]{spatShift}}, \code{\link[GiottoClass:giotto_schema]{spatUnit}}, \code{\link[GiottoClass:giotto_schema]{spatUnit<-}}, \code{\link[GiottoClass]{spin}}, \code{\link[GiottoClass]{stitchFieldCoordinates}}, \code{\link[GiottoClass]{stitchFieldCoordinates}}, \code{\link[GiottoClass]{stitchGiottoLargeImage}}, \code{\link[GiottoClass]{subsetGiotto}}, \code{\link[GiottoClass]{subsetGiottoLocs}}, \code{\link[GiottoClass]{subsetGiottoLocsMulti}}, \code{\link[GiottoClass]{subsetGiottoLocsSubcellular}}, \code{\link[GiottoClass]{tessellate}}, \code{\link[GiottoClass:generate_grid]{triGrid}}, \code{\link[GiottoClass]{updateGiottoImage}}, \code{\link[GiottoClass]{updateGiottoImageMG}}, \code{\link[GiottoClass]{updateGiottoLargeImage}}, \code{\link[GiottoClass]{updateGiottoObject}}, \code{\link[GiottoClass]{updateGiottoPointsObject}}, \code{\link[GiottoClass]{updateGiottoPolygonObject}}, \code{\link[GiottoClass:wrap]{vect}}, \code{\link[GiottoClass]{wrap}}, \code{\link[GiottoClass]{writeGiottoLargeImage}}} + \item{GiottoClass}{\code{\link[GiottoClass:activeFeatType-generic]{activeFeatType}}, \code{\link[GiottoClass:activeFeatType-generic]{activeFeatType<-}}, \code{\link[GiottoClass:activeSpatUnit-generic]{activeSpatUnit}}, \code{\link[GiottoClass:activeSpatUnit-generic]{activeSpatUnit<-}}, \code{\link[GiottoClass]{addCellMetadata}}, \code{\link[GiottoClass]{addFeatMetadata}}, \code{\link[GiottoClass]{addGiottoImage}}, \code{\link[GiottoClass]{addGiottoImageMG}}, \code{\link[GiottoClass]{addGiottoLargeImage}}, \code{\link[GiottoClass]{addGiottoPoints}}, \code{\link[GiottoClass:addGiottoPoints]{addGiottoPoints3D}}, \code{\link[GiottoClass]{addGiottoPolygons}}, \code{\link[GiottoClass]{addNetworkLayout}}, \code{\link[GiottoClass]{addSpatialCentroidLocations}}, \code{\link[GiottoClass]{addSpatialCentroidLocationsLayer}}, \code{\link[GiottoClass]{aggregateStacks}}, \code{\link[GiottoClass]{aggregateStacksExpression}}, \code{\link[GiottoClass]{aggregateStacksLocations}}, \code{\link[GiottoClass]{aggregateStacksPolygonOverlaps}}, \code{\link[GiottoClass]{aggregateStacksPolygons}}, \code{\link[GiottoClass]{anndataToGiotto}}, \code{\link[GiottoClass]{annotateGiotto}}, \code{\link[GiottoClass]{annotateSpatialGrid}}, \code{\link[GiottoClass]{annotateSpatialNetwork}}, \code{\link[GiottoClass]{as.points}}, \code{\link[GiottoClass]{as.polygons}}, \code{\link[GiottoClass:r_spatial_conversions]{as.sf}}, \code{\link[GiottoClass:r_spatial_conversions]{as.sp}}, \code{\link[GiottoClass:r_spatial_conversions]{as.stars}}, \code{\link[GiottoClass:r_spatial_conversions]{as.terra}}, \code{\link[GiottoClass]{calculateMetaTable}}, \code{\link[GiottoClass]{calculateMetaTableCells}}, \code{\link[GiottoClass]{calculateOverlap}}, \code{\link[GiottoClass]{calculateOverlapParallel}}, \code{\link[GiottoClass]{calculateOverlapPolygonImages}}, \code{\link[GiottoClass]{calculateOverlapRaster}}, \code{\link[GiottoClass]{calculateOverlapSerial}}, \code{\link[GiottoClass]{calculateSpatCellMetadataProportions}}, \code{\link[GiottoClass:centroids-generic]{centroids}}, \code{\link[GiottoClass]{changeGiottoInstructions}}, \code{\link[GiottoClass]{changeImageBg}}, \code{\link[GiottoClass:giotto_python]{checkGiottoEnvironment}}, \code{\link[GiottoClass]{circleVertices}}, \code{\link[GiottoClass]{combineCellData}}, \code{\link[GiottoClass]{combineFeatureData}}, \code{\link[GiottoClass]{combineFeatureOverlapData}}, \code{\link[GiottoClass]{combineMetadata}}, \code{\link[GiottoClass]{combineSpatialCellMetadataInfo}}, \code{\link[GiottoClass]{combineToMultiPolygon}}, \code{\link[GiottoClass]{convertGiottoLargeImageToMG}}, \code{\link[GiottoClass]{copy}}, \code{\link[GiottoClass]{createBentoAdata}}, \code{\link[GiottoClass]{createCellMetaObj}}, \code{\link[GiottoClass]{createDimObj}}, \code{\link[GiottoClass]{createExprObj}}, \code{\link[GiottoClass]{createFeatMetaObj}}, \code{\link[GiottoClass]{createGiottoImage}}, \code{\link[GiottoClass:giotto_instructions]{createGiottoInstructions}}, \code{\link[GiottoClass]{createGiottoLargeImage}}, \code{\link[GiottoClass]{createGiottoLargeImageList}}, \code{\link[GiottoClass:create_giotto]{createGiottoObject}}, \code{\link[GiottoClass:create_giotto]{createGiottoObjectSubcellular}}, \code{\link[GiottoClass]{createGiottoPoints}}, \code{\link[GiottoClass]{createGiottoPolygon}}, \code{\link[GiottoClass:createGiottoPolygon]{createGiottoPolygonsFromDfr}}, \code{\link[GiottoClass:createGiottoPolygon]{createGiottoPolygonsFromGeoJSON}}, \code{\link[GiottoClass:createGiottoPolygon]{createGiottoPolygonsFromMask}}, \code{\link[GiottoClass]{createMetafeats}}, \code{\link[GiottoClass]{createNearestNetObj}}, \code{\link[GiottoClass]{createNearestNetwork}}, \code{\link[GiottoClass]{createSpatEnrObj}}, \code{\link[GiottoClass]{createSpatialDefaultGrid}}, \code{\link[GiottoClass]{createSpatialDelaunayNetwork}}, \code{\link[GiottoClass]{createSpatialFeaturesKNNnetwork}}, \code{\link[GiottoClass]{createSpatialGrid}}, \code{\link[GiottoClass]{createSpatialKNNnetwork}}, \code{\link[GiottoClass]{createSpatialNetwork}}, \code{\link[GiottoClass]{createSpatialWeightMatrix}}, \code{\link[GiottoClass]{createSpatLocsObj}}, \code{\link[GiottoClass]{createSpatNetObj}}, \code{\link[GiottoClass]{crop}}, \code{\link[GiottoClass]{cropGiottoLargeImage}}, \code{\link[GiottoClass]{density}}, \code{\link[GiottoClass]{distGiottoImage}}, \code{\link[GiottoClass]{estimateImageBg}}, \code{\link[GiottoClass]{ext}}, \code{\link[GiottoClass:ext]{ext<-}}, \code{\link[GiottoClass]{fDataDT}}, \code{\link[GiottoClass:spatIDs-generic]{featIDs}}, \code{\link[GiottoClass:giotto_schema]{featType}}, \code{\link[GiottoClass:giotto_schema]{featType<-}}, \code{\link[GiottoClass:featureNetwork-class]{featureNetwork}}, \code{\link[GiottoClass]{flip}}, \code{\link[GiottoClass]{gefToGiotto}}, \code{\link[GiottoClass]{getCellMetadata}}, \code{\link[GiottoClass]{getDimReduction}}, \code{\link[GiottoClass]{getExpression}}, \code{\link[GiottoClass]{getFeatureInfo}}, \code{\link[GiottoClass]{getFeatureMetadata}}, \code{\link[GiottoClass]{getGiottoImage}}, \code{\link[GiottoClass]{getMultiomics}}, \code{\link[GiottoClass]{getNearestNetwork}}, \code{\link[GiottoClass]{getPolygonInfo}}, \code{\link[GiottoClass]{getSpatialEnrichment}}, \code{\link[GiottoClass]{getSpatialEnrichment}}, \code{\link[GiottoClass]{getSpatialGrid}}, \code{\link[GiottoClass]{getSpatialGrid}}, \code{\link[GiottoClass]{getSpatialLocations}}, \code{\link[GiottoClass]{getSpatialLocations}}, \code{\link[GiottoClass]{getSpatialNetwork}}, \code{\link[GiottoClass]{getSpatialNetwork}}, \code{\link[GiottoClass:giotto-class]{giotto}}, \code{\link[GiottoClass:giottoImage-class]{giottoImage}}, \code{\link[GiottoClass:giottoLargeImage-class]{giottoLargeImage}}, \code{\link[GiottoClass]{giottoMasterToSuite}}, \code{\link[GiottoClass:giottoPoints-class]{giottoPoints}}, \code{\link[GiottoClass:giottoPolygon-class]{giottoPolygon}}, \code{\link[GiottoClass]{giottoToAnnData}}, \code{\link[GiottoClass]{giottoToSeurat}}, \code{\link[GiottoClass]{giottoToSeuratV4}}, \code{\link[GiottoClass]{giottoToSeuratV5}}, \code{\link[GiottoClass]{giottoToSpatialExperiment}}, \code{\link[GiottoClass]{hexVertices}}, \code{\link[GiottoClass]{hist}}, \code{\link[GiottoClass:giotto_python]{installGiottoEnvironment}}, \code{\link[GiottoClass:giotto_instructions]{instructions}}, \code{\link[GiottoClass:giotto_instructions]{instructions<-}}, \code{\link[GiottoClass]{joinGiottoObjects}}, \code{\link[GiottoClass]{loadGiotto}}, \code{\link[GiottoClass]{makePseudoVisium}}, \code{\link[GiottoClass]{objHistory}}, \code{\link[GiottoClass:giotto_schema]{objName}}, \code{\link[GiottoClass:giotto_schema]{objName<-}}, \code{\link[GiottoClass:generate_grid]{orthoGrid}}, \code{\link[GiottoClass]{overlapImagesToMatrix}}, \code{\link[GiottoClass:overlaps-generic]{overlaps}}, \code{\link[GiottoClass]{overlapToMatrix}}, \code{\link[GiottoClass]{overlapToMatrixMultiPoly}}, \code{\link[GiottoClass]{pDataDT}}, \code{\link[GiottoClass]{plotGiottoImage}}, \code{\link[GiottoClass]{polyStamp}}, \code{\link[GiottoClass:giotto_schema]{prov}}, \code{\link[GiottoClass:giotto_schema]{prov<-}}, \code{\link[GiottoClass]{readCellMetadata}}, \code{\link[GiottoClass]{readDimReducData}}, \code{\link[GiottoClass]{readExprData}}, \code{\link[GiottoClass]{readExprMatrix}}, \code{\link[GiottoClass]{readFeatData}}, \code{\link[GiottoClass]{readFeatMetadata}}, \code{\link[GiottoClass]{readGiottoInstructions}}, \code{\link[GiottoClass]{readNearestNetData}}, \code{\link[GiottoClass]{readPolygonData}}, \code{\link[GiottoClass]{readSpatEnrichData}}, \code{\link[GiottoClass]{readSpatLocsData}}, \code{\link[GiottoClass]{readSpatNetData}}, \code{\link[GiottoClass]{reconnectGiottoImage}}, \code{\link[GiottoClass]{rectVertices}}, \code{\link[GiottoClass]{removeCellAnnotation}}, \code{\link[GiottoClass]{removeFeatAnnotation}}, \code{\link[GiottoClass:giotto_python]{removeGiottoEnvironment}}, \code{\link[GiottoClass]{replaceGiottoInstructions}}, \code{\link[GiottoClass]{rescale}}, \code{\link[GiottoClass]{rescalePolygons}}, \code{\link[GiottoClass]{saveGiotto}}, \code{\link[GiottoClass]{setCellMetadata}}, \code{\link[GiottoClass]{setDimReduction}}, \code{\link[GiottoClass]{setExpression}}, \code{\link[GiottoClass]{setFeatureInfo}}, \code{\link[GiottoClass]{setFeatureMetadata}}, \code{\link[GiottoClass]{setGiotto}}, \code{\link[GiottoClass]{setGiottoImage}}, \code{\link[GiottoClass]{setMultiomics}}, \code{\link[GiottoClass]{setNearestNetwork}}, \code{\link[GiottoClass]{setPolygonInfo}}, \code{\link[GiottoClass]{setSpatialEnrichment}}, \code{\link[GiottoClass]{setSpatialGrid}}, \code{\link[GiottoClass]{setSpatialLocations}}, \code{\link[GiottoClass]{setSpatialNetwork}}, \code{\link[GiottoClass]{seuratToGiotto}}, \code{\link[GiottoClass]{seuratToGiottoV4}}, \code{\link[GiottoClass]{seuratToGiottoV5}}, \code{\link[GiottoClass]{showGiottoCellMetadata}}, \code{\link[GiottoClass]{showGiottoDimRed}}, \code{\link[GiottoClass]{showGiottoExpression}}, \code{\link[GiottoClass]{showGiottoFeatInfo}}, \code{\link[GiottoClass]{showGiottoFeatMetadata}}, \code{\link[GiottoClass]{showGiottoImageNames}}, \code{\link[GiottoClass]{showGiottoInstructions}}, \code{\link[GiottoClass]{showGiottoNearestNetworks}}, \code{\link[GiottoClass]{showGiottoSpatEnrichments}}, \code{\link[GiottoClass]{showGiottoSpatGrids}}, \code{\link[GiottoClass]{showGiottoSpatialInfo}}, \code{\link[GiottoClass]{showGiottoSpatLocs}}, \code{\link[GiottoClass]{showGiottoSpatNetworks}}, \code{\link[GiottoClass]{showProcessingSteps}}, \code{\link[GiottoClass]{smoothGiottoPolygons}}, \code{\link[GiottoClass]{spatialExperimentToGiotto}}, \code{\link[GiottoClass:spatIDs-generic]{spatIDs}}, \code{\link[GiottoClass]{spatQueryGiottoPolygons}}, \code{\link[GiottoClass]{spatShift}}, \code{\link[GiottoClass:giotto_schema]{spatUnit}}, \code{\link[GiottoClass:giotto_schema]{spatUnit<-}}, \code{\link[GiottoClass]{spin}}, \code{\link[GiottoClass]{stitchFieldCoordinates}}, \code{\link[GiottoClass]{stitchFieldCoordinates}}, \code{\link[GiottoClass]{stitchGiottoLargeImage}}, \code{\link[GiottoClass]{subsetGiotto}}, \code{\link[GiottoClass]{subsetGiottoLocs}}, \code{\link[GiottoClass]{subsetGiottoLocsMulti}}, \code{\link[GiottoClass]{subsetGiottoLocsSubcellular}}, \code{\link[GiottoClass]{tessellate}}, \code{\link[GiottoClass:generate_grid]{triGrid}}, \code{\link[GiottoClass]{updateGiottoImage}}, \code{\link[GiottoClass]{updateGiottoImageMG}}, \code{\link[GiottoClass]{updateGiottoLargeImage}}, \code{\link[GiottoClass]{updateGiottoObject}}, \code{\link[GiottoClass]{updateGiottoPointsObject}}, \code{\link[GiottoClass]{updateGiottoPolygonObject}}, \code{\link[GiottoClass:wrap]{vect}}, \code{\link[GiottoClass]{wrap}}, \code{\link[GiottoClass]{writeGiottoLargeImage}}} \item{GiottoUtils}{\code{\link[GiottoUtils:pipe]{\%>\%}}, \code{\link[GiottoUtils]{getDistinctColors}}, \code{\link[GiottoUtils]{getRainbowColors}}} From fc8061669e5e2390e53c4f7197b2f057edd515b8 Mon Sep 17 00:00:00 2001 From: George Chen <72078254+jiajic@users.noreply.github.com> Date: Tue, 25 Feb 2025 18:10:53 -0500 Subject: [PATCH 07/11] enh: cosmx convenience - import utility now supports vectors of filepaths when provided to `load_images()` and `load_polys()` --- R/convenience_cosmx.R | 75 ++++++++++++++++++++++++++++--------------- man/importCosMx.Rd | 16 ++++++++- 2 files changed, 65 insertions(+), 26 deletions(-) diff --git a/R/convenience_cosmx.R b/R/convenience_cosmx.R index 83b90dd8a..17744a36f 100644 --- a/R/convenience_cosmx.R +++ b/R/convenience_cosmx.R @@ -147,7 +147,8 @@ setMethod( #' #' \dontrun{ #' # Set the cosmx_dir and fov parameters -#' reader$cosmx_dir <- "path to cosmx dir" +#' path <- "path/to/cosmx/dir" +#' reader$cosmx_dir <- path #' reader$fov <- c(1, 4) #' #' plot(reader) # displays FOVs (top left corner) in px scale. @@ -156,6 +157,19 @@ setMethod( #' polys <- reader$load_polys() #' tx <- reader$load_transcripts() #' imgs <- reader$load_images() +#' +#' # polygons (mask) and images loading supports multiple filepaths +#' # This can be useful when loading AtoMx outputs +#' polys <- reader$load_polys(path = list.files(path, +#' pattern = "CellLabels_F", +#' recursive = TRUE, +#' full.names = TRUE +#' )) +#' imgs <- reader$load_images(path = list.files(path, +#' pattern = "Composite_F", +#' recursive = TRUE, +#' full.names = TRUE +#' )) #' #' # Create a `giotto` object and add the loaded data #' g <- giotto() @@ -792,13 +806,15 @@ setMethod("$<-", signature("CosmxReader"), function(x, name, value) { } .cosmx_imgname_fovparser <- function(path) { - im_names <- list.files(path) + if (length(path) == 1) im_names <- list.files(path) + else im_names <- path fovs <- as.numeric(sub(".*F(\\d+)\\..*", "\\1", im_names)) if (any(is.na(fovs))) { warning(wrap_txt( "Images to load should be sets of images/fov in subdirectories. No other files should be present." - )) + ), call. = FALSE) + fovs <- fovs[!is.na(fovs)] } return(fovs) } @@ -821,6 +837,8 @@ setMethod("$<-", signature("CosmxReader"), function(x, name, value) { # NSE params f <- x <- y <- NULL + path <- normalizePath(path) + GiottoUtils::vmsg(.v = verbose, "loading segmentation masks...") vmsg(.v = verbose, .is_debug = TRUE, path) @@ -848,7 +866,12 @@ setMethod("$<-", signature("CosmxReader"), function(x, name, value) { p <- pbar(along = fovs) gpolys <- lapply(fovs, function(f) { - segfile <- Sys.glob(paths = sprintf("%s/*F%03d*", path, f)) + if (length(path) == 1L) { + segfile <- Sys.glob(paths = sprintf("%s/*F%03d*", path, f)) + } else { + segfile <- path[grepl(pattern = sprintf("F%03d", f), path)] + } + # naming format: c_SLIDENUMBER_FOVNUMBER_CELLID mask_params$ID_fmt <- paste0( sprintf("c_%d_%d_", slide, f), "%d" @@ -950,7 +973,9 @@ setMethod("$<-", signature("CosmxReader"), function(x, name, value) { stop(call. = FALSE) } - if (dir.exists(path)) { + if (length(path) > 1L) { + gpolys <- do.call(.cosmx_poly_maskimage, args = a) + } else if (dir.exists(path)) { gpolys <- do.call(.cosmx_poly_maskimage, args = a) } else if ("csv" %in% GiottoUtils::file_extension(path)) { gpolys <- do.call(.cosmx_poly_csv, args = a) @@ -1094,23 +1119,23 @@ setMethod("$<-", signature("CosmxReader"), function(x, name, value) { return(expr_list) } -.cosmx_image <- function( - path, - fovs = NULL, - img_type = "composite", - img_name_fmt = paste(img_type, "_fov%03d"), - negative_y = FALSE, - flip_vertical = FALSE, - flip_horizontal = FALSE, - micron = FALSE, - px2um = 0.12028, - offsets, - verbose = NULL) { +.cosmx_image <- function(path, + fovs = NULL, + img_type = "composite", + img_name_fmt = paste(img_type, "_fov%03d"), + negative_y = FALSE, + flip_vertical = FALSE, + flip_horizontal = FALSE, + micron = FALSE, + px2um = 0.12028, + offsets, + verbose = NULL) { if (missing(path)) { stop(wrap_txt( "No path to image subdirectory to load provided or auto-detected" ), call. = FALSE) } + path <- normalizePath(path) GiottoUtils::vmsg(.v = verbose, sprintf("loading %s images...", img_type)) vmsg(.v = verbose, .is_debug = TRUE, path) @@ -1122,22 +1147,22 @@ setMethod("$<-", signature("CosmxReader"), function(x, name, value) { p <- pbar(along = fovs) gimg_list <- lapply(fovs, function(f) { - imgfile <- Sys.glob(paths = sprintf("%s/*F%03d*", path, f)) + if (length(path) == 1) { + imgfile <- Sys.glob(paths = sprintf("%s/*F%03d*", path, f)) + } else { + imgfile <- path[grepl(pattern = sprintf("F%03d", f), path)] + } + img_name <- sprintf(img_name_fmt, f) - gimg <- try(createGiottoLargeImage( + gimg <- createGiottoLargeImage( raster_object = imgfile, name = img_name, negative_y = negative_y, flip_vertical = flip_vertical, flip_horizontal = flip_horizontal, verbose = verbose - ), silent = TRUE) - # catch stray metadata files like thumbnails - if (inherits(gimg, "try-error")) { - warning(sprintf("[load_image] unreadable image: %s", imgfile), - call. = FALSE) - } + ) xshift <- offsets[fov == f, x] yshift <- offsets[fov == f, y] diff --git a/man/importCosMx.Rd b/man/importCosMx.Rd index edf8e8701..cf787b1da 100644 --- a/man/importCosMx.Rd +++ b/man/importCosMx.Rd @@ -57,7 +57,8 @@ reader <- importCosMx() \dontrun{ # Set the cosmx_dir and fov parameters -reader$cosmx_dir <- "path to cosmx dir" +path <- "path/to/cosmx/dir" +reader$cosmx_dir <- path reader$fov <- c(1, 4) plot(reader) # displays FOVs (top left corner) in px scale. @@ -67,6 +68,19 @@ polys <- reader$load_polys() tx <- reader$load_transcripts() imgs <- reader$load_images() +# polygons (mask) and images loading supports multiple filepaths +# This can be useful when loading AtoMx outputs +polys <- reader$load_polys(path = list.files(path, + pattern = "CellLabels_F", + recursive = TRUE, + full.names = TRUE +)) +imgs <- reader$load_images(path = list.files(path, + pattern = "Composite_F", + recursive = TRUE, + full.names = TRUE +)) + # Create a `giotto` object and add the loaded data g <- giotto() g <- setGiotto(g, tx[["rna"]]) From 1cbd39d489bc101e9ba6d6a8d0e3acde8ff5bc45 Mon Sep 17 00:00:00 2001 From: George Chen <72078254+jiajic@users.noreply.github.com> Date: Tue, 25 Feb 2025 18:13:52 -0500 Subject: [PATCH 08/11] chore: news --- NEWS.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/NEWS.md b/NEWS.md index 62042ef54..ba8231671 100644 --- a/NEWS.md +++ b/NEWS.md @@ -11,6 +11,8 @@ * `poly_pref` param for `createGiottoCosMxObject()` and `importCosMx()` to select between loading the mask images or the `polygons.csv` as polygon info. * `image_negative_y` param for `createGiottoCosMxObject()` for toggling how images and polygons from mask images should be spatially mapped * `slide` param made more prominent in `createGiottoCosMxObject()` +* `importCosMx()` now supports vectors of filepaths when provided to `$load_images()` and `$load_polys()` +* `importCosMx()` Selected FOVs are now selected in `plot()`. # Giotto 4.2.0 (2025/01/17) From 6948df3587162fa0af862687b6a680ceb88909fa Mon Sep 17 00:00:00 2001 From: George Chen <72078254+jiajic@users.noreply.github.com> Date: Tue, 25 Feb 2025 18:27:53 -0500 Subject: [PATCH 09/11] fix: remove too restrictive filtering on scran results --- R/differential_expression.R | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/R/differential_expression.R b/R/differential_expression.R index 68c557814..89850c811 100644 --- a/R/differential_expression.R +++ b/R/differential_expression.R @@ -324,18 +324,17 @@ findScranMarkers_one_vs_all <- function( ) # filter selected table - filtered_table <- selected_table[logFC > 0] - filtered_table[, "ranking" := rank(-logFC)] + selected_table[, "ranking" := rank(-logFC)] # data.table variables p.value <- ranking <- NULL - filtered_table <- filtered_table[ + selected_table <- selected_table[ (p.value <= pval & logFC >= logFC) | (ranking <= min_feats) ] pb(message = c("cluster ", clus_i, "/", length(uniq_clusters))) - return(filtered_table) + return(selected_table) } ) }) From 6faa33d36f4749c8fcd7f21b1b4563741fdf01e8 Mon Sep 17 00:00:00 2001 From: George Chen <72078254+jiajic@users.noreply.github.com> Date: Fri, 28 Feb 2025 17:46:19 -0500 Subject: [PATCH 10/11] chore: update test --- tests/testthat/test_dataImports.R | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/tests/testthat/test_dataImports.R b/tests/testthat/test_dataImports.R index 5adf3421c..3db34a6a4 100644 --- a/tests/testthat/test_dataImports.R +++ b/tests/testthat/test_dataImports.R @@ -10,10 +10,14 @@ test_that("Expression matrix is read correctly", { # getSpatialDataset - GiottoData::getSpatialDataset(dataset = "scRNA_mouse_brain", directory = paste0(getwd(), "/testdata/")) + expect_warning(expect_warning(GiottoData::getSpatialDataset( + dataset = "scRNA_mouse_brain", + directory = paste0(getwd(), "/testdata/") + ), regexp = "output directory does not exist"), regexp = "footer") # readExprMatrix - expr_mat <- readExprMatrix(paste0(getwd(), "/testdata/brain_sc_expression_matrix.txt.gz")) + expr_mat <- readExprMatrix( + paste0(getwd(), "/testdata/brain_sc_expression_matrix.txt.gz")) expect_s4_class(expr_mat, "dgCMatrix") expect_equal(expr_mat@Dim, c(27998, 8039)) From 0f6feb86556e287891a3d40b7b23c483dad39bc0 Mon Sep 17 00:00:00 2001 From: George Chen <72078254+jiajic@users.noreply.github.com> Date: Fri, 28 Feb 2025 20:55:17 -0500 Subject: [PATCH 11/11] fix: slide setting passing --- R/convenience_cosmx.R | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/R/convenience_cosmx.R b/R/convenience_cosmx.R index 17744a36f..daa92b0b3 100644 --- a/R/convenience_cosmx.R +++ b/R/convenience_cosmx.R @@ -360,6 +360,7 @@ setMethod( micron = .Object@micron, px2um = .Object@px2um, offsets = .Object@offsets, + slide = .Object@slide, verbose = verbose ) } @@ -375,7 +376,8 @@ setMethod( path = path, fovs = .Object@fovs %none% NULL, feat_type = feat_type, - split_keyword = split_keyword + split_keyword = split_keyword, + slide = .Object@slide ) } .Object@calls$load_expression <- expr_fun @@ -426,6 +428,7 @@ setMethod( verbose = NULL) { .cosmx_cellmeta( path = path, + slide = .Object@slide, fovs = .Object@fovs %none% NULL, dropcols = dropcols, cores = cores, @@ -838,7 +841,7 @@ setMethod("$<-", signature("CosmxReader"), function(x, name, value) { f <- x <- y <- NULL path <- normalizePath(path) - + GiottoUtils::vmsg(.v = verbose, "loading segmentation masks...") vmsg(.v = verbose, .is_debug = TRUE, path) @@ -1368,7 +1371,6 @@ createGiottoCosMxObject <- function( "4.2.0", "createGiottoCosMxObject(background_algo)") } - # setup importer x <- importCosMx(cosmx_dir, fovs = FOVs,