From 9e04dd811cf232020e2799c3a37ed707128baf74 Mon Sep 17 00:00:00 2001 From: George Chen <72078254+jiajic@users.noreply.github.com> Date: Wed, 16 Oct 2024 22:33:50 -0400 Subject: [PATCH 01/11] enh: `createGiottoLargeImage` now works for all things rast does --- R/create.R | 42 +++++++++++++----------------------------- 1 file changed, 13 insertions(+), 29 deletions(-) diff --git a/R/create.R b/R/create.R index d8c72b90..83683027 100644 --- a/R/create.R +++ b/R/create.R @@ -3174,7 +3174,8 @@ createGiottoImage <- function( #' @name createGiottoLargeImage #' @description Creates a large giotto image that can be added to a Giotto #' subcellular object. Generates deep copy of SpatRaster -#' @param raster_object terra SpatRaster image object +#' @param raster_object filepath to an image, a terra `SpatRaster` or, other format +#' openable via [terra::rast()] #' @param name name for the image #' @param negative_y Map image to negative y spatial values if TRUE. Meaning #' that origin is in upper left instead of lower left. @@ -3216,42 +3217,25 @@ createGiottoLargeImage <- function( # create minimum giotto g_imageL <- new("giottoLargeImage", name = name) - ## 1. check raster object and load as SpatRaster if necessary - if (!inherits(raster_object, "SpatRaster")) { - if (file.exists(raster_object)) { - g_imageL@file_path <- raster_object - raster_object <- .create_terra_spatraster( - image_path = raster_object - ) - } else { - stop("raster_object needs to be a 'SpatRaster' object from the - terra package or \n an existing path that can be read by - terra::rast()") - } - } - - # Prevent updates to original raster object input - if (getNamespaceVersion("terra") >= "1.15-12") { + if (inherits(raster_object, "SpatRaster")) { + # Prevent updates to original raster object input raster_object <- terra::deepcopy(raster_object) + } else if (is.character(raster_object)) { + checkmate::assert_file_exists(raster_object) + g_imageL@file_path <- raster_object + raster_object <- .create_terra_spatraster(raster_object) } else { - # raster_object = terra::copy(raster_object) - if (isTRUE(verbose)) { - warning("\n If largeImage was created from a terra raster object, - manipulations to the giotto image may be reflected in the - raster object as well. Update terra to >= 1.15-12 to avoid - this issue. \n") - } + # assume class readable by terra rast + raster_object <- .create_terra_spatraster(raster_object) } ## 2. image bound spatial extent - if (use_rast_ext == TRUE) { + if (use_rast_ext) { extent <- terra::ext(raster_object) - if (verbose == TRUE) { - wrap_msg("use_rast_ext == TRUE, extent from input raster_object will - be used.") - } + vmsg(.v = verbose, "use_rast_ext == TRUE + extent from input raster_object will be used.") } # By extent object (priority) From f2161810c52a1c9edcb61c92399dd48cd053354e Mon Sep 17 00:00:00 2001 From: George Chen <72078254+jiajic@users.noreply.github.com> Date: Wed, 16 Oct 2024 22:45:09 -0400 Subject: [PATCH 02/11] chore: docs --- man/createGiottoLargeImage.Rd | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/man/createGiottoLargeImage.Rd b/man/createGiottoLargeImage.Rd index 9d5efc0a..b062a9ec 100644 --- a/man/createGiottoLargeImage.Rd +++ b/man/createGiottoLargeImage.Rd @@ -22,7 +22,8 @@ createGiottoLargeImage( ) } \arguments{ -\item{raster_object}{terra SpatRaster image object} +\item{raster_object}{filepath to an image, a terra \code{SpatRaster} or, other format +openable via \code{\link[terra:rast]{terra::rast()}}} \item{name}{name for the image} From f4caa2732f93b2ec11b70c1166a2d70b1677c45a Mon Sep 17 00:00:00 2001 From: George Chen <72078254+jiajic@users.noreply.github.com> Date: Thu, 17 Oct 2024 00:16:52 -0400 Subject: [PATCH 03/11] fix: createGiottoPolygonsFromMask() shift step functions now actually work as steps --- R/create.R | 18 ++++++++++-------- man/createGiottoPolygon.Rd | 3 ++- 2 files changed, 12 insertions(+), 9 deletions(-) diff --git a/R/create.R b/R/create.R index 83683027..acfe84eb 100644 --- a/R/create.R +++ b/R/create.R @@ -2418,7 +2418,8 @@ setMethod( #' @rdname createGiottoPolygon -#' @param maskfile path to mask file +#' @param maskfile path to mask file, a terra `SpatRaster`, or some other +#' data class readable by [terra::rast()] #' @param mask_method how the mask file defines individual segmentation #' annotations. See *mask_method* section #' @param name character. Name to assign created `giottoPolygon` @@ -2521,15 +2522,16 @@ createGiottoPolygonsFromMask <- function(maskfile, # if maskfile input is not a spatraster, read it in as spatraster # if it is spatraster, skip - if (!inherits(maskfile, "SpatRaster")) { + if (inherits(maskfile, "SpatRaster")) { + terra_rast <- maskfile + } else if (is.character(maskfile)) { # check if mask file exists maskfile <- path.expand(maskfile) - if (!file.exists(maskfile)) { - stop("path : ", maskfile, " does not exist \n") - } + checkmate::assert_file_exists(maskfile) terra_rast <- .create_terra_spatraster(maskfile) } else { - terra_rast <- maskfile + # assume some other class readable by terra::rast() + terra_rast <- .create_terra_spatraster(maskfile) } # create polygons from mask @@ -2627,14 +2629,14 @@ createGiottoPolygonsFromMask <- function(maskfile, if (identical(shift_vertical_step, TRUE)) { shift_vertical_step <- rast_dimensions[1] # nrows of raster } else if (is.numeric(shift_vertical_step)) { - shift_vertical_step <- shift_vertical_step + shift_vertical_step <- rast_dimensions[1] * shift_vertical_step } else { shift_vertical_step <- 0 } if (identical(shift_horizontal_step, TRUE)) { shift_horizontal_step <- rast_dimensions[2] # ncols of raster } else if (is.numeric(shift_horizontal_step)) { - shift_horizontal_step <- shift_horizontal_step + shift_horizontal_step <- rast_dimensions[2] * shift_horizontal_step } else { shift_horizontal_step <- 0 } diff --git a/man/createGiottoPolygon.Rd b/man/createGiottoPolygon.Rd index d2a1a542..24df4b18 100644 --- a/man/createGiottoPolygon.Rd +++ b/man/createGiottoPolygon.Rd @@ -121,7 +121,8 @@ poly_IDs. Default = "cell_". See \emph{ID_fmt} section.} \item{copy_dt}{(default TRUE) if segmdfr is provided as dt, this determines whether a copy is made} -\item{maskfile}{path to mask file} +\item{maskfile}{path to mask file, a terra \code{SpatRaster}, or some other +data class readable by \code{\link[terra:rast]{terra::rast()}}} \item{segmdfr}{data.frame-like object with polygon coordinate information (x, y, poly_ID) with x and y being vertex information for the From 7f54f0383903b8be279c7328457d1ca7cd244f5a Mon Sep 17 00:00:00 2001 From: George Chen <72078254+jiajic@users.noreply.github.com> Date: Thu, 17 Oct 2024 00:17:09 -0400 Subject: [PATCH 04/11] chore: update news --- NEWS.md | 3 +++ 1 file changed, 3 insertions(+) diff --git a/NEWS.md b/NEWS.md index 574ac55e..894f6b0c 100644 --- a/NEWS.md +++ b/NEWS.md @@ -9,6 +9,7 @@ - fix `joinGiottoObject()` for gobjects with only poly and point data [#233](https://github.com/drieslab/GiottoClass/issues/233) - fix `joinGiottoObject()` for gobjects with image intensity overlaps features - fix subsetting error due to expression `matrix` drop to `numeric` when only one cell is left +- `shift_vertical_step` and `shift_horizontal_step` args in `createGiottoPolygonsFromMask()` when numeric now shift by steps based on the dims of the image instead of just by the numerical value provided. ## enhancements - python packages to install through pip is now settable in `installGiottoEnvironment()` [#224](https://github.com/drieslab/GiottoClass/issues/224) @@ -22,6 +23,8 @@ - `ext()` and `ext<-()` can now be used to get and set extent of `affine2d` - `rownames()`, `colnames()`, `dimnames()` for `giotto` - `spatValues()` can get values from multiple spatial units. +- `createGiottoPolygonsFromMask()` now works with anything `terra::rast()` can read +- `createGiottoLargeImage()` now works with anything `terra::rast()` can read ## new - `sliceGiotto()` for pulling out specific spatial units and feature types as independent `giotto` objects From 22695204be987d174bbc687cd21a7c773501c6d8 Mon Sep 17 00:00:00 2001 From: George Chen <72078254+jiajic@users.noreply.github.com> Date: Thu, 17 Oct 2024 14:31:00 -0400 Subject: [PATCH 05/11] feat: `XY()` and `XY<-()` for coord access --- DESCRIPTION | 1 + NAMESPACE | 2 + NEWS.md | 1 + R/generics.R | 18 +++--- R/methods-XY.R | 147 +++++++++++++++++++++++++++++++++++++++++++++++++ man/XY.Rd | 69 +++++++++++++++++++++++ 6 files changed, 230 insertions(+), 8 deletions(-) create mode 100644 R/methods-XY.R create mode 100644 man/XY.Rd diff --git a/DESCRIPTION b/DESCRIPTION index e8796748..b00689f9 100644 --- a/DESCRIPTION +++ b/DESCRIPTION @@ -105,6 +105,7 @@ Collate: 'interoperability.R' 'join.R' 'methods-IDs.R' + 'methods-XY.R' 'methods-affine.R' 'methods-centroids.R' 'methods-coerce.R' diff --git a/NAMESPACE b/NAMESPACE index 00a0a9d4..0083bd2b 100644 --- a/NAMESPACE +++ b/NAMESPACE @@ -292,6 +292,7 @@ exportMethods("$") exportMethods("$<-") exportMethods("+") exportMethods("-") +exportMethods("XY<-") exportMethods("[") exportMethods("[<-") exportMethods("[[") @@ -303,6 +304,7 @@ exportMethods("instructions<-") exportMethods("objName<-") exportMethods("prov<-") exportMethods("spatUnit<-") +exportMethods(XY) exportMethods(activeFeatType) exportMethods(activeSpatUnit) exportMethods(affine) diff --git a/NEWS.md b/NEWS.md index 894f6b0c..01ff29a8 100644 --- a/NEWS.md +++ b/NEWS.md @@ -30,6 +30,7 @@ - `sliceGiotto()` for pulling out specific spatial units and feature types as independent `giotto` objects - `splitGiotto()` for splitting a Giotto object into a list of Giotto objects based on a cell metadata column - `as.list()` method for `giotto` to dump the data as a list of subobjects +- `XY()` and `XY<-()` for accessing and setting coordinate values of subobjects as `matrix` # GiottoClass 0.3.5 (2024/08/28) diff --git a/R/generics.R b/R/generics.R index 87752166..1d30bb90 100644 --- a/R/generics.R +++ b/R/generics.R @@ -33,14 +33,6 @@ setGeneric( ) -# Methods and documentations found in methods-spatShift.R -setGeneric("spatShift", function(x, ...) standardGeneric("spatShift")) -setGeneric("affine", function(x, y, ...) standardGeneric("affine")) -setGeneric("shear", function(x, ...) standardGeneric("shear")) - -# Methods and documentations found in methods-overlaps.R -setGeneric("overlaps", function(x, ...) standardGeneric("overlaps")) - # Object creation #### setGeneric( @@ -87,6 +79,16 @@ setGeneric( function(x, ...) standardGeneric("overlapToMatrix") ) +# Methods and documentations found in methods-spatShift.R +setGeneric("spatShift", function(x, ...) standardGeneric("spatShift")) +setGeneric("affine", function(x, y, ...) standardGeneric("affine")) +setGeneric("shear", function(x, ...) standardGeneric("shear")) +setGeneric("XY", function(x, ...) standardGeneric("XY")) +setGeneric("XY<-", function(x, ..., value) standardGeneric("XY<-")) + +# Methods and documentations found in methods-overlaps.R +setGeneric("overlaps", function(x, ...) standardGeneric("overlaps")) + # Giotto subnesting #### # All methods and documentations found in methods-nesting.R diff --git a/R/methods-XY.R b/R/methods-XY.R new file mode 100644 index 00000000..0bc30ac7 --- /dev/null +++ b/R/methods-XY.R @@ -0,0 +1,147 @@ +# docs ----------------------------------------------------------- # +#' @title Spatial coordinates +#' @name XY +#' @aliases XY<- +#' @description Directly get and set the xy(z) coordinates of spatial +#' subobjects (currently `spatLocsObj`, `giottoPoints`, `giottoPolygon`). +#' coordinate values are retrieved and set as `matrix`. +#' @param x object +#' @param value matrix. xy(z) coordinates to set +#' @param ... additional args to pass +#' @returns same class as `x` +#' @examples +#' sl <- GiottoData::loadSubObjectMini("spatLocsObj") +#' gpoly <- GiottoData::loadSubObjectMini("giottoPolygon") +#' gpoints <- GiottoData::loadSubObjectMini("giottoPoints") +#' +#' m1 <- XY(sl) +#' plot(sl) +#' XY(sl) <- m1 + 1000 +#' plot(sl) +#' +#' m2 <- XY(gpoints) +#' plot(gpoints) +#' XY(gpoints) <- m2 * 2 + 1000 +#' plot(gpoints) +#' +#' m3 <- XY(gpoly) +#' plot(gpoly) +#' XY(gpoly) <- m3 / 2 +#' plot(gpoly) +NULL +# ---------------------------------------------------------------- # + + + +# * spatLocsObj #### + +#' @rdname XY +#' @export +setMethod("XY", signature("spatLocsObj"), function(x, ...) { + m <- x[][, colnames(sl) != "cell_ID", with = F] |> + as.matrix(...) + if (ncol(m) == 2L) colnames(m) <- c("x", "y") + if (ncol(m) == 3L) colnames(m) <- c("x", "y", "z") + return(m) +}) + +#' @rdname XY +#' @export +setMethod( + "XY<-", signature(x = "spatLocsObj", value = "matrix"), + function(x, value) { + dt <- data.table::as.data.table(value) + if (ncol(dt) == 2L) + data.table::setnames(dt, new = c("sdimx", "sdimy")) + if (ncol(dt) == 3L) + data.table::setnames(dt, new = c("sdimx", "sdimy", "sdimx")) + x[] <- cbind(dt, x[][, "cell_ID"]) + return(x) + }) + +# * giottoPoints & giottoPolygon #### + +#' @rdname XY +#' @export +setMethod("XY", signature("giottoPoints"), function(x, ...) { + return(XY(x[], ...)) +}) + +#' @rdname XY +#' @export +setMethod( + "XY<-", signature(x = "giottoPoints", value = "ANY"), + function(x, ..., value) { + XY(x[]) <- value + return(x) + }) + +#' @rdname XY +#' @export +setMethod("XY", signature("giottoPolygon"), function(x, ...) { + return(XY(x[], ...)) +}) + +#' @rdname XY +#' @export +setMethod( + "XY<-", signature(x = "giottoPolygon", value = "ANY"), + function(x, ..., value) { + XY(x[]) <- value + return(x) + }) + +# * SpatVector #### + +#' @rdname XY +#' @param include_geom logical. Whether `geom`, `part`, and `hole` from the +#' terra geometry matrix should be included. +#' @export +setMethod("XY", signature("SpatVector"), function(x, include_geom = FALSE, ...) { + m <- terra::geom(x, ...) + if (!include_geom) { + m <- m[, c("x", "y")] + } + return(m) +}) + +#' @rdname XY +#' @export +setMethod("XY<-", signature(x = "SpatVector", value = "matrix"), function(x, ..., value) { + switch(terra::geomtype(x), + "points" = .xy_sv_points_set(x, ..., value = value), + "polygons" = .xy_sv_polys_set(x, ..., value = value) + ) +}) + + + +# internals #### + + +.xy_sv_points_set <- function(x, ..., value) { + atts <- terra::values(x) + v <- terra::vect(value, type = "points", ..., atts = atts) + return(v) +} + +.xy_sv_polys_set <- function(x, ..., value) { + atts <- terra::values(x) + if (identical(colnames(x), c("geom", "part", "x", "y", "hole"))) { + # the entire geom matrix is given. Directly use it. + v <- terra::vect(value, type = "polygons", ..., atts = atts) + } else { + # replace xy values in geom matrix + m <- terra::geom(x) + m[, "x"] <- value[, "x"] + m[, "y"] <- value[, "y"] + v <- terra::vect(m, type = "polygons", ..., atts = atts) + } +} + + + + + + + diff --git a/man/XY.Rd b/man/XY.Rd new file mode 100644 index 00000000..0088ea34 --- /dev/null +++ b/man/XY.Rd @@ -0,0 +1,69 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/methods-XY.R +\name{XY} +\alias{XY} +\alias{XY<-} +\alias{XY,spatLocsObj-method} +\alias{XY<-,spatLocsObj,matrix-method} +\alias{XY,giottoPoints-method} +\alias{XY<-,giottoPoints,ANY-method} +\alias{XY,giottoPolygon-method} +\alias{XY<-,giottoPolygon,ANY-method} +\alias{XY,SpatVector-method} +\alias{XY<-,SpatVector,matrix-method} +\title{Spatial coordinates} +\usage{ +\S4method{XY}{spatLocsObj}(x, ...) + +\S4method{XY}{spatLocsObj,matrix}(x) <- value + +\S4method{XY}{giottoPoints}(x, ...) + +\S4method{XY}{giottoPoints,ANY}(x, ...) <- value + +\S4method{XY}{giottoPolygon}(x, ...) + +\S4method{XY}{giottoPolygon,ANY}(x, ...) <- value + +\S4method{XY}{SpatVector}(x, include_geom = FALSE, ...) + +\S4method{XY}{SpatVector,matrix}(x, ...) <- value +} +\arguments{ +\item{x}{object} + +\item{...}{additional args to pass} + +\item{value}{matrix. xy(z) coordinates to set} + +\item{include_geom}{logical. Whether \code{geom}, \code{part}, and \code{hole} from the +terra geometry matrix should be included.} +} +\value{ +same class as \code{x} +} +\description{ +Directly get and set the xy(z) coordinates of spatial +subobjects (currently \code{spatLocsObj}, \code{giottoPoints}, \code{giottoPolygon}). +coordinate values are retrieved and set as \code{matrix}. +} +\examples{ +sl <- GiottoData::loadSubObjectMini("spatLocsObj") +gpoly <- GiottoData::loadSubObjectMini("giottoPolygon") +gpoints <- GiottoData::loadSubObjectMini("giottoPoints") + +m1 <- XY(sl) +plot(sl) +XY(sl) <- m1 + 1000 +plot(sl) + +m2 <- XY(gpoints) +plot(gpoints) +XY(gpoints) <- m2 * 2 + 1000 +plot(gpoints) + +m3 <- XY(gpoly) +plot(gpoly) +XY(gpoly) <- m3 / 2 +plot(gpoly) +} From 549d6e044178391903bf1a072d23790d35cde4be Mon Sep 17 00:00:00 2001 From: George Chen <72078254+jiajic@users.noreply.github.com> Date: Fri, 18 Oct 2024 08:20:15 -0400 Subject: [PATCH 06/11] enh: feat meta + matrix joining can select ids - feat meta also properly mixed sorts after a join --- NEWS.md | 1 + R/join.R | 33 +++++++++++++++++++++++---------- 2 files changed, 24 insertions(+), 10 deletions(-) diff --git a/NEWS.md b/NEWS.md index 01ff29a8..c6961df5 100644 --- a/NEWS.md +++ b/NEWS.md @@ -10,6 +10,7 @@ - fix `joinGiottoObject()` for gobjects with image intensity overlaps features - fix subsetting error due to expression `matrix` drop to `numeric` when only one cell is left - `shift_vertical_step` and `shift_horizontal_step` args in `createGiottoPolygonsFromMask()` when numeric now shift by steps based on the dims of the image instead of just by the numerical value provided. +- fix feature metadata not being mixedsorted after join ## enhancements - python packages to install through pip is now settable in `installGiottoEnvironment()` [#224](https://github.com/drieslab/GiottoClass/issues/224) diff --git a/R/join.R b/R/join.R index 9f06d902..9b759deb 100644 --- a/R/join.R +++ b/R/join.R @@ -4,19 +4,17 @@ #' @name .join_expression_matrices #' @keywords internal #' @noRd -.join_expression_matrices <- function(matrix_list) { +.join_expression_matrices <- function(matrix_list, feat_ids = NULL) { + # find all features - final_feats <- list() - for (matr_i in seq_len(length(matrix_list))) { - rowfeats <- rownames(matrix_list[[matr_i]]) - final_feats[[matr_i]] <- rowfeats + if (is.null(feat_ids)) { + final_feats <- lapply(matrix_list, rownames) + final_feats <- unique(unlist(final_feats)) + } else { + final_feats <- feat_ids } - - final_feats <- unique(unlist(final_feats)) final_feats <- mixedsort(final_feats) - - # extend matrices with missing ids final_mats <- list() for (matr_i in seq_len(length(matrix_list))) { @@ -60,9 +58,20 @@ #' @name .join_feat_meta #' @keywords internal #' @noRd -.join_feat_meta <- function(dt_list) { +.join_feat_meta <- function(dt_list, feat_ids = NULL) { feat_ID <- NULL + if (!is.null(feat_ids)) { + dt_list <- lapply(dt_list, function(dt) { + dt <- dt[feat_ID %in% feat_ids] + missing_feat <- dt[, feat_ids[!feat_ids %in% feat_ID]] + if (length(missing_feat) > 0L) { + dt_append <- data.table::data.table(feat_ID = missing_feat) + dt <- rbind(dt, dt_append, fill = TRUE) + } + }) + } + comb_meta <- do.call("rbind", c(dt_list, fill = TRUE)) comb_meta <- unique(comb_meta) @@ -77,8 +86,12 @@ "feature metadata: multiple versions of metadata for:\n", dup_feats, "\n First entry will be selected for joined object." + # "first" is based on gobject order )) } + + # order by feat_ID + comb_meta <- comb_meta[mixedorder(feat_ID)] return(comb_meta) } From d6468bb1538dc69aeae986963e734fd86ae5e658 Mon Sep 17 00:00:00 2001 From: George Chen <72078254+jiajic@users.noreply.github.com> Date: Mon, 21 Oct 2024 00:30:48 -0400 Subject: [PATCH 07/11] fix: ":all:" passing for subsetGiotto --- R/methods-extract.R | 3 ++- R/subset.R | 4 ++++ 2 files changed, 6 insertions(+), 1 deletion(-) diff --git a/R/methods-extract.R b/R/methods-extract.R index c34262fe..36049f5f 100644 --- a/R/methods-extract.R +++ b/R/methods-extract.R @@ -1450,7 +1450,8 @@ setMethod("subset", signature("giotto"), function(x, spat_unit = ":all:", feat_type = feat_type, feat_ids = fids, - cell_ids = sids + cell_ids = sids, + poly_info = spat_unit ) }) diff --git a/R/subset.R b/R/subset.R index 773c1b67..49390950 100644 --- a/R/subset.R +++ b/R/subset.R @@ -910,6 +910,10 @@ # # aggregate spatial locations and expression information # # # # Should only be checked for cell_ids subsets + + if (isTRUE(poly_info, ":all:")) { + poly_info <- list_spatial_info_names(gobject) + } for (select_poly_info in poly_info) { # For each entry entry in poly_info, subset using cell_ids. From f0f30923088c90465fab99723c159a6d1fbd402c Mon Sep 17 00:00:00 2001 From: George Chen <72078254+jiajic@users.noreply.github.com> Date: Mon, 21 Oct 2024 14:33:22 -0400 Subject: [PATCH 08/11] fix: poly subsetting now matches spatlocs when possible --- R/methods-XY.R | 2 ++ R/subset.R | 12 +++++++++--- 2 files changed, 11 insertions(+), 3 deletions(-) diff --git a/R/methods-XY.R b/R/methods-XY.R index 0bc30ac7..e8ad4329 100644 --- a/R/methods-XY.R +++ b/R/methods-XY.R @@ -28,6 +28,8 @@ #' plot(gpoly) #' XY(gpoly) <- m3 / 2 #' plot(gpoly) +#' +#' XY(gpoly[1:10]) # vertices from first 10 polys NULL # ---------------------------------------------------------------- # diff --git a/R/subset.R b/R/subset.R index 49390950..97ab333d 100644 --- a/R/subset.R +++ b/R/subset.R @@ -911,8 +911,14 @@ # # # # Should only be checked for cell_ids subsets - if (isTRUE(poly_info, ":all:")) { - poly_info <- list_spatial_info_names(gobject) + attached_polys <- list_spatial_info_names(gobject) + + if (is.null(poly_info)) { + poly_info <- spat_unit[spat_unit %in% attached_polys] + } + + if (isTRUE(poly_info == ":all:")) { + poly_info <- attached_polys } for (select_poly_info in poly_info) { @@ -1430,7 +1436,7 @@ subsetGiotto <- function( feat_type = "rna", cell_ids = NULL, feat_ids = NULL, - poly_info = NULL, + poly_info = spat_unit, all_spat_units = NULL, all_feat_types = NULL, spat_unit_fsub = ":all:", From 162454485bf091fc3ff3c9dd0fa9eb0263136985 Mon Sep 17 00:00:00 2001 From: George Chen <72078254+jiajic@users.noreply.github.com> Date: Mon, 21 Oct 2024 17:13:17 -0400 Subject: [PATCH 09/11] chore: docs --- man/XY.Rd | 2 ++ man/subsetGiotto.Rd | 2 +- 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/man/XY.Rd b/man/XY.Rd index 0088ea34..3adbba72 100644 --- a/man/XY.Rd +++ b/man/XY.Rd @@ -66,4 +66,6 @@ m3 <- XY(gpoly) plot(gpoly) XY(gpoly) <- m3 / 2 plot(gpoly) + +XY(gpoly[1:10]) # vertices from first 10 polys } diff --git a/man/subsetGiotto.Rd b/man/subsetGiotto.Rd index 5e980771..adcb8701 100644 --- a/man/subsetGiotto.Rd +++ b/man/subsetGiotto.Rd @@ -10,7 +10,7 @@ subsetGiotto( feat_type = "rna", cell_ids = NULL, feat_ids = NULL, - poly_info = NULL, + poly_info = spat_unit, all_spat_units = NULL, all_feat_types = NULL, spat_unit_fsub = ":all:", From 97a80c4536ef1b4d9b2bf8957c3d00c81d291585 Mon Sep 17 00:00:00 2001 From: George Chen <72078254+jiajic@users.noreply.github.com> Date: Mon, 21 Oct 2024 17:13:38 -0400 Subject: [PATCH 10/11] enh: relate method for `giotto` --- R/methods-relate.R | 52 +++++++++++++++++++++++++++++++++++++++++++++- man/relate.Rd | 23 +++++++++++++++++++- 2 files changed, 73 insertions(+), 2 deletions(-) diff --git a/R/methods-relate.R b/R/methods-relate.R index 88dc21bf..a4ab2169 100644 --- a/R/methods-relate.R +++ b/R/methods-relate.R @@ -18,6 +18,7 @@ #' gpoly <- GiottoData::loadSubObjectMini("giottoPolygon") #' #' relate(gpoints, gpoly, relation = "intersects") +#' relate(gpoints, gpoly, relation = "intersects", use_names = FALSE) NULL # ---------------------------------------------------------------- # @@ -29,7 +30,7 @@ setMethod( function(x, y, relation, pairs = TRUE, na.rm = TRUE, - output = c("data.table", "list", "matrix"), + output = c("data.table", "matrix"), use_names = TRUE, ...) { output <- match.arg(output, choices = c("data.table", "matrix")) @@ -57,6 +58,55 @@ setMethod( } ) +#' @rdname relate +#' @param what character. Which type of spatial data in the `giotto` object to +#' relate. One of "polygon", "spatlocs", "points" +#' @param spat_unit spatial unit +#' @param feat_type feature type +#' @param spat_locs_name name of spatlocs to use if what = "spatlocs" +#' @export +setMethod( + "relate", signature(x = "giotto", y = "giottoSpatial"), + function(x, y, ..., + what = c("polygon", "spatlocs", "points"), + spat_unit = NULL, + feat_type = NULL, + spat_locs_name = NULL) { + + what <- match.arg(what, c("polygon", "spatlocs", "points")) + + spat_unit <- set_default_spat_unit(x, spat_unit = spat_unit) + feat_type <- set_default_feat_type( + x, spat_unit = spat_unit, feat_type = feat_type + ) + + x <- switch(what, + "polygon" = { + getPolygonInfo(x, + polygon_name = spat_unit, + return_giottoPolygon = TRUE + ) + }, + "points" = { + getFeatureInfo(x, + feat_type = feat_type, + return_giottoPoints = TRUE + ) + }, + "spatlocs" = { + getSpatialLocations(x, + spat_unit = spat_unit, + output = "spatLocsObj", + name = spat_locs_name + ) + } + ) + + res <- relate(x, y, ...) + return(res) + } +) + diff --git a/man/relate.Rd b/man/relate.Rd index 06040438..2f4b5484 100644 --- a/man/relate.Rd +++ b/man/relate.Rd @@ -3,6 +3,7 @@ \name{relate} \alias{relate} \alias{relate,giottoSpatial,giottoSpatial-method} +\alias{relate,giotto,giottoSpatial-method} \title{Spatial relationships between geometries} \usage{ \S4method{relate}{giottoSpatial,giottoSpatial}( @@ -11,10 +12,20 @@ relation, pairs = TRUE, na.rm = TRUE, - output = c("data.table", "list", "matrix"), + output = c("data.table", "matrix"), use_names = TRUE, ... ) + +\S4method{relate}{giotto,giottoSpatial}( + x, + y, + ..., + what = c("polygon", "spatlocs", "points"), + spat_unit = NULL, + feat_type = NULL, + spat_locs_name = NULL +) } \arguments{ \item{x}{spatial object with records to test} @@ -34,6 +45,15 @@ only possible when \code{pairs=TRUE}} the IDs of the geometries will be used.} \item{...}{additional args to pass} + +\item{what}{character. Which type of spatial data in the \code{giotto} object to +relate. One of "polygon", "spatlocs", "points"} + +\item{spat_unit}{spatial unit} + +\item{feat_type}{feature type} + +\item{spat_locs_name}{name of spatlocs to use if what = "spatlocs"} } \value{ \code{data.table} if \code{output="data.table"}. \code{matrix} if \code{output="matrix"} @@ -49,4 +69,5 @@ gpoints <- GiottoData::loadSubObjectMini("giottoPoints") gpoly <- GiottoData::loadSubObjectMini("giottoPolygon") relate(gpoints, gpoly, relation = "intersects") +relate(gpoints, gpoly, relation = "intersects", use_names = FALSE) } From d47a88cba33e371dfb17a49bd4a81157fcfd8907 Mon Sep 17 00:00:00 2001 From: George Chen <72078254+jiajic@users.noreply.github.com> Date: Mon, 21 Oct 2024 17:34:31 -0400 Subject: [PATCH 11/11] chore: update relate docs --- R/methods-relate.R | 17 +++++++++-- inst/extdata/viz_interactive_select.csv | 40 +++++++++++++++++++++++++ man/relate.Rd | 17 +++++++++-- 3 files changed, 68 insertions(+), 6 deletions(-) create mode 100644 inst/extdata/viz_interactive_select.csv diff --git a/R/methods-relate.R b/R/methods-relate.R index a4ab2169..763aa837 100644 --- a/R/methods-relate.R +++ b/R/methods-relate.R @@ -13,12 +13,23 @@ #' the IDs of the geometries will be used. #' @returns `data.table` if `output="data.table"`. `matrix` if `output="matrix"` #' @examples -#' sl <- GiottoData::loadSubObjectMini("spatLocsObj") -#' gpoints <- GiottoData::loadSubObjectMini("giottoPoints") -#' gpoly <- GiottoData::loadSubObjectMini("giottoPolygon") +#' g <- GiottoData::loadGiottoMini("viz") +#' activeSpatUnit(g) <- "aggregate" +#' sl <- g[["spatial_locs"]][[1]] +#' gpoints <- g[["spatial_info]][[1]] +#' gpoly <- g[["feat_info]][[1]] #' #' relate(gpoints, gpoly, relation = "intersects") #' relate(gpoints, gpoly, relation = "intersects", use_names = FALSE) +#' +#' selection <- system.file("extdata/viz_interactive_select.csv", +#' package = "GiottoClass" +#' ) +#' select_polys <- createGiottoPolygon(data.table::fread(selection)) +#' res <- relate(g, select_polys, relation = "intersects") +#' g[,res[y == "polygon1", x]] +#' g[,res[y == "polygon2", x]] +#' g[,res[y == "polygon3", x]] NULL # ---------------------------------------------------------------- # diff --git a/inst/extdata/viz_interactive_select.csv b/inst/extdata/viz_interactive_select.csv new file mode 100644 index 00000000..c23d6043 --- /dev/null +++ b/inst/extdata/viz_interactive_select.csv @@ -0,0 +1,40 @@ +"","x","y","name" +"1",6425.22739495473,-4731.2084196259,"polygon1" +"2",6389.47789256765,-4802.70742440005,"polygon1" +"3",6393.60283515077,-4889.33121864567,"polygon1" +"4",6454.1019930366,-4861.83160142484,"polygon1" +"5",6503.60130403409,-4809.58232870526,"polygon1" +"6",6531.10092125492,-4780.70773062339,"polygon1" +"7",6576.47528966929,-4769.70788373506,"polygon1" +"8",6605.34988775116,-4742.20826651423,"polygon1" +"9",6632.84950497199,-4709.20872584923,"polygon1" +"10",6500.85134231201,-4688.58401293361,"polygon1" +"11",6548.97567244846,-4835.70696506505,"polygon2" +"12",6481.60161025743,-4853.58171625859,"polygon2" +"13",6410.10260548327,-4912.70589328338,"polygon2" +"14",6397.7277777339,-4959.45524255879,"polygon2" +"15",6394.97781601181,-5043.32907508232,"polygon2" +"16",6397.7277777339,-5140.95271621627,"polygon2" +"17",6489.85149542368,-5098.32830952398,"polygon2" +"18",6547.60069158742,-5077.70359660836,"polygon2" +"19",6533.850882977,-5035.07918991607,"polygon2" +"20",6543.4757490043,-4947.08041480941,"polygon2" +"21",6569.60038536408,-4908.58095070025,"polygon2" +"22",6639.7244092772,-4875.58141003525,"polygon2" +"23",6664.47406477595,-4842.58186937026,"polygon2" +"24",6595.72502172387,-4812.33229042734,"polygon2" +"25",6755.22280160469,-4694.08393637777,"polygon3" +"26",6751.09785902156,-4773.83282631818,"polygon3" +"27",6745.5979355774,-4872.83144831317,"polygon3" +"28",6733.22310782802,-4926.45570189379,"polygon3" +"29",6755.22280160469,-5004.82961097316,"polygon3" +"30",6767.59762935406,-5043.32907508232,"polygon3" +"31",6749.72287816052,-5103.82823296815,"polygon3" +"32",6729.0981652449,-5139.57773535522,"polygon3" +"33",6799.22218915802,-5145.07765879939,"polygon3" +"34",6876.22111737634,-5121.70298416169,"polygon3" +"35",6907.8456771803,-5054.32892197065,"polygon3" +"36",6902.34575373613,-4893.45616122879,"polygon3" +"37",6833.59671068405,-4875.58141003525,"polygon3" +"38",6822.59686379572,-4780.70773062339,"polygon3" +"39",6817.09694035156,-4689.95899379465,"polygon3" diff --git a/man/relate.Rd b/man/relate.Rd index 2f4b5484..ffebc4bc 100644 --- a/man/relate.Rd +++ b/man/relate.Rd @@ -64,10 +64,21 @@ absence of a specific spatial relationships between the geometries in x and y. } \examples{ -sl <- GiottoData::loadSubObjectMini("spatLocsObj") -gpoints <- GiottoData::loadSubObjectMini("giottoPoints") -gpoly <- GiottoData::loadSubObjectMini("giottoPolygon") +g <- GiottoData::loadGiottoMini("viz") +activeSpatUnit(g) <- "aggregate" +sl <- g[["spatial_locs"]][[1]] +gpoints <- g[["spatial_info]][[1]] +gpoly <- g[["feat_info]][[1]] relate(gpoints, gpoly, relation = "intersects") relate(gpoints, gpoly, relation = "intersects", use_names = FALSE) + +selection <- system.file("extdata/viz_interactive_select.csv", + package = "GiottoClass" +) +select_polys <- createGiottoPolygon(data.table::fread(selection)) +res <- relate(g, select_polys, relation = "intersects") +g[,res[y == "polygon1", x]] +g[,res[y == "polygon2", x]] +g[,res[y == "polygon3", x]] }