From 9180edd61ddc405afded4dca671a2dc0c17dac99 Mon Sep 17 00:00:00 2001 From: jiajic <72078254+jiajic@users.noreply.github.com> Date: Thu, 1 Dec 2022 16:04:23 -0500 Subject: [PATCH 001/129] Make polystamp more flexible --- NEWS.md | 9 +++++++++ R/giotto_structures.R | 24 +++++++++++++++++++----- man/polyStamp.Rd | 19 +++++++++++++++++-- 3 files changed, 45 insertions(+), 7 deletions(-) diff --git a/NEWS.md b/NEWS.md index 319f7bdd1..fd6ae233a 100644 --- a/NEWS.md +++ b/NEWS.md @@ -1,3 +1,12 @@ +# TBD RELEASE + +## Changes +- Add `id_col`, `x_col`, `y_col` params to `polyStamp()` to make stamp location input more flexible + + + + + # Giotto Suite 3.1.0 (2202-12-01) diff --git a/R/giotto_structures.R b/R/giotto_structures.R index 1b70f551a..6b39ab1a4 100644 --- a/R/giotto_structures.R +++ b/R/giotto_structures.R @@ -930,11 +930,23 @@ smoothGiottoPolygons = function(gpolygon, #' @param stamp_dt data.table with x and y vertices for a polygon to be stamped. #' Column names are expected to be 'x' and 'y' respectively #' @param spatlocs spatial locations with x and y coordinates where polygons should -#' be stamped. Column names are expected to be 'sdimx' and 'sdimy' respectively. +#' be stamped. Column names are 'cell_ID', 'sdimx' and 'sdimy' by default +#' @param id_col column in spatlocs to use as IDs (default is 'cell_ID') +#' @param x_col column in spatlocs to use as x locations (default is 'sdimx') +#' @param y_col column in spatlocs to use as y locations (default is 'sdimy') +#' @param verbose be verbose #' @return returns a data.table of polygon vertices #' @export polyStamp = function(stamp_dt, - spatlocs) { + spatlocs, + id_col = 'cell_ID', + x_col = 'sdimx', + y_col = 'sdimy', + verbose = TRUE) { + + if(!all(c(id_col, x_col, y_col) %in% colnames(spatlocs))) { + stop(wrap_txt('Not all colnames found in spatlocs')) + } # define polys relative to centroid stamp_centroid = c(x = mean(stamp_dt[['x']]), @@ -946,11 +958,13 @@ polyStamp = function(stamp_dt, poly_dt = apply(X = spatlocs, MARGIN = 1, function(r) { - return(data.table::data.table(x = rel_vertices[['x']] + as.numeric(r[['sdimx']]), - y = rel_vertices[['y']] + as.numeric(r[['sdimy']]), - poly_ID = as.character(r[['cell_ID']]))) + return(data.table::data.table(x = rel_vertices[['x']] + as.numeric(r[[x_col]]), + y = rel_vertices[['y']] + as.numeric(r[[y_col]]), + poly_ID = as.character(r[[id_col]]))) }) + if(isTRUE(verbose)) wrap_msg(nrow(spatlocs), 'polygons stamped') + return(do.call(rbind, poly_dt)) } diff --git a/man/polyStamp.Rd b/man/polyStamp.Rd index 491cd32e4..591862855 100644 --- a/man/polyStamp.Rd +++ b/man/polyStamp.Rd @@ -4,14 +4,29 @@ \alias{polyStamp} \title{Spatial polygons stamp} \usage{ -polyStamp(stamp_dt, spatlocs) +polyStamp( + stamp_dt, + spatlocs, + id_col = "cell_ID", + x_col = "sdimx", + y_col = "sdimy", + verbose = TRUE +) } \arguments{ \item{stamp_dt}{data.table with x and y vertices for a polygon to be stamped. Column names are expected to be 'x' and 'y' respectively} \item{spatlocs}{spatial locations with x and y coordinates where polygons should -be stamped. Column names are expected to be 'sdimx' and 'sdimy' respectively.} +be stamped. Column names are 'cell_ID', 'sdimx' and 'sdimy' by default} + +\item{id_col}{column in spatlocs to use as IDs (default is 'cell_ID')} + +\item{x_col}{column in spatlocs to use as x locations (default is 'sdimx')} + +\item{y_col}{column in spatlocs to use as y locations (default is 'sdimy')} + +\item{verbose}{be verbose} } \value{ returns a data.table of polygon vertices From 17b45d0334f96019dd098f7a0c8f3ae65cc3fcc6 Mon Sep 17 00:00:00 2001 From: jiajic <72078254+jiajic@users.noreply.github.com> Date: Sun, 4 Dec 2022 15:28:33 -0500 Subject: [PATCH 002/129] update spatFeatPlot2D() `spatFeatPlot2D()` add `coor_fix_ratio` param --- NEWS.md | 1 + R/spatial_visuals.R | 5 +++++ 2 files changed, 6 insertions(+) diff --git a/NEWS.md b/NEWS.md index fd6ae233a..0a40841d8 100644 --- a/NEWS.md +++ b/NEWS.md @@ -2,6 +2,7 @@ ## Changes - Add `id_col`, `x_col`, `y_col` params to `polyStamp()` to make stamp location input more flexible +- Add `coord_fix_ratio` param to `spatFeatPlot2D()` and `spatFeatPlot2D_single()` diff --git a/R/spatial_visuals.R b/R/spatial_visuals.R index 10eb94b18..00618751d 100644 --- a/R/spatial_visuals.R +++ b/R/spatial_visuals.R @@ -4207,6 +4207,7 @@ spatFeatPlot2D_single <- function(gobject, point_alpha = 1, point_border_col = 'black', point_border_stroke = 0.1, + coord_fix_ratio = 1, show_legend = T, legend_text = 8, background_color = 'white', @@ -4575,6 +4576,9 @@ spatFeatPlot2D_single <- function(gobject, panel.grid = element_blank(), panel.background = element_rect(fill = background_color)) + if(!is.null(coord_fix_ratio)) { + pl <- pl + ggplot2::coord_fixed(ratio = coord_fix_ratio) + } savelist[[feat]] <- pl } @@ -4692,6 +4696,7 @@ spatFeatPlot2D <- function(gobject, point_alpha = 1, point_border_col = 'black', point_border_stroke = 0.1, + coord_fix_ratio = 1, show_legend = T, legend_text = 8, background_color = 'white', From d06578191cbb0064a97261896624ae6ee36ec7e7 Mon Sep 17 00:00:00 2001 From: josschavezf Date: Mon, 5 Dec 2022 00:47:55 -0500 Subject: [PATCH 003/129] update tests to pass rcmdcheck --- tests/testthat/test_dataImports.R | 12 ++-- tests/testthat/test_giottoInstr.R | 4 +- tests/testthat/test_merFISH.R | 94 +++++++++++++++---------------- 3 files changed, 55 insertions(+), 55 deletions(-) diff --git a/tests/testthat/test_dataImports.R b/tests/testthat/test_dataImports.R index b4c5415d5..d4a2e3090 100644 --- a/tests/testthat/test_dataImports.R +++ b/tests/testthat/test_dataImports.R @@ -5,20 +5,20 @@ if(is.null(python_path)) { ### TESTS FOR DATA IMPORT FUNCTIONS # ------------------------------------ -library(GiottoData) - -# getSpatialDataset -getSpatialDataset(dataset = c("Mouse_brain_scRNAseq"), directory = paste0(getwd(), "/testdata/")) test_that("Spatial dataset was downloaded", { + # getSpatialDataset + GiottoData::getSpatialDataset(dataset = "scRNA_mouse_brain", directory = paste0(getwd(), "/testdata/")) + expect_true(file.exists("./testdata/brain_sc_expression_matrix.txt.gz")) expect_true(file.exists("./testdata/brain_sc_metadata.csv")) }) -# readExprMatrix -expr_mat <- readExprMatrix(paste0(getwd(), "/testdata/brain_sc_expression_matrix.txt.gz")) test_that("Expression matrix is read correctly", { + # readExprMatrix + 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)) diff --git a/tests/testthat/test_giottoInstr.R b/tests/testthat/test_giottoInstr.R index a038054e0..09db7deaf 100644 --- a/tests/testthat/test_giottoInstr.R +++ b/tests/testthat/test_giottoInstr.R @@ -1,9 +1,9 @@ -python_path = NULL +python_path = NULL if(is.null(python_path)) { installGiottoEnvironment() } -getSpatialDataset(dataset = "merfish_preoptic", directory = paste0(getwd(), "/testdata/")) +GiottoData::getSpatialDataset(dataset = "merfish_preoptic", directory = paste0(getwd(), "/testdata/")) expr_path = "./testdata/merFISH_3D_data_expression.txt.gz" loc_path = "./testdata/merFISH_3D_data_cell_locations.txt" diff --git a/tests/testthat/test_merFISH.R b/tests/testthat/test_merFISH.R index 01ff47cb6..aba3b388d 100644 --- a/tests/testthat/test_merFISH.R +++ b/tests/testthat/test_merFISH.R @@ -3,11 +3,11 @@ if(is.null(python_path)) { installGiottoEnvironment() } -getSpatialDataset(dataset = "merfish_preoptic", directory = paste0(getwd(), "/testdata/")) +GiottoData::getSpatialDataset(dataset = 'merfish_preoptic', directory = paste0(getwd(), '/testdata/')) -expr_path = "./testdata/merFISH_3D_data_expression.txt.gz" -loc_path = "./testdata/merFISH_3D_data_cell_locations.txt" -meta_path = "./testdata/merFISH_3D_metadata.txt" +expr_path = './testdata/merFISH_3D_data_expression.txt.gz' +loc_path = './testdata/merFISH_3D_data_cell_locations.txt' +meta_path = './testdata/merFISH_3D_metadata.txt' ### TESTS FOR MERFISH MOUSE HYPOTHALMIC PREOPTIC REGION DATASET # -------------------------------------------------------------- @@ -23,11 +23,11 @@ test_that("Object initialization creates expected Giotto object", { expect_s4_class(object, "giotto") # gobject contains S4 object of class "dgCMatrix" containing raw expression - expect_s4_class(object@expression[["cell"]][["rna"]][["raw"]], "dgCMatrix") - expect_true(all(object@expression[["cell"]][["rna"]][["raw"]]@Dim == c(161, 73655))) + expect_s4_class(slot(object@expression[["cell"]][["rna"]][["raw"]], "exprMat"), "dgCMatrix") + expect_true(all(slot(object@expression[["cell"]][["rna"]][["raw"]], "exprMat")@Dim == c(161, 73655))) # gobject contains S4 object "spatLocsObj" of dimensions 73655 x 4 containing spatial locations - st = get_spatial_locations(test, spat_unit = 'cell', spat_loc_name = 'raw', return_spatlocs_Obj = TRUE) + st = get_spatial_locations(object, spat_unit = 'cell', spat_loc_name = 'raw') expect_identical(st@coordinates, object@spatial_locs[["cell"]][["raw"]]@coordinates) expect_s4_class(object@spatial_locs[["cell"]][["raw"]], "spatLocsObj") expect_length(object@spatial_locs[["cell"]][["raw"]]@coordinates[["sdimx"]], 73655) @@ -48,13 +48,13 @@ test_that("Cell metadata are read and added to Giotto object", { expect_named(metadata, c("orig_cell_types", "layer_ID")) # metadata length matches number of preexisting cell_IDs - expect_equal(nrow(metadata), length(object@cell_metadata[["cell"]][["rna"]][["cell_ID"]])) + expect_equal(nrow(metadata), length(slot(object@cell_metadata[["cell"]][["rna"]], 'metaDT')[["cell_ID"]])) # metadata length/types after added to object - expect_length(object@cell_metadata[["cell"]][["rna"]][["layer_ID"]], 73655) - expect_type(object@cell_metadata[["cell"]][["rna"]][["layer_ID"]], "integer") - expect_length(object@cell_metadata[["cell"]][["rna"]][["orig_cell_types"]], 73655) - expect_type(object@cell_metadata[["cell"]][["rna"]][["orig_cell_types"]], "character") + expect_length(slot(object@cell_metadata[["cell"]][["rna"]], 'metaDT')[["layer_ID"]], 73655) + expect_type(slot(object@cell_metadata[["cell"]][["rna"]], 'metaDT')[["layer_ID"]], "integer") + expect_length(slot(object@cell_metadata[["cell"]][["rna"]], 'metaDT')[["orig_cell_types"]], 73655) + expect_type(slot(object@cell_metadata[["cell"]][["rna"]], 'metaDT')[["orig_cell_types"]], "character") }) @@ -69,7 +69,7 @@ filtered_object <- filterGiotto(gobject = object, test_that("Data in filtered object is expected size", { # filtered object expression values have expected dimensions - expect_true(all(filtered_object@expression[["cell"]][["rna"]][["raw"]]@Dim == c(153, 17814))) + expect_true(all(slot(filtered_object@expression[["cell"]][["rna"]][["raw"]],'exprMat')@Dim == c(153, 17814))) # filtered object spatial locations have expected length expect_length(filtered_object@spatial_locs[["cell"]][["raw"]]@coordinates[["sdimx"]], 17814) @@ -78,8 +78,8 @@ test_that("Data in filtered object is expected size", { expect_length(filtered_object@spatial_locs[["cell"]][["raw"]]@coordinates[["cell_ID"]], 17814) # filtered object metadata has expected length - expect_length(filtered_object@cell_metadata[["cell"]][["rna"]][["layer_ID"]], 17814) - expect_length(filtered_object@cell_metadata[["cell"]][["rna"]][["orig_cell_types"]], 17814) + expect_length(slot(filtered_object@cell_metadata[["cell"]][["rna"]],'metaDT')[["layer_ID"]], 17814) + expect_length(slot(filtered_object@cell_metadata[["cell"]][["rna"]],'metaDT')[["orig_cell_types"]], 17814) }) @@ -89,12 +89,12 @@ object <- normalizeGiotto(gobject = object, scalefactor = 10000, verbose = F) test_that("Normalized data added to giotto object", { # gobject now also contains S4 object of class "dgCMatrix" containing normalized expression - expect_s4_class(object@expression[["cell"]][["rna"]][["normalized"]], "dgCMatrix") - expect_true(all(object@expression[["cell"]][["rna"]][["normalized"]]@Dim == c(161, 73655))) + expect_s4_class(slot(object@expression[["cell"]][["rna"]][["normalized"]], 'exprMat'), "dgCMatrix") + expect_true(all(slot(object@expression[["cell"]][["rna"]][["normalized"]], 'exprMat')@Dim == c(161, 73655))) # gobject now also contains S4 object of class "dgeMatrix" containing scaled expression - expect_s4_class(object@expression[["cell"]][["rna"]][["scaled"]], "dgeMatrix") - expect_true(all(object@expression[["cell"]][["rna"]][["scaled"]]@Dim == c(161, 73655))) + expect_s4_class(slot(object@expression[["cell"]][["rna"]][["scaled"]], 'exprMat'), "dgeMatrix") + expect_true(all(slot(object@expression[["cell"]][["rna"]][["scaled"]], 'exprMat')@Dim == c(161, 73655))) }) @@ -104,24 +104,24 @@ object <- addStatistics(gobject = object) test_that("Feature and cell statistics are added to giotto object", { # gobject cell metadata contains nr_feats, perc_feats, total_expr - expect_length(object@cell_metadata[["cell"]][["rna"]][["nr_feats"]], 73655) - expect_type(object@cell_metadata[["cell"]][["rna"]][["nr_feats"]], "integer") - expect_length(object@cell_metadata[["cell"]][["rna"]][["perc_feats"]], 73655) - expect_type(object@cell_metadata[["cell"]][["rna"]][["perc_feats"]], "double") - expect_length(object@cell_metadata[["cell"]][["rna"]][["total_expr"]], 73655) - expect_type(object@cell_metadata[["cell"]][["rna"]][["total_expr"]], "double") + expect_length(slot(object@cell_metadata[["cell"]][["rna"]], 'metaDT')[["nr_feats"]], 73655) + expect_type(slot(object@cell_metadata[["cell"]][["rna"]], 'metaDT')[["nr_feats"]], "integer") + expect_length(slot(object@cell_metadata[["cell"]][["rna"]], 'metaDT')[["perc_feats"]], 73655) + expect_type(slot(object@cell_metadata[["cell"]][["rna"]], 'metaDT')[["perc_feats"]], "double") + expect_length(slot(object@cell_metadata[["cell"]][["rna"]], 'metaDT')[["total_expr"]], 73655) + expect_type(slot(object@cell_metadata[["cell"]][["rna"]], 'metaDT')[["total_expr"]], "double") # gobject feat metadata contains nr_cells, perc_cells, total_expr, mean_expr, mean_expr_det - expect_length(object@feat_metadata[["cell"]][["rna"]][["nr_cells"]], 161) - expect_type(object@feat_metadata[["cell"]][["rna"]][["nr_cells"]], "integer") - expect_length(object@feat_metadata[["cell"]][["rna"]][["perc_cells"]], 161) - expect_type(object@feat_metadata[["cell"]][["rna"]][["perc_cells"]], "double") - expect_length(object@feat_metadata[["cell"]][["rna"]][["total_expr"]], 161) - expect_type(object@feat_metadata[["cell"]][["rna"]][["total_expr"]], "double") - expect_length(object@feat_metadata[["cell"]][["rna"]][["mean_expr"]], 161) - expect_type(object@feat_metadata[["cell"]][["rna"]][["mean_expr"]], "double") - expect_length(object@feat_metadata[["cell"]][["rna"]][["mean_expr_det"]], 161) - expect_type(object@feat_metadata[["cell"]][["rna"]][["mean_expr_det"]], "double") + expect_length(slot(object@feat_metadata[["cell"]][["rna"]], 'metaDT')[["nr_cells"]], 161) + expect_type(slot(object@feat_metadata[["cell"]][["rna"]], 'metaDT')[["nr_cells"]], "integer") + expect_length(slot(object@feat_metadata[["cell"]][["rna"]], 'metaDT')[["perc_cells"]], 161) + expect_type(slot(object@feat_metadata[["cell"]][["rna"]], 'metaDT')[["perc_cells"]], "double") + expect_length(slot(object@feat_metadata[["cell"]][["rna"]], 'metaDT')[["total_expr"]], 161) + expect_type(slot(object@feat_metadata[["cell"]][["rna"]], 'metaDT')[["total_expr"]], "double") + expect_length(slot(object@feat_metadata[["cell"]][["rna"]], 'metaDT')[["mean_expr"]], 161) + expect_type(slot(object@feat_metadata[["cell"]][["rna"]], 'metaDT')[["mean_expr"]], "double") + expect_length(slot(object@feat_metadata[["cell"]][["rna"]], 'metaDT')[["mean_expr_det"]], 161) + expect_type(slot(object@feat_metadata[["cell"]][["rna"]], 'metaDT')[["mean_expr_det"]], "double") }) @@ -134,9 +134,9 @@ object <- adjustGiottoMatrix(gobject = object, expression_values = c('normalized test_that("Adjusted values are created in 'custom' slot", { # expression now also contains custom object of class double - expect_type(object@expression[["cell"]][["rna"]][["custom"]], "double") - expect_equal(nrow(object@expression[["cell"]][["rna"]][["custom"]]), 161) - expect_equal(ncol(object@expression[["cell"]][["rna"]][["custom"]]), 73655) + expect_type(slot(object@expression[["cell"]][["rna"]][["custom"]], 'exprMat'), "double") + expect_equal(nrow(slot(object@expression[["cell"]][["rna"]][["custom"]], 'exprMat')), 161) + expect_equal(ncol(slot(object@expression[["cell"]][["rna"]][["custom"]], 'exprMat')), 73655) }) @@ -194,7 +194,7 @@ object <- createNearestNetwork(gobject = object, dimensions_to_use = 1:8, k = 15 test_that("sNN S3 object is created as expected", { # igraph s3 object - expect_s3_class(object@nn_network[["cell"]][["rna"]][["sNN"]][["sNN.pca"]], "igraph") + expect_s3_class(slot(object@nn_network[["cell"]][["rna"]][["sNN"]][["sNN.pca"]], 'igraph'), "igraph") }) @@ -204,11 +204,11 @@ object <- doLeidenCluster(gobject = object, resolution = 0.2, n_iterations = 200 test_that("New clusters are added to cell metadata", { - expect_length(object@cell_metadata[["cell"]][["rna"]][["leiden_0.2"]], 73655) + expect_length(slot(object@cell_metadata[["cell"]][["rna"]], 'metaDT')[["leiden_0.2"]], 73655) # test a few cluster assignments - expect_equal(object@cell_metadata[["cell"]][["rna"]][["leiden_0.2"]][10], 5) - expect_equal(object@cell_metadata[["cell"]][["rna"]][["leiden_0.2"]][80], 4) + expect_equal(slot(object@cell_metadata[["cell"]][["rna"]], 'metaDT')[["leiden_0.2"]][10], 5) + expect_equal(slot(object@cell_metadata[["cell"]][["rna"]], 'metaDT')[["leiden_0.2"]][80], 4) }) @@ -228,7 +228,7 @@ test_that("Cell type markers are detected", { "detection_rank", "comb_score", "comb_rank")) # number of markers - expect_equal(nrow(markers), 584) + expect_equal(nrow(markers), 585) }) @@ -249,12 +249,12 @@ object = annotateGiotto(gobject = object, annotation_vector = clusters_cell_type test_that("Cell type annotations are added to cell metadata", { - expect_type(object@cell_metadata[["cell"]][["rna"]][["cell_types"]], "character") - expect_length(object@cell_metadata[["cell"]][["rna"]][["cell_types"]], 73655) + expect_type(slot(object@cell_metadata[["cell"]][["rna"]], 'metaDT')[["cell_types"]], "character") + expect_length(slot(object@cell_metadata[["cell"]][["rna"]], 'metaDT')[["cell_types"]], 73655) # check a few annotations - expect_equal(object@cell_metadata[["cell"]][["rna"]][["cell_types"]][5], "Inhibitory") - expect_equal(object@cell_metadata[["cell"]][["rna"]][["cell_types"]][250], "OD Immature") + expect_equal(slot(object@cell_metadata[["cell"]][["rna"]], 'metaDT')[["cell_types"]][5], "Inhibitory") + expect_equal(slot(object@cell_metadata[["cell"]][["rna"]], 'metaDT')[["cell_types"]][250], "OD Immature") }) From 1cf6803b1a84a85b21a9235d7bcf4117f2ab66b6 Mon Sep 17 00:00:00 2001 From: josschavezf Date: Mon, 5 Dec 2022 00:48:38 -0500 Subject: [PATCH 004/129] add accessor functions set_multiomics and get_multiomics --- NAMESPACE | 2 + R/wnn.R | 241 +++++++++++++++++++++++++++++++----------- man/get_multiomics.Rd | 49 +++++++++ man/set_multiomics.Rd | 61 +++++++++++ 4 files changed, 289 insertions(+), 64 deletions(-) create mode 100644 man/get_multiomics.Rd create mode 100644 man/set_multiomics.Rd diff --git a/NAMESPACE b/NAMESPACE index 4e1cd1585..ad5be90dc 100644 --- a/NAMESPACE +++ b/NAMESPACE @@ -176,6 +176,7 @@ export(get_dimReduction) export(get_expression_values) export(get_feature_info) export(get_giottoImage) +export(get_multiomics) export(get_polygon_info) export(get_spatialGrid) export(get_spatialNetwork) @@ -287,6 +288,7 @@ export(set_dimReduction) export(set_expression_values) export(set_feature_info) export(set_giottoImage) +export(set_multiomics) export(set_polygon_info) export(set_spatialGrid) export(set_spatialNetwork) diff --git a/R/wnn.R b/R/wnn.R index f65e5589b..f45edd894 100644 --- a/R/wnn.R +++ b/R/wnn.R @@ -5,16 +5,26 @@ #' @param spat_unit spatial unit #' @param modality_1 modality 1 name. Default = "rna" #' @param modality_2 modality 2 name. Default = "protein" +#' @param pca_name_modality_1 Default = 'rna.pca' +#' @param pca_name_modality_2 Default = 'protein.pca' +#' @param integrated_feat_type integrated feature type (e.g. 'rna_protein') +#' @param matrix_result_name Default = 'theta_weighted_matrix' +#' @param w_name_modality_1 name for modality 1 weights +#' @param w_name_modality_2 name for modality 2 weights #' #' @return A Giotto object with integrated UMAP (integrated.umap) within the dimension_reduction slot and Leiden clusters (integrated_leiden_clus) in the cellular metadata. #' @export runWNN <- function(gobject, - spat_unit = "cell", - modality_1 = "rna", - modality_2 = "protein", - pca_name_modality_1 = "rna.pca", - pca_name_modality_2 = "protein.pca", - k = 20) { + spat_unit = 'cell', + modality_1 = 'rna', + modality_2 = 'protein', + pca_name_modality_1 = 'rna.pca', + pca_name_modality_2 = 'protein.pca', + k = 20, + integrated_feat_type = NULL, + matrix_result_name = NULL, + w_name_modality_1 = NULL, + w_name_modality_2 = NULL) { # validate Giotto object if (!inherits(gobject, "giotto")) { @@ -33,13 +43,7 @@ runWNN <- function(gobject, spat_unit = spat_unit, feat_type = modality_1, nn_network_to_use = "kNN") - #kNN_1 <- gobject@nn_network$cell$modality1$kNN$modality1_kNN.pca - # pca_1 <- get_dimReduction(gobject, - # spat_unit = "cell", - # feat_type = modality_1, - # reduction = "cells", - # reduction_method = "pca", - # name = "pca") + pca_1 <- get_dimReduction(gobject, spat_unit = spat_unit, feat_type = modality_1, @@ -52,13 +56,7 @@ runWNN <- function(gobject, spat_unit = spat_unit, feat_type = modality_2, nn_network_to_use = "kNN") - #kNN_2 <- gobject@nn_network$cell$modality2$kNN$modality2_kNN.pca - # pca_2 <- get_dimReduction(gobject, - # spat_unit = "cell", - # feat_type = modality_2, - # reduction = "cells", - # reduction_method = "pca", - # name = "modality2.pca") + pca_2 <- get_dimReduction(gobject, spat_unit = "cell", feat_type = modality_2, @@ -400,48 +398,44 @@ runWNN <- function(gobject, } # save theta_weighted - dimObject <- Giotto:::create_dimObject(name = "theta_weighted", - spat_unit = "cell", - feat_type = "WNN", - reduction_method = "umap", - coordinates = theta_weighted) - gobject <- set_dimReduction(gobject = gobject, - spat_unit = spat_unit, - feat_type = "WNN", - reduction = "cell", - reduction_method = "umap", - name = "theta_weighted", - dimObject = dimObject) + + ## set integrated feat_type and result name if not provided + if(is.null(integrated_feat_type)) {integrated_feat_type = paste0(modality_1,'_',modality_2)} + + if(is.null(matrix_result_name)) {matrix_result_name = 'theta_weighted_matrix'} + + gobject <- set_multiomics(gobject = gobject, + result = theta_weighted, + spat_unit = spat_unit, + feat_type = integrated_feat_type, + integration_method = 'WNN', + result_name = matrix_result_name, + verbose = TRUE) + # save modalities weight ## modality 1 - # dimObject <- Giotto:::create_dimObject(name = paste0("weight_",modality_1), - # spat_unit = "cell", - # feat_type = "WNN", - # reduction_method = "umap", - # coordinates = w_modality1) - # gobject <- set_dimReduction(gobject = gobject, - # spat_unit = spat_unit, - # feat_type = "WNN", - # reduction_method = "umap", - # name = paste0("weight_",modality_1), - # dimObject = dimObject) - # - # ## modality 2 - # dimObject <- Giotto:::create_dimObject(name = paste0("weight_",modality_2), - # spat_unit = "cell", - # feat_type = "WNN", - # reduction_method = "umap", - # coordinates = w_modality2) - # gobject <- set_dimReduction(gobject = gobject, - # spat_unit = spat_unit, - # feat_type = "WNN", - # reduction_method = "umap", - # name = paste0("weight_",modality_2), - # dimObject = dimObject) - - #gobject@dimension_reduction$cells$cell[['WNN']][['theta_weighted']] <- theta_weighted + if(is.null(w_name_modality_1)) {w_name_modality_1 = paste0('w_',modality_1)} + + gobject <- set_multiomics(gobject = gobject, + result = w_modality1, + spat_unit = spat_unit, + feat_type = integrated_feat_type, + integration_method = 'WNN', + result_name = w_name_modality_1, + verbose = TRUE) + + ## modality 2 + if(is.null(w_name_modality_2)) {w_name_modality_2 = paste0('w_',modality_2)} + + gobject <- set_multiomics(gobject = gobject, + result = w_modality2, + spat_unit = spat_unit, + feat_type = integrated_feat_type, + integration_method = 'WNN', + result_name = w_name_modality_2, + verbose = TRUE) return(gobject) } @@ -456,6 +450,9 @@ runWNN <- function(gobject, #' @param k k number #' @param spread UMAP param: spread #' @param min_dist UMAP param: min_dist +#' @param integrated_feat_type integrated feature type (e.g. 'rna_protein') +#' @param integration_method multiomics integration method used. Default = 'WNN' +#' @param matrix_result_name Default = 'theta_weighted_matrix' #' @param ... additional UMAP parameters #' #' @return A Giotto object with integrated UMAP @@ -464,6 +461,9 @@ runIntegratedUMAP <- function(gobject, spat_unit = "cell", modality1 = "rna", modality2 = "protein", + integrated_feat_type = NULL, + integration_method = 'WNN', + matrix_result_name = 'theta_weighted_matrix', k = 20, spread = 5, min_dist = 0.01, @@ -471,12 +471,13 @@ runIntegratedUMAP <- function(gobject, ################# Calculate integrated Nearest Neighbors ####################### - theta_weighted <- get_dimReduction(gobject = gobject, - spat_unit = spat_unit, - feat_type = "WNN", - reduction_method = "umap", - name = "theta_weighted", - ) + if(is.null(integrated_feat_type)) {integrated_feat_type = paste0(modality1,'_',modality2)} + + theta_weighted <- get_multiomics(gobject, + spat_unit = spat_unit, + feat_type = integrated_feat_type, + integration_method = integration_method, + result_name = matrix_result_name) #theta_weighted <- gobject@dimension_reduction$cells$cell$WNN$theta_weighted theta_weighted[is.na(theta_weighted)] <- 0 @@ -537,3 +538,115 @@ runIntegratedUMAP <- function(gobject, return(gobject) } + + +#' @title Set multiomics integration results +#' @name set_multiomics +#' @description Set a multiomics integration result in a Giotto object +#' +#' @param gobject A Giotto object +#' @param spat_unit spatial unit (e.g. 'cell') +#' @param feat_type (e.g. 'rna_protein') +#' @param result A matrix or result from multiomics integration (e.g. theta weighted values from runWNN) +#' @param integration_method multiomics integration method used. Default = 'WNN' +#' @param result_name Default = 'theta_weighted_matrix' +#' @param verbose be verbose +#' +#' @return A giotto object +#' @family multiomics accessor functions +#' @family functions to set data in giotto object +#' @export +set_multiomics = function(gobject, + result, + spat_unit = NULL, + feat_type = NULL, + integration_method = 'WNN', + result_name = 'theta_weighted_matrix', + verbose = TRUE) { + + # 1. determine user input + nospec_unit = ifelse(is.null(spat_unit), yes = TRUE, no = FALSE) + nospec_feat = ifelse(is.null(feat_type), yes = TRUE, no = FALSE) + + # 2. Set feat_type and spat_unit + spat_unit = set_default_spat_unit(gobject = gobject, + spat_unit = spat_unit) + feat_type = set_default_feat_type(gobject = gobject, + spat_unit = spat_unit, + feat_type = feat_type) + + # 3. If input is null, remove object + if(is.null(result)) { + if(isTRUE(verbose)) message('NULL passed to result\n Removing specified result') + gobject@multiomics[[spat_unit]][[feat_type]][[integration_method]][[result_name]] = result + return(gobject) + } + + ## 4. check if specified name has already been used + potential_names = names(slot(gobject, 'multiomics')[[spat_unit]][[integration_method]][[feat_type]]) + + if(result_name %in% potential_names) { + if(isTRUE(verbose)) wrap_msg('> "',result_name, '" already exists and will be replaced with new result') + } + + ## 5. update and return giotto object + gobject@multiomics[[spat_unit]][[feat_type]][[integration_method]][[result_name]] = result + return(gobject) + +} + +#' @title Get multiomics integration results +#' @name get_multiomics +#' @description Get a multiomics integration result from a Giotto object +#' +#' @param gobject A Giotto object +#' @param spat_unit spatial unit (e.g. 'cell') +#' @param feat_type integrated feature type (e.g. 'rna_protein') +#' @param integration_method multiomics integration method used. Default = 'WNN' +#' @param result_name Default = 'theta_weighted_matrix' +#' +#' @return A multiomics integration result (e.g. theta_weighted_matrix from WNN) +#' @family multiomics accessor functions +#' @family functions to get data from giotto object +#' @export +get_multiomics = function(gobject, + spat_unit = NULL, + feat_type = NULL, + integration_method = 'WNN', + result_name = 'theta_weighted_matrix') { + + # 1. Set feat_type and spat_unit + + spat_unit = set_default_spat_unit(gobject = gobject, + spat_unit = spat_unit) + feat_type = set_default_feat_type(gobject = gobject, + spat_unit = spat_unit, + feat_type = feat_type) + + # 2 Find the object + + # automatic result selection + if(is.null(result_name)) { + result_to_use = names(gobject@multiomics[[spat_unit]][[integration_method]][[feat_type]])[[1]] + if(is.null(result_to_use)) { + + stop('There is currently no multiomics integration created for + spatial unit: "', spat_unit, '" and feature type "', feat_type, '". + First run runWNN() or other multiomics integration method\n') + } else { + message('The result name was not specified, default to the first: "', result_to_use,'"') + } + } + + # 3. get object + + result = gobject@multiomics[[spat_unit]][[feat_type]][[integration_method]][[result_name]] + if(is.null(result)) { + stop('result: "', result_to_use, '" does not exist. Create a multiomics integration first') + } + + # return WNN_result + return(result) + +} + diff --git a/man/get_multiomics.Rd b/man/get_multiomics.Rd new file mode 100644 index 000000000..b2ea389b5 --- /dev/null +++ b/man/get_multiomics.Rd @@ -0,0 +1,49 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/wnn.R +\name{get_multiomics} +\alias{get_multiomics} +\title{Get multiomics integration results} +\usage{ +get_multiomics( + gobject, + spat_unit = NULL, + feat_type = NULL, + integration_method = "WNN", + result_name = "theta_weighted_matrix" +) +} +\arguments{ +\item{gobject}{A Giotto object} + +\item{spat_unit}{spatial unit (e.g. 'cell')} + +\item{feat_type}{integrated feature type (e.g. 'rna_protein')} + +\item{integration_method}{multiomics integration method used. Default = 'WNN'} + +\item{result_name}{Default = 'theta_weighted_matrix'} +} +\value{ +A multiomics integration result (e.g. theta_weighted_matrix from WNN) +} +\description{ +Get a multiomics integration result from a Giotto object +} +\seealso{ +Other multiomics accessor functions: +\code{\link{set_multiomics}()} + +Other functions to get data from giotto object: +\code{\link{get_NearestNetwork}()}, +\code{\link{get_dimReduction}()}, +\code{\link{get_expression_values}()}, +\code{\link{get_feature_info}()}, +\code{\link{get_giottoImage}()}, +\code{\link{get_polygon_info}()}, +\code{\link{get_spatialGrid}()}, +\code{\link{get_spatialNetwork}()}, +\code{\link{get_spatial_enrichment}()}, +\code{\link{get_spatial_locations}()} +} +\concept{functions to get data from giotto object} +\concept{multiomics accessor functions} diff --git a/man/set_multiomics.Rd b/man/set_multiomics.Rd new file mode 100644 index 000000000..a4a65bb24 --- /dev/null +++ b/man/set_multiomics.Rd @@ -0,0 +1,61 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/wnn.R +\name{set_multiomics} +\alias{set_multiomics} +\title{Set multiomics integration results} +\usage{ +set_multiomics( + gobject, + result, + spat_unit = NULL, + feat_type = NULL, + integration_method = "WNN", + result_name = "theta_weighted_matrix", + verbose = TRUE +) +} +\arguments{ +\item{gobject}{A Giotto object} + +\item{result}{A matrix or result from multiomics integration (e.g. theta weighted values from runWNN)} + +\item{spat_unit}{spatial unit (e.g. 'cell')} + +\item{feat_type}{(e.g. 'rna_protein')} + +\item{integration_method}{multiomics integration method used. Default = 'WNN'} + +\item{result_name}{Default = 'theta_weighted_matrix'} + +\item{verbose}{be verbose} +} +\value{ +A giotto object +} +\description{ +Set a multiomics integration result in a Giotto object +} +\seealso{ +Other multiomics accessor functions: +\code{\link{get_multiomics}()} + +Other functions to set data in giotto object: +\code{\link{get_cell_id}()}, +\code{\link{get_feat_id}()}, +\code{\link{set_NearestNetwork}()}, +\code{\link{set_cell_id}()}, +\code{\link{set_cell_metadata}()}, +\code{\link{set_dimReduction}()}, +\code{\link{set_expression_values}()}, +\code{\link{set_feat_id}()}, +\code{\link{set_feature_info}()}, +\code{\link{set_feature_metadata}()}, +\code{\link{set_giottoImage}()}, +\code{\link{set_polygon_info}()}, +\code{\link{set_spatialGrid}()}, +\code{\link{set_spatialNetwork}()}, +\code{\link{set_spatial_enrichment}()}, +\code{\link{set_spatial_locations}()} +} +\concept{functions to set data in giotto object} +\concept{multiomics accessor functions} From bd436295161da4d87237ed5b854ba237d3f5acc2 Mon Sep 17 00:00:00 2001 From: josschavezf Date: Mon, 5 Dec 2022 00:48:56 -0500 Subject: [PATCH 005/129] update documentation --- R/auxiliary_giotto.R | 2 +- R/classes.R | 17 ++++++++++------- man/get_NearestNetwork.Rd | 1 + man/get_cell_id.Rd | 1 + man/get_dimReduction.Rd | 1 + man/get_expression_values.Rd | 1 + man/get_feat_id.Rd | 1 + man/get_feature_info.Rd | 1 + man/get_giottoImage.Rd | 1 + man/get_polygon_info.Rd | 1 + man/get_spatialGrid.Rd | 1 + man/get_spatialNetwork.Rd | 1 + man/get_spatial_enrichment.Rd | 1 + man/get_spatial_locations.Rd | 1 + man/giotto-class.Rd | 2 ++ man/runIntegratedUMAP.Rd | 9 +++++++++ man/runWNN.Rd | 18 +++++++++++++++++- man/set_NearestNetwork.Rd | 1 + man/set_cell_id.Rd | 1 + man/set_cell_metadata.Rd | 1 + man/set_dimReduction.Rd | 1 + man/set_expression_values.Rd | 1 + man/set_feat_id.Rd | 1 + man/set_feature_info.Rd | 1 + man/set_feature_metadata.Rd | 1 + man/set_giottoImage.Rd | 1 + man/set_polygon_info.Rd | 1 + man/set_spatialGrid.Rd | 1 + man/set_spatialNetwork.Rd | 1 + man/set_spatial_enrichment.Rd | 1 + man/set_spatial_locations.Rd | 1 + man/spatFeatPlot2D.Rd | 1 + man/spatFeatPlot2D_single.Rd | 1 + 33 files changed, 67 insertions(+), 9 deletions(-) diff --git a/R/auxiliary_giotto.R b/R/auxiliary_giotto.R index 3f84de630..49093a307 100644 --- a/R/auxiliary_giotto.R +++ b/R/auxiliary_giotto.R @@ -2793,7 +2793,7 @@ combine_matrices = function(mat_list, stop('Matrix needs to be a base or sparse matrix from the Matrix package') } - if(inherits(mat, 'matrix')) mat = as(mat, 'dgCMatrix') + if(inherits(mat, 'matrix')) mat = methods::as(mat, 'dgCMatrix') mat_feats = mat@Dimnames[[1]] names(mat_feats) = 1:mat@Dim[[1]] diff --git a/R/classes.R b/R/classes.R index 060d14774..9610412c0 100644 --- a/R/classes.R +++ b/R/classes.R @@ -55,7 +55,7 @@ setClass('coordDataDT', setMethod('initialize', 'coordDataDT', function(.Object, ...) { - .Object = callNextMethod() + .Object = methods::callNextMethod() # prepare DT for set by reference .Object@coordinates = data.table::setalloccol(.Object@coordinates) .Object @@ -81,7 +81,7 @@ setClass('metaData', setMethod('initialize', 'metaData', function(.Object, ...) { - .Object = callNextMethod() + .Object = methods::callNextMethod() # prepare DT for set by reference .Object@metaDT = data.table::setalloccol(.Object@metaDT) .Object @@ -97,7 +97,7 @@ setClass('enrData', setMethod('initialize', 'enrData', function(.Object, ...) { - .Object = callNextMethod() + .Object = methods::callNextMethod() # prepare DT for set by reference .Object@enrichDT = data.table::setalloccol(.Object@enrichDT) .Object @@ -130,7 +130,7 @@ setClass('spatNetData', setMethod('initialize', 'spatNetData', function(.Object, ...) { - .Object = callNextMethod() + .Object = methods::callNextMethod() # prepare DT for set by reference .Object@networkDT = data.table::setalloccol(.Object@networkDT) if(!is.null(.Object@networkDT_before_filter)) { @@ -152,7 +152,7 @@ setClass('spatGridData', setMethod('initialize', 'spatGridData', function(.Object, ...) { - .Object = callNextMethod() + .Object = methods::callNextMethod() # prepare DT for set by reference .Object@gridDT = data.table::setalloccol(.Object@gridDT) .Object @@ -378,6 +378,7 @@ setClass('spatFeatData', #' @slot offset_file offset file used to stitch together image fields #' @slot OS_platform Operating System to run Giotto analysis on #' @slot join_info information about joined Giotto objects +#' @slot multiomics multiomics integration results #' @details #' [\strong{expression}] There are several ways to provide expression information: #' @@ -409,7 +410,8 @@ giotto <- setClass( instructions = "ANY", offset_file = "ANY", OS_platform = "ANY", - join_info = "ANY" + join_info = "ANY", + multiomics = "ANY" ), @@ -434,7 +436,8 @@ giotto <- setClass( instructions = NULL, offset_file = NULL, OS_platform = NULL, - join_info = NULL + join_info = NULL, + multiomics = NULL ) ) diff --git a/man/get_NearestNetwork.Rd b/man/get_NearestNetwork.Rd index 13d7dacf7..ac80ed83d 100644 --- a/man/get_NearestNetwork.Rd +++ b/man/get_NearestNetwork.Rd @@ -45,6 +45,7 @@ Other functions to get data from giotto object: \code{\link{get_expression_values}()}, \code{\link{get_feature_info}()}, \code{\link{get_giottoImage}()}, +\code{\link{get_multiomics}()}, \code{\link{get_polygon_info}()}, \code{\link{get_spatialGrid}()}, \code{\link{get_spatialNetwork}()}, diff --git a/man/get_cell_id.Rd b/man/get_cell_id.Rd index 08f3c7385..8a89dc8ca 100644 --- a/man/get_cell_id.Rd +++ b/man/get_cell_id.Rd @@ -37,6 +37,7 @@ Other functions to set data in giotto object: \code{\link{set_feature_info}()}, \code{\link{set_feature_metadata}()}, \code{\link{set_giottoImage}()}, +\code{\link{set_multiomics}()}, \code{\link{set_polygon_info}()}, \code{\link{set_spatialGrid}()}, \code{\link{set_spatialNetwork}()}, diff --git a/man/get_dimReduction.Rd b/man/get_dimReduction.Rd index 199fba90e..3349c4be6 100644 --- a/man/get_dimReduction.Rd +++ b/man/get_dimReduction.Rd @@ -49,6 +49,7 @@ Other functions to get data from giotto object: \code{\link{get_expression_values}()}, \code{\link{get_feature_info}()}, \code{\link{get_giottoImage}()}, +\code{\link{get_multiomics}()}, \code{\link{get_polygon_info}()}, \code{\link{get_spatialGrid}()}, \code{\link{get_spatialNetwork}()}, diff --git a/man/get_expression_values.Rd b/man/get_expression_values.Rd index c3ef2b60c..f99ec308e 100644 --- a/man/get_expression_values.Rd +++ b/man/get_expression_values.Rd @@ -44,6 +44,7 @@ Other functions to get data from giotto object: \code{\link{get_dimReduction}()}, \code{\link{get_feature_info}()}, \code{\link{get_giottoImage}()}, +\code{\link{get_multiomics}()}, \code{\link{get_polygon_info}()}, \code{\link{get_spatialGrid}()}, \code{\link{get_spatialNetwork}()}, diff --git a/man/get_feat_id.Rd b/man/get_feat_id.Rd index 1d66e0d2d..06f8cb180 100644 --- a/man/get_feat_id.Rd +++ b/man/get_feat_id.Rd @@ -34,6 +34,7 @@ Other functions to set data in giotto object: \code{\link{set_feature_info}()}, \code{\link{set_feature_metadata}()}, \code{\link{set_giottoImage}()}, +\code{\link{set_multiomics}()}, \code{\link{set_polygon_info}()}, \code{\link{set_spatialGrid}()}, \code{\link{set_spatialNetwork}()}, diff --git a/man/get_feature_info.Rd b/man/get_feature_info.Rd index 7df8ae080..e40d85e8a 100644 --- a/man/get_feature_info.Rd +++ b/man/get_feature_info.Rd @@ -26,6 +26,7 @@ Other functions to get data from giotto object: \code{\link{get_dimReduction}()}, \code{\link{get_expression_values}()}, \code{\link{get_giottoImage}()}, +\code{\link{get_multiomics}()}, \code{\link{get_polygon_info}()}, \code{\link{get_spatialGrid}()}, \code{\link{get_spatialNetwork}()}, diff --git a/man/get_giottoImage.Rd b/man/get_giottoImage.Rd index 6a18b1229..c246355ed 100644 --- a/man/get_giottoImage.Rd +++ b/man/get_giottoImage.Rd @@ -32,6 +32,7 @@ Other functions to get data from giotto object: \code{\link{get_dimReduction}()}, \code{\link{get_expression_values}()}, \code{\link{get_feature_info}()}, +\code{\link{get_multiomics}()}, \code{\link{get_polygon_info}()}, \code{\link{get_spatialGrid}()}, \code{\link{get_spatialNetwork}()}, diff --git a/man/get_polygon_info.Rd b/man/get_polygon_info.Rd index ef8b491b9..50275afaf 100644 --- a/man/get_polygon_info.Rd +++ b/man/get_polygon_info.Rd @@ -33,6 +33,7 @@ Other functions to get data from giotto object: \code{\link{get_expression_values}()}, \code{\link{get_feature_info}()}, \code{\link{get_giottoImage}()}, +\code{\link{get_multiomics}()}, \code{\link{get_spatialGrid}()}, \code{\link{get_spatialNetwork}()}, \code{\link{get_spatial_enrichment}()}, diff --git a/man/get_spatialGrid.Rd b/man/get_spatialGrid.Rd index 62b4b8764..8fa404663 100644 --- a/man/get_spatialGrid.Rd +++ b/man/get_spatialGrid.Rd @@ -40,6 +40,7 @@ Other functions to get data from giotto object: \code{\link{get_expression_values}()}, \code{\link{get_feature_info}()}, \code{\link{get_giottoImage}()}, +\code{\link{get_multiomics}()}, \code{\link{get_polygon_info}()}, \code{\link{get_spatialNetwork}()}, \code{\link{get_spatial_enrichment}()}, diff --git a/man/get_spatialNetwork.Rd b/man/get_spatialNetwork.Rd index adef953e6..43d2ce076 100644 --- a/man/get_spatialNetwork.Rd +++ b/man/get_spatialNetwork.Rd @@ -38,6 +38,7 @@ Other functions to get data from giotto object: \code{\link{get_expression_values}()}, \code{\link{get_feature_info}()}, \code{\link{get_giottoImage}()}, +\code{\link{get_multiomics}()}, \code{\link{get_polygon_info}()}, \code{\link{get_spatialGrid}()}, \code{\link{get_spatial_enrichment}()}, diff --git a/man/get_spatial_enrichment.Rd b/man/get_spatial_enrichment.Rd index 17e92bba4..e09eb6097 100644 --- a/man/get_spatial_enrichment.Rd +++ b/man/get_spatial_enrichment.Rd @@ -44,6 +44,7 @@ Other functions to get data from giotto object: \code{\link{get_expression_values}()}, \code{\link{get_feature_info}()}, \code{\link{get_giottoImage}()}, +\code{\link{get_multiomics}()}, \code{\link{get_polygon_info}()}, \code{\link{get_spatialGrid}()}, \code{\link{get_spatialNetwork}()}, diff --git a/man/get_spatial_locations.Rd b/man/get_spatial_locations.Rd index a4670f3d2..a52887126 100644 --- a/man/get_spatial_locations.Rd +++ b/man/get_spatial_locations.Rd @@ -47,6 +47,7 @@ Other functions to get data from giotto object: \code{\link{get_expression_values}()}, \code{\link{get_feature_info}()}, \code{\link{get_giottoImage}()}, +\code{\link{get_multiomics}()}, \code{\link{get_polygon_info}()}, \code{\link{get_spatialGrid}()}, \code{\link{get_spatialNetwork}()}, diff --git a/man/giotto-class.Rd b/man/giotto-class.Rd index 9df2274c9..926c19a15 100644 --- a/man/giotto-class.Rd +++ b/man/giotto-class.Rd @@ -58,6 +58,8 @@ that are provided in the expression slot. \item{\code{OS_platform}}{Operating System to run Giotto analysis on} \item{\code{join_info}}{information about joined Giotto objects} + +\item{\code{multiomics}}{multiomics integration results} }} \concept{giotto object} diff --git a/man/runIntegratedUMAP.Rd b/man/runIntegratedUMAP.Rd index a1db88e67..af6365d46 100644 --- a/man/runIntegratedUMAP.Rd +++ b/man/runIntegratedUMAP.Rd @@ -9,6 +9,9 @@ runIntegratedUMAP( spat_unit = "cell", modality1 = "rna", modality2 = "protein", + integrated_feat_type = NULL, + integration_method = "WNN", + matrix_result_name = "theta_weighted_matrix", k = 20, spread = 5, min_dist = 0.01, @@ -24,6 +27,12 @@ runIntegratedUMAP( \item{modality2}{modality 2 name. Default = "protein"} +\item{integrated_feat_type}{integrated feature type (e.g. 'rna_protein')} + +\item{integration_method}{multiomics integration method used. Default = 'WNN'} + +\item{matrix_result_name}{Default = 'theta_weighted_matrix'} + \item{k}{k number} \item{spread}{UMAP param: spread} diff --git a/man/runWNN.Rd b/man/runWNN.Rd index 181e2f101..d66d96653 100644 --- a/man/runWNN.Rd +++ b/man/runWNN.Rd @@ -11,7 +11,11 @@ runWNN( modality_2 = "protein", pca_name_modality_1 = "rna.pca", pca_name_modality_2 = "protein.pca", - k = 20 + k = 20, + integrated_feat_type = NULL, + matrix_result_name = NULL, + w_name_modality_1 = NULL, + w_name_modality_2 = NULL ) } \arguments{ @@ -23,7 +27,19 @@ runWNN( \item{modality_2}{modality 2 name. Default = "protein"} +\item{pca_name_modality_1}{Default = 'rna.pca'} + +\item{pca_name_modality_2}{Default = 'protein.pca'} + \item{k}{k number, default = 20} + +\item{integrated_feat_type}{integrated feature type (e.g. 'rna_protein')} + +\item{matrix_result_name}{Default = 'theta_weighted_matrix'} + +\item{w_name_modality_1}{name for modality 1 weights} + +\item{w_name_modality_2}{name for modality 2 weights} } \value{ A Giotto object with integrated UMAP (integrated.umap) within the dimension_reduction slot and Leiden clusters (integrated_leiden_clus) in the cellular metadata. diff --git a/man/set_NearestNetwork.Rd b/man/set_NearestNetwork.Rd index 200afd7de..8d1bb1e20 100644 --- a/man/set_NearestNetwork.Rd +++ b/man/set_NearestNetwork.Rd @@ -58,6 +58,7 @@ Other functions to set data in giotto object: \code{\link{set_feature_info}()}, \code{\link{set_feature_metadata}()}, \code{\link{set_giottoImage}()}, +\code{\link{set_multiomics}()}, \code{\link{set_polygon_info}()}, \code{\link{set_spatialGrid}()}, \code{\link{set_spatialNetwork}()}, diff --git a/man/set_cell_id.Rd b/man/set_cell_id.Rd index b93890e85..190c7d0f0 100644 --- a/man/set_cell_id.Rd +++ b/man/set_cell_id.Rd @@ -40,6 +40,7 @@ Other functions to set data in giotto object: \code{\link{set_feature_info}()}, \code{\link{set_feature_metadata}()}, \code{\link{set_giottoImage}()}, +\code{\link{set_multiomics}()}, \code{\link{set_polygon_info}()}, \code{\link{set_spatialGrid}()}, \code{\link{set_spatialNetwork}()}, diff --git a/man/set_cell_metadata.Rd b/man/set_cell_metadata.Rd index b2fead6db..ebadc3655 100644 --- a/man/set_cell_metadata.Rd +++ b/man/set_cell_metadata.Rd @@ -49,6 +49,7 @@ Other functions to set data in giotto object: \code{\link{set_feature_info}()}, \code{\link{set_feature_metadata}()}, \code{\link{set_giottoImage}()}, +\code{\link{set_multiomics}()}, \code{\link{set_polygon_info}()}, \code{\link{set_spatialGrid}()}, \code{\link{set_spatialNetwork}()}, diff --git a/man/set_dimReduction.Rd b/man/set_dimReduction.Rd index 7178e1cf8..61ccb945f 100644 --- a/man/set_dimReduction.Rd +++ b/man/set_dimReduction.Rd @@ -60,6 +60,7 @@ Other functions to set data in giotto object: \code{\link{set_feature_info}()}, \code{\link{set_feature_metadata}()}, \code{\link{set_giottoImage}()}, +\code{\link{set_multiomics}()}, \code{\link{set_polygon_info}()}, \code{\link{set_spatialGrid}()}, \code{\link{set_spatialNetwork}()}, diff --git a/man/set_expression_values.Rd b/man/set_expression_values.Rd index 12a4a1aac..2b1f28218 100644 --- a/man/set_expression_values.Rd +++ b/man/set_expression_values.Rd @@ -55,6 +55,7 @@ Other functions to set data in giotto object: \code{\link{set_feature_info}()}, \code{\link{set_feature_metadata}()}, \code{\link{set_giottoImage}()}, +\code{\link{set_multiomics}()}, \code{\link{set_polygon_info}()}, \code{\link{set_spatialGrid}()}, \code{\link{set_spatialNetwork}()}, diff --git a/man/set_feat_id.Rd b/man/set_feat_id.Rd index 81edafa74..0d059f4d3 100644 --- a/man/set_feat_id.Rd +++ b/man/set_feat_id.Rd @@ -37,6 +37,7 @@ Other functions to set data in giotto object: \code{\link{set_feature_info}()}, \code{\link{set_feature_metadata}()}, \code{\link{set_giottoImage}()}, +\code{\link{set_multiomics}()}, \code{\link{set_polygon_info}()}, \code{\link{set_spatialGrid}()}, \code{\link{set_spatialNetwork}()}, diff --git a/man/set_feature_info.Rd b/man/set_feature_info.Rd index d1d6f04c9..856491b84 100644 --- a/man/set_feature_info.Rd +++ b/man/set_feature_info.Rd @@ -36,6 +36,7 @@ Other functions to set data in giotto object: \code{\link{set_feat_id}()}, \code{\link{set_feature_metadata}()}, \code{\link{set_giottoImage}()}, +\code{\link{set_multiomics}()}, \code{\link{set_polygon_info}()}, \code{\link{set_spatialGrid}()}, \code{\link{set_spatialNetwork}()}, diff --git a/man/set_feature_metadata.Rd b/man/set_feature_metadata.Rd index f7e9a8e9a..229ea3e98 100644 --- a/man/set_feature_metadata.Rd +++ b/man/set_feature_metadata.Rd @@ -49,6 +49,7 @@ Other functions to set data in giotto object: \code{\link{set_feat_id}()}, \code{\link{set_feature_info}()}, \code{\link{set_giottoImage}()}, +\code{\link{set_multiomics}()}, \code{\link{set_polygon_info}()}, \code{\link{set_spatialGrid}()}, \code{\link{set_spatialNetwork}()}, diff --git a/man/set_giottoImage.Rd b/man/set_giottoImage.Rd index 7794123f6..9c11093d0 100644 --- a/man/set_giottoImage.Rd +++ b/man/set_giottoImage.Rd @@ -54,6 +54,7 @@ Other functions to set data in giotto object: \code{\link{set_feat_id}()}, \code{\link{set_feature_info}()}, \code{\link{set_feature_metadata}()}, +\code{\link{set_multiomics}()}, \code{\link{set_polygon_info}()}, \code{\link{set_spatialGrid}()}, \code{\link{set_spatialNetwork}()}, diff --git a/man/set_polygon_info.Rd b/man/set_polygon_info.Rd index 6ba8eacd9..859f1de5a 100644 --- a/man/set_polygon_info.Rd +++ b/man/set_polygon_info.Rd @@ -37,6 +37,7 @@ Other functions to set data in giotto object: \code{\link{set_feature_info}()}, \code{\link{set_feature_metadata}()}, \code{\link{set_giottoImage}()}, +\code{\link{set_multiomics}()}, \code{\link{set_spatialGrid}()}, \code{\link{set_spatialNetwork}()}, \code{\link{set_spatial_enrichment}()}, diff --git a/man/set_spatialGrid.Rd b/man/set_spatialGrid.Rd index c7b06977c..4f76889aa 100644 --- a/man/set_spatialGrid.Rd +++ b/man/set_spatialGrid.Rd @@ -52,6 +52,7 @@ Other functions to set data in giotto object: \code{\link{set_feature_info}()}, \code{\link{set_feature_metadata}()}, \code{\link{set_giottoImage}()}, +\code{\link{set_multiomics}()}, \code{\link{set_polygon_info}()}, \code{\link{set_spatialNetwork}()}, \code{\link{set_spatial_enrichment}()}, diff --git a/man/set_spatialNetwork.Rd b/man/set_spatialNetwork.Rd index 78a89dff8..c2896794c 100644 --- a/man/set_spatialNetwork.Rd +++ b/man/set_spatialNetwork.Rd @@ -49,6 +49,7 @@ Other functions to set data in giotto object: \code{\link{set_feature_info}()}, \code{\link{set_feature_metadata}()}, \code{\link{set_giottoImage}()}, +\code{\link{set_multiomics}()}, \code{\link{set_polygon_info}()}, \code{\link{set_spatialGrid}()}, \code{\link{set_spatial_enrichment}()}, diff --git a/man/set_spatial_enrichment.Rd b/man/set_spatial_enrichment.Rd index c238ca610..b6377ab91 100644 --- a/man/set_spatial_enrichment.Rd +++ b/man/set_spatial_enrichment.Rd @@ -52,6 +52,7 @@ Other functions to set data in giotto object: \code{\link{set_feature_info}()}, \code{\link{set_feature_metadata}()}, \code{\link{set_giottoImage}()}, +\code{\link{set_multiomics}()}, \code{\link{set_polygon_info}()}, \code{\link{set_spatialGrid}()}, \code{\link{set_spatialNetwork}()}, diff --git a/man/set_spatial_locations.Rd b/man/set_spatial_locations.Rd index b84bccc92..401036b6f 100644 --- a/man/set_spatial_locations.Rd +++ b/man/set_spatial_locations.Rd @@ -64,6 +64,7 @@ Other functions to set data in giotto object: \code{\link{set_feature_info}()}, \code{\link{set_feature_metadata}()}, \code{\link{set_giottoImage}()}, +\code{\link{set_multiomics}()}, \code{\link{set_polygon_info}()}, \code{\link{set_spatialGrid}()}, \code{\link{set_spatialNetwork}()}, diff --git a/man/spatFeatPlot2D.Rd b/man/spatFeatPlot2D.Rd index 521f9a7c4..71d56e9d6 100644 --- a/man/spatFeatPlot2D.Rd +++ b/man/spatFeatPlot2D.Rd @@ -36,6 +36,7 @@ spatFeatPlot2D( point_alpha = 1, point_border_col = "black", point_border_stroke = 0.1, + coord_fix_ratio = 1, show_legend = T, legend_text = 8, background_color = "white", diff --git a/man/spatFeatPlot2D_single.Rd b/man/spatFeatPlot2D_single.Rd index ab7c299df..29cfe7fc5 100644 --- a/man/spatFeatPlot2D_single.Rd +++ b/man/spatFeatPlot2D_single.Rd @@ -34,6 +34,7 @@ spatFeatPlot2D_single( point_alpha = 1, point_border_col = "black", point_border_stroke = 0.1, + coord_fix_ratio = 1, show_legend = T, legend_text = 8, background_color = "white", From 6c16093d657e882eb71512e89f75fd2f2fc8d13d Mon Sep 17 00:00:00 2001 From: josschavezf Date: Mon, 5 Dec 2022 01:01:25 -0500 Subject: [PATCH 006/129] add S4 access in WNN --- R/wnn.R | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/R/wnn.R b/R/wnn.R index f45edd894..bf784c54f 100644 --- a/R/wnn.R +++ b/R/wnn.R @@ -43,6 +43,7 @@ runWNN <- function(gobject, spat_unit = spat_unit, feat_type = modality_1, nn_network_to_use = "kNN") + kNN_1 <- slot(kNN_1, "igraph") pca_1 <- get_dimReduction(gobject, spat_unit = spat_unit, @@ -50,12 +51,14 @@ runWNN <- function(gobject, reduction = "cells", reduction_method = "pca", name = pca_name_modality_1) + pca_1 <- slot(pca_1, "coordinates") ## modality 2 kNN_2 <- get_NearestNetwork(gobject, spat_unit = spat_unit, feat_type = modality_2, nn_network_to_use = "kNN") + kNN_2 <- slot(kNN_2, "igraph") pca_2 <- get_dimReduction(gobject, spat_unit = "cell", @@ -63,6 +66,7 @@ runWNN <- function(gobject, reduction = "cells", reduction_method = "pca", name = pca_name_modality_2) + pca_2 <- slot(pca_2, "coordinates") ## get cell names cell_names <- unique(igraph::get.edgelist(kNN_1)[,1]) From af71565a3b22d14ef214fc2cd2466c2ff7bf1157 Mon Sep 17 00:00:00 2001 From: jiajic <72078254+jiajic@users.noreply.github.com> Date: Mon, 5 Dec 2022 17:28:59 -0500 Subject: [PATCH 007/129] documentation updates --- R/accessors.R | 3 +- R/auxiliary_giotto.R | 81 +++++++++++++++++++++++++++- R/classes.R | 2 +- R/generics.R | 11 ++-- R/giotto.R | 1 + R/giotto_structures.R | 1 + R/interactivity.R | 1 + R/spatial_interaction.R | 1 + R/spatial_visuals.R | 2 + R/utilities.R | 5 +- man/addPolygonCells.Rd | 2 + man/cellMetaObj-class.Rd | 2 +- man/createGiottoObjectSubcellular.Rd | 2 + man/data_access.Rd | 4 +- man/extract-generic.Rd | 9 ++-- man/extractNearestNetwork.Rd | 3 +- man/featType-generic.Rd | 1 + man/filterDistributions.Rd | 15 +++--- man/findInteractionChangedGenes.Rd | 3 ++ man/get_NearestNetwork.Rd | 3 +- man/get_cell_id.Rd | 3 +- man/get_cell_metadata.Rd | 4 +- man/get_dimReduction.Rd | 3 +- man/get_expression_values.Rd | 3 +- man/get_feat_id.Rd | 3 +- man/get_feature_info.Rd | 3 +- man/get_feature_metadata.Rd | 3 +- man/get_spatialGrid.Rd | 3 +- man/get_spatialNetwork.Rd | 3 +- man/get_spatial_enrichment.Rd | 4 +- man/get_spatial_locations.Rd | 3 +- man/mat_queryDT.Rd | 24 +++++++++ man/overlapImagesToMatrix.Rd | 2 + man/prov-generic.Rd | 1 + man/select_NearestNetwork.Rd | 3 +- man/select_dimReduction.Rd | 3 +- man/select_expression_values.Rd | 3 +- man/select_feature_info.Rd | 3 +- man/select_spatialGrid.Rd | 3 +- man/select_spatialNetwork.Rd | 3 +- man/select_spatial_locations.Rd | 3 +- man/set_NearestNetwork.Rd | 3 +- man/set_cell_id.Rd | 3 +- man/set_cell_metadata.Rd | 3 +- man/set_dimReduction.Rd | 3 +- man/set_expression_values.Rd | 3 +- man/set_feat_id.Rd | 3 +- man/set_feature_metadata.Rd | 3 +- man/set_spatialGrid.Rd | 3 +- man/set_spatialNetwork.Rd | 3 +- man/set_spatial_enrichment.Rd | 3 +- man/set_spatial_locations.Rd | 3 +- man/showGiottoCellMetadata.Rd | 2 - man/showGiottoFeatMetadata.Rd | 2 - man/spatFeatPlot2D.Rd | 3 ++ man/spatFeatPlot2D_single.Rd | 3 ++ man/spatGenePlot2D.Rd | 1 + man/spatUnit-generic.Rd | 1 + man/subsetGiotto.Rd | 2 + man/wrap_msg.Rd | 7 +-- 60 files changed, 198 insertions(+), 91 deletions(-) create mode 100644 man/mat_queryDT.Rd diff --git a/R/accessors.R b/R/accessors.R index 664296766..93e6a4b53 100644 --- a/R/accessors.R +++ b/R/accessors.R @@ -10,6 +10,7 @@ #' @param return_uniques return unique nesting names (ignores if final object exists/is correct class) #' @param output what format in which to get information (e.g. "data.table") #' @param set_defaults set default spat_unit and feat_type. Change to FALSE only when +#' @param copy_obj whether to deep copy/duplicate when getting the object (default = TRUE) #' expression and spat_info are not expected to exist. #' @keywords internal NULL @@ -2488,7 +2489,6 @@ showGiottoExpression = function(gobject, nrows = 4, ncols = 4) { #' @description shows the available cell metadata #' @param gobject giotto object #' @param nrows number of rows to print for each metadata -#' @param ncols number of columns to print for each metadata #' @return prints the name and small subset of available metadata #' @family functions to show data in giotto object #' @keywords show @@ -2563,7 +2563,6 @@ showGiottoCellMetadata = function(gobject, #' @description shows the available feature metadata #' @param gobject giotto object #' @param nrows number of rows to print for each metadata -#' @param ncols number of columns to print for each metadata #' @return prints the name and small subset of available metadata #' @family functions to show data in giotto object #' @keywords show diff --git a/R/auxiliary_giotto.R b/R/auxiliary_giotto.R index 3f84de630..fbe3321d7 100644 --- a/R/auxiliary_giotto.R +++ b/R/auxiliary_giotto.R @@ -1191,6 +1191,7 @@ subset_feature_info_data = function(feat_info, #' @param feat_type feature type to use #' @param cell_ids cell IDs to keep #' @param feat_ids feature IDs to keep +#' @param gene_ids deprecated. Use \code{feat_ids} #' @param poly_info polygon information to use #' @param all_spat_units subset all spatial units with selected feature ids #' @param all_feat_types subset all feature type data with selected cell ids @@ -1668,7 +1669,7 @@ subsetGiottoLocsMulti = function(gobject, #' @param save_plot directly save the plot [boolean] #' @param save_param list of saving parameters from \code{\link{all_plots_save_function}} #' @param default_save_name default save name for saving, don't change, change save_name in save_param -#' @param details +#' @details #' There are 3 ways to create a distribution profile and summarize it for either the features or the cells (spatial units) \cr #' \itemize{ #' \item{1. threshold: calculate features that cross a thresold (default)} @@ -4723,4 +4724,82 @@ combineSpatialCellMetadataInfo = function(gobject, +#' @title Query Matrix with data.table syntax +#' @name mat_queryDT +#' @description Finds the rows of the Matrix needed to perform the query, converts +#' first to matrix, transposes, then to data.table after which the query is performed +#' just as if it had been a cell_ID (rows) by gene (cols) data.table. Only works +#' when j param is provided. +#' @param i select by row +#' @param j select by column or expression to query +#' @param by return results by which column +#' @param mtx matrix to use +#' @keywords internal +mat_queryDT = function(i = NULL, + j = NULL, + by = cell_ID, + mtx) { + + i_sub = deparse(substitute(i)) + j_sub = deparse(substitute(j)) + by_sub = deparse(substitute(by)) + + # only i + if(i_sub != 'NULL' & j_sub == 'NULL' & by_sub == 'NULL') { + warning('Only i not supported') + return(NULL) + } + + # by only + # i,by + if(i_sub != 'NULL' & by_sub != 'NULL') { + warning(wrap_txt('Ignoring by= because j= is not supplied')) + return(NULL) + } + + query_to_match = paste(i_sub, j_sub, by_sub) + print(query_to_match) + + genes = rownames(mtx) + gene_matches = genes[sapply(genes, function(x) {grepl(x, query_to_match)})] + names(gene_matches) = NULL + + print(gene_matches) + + cell_IDs = colnames(mtx) + match_dt = data.table::as.data.table(t_flex(as.matrix(mtx[gene_matches,,drop = FALSE]))) + match_dt[, cell_ID := cell_IDs] + + print(match_dt) + + + + # only j + if(i_sub == 'NULL' & j_sub != 'NULL' & by_sub == 'NULL') { + return(match_dt[,eval(parse(text = j_sub))]) + } + + # i,j + if(i_sub != 'NULL' & j_sub != 'NULL' & by_sub == 'NULL') { + return(match_dt[eval(parse(text = i_sub)), + eval(parse(text = j_sub))]) + } + + # j,by + if(i_sub == 'NULL' & j_sub != 'NULL' & by_sub != 'NULL') { + return(match_dt[,eval(parse(text = j_sub)), c(by_sub)]) + } + + # i,j,by + if(i_sub != 'NULL' & j_sub != 'NULL' & by_sub != 'NULL') { + return(match_dt[eval(parse(text = i_sub)), + eval(parse(text = j_sub)), + c(by_sub)]) + } + +} + + + + diff --git a/R/classes.R b/R/classes.R index 060d14774..642fe4805 100644 --- a/R/classes.R +++ b/R/classes.R @@ -645,7 +645,7 @@ check_cell_meta_obj = function(object) { # * Definition #### #' @title S4 cellMetaObj #' @description Framework to store cell metadata -#' @slot metadata metadata info +#' @slot metaDT metadata info #' @slot col_desc (optional) character vector describing columns of the metadata #' @slot spat_unit spatial unit of aggregated expression (e.g. 'cell') #' @slot feat_type feature type of aggregated expression (e.g. 'rna', 'protein') diff --git a/R/generics.R b/R/generics.R index 73a53083e..a3a902507 100644 --- a/R/generics.R +++ b/R/generics.R @@ -172,6 +172,7 @@ setMethod('copy', signature(x = 'coordDataDT'), function(x) { #' @description access and set provenance slot of S4 subobject #' @param x a Giotto S4 class subobject #' @param value value to set as provenance +#' @aliases prov #' @include classes.R #' @export setGeneric('prov', function(x) standardGeneric('prov')) @@ -199,6 +200,7 @@ setMethod('prov<-', signature = 'provData', function(x, value) { #' @description access and set spat_unit slot of S4 subobject #' @param x a Giotto S4 class subobject with spatial unit #' @param value value to set as spatial unit +#' @aliases spatUnit #' @include classes.R #' @export setGeneric('spatUnit', function(x) standardGeneric('spatUnit')) @@ -226,6 +228,7 @@ setMethod('spatUnit<-', signature = 'spatData', function(x, value) { #' @description access and set feat_type slot of S4 subobject #' @param x a Giotto S4 class subobject with feature type #' @param value value to set as feature type +#' @aliases featType #' @include classes.R #' @export setGeneric('featType', function(x) standardGeneric('featType')) @@ -354,7 +357,7 @@ setMethod('[', signature(x = 'coordDataDT', i = 'missing', j = 'missing', drop = #' @rdname extract-generic #' @section \code{`[<-`} methods: -#' Return \code{coordinates} slot data.table from giotto S4 +#' Assign to \code{coordinates} slot in giotto S4 #' @export setMethod('[<-', signature(x = 'coordDataDT', i = 'missing', j = 'missing', value = 'ANY'), function(x, i, j, value) { @@ -403,7 +406,7 @@ setMethod('[', signature(x = 'metaData', i = 'missing', j = 'missing', drop = 'm #' @rdname extract-generic #' @section \code{`[<-`} methods: -#' Return \code{coordinates} slot data.table from giotto S4 +#' Assign to \code{metaDT} slot in giotto S4 #' @export setMethod('[<-', signature(x = 'metaData', i = 'missing', j = 'missing', value = 'ANY'), function(x, i, j, value) { @@ -430,6 +433,8 @@ setMethod('[', signature(x = 'dimObj', i = 'missing', j = 'missing', drop = 'mis }) #' @rdname extract-generic +#' @section \code{`[<-`} methods: +#' Assign to \code{coordinates} slot in giotto S4 #' @export setMethod('[<-', signature(x = 'dimObj', i = 'missing', j = 'missing', value = 'ANY'), function(x, i, j, value) { @@ -476,7 +481,7 @@ setMethod('[', signature(x = 'exprData', i = 'missing', j = 'missing', drop = 'm #' @rdname extract-generic #' @section \code{`[<-`} methods: -#' Return \code{exprMat} slot Matrix object from giotto S4 +#' Assign to \code{exprMat} slot in giotto S4 #' @export setMethod('[<-', signature(x = 'exprData', i = 'missing', j = 'missing', value = 'ANY'), function(x, i, j, value) { diff --git a/R/giotto.R b/R/giotto.R index 5035a5d1b..0d36d1980 100644 --- a/R/giotto.R +++ b/R/giotto.R @@ -2409,6 +2409,7 @@ createGiottoVisiumObject = function(visium_dir = NULL, #' @param nn_network list of nearest neighbor network(s) #' @param images list of images #' @param largeImages list of large images +#' @param largeImages_list_params image params when loading largeImages as list #' @param instructions list of instructions or output result from \code{\link{createGiottoInstructions}} #' @param cores how many cores or threads to use to read data if paths are provided #' @param verbose be verbose when building Giotto object diff --git a/R/giotto_structures.R b/R/giotto_structures.R index 6b39ab1a4..67e503b33 100644 --- a/R/giotto_structures.R +++ b/R/giotto_structures.R @@ -2699,6 +2699,7 @@ overlapToMatrixMultiPoly = function(gobject, #' @param name name for the overlap count matrix #' @param poly_info polygon information #' @param feat_info feature information +#' @param name_overlap name of the overlap #' @param image_names names of images you used #' @param spat_locs_name name for spatial centroids / locations associated with matrix #' @param return_gobject return giotto object (default: TRUE) diff --git a/R/interactivity.R b/R/interactivity.R index 2f5a685a3..5c9aac1ed 100644 --- a/R/interactivity.R +++ b/R/interactivity.R @@ -205,6 +205,7 @@ getCellsFromPolygon <- function(gobject, #' @param polygon_name name of polygon selections #' @param feat_type feature name where metadata will be added #' @param spat_unit spatial unit +#' @param spat_loc_name name of spatial locations to use #' @param na.label polygon label for cells located outside of polygons area. Default = "no_polygon" #' #' @return A Giotto object with a modified cell_metadata slot that includes the diff --git a/R/spatial_interaction.R b/R/spatial_interaction.R index 24f1a49f6..b04394aa5 100644 --- a/R/spatial_interaction.R +++ b/R/spatial_interaction.R @@ -1154,6 +1154,7 @@ findInteractionChangedFeats = function(gobject, #' @name findInteractionChangedGenes #' @description Identifies cell-to-cell Interaction Changed Features (ICF), #' i.e. genes that are differentially expressed due to interactions with other cell types. +#' @param ... params to pass to \code{findInteractionChangedFeats} #' @seealso \code{\link{findInteractionChangedFeats}} #' @export findInteractionChangedGenes = function(...) { diff --git a/R/spatial_visuals.R b/R/spatial_visuals.R index 00618751d..007e665d7 100644 --- a/R/spatial_visuals.R +++ b/R/spatial_visuals.R @@ -4156,6 +4156,7 @@ spatDimPlot = function(...) { #' @param point_alpha transparancy of points #' @param point_border_col color of border around points #' @param point_border_stroke stroke size of border around points +#' @param coord_fix_ratio fix ratio between x and y-axis (default = 1) #' @param cow_n_col cowplot param: how many columns #' @param cow_rel_h cowplot param: relative height #' @param cow_rel_w cowplot param: relative width @@ -4643,6 +4644,7 @@ spatFeatPlot2D_single <- function(gobject, #' @param point_alpha transparancy of points #' @param point_border_col color of border around points #' @param point_border_stroke stroke size of border around points +#' @param coord_fix_ratio fix ratio between x and y-axis (default = 1) #' @param cow_n_col cowplot param: how many columns #' @param cow_rel_h cowplot param: relative height #' @param cow_rel_w cowplot param: relative width diff --git a/R/utilities.R b/R/utilities.R index f75239f48..6d4561258 100644 --- a/R/utilities.R +++ b/R/utilities.R @@ -509,10 +509,9 @@ abb_spatlocs = function(spatLocsObj, nrows) { #' @title Wrap message #' @name wrap_msg -#' @param ... additional strings and/or elements to pass to cat +#' @param ... additional strings and/or elements to pass to wrap_txt #' @param sep how to join elements of string (default is one space) -#' @param strWidth externally set wrapping width. (default value of 100 is not effected) -#' @param keywords internal +#' @keywords internal wrap_msg = function(..., sep = ' ') { message(wrap_txt(..., sep = sep)) } diff --git a/man/addPolygonCells.Rd b/man/addPolygonCells.Rd index 7a2596f7d..5df57af3d 100644 --- a/man/addPolygonCells.Rd +++ b/man/addPolygonCells.Rd @@ -21,6 +21,8 @@ addPolygonCells( \item{spat_unit}{spatial unit} +\item{spat_loc_name}{name of spatial locations to use} + \item{feat_type}{feature name where metadata will be added} \item{na.label}{polygon label for cells located outside of polygons area. Default = "no_polygon"} diff --git a/man/cellMetaObj-class.Rd b/man/cellMetaObj-class.Rd index d911c7eda..d8e8f45bd 100644 --- a/man/cellMetaObj-class.Rd +++ b/man/cellMetaObj-class.Rd @@ -10,7 +10,7 @@ Framework to store cell metadata \section{Slots}{ \describe{ -\item{\code{metadata}}{metadata info} +\item{\code{metaDT}}{metadata info} \item{\code{col_desc}}{(optional) character vector describing columns of the metadata} diff --git a/man/createGiottoObjectSubcellular.Rd b/man/createGiottoObjectSubcellular.Rd index af60eb343..cc20d99e9 100644 --- a/man/createGiottoObjectSubcellular.Rd +++ b/man/createGiottoObjectSubcellular.Rd @@ -60,6 +60,8 @@ createGiottoObjectSubcellular( \item{largeImages}{list of large images} +\item{largeImages_list_params}{image params when loading largeImages as list} + \item{instructions}{list of instructions or output result from \code{\link{createGiottoInstructions}}} \item{cores}{how many cores or threads to use to read data if paths are provided} diff --git a/man/data_access.Rd b/man/data_access.Rd index b06690136..de2dd22f5 100644 --- a/man/data_access.Rd +++ b/man/data_access.Rd @@ -14,7 +14,9 @@ \item{output}{what format in which to get information (e.g. "data.table")} -\item{set_defaults}{set default spat_unit and feat_type. Change to FALSE only when +\item{set_defaults}{set default spat_unit and feat_type. Change to FALSE only when} + +\item{copy_obj}{whether to deep copy/duplicate when getting the object (default = TRUE) expression and spat_info are not expected to exist.} } \description{ diff --git a/man/extract-generic.Rd b/man/extract-generic.Rd index 29684ae06..50666c70f 100644 --- a/man/extract-generic.Rd +++ b/man/extract-generic.Rd @@ -170,13 +170,16 @@ or replace parts. TODO - Return \code{coordinates} slot data.table from giotto S4 + Assign to \code{coordinates} slot in giotto S4 - Return \code{coordinates} slot data.table from giotto S4 + Assign to \code{metaDT} slot in giotto S4 - Return \code{exprMat} slot Matrix object from giotto S4 + Assign to \code{coordinates} slot in giotto S4 + + + Assign to \code{exprMat} slot in giotto S4 Return \code{spatNetData} slot network data.table object from giotto S4 diff --git a/man/extractNearestNetwork.Rd b/man/extractNearestNetwork.Rd index 3eba78373..dc8bc1dd1 100644 --- a/man/extractNearestNetwork.Rd +++ b/man/extractNearestNetwork.Rd @@ -16,8 +16,7 @@ extractNearestNetwork(...) \item{\code{gobject}}{giotto object} \item{\code{spat_unit}}{spatial unit (e.g. "cell")} \item{\code{feat_type}}{feature type (e.g. "rna", "dna", "protein")} - \item{\code{set_defaults}}{set default spat_unit and feat_type. Change to FALSE only when -expression and spat_info are not expected to exist.} + \item{\code{set_defaults}}{set default spat_unit and feat_type. Change to FALSE only when} }} } \description{ diff --git a/man/featType-generic.Rd b/man/featType-generic.Rd index ceea7450e..b1c26a4e7 100644 --- a/man/featType-generic.Rd +++ b/man/featType-generic.Rd @@ -2,6 +2,7 @@ % Please edit documentation in R/generics.R \name{featType-generic} \alias{featType-generic} +\alias{featType} \alias{featType,featData-method} \alias{featType<-,featData-method} \title{Feature type information} diff --git a/man/filterDistributions.Rd b/man/filterDistributions.Rd index 1465df094..141cc31f1 100644 --- a/man/filterDistributions.Rd +++ b/man/filterDistributions.Rd @@ -61,13 +61,6 @@ filterDistributions( \item{save_param}{list of saving parameters from \code{\link{all_plots_save_function}}} \item{default_save_name}{default save name for saving, don't change, change save_name in save_param} - -\item{details}{There are 3 ways to create a distribution profile and summarize it for either the features or the cells (spatial units) \cr -\itemize{ - \item{1. threshold: calculate features that cross a thresold (default)} - \item{2. sum: summarize the features, i.e. total of a feature} - \item{3. mean: calculate mean of the features, i.e. average expression} -}} } \value{ ggplot object @@ -75,3 +68,11 @@ ggplot object \description{ show gene or cell distribution after filtering on expression threshold } +\details{ +There are 3 ways to create a distribution profile and summarize it for either the features or the cells (spatial units) \cr +\itemize{ + \item{1. threshold: calculate features that cross a thresold (default)} + \item{2. sum: summarize the features, i.e. total of a feature} + \item{3. mean: calculate mean of the features, i.e. average expression} +} +} diff --git a/man/findInteractionChangedGenes.Rd b/man/findInteractionChangedGenes.Rd index 4df08494d..eefdba7ef 100644 --- a/man/findInteractionChangedGenes.Rd +++ b/man/findInteractionChangedGenes.Rd @@ -6,6 +6,9 @@ \usage{ findInteractionChangedGenes(...) } +\arguments{ +\item{...}{params to pass to \code{findInteractionChangedFeats}} +} \description{ Identifies cell-to-cell Interaction Changed Features (ICF), i.e. genes that are differentially expressed due to interactions with other cell types. diff --git a/man/get_NearestNetwork.Rd b/man/get_NearestNetwork.Rd index 13d7dacf7..b9dd75a82 100644 --- a/man/get_NearestNetwork.Rd +++ b/man/get_NearestNetwork.Rd @@ -27,8 +27,7 @@ get_NearestNetwork( \item{output}{return a igraph or data.table object. Default 'igraph'} -\item{set_defaults}{set default spat_unit and feat_type. Change to FALSE only when -expression and spat_info are not expected to exist.} +\item{set_defaults}{set default spat_unit and feat_type. Change to FALSE only when} } \value{ igraph or data.table object diff --git a/man/get_cell_id.Rd b/man/get_cell_id.Rd index 08f3c7385..e34d7e277 100644 --- a/man/get_cell_id.Rd +++ b/man/get_cell_id.Rd @@ -11,8 +11,7 @@ get_cell_id(gobject, spat_unit = NULL, set_defaults = TRUE) \item{spat_unit}{spatial unit (e.g. "cell")} -\item{set_defaults}{set default spat_unit and feat_type. Change to FALSE only when -expression and spat_info are not expected to exist.} +\item{set_defaults}{set default spat_unit and feat_type. Change to FALSE only when} } \value{ character vector of cell_IDs diff --git a/man/get_cell_metadata.Rd b/man/get_cell_metadata.Rd index 7132493f8..08f17a398 100644 --- a/man/get_cell_metadata.Rd +++ b/man/get_cell_metadata.Rd @@ -22,8 +22,10 @@ get_cell_metadata( \item{output}{return as either 'data.table' or 'cellMetaObj'} -\item{set_defaults}{set default spat_unit and feat_type. Change to FALSE only when +\item{copy_obj}{whether to deep copy/duplicate when getting the object (default = TRUE) expression and spat_info are not expected to exist.} + +\item{set_defaults}{set default spat_unit and feat_type. Change to FALSE only when} } \description{ Get cell metadata from giotto object diff --git a/man/get_dimReduction.Rd b/man/get_dimReduction.Rd index 199fba90e..89fe82547 100644 --- a/man/get_dimReduction.Rd +++ b/man/get_dimReduction.Rd @@ -31,8 +31,7 @@ get_dimReduction( \item{output}{object type to return as. Either 'dimObj' (default) or 'data.table of the embedding coordinates.} -\item{set_defaults}{set default spat_unit and feat_type. Change to FALSE only when -expression and spat_info are not expected to exist.} +\item{set_defaults}{set default spat_unit and feat_type. Change to FALSE only when} } \value{ dim reduction object (default) or dim reduction coordinates diff --git a/man/get_expression_values.Rd b/man/get_expression_values.Rd index c3ef2b60c..707523592 100644 --- a/man/get_expression_values.Rd +++ b/man/get_expression_values.Rd @@ -26,8 +26,7 @@ get_expression_values( 'matrix' for the matrix object contained in the exprObj or 'exprObj' (default) for the exprObj itself are allowed.} -\item{set_defaults}{set default spat_unit and feat_type. Change to FALSE only when -expression and spat_info are not expected to exist.} +\item{set_defaults}{set default spat_unit and feat_type. Change to FALSE only when} } \value{ expression matrix diff --git a/man/get_feat_id.Rd b/man/get_feat_id.Rd index 1d66e0d2d..ea1227445 100644 --- a/man/get_feat_id.Rd +++ b/man/get_feat_id.Rd @@ -11,8 +11,7 @@ get_feat_id(gobject, feat_type = NULL, set_defaults = TRUE) \item{feat_type}{feature type (e.g. "rna", "dna", "protein")} -\item{set_defaults}{set default spat_unit and feat_type. Change to FALSE only when -expression and spat_info are not expected to exist.} +\item{set_defaults}{set default spat_unit and feat_type. Change to FALSE only when} } \description{ Across a single modality/feature type, all feature information is diff --git a/man/get_feature_info.Rd b/man/get_feature_info.Rd index 7df8ae080..f7c6d9823 100644 --- a/man/get_feature_info.Rd +++ b/man/get_feature_info.Rd @@ -11,8 +11,7 @@ get_feature_info(gobject, feat_type = NULL, set_defaults = TRUE) \item{feat_type}{feature type (e.g. "rna", "dna", "protein")} -\item{set_defaults}{set default spat_unit and feat_type. Change to FALSE only when -expression and spat_info are not expected to exist.} +\item{set_defaults}{set default spat_unit and feat_type. Change to FALSE only when} } \description{ Get giotto points spatVector diff --git a/man/get_feature_metadata.Rd b/man/get_feature_metadata.Rd index 3c0bc2c0a..90c940c1a 100644 --- a/man/get_feature_metadata.Rd +++ b/man/get_feature_metadata.Rd @@ -24,8 +24,7 @@ get_feature_metadata( \item{copy_obj}{whether to perform a deepcopy of the data.table information} -\item{set_defaults}{set default spat_unit and feat_type. Change to FALSE only when -expression and spat_info are not expected to exist.} +\item{set_defaults}{set default spat_unit and feat_type. Change to FALSE only when} } \description{ Get feature metadata from giotto object diff --git a/man/get_spatialGrid.Rd b/man/get_spatialGrid.Rd index 62b4b8764..7ba75ff53 100644 --- a/man/get_spatialGrid.Rd +++ b/man/get_spatialGrid.Rd @@ -24,8 +24,7 @@ get_spatialGrid( \item{return_grid_Obj}{return grid object (default = FALSE)} -\item{set_defaults}{set default spat_unit and feat_type. Change to FALSE only when -expression and spat_info are not expected to exist.} +\item{set_defaults}{set default spat_unit and feat_type. Change to FALSE only when} } \description{ Function to get spatial grid diff --git a/man/get_spatialNetwork.Rd b/man/get_spatialNetwork.Rd index adef953e6..e6abf90ba 100644 --- a/man/get_spatialNetwork.Rd +++ b/man/get_spatialNetwork.Rd @@ -22,8 +22,7 @@ get_spatialNetwork( \item{output}{object type to return as. Options: 'spatialNetworkObj' (default), 'networkDT' and 'networkDT_before_filter' for data.table outputs.} -\item{set_defaults}{set default spat_unit and feat_type. Change to FALSE only when -expression and spat_info are not expected to exist.} +\item{set_defaults}{set default spat_unit and feat_type. Change to FALSE only when} } \description{ Function to get a spatial network diff --git a/man/get_spatial_enrichment.Rd b/man/get_spatial_enrichment.Rd index 17e92bba4..863f8333e 100644 --- a/man/get_spatial_enrichment.Rd +++ b/man/get_spatial_enrichment.Rd @@ -25,8 +25,10 @@ get_spatial_enrichment( \item{output}{what format in which to get information (e.g. "data.table")} -\item{set_defaults}{set default spat_unit and feat_type. Change to FALSE only when +\item{copy_obj}{whether to deep copy/duplicate when getting the object (default = TRUE) expression and spat_info are not expected to exist.} + +\item{set_defaults}{set default spat_unit and feat_type. Change to FALSE only when} } \value{ data.table with fractions diff --git a/man/get_spatial_locations.Rd b/man/get_spatial_locations.Rd index a4670f3d2..7d6f9e74d 100644 --- a/man/get_spatial_locations.Rd +++ b/man/get_spatial_locations.Rd @@ -28,8 +28,7 @@ a 'spatLocsObj'. Returning as 'data.table' is also possible.} \item{verbose}{be verbose} -\item{set_defaults}{set default spat_unit and feat_type. Change to FALSE only when -expression and spat_info are not expected to exist.} +\item{set_defaults}{set default spat_unit and feat_type. Change to FALSE only when} } \value{ data.table with coordinates or spatLocsObj depending on \code{output} diff --git a/man/mat_queryDT.Rd b/man/mat_queryDT.Rd new file mode 100644 index 000000000..b4db2ffa3 --- /dev/null +++ b/man/mat_queryDT.Rd @@ -0,0 +1,24 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/auxiliary_giotto.R +\name{mat_queryDT} +\alias{mat_queryDT} +\title{Query Matrix with data.table syntax} +\usage{ +mat_queryDT(i = NULL, j = NULL, by = cell_ID, mtx) +} +\arguments{ +\item{i}{select by row} + +\item{j}{select by column or expression to query} + +\item{by}{return results by which column} + +\item{mtx}{matrix to use} +} +\description{ +Finds the rows of the Matrix needed to perform the query, converts +first to matrix, transposes, then to data.table after which the query is performed +just as if it had been a cell_ID (rows) by gene (cols) data.table. Only works +when j param is provided. +} +\keyword{internal} diff --git a/man/overlapImagesToMatrix.Rd b/man/overlapImagesToMatrix.Rd index 6c9c54997..841a2bbf2 100644 --- a/man/overlapImagesToMatrix.Rd +++ b/man/overlapImagesToMatrix.Rd @@ -24,6 +24,8 @@ overlapImagesToMatrix( \item{feat_info}{feature information} +\item{name_overlap}{name of the overlap} + \item{image_names}{names of images you used} \item{spat_locs_name}{name for spatial centroids / locations associated with matrix} diff --git a/man/prov-generic.Rd b/man/prov-generic.Rd index fdc6a3e49..45445bb45 100644 --- a/man/prov-generic.Rd +++ b/man/prov-generic.Rd @@ -2,6 +2,7 @@ % Please edit documentation in R/generics.R \name{prov-generic} \alias{prov-generic} +\alias{prov} \alias{prov,provData-method} \alias{prov<-,provData-method} \title{Provenance information} diff --git a/man/select_NearestNetwork.Rd b/man/select_NearestNetwork.Rd index 0838fa28c..83c7c87fd 100644 --- a/man/select_NearestNetwork.Rd +++ b/man/select_NearestNetwork.Rd @@ -16,8 +16,7 @@ select_NearestNetwork(...) \item{\code{gobject}}{giotto object} \item{\code{spat_unit}}{spatial unit (e.g. "cell")} \item{\code{feat_type}}{feature type (e.g. "rna", "dna", "protein")} - \item{\code{set_defaults}}{set default spat_unit and feat_type. Change to FALSE only when -expression and spat_info are not expected to exist.} + \item{\code{set_defaults}}{set default spat_unit and feat_type. Change to FALSE only when} }} } \description{ diff --git a/man/select_dimReduction.Rd b/man/select_dimReduction.Rd index 13191f13c..470172b39 100644 --- a/man/select_dimReduction.Rd +++ b/man/select_dimReduction.Rd @@ -18,8 +18,7 @@ of the embedding coordinates.} \item{\code{gobject}}{giotto object} \item{\code{spat_unit}}{spatial unit (e.g. "cell")} \item{\code{feat_type}}{feature type (e.g. "rna", "dna", "protein")} - \item{\code{set_defaults}}{set default spat_unit and feat_type. Change to FALSE only when -expression and spat_info are not expected to exist.} + \item{\code{set_defaults}}{set default spat_unit and feat_type. Change to FALSE only when} }} } \description{ diff --git a/man/select_expression_values.Rd b/man/select_expression_values.Rd index e75bd3fe5..cbb01347b 100644 --- a/man/select_expression_values.Rd +++ b/man/select_expression_values.Rd @@ -17,8 +17,7 @@ the exprObj itself are allowed.} \item{\code{gobject}}{giotto object} \item{\code{spat_unit}}{spatial unit (e.g. "cell")} \item{\code{feat_type}}{feature type (e.g. "rna", "dna", "protein")} - \item{\code{set_defaults}}{set default spat_unit and feat_type. Change to FALSE only when -expression and spat_info are not expected to exist.} + \item{\code{set_defaults}}{set default spat_unit and feat_type. Change to FALSE only when} }} } \description{ diff --git a/man/select_feature_info.Rd b/man/select_feature_info.Rd index 755cbae74..816dba7d9 100644 --- a/man/select_feature_info.Rd +++ b/man/select_feature_info.Rd @@ -12,8 +12,7 @@ select_feature_info(...) \describe{ \item{\code{gobject}}{giotto object} \item{\code{feat_type}}{feature type (e.g. "rna", "dna", "protein")} - \item{\code{set_defaults}}{set default spat_unit and feat_type. Change to FALSE only when -expression and spat_info are not expected to exist.} + \item{\code{set_defaults}}{set default spat_unit and feat_type. Change to FALSE only when} }} } \description{ diff --git a/man/select_spatialGrid.Rd b/man/select_spatialGrid.Rd index e31c264c2..01922157b 100644 --- a/man/select_spatialGrid.Rd +++ b/man/select_spatialGrid.Rd @@ -15,8 +15,7 @@ select_spatialGrid(...) \item{\code{gobject}}{giotto object} \item{\code{spat_unit}}{spatial unit (e.g. "cell")} \item{\code{feat_type}}{feature type (e.g. "rna", "dna", "protein")} - \item{\code{set_defaults}}{set default spat_unit and feat_type. Change to FALSE only when -expression and spat_info are not expected to exist.} + \item{\code{set_defaults}}{set default spat_unit and feat_type. Change to FALSE only when} }} } \description{ diff --git a/man/select_spatialNetwork.Rd b/man/select_spatialNetwork.Rd index e6b4f6e8b..aaf7e09b4 100644 --- a/man/select_spatialNetwork.Rd +++ b/man/select_spatialNetwork.Rd @@ -15,8 +15,7 @@ select_spatialNetwork(...) 'networkDT' and 'networkDT_before_filter' for data.table outputs.} \item{\code{gobject}}{giotto object} \item{\code{spat_unit}}{spatial unit (e.g. "cell")} - \item{\code{set_defaults}}{set default spat_unit and feat_type. Change to FALSE only when -expression and spat_info are not expected to exist.} + \item{\code{set_defaults}}{set default spat_unit and feat_type. Change to FALSE only when} }} } \description{ diff --git a/man/select_spatial_locations.Rd b/man/select_spatial_locations.Rd index 57186b731..394701e22 100644 --- a/man/select_spatial_locations.Rd +++ b/man/select_spatial_locations.Rd @@ -17,8 +17,7 @@ a 'spatLocsObj'. Returning as 'data.table' is also possible.} \item{\code{verbose}}{be verbose} \item{\code{gobject}}{giotto object} \item{\code{spat_unit}}{spatial unit (e.g. "cell")} - \item{\code{set_defaults}}{set default spat_unit and feat_type. Change to FALSE only when -expression and spat_info are not expected to exist.} + \item{\code{set_defaults}}{set default spat_unit and feat_type. Change to FALSE only when} }} } \description{ diff --git a/man/set_NearestNetwork.Rd b/man/set_NearestNetwork.Rd index 200afd7de..831bdafdb 100644 --- a/man/set_NearestNetwork.Rd +++ b/man/set_NearestNetwork.Rd @@ -34,8 +34,7 @@ yet supported.} \item{verbose}{be verbose} -\item{set_defaults}{set default spat_unit and feat_type. Change to FALSE only when -expression and spat_info are not expected to exist.} +\item{set_defaults}{set default spat_unit and feat_type. Change to FALSE only when} } \value{ giotto object diff --git a/man/set_cell_id.Rd b/man/set_cell_id.Rd index b93890e85..fb33ab4bb 100644 --- a/man/set_cell_id.Rd +++ b/man/set_cell_id.Rd @@ -13,8 +13,7 @@ set_cell_id(gobject, spat_unit = NULL, cell_IDs, set_defaults = TRUE) \item{cell_IDs}{character vector of cell IDs to set} -\item{set_defaults}{set default spat_unit and feat_type. Change to FALSE only when -expression and spat_info are not expected to exist.} +\item{set_defaults}{set default spat_unit and feat_type. Change to FALSE only when} } \value{ giotto object with set cell_ID slot diff --git a/man/set_cell_metadata.Rd b/man/set_cell_metadata.Rd index b2fead6db..117327f58 100644 --- a/man/set_cell_metadata.Rd +++ b/man/set_cell_metadata.Rd @@ -28,8 +28,7 @@ the object. Passing 'initialize' will reset the object.} \item{verbose}{be verbose} -\item{set_defaults}{set default spat_unit and feat_type. Change to FALSE only when -expression and spat_info are not expected to exist.} +\item{set_defaults}{set default spat_unit and feat_type. Change to FALSE only when} } \value{ giotto object diff --git a/man/set_dimReduction.Rd b/man/set_dimReduction.Rd index 7178e1cf8..b852aff8d 100644 --- a/man/set_dimReduction.Rd +++ b/man/set_dimReduction.Rd @@ -36,8 +36,7 @@ set_dimReduction( \item{verbose}{be verbose} -\item{set_defaults}{set default spat_unit and feat_type. Change to FALSE only when -expression and spat_info are not expected to exist.} +\item{set_defaults}{set default spat_unit and feat_type. Change to FALSE only when} } \value{ giotto object diff --git a/man/set_expression_values.Rd b/man/set_expression_values.Rd index 12a4a1aac..23eea01f9 100644 --- a/man/set_expression_values.Rd +++ b/man/set_expression_values.Rd @@ -31,8 +31,7 @@ will be removed.} \item{verbose}{be verbose} -\item{set_defaults}{set default spat_unit and feat_type. Change to FALSE only when -expression and spat_info are not expected to exist.} +\item{set_defaults}{set default spat_unit and feat_type. Change to FALSE only when} } \value{ giotto object diff --git a/man/set_feat_id.Rd b/man/set_feat_id.Rd index 81edafa74..965a873c2 100644 --- a/man/set_feat_id.Rd +++ b/man/set_feat_id.Rd @@ -11,8 +11,7 @@ set_feat_id(gobject, feat_type = NULL, feat_IDs, set_defaults = TRUE) \item{feat_type}{feature type (e.g. "rna", "dna", "protein")} -\item{set_defaults}{set default spat_unit and feat_type. Change to FALSE only when -expression and spat_info are not expected to exist.} +\item{set_defaults}{set default spat_unit and feat_type. Change to FALSE only when} } \value{ giotto object with set cell_ID slot diff --git a/man/set_feature_metadata.Rd b/man/set_feature_metadata.Rd index f7e9a8e9a..5bf65d79c 100644 --- a/man/set_feature_metadata.Rd +++ b/man/set_feature_metadata.Rd @@ -28,8 +28,7 @@ Setting NULL will remove the object.} \item{verbose}{be verbose} -\item{set_defaults}{set default spat_unit and feat_type. Change to FALSE only when -expression and spat_info are not expected to exist.} +\item{set_defaults}{set default spat_unit and feat_type. Change to FALSE only when} } \value{ giotto object diff --git a/man/set_spatialGrid.Rd b/man/set_spatialGrid.Rd index c7b06977c..24471ea9e 100644 --- a/man/set_spatialGrid.Rd +++ b/man/set_spatialGrid.Rd @@ -27,8 +27,7 @@ set_spatialGrid( \item{verbose}{be verbose} -\item{set_defaults}{set default spat_unit and feat_type. Change to FALSE only when -expression and spat_info are not expected to exist.} +\item{set_defaults}{set default spat_unit and feat_type. Change to FALSE only when} } \value{ giotto object diff --git a/man/set_spatialNetwork.Rd b/man/set_spatialNetwork.Rd index 78a89dff8..3a95e54cd 100644 --- a/man/set_spatialNetwork.Rd +++ b/man/set_spatialNetwork.Rd @@ -24,8 +24,7 @@ set_spatialNetwork( \item{verbose}{be verbose} -\item{set_defaults}{set default spat_unit and feat_type. Change to FALSE only when -expression and spat_info are not expected to exist.} +\item{set_defaults}{set default spat_unit and feat_type. Change to FALSE only when} } \value{ giotto object diff --git a/man/set_spatial_enrichment.Rd b/man/set_spatial_enrichment.Rd index c238ca610..5fcde96f5 100644 --- a/man/set_spatial_enrichment.Rd +++ b/man/set_spatial_enrichment.Rd @@ -27,8 +27,7 @@ set_spatial_enrichment( \item{verbose}{be verbose} -\item{set_defaults}{set default spat_unit and feat_type. Change to FALSE only when -expression and spat_info are not expected to exist.} +\item{set_defaults}{set default spat_unit and feat_type. Change to FALSE only when} } \value{ giotto object diff --git a/man/set_spatial_locations.Rd b/man/set_spatial_locations.Rd index b84bccc92..384f7fb93 100644 --- a/man/set_spatial_locations.Rd +++ b/man/set_spatial_locations.Rd @@ -28,8 +28,7 @@ set_spatial_locations( \item{verbose}{be verbose} -\item{set_defaults}{set default spat_unit and feat_type. Change to FALSE only when -expression and spat_info are not expected to exist.} +\item{set_defaults}{set default spat_unit and feat_type. Change to FALSE only when} } \value{ giotto object diff --git a/man/showGiottoCellMetadata.Rd b/man/showGiottoCellMetadata.Rd index 77ac3f49c..beb472a1a 100644 --- a/man/showGiottoCellMetadata.Rd +++ b/man/showGiottoCellMetadata.Rd @@ -10,8 +10,6 @@ showGiottoCellMetadata(gobject, nrows = 4) \item{gobject}{giotto object} \item{nrows}{number of rows to print for each metadata} - -\item{ncols}{number of columns to print for each metadata} } \value{ prints the name and small subset of available metadata diff --git a/man/showGiottoFeatMetadata.Rd b/man/showGiottoFeatMetadata.Rd index d4ec1b4bc..1e3111c34 100644 --- a/man/showGiottoFeatMetadata.Rd +++ b/man/showGiottoFeatMetadata.Rd @@ -10,8 +10,6 @@ showGiottoFeatMetadata(gobject, nrows = 4) \item{gobject}{giotto object} \item{nrows}{number of rows to print for each metadata} - -\item{ncols}{number of columns to print for each metadata} } \value{ prints the name and small subset of available metadata diff --git a/man/spatFeatPlot2D.Rd b/man/spatFeatPlot2D.Rd index 521f9a7c4..17774d417 100644 --- a/man/spatFeatPlot2D.Rd +++ b/man/spatFeatPlot2D.Rd @@ -36,6 +36,7 @@ spatFeatPlot2D( point_alpha = 1, point_border_col = "black", point_border_stroke = 0.1, + coord_fix_ratio = 1, show_legend = T, legend_text = 8, background_color = "white", @@ -118,6 +119,8 @@ spatFeatPlot2D( \item{point_border_stroke}{stroke size of border around points} +\item{coord_fix_ratio}{fix ratio between x and y-axis (default = 1)} + \item{show_legend}{show legend} \item{legend_text}{size of legend text} diff --git a/man/spatFeatPlot2D_single.Rd b/man/spatFeatPlot2D_single.Rd index ab7c299df..4191d7af0 100644 --- a/man/spatFeatPlot2D_single.Rd +++ b/man/spatFeatPlot2D_single.Rd @@ -34,6 +34,7 @@ spatFeatPlot2D_single( point_alpha = 1, point_border_col = "black", point_border_stroke = 0.1, + coord_fix_ratio = 1, show_legend = T, legend_text = 8, background_color = "white", @@ -112,6 +113,8 @@ spatFeatPlot2D_single( \item{point_border_stroke}{stroke size of border around points} +\item{coord_fix_ratio}{fix ratio between x and y-axis (default = 1)} + \item{show_legend}{show legend} \item{legend_text}{size of legend text} diff --git a/man/spatGenePlot2D.Rd b/man/spatGenePlot2D.Rd index 54ed25132..297e7128f 100644 --- a/man/spatGenePlot2D.Rd +++ b/man/spatGenePlot2D.Rd @@ -45,6 +45,7 @@ spatGenePlot2D(gobject, genes, default_save_name = "spatGenePlot2D", ...) \item{\code{point_alpha}}{transparancy of points} \item{\code{point_border_col}}{color of border around points} \item{\code{point_border_stroke}}{stroke size of border around points} + \item{\code{coord_fix_ratio}}{fix ratio between x and y-axis (default = 1)} \item{\code{cow_n_col}}{cowplot param: how many columns} \item{\code{cow_rel_h}}{cowplot param: relative height} \item{\code{cow_rel_w}}{cowplot param: relative width} diff --git a/man/spatUnit-generic.Rd b/man/spatUnit-generic.Rd index 30302f2c2..a44ae75db 100644 --- a/man/spatUnit-generic.Rd +++ b/man/spatUnit-generic.Rd @@ -2,6 +2,7 @@ % Please edit documentation in R/generics.R \name{spatUnit-generic} \alias{spatUnit-generic} +\alias{spatUnit} \alias{spatUnit,spatData-method} \alias{spatUnit<-,spatData-method} \title{Spatial unit information} diff --git a/man/subsetGiotto.Rd b/man/subsetGiotto.Rd index cacf4f0d4..3dc5844b7 100644 --- a/man/subsetGiotto.Rd +++ b/man/subsetGiotto.Rd @@ -33,6 +33,8 @@ subsetGiotto( \item{feat_ids}{feature IDs to keep} +\item{gene_ids}{deprecated. Use \code{feat_ids}} + \item{poly_info}{polygon information to use} \item{all_spat_units}{subset all spatial units with selected feature ids} diff --git a/man/wrap_msg.Rd b/man/wrap_msg.Rd index 0c4261bd0..7bd3074d1 100644 --- a/man/wrap_msg.Rd +++ b/man/wrap_msg.Rd @@ -7,14 +7,11 @@ wrap_msg(..., sep = " ") } \arguments{ -\item{...}{additional strings and/or elements to pass to cat} +\item{...}{additional strings and/or elements to pass to wrap_txt} \item{sep}{how to join elements of string (default is one space)} - -\item{strWidth}{externally set wrapping width. (default value of 100 is not effected)} - -\item{keywords}{internal} } \description{ Wrap message } +\keyword{internal} From 7655b687949df86d6897415200ce7a064a2f112e Mon Sep 17 00:00:00 2001 From: mattobny Date: Thu, 8 Dec 2022 13:18:55 -0500 Subject: [PATCH 008/129] Feature PCA fix --- R/dimension_reduction.R | 28 +++++++++++++++++----------- 1 file changed, 17 insertions(+), 11 deletions(-) diff --git a/R/dimension_reduction.R b/R/dimension_reduction.R index ed45ca093..98d1df34c 100644 --- a/R/dimension_reduction.R +++ b/R/dimension_reduction.R @@ -573,16 +573,16 @@ runPCA <- function(gobject, } else { # PCA on genes if(method %in% c('irlba', 'exact', 'random')) { - runPCA_BiocSingular(x = expr_values, - center = center, - scale = scale_unit, - ncp = ncp, - rev = rev, - set_seed = set_seed, - seed_number = seed_number, - BSPARAM = method, - BSParameters = method_params, - ...) + pca_object = runPCA_BiocSingular(x = expr_values, + center = center, + scale = scale_unit, + ncp = ncp, + rev = rev, + set_seed = set_seed, + seed_number = seed_number, + BSPARAM = method, + BSParameters = method_params, + ...) } else if(method == 'factominer') { pca_object = runPCA_factominer(x = expr_values, @@ -607,6 +607,12 @@ runPCA <- function(gobject, cat('\n ', name, ' has already been used, will be overwritten \n') } + if (reduction == "cells") { + my_row_names = colnames(expr_values) + } else { + my_row_names = rownames(expr_values) + } + dimObject = create_dimObject(name = name, feat_type = feat_type, spat_unit = spat_unit, @@ -615,7 +621,7 @@ runPCA <- function(gobject, coordinates = pca_object$coords, misc = list(eigenvalues = pca_object$eigenvalues, loadings = pca_object$loadings), - my_rownames = colnames(expr_values)) + my_rownames = my_row_names) gobject = set_dimReduction(gobject = gobject, dimObject) From 9d271c9ea2344e5273aecbd0035a6593be8a9d00 Mon Sep 17 00:00:00 2001 From: jiajic <72078254+jiajic@users.noreply.github.com> Date: Fri, 9 Dec 2022 02:46:32 -0500 Subject: [PATCH 009/129] test --- DESCRIPTION | 1 + NAMESPACE | 1 + NEWS.md | 2 + R/convenience_create.R | 1794 +++++++++++++++++++ R/general_help.R | 32 +- R/giotto.R | 1350 +------------- R/utilities.R | 57 + man/createGiottoCosMxObject.Rd | 2 +- man/createGiottoCosMxObject_aggregate.Rd | 2 +- man/createGiottoCosMxObject_all.Rd | 2 +- man/createGiottoCosMxObject_subcellular.Rd | 2 +- man/createGiottoMerscopeObject.Rd | 65 + man/createGiottoXeniumObject.Rd | 2 +- man/createGiottoXeniumObject_aggregate.Rd | 2 +- man/createGiottoXeniumObject_subcellular.Rd | 2 +- man/create_pb.Rd | 12 + man/load_cosmx_folder_aggregate.Rd | 2 +- man/load_cosmx_folder_subcellular.Rd | 2 +- man/load_merscope_folder.Rd | 55 + man/load_xenium_folder.Rd | 2 +- man/read_cosmx_folder.Rd | 2 +- man/read_data_folder.Rd | 59 + man/read_xenium_folder.Rd | 2 +- man/round_seconds.Rd | 12 + 24 files changed, 2103 insertions(+), 1361 deletions(-) create mode 100644 R/convenience_create.R create mode 100644 man/createGiottoMerscopeObject.Rd create mode 100644 man/create_pb.Rd create mode 100644 man/load_merscope_folder.Rd create mode 100644 man/read_data_folder.Rd create mode 100644 man/round_seconds.Rd diff --git a/DESCRIPTION b/DESCRIPTION index 8ffd3f0ac..bffe1035f 100644 --- a/DESCRIPTION +++ b/DESCRIPTION @@ -118,6 +118,7 @@ Collate: 'cell_segmentation.R' 'classes.R' 'clustering.R' + 'convenience_create.R' 'cross_section.R' 'differential_expression.R' 'dimension_reduction.R' diff --git a/NAMESPACE b/NAMESPACE index 4e1cd1585..55e5d5055 100644 --- a/NAMESPACE +++ b/NAMESPACE @@ -85,6 +85,7 @@ export(createGiottoImageOLD) export(createGiottoInstructions) export(createGiottoLargeImage) export(createGiottoLargeImageList) +export(createGiottoMerscopeObject) export(createGiottoObject) export(createGiottoObjectSubcellular) export(createGiottoPoints) diff --git a/NEWS.md b/NEWS.md index 0a40841d8..7f4df2d53 100644 --- a/NEWS.md +++ b/NEWS.md @@ -3,6 +3,8 @@ ## Changes - Add `id_col`, `x_col`, `y_col` params to `polyStamp()` to make stamp location input more flexible - Add `coord_fix_ratio` param to `spatFeatPlot2D()` and `spatFeatPlot2D_single()` +- Add `createGiottoMerscopeObject()` +- Move giotto object method-specific creation functions from `giotto.R` to `convenience_create.R` diff --git a/R/convenience_create.R b/R/convenience_create.R new file mode 100644 index 000000000..605820873 --- /dev/null +++ b/R/convenience_create.R @@ -0,0 +1,1794 @@ + +# ** Spatial Method-Specific Convenience Functions for Giotto Object Creation ** # + + + +# Common Utility Functions #### + +#' @title Read a structured folder of exported data +#' @name read_data_folder +#' @description Read the exported folder of a spatial method and +#' detect the presence of needed files. NULL values denote missing items. +#' @param spat_method spatial method for which the data is being read +#' @param data_dir exported data directory to read from +#' @param dir_items named list of directory items to expect and keywords to match +#' @param data_to_use which type(s) of expression data to build the gobject with +#' @param require_data_DT data.table detailing if expected data items are required +#' or optional for each \code{data_to_use} workflow +#' @param cores cores to use +#' @param verbose be verbose +#' @details Steps performed: +#' \itemize{ +#' \item{1. detection of items within \code{data_dir} by looking for keywords +#' assigned through \code{dir_items}} +#' \item{2. check of detected items to see if everything needed has been found. +#' Dictionary of necessary vs optional items for each \code{data_to_use} workflow +#' is provided through \code{require_data_DT}} +#' \item{3. if multiple filepaths are found to be matching then select the first +#' one. This function is only intended to find the first level subdirectories +#' and files.} +#' } +#' @keywords internal +read_data_folder = function(spat_method = NULL, + data_dir = NULL, + dir_items, + data_to_use, + load_format = NULL, + require_data_DT, + cores = NA, + verbose = TRUE) { + + ch = box_chars() + + # 0. check params + if(is.null(data_dir) | !dir.exists(data_dir)) stop(wrap_txt('The full path to a', spat_method, 'directory must be given.\n')) + if(isTRUE(verbose)) wrap_msg('A structured', spat_method, 'directory will be used') + if(!data_to_use %in% require_data_DT$workflow) stop(wrap_txt('Data requirements for data_to_use not found in require_data_DT')) + + # 1. detect items + dir_items = lapply_flex(dir_items, function(x) { + Sys.glob(paths = file.path(merscope_dir, x)) + }, cores = cores) + # (length = 1 if present, length = 0 if missing) + dir_items_lengths = lengths(dir_items) + + # 2. check directory contents + if(isTRUE(verbose)) wrap_msg('Checking directory contents...') + + for(item in names(dir_items)) { + + # IF ITEM FOUND + + if(dir_items_lengths[[item]] > 0) { + if(isTRUE(verbose)) { + message(ch$s, '> ' ,item, ' found') + for(item_i in seq_along(dir_items[[item]])) { # print found item names + subItem = gsub(pattern = '.*/', replacement = '', x = dir_items[[item]][[item_i]]) + message(ch$s, ch$s, ch$l, ch$h, ch$h, subItem) + } + } + } else { + + # IF ITEM MISSING + # necessary (error) + # optional (warning) + + # data.table variables + workflow = needed = filetype = NULL + + + require_data_DT = require_data_DT[workflow == data_to_use,] + if(!is.null(load_format)) require_data_DT = require_data_DT[filetype == load_format,] + + if(item %in% require_data_DT[needed == TRUE, item]) stop(item, ' is missing\n') + if(item %in% require_data_DT[needed == FALSE, item]) warning(item, 'is missing (optional)\n') + + } + } + + # 3. select first path in list if multiple are detected + if(any(dir_items_lengths > 1)) { + warning(wrap_txt('Multiple matches for expected directory item(s). + First matching item selected')) + + multiples = which(dir_items_lengths > 1) + for(mult_i in multiples) { + message(names(dir_items)[[mult_i]], 'multiple matches found:') + print(dir_items[[mult_i]]) + dir_items[[mult_i]] = dir_items[[mult_i]][[1]] + } + } + if(isTRUE(verbose)) message('Directory check done') + + return(dir_items) + +} + + + + + + + + + +# object creation #### + + + + +## MERSCOPE #### + +#' @title Create Vizgen MERSCOPE Giotto Object +#' @name createGiottoMerscopeObject +#' @description Given the path to a MERSCOPE experiment directory, creates a Giotto +#' object. +#' @param merscope_dir full path to the exported merscope directory +#' @param data_to_use which of either the 'subcellular' or 'aggregate' information +#' to use for object creation +#' @param FOVs which FOVs to use when building the subcellular object. (default is NULL) +#' NULL loads all FOVs (very slow) +#' @inheritParams createGiottoObjectSubcellular +#' @return a giotto object +#' @export +#' @details +#' [\strong{Expected Directory}] This function generates a giotto object when given a +#' link to a MERSCOPE output directory. It expects the following items within the directory +#' where the \strong{bolded} portions are what this function matches against: +#' \itemize{ +#' \item{\strong{cell_boundaries} (folder .hdf5 files)} +#' \item{\strong{images} (folder of .tif images and a scalefactor/transfrom table)} +#' \item{\strong{cell_by_gene}.csv (file)} +#' \item{cell_metadata\strong{fov_positions_file}.csv (file)} +#' \item{detected_transcripts\strong{metadata_file}.csv (file)} +#' } +createGiottoMerscopeObject = function(merscope_dir, + data_to_use = c('subcellular', 'aggregate'), + FOVs = NULL, + instructions = NULL, + cores = NA, + verbose = TRUE) { + + # 0. setup + # set number of cores automatically, but with limit of 10 + cores = determine_cores(cores) + data.table::setDTthreads(threads = cores) + + # determine data to use + data_to_use = match.arg(arg = data_to_use, choices = c('subcellular','aggregate')) + + # 1. test if folder structure exists and is as expected + dir_items = read_merscope_folder(merscope_dir = merscope_dir, + data_to_use = data_to_use, + cores = cores, + verbose = verbose) + + # 2. load in directory items + data_list = load_merscope_folder(dir_items = dir_items, + data_to_use = data_to_use, + fovs = fovs, + cores = cores, + verbose = verbose) + + # 3. Create giotto object + if(data_to_use == 'subcellular') { + + merscope_gobject = createGiottoMerscopeObject_subcellular(data_list = data_list, + corse = cores, + verbose = verbose) + + } else if(data_to_use == 'aggregate') { + + merscope_gobject = createGiottoMerscopeObject_aggregate(data_list = data_list, + cores = cores, + verbose = verbose) + + } else { + stop(wrap_txt('data_to_use "', data_to_use, '" not implemented', sep = '')) + } + + return(merscope_gobject) + +} + + + + +#' @describeIn createGiottoMerscopeObject Create giotto object with 'subcellular' workflow +#' @param data_list list of loaded data from \code{\link{load_merscope_folder}} +#' @keywords internal +createGiottoMerscopeObject_subcellular = function(data_list, + cores = NA, + verbose = TRUE) { + + # unpack data_list + poly_info = data_list$poly_info + tx_dt = data_list$tx_dt + micronToPixelScale = data_list$micronToPixelScale + image_list = data_list$images + + + +} + + + + +#' @describeIn createGiottoMerscopeObject Create giotto object with 'aggregate' workflow +#' @param data_list list of loaded data from \code{\link{load_merscope_folder}} +#' @keywords internal +createGiottoMerscopeObject_aggregate = function(data_list, + cores = NA, + verbose = TRUE) { + + # unpack data_list + micronToPixelScale = data_list$micronToPixelScale + expr_mat = data_list$expr_mat + cell_meta = data_list$expr_mat + image_list = data_list$images + + + +} + + + + + + + + + + + + + + + +## CosMx #### + +#' @title Create Nanostring CosMx Giotto Object +#' @name createGiottoCosMxObject +#' @description Given the path to a CosMx experiment directory, creates a Giotto +#' object. +#' @param cosmx_dir full path to the exported cosmx directory +#' @param data_to_use which type(s) of expression data to build the gobject with +#' Default is \code{'all'} information available. \code{'subcellular'} loads the transcript +#' coordinates only. \code{'aggregate'} loads the provided aggregated expression matrix. +#' @param FOVs field of views to load (only affects subcellular data and images) +#' @inheritParams createGiottoObjectSubcellular +#' @return a giotto object +#' @export +#' @details +#' [\strong{Expected Directory}] This function generates a giotto object when given a +#' link to a cosmx output directory. It expects the following items within the directory +#' where the \strong{bolded} portions are what this function matches against: +#' \itemize{ +#' \item{\strong{CellComposite} (folder of images)} +#' \item{\strong{CellLabels} (folder of images)} +#' \item{\strong{CellOverlay} (folder of images)} +#' \item{\strong{CompartmentLabels} (folder of images)} +#' \item{experimentname_\strong{exprMat_file}.csv (file)} +#' \item{experimentname_\strong{fov_positions_file}.csv (file)} +#' \item{experimentname_\strong{metadata_file}.csv (file)} +#' \item{experimentname_\strong{tx_file}.csv (file)} +#' } +#' +#' [\strong{Workflows}] Workflow to use is accessed through the data_to_use param +#' \itemize{ +#' \item{'all' - loads and requires subcellular information from tx_file and fov_positions_file +#' and also the existing aggregated information (expression, spatial locations, and metadata) +#' from exprMat_file and metadata_file.} +#' \item{'subcellular' - loads and requires subcellular information from tx_file and +#' fov_positions_file only.} +#' \item{'aggregate' - loads and requires the existing aggregate information (expression, +#' spatial locations, and metadata) from exprMat_file and metadata_file.} +#' } +#' +#' [\strong{Images}] Images in the default CellComposite, CellLabels, CompartmentLabels, and CellOverlay +#' folders will be loaded as giotto largeImage objects in all workflows as long as they are available. +#' Additionally, CellComposite images will be converted to giotto image objects, making plotting with +#' these image objects more responsive when accessing them from a server. +#' \code{\link{showGiottoImageNames}} can be used to see the available images. +#' +#' +createGiottoCosMxObject = function(cosmx_dir = NULL, + data_to_use = c('all','subcellular','aggregate'), + FOVs = NULL, + instructions = NULL, + cores = NA, + verbose = TRUE) { + + # 0. setup + # set number of cores automatically, but with limit of 10 + cores = determine_cores(cores) + data.table::setDTthreads(threads = cores) + + # determine data to use + data_to_use = match.arg(arg = data_to_use, choices = c('all','subcellular','aggregate')) + + # Define for data.table + fov = target = x_local_px = y_local_px = z = cell_ID = CenterX_global_px = CenterY_global_px = + CenterX_local_px = CenterY_local_px = NULL + + + # 1. test if folder structure exists and is as expected + dir_items = read_cosmx_folder(cosmx_dir = cosmx_dir, + verbose = verbose) + + + # 2. load and create giotto object + if(data_to_use == 'subcellular') { + + cosmx_gobject = createGiottoCosMxObject_subcellular(dir_items, + FOVs = FOVs, + cores = cores, + verbose = verbose, + instructions = instructions) + + } + + if(data_to_use == 'aggregate') { + + cosmx_gobject = createGiottoCosMxObject_aggregate(dir_items, + cores = cores, + verbose = verbose, + instructions = instructions) + + } + + if(data_to_use == 'all') { + + cosmx_gobject = createGiottoCosMxObject_all(dir_items, + FOVs = FOVs, + cores = cores, + verbose = verbose, + instructions = instructions) + + } + + + # load in subcellular information, subcellular FOV objects, then join + + + # load in pre-generated aggregated expression matrix + if(data_to_use == 'aggregate' | data_to_use == 'all') { + + } + + + + message('done') + return(cosmx_gobject) + +} + + + +#' @title Load and create a CosMx Giotto object from subcellular info +#' @name createGiottoCosMxObject_subcellular +#' @inheritParams createGiottoCosMxObject +#' @keywords internal +createGiottoCosMxObject_subcellular = function(dir_items, + FOVs = NULL, + cores, + verbose = TRUE, + instructions = NULL) { + + # load tx detections and FOV offsets + data_list = load_cosmx_folder_subcellular(dir_items = dir_items, + FOVs = FOVs, + cores = cores, + verbose = verbose) + + # unpack data_list + FOV_ID = data_list$FOV_ID + fov_offset_file = data_list$fov_offset_file + tx_coord_all = data_list$tx_coord_all + + # remove global xy values and cell_ID + tx_coord_all[, c('x_global_px', 'y_global_px', 'cell_ID') := NULL] + + data.table::setcolorder(tx_coord_all, c('target', 'x_local_px', 'y_local_px', 'z', 'fov')) + + if(isTRUE(verbose)) wrap_msg('Splitting detections by feature vs neg probe') + all_IDs = tx_coord_all[, unique(target)] + neg_IDs = all_IDs[grepl(pattern = 'NegPrb', all_IDs)] + feat_IDs = all_IDs[!all_IDs %in% neg_IDs] + + # split detections DT + feat_coords_all = tx_coord_all[target %in% feat_IDs] + neg_coords_all = tx_coord_all[target %in% neg_IDs] + + if(isTRUE(verbose)) { + message(' > Features: ', feat_coords_all[, .N]) + message(' > NegProbes: ', neg_coords_all[, .N]) + } + + # Start FOV lapply + fov_gobjects_list = lapply(FOV_ID, function(x) { + + # Build image paths + if(isTRUE(verbose)) message('Loading image information...') + + composite_dir = Sys.glob(paths = file.path(dir_items$`CellComposite folder`, paste0('*',x, '*'))) + cellLabel_dir = Sys.glob(paths = file.path(dir_items$`CellLabels folder`, paste0('*',x, '*'))) + compartmentLabel_dir = Sys.glob(paths = file.path(dir_items$`CompartmentLabels folder`, paste0('*',x, '*'))) + cellOverlay_dir = Sys.glob(paths = file.path(dir_items$`CellOverlay folder`, paste0('*',x, '*'))) + # Missing warnings + if(length(composite_dir) == 0) {warning('[ FOV ', x, ' ] No composite images found') ; composite_dir = NULL} + if(length(cellLabel_dir) == 0) {stop('[ FOV ', x, ' ] No cell mask images found')} # cell masks are necessary + if(length(compartmentLabel_dir) == 0) {warning('[ FOV ', x, ' ] No compartment label images found') ; compartmentLabel_dir = NULL} + if(length(cellOverlay_dir) == 0) {warning('[ FOV ', x, ' ] No cell polygon overlay images found') ; cellOverlay_dir = NULL} + + if(isTRUE(verbose)) message('Image load done') + + if(isTRUE(verbose)) wrap_msg('[ FOV ', x, ']') + + # get FOV specific tx locations + if(isTRUE(verbose)) wrap_msg('Assigning FOV feature detections...') + + + # feature info + coord_oldnames = c('target', 'x_local_px', 'y_local_px') + coord_newnames = c('feat_ID', 'x', 'y') + + feat_coord = feat_coords_all[fov == as.numeric(x)] + data.table::setnames(feat_coord, old = coord_oldnames, new = coord_newnames) + # neg probe info + neg_coord = neg_coords_all[fov == as.numeric(x)] + data.table::setnames(neg_coord, old = coord_oldnames, new = coord_newnames) + + + # build giotto object + if(isTRUE(verbose)) wrap_msg('Building subcellular giotto object...') + fov_subset = createGiottoObjectSubcellular( + gpoints = list('rna' = feat_coord, + 'neg_probe' = neg_coord), + gpolygons = list('cell' = cellLabel_dir), + polygon_mask_list_params = list( + mask_method = 'guess', + flip_vertical = TRUE, + flip_horizontal = FALSE, + shift_horizontal_step = FALSE + ), + instructions = instructions, + cores = cores + ) + + + # find centroids as spatial locations + if(isTRUE(verbose)) wrap_msg('Finding polygon centroids as cell spatial locations...') + fov_subset = addSpatialCentroidLocations(fov_subset, + poly_info = 'cell', + spat_loc_name = 'raw') + + + # create and add giotto image objects + if(isTRUE(verbose)) message('Attaching image files...') + print(composite_dir) + print(cellOverlay_dir) + print(compartmentLabel_dir) + + gImage_list = list() + + # load image if files are found + if(!is.null(composite_dir)) + gImage_list$composite = createGiottoLargeImage(raster_object = composite_dir, + negative_y = F, + name = 'composite') + if(!is.null(cellOverlay_dir)) + gImage_list$overlay = createGiottoLargeImage(raster_object = cellOverlay_dir, + negative_y = F, + name = 'overlay') + if(!is.null(compartmentLabel_dir)) + gImage_list$compartment = createGiottoLargeImage(raster_object = compartmentLabel_dir, + negative_y = F, + name = 'compartment') #TODO + + + + if(length(gImage_list) > 0) { + fov_subset = addGiottoImage(gobject = fov_subset, + largeImages = gImage_list) + + # convert to MG for faster loading (particularly relevant for pulling from server) + fov_subset = convertGiottoLargeImageToMG(giottoLargeImage = gImage_list$composite, + gobject = fov_subset, + return_gobject = TRUE, + verbose = FALSE) + # fov_subset = convertGiottoLargeImageToMG(giottoLargeImage = gImage_list$overlay, gobject = fov_subset, return_gobject = TRUE) + # fov_subset = convertGiottoLargeImageToMG(giottoLargeImage = gImage_list$compartment, gobject = fov_subset, return_gobject = TRUE) + } else { + message('No images found for fov') + } + + + }) #lapply end + + if(length(FOVs) == 1) { + return(fov_gobjects_list[[1]]) + } else { + # join giotto objects according to FOV positions file + if(isTRUE(verbose)) message('Joining FOV gobjects...') + new_gobj_names = paste0('fov', FOV_ID) + id_match = match(as.numeric(FOV_ID), fov_offset_file$fov) + x_shifts = fov_offset_file[id_match]$x_global_px + y_shifts = fov_offset_file[id_match]$y_global_px + # Join giotto objects + cosmx_gobject = joinGiottoObjects(gobject_list = fov_gobjects_list, + gobject_names = new_gobj_names, + join_method = 'shift', + x_shift = x_shifts, + y_shift = y_shifts) + return(cosmx_gobject) + } + +} + + + +#' @title Load and create a CosMx Giotto object from aggregate info +#' @name createGiottoCosMxObject_aggregate +#' @inheritParams createGiottoCosMxObject +#' @keywords internal +createGiottoCosMxObject_aggregate = function(dir_items, + cores, + verbose = TRUE, + instructions = NULL) { + + + + data_list = load_cosmx_folder_aggregate(dir_items = dir_items, + cores = cores, + verbose = verbose) + + # unpack data_list + spatlocs = data_list$spatlocs + spatlocs_fov = data_list$spatlocs_fov + metadata = data_list$metadata + protM = data_list$protM + spM = data_list$spM + fov_shifts = data_list$fov_shifts + + + # create standard gobject from aggregate matrix + if(data_to_use == 'aggregate') { + + # Create aggregate gobject + if(isTRUE(verbose)) message('Building giotto object...') + cosmx_gobject = createGiottoObject(expression = list('raw' = spM, 'protein' = protM), + cell_metadata = list('cell' = list('rna' = metadata, + 'protein' = metadata)), + spatial_locs = spatlocs, + instructions = instructions, + cores = cores) + + + # load in images + img_ID = data.table::data.table(fov = fov_shifts[, fov], + img_name = paste0('fov', sprintf('%03d', fov_shifts[, fov]), '-image')) + + if(isTRUE(verbose)) message('Attaching image files...') + composite_dir = Sys.glob(paths = file.path(dir_items$`CellComposite folder`, paste0('/*'))) + cellLabel_dir = Sys.glob(paths = file.path(dir_items$`CellLabels folder`, paste0('/*'))) + compartmentLabel_dir = Sys.glob(paths = file.path(dir_items$`CompartmentLabels folder`, paste0('/*'))) + overlay_dir = Sys.glob(paths = file.path(dir_items$`CellOverlay folder`, paste0('/*'))) + + if(length(cellLabel_imgList) > 0) cellLabel_imgList = lapply(cellLabel_dir, function(x) {createGiottoLargeImage(x,name = 'cellLabel',negative_y = TRUE)}) + if(length(composite_imgList) > 0) composite_imgList = lapply(composite_dir, function(x) {createGiottoLargeImage(x,name = 'composite',negative_y = TRUE)}) + if(length(compartmentLabel_dir) > 0) compartmentLabel_imgList = lapply(compartmentLabel_dir, function(x) {createGiottoLargeImage(x,name = 'composite',negative_y = TRUE)}) + if(length(overlay_dir) > 0) overlay_imgList = lapply(overlay_dir, function(x) {createGiottoLargeImage(x,name = 'composite',negative_y = TRUE)}) + + + + } + +} + + + + +#' @title Load and create a CosMx Giotto object from subcellular and aggregate info +#' @name createGiottoCosMxObject_all +#' @param dir_items list of full directory paths from \code{read_cosmx_folder} +#' @inheritParams createGiottoCosMxObject +#' @details Both \emph{subcellular} (subellular transcript detection information) and +#' \emph{aggregate} (aggregated detection count matrices by cell polygon from NanoString) +#' data will be loaded in. The two will be separated into 'cell' and 'cell_agg' +#' spatial units in order to denote the difference in origin of the two. +#' @seealso createGiottoCosMxObject createGiottoCosMxObject_aggregate +#' createGiottoCosMxObject_subcellular +#' @keywords internal +createGiottoCosMxObject_all = function(dir_items, + FOVs, + cores, + verbose = TRUE, + instructions = NULL) { + + # 1. create subcellular giotto as spat_unit 'cell' + cosmx_gobject = createGiottoCosMxObject_subcellular(dir_items = dir_items, + FOVs = FOVs, + cores = cores, + verbose = verbose, + instructions = instructions) + + # 2. load and append aggregated information in spat_unit 'cell_agg' + agg_data = load_cosmx_folder_aggregate(dir_items = dir_items, + cores = cores, + verbose = verbose) + + # unpack data_list + spatlocs = agg_data$spatlocs + spatlocs_fov = agg_data$spatlocs_fov + metadata = agg_data$metadata + protM = agg_data$protM + spM = agg_data$spM + + # add in pre-generated aggregated expression matrix information for 'all' workflow + + # Add aggregate expression information + if(isTRUE(verbose)) wrap_msg('Appending provided aggregate expression data as... + spat_unit: "cell_agg" + feat_type: "rna" + name: "raw"') + # add expression data to expression slot + s4_expr = create_expr_obj(name = 'raw', + exprMat = spM, + spat_unit = 'cell_agg', + feat_type = 'rna', + provenance = 'cell_agg') + + cosmx_gobject = set_expression_values(cosmx_gobject, values = s4_expr) + + # Add spatial locations + if(isTRUE(verbose)) wrap_msg('Appending metadata provided spatial locations data as... + --> spat_unit: "cell_agg" name: "raw" + --> spat_unit: "cell" name: "raw_fov"') + if(isTRUE(verbose)) wrap_msg('Polygon centroid derived spatial locations assigned as... + --> spat_unit: "cell" name: "raw" (default)') + + locsObj = create_spat_locs_obj(name = 'raw', + coordinates = spatlocs, + spat_unit = 'cell_agg', + provenance = 'cell_agg') + locsObj_fov = create_spat_locs_obj(name = 'raw_fov', + coordinates = spatlocs_fov, + spat_unit = 'cell_agg', + provenance = 'cell_agg') + + cosmx_gobject = set_spatial_locations(cosmx_gobject, spatlocs = locsObj) + cosmx_gobject = set_spatial_locations(cosmx_gobject, spatlocs = locsObj_fov) + + # cosmx_gobject = set_spatial_locations(cosmx_gobject, + # spat_unit = 'cell_agg', + # spat_loc_name = 'raw', + # spatlocs = spatlocs) + # cosmx_gobject = set_spatial_locations(cosmx_gobject, + # spat_unit = 'cell_agg', + # spat_loc_name = 'raw_fov', + # spatlocs = spatlocs_fov) + + # initialize cell and feat IDs and metadata slots for 'cell_agg' spat_unit + agg_cell_ID = colnames(s4_expr[]) + agg_feat_ID = rownames(s4_expr[]) + + sub_feat_ID = get_feat_id(cosmx_gobject, feat_type = 'rna') + feat_ID_new = unique(c(agg_feat_ID, sub_feat_ID)) + + cosmx_gobject = set_cell_id(gobject = cosmx_gobject, + spat_unit = 'cell_agg', + cell_IDs = agg_cell_ID) + cosmx_gobject = set_feat_id(gobject = cosmx_gobject, + feat_type = 'rna', + feat_IDs = feat_ID_new) + + # cell metadata + + # cosmx_gobject@cell_ID[['cell_agg']] = colnames(cosmx_gobject@expression[['cell_agg']][[1]][[1]]) + # cosmx_gobject@feat_ID[['rna']] = unique(c(cosmx_gobject@feat_ID, rownames(cosmx_gobject@expression[['cell_agg']][['rna']][[1]]))) + # cosmx_gobject@cell_metadata[['cell_agg']][['rna']] = data.table::data.table(cell_ID = cosmx_gobject@cell_ID[['cell_agg']]) + # cosmx_gobject@feat_metadata[['cell_agg']][['rna']] = data.table::data.table(feat_ID = cosmx_gobject@feat_ID[['rna']]) + + # Add metadata to both the given and the poly spat_units + if(isTRUE(verbose)) message('Appending provided cell metadata...') + cosmx_gobject = addCellMetadata(cosmx_gobject, + spat_unit = 'cell', + feat_type = 'rna', + new_metadata = metadata, + by_column = TRUE, + column_cell_ID = 'cell_ID') + cosmx_gobject = addCellMetadata(cosmx_gobject, + spat_unit = 'cell_agg', + feat_type = 'rna', + new_metadata = metadata, + by_column = TRUE, + column_cell_ID = 'cell_ID') + +} + + + + + + + + + + +## Xenium #### + +#' @title Create 10x Xenium Giotto Object +#' @name createGiottoXeniumObject +#' @description Given the path to a Xenium experiment output folder, creates a Giotto +#' object +#' @param xenium_dir full path to the exported xenium directory +#' @param data_to_use which type(s) of expression data to build the gobject with +#' (e.g. default: \strong{'subcellular'}, 'aggregate', or 'all') +#' @param load_format files formats from which to load the data. Either `csv` or +#' `parquet` currently supported. +#' @param h5_expression (boolean) whether to load cell_feature_matrix from .h5 file. +#' Default is \code{TRUE} +#' @param h5_gene_ids use gene symbols (default) or ensembl ids for the .h5 gene +#' expression matrix +#' @param bounds_to_load vector of boundary information to load (e.g. \code{'cell'} +#' or \code{'nucleus'} by themselves or \code{c('cell', 'nucleus')} to load both +#' at the same time.) +#' @param qv_threshold Minimum Phred-scaled quality score cutoff to be included as +#' a subcellular transcript detection (default = 20) +#' @param key_list (advanced) list of grep-based keywords to split the subcellular +#' feature detections by feature type. See details +#' @inheritParams get10Xmatrix +#' @inheritParams createGiottoObjectSubcellular +#' @details +#' +#' [\strong{QC feature types}] +#' Xenium provides info on feature detections that include more than only the +#' Gene Expression specific probes. Additional probes for QC are included: +#' \emph{blank codeword}, \emph{negative control codeword}, and +#' \emph{negative control probe}. These additional QC probes each occupy and are treated +#' as their own feature types so that they can largely remain independent of the +#' gene expression information. +#' +#' [\strong{key_list}] +#' Related to \code{data_to_use = 'subcellular'} workflow only: +#' Additional QC probe information is in the subcellular feature detections information +#' and must be separated from the gene expression information during processing. +#' The QC probes have prefixes that allow them to be selected from the rest of the +#' feature IDs. +#' Giotto uses a named list of keywords (\code{key_list}) to select these QC probes, +#' with the list names being the names that will be assigned as the feature type +#' of these feature detections. The default list is used when \code{key_list} = NULL. +#' +#' Default list: +#' \preformatted{ +#' list(blank_code = 'BLANK_', +#' neg_code = 'NegControlCodeword_', +#' neg_probe = c('NegControlProbe_|antisense_')) +#' } +#' +#' The Gene expression subset is accepted as the subset of feat_IDs that do not +#' map to any of the keys. +#' +#' @export +createGiottoXeniumObject = function(xenium_dir, + data_to_use = c('subcellular','aggregate'), + load_format = 'csv', + h5_expression = TRUE, + h5_gene_ids = c('symbols', 'ensembl'), + gene_column_index = 1, + bounds_to_load = c('cell'), + qv_threshold = 20, + key_list = NULL, + # include_analysis = FALSE, + instructions = NULL, + cores = NA, + verbose = TRUE) { + + # 0. setup + + # Determine data to load + data_to_use = match.arg(arg = data_to_use, choices = c('subcellular','aggregate')) + + # Determine load formats + load_format = 'csv' # TODO Remove this and add as param once other options are available + load_format = match.arg(arg = load_format, choices = c('csv', 'parquet', 'zarr')) + + # set number of cores automatically, but with limit of 10 + cores = determine_cores(cores) + data.table::setDTthreads(threads = cores) + + # 1. detect xenium folder and find filepaths to load + + # path_list contents: + # tx_path + # bound_paths + # cell_meta_path + # agg_expr_path + # panel_meta_path + path_list = read_xenium_folder(xenium_dir = xenium_dir, + data_to_use = data_to_use, + bounds_to_load = bounds_to_load, + load_format = load_format, + h5_expression = h5_expression, + verbose = verbose) + + + # 2. load in data + + # data_list contents: + # feat_meta + # tx_dt + # bound_dt_list + # cell_meta + # agg_expr + data_list = load_xenium_folder(path_list = path_list, + load_format = load_format, + data_to_use = data_to_use, + h5_expression = h5_expression, + h5_gene_ids = h5_gene_ids, + gene_column_index = gene_column_index, + cores = cores, + verbose = verbose) + + + # TODO load images + + + # 3. Create giotto objects + + if(data_to_use == 'subcellular') { + + # ** feat type search keys ** + if(is.null(key_list)) { + key_list = list(blank_code = 'BLANK_', + neg_code = 'NegControlCodeword_', + neg_probe = c('NegControlProbe_|antisense_')) + } + + # needed: + # feat_meta + # tx_dt + # bound_dt_list + xenium_gobject = createGiottoXeniumObject_subcellular(data_list = data_list, + qv_threshold = qv_threshold, + key_list = key_list, + instructions = instructions, + cores = cores, + verbose = verbose) + + } + + if(data_to_use == 'aggregate') { + + # needed: + # feat_meta + # cell_meta + # agg_expr + # optional? + # tx_dt + # bound_dt_list + xenium_gobject = createGiottoXeniumObject_aggregate(data_list = data_list, + instructions = instructions, + cores = cores, + verbose = verbose) + + } + + return(xenium_gobject) + +} + + + + +#' @title Create a Xenium Giotto object from subcellular info +#' @name createGiottoXeniumObject_subcellular +#' @description Subcellular workflow for createGiottoXeniumObject +#' @param data_list list of data loaded by \code{\link{load_xenium_folder}} +#' @param key_list regex-based search keys for feature IDs to allow separation +#' into separate giottoPoints objects by feat_type +#' @param qv_threshold Minimum Phred-scaled quality score cutoff to be included as +#' a subcellular transcript detection (default = 20) +#' @inheritParams get10Xmatrix +#' @inheritParams createGiottoObjectSubcellular +#' @seealso createGiottoXeniumObject createGiottoXeniumObject_aggregate +#' @keywords internal +createGiottoXeniumObject_subcellular = function(data_list, + key_list = NULL, + qv_threshold = 20, + instructions = NULL, + cores = NA, + verbose = TRUE) { + + # Unpack data_list info + feat_meta = data_list$feat_meta + tx_dt = data_list$tx_dt + bound_dt_list = data_list$bound_dt_list + # cell_meta = data_list$cell_meta + # agg_expr = data_list$agg_expr + + # define for data.table + cell_id = feat_ID = feature_name = NULL + + if(isTRUE(verbose)) message('Building subcellular giotto object...') + # Giotto points object + if(isTRUE(verbose)) message('> points data prep...') + + # filter by qv_threshold + if(isTRUE(verbose)) wrap_msg('> filtering feature detections for Phred score >= ', qv_threshold) + n_before = tx_dt[,.N] + tx_dt_filtered = tx_dt[qv >= qv_threshold] + n_after = tx_dt_filtered[,.N] + + cat('Number of feature points removed: ', + n_before - n_after, + ' out of ', n_before, '\n') + + if(isTRUE(verbose)) message('> splitting detections by feat_type') + # discover feat_IDs for each feat_type + all_IDs = tx_dt_filtered[, unique(feat_ID)] + feat_types_IDs = lapply(key_list, function(x) all_IDs[grepl(pattern = x, all_IDs)]) + rna = list('rna' = all_IDs[!all_IDs %in% unlist(feat_types_IDs)]) + feat_types_IDs = append(rna, feat_types_IDs) + + # separate detections by feature type + points_list = lapply( + feat_types_IDs, + function(types) { + tx_dt_filtered[feat_ID %in% types] + } + ) + + # Giotto polygons object + if(isTRUE(verbose)) message('> polygons data prep...') + polys_list = lapply( + bound_dt_list, + function(bound_type) { + bound_type[, cell_id := as.character(cell_id)] + } + ) + + xenium_gobject = createGiottoObjectSubcellular(gpoints = points_list, + gpolygons = polys_list, + instructions = instructions, + cores = cores, + verbose = verbose) + + # generate centroids + if(isTRUE(verbose)) message('Calculating polygon centroids...') + xenium_gobject = addSpatialCentroidLocations(xenium_gobject, + poly_info = c(names(bound_dt_list))) + + # add in feature metadata + # xenium_gobject = addFeatMetadata(gobject = xenium_gobject, + # new_metadata = feat_meta, + # by_column = TRUE, + # column_feat_ID = 'feat_ID') + + return(xenium_gobject) + +} + + + + + +#' @title Create a Xenium Giotto object from aggregate info +#' @name createGiottoXeniumObject_aggregate +#' @description Aggregate workflow for createGiottoXeniumObject +#' @param data_list list of data loaded by \code{load_xenium_folder} +#' @inheritParams get10Xmatrix +#' @inheritParams createGiottoObjectSubcellular +#' @seealso createGiottoXeniumObject createGiottoXeniumObject_subcellular +#' @keywords internal +createGiottoXeniumObject_aggregate = function(data_list, + # include_analysis = FALSE, + instructions = NULL, + cores = NA, + verbose = TRUE) { + + # Unpack data_list info + feat_meta = data_list$feat_meta + # tx_dt = data_list$tx_dt + # bound_dt_list = data_list$bound_dt_list + cell_meta = data_list$cell_meta + agg_expr = data_list$agg_expr + + # define for data.table + cell_ID = x_centroid = y_centroid = NULL + + # clean up names for aggregate matrices + names(agg_expr) = gsub(pattern = ' ', replacement = '_' ,names(agg_expr)) + geneExpMat = which(names(agg_expr) == 'Gene_Expression') + names(agg_expr)[[geneExpMat]] = 'raw' + + # set cell_id as character + cell_meta = cell_meta[, data.table::setnames(.SD, 'cell_id', 'cell_ID')] + cell_meta = cell_meta[, cell_ID := as.character(cell_ID)] + + # set up spatial locations + agg_spatlocs = cell_meta[, .(x_centroid, y_centroid, cell_ID)] + + # set up metadata + agg_meta = cell_meta[, !c('x_centroid','y_centroid')] + + if(isTRUE(verbose)) message('Building aggregate giotto object...') + xenium_gobject = createGiottoObject(expression = agg_expr, + spatial_locs = agg_spatlocs, + instructions = instructions, + cores = cores, + verbose = verbose) + + # append aggregate metadata + xenium_gobject = addCellMetadata(gobject = xenium_gobject, + new_metadata = agg_meta, + by_column = TRUE, + column_cell_ID = 'cell_ID') + xenium_gobject = addFeatMetadata(gobject = xenium_gobject, + new_metadata = feat_meta, + by_column = TRUE, + column_feat_ID = 'feat_ID') + + return(xenium_gobject) + +} + + + + + + + +# folder reading and detection #### + + + + +#' @describeIn read_data_folder Read a structured MERSCOPE folder +#' @keywords internal +read_merscope_folder = function(merscope_dir, + data_to_use, + cores = NA, + verbose = TRUE) { + + # prepare dir_items list + dir_items = list(`boundary info` = '*cell_boundaries*', + `image info` = '*images*', + `cell feature matrix` = '*cell_by_gene*', + `cell metadata` = '*cell_metadata*', + `raw transcript info` = '*transcripts*') + + # prepare require_data_DT + sub_reqs = data.table::data.table(workflow = c('subcellular'), + item = c('boundary info', + 'raw transcript info', + 'image info', + 'cell by gene matrix', + 'cell metadata'), + needed = c(TRUE, TRUE, FALSE, FALSE, FALSE)) + + agg_reqs = data.table::data.table(workflow = c('aggregate'), + item = c('boundary info', + 'raw transcript info', + 'image info', + 'cell by gene matrix', + 'cell metadata'), + needed = c(FALSE, FALSE, FALSE, TRUE, TRUE)) + + require_data_DT = rbind(sub_reqs, agg_reqs) + + dir_items = read_data_folder(spat_method = 'MERSCOPE', + data_dir = merscope_dir, + dir_items = dir_items, + data_to_use = data_to_use, + require_data_DT = require_data_DT, + cores = cores, + verbose = verbose) + + return(dir_items) + +} + + + +#' @title Read a structured CosMx folder +#' @name read_cosmx_folder +#' @inheritParams createGiottoCosMxObject +#' @seealso createGiottoCosMxObject load_cosmx_folder +#' @return path_list a list of cosmx files discovered and their filepaths. NULL +#' values denote missing items +#' @keywords internal +read_cosmx_folder = function(cosmx_dir, + verbose = TRUE) { + + ch = box_chars() + + if(is.null(cosmx_dir) | !dir.exists(cosmx_dir)) stop('The full path to a cosmx directory must be given.\n') + if(isTRUE(verbose)) wrap_msg('A structured CosMx directory will be used\n') + + # find directories (length = 1 if present, length = 0 if missing) + dir_items = list(`CellLabels folder` = '*CellLabels', + `CompartmentLabels folder` = '*CompartmentLabels', + `CellComposite folder` = '*CellComposite', + `CellOverlay folder` = '*CellOverlay', + `transcript locations file` = '*tx_file*', + `fov positions file` = '*fov_positions_file*', + `expression matrix file` = '*exprMat_file*', + `metadata file` = '*metadata_file*') + dir_items = lapply(dir_items, function(x) Sys.glob(paths = file.path(cosmx_dir, x))) + dir_items_lengths = lengths(dir_items) + + if(isTRUE(verbose)) { + message('Checking directory contents...') + for(item in names(dir_items)) { + if(dir_items_lengths[[item]] > 0) { + message(ch$s, '> ' ,item, ' found') + } else { + warning(item, ' is missing\n') + } + } + } + + # select first directory in list if multiple are detected + if(any(dir_items_lengths > 1)) { + warning('Multiple matches for expected subdirectory item(s).\n First matching item selected') + + multiples = which(dir_items_lengths > 1) + for(mult_i in multiples) { + message(names(dir_items)[[mult_i]], 'multiple matches found:') + print(dir_items[[mult_i]]) + dir_items[[mult_i]] = dir_items[[mult_i]][[1]] + } + } + if(isTRUE(verbose)) message('Directory check done') + + return(dir_items) + +} + + + + +#' @title Read a structured xenium folder +#' @name read_xenium_folder +#' @inheritParams createGiottoXeniumObject +#' @keywords internal +#' @return path_list a list of xenium files discovered and their filepaths. NULL +#' values denote missing items +read_xenium_folder = function(xenium_dir, + data_to_use = 'subcellular', + bounds_to_load = c('cell'), + load_format = 'csv', + h5_expression = FALSE, + verbose = TRUE) { + + # Check needed packages + if(load_format == 'parquet') { + package_check(pkg_name = 'arrow', repository = 'CRAN') + package_check(pkg_name = 'dplyr', repository = 'CRAN') + } + if(isTRUE(h5_expression)) { + package_check(pkg_name = 'hdf5r', repository = 'CRAN') + } + + ch = box_chars() + + + # 0. test if folder structure exists and is as expected + + + if(is.null(xenium_dir) | !dir.exists(xenium_dir)) stop('The full path to a xenium directory must be given.\n') + if(isTRUE(verbose)) message('A structured Xenium directory will be used\n') + + # find items (length = 1 if present, length = 0 if missing) + dir_items = list(`analysis info` = '*analysis*', + `boundary info` = '*bound*', + `cell feature matrix` = '*cell_feature_matrix*', + `cell metadata` = '*cells*', + `image info` = '*tif', + `panel metadata` = '*panel*', + `raw transcript info` = '*transcripts*', + `experiment info (.xenium)` = '*.xenium') + + dir_items = lapply(dir_items, function(x) Sys.glob(paths = file.path(xenium_dir, x))) + dir_items_lengths = lengths(dir_items) + + if(isTRUE(verbose)) { + message('Checking directory contents...') + for(item in names(dir_items)) { + + # IF ITEM FOUND + + if(dir_items_lengths[[item]] > 0) { + message(ch$s, '> ' ,item, ' found') + for(item_i in seq_along(dir_items[[item]])) { # print found item names + subItem = gsub(pattern = '.*/', replacement = '', x = dir_items[[item]][[item_i]]) + message(ch$s, ch$s, ch$l,ch$h,ch$h, subItem) + } + } else { + + # IF ITEM MISSING + # Based on workflow, determine if: + # necessary (error) + # optional (warning) + + if(data_to_use == 'subcellular') { + # necessary items + if(item %in% c('boundary info', 'raw transcript info')) stop(item, ' is missing\n') + # optional items + if(item %in% c('image info', 'experiment info (.xenium)', 'panel metadata')) warning(item, ' is missing (optional)\n') + # items to ignore: analysis info, cell feature matrix, cell metadata + } else if(data_to_use == 'aggregate') { + # necessary items + if(item %in% c('cell feature matrix', 'cell metadata')) stop(item, ' is missing\n') + # optional items + if(item %in% c('image info', 'experiment info (.xenium)', 'panel metadata', 'analysis info')) warning(item, ' is missing (optional)\n') + # items to ignore: boundary info, raw transcript info + } + } + } + } + + + # 1. Select data to load + + + # **** transcript info **** + tx_path = NULL + tx_path = dir_items$`raw transcript info`[grepl(pattern = load_format, dir_items$`raw transcript info`)] + # **** cell metadata **** + cell_meta_path = NULL + cell_meta_path = dir_items$`cell metadata`[grepl(pattern = load_format, dir_items$`cell metadata`)] + + # **** boundary info **** + # Select bound load format + if(load_format != 'zarr') { # No zarr available for boundary info + dir_items$`boundary info` = dir_items$`boundary info`[grepl(pattern = load_format, dir_items$`boundary info`)] + } else dir_items$`boundary info` = dir_items$`boundary info`[grepl(pattern = 'csv', dir_items$`boundary info`)] + + # Organize bound paths by type of bound (bounds_to_load param) + bound_paths = NULL + bound_names = bounds_to_load + bounds_to_load = as.list(bounds_to_load) + bound_paths = lapply(bounds_to_load, function(x) dir_items$`boundary info`[grepl(pattern = x, dir_items$`boundary info`)]) + names(bound_paths) = bound_names + + # **** aggregated expression info **** + agg_expr_path = NULL + if(isTRUE(h5_expression)) { # h5 expression matrix loading is default + agg_expr_path = dir_items$`cell feature matrix`[grepl(pattern = 'h5', dir_items$`cell feature matrix`)] + h5_gene_ids = match.arg(arg = h5_gene_ids, choices = c('symbols', 'ensembl')) + } else if(load_format == 'zarr') { + agg_expr_path = dir_items$`cell feature matrix`[grepl(pattern = 'zarr', dir_items$`cell feature matrix`)] + } else { # No parquet for aggregated expression - default to normal 10x loading + agg_expr_path = dir_items$`cell feature matrix`[sapply(dir_items$`cell feature matrix`, function(x) file_test(op = '-d', x))] + if(length(agg_expr_path) == 0) stop(wrap_txt( + 'Expression matrix cannot be loaded.\nHas cell_feature_matrix(.tar.gz) been unpacked into a directory?' + )) + } + if(data_to_use == 'aggregate') { + if(length(path_list$agg_expr_path) == 0) stop(wrap_txt( + 'Aggregated expression not found.\nPlease confirm h5_expression and load_format params are correct\n' + )) + } + + # **** panel info **** + panel_meta_path = NULL + panel_meta_path = dir_items$`panel metadata` + + + if(isTRUE(verbose)) message('Directory check done') + + path_list = list('tx_path' = tx_path, + 'bound_paths' = bound_paths, + 'cell_meta_path' = cell_meta_path, + 'agg_expr_path' = agg_expr_path, + 'panel_meta_path' = panel_meta_path) + + return(path_list) + +} + + + + + + +# folder loading #### + + +## MERSCOPE #### + +#' @title Load MERSCOPE data from folder +#' @name load_merscope_folder +#' @param dir_items list of full filepaths from \code{\link{read_merscope_folder}} +#' @inheritParams createGiottoMerscopeObject +#' @keywords internal +#' @return list of loaded-in MERSCOPE data +load_merscope_folder = function(dir_items, + data_to_use, + fovs = NULL, + cores = NA, + verbose = TRUE) { + + # 1. load data_to_use-specific + if(data_to_use == 'subcellular') { + data_list = load_merscope_folder_subcellular(dir_items = dir_items, + data_to_use = data_to_use, + fovs = fovs, + cores = cores, + verbose = verbose) + } else if(data_to_use == 'aggregate') { + data_list = load_merscope_folder_aggregate(dir_items = dir_items, + data_to_use = data_to_use, + cores = cores, + verbose = verbose) + } else { + stop(wrap_txt('data_to_use "', data_to_use, '" not implemented', sep = '')) + } + + # 2. Load images if available + if(!is.null(dir_items$`image info`)) { + ## micron to px scaling factor + micronToPixelScale = Sys.glob(paths = file.path(dir_items$`image info`, '*micron_to_mosaic_pixel_transform*'))[[1]] + micronToPixelScale = data.table::fread(micronToPixelScale, nThread = cores) + # add to data_list + data_list$micronToPixelScale = micronToPixelScale + + ## staining images + ## determine types of stains + images_filenames = list.files(dir_items$`image info`) + bound_stains_filenames = images_filenames[grep(pattern = '.tif', images_filenames)] + bound_stains_types = sapply(strsplit(bound_stains_filenames, '_'), `[`, 2) + bound_stains_types = unique(bound_stains_types) + + img_list = lapply_flex(bound_stains_types, function(stype) { + img_paths = Sys.glob(paths = file.path(dir_items$`image info`, paste0('*',stype,'*'))) + # print(img_paths) + lapply_flex(img_paths, function(img) { + createGiottoLargeImage(raster_object = img) + }, cores = cores) + }, cores = cores) + # add to data_list + data_list$images = img_list + } + + + + return(data_list) + +} + + + +#' @describeIn load_merscope_folder Load items for 'subcellular' workflow +#' @keywords internal +load_merscope_folder_subcellular = function(dir_items, + data_to_use, + cores = NA, + verbose = TRUE, + fovs = NULL) { + + if(isTRUE(verbose)) wrap_msg('Loading transcript level info...') + tx_dt = data.table::fread(dir_items$dir_items$`raw transcript info`, nThread = cores) + + if(isTRUE(verbose)) wrap_msg('Loading polygon info...') + poly_info = readPolygonFilesVizgenHDF5(boundaries_path = dir_items$`boundary info`, + polygon_feat_types = c(0,6), + flip_y_axis = TRUE, + fovs = subsetFOVs) + + data_list = list( + 'poly_info' = poly_info, + 'tx_dt' = tx_dt, + 'micronToPixelScale' = NULL, + 'expr_mat' = NULL, + 'cell_meta' = NULL, + 'images' = NULL + ) + +} + + + +#' @describeIn load_merscope_folder Load items for 'aggregate' workflow +#' @keywords internal +load_merscope_folder_aggregate = function(dir_items, + data_to_use, + cores = NA, + verbose = TRUE) { + + # metadata is polygon-related measurements + if(isTRUE(verbose)) wrap_msg('Loading cell metadata...') + cell_metadata_file = data.table::fread(dir_items$`cell metadata`, nThread = cores) + # expr_mat contains Blank probes + if(isTRUE(verbose)) wrap_msg('Loading expression matrix') + expr_mat = data.table::fread(dir_items$`cell feature matrix`, nThread = cores) + + + data_list = list( + 'poly_info' = NULL, + 'tx_dt' = NULL, + 'micronToPixelScale' = NULL, + 'expr_mat' = expr_mat, + 'cell_meta' = cell_metadata_file, + 'images' = NULL + ) + +} + + + + + + + +## CosMx #### + +#' @title Load CosMx folder subcellular info +#' @name load_cosmx_folder_subcellular +#' @description loads in the feature detections information. Note that the mask +#' images are still required for a working subcellular object, and those are loaded +#' in \code{\link{createGiottoCosMxObject_subcellular}} +#' @inheritParams createGiottoCosMxObject +#' @keywords internal +load_cosmx_folder_subcellular = function(dir_items, + FOVs = NULL, + cores, + verbose = TRUE) { + + if(isTRUE(verbose)) wrap_msg('Loading subcellular information...') + + # subcellular checks + if(!file.exists(dir_items$`transcript locations file`)) + stop(wrap_txt('No transcript locations file (.csv) detected')) + if(!file.exists(dir_items$`fov positions file`)) + stop(wrap_txt('No fov positions file (.csv) detected')) + + # FOVs to load + if(isTRUE(verbose)) wrap_msg('Loading FOV offsets...') + fov_offset_file = fread(input = dir_items$`fov positions file`, nThread = cores) + if(is.null(FOVs)) FOVs = fov_offset_file$fov # default to ALL FOVs + FOV_ID = as.list(sprintf('%03d', FOVs)) + + #TODO Load only relevant portions of file? + + if(isTRUE(verbose)) wrap_msg('Loading transcript level info...') + tx_coord_all = fread(input = dir_items$`transcript locations file`, nThread = cores) + if(isTRUE(verbose)) wrap_msg('Subcellular load done') + + data_list = list( + 'FOV_ID' = FOV_ID, + 'fov_offset_file' = fov_offset_file, + 'tx_coord_all' = tx_coord_all + ) + + return(data_list) + +} + + + +#' @title Load CosMx folder aggregate info +#' @name load_cosmx_folder_aggregate +#' @inheritParams createGiottoCosMxObject +#' @keywords internal +load_cosmx_folder_aggregate = function(dir_items, + cores, + verbose = TRUE) { + + # load aggregate information + wrap_msg('Loading provided aggregated information...') + + # aggregate checks + if(!file.exists(dir_items$`expression matrix file`)) stop(wrap_txt('No expression matrix file (.csv) detected')) + if(!file.exists(dir_items$`metadata file`)) stop(wrap_txt('No metadata file (.csv) detected. Needed for cell spatial locations.')) + + # read in aggregate data + expr_mat = fread(input = dir_items$`expression matrix file`, nThread = cores) + metadata = fread(input = dir_items$`metadata file`, nThread = cores) + + # setorder expression and spatlocs + data.table::setorder(metadata, fov, cell_ID) + data.table::setorder(expr_mat, fov, cell_ID) + + + # generate unique cell IDs + expr_mat[, cell_ID := paste0('fov', sprintf('%03d', fov), '-', 'cell_', cell_ID)] + # expr_mat$cell_ID = paste0('fov', sprintf('%03d', expr_mat$fov), '-', 'cell_', expr_mat$cell_ID) + expr_mat = expr_mat[, fov := NULL] + + metadata[, fov_cell_ID := cell_ID] + metadata[, cell_ID := paste0('fov', sprintf('%03d', fov), '-', 'cell_', cell_ID)] + # metadata$cell_ID = paste0('fov', sprintf('%03d', metadata$fov), '-', 'cell_', metadata$cell_ID) + # reorder + data.table::setcolorder(x = metadata, c('cell_ID','fov','fov_cell_ID')) + + + # extract spatial locations + spatlocs = metadata[,.(CenterX_global_px, CenterY_global_px, cell_ID)] + spatlocs_fov = metadata[,.(CenterX_local_px, CenterY_local_px, cell_ID)] + # regenerate FOV shifts + metadata[, x_shift := CenterX_global_px - CenterX_local_px] + metadata[, y_shift := CenterY_global_px - CenterY_local_px] + fov_shifts = metadata[, .(mean(x_shift), mean(y_shift)), fov] + colnames(fov_shifts) = c('fov', 'x_shift', 'y_shift') + + + # rename spatloc column names + spatloc_oldnames = c('CenterX_global_px', 'CenterY_global_px', 'cell_ID') + spatloc_oldnames_fov = c('CenterX_local_px', 'CenterY_local_px', 'cell_ID') + spatloc_newnames = c('sdimx', 'sdimy', 'cell_ID') + data.table::setnames(spatlocs, old = spatloc_oldnames, new = spatloc_newnames) + data.table::setnames(spatlocs_fov, old = spatloc_oldnames_fov, new = spatloc_newnames) + + # cleanup metadata and spatlocs + metadata = metadata[,c('CenterX_global_px', 'CenterY_global_px', 'CenterX_local_px', 'CenterY_local_px') := NULL] + # find unique cell_IDs present in both expression and metadata + giotto_cell_ID = unique(intersect(expr_mat$cell_ID, metadata$cell_ID)) + + # subset to only unique cell_IDs + expr_mat = expr_mat[cell_ID %in% giotto_cell_ID,] + metadata = metadata[cell_ID %in% giotto_cell_ID,] + + + # convert protein metadata to expr mat + # take all mean intensity protein information except for MembraneStain and DAPI + protein_meta_cols = colnames(metadata) + protein_meta_cols = protein_meta_cols[grepl(pattern = 'Mean.*', x = protein_meta_cols)] + protein_meta_cols = protein_meta_cols[!protein_meta_cols %in% c('Mean.MembraneStain', 'Mean.DAPI')] + protein_meta_cols = c('cell_ID', protein_meta_cols) + + prot_expr = metadata[, protein_meta_cols, with = FALSE] + prot_cell_ID = metadata[, cell_ID] + protM = Matrix::Matrix(as.matrix(prot_expr[,-1]), dimnames = list(prot_expr[[1]], colnames(prot_expr[,-1])), sparse = FALSE) + protM = t_flex(protM) + + # convert expression to sparse matrix + spM = Matrix::Matrix(as.matrix(expr_mat[,-1]), dimnames = list(expr_mat[[1]], colnames(expr_mat[,-1])), sparse = TRUE) + spM = t_flex(spM) + + ## Ready for downstream aggregate gobject creation or appending into existing subcellular Giotto object ## + + data_list = list( + 'spatlocs' = spatlocs, + 'spatlocs_fov' = spatlocs_fov, + 'metadata' = metadata, + 'protM' = protM, + 'spM' = spM, + 'fov_shifts' = fov_shifts + ) + + return(data_list) + +} + + + + + + + +## Xenium #### + +#' @title Load xenium data from folder +#' @name load_xenium_folder +#' @param path_list list of full filepaths from read_xenium_folder +#' @inheritParams createGiottoXeniumObject +#' @keywords internal +#' @return list of loaded in xenium data +load_xenium_folder = function(path_list, + load_format = 'csv', + data_to_use = 'subcellular', + h5_expression = 'FALSE', + h5_gene_ids = 'symbols', + gene_column_index = 1, + cores, + verbose = TRUE) { + + if(load_format == 'csv') { + data_list = load_xenium_folder_csv(path_list = path_list, + data_to_use = data_to_use, + h5_expression = h5_expression, + h5_gene_ids = h5_gene_ids, + gene_column_index = gene_column_index, + cores = cores, + verbose = verbose) + } + + if(load_format == 'parquet') { + data_list = load_xenium_folder_parquet(path_list = path_list, + data_to_use = data_to_use, + h5_expression = h5_expression, + h5_gene_ids = h5_gene_ids, + gene_column_index = gene_column_index, + cores = cores, + verbose = verbose) + } + + if(load_format == 'zarr') { + # TODO + } + + + return(data_list) +} + + +#' @describeIn load_xenium_folder Load from csv files +#' @keywords internal +load_xenium_folder_csv = function(path_list, + cores, + data_to_use = 'subcellular', + h5_expression = FALSE, + h5_gene_ids = 'symbols', + gene_column_index = 1, + verbose = TRUE) { + + # initialize return vars + feat_meta = tx_dt = bound_dt_list = cell_meta = agg_expr = NULL + + if(isTRUE(verbose)) message('Loading feature metadata...') + feat_meta = data.table::fread(path_list$panel_meta_path[[1]], nThread = cores) + colnames(feat_meta)[[1]] = 'feat_ID' + + # **** subcellular info **** + if(data_to_use == 'subcellular') { + # append missing QC probe info to feat_meta + if(isTRUE(h5_expression)) { + h5 = hdf5r::H5File$new(path_list$agg_expr_path) + tryCatch({ + root = names(h5) + feature_id = h5[[paste0(root, "/features/id")]][] + feature_info = h5[[paste0(root,"/features/feature_type")]][] + feature_names = h5[[paste0(root, "/features/name")]][] + features_dt = data.table::data.table( + 'id' = feature_id, + 'name' = feature_names, + 'feature_type' = feature_info + ) + }, finally = { + h5$close_all() + }) + } else { + features_dt = data.table::fread(paste0(path_list$agg_expr_path, '/features.tsv.gz'), header = F) + } + colnames(features_dt) = c('id', 'feat_ID', 'feat_class') + feat_meta = merge(features_dt[,c(2,3)], feat_meta, all.x = TRUE, by = 'feat_ID') + + if(isTRUE(verbose)) message('Loading transcript level info...') + tx_dt = data.table::fread(path_list$tx_path[[1]], nThread = cores) + data.table::setnames(x = tx_dt, + old = c('feature_name', 'x_location', 'y_location'), + new = c('feat_ID', 'x', 'y')) + if(isTRUE(verbose)) message('Loading boundary info...') + bound_dt_list = lapply(path_list$bound_paths, function(x) data.table::fread(x[[1]], nThread = cores)) + } + + # **** aggregate info **** + if(isTRUE(verbose)) message('Loading cell metadata...') + cell_meta = data.table::fread(path_list$cell_meta_path[[1]], nThread = cores) + + if(data_to_use == 'aggregate') { + if(isTRUE(verbose)) message('Loading aggregated expression...') + if(isTRUE(h5_expression)) agg_expr = get10Xmatrix_h5(path_to_data = path_list$agg_expr_path, + gene_ids = h5_gene_ids, + remove_zero_rows = TRUE, + split_by_type = TRUE) + else agg_expr = get10Xmatrix(path_to_data = path_list$agg_expr_path, + gene_column_index = gene_column_index, + remove_zero_rows = TRUE, + split_by_type = TRUE) + } + + data_list = list( + 'feat_meta' = feat_meta, + 'tx_dt' = tx_dt, + 'bound_dt_list' = bound_dt_list, + 'cell_meta' = cell_meta, + 'agg_expr' = agg_expr + ) + + return(data_list) + +} + + + + +#' @describeIn load_xenium_folder Load from parquet files +#' @keywords internal +load_xenium_folder_parquet = function(path_list, + cores, + data_to_use = 'subcellular', + h5_expression = FALSE, + h5_gene_ids = 'symbols', + gene_column_index = 1, + verbose = TRUE) { + + # initialize return vars + feat_meta = tx_dt = bound_dt_list = cell_meta = agg_expr = NULL + + if(isTRUE(verbose)) message('Loading feature metadata...') + feat_meta = data.table::fread(path_list$panel_meta_path[[1]], nThread = cores) + colnames(feat_meta)[[1]] = 'feat_ID' + + # **** subcellular info **** + if(data_to_use == 'subcellular') { + + # define for data.table + transcript_id = feature_name = NULL + + # append missing QC probe info to feat_meta + if(isTRUE(h5_expression)) { + h5 = hdf5r::H5File$new(path_list$agg_expr_path) + tryCatch({ + root = names(h5) + feature_id = h5[[paste0(root, "/features/id")]][] + feature_info = h5[[paste0(root,"/features/feature_type")]][] + feature_names = h5[[paste0(root, "/features/name")]][] + features_dt = data.table::data.table( + 'id' = feature_id, + 'name' = feature_names, + 'feature_type' = feature_info + ) + }, finally = { + h5$close_all() + }) + } else { + features_dt = arrow::read_tsv_arrow(paste0(path_list$agg_expr_path, '/features.tsv.gz'), + col_names = FALSE) %>% + data.table::setDT() + } + colnames(features_dt) = c('id', 'feat_ID', 'feat_class') + feat_meta = merge(features_dt[,c(2,3)], feat_meta, all.x = TRUE, by = 'feat_ID') + + if(isTRUE(verbose)) message('Loading transcript level info...') + tx_dt = arrow::read_parquet(file = path_list$tx_path[[1]], as_data_frame = FALSE) %>% + dplyr::mutate(transcript_id = cast(transcript_id, arrow::string())) %>% + dplyr::mutate(cell_id = cast(cell_id, arrow::string())) %>% + dplyr::mutate(feature_name = cast(feature_name, arrow::string())) %>% + as.data.frame() %>% + data.table::setDT() + data.table::setnames(x = tx_dt, + old = c('feature_name', 'x_location', 'y_location'), + new = c('feat_ID', 'x', 'y')) + if(isTRUE(verbose)) message('Loading boundary info...') + bound_dt_list = lapply(path_list$bound_paths, function(x) { + arrow::read_parquet(file = x[[1]], as_data_frame = FALSE) %>% + dplyr::mutate(cell_id = cast(cell_id, arrow::string())) %>% + as.data.frame() %>% + data.table::setDT()}) + } + # **** aggregate info **** + if(data_to_use == 'aggregate') { + if(isTRUE(verbose)) message('Loading cell metadata...') + cell_meta = arrow::read_parquet(file = path_list$cell_meta_path[[1]], as_data_frame = FALSE) %>% + dplyr::mutate(cell_id = cast(cell_id, arrow::string())) %>% + as.data.frame() %>% + data.table::setDT() + + # NOTE: no parquet for agg_expr. + if(isTRUE(verbose)) message('Loading aggregated expression...') + if(isTRUE(h5_expression)) agg_expr = get10Xmatrix_h5(path_to_data = path_list$agg_expr_path, + gene_ids = h5_gene_ids, + remove_zero_rows = TRUE, + split_by_type = TRUE) + else agg_expr = get10Xmatrix(path_to_data = path_list$agg_expr_path, + gene_column_index = gene_column_index, + remove_zero_rows = TRUE, + split_by_type = TRUE) + } + + data_list = list( + 'feat_meta' = feat_meta, + 'tx_dt' = tx_dt, + 'bound_dt_list' = bound_dt_list, + 'cell_meta' = cell_meta, + 'agg_expr' = agg_expr + ) + + return(data_list) + +} diff --git a/R/general_help.R b/R/general_help.R index 552ac3e77..3750c437d 100644 --- a/R/general_help.R +++ b/R/general_help.R @@ -1370,7 +1370,18 @@ readPolygonFilesVizgenHDF5 = function(boundaries_path, hdf5_list_length = length(hdf5_boundary_selected_list) - for(bound_i in 1:hdf5_list_length) { + # create progressbar + n_iter = 100 + pb = create_pb(max = hdf5_list_length) + + # keep track of time per iteration + init = numeric() + end = numeric() + + for(bound_i in seq(hdf5_list_length)) { + + # time start + init[bound_i] = Sys.time() if(verbose == TRUE) cat('hdf5: ', (hdf5_list_length - bound_i) ,'\n') print(hdf5_boundary_selected_list[bound_i][[1]]) @@ -1402,10 +1413,25 @@ readPolygonFilesVizgenHDF5 = function(boundaries_path, for (i in 1:length(multidt_list)) { multidt_list[[i]] = do.call('rbind', result_list[[i]]) } + + # time end + end[bound_i] = Sys.time() + setTxtProgressBar(pb, bound_i) + time = sum(end - init) + # estimated time remaining + est = hdf5_list_length * (mean(end[end != 0] - init[init != 0])) - time + remaining = round_seconds(sec = round(as.numeric(est)), output = 'char') + time_taken = round_seconds(sec = round(as.numeric(time)), output = 'char') + + cat(paste(' // Execution time:', time_taken, + ' // Estimated time remaining:', remaining), '') + } - if(verbose == TRUE) cat('finished extracting .hdf5 files \n - start creating polygons \n') + close(pb) + + if(verbose == TRUE) wrap_msg('finished extracting .hdf5 files + start creating polygons') # create Giotto polygons and add them to gobject diff --git a/R/giotto.R b/R/giotto.R index 0d36d1980..85a28a766 100644 --- a/R/giotto.R +++ b/R/giotto.R @@ -2913,1352 +2913,10 @@ createGiottoObjectSubcellular = function(gpolygons = NULL, -#' @title Create Nanostring CosMx Giotto Object -#' @name createGiottoCosMxObject -#' @description Given the path to a CosMx experiment directory, creates a Giotto -#' object. -#' @param cosmx_dir full path to the exported cosmx directory -#' @param data_to_use which type(s) of expression data to build the gobject with -#' Default is \code{'all'} information available. \code{'subcellular'} loads the transcript -#' coordinates only. \code{'aggregate'} loads the provided aggregated expression matrix. -#' @param FOVs field of views to load (only affects subcellular data and images) -#' @inheritParams createGiottoObjectSubcellular -#' @return a giotto object -#' @export -#' @details -#' [\strong{Expected Directory}] This function generates a giotto object when given a -#' link to a cosmx output directory. It expects the following items within the directory -#' where the \strong{bolded} portions are what this function matches against: -#' \itemize{ -#' \item{\strong{CellComposite} (folder of images)} -#' \item{\strong{CellLabels} (folder of images)} -#' \item{\strong{CellOverlay} (folder of images)} -#' \item{\strong{CompartmentLabels} (folder of images)} -#' \item{experimentname_\strong{exprMat_file}.csv (file)} -#' \item{experimentname_\strong{fov_positions_file}.csv (file)} -#' \item{experimentname_\strong{metadata_file}.csv (file)} -#' \item{experimentname_\strong{tx_file}.csv (file)} -#' } -#' -#' [\strong{Workflows}] Workflow to use is accessed through the data_to_use param -#' \itemize{ -#' \item{'all' - loads and requires subcellular information from tx_file and fov_positions_file -#' and also the existing aggregated information (expression, spatial locations, and metadata) -#' from exprMat_file and metadata_file.} -#' \item{'subcellular' - loads and requires subcellular information from tx_file and -#' fov_positions_file only.} -#' \item{'aggregate' - loads and requires the existing aggregate information (expression, -#' spatial locations, and metadata) from exprMat_file and metadata_file.} -#' } -#' -#' [\strong{Images}] Images in the default CellComposite, CellLabels, CompartmentLabels, and CellOverlay -#' folders will be loaded as giotto largeImage objects in all workflows as long as they are available. -#' Additionally, CellComposite images will be converted to giotto image objects, making plotting with -#' these image objects more responsive when accessing them from a server. -#' \code{\link{showGiottoImageNames}} can be used to see the available images. -#' -#' -createGiottoCosMxObject = function(cosmx_dir = NULL, - data_to_use = c('all','subcellular','aggregate'), - FOVs = NULL, - instructions = NULL, - cores = NA, - verbose = TRUE) { - - # 0. setup - # set number of cores automatically, but with limit of 10 - cores = determine_cores(cores) - data.table::setDTthreads(threads = cores) - - # determine data to use - data_to_use = match.arg(arg = data_to_use, choices = c('all','subcellular','aggregate')) - - # Define for data.table - fov = target = x_local_px = y_local_px = z = cell_ID = CenterX_global_px = CenterY_global_px = - CenterX_local_px = CenterY_local_px = NULL - - - # 1. test if folder structure exists and is as expected - dir_items = read_cosmx_folder(cosmx_dir = cosmx_dir, - verbose = verbose) - - - # 2. load and create giotto object - if(data_to_use == 'subcellular') { - - cosmx_gobject = createGiottoCosMxObject_subcellular(dir_items, - FOVs = FOVs, - cores = cores, - verbose = verbose, - instructions = instructions) - - } - - if(data_to_use == 'aggregate') { - - cosmx_gobject = createGiottoCosMxObject_aggregate(dir_items, - cores = cores, - verbose = verbose, - instructions = instructions) - - } - - if(data_to_use == 'all') { - - cosmx_gobject = createGiottoCosMxObject_all(dir_items, - FOVs = FOVs, - cores = cores, - verbose = verbose, - instructions = instructions) - - } - - - # load in subcellular information, subcellular FOV objects, then join - - - # load in pre-generated aggregated expression matrix - if(data_to_use == 'aggregate' | data_to_use == 'all') { - - } - - - - message('done') - return(cosmx_gobject) - -} - - - -#' @title Load and create a CosMx Giotto object from subcellular info -#' @name createGiottoCosMxObject_subcellular -#' @inheritParams createGiottoCosMxObject -#' @keywords internal -createGiottoCosMxObject_subcellular = function(dir_items, - FOVs = NULL, - cores, - verbose = TRUE, - instructions = NULL) { - - # load tx detections and FOV offsets - data_list = load_cosmx_folder_subcellular(dir_items = dir_items, - FOVs = FOVs, - cores = cores, - verbose = verbose) - - # unpack data_list - FOV_ID = data_list$FOV_ID - fov_offset_file = data_list$fov_offset_file - tx_coord_all = data_list$tx_coord_all - - # remove global xy values and cell_ID - tx_coord_all[, c('x_global_px', 'y_global_px', 'cell_ID') := NULL] - - data.table::setcolorder(tx_coord_all, c('target', 'x_local_px', 'y_local_px', 'z', 'fov')) - - if(isTRUE(verbose)) wrap_msg('Splitting detections by feature vs neg probe') - all_IDs = tx_coord_all[, unique(target)] - neg_IDs = all_IDs[grepl(pattern = 'NegPrb', all_IDs)] - feat_IDs = all_IDs[!all_IDs %in% neg_IDs] - - # split detections DT - feat_coords_all = tx_coord_all[target %in% feat_IDs] - neg_coords_all = tx_coord_all[target %in% neg_IDs] - - if(isTRUE(verbose)) { - message(' > Features: ', feat_coords_all[, .N]) - message(' > NegProbes: ', neg_coords_all[, .N]) - } - - # Start FOV lapply - fov_gobjects_list = lapply(FOV_ID, function(x) { - - # Build image paths - if(isTRUE(verbose)) message('Loading image information...') - - composite_dir = Sys.glob(paths = file.path(dir_items$`CellComposite folder`, paste0('*',x, '*'))) - cellLabel_dir = Sys.glob(paths = file.path(dir_items$`CellLabels folder`, paste0('*',x, '*'))) - compartmentLabel_dir = Sys.glob(paths = file.path(dir_items$`CompartmentLabels folder`, paste0('*',x, '*'))) - cellOverlay_dir = Sys.glob(paths = file.path(dir_items$`CellOverlay folder`, paste0('*',x, '*'))) - # Missing warnings - if(length(composite_dir) == 0) {warning('[ FOV ', x, ' ] No composite images found') ; composite_dir = NULL} - if(length(cellLabel_dir) == 0) {stop('[ FOV ', x, ' ] No cell mask images found')} # cell masks are necessary - if(length(compartmentLabel_dir) == 0) {warning('[ FOV ', x, ' ] No compartment label images found') ; compartmentLabel_dir = NULL} - if(length(cellOverlay_dir) == 0) {warning('[ FOV ', x, ' ] No cell polygon overlay images found') ; cellOverlay_dir = NULL} - - if(isTRUE(verbose)) message('Image load done') - - if(isTRUE(verbose)) wrap_msg('[ FOV ', x, ']') - - # get FOV specific tx locations - if(isTRUE(verbose)) wrap_msg('Assigning FOV feature detections...') - - - # feature info - coord_oldnames = c('target', 'x_local_px', 'y_local_px') - coord_newnames = c('feat_ID', 'x', 'y') - - feat_coord = feat_coords_all[fov == as.numeric(x)] - data.table::setnames(feat_coord, old = coord_oldnames, new = coord_newnames) - # neg probe info - neg_coord = neg_coords_all[fov == as.numeric(x)] - data.table::setnames(neg_coord, old = coord_oldnames, new = coord_newnames) - - - # build giotto object - if(isTRUE(verbose)) wrap_msg('Building subcellular giotto object...') - fov_subset = createGiottoObjectSubcellular( - gpoints = list('rna' = feat_coord, - 'neg_probe' = neg_coord), - gpolygons = list('cell' = cellLabel_dir), - polygon_mask_list_params = list( - mask_method = 'guess', - flip_vertical = TRUE, - flip_horizontal = FALSE, - shift_horizontal_step = FALSE - ), - instructions = instructions, - cores = cores - ) - - - # find centroids as spatial locations - if(isTRUE(verbose)) wrap_msg('Finding polygon centroids as cell spatial locations...') - fov_subset = addSpatialCentroidLocations(fov_subset, - poly_info = 'cell', - spat_loc_name = 'raw') - - - # create and add giotto image objects - if(isTRUE(verbose)) message('Attaching image files...') - print(composite_dir) - print(cellOverlay_dir) - print(compartmentLabel_dir) - - gImage_list = list() - - # load image if files are found - if(!is.null(composite_dir)) - gImage_list$composite = createGiottoLargeImage(raster_object = composite_dir, - negative_y = F, - name = 'composite') - if(!is.null(cellOverlay_dir)) - gImage_list$overlay = createGiottoLargeImage(raster_object = cellOverlay_dir, - negative_y = F, - name = 'overlay') - if(!is.null(compartmentLabel_dir)) - gImage_list$compartment = createGiottoLargeImage(raster_object = compartmentLabel_dir, - negative_y = F, - name = 'compartment') #TODO - - - - if(length(gImage_list) > 0) { - fov_subset = addGiottoImage(gobject = fov_subset, - largeImages = gImage_list) - - # convert to MG for faster loading (particularly relevant for pulling from server) - fov_subset = convertGiottoLargeImageToMG(giottoLargeImage = gImage_list$composite, - gobject = fov_subset, - return_gobject = TRUE, - verbose = FALSE) - # fov_subset = convertGiottoLargeImageToMG(giottoLargeImage = gImage_list$overlay, gobject = fov_subset, return_gobject = TRUE) - # fov_subset = convertGiottoLargeImageToMG(giottoLargeImage = gImage_list$compartment, gobject = fov_subset, return_gobject = TRUE) - } else { - message('No images found for fov') - } - - - }) #lapply end - - if(length(FOVs) == 1) { - return(fov_gobjects_list[[1]]) - } else { - # join giotto objects according to FOV positions file - if(isTRUE(verbose)) message('Joining FOV gobjects...') - new_gobj_names = paste0('fov', FOV_ID) - id_match = match(as.numeric(FOV_ID), fov_offset_file$fov) - x_shifts = fov_offset_file[id_match]$x_global_px - y_shifts = fov_offset_file[id_match]$y_global_px - # Join giotto objects - cosmx_gobject = joinGiottoObjects(gobject_list = fov_gobjects_list, - gobject_names = new_gobj_names, - join_method = 'shift', - x_shift = x_shifts, - y_shift = y_shifts) - return(cosmx_gobject) - } - -} - - - -#' @title Load and create a CosMx Giotto object from aggregate info -#' @name createGiottoCosMxObject_aggregate -#' @inheritParams createGiottoCosMxObject -#' @keywords internal -createGiottoCosMxObject_aggregate = function(dir_items, - cores, - verbose = TRUE, - instructions = NULL) { - - - - data_list = load_cosmx_folder_aggregate(dir_items = dir_items, - cores = cores, - verbose = verbose) - - # unpack data_list - spatlocs = data_list$spatlocs - spatlocs_fov = data_list$spatlocs_fov - metadata = data_list$metadata - protM = data_list$protM - spM = data_list$spM - fov_shifts = data_list$fov_shifts - - - # create standard gobject from aggregate matrix - if(data_to_use == 'aggregate') { - - # Create aggregate gobject - if(isTRUE(verbose)) message('Building giotto object...') - cosmx_gobject = createGiottoObject(expression = list('raw' = spM, 'protein' = protM), - cell_metadata = list('cell' = list('rna' = metadata, - 'protein' = metadata)), - spatial_locs = spatlocs, - instructions = instructions, - cores = cores) - - - # load in images - img_ID = data.table::data.table(fov = fov_shifts[, fov], - img_name = paste0('fov', sprintf('%03d', fov_shifts[, fov]), '-image')) - - if(isTRUE(verbose)) message('Attaching image files...') - composite_dir = Sys.glob(paths = file.path(dir_items$`CellComposite folder`, paste0('/*'))) - cellLabel_dir = Sys.glob(paths = file.path(dir_items$`CellLabels folder`, paste0('/*'))) - compartmentLabel_dir = Sys.glob(paths = file.path(dir_items$`CompartmentLabels folder`, paste0('/*'))) - overlay_dir = Sys.glob(paths = file.path(dir_items$`CellOverlay folder`, paste0('/*'))) - - if(length(cellLabel_imgList) > 0) cellLabel_imgList = lapply(cellLabel_dir, function(x) {createGiottoLargeImage(x,name = 'cellLabel',negative_y = TRUE)}) - if(length(composite_imgList) > 0) composite_imgList = lapply(composite_dir, function(x) {createGiottoLargeImage(x,name = 'composite',negative_y = TRUE)}) - if(length(compartmentLabel_dir) > 0) compartmentLabel_imgList = lapply(compartmentLabel_dir, function(x) {createGiottoLargeImage(x,name = 'composite',negative_y = TRUE)}) - if(length(overlay_dir) > 0) overlay_imgList = lapply(overlay_dir, function(x) {createGiottoLargeImage(x,name = 'composite',negative_y = TRUE)}) - - - - } - -} - - - - -#' @title Load and create a CosMx Giotto object from subcellular and aggregate info -#' @name createGiottoCosMxObject_all -#' @param dir_items list of full directory paths from \code{read_cosmx_folder} -#' @inheritParams createGiottoCosMxObject -#' @details Both \emph{subcellular} (subellular transcript detection information) and -#' \emph{aggregate} (aggregated detection count matrices by cell polygon from NanoString) -#' data will be loaded in. The two will be separated into 'cell' and 'cell_agg' -#' spatial units in order to denote the difference in origin of the two. -#' @seealso createGiottoCosMxObject createGiottoCosMxObject_aggregate -#' createGiottoCosMxObject_subcellular -#' @keywords internal -createGiottoCosMxObject_all = function(dir_items, - FOVs, - cores, - verbose = TRUE, - instructions = NULL) { - - # 1. create subcellular giotto as spat_unit 'cell' - cosmx_gobject = createGiottoCosMxObject_subcellular(dir_items = dir_items, - FOVs = FOVs, - cores = cores, - verbose = verbose, - instructions = instructions) - - # 2. load and append aggregated information in spat_unit 'cell_agg' - agg_data = load_cosmx_folder_aggregate(dir_items = dir_items, - cores = cores, - verbose = verbose) - - # unpack data_list - spatlocs = agg_data$spatlocs - spatlocs_fov = agg_data$spatlocs_fov - metadata = agg_data$metadata - protM = agg_data$protM - spM = agg_data$spM - - # add in pre-generated aggregated expression matrix information for 'all' workflow - - # Add aggregate expression information - if(isTRUE(verbose)) wrap_msg('Appending provided aggregate expression data as... - spat_unit: "cell_agg" - feat_type: "rna" - name: "raw"') - # add expression data to expression slot - s4_expr = create_expr_obj(name = 'raw', - exprMat = spM, - spat_unit = 'cell_agg', - feat_type = 'rna', - provenance = 'cell_agg') - - cosmx_gobject = set_expression_values(cosmx_gobject, values = s4_expr) - - # Add spatial locations - if(isTRUE(verbose)) wrap_msg('Appending metadata provided spatial locations data as... - --> spat_unit: "cell_agg" name: "raw" - --> spat_unit: "cell" name: "raw_fov"') - if(isTRUE(verbose)) wrap_msg('Polygon centroid derived spatial locations assigned as... - --> spat_unit: "cell" name: "raw" (default)') - - locsObj = create_spat_locs_obj(name = 'raw', - coordinates = spatlocs, - spat_unit = 'cell_agg', - provenance = 'cell_agg') - locsObj_fov = create_spat_locs_obj(name = 'raw_fov', - coordinates = spatlocs_fov, - spat_unit = 'cell_agg', - provenance = 'cell_agg') - - cosmx_gobject = set_spatial_locations(cosmx_gobject, spatlocs = locsObj) - cosmx_gobject = set_spatial_locations(cosmx_gobject, spatlocs = locsObj_fov) - - # cosmx_gobject = set_spatial_locations(cosmx_gobject, - # spat_unit = 'cell_agg', - # spat_loc_name = 'raw', - # spatlocs = spatlocs) - # cosmx_gobject = set_spatial_locations(cosmx_gobject, - # spat_unit = 'cell_agg', - # spat_loc_name = 'raw_fov', - # spatlocs = spatlocs_fov) - - # initialize cell and feat IDs and metadata slots for 'cell_agg' spat_unit - agg_cell_ID = colnames(s4_expr[]) - agg_feat_ID = rownames(s4_expr[]) - - sub_feat_ID = get_feat_id(cosmx_gobject, feat_type = 'rna') - feat_ID_new = unique(c(agg_feat_ID, sub_feat_ID)) - - cosmx_gobject = set_cell_id(gobject = cosmx_gobject, - spat_unit = 'cell_agg', - cell_IDs = agg_cell_ID) - cosmx_gobject = set_feat_id(gobject = cosmx_gobject, - feat_type = 'rna', - feat_IDs = feat_ID_new) - - # cell metadata - - # cosmx_gobject@cell_ID[['cell_agg']] = colnames(cosmx_gobject@expression[['cell_agg']][[1]][[1]]) - # cosmx_gobject@feat_ID[['rna']] = unique(c(cosmx_gobject@feat_ID, rownames(cosmx_gobject@expression[['cell_agg']][['rna']][[1]]))) - # cosmx_gobject@cell_metadata[['cell_agg']][['rna']] = data.table::data.table(cell_ID = cosmx_gobject@cell_ID[['cell_agg']]) - # cosmx_gobject@feat_metadata[['cell_agg']][['rna']] = data.table::data.table(feat_ID = cosmx_gobject@feat_ID[['rna']]) - - # Add metadata to both the given and the poly spat_units - if(isTRUE(verbose)) message('Appending provided cell metadata...') - cosmx_gobject = addCellMetadata(cosmx_gobject, - spat_unit = 'cell', - feat_type = 'rna', - new_metadata = metadata, - by_column = TRUE, - column_cell_ID = 'cell_ID') - cosmx_gobject = addCellMetadata(cosmx_gobject, - spat_unit = 'cell_agg', - feat_type = 'rna', - new_metadata = metadata, - by_column = TRUE, - column_cell_ID = 'cell_ID') - -} - - - - -#' @title Create 10x Xenium Giotto Object -#' @name createGiottoXeniumObject -#' @description Given the path to a Xenium experiment output folder, creates a Giotto -#' object -#' @param xenium_dir full path to the exported xenium directory -#' @param data_to_use which type(s) of expression data to build the gobject with -#' (e.g. default: \strong{'subcellular'}, 'aggregate', or 'all') -#' @param load_format files formats from which to load the data. Either `csv` or -#' `parquet` currently supported. -#' @param h5_expression (boolean) whether to load cell_feature_matrix from .h5 file. -#' Default is \code{TRUE} -#' @param h5_gene_ids use gene symbols (default) or ensembl ids for the .h5 gene -#' expression matrix -#' @param bounds_to_load vector of boundary information to load (e.g. \code{'cell'} -#' or \code{'nucleus'} by themselves or \code{c('cell', 'nucleus')} to load both -#' at the same time.) -#' @param qv_threshold Minimum Phred-scaled quality score cutoff to be included as -#' a subcellular transcript detection (default = 20) -#' @param key_list (advanced) list of grep-based keywords to split the subcellular -#' feature detections by feature type. See details -#' @inheritParams get10Xmatrix -#' @inheritParams createGiottoObjectSubcellular -#' @details -#' -#' [\strong{QC feature types}] -#' Xenium provides info on feature detections that include more than only the -#' Gene Expression specific probes. Additional probes for QC are included: -#' \emph{blank codeword}, \emph{negative control codeword}, and -#' \emph{negative control probe}. These additional QC probes each occupy and are treated -#' as their own feature types so that they can largely remain independent of the -#' gene expression information. -#' -#' [\strong{key_list}] -#' Related to \code{data_to_use = 'subcellular'} workflow only: -#' Additional QC probe information is in the subcellular feature detections information -#' and must be separated from the gene expression information during processing. -#' The QC probes have prefixes that allow them to be selected from the rest of the -#' feature IDs. -#' Giotto uses a named list of keywords (\code{key_list}) to select these QC probes, -#' with the list names being the names that will be assigned as the feature type -#' of these feature detections. The default list is used when \code{key_list} = NULL. -#' -#' Default list: -#' \preformatted{ -#' list(blank_code = 'BLANK_', -#' neg_code = 'NegControlCodeword_', -#' neg_probe = c('NegControlProbe_|antisense_')) -#' } -#' -#' The Gene expression subset is accepted as the subset of feat_IDs that do not -#' map to any of the keys. -#' -#' @export -createGiottoXeniumObject = function(xenium_dir, - data_to_use = c('subcellular','aggregate'), - load_format = 'csv', - h5_expression = TRUE, - h5_gene_ids = c('symbols', 'ensembl'), - gene_column_index = 1, - bounds_to_load = c('cell'), - qv_threshold = 20, - key_list = NULL, - # include_analysis = FALSE, - instructions = NULL, - cores = NA, - verbose = TRUE) { - - # 0. setup - - # Determine data to load - data_to_use = match.arg(arg = data_to_use, choices = c('subcellular','aggregate')) - - # Determine load formats - load_format = 'csv' # TODO Remove this and add as param once other options are available - load_format = match.arg(arg = load_format, choices = c('csv', 'parquet', 'zarr')) - - # set number of cores automatically, but with limit of 10 - cores = determine_cores(cores) - data.table::setDTthreads(threads = cores) - - # 1. detect xenium folder and find filepaths to load - - # path_list contents: - # tx_path - # bound_paths - # cell_meta_path - # agg_expr_path - # panel_meta_path - path_list = read_xenium_folder(xenium_dir = xenium_dir, - data_to_use = data_to_use, - bounds_to_load = bounds_to_load, - load_format = load_format, - h5_expression = h5_expression, - verbose = verbose) - - - # 2. load in data - - # data_list contents: - # feat_meta - # tx_dt - # bound_dt_list - # cell_meta - # agg_expr - data_list = load_xenium_folder(path_list = path_list, - load_format = load_format, - data_to_use = data_to_use, - h5_expression = h5_expression, - h5_gene_ids = h5_gene_ids, - gene_column_index = gene_column_index, - cores = cores, - verbose = verbose) - - - # TODO load images - - - # 3. Create giotto objects - - if(data_to_use == 'subcellular') { - - # ** feat type search keys ** - if(is.null(key_list)) { - key_list = list(blank_code = 'BLANK_', - neg_code = 'NegControlCodeword_', - neg_probe = c('NegControlProbe_|antisense_')) - } - - # needed: - # feat_meta - # tx_dt - # bound_dt_list - xenium_gobject = createGiottoXeniumObject_subcellular(data_list = data_list, - qv_threshold = qv_threshold, - key_list = key_list, - instructions = instructions, - cores = cores, - verbose = verbose) - - } - - if(data_to_use == 'aggregate') { - - # needed: - # feat_meta - # cell_meta - # agg_expr - # optional? - # tx_dt - # bound_dt_list - xenium_gobject = createGiottoXeniumObject_aggregate(data_list = data_list, - instructions = instructions, - cores = cores, - verbose = verbose) - - } - - return(xenium_gobject) - -} - - - - -#' @title Create a Xenium Giotto object from subcellular info -#' @name createGiottoXeniumObject_subcellular -#' @description Subcellular workflow for createGiottoXeniumObject -#' @param data_list list of data loaded by \code{\link{load_xenium_folder}} -#' @param key_list regex-based search keys for feature IDs to allow separation -#' into separate giottoPoints objects by feat_type -#' @param qv_threshold Minimum Phred-scaled quality score cutoff to be included as -#' a subcellular transcript detection (default = 20) -#' @inheritParams get10Xmatrix -#' @inheritParams createGiottoObjectSubcellular -#' @seealso createGiottoXeniumObject createGiottoXeniumObject_aggregate -#' @keywords internal -createGiottoXeniumObject_subcellular = function(data_list, - key_list = NULL, - qv_threshold = 20, - instructions = NULL, - cores = NA, - verbose = TRUE) { - - # Unpack data_list info - feat_meta = data_list$feat_meta - tx_dt = data_list$tx_dt - bound_dt_list = data_list$bound_dt_list - # cell_meta = data_list$cell_meta - # agg_expr = data_list$agg_expr - - # define for data.table - cell_id = feat_ID = feature_name = NULL - - if(isTRUE(verbose)) message('Building subcellular giotto object...') - # Giotto points object - if(isTRUE(verbose)) message('> points data prep...') - - # filter by qv_threshold - if(isTRUE(verbose)) wrap_msg('> filtering feature detections for Phred score >= ', qv_threshold) - n_before = tx_dt[,.N] - tx_dt_filtered = tx_dt[qv >= qv_threshold] - n_after = tx_dt_filtered[,.N] - - cat('Number of feature points removed: ', - n_before - n_after, - ' out of ', n_before, '\n') - - if(isTRUE(verbose)) message('> splitting detections by feat_type') - # discover feat_IDs for each feat_type - all_IDs = tx_dt_filtered[, unique(feat_ID)] - feat_types_IDs = lapply(key_list, function(x) all_IDs[grepl(pattern = x, all_IDs)]) - rna = list('rna' = all_IDs[!all_IDs %in% unlist(feat_types_IDs)]) - feat_types_IDs = append(rna, feat_types_IDs) - - # separate detections by feature type - points_list = lapply( - feat_types_IDs, - function(types) { - tx_dt_filtered[feat_ID %in% types] - } - ) - - # Giotto polygons object - if(isTRUE(verbose)) message('> polygons data prep...') - polys_list = lapply( - bound_dt_list, - function(bound_type) { - bound_type[, cell_id := as.character(cell_id)] - } - ) - - xenium_gobject = createGiottoObjectSubcellular(gpoints = points_list, - gpolygons = polys_list, - instructions = instructions, - cores = cores, - verbose = verbose) - - # generate centroids - if(isTRUE(verbose)) message('Calculating polygon centroids...') - xenium_gobject = addSpatialCentroidLocations(xenium_gobject, - poly_info = c(names(bound_dt_list))) - - # add in feature metadata - # xenium_gobject = addFeatMetadata(gobject = xenium_gobject, - # new_metadata = feat_meta, - # by_column = TRUE, - # column_feat_ID = 'feat_ID') - - return(xenium_gobject) - -} - - - - - -#' @title Create a Xenium Giotto object from aggregate info -#' @name createGiottoXeniumObject_aggregate -#' @description Aggregate workflow for createGiottoXeniumObject -#' @param data_list list of data loaded by \code{load_xenium_folder} -#' @inheritParams get10Xmatrix -#' @inheritParams createGiottoObjectSubcellular -#' @seealso createGiottoXeniumObject createGiottoXeniumObject_subcellular -#' @keywords internal -createGiottoXeniumObject_aggregate = function(data_list, - # include_analysis = FALSE, - instructions = NULL, - cores = NA, - verbose = TRUE) { - - # Unpack data_list info - feat_meta = data_list$feat_meta - # tx_dt = data_list$tx_dt - # bound_dt_list = data_list$bound_dt_list - cell_meta = data_list$cell_meta - agg_expr = data_list$agg_expr - - # define for data.table - cell_ID = x_centroid = y_centroid = NULL - - # clean up names for aggregate matrices - names(agg_expr) = gsub(pattern = ' ', replacement = '_' ,names(agg_expr)) - geneExpMat = which(names(agg_expr) == 'Gene_Expression') - names(agg_expr)[[geneExpMat]] = 'raw' - - # set cell_id as character - cell_meta = cell_meta[, data.table::setnames(.SD, 'cell_id', 'cell_ID')] - cell_meta = cell_meta[, cell_ID := as.character(cell_ID)] - - # set up spatial locations - agg_spatlocs = cell_meta[, .(x_centroid, y_centroid, cell_ID)] - - # set up metadata - agg_meta = cell_meta[, !c('x_centroid','y_centroid')] - - if(isTRUE(verbose)) message('Building aggregate giotto object...') - xenium_gobject = createGiottoObject(expression = agg_expr, - spatial_locs = agg_spatlocs, - instructions = instructions, - cores = cores, - verbose = verbose) - - # append aggregate metadata - xenium_gobject = addCellMetadata(gobject = xenium_gobject, - new_metadata = agg_meta, - by_column = TRUE, - column_cell_ID = 'cell_ID') - xenium_gobject = addFeatMetadata(gobject = xenium_gobject, - new_metadata = feat_meta, - by_column = TRUE, - column_feat_ID = 'feat_ID') - - return(xenium_gobject) - -} - - - - - - - -#### folder detection and loading #### - - -#' @title Read a structured CosMx folder -#' @name read_cosmx_folder -#' @inheritParams createGiottoCosMxObject -#' @seealso createGiottoCosMxObject load_cosmx_folder -#' @return path_list a list of cosmx files discovered and their filepaths. NULL -#' values denote missing items -#' @keywords internal -read_cosmx_folder = function(cosmx_dir, - verbose = TRUE) { - - ch = box_chars() - - if(is.null(cosmx_dir) | !dir.exists(cosmx_dir)) stop('The full path to a cosmx directory must be given.\n') - if(isTRUE(verbose)) wrap_msg('A structured CosMx directory will be used\n') - - # find directories (length = 1 if present, length = 0 if missing) - dir_items = list(`CellLabels folder` = '*CellLabels', - `CompartmentLabels folder` = '*CompartmentLabels', - `CellComposite folder` = '*CellComposite', - `CellOverlay folder` = '*CellOverlay', - `transcript locations file` = '*tx_file*', - `fov positions file` = '*fov_positions_file*', - `expression matrix file` = '*exprMat_file*', - `metadata file` = '*metadata_file*') - dir_items = lapply(dir_items, function(x) Sys.glob(paths = file.path(cosmx_dir, x))) - dir_items_lengths = lengths(dir_items) - - if(isTRUE(verbose)) { - message('Checking directory contents...') - for(item in names(dir_items)) { - if(dir_items_lengths[[item]] > 0) { - message(ch$s, '> ' ,item, ' found') - } else { - warning(item, ' is missing\n') - } - } - } - - # select first directory in list if multiple are detected - if(any(dir_items_lengths > 1)) { - warning('Multiple matches for expected subdirectory item(s).\n First matching item selected') - - multiples = which(dir_items_lengths > 1) - for(mult_i in multiples) { - message(names(dir_items)[[mult_i]], 'multiple matches found:') - print(dir_items[[mult_i]]) - dir_items[[mult_i]] = dir_items[[mult_i]][[1]] - } - } - if(isTRUE(verbose)) message('Directory check done') - - return(dir_items) - -} - - -#' @title Load CosMx folder subcellular info -#' @name load_cosmx_folder_subcellular -#' @description loads in the feature detections information. Note that the mask -#' images are still required for a working subcellular object, and those are loaded -#' in \code{\link{createGiottoCosMxObject_subcellular}} -#' @inheritParams createGiottoCosMxObject -#' @keywords internal -load_cosmx_folder_subcellular = function(dir_items, - FOVs = NULL, - cores, - verbose = TRUE) { - - if(isTRUE(verbose)) wrap_msg('Loading subcellular information...') - - # subcellular checks - if(!file.exists(dir_items$`transcript locations file`)) - stop(wrap_txt('No transcript locations file (.csv) detected')) - if(!file.exists(dir_items$`fov positions file`)) - stop(wrap_txt('No fov positions file (.csv) detected')) - - # FOVs to load - if(isTRUE(verbose)) wrap_msg('Loading FOV offsets...') - fov_offset_file = fread(input = dir_items$`fov positions file`, nThread = cores) - if(is.null(FOVs)) FOVs = fov_offset_file$fov # default to ALL FOVs - FOV_ID = as.list(sprintf('%03d', FOVs)) - - #TODO Load only relevant portions of file? - - if(isTRUE(verbose)) wrap_msg('Loading transcript level info...') - tx_coord_all = fread(input = dir_items$`transcript locations file`, nThread = cores) - if(isTRUE(verbose)) wrap_msg('Subcellular load done') - - data_list = list( - 'FOV_ID' = FOV_ID, - 'fov_offset_file' = fov_offset_file, - 'tx_coord_all' = tx_coord_all - ) - - return(data_list) - -} - - - -#' @title Load CosMx folder aggregate info -#' @name load_cosmx_folder_aggregate -#' @inheritParams createGiottoCosMxObject -#' @keywords internal -load_cosmx_folder_aggregate = function(dir_items, - cores, - verbose = TRUE) { - - # load aggregate information - wrap_msg('Loading provided aggregated information...') - - # aggregate checks - if(!file.exists(dir_items$`expression matrix file`)) stop(wrap_txt('No expression matrix file (.csv) detected')) - if(!file.exists(dir_items$`metadata file`)) stop(wrap_txt('No metadata file (.csv) detected. Needed for cell spatial locations.')) - - # read in aggregate data - expr_mat = fread(input = dir_items$`expression matrix file`, nThread = cores) - metadata = fread(input = dir_items$`metadata file`, nThread = cores) - - # setorder expression and spatlocs - data.table::setorder(metadata, fov, cell_ID) - data.table::setorder(expr_mat, fov, cell_ID) - - - # generate unique cell IDs - expr_mat[, cell_ID := paste0('fov', sprintf('%03d', fov), '-', 'cell_', cell_ID)] - # expr_mat$cell_ID = paste0('fov', sprintf('%03d', expr_mat$fov), '-', 'cell_', expr_mat$cell_ID) - expr_mat = expr_mat[, fov := NULL] - - metadata[, fov_cell_ID := cell_ID] - metadata[, cell_ID := paste0('fov', sprintf('%03d', fov), '-', 'cell_', cell_ID)] - # metadata$cell_ID = paste0('fov', sprintf('%03d', metadata$fov), '-', 'cell_', metadata$cell_ID) - # reorder - data.table::setcolorder(x = metadata, c('cell_ID','fov','fov_cell_ID')) - - - # extract spatial locations - spatlocs = metadata[,.(CenterX_global_px, CenterY_global_px, cell_ID)] - spatlocs_fov = metadata[,.(CenterX_local_px, CenterY_local_px, cell_ID)] - # regenerate FOV shifts - metadata[, x_shift := CenterX_global_px - CenterX_local_px] - metadata[, y_shift := CenterY_global_px - CenterY_local_px] - fov_shifts = metadata[, .(mean(x_shift), mean(y_shift)), fov] - colnames(fov_shifts) = c('fov', 'x_shift', 'y_shift') - - - # rename spatloc column names - spatloc_oldnames = c('CenterX_global_px', 'CenterY_global_px', 'cell_ID') - spatloc_oldnames_fov = c('CenterX_local_px', 'CenterY_local_px', 'cell_ID') - spatloc_newnames = c('sdimx', 'sdimy', 'cell_ID') - data.table::setnames(spatlocs, old = spatloc_oldnames, new = spatloc_newnames) - data.table::setnames(spatlocs_fov, old = spatloc_oldnames_fov, new = spatloc_newnames) - - # cleanup metadata and spatlocs - metadata = metadata[,c('CenterX_global_px', 'CenterY_global_px', 'CenterX_local_px', 'CenterY_local_px') := NULL] - # find unique cell_IDs present in both expression and metadata - giotto_cell_ID = unique(intersect(expr_mat$cell_ID, metadata$cell_ID)) - - # subset to only unique cell_IDs - expr_mat = expr_mat[cell_ID %in% giotto_cell_ID,] - metadata = metadata[cell_ID %in% giotto_cell_ID,] - - - # convert protein metadata to expr mat - # take all mean intensity protein information except for MembraneStain and DAPI - protein_meta_cols = colnames(metadata) - protein_meta_cols = protein_meta_cols[grepl(pattern = 'Mean.*', x = protein_meta_cols)] - protein_meta_cols = protein_meta_cols[!protein_meta_cols %in% c('Mean.MembraneStain', 'Mean.DAPI')] - protein_meta_cols = c('cell_ID', protein_meta_cols) - - prot_expr = metadata[, protein_meta_cols, with = FALSE] - prot_cell_ID = metadata[, cell_ID] - protM = Matrix::Matrix(as.matrix(prot_expr[,-1]), dimnames = list(prot_expr[[1]], colnames(prot_expr[,-1])), sparse = FALSE) - protM = t_flex(protM) - - # convert expression to sparse matrix - spM = Matrix::Matrix(as.matrix(expr_mat[,-1]), dimnames = list(expr_mat[[1]], colnames(expr_mat[,-1])), sparse = TRUE) - spM = t_flex(spM) - - ## Ready for downstream aggregate gobject creation or appending into existing subcellular Giotto object ## - - data_list = list( - 'spatlocs' = spatlocs, - 'spatlocs_fov' = spatlocs_fov, - 'metadata' = metadata, - 'protM' = protM, - 'spM' = spM, - 'fov_shifts' = fov_shifts - ) - - return(data_list) - -} - - - -#' @title Read a structured xenium folder -#' @name read_xenium_folder -#' @inheritParams createGiottoXeniumObject -#' @keywords internal -#' @return path_list a list of xenium files discovered and their filepaths. NULL -#' values denote missing items -read_xenium_folder = function(xenium_dir, - data_to_use = 'subcellular', - bounds_to_load = c('cell'), - load_format = 'csv', - h5_expression = FALSE, - verbose = TRUE) { - - # Check needed packages - if(load_format == 'parquet') { - package_check(pkg_name = 'arrow', repository = 'CRAN') - package_check(pkg_name = 'dplyr', repository = 'CRAN') - } - if(isTRUE(h5_expression)) { - package_check(pkg_name = 'hdf5r', repository = 'CRAN') - } - - ch = box_chars() - - - # 0. test if folder structure exists and is as expected - - - if(is.null(xenium_dir) | !dir.exists(xenium_dir)) stop('The full path to a xenium directory must be given.\n') - if(isTRUE(verbose)) message('A structured Xenium directory will be used\n') - - # find items (length = 1 if present, length = 0 if missing) - dir_items = list(`analysis info` = '*analysis*', - `boundary info` = '*bound*', - `cell feature matrix` = '*cell_feature_matrix*', - `cell metadata` = '*cells*', - `image info` = '*tif', - `panel metadata` = '*panel*', - `raw transcript info` = '*transcripts*', - `experiment info (.xenium)` = '*.xenium') - - dir_items = lapply(dir_items, function(x) Sys.glob(paths = file.path(xenium_dir, x))) - dir_items_lengths = lengths(dir_items) - - if(isTRUE(verbose)) { - message('Checking directory contents...') - for(item in names(dir_items)) { - - # IF ITEM FOUND - - if(dir_items_lengths[[item]] > 0) { - message(ch$s, '> ' ,item, ' found') - for(item_i in seq_along(dir_items[[item]])) { # print found item names - subItem = gsub(pattern = '.*/', replacement = '', x = dir_items[[item]][[item_i]]) - message(ch$s, ch$s, ch$l,ch$h,ch$h, subItem) - } - } else { - - # IF ITEM MISSING - # Based on workflow, determine if: - # necessary (error) - # optional (warning) - - if(data_to_use == 'subcellular') { - # necessary items - if(item %in% c('boundary info', 'raw transcript info')) stop(item, ' is missing\n') - # optional items - if(item %in% c('image info', 'experiment info (.xenium)', 'panel metadata')) warning(item, ' is missing (optional)\n') - # items to ignore: analysis info, cell feature matrix, cell metadata - } else if(data_to_use == 'aggregate') { - # necessary items - if(item %in% c('cell feature matrix', 'cell metadata')) stop(item, ' is missing\n') - # optional items - if(item %in% c('image info', 'experiment info (.xenium)', 'panel metadata', 'analysis info')) warning(item, ' is missing (optional)\n') - # items to ignore: boundary info, raw transcript info - } - } - } - } - - - # 1. Select data to load - - - # **** transcript info **** - tx_path = NULL - tx_path = dir_items$`raw transcript info`[grepl(pattern = load_format, dir_items$`raw transcript info`)] - # **** cell metadata **** - cell_meta_path = NULL - cell_meta_path = dir_items$`cell metadata`[grepl(pattern = load_format, dir_items$`cell metadata`)] - - # **** boundary info **** - # Select bound load format - if(load_format != 'zarr') { # No zarr available for boundary info - dir_items$`boundary info` = dir_items$`boundary info`[grepl(pattern = load_format, dir_items$`boundary info`)] - } else dir_items$`boundary info` = dir_items$`boundary info`[grepl(pattern = 'csv', dir_items$`boundary info`)] - - # Organize bound paths by type of bound (bounds_to_load param) - bound_paths = NULL - bound_names = bounds_to_load - bounds_to_load = as.list(bounds_to_load) - bound_paths = lapply(bounds_to_load, function(x) dir_items$`boundary info`[grepl(pattern = x, dir_items$`boundary info`)]) - names(bound_paths) = bound_names - - # **** aggregated expression info **** - agg_expr_path = NULL - if(isTRUE(h5_expression)) { # h5 expression matrix loading is default - agg_expr_path = dir_items$`cell feature matrix`[grepl(pattern = 'h5', dir_items$`cell feature matrix`)] - h5_gene_ids = match.arg(arg = h5_gene_ids, choices = c('symbols', 'ensembl')) - } else if(load_format == 'zarr') { - agg_expr_path = dir_items$`cell feature matrix`[grepl(pattern = 'zarr', dir_items$`cell feature matrix`)] - } else { # No parquet for aggregated expression - default to normal 10x loading - agg_expr_path = dir_items$`cell feature matrix`[sapply(dir_items$`cell feature matrix`, function(x) file_test(op = '-d', x))] - if(length(agg_expr_path) == 0) stop(wrap_txt( - 'Expression matrix cannot be loaded.\nHas cell_feature_matrix(.tar.gz) been unpacked into a directory?' - )) - } - if(data_to_use == 'aggregate') { - if(length(path_list$agg_expr_path) == 0) stop(wrap_txt( - 'Aggregated expression not found.\nPlease confirm h5_expression and load_format params are correct\n' - )) - } - - # **** panel info **** - panel_meta_path = NULL - panel_meta_path = dir_items$`panel metadata` - - - if(isTRUE(verbose)) message('Directory check done') - - path_list = list('tx_path' = tx_path, - 'bound_paths' = bound_paths, - 'cell_meta_path' = cell_meta_path, - 'agg_expr_path' = agg_expr_path, - 'panel_meta_path' = panel_meta_path) - - return(path_list) - -} - - -#' @title Load xenium data from folder -#' @name load_xenium_folder -#' @param path_list list of full filepaths from read_xenium_folder -#' @inheritParams createGiottoXeniumObject -#' @keywords internal -#' @return list of loaded in xenium data -load_xenium_folder = function(path_list, - load_format = 'csv', - data_to_use = 'subcellular', - h5_expression = 'FALSE', - h5_gene_ids = 'symbols', - gene_column_index = 1, - cores, - verbose = TRUE) { - - if(load_format == 'csv') { - data_list = load_xenium_folder_csv(path_list = path_list, - data_to_use = data_to_use, - h5_expression = h5_expression, - h5_gene_ids = h5_gene_ids, - gene_column_index = gene_column_index, - cores = cores, - verbose = verbose) - } - - if(load_format == 'parquet') { - data_list = load_xenium_folder_parquet(path_list = path_list, - data_to_use = data_to_use, - h5_expression = h5_expression, - h5_gene_ids = h5_gene_ids, - gene_column_index = gene_column_index, - cores = cores, - verbose = verbose) - } - - if(load_format == 'zarr') { - # TODO - } - - - return(data_list) -} - - -#' @describeIn load_xenium_folder Load from csv files -#' @keywords internal -load_xenium_folder_csv = function(path_list, - cores, - data_to_use = 'subcellular', - h5_expression = FALSE, - h5_gene_ids = 'symbols', - gene_column_index = 1, - verbose = TRUE) { - - # initialize return vars - feat_meta = tx_dt = bound_dt_list = cell_meta = agg_expr = NULL - - if(isTRUE(verbose)) message('Loading feature metadata...') - feat_meta = data.table::fread(path_list$panel_meta_path[[1]], nThread = cores) - colnames(feat_meta)[[1]] = 'feat_ID' - - # **** subcellular info **** - if(data_to_use == 'subcellular') { - # append missing QC probe info to feat_meta - if(isTRUE(h5_expression)) { - h5 = hdf5r::H5File$new(path_list$agg_expr_path) - tryCatch({ - root = names(h5) - feature_id = h5[[paste0(root, "/features/id")]][] - feature_info = h5[[paste0(root,"/features/feature_type")]][] - feature_names = h5[[paste0(root, "/features/name")]][] - features_dt = data.table::data.table( - 'id' = feature_id, - 'name' = feature_names, - 'feature_type' = feature_info - ) - }, finally = { - h5$close_all() - }) - } else { - features_dt = data.table::fread(paste0(path_list$agg_expr_path, '/features.tsv.gz'), header = F) - } - colnames(features_dt) = c('id', 'feat_ID', 'feat_class') - feat_meta = merge(features_dt[,c(2,3)], feat_meta, all.x = TRUE, by = 'feat_ID') - - if(isTRUE(verbose)) message('Loading transcript level info...') - tx_dt = data.table::fread(path_list$tx_path[[1]], nThread = cores) - data.table::setnames(x = tx_dt, - old = c('feature_name', 'x_location', 'y_location'), - new = c('feat_ID', 'x', 'y')) - if(isTRUE(verbose)) message('Loading boundary info...') - bound_dt_list = lapply(path_list$bound_paths, function(x) data.table::fread(x[[1]], nThread = cores)) - } - - # **** aggregate info **** - if(isTRUE(verbose)) message('Loading cell metadata...') - cell_meta = data.table::fread(path_list$cell_meta_path[[1]], nThread = cores) - - if(data_to_use == 'aggregate') { - if(isTRUE(verbose)) message('Loading aggregated expression...') - if(isTRUE(h5_expression)) agg_expr = get10Xmatrix_h5(path_to_data = path_list$agg_expr_path, - gene_ids = h5_gene_ids, - remove_zero_rows = TRUE, - split_by_type = TRUE) - else agg_expr = get10Xmatrix(path_to_data = path_list$agg_expr_path, - gene_column_index = gene_column_index, - remove_zero_rows = TRUE, - split_by_type = TRUE) - } - - data_list = list( - 'feat_meta' = feat_meta, - 'tx_dt' = tx_dt, - 'bound_dt_list' = bound_dt_list, - 'cell_meta' = cell_meta, - 'agg_expr' = agg_expr - ) - - return(data_list) - -} - - - - -#' @describeIn load_xenium_folder Load from parquet files -#' @keywords internal -load_xenium_folder_parquet = function(path_list, - cores, - data_to_use = 'subcellular', - h5_expression = FALSE, - h5_gene_ids = 'symbols', - gene_column_index = 1, - verbose = TRUE) { - - # initialize return vars - feat_meta = tx_dt = bound_dt_list = cell_meta = agg_expr = NULL - - if(isTRUE(verbose)) message('Loading feature metadata...') - feat_meta = data.table::fread(path_list$panel_meta_path[[1]], nThread = cores) - colnames(feat_meta)[[1]] = 'feat_ID' - - # **** subcellular info **** - if(data_to_use == 'subcellular') { - - # define for data.table - transcript_id = feature_name = NULL - - # append missing QC probe info to feat_meta - if(isTRUE(h5_expression)) { - h5 = hdf5r::H5File$new(path_list$agg_expr_path) - tryCatch({ - root = names(h5) - feature_id = h5[[paste0(root, "/features/id")]][] - feature_info = h5[[paste0(root,"/features/feature_type")]][] - feature_names = h5[[paste0(root, "/features/name")]][] - features_dt = data.table::data.table( - 'id' = feature_id, - 'name' = feature_names, - 'feature_type' = feature_info - ) - }, finally = { - h5$close_all() - }) - } else { - features_dt = arrow::read_tsv_arrow(paste0(path_list$agg_expr_path, '/features.tsv.gz'), - col_names = FALSE) %>% - data.table::setDT() - } - colnames(features_dt) = c('id', 'feat_ID', 'feat_class') - feat_meta = merge(features_dt[,c(2,3)], feat_meta, all.x = TRUE, by = 'feat_ID') - - if(isTRUE(verbose)) message('Loading transcript level info...') - tx_dt = arrow::read_parquet(file = path_list$tx_path[[1]], as_data_frame = FALSE) %>% - dplyr::mutate(transcript_id = cast(transcript_id, arrow::string())) %>% - dplyr::mutate(cell_id = cast(cell_id, arrow::string())) %>% - dplyr::mutate(feature_name = cast(feature_name, arrow::string())) %>% - as.data.frame() %>% - data.table::setDT() - data.table::setnames(x = tx_dt, - old = c('feature_name', 'x_location', 'y_location'), - new = c('feat_ID', 'x', 'y')) - if(isTRUE(verbose)) message('Loading boundary info...') - bound_dt_list = lapply(path_list$bound_paths, function(x) { - arrow::read_parquet(file = x[[1]], as_data_frame = FALSE) %>% - dplyr::mutate(cell_id = cast(cell_id, arrow::string())) %>% - as.data.frame() %>% - data.table::setDT()}) - } - # **** aggregate info **** - if(data_to_use == 'aggregate') { - if(isTRUE(verbose)) message('Loading cell metadata...') - cell_meta = arrow::read_parquet(file = path_list$cell_meta_path[[1]], as_data_frame = FALSE) %>% - dplyr::mutate(cell_id = cast(cell_id, arrow::string())) %>% - as.data.frame() %>% - data.table::setDT() - - # NOTE: no parquet for agg_expr. - if(isTRUE(verbose)) message('Loading aggregated expression...') - if(isTRUE(h5_expression)) agg_expr = get10Xmatrix_h5(path_to_data = path_list$agg_expr_path, - gene_ids = h5_gene_ids, - remove_zero_rows = TRUE, - split_by_type = TRUE) - else agg_expr = get10Xmatrix(path_to_data = path_list$agg_expr_path, - gene_column_index = gene_column_index, - remove_zero_rows = TRUE, - split_by_type = TRUE) - } - - data_list = list( - 'feat_meta' = feat_meta, - 'tx_dt' = tx_dt, - 'bound_dt_list' = bound_dt_list, - 'cell_meta' = cell_meta, - 'agg_expr' = agg_expr - ) - - return(data_list) - -} - +# ********************************************************************** # +# Spatial-method specific object creation convenience functions moved to +# convenience_create.R +# ********************************************************************** # diff --git a/R/utilities.R b/R/utilities.R index 6d4561258..0cd296c0b 100644 --- a/R/utilities.R +++ b/R/utilities.R @@ -646,6 +646,63 @@ emacs_version = function() { as.numeric(ver) } +# time periods #### + +#' @title Round seconds to other periods of time +#' @name round_seconds +#' @keywords internal +round_seconds = function(sec, + output = c('list', 'char')) { + + output = match.arg(output, choices = c('list', 'char')) + + days = floor(sec/86400) + hrs = floor((sec%%86400)/3600) + mins = floor(((sec%%86400)%%3600/60)) + secs = (((sec%%86400)%%3600%%60)) + + out = list() + if(days > 0) out$days = days + if(hrs > 0) out$hrs = hrs + if(mins > 0) out$mins = mins + if(secs > 0) out$secs = secs + + out_print = paste( + switch(length(out$days) + 1, NULL, paste0(days, 'D')), + switch(length(out$hrs) + 1, NULL, paste0(hrs, 'H')), + switch(length(out$mins) + 1, NULL, paste0(mins, 'M')), + switch(length(out$secs) + 1, NULL, paste0(secs, 'S')) + ) + + if(output == 'list') { + return(out) + } else if(output == 'char') { + return(out_print) + } +} + +# progress bar setup #### + +#' @title Create a txt progressbar +#' @name create_pb +#' @keywords internal +create_pb = function(max, + min = 0, + width = min(35, getOption('width')), + char = '=') { + + txtProgressBar(min = min, + max = max, + style = 3, + width = width, + char = char) + +} + + + + + diff --git a/man/createGiottoCosMxObject.Rd b/man/createGiottoCosMxObject.Rd index bcbf9374d..80c56e389 100644 --- a/man/createGiottoCosMxObject.Rd +++ b/man/createGiottoCosMxObject.Rd @@ -1,5 +1,5 @@ % Generated by roxygen2: do not edit by hand -% Please edit documentation in R/giotto.R +% Please edit documentation in R/convenience_create.R \name{createGiottoCosMxObject} \alias{createGiottoCosMxObject} \title{Create Nanostring CosMx Giotto Object} diff --git a/man/createGiottoCosMxObject_aggregate.Rd b/man/createGiottoCosMxObject_aggregate.Rd index 2bdd6d595..aa1f48cf5 100644 --- a/man/createGiottoCosMxObject_aggregate.Rd +++ b/man/createGiottoCosMxObject_aggregate.Rd @@ -1,5 +1,5 @@ % Generated by roxygen2: do not edit by hand -% Please edit documentation in R/giotto.R +% Please edit documentation in R/convenience_create.R \name{createGiottoCosMxObject_aggregate} \alias{createGiottoCosMxObject_aggregate} \title{Load and create a CosMx Giotto object from aggregate info} diff --git a/man/createGiottoCosMxObject_all.Rd b/man/createGiottoCosMxObject_all.Rd index 15559138a..ad2a5ab14 100644 --- a/man/createGiottoCosMxObject_all.Rd +++ b/man/createGiottoCosMxObject_all.Rd @@ -1,5 +1,5 @@ % Generated by roxygen2: do not edit by hand -% Please edit documentation in R/giotto.R +% Please edit documentation in R/convenience_create.R \name{createGiottoCosMxObject_all} \alias{createGiottoCosMxObject_all} \title{Load and create a CosMx Giotto object from subcellular and aggregate info} diff --git a/man/createGiottoCosMxObject_subcellular.Rd b/man/createGiottoCosMxObject_subcellular.Rd index fef11853c..4621359a0 100644 --- a/man/createGiottoCosMxObject_subcellular.Rd +++ b/man/createGiottoCosMxObject_subcellular.Rd @@ -1,5 +1,5 @@ % Generated by roxygen2: do not edit by hand -% Please edit documentation in R/giotto.R +% Please edit documentation in R/convenience_create.R \name{createGiottoCosMxObject_subcellular} \alias{createGiottoCosMxObject_subcellular} \title{Load and create a CosMx Giotto object from subcellular info} diff --git a/man/createGiottoMerscopeObject.Rd b/man/createGiottoMerscopeObject.Rd new file mode 100644 index 000000000..e79bb07cd --- /dev/null +++ b/man/createGiottoMerscopeObject.Rd @@ -0,0 +1,65 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/convenience_create.R +\name{createGiottoMerscopeObject} +\alias{createGiottoMerscopeObject} +\alias{createGiottoMerscopeObject_subcellular} +\alias{createGiottoMerscopeObject_aggregate} +\title{Create Vizgen MERSCOPE Giotto Object} +\usage{ +createGiottoMerscopeObject( + merscope_dir, + data_to_use = c("subcellular", "aggregate"), + FOVs = NULL, + instructions = NULL, + cores = NA, + verbose = TRUE +) + +createGiottoMerscopeObject_subcellular(data_list, cores = NA, verbose = TRUE) + +createGiottoMerscopeObject_aggregate(data_list, cores = NA, verbose = TRUE) +} +\arguments{ +\item{merscope_dir}{full path to the exported merscope directory} + +\item{data_to_use}{which of either the 'subcellular' or 'aggregate' information +to use for object creation} + +\item{FOVs}{which FOVs to use when building the subcellular object. (default is NULL) +NULL loads all FOVs (very slow)} + +\item{instructions}{list of instructions or output result from \code{\link{createGiottoInstructions}}} + +\item{cores}{how many cores or threads to use to read data if paths are provided} + +\item{verbose}{be verbose when building Giotto object} + +\item{data_list}{list of loaded data from \code{\link{load_merscope_folder}}} +} +\value{ +a giotto object +} +\description{ +Given the path to a MERSCOPE experiment directory, creates a Giotto +object. +} +\details{ +[\strong{Expected Directory}] This function generates a giotto object when given a +link to a MERSCOPE output directory. It expects the following items within the directory +where the \strong{bolded} portions are what this function matches against: +\itemize{ + \item{\strong{cell_boundaries} (folder .hdf5 files)} + \item{\strong{images} (folder of .tif images and a scalefactor/transfrom table)} + \item{\strong{cell_by_gene}.csv (file)} + \item{cell_metadata\strong{fov_positions_file}.csv (file)} + \item{detected_transcripts\strong{metadata_file}.csv (file)} +} +} +\section{Functions}{ +\itemize{ +\item \code{createGiottoMerscopeObject_subcellular()}: Create giotto object with 'subcellular' workflow + +\item \code{createGiottoMerscopeObject_aggregate()}: Create giotto object with 'aggregate' workflow + +}} +\keyword{internal} diff --git a/man/createGiottoXeniumObject.Rd b/man/createGiottoXeniumObject.Rd index 686d31d5b..0c6943241 100644 --- a/man/createGiottoXeniumObject.Rd +++ b/man/createGiottoXeniumObject.Rd @@ -1,5 +1,5 @@ % Generated by roxygen2: do not edit by hand -% Please edit documentation in R/giotto.R +% Please edit documentation in R/convenience_create.R \name{createGiottoXeniumObject} \alias{createGiottoXeniumObject} \title{Create 10x Xenium Giotto Object} diff --git a/man/createGiottoXeniumObject_aggregate.Rd b/man/createGiottoXeniumObject_aggregate.Rd index 1efeb4935..a414df3b9 100644 --- a/man/createGiottoXeniumObject_aggregate.Rd +++ b/man/createGiottoXeniumObject_aggregate.Rd @@ -1,5 +1,5 @@ % Generated by roxygen2: do not edit by hand -% Please edit documentation in R/giotto.R +% Please edit documentation in R/convenience_create.R \name{createGiottoXeniumObject_aggregate} \alias{createGiottoXeniumObject_aggregate} \title{Create a Xenium Giotto object from aggregate info} diff --git a/man/createGiottoXeniumObject_subcellular.Rd b/man/createGiottoXeniumObject_subcellular.Rd index da219c25d..9c5dadc12 100644 --- a/man/createGiottoXeniumObject_subcellular.Rd +++ b/man/createGiottoXeniumObject_subcellular.Rd @@ -1,5 +1,5 @@ % Generated by roxygen2: do not edit by hand -% Please edit documentation in R/giotto.R +% Please edit documentation in R/convenience_create.R \name{createGiottoXeniumObject_subcellular} \alias{createGiottoXeniumObject_subcellular} \title{Create a Xenium Giotto object from subcellular info} diff --git a/man/create_pb.Rd b/man/create_pb.Rd new file mode 100644 index 000000000..0f5025b7a --- /dev/null +++ b/man/create_pb.Rd @@ -0,0 +1,12 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/utilities.R +\name{create_pb} +\alias{create_pb} +\title{Create a txt progressbar} +\usage{ +create_pb(max, min = 0, width = min(35, getOption("width")), char = "=") +} +\description{ +Create a txt progressbar +} +\keyword{internal} diff --git a/man/load_cosmx_folder_aggregate.Rd b/man/load_cosmx_folder_aggregate.Rd index f1641b9dd..cad49acca 100644 --- a/man/load_cosmx_folder_aggregate.Rd +++ b/man/load_cosmx_folder_aggregate.Rd @@ -1,5 +1,5 @@ % Generated by roxygen2: do not edit by hand -% Please edit documentation in R/giotto.R +% Please edit documentation in R/convenience_create.R \name{load_cosmx_folder_aggregate} \alias{load_cosmx_folder_aggregate} \title{Load CosMx folder aggregate info} diff --git a/man/load_cosmx_folder_subcellular.Rd b/man/load_cosmx_folder_subcellular.Rd index 7b2a90031..7e0b28a86 100644 --- a/man/load_cosmx_folder_subcellular.Rd +++ b/man/load_cosmx_folder_subcellular.Rd @@ -1,5 +1,5 @@ % Generated by roxygen2: do not edit by hand -% Please edit documentation in R/giotto.R +% Please edit documentation in R/convenience_create.R \name{load_cosmx_folder_subcellular} \alias{load_cosmx_folder_subcellular} \title{Load CosMx folder subcellular info} diff --git a/man/load_merscope_folder.Rd b/man/load_merscope_folder.Rd new file mode 100644 index 000000000..2dc9a83c0 --- /dev/null +++ b/man/load_merscope_folder.Rd @@ -0,0 +1,55 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/convenience_create.R +\name{load_merscope_folder} +\alias{load_merscope_folder} +\alias{load_merscope_folder_subcellular} +\alias{load_merscope_folder_aggregate} +\title{Load MERSCOPE data from folder} +\usage{ +load_merscope_folder( + dir_items, + data_to_use, + fovs = NULL, + cores = NA, + verbose = TRUE +) + +load_merscope_folder_subcellular( + dir_items, + data_to_use, + cores = NA, + verbose = TRUE, + fovs = NULL +) + +load_merscope_folder_aggregate( + dir_items, + data_to_use, + cores = NA, + verbose = TRUE +) +} +\arguments{ +\item{dir_items}{list of full filepaths from \code{\link{read_merscope_folder}}} + +\item{data_to_use}{which of either the 'subcellular' or 'aggregate' information +to use for object creation} + +\item{cores}{how many cores or threads to use to read data if paths are provided} + +\item{verbose}{be verbose when building Giotto object} +} +\value{ +list of loaded-in MERSCOPE data +} +\description{ +Load MERSCOPE data from folder +} +\section{Functions}{ +\itemize{ +\item \code{load_merscope_folder_subcellular()}: Load items for 'subcellular' workflow + +\item \code{load_merscope_folder_aggregate()}: Load items for 'aggregate' workflow + +}} +\keyword{internal} diff --git a/man/load_xenium_folder.Rd b/man/load_xenium_folder.Rd index c6f46b185..1f4c7cbd4 100644 --- a/man/load_xenium_folder.Rd +++ b/man/load_xenium_folder.Rd @@ -1,5 +1,5 @@ % Generated by roxygen2: do not edit by hand -% Please edit documentation in R/giotto.R +% Please edit documentation in R/convenience_create.R \name{load_xenium_folder} \alias{load_xenium_folder} \alias{load_xenium_folder_csv} diff --git a/man/read_cosmx_folder.Rd b/man/read_cosmx_folder.Rd index 8e444c717..1607283d3 100644 --- a/man/read_cosmx_folder.Rd +++ b/man/read_cosmx_folder.Rd @@ -1,5 +1,5 @@ % Generated by roxygen2: do not edit by hand -% Please edit documentation in R/giotto.R +% Please edit documentation in R/convenience_create.R \name{read_cosmx_folder} \alias{read_cosmx_folder} \title{Read a structured CosMx folder} diff --git a/man/read_data_folder.Rd b/man/read_data_folder.Rd new file mode 100644 index 000000000..bf8625909 --- /dev/null +++ b/man/read_data_folder.Rd @@ -0,0 +1,59 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/convenience_create.R +\name{read_data_folder} +\alias{read_data_folder} +\alias{read_merscope_folder} +\title{Read a structured folder of exported data} +\usage{ +read_data_folder( + spat_method = NULL, + data_dir = NULL, + dir_items, + data_to_use, + load_format = NULL, + require_data_DT, + cores = NA, + verbose = TRUE +) + +read_merscope_folder(merscope_dir, data_to_use, cores = NA, verbose = TRUE) +} +\arguments{ +\item{spat_method}{spatial method for which the data is being read} + +\item{data_dir}{exported data directory to read from} + +\item{dir_items}{named list of directory items to expect and keywords to match} + +\item{data_to_use}{which type(s) of expression data to build the gobject with} + +\item{require_data_DT}{data.table detailing if expected data items are required +or optional for each \code{data_to_use} workflow} + +\item{cores}{cores to use} + +\item{verbose}{be verbose} +} +\description{ +Read the exported folder of a spatial method and +detect the presence of needed files. NULL values denote missing items. +} +\details{ +Steps performed: +\itemize{ + \item{1. detection of items within \code{data_dir} by looking for keywords + assigned through \code{dir_items}} + \item{2. check of detected items to see if everything needed has been found. + Dictionary of necessary vs optional items for each \code{data_to_use} workflow + is provided through \code{require_data_DT}} + \item{3. if multiple filepaths are found to be matching then select the first + one. This function is only intended to find the first level subdirectories + and files.} +} +} +\section{Functions}{ +\itemize{ +\item \code{read_merscope_folder()}: Read a structured MERSCOPE folder + +}} +\keyword{internal} diff --git a/man/read_xenium_folder.Rd b/man/read_xenium_folder.Rd index e4df7b4f7..af0de5996 100644 --- a/man/read_xenium_folder.Rd +++ b/man/read_xenium_folder.Rd @@ -1,5 +1,5 @@ % Generated by roxygen2: do not edit by hand -% Please edit documentation in R/giotto.R +% Please edit documentation in R/convenience_create.R \name{read_xenium_folder} \alias{read_xenium_folder} \title{Read a structured xenium folder} diff --git a/man/round_seconds.Rd b/man/round_seconds.Rd new file mode 100644 index 000000000..1b02b2055 --- /dev/null +++ b/man/round_seconds.Rd @@ -0,0 +1,12 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/utilities.R +\name{round_seconds} +\alias{round_seconds} +\title{Round seconds to other periods of time} +\usage{ +round_seconds(sec, output = c("list", "char")) +} +\description{ +Round seconds to other periods of time +} +\keyword{internal} From 488beb6f36d60168fad06b568365f49961f14a14 Mon Sep 17 00:00:00 2001 From: jiajic <72078254+jiajic@users.noreply.github.com> Date: Fri, 9 Dec 2022 03:06:27 -0500 Subject: [PATCH 010/129] typos --- R/convenience_create.R | 2 +- R/general_help.R | 5 +++-- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/R/convenience_create.R b/R/convenience_create.R index 605820873..3bc2b8c9d 100644 --- a/R/convenience_create.R +++ b/R/convenience_create.R @@ -174,7 +174,7 @@ createGiottoMerscopeObject = function(merscope_dir, if(data_to_use == 'subcellular') { merscope_gobject = createGiottoMerscopeObject_subcellular(data_list = data_list, - corse = cores, + cores = cores, verbose = verbose) } else if(data_to_use == 'aggregate') { diff --git a/R/general_help.R b/R/general_help.R index 3750c437d..a42c72a43 100644 --- a/R/general_help.R +++ b/R/general_help.R @@ -1385,6 +1385,7 @@ readPolygonFilesVizgenHDF5 = function(boundaries_path, if(verbose == TRUE) cat('hdf5: ', (hdf5_list_length - bound_i) ,'\n') print(hdf5_boundary_selected_list[bound_i][[1]]) + cat('\n') # read file and select feature data read_file = rhdf5::H5Fopen(hdf5_boundary_selected_list[bound_i][[1]], flags = H5Fopen_flags) @@ -1423,8 +1424,8 @@ readPolygonFilesVizgenHDF5 = function(boundaries_path, remaining = round_seconds(sec = round(as.numeric(est)), output = 'char') time_taken = round_seconds(sec = round(as.numeric(time)), output = 'char') - cat(paste(' // Execution time:', time_taken, - ' // Estimated time remaining:', remaining), '') + cat(wrap_txt('\n // Execution time:', time_taken, + '// Estimated time remaining:', remaining), '\n') } From 8b817e0b00cb3b06af4521441c974b6c10722091 Mon Sep 17 00:00:00 2001 From: jiajic <72078254+jiajic@users.noreply.github.com> Date: Fri, 9 Dec 2022 03:13:19 -0500 Subject: [PATCH 011/129] Update general_help.R --- R/general_help.R | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/R/general_help.R b/R/general_help.R index a42c72a43..2fed9d029 100644 --- a/R/general_help.R +++ b/R/general_help.R @@ -1359,8 +1359,8 @@ readPolygonFilesVizgenHDF5 = function(boundaries_path, } - if(verbose == TRUE) cat('finished listing .hdf5 files \n - start extracting .hdf5 information \n') + if(verbose == TRUE) cat(wrap_txt('finished listing .hdf5 files + start extracting .hdf5 information')) # read selected polygon files start_index = 1 From 987b7c68333f5b9366397b02a27c250aa15f46fa Mon Sep 17 00:00:00 2001 From: jiajic <72078254+jiajic@users.noreply.github.com> Date: Fri, 9 Dec 2022 10:10:29 -0500 Subject: [PATCH 012/129] update vizgen read HDF5 change for loop to lapply_flex --- R/general_help.R | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/R/general_help.R b/R/general_help.R index 2fed9d029..8b34ed816 100644 --- a/R/general_help.R +++ b/R/general_help.R @@ -1302,6 +1302,7 @@ convertEnsemblToGeneSymbol = function(matrix, #' @param smooth_vertices number of vertices for smoothing #' @param set_neg_to_zero set negative values to zero when smoothing #' @param H5Fopen_flags see \code{\link[rhdf5]{H5Fopen}} for more details +#' @param cores cores to use #' @param verbose be verbose #' @seealso \code{\link{smoothGiottoPolygons}} #' @details Set H5Fopen_flags to "H5F_ACC_RDONLY" if you encounter permission issues. @@ -1316,10 +1317,13 @@ readPolygonFilesVizgenHDF5 = function(boundaries_path, smooth_vertices = 60, set_neg_to_zero = FALSE, H5Fopen_flags = "H5F_ACC_RDWR", + cores = NA, verbose = TRUE) { package_check(pkg_name = 'rhdf5', repository = 'Bioc') + cores = determine_cores(cores) + # define for .() x = NULL y = NULL @@ -1378,12 +1382,12 @@ readPolygonFilesVizgenHDF5 = function(boundaries_path, init = numeric() end = numeric() - for(bound_i in seq(hdf5_list_length)) { + lapply_flex(seq(hdf5_list_length), cores = cores, function(bound_i) { # time start init[bound_i] = Sys.time() - if(verbose == TRUE) cat('hdf5: ', (hdf5_list_length - bound_i) ,'\n') + if(verbose == TRUE) cat('\n','hdf5: ', (hdf5_list_length - bound_i) ,'\n') print(hdf5_boundary_selected_list[bound_i][[1]]) cat('\n') @@ -1427,7 +1431,7 @@ readPolygonFilesVizgenHDF5 = function(boundaries_path, cat(wrap_txt('\n // Execution time:', time_taken, '// Estimated time remaining:', remaining), '\n') - } + }) close(pb) From c698f77ff0c360102e72b1e1adbd4811c7bd40db Mon Sep 17 00:00:00 2001 From: jiajic <72078254+jiajic@users.noreply.github.com> Date: Fri, 9 Dec 2022 11:03:37 -0500 Subject: [PATCH 013/129] fix time tracking --- R/general_help.R | 19 +++++-------- R/utilities.R | 44 ++++++++++--------------------- man/readPolygonFilesVizgenHDF5.Rd | 3 +++ man/round_seconds.Rd | 12 --------- man/time_format.Rd | 15 +++++++++++ 5 files changed, 38 insertions(+), 55 deletions(-) delete mode 100644 man/round_seconds.Rd create mode 100644 man/time_format.Rd diff --git a/R/general_help.R b/R/general_help.R index 8b34ed816..dd69183a1 100644 --- a/R/general_help.R +++ b/R/general_help.R @@ -1378,15 +1378,10 @@ readPolygonFilesVizgenHDF5 = function(boundaries_path, n_iter = 100 pb = create_pb(max = hdf5_list_length) - # keep track of time per iteration - init = numeric() - end = numeric() + init = proc.time() lapply_flex(seq(hdf5_list_length), cores = cores, function(bound_i) { - # time start - init[bound_i] = Sys.time() - if(verbose == TRUE) cat('\n','hdf5: ', (hdf5_list_length - bound_i) ,'\n') print(hdf5_boundary_selected_list[bound_i][[1]]) cat('\n') @@ -1420,16 +1415,14 @@ readPolygonFilesVizgenHDF5 = function(boundaries_path, } # time end - end[bound_i] = Sys.time() setTxtProgressBar(pb, bound_i) - time = sum(end - init) # estimated time remaining - est = hdf5_list_length * (mean(end[end != 0] - init[init != 0])) - time - remaining = round_seconds(sec = round(as.numeric(est)), output = 'char') - time_taken = round_seconds(sec = round(as.numeric(time)), output = 'char') + elapsed = (proc.time() - init)[[3L]] + step_time = elapsed/bound_i + est = (hdf5_list_length * step_time) - elapsed - cat(wrap_txt('\n // Execution time:', time_taken, - '// Estimated time remaining:', remaining), '\n') + cat(wrap_txt('\n // Execution time:', time_format(elapsed), + '// Estimated time remaining:', time_format(est), '\n')) }) diff --git a/R/utilities.R b/R/utilities.R index 0cd296c0b..0e879ed91 100644 --- a/R/utilities.R +++ b/R/utilities.R @@ -646,38 +646,22 @@ emacs_version = function() { as.numeric(ver) } -# time periods #### +# time format #### -#' @title Round seconds to other periods of time -#' @name round_seconds +#' @title Format time for printing +#' @name time_format #' @keywords internal -round_seconds = function(sec, - output = c('list', 'char')) { - - output = match.arg(output, choices = c('list', 'char')) - - days = floor(sec/86400) - hrs = floor((sec%%86400)/3600) - mins = floor(((sec%%86400)%%3600/60)) - secs = (((sec%%86400)%%3600%%60)) - - out = list() - if(days > 0) out$days = days - if(hrs > 0) out$hrs = hrs - if(mins > 0) out$mins = mins - if(secs > 0) out$secs = secs - - out_print = paste( - switch(length(out$days) + 1, NULL, paste0(days, 'D')), - switch(length(out$hrs) + 1, NULL, paste0(hrs, 'H')), - switch(length(out$mins) + 1, NULL, paste0(mins, 'M')), - switch(length(out$secs) + 1, NULL, paste0(secs, 'S')) - ) - - if(output == 'list') { - return(out) - } else if(output == 'char') { - return(out_print) +#' @details Code from \code{\link[data.table]{timetaken}} +time_format = function(secs) { + if (secs > 60) { + secs = as.integer(secs) + sprintf("%02d:%02d:%02d", secs%/%3600L, (secs%/%60L)%%60L, + secs%%60L) + } + else { + sprintf(if (secs >= 10) + "%.1fs" + else "%.3fs", secs) } } diff --git a/man/readPolygonFilesVizgenHDF5.Rd b/man/readPolygonFilesVizgenHDF5.Rd index 459bcb5fc..4573162d3 100644 --- a/man/readPolygonFilesVizgenHDF5.Rd +++ b/man/readPolygonFilesVizgenHDF5.Rd @@ -15,6 +15,7 @@ readPolygonFilesVizgenHDF5( smooth_vertices = 60, set_neg_to_zero = FALSE, H5Fopen_flags = "H5F_ACC_RDWR", + cores = NA, verbose = TRUE ) } @@ -40,6 +41,8 @@ readPolygonFilesVizgenHDF5( \item{H5Fopen_flags}{see \code{\link[rhdf5]{H5Fopen}} for more details} +\item{cores}{cores to use} + \item{verbose}{be verbose} } \description{ diff --git a/man/round_seconds.Rd b/man/round_seconds.Rd deleted file mode 100644 index 1b02b2055..000000000 --- a/man/round_seconds.Rd +++ /dev/null @@ -1,12 +0,0 @@ -% Generated by roxygen2: do not edit by hand -% Please edit documentation in R/utilities.R -\name{round_seconds} -\alias{round_seconds} -\title{Round seconds to other periods of time} -\usage{ -round_seconds(sec, output = c("list", "char")) -} -\description{ -Round seconds to other periods of time -} -\keyword{internal} diff --git a/man/time_format.Rd b/man/time_format.Rd new file mode 100644 index 000000000..be19f26e2 --- /dev/null +++ b/man/time_format.Rd @@ -0,0 +1,15 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/utilities.R +\name{time_format} +\alias{time_format} +\title{Format time for printing} +\usage{ +time_format(secs) +} +\description{ +Format time for printing +} +\details{ +Code from \code{\link[data.table]{timetaken}} +} +\keyword{internal} From 696e6af37249f72fca2383fd04c750700e6cebb0 Mon Sep 17 00:00:00 2001 From: jiajic <72078254+jiajic@users.noreply.github.com> Date: Fri, 9 Dec 2022 14:43:27 -0500 Subject: [PATCH 014/129] test lapply --- R/general_help.R | 53 +++++++++++++++++++++++------------------------- 1 file changed, 25 insertions(+), 28 deletions(-) diff --git a/R/general_help.R b/R/general_help.R index dd69183a1..6998de108 100644 --- a/R/general_help.R +++ b/R/general_help.R @@ -1367,10 +1367,9 @@ readPolygonFilesVizgenHDF5 = function(boundaries_path, start extracting .hdf5 information')) # read selected polygon files - start_index = 1 # create a results list for each z index of the polygon file - result_list = replicate(length(polygon_feat_types), list()) - multidt_list = replicate(length(polygon_feat_types), list()) + # result_list = replicate(length(polygon_feat_types), list()) + # multidt_list = replicate(length(polygon_feat_types), list()) hdf5_list_length = length(hdf5_boundary_selected_list) @@ -1380,20 +1379,23 @@ readPolygonFilesVizgenHDF5 = function(boundaries_path, init = proc.time() - lapply_flex(seq(hdf5_list_length), cores = cores, function(bound_i) { + # lapply for list of hdf5 to read + result_list = lapply_flex(seq(hdf5_list_length), cores = cores, function(bound_i) { - if(verbose == TRUE) cat('\n','hdf5: ', (hdf5_list_length - bound_i) ,'\n') - print(hdf5_boundary_selected_list[bound_i][[1]]) - cat('\n') + if(verbose == TRUE) { + cat('\n','hdf5: ', (hdf5_list_length - bound_i) ,'\n') + print(hdf5_boundary_selected_list[bound_i][[1]]) + cat('\n') + } # read file and select feature data read_file = rhdf5::H5Fopen(hdf5_boundary_selected_list[bound_i][[1]], flags = H5Fopen_flags) featdt = read_file$featuredata cell_names = names(featdt) - # extract values for each z index - for(cell_i in 1:length(featdt)) { - for(z_i in 1:length(poly_feat_indexes)) { + # extract values for each z index and cell + result_list = lapply_flex(seq_along(poly_feat_indexes), cores = cores, function(z_i) { + lapply_flex(seq_along(featdt), cores = cores, function(cell_i) { singlearray = featdt[[cell_i]][[poly_feat_indexes[z_i]]]$p_0$coordinates cell_name = cell_names[[cell_i]] if(!is.null(singlearray)) { @@ -1404,15 +1406,13 @@ readPolygonFilesVizgenHDF5 = function(boundaries_path, singlearraydt[, file_id := paste0('file', bound_i)] singlearraydt[, cell_id := cell_name] - singlearraydt[, my_id := paste0('cell', start_index)] - result_list[[z_i]][[start_index]] = singlearraydt + singlearraydt[, my_id := paste0('cell', cell_i)] } - } - start_index = start_index + 1 - } - for (i in 1:length(multidt_list)) { - multidt_list[[i]] = do.call('rbind', result_list[[i]]) - } + }) + }) + multidt_list = lapply_flex(seq_along(result_list), cores = cores, function(z_i) { + do.call('rbind', result_list[[z_i]]) + }) # time end setTxtProgressBar(pb, bound_i) @@ -1433,24 +1433,21 @@ readPolygonFilesVizgenHDF5 = function(boundaries_path, # create Giotto polygons and add them to gobject - smooth_cell_polygons_list = list() + # smooth_cell_polygons_list = list() - for (i in 1:length(multidt_list)) { + smooth_cell_polygons_list = lapply_flex(seq_along(multidt_list), cores = cores, function(i) { dfr_subset = multidt_list[[i]][,.(x, y, cell_id)] cell_polygons = createGiottoPolygonsFromDfr(segmdfr = dfr_subset, name = poly_feat_names[i]) if(smooth_polygons == TRUE) { - smooth_cell_polygons = smoothGiottoPolygons(cell_polygons, - vertices = smooth_vertices, - set_neg_to_zero = set_neg_to_zero) + return(smoothGiottoPolygons(cell_polygons, + vertices = smooth_vertices, + set_neg_to_zero = set_neg_to_zero)) } else { - smooth_cell_polygons = cell_polygons + return(cell_polygons) } - - smooth_cell_polygons_list[[i]] = smooth_cell_polygons - } - + }) # TODO: add spatial centroids # needs to happen after smoothing to be correct From a4656ebe7e41eb041ce657b6c771faec7326c2c4 Mon Sep 17 00:00:00 2001 From: jiajic <72078254+jiajic@users.noreply.github.com> Date: Sat, 10 Dec 2022 17:00:15 -0500 Subject: [PATCH 015/129] vizgen workflow update add `fread_colmatch()` try to fix vizgen HDF5 polygon reading more work on vizgen loading functions --- NEWS.md | 1 + R/convenience_create.R | 82 ++++++++++++++++++++++++++++++++++++++---- R/general_help.R | 5 +-- R/utilities.R | 37 +++++++++++++++++++ 4 files changed, 117 insertions(+), 8 deletions(-) diff --git a/NEWS.md b/NEWS.md index 7f4df2d53..511412e1f 100644 --- a/NEWS.md +++ b/NEWS.md @@ -5,6 +5,7 @@ - Add `coord_fix_ratio` param to `spatFeatPlot2D()` and `spatFeatPlot2D_single()` - Add `createGiottoMerscopeObject()` - Move giotto object method-specific creation functions from `giotto.R` to `convenience_create.R` +- Add `fread_colmatch()` internal for fread loading a subset of rows based on matches in a specified column diff --git a/R/convenience_create.R b/R/convenience_create.R index 3bc2b8c9d..8a7b1d5c4 100644 --- a/R/convenience_create.R +++ b/R/convenience_create.R @@ -128,6 +128,10 @@ read_data_folder = function(spat_method = NULL, #' to use for object creation #' @param FOVs which FOVs to use when building the subcellular object. (default is NULL) #' NULL loads all FOVs (very slow) +#' @param calculate_overlap whether to run \code{\link{calculateOverlapRaster}} +#' @param overlap_to_matrix whether to run \code{\link{overlapToMatrix}} +#' @param aggregate_stack whether to run \code{\link{aggregateStacks}} +#' @param aggregate_stack_param params to pass to \code{\link{aggregateStacks}} #' @inheritParams createGiottoObjectSubcellular #' @return a giotto object #' @export @@ -145,6 +149,12 @@ read_data_folder = function(spat_method = NULL, createGiottoMerscopeObject = function(merscope_dir, data_to_use = c('subcellular', 'aggregate'), FOVs = NULL, + calculate_overlap = TRUE, + overlap_to_matrix = TRUE, + aggregate_stack = TRUE, + aggregate_stack_param = list(summarize_expression = 'sum', + summarize_locations = 'mean', + new_spat_unit = 'cell'), instructions = NULL, cores = NA, verbose = TRUE) { @@ -174,6 +184,10 @@ createGiottoMerscopeObject = function(merscope_dir, if(data_to_use == 'subcellular') { merscope_gobject = createGiottoMerscopeObject_subcellular(data_list = data_list, + calculate_overlap = calculate_overlap, + overlap_to_matrix = overlap_to_matrix, + aggregate_stack = aggregate_stack, + aggregate_stack_param = aggregate_stack_param, cores = cores, verbose = verbose) @@ -198,6 +212,12 @@ createGiottoMerscopeObject = function(merscope_dir, #' @param data_list list of loaded data from \code{\link{load_merscope_folder}} #' @keywords internal createGiottoMerscopeObject_subcellular = function(data_list, + calculate_overlap = TRUE, + overlap_to_matrix = TRUE, + aggregate_stack = TRUE, + aggregate_stack_param = list(summarize_expression = 'sum', + summarize_locations = 'mean', + new_spat_unit = 'cell'), cores = NA, verbose = TRUE) { @@ -207,7 +227,44 @@ createGiottoMerscopeObject_subcellular = function(data_list, micronToPixelScale = data_list$micronToPixelScale image_list = data_list$images + # data.table vars + gene = NULL + # split tx_dt by expression and blank + if(isTRUE(verbose)) wrap_msg('Splitting detections by feature vs blank') + feat_id_all = tx_dt[, unique(gene)] + blank_id = feat_id_all[grepl(pattern = 'Blank', feat_id_all)] + feat_id = feat_id_all[!feat_id_all %in% blank_id] + + feat_dt = tx_dt[gene %in% feat_id,] + blank_dt = tx_dt[gene %in% blank_id,] + + # extract transcript_id col and store as feature meta + feat_meta = unique(feat_dt[, c('gene', 'transcript_id', 'barcode_id'), with = FALSE]) + blank_meta = unique(blank_dt[, c('gene', 'transcript_id', 'barcode_id'), with = FALSE]) + feat_dt[, c('transcript_id', 'barcode_id') := NULL] + blank_dt[, c('transcript_id', 'barcode_id') := NULL] + + if(isTRUE(verbose)) { + message(' > Features: ', feat_dt[, .N]) + message(' > Blanks: ', blank_dt[, .N]) + } + + # build giotto object + if(isTRUE(verbose)) wrap_msg('Building subcellular giotto object...') + z_sub = createGiottoObjectSubcellular( + gpoints = list('rna' = feat_coord, + 'neg_probe' = neg_coord), + gpolygons = list('cell' = cellLabel_dir), + polygon_mask_list_params = list( + mask_method = 'guess', + flip_vertical = TRUE, + flip_horizontal = FALSE, + shift_horizontal_step = FALSE + ), + instructions = instructions, + cores = cores + ) } @@ -223,11 +280,13 @@ createGiottoMerscopeObject_aggregate = function(data_list, # unpack data_list micronToPixelScale = data_list$micronToPixelScale - expr_mat = data_list$expr_mat + expr_dt = data_list$expr_dt cell_meta = data_list$expr_mat image_list = data_list$images + # split expr_dt by expression and blank + # feat_id_all = } @@ -1371,7 +1430,18 @@ load_merscope_folder_subcellular = function(dir_items, fovs = NULL) { if(isTRUE(verbose)) wrap_msg('Loading transcript level info...') - tx_dt = data.table::fread(dir_items$dir_items$`raw transcript info`, nThread = cores) + if(is.null(fovs)) { + tx_dt = data.table::fread(dir_items$`raw transcript info`, nThread = cores) + } else { + if(isTRUE(verbose)) wrap_msg('Selecting FOV subset transcripts') + tx_dt = fread_colmatch(file = dir_items$`raw transcript info`, + col = 'fov', + values_to_match = fovs, + verbose = FALSE, + nThread = cores) + } + tx_dt[, c('x','y') := NULL] # remove unneeded cols + data.table::setcolorder(tx_dt, c('gene', 'global_x', 'global_y', 'global_z')) if(isTRUE(verbose)) wrap_msg('Loading polygon info...') poly_info = readPolygonFilesVizgenHDF5(boundaries_path = dir_items$`boundary info`, @@ -1383,7 +1453,7 @@ load_merscope_folder_subcellular = function(dir_items, 'poly_info' = poly_info, 'tx_dt' = tx_dt, 'micronToPixelScale' = NULL, - 'expr_mat' = NULL, + 'expr_dt' = NULL, 'cell_meta' = NULL, 'images' = NULL ) @@ -1402,16 +1472,16 @@ load_merscope_folder_aggregate = function(dir_items, # metadata is polygon-related measurements if(isTRUE(verbose)) wrap_msg('Loading cell metadata...') cell_metadata_file = data.table::fread(dir_items$`cell metadata`, nThread = cores) - # expr_mat contains Blank probes + if(isTRUE(verbose)) wrap_msg('Loading expression matrix') - expr_mat = data.table::fread(dir_items$`cell feature matrix`, nThread = cores) + expr_dt = data.table::fread(dir_items$`cell feature matrix`, nThread = cores) data_list = list( 'poly_info' = NULL, 'tx_dt' = NULL, 'micronToPixelScale' = NULL, - 'expr_mat' = expr_mat, + 'expr_dt' = expr_dt, 'cell_meta' = cell_metadata_file, 'images' = NULL ) diff --git a/R/general_help.R b/R/general_help.R index 6998de108..3c3ffd694 100644 --- a/R/general_help.R +++ b/R/general_help.R @@ -1380,7 +1380,7 @@ readPolygonFilesVizgenHDF5 = function(boundaries_path, init = proc.time() # lapply for list of hdf5 to read - result_list = lapply_flex(seq(hdf5_list_length), cores = cores, function(bound_i) { + multidt_list = lapply_flex(seq(hdf5_list_length), cores = cores, function(bound_i) { if(verbose == TRUE) { cat('\n','hdf5: ', (hdf5_list_length - bound_i) ,'\n') @@ -1410,7 +1410,7 @@ readPolygonFilesVizgenHDF5 = function(boundaries_path, } }) }) - multidt_list = lapply_flex(seq_along(result_list), cores = cores, function(z_i) { + result_list_rbind = lapply_flex(seq_along(result_list), cores = cores, function(z_i) { do.call('rbind', result_list[[z_i]]) }) @@ -1424,6 +1424,7 @@ readPolygonFilesVizgenHDF5 = function(boundaries_path, cat(wrap_txt('\n // Execution time:', time_format(elapsed), '// Estimated time remaining:', time_format(est), '\n')) + return(result_list_rbind) }) close(pb) diff --git a/R/utilities.R b/R/utilities.R index 0e879ed91..cf02a3c98 100644 --- a/R/utilities.R +++ b/R/utilities.R @@ -684,8 +684,45 @@ create_pb = function(max, } +#' @param file path to file to load +#' @param col name of col to match from +#' @param sep grep term to match as column delimiters within the file +#' @param values_to_match values in \code{col} to match given as a vector +#' @param verbose whether to print the grep command +#' @param ... additional parameters to pass to \code{\link[data.table]{fread}} +#' @keywords internal +fread_colmatch = function(file, + col, + sep = NULL, + values_to_match, + verbose = FALSE, + ...) { + + # get colnames + col_names = colnames(data.table::fread(file, nrows = 1L)) + col_num = which(col_names == col) + + # try to guess col separating char if not given + if(is.null(sep)) { + filename = basename(file) + if(grepl(pattern = '.csv', x = filename)) { + sep = '.*,' + } else if(grepl(pattern = '.tsv', x = filename)) { + sep = '.*\t' + } else { + stop('sep param cannot be guessed') + } + } + # create grep search + pattern = paste(values_to_match, collapse = '|') + gpat = paste0('\'', strrep(x = sep, times = col_num - 1), '(', pattern, '),\' ') + fread_cmd = paste0('grep -E ', gpat, file) + if(isTRUE(verbose)) print(fread_cmd) + file_DT = data.table::fread(cmd = fread_cmd, col.names = col_names, ...) + return(file_DT) +} From 92fbf8feeef312bdf1210aad2c5524b7d39ac18a Mon Sep 17 00:00:00 2001 From: jiajic <72078254+jiajic@users.noreply.github.com> Date: Mon, 12 Dec 2022 23:56:28 -0500 Subject: [PATCH 016/129] test lapply again with progressbar --- NEWS.md | 1 + R/general_help.R | 208 +++++++++++++++++++++++++++++------------------ 2 files changed, 129 insertions(+), 80 deletions(-) diff --git a/NEWS.md b/NEWS.md index 511412e1f..fe31f355d 100644 --- a/NEWS.md +++ b/NEWS.md @@ -6,6 +6,7 @@ - Add `createGiottoMerscopeObject()` - Move giotto object method-specific creation functions from `giotto.R` to `convenience_create.R` - Add `fread_colmatch()` internal for fread loading a subset of rows based on matches in a specified column +- Add `optional` and `custom_msg` params to `package_check()` diff --git a/R/general_help.R b/R/general_help.R index 3c3ffd694..abf1bcc84 100644 --- a/R/general_help.R +++ b/R/general_help.R @@ -561,21 +561,41 @@ sort_combine_two_DT_columns = function(DT, #' @param pkg_name name of package #' @param repository where is the package #' @param github_repo name of github repository if needed +#' @param optional whether the package is optional. \code{stop()} is used if TRUE +#' and only \code{message()} will be sent if FALSE. +#' @param custom_msg custom message to be sent instead of default error or message #' @description check if package is available and provide installation instruction if not available #' @keywords internal package_check = function(pkg_name, repository = c('CRAN', 'Bioc', 'github', 'pip'), - github_repo = NULL) { + github_repo = NULL, + optional = FALSE, + custom_msg = NULL) { repository = match.arg(repository, choices = c('CRAN', 'Bioc', 'github', 'pip')) + check_message = function(default_msg, custom_msg, optional) { + if(!isTRUE(optional)) { + if(is.null(custom_msg)) stop(default_msg, call. = FALSE) + else stop(custom_msg, call. = FALSE) + } else { + if(is.null(custom_msg)) message(default_msg) + else message(custom_msg) + } + } + if(repository == 'CRAN') { + default_msg = c("\n package ", pkg_name ," is not yet installed \n", + "To install: \n", + "install.packages('",pkg_name,"')") + if(!requireNamespace(pkg_name, quietly = TRUE)) { - stop("\n package ", pkg_name ," is not yet installed \n", - "To install: \n", - "install.packages('",pkg_name,"')", - call. = FALSE) + + check_message(default_msg = default_msg, + custom_msg = custom_msg, + optional = optional) + } else { return(TRUE) } @@ -583,36 +603,50 @@ package_check = function(pkg_name, } else if(repository == 'Bioc') { + default_msg = c("\n package ", pkg_name ," is not yet installed \n", + "To install: \n", + "if(!requireNamespace('BiocManager', quietly = TRUE)) install.packages('BiocManager');\nBiocManager::install('",pkg_name,"')") + if(!requireNamespace(pkg_name, quietly = TRUE)) { - stop("\n package ", pkg_name ," is not yet installed \n", - "To install: \n", - "if (!requireNamespace('BiocManager', quietly = TRUE)) install.packages('BiocManager'); - BiocManager::install('",pkg_name,"')", - call. = FALSE) + + check_message(default_msg = default_msg, + custom_msg = custom_msg, + optional = optional) + } else { return(TRUE) } } else if(repository == 'github') { - if(is.null(github_repo)) stop("provide the github repo of package, e.g. 'johndoe/cooltool' ") + if(is.null(github_repo)) stop(wrap_txt("provide the github repo of package, e.g. 'johndoe/cooltool' ", sep = '')) + + default_msg = c("\n package ", pkg_name ," is not yet installed \n", + "To install: \n", + "devtools::install_github('",github_repo,"')") if(!requireNamespace(pkg_name, quietly = TRUE)) { - stop("\n package ", pkg_name ," is not yet installed \n", - "To install: \n", - "devtools::install_github('",github_repo,"')", - call. = FALSE) + + check_message(default_msg = default_msg, + custom_msg = custom_msg, + optional = optional) + } else { return(TRUE) } } else if(repository == 'pip') { + default_msg = c("\n package ", pkg_name ," is not yet installed \n", + "To install for default Giotto miniconda environment: \n", + "reticulate::conda_install(envname = 'giotto_env',packages = '",pkg_name,"',pip = TRUE)") + if(!reticulate::py_module_available(pkg_name)) { - stop("\n package ", pkg_name ," is not yet installed \n", - "To install for default Giotto miniconda environment: \n", - "reticulate::conda_install(envname = 'giotto_env',packages = '",pkg_name,"',pip = TRUE)", - call. = FALSE) + + check_message(default_msg = default_msg, + custom_msg = custom_msg, + optional = optional) + } } @@ -1320,7 +1354,16 @@ readPolygonFilesVizgenHDF5 = function(boundaries_path, cores = NA, verbose = TRUE) { + # necessary pkgs package_check(pkg_name = 'rhdf5', repository = 'Bioc') + # optional pkgs + progressr_avail = package_check( + pkg_name = 'progressr', + repository = 'CRAN', + optional = TRUE, + custom_msg = c('(Optional) For progress bar, install:\ninstall.packages("progressr)\n', + 'After install:\nprogressr::handlers("progress")') + ) cores = determine_cores(cores) @@ -1331,7 +1374,7 @@ readPolygonFilesVizgenHDF5 = function(boundaries_path, file_id = NULL my_id = NULL - # define names + # prepare poly feat names poly_feat_names = paste0('z', polygon_feat_types) poly_feat_indexes = paste0('zIndex_', polygon_feat_types) @@ -1339,95 +1382,100 @@ readPolygonFilesVizgenHDF5 = function(boundaries_path, if(!is.null(custom_polygon_names)) { if(!is.character(custom_polygon_names)) { - stop('If custom_polygon_names are provided, it needs to be a character vector') + stop(wrap_txt('If custom_polygon_names are provided, it needs to be a character vector')) } if(length(custom_polygon_names) != length(poly_feat_names)) { - stop('length of custom names need to be same as polygon_feat_types') + stop(wrap_txt('length of custom names need to be same as polygon_feat_types')) } else { poly_feat_names = custom_polygon_names } } + if(isTRUE(verbose)) wrap_msg('Reading from:', boundaries_path) # list all files in the folder - hdf5_boundary_list = list.files(full.names = T, boundaries_path) - + hdf5_boundary_list = list.files(full.names = TRUE, boundaries_path) + # only load subset of files if fov is given if(!is.null(fovs)) { selected_hdf5s = paste0('feature_data_', fovs, '.hdf5') selected_hdf5s_concatenated = paste0(selected_hdf5s, collapse = '|') - hdf5_boundary_selected_list = grep(selected_hdf5s_concatenated, x = hdf5_boundary_list, value = T) + hdf5_boundary_selected_list = grep(selected_hdf5s_concatenated, x = hdf5_boundary_list, value = TRUE) } else { hdf5_boundary_selected_list = hdf5_boundary_list } + if(isTRUE(verbose)) wrap_msg('finished listing .hdf5 files + start extracting .hdf5 information') - if(verbose == TRUE) cat(wrap_txt('finished listing .hdf5 files - start extracting .hdf5 information')) - - # read selected polygon files - # create a results list for each z index of the polygon file - # result_list = replicate(length(polygon_feat_types), list()) - # multidt_list = replicate(length(polygon_feat_types), list()) - + # open selected polygon files + # append data from all FOVs to single list hdf5_list_length = length(hdf5_boundary_selected_list) - # create progressbar - n_iter = 100 - pb = create_pb(max = hdf5_list_length) - - init = proc.time() + if(isTRUE(progressr_avail)) { + progressr::with_progress({ + pb = progressr::progressor(along = hdf5_boundary_list) + read_list = lapply_flex(hdf5_boundary_selected_list, cores = cores, function(bound_i) { - # lapply for list of hdf5 to read - multidt_list = lapply_flex(seq(hdf5_list_length), cores = cores, function(bound_i) { + # read file and select feature data + read_file = rhdf5::H5Fopen(bound_i[[1]], flags = H5Fopen_flags) + fov_info = read_file$featuredata - if(verbose == TRUE) { - cat('\n','hdf5: ', (hdf5_list_length - bound_i) ,'\n') - print(hdf5_boundary_selected_list[bound_i][[1]]) - cat('\n') - } + # combine to FOV data single list + read_list = do.call('append', fov_info) - # read file and select feature data - read_file = rhdf5::H5Fopen(hdf5_boundary_selected_list[bound_i][[1]], flags = H5Fopen_flags) - featdt = read_file$featuredata - cell_names = names(featdt) - - # extract values for each z index and cell - result_list = lapply_flex(seq_along(poly_feat_indexes), cores = cores, function(z_i) { - lapply_flex(seq_along(featdt), cores = cores, function(cell_i) { - singlearray = featdt[[cell_i]][[poly_feat_indexes[z_i]]]$p_0$coordinates - cell_name = cell_names[[cell_i]] - if(!is.null(singlearray)) { - singlearraydt = data.table::as.data.table(t(as.matrix(singlearray[,,1]))) - data.table::setnames(singlearraydt, old = c('V1', 'V2'), new = c('x', 'y')) - if(flip_x_axis) singlearraydt[, x := -1 * x] - if(flip_y_axis) singlearraydt[, y := -1 * y] - - singlearraydt[, file_id := paste0('file', bound_i)] - singlearraydt[, cell_id := cell_name] - singlearraydt[, my_id := paste0('cell', cell_i)] - } + # update progress + f_n = basename(bound_i[[1]]) + pb_msg = c('...', substr(f_n, nchar(f_n) - 14, nchar(f_n))) + pb(message = pg_msg) + return(read_list) }) }) - result_list_rbind = lapply_flex(seq_along(result_list), cores = cores, function(z_i) { - do.call('rbind', result_list[[z_i]]) - }) + } else { + read_list = lapply_flex(hdf5_boundary_selected_list, cores = cores, function(bound_i) { - # time end - setTxtProgressBar(pb, bound_i) - # estimated time remaining - elapsed = (proc.time() - init)[[3L]] - step_time = elapsed/bound_i - est = (hdf5_list_length * step_time) - elapsed + if(isTRUE(verbose)) { + cat('\n','hdf5: ', (hdf5_list_length - bound_i) ,'\n') + print(basename(bound_i[[1]])) + cat('\n') + } + + # read file and select feature data + read_file = rhdf5::H5Fopen(bound_i[[1]], flags = H5Fopen_flags) + fov_info = read_file$featuredata - cat(wrap_txt('\n // Execution time:', time_format(elapsed), - '// Estimated time remaining:', time_format(est), '\n')) + # combine to FOV data single list + read_list = do.call('append', fov_info) - return(result_list_rbind) + return(read_list) + }) + } + cell_names = names(read_list) + + + # extract values for each z index and cell from read_list + result_list = lapply_flex(seq_along(poly_feat_indexes), cores = cores, function(z_i) { + lapply_flex(seq_along(read_list), cores = cores, function(cell_i) { + singlearray = read_list[[cell_i]][[poly_feat_indexes[z_i]]]$p_0$coordinates + cell_name = cell_names[[cell_i]] + if(!is.null(singlearray)) { + singlearraydt = data.table::as.data.table(t_flex(as.matrix(singlearray[,,1]))) + data.table::setnames(singlearraydt, old = c('V1', 'V2'), new = c('x', 'y')) + if(flip_x_axis) singlearraydt[, x := -1 * x] + if(flip_y_axis) singlearraydt[, y := -1 * y] + + singlearraydt[, file_id := paste0('file', bound_i)] + singlearraydt[, cell_id := cell_name] + singlearraydt[, my_id := paste0('cell', cell_i)] + } + }) }) + result_list_rbind = lapply_flex(seq_along(result_list), cores = cores, function(z_i) { + do.call('rbind', result_list[[z_i]]) + }) + - close(pb) if(verbose == TRUE) wrap_msg('finished extracting .hdf5 files start creating polygons') @@ -1436,8 +1484,8 @@ readPolygonFilesVizgenHDF5 = function(boundaries_path, # create Giotto polygons and add them to gobject # smooth_cell_polygons_list = list() - smooth_cell_polygons_list = lapply_flex(seq_along(multidt_list), cores = cores, function(i) { - dfr_subset = multidt_list[[i]][,.(x, y, cell_id)] + smooth_cell_polygons_list = lapply_flex(seq_along(result_list_rbind), cores = cores, function(i) { + dfr_subset = result_list_rbind[[i]][,.(x, y, cell_id)] cell_polygons = createGiottoPolygonsFromDfr(segmdfr = dfr_subset, name = poly_feat_names[i]) From d29c557a9bae962d9d35ff855bf5aba5a5c7bcb5 Mon Sep 17 00:00:00 2001 From: jiajic <72078254+jiajic@users.noreply.github.com> Date: Tue, 13 Dec 2022 00:30:47 -0500 Subject: [PATCH 017/129] test1 --- R/general_help.R | 12 ++++-------- 1 file changed, 4 insertions(+), 8 deletions(-) diff --git a/R/general_help.R b/R/general_help.R index abf1bcc84..8f9d8a328 100644 --- a/R/general_help.R +++ b/R/general_help.R @@ -1422,14 +1422,11 @@ readPolygonFilesVizgenHDF5 = function(boundaries_path, read_file = rhdf5::H5Fopen(bound_i[[1]], flags = H5Fopen_flags) fov_info = read_file$featuredata - # combine to FOV data single list - read_list = do.call('append', fov_info) - # update progress f_n = basename(bound_i[[1]]) pb_msg = c('...', substr(f_n, nchar(f_n) - 14, nchar(f_n))) pb(message = pg_msg) - return(read_list) + return(fov_info) }) }) } else { @@ -1445,12 +1442,11 @@ readPolygonFilesVizgenHDF5 = function(boundaries_path, read_file = rhdf5::H5Fopen(bound_i[[1]], flags = H5Fopen_flags) fov_info = read_file$featuredata - # combine to FOV data single list - read_list = do.call('append', fov_info) - - return(read_list) + return(fov_info) }) } + # combine to FOV data single list + read_list = Reduce('append', fov_info) cell_names = names(read_list) From f13fd9421635d82628f44cb00b50eddbb7370ba4 Mon Sep 17 00:00:00 2001 From: jiajic <72078254+jiajic@users.noreply.github.com> Date: Tue, 13 Dec 2022 00:32:18 -0500 Subject: [PATCH 018/129] test2 --- R/general_help.R | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/R/general_help.R b/R/general_help.R index 8f9d8a328..5d7150276 100644 --- a/R/general_help.R +++ b/R/general_help.R @@ -1425,7 +1425,7 @@ readPolygonFilesVizgenHDF5 = function(boundaries_path, # update progress f_n = basename(bound_i[[1]]) pb_msg = c('...', substr(f_n, nchar(f_n) - 14, nchar(f_n))) - pb(message = pg_msg) + pb(message = pb_msg) return(fov_info) }) }) From 6fed3b216c5c3fecf09be53781b4502500922847 Mon Sep 17 00:00:00 2001 From: jiajic <72078254+jiajic@users.noreply.github.com> Date: Tue, 13 Dec 2022 00:36:13 -0500 Subject: [PATCH 019/129] test2 --- R/general_help.R | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/R/general_help.R b/R/general_help.R index 5d7150276..8df37584e 100644 --- a/R/general_help.R +++ b/R/general_help.R @@ -1446,7 +1446,7 @@ readPolygonFilesVizgenHDF5 = function(boundaries_path, }) } # combine to FOV data single list - read_list = Reduce('append', fov_info) + read_list = Reduce('append', read_list) cell_names = names(read_list) From 589a3b21f654cd0403ff6be3e16c8d8340fc47ff Mon Sep 17 00:00:00 2001 From: jiajic <72078254+jiajic@users.noreply.github.com> Date: Tue, 13 Dec 2022 01:56:58 -0500 Subject: [PATCH 020/129] test3 --- R/general_help.R | 41 ++++++++++++++++++++++------------------- 1 file changed, 22 insertions(+), 19 deletions(-) diff --git a/R/general_help.R b/R/general_help.R index 8df37584e..e8e367f3e 100644 --- a/R/general_help.R +++ b/R/general_help.R @@ -1415,7 +1415,7 @@ readPolygonFilesVizgenHDF5 = function(boundaries_path, if(isTRUE(progressr_avail)) { progressr::with_progress({ - pb = progressr::progressor(along = hdf5_boundary_list) + pb = progressr::progressor(along = hdf5_boundary_selected_list) read_list = lapply_flex(hdf5_boundary_selected_list, cores = cores, function(bound_i) { # read file and select feature data @@ -1424,7 +1424,7 @@ readPolygonFilesVizgenHDF5 = function(boundaries_path, # update progress f_n = basename(bound_i[[1]]) - pb_msg = c('...', substr(f_n, nchar(f_n) - 14, nchar(f_n))) + pb_msg = c('...', substr(f_n, nchar(f_n) - 19, nchar(f_n))) pb(message = pb_msg) return(fov_info) }) @@ -1445,27 +1445,30 @@ readPolygonFilesVizgenHDF5 = function(boundaries_path, return(fov_info) }) } - # combine to FOV data single list - read_list = Reduce('append', read_list) - cell_names = names(read_list) + # # combine to FOV data single list + # read_list = Reduce('append', read_list) + # cell_names = names(read_list) # extract values for each z index and cell from read_list result_list = lapply_flex(seq_along(poly_feat_indexes), cores = cores, function(z_i) { - lapply_flex(seq_along(read_list), cores = cores, function(cell_i) { - singlearray = read_list[[cell_i]][[poly_feat_indexes[z_i]]]$p_0$coordinates - cell_name = cell_names[[cell_i]] - if(!is.null(singlearray)) { - singlearraydt = data.table::as.data.table(t_flex(as.matrix(singlearray[,,1]))) - data.table::setnames(singlearraydt, old = c('V1', 'V2'), new = c('x', 'y')) - if(flip_x_axis) singlearraydt[, x := -1 * x] - if(flip_y_axis) singlearraydt[, y := -1 * y] - - singlearraydt[, file_id := paste0('file', bound_i)] - singlearraydt[, cell_id := cell_name] - singlearraydt[, my_id := paste0('cell', cell_i)] - } - }) + Reduce('append', lapply_flex(seq_along(read_list), cores = cores, function(bound_i) { + cell_names = names(read_list[[bound_i]]) + lapply_flex(seq_along(read_list[[bound_i]]), cores = cores, function(cell_i) { + singlearray = read_list[[cell_i]][[poly_feat_indexes[z_i]]]$p_0$coordinates + cell_name = cell_names[[cell_i]] + if(!is.null(singlearray)) { + singlearraydt = data.table::as.data.table(t_flex(as.matrix(singlearray[,,1]))) + data.table::setnames(singlearraydt, old = c('V1', 'V2'), new = c('x', 'y')) + if(flip_x_axis) singlearraydt[, x := -1 * x] + if(flip_y_axis) singlearraydt[, y := -1 * y] + + singlearraydt[, file_id := paste0('file', bound_i)] + singlearraydt[, cell_id := cell_name] + singlearraydt[, my_id := paste0('cell', cell_i)] + } + }) + })) }) result_list_rbind = lapply_flex(seq_along(result_list), cores = cores, function(z_i) { do.call('rbind', result_list[[z_i]]) From bee7cc7de0df9421902fdc33c0b351b28c2b7878 Mon Sep 17 00:00:00 2001 From: jiajic <72078254+jiajic@users.noreply.github.com> Date: Tue, 13 Dec 2022 02:00:31 -0500 Subject: [PATCH 021/129] test4 --- R/general_help.R | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/R/general_help.R b/R/general_help.R index e8e367f3e..3536d4492 100644 --- a/R/general_help.R +++ b/R/general_help.R @@ -1455,7 +1455,7 @@ readPolygonFilesVizgenHDF5 = function(boundaries_path, Reduce('append', lapply_flex(seq_along(read_list), cores = cores, function(bound_i) { cell_names = names(read_list[[bound_i]]) lapply_flex(seq_along(read_list[[bound_i]]), cores = cores, function(cell_i) { - singlearray = read_list[[cell_i]][[poly_feat_indexes[z_i]]]$p_0$coordinates + singlearray = read_list[[bound_i]][[cell_i]][[poly_feat_indexes[z_i]]]$p_0$coordinates cell_name = cell_names[[cell_i]] if(!is.null(singlearray)) { singlearraydt = data.table::as.data.table(t_flex(as.matrix(singlearray[,,1]))) From c95875266cc1286e76bcee0c9382636d6b6d1728 Mon Sep 17 00:00:00 2001 From: jiajic <72078254+jiajic@users.noreply.github.com> Date: Tue, 13 Dec 2022 11:22:27 -0500 Subject: [PATCH 022/129] test5 --- R/general_help.R | 52 ++++++++++++++++++++++++++++++++++++------------ 1 file changed, 39 insertions(+), 13 deletions(-) diff --git a/R/general_help.R b/R/general_help.R index 3536d4492..88739c586 100644 --- a/R/general_help.R +++ b/R/general_help.R @@ -1476,26 +1476,52 @@ readPolygonFilesVizgenHDF5 = function(boundaries_path, - if(verbose == TRUE) wrap_msg('finished extracting .hdf5 files + if(isTRUE(verbose)) wrap_msg('finished extracting .hdf5 files start creating polygons') # create Giotto polygons and add them to gobject # smooth_cell_polygons_list = list() - smooth_cell_polygons_list = lapply_flex(seq_along(result_list_rbind), cores = cores, function(i) { - dfr_subset = result_list_rbind[[i]][,.(x, y, cell_id)] - cell_polygons = createGiottoPolygonsFromDfr(segmdfr = dfr_subset, - name = poly_feat_names[i]) + if(isTRUE(progressr_avail)) { + progressr::with_progress({ + pb = progressr::progressor(along = result_list_rbind) + smooth_cell_polygons_list = lapply_flex(seq_along(result_list_rbind), cores = cores, function(i) { + dfr_subset = result_list_rbind[[i]][,.(x, y, cell_id)] + cell_polygons = createGiottoPolygonsFromDfr(segmdfr = dfr_subset, + name = poly_feat_names[i], + verbose = verbose) + + pb(message = poly_feat_names[i]) + + if(smooth_polygons == TRUE) { + return(smoothGiottoPolygons(cell_polygons, + vertices = smooth_vertices, + set_neg_to_zero = set_neg_to_zero, + verbose = FALSE)) + } else { + return(cell_polygons) + } + }) + }) + } else { + smooth_cell_polygons_list = lapply_flex(seq_along(result_list_rbind), cores = cores, function(i) { + dfr_subset = result_list_rbind[[i]][,.(x, y, cell_id)] + cell_polygons = createGiottoPolygonsFromDfr(segmdfr = dfr_subset, + name = poly_feat_names[i], + verbose = verbose, + verbose = TRUE) + + if(smooth_polygons == TRUE) { + return(smoothGiottoPolygons(cell_polygons, + vertices = smooth_vertices, + set_neg_to_zero = set_neg_to_zero)) + } else { + return(cell_polygons) + } + }) + } - if(smooth_polygons == TRUE) { - return(smoothGiottoPolygons(cell_polygons, - vertices = smooth_vertices, - set_neg_to_zero = set_neg_to_zero)) - } else { - return(cell_polygons) - } - }) # TODO: add spatial centroids # needs to happen after smoothing to be correct From 48af3f343bb3883821ce7cd93259e49e772b15b2 Mon Sep 17 00:00:00 2001 From: jiajic <72078254+jiajic@users.noreply.github.com> Date: Tue, 13 Dec 2022 11:27:49 -0500 Subject: [PATCH 023/129] test6 --- R/giotto_structures.R | 18 +++++++++++------- 1 file changed, 11 insertions(+), 7 deletions(-) diff --git a/R/giotto_structures.R b/R/giotto_structures.R index 67e503b33..c7496c089 100644 --- a/R/giotto_structures.R +++ b/R/giotto_structures.R @@ -842,6 +842,7 @@ spline_poly <- function(xy, vertices = 20, k = 3, ...) { #' @param vertices number of vertices #' @param k k #' @param set_neg_to_zero set negative values to zero (default: TRUE) +#' @param verbose be verbose (default: TRUE) #' @param ... additional params to pass to \code{spline} #' @return Smoothed Giotto polygon object with reduced vertices #' @concept polygon @@ -851,6 +852,7 @@ smoothGiottoPolygons = function(gpolygon, vertices = 20, k = 3, set_neg_to_zero = TRUE, + verbose = TRUE ...) { # define for .() @@ -899,13 +901,15 @@ smoothGiottoPolygons = function(gpolygon, new_spatvec = dt_to_spatVector_polygon(comb_res) - for(ID in new_spatvec$poly_ID) { - bool = terra::is.valid(new_spatvec[new_spatvec$poly_ID == ID]) - if(bool == FALSE) { - print(ID) - #plot(new_spatvec[new_spatvec$poly_ID == ID]) - #orig_spatvector = gpolygon@spatVector - #new_spatvec[new_spatvec$poly_ID == ID] = orig_spatvector[orig_spatvector$poly_ID == ID] + if(isTRUE(verbose)) { + for(ID in new_spatvec$poly_ID) { + bool = terra::is.valid(new_spatvec[new_spatvec$poly_ID == ID]) + if(!isTRUE(bool)) { + print(ID) + #plot(new_spatvec[new_spatvec$poly_ID == ID]) + #orig_spatvector = gpolygon@spatVector + #new_spatvec[new_spatvec$poly_ID == ID] = orig_spatvector[orig_spatvector$poly_ID == ID] + } } } From 4d8491f8837172f3483d2ba905a28005b7615ddf Mon Sep 17 00:00:00 2001 From: jiajic <72078254+jiajic@users.noreply.github.com> Date: Tue, 13 Dec 2022 11:28:45 -0500 Subject: [PATCH 024/129] test7 --- R/giotto_structures.R | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/R/giotto_structures.R b/R/giotto_structures.R index c7496c089..056aa0546 100644 --- a/R/giotto_structures.R +++ b/R/giotto_structures.R @@ -852,7 +852,7 @@ smoothGiottoPolygons = function(gpolygon, vertices = 20, k = 3, set_neg_to_zero = TRUE, - verbose = TRUE + verbose = TRUE, ...) { # define for .() From aa84cf21d40c9e21605241200878702ac6e0dbea Mon Sep 17 00:00:00 2001 From: jiajic <72078254+jiajic@users.noreply.github.com> Date: Tue, 13 Dec 2022 11:47:13 -0500 Subject: [PATCH 025/129] simplify comment out unused outputs --- R/general_help.R | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/R/general_help.R b/R/general_help.R index 88739c586..0bdaa824a 100644 --- a/R/general_help.R +++ b/R/general_help.R @@ -1446,14 +1446,14 @@ readPolygonFilesVizgenHDF5 = function(boundaries_path, }) } # # combine to FOV data single list - # read_list = Reduce('append', read_list) - # cell_names = names(read_list) + read_list = Reduce('append', read_list) + cell_names = names(read_list) # extract values for each z index and cell from read_list result_list = lapply_flex(seq_along(poly_feat_indexes), cores = cores, function(z_i) { - Reduce('append', lapply_flex(seq_along(read_list), cores = cores, function(bound_i) { - cell_names = names(read_list[[bound_i]]) + # Reduce('append', lapply_flex(seq_along(read_list), cores = cores, function(bound_i) { + # cell_names = names(read_list[[bound_i]]) lapply_flex(seq_along(read_list[[bound_i]]), cores = cores, function(cell_i) { singlearray = read_list[[bound_i]][[cell_i]][[poly_feat_indexes[z_i]]]$p_0$coordinates cell_name = cell_names[[cell_i]] @@ -1463,12 +1463,12 @@ readPolygonFilesVizgenHDF5 = function(boundaries_path, if(flip_x_axis) singlearraydt[, x := -1 * x] if(flip_y_axis) singlearraydt[, y := -1 * y] - singlearraydt[, file_id := paste0('file', bound_i)] + # singlearraydt[, file_id := paste0('file', bound_i)] singlearraydt[, cell_id := cell_name] - singlearraydt[, my_id := paste0('cell', cell_i)] + # singlearraydt[, my_id := paste0('cell', cell_i)] } }) - })) + # })) }) result_list_rbind = lapply_flex(seq_along(result_list), cores = cores, function(z_i) { do.call('rbind', result_list[[z_i]]) From 9090cf1b1cf52edc906ea34fa9367a19cfc6e10f Mon Sep 17 00:00:00 2001 From: jiajic <72078254+jiajic@users.noreply.github.com> Date: Tue, 13 Dec 2022 11:49:31 -0500 Subject: [PATCH 026/129] test8 --- R/general_help.R | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/R/general_help.R b/R/general_help.R index 0bdaa824a..36b2b45e3 100644 --- a/R/general_help.R +++ b/R/general_help.R @@ -1454,7 +1454,8 @@ readPolygonFilesVizgenHDF5 = function(boundaries_path, result_list = lapply_flex(seq_along(poly_feat_indexes), cores = cores, function(z_i) { # Reduce('append', lapply_flex(seq_along(read_list), cores = cores, function(bound_i) { # cell_names = names(read_list[[bound_i]]) - lapply_flex(seq_along(read_list[[bound_i]]), cores = cores, function(cell_i) { + # lapply_flex(seq_along(read_list[[bound_i]]), cores = cores, function(cell_i) { + lapply_flex(seq_along(read_list), cores = cores, function(cell_i) { singlearray = read_list[[bound_i]][[cell_i]][[poly_feat_indexes[z_i]]]$p_0$coordinates cell_name = cell_names[[cell_i]] if(!is.null(singlearray)) { From f1ad64858cd013fd867a4736af69a9d1cb749a1a Mon Sep 17 00:00:00 2001 From: jiajic <72078254+jiajic@users.noreply.github.com> Date: Tue, 13 Dec 2022 11:52:03 -0500 Subject: [PATCH 027/129] test 9 --- R/general_help.R | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/R/general_help.R b/R/general_help.R index 36b2b45e3..637a5fb23 100644 --- a/R/general_help.R +++ b/R/general_help.R @@ -1456,7 +1456,8 @@ readPolygonFilesVizgenHDF5 = function(boundaries_path, # cell_names = names(read_list[[bound_i]]) # lapply_flex(seq_along(read_list[[bound_i]]), cores = cores, function(cell_i) { lapply_flex(seq_along(read_list), cores = cores, function(cell_i) { - singlearray = read_list[[bound_i]][[cell_i]][[poly_feat_indexes[z_i]]]$p_0$coordinates + # singlearray = read_list[[bound_i]][[cell_i]][[poly_feat_indexes[z_i]]]$p_0$coordinates + singlearray = read_list[[cell_i]][[poly_feat_indexes[z_i]]]$p_0$coordinates cell_name = cell_names[[cell_i]] if(!is.null(singlearray)) { singlearraydt = data.table::as.data.table(t_flex(as.matrix(singlearray[,,1]))) From 7c860425612ff718f03dbca6897d239a03738cc0 Mon Sep 17 00:00:00 2001 From: jiajic <72078254+jiajic@users.noreply.github.com> Date: Tue, 13 Dec 2022 16:43:41 -0500 Subject: [PATCH 028/129] docu updates --- DESCRIPTION | 3 ++ R/accessors.R | 6 +++ R/auxiliary_giotto.R | 18 +++++++ R/convenience_create.R | 13 +++++- R/general_help.R | 56 ++++++++++++++++++++-- R/giotto.R | 14 ++++-- R/giotto_structures.R | 3 ++ R/interactivity.R | 2 +- R/spatial_genes.R | 3 ++ R/spatial_in_situ_visuals.R | 2 + R/utilities.R | 78 ++----------------------------- man/createGiottoMerscopeObject.Rd | 24 +++++++++- man/fread_colmatch.Rd | 25 ++++++++++ man/package_check.Rd | 9 +++- man/smoothGiottoPolygons.Rd | 3 ++ 15 files changed, 172 insertions(+), 87 deletions(-) create mode 100644 man/fread_colmatch.Rd diff --git a/DESCRIPTION b/DESCRIPTION index bffe1035f..93a9b7d0c 100644 --- a/DESCRIPTION +++ b/DESCRIPTION @@ -70,6 +70,7 @@ Suggests: deldir, dendextend (>= 1.13.0), dplyr, + exactextractr, FactoMineR, factoextra, fitdistrplus, @@ -88,6 +89,7 @@ Suggests: MAST, miniUI, multinet (>= 3.0.2), + progressr, png, quadprog, harmony, @@ -97,6 +99,7 @@ Suggests: Rvision, S4Vectors, Seurat, + sf, scatterpie, scattermore, scran (>= 1.10.1), diff --git a/R/accessors.R b/R/accessors.R index 93e6a4b53..7285bfd94 100644 --- a/R/accessors.R +++ b/R/accessors.R @@ -323,6 +323,9 @@ set_cell_metadata = function(gobject, verbose = TRUE, set_defaults = TRUE) { + # data.table vars + cell_ID = NULL + if(!inherits(gobject, 'giotto')) stop("Only Giotto Objects are supported for this function.") # 1. determine if user input was supplied @@ -550,6 +553,9 @@ set_feature_metadata = function(gobject, verbose = TRUE, set_defaults = TRUE) { + # data.table vars + feat_ID = NULL + if(!inherits(gobject, 'giotto')) stop("Only Giotto Objects are supported for this function.") # 1. determine if user input was supplied diff --git a/R/auxiliary_giotto.R b/R/auxiliary_giotto.R index 061f959cf..aab414ab8 100644 --- a/R/auxiliary_giotto.R +++ b/R/auxiliary_giotto.R @@ -335,6 +335,9 @@ create_average_detection_DT <- function(gobject, init_cell_metadata = function(gobject, provenance = NULL) { + # data.table vars + spat_unit = feat_type = NULL + avail_expr = list_expression(gobject) avail_spat_info = list_spatial_info_names(gobject) avail_feat_info = list_feature_info_names(gobject) @@ -388,6 +391,9 @@ init_cell_metadata = function(gobject, init_feat_metadata = function(gobject, provenance = NULL) { + # data.table vars + spat_unit = feat_type = NULL + avail_expr = list_expression(gobject) avail_spat_info = list_spatial_info_names(gobject) avail_feat_info = list_feature_info_names(gobject) @@ -2052,6 +2058,9 @@ filterGiotto = function(gobject, tag_feats_name = 'tag', verbose = TRUE) { + # data.table vars + cell_ID = feat_ID = NULL + ## deprecated arguments if(!is.null(gene_det_in_min_cells)) { feat_det_in_min_cells = gene_det_in_min_cells @@ -2780,6 +2789,9 @@ processGiotto = function(gobject, combine_matrices = function(mat_list, summarize = 'sum') { + # data.table vars + i = j = x = NULL + feats_list = list() sample_list = list() DT_list = list() @@ -2921,6 +2933,9 @@ aggregateStacksExpression = function(gobject, combine_spatlocs = function(spatlocs_list, summarize = 'mean') { + # data.table vars + sdimx = sdimy = sdimz = NULL + newlocs = data.table::rbindlist(spatlocs_list) if(summarize == 'mean') { @@ -4740,6 +4755,9 @@ mat_queryDT = function(i = NULL, by = cell_ID, mtx) { + # data.table vars + cell_ID = NULL + i_sub = deparse(substitute(i)) j_sub = deparse(substitute(j)) by_sub = deparse(substitute(by)) diff --git a/R/convenience_create.R b/R/convenience_create.R index 8a7b1d5c4..45b1cb830 100644 --- a/R/convenience_create.R +++ b/R/convenience_create.R @@ -47,7 +47,7 @@ read_data_folder = function(spat_method = NULL, # 1. detect items dir_items = lapply_flex(dir_items, function(x) { - Sys.glob(paths = file.path(merscope_dir, x)) + Sys.glob(paths = file.path(data_dir, x)) }, cores = cores) # (length = 1 if present, length = 0 if missing) dir_items_lengths = lengths(dir_items) @@ -960,6 +960,9 @@ createGiottoXeniumObject_subcellular = function(data_list, cores = NA, verbose = TRUE) { + # data.table vars + qv = NULL + # Unpack data_list info feat_meta = data_list$feat_meta tx_dt = data_list$tx_dt @@ -1447,7 +1450,7 @@ load_merscope_folder_subcellular = function(dir_items, poly_info = readPolygonFilesVizgenHDF5(boundaries_path = dir_items$`boundary info`, polygon_feat_types = c(0,6), flip_y_axis = TRUE, - fovs = subsetFOVs) + fovs = fovs) data_list = list( 'poly_info' = poly_info, @@ -1548,6 +1551,10 @@ load_cosmx_folder_aggregate = function(dir_items, cores, verbose = TRUE) { + # data.table vars + fov = cell_ID = fov_cell_ID = CenterX_global_px = CenterY_global_px = CenterX_local_px = + CenterY_local_px = x_shift = y_shift = NULL + # load aggregate information wrap_msg('Loading provided aggregated information...') @@ -1779,6 +1786,8 @@ load_xenium_folder_parquet = function(path_list, # initialize return vars feat_meta = tx_dt = bound_dt_list = cell_meta = agg_expr = NULL + # dplyr variable + cell_id = NULL if(isTRUE(verbose)) message('Loading feature metadata...') feat_meta = data.table::fread(path_list$panel_meta_path[[1]], nThread = cores) diff --git a/R/general_help.R b/R/general_help.R index 637a5fb23..08754bbc8 100644 --- a/R/general_help.R +++ b/R/general_help.R @@ -1473,7 +1473,7 @@ readPolygonFilesVizgenHDF5 = function(boundaries_path, # })) }) result_list_rbind = lapply_flex(seq_along(result_list), cores = cores, function(z_i) { - do.call('rbind', result_list[[z_i]]) + data.table::rbindlist(result_list[[z_i]]) }) @@ -1511,13 +1511,13 @@ readPolygonFilesVizgenHDF5 = function(boundaries_path, dfr_subset = result_list_rbind[[i]][,.(x, y, cell_id)] cell_polygons = createGiottoPolygonsFromDfr(segmdfr = dfr_subset, name = poly_feat_names[i], - verbose = verbose, - verbose = TRUE) + verbose = verbose) if(smooth_polygons == TRUE) { return(smoothGiottoPolygons(cell_polygons, vertices = smooth_vertices, - set_neg_to_zero = set_neg_to_zero)) + set_neg_to_zero = set_neg_to_zero, + verbose = FALSE)) } else { return(cell_polygons) } @@ -1609,6 +1609,9 @@ readPolygonFilesVizgen = function(gobject, getGEFtxCoords = function(gef_file, bin_size = 'bin100') { + # data.table vars + genes = NULL + # package check package_check(pkg_name = 'rhdf5', repository = 'Bioc') if(!file.exists(gef_file)) stop('File path to .gef file does not exist') @@ -1624,3 +1627,48 @@ getGEFtxCoords = function(gef_file, return(exprDT) } + + + +#' @title Fread rows based on column matches +#' @name fread_colmatch +#' @param file path to file to load +#' @param col name of col to match from +#' @param sep grep term to match as column delimiters within the file +#' @param values_to_match values in \code{col} to match given as a vector +#' @param verbose whether to print the grep command +#' @param ... additional parameters to pass to \code{\link[data.table]{fread}} +#' @keywords internal +fread_colmatch = function(file, + col, + sep = NULL, + values_to_match, + verbose = FALSE, + ...) { + + # get colnames + col_names = colnames(data.table::fread(file, nrows = 1L)) + col_num = which(col_names == col) + + # try to guess col separating char if not given + if(is.null(sep)) { + filename = basename(file) + if(grepl(pattern = '.csv', x = filename)) { + sep = '.*,' + } else if(grepl(pattern = '.tsv', x = filename)) { + sep = '.*\t' + } else { + stop('sep param cannot be guessed') + } + } + + # create grep search + pattern = paste(values_to_match, collapse = '|') + gpat = paste0('\'', strrep(x = sep, times = col_num - 1), '(', pattern, '),\' ') + fread_cmd = paste0('grep -E ', gpat, file) + if(isTRUE(verbose)) print(fread_cmd) + + file_DT = data.table::fread(cmd = fread_cmd, col.names = col_names, ...) + return(file_DT) +} + diff --git a/R/giotto.R b/R/giotto.R index 85a28a766..1495d7dc4 100644 --- a/R/giotto.R +++ b/R/giotto.R @@ -766,6 +766,9 @@ read_cell_metadata = function(gobject, provenance = NULL, verbose = TRUE) { + # data.table vars + cell_ID = NULL + cellMetaObj_list = list() # extract all metadata information @@ -834,6 +837,9 @@ read_feature_metadata = function(gobject, provenance = NULL, verbose = TRUE) { + # data.table vars + feat_ID = NULL + featMetaObj_list = list() # extract all metadata information @@ -1066,6 +1072,9 @@ read_spatial_location_data = function(gobject, provenance = NULL, verbose = TRUE) { + # data.table vars + cell_ID = NULL + if(is.null(spat_loc_list)) return(NULL) @@ -2440,9 +2449,8 @@ createGiottoObjectSubcellular = function(gpolygons = NULL, cores = NA, verbose = TRUE) { - # define for data.table := - cell_ID = NULL - feat_ID = NULL + # data.table vars + cell_ID feat_ID = x = y = NULL # create minimum giotto gobject = giotto(expression = NULL, diff --git a/R/giotto_structures.R b/R/giotto_structures.R index 056aa0546..464dbf74b 100644 --- a/R/giotto_structures.R +++ b/R/giotto_structures.R @@ -2719,6 +2719,9 @@ overlapImagesToMatrix = function(gobject, spat_locs_name = 'raw', return_gobject = TRUE) { + # data.table vars + value = poly_ID = feat_ID = x = y = NULL + ## get polygon information polygon_info = get_polygon_info(gobject = gobject, polygon_name = poly_info, diff --git a/R/interactivity.R b/R/interactivity.R index 5c9aac1ed..55a392aad 100644 --- a/R/interactivity.R +++ b/R/interactivity.R @@ -412,7 +412,7 @@ compareCellAbundance <- function(gobject, output = 'data.table', copy_obj = TRUE) columns_to_select = c(polygon_name, cell_type_column) - my_metadata <- my_metadata[, ..columns_to_select] + my_metadata <- my_metadata[, columns_to_select, with = FALSE] # count cell_type per polygon my_cell_counts <- table(my_metadata) diff --git a/R/spatial_genes.R b/R/spatial_genes.R index 9a69d8913..26bedc497 100644 --- a/R/spatial_genes.R +++ b/R/spatial_genes.R @@ -3949,6 +3949,9 @@ getBalancedSpatCoexpressionFeats = function(spatCorObject, seed = NA, verbose = TRUE) { + # data.table vars + feat_ID = variable = combo = spat_cor = rnk = feat_id = V1 = NULL + rank = match.arg(rank, choices = c('weighted', 'random', 'informed')) clusters = spatCorObject$cor_clusters$spat_netw_clus diff --git a/R/spatial_in_situ_visuals.R b/R/spatial_in_situ_visuals.R index 94a2e1b2c..8dae8f1d9 100644 --- a/R/spatial_in_situ_visuals.R +++ b/R/spatial_in_situ_visuals.R @@ -178,6 +178,8 @@ expand_feature_info = function(spatial_feat_info, jitter = c(0,0), verbose = TRUE) { + # data.table variables + feat_ID = x = y = feat = spat_unit = NULL # 1. expand feature locations with multiple counts (e.g. in seq-Scope or Stereo-seq) if(isTRUE(expand_counts)) { diff --git a/R/utilities.R b/R/utilities.R index cf02a3c98..fb896b7a8 100644 --- a/R/utilities.R +++ b/R/utilities.R @@ -488,6 +488,9 @@ abb_mat = function(exprObj, nrows, ncols, header = TRUE) { #' @description print abbreviated spatLocsObj #' @keywords internal abb_spatlocs = function(spatLocsObj, nrows) { + # data.table vars + sdimx = sdimy = NULL + DT_rows = nrow(spatLocsObj[]) spatlocs = spatLocsObj[][1:if(nrows <= DT_rows) nrows else DT_rows,] @@ -646,83 +649,8 @@ emacs_version = function() { as.numeric(ver) } -# time format #### - -#' @title Format time for printing -#' @name time_format -#' @keywords internal -#' @details Code from \code{\link[data.table]{timetaken}} -time_format = function(secs) { - if (secs > 60) { - secs = as.integer(secs) - sprintf("%02d:%02d:%02d", secs%/%3600L, (secs%/%60L)%%60L, - secs%%60L) - } - else { - sprintf(if (secs >= 10) - "%.1fs" - else "%.3fs", secs) - } -} - -# progress bar setup #### -#' @title Create a txt progressbar -#' @name create_pb -#' @keywords internal -create_pb = function(max, - min = 0, - width = min(35, getOption('width')), - char = '=') { - txtProgressBar(min = min, - max = max, - style = 3, - width = width, - char = char) - -} - - -#' @param file path to file to load -#' @param col name of col to match from -#' @param sep grep term to match as column delimiters within the file -#' @param values_to_match values in \code{col} to match given as a vector -#' @param verbose whether to print the grep command -#' @param ... additional parameters to pass to \code{\link[data.table]{fread}} -#' @keywords internal -fread_colmatch = function(file, - col, - sep = NULL, - values_to_match, - verbose = FALSE, - ...) { - - # get colnames - col_names = colnames(data.table::fread(file, nrows = 1L)) - col_num = which(col_names == col) - - # try to guess col separating char if not given - if(is.null(sep)) { - filename = basename(file) - if(grepl(pattern = '.csv', x = filename)) { - sep = '.*,' - } else if(grepl(pattern = '.tsv', x = filename)) { - sep = '.*\t' - } else { - stop('sep param cannot be guessed') - } - } - - # create grep search - pattern = paste(values_to_match, collapse = '|') - gpat = paste0('\'', strrep(x = sep, times = col_num - 1), '(', pattern, '),\' ') - fread_cmd = paste0('grep -E ', gpat, file) - if(isTRUE(verbose)) print(fread_cmd) - - file_DT = data.table::fread(cmd = fread_cmd, col.names = col_names, ...) - return(file_DT) -} diff --git a/man/createGiottoMerscopeObject.Rd b/man/createGiottoMerscopeObject.Rd index e79bb07cd..7389badff 100644 --- a/man/createGiottoMerscopeObject.Rd +++ b/man/createGiottoMerscopeObject.Rd @@ -10,12 +10,26 @@ createGiottoMerscopeObject( merscope_dir, data_to_use = c("subcellular", "aggregate"), FOVs = NULL, + calculate_overlap = TRUE, + overlap_to_matrix = TRUE, + aggregate_stack = TRUE, + aggregate_stack_param = list(summarize_expression = "sum", summarize_locations = + "mean", new_spat_unit = "cell"), instructions = NULL, cores = NA, verbose = TRUE ) -createGiottoMerscopeObject_subcellular(data_list, cores = NA, verbose = TRUE) +createGiottoMerscopeObject_subcellular( + data_list, + calculate_overlap = TRUE, + overlap_to_matrix = TRUE, + aggregate_stack = TRUE, + aggregate_stack_param = list(summarize_expression = "sum", summarize_locations = + "mean", new_spat_unit = "cell"), + cores = NA, + verbose = TRUE +) createGiottoMerscopeObject_aggregate(data_list, cores = NA, verbose = TRUE) } @@ -28,6 +42,14 @@ to use for object creation} \item{FOVs}{which FOVs to use when building the subcellular object. (default is NULL) NULL loads all FOVs (very slow)} +\item{calculate_overlap}{whether to run \code{\link{calculateOverlapRaster}}} + +\item{overlap_to_matrix}{whether to run \code{\link{overlapToMatrix}}} + +\item{aggregate_stack}{whether to run \code{\link{aggregateStacks}}} + +\item{aggregate_stack_param}{params to pass to \code{\link{aggregateStacks}}} + \item{instructions}{list of instructions or output result from \code{\link{createGiottoInstructions}}} \item{cores}{how many cores or threads to use to read data if paths are provided} diff --git a/man/fread_colmatch.Rd b/man/fread_colmatch.Rd new file mode 100644 index 000000000..7cdc75b2a --- /dev/null +++ b/man/fread_colmatch.Rd @@ -0,0 +1,25 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/utilities.R +\name{fread_colmatch} +\alias{fread_colmatch} +\title{Fread rows based on column matches} +\usage{ +fread_colmatch(file, col, sep = NULL, values_to_match, verbose = FALSE, ...) +} +\arguments{ +\item{file}{path to file to load} + +\item{col}{name of col to match from} + +\item{sep}{grep term to match as column delimiters within the file} + +\item{values_to_match}{values in \code{col} to match given as a vector} + +\item{verbose}{whether to print the grep command} + +\item{...}{additional parameters to pass to \code{\link[data.table]{fread}}} +} +\description{ +Fread rows based on column matches +} +\keyword{internal} diff --git a/man/package_check.Rd b/man/package_check.Rd index b7e88c83c..32c7ab1df 100644 --- a/man/package_check.Rd +++ b/man/package_check.Rd @@ -7,7 +7,9 @@ package_check( pkg_name, repository = c("CRAN", "Bioc", "github", "pip"), - github_repo = NULL + github_repo = NULL, + optional = FALSE, + custom_msg = NULL ) } \arguments{ @@ -16,6 +18,11 @@ package_check( \item{repository}{where is the package} \item{github_repo}{name of github repository if needed} + +\item{optional}{whether the package is optional. \code{stop()} is used if TRUE +and only \code{message()} will be sent if FALSE.} + +\item{custom_msg}{custom message to be sent instead of default error or message} } \description{ check if package is available and provide installation instruction if not available diff --git a/man/smoothGiottoPolygons.Rd b/man/smoothGiottoPolygons.Rd index 10e8541c8..5ac106a61 100644 --- a/man/smoothGiottoPolygons.Rd +++ b/man/smoothGiottoPolygons.Rd @@ -9,6 +9,7 @@ smoothGiottoPolygons( vertices = 20, k = 3, set_neg_to_zero = TRUE, + verbose = TRUE, ... ) } @@ -21,6 +22,8 @@ smoothGiottoPolygons( \item{set_neg_to_zero}{set negative values to zero (default: TRUE)} +\item{verbose}{be verbose (default: TRUE)} + \item{...}{additional params to pass to \code{spline}} } \value{ From 295e4ab9aaa721e55f520649e06ca9c95012e348 Mon Sep 17 00:00:00 2001 From: jiajic <72078254+jiajic@users.noreply.github.com> Date: Tue, 13 Dec 2022 16:44:52 -0500 Subject: [PATCH 029/129] Update giotto.R --- R/giotto.R | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/R/giotto.R b/R/giotto.R index 1495d7dc4..e0f1e954d 100644 --- a/R/giotto.R +++ b/R/giotto.R @@ -2450,7 +2450,7 @@ createGiottoObjectSubcellular = function(gpolygons = NULL, verbose = TRUE) { # data.table vars - cell_ID feat_ID = x = y = NULL + cell_ID = feat_ID = x = y = NULL # create minimum giotto gobject = giotto(expression = NULL, From 4bbc82531926d837068d13450546a5264fbd9cb7 Mon Sep 17 00:00:00 2001 From: jiajic <72078254+jiajic@users.noreply.github.com> Date: Wed, 14 Dec 2022 12:00:37 -0500 Subject: [PATCH 030/129] Fix documentations issues --- DESCRIPTION | 3 +- NEWS.md | 5 +- R/auxiliary_giotto.R | 8 +- R/classes.R | 46 +- R/convenience.R | 1873 +++++++++++++++++ R/convenience_create.R | 87 +- R/generics.R | 112 +- R/giotto.R | 2 +- R/giotto_structures.R | 3 + man/createGiottoCosMxObject.Rd | 49 +- man/createGiottoCosMxObject_aggregate.Rd | 11 +- man/createGiottoCosMxObject_all.Rd | 20 +- man/createGiottoCosMxObject_subcellular.Rd | 12 +- man/createGiottoMerscopeObject.Rd | 67 +- man/createGiottoXeniumObject.Rd | 48 +- man/createGiottoXeniumObject_aggregate.Rd | 13 +- man/createGiottoXeniumObject_subcellular.Rd | 15 +- man/create_pb.Rd | 12 - ...{extract-generic.Rd => extract-methods.Rd} | 36 +- man/featType-generic.Rd | 1 + man/fread_colmatch.Rd | 2 +- man/load_cosmx_folder_aggregate.Rd | 6 +- man/load_cosmx_folder_subcellular.Rd | 8 +- man/load_merscope_folder.Rd | 46 +- man/load_xenium_folder.Rd | 41 +- man/prov-generic.Rd | 1 + man/read_cosmx_folder.Rd | 11 +- man/read_data_folder.Rd | 32 +- man/read_xenium_folder.Rd | 16 +- man/spatUnit-generic.Rd | 1 + man/time_format.Rd | 15 - 31 files changed, 2439 insertions(+), 163 deletions(-) create mode 100644 R/convenience.R delete mode 100644 man/create_pb.Rd rename man/{extract-generic.Rd => extract-methods.Rd} (83%) delete mode 100644 man/time_format.Rd diff --git a/DESCRIPTION b/DESCRIPTION index 93a9b7d0c..5ae7c0c41 100644 --- a/DESCRIPTION +++ b/DESCRIPTION @@ -49,6 +49,7 @@ Imports: matrixStats (>= 0.55.0), plotly, parallel, + progressr, RColorBrewer (>= 1.1-2), reshape2, reticulate (>= 1.25), @@ -89,7 +90,6 @@ Suggests: MAST, miniUI, multinet (>= 3.0.2), - progressr, png, quadprog, harmony, @@ -121,6 +121,7 @@ Collate: 'cell_segmentation.R' 'classes.R' 'clustering.R' + 'convenience.R' 'convenience_create.R' 'cross_section.R' 'differential_expression.R' diff --git a/NEWS.md b/NEWS.md index fe31f355d..6efd091b7 100644 --- a/NEWS.md +++ b/NEWS.md @@ -4,9 +4,12 @@ - Add `id_col`, `x_col`, `y_col` params to `polyStamp()` to make stamp location input more flexible - Add `coord_fix_ratio` param to `spatFeatPlot2D()` and `spatFeatPlot2D_single()` - Add `createGiottoMerscopeObject()` -- Move giotto object method-specific creation functions from `giotto.R` to `convenience_create.R` +- Move giotto object method-specific creation functions from `giotto.R` to `convenience.R` - Add `fread_colmatch()` internal for fread loading a subset of rows based on matches in a specified column - Add `optional` and `custom_msg` params to `package_check()` +- Add packages `exactextractr` and `sf` to "suggests" packages +- Add package `progressr` to "imports" packages +- Removed `createGiottoCosMxObject()` `aggregate` and `all` workflows until they are updated diff --git a/R/auxiliary_giotto.R b/R/auxiliary_giotto.R index aab414ab8..8f3830e0a 100644 --- a/R/auxiliary_giotto.R +++ b/R/auxiliary_giotto.R @@ -2973,7 +2973,7 @@ aggregateStacksLocations = function(gobject, # aggregate locations locs_list = list() for(spat_unit in spat_units) { - locDT = get_spatial_locations(vizsubc, + locDT = get_spatial_locations(gobject = gobject, spat_unit = spat_unit, spat_loc_name = values, output = 'data.table') @@ -2989,7 +2989,11 @@ aggregateStacksLocations = function(gobject, provenance = spat_units, misc = NULL) - gobject = set_spatial_locations(gobject = gobject, spatlocs = new_spatlocs_obj) + ### ### ### ### ### ### ### ### ### ### ### ### ### ### ### ### ### ### ### + gobject = set_spatial_locations(gobject = gobject, + spatlocs = new_spatlocs_obj, + set_defaults = FALSE) + ### ### ### ### ### ### ### ### ### ### ### ### ### ### ### ### ### ### ### return(gobject) diff --git a/R/classes.R b/R/classes.R index 05e06d697..3122f3a10 100644 --- a/R/classes.R +++ b/R/classes.R @@ -37,7 +37,7 @@ setOldClass('data.table') #' Basic class for classes with expression information #' setClass('exprData', - representation = list(exprMat = 'ANY'), + slots = list(exprMat = 'ANY'), prototype = prototype(exprMat = NULL)) @@ -50,7 +50,7 @@ setClass('exprData', #' data.table when interacting with some basic generic operators for data #' retreival and setting. setClass('coordDataDT', - representation = list(coordinates = 'data.table'), + slots = list(coordinates = 'data.table'), prototype = prototype(coordinates = data.table::data.table())) setMethod('initialize', 'coordDataDT', @@ -64,7 +64,7 @@ setMethod('initialize', 'coordDataDT', }) # setClass('coordDataMT', -# representation = list(coordinates = 'matrix'), +# slots = list(coordinates = 'matrix'), # prototype = prototype(coordinates = matrix())) @@ -75,8 +75,8 @@ setMethod('initialize', 'coordDataDT', #' information in a data.table and should work similarly to data.table when interacting #' with some basic generic operators for data retrieval and setting setClass('metaData', - representation = list(metaDT = 'data.table', - col_desc = 'character'), + slots = list(metaDT = 'data.table', + col_desc = 'character'), prototype = prototype(metaDT = data.table::data.table(), col_desc = NA_character_)) @@ -94,8 +94,8 @@ setMethod('initialize', 'metaData', # ** enrData #### setClass('enrData', - representation = list(method = 'character', - enrichDT = 'nullOrDatatable'), + slots = list(method = 'character', + enrichDT = 'nullOrDatatable'), prototype = prototype(method = NA_character_, enrichDT = NULL)) @@ -113,20 +113,20 @@ setMethod('initialize', 'enrData', # ** nnData #### setClass('nnData', - representation = list(nn_type = 'character', - igraph = 'ANY'), + slots = list(nn_type = 'character', + igraph = 'ANY'), prototype = prototype(nn_type = NA_character_, igraph = NULL)) # ** spatNetData #### setClass('spatNetData', - representation = list(method = 'character', - parameters = 'ANY', - outputObj = 'ANY', - networkDT = 'nullOrDatatable', - networkDT_before_filter = 'nullOrDatatable', - cellShapeObj = 'ANY'), + slots = list(method = 'character', + parameters = 'ANY', + outputObj = 'ANY', + networkDT = 'nullOrDatatable', + networkDT_before_filter = 'nullOrDatatable', + cellShapeObj = 'ANY'), prototype = prototype(method = NA_character_, parameters = NULL, outputObj = NULL, @@ -150,9 +150,9 @@ setMethod('initialize', 'spatNetData', # ** spatGridData #### setClass('spatGridData', - representation = list(method = 'character', - parameters = 'ANY', - gridDT = 'nullOrDatatable'), + slots = list(method = 'character', + parameters = 'ANY', + gridDT = 'nullOrDatatable'), prototype = prototype(method = NA_character_, parameters = NULL, gridDT = NULL)) @@ -179,7 +179,7 @@ setMethod('initialize', 'spatGridData', #' is Giotto's method of mapping this aggregated information back to the original #' z layers that were used in its generation. setClass('provData', - representation = list(provenance = 'ANY'), + slots = list(provenance = 'ANY'), prototype = prototype(provenance = NULL)) @@ -195,7 +195,7 @@ setClass('provData', #' setClass('spatData', contains = c('provData'), - representation = list(spat_unit = 'character'), # not allowed to be NULL + slots = list(spat_unit = 'character'), # not allowed to be NULL prototype = prototype(spat_unit = NA_character_)) @@ -212,7 +212,7 @@ setClass('spatData', #' and then by feature type #' setClass('featData', - representation = list(feat_type = 'character'), # not allowed to be NULL + slots = list(feat_type = 'character'), # not allowed to be NULL prototype = prototype(feat_type = NA_character_)) @@ -225,7 +225,7 @@ setClass('featData', #' use the misc slot to hold additional information specific to each method. #' Information may be stored within as S3 structures. setClass('miscData', - representation = list(misc = 'ANY'), + slots = list(misc = 'ANY'), prototype = prototype(misc = NULL)) @@ -862,7 +862,7 @@ S3toS4dimObj = function(object) { setClass('nnNetObj', contains = c('nnData', 'spatFeatData', 'miscData'), - representation = list(name = 'character'), + slots = list(name = 'character'), prototype = prototype(name = NA_character_)) diff --git a/R/convenience.R b/R/convenience.R new file mode 100644 index 000000000..45b1cb830 --- /dev/null +++ b/R/convenience.R @@ -0,0 +1,1873 @@ + +# ** Spatial Method-Specific Convenience Functions for Giotto Object Creation ** # + + + +# Common Utility Functions #### + +#' @title Read a structured folder of exported data +#' @name read_data_folder +#' @description Read the exported folder of a spatial method and +#' detect the presence of needed files. NULL values denote missing items. +#' @param spat_method spatial method for which the data is being read +#' @param data_dir exported data directory to read from +#' @param dir_items named list of directory items to expect and keywords to match +#' @param data_to_use which type(s) of expression data to build the gobject with +#' @param require_data_DT data.table detailing if expected data items are required +#' or optional for each \code{data_to_use} workflow +#' @param cores cores to use +#' @param verbose be verbose +#' @details Steps performed: +#' \itemize{ +#' \item{1. detection of items within \code{data_dir} by looking for keywords +#' assigned through \code{dir_items}} +#' \item{2. check of detected items to see if everything needed has been found. +#' Dictionary of necessary vs optional items for each \code{data_to_use} workflow +#' is provided through \code{require_data_DT}} +#' \item{3. if multiple filepaths are found to be matching then select the first +#' one. This function is only intended to find the first level subdirectories +#' and files.} +#' } +#' @keywords internal +read_data_folder = function(spat_method = NULL, + data_dir = NULL, + dir_items, + data_to_use, + load_format = NULL, + require_data_DT, + cores = NA, + verbose = TRUE) { + + ch = box_chars() + + # 0. check params + if(is.null(data_dir) | !dir.exists(data_dir)) stop(wrap_txt('The full path to a', spat_method, 'directory must be given.\n')) + if(isTRUE(verbose)) wrap_msg('A structured', spat_method, 'directory will be used') + if(!data_to_use %in% require_data_DT$workflow) stop(wrap_txt('Data requirements for data_to_use not found in require_data_DT')) + + # 1. detect items + dir_items = lapply_flex(dir_items, function(x) { + Sys.glob(paths = file.path(data_dir, x)) + }, cores = cores) + # (length = 1 if present, length = 0 if missing) + dir_items_lengths = lengths(dir_items) + + # 2. check directory contents + if(isTRUE(verbose)) wrap_msg('Checking directory contents...') + + for(item in names(dir_items)) { + + # IF ITEM FOUND + + if(dir_items_lengths[[item]] > 0) { + if(isTRUE(verbose)) { + message(ch$s, '> ' ,item, ' found') + for(item_i in seq_along(dir_items[[item]])) { # print found item names + subItem = gsub(pattern = '.*/', replacement = '', x = dir_items[[item]][[item_i]]) + message(ch$s, ch$s, ch$l, ch$h, ch$h, subItem) + } + } + } else { + + # IF ITEM MISSING + # necessary (error) + # optional (warning) + + # data.table variables + workflow = needed = filetype = NULL + + + require_data_DT = require_data_DT[workflow == data_to_use,] + if(!is.null(load_format)) require_data_DT = require_data_DT[filetype == load_format,] + + if(item %in% require_data_DT[needed == TRUE, item]) stop(item, ' is missing\n') + if(item %in% require_data_DT[needed == FALSE, item]) warning(item, 'is missing (optional)\n') + + } + } + + # 3. select first path in list if multiple are detected + if(any(dir_items_lengths > 1)) { + warning(wrap_txt('Multiple matches for expected directory item(s). + First matching item selected')) + + multiples = which(dir_items_lengths > 1) + for(mult_i in multiples) { + message(names(dir_items)[[mult_i]], 'multiple matches found:') + print(dir_items[[mult_i]]) + dir_items[[mult_i]] = dir_items[[mult_i]][[1]] + } + } + if(isTRUE(verbose)) message('Directory check done') + + return(dir_items) + +} + + + + + + + + + +# object creation #### + + + + +## MERSCOPE #### + +#' @title Create Vizgen MERSCOPE Giotto Object +#' @name createGiottoMerscopeObject +#' @description Given the path to a MERSCOPE experiment directory, creates a Giotto +#' object. +#' @param merscope_dir full path to the exported merscope directory +#' @param data_to_use which of either the 'subcellular' or 'aggregate' information +#' to use for object creation +#' @param FOVs which FOVs to use when building the subcellular object. (default is NULL) +#' NULL loads all FOVs (very slow) +#' @param calculate_overlap whether to run \code{\link{calculateOverlapRaster}} +#' @param overlap_to_matrix whether to run \code{\link{overlapToMatrix}} +#' @param aggregate_stack whether to run \code{\link{aggregateStacks}} +#' @param aggregate_stack_param params to pass to \code{\link{aggregateStacks}} +#' @inheritParams createGiottoObjectSubcellular +#' @return a giotto object +#' @export +#' @details +#' [\strong{Expected Directory}] This function generates a giotto object when given a +#' link to a MERSCOPE output directory. It expects the following items within the directory +#' where the \strong{bolded} portions are what this function matches against: +#' \itemize{ +#' \item{\strong{cell_boundaries} (folder .hdf5 files)} +#' \item{\strong{images} (folder of .tif images and a scalefactor/transfrom table)} +#' \item{\strong{cell_by_gene}.csv (file)} +#' \item{cell_metadata\strong{fov_positions_file}.csv (file)} +#' \item{detected_transcripts\strong{metadata_file}.csv (file)} +#' } +createGiottoMerscopeObject = function(merscope_dir, + data_to_use = c('subcellular', 'aggregate'), + FOVs = NULL, + calculate_overlap = TRUE, + overlap_to_matrix = TRUE, + aggregate_stack = TRUE, + aggregate_stack_param = list(summarize_expression = 'sum', + summarize_locations = 'mean', + new_spat_unit = 'cell'), + instructions = NULL, + cores = NA, + verbose = TRUE) { + + # 0. setup + # set number of cores automatically, but with limit of 10 + cores = determine_cores(cores) + data.table::setDTthreads(threads = cores) + + # determine data to use + data_to_use = match.arg(arg = data_to_use, choices = c('subcellular','aggregate')) + + # 1. test if folder structure exists and is as expected + dir_items = read_merscope_folder(merscope_dir = merscope_dir, + data_to_use = data_to_use, + cores = cores, + verbose = verbose) + + # 2. load in directory items + data_list = load_merscope_folder(dir_items = dir_items, + data_to_use = data_to_use, + fovs = fovs, + cores = cores, + verbose = verbose) + + # 3. Create giotto object + if(data_to_use == 'subcellular') { + + merscope_gobject = createGiottoMerscopeObject_subcellular(data_list = data_list, + calculate_overlap = calculate_overlap, + overlap_to_matrix = overlap_to_matrix, + aggregate_stack = aggregate_stack, + aggregate_stack_param = aggregate_stack_param, + cores = cores, + verbose = verbose) + + } else if(data_to_use == 'aggregate') { + + merscope_gobject = createGiottoMerscopeObject_aggregate(data_list = data_list, + cores = cores, + verbose = verbose) + + } else { + stop(wrap_txt('data_to_use "', data_to_use, '" not implemented', sep = '')) + } + + return(merscope_gobject) + +} + + + + +#' @describeIn createGiottoMerscopeObject Create giotto object with 'subcellular' workflow +#' @param data_list list of loaded data from \code{\link{load_merscope_folder}} +#' @keywords internal +createGiottoMerscopeObject_subcellular = function(data_list, + calculate_overlap = TRUE, + overlap_to_matrix = TRUE, + aggregate_stack = TRUE, + aggregate_stack_param = list(summarize_expression = 'sum', + summarize_locations = 'mean', + new_spat_unit = 'cell'), + cores = NA, + verbose = TRUE) { + + # unpack data_list + poly_info = data_list$poly_info + tx_dt = data_list$tx_dt + micronToPixelScale = data_list$micronToPixelScale + image_list = data_list$images + + # data.table vars + gene = NULL + + # split tx_dt by expression and blank + if(isTRUE(verbose)) wrap_msg('Splitting detections by feature vs blank') + feat_id_all = tx_dt[, unique(gene)] + blank_id = feat_id_all[grepl(pattern = 'Blank', feat_id_all)] + feat_id = feat_id_all[!feat_id_all %in% blank_id] + + feat_dt = tx_dt[gene %in% feat_id,] + blank_dt = tx_dt[gene %in% blank_id,] + + # extract transcript_id col and store as feature meta + feat_meta = unique(feat_dt[, c('gene', 'transcript_id', 'barcode_id'), with = FALSE]) + blank_meta = unique(blank_dt[, c('gene', 'transcript_id', 'barcode_id'), with = FALSE]) + feat_dt[, c('transcript_id', 'barcode_id') := NULL] + blank_dt[, c('transcript_id', 'barcode_id') := NULL] + + if(isTRUE(verbose)) { + message(' > Features: ', feat_dt[, .N]) + message(' > Blanks: ', blank_dt[, .N]) + } + + # build giotto object + if(isTRUE(verbose)) wrap_msg('Building subcellular giotto object...') + z_sub = createGiottoObjectSubcellular( + gpoints = list('rna' = feat_coord, + 'neg_probe' = neg_coord), + gpolygons = list('cell' = cellLabel_dir), + polygon_mask_list_params = list( + mask_method = 'guess', + flip_vertical = TRUE, + flip_horizontal = FALSE, + shift_horizontal_step = FALSE + ), + instructions = instructions, + cores = cores + ) + +} + + + + +#' @describeIn createGiottoMerscopeObject Create giotto object with 'aggregate' workflow +#' @param data_list list of loaded data from \code{\link{load_merscope_folder}} +#' @keywords internal +createGiottoMerscopeObject_aggregate = function(data_list, + cores = NA, + verbose = TRUE) { + + # unpack data_list + micronToPixelScale = data_list$micronToPixelScale + expr_dt = data_list$expr_dt + cell_meta = data_list$expr_mat + image_list = data_list$images + + # split expr_dt by expression and blank + + # feat_id_all = + +} + + + + + + + + + + + + + + + +## CosMx #### + +#' @title Create Nanostring CosMx Giotto Object +#' @name createGiottoCosMxObject +#' @description Given the path to a CosMx experiment directory, creates a Giotto +#' object. +#' @param cosmx_dir full path to the exported cosmx directory +#' @param data_to_use which type(s) of expression data to build the gobject with +#' Default is \code{'all'} information available. \code{'subcellular'} loads the transcript +#' coordinates only. \code{'aggregate'} loads the provided aggregated expression matrix. +#' @param FOVs field of views to load (only affects subcellular data and images) +#' @inheritParams createGiottoObjectSubcellular +#' @return a giotto object +#' @export +#' @details +#' [\strong{Expected Directory}] This function generates a giotto object when given a +#' link to a cosmx output directory. It expects the following items within the directory +#' where the \strong{bolded} portions are what this function matches against: +#' \itemize{ +#' \item{\strong{CellComposite} (folder of images)} +#' \item{\strong{CellLabels} (folder of images)} +#' \item{\strong{CellOverlay} (folder of images)} +#' \item{\strong{CompartmentLabels} (folder of images)} +#' \item{experimentname_\strong{exprMat_file}.csv (file)} +#' \item{experimentname_\strong{fov_positions_file}.csv (file)} +#' \item{experimentname_\strong{metadata_file}.csv (file)} +#' \item{experimentname_\strong{tx_file}.csv (file)} +#' } +#' +#' [\strong{Workflows}] Workflow to use is accessed through the data_to_use param +#' \itemize{ +#' \item{'all' - loads and requires subcellular information from tx_file and fov_positions_file +#' and also the existing aggregated information (expression, spatial locations, and metadata) +#' from exprMat_file and metadata_file.} +#' \item{'subcellular' - loads and requires subcellular information from tx_file and +#' fov_positions_file only.} +#' \item{'aggregate' - loads and requires the existing aggregate information (expression, +#' spatial locations, and metadata) from exprMat_file and metadata_file.} +#' } +#' +#' [\strong{Images}] Images in the default CellComposite, CellLabels, CompartmentLabels, and CellOverlay +#' folders will be loaded as giotto largeImage objects in all workflows as long as they are available. +#' Additionally, CellComposite images will be converted to giotto image objects, making plotting with +#' these image objects more responsive when accessing them from a server. +#' \code{\link{showGiottoImageNames}} can be used to see the available images. +#' +#' +createGiottoCosMxObject = function(cosmx_dir = NULL, + data_to_use = c('all','subcellular','aggregate'), + FOVs = NULL, + instructions = NULL, + cores = NA, + verbose = TRUE) { + + # 0. setup + # set number of cores automatically, but with limit of 10 + cores = determine_cores(cores) + data.table::setDTthreads(threads = cores) + + # determine data to use + data_to_use = match.arg(arg = data_to_use, choices = c('all','subcellular','aggregate')) + + # Define for data.table + fov = target = x_local_px = y_local_px = z = cell_ID = CenterX_global_px = CenterY_global_px = + CenterX_local_px = CenterY_local_px = NULL + + + # 1. test if folder structure exists and is as expected + dir_items = read_cosmx_folder(cosmx_dir = cosmx_dir, + verbose = verbose) + + + # 2. load and create giotto object + if(data_to_use == 'subcellular') { + + cosmx_gobject = createGiottoCosMxObject_subcellular(dir_items, + FOVs = FOVs, + cores = cores, + verbose = verbose, + instructions = instructions) + + } + + if(data_to_use == 'aggregate') { + + cosmx_gobject = createGiottoCosMxObject_aggregate(dir_items, + cores = cores, + verbose = verbose, + instructions = instructions) + + } + + if(data_to_use == 'all') { + + cosmx_gobject = createGiottoCosMxObject_all(dir_items, + FOVs = FOVs, + cores = cores, + verbose = verbose, + instructions = instructions) + + } + + + # load in subcellular information, subcellular FOV objects, then join + + + # load in pre-generated aggregated expression matrix + if(data_to_use == 'aggregate' | data_to_use == 'all') { + + } + + + + message('done') + return(cosmx_gobject) + +} + + + +#' @title Load and create a CosMx Giotto object from subcellular info +#' @name createGiottoCosMxObject_subcellular +#' @inheritParams createGiottoCosMxObject +#' @keywords internal +createGiottoCosMxObject_subcellular = function(dir_items, + FOVs = NULL, + cores, + verbose = TRUE, + instructions = NULL) { + + # load tx detections and FOV offsets + data_list = load_cosmx_folder_subcellular(dir_items = dir_items, + FOVs = FOVs, + cores = cores, + verbose = verbose) + + # unpack data_list + FOV_ID = data_list$FOV_ID + fov_offset_file = data_list$fov_offset_file + tx_coord_all = data_list$tx_coord_all + + # remove global xy values and cell_ID + tx_coord_all[, c('x_global_px', 'y_global_px', 'cell_ID') := NULL] + + data.table::setcolorder(tx_coord_all, c('target', 'x_local_px', 'y_local_px', 'z', 'fov')) + + if(isTRUE(verbose)) wrap_msg('Splitting detections by feature vs neg probe') + all_IDs = tx_coord_all[, unique(target)] + neg_IDs = all_IDs[grepl(pattern = 'NegPrb', all_IDs)] + feat_IDs = all_IDs[!all_IDs %in% neg_IDs] + + # split detections DT + feat_coords_all = tx_coord_all[target %in% feat_IDs] + neg_coords_all = tx_coord_all[target %in% neg_IDs] + + if(isTRUE(verbose)) { + message(' > Features: ', feat_coords_all[, .N]) + message(' > NegProbes: ', neg_coords_all[, .N]) + } + + # Start FOV lapply + fov_gobjects_list = lapply(FOV_ID, function(x) { + + # Build image paths + if(isTRUE(verbose)) message('Loading image information...') + + composite_dir = Sys.glob(paths = file.path(dir_items$`CellComposite folder`, paste0('*',x, '*'))) + cellLabel_dir = Sys.glob(paths = file.path(dir_items$`CellLabels folder`, paste0('*',x, '*'))) + compartmentLabel_dir = Sys.glob(paths = file.path(dir_items$`CompartmentLabels folder`, paste0('*',x, '*'))) + cellOverlay_dir = Sys.glob(paths = file.path(dir_items$`CellOverlay folder`, paste0('*',x, '*'))) + # Missing warnings + if(length(composite_dir) == 0) {warning('[ FOV ', x, ' ] No composite images found') ; composite_dir = NULL} + if(length(cellLabel_dir) == 0) {stop('[ FOV ', x, ' ] No cell mask images found')} # cell masks are necessary + if(length(compartmentLabel_dir) == 0) {warning('[ FOV ', x, ' ] No compartment label images found') ; compartmentLabel_dir = NULL} + if(length(cellOverlay_dir) == 0) {warning('[ FOV ', x, ' ] No cell polygon overlay images found') ; cellOverlay_dir = NULL} + + if(isTRUE(verbose)) message('Image load done') + + if(isTRUE(verbose)) wrap_msg('[ FOV ', x, ']') + + # get FOV specific tx locations + if(isTRUE(verbose)) wrap_msg('Assigning FOV feature detections...') + + + # feature info + coord_oldnames = c('target', 'x_local_px', 'y_local_px') + coord_newnames = c('feat_ID', 'x', 'y') + + feat_coord = feat_coords_all[fov == as.numeric(x)] + data.table::setnames(feat_coord, old = coord_oldnames, new = coord_newnames) + # neg probe info + neg_coord = neg_coords_all[fov == as.numeric(x)] + data.table::setnames(neg_coord, old = coord_oldnames, new = coord_newnames) + + + # build giotto object + if(isTRUE(verbose)) wrap_msg('Building subcellular giotto object...') + fov_subset = createGiottoObjectSubcellular( + gpoints = list('rna' = feat_coord, + 'neg_probe' = neg_coord), + gpolygons = list('cell' = cellLabel_dir), + polygon_mask_list_params = list( + mask_method = 'guess', + flip_vertical = TRUE, + flip_horizontal = FALSE, + shift_horizontal_step = FALSE + ), + instructions = instructions, + cores = cores + ) + + + # find centroids as spatial locations + if(isTRUE(verbose)) wrap_msg('Finding polygon centroids as cell spatial locations...') + fov_subset = addSpatialCentroidLocations(fov_subset, + poly_info = 'cell', + spat_loc_name = 'raw') + + + # create and add giotto image objects + if(isTRUE(verbose)) message('Attaching image files...') + print(composite_dir) + print(cellOverlay_dir) + print(compartmentLabel_dir) + + gImage_list = list() + + # load image if files are found + if(!is.null(composite_dir)) + gImage_list$composite = createGiottoLargeImage(raster_object = composite_dir, + negative_y = F, + name = 'composite') + if(!is.null(cellOverlay_dir)) + gImage_list$overlay = createGiottoLargeImage(raster_object = cellOverlay_dir, + negative_y = F, + name = 'overlay') + if(!is.null(compartmentLabel_dir)) + gImage_list$compartment = createGiottoLargeImage(raster_object = compartmentLabel_dir, + negative_y = F, + name = 'compartment') #TODO + + + + if(length(gImage_list) > 0) { + fov_subset = addGiottoImage(gobject = fov_subset, + largeImages = gImage_list) + + # convert to MG for faster loading (particularly relevant for pulling from server) + fov_subset = convertGiottoLargeImageToMG(giottoLargeImage = gImage_list$composite, + gobject = fov_subset, + return_gobject = TRUE, + verbose = FALSE) + # fov_subset = convertGiottoLargeImageToMG(giottoLargeImage = gImage_list$overlay, gobject = fov_subset, return_gobject = TRUE) + # fov_subset = convertGiottoLargeImageToMG(giottoLargeImage = gImage_list$compartment, gobject = fov_subset, return_gobject = TRUE) + } else { + message('No images found for fov') + } + + + }) #lapply end + + if(length(FOVs) == 1) { + return(fov_gobjects_list[[1]]) + } else { + # join giotto objects according to FOV positions file + if(isTRUE(verbose)) message('Joining FOV gobjects...') + new_gobj_names = paste0('fov', FOV_ID) + id_match = match(as.numeric(FOV_ID), fov_offset_file$fov) + x_shifts = fov_offset_file[id_match]$x_global_px + y_shifts = fov_offset_file[id_match]$y_global_px + # Join giotto objects + cosmx_gobject = joinGiottoObjects(gobject_list = fov_gobjects_list, + gobject_names = new_gobj_names, + join_method = 'shift', + x_shift = x_shifts, + y_shift = y_shifts) + return(cosmx_gobject) + } + +} + + + +#' @title Load and create a CosMx Giotto object from aggregate info +#' @name createGiottoCosMxObject_aggregate +#' @inheritParams createGiottoCosMxObject +#' @keywords internal +createGiottoCosMxObject_aggregate = function(dir_items, + cores, + verbose = TRUE, + instructions = NULL) { + + + + data_list = load_cosmx_folder_aggregate(dir_items = dir_items, + cores = cores, + verbose = verbose) + + # unpack data_list + spatlocs = data_list$spatlocs + spatlocs_fov = data_list$spatlocs_fov + metadata = data_list$metadata + protM = data_list$protM + spM = data_list$spM + fov_shifts = data_list$fov_shifts + + + # create standard gobject from aggregate matrix + if(data_to_use == 'aggregate') { + + # Create aggregate gobject + if(isTRUE(verbose)) message('Building giotto object...') + cosmx_gobject = createGiottoObject(expression = list('raw' = spM, 'protein' = protM), + cell_metadata = list('cell' = list('rna' = metadata, + 'protein' = metadata)), + spatial_locs = spatlocs, + instructions = instructions, + cores = cores) + + + # load in images + img_ID = data.table::data.table(fov = fov_shifts[, fov], + img_name = paste0('fov', sprintf('%03d', fov_shifts[, fov]), '-image')) + + if(isTRUE(verbose)) message('Attaching image files...') + composite_dir = Sys.glob(paths = file.path(dir_items$`CellComposite folder`, paste0('/*'))) + cellLabel_dir = Sys.glob(paths = file.path(dir_items$`CellLabels folder`, paste0('/*'))) + compartmentLabel_dir = Sys.glob(paths = file.path(dir_items$`CompartmentLabels folder`, paste0('/*'))) + overlay_dir = Sys.glob(paths = file.path(dir_items$`CellOverlay folder`, paste0('/*'))) + + if(length(cellLabel_imgList) > 0) cellLabel_imgList = lapply(cellLabel_dir, function(x) {createGiottoLargeImage(x,name = 'cellLabel',negative_y = TRUE)}) + if(length(composite_imgList) > 0) composite_imgList = lapply(composite_dir, function(x) {createGiottoLargeImage(x,name = 'composite',negative_y = TRUE)}) + if(length(compartmentLabel_dir) > 0) compartmentLabel_imgList = lapply(compartmentLabel_dir, function(x) {createGiottoLargeImage(x,name = 'composite',negative_y = TRUE)}) + if(length(overlay_dir) > 0) overlay_imgList = lapply(overlay_dir, function(x) {createGiottoLargeImage(x,name = 'composite',negative_y = TRUE)}) + + + + } + +} + + + + +#' @title Load and create a CosMx Giotto object from subcellular and aggregate info +#' @name createGiottoCosMxObject_all +#' @param dir_items list of full directory paths from \code{read_cosmx_folder} +#' @inheritParams createGiottoCosMxObject +#' @details Both \emph{subcellular} (subellular transcript detection information) and +#' \emph{aggregate} (aggregated detection count matrices by cell polygon from NanoString) +#' data will be loaded in. The two will be separated into 'cell' and 'cell_agg' +#' spatial units in order to denote the difference in origin of the two. +#' @seealso createGiottoCosMxObject createGiottoCosMxObject_aggregate +#' createGiottoCosMxObject_subcellular +#' @keywords internal +createGiottoCosMxObject_all = function(dir_items, + FOVs, + cores, + verbose = TRUE, + instructions = NULL) { + + # 1. create subcellular giotto as spat_unit 'cell' + cosmx_gobject = createGiottoCosMxObject_subcellular(dir_items = dir_items, + FOVs = FOVs, + cores = cores, + verbose = verbose, + instructions = instructions) + + # 2. load and append aggregated information in spat_unit 'cell_agg' + agg_data = load_cosmx_folder_aggregate(dir_items = dir_items, + cores = cores, + verbose = verbose) + + # unpack data_list + spatlocs = agg_data$spatlocs + spatlocs_fov = agg_data$spatlocs_fov + metadata = agg_data$metadata + protM = agg_data$protM + spM = agg_data$spM + + # add in pre-generated aggregated expression matrix information for 'all' workflow + + # Add aggregate expression information + if(isTRUE(verbose)) wrap_msg('Appending provided aggregate expression data as... + spat_unit: "cell_agg" + feat_type: "rna" + name: "raw"') + # add expression data to expression slot + s4_expr = create_expr_obj(name = 'raw', + exprMat = spM, + spat_unit = 'cell_agg', + feat_type = 'rna', + provenance = 'cell_agg') + + cosmx_gobject = set_expression_values(cosmx_gobject, values = s4_expr) + + # Add spatial locations + if(isTRUE(verbose)) wrap_msg('Appending metadata provided spatial locations data as... + --> spat_unit: "cell_agg" name: "raw" + --> spat_unit: "cell" name: "raw_fov"') + if(isTRUE(verbose)) wrap_msg('Polygon centroid derived spatial locations assigned as... + --> spat_unit: "cell" name: "raw" (default)') + + locsObj = create_spat_locs_obj(name = 'raw', + coordinates = spatlocs, + spat_unit = 'cell_agg', + provenance = 'cell_agg') + locsObj_fov = create_spat_locs_obj(name = 'raw_fov', + coordinates = spatlocs_fov, + spat_unit = 'cell_agg', + provenance = 'cell_agg') + + cosmx_gobject = set_spatial_locations(cosmx_gobject, spatlocs = locsObj) + cosmx_gobject = set_spatial_locations(cosmx_gobject, spatlocs = locsObj_fov) + + # cosmx_gobject = set_spatial_locations(cosmx_gobject, + # spat_unit = 'cell_agg', + # spat_loc_name = 'raw', + # spatlocs = spatlocs) + # cosmx_gobject = set_spatial_locations(cosmx_gobject, + # spat_unit = 'cell_agg', + # spat_loc_name = 'raw_fov', + # spatlocs = spatlocs_fov) + + # initialize cell and feat IDs and metadata slots for 'cell_agg' spat_unit + agg_cell_ID = colnames(s4_expr[]) + agg_feat_ID = rownames(s4_expr[]) + + sub_feat_ID = get_feat_id(cosmx_gobject, feat_type = 'rna') + feat_ID_new = unique(c(agg_feat_ID, sub_feat_ID)) + + cosmx_gobject = set_cell_id(gobject = cosmx_gobject, + spat_unit = 'cell_agg', + cell_IDs = agg_cell_ID) + cosmx_gobject = set_feat_id(gobject = cosmx_gobject, + feat_type = 'rna', + feat_IDs = feat_ID_new) + + # cell metadata + + # cosmx_gobject@cell_ID[['cell_agg']] = colnames(cosmx_gobject@expression[['cell_agg']][[1]][[1]]) + # cosmx_gobject@feat_ID[['rna']] = unique(c(cosmx_gobject@feat_ID, rownames(cosmx_gobject@expression[['cell_agg']][['rna']][[1]]))) + # cosmx_gobject@cell_metadata[['cell_agg']][['rna']] = data.table::data.table(cell_ID = cosmx_gobject@cell_ID[['cell_agg']]) + # cosmx_gobject@feat_metadata[['cell_agg']][['rna']] = data.table::data.table(feat_ID = cosmx_gobject@feat_ID[['rna']]) + + # Add metadata to both the given and the poly spat_units + if(isTRUE(verbose)) message('Appending provided cell metadata...') + cosmx_gobject = addCellMetadata(cosmx_gobject, + spat_unit = 'cell', + feat_type = 'rna', + new_metadata = metadata, + by_column = TRUE, + column_cell_ID = 'cell_ID') + cosmx_gobject = addCellMetadata(cosmx_gobject, + spat_unit = 'cell_agg', + feat_type = 'rna', + new_metadata = metadata, + by_column = TRUE, + column_cell_ID = 'cell_ID') + +} + + + + + + + + + + +## Xenium #### + +#' @title Create 10x Xenium Giotto Object +#' @name createGiottoXeniumObject +#' @description Given the path to a Xenium experiment output folder, creates a Giotto +#' object +#' @param xenium_dir full path to the exported xenium directory +#' @param data_to_use which type(s) of expression data to build the gobject with +#' (e.g. default: \strong{'subcellular'}, 'aggregate', or 'all') +#' @param load_format files formats from which to load the data. Either `csv` or +#' `parquet` currently supported. +#' @param h5_expression (boolean) whether to load cell_feature_matrix from .h5 file. +#' Default is \code{TRUE} +#' @param h5_gene_ids use gene symbols (default) or ensembl ids for the .h5 gene +#' expression matrix +#' @param bounds_to_load vector of boundary information to load (e.g. \code{'cell'} +#' or \code{'nucleus'} by themselves or \code{c('cell', 'nucleus')} to load both +#' at the same time.) +#' @param qv_threshold Minimum Phred-scaled quality score cutoff to be included as +#' a subcellular transcript detection (default = 20) +#' @param key_list (advanced) list of grep-based keywords to split the subcellular +#' feature detections by feature type. See details +#' @inheritParams get10Xmatrix +#' @inheritParams createGiottoObjectSubcellular +#' @details +#' +#' [\strong{QC feature types}] +#' Xenium provides info on feature detections that include more than only the +#' Gene Expression specific probes. Additional probes for QC are included: +#' \emph{blank codeword}, \emph{negative control codeword}, and +#' \emph{negative control probe}. These additional QC probes each occupy and are treated +#' as their own feature types so that they can largely remain independent of the +#' gene expression information. +#' +#' [\strong{key_list}] +#' Related to \code{data_to_use = 'subcellular'} workflow only: +#' Additional QC probe information is in the subcellular feature detections information +#' and must be separated from the gene expression information during processing. +#' The QC probes have prefixes that allow them to be selected from the rest of the +#' feature IDs. +#' Giotto uses a named list of keywords (\code{key_list}) to select these QC probes, +#' with the list names being the names that will be assigned as the feature type +#' of these feature detections. The default list is used when \code{key_list} = NULL. +#' +#' Default list: +#' \preformatted{ +#' list(blank_code = 'BLANK_', +#' neg_code = 'NegControlCodeword_', +#' neg_probe = c('NegControlProbe_|antisense_')) +#' } +#' +#' The Gene expression subset is accepted as the subset of feat_IDs that do not +#' map to any of the keys. +#' +#' @export +createGiottoXeniumObject = function(xenium_dir, + data_to_use = c('subcellular','aggregate'), + load_format = 'csv', + h5_expression = TRUE, + h5_gene_ids = c('symbols', 'ensembl'), + gene_column_index = 1, + bounds_to_load = c('cell'), + qv_threshold = 20, + key_list = NULL, + # include_analysis = FALSE, + instructions = NULL, + cores = NA, + verbose = TRUE) { + + # 0. setup + + # Determine data to load + data_to_use = match.arg(arg = data_to_use, choices = c('subcellular','aggregate')) + + # Determine load formats + load_format = 'csv' # TODO Remove this and add as param once other options are available + load_format = match.arg(arg = load_format, choices = c('csv', 'parquet', 'zarr')) + + # set number of cores automatically, but with limit of 10 + cores = determine_cores(cores) + data.table::setDTthreads(threads = cores) + + # 1. detect xenium folder and find filepaths to load + + # path_list contents: + # tx_path + # bound_paths + # cell_meta_path + # agg_expr_path + # panel_meta_path + path_list = read_xenium_folder(xenium_dir = xenium_dir, + data_to_use = data_to_use, + bounds_to_load = bounds_to_load, + load_format = load_format, + h5_expression = h5_expression, + verbose = verbose) + + + # 2. load in data + + # data_list contents: + # feat_meta + # tx_dt + # bound_dt_list + # cell_meta + # agg_expr + data_list = load_xenium_folder(path_list = path_list, + load_format = load_format, + data_to_use = data_to_use, + h5_expression = h5_expression, + h5_gene_ids = h5_gene_ids, + gene_column_index = gene_column_index, + cores = cores, + verbose = verbose) + + + # TODO load images + + + # 3. Create giotto objects + + if(data_to_use == 'subcellular') { + + # ** feat type search keys ** + if(is.null(key_list)) { + key_list = list(blank_code = 'BLANK_', + neg_code = 'NegControlCodeword_', + neg_probe = c('NegControlProbe_|antisense_')) + } + + # needed: + # feat_meta + # tx_dt + # bound_dt_list + xenium_gobject = createGiottoXeniumObject_subcellular(data_list = data_list, + qv_threshold = qv_threshold, + key_list = key_list, + instructions = instructions, + cores = cores, + verbose = verbose) + + } + + if(data_to_use == 'aggregate') { + + # needed: + # feat_meta + # cell_meta + # agg_expr + # optional? + # tx_dt + # bound_dt_list + xenium_gobject = createGiottoXeniumObject_aggregate(data_list = data_list, + instructions = instructions, + cores = cores, + verbose = verbose) + + } + + return(xenium_gobject) + +} + + + + +#' @title Create a Xenium Giotto object from subcellular info +#' @name createGiottoXeniumObject_subcellular +#' @description Subcellular workflow for createGiottoXeniumObject +#' @param data_list list of data loaded by \code{\link{load_xenium_folder}} +#' @param key_list regex-based search keys for feature IDs to allow separation +#' into separate giottoPoints objects by feat_type +#' @param qv_threshold Minimum Phred-scaled quality score cutoff to be included as +#' a subcellular transcript detection (default = 20) +#' @inheritParams get10Xmatrix +#' @inheritParams createGiottoObjectSubcellular +#' @seealso createGiottoXeniumObject createGiottoXeniumObject_aggregate +#' @keywords internal +createGiottoXeniumObject_subcellular = function(data_list, + key_list = NULL, + qv_threshold = 20, + instructions = NULL, + cores = NA, + verbose = TRUE) { + + # data.table vars + qv = NULL + + # Unpack data_list info + feat_meta = data_list$feat_meta + tx_dt = data_list$tx_dt + bound_dt_list = data_list$bound_dt_list + # cell_meta = data_list$cell_meta + # agg_expr = data_list$agg_expr + + # define for data.table + cell_id = feat_ID = feature_name = NULL + + if(isTRUE(verbose)) message('Building subcellular giotto object...') + # Giotto points object + if(isTRUE(verbose)) message('> points data prep...') + + # filter by qv_threshold + if(isTRUE(verbose)) wrap_msg('> filtering feature detections for Phred score >= ', qv_threshold) + n_before = tx_dt[,.N] + tx_dt_filtered = tx_dt[qv >= qv_threshold] + n_after = tx_dt_filtered[,.N] + + cat('Number of feature points removed: ', + n_before - n_after, + ' out of ', n_before, '\n') + + if(isTRUE(verbose)) message('> splitting detections by feat_type') + # discover feat_IDs for each feat_type + all_IDs = tx_dt_filtered[, unique(feat_ID)] + feat_types_IDs = lapply(key_list, function(x) all_IDs[grepl(pattern = x, all_IDs)]) + rna = list('rna' = all_IDs[!all_IDs %in% unlist(feat_types_IDs)]) + feat_types_IDs = append(rna, feat_types_IDs) + + # separate detections by feature type + points_list = lapply( + feat_types_IDs, + function(types) { + tx_dt_filtered[feat_ID %in% types] + } + ) + + # Giotto polygons object + if(isTRUE(verbose)) message('> polygons data prep...') + polys_list = lapply( + bound_dt_list, + function(bound_type) { + bound_type[, cell_id := as.character(cell_id)] + } + ) + + xenium_gobject = createGiottoObjectSubcellular(gpoints = points_list, + gpolygons = polys_list, + instructions = instructions, + cores = cores, + verbose = verbose) + + # generate centroids + if(isTRUE(verbose)) message('Calculating polygon centroids...') + xenium_gobject = addSpatialCentroidLocations(xenium_gobject, + poly_info = c(names(bound_dt_list))) + + # add in feature metadata + # xenium_gobject = addFeatMetadata(gobject = xenium_gobject, + # new_metadata = feat_meta, + # by_column = TRUE, + # column_feat_ID = 'feat_ID') + + return(xenium_gobject) + +} + + + + + +#' @title Create a Xenium Giotto object from aggregate info +#' @name createGiottoXeniumObject_aggregate +#' @description Aggregate workflow for createGiottoXeniumObject +#' @param data_list list of data loaded by \code{load_xenium_folder} +#' @inheritParams get10Xmatrix +#' @inheritParams createGiottoObjectSubcellular +#' @seealso createGiottoXeniumObject createGiottoXeniumObject_subcellular +#' @keywords internal +createGiottoXeniumObject_aggregate = function(data_list, + # include_analysis = FALSE, + instructions = NULL, + cores = NA, + verbose = TRUE) { + + # Unpack data_list info + feat_meta = data_list$feat_meta + # tx_dt = data_list$tx_dt + # bound_dt_list = data_list$bound_dt_list + cell_meta = data_list$cell_meta + agg_expr = data_list$agg_expr + + # define for data.table + cell_ID = x_centroid = y_centroid = NULL + + # clean up names for aggregate matrices + names(agg_expr) = gsub(pattern = ' ', replacement = '_' ,names(agg_expr)) + geneExpMat = which(names(agg_expr) == 'Gene_Expression') + names(agg_expr)[[geneExpMat]] = 'raw' + + # set cell_id as character + cell_meta = cell_meta[, data.table::setnames(.SD, 'cell_id', 'cell_ID')] + cell_meta = cell_meta[, cell_ID := as.character(cell_ID)] + + # set up spatial locations + agg_spatlocs = cell_meta[, .(x_centroid, y_centroid, cell_ID)] + + # set up metadata + agg_meta = cell_meta[, !c('x_centroid','y_centroid')] + + if(isTRUE(verbose)) message('Building aggregate giotto object...') + xenium_gobject = createGiottoObject(expression = agg_expr, + spatial_locs = agg_spatlocs, + instructions = instructions, + cores = cores, + verbose = verbose) + + # append aggregate metadata + xenium_gobject = addCellMetadata(gobject = xenium_gobject, + new_metadata = agg_meta, + by_column = TRUE, + column_cell_ID = 'cell_ID') + xenium_gobject = addFeatMetadata(gobject = xenium_gobject, + new_metadata = feat_meta, + by_column = TRUE, + column_feat_ID = 'feat_ID') + + return(xenium_gobject) + +} + + + + + + + +# folder reading and detection #### + + + + +#' @describeIn read_data_folder Read a structured MERSCOPE folder +#' @keywords internal +read_merscope_folder = function(merscope_dir, + data_to_use, + cores = NA, + verbose = TRUE) { + + # prepare dir_items list + dir_items = list(`boundary info` = '*cell_boundaries*', + `image info` = '*images*', + `cell feature matrix` = '*cell_by_gene*', + `cell metadata` = '*cell_metadata*', + `raw transcript info` = '*transcripts*') + + # prepare require_data_DT + sub_reqs = data.table::data.table(workflow = c('subcellular'), + item = c('boundary info', + 'raw transcript info', + 'image info', + 'cell by gene matrix', + 'cell metadata'), + needed = c(TRUE, TRUE, FALSE, FALSE, FALSE)) + + agg_reqs = data.table::data.table(workflow = c('aggregate'), + item = c('boundary info', + 'raw transcript info', + 'image info', + 'cell by gene matrix', + 'cell metadata'), + needed = c(FALSE, FALSE, FALSE, TRUE, TRUE)) + + require_data_DT = rbind(sub_reqs, agg_reqs) + + dir_items = read_data_folder(spat_method = 'MERSCOPE', + data_dir = merscope_dir, + dir_items = dir_items, + data_to_use = data_to_use, + require_data_DT = require_data_DT, + cores = cores, + verbose = verbose) + + return(dir_items) + +} + + + +#' @title Read a structured CosMx folder +#' @name read_cosmx_folder +#' @inheritParams createGiottoCosMxObject +#' @seealso createGiottoCosMxObject load_cosmx_folder +#' @return path_list a list of cosmx files discovered and their filepaths. NULL +#' values denote missing items +#' @keywords internal +read_cosmx_folder = function(cosmx_dir, + verbose = TRUE) { + + ch = box_chars() + + if(is.null(cosmx_dir) | !dir.exists(cosmx_dir)) stop('The full path to a cosmx directory must be given.\n') + if(isTRUE(verbose)) wrap_msg('A structured CosMx directory will be used\n') + + # find directories (length = 1 if present, length = 0 if missing) + dir_items = list(`CellLabels folder` = '*CellLabels', + `CompartmentLabels folder` = '*CompartmentLabels', + `CellComposite folder` = '*CellComposite', + `CellOverlay folder` = '*CellOverlay', + `transcript locations file` = '*tx_file*', + `fov positions file` = '*fov_positions_file*', + `expression matrix file` = '*exprMat_file*', + `metadata file` = '*metadata_file*') + dir_items = lapply(dir_items, function(x) Sys.glob(paths = file.path(cosmx_dir, x))) + dir_items_lengths = lengths(dir_items) + + if(isTRUE(verbose)) { + message('Checking directory contents...') + for(item in names(dir_items)) { + if(dir_items_lengths[[item]] > 0) { + message(ch$s, '> ' ,item, ' found') + } else { + warning(item, ' is missing\n') + } + } + } + + # select first directory in list if multiple are detected + if(any(dir_items_lengths > 1)) { + warning('Multiple matches for expected subdirectory item(s).\n First matching item selected') + + multiples = which(dir_items_lengths > 1) + for(mult_i in multiples) { + message(names(dir_items)[[mult_i]], 'multiple matches found:') + print(dir_items[[mult_i]]) + dir_items[[mult_i]] = dir_items[[mult_i]][[1]] + } + } + if(isTRUE(verbose)) message('Directory check done') + + return(dir_items) + +} + + + + +#' @title Read a structured xenium folder +#' @name read_xenium_folder +#' @inheritParams createGiottoXeniumObject +#' @keywords internal +#' @return path_list a list of xenium files discovered and their filepaths. NULL +#' values denote missing items +read_xenium_folder = function(xenium_dir, + data_to_use = 'subcellular', + bounds_to_load = c('cell'), + load_format = 'csv', + h5_expression = FALSE, + verbose = TRUE) { + + # Check needed packages + if(load_format == 'parquet') { + package_check(pkg_name = 'arrow', repository = 'CRAN') + package_check(pkg_name = 'dplyr', repository = 'CRAN') + } + if(isTRUE(h5_expression)) { + package_check(pkg_name = 'hdf5r', repository = 'CRAN') + } + + ch = box_chars() + + + # 0. test if folder structure exists and is as expected + + + if(is.null(xenium_dir) | !dir.exists(xenium_dir)) stop('The full path to a xenium directory must be given.\n') + if(isTRUE(verbose)) message('A structured Xenium directory will be used\n') + + # find items (length = 1 if present, length = 0 if missing) + dir_items = list(`analysis info` = '*analysis*', + `boundary info` = '*bound*', + `cell feature matrix` = '*cell_feature_matrix*', + `cell metadata` = '*cells*', + `image info` = '*tif', + `panel metadata` = '*panel*', + `raw transcript info` = '*transcripts*', + `experiment info (.xenium)` = '*.xenium') + + dir_items = lapply(dir_items, function(x) Sys.glob(paths = file.path(xenium_dir, x))) + dir_items_lengths = lengths(dir_items) + + if(isTRUE(verbose)) { + message('Checking directory contents...') + for(item in names(dir_items)) { + + # IF ITEM FOUND + + if(dir_items_lengths[[item]] > 0) { + message(ch$s, '> ' ,item, ' found') + for(item_i in seq_along(dir_items[[item]])) { # print found item names + subItem = gsub(pattern = '.*/', replacement = '', x = dir_items[[item]][[item_i]]) + message(ch$s, ch$s, ch$l,ch$h,ch$h, subItem) + } + } else { + + # IF ITEM MISSING + # Based on workflow, determine if: + # necessary (error) + # optional (warning) + + if(data_to_use == 'subcellular') { + # necessary items + if(item %in% c('boundary info', 'raw transcript info')) stop(item, ' is missing\n') + # optional items + if(item %in% c('image info', 'experiment info (.xenium)', 'panel metadata')) warning(item, ' is missing (optional)\n') + # items to ignore: analysis info, cell feature matrix, cell metadata + } else if(data_to_use == 'aggregate') { + # necessary items + if(item %in% c('cell feature matrix', 'cell metadata')) stop(item, ' is missing\n') + # optional items + if(item %in% c('image info', 'experiment info (.xenium)', 'panel metadata', 'analysis info')) warning(item, ' is missing (optional)\n') + # items to ignore: boundary info, raw transcript info + } + } + } + } + + + # 1. Select data to load + + + # **** transcript info **** + tx_path = NULL + tx_path = dir_items$`raw transcript info`[grepl(pattern = load_format, dir_items$`raw transcript info`)] + # **** cell metadata **** + cell_meta_path = NULL + cell_meta_path = dir_items$`cell metadata`[grepl(pattern = load_format, dir_items$`cell metadata`)] + + # **** boundary info **** + # Select bound load format + if(load_format != 'zarr') { # No zarr available for boundary info + dir_items$`boundary info` = dir_items$`boundary info`[grepl(pattern = load_format, dir_items$`boundary info`)] + } else dir_items$`boundary info` = dir_items$`boundary info`[grepl(pattern = 'csv', dir_items$`boundary info`)] + + # Organize bound paths by type of bound (bounds_to_load param) + bound_paths = NULL + bound_names = bounds_to_load + bounds_to_load = as.list(bounds_to_load) + bound_paths = lapply(bounds_to_load, function(x) dir_items$`boundary info`[grepl(pattern = x, dir_items$`boundary info`)]) + names(bound_paths) = bound_names + + # **** aggregated expression info **** + agg_expr_path = NULL + if(isTRUE(h5_expression)) { # h5 expression matrix loading is default + agg_expr_path = dir_items$`cell feature matrix`[grepl(pattern = 'h5', dir_items$`cell feature matrix`)] + h5_gene_ids = match.arg(arg = h5_gene_ids, choices = c('symbols', 'ensembl')) + } else if(load_format == 'zarr') { + agg_expr_path = dir_items$`cell feature matrix`[grepl(pattern = 'zarr', dir_items$`cell feature matrix`)] + } else { # No parquet for aggregated expression - default to normal 10x loading + agg_expr_path = dir_items$`cell feature matrix`[sapply(dir_items$`cell feature matrix`, function(x) file_test(op = '-d', x))] + if(length(agg_expr_path) == 0) stop(wrap_txt( + 'Expression matrix cannot be loaded.\nHas cell_feature_matrix(.tar.gz) been unpacked into a directory?' + )) + } + if(data_to_use == 'aggregate') { + if(length(path_list$agg_expr_path) == 0) stop(wrap_txt( + 'Aggregated expression not found.\nPlease confirm h5_expression and load_format params are correct\n' + )) + } + + # **** panel info **** + panel_meta_path = NULL + panel_meta_path = dir_items$`panel metadata` + + + if(isTRUE(verbose)) message('Directory check done') + + path_list = list('tx_path' = tx_path, + 'bound_paths' = bound_paths, + 'cell_meta_path' = cell_meta_path, + 'agg_expr_path' = agg_expr_path, + 'panel_meta_path' = panel_meta_path) + + return(path_list) + +} + + + + + + +# folder loading #### + + +## MERSCOPE #### + +#' @title Load MERSCOPE data from folder +#' @name load_merscope_folder +#' @param dir_items list of full filepaths from \code{\link{read_merscope_folder}} +#' @inheritParams createGiottoMerscopeObject +#' @keywords internal +#' @return list of loaded-in MERSCOPE data +load_merscope_folder = function(dir_items, + data_to_use, + fovs = NULL, + cores = NA, + verbose = TRUE) { + + # 1. load data_to_use-specific + if(data_to_use == 'subcellular') { + data_list = load_merscope_folder_subcellular(dir_items = dir_items, + data_to_use = data_to_use, + fovs = fovs, + cores = cores, + verbose = verbose) + } else if(data_to_use == 'aggregate') { + data_list = load_merscope_folder_aggregate(dir_items = dir_items, + data_to_use = data_to_use, + cores = cores, + verbose = verbose) + } else { + stop(wrap_txt('data_to_use "', data_to_use, '" not implemented', sep = '')) + } + + # 2. Load images if available + if(!is.null(dir_items$`image info`)) { + ## micron to px scaling factor + micronToPixelScale = Sys.glob(paths = file.path(dir_items$`image info`, '*micron_to_mosaic_pixel_transform*'))[[1]] + micronToPixelScale = data.table::fread(micronToPixelScale, nThread = cores) + # add to data_list + data_list$micronToPixelScale = micronToPixelScale + + ## staining images + ## determine types of stains + images_filenames = list.files(dir_items$`image info`) + bound_stains_filenames = images_filenames[grep(pattern = '.tif', images_filenames)] + bound_stains_types = sapply(strsplit(bound_stains_filenames, '_'), `[`, 2) + bound_stains_types = unique(bound_stains_types) + + img_list = lapply_flex(bound_stains_types, function(stype) { + img_paths = Sys.glob(paths = file.path(dir_items$`image info`, paste0('*',stype,'*'))) + # print(img_paths) + lapply_flex(img_paths, function(img) { + createGiottoLargeImage(raster_object = img) + }, cores = cores) + }, cores = cores) + # add to data_list + data_list$images = img_list + } + + + + return(data_list) + +} + + + +#' @describeIn load_merscope_folder Load items for 'subcellular' workflow +#' @keywords internal +load_merscope_folder_subcellular = function(dir_items, + data_to_use, + cores = NA, + verbose = TRUE, + fovs = NULL) { + + if(isTRUE(verbose)) wrap_msg('Loading transcript level info...') + if(is.null(fovs)) { + tx_dt = data.table::fread(dir_items$`raw transcript info`, nThread = cores) + } else { + if(isTRUE(verbose)) wrap_msg('Selecting FOV subset transcripts') + tx_dt = fread_colmatch(file = dir_items$`raw transcript info`, + col = 'fov', + values_to_match = fovs, + verbose = FALSE, + nThread = cores) + } + tx_dt[, c('x','y') := NULL] # remove unneeded cols + data.table::setcolorder(tx_dt, c('gene', 'global_x', 'global_y', 'global_z')) + + if(isTRUE(verbose)) wrap_msg('Loading polygon info...') + poly_info = readPolygonFilesVizgenHDF5(boundaries_path = dir_items$`boundary info`, + polygon_feat_types = c(0,6), + flip_y_axis = TRUE, + fovs = fovs) + + data_list = list( + 'poly_info' = poly_info, + 'tx_dt' = tx_dt, + 'micronToPixelScale' = NULL, + 'expr_dt' = NULL, + 'cell_meta' = NULL, + 'images' = NULL + ) + +} + + + +#' @describeIn load_merscope_folder Load items for 'aggregate' workflow +#' @keywords internal +load_merscope_folder_aggregate = function(dir_items, + data_to_use, + cores = NA, + verbose = TRUE) { + + # metadata is polygon-related measurements + if(isTRUE(verbose)) wrap_msg('Loading cell metadata...') + cell_metadata_file = data.table::fread(dir_items$`cell metadata`, nThread = cores) + + if(isTRUE(verbose)) wrap_msg('Loading expression matrix') + expr_dt = data.table::fread(dir_items$`cell feature matrix`, nThread = cores) + + + data_list = list( + 'poly_info' = NULL, + 'tx_dt' = NULL, + 'micronToPixelScale' = NULL, + 'expr_dt' = expr_dt, + 'cell_meta' = cell_metadata_file, + 'images' = NULL + ) + +} + + + + + + + +## CosMx #### + +#' @title Load CosMx folder subcellular info +#' @name load_cosmx_folder_subcellular +#' @description loads in the feature detections information. Note that the mask +#' images are still required for a working subcellular object, and those are loaded +#' in \code{\link{createGiottoCosMxObject_subcellular}} +#' @inheritParams createGiottoCosMxObject +#' @keywords internal +load_cosmx_folder_subcellular = function(dir_items, + FOVs = NULL, + cores, + verbose = TRUE) { + + if(isTRUE(verbose)) wrap_msg('Loading subcellular information...') + + # subcellular checks + if(!file.exists(dir_items$`transcript locations file`)) + stop(wrap_txt('No transcript locations file (.csv) detected')) + if(!file.exists(dir_items$`fov positions file`)) + stop(wrap_txt('No fov positions file (.csv) detected')) + + # FOVs to load + if(isTRUE(verbose)) wrap_msg('Loading FOV offsets...') + fov_offset_file = fread(input = dir_items$`fov positions file`, nThread = cores) + if(is.null(FOVs)) FOVs = fov_offset_file$fov # default to ALL FOVs + FOV_ID = as.list(sprintf('%03d', FOVs)) + + #TODO Load only relevant portions of file? + + if(isTRUE(verbose)) wrap_msg('Loading transcript level info...') + tx_coord_all = fread(input = dir_items$`transcript locations file`, nThread = cores) + if(isTRUE(verbose)) wrap_msg('Subcellular load done') + + data_list = list( + 'FOV_ID' = FOV_ID, + 'fov_offset_file' = fov_offset_file, + 'tx_coord_all' = tx_coord_all + ) + + return(data_list) + +} + + + +#' @title Load CosMx folder aggregate info +#' @name load_cosmx_folder_aggregate +#' @inheritParams createGiottoCosMxObject +#' @keywords internal +load_cosmx_folder_aggregate = function(dir_items, + cores, + verbose = TRUE) { + + # data.table vars + fov = cell_ID = fov_cell_ID = CenterX_global_px = CenterY_global_px = CenterX_local_px = + CenterY_local_px = x_shift = y_shift = NULL + + # load aggregate information + wrap_msg('Loading provided aggregated information...') + + # aggregate checks + if(!file.exists(dir_items$`expression matrix file`)) stop(wrap_txt('No expression matrix file (.csv) detected')) + if(!file.exists(dir_items$`metadata file`)) stop(wrap_txt('No metadata file (.csv) detected. Needed for cell spatial locations.')) + + # read in aggregate data + expr_mat = fread(input = dir_items$`expression matrix file`, nThread = cores) + metadata = fread(input = dir_items$`metadata file`, nThread = cores) + + # setorder expression and spatlocs + data.table::setorder(metadata, fov, cell_ID) + data.table::setorder(expr_mat, fov, cell_ID) + + + # generate unique cell IDs + expr_mat[, cell_ID := paste0('fov', sprintf('%03d', fov), '-', 'cell_', cell_ID)] + # expr_mat$cell_ID = paste0('fov', sprintf('%03d', expr_mat$fov), '-', 'cell_', expr_mat$cell_ID) + expr_mat = expr_mat[, fov := NULL] + + metadata[, fov_cell_ID := cell_ID] + metadata[, cell_ID := paste0('fov', sprintf('%03d', fov), '-', 'cell_', cell_ID)] + # metadata$cell_ID = paste0('fov', sprintf('%03d', metadata$fov), '-', 'cell_', metadata$cell_ID) + # reorder + data.table::setcolorder(x = metadata, c('cell_ID','fov','fov_cell_ID')) + + + # extract spatial locations + spatlocs = metadata[,.(CenterX_global_px, CenterY_global_px, cell_ID)] + spatlocs_fov = metadata[,.(CenterX_local_px, CenterY_local_px, cell_ID)] + # regenerate FOV shifts + metadata[, x_shift := CenterX_global_px - CenterX_local_px] + metadata[, y_shift := CenterY_global_px - CenterY_local_px] + fov_shifts = metadata[, .(mean(x_shift), mean(y_shift)), fov] + colnames(fov_shifts) = c('fov', 'x_shift', 'y_shift') + + + # rename spatloc column names + spatloc_oldnames = c('CenterX_global_px', 'CenterY_global_px', 'cell_ID') + spatloc_oldnames_fov = c('CenterX_local_px', 'CenterY_local_px', 'cell_ID') + spatloc_newnames = c('sdimx', 'sdimy', 'cell_ID') + data.table::setnames(spatlocs, old = spatloc_oldnames, new = spatloc_newnames) + data.table::setnames(spatlocs_fov, old = spatloc_oldnames_fov, new = spatloc_newnames) + + # cleanup metadata and spatlocs + metadata = metadata[,c('CenterX_global_px', 'CenterY_global_px', 'CenterX_local_px', 'CenterY_local_px') := NULL] + # find unique cell_IDs present in both expression and metadata + giotto_cell_ID = unique(intersect(expr_mat$cell_ID, metadata$cell_ID)) + + # subset to only unique cell_IDs + expr_mat = expr_mat[cell_ID %in% giotto_cell_ID,] + metadata = metadata[cell_ID %in% giotto_cell_ID,] + + + # convert protein metadata to expr mat + # take all mean intensity protein information except for MembraneStain and DAPI + protein_meta_cols = colnames(metadata) + protein_meta_cols = protein_meta_cols[grepl(pattern = 'Mean.*', x = protein_meta_cols)] + protein_meta_cols = protein_meta_cols[!protein_meta_cols %in% c('Mean.MembraneStain', 'Mean.DAPI')] + protein_meta_cols = c('cell_ID', protein_meta_cols) + + prot_expr = metadata[, protein_meta_cols, with = FALSE] + prot_cell_ID = metadata[, cell_ID] + protM = Matrix::Matrix(as.matrix(prot_expr[,-1]), dimnames = list(prot_expr[[1]], colnames(prot_expr[,-1])), sparse = FALSE) + protM = t_flex(protM) + + # convert expression to sparse matrix + spM = Matrix::Matrix(as.matrix(expr_mat[,-1]), dimnames = list(expr_mat[[1]], colnames(expr_mat[,-1])), sparse = TRUE) + spM = t_flex(spM) + + ## Ready for downstream aggregate gobject creation or appending into existing subcellular Giotto object ## + + data_list = list( + 'spatlocs' = spatlocs, + 'spatlocs_fov' = spatlocs_fov, + 'metadata' = metadata, + 'protM' = protM, + 'spM' = spM, + 'fov_shifts' = fov_shifts + ) + + return(data_list) + +} + + + + + + + +## Xenium #### + +#' @title Load xenium data from folder +#' @name load_xenium_folder +#' @param path_list list of full filepaths from read_xenium_folder +#' @inheritParams createGiottoXeniumObject +#' @keywords internal +#' @return list of loaded in xenium data +load_xenium_folder = function(path_list, + load_format = 'csv', + data_to_use = 'subcellular', + h5_expression = 'FALSE', + h5_gene_ids = 'symbols', + gene_column_index = 1, + cores, + verbose = TRUE) { + + if(load_format == 'csv') { + data_list = load_xenium_folder_csv(path_list = path_list, + data_to_use = data_to_use, + h5_expression = h5_expression, + h5_gene_ids = h5_gene_ids, + gene_column_index = gene_column_index, + cores = cores, + verbose = verbose) + } + + if(load_format == 'parquet') { + data_list = load_xenium_folder_parquet(path_list = path_list, + data_to_use = data_to_use, + h5_expression = h5_expression, + h5_gene_ids = h5_gene_ids, + gene_column_index = gene_column_index, + cores = cores, + verbose = verbose) + } + + if(load_format == 'zarr') { + # TODO + } + + + return(data_list) +} + + +#' @describeIn load_xenium_folder Load from csv files +#' @keywords internal +load_xenium_folder_csv = function(path_list, + cores, + data_to_use = 'subcellular', + h5_expression = FALSE, + h5_gene_ids = 'symbols', + gene_column_index = 1, + verbose = TRUE) { + + # initialize return vars + feat_meta = tx_dt = bound_dt_list = cell_meta = agg_expr = NULL + + if(isTRUE(verbose)) message('Loading feature metadata...') + feat_meta = data.table::fread(path_list$panel_meta_path[[1]], nThread = cores) + colnames(feat_meta)[[1]] = 'feat_ID' + + # **** subcellular info **** + if(data_to_use == 'subcellular') { + # append missing QC probe info to feat_meta + if(isTRUE(h5_expression)) { + h5 = hdf5r::H5File$new(path_list$agg_expr_path) + tryCatch({ + root = names(h5) + feature_id = h5[[paste0(root, "/features/id")]][] + feature_info = h5[[paste0(root,"/features/feature_type")]][] + feature_names = h5[[paste0(root, "/features/name")]][] + features_dt = data.table::data.table( + 'id' = feature_id, + 'name' = feature_names, + 'feature_type' = feature_info + ) + }, finally = { + h5$close_all() + }) + } else { + features_dt = data.table::fread(paste0(path_list$agg_expr_path, '/features.tsv.gz'), header = F) + } + colnames(features_dt) = c('id', 'feat_ID', 'feat_class') + feat_meta = merge(features_dt[,c(2,3)], feat_meta, all.x = TRUE, by = 'feat_ID') + + if(isTRUE(verbose)) message('Loading transcript level info...') + tx_dt = data.table::fread(path_list$tx_path[[1]], nThread = cores) + data.table::setnames(x = tx_dt, + old = c('feature_name', 'x_location', 'y_location'), + new = c('feat_ID', 'x', 'y')) + if(isTRUE(verbose)) message('Loading boundary info...') + bound_dt_list = lapply(path_list$bound_paths, function(x) data.table::fread(x[[1]], nThread = cores)) + } + + # **** aggregate info **** + if(isTRUE(verbose)) message('Loading cell metadata...') + cell_meta = data.table::fread(path_list$cell_meta_path[[1]], nThread = cores) + + if(data_to_use == 'aggregate') { + if(isTRUE(verbose)) message('Loading aggregated expression...') + if(isTRUE(h5_expression)) agg_expr = get10Xmatrix_h5(path_to_data = path_list$agg_expr_path, + gene_ids = h5_gene_ids, + remove_zero_rows = TRUE, + split_by_type = TRUE) + else agg_expr = get10Xmatrix(path_to_data = path_list$agg_expr_path, + gene_column_index = gene_column_index, + remove_zero_rows = TRUE, + split_by_type = TRUE) + } + + data_list = list( + 'feat_meta' = feat_meta, + 'tx_dt' = tx_dt, + 'bound_dt_list' = bound_dt_list, + 'cell_meta' = cell_meta, + 'agg_expr' = agg_expr + ) + + return(data_list) + +} + + + + +#' @describeIn load_xenium_folder Load from parquet files +#' @keywords internal +load_xenium_folder_parquet = function(path_list, + cores, + data_to_use = 'subcellular', + h5_expression = FALSE, + h5_gene_ids = 'symbols', + gene_column_index = 1, + verbose = TRUE) { + + # initialize return vars + feat_meta = tx_dt = bound_dt_list = cell_meta = agg_expr = NULL + # dplyr variable + cell_id = NULL + + if(isTRUE(verbose)) message('Loading feature metadata...') + feat_meta = data.table::fread(path_list$panel_meta_path[[1]], nThread = cores) + colnames(feat_meta)[[1]] = 'feat_ID' + + # **** subcellular info **** + if(data_to_use == 'subcellular') { + + # define for data.table + transcript_id = feature_name = NULL + + # append missing QC probe info to feat_meta + if(isTRUE(h5_expression)) { + h5 = hdf5r::H5File$new(path_list$agg_expr_path) + tryCatch({ + root = names(h5) + feature_id = h5[[paste0(root, "/features/id")]][] + feature_info = h5[[paste0(root,"/features/feature_type")]][] + feature_names = h5[[paste0(root, "/features/name")]][] + features_dt = data.table::data.table( + 'id' = feature_id, + 'name' = feature_names, + 'feature_type' = feature_info + ) + }, finally = { + h5$close_all() + }) + } else { + features_dt = arrow::read_tsv_arrow(paste0(path_list$agg_expr_path, '/features.tsv.gz'), + col_names = FALSE) %>% + data.table::setDT() + } + colnames(features_dt) = c('id', 'feat_ID', 'feat_class') + feat_meta = merge(features_dt[,c(2,3)], feat_meta, all.x = TRUE, by = 'feat_ID') + + if(isTRUE(verbose)) message('Loading transcript level info...') + tx_dt = arrow::read_parquet(file = path_list$tx_path[[1]], as_data_frame = FALSE) %>% + dplyr::mutate(transcript_id = cast(transcript_id, arrow::string())) %>% + dplyr::mutate(cell_id = cast(cell_id, arrow::string())) %>% + dplyr::mutate(feature_name = cast(feature_name, arrow::string())) %>% + as.data.frame() %>% + data.table::setDT() + data.table::setnames(x = tx_dt, + old = c('feature_name', 'x_location', 'y_location'), + new = c('feat_ID', 'x', 'y')) + if(isTRUE(verbose)) message('Loading boundary info...') + bound_dt_list = lapply(path_list$bound_paths, function(x) { + arrow::read_parquet(file = x[[1]], as_data_frame = FALSE) %>% + dplyr::mutate(cell_id = cast(cell_id, arrow::string())) %>% + as.data.frame() %>% + data.table::setDT()}) + } + # **** aggregate info **** + if(data_to_use == 'aggregate') { + if(isTRUE(verbose)) message('Loading cell metadata...') + cell_meta = arrow::read_parquet(file = path_list$cell_meta_path[[1]], as_data_frame = FALSE) %>% + dplyr::mutate(cell_id = cast(cell_id, arrow::string())) %>% + as.data.frame() %>% + data.table::setDT() + + # NOTE: no parquet for agg_expr. + if(isTRUE(verbose)) message('Loading aggregated expression...') + if(isTRUE(h5_expression)) agg_expr = get10Xmatrix_h5(path_to_data = path_list$agg_expr_path, + gene_ids = h5_gene_ids, + remove_zero_rows = TRUE, + split_by_type = TRUE) + else agg_expr = get10Xmatrix(path_to_data = path_list$agg_expr_path, + gene_column_index = gene_column_index, + remove_zero_rows = TRUE, + split_by_type = TRUE) + } + + data_list = list( + 'feat_meta' = feat_meta, + 'tx_dt' = tx_dt, + 'bound_dt_list' = bound_dt_list, + 'cell_meta' = cell_meta, + 'agg_expr' = agg_expr + ) + + return(data_list) + +} diff --git a/R/convenience_create.R b/R/convenience_create.R index 45b1cb830..a57be6290 100644 --- a/R/convenience_create.R +++ b/R/convenience_create.R @@ -128,6 +128,7 @@ read_data_folder = function(spat_method = NULL, #' to use for object creation #' @param FOVs which FOVs to use when building the subcellular object. (default is NULL) #' NULL loads all FOVs (very slow) +#' @param polygon_feat_types which Vizgen polygon z slices are loaded (There are 0 - 6) #' @param calculate_overlap whether to run \code{\link{calculateOverlapRaster}} #' @param overlap_to_matrix whether to run \code{\link{overlapToMatrix}} #' @param aggregate_stack whether to run \code{\link{aggregateStacks}} @@ -149,6 +150,7 @@ read_data_folder = function(spat_method = NULL, createGiottoMerscopeObject = function(merscope_dir, data_to_use = c('subcellular', 'aggregate'), FOVs = NULL, + polygon_feat_types = 0:6, calculate_overlap = TRUE, overlap_to_matrix = TRUE, aggregate_stack = TRUE, @@ -176,7 +178,8 @@ createGiottoMerscopeObject = function(merscope_dir, # 2. load in directory items data_list = load_merscope_folder(dir_items = dir_items, data_to_use = data_to_use, - fovs = fovs, + FOVs = FOVs, + polygon_feat_types = polygon_feat_types, cores = cores, verbose = verbose) @@ -188,12 +191,14 @@ createGiottoMerscopeObject = function(merscope_dir, overlap_to_matrix = overlap_to_matrix, aggregate_stack = aggregate_stack, aggregate_stack_param = aggregate_stack_param, + instructions = instructions, cores = cores, verbose = verbose) } else if(data_to_use == 'aggregate') { merscope_gobject = createGiottoMerscopeObject_aggregate(data_list = data_list, + instructions = instructions, cores = cores, verbose = verbose) @@ -218,11 +223,15 @@ createGiottoMerscopeObject_subcellular = function(data_list, aggregate_stack_param = list(summarize_expression = 'sum', summarize_locations = 'mean', new_spat_unit = 'cell'), + instructions, cores = NA, verbose = TRUE) { + # data.table vars + feat_coord = neg_coord = cellLabel_dir = NULL + # unpack data_list - poly_info = data_list$poly_info + poly_info = data_list$poly_info # expected to be list of giottoPolygons tx_dt = data_list$tx_dt micronToPixelScale = data_list$micronToPixelScale image_list = data_list$images @@ -255,7 +264,7 @@ createGiottoMerscopeObject_subcellular = function(data_list, z_sub = createGiottoObjectSubcellular( gpoints = list('rna' = feat_coord, 'neg_probe' = neg_coord), - gpolygons = list('cell' = cellLabel_dir), + gpolygons = poly_info, polygon_mask_list_params = list( mask_method = 'guess', flip_vertical = TRUE, @@ -275,6 +284,7 @@ createGiottoMerscopeObject_subcellular = function(data_list, #' @param data_list list of loaded data from \code{\link{load_merscope_folder}} #' @keywords internal createGiottoMerscopeObject_aggregate = function(data_list, + instructions = NULL, cores = NA, verbose = TRUE) { @@ -352,7 +362,8 @@ createGiottoMerscopeObject_aggregate = function(data_list, #' #' createGiottoCosMxObject = function(cosmx_dir = NULL, - data_to_use = c('all','subcellular','aggregate'), + # data_to_use = c('subcellular','aggregate','all'), + data_to_use = c('subcellular'), FOVs = NULL, instructions = NULL, cores = NA, @@ -364,7 +375,8 @@ createGiottoCosMxObject = function(cosmx_dir = NULL, data.table::setDTthreads(threads = cores) # determine data to use - data_to_use = match.arg(arg = data_to_use, choices = c('all','subcellular','aggregate')) + data_to_use = match.arg(arg = data_to_use, choices = c('subcellular')) + # data_to_use = match.arg(arg = data_to_use, choices = c('subcellular','aggregate','all')) # Define for data.table fov = target = x_local_px = y_local_px = z = cell_ID = CenterX_global_px = CenterY_global_px = @@ -434,6 +446,9 @@ createGiottoCosMxObject_subcellular = function(dir_items, verbose = TRUE, instructions = NULL) { + # data.table vars + target = fov = NULL + # load tx detections and FOV offsets data_list = load_cosmx_folder_subcellular(dir_items = dir_items, FOVs = FOVs, @@ -602,6 +617,9 @@ createGiottoCosMxObject_aggregate = function(dir_items, cores = cores, verbose = verbose) + # data.table vars + fov = NULL + # unpack data_list spatlocs = data_list$spatlocs spatlocs_fov = data_list$spatlocs_fov @@ -612,36 +630,34 @@ createGiottoCosMxObject_aggregate = function(dir_items, # create standard gobject from aggregate matrix - if(data_to_use == 'aggregate') { - # Create aggregate gobject - if(isTRUE(verbose)) message('Building giotto object...') - cosmx_gobject = createGiottoObject(expression = list('raw' = spM, 'protein' = protM), - cell_metadata = list('cell' = list('rna' = metadata, - 'protein' = metadata)), - spatial_locs = spatlocs, - instructions = instructions, - cores = cores) + # Create aggregate gobject + if(isTRUE(verbose)) message('Building giotto object...') + cosmx_gobject = createGiottoObject(expression = list('raw' = spM, 'protein' = protM), + cell_metadata = list('cell' = list('rna' = metadata, + 'protein' = metadata)), + spatial_locs = spatlocs, + instructions = instructions, + cores = cores) - # load in images - img_ID = data.table::data.table(fov = fov_shifts[, fov], - img_name = paste0('fov', sprintf('%03d', fov_shifts[, fov]), '-image')) + # load in images + img_ID = data.table::data.table(fov = fov_shifts[, fov], + img_name = paste0('fov', sprintf('%03d', fov_shifts[, fov]), '-image')) - if(isTRUE(verbose)) message('Attaching image files...') - composite_dir = Sys.glob(paths = file.path(dir_items$`CellComposite folder`, paste0('/*'))) - cellLabel_dir = Sys.glob(paths = file.path(dir_items$`CellLabels folder`, paste0('/*'))) - compartmentLabel_dir = Sys.glob(paths = file.path(dir_items$`CompartmentLabels folder`, paste0('/*'))) - overlay_dir = Sys.glob(paths = file.path(dir_items$`CellOverlay folder`, paste0('/*'))) + if(isTRUE(verbose)) message('Attaching image files...') + composite_dir = Sys.glob(paths = file.path(dir_items$`CellComposite folder`, paste0('/*'))) + cellLabel_dir = Sys.glob(paths = file.path(dir_items$`CellLabels folder`, paste0('/*'))) + compartmentLabel_dir = Sys.glob(paths = file.path(dir_items$`CompartmentLabels folder`, paste0('/*'))) + overlay_dir = Sys.glob(paths = file.path(dir_items$`CellOverlay folder`, paste0('/*'))) - if(length(cellLabel_imgList) > 0) cellLabel_imgList = lapply(cellLabel_dir, function(x) {createGiottoLargeImage(x,name = 'cellLabel',negative_y = TRUE)}) - if(length(composite_imgList) > 0) composite_imgList = lapply(composite_dir, function(x) {createGiottoLargeImage(x,name = 'composite',negative_y = TRUE)}) - if(length(compartmentLabel_dir) > 0) compartmentLabel_imgList = lapply(compartmentLabel_dir, function(x) {createGiottoLargeImage(x,name = 'composite',negative_y = TRUE)}) - if(length(overlay_dir) > 0) overlay_imgList = lapply(overlay_dir, function(x) {createGiottoLargeImage(x,name = 'composite',negative_y = TRUE)}) + if(length(cellLabel_imgList) > 0) cellLabel_imgList = lapply(cellLabel_dir, function(x) {createGiottoLargeImage(x,name = 'cellLabel',negative_y = TRUE)}) + if(length(composite_imgList) > 0) composite_imgList = lapply(composite_dir, function(x) {createGiottoLargeImage(x,name = 'composite',negative_y = TRUE)}) + if(length(compartmentLabel_dir) > 0) compartmentLabel_imgList = lapply(compartmentLabel_dir, function(x) {createGiottoLargeImage(x,name = 'composite',negative_y = TRUE)}) + if(length(overlay_dir) > 0) overlay_imgList = lapply(overlay_dir, function(x) {createGiottoLargeImage(x,name = 'composite',negative_y = TRUE)}) - } } @@ -1370,7 +1386,8 @@ read_xenium_folder = function(xenium_dir, #' @return list of loaded-in MERSCOPE data load_merscope_folder = function(dir_items, data_to_use, - fovs = NULL, + FOVs = NULL, + polygon_feat_types = 0:6, cores = NA, verbose = TRUE) { @@ -1378,7 +1395,8 @@ load_merscope_folder = function(dir_items, if(data_to_use == 'subcellular') { data_list = load_merscope_folder_subcellular(dir_items = dir_items, data_to_use = data_to_use, - fovs = fovs, + FOVs = FOVs, + polygon_feat_types = polygon_feat_types, cores = cores, verbose = verbose) } else if(data_to_use == 'aggregate') { @@ -1428,18 +1446,19 @@ load_merscope_folder = function(dir_items, #' @keywords internal load_merscope_folder_subcellular = function(dir_items, data_to_use, + polygon_feat_types = 0:6, cores = NA, verbose = TRUE, - fovs = NULL) { + FOVs = NULL) { if(isTRUE(verbose)) wrap_msg('Loading transcript level info...') - if(is.null(fovs)) { + if(is.null(FOVs)) { tx_dt = data.table::fread(dir_items$`raw transcript info`, nThread = cores) } else { if(isTRUE(verbose)) wrap_msg('Selecting FOV subset transcripts') tx_dt = fread_colmatch(file = dir_items$`raw transcript info`, col = 'fov', - values_to_match = fovs, + values_to_match = FOVs, verbose = FALSE, nThread = cores) } @@ -1448,9 +1467,9 @@ load_merscope_folder_subcellular = function(dir_items, if(isTRUE(verbose)) wrap_msg('Loading polygon info...') poly_info = readPolygonFilesVizgenHDF5(boundaries_path = dir_items$`boundary info`, - polygon_feat_types = c(0,6), + polygon_feat_types = polygon_feat_types, flip_y_axis = TRUE, - fovs = fovs) + fovs = FOVs) data_list = list( 'poly_info' = poly_info, diff --git a/R/generics.R b/R/generics.R index a3a902507..17dfa8eb4 100644 --- a/R/generics.R +++ b/R/generics.R @@ -172,7 +172,7 @@ setMethod('copy', signature(x = 'coordDataDT'), function(x) { #' @description access and set provenance slot of S4 subobject #' @param x a Giotto S4 class subobject #' @param value value to set as provenance -#' @aliases prov +#' @aliases prov prov<- #' @include classes.R #' @export setGeneric('prov', function(x) standardGeneric('prov')) @@ -200,7 +200,7 @@ setMethod('prov<-', signature = 'provData', function(x, value) { #' @description access and set spat_unit slot of S4 subobject #' @param x a Giotto S4 class subobject with spatial unit #' @param value value to set as spatial unit -#' @aliases spatUnit +#' @aliases spatUnit spatUnit<- #' @include classes.R #' @export setGeneric('spatUnit', function(x) standardGeneric('spatUnit')) @@ -228,7 +228,7 @@ setMethod('spatUnit<-', signature = 'spatData', function(x, value) { #' @description access and set feat_type slot of S4 subobject #' @param x a Giotto S4 class subobject with feature type #' @param value value to set as feature type -#' @aliases featType +#' @aliases featType featType<- #' @include classes.R #' @export setGeneric('featType', function(x) standardGeneric('featType')) @@ -253,7 +253,9 @@ setMethod('featType<-', signature = 'featData', function(x, value) { #' @title Extract or replace parts of an object -#' @name extract-generic +#' @name extract-methods +#' @docType methods +#' @aliases `[` `[<-` `$` `$<-` #' @description Operators Giotto S4 internal data.tables to extract #' or replace parts. #' @param x Giotto S4 object to extract columns from @@ -266,14 +268,14 @@ setMethod('featType<-', signature = 'featData', function(x, value) { #' @section \code{`$<-`} methods: #' @section \code{`[`} methods: #' @section \code{`[<-`} methods: -#' TODO +#' NULL # $ S4 access generic #### ## * coordDataDT #### -#' @rdname extract-generic +#' @rdname extract-methods #' @section \code{`$`} methods: #' Select by colname from giotto S4 data.table coordinates slot. #' @export @@ -281,7 +283,7 @@ setMethod('$', signature(x = 'coordDataDT'), function(x, name) x@coordinates[[name]]) -#' @rdname extract-generic +#' @rdname extract-methods #' @section \code{`$<-`} methods: #' Set values by colname into giotto S4 data.table coordinates slot. #' Works via data.table methods @@ -295,7 +297,7 @@ setMethod('$<-', signature(x = 'coordDataDT'), ## * metaData #### -#' @rdname extract-generic +#' @rdname extract-methods #' @section \code{`$`} methods: #' Select by colname from giotto S4 data.table metaDT slot. #' @export @@ -303,7 +305,7 @@ setMethod('$', signature(x = 'metaData'), function(x, name) x@metaDT[[name]]) -#' @rdname extract-generic +#' @rdname extract-methods #' @section \code{`$<-`} methods: #' Set values by colname into giotto S4 data.table metaDT slot. #' Works via data.table methods @@ -320,7 +322,9 @@ setMethod('$<-', signature(x = 'metaData'), ## * coordDataDT #### -#' @rdname extract-generic + + +#' @rdname extract-methods #' @section \code{`[`} methods: #' Select rows (i) and cols (j) from giotto S4 coordinates slot #' @export @@ -330,7 +334,7 @@ setMethod('[', signature(x = 'coordDataDT', i = 'missing', j = 'ANY', drop = 'mi x }) -#' @rdname extract-generic +#' @rdname extract-methods #' @export setMethod('[', signature(x = 'coordDataDT', i = 'ANY', j = 'missing', drop = 'missing'), function(x, i, j) { @@ -338,7 +342,7 @@ setMethod('[', signature(x = 'coordDataDT', i = 'ANY', j = 'missing', drop = 'mi x }) -#' @rdname extract-generic +#' @rdname extract-methods #' @export setMethod('[', signature(x = 'coordDataDT', i = 'ANY', j = 'ANY', drop = 'missing'), function(x, i, j) { @@ -346,7 +350,9 @@ setMethod('[', signature(x = 'coordDataDT', i = 'ANY', j = 'ANY', drop = 'missin x }) -#' @rdname extract-generic +#' @name [ +#' @rdname extract-methods +#' @aliases [,coordDataDT,missing,missing,missing-method #' @section \code{`[`} methods: #' Return \code{coordinates} slot data.table from giotto S4 #' @export @@ -355,11 +361,13 @@ setMethod('[', signature(x = 'coordDataDT', i = 'missing', j = 'missing', drop = x@coordinates }) -#' @rdname extract-generic +#' @name [ +#' @rdname extract-methods +#' @aliases [<-,coordDataDT,missing,missing,ANY-method [<-,coordDataDT,missing,missing-method +#' @docType methods #' @section \code{`[<-`} methods: #' Assign to \code{coordinates} slot in giotto S4 -#' @export -setMethod('[<-', signature(x = 'coordDataDT', i = 'missing', j = 'missing', value = 'ANY'), +setReplaceMethod('[', signature(x = 'coordDataDT', i = 'missing', j = 'missing', value = 'ANY'), function(x, i, j, value) { x@coordinates = value x @@ -369,7 +377,7 @@ setMethod('[<-', signature(x = 'coordDataDT', i = 'missing', j = 'missing', valu ## * metaData #### -#' @rdname extract-generic +#' @rdname extract-methods #' @section \code{`[`} methods: #' Select rows (i) and cols (j) from giotto S4 metaDT slot #' @export @@ -379,7 +387,7 @@ setMethod('[', signature(x = 'metaData', i = 'missing', j = 'ANY', drop = 'missi x }) -#' @rdname extract-generic +#' @rdname extract-methods #' @export setMethod('[', signature(x = 'metaData', i = 'ANY', j = 'missing', drop = 'missing'), function(x, i, j) { @@ -387,7 +395,7 @@ setMethod('[', signature(x = 'metaData', i = 'ANY', j = 'missing', drop = 'missi x }) -#' @rdname extract-generic +#' @rdname extract-methods #' @export setMethod('[', signature(x = 'metaData', i = 'ANY', j = 'ANY', drop = 'missing'), function(x, i, j) { @@ -395,16 +403,18 @@ setMethod('[', signature(x = 'metaData', i = 'ANY', j = 'ANY', drop = 'missing') x }) -#' @rdname extract-generic +#' @rdname extract-methods #' @section \code{`[`} methods: -#' Return \code{coordinates} slot data.table from giotto S4 +#' Return \code{metaDT} slot data.table from giotto S4 #' @export setMethod('[', signature(x = 'metaData', i = 'missing', j = 'missing', drop = 'missing'), function(x, i, j) { x@metaDT }) -#' @rdname extract-generic +#' @rdname extract-methods +#' @aliases [<-,metaData,missing,missing,ANY-method [<-,metaData,missing,missing-method +#' @docType methods #' @section \code{`[<-`} methods: #' Assign to \code{metaDT} slot in giotto S4 #' @export @@ -417,7 +427,7 @@ setMethod('[<-', signature(x = 'metaData', i = 'missing', j = 'missing', value = ## * dimObj (temp) #### -#' @rdname extract-generic +#' @rdname extract-methods #' @export setMethod('[', signature(x = 'dimObj', i = 'ANY', j = 'ANY', drop = 'missing'), function(x, i, j) { @@ -425,16 +435,20 @@ setMethod('[', signature(x = 'dimObj', i = 'ANY', j = 'ANY', drop = 'missing'), x }) -#' @rdname extract-generic +#' @rdname extract-methods +#' @section \code{`[`} methods: +#' Return \code{coordinates} slot matrix from giotto S4 dimObj #' @export setMethod('[', signature(x = 'dimObj', i = 'missing', j = 'missing', drop = 'missing'), function(x, i, j) { x@coordinates }) -#' @rdname extract-generic +#' @rdname extract-methods +#' @aliases [<-,dimObj,missing,missing,ANY-method [<-,dimObj,missing,missing-method +#' @docType methods #' @section \code{`[<-`} methods: -#' Assign to \code{coordinates} slot in giotto S4 +#' Assign to \code{coordinates} slot in giotto S4 dimObj #' @export setMethod('[<-', signature(x = 'dimObj', i = 'missing', j = 'missing', value = 'ANY'), function(x, i, j, value) { @@ -444,7 +458,7 @@ setMethod('[<-', signature(x = 'dimObj', i = 'missing', j = 'missing', value = ' ## * exprData #### -#' @rdname extract-generic +#' @rdname extract-methods #' @section \code{`[`} methods: #' Select rows (i) and cols (j) from giotto S4 exprMat slot #' @export @@ -454,7 +468,7 @@ setMethod('[', signature(x = 'exprData', i = 'missing', j = 'ANY', drop = 'missi x }) -#' @rdname extract-generic +#' @rdname extract-methods #' @export setMethod('[', signature(x = 'exprData', i = 'ANY', j = 'missing', drop = 'missing'), function(x, i, j) { @@ -462,7 +476,7 @@ setMethod('[', signature(x = 'exprData', i = 'ANY', j = 'missing', drop = 'missi x }) -#' @rdname extract-generic +#' @rdname extract-methods #' @export setMethod('[', signature(x = 'exprData', i = 'ANY', j = 'ANY', drop = 'missing'), function(x, i, j) { @@ -470,7 +484,7 @@ setMethod('[', signature(x = 'exprData', i = 'ANY', j = 'ANY', drop = 'missing') x }) -#' @rdname extract-generic +#' @rdname extract-methods #' @section \code{`[`} methods: #' Return \code{exprMat} slot Matrix object from giotto S4 #' @export @@ -479,7 +493,9 @@ setMethod('[', signature(x = 'exprData', i = 'missing', j = 'missing', drop = 'm x@exprMat }) -#' @rdname extract-generic +#' @rdname extract-methods +#' @aliases [<-,exprData,missing,missing,ANY-method [<-,exprData,missing,missing-method +#' @docType methods #' @section \code{`[<-`} methods: #' Assign to \code{exprMat} slot in giotto S4 #' @export @@ -490,7 +506,7 @@ setMethod('[<-', signature(x = 'exprData', i = 'missing', j = 'missing', value = }) # * spatNetData #### -#' @rdname extract-generic +#' @rdname extract-methods #' @section \code{`[`} methods: #' Return \code{spatNetData} slot network data.table object from giotto S4 #' @export @@ -499,9 +515,11 @@ setMethod('[', signature(x = 'spatNetData', i = 'missing', j = 'missing', drop = x@networkDT }) -#' @rdname extract-generic +#' @rdname extract-methods +#' @aliases [<-,spatNetData,missing,missing,ANY-method [<-,spatNetData,missing,missing-method +#' @docType methods #' @section \code{`[<-`} methods: -#' Return \code{spatNetData} slot network data.table object from giotto S4 +#' Assign to \code{networkDT} slot in giotto S4 #' @export setMethod('[<-', signature(x = 'spatNetData', i = 'missing', j = 'missing', value = 'ANY'), function(x, i, j, value) { @@ -511,7 +529,7 @@ setMethod('[<-', signature(x = 'spatNetData', i = 'missing', j = 'missing', valu # * nnData #### -#' @rdname extract-generic +#' @rdname extract-methods #' @section \code{`[`} methods: #' Return \code{nnData} slot igraph object from giotto S4 #' @export @@ -520,9 +538,11 @@ setMethod('[', signature(x = 'nnData', i = 'missing', j = 'missing', drop = 'mis x@igraph }) -#' @rdname extract-generic +#' @rdname extract-methods +#' @aliases [<-,nnData,missing,missing,ANY-method [<-,nnData,missing,missing-method +#' @docType methods #' @section \code{`[<-`} methods: -#' Return \code{nnData} slot igraph object from giotto S4 +#' Assign to \code{igraph} slot in giotto S4 #' @export setMethod('[<-', signature(x = 'nnData', i = 'missing', j = 'missing', value = 'ANY'), function(x, i, j, value) { @@ -532,7 +552,7 @@ setMethod('[<-', signature(x = 'nnData', i = 'missing', j = 'missing', value = ' # * enrData #### -#' @rdname extract-generic +#' @rdname extract-methods #' @section \code{`[`} methods: #' Return \code{enrData} slot enrichment data.table object from giotto S4 #' @export @@ -541,9 +561,11 @@ setMethod('[', signature(x = 'enrData', i = 'missing', j = 'missing', drop = 'mi x@enrichDT }) -#' @rdname extract-generic +#' @rdname extract-methods +#' @aliases [<-,enrData,missing,missing,ANY-method [<-,enrData,missing,missing-method +#' @docType methods #' @section \code{`[<-`} methods: -#' Return \code{enrData} slot enrichment data.table object from giotto S4 +#' Assign to \code{enrichDT} slot in giotto S4 #' @export setMethod('[<-', signature(x = 'enrData', i = 'missing', j = 'missing', value = 'ANY'), function(x, i, j, value) { @@ -552,18 +574,20 @@ setMethod('[<-', signature(x = 'enrData', i = 'missing', j = 'missing', value = }) # * spatGridData #### -#' @rdname extract-generic +#' @rdname extract-methods #' @section \code{`[`} methods: -#' Return \code{spatGridData} slot enrichment data.table object from giotto S4 +#' Return \code{spatGridData} slot data.table object from giotto S4 #' @export setMethod('[', signature(x = 'spatGridData', i = 'missing', j = 'missing', drop = 'missing'), function(x, i, j) { x@gridDT }) -#' @rdname extract-generic +#' @rdname extract-methods +#' @aliases [<-,spatGridData,missing,missing,ANY-method [<-,spatGridData,missing,missing-method +#' @docType methods #' @section \code{`[<-`} methods: -#' Return \code{spatGridData} slot enrichment data.table object from giotto S4 +#' Assign to \code{gridDT} slot in giotto S4 #' @export setMethod('[<-', signature(x = 'spatGridData', i = 'missing', j = 'missing', value = 'ANY'), function(x, i, j, value) { diff --git a/R/giotto.R b/R/giotto.R index e0f1e954d..9d66bc792 100644 --- a/R/giotto.R +++ b/R/giotto.R @@ -2450,7 +2450,7 @@ createGiottoObjectSubcellular = function(gpolygons = NULL, verbose = TRUE) { # data.table vars - cell_ID = feat_ID = x = y = NULL + poly_ID = cell_ID = feat_ID = x = y = NULL # create minimum giotto gobject = giotto(expression = NULL, diff --git a/R/giotto_structures.R b/R/giotto_structures.R index 464dbf74b..65a6029a7 100644 --- a/R/giotto_structures.R +++ b/R/giotto_structures.R @@ -2119,6 +2119,9 @@ calculateOverlapPolygonImages = function(gobject, verbose = TRUE, ...) { + # data.table vars + coverage_fraction = NULL + if(is.null(image_names)) { stop('image_names = NULL, you need to provide the names of the images you want to use, see showGiottoImageNames() for attached images') diff --git a/man/createGiottoCosMxObject.Rd b/man/createGiottoCosMxObject.Rd index 80c56e389..db98a4e3c 100644 --- a/man/createGiottoCosMxObject.Rd +++ b/man/createGiottoCosMxObject.Rd @@ -1,12 +1,21 @@ % Generated by roxygen2: do not edit by hand -% Please edit documentation in R/convenience_create.R +% Please edit documentation in R/convenience.R, R/convenience_create.R \name{createGiottoCosMxObject} \alias{createGiottoCosMxObject} \title{Create Nanostring CosMx Giotto Object} \usage{ createGiottoCosMxObject( cosmx_dir = NULL, - data_to_use = c("all", "subcellular", "aggregate"), + data_to_use = c("subcellular"), + FOVs = NULL, + instructions = NULL, + cores = NA, + verbose = TRUE +) + +createGiottoCosMxObject( + cosmx_dir = NULL, + data_to_use = c("subcellular"), FOVs = NULL, instructions = NULL, cores = NA, @@ -29,9 +38,14 @@ coordinates only. \code{'aggregate'} loads the provided aggregated expression ma \item{verbose}{be verbose when building Giotto object} } \value{ +a giotto object + a giotto object } \description{ +Given the path to a CosMx experiment directory, creates a Giotto +object. + Given the path to a CosMx experiment directory, creates a Giotto object. } @@ -61,6 +75,37 @@ where the \strong{bolded} portions are what this function matches against: spatial locations, and metadata) from exprMat_file and metadata_file.} } +[\strong{Images}] Images in the default CellComposite, CellLabels, CompartmentLabels, and CellOverlay +folders will be loaded as giotto largeImage objects in all workflows as long as they are available. +Additionally, CellComposite images will be converted to giotto image objects, making plotting with +these image objects more responsive when accessing them from a server. +\code{\link{showGiottoImageNames}} can be used to see the available images. + +[\strong{Expected Directory}] This function generates a giotto object when given a +link to a cosmx output directory. It expects the following items within the directory +where the \strong{bolded} portions are what this function matches against: +\itemize{ + \item{\strong{CellComposite} (folder of images)} + \item{\strong{CellLabels} (folder of images)} + \item{\strong{CellOverlay} (folder of images)} + \item{\strong{CompartmentLabels} (folder of images)} + \item{experimentname_\strong{exprMat_file}.csv (file)} + \item{experimentname_\strong{fov_positions_file}.csv (file)} + \item{experimentname_\strong{metadata_file}.csv (file)} + \item{experimentname_\strong{tx_file}.csv (file)} +} + +[\strong{Workflows}] Workflow to use is accessed through the data_to_use param +\itemize{ + \item{'all' - loads and requires subcellular information from tx_file and fov_positions_file + and also the existing aggregated information (expression, spatial locations, and metadata) + from exprMat_file and metadata_file.} + \item{'subcellular' - loads and requires subcellular information from tx_file and + fov_positions_file only.} + \item{'aggregate' - loads and requires the existing aggregate information (expression, + spatial locations, and metadata) from exprMat_file and metadata_file.} +} + [\strong{Images}] Images in the default CellComposite, CellLabels, CompartmentLabels, and CellOverlay folders will be loaded as giotto largeImage objects in all workflows as long as they are available. Additionally, CellComposite images will be converted to giotto image objects, making plotting with diff --git a/man/createGiottoCosMxObject_aggregate.Rd b/man/createGiottoCosMxObject_aggregate.Rd index aa1f48cf5..75dd97e65 100644 --- a/man/createGiottoCosMxObject_aggregate.Rd +++ b/man/createGiottoCosMxObject_aggregate.Rd @@ -1,9 +1,16 @@ % Generated by roxygen2: do not edit by hand -% Please edit documentation in R/convenience_create.R +% Please edit documentation in R/convenience.R, R/convenience_create.R \name{createGiottoCosMxObject_aggregate} \alias{createGiottoCosMxObject_aggregate} \title{Load and create a CosMx Giotto object from aggregate info} \usage{ +createGiottoCosMxObject_aggregate( + dir_items, + cores, + verbose = TRUE, + instructions = NULL +) + createGiottoCosMxObject_aggregate( dir_items, cores, @@ -19,6 +26,8 @@ createGiottoCosMxObject_aggregate( \item{instructions}{list of instructions or output result from \code{\link{createGiottoInstructions}}} } \description{ +Load and create a CosMx Giotto object from aggregate info + Load and create a CosMx Giotto object from aggregate info } \keyword{internal} diff --git a/man/createGiottoCosMxObject_all.Rd b/man/createGiottoCosMxObject_all.Rd index ad2a5ab14..1b3c93bae 100644 --- a/man/createGiottoCosMxObject_all.Rd +++ b/man/createGiottoCosMxObject_all.Rd @@ -1,9 +1,17 @@ % Generated by roxygen2: do not edit by hand -% Please edit documentation in R/convenience_create.R +% Please edit documentation in R/convenience.R, R/convenience_create.R \name{createGiottoCosMxObject_all} \alias{createGiottoCosMxObject_all} \title{Load and create a CosMx Giotto object from subcellular and aggregate info} \usage{ +createGiottoCosMxObject_all( + dir_items, + FOVs, + cores, + verbose = TRUE, + instructions = NULL +) + createGiottoCosMxObject_all( dir_items, FOVs, @@ -24,15 +32,25 @@ createGiottoCosMxObject_all( \item{instructions}{list of instructions or output result from \code{\link{createGiottoInstructions}}} } \description{ +Load and create a CosMx Giotto object from subcellular and aggregate info + Load and create a CosMx Giotto object from subcellular and aggregate info } \details{ +Both \emph{subcellular} (subellular transcript detection information) and +\emph{aggregate} (aggregated detection count matrices by cell polygon from NanoString) +data will be loaded in. The two will be separated into 'cell' and 'cell_agg' +spatial units in order to denote the difference in origin of the two. + Both \emph{subcellular} (subellular transcript detection information) and \emph{aggregate} (aggregated detection count matrices by cell polygon from NanoString) data will be loaded in. The two will be separated into 'cell' and 'cell_agg' spatial units in order to denote the difference in origin of the two. } \seealso{ +createGiottoCosMxObject createGiottoCosMxObject_aggregate +createGiottoCosMxObject_subcellular + createGiottoCosMxObject createGiottoCosMxObject_aggregate createGiottoCosMxObject_subcellular } diff --git a/man/createGiottoCosMxObject_subcellular.Rd b/man/createGiottoCosMxObject_subcellular.Rd index 4621359a0..ce4e95724 100644 --- a/man/createGiottoCosMxObject_subcellular.Rd +++ b/man/createGiottoCosMxObject_subcellular.Rd @@ -1,9 +1,17 @@ % Generated by roxygen2: do not edit by hand -% Please edit documentation in R/convenience_create.R +% Please edit documentation in R/convenience.R, R/convenience_create.R \name{createGiottoCosMxObject_subcellular} \alias{createGiottoCosMxObject_subcellular} \title{Load and create a CosMx Giotto object from subcellular info} \usage{ +createGiottoCosMxObject_subcellular( + dir_items, + FOVs = NULL, + cores, + verbose = TRUE, + instructions = NULL +) + createGiottoCosMxObject_subcellular( dir_items, FOVs = NULL, @@ -22,6 +30,8 @@ createGiottoCosMxObject_subcellular( \item{instructions}{list of instructions or output result from \code{\link{createGiottoInstructions}}} } \description{ +Load and create a CosMx Giotto object from subcellular info + Load and create a CosMx Giotto object from subcellular info } \keyword{internal} diff --git a/man/createGiottoMerscopeObject.Rd b/man/createGiottoMerscopeObject.Rd index 7389badff..23b97d9f0 100644 --- a/man/createGiottoMerscopeObject.Rd +++ b/man/createGiottoMerscopeObject.Rd @@ -1,5 +1,5 @@ % Generated by roxygen2: do not edit by hand -% Please edit documentation in R/convenience_create.R +% Please edit documentation in R/convenience.R, R/convenience_create.R \name{createGiottoMerscopeObject} \alias{createGiottoMerscopeObject} \alias{createGiottoMerscopeObject_subcellular} @@ -10,6 +10,7 @@ createGiottoMerscopeObject( merscope_dir, data_to_use = c("subcellular", "aggregate"), FOVs = NULL, + polygon_feat_types = 0:6, calculate_overlap = TRUE, overlap_to_matrix = TRUE, aggregate_stack = TRUE, @@ -27,11 +28,51 @@ createGiottoMerscopeObject_subcellular( aggregate_stack = TRUE, aggregate_stack_param = list(summarize_expression = "sum", summarize_locations = "mean", new_spat_unit = "cell"), + instructions, cores = NA, verbose = TRUE ) -createGiottoMerscopeObject_aggregate(data_list, cores = NA, verbose = TRUE) +createGiottoMerscopeObject_aggregate( + data_list, + instructions = NULL, + cores = NA, + verbose = TRUE +) + +createGiottoMerscopeObject( + merscope_dir, + data_to_use = c("subcellular", "aggregate"), + FOVs = NULL, + polygon_feat_types = 0:6, + calculate_overlap = TRUE, + overlap_to_matrix = TRUE, + aggregate_stack = TRUE, + aggregate_stack_param = list(summarize_expression = "sum", summarize_locations = + "mean", new_spat_unit = "cell"), + instructions = NULL, + cores = NA, + verbose = TRUE +) + +createGiottoMerscopeObject_subcellular( + data_list, + calculate_overlap = TRUE, + overlap_to_matrix = TRUE, + aggregate_stack = TRUE, + aggregate_stack_param = list(summarize_expression = "sum", summarize_locations = + "mean", new_spat_unit = "cell"), + instructions, + cores = NA, + verbose = TRUE +) + +createGiottoMerscopeObject_aggregate( + data_list, + instructions = NULL, + cores = NA, + verbose = TRUE +) } \arguments{ \item{merscope_dir}{full path to the exported merscope directory} @@ -42,6 +83,8 @@ to use for object creation} \item{FOVs}{which FOVs to use when building the subcellular object. (default is NULL) NULL loads all FOVs (very slow)} +\item{polygon_feat_types}{which Vizgen polygon z slices are loaded (There are 0 - 6)} + \item{calculate_overlap}{whether to run \code{\link{calculateOverlapRaster}}} \item{overlap_to_matrix}{whether to run \code{\link{overlapToMatrix}}} @@ -59,13 +102,29 @@ NULL loads all FOVs (very slow)} \item{data_list}{list of loaded data from \code{\link{load_merscope_folder}}} } \value{ +a giotto object + a giotto object } \description{ +Given the path to a MERSCOPE experiment directory, creates a Giotto +object. + Given the path to a MERSCOPE experiment directory, creates a Giotto object. } \details{ +[\strong{Expected Directory}] This function generates a giotto object when given a +link to a MERSCOPE output directory. It expects the following items within the directory +where the \strong{bolded} portions are what this function matches against: +\itemize{ + \item{\strong{cell_boundaries} (folder .hdf5 files)} + \item{\strong{images} (folder of .tif images and a scalefactor/transfrom table)} + \item{\strong{cell_by_gene}.csv (file)} + \item{cell_metadata\strong{fov_positions_file}.csv (file)} + \item{detected_transcripts\strong{metadata_file}.csv (file)} +} + [\strong{Expected Directory}] This function generates a giotto object when given a link to a MERSCOPE output directory. It expects the following items within the directory where the \strong{bolded} portions are what this function matches against: @@ -83,5 +142,9 @@ where the \strong{bolded} portions are what this function matches against: \item \code{createGiottoMerscopeObject_aggregate()}: Create giotto object with 'aggregate' workflow +\item \code{createGiottoMerscopeObject_subcellular()}: Create giotto object with 'subcellular' workflow + +\item \code{createGiottoMerscopeObject_aggregate()}: Create giotto object with 'aggregate' workflow + }} \keyword{internal} diff --git a/man/createGiottoXeniumObject.Rd b/man/createGiottoXeniumObject.Rd index 0c6943241..f760e8918 100644 --- a/man/createGiottoXeniumObject.Rd +++ b/man/createGiottoXeniumObject.Rd @@ -1,9 +1,24 @@ % Generated by roxygen2: do not edit by hand -% Please edit documentation in R/convenience_create.R +% Please edit documentation in R/convenience.R, R/convenience_create.R \name{createGiottoXeniumObject} \alias{createGiottoXeniumObject} \title{Create 10x Xenium Giotto Object} \usage{ +createGiottoXeniumObject( + xenium_dir, + data_to_use = c("subcellular", "aggregate"), + load_format = "csv", + h5_expression = TRUE, + h5_gene_ids = c("symbols", "ensembl"), + gene_column_index = 1, + bounds_to_load = c("cell"), + qv_threshold = 20, + key_list = NULL, + instructions = NULL, + cores = NA, + verbose = TRUE +) + createGiottoXeniumObject( xenium_dir, data_to_use = c("subcellular", "aggregate"), @@ -53,6 +68,9 @@ feature detections by feature type. See details} \item{verbose}{be verbose when building Giotto object} } \description{ +Given the path to a Xenium experiment output folder, creates a Giotto +object + Given the path to a Xenium experiment output folder, creates a Giotto object } @@ -82,6 +100,34 @@ Default list: neg_probe = c('NegControlProbe_|antisense_')) } +The Gene expression subset is accepted as the subset of feat_IDs that do not +map to any of the keys. + +[\strong{QC feature types}] +Xenium provides info on feature detections that include more than only the +Gene Expression specific probes. Additional probes for QC are included: +\emph{blank codeword}, \emph{negative control codeword}, and +\emph{negative control probe}. These additional QC probes each occupy and are treated +as their own feature types so that they can largely remain independent of the +gene expression information. + +[\strong{key_list}] +Related to \code{data_to_use = 'subcellular'} workflow only: +Additional QC probe information is in the subcellular feature detections information +and must be separated from the gene expression information during processing. +The QC probes have prefixes that allow them to be selected from the rest of the +feature IDs. +Giotto uses a named list of keywords (\code{key_list}) to select these QC probes, +with the list names being the names that will be assigned as the feature type +of these feature detections. The default list is used when \code{key_list} = NULL. + +Default list: +\preformatted{ + list(blank_code = 'BLANK_', + neg_code = 'NegControlCodeword_', + neg_probe = c('NegControlProbe_|antisense_')) +} + The Gene expression subset is accepted as the subset of feat_IDs that do not map to any of the keys. } diff --git a/man/createGiottoXeniumObject_aggregate.Rd b/man/createGiottoXeniumObject_aggregate.Rd index a414df3b9..076143fcf 100644 --- a/man/createGiottoXeniumObject_aggregate.Rd +++ b/man/createGiottoXeniumObject_aggregate.Rd @@ -1,9 +1,16 @@ % Generated by roxygen2: do not edit by hand -% Please edit documentation in R/convenience_create.R +% Please edit documentation in R/convenience.R, R/convenience_create.R \name{createGiottoXeniumObject_aggregate} \alias{createGiottoXeniumObject_aggregate} \title{Create a Xenium Giotto object from aggregate info} \usage{ +createGiottoXeniumObject_aggregate( + data_list, + instructions = NULL, + cores = NA, + verbose = TRUE +) + createGiottoXeniumObject_aggregate( data_list, instructions = NULL, @@ -21,9 +28,13 @@ createGiottoXeniumObject_aggregate( \item{verbose}{be verbose when building Giotto object} } \description{ +Aggregate workflow for createGiottoXeniumObject + Aggregate workflow for createGiottoXeniumObject } \seealso{ +createGiottoXeniumObject createGiottoXeniumObject_subcellular + createGiottoXeniumObject createGiottoXeniumObject_subcellular } \keyword{internal} diff --git a/man/createGiottoXeniumObject_subcellular.Rd b/man/createGiottoXeniumObject_subcellular.Rd index 9c5dadc12..e9b8ddf4a 100644 --- a/man/createGiottoXeniumObject_subcellular.Rd +++ b/man/createGiottoXeniumObject_subcellular.Rd @@ -1,9 +1,18 @@ % Generated by roxygen2: do not edit by hand -% Please edit documentation in R/convenience_create.R +% Please edit documentation in R/convenience.R, R/convenience_create.R \name{createGiottoXeniumObject_subcellular} \alias{createGiottoXeniumObject_subcellular} \title{Create a Xenium Giotto object from subcellular info} \usage{ +createGiottoXeniumObject_subcellular( + data_list, + key_list = NULL, + qv_threshold = 20, + instructions = NULL, + cores = NA, + verbose = TRUE +) + createGiottoXeniumObject_subcellular( data_list, key_list = NULL, @@ -29,9 +38,13 @@ a subcellular transcript detection (default = 20)} \item{verbose}{be verbose when building Giotto object} } \description{ +Subcellular workflow for createGiottoXeniumObject + Subcellular workflow for createGiottoXeniumObject } \seealso{ +createGiottoXeniumObject createGiottoXeniumObject_aggregate + createGiottoXeniumObject createGiottoXeniumObject_aggregate } \keyword{internal} diff --git a/man/create_pb.Rd b/man/create_pb.Rd deleted file mode 100644 index 0f5025b7a..000000000 --- a/man/create_pb.Rd +++ /dev/null @@ -1,12 +0,0 @@ -% Generated by roxygen2: do not edit by hand -% Please edit documentation in R/utilities.R -\name{create_pb} -\alias{create_pb} -\title{Create a txt progressbar} -\usage{ -create_pb(max, min = 0, width = min(35, getOption("width")), char = "=") -} -\description{ -Create a txt progressbar -} -\keyword{internal} diff --git a/man/extract-generic.Rd b/man/extract-methods.Rd similarity index 83% rename from man/extract-generic.Rd rename to man/extract-methods.Rd index 50666c70f..a347e8374 100644 --- a/man/extract-generic.Rd +++ b/man/extract-methods.Rd @@ -1,7 +1,12 @@ % Generated by roxygen2: do not edit by hand % Please edit documentation in R/generics.R -\name{extract-generic} -\alias{extract-generic} +\docType{methods} +\name{extract-methods} +\alias{extract-methods} +\alias{`[`} +\alias{`[<-`} +\alias{`$`} +\alias{`$<-`} \alias{$,coordDataDT-method} \alias{$<-,coordDataDT-method} \alias{$,metaData-method} @@ -9,29 +14,38 @@ \alias{[,coordDataDT,missing,ANY,missing-method} \alias{[,coordDataDT,ANY,missing,missing-method} \alias{[,coordDataDT,ANY,ANY,missing-method} +\alias{[} \alias{[,coordDataDT,missing,missing,missing-method} \alias{[<-,coordDataDT,missing,missing,ANY-method} +\alias{[<-,coordDataDT,missing,missing-method} \alias{[,metaData,missing,ANY,missing-method} \alias{[,metaData,ANY,missing,missing-method} \alias{[,metaData,ANY,ANY,missing-method} \alias{[,metaData,missing,missing,missing-method} \alias{[<-,metaData,missing,missing,ANY-method} +\alias{[<-,metaData,missing,missing-method} \alias{[,dimObj,ANY,ANY,missing-method} \alias{[,dimObj,missing,missing,missing-method} \alias{[<-,dimObj,missing,missing,ANY-method} +\alias{[<-,dimObj,missing,missing-method} \alias{[,exprData,missing,ANY,missing-method} \alias{[,exprData,ANY,missing,missing-method} \alias{[,exprData,ANY,ANY,missing-method} \alias{[,exprData,missing,missing,missing-method} \alias{[<-,exprData,missing,missing,ANY-method} +\alias{[<-,exprData,missing,missing-method} \alias{[,spatNetData,missing,missing,missing-method} \alias{[<-,spatNetData,missing,missing,ANY-method} +\alias{[<-,spatNetData,missing,missing-method} \alias{[,nnData,missing,missing,missing-method} \alias{[<-,nnData,missing,missing,ANY-method} +\alias{[<-,nnData,missing,missing-method} \alias{[,enrData,missing,missing,missing-method} \alias{[<-,enrData,missing,missing,ANY-method} +\alias{[<-,enrData,missing,missing-method} \alias{[,spatGridData,missing,missing,missing-method} \alias{[<-,spatGridData,missing,missing,ANY-method} +\alias{[<-,spatGridData,missing,missing-method} \title{Extract or replace parts of an object} \usage{ \S4method{$}{coordDataDT}(x, name) @@ -144,7 +158,10 @@ or replace parts. Select rows (i) and cols (j) from giotto S4 metaDT slot - Return \code{coordinates} slot data.table from giotto S4 + Return \code{metaDT} slot data.table from giotto S4 + + + Return \code{coordinates} slot matrix from giotto S4 dimObj Select rows (i) and cols (j) from giotto S4 exprMat slot @@ -162,12 +179,11 @@ or replace parts. Return \code{enrData} slot enrichment data.table object from giotto S4 - Return \code{spatGridData} slot enrichment data.table object from giotto S4 + Return \code{spatGridData} slot data.table object from giotto S4 } \section{\code{`[<-`} methods}{ - TODO Assign to \code{coordinates} slot in giotto S4 @@ -176,21 +192,21 @@ or replace parts. Assign to \code{metaDT} slot in giotto S4 - Assign to \code{coordinates} slot in giotto S4 + Assign to \code{coordinates} slot in giotto S4 dimObj Assign to \code{exprMat} slot in giotto S4 - Return \code{spatNetData} slot network data.table object from giotto S4 + Assign to \code{networkDT} slot in giotto S4 - Return \code{nnData} slot igraph object from giotto S4 + Assign to \code{igraph} slot in giotto S4 - Return \code{enrData} slot enrichment data.table object from giotto S4 + Assign to \code{enrichDT} slot in giotto S4 - Return \code{spatGridData} slot enrichment data.table object from giotto S4 + Assign to \code{gridDT} slot in giotto S4 } diff --git a/man/featType-generic.Rd b/man/featType-generic.Rd index b1c26a4e7..bd1556ffa 100644 --- a/man/featType-generic.Rd +++ b/man/featType-generic.Rd @@ -3,6 +3,7 @@ \name{featType-generic} \alias{featType-generic} \alias{featType} +\alias{featType<-} \alias{featType,featData-method} \alias{featType<-,featData-method} \title{Feature type information} diff --git a/man/fread_colmatch.Rd b/man/fread_colmatch.Rd index 7cdc75b2a..523d27bef 100644 --- a/man/fread_colmatch.Rd +++ b/man/fread_colmatch.Rd @@ -1,5 +1,5 @@ % Generated by roxygen2: do not edit by hand -% Please edit documentation in R/utilities.R +% Please edit documentation in R/general_help.R \name{fread_colmatch} \alias{fread_colmatch} \title{Fread rows based on column matches} diff --git a/man/load_cosmx_folder_aggregate.Rd b/man/load_cosmx_folder_aggregate.Rd index cad49acca..e6ba5b9c2 100644 --- a/man/load_cosmx_folder_aggregate.Rd +++ b/man/load_cosmx_folder_aggregate.Rd @@ -1,9 +1,11 @@ % Generated by roxygen2: do not edit by hand -% Please edit documentation in R/convenience_create.R +% Please edit documentation in R/convenience.R, R/convenience_create.R \name{load_cosmx_folder_aggregate} \alias{load_cosmx_folder_aggregate} \title{Load CosMx folder aggregate info} \usage{ +load_cosmx_folder_aggregate(dir_items, cores, verbose = TRUE) + load_cosmx_folder_aggregate(dir_items, cores, verbose = TRUE) } \arguments{ @@ -12,6 +14,8 @@ load_cosmx_folder_aggregate(dir_items, cores, verbose = TRUE) \item{verbose}{be verbose when building Giotto object} } \description{ +Load CosMx folder aggregate info + Load CosMx folder aggregate info } \keyword{internal} diff --git a/man/load_cosmx_folder_subcellular.Rd b/man/load_cosmx_folder_subcellular.Rd index 7e0b28a86..6c9923972 100644 --- a/man/load_cosmx_folder_subcellular.Rd +++ b/man/load_cosmx_folder_subcellular.Rd @@ -1,9 +1,11 @@ % Generated by roxygen2: do not edit by hand -% Please edit documentation in R/convenience_create.R +% Please edit documentation in R/convenience.R, R/convenience_create.R \name{load_cosmx_folder_subcellular} \alias{load_cosmx_folder_subcellular} \title{Load CosMx folder subcellular info} \usage{ +load_cosmx_folder_subcellular(dir_items, FOVs = NULL, cores, verbose = TRUE) + load_cosmx_folder_subcellular(dir_items, FOVs = NULL, cores, verbose = TRUE) } \arguments{ @@ -14,6 +16,10 @@ load_cosmx_folder_subcellular(dir_items, FOVs = NULL, cores, verbose = TRUE) \item{verbose}{be verbose when building Giotto object} } \description{ +loads in the feature detections information. Note that the mask +images are still required for a working subcellular object, and those are loaded +in \code{\link{createGiottoCosMxObject_subcellular}} + loads in the feature detections information. Note that the mask images are still required for a working subcellular object, and those are loaded in \code{\link{createGiottoCosMxObject_subcellular}} diff --git a/man/load_merscope_folder.Rd b/man/load_merscope_folder.Rd index 2dc9a83c0..00afc35ff 100644 --- a/man/load_merscope_folder.Rd +++ b/man/load_merscope_folder.Rd @@ -1,5 +1,5 @@ % Generated by roxygen2: do not edit by hand -% Please edit documentation in R/convenience_create.R +% Please edit documentation in R/convenience.R, R/convenience_create.R \name{load_merscope_folder} \alias{load_merscope_folder} \alias{load_merscope_folder_subcellular} @@ -9,7 +9,8 @@ load_merscope_folder( dir_items, data_to_use, - fovs = NULL, + FOVs = NULL, + polygon_feat_types = 0:6, cores = NA, verbose = TRUE ) @@ -17,9 +18,35 @@ load_merscope_folder( load_merscope_folder_subcellular( dir_items, data_to_use, + polygon_feat_types = 0:6, cores = NA, verbose = TRUE, - fovs = NULL + FOVs = NULL +) + +load_merscope_folder_aggregate( + dir_items, + data_to_use, + cores = NA, + verbose = TRUE +) + +load_merscope_folder( + dir_items, + data_to_use, + FOVs = NULL, + polygon_feat_types = 0:6, + cores = NA, + verbose = TRUE +) + +load_merscope_folder_subcellular( + dir_items, + data_to_use, + polygon_feat_types = 0:6, + cores = NA, + verbose = TRUE, + FOVs = NULL ) load_merscope_folder_aggregate( @@ -35,14 +62,23 @@ load_merscope_folder_aggregate( \item{data_to_use}{which of either the 'subcellular' or 'aggregate' information to use for object creation} +\item{FOVs}{which FOVs to use when building the subcellular object. (default is NULL) +NULL loads all FOVs (very slow)} + +\item{polygon_feat_types}{which Vizgen polygon z slices are loaded (There are 0 - 6)} + \item{cores}{how many cores or threads to use to read data if paths are provided} \item{verbose}{be verbose when building Giotto object} } \value{ +list of loaded-in MERSCOPE data + list of loaded-in MERSCOPE data } \description{ +Load MERSCOPE data from folder + Load MERSCOPE data from folder } \section{Functions}{ @@ -51,5 +87,9 @@ Load MERSCOPE data from folder \item \code{load_merscope_folder_aggregate()}: Load items for 'aggregate' workflow +\item \code{load_merscope_folder_subcellular()}: Load items for 'subcellular' workflow + +\item \code{load_merscope_folder_aggregate()}: Load items for 'aggregate' workflow + }} \keyword{internal} diff --git a/man/load_xenium_folder.Rd b/man/load_xenium_folder.Rd index 1f4c7cbd4..3e7304d20 100644 --- a/man/load_xenium_folder.Rd +++ b/man/load_xenium_folder.Rd @@ -1,5 +1,5 @@ % Generated by roxygen2: do not edit by hand -% Please edit documentation in R/convenience_create.R +% Please edit documentation in R/convenience.R, R/convenience_create.R \name{load_xenium_folder} \alias{load_xenium_folder} \alias{load_xenium_folder_csv} @@ -27,6 +27,37 @@ load_xenium_folder_csv( verbose = TRUE ) +load_xenium_folder_parquet( + path_list, + cores, + data_to_use = "subcellular", + h5_expression = FALSE, + h5_gene_ids = "symbols", + gene_column_index = 1, + verbose = TRUE +) + +load_xenium_folder( + path_list, + load_format = "csv", + data_to_use = "subcellular", + h5_expression = "FALSE", + h5_gene_ids = "symbols", + gene_column_index = 1, + cores, + verbose = TRUE +) + +load_xenium_folder_csv( + path_list, + cores, + data_to_use = "subcellular", + h5_expression = FALSE, + h5_gene_ids = "symbols", + gene_column_index = 1, + verbose = TRUE +) + load_xenium_folder_parquet( path_list, cores, @@ -59,9 +90,13 @@ expression matrix} \item{verbose}{be verbose when building Giotto object} } \value{ +list of loaded in xenium data + list of loaded in xenium data } \description{ +Load xenium data from folder + Load xenium data from folder } \section{Functions}{ @@ -70,5 +105,9 @@ Load xenium data from folder \item \code{load_xenium_folder_parquet()}: Load from parquet files +\item \code{load_xenium_folder_csv()}: Load from csv files + +\item \code{load_xenium_folder_parquet()}: Load from parquet files + }} \keyword{internal} diff --git a/man/prov-generic.Rd b/man/prov-generic.Rd index 45445bb45..8a74c3c01 100644 --- a/man/prov-generic.Rd +++ b/man/prov-generic.Rd @@ -3,6 +3,7 @@ \name{prov-generic} \alias{prov-generic} \alias{prov} +\alias{prov<-} \alias{prov,provData-method} \alias{prov<-,provData-method} \title{Provenance information} diff --git a/man/read_cosmx_folder.Rd b/man/read_cosmx_folder.Rd index 1607283d3..31c913f0b 100644 --- a/man/read_cosmx_folder.Rd +++ b/man/read_cosmx_folder.Rd @@ -1,9 +1,11 @@ % Generated by roxygen2: do not edit by hand -% Please edit documentation in R/convenience_create.R +% Please edit documentation in R/convenience.R, R/convenience_create.R \name{read_cosmx_folder} \alias{read_cosmx_folder} \title{Read a structured CosMx folder} \usage{ +read_cosmx_folder(cosmx_dir, verbose = TRUE) + read_cosmx_folder(cosmx_dir, verbose = TRUE) } \arguments{ @@ -12,13 +14,20 @@ read_cosmx_folder(cosmx_dir, verbose = TRUE) \item{verbose}{be verbose when building Giotto object} } \value{ +path_list a list of cosmx files discovered and their filepaths. NULL +values denote missing items + path_list a list of cosmx files discovered and their filepaths. NULL values denote missing items } \description{ +Read a structured CosMx folder + Read a structured CosMx folder } \seealso{ +createGiottoCosMxObject load_cosmx_folder + createGiottoCosMxObject load_cosmx_folder } \keyword{internal} diff --git a/man/read_data_folder.Rd b/man/read_data_folder.Rd index bf8625909..759036c92 100644 --- a/man/read_data_folder.Rd +++ b/man/read_data_folder.Rd @@ -1,5 +1,5 @@ % Generated by roxygen2: do not edit by hand -% Please edit documentation in R/convenience_create.R +% Please edit documentation in R/convenience.R, R/convenience_create.R \name{read_data_folder} \alias{read_data_folder} \alias{read_merscope_folder} @@ -16,6 +16,19 @@ read_data_folder( verbose = TRUE ) +read_merscope_folder(merscope_dir, data_to_use, cores = NA, verbose = TRUE) + +read_data_folder( + spat_method = NULL, + data_dir = NULL, + dir_items, + data_to_use, + load_format = NULL, + require_data_DT, + cores = NA, + verbose = TRUE +) + read_merscope_folder(merscope_dir, data_to_use, cores = NA, verbose = TRUE) } \arguments{ @@ -35,10 +48,25 @@ or optional for each \code{data_to_use} workflow} \item{verbose}{be verbose} } \description{ +Read the exported folder of a spatial method and +detect the presence of needed files. NULL values denote missing items. + Read the exported folder of a spatial method and detect the presence of needed files. NULL values denote missing items. } \details{ +Steps performed: +\itemize{ + \item{1. detection of items within \code{data_dir} by looking for keywords + assigned through \code{dir_items}} + \item{2. check of detected items to see if everything needed has been found. + Dictionary of necessary vs optional items for each \code{data_to_use} workflow + is provided through \code{require_data_DT}} + \item{3. if multiple filepaths are found to be matching then select the first + one. This function is only intended to find the first level subdirectories + and files.} +} + Steps performed: \itemize{ \item{1. detection of items within \code{data_dir} by looking for keywords @@ -55,5 +83,7 @@ Steps performed: \itemize{ \item \code{read_merscope_folder()}: Read a structured MERSCOPE folder +\item \code{read_merscope_folder()}: Read a structured MERSCOPE folder + }} \keyword{internal} diff --git a/man/read_xenium_folder.Rd b/man/read_xenium_folder.Rd index af0de5996..74fc4f835 100644 --- a/man/read_xenium_folder.Rd +++ b/man/read_xenium_folder.Rd @@ -1,9 +1,18 @@ % Generated by roxygen2: do not edit by hand -% Please edit documentation in R/convenience_create.R +% Please edit documentation in R/convenience.R, R/convenience_create.R \name{read_xenium_folder} \alias{read_xenium_folder} \title{Read a structured xenium folder} \usage{ +read_xenium_folder( + xenium_dir, + data_to_use = "subcellular", + bounds_to_load = c("cell"), + load_format = "csv", + h5_expression = FALSE, + verbose = TRUE +) + read_xenium_folder( xenium_dir, data_to_use = "subcellular", @@ -32,10 +41,15 @@ Default is \code{TRUE}} \item{verbose}{be verbose when building Giotto object} } \value{ +path_list a list of xenium files discovered and their filepaths. NULL +values denote missing items + path_list a list of xenium files discovered and their filepaths. NULL values denote missing items } \description{ +Read a structured xenium folder + Read a structured xenium folder } \keyword{internal} diff --git a/man/spatUnit-generic.Rd b/man/spatUnit-generic.Rd index a44ae75db..9a3068e53 100644 --- a/man/spatUnit-generic.Rd +++ b/man/spatUnit-generic.Rd @@ -3,6 +3,7 @@ \name{spatUnit-generic} \alias{spatUnit-generic} \alias{spatUnit} +\alias{spatUnit<-} \alias{spatUnit,spatData-method} \alias{spatUnit<-,spatData-method} \title{Spatial unit information} diff --git a/man/time_format.Rd b/man/time_format.Rd deleted file mode 100644 index be19f26e2..000000000 --- a/man/time_format.Rd +++ /dev/null @@ -1,15 +0,0 @@ -% Generated by roxygen2: do not edit by hand -% Please edit documentation in R/utilities.R -\name{time_format} -\alias{time_format} -\title{Format time for printing} -\usage{ -time_format(secs) -} -\description{ -Format time for printing -} -\details{ -Code from \code{\link[data.table]{timetaken}} -} -\keyword{internal} From 336c03ce871edda240ac57db8de6a3e5a72ed48c Mon Sep 17 00:00:00 2001 From: jiajic <72078254+jiajic@users.noreply.github.com> Date: Wed, 14 Dec 2022 12:55:10 -0500 Subject: [PATCH 031/129] add nameData --- R/classes.R | 42 +++++++++++++++++------------------------- 1 file changed, 17 insertions(+), 25 deletions(-) diff --git a/R/classes.R b/R/classes.R index 3122f3a10..436ca30d0 100644 --- a/R/classes.R +++ b/R/classes.R @@ -33,6 +33,12 @@ setOldClass('data.table') # BASIC CLASSES #### +# ** nameData Class #### +#' +setClass('nameData', + slots = list(name = 'character'), + prototype = prototype(name = NA_character_)) + # ** exprData Class #### #' Basic class for classes with expression information #' @@ -567,9 +573,7 @@ check_expr_obj = function(object) { #' @slot misc misc #' @export setClass('exprObj', - contains = c('exprData', 'spatFeatData', 'miscData'), - slots = c(name = 'character'), - prototype = list(name = NA_character_), + contains = c('nameData', 'exprData', 'spatFeatData', 'miscData'), validity = check_expr_obj) ## * Show #### @@ -788,14 +792,12 @@ check_dim_obj = function(object) { #' @slot misc method-specific additional outputs #' @export setClass('dimObj', - contains = c('spatFeatData'), - slots = c(name = 'character', - reduction = 'character', + contains = c('nameData', 'spatFeatData'), + slots = c(reduction = 'character', reduction_method = 'character', coordinates = 'ANY', misc = 'ANY'), - prototype = list(name = NA_character_, - reduction = NA_character_, + prototype = list(reduction = NA_character_, reduction_method = NA_character_, coordinates = NULL, misc = NULL), @@ -861,9 +863,7 @@ S3toS4dimObj = function(object) { ## nnNetObj #### setClass('nnNetObj', - contains = c('nnData', 'spatFeatData', 'miscData'), - slots = list(name = 'character'), - prototype = prototype(name = NA_character_)) + contains = c('nameData', 'nnData', 'spatFeatData', 'miscData')) @@ -919,9 +919,7 @@ check_spat_locs_obj = function(object) { #' @slot provenance origin of aggregated information (if applicable) #' @export setClass('spatLocsObj', - contains = c('coordDataDT', 'spatData', 'miscData'), - slots = c(name = 'character'), - prototype = list(name = NA_character_), + contains = c('nameData', 'coordDataDT', 'spatData', 'miscData'), validity = check_spat_locs_obj) @@ -1014,11 +1012,9 @@ check_spat_net_obj = function(object) { #' slot (filtered). #' @export setClass('spatialNetworkObj', - contains = c('spatNetData' ,'spatData', 'miscData'), - slots = c(name = 'character', - crossSectionObjects = 'ANY'), - prototype = list(name = NA_character_, - crossSectionObjects = NULL), + contains = c('nameData', 'spatNetData' ,'spatData', 'miscData'), + slots = c(crossSectionObjects = 'ANY'), + prototype = list(crossSectionObjects = NULL), validity = check_spat_net_obj) @@ -1143,9 +1139,7 @@ check_spat_grid_obj = function(object) { #' Grids can be annotated with both spatial and feature information #' @export setClass('spatialGridObj', - contains = c('spatGridData', 'spatFeatData', 'miscData'), - slots = c(name = 'character'), - prototype = list(name = NA_character_), + contains = c('nameData', 'spatGridData', 'spatFeatData', 'miscData'), validity = check_spat_grid_obj) @@ -1250,9 +1244,7 @@ S3toS4spatialGridObj = function(object) { #' @slot misc misc #' @export setClass('spatEnrObj', - contains = c('enrData', 'spatFeatData', 'miscData'), - slots = c(name = 'character'), - prototype = list(name = NA_character_)) + contains = c('nameData', 'enrData', 'spatFeatData', 'miscData')) # * show #### From 5e66e862833b88012ced23c3eca911876a33cfab Mon Sep 17 00:00:00 2001 From: jiajic <72078254+jiajic@users.noreply.github.com> Date: Wed, 14 Dec 2022 14:04:48 -0500 Subject: [PATCH 032/129] remove extra file --- DESCRIPTION | 1 - R/convenience_create.R | 1892 ------------------- man/createGiottoCosMxObject.Rd | 49 +- man/createGiottoCosMxObject_aggregate.Rd | 11 +- man/createGiottoCosMxObject_all.Rd | 20 +- man/createGiottoCosMxObject_subcellular.Rd | 12 +- man/createGiottoMerscopeObject.Rd | 67 +- man/createGiottoXeniumObject.Rd | 48 +- man/createGiottoXeniumObject_aggregate.Rd | 13 +- man/createGiottoXeniumObject_subcellular.Rd | 15 +- man/load_cosmx_folder_aggregate.Rd | 6 +- man/load_cosmx_folder_subcellular.Rd | 8 +- man/load_merscope_folder.Rd | 46 +- man/load_xenium_folder.Rd | 41 +- man/read_cosmx_folder.Rd | 11 +- man/read_data_folder.Rd | 32 +- man/read_xenium_folder.Rd | 16 +- 17 files changed, 19 insertions(+), 2269 deletions(-) delete mode 100644 R/convenience_create.R diff --git a/DESCRIPTION b/DESCRIPTION index 5ae7c0c41..0c62ec577 100644 --- a/DESCRIPTION +++ b/DESCRIPTION @@ -122,7 +122,6 @@ Collate: 'classes.R' 'clustering.R' 'convenience.R' - 'convenience_create.R' 'cross_section.R' 'differential_expression.R' 'dimension_reduction.R' diff --git a/R/convenience_create.R b/R/convenience_create.R deleted file mode 100644 index a57be6290..000000000 --- a/R/convenience_create.R +++ /dev/null @@ -1,1892 +0,0 @@ - -# ** Spatial Method-Specific Convenience Functions for Giotto Object Creation ** # - - - -# Common Utility Functions #### - -#' @title Read a structured folder of exported data -#' @name read_data_folder -#' @description Read the exported folder of a spatial method and -#' detect the presence of needed files. NULL values denote missing items. -#' @param spat_method spatial method for which the data is being read -#' @param data_dir exported data directory to read from -#' @param dir_items named list of directory items to expect and keywords to match -#' @param data_to_use which type(s) of expression data to build the gobject with -#' @param require_data_DT data.table detailing if expected data items are required -#' or optional for each \code{data_to_use} workflow -#' @param cores cores to use -#' @param verbose be verbose -#' @details Steps performed: -#' \itemize{ -#' \item{1. detection of items within \code{data_dir} by looking for keywords -#' assigned through \code{dir_items}} -#' \item{2. check of detected items to see if everything needed has been found. -#' Dictionary of necessary vs optional items for each \code{data_to_use} workflow -#' is provided through \code{require_data_DT}} -#' \item{3. if multiple filepaths are found to be matching then select the first -#' one. This function is only intended to find the first level subdirectories -#' and files.} -#' } -#' @keywords internal -read_data_folder = function(spat_method = NULL, - data_dir = NULL, - dir_items, - data_to_use, - load_format = NULL, - require_data_DT, - cores = NA, - verbose = TRUE) { - - ch = box_chars() - - # 0. check params - if(is.null(data_dir) | !dir.exists(data_dir)) stop(wrap_txt('The full path to a', spat_method, 'directory must be given.\n')) - if(isTRUE(verbose)) wrap_msg('A structured', spat_method, 'directory will be used') - if(!data_to_use %in% require_data_DT$workflow) stop(wrap_txt('Data requirements for data_to_use not found in require_data_DT')) - - # 1. detect items - dir_items = lapply_flex(dir_items, function(x) { - Sys.glob(paths = file.path(data_dir, x)) - }, cores = cores) - # (length = 1 if present, length = 0 if missing) - dir_items_lengths = lengths(dir_items) - - # 2. check directory contents - if(isTRUE(verbose)) wrap_msg('Checking directory contents...') - - for(item in names(dir_items)) { - - # IF ITEM FOUND - - if(dir_items_lengths[[item]] > 0) { - if(isTRUE(verbose)) { - message(ch$s, '> ' ,item, ' found') - for(item_i in seq_along(dir_items[[item]])) { # print found item names - subItem = gsub(pattern = '.*/', replacement = '', x = dir_items[[item]][[item_i]]) - message(ch$s, ch$s, ch$l, ch$h, ch$h, subItem) - } - } - } else { - - # IF ITEM MISSING - # necessary (error) - # optional (warning) - - # data.table variables - workflow = needed = filetype = NULL - - - require_data_DT = require_data_DT[workflow == data_to_use,] - if(!is.null(load_format)) require_data_DT = require_data_DT[filetype == load_format,] - - if(item %in% require_data_DT[needed == TRUE, item]) stop(item, ' is missing\n') - if(item %in% require_data_DT[needed == FALSE, item]) warning(item, 'is missing (optional)\n') - - } - } - - # 3. select first path in list if multiple are detected - if(any(dir_items_lengths > 1)) { - warning(wrap_txt('Multiple matches for expected directory item(s). - First matching item selected')) - - multiples = which(dir_items_lengths > 1) - for(mult_i in multiples) { - message(names(dir_items)[[mult_i]], 'multiple matches found:') - print(dir_items[[mult_i]]) - dir_items[[mult_i]] = dir_items[[mult_i]][[1]] - } - } - if(isTRUE(verbose)) message('Directory check done') - - return(dir_items) - -} - - - - - - - - - -# object creation #### - - - - -## MERSCOPE #### - -#' @title Create Vizgen MERSCOPE Giotto Object -#' @name createGiottoMerscopeObject -#' @description Given the path to a MERSCOPE experiment directory, creates a Giotto -#' object. -#' @param merscope_dir full path to the exported merscope directory -#' @param data_to_use which of either the 'subcellular' or 'aggregate' information -#' to use for object creation -#' @param FOVs which FOVs to use when building the subcellular object. (default is NULL) -#' NULL loads all FOVs (very slow) -#' @param polygon_feat_types which Vizgen polygon z slices are loaded (There are 0 - 6) -#' @param calculate_overlap whether to run \code{\link{calculateOverlapRaster}} -#' @param overlap_to_matrix whether to run \code{\link{overlapToMatrix}} -#' @param aggregate_stack whether to run \code{\link{aggregateStacks}} -#' @param aggregate_stack_param params to pass to \code{\link{aggregateStacks}} -#' @inheritParams createGiottoObjectSubcellular -#' @return a giotto object -#' @export -#' @details -#' [\strong{Expected Directory}] This function generates a giotto object when given a -#' link to a MERSCOPE output directory. It expects the following items within the directory -#' where the \strong{bolded} portions are what this function matches against: -#' \itemize{ -#' \item{\strong{cell_boundaries} (folder .hdf5 files)} -#' \item{\strong{images} (folder of .tif images and a scalefactor/transfrom table)} -#' \item{\strong{cell_by_gene}.csv (file)} -#' \item{cell_metadata\strong{fov_positions_file}.csv (file)} -#' \item{detected_transcripts\strong{metadata_file}.csv (file)} -#' } -createGiottoMerscopeObject = function(merscope_dir, - data_to_use = c('subcellular', 'aggregate'), - FOVs = NULL, - polygon_feat_types = 0:6, - calculate_overlap = TRUE, - overlap_to_matrix = TRUE, - aggregate_stack = TRUE, - aggregate_stack_param = list(summarize_expression = 'sum', - summarize_locations = 'mean', - new_spat_unit = 'cell'), - instructions = NULL, - cores = NA, - verbose = TRUE) { - - # 0. setup - # set number of cores automatically, but with limit of 10 - cores = determine_cores(cores) - data.table::setDTthreads(threads = cores) - - # determine data to use - data_to_use = match.arg(arg = data_to_use, choices = c('subcellular','aggregate')) - - # 1. test if folder structure exists and is as expected - dir_items = read_merscope_folder(merscope_dir = merscope_dir, - data_to_use = data_to_use, - cores = cores, - verbose = verbose) - - # 2. load in directory items - data_list = load_merscope_folder(dir_items = dir_items, - data_to_use = data_to_use, - FOVs = FOVs, - polygon_feat_types = polygon_feat_types, - cores = cores, - verbose = verbose) - - # 3. Create giotto object - if(data_to_use == 'subcellular') { - - merscope_gobject = createGiottoMerscopeObject_subcellular(data_list = data_list, - calculate_overlap = calculate_overlap, - overlap_to_matrix = overlap_to_matrix, - aggregate_stack = aggregate_stack, - aggregate_stack_param = aggregate_stack_param, - instructions = instructions, - cores = cores, - verbose = verbose) - - } else if(data_to_use == 'aggregate') { - - merscope_gobject = createGiottoMerscopeObject_aggregate(data_list = data_list, - instructions = instructions, - cores = cores, - verbose = verbose) - - } else { - stop(wrap_txt('data_to_use "', data_to_use, '" not implemented', sep = '')) - } - - return(merscope_gobject) - -} - - - - -#' @describeIn createGiottoMerscopeObject Create giotto object with 'subcellular' workflow -#' @param data_list list of loaded data from \code{\link{load_merscope_folder}} -#' @keywords internal -createGiottoMerscopeObject_subcellular = function(data_list, - calculate_overlap = TRUE, - overlap_to_matrix = TRUE, - aggregate_stack = TRUE, - aggregate_stack_param = list(summarize_expression = 'sum', - summarize_locations = 'mean', - new_spat_unit = 'cell'), - instructions, - cores = NA, - verbose = TRUE) { - - # data.table vars - feat_coord = neg_coord = cellLabel_dir = NULL - - # unpack data_list - poly_info = data_list$poly_info # expected to be list of giottoPolygons - tx_dt = data_list$tx_dt - micronToPixelScale = data_list$micronToPixelScale - image_list = data_list$images - - # data.table vars - gene = NULL - - # split tx_dt by expression and blank - if(isTRUE(verbose)) wrap_msg('Splitting detections by feature vs blank') - feat_id_all = tx_dt[, unique(gene)] - blank_id = feat_id_all[grepl(pattern = 'Blank', feat_id_all)] - feat_id = feat_id_all[!feat_id_all %in% blank_id] - - feat_dt = tx_dt[gene %in% feat_id,] - blank_dt = tx_dt[gene %in% blank_id,] - - # extract transcript_id col and store as feature meta - feat_meta = unique(feat_dt[, c('gene', 'transcript_id', 'barcode_id'), with = FALSE]) - blank_meta = unique(blank_dt[, c('gene', 'transcript_id', 'barcode_id'), with = FALSE]) - feat_dt[, c('transcript_id', 'barcode_id') := NULL] - blank_dt[, c('transcript_id', 'barcode_id') := NULL] - - if(isTRUE(verbose)) { - message(' > Features: ', feat_dt[, .N]) - message(' > Blanks: ', blank_dt[, .N]) - } - - # build giotto object - if(isTRUE(verbose)) wrap_msg('Building subcellular giotto object...') - z_sub = createGiottoObjectSubcellular( - gpoints = list('rna' = feat_coord, - 'neg_probe' = neg_coord), - gpolygons = poly_info, - polygon_mask_list_params = list( - mask_method = 'guess', - flip_vertical = TRUE, - flip_horizontal = FALSE, - shift_horizontal_step = FALSE - ), - instructions = instructions, - cores = cores - ) - -} - - - - -#' @describeIn createGiottoMerscopeObject Create giotto object with 'aggregate' workflow -#' @param data_list list of loaded data from \code{\link{load_merscope_folder}} -#' @keywords internal -createGiottoMerscopeObject_aggregate = function(data_list, - instructions = NULL, - cores = NA, - verbose = TRUE) { - - # unpack data_list - micronToPixelScale = data_list$micronToPixelScale - expr_dt = data_list$expr_dt - cell_meta = data_list$expr_mat - image_list = data_list$images - - # split expr_dt by expression and blank - - # feat_id_all = - -} - - - - - - - - - - - - - - - -## CosMx #### - -#' @title Create Nanostring CosMx Giotto Object -#' @name createGiottoCosMxObject -#' @description Given the path to a CosMx experiment directory, creates a Giotto -#' object. -#' @param cosmx_dir full path to the exported cosmx directory -#' @param data_to_use which type(s) of expression data to build the gobject with -#' Default is \code{'all'} information available. \code{'subcellular'} loads the transcript -#' coordinates only. \code{'aggregate'} loads the provided aggregated expression matrix. -#' @param FOVs field of views to load (only affects subcellular data and images) -#' @inheritParams createGiottoObjectSubcellular -#' @return a giotto object -#' @export -#' @details -#' [\strong{Expected Directory}] This function generates a giotto object when given a -#' link to a cosmx output directory. It expects the following items within the directory -#' where the \strong{bolded} portions are what this function matches against: -#' \itemize{ -#' \item{\strong{CellComposite} (folder of images)} -#' \item{\strong{CellLabels} (folder of images)} -#' \item{\strong{CellOverlay} (folder of images)} -#' \item{\strong{CompartmentLabels} (folder of images)} -#' \item{experimentname_\strong{exprMat_file}.csv (file)} -#' \item{experimentname_\strong{fov_positions_file}.csv (file)} -#' \item{experimentname_\strong{metadata_file}.csv (file)} -#' \item{experimentname_\strong{tx_file}.csv (file)} -#' } -#' -#' [\strong{Workflows}] Workflow to use is accessed through the data_to_use param -#' \itemize{ -#' \item{'all' - loads and requires subcellular information from tx_file and fov_positions_file -#' and also the existing aggregated information (expression, spatial locations, and metadata) -#' from exprMat_file and metadata_file.} -#' \item{'subcellular' - loads and requires subcellular information from tx_file and -#' fov_positions_file only.} -#' \item{'aggregate' - loads and requires the existing aggregate information (expression, -#' spatial locations, and metadata) from exprMat_file and metadata_file.} -#' } -#' -#' [\strong{Images}] Images in the default CellComposite, CellLabels, CompartmentLabels, and CellOverlay -#' folders will be loaded as giotto largeImage objects in all workflows as long as they are available. -#' Additionally, CellComposite images will be converted to giotto image objects, making plotting with -#' these image objects more responsive when accessing them from a server. -#' \code{\link{showGiottoImageNames}} can be used to see the available images. -#' -#' -createGiottoCosMxObject = function(cosmx_dir = NULL, - # data_to_use = c('subcellular','aggregate','all'), - data_to_use = c('subcellular'), - FOVs = NULL, - instructions = NULL, - cores = NA, - verbose = TRUE) { - - # 0. setup - # set number of cores automatically, but with limit of 10 - cores = determine_cores(cores) - data.table::setDTthreads(threads = cores) - - # determine data to use - data_to_use = match.arg(arg = data_to_use, choices = c('subcellular')) - # data_to_use = match.arg(arg = data_to_use, choices = c('subcellular','aggregate','all')) - - # Define for data.table - fov = target = x_local_px = y_local_px = z = cell_ID = CenterX_global_px = CenterY_global_px = - CenterX_local_px = CenterY_local_px = NULL - - - # 1. test if folder structure exists and is as expected - dir_items = read_cosmx_folder(cosmx_dir = cosmx_dir, - verbose = verbose) - - - # 2. load and create giotto object - if(data_to_use == 'subcellular') { - - cosmx_gobject = createGiottoCosMxObject_subcellular(dir_items, - FOVs = FOVs, - cores = cores, - verbose = verbose, - instructions = instructions) - - } - - if(data_to_use == 'aggregate') { - - cosmx_gobject = createGiottoCosMxObject_aggregate(dir_items, - cores = cores, - verbose = verbose, - instructions = instructions) - - } - - if(data_to_use == 'all') { - - cosmx_gobject = createGiottoCosMxObject_all(dir_items, - FOVs = FOVs, - cores = cores, - verbose = verbose, - instructions = instructions) - - } - - - # load in subcellular information, subcellular FOV objects, then join - - - # load in pre-generated aggregated expression matrix - if(data_to_use == 'aggregate' | data_to_use == 'all') { - - } - - - - message('done') - return(cosmx_gobject) - -} - - - -#' @title Load and create a CosMx Giotto object from subcellular info -#' @name createGiottoCosMxObject_subcellular -#' @inheritParams createGiottoCosMxObject -#' @keywords internal -createGiottoCosMxObject_subcellular = function(dir_items, - FOVs = NULL, - cores, - verbose = TRUE, - instructions = NULL) { - - # data.table vars - target = fov = NULL - - # load tx detections and FOV offsets - data_list = load_cosmx_folder_subcellular(dir_items = dir_items, - FOVs = FOVs, - cores = cores, - verbose = verbose) - - # unpack data_list - FOV_ID = data_list$FOV_ID - fov_offset_file = data_list$fov_offset_file - tx_coord_all = data_list$tx_coord_all - - # remove global xy values and cell_ID - tx_coord_all[, c('x_global_px', 'y_global_px', 'cell_ID') := NULL] - - data.table::setcolorder(tx_coord_all, c('target', 'x_local_px', 'y_local_px', 'z', 'fov')) - - if(isTRUE(verbose)) wrap_msg('Splitting detections by feature vs neg probe') - all_IDs = tx_coord_all[, unique(target)] - neg_IDs = all_IDs[grepl(pattern = 'NegPrb', all_IDs)] - feat_IDs = all_IDs[!all_IDs %in% neg_IDs] - - # split detections DT - feat_coords_all = tx_coord_all[target %in% feat_IDs] - neg_coords_all = tx_coord_all[target %in% neg_IDs] - - if(isTRUE(verbose)) { - message(' > Features: ', feat_coords_all[, .N]) - message(' > NegProbes: ', neg_coords_all[, .N]) - } - - # Start FOV lapply - fov_gobjects_list = lapply(FOV_ID, function(x) { - - # Build image paths - if(isTRUE(verbose)) message('Loading image information...') - - composite_dir = Sys.glob(paths = file.path(dir_items$`CellComposite folder`, paste0('*',x, '*'))) - cellLabel_dir = Sys.glob(paths = file.path(dir_items$`CellLabels folder`, paste0('*',x, '*'))) - compartmentLabel_dir = Sys.glob(paths = file.path(dir_items$`CompartmentLabels folder`, paste0('*',x, '*'))) - cellOverlay_dir = Sys.glob(paths = file.path(dir_items$`CellOverlay folder`, paste0('*',x, '*'))) - # Missing warnings - if(length(composite_dir) == 0) {warning('[ FOV ', x, ' ] No composite images found') ; composite_dir = NULL} - if(length(cellLabel_dir) == 0) {stop('[ FOV ', x, ' ] No cell mask images found')} # cell masks are necessary - if(length(compartmentLabel_dir) == 0) {warning('[ FOV ', x, ' ] No compartment label images found') ; compartmentLabel_dir = NULL} - if(length(cellOverlay_dir) == 0) {warning('[ FOV ', x, ' ] No cell polygon overlay images found') ; cellOverlay_dir = NULL} - - if(isTRUE(verbose)) message('Image load done') - - if(isTRUE(verbose)) wrap_msg('[ FOV ', x, ']') - - # get FOV specific tx locations - if(isTRUE(verbose)) wrap_msg('Assigning FOV feature detections...') - - - # feature info - coord_oldnames = c('target', 'x_local_px', 'y_local_px') - coord_newnames = c('feat_ID', 'x', 'y') - - feat_coord = feat_coords_all[fov == as.numeric(x)] - data.table::setnames(feat_coord, old = coord_oldnames, new = coord_newnames) - # neg probe info - neg_coord = neg_coords_all[fov == as.numeric(x)] - data.table::setnames(neg_coord, old = coord_oldnames, new = coord_newnames) - - - # build giotto object - if(isTRUE(verbose)) wrap_msg('Building subcellular giotto object...') - fov_subset = createGiottoObjectSubcellular( - gpoints = list('rna' = feat_coord, - 'neg_probe' = neg_coord), - gpolygons = list('cell' = cellLabel_dir), - polygon_mask_list_params = list( - mask_method = 'guess', - flip_vertical = TRUE, - flip_horizontal = FALSE, - shift_horizontal_step = FALSE - ), - instructions = instructions, - cores = cores - ) - - - # find centroids as spatial locations - if(isTRUE(verbose)) wrap_msg('Finding polygon centroids as cell spatial locations...') - fov_subset = addSpatialCentroidLocations(fov_subset, - poly_info = 'cell', - spat_loc_name = 'raw') - - - # create and add giotto image objects - if(isTRUE(verbose)) message('Attaching image files...') - print(composite_dir) - print(cellOverlay_dir) - print(compartmentLabel_dir) - - gImage_list = list() - - # load image if files are found - if(!is.null(composite_dir)) - gImage_list$composite = createGiottoLargeImage(raster_object = composite_dir, - negative_y = F, - name = 'composite') - if(!is.null(cellOverlay_dir)) - gImage_list$overlay = createGiottoLargeImage(raster_object = cellOverlay_dir, - negative_y = F, - name = 'overlay') - if(!is.null(compartmentLabel_dir)) - gImage_list$compartment = createGiottoLargeImage(raster_object = compartmentLabel_dir, - negative_y = F, - name = 'compartment') #TODO - - - - if(length(gImage_list) > 0) { - fov_subset = addGiottoImage(gobject = fov_subset, - largeImages = gImage_list) - - # convert to MG for faster loading (particularly relevant for pulling from server) - fov_subset = convertGiottoLargeImageToMG(giottoLargeImage = gImage_list$composite, - gobject = fov_subset, - return_gobject = TRUE, - verbose = FALSE) - # fov_subset = convertGiottoLargeImageToMG(giottoLargeImage = gImage_list$overlay, gobject = fov_subset, return_gobject = TRUE) - # fov_subset = convertGiottoLargeImageToMG(giottoLargeImage = gImage_list$compartment, gobject = fov_subset, return_gobject = TRUE) - } else { - message('No images found for fov') - } - - - }) #lapply end - - if(length(FOVs) == 1) { - return(fov_gobjects_list[[1]]) - } else { - # join giotto objects according to FOV positions file - if(isTRUE(verbose)) message('Joining FOV gobjects...') - new_gobj_names = paste0('fov', FOV_ID) - id_match = match(as.numeric(FOV_ID), fov_offset_file$fov) - x_shifts = fov_offset_file[id_match]$x_global_px - y_shifts = fov_offset_file[id_match]$y_global_px - # Join giotto objects - cosmx_gobject = joinGiottoObjects(gobject_list = fov_gobjects_list, - gobject_names = new_gobj_names, - join_method = 'shift', - x_shift = x_shifts, - y_shift = y_shifts) - return(cosmx_gobject) - } - -} - - - -#' @title Load and create a CosMx Giotto object from aggregate info -#' @name createGiottoCosMxObject_aggregate -#' @inheritParams createGiottoCosMxObject -#' @keywords internal -createGiottoCosMxObject_aggregate = function(dir_items, - cores, - verbose = TRUE, - instructions = NULL) { - - - - data_list = load_cosmx_folder_aggregate(dir_items = dir_items, - cores = cores, - verbose = verbose) - - # data.table vars - fov = NULL - - # unpack data_list - spatlocs = data_list$spatlocs - spatlocs_fov = data_list$spatlocs_fov - metadata = data_list$metadata - protM = data_list$protM - spM = data_list$spM - fov_shifts = data_list$fov_shifts - - - # create standard gobject from aggregate matrix - - # Create aggregate gobject - if(isTRUE(verbose)) message('Building giotto object...') - cosmx_gobject = createGiottoObject(expression = list('raw' = spM, 'protein' = protM), - cell_metadata = list('cell' = list('rna' = metadata, - 'protein' = metadata)), - spatial_locs = spatlocs, - instructions = instructions, - cores = cores) - - - # load in images - img_ID = data.table::data.table(fov = fov_shifts[, fov], - img_name = paste0('fov', sprintf('%03d', fov_shifts[, fov]), '-image')) - - if(isTRUE(verbose)) message('Attaching image files...') - composite_dir = Sys.glob(paths = file.path(dir_items$`CellComposite folder`, paste0('/*'))) - cellLabel_dir = Sys.glob(paths = file.path(dir_items$`CellLabels folder`, paste0('/*'))) - compartmentLabel_dir = Sys.glob(paths = file.path(dir_items$`CompartmentLabels folder`, paste0('/*'))) - overlay_dir = Sys.glob(paths = file.path(dir_items$`CellOverlay folder`, paste0('/*'))) - - if(length(cellLabel_imgList) > 0) cellLabel_imgList = lapply(cellLabel_dir, function(x) {createGiottoLargeImage(x,name = 'cellLabel',negative_y = TRUE)}) - if(length(composite_imgList) > 0) composite_imgList = lapply(composite_dir, function(x) {createGiottoLargeImage(x,name = 'composite',negative_y = TRUE)}) - if(length(compartmentLabel_dir) > 0) compartmentLabel_imgList = lapply(compartmentLabel_dir, function(x) {createGiottoLargeImage(x,name = 'composite',negative_y = TRUE)}) - if(length(overlay_dir) > 0) overlay_imgList = lapply(overlay_dir, function(x) {createGiottoLargeImage(x,name = 'composite',negative_y = TRUE)}) - - - - -} - - - - -#' @title Load and create a CosMx Giotto object from subcellular and aggregate info -#' @name createGiottoCosMxObject_all -#' @param dir_items list of full directory paths from \code{read_cosmx_folder} -#' @inheritParams createGiottoCosMxObject -#' @details Both \emph{subcellular} (subellular transcript detection information) and -#' \emph{aggregate} (aggregated detection count matrices by cell polygon from NanoString) -#' data will be loaded in. The two will be separated into 'cell' and 'cell_agg' -#' spatial units in order to denote the difference in origin of the two. -#' @seealso createGiottoCosMxObject createGiottoCosMxObject_aggregate -#' createGiottoCosMxObject_subcellular -#' @keywords internal -createGiottoCosMxObject_all = function(dir_items, - FOVs, - cores, - verbose = TRUE, - instructions = NULL) { - - # 1. create subcellular giotto as spat_unit 'cell' - cosmx_gobject = createGiottoCosMxObject_subcellular(dir_items = dir_items, - FOVs = FOVs, - cores = cores, - verbose = verbose, - instructions = instructions) - - # 2. load and append aggregated information in spat_unit 'cell_agg' - agg_data = load_cosmx_folder_aggregate(dir_items = dir_items, - cores = cores, - verbose = verbose) - - # unpack data_list - spatlocs = agg_data$spatlocs - spatlocs_fov = agg_data$spatlocs_fov - metadata = agg_data$metadata - protM = agg_data$protM - spM = agg_data$spM - - # add in pre-generated aggregated expression matrix information for 'all' workflow - - # Add aggregate expression information - if(isTRUE(verbose)) wrap_msg('Appending provided aggregate expression data as... - spat_unit: "cell_agg" - feat_type: "rna" - name: "raw"') - # add expression data to expression slot - s4_expr = create_expr_obj(name = 'raw', - exprMat = spM, - spat_unit = 'cell_agg', - feat_type = 'rna', - provenance = 'cell_agg') - - cosmx_gobject = set_expression_values(cosmx_gobject, values = s4_expr) - - # Add spatial locations - if(isTRUE(verbose)) wrap_msg('Appending metadata provided spatial locations data as... - --> spat_unit: "cell_agg" name: "raw" - --> spat_unit: "cell" name: "raw_fov"') - if(isTRUE(verbose)) wrap_msg('Polygon centroid derived spatial locations assigned as... - --> spat_unit: "cell" name: "raw" (default)') - - locsObj = create_spat_locs_obj(name = 'raw', - coordinates = spatlocs, - spat_unit = 'cell_agg', - provenance = 'cell_agg') - locsObj_fov = create_spat_locs_obj(name = 'raw_fov', - coordinates = spatlocs_fov, - spat_unit = 'cell_agg', - provenance = 'cell_agg') - - cosmx_gobject = set_spatial_locations(cosmx_gobject, spatlocs = locsObj) - cosmx_gobject = set_spatial_locations(cosmx_gobject, spatlocs = locsObj_fov) - - # cosmx_gobject = set_spatial_locations(cosmx_gobject, - # spat_unit = 'cell_agg', - # spat_loc_name = 'raw', - # spatlocs = spatlocs) - # cosmx_gobject = set_spatial_locations(cosmx_gobject, - # spat_unit = 'cell_agg', - # spat_loc_name = 'raw_fov', - # spatlocs = spatlocs_fov) - - # initialize cell and feat IDs and metadata slots for 'cell_agg' spat_unit - agg_cell_ID = colnames(s4_expr[]) - agg_feat_ID = rownames(s4_expr[]) - - sub_feat_ID = get_feat_id(cosmx_gobject, feat_type = 'rna') - feat_ID_new = unique(c(agg_feat_ID, sub_feat_ID)) - - cosmx_gobject = set_cell_id(gobject = cosmx_gobject, - spat_unit = 'cell_agg', - cell_IDs = agg_cell_ID) - cosmx_gobject = set_feat_id(gobject = cosmx_gobject, - feat_type = 'rna', - feat_IDs = feat_ID_new) - - # cell metadata - - # cosmx_gobject@cell_ID[['cell_agg']] = colnames(cosmx_gobject@expression[['cell_agg']][[1]][[1]]) - # cosmx_gobject@feat_ID[['rna']] = unique(c(cosmx_gobject@feat_ID, rownames(cosmx_gobject@expression[['cell_agg']][['rna']][[1]]))) - # cosmx_gobject@cell_metadata[['cell_agg']][['rna']] = data.table::data.table(cell_ID = cosmx_gobject@cell_ID[['cell_agg']]) - # cosmx_gobject@feat_metadata[['cell_agg']][['rna']] = data.table::data.table(feat_ID = cosmx_gobject@feat_ID[['rna']]) - - # Add metadata to both the given and the poly spat_units - if(isTRUE(verbose)) message('Appending provided cell metadata...') - cosmx_gobject = addCellMetadata(cosmx_gobject, - spat_unit = 'cell', - feat_type = 'rna', - new_metadata = metadata, - by_column = TRUE, - column_cell_ID = 'cell_ID') - cosmx_gobject = addCellMetadata(cosmx_gobject, - spat_unit = 'cell_agg', - feat_type = 'rna', - new_metadata = metadata, - by_column = TRUE, - column_cell_ID = 'cell_ID') - -} - - - - - - - - - - -## Xenium #### - -#' @title Create 10x Xenium Giotto Object -#' @name createGiottoXeniumObject -#' @description Given the path to a Xenium experiment output folder, creates a Giotto -#' object -#' @param xenium_dir full path to the exported xenium directory -#' @param data_to_use which type(s) of expression data to build the gobject with -#' (e.g. default: \strong{'subcellular'}, 'aggregate', or 'all') -#' @param load_format files formats from which to load the data. Either `csv` or -#' `parquet` currently supported. -#' @param h5_expression (boolean) whether to load cell_feature_matrix from .h5 file. -#' Default is \code{TRUE} -#' @param h5_gene_ids use gene symbols (default) or ensembl ids for the .h5 gene -#' expression matrix -#' @param bounds_to_load vector of boundary information to load (e.g. \code{'cell'} -#' or \code{'nucleus'} by themselves or \code{c('cell', 'nucleus')} to load both -#' at the same time.) -#' @param qv_threshold Minimum Phred-scaled quality score cutoff to be included as -#' a subcellular transcript detection (default = 20) -#' @param key_list (advanced) list of grep-based keywords to split the subcellular -#' feature detections by feature type. See details -#' @inheritParams get10Xmatrix -#' @inheritParams createGiottoObjectSubcellular -#' @details -#' -#' [\strong{QC feature types}] -#' Xenium provides info on feature detections that include more than only the -#' Gene Expression specific probes. Additional probes for QC are included: -#' \emph{blank codeword}, \emph{negative control codeword}, and -#' \emph{negative control probe}. These additional QC probes each occupy and are treated -#' as their own feature types so that they can largely remain independent of the -#' gene expression information. -#' -#' [\strong{key_list}] -#' Related to \code{data_to_use = 'subcellular'} workflow only: -#' Additional QC probe information is in the subcellular feature detections information -#' and must be separated from the gene expression information during processing. -#' The QC probes have prefixes that allow them to be selected from the rest of the -#' feature IDs. -#' Giotto uses a named list of keywords (\code{key_list}) to select these QC probes, -#' with the list names being the names that will be assigned as the feature type -#' of these feature detections. The default list is used when \code{key_list} = NULL. -#' -#' Default list: -#' \preformatted{ -#' list(blank_code = 'BLANK_', -#' neg_code = 'NegControlCodeword_', -#' neg_probe = c('NegControlProbe_|antisense_')) -#' } -#' -#' The Gene expression subset is accepted as the subset of feat_IDs that do not -#' map to any of the keys. -#' -#' @export -createGiottoXeniumObject = function(xenium_dir, - data_to_use = c('subcellular','aggregate'), - load_format = 'csv', - h5_expression = TRUE, - h5_gene_ids = c('symbols', 'ensembl'), - gene_column_index = 1, - bounds_to_load = c('cell'), - qv_threshold = 20, - key_list = NULL, - # include_analysis = FALSE, - instructions = NULL, - cores = NA, - verbose = TRUE) { - - # 0. setup - - # Determine data to load - data_to_use = match.arg(arg = data_to_use, choices = c('subcellular','aggregate')) - - # Determine load formats - load_format = 'csv' # TODO Remove this and add as param once other options are available - load_format = match.arg(arg = load_format, choices = c('csv', 'parquet', 'zarr')) - - # set number of cores automatically, but with limit of 10 - cores = determine_cores(cores) - data.table::setDTthreads(threads = cores) - - # 1. detect xenium folder and find filepaths to load - - # path_list contents: - # tx_path - # bound_paths - # cell_meta_path - # agg_expr_path - # panel_meta_path - path_list = read_xenium_folder(xenium_dir = xenium_dir, - data_to_use = data_to_use, - bounds_to_load = bounds_to_load, - load_format = load_format, - h5_expression = h5_expression, - verbose = verbose) - - - # 2. load in data - - # data_list contents: - # feat_meta - # tx_dt - # bound_dt_list - # cell_meta - # agg_expr - data_list = load_xenium_folder(path_list = path_list, - load_format = load_format, - data_to_use = data_to_use, - h5_expression = h5_expression, - h5_gene_ids = h5_gene_ids, - gene_column_index = gene_column_index, - cores = cores, - verbose = verbose) - - - # TODO load images - - - # 3. Create giotto objects - - if(data_to_use == 'subcellular') { - - # ** feat type search keys ** - if(is.null(key_list)) { - key_list = list(blank_code = 'BLANK_', - neg_code = 'NegControlCodeword_', - neg_probe = c('NegControlProbe_|antisense_')) - } - - # needed: - # feat_meta - # tx_dt - # bound_dt_list - xenium_gobject = createGiottoXeniumObject_subcellular(data_list = data_list, - qv_threshold = qv_threshold, - key_list = key_list, - instructions = instructions, - cores = cores, - verbose = verbose) - - } - - if(data_to_use == 'aggregate') { - - # needed: - # feat_meta - # cell_meta - # agg_expr - # optional? - # tx_dt - # bound_dt_list - xenium_gobject = createGiottoXeniumObject_aggregate(data_list = data_list, - instructions = instructions, - cores = cores, - verbose = verbose) - - } - - return(xenium_gobject) - -} - - - - -#' @title Create a Xenium Giotto object from subcellular info -#' @name createGiottoXeniumObject_subcellular -#' @description Subcellular workflow for createGiottoXeniumObject -#' @param data_list list of data loaded by \code{\link{load_xenium_folder}} -#' @param key_list regex-based search keys for feature IDs to allow separation -#' into separate giottoPoints objects by feat_type -#' @param qv_threshold Minimum Phred-scaled quality score cutoff to be included as -#' a subcellular transcript detection (default = 20) -#' @inheritParams get10Xmatrix -#' @inheritParams createGiottoObjectSubcellular -#' @seealso createGiottoXeniumObject createGiottoXeniumObject_aggregate -#' @keywords internal -createGiottoXeniumObject_subcellular = function(data_list, - key_list = NULL, - qv_threshold = 20, - instructions = NULL, - cores = NA, - verbose = TRUE) { - - # data.table vars - qv = NULL - - # Unpack data_list info - feat_meta = data_list$feat_meta - tx_dt = data_list$tx_dt - bound_dt_list = data_list$bound_dt_list - # cell_meta = data_list$cell_meta - # agg_expr = data_list$agg_expr - - # define for data.table - cell_id = feat_ID = feature_name = NULL - - if(isTRUE(verbose)) message('Building subcellular giotto object...') - # Giotto points object - if(isTRUE(verbose)) message('> points data prep...') - - # filter by qv_threshold - if(isTRUE(verbose)) wrap_msg('> filtering feature detections for Phred score >= ', qv_threshold) - n_before = tx_dt[,.N] - tx_dt_filtered = tx_dt[qv >= qv_threshold] - n_after = tx_dt_filtered[,.N] - - cat('Number of feature points removed: ', - n_before - n_after, - ' out of ', n_before, '\n') - - if(isTRUE(verbose)) message('> splitting detections by feat_type') - # discover feat_IDs for each feat_type - all_IDs = tx_dt_filtered[, unique(feat_ID)] - feat_types_IDs = lapply(key_list, function(x) all_IDs[grepl(pattern = x, all_IDs)]) - rna = list('rna' = all_IDs[!all_IDs %in% unlist(feat_types_IDs)]) - feat_types_IDs = append(rna, feat_types_IDs) - - # separate detections by feature type - points_list = lapply( - feat_types_IDs, - function(types) { - tx_dt_filtered[feat_ID %in% types] - } - ) - - # Giotto polygons object - if(isTRUE(verbose)) message('> polygons data prep...') - polys_list = lapply( - bound_dt_list, - function(bound_type) { - bound_type[, cell_id := as.character(cell_id)] - } - ) - - xenium_gobject = createGiottoObjectSubcellular(gpoints = points_list, - gpolygons = polys_list, - instructions = instructions, - cores = cores, - verbose = verbose) - - # generate centroids - if(isTRUE(verbose)) message('Calculating polygon centroids...') - xenium_gobject = addSpatialCentroidLocations(xenium_gobject, - poly_info = c(names(bound_dt_list))) - - # add in feature metadata - # xenium_gobject = addFeatMetadata(gobject = xenium_gobject, - # new_metadata = feat_meta, - # by_column = TRUE, - # column_feat_ID = 'feat_ID') - - return(xenium_gobject) - -} - - - - - -#' @title Create a Xenium Giotto object from aggregate info -#' @name createGiottoXeniumObject_aggregate -#' @description Aggregate workflow for createGiottoXeniumObject -#' @param data_list list of data loaded by \code{load_xenium_folder} -#' @inheritParams get10Xmatrix -#' @inheritParams createGiottoObjectSubcellular -#' @seealso createGiottoXeniumObject createGiottoXeniumObject_subcellular -#' @keywords internal -createGiottoXeniumObject_aggregate = function(data_list, - # include_analysis = FALSE, - instructions = NULL, - cores = NA, - verbose = TRUE) { - - # Unpack data_list info - feat_meta = data_list$feat_meta - # tx_dt = data_list$tx_dt - # bound_dt_list = data_list$bound_dt_list - cell_meta = data_list$cell_meta - agg_expr = data_list$agg_expr - - # define for data.table - cell_ID = x_centroid = y_centroid = NULL - - # clean up names for aggregate matrices - names(agg_expr) = gsub(pattern = ' ', replacement = '_' ,names(agg_expr)) - geneExpMat = which(names(agg_expr) == 'Gene_Expression') - names(agg_expr)[[geneExpMat]] = 'raw' - - # set cell_id as character - cell_meta = cell_meta[, data.table::setnames(.SD, 'cell_id', 'cell_ID')] - cell_meta = cell_meta[, cell_ID := as.character(cell_ID)] - - # set up spatial locations - agg_spatlocs = cell_meta[, .(x_centroid, y_centroid, cell_ID)] - - # set up metadata - agg_meta = cell_meta[, !c('x_centroid','y_centroid')] - - if(isTRUE(verbose)) message('Building aggregate giotto object...') - xenium_gobject = createGiottoObject(expression = agg_expr, - spatial_locs = agg_spatlocs, - instructions = instructions, - cores = cores, - verbose = verbose) - - # append aggregate metadata - xenium_gobject = addCellMetadata(gobject = xenium_gobject, - new_metadata = agg_meta, - by_column = TRUE, - column_cell_ID = 'cell_ID') - xenium_gobject = addFeatMetadata(gobject = xenium_gobject, - new_metadata = feat_meta, - by_column = TRUE, - column_feat_ID = 'feat_ID') - - return(xenium_gobject) - -} - - - - - - - -# folder reading and detection #### - - - - -#' @describeIn read_data_folder Read a structured MERSCOPE folder -#' @keywords internal -read_merscope_folder = function(merscope_dir, - data_to_use, - cores = NA, - verbose = TRUE) { - - # prepare dir_items list - dir_items = list(`boundary info` = '*cell_boundaries*', - `image info` = '*images*', - `cell feature matrix` = '*cell_by_gene*', - `cell metadata` = '*cell_metadata*', - `raw transcript info` = '*transcripts*') - - # prepare require_data_DT - sub_reqs = data.table::data.table(workflow = c('subcellular'), - item = c('boundary info', - 'raw transcript info', - 'image info', - 'cell by gene matrix', - 'cell metadata'), - needed = c(TRUE, TRUE, FALSE, FALSE, FALSE)) - - agg_reqs = data.table::data.table(workflow = c('aggregate'), - item = c('boundary info', - 'raw transcript info', - 'image info', - 'cell by gene matrix', - 'cell metadata'), - needed = c(FALSE, FALSE, FALSE, TRUE, TRUE)) - - require_data_DT = rbind(sub_reqs, agg_reqs) - - dir_items = read_data_folder(spat_method = 'MERSCOPE', - data_dir = merscope_dir, - dir_items = dir_items, - data_to_use = data_to_use, - require_data_DT = require_data_DT, - cores = cores, - verbose = verbose) - - return(dir_items) - -} - - - -#' @title Read a structured CosMx folder -#' @name read_cosmx_folder -#' @inheritParams createGiottoCosMxObject -#' @seealso createGiottoCosMxObject load_cosmx_folder -#' @return path_list a list of cosmx files discovered and their filepaths. NULL -#' values denote missing items -#' @keywords internal -read_cosmx_folder = function(cosmx_dir, - verbose = TRUE) { - - ch = box_chars() - - if(is.null(cosmx_dir) | !dir.exists(cosmx_dir)) stop('The full path to a cosmx directory must be given.\n') - if(isTRUE(verbose)) wrap_msg('A structured CosMx directory will be used\n') - - # find directories (length = 1 if present, length = 0 if missing) - dir_items = list(`CellLabels folder` = '*CellLabels', - `CompartmentLabels folder` = '*CompartmentLabels', - `CellComposite folder` = '*CellComposite', - `CellOverlay folder` = '*CellOverlay', - `transcript locations file` = '*tx_file*', - `fov positions file` = '*fov_positions_file*', - `expression matrix file` = '*exprMat_file*', - `metadata file` = '*metadata_file*') - dir_items = lapply(dir_items, function(x) Sys.glob(paths = file.path(cosmx_dir, x))) - dir_items_lengths = lengths(dir_items) - - if(isTRUE(verbose)) { - message('Checking directory contents...') - for(item in names(dir_items)) { - if(dir_items_lengths[[item]] > 0) { - message(ch$s, '> ' ,item, ' found') - } else { - warning(item, ' is missing\n') - } - } - } - - # select first directory in list if multiple are detected - if(any(dir_items_lengths > 1)) { - warning('Multiple matches for expected subdirectory item(s).\n First matching item selected') - - multiples = which(dir_items_lengths > 1) - for(mult_i in multiples) { - message(names(dir_items)[[mult_i]], 'multiple matches found:') - print(dir_items[[mult_i]]) - dir_items[[mult_i]] = dir_items[[mult_i]][[1]] - } - } - if(isTRUE(verbose)) message('Directory check done') - - return(dir_items) - -} - - - - -#' @title Read a structured xenium folder -#' @name read_xenium_folder -#' @inheritParams createGiottoXeniumObject -#' @keywords internal -#' @return path_list a list of xenium files discovered and their filepaths. NULL -#' values denote missing items -read_xenium_folder = function(xenium_dir, - data_to_use = 'subcellular', - bounds_to_load = c('cell'), - load_format = 'csv', - h5_expression = FALSE, - verbose = TRUE) { - - # Check needed packages - if(load_format == 'parquet') { - package_check(pkg_name = 'arrow', repository = 'CRAN') - package_check(pkg_name = 'dplyr', repository = 'CRAN') - } - if(isTRUE(h5_expression)) { - package_check(pkg_name = 'hdf5r', repository = 'CRAN') - } - - ch = box_chars() - - - # 0. test if folder structure exists and is as expected - - - if(is.null(xenium_dir) | !dir.exists(xenium_dir)) stop('The full path to a xenium directory must be given.\n') - if(isTRUE(verbose)) message('A structured Xenium directory will be used\n') - - # find items (length = 1 if present, length = 0 if missing) - dir_items = list(`analysis info` = '*analysis*', - `boundary info` = '*bound*', - `cell feature matrix` = '*cell_feature_matrix*', - `cell metadata` = '*cells*', - `image info` = '*tif', - `panel metadata` = '*panel*', - `raw transcript info` = '*transcripts*', - `experiment info (.xenium)` = '*.xenium') - - dir_items = lapply(dir_items, function(x) Sys.glob(paths = file.path(xenium_dir, x))) - dir_items_lengths = lengths(dir_items) - - if(isTRUE(verbose)) { - message('Checking directory contents...') - for(item in names(dir_items)) { - - # IF ITEM FOUND - - if(dir_items_lengths[[item]] > 0) { - message(ch$s, '> ' ,item, ' found') - for(item_i in seq_along(dir_items[[item]])) { # print found item names - subItem = gsub(pattern = '.*/', replacement = '', x = dir_items[[item]][[item_i]]) - message(ch$s, ch$s, ch$l,ch$h,ch$h, subItem) - } - } else { - - # IF ITEM MISSING - # Based on workflow, determine if: - # necessary (error) - # optional (warning) - - if(data_to_use == 'subcellular') { - # necessary items - if(item %in% c('boundary info', 'raw transcript info')) stop(item, ' is missing\n') - # optional items - if(item %in% c('image info', 'experiment info (.xenium)', 'panel metadata')) warning(item, ' is missing (optional)\n') - # items to ignore: analysis info, cell feature matrix, cell metadata - } else if(data_to_use == 'aggregate') { - # necessary items - if(item %in% c('cell feature matrix', 'cell metadata')) stop(item, ' is missing\n') - # optional items - if(item %in% c('image info', 'experiment info (.xenium)', 'panel metadata', 'analysis info')) warning(item, ' is missing (optional)\n') - # items to ignore: boundary info, raw transcript info - } - } - } - } - - - # 1. Select data to load - - - # **** transcript info **** - tx_path = NULL - tx_path = dir_items$`raw transcript info`[grepl(pattern = load_format, dir_items$`raw transcript info`)] - # **** cell metadata **** - cell_meta_path = NULL - cell_meta_path = dir_items$`cell metadata`[grepl(pattern = load_format, dir_items$`cell metadata`)] - - # **** boundary info **** - # Select bound load format - if(load_format != 'zarr') { # No zarr available for boundary info - dir_items$`boundary info` = dir_items$`boundary info`[grepl(pattern = load_format, dir_items$`boundary info`)] - } else dir_items$`boundary info` = dir_items$`boundary info`[grepl(pattern = 'csv', dir_items$`boundary info`)] - - # Organize bound paths by type of bound (bounds_to_load param) - bound_paths = NULL - bound_names = bounds_to_load - bounds_to_load = as.list(bounds_to_load) - bound_paths = lapply(bounds_to_load, function(x) dir_items$`boundary info`[grepl(pattern = x, dir_items$`boundary info`)]) - names(bound_paths) = bound_names - - # **** aggregated expression info **** - agg_expr_path = NULL - if(isTRUE(h5_expression)) { # h5 expression matrix loading is default - agg_expr_path = dir_items$`cell feature matrix`[grepl(pattern = 'h5', dir_items$`cell feature matrix`)] - h5_gene_ids = match.arg(arg = h5_gene_ids, choices = c('symbols', 'ensembl')) - } else if(load_format == 'zarr') { - agg_expr_path = dir_items$`cell feature matrix`[grepl(pattern = 'zarr', dir_items$`cell feature matrix`)] - } else { # No parquet for aggregated expression - default to normal 10x loading - agg_expr_path = dir_items$`cell feature matrix`[sapply(dir_items$`cell feature matrix`, function(x) file_test(op = '-d', x))] - if(length(agg_expr_path) == 0) stop(wrap_txt( - 'Expression matrix cannot be loaded.\nHas cell_feature_matrix(.tar.gz) been unpacked into a directory?' - )) - } - if(data_to_use == 'aggregate') { - if(length(path_list$agg_expr_path) == 0) stop(wrap_txt( - 'Aggregated expression not found.\nPlease confirm h5_expression and load_format params are correct\n' - )) - } - - # **** panel info **** - panel_meta_path = NULL - panel_meta_path = dir_items$`panel metadata` - - - if(isTRUE(verbose)) message('Directory check done') - - path_list = list('tx_path' = tx_path, - 'bound_paths' = bound_paths, - 'cell_meta_path' = cell_meta_path, - 'agg_expr_path' = agg_expr_path, - 'panel_meta_path' = panel_meta_path) - - return(path_list) - -} - - - - - - -# folder loading #### - - -## MERSCOPE #### - -#' @title Load MERSCOPE data from folder -#' @name load_merscope_folder -#' @param dir_items list of full filepaths from \code{\link{read_merscope_folder}} -#' @inheritParams createGiottoMerscopeObject -#' @keywords internal -#' @return list of loaded-in MERSCOPE data -load_merscope_folder = function(dir_items, - data_to_use, - FOVs = NULL, - polygon_feat_types = 0:6, - cores = NA, - verbose = TRUE) { - - # 1. load data_to_use-specific - if(data_to_use == 'subcellular') { - data_list = load_merscope_folder_subcellular(dir_items = dir_items, - data_to_use = data_to_use, - FOVs = FOVs, - polygon_feat_types = polygon_feat_types, - cores = cores, - verbose = verbose) - } else if(data_to_use == 'aggregate') { - data_list = load_merscope_folder_aggregate(dir_items = dir_items, - data_to_use = data_to_use, - cores = cores, - verbose = verbose) - } else { - stop(wrap_txt('data_to_use "', data_to_use, '" not implemented', sep = '')) - } - - # 2. Load images if available - if(!is.null(dir_items$`image info`)) { - ## micron to px scaling factor - micronToPixelScale = Sys.glob(paths = file.path(dir_items$`image info`, '*micron_to_mosaic_pixel_transform*'))[[1]] - micronToPixelScale = data.table::fread(micronToPixelScale, nThread = cores) - # add to data_list - data_list$micronToPixelScale = micronToPixelScale - - ## staining images - ## determine types of stains - images_filenames = list.files(dir_items$`image info`) - bound_stains_filenames = images_filenames[grep(pattern = '.tif', images_filenames)] - bound_stains_types = sapply(strsplit(bound_stains_filenames, '_'), `[`, 2) - bound_stains_types = unique(bound_stains_types) - - img_list = lapply_flex(bound_stains_types, function(stype) { - img_paths = Sys.glob(paths = file.path(dir_items$`image info`, paste0('*',stype,'*'))) - # print(img_paths) - lapply_flex(img_paths, function(img) { - createGiottoLargeImage(raster_object = img) - }, cores = cores) - }, cores = cores) - # add to data_list - data_list$images = img_list - } - - - - return(data_list) - -} - - - -#' @describeIn load_merscope_folder Load items for 'subcellular' workflow -#' @keywords internal -load_merscope_folder_subcellular = function(dir_items, - data_to_use, - polygon_feat_types = 0:6, - cores = NA, - verbose = TRUE, - FOVs = NULL) { - - if(isTRUE(verbose)) wrap_msg('Loading transcript level info...') - if(is.null(FOVs)) { - tx_dt = data.table::fread(dir_items$`raw transcript info`, nThread = cores) - } else { - if(isTRUE(verbose)) wrap_msg('Selecting FOV subset transcripts') - tx_dt = fread_colmatch(file = dir_items$`raw transcript info`, - col = 'fov', - values_to_match = FOVs, - verbose = FALSE, - nThread = cores) - } - tx_dt[, c('x','y') := NULL] # remove unneeded cols - data.table::setcolorder(tx_dt, c('gene', 'global_x', 'global_y', 'global_z')) - - if(isTRUE(verbose)) wrap_msg('Loading polygon info...') - poly_info = readPolygonFilesVizgenHDF5(boundaries_path = dir_items$`boundary info`, - polygon_feat_types = polygon_feat_types, - flip_y_axis = TRUE, - fovs = FOVs) - - data_list = list( - 'poly_info' = poly_info, - 'tx_dt' = tx_dt, - 'micronToPixelScale' = NULL, - 'expr_dt' = NULL, - 'cell_meta' = NULL, - 'images' = NULL - ) - -} - - - -#' @describeIn load_merscope_folder Load items for 'aggregate' workflow -#' @keywords internal -load_merscope_folder_aggregate = function(dir_items, - data_to_use, - cores = NA, - verbose = TRUE) { - - # metadata is polygon-related measurements - if(isTRUE(verbose)) wrap_msg('Loading cell metadata...') - cell_metadata_file = data.table::fread(dir_items$`cell metadata`, nThread = cores) - - if(isTRUE(verbose)) wrap_msg('Loading expression matrix') - expr_dt = data.table::fread(dir_items$`cell feature matrix`, nThread = cores) - - - data_list = list( - 'poly_info' = NULL, - 'tx_dt' = NULL, - 'micronToPixelScale' = NULL, - 'expr_dt' = expr_dt, - 'cell_meta' = cell_metadata_file, - 'images' = NULL - ) - -} - - - - - - - -## CosMx #### - -#' @title Load CosMx folder subcellular info -#' @name load_cosmx_folder_subcellular -#' @description loads in the feature detections information. Note that the mask -#' images are still required for a working subcellular object, and those are loaded -#' in \code{\link{createGiottoCosMxObject_subcellular}} -#' @inheritParams createGiottoCosMxObject -#' @keywords internal -load_cosmx_folder_subcellular = function(dir_items, - FOVs = NULL, - cores, - verbose = TRUE) { - - if(isTRUE(verbose)) wrap_msg('Loading subcellular information...') - - # subcellular checks - if(!file.exists(dir_items$`transcript locations file`)) - stop(wrap_txt('No transcript locations file (.csv) detected')) - if(!file.exists(dir_items$`fov positions file`)) - stop(wrap_txt('No fov positions file (.csv) detected')) - - # FOVs to load - if(isTRUE(verbose)) wrap_msg('Loading FOV offsets...') - fov_offset_file = fread(input = dir_items$`fov positions file`, nThread = cores) - if(is.null(FOVs)) FOVs = fov_offset_file$fov # default to ALL FOVs - FOV_ID = as.list(sprintf('%03d', FOVs)) - - #TODO Load only relevant portions of file? - - if(isTRUE(verbose)) wrap_msg('Loading transcript level info...') - tx_coord_all = fread(input = dir_items$`transcript locations file`, nThread = cores) - if(isTRUE(verbose)) wrap_msg('Subcellular load done') - - data_list = list( - 'FOV_ID' = FOV_ID, - 'fov_offset_file' = fov_offset_file, - 'tx_coord_all' = tx_coord_all - ) - - return(data_list) - -} - - - -#' @title Load CosMx folder aggregate info -#' @name load_cosmx_folder_aggregate -#' @inheritParams createGiottoCosMxObject -#' @keywords internal -load_cosmx_folder_aggregate = function(dir_items, - cores, - verbose = TRUE) { - - # data.table vars - fov = cell_ID = fov_cell_ID = CenterX_global_px = CenterY_global_px = CenterX_local_px = - CenterY_local_px = x_shift = y_shift = NULL - - # load aggregate information - wrap_msg('Loading provided aggregated information...') - - # aggregate checks - if(!file.exists(dir_items$`expression matrix file`)) stop(wrap_txt('No expression matrix file (.csv) detected')) - if(!file.exists(dir_items$`metadata file`)) stop(wrap_txt('No metadata file (.csv) detected. Needed for cell spatial locations.')) - - # read in aggregate data - expr_mat = fread(input = dir_items$`expression matrix file`, nThread = cores) - metadata = fread(input = dir_items$`metadata file`, nThread = cores) - - # setorder expression and spatlocs - data.table::setorder(metadata, fov, cell_ID) - data.table::setorder(expr_mat, fov, cell_ID) - - - # generate unique cell IDs - expr_mat[, cell_ID := paste0('fov', sprintf('%03d', fov), '-', 'cell_', cell_ID)] - # expr_mat$cell_ID = paste0('fov', sprintf('%03d', expr_mat$fov), '-', 'cell_', expr_mat$cell_ID) - expr_mat = expr_mat[, fov := NULL] - - metadata[, fov_cell_ID := cell_ID] - metadata[, cell_ID := paste0('fov', sprintf('%03d', fov), '-', 'cell_', cell_ID)] - # metadata$cell_ID = paste0('fov', sprintf('%03d', metadata$fov), '-', 'cell_', metadata$cell_ID) - # reorder - data.table::setcolorder(x = metadata, c('cell_ID','fov','fov_cell_ID')) - - - # extract spatial locations - spatlocs = metadata[,.(CenterX_global_px, CenterY_global_px, cell_ID)] - spatlocs_fov = metadata[,.(CenterX_local_px, CenterY_local_px, cell_ID)] - # regenerate FOV shifts - metadata[, x_shift := CenterX_global_px - CenterX_local_px] - metadata[, y_shift := CenterY_global_px - CenterY_local_px] - fov_shifts = metadata[, .(mean(x_shift), mean(y_shift)), fov] - colnames(fov_shifts) = c('fov', 'x_shift', 'y_shift') - - - # rename spatloc column names - spatloc_oldnames = c('CenterX_global_px', 'CenterY_global_px', 'cell_ID') - spatloc_oldnames_fov = c('CenterX_local_px', 'CenterY_local_px', 'cell_ID') - spatloc_newnames = c('sdimx', 'sdimy', 'cell_ID') - data.table::setnames(spatlocs, old = spatloc_oldnames, new = spatloc_newnames) - data.table::setnames(spatlocs_fov, old = spatloc_oldnames_fov, new = spatloc_newnames) - - # cleanup metadata and spatlocs - metadata = metadata[,c('CenterX_global_px', 'CenterY_global_px', 'CenterX_local_px', 'CenterY_local_px') := NULL] - # find unique cell_IDs present in both expression and metadata - giotto_cell_ID = unique(intersect(expr_mat$cell_ID, metadata$cell_ID)) - - # subset to only unique cell_IDs - expr_mat = expr_mat[cell_ID %in% giotto_cell_ID,] - metadata = metadata[cell_ID %in% giotto_cell_ID,] - - - # convert protein metadata to expr mat - # take all mean intensity protein information except for MembraneStain and DAPI - protein_meta_cols = colnames(metadata) - protein_meta_cols = protein_meta_cols[grepl(pattern = 'Mean.*', x = protein_meta_cols)] - protein_meta_cols = protein_meta_cols[!protein_meta_cols %in% c('Mean.MembraneStain', 'Mean.DAPI')] - protein_meta_cols = c('cell_ID', protein_meta_cols) - - prot_expr = metadata[, protein_meta_cols, with = FALSE] - prot_cell_ID = metadata[, cell_ID] - protM = Matrix::Matrix(as.matrix(prot_expr[,-1]), dimnames = list(prot_expr[[1]], colnames(prot_expr[,-1])), sparse = FALSE) - protM = t_flex(protM) - - # convert expression to sparse matrix - spM = Matrix::Matrix(as.matrix(expr_mat[,-1]), dimnames = list(expr_mat[[1]], colnames(expr_mat[,-1])), sparse = TRUE) - spM = t_flex(spM) - - ## Ready for downstream aggregate gobject creation or appending into existing subcellular Giotto object ## - - data_list = list( - 'spatlocs' = spatlocs, - 'spatlocs_fov' = spatlocs_fov, - 'metadata' = metadata, - 'protM' = protM, - 'spM' = spM, - 'fov_shifts' = fov_shifts - ) - - return(data_list) - -} - - - - - - - -## Xenium #### - -#' @title Load xenium data from folder -#' @name load_xenium_folder -#' @param path_list list of full filepaths from read_xenium_folder -#' @inheritParams createGiottoXeniumObject -#' @keywords internal -#' @return list of loaded in xenium data -load_xenium_folder = function(path_list, - load_format = 'csv', - data_to_use = 'subcellular', - h5_expression = 'FALSE', - h5_gene_ids = 'symbols', - gene_column_index = 1, - cores, - verbose = TRUE) { - - if(load_format == 'csv') { - data_list = load_xenium_folder_csv(path_list = path_list, - data_to_use = data_to_use, - h5_expression = h5_expression, - h5_gene_ids = h5_gene_ids, - gene_column_index = gene_column_index, - cores = cores, - verbose = verbose) - } - - if(load_format == 'parquet') { - data_list = load_xenium_folder_parquet(path_list = path_list, - data_to_use = data_to_use, - h5_expression = h5_expression, - h5_gene_ids = h5_gene_ids, - gene_column_index = gene_column_index, - cores = cores, - verbose = verbose) - } - - if(load_format == 'zarr') { - # TODO - } - - - return(data_list) -} - - -#' @describeIn load_xenium_folder Load from csv files -#' @keywords internal -load_xenium_folder_csv = function(path_list, - cores, - data_to_use = 'subcellular', - h5_expression = FALSE, - h5_gene_ids = 'symbols', - gene_column_index = 1, - verbose = TRUE) { - - # initialize return vars - feat_meta = tx_dt = bound_dt_list = cell_meta = agg_expr = NULL - - if(isTRUE(verbose)) message('Loading feature metadata...') - feat_meta = data.table::fread(path_list$panel_meta_path[[1]], nThread = cores) - colnames(feat_meta)[[1]] = 'feat_ID' - - # **** subcellular info **** - if(data_to_use == 'subcellular') { - # append missing QC probe info to feat_meta - if(isTRUE(h5_expression)) { - h5 = hdf5r::H5File$new(path_list$agg_expr_path) - tryCatch({ - root = names(h5) - feature_id = h5[[paste0(root, "/features/id")]][] - feature_info = h5[[paste0(root,"/features/feature_type")]][] - feature_names = h5[[paste0(root, "/features/name")]][] - features_dt = data.table::data.table( - 'id' = feature_id, - 'name' = feature_names, - 'feature_type' = feature_info - ) - }, finally = { - h5$close_all() - }) - } else { - features_dt = data.table::fread(paste0(path_list$agg_expr_path, '/features.tsv.gz'), header = F) - } - colnames(features_dt) = c('id', 'feat_ID', 'feat_class') - feat_meta = merge(features_dt[,c(2,3)], feat_meta, all.x = TRUE, by = 'feat_ID') - - if(isTRUE(verbose)) message('Loading transcript level info...') - tx_dt = data.table::fread(path_list$tx_path[[1]], nThread = cores) - data.table::setnames(x = tx_dt, - old = c('feature_name', 'x_location', 'y_location'), - new = c('feat_ID', 'x', 'y')) - if(isTRUE(verbose)) message('Loading boundary info...') - bound_dt_list = lapply(path_list$bound_paths, function(x) data.table::fread(x[[1]], nThread = cores)) - } - - # **** aggregate info **** - if(isTRUE(verbose)) message('Loading cell metadata...') - cell_meta = data.table::fread(path_list$cell_meta_path[[1]], nThread = cores) - - if(data_to_use == 'aggregate') { - if(isTRUE(verbose)) message('Loading aggregated expression...') - if(isTRUE(h5_expression)) agg_expr = get10Xmatrix_h5(path_to_data = path_list$agg_expr_path, - gene_ids = h5_gene_ids, - remove_zero_rows = TRUE, - split_by_type = TRUE) - else agg_expr = get10Xmatrix(path_to_data = path_list$agg_expr_path, - gene_column_index = gene_column_index, - remove_zero_rows = TRUE, - split_by_type = TRUE) - } - - data_list = list( - 'feat_meta' = feat_meta, - 'tx_dt' = tx_dt, - 'bound_dt_list' = bound_dt_list, - 'cell_meta' = cell_meta, - 'agg_expr' = agg_expr - ) - - return(data_list) - -} - - - - -#' @describeIn load_xenium_folder Load from parquet files -#' @keywords internal -load_xenium_folder_parquet = function(path_list, - cores, - data_to_use = 'subcellular', - h5_expression = FALSE, - h5_gene_ids = 'symbols', - gene_column_index = 1, - verbose = TRUE) { - - # initialize return vars - feat_meta = tx_dt = bound_dt_list = cell_meta = agg_expr = NULL - # dplyr variable - cell_id = NULL - - if(isTRUE(verbose)) message('Loading feature metadata...') - feat_meta = data.table::fread(path_list$panel_meta_path[[1]], nThread = cores) - colnames(feat_meta)[[1]] = 'feat_ID' - - # **** subcellular info **** - if(data_to_use == 'subcellular') { - - # define for data.table - transcript_id = feature_name = NULL - - # append missing QC probe info to feat_meta - if(isTRUE(h5_expression)) { - h5 = hdf5r::H5File$new(path_list$agg_expr_path) - tryCatch({ - root = names(h5) - feature_id = h5[[paste0(root, "/features/id")]][] - feature_info = h5[[paste0(root,"/features/feature_type")]][] - feature_names = h5[[paste0(root, "/features/name")]][] - features_dt = data.table::data.table( - 'id' = feature_id, - 'name' = feature_names, - 'feature_type' = feature_info - ) - }, finally = { - h5$close_all() - }) - } else { - features_dt = arrow::read_tsv_arrow(paste0(path_list$agg_expr_path, '/features.tsv.gz'), - col_names = FALSE) %>% - data.table::setDT() - } - colnames(features_dt) = c('id', 'feat_ID', 'feat_class') - feat_meta = merge(features_dt[,c(2,3)], feat_meta, all.x = TRUE, by = 'feat_ID') - - if(isTRUE(verbose)) message('Loading transcript level info...') - tx_dt = arrow::read_parquet(file = path_list$tx_path[[1]], as_data_frame = FALSE) %>% - dplyr::mutate(transcript_id = cast(transcript_id, arrow::string())) %>% - dplyr::mutate(cell_id = cast(cell_id, arrow::string())) %>% - dplyr::mutate(feature_name = cast(feature_name, arrow::string())) %>% - as.data.frame() %>% - data.table::setDT() - data.table::setnames(x = tx_dt, - old = c('feature_name', 'x_location', 'y_location'), - new = c('feat_ID', 'x', 'y')) - if(isTRUE(verbose)) message('Loading boundary info...') - bound_dt_list = lapply(path_list$bound_paths, function(x) { - arrow::read_parquet(file = x[[1]], as_data_frame = FALSE) %>% - dplyr::mutate(cell_id = cast(cell_id, arrow::string())) %>% - as.data.frame() %>% - data.table::setDT()}) - } - # **** aggregate info **** - if(data_to_use == 'aggregate') { - if(isTRUE(verbose)) message('Loading cell metadata...') - cell_meta = arrow::read_parquet(file = path_list$cell_meta_path[[1]], as_data_frame = FALSE) %>% - dplyr::mutate(cell_id = cast(cell_id, arrow::string())) %>% - as.data.frame() %>% - data.table::setDT() - - # NOTE: no parquet for agg_expr. - if(isTRUE(verbose)) message('Loading aggregated expression...') - if(isTRUE(h5_expression)) agg_expr = get10Xmatrix_h5(path_to_data = path_list$agg_expr_path, - gene_ids = h5_gene_ids, - remove_zero_rows = TRUE, - split_by_type = TRUE) - else agg_expr = get10Xmatrix(path_to_data = path_list$agg_expr_path, - gene_column_index = gene_column_index, - remove_zero_rows = TRUE, - split_by_type = TRUE) - } - - data_list = list( - 'feat_meta' = feat_meta, - 'tx_dt' = tx_dt, - 'bound_dt_list' = bound_dt_list, - 'cell_meta' = cell_meta, - 'agg_expr' = agg_expr - ) - - return(data_list) - -} diff --git a/man/createGiottoCosMxObject.Rd b/man/createGiottoCosMxObject.Rd index db98a4e3c..72996db2d 100644 --- a/man/createGiottoCosMxObject.Rd +++ b/man/createGiottoCosMxObject.Rd @@ -1,21 +1,12 @@ % Generated by roxygen2: do not edit by hand -% Please edit documentation in R/convenience.R, R/convenience_create.R +% Please edit documentation in R/convenience.R \name{createGiottoCosMxObject} \alias{createGiottoCosMxObject} \title{Create Nanostring CosMx Giotto Object} \usage{ createGiottoCosMxObject( cosmx_dir = NULL, - data_to_use = c("subcellular"), - FOVs = NULL, - instructions = NULL, - cores = NA, - verbose = TRUE -) - -createGiottoCosMxObject( - cosmx_dir = NULL, - data_to_use = c("subcellular"), + data_to_use = c("all", "subcellular", "aggregate"), FOVs = NULL, instructions = NULL, cores = NA, @@ -38,14 +29,9 @@ coordinates only. \code{'aggregate'} loads the provided aggregated expression ma \item{verbose}{be verbose when building Giotto object} } \value{ -a giotto object - a giotto object } \description{ -Given the path to a CosMx experiment directory, creates a Giotto -object. - Given the path to a CosMx experiment directory, creates a Giotto object. } @@ -75,37 +61,6 @@ where the \strong{bolded} portions are what this function matches against: spatial locations, and metadata) from exprMat_file and metadata_file.} } -[\strong{Images}] Images in the default CellComposite, CellLabels, CompartmentLabels, and CellOverlay -folders will be loaded as giotto largeImage objects in all workflows as long as they are available. -Additionally, CellComposite images will be converted to giotto image objects, making plotting with -these image objects more responsive when accessing them from a server. -\code{\link{showGiottoImageNames}} can be used to see the available images. - -[\strong{Expected Directory}] This function generates a giotto object when given a -link to a cosmx output directory. It expects the following items within the directory -where the \strong{bolded} portions are what this function matches against: -\itemize{ - \item{\strong{CellComposite} (folder of images)} - \item{\strong{CellLabels} (folder of images)} - \item{\strong{CellOverlay} (folder of images)} - \item{\strong{CompartmentLabels} (folder of images)} - \item{experimentname_\strong{exprMat_file}.csv (file)} - \item{experimentname_\strong{fov_positions_file}.csv (file)} - \item{experimentname_\strong{metadata_file}.csv (file)} - \item{experimentname_\strong{tx_file}.csv (file)} -} - -[\strong{Workflows}] Workflow to use is accessed through the data_to_use param -\itemize{ - \item{'all' - loads and requires subcellular information from tx_file and fov_positions_file - and also the existing aggregated information (expression, spatial locations, and metadata) - from exprMat_file and metadata_file.} - \item{'subcellular' - loads and requires subcellular information from tx_file and - fov_positions_file only.} - \item{'aggregate' - loads and requires the existing aggregate information (expression, - spatial locations, and metadata) from exprMat_file and metadata_file.} -} - [\strong{Images}] Images in the default CellComposite, CellLabels, CompartmentLabels, and CellOverlay folders will be loaded as giotto largeImage objects in all workflows as long as they are available. Additionally, CellComposite images will be converted to giotto image objects, making plotting with diff --git a/man/createGiottoCosMxObject_aggregate.Rd b/man/createGiottoCosMxObject_aggregate.Rd index 75dd97e65..564e4fc51 100644 --- a/man/createGiottoCosMxObject_aggregate.Rd +++ b/man/createGiottoCosMxObject_aggregate.Rd @@ -1,16 +1,9 @@ % Generated by roxygen2: do not edit by hand -% Please edit documentation in R/convenience.R, R/convenience_create.R +% Please edit documentation in R/convenience.R \name{createGiottoCosMxObject_aggregate} \alias{createGiottoCosMxObject_aggregate} \title{Load and create a CosMx Giotto object from aggregate info} \usage{ -createGiottoCosMxObject_aggregate( - dir_items, - cores, - verbose = TRUE, - instructions = NULL -) - createGiottoCosMxObject_aggregate( dir_items, cores, @@ -26,8 +19,6 @@ createGiottoCosMxObject_aggregate( \item{instructions}{list of instructions or output result from \code{\link{createGiottoInstructions}}} } \description{ -Load and create a CosMx Giotto object from aggregate info - Load and create a CosMx Giotto object from aggregate info } \keyword{internal} diff --git a/man/createGiottoCosMxObject_all.Rd b/man/createGiottoCosMxObject_all.Rd index 1b3c93bae..82b37250c 100644 --- a/man/createGiottoCosMxObject_all.Rd +++ b/man/createGiottoCosMxObject_all.Rd @@ -1,17 +1,9 @@ % Generated by roxygen2: do not edit by hand -% Please edit documentation in R/convenience.R, R/convenience_create.R +% Please edit documentation in R/convenience.R \name{createGiottoCosMxObject_all} \alias{createGiottoCosMxObject_all} \title{Load and create a CosMx Giotto object from subcellular and aggregate info} \usage{ -createGiottoCosMxObject_all( - dir_items, - FOVs, - cores, - verbose = TRUE, - instructions = NULL -) - createGiottoCosMxObject_all( dir_items, FOVs, @@ -32,25 +24,15 @@ createGiottoCosMxObject_all( \item{instructions}{list of instructions or output result from \code{\link{createGiottoInstructions}}} } \description{ -Load and create a CosMx Giotto object from subcellular and aggregate info - Load and create a CosMx Giotto object from subcellular and aggregate info } \details{ -Both \emph{subcellular} (subellular transcript detection information) and -\emph{aggregate} (aggregated detection count matrices by cell polygon from NanoString) -data will be loaded in. The two will be separated into 'cell' and 'cell_agg' -spatial units in order to denote the difference in origin of the two. - Both \emph{subcellular} (subellular transcript detection information) and \emph{aggregate} (aggregated detection count matrices by cell polygon from NanoString) data will be loaded in. The two will be separated into 'cell' and 'cell_agg' spatial units in order to denote the difference in origin of the two. } \seealso{ -createGiottoCosMxObject createGiottoCosMxObject_aggregate -createGiottoCosMxObject_subcellular - createGiottoCosMxObject createGiottoCosMxObject_aggregate createGiottoCosMxObject_subcellular } diff --git a/man/createGiottoCosMxObject_subcellular.Rd b/man/createGiottoCosMxObject_subcellular.Rd index ce4e95724..89e361270 100644 --- a/man/createGiottoCosMxObject_subcellular.Rd +++ b/man/createGiottoCosMxObject_subcellular.Rd @@ -1,17 +1,9 @@ % Generated by roxygen2: do not edit by hand -% Please edit documentation in R/convenience.R, R/convenience_create.R +% Please edit documentation in R/convenience.R \name{createGiottoCosMxObject_subcellular} \alias{createGiottoCosMxObject_subcellular} \title{Load and create a CosMx Giotto object from subcellular info} \usage{ -createGiottoCosMxObject_subcellular( - dir_items, - FOVs = NULL, - cores, - verbose = TRUE, - instructions = NULL -) - createGiottoCosMxObject_subcellular( dir_items, FOVs = NULL, @@ -30,8 +22,6 @@ createGiottoCosMxObject_subcellular( \item{instructions}{list of instructions or output result from \code{\link{createGiottoInstructions}}} } \description{ -Load and create a CosMx Giotto object from subcellular info - Load and create a CosMx Giotto object from subcellular info } \keyword{internal} diff --git a/man/createGiottoMerscopeObject.Rd b/man/createGiottoMerscopeObject.Rd index 23b97d9f0..9067de42c 100644 --- a/man/createGiottoMerscopeObject.Rd +++ b/man/createGiottoMerscopeObject.Rd @@ -1,5 +1,5 @@ % Generated by roxygen2: do not edit by hand -% Please edit documentation in R/convenience.R, R/convenience_create.R +% Please edit documentation in R/convenience.R \name{createGiottoMerscopeObject} \alias{createGiottoMerscopeObject} \alias{createGiottoMerscopeObject_subcellular} @@ -10,7 +10,6 @@ createGiottoMerscopeObject( merscope_dir, data_to_use = c("subcellular", "aggregate"), FOVs = NULL, - polygon_feat_types = 0:6, calculate_overlap = TRUE, overlap_to_matrix = TRUE, aggregate_stack = TRUE, @@ -28,51 +27,11 @@ createGiottoMerscopeObject_subcellular( aggregate_stack = TRUE, aggregate_stack_param = list(summarize_expression = "sum", summarize_locations = "mean", new_spat_unit = "cell"), - instructions, cores = NA, verbose = TRUE ) -createGiottoMerscopeObject_aggregate( - data_list, - instructions = NULL, - cores = NA, - verbose = TRUE -) - -createGiottoMerscopeObject( - merscope_dir, - data_to_use = c("subcellular", "aggregate"), - FOVs = NULL, - polygon_feat_types = 0:6, - calculate_overlap = TRUE, - overlap_to_matrix = TRUE, - aggregate_stack = TRUE, - aggregate_stack_param = list(summarize_expression = "sum", summarize_locations = - "mean", new_spat_unit = "cell"), - instructions = NULL, - cores = NA, - verbose = TRUE -) - -createGiottoMerscopeObject_subcellular( - data_list, - calculate_overlap = TRUE, - overlap_to_matrix = TRUE, - aggregate_stack = TRUE, - aggregate_stack_param = list(summarize_expression = "sum", summarize_locations = - "mean", new_spat_unit = "cell"), - instructions, - cores = NA, - verbose = TRUE -) - -createGiottoMerscopeObject_aggregate( - data_list, - instructions = NULL, - cores = NA, - verbose = TRUE -) +createGiottoMerscopeObject_aggregate(data_list, cores = NA, verbose = TRUE) } \arguments{ \item{merscope_dir}{full path to the exported merscope directory} @@ -83,8 +42,6 @@ to use for object creation} \item{FOVs}{which FOVs to use when building the subcellular object. (default is NULL) NULL loads all FOVs (very slow)} -\item{polygon_feat_types}{which Vizgen polygon z slices are loaded (There are 0 - 6)} - \item{calculate_overlap}{whether to run \code{\link{calculateOverlapRaster}}} \item{overlap_to_matrix}{whether to run \code{\link{overlapToMatrix}}} @@ -102,29 +59,13 @@ NULL loads all FOVs (very slow)} \item{data_list}{list of loaded data from \code{\link{load_merscope_folder}}} } \value{ -a giotto object - a giotto object } \description{ -Given the path to a MERSCOPE experiment directory, creates a Giotto -object. - Given the path to a MERSCOPE experiment directory, creates a Giotto object. } \details{ -[\strong{Expected Directory}] This function generates a giotto object when given a -link to a MERSCOPE output directory. It expects the following items within the directory -where the \strong{bolded} portions are what this function matches against: -\itemize{ - \item{\strong{cell_boundaries} (folder .hdf5 files)} - \item{\strong{images} (folder of .tif images and a scalefactor/transfrom table)} - \item{\strong{cell_by_gene}.csv (file)} - \item{cell_metadata\strong{fov_positions_file}.csv (file)} - \item{detected_transcripts\strong{metadata_file}.csv (file)} -} - [\strong{Expected Directory}] This function generates a giotto object when given a link to a MERSCOPE output directory. It expects the following items within the directory where the \strong{bolded} portions are what this function matches against: @@ -142,9 +83,5 @@ where the \strong{bolded} portions are what this function matches against: \item \code{createGiottoMerscopeObject_aggregate()}: Create giotto object with 'aggregate' workflow -\item \code{createGiottoMerscopeObject_subcellular()}: Create giotto object with 'subcellular' workflow - -\item \code{createGiottoMerscopeObject_aggregate()}: Create giotto object with 'aggregate' workflow - }} \keyword{internal} diff --git a/man/createGiottoXeniumObject.Rd b/man/createGiottoXeniumObject.Rd index f760e8918..3b1d71617 100644 --- a/man/createGiottoXeniumObject.Rd +++ b/man/createGiottoXeniumObject.Rd @@ -1,24 +1,9 @@ % Generated by roxygen2: do not edit by hand -% Please edit documentation in R/convenience.R, R/convenience_create.R +% Please edit documentation in R/convenience.R \name{createGiottoXeniumObject} \alias{createGiottoXeniumObject} \title{Create 10x Xenium Giotto Object} \usage{ -createGiottoXeniumObject( - xenium_dir, - data_to_use = c("subcellular", "aggregate"), - load_format = "csv", - h5_expression = TRUE, - h5_gene_ids = c("symbols", "ensembl"), - gene_column_index = 1, - bounds_to_load = c("cell"), - qv_threshold = 20, - key_list = NULL, - instructions = NULL, - cores = NA, - verbose = TRUE -) - createGiottoXeniumObject( xenium_dir, data_to_use = c("subcellular", "aggregate"), @@ -68,9 +53,6 @@ feature detections by feature type. See details} \item{verbose}{be verbose when building Giotto object} } \description{ -Given the path to a Xenium experiment output folder, creates a Giotto -object - Given the path to a Xenium experiment output folder, creates a Giotto object } @@ -100,34 +82,6 @@ Default list: neg_probe = c('NegControlProbe_|antisense_')) } -The Gene expression subset is accepted as the subset of feat_IDs that do not -map to any of the keys. - -[\strong{QC feature types}] -Xenium provides info on feature detections that include more than only the -Gene Expression specific probes. Additional probes for QC are included: -\emph{blank codeword}, \emph{negative control codeword}, and -\emph{negative control probe}. These additional QC probes each occupy and are treated -as their own feature types so that they can largely remain independent of the -gene expression information. - -[\strong{key_list}] -Related to \code{data_to_use = 'subcellular'} workflow only: -Additional QC probe information is in the subcellular feature detections information -and must be separated from the gene expression information during processing. -The QC probes have prefixes that allow them to be selected from the rest of the -feature IDs. -Giotto uses a named list of keywords (\code{key_list}) to select these QC probes, -with the list names being the names that will be assigned as the feature type -of these feature detections. The default list is used when \code{key_list} = NULL. - -Default list: -\preformatted{ - list(blank_code = 'BLANK_', - neg_code = 'NegControlCodeword_', - neg_probe = c('NegControlProbe_|antisense_')) -} - The Gene expression subset is accepted as the subset of feat_IDs that do not map to any of the keys. } diff --git a/man/createGiottoXeniumObject_aggregate.Rd b/man/createGiottoXeniumObject_aggregate.Rd index 076143fcf..463624c80 100644 --- a/man/createGiottoXeniumObject_aggregate.Rd +++ b/man/createGiottoXeniumObject_aggregate.Rd @@ -1,16 +1,9 @@ % Generated by roxygen2: do not edit by hand -% Please edit documentation in R/convenience.R, R/convenience_create.R +% Please edit documentation in R/convenience.R \name{createGiottoXeniumObject_aggregate} \alias{createGiottoXeniumObject_aggregate} \title{Create a Xenium Giotto object from aggregate info} \usage{ -createGiottoXeniumObject_aggregate( - data_list, - instructions = NULL, - cores = NA, - verbose = TRUE -) - createGiottoXeniumObject_aggregate( data_list, instructions = NULL, @@ -28,13 +21,9 @@ createGiottoXeniumObject_aggregate( \item{verbose}{be verbose when building Giotto object} } \description{ -Aggregate workflow for createGiottoXeniumObject - Aggregate workflow for createGiottoXeniumObject } \seealso{ -createGiottoXeniumObject createGiottoXeniumObject_subcellular - createGiottoXeniumObject createGiottoXeniumObject_subcellular } \keyword{internal} diff --git a/man/createGiottoXeniumObject_subcellular.Rd b/man/createGiottoXeniumObject_subcellular.Rd index e9b8ddf4a..8bec3feee 100644 --- a/man/createGiottoXeniumObject_subcellular.Rd +++ b/man/createGiottoXeniumObject_subcellular.Rd @@ -1,18 +1,9 @@ % Generated by roxygen2: do not edit by hand -% Please edit documentation in R/convenience.R, R/convenience_create.R +% Please edit documentation in R/convenience.R \name{createGiottoXeniumObject_subcellular} \alias{createGiottoXeniumObject_subcellular} \title{Create a Xenium Giotto object from subcellular info} \usage{ -createGiottoXeniumObject_subcellular( - data_list, - key_list = NULL, - qv_threshold = 20, - instructions = NULL, - cores = NA, - verbose = TRUE -) - createGiottoXeniumObject_subcellular( data_list, key_list = NULL, @@ -38,13 +29,9 @@ a subcellular transcript detection (default = 20)} \item{verbose}{be verbose when building Giotto object} } \description{ -Subcellular workflow for createGiottoXeniumObject - Subcellular workflow for createGiottoXeniumObject } \seealso{ -createGiottoXeniumObject createGiottoXeniumObject_aggregate - createGiottoXeniumObject createGiottoXeniumObject_aggregate } \keyword{internal} diff --git a/man/load_cosmx_folder_aggregate.Rd b/man/load_cosmx_folder_aggregate.Rd index e6ba5b9c2..f3aa8e57b 100644 --- a/man/load_cosmx_folder_aggregate.Rd +++ b/man/load_cosmx_folder_aggregate.Rd @@ -1,11 +1,9 @@ % Generated by roxygen2: do not edit by hand -% Please edit documentation in R/convenience.R, R/convenience_create.R +% Please edit documentation in R/convenience.R \name{load_cosmx_folder_aggregate} \alias{load_cosmx_folder_aggregate} \title{Load CosMx folder aggregate info} \usage{ -load_cosmx_folder_aggregate(dir_items, cores, verbose = TRUE) - load_cosmx_folder_aggregate(dir_items, cores, verbose = TRUE) } \arguments{ @@ -14,8 +12,6 @@ load_cosmx_folder_aggregate(dir_items, cores, verbose = TRUE) \item{verbose}{be verbose when building Giotto object} } \description{ -Load CosMx folder aggregate info - Load CosMx folder aggregate info } \keyword{internal} diff --git a/man/load_cosmx_folder_subcellular.Rd b/man/load_cosmx_folder_subcellular.Rd index 6c9923972..06bee492e 100644 --- a/man/load_cosmx_folder_subcellular.Rd +++ b/man/load_cosmx_folder_subcellular.Rd @@ -1,11 +1,9 @@ % Generated by roxygen2: do not edit by hand -% Please edit documentation in R/convenience.R, R/convenience_create.R +% Please edit documentation in R/convenience.R \name{load_cosmx_folder_subcellular} \alias{load_cosmx_folder_subcellular} \title{Load CosMx folder subcellular info} \usage{ -load_cosmx_folder_subcellular(dir_items, FOVs = NULL, cores, verbose = TRUE) - load_cosmx_folder_subcellular(dir_items, FOVs = NULL, cores, verbose = TRUE) } \arguments{ @@ -16,10 +14,6 @@ load_cosmx_folder_subcellular(dir_items, FOVs = NULL, cores, verbose = TRUE) \item{verbose}{be verbose when building Giotto object} } \description{ -loads in the feature detections information. Note that the mask -images are still required for a working subcellular object, and those are loaded -in \code{\link{createGiottoCosMxObject_subcellular}} - loads in the feature detections information. Note that the mask images are still required for a working subcellular object, and those are loaded in \code{\link{createGiottoCosMxObject_subcellular}} diff --git a/man/load_merscope_folder.Rd b/man/load_merscope_folder.Rd index 00afc35ff..03938691f 100644 --- a/man/load_merscope_folder.Rd +++ b/man/load_merscope_folder.Rd @@ -1,5 +1,5 @@ % Generated by roxygen2: do not edit by hand -% Please edit documentation in R/convenience.R, R/convenience_create.R +% Please edit documentation in R/convenience.R \name{load_merscope_folder} \alias{load_merscope_folder} \alias{load_merscope_folder_subcellular} @@ -9,8 +9,7 @@ load_merscope_folder( dir_items, data_to_use, - FOVs = NULL, - polygon_feat_types = 0:6, + fovs = NULL, cores = NA, verbose = TRUE ) @@ -18,35 +17,9 @@ load_merscope_folder( load_merscope_folder_subcellular( dir_items, data_to_use, - polygon_feat_types = 0:6, cores = NA, verbose = TRUE, - FOVs = NULL -) - -load_merscope_folder_aggregate( - dir_items, - data_to_use, - cores = NA, - verbose = TRUE -) - -load_merscope_folder( - dir_items, - data_to_use, - FOVs = NULL, - polygon_feat_types = 0:6, - cores = NA, - verbose = TRUE -) - -load_merscope_folder_subcellular( - dir_items, - data_to_use, - polygon_feat_types = 0:6, - cores = NA, - verbose = TRUE, - FOVs = NULL + fovs = NULL ) load_merscope_folder_aggregate( @@ -62,23 +35,14 @@ load_merscope_folder_aggregate( \item{data_to_use}{which of either the 'subcellular' or 'aggregate' information to use for object creation} -\item{FOVs}{which FOVs to use when building the subcellular object. (default is NULL) -NULL loads all FOVs (very slow)} - -\item{polygon_feat_types}{which Vizgen polygon z slices are loaded (There are 0 - 6)} - \item{cores}{how many cores or threads to use to read data if paths are provided} \item{verbose}{be verbose when building Giotto object} } \value{ -list of loaded-in MERSCOPE data - list of loaded-in MERSCOPE data } \description{ -Load MERSCOPE data from folder - Load MERSCOPE data from folder } \section{Functions}{ @@ -87,9 +51,5 @@ Load MERSCOPE data from folder \item \code{load_merscope_folder_aggregate()}: Load items for 'aggregate' workflow -\item \code{load_merscope_folder_subcellular()}: Load items for 'subcellular' workflow - -\item \code{load_merscope_folder_aggregate()}: Load items for 'aggregate' workflow - }} \keyword{internal} diff --git a/man/load_xenium_folder.Rd b/man/load_xenium_folder.Rd index 3e7304d20..88549dbf8 100644 --- a/man/load_xenium_folder.Rd +++ b/man/load_xenium_folder.Rd @@ -1,5 +1,5 @@ % Generated by roxygen2: do not edit by hand -% Please edit documentation in R/convenience.R, R/convenience_create.R +% Please edit documentation in R/convenience.R \name{load_xenium_folder} \alias{load_xenium_folder} \alias{load_xenium_folder_csv} @@ -27,37 +27,6 @@ load_xenium_folder_csv( verbose = TRUE ) -load_xenium_folder_parquet( - path_list, - cores, - data_to_use = "subcellular", - h5_expression = FALSE, - h5_gene_ids = "symbols", - gene_column_index = 1, - verbose = TRUE -) - -load_xenium_folder( - path_list, - load_format = "csv", - data_to_use = "subcellular", - h5_expression = "FALSE", - h5_gene_ids = "symbols", - gene_column_index = 1, - cores, - verbose = TRUE -) - -load_xenium_folder_csv( - path_list, - cores, - data_to_use = "subcellular", - h5_expression = FALSE, - h5_gene_ids = "symbols", - gene_column_index = 1, - verbose = TRUE -) - load_xenium_folder_parquet( path_list, cores, @@ -90,13 +59,9 @@ expression matrix} \item{verbose}{be verbose when building Giotto object} } \value{ -list of loaded in xenium data - list of loaded in xenium data } \description{ -Load xenium data from folder - Load xenium data from folder } \section{Functions}{ @@ -105,9 +70,5 @@ Load xenium data from folder \item \code{load_xenium_folder_parquet()}: Load from parquet files -\item \code{load_xenium_folder_csv()}: Load from csv files - -\item \code{load_xenium_folder_parquet()}: Load from parquet files - }} \keyword{internal} diff --git a/man/read_cosmx_folder.Rd b/man/read_cosmx_folder.Rd index 31c913f0b..407834bca 100644 --- a/man/read_cosmx_folder.Rd +++ b/man/read_cosmx_folder.Rd @@ -1,11 +1,9 @@ % Generated by roxygen2: do not edit by hand -% Please edit documentation in R/convenience.R, R/convenience_create.R +% Please edit documentation in R/convenience.R \name{read_cosmx_folder} \alias{read_cosmx_folder} \title{Read a structured CosMx folder} \usage{ -read_cosmx_folder(cosmx_dir, verbose = TRUE) - read_cosmx_folder(cosmx_dir, verbose = TRUE) } \arguments{ @@ -14,20 +12,13 @@ read_cosmx_folder(cosmx_dir, verbose = TRUE) \item{verbose}{be verbose when building Giotto object} } \value{ -path_list a list of cosmx files discovered and their filepaths. NULL -values denote missing items - path_list a list of cosmx files discovered and their filepaths. NULL values denote missing items } \description{ -Read a structured CosMx folder - Read a structured CosMx folder } \seealso{ -createGiottoCosMxObject load_cosmx_folder - createGiottoCosMxObject load_cosmx_folder } \keyword{internal} diff --git a/man/read_data_folder.Rd b/man/read_data_folder.Rd index 759036c92..8b57d2b49 100644 --- a/man/read_data_folder.Rd +++ b/man/read_data_folder.Rd @@ -1,5 +1,5 @@ % Generated by roxygen2: do not edit by hand -% Please edit documentation in R/convenience.R, R/convenience_create.R +% Please edit documentation in R/convenience.R \name{read_data_folder} \alias{read_data_folder} \alias{read_merscope_folder} @@ -16,19 +16,6 @@ read_data_folder( verbose = TRUE ) -read_merscope_folder(merscope_dir, data_to_use, cores = NA, verbose = TRUE) - -read_data_folder( - spat_method = NULL, - data_dir = NULL, - dir_items, - data_to_use, - load_format = NULL, - require_data_DT, - cores = NA, - verbose = TRUE -) - read_merscope_folder(merscope_dir, data_to_use, cores = NA, verbose = TRUE) } \arguments{ @@ -48,25 +35,10 @@ or optional for each \code{data_to_use} workflow} \item{verbose}{be verbose} } \description{ -Read the exported folder of a spatial method and -detect the presence of needed files. NULL values denote missing items. - Read the exported folder of a spatial method and detect the presence of needed files. NULL values denote missing items. } \details{ -Steps performed: -\itemize{ - \item{1. detection of items within \code{data_dir} by looking for keywords - assigned through \code{dir_items}} - \item{2. check of detected items to see if everything needed has been found. - Dictionary of necessary vs optional items for each \code{data_to_use} workflow - is provided through \code{require_data_DT}} - \item{3. if multiple filepaths are found to be matching then select the first - one. This function is only intended to find the first level subdirectories - and files.} -} - Steps performed: \itemize{ \item{1. detection of items within \code{data_dir} by looking for keywords @@ -83,7 +55,5 @@ Steps performed: \itemize{ \item \code{read_merscope_folder()}: Read a structured MERSCOPE folder -\item \code{read_merscope_folder()}: Read a structured MERSCOPE folder - }} \keyword{internal} diff --git a/man/read_xenium_folder.Rd b/man/read_xenium_folder.Rd index 74fc4f835..dba7913af 100644 --- a/man/read_xenium_folder.Rd +++ b/man/read_xenium_folder.Rd @@ -1,18 +1,9 @@ % Generated by roxygen2: do not edit by hand -% Please edit documentation in R/convenience.R, R/convenience_create.R +% Please edit documentation in R/convenience.R \name{read_xenium_folder} \alias{read_xenium_folder} \title{Read a structured xenium folder} \usage{ -read_xenium_folder( - xenium_dir, - data_to_use = "subcellular", - bounds_to_load = c("cell"), - load_format = "csv", - h5_expression = FALSE, - verbose = TRUE -) - read_xenium_folder( xenium_dir, data_to_use = "subcellular", @@ -41,15 +32,10 @@ Default is \code{TRUE}} \item{verbose}{be verbose when building Giotto object} } \value{ -path_list a list of xenium files discovered and their filepaths. NULL -values denote missing items - path_list a list of xenium files discovered and their filepaths. NULL values denote missing items } \description{ -Read a structured xenium folder - Read a structured xenium folder } \keyword{internal} From 1ac7f0c964e57e1516ebf8e2d98b132e6fcd2532 Mon Sep 17 00:00:00 2001 From: jiajic <72078254+jiajic@users.noreply.github.com> Date: Wed, 14 Dec 2022 14:51:50 -0500 Subject: [PATCH 033/129] test --- R/general_help.R | 82 +++++++++++++++--------------------------------- R/utilities.R | 18 +++++++++++ 2 files changed, 43 insertions(+), 57 deletions(-) diff --git a/R/general_help.R b/R/general_help.R index 08754bbc8..a8a48ed51 100644 --- a/R/general_help.R +++ b/R/general_help.R @@ -1356,14 +1356,6 @@ readPolygonFilesVizgenHDF5 = function(boundaries_path, # necessary pkgs package_check(pkg_name = 'rhdf5', repository = 'Bioc') - # optional pkgs - progressr_avail = package_check( - pkg_name = 'progressr', - repository = 'CRAN', - optional = TRUE, - custom_msg = c('(Optional) For progress bar, install:\ninstall.packages("progressr)\n', - 'After install:\nprogressr::handlers("progress")') - ) cores = determine_cores(cores) @@ -1412,39 +1404,34 @@ readPolygonFilesVizgenHDF5 = function(boundaries_path, # open selected polygon files # append data from all FOVs to single list hdf5_list_length = length(hdf5_boundary_selected_list) + if(isTRUE(verbose)) files_read = c() + init = proc.time() - if(isTRUE(progressr_avail)) { - progressr::with_progress({ - pb = progressr::progressor(along = hdf5_boundary_selected_list) - read_list = lapply_flex(hdf5_boundary_selected_list, cores = cores, function(bound_i) { - - # read file and select feature data - read_file = rhdf5::H5Fopen(bound_i[[1]], flags = H5Fopen_flags) - fov_info = read_file$featuredata - - # update progress - f_n = basename(bound_i[[1]]) - pb_msg = c('...', substr(f_n, nchar(f_n) - 19, nchar(f_n))) - pb(message = pb_msg) - return(fov_info) - }) - }) - } else { - read_list = lapply_flex(hdf5_boundary_selected_list, cores = cores, function(bound_i) { - - if(isTRUE(verbose)) { - cat('\n','hdf5: ', (hdf5_list_length - bound_i) ,'\n') - print(basename(bound_i[[1]])) - cat('\n') - } + progressr::with_progress({ + pb = progressr::progressor(along = hdf5_boundary_selected_list) + read_list = lapply_flex(seq_along(hdf5_boundary_selected_list), cores = cores, function(bound_i) { # read file and select feature data - read_file = rhdf5::H5Fopen(bound_i[[1]], flags = H5Fopen_flags) + read_file = rhdf5::H5Fopen(hdf5_boundary_selected_list[[bound_i]][[1]], flags = H5Fopen_flags) fov_info = read_file$featuredata + # update progress + if(isTRUE(verbose)) { + f_n = basename(hdf5_boundary_selected_list[[bound_i]][[1]]) + files_read = c(files_read, f_n) + } + elapsed = (proc.time() - init)[[3L]] + step_time = elapsed/bound_i + est = (hdf5_list_length * step_time) - elapsed + pb(message = c('// E:', time_format(elapsed), '| R:', time_format(est))) return(fov_info) }) + }) + if(isTRUE(verbose)) { + message('Files read:') + print(files_read) } + # # combine to FOV data single list read_list = Reduce('append', read_list) cell_names = names(read_list) @@ -1484,35 +1471,16 @@ readPolygonFilesVizgenHDF5 = function(boundaries_path, # create Giotto polygons and add them to gobject # smooth_cell_polygons_list = list() - - if(isTRUE(progressr_avail)) { - progressr::with_progress({ - pb = progressr::progressor(along = result_list_rbind) - smooth_cell_polygons_list = lapply_flex(seq_along(result_list_rbind), cores = cores, function(i) { - dfr_subset = result_list_rbind[[i]][,.(x, y, cell_id)] - cell_polygons = createGiottoPolygonsFromDfr(segmdfr = dfr_subset, - name = poly_feat_names[i], - verbose = verbose) - - pb(message = poly_feat_names[i]) - - if(smooth_polygons == TRUE) { - return(smoothGiottoPolygons(cell_polygons, - vertices = smooth_vertices, - set_neg_to_zero = set_neg_to_zero, - verbose = FALSE)) - } else { - return(cell_polygons) - } - }) - }) - } else { + progressr::with_progress({ + pb = progressr::progressor(along = result_list_rbind) smooth_cell_polygons_list = lapply_flex(seq_along(result_list_rbind), cores = cores, function(i) { dfr_subset = result_list_rbind[[i]][,.(x, y, cell_id)] cell_polygons = createGiottoPolygonsFromDfr(segmdfr = dfr_subset, name = poly_feat_names[i], verbose = verbose) + pb(message = poly_feat_names[i]) + if(smooth_polygons == TRUE) { return(smoothGiottoPolygons(cell_polygons, vertices = smooth_vertices, @@ -1522,7 +1490,7 @@ readPolygonFilesVizgenHDF5 = function(boundaries_path, return(cell_polygons) } }) - } + }) # TODO: add spatial centroids diff --git a/R/utilities.R b/R/utilities.R index fb896b7a8..f6a6242df 100644 --- a/R/utilities.R +++ b/R/utilities.R @@ -650,6 +650,24 @@ emacs_version = function() { } +# time formatting #### + +#' @title Format time for printing +#' @name time_format +#' @keywords internal +#' @details Code from \code{\link[data.table]{timetaken}} +time_format = function(secs) { + if (secs > 60) { + secs = as.integer(secs) + sprintf("%02d:%02d:%02d", secs%/%3600L, (secs%/%60L)%%60L, + secs%%60L) + } + else { + sprintf(if (secs >= 10) + "%.1fs" + else "%.3fs", secs) + } +} From ff8f3b70bcd753471099d835f12ffe10e4375db6 Mon Sep 17 00:00:00 2001 From: mattobny Date: Wed, 14 Dec 2022 15:04:35 -0500 Subject: [PATCH 034/129] Added giottoToAnnData --- .gitignore | 3 +- R/globals.R | 10 +- R/interoperability.R | 368 ++++++++++++++++++++++++++++++++++++++++++- inst/python/ad2g.py | 4 +- inst/python/g2ad.py | 172 ++++++++++++++++++++ 5 files changed, 550 insertions(+), 7 deletions(-) create mode 100644 inst/python/g2ad.py diff --git a/.gitignore b/.gitignore index be19d1c96..cfd5f1a2b 100644 --- a/.gitignore +++ b/.gitignore @@ -6,4 +6,5 @@ inst/doc *.Rproj .git_old merfish_preoptic/ -.vscode/launch.json +.vscode/* +.Rprofile diff --git a/R/globals.R b/R/globals.R index 45a4ccebd..22821f5bc 100644 --- a/R/globals.R +++ b/R/globals.R @@ -6,5 +6,13 @@ utils::globalVariables(names = c(":=", ".N", ".SD", ".", "cast", "python_leiden", "python_louvain", "python_spatial_genes", "Spatial_DE_AEH", "Spatial_DE", "silhouette_rank", "python_scrublet", "python_create_mesmer_app", - "python_segment_image")) + "python_segment_image","ad_guard","dir_guard","ad_obj", + "lay_inv","set_adg_layer_data","set_adg_spat_locs", + "set_adg_metadata","set_adg_pca","set_adg_umap", + "set_adg_tsne","write_ad_h5ad","read_anndata_from_path", + "extract_expression","extract_cell_IDs","extract_feat_IDs", + "extract_pca","extract_umap","extract_tsne", + "parse_obsm_for_spat_locs","extract_cell_metadata", + "extract_feat_metadata","extract_layer_names", + "extract_layered_data")) diff --git a/R/interoperability.R b/R/interoperability.R index eaeea66a4..0de73a8cf 100644 --- a/R/interoperability.R +++ b/R/interoperability.R @@ -190,8 +190,14 @@ anndataToGiotto = function(anndata_path = NULL, if (!is.null(lay_names)) { for (l_n in lay_names){ lay = extract_layered_data(adata, layer_name = l_n) - lay@Dimnames[[1]] = fID - lay@Dimnames[[2]] = cID + if ("data.frame" %in% class(lay)){ + names(lay) = fID + row.names(lay) = cID + } + else{ + lay@Dimnames[[1]] = fID + lay@Dimnames[[2]] = cID + } gobject = set_expression_values(gobject = gobject, spat_unit = spat_unit, feat_type = feat_type, @@ -203,12 +209,368 @@ anndataToGiotto = function(anndata_path = NULL, gobject <- update_giotto_params(gobject = gobject, description = "_AnnData_Conversion") - + wrap_msg("\nAnnData object successfully converted to Giotto.\n") return(gobject) } +#' @title Convert Giotto to anndata +#' @name giottoToAnnData +#' @description Converts a Giotto object to a spatial anndata (e.g. scanpy) .h5ad file +#' @param gobject giotto object to be converted +#' @param spat_unit spatial unit which will be used in conversion. +#' @param feat_type feature type which will be used in conversion. +#' @param python_path path to python executable within a conda/miniconda environment +#' @param save_directory directory in which the file will be saved. +#' @return .h5ad file path(s) +#' @details Function in beta. Converts a Giotto object into .h5ad file(s). +#' +#' If there are multiple spatial units and/or feature types, but only +#' one spatial unit and/or feature type is specified, then only the +#' specified spatial unit and/or feature type will be used. If NULL, +#' by default, all spatial units will be used in conversion. +#' +#' If multiple spatial units or feature types are specified, multiple +#' AnnData object will be created and returned. +#' +#' The save_directory will be created if it does not already exist. +#' The default save_directory is the working directory. +#' +#' +#' +#' @export +giottoToAnnData <- function(gobject = NULL, + spat_unit = NULL, + feat_type = NULL, + python_path = NULL, + save_directory = NULL){ + # Check gobject + invalid_obj = !("giotto" %in% class(gobject)) + if (is.null(gobject) || invalid_obj) { + stop(wrap_msg("Please provide a valid Giotto Object for conversion.")) + } + + # Python module import + g2ad_path <- system.file("python","g2ad.py",package="Giotto") + reticulate::source_python(g2ad_path) + if (!is.null(save_directory)) dir_guard(save_directory) + + # Check directory, make it if it doesn't exist + if (is.null(save_directory)) save_directory = paste0(getwd(),"/") + else if (!dir.exists(save_directory)) { + warning(wrap_msg("Provided save directory not found. Creating save directory at location:")) + cat(save_directory) + dir.create(save_directory, recursive = TRUE) + if (dir.exists(save_directory)) cat("Created directory", save_directory) + else stop(wrap_msg("Unable to create directory. Please change the provided path and try again.")) + } + else { + wrap_msg("Directory", save_directory,"found. The converted Giotto object will be saved here as a .h5ad file.") + } + + # Expresion + expr_dt <- list_expression(gobject) + # ID spat_unit and feat_type if not already provided. + if (is.null(spat_unit) && is.null(feat_type)) { + spat_unit = unique(expr_dt$spat_unit) + feat_type = unique(expr_dt$feat_type) + } else if (is.null(spat_unit && !is.null(feat_type))) { + spat_unit = unique(expr_dt$spat_unit) + } else if (!is.null(spat_unit && is.null(feat_type))) { + feat_type = unique(expr_dt$feat_type) + } + + for (su in spat_unit) wrap_msg("Spatial unit(s)", su, "will be used in conversion.") + for (ft in feat_type) wrap_msg("Feature type(s)", ft, "will be used in conversion.") + + # Iterate through spat_unit and feat_type to pull out expression data. + # By default, the raw expression in the slot of the first spatial unit + # and first feature type (if multiple are present) will be transferred to + # the AnnData.anndata.X slot + # Any other expression data will be inserted into AnnData.anndata.layers + # By default, layer names are formed by "'spatial_unit'_'feature_type'_'value'" + + adata = NULL #scope + su_ft_length = 0 + + for (su in spat_unit) { + for (ft in names(gobject@expression[[su]])) { + su_ft_length = su_ft_length + 1 + } + } + + + adata_list = lapply(1:su_ft_length, function(i) adata) + adata_pos = 1 + + for (su in spat_unit) { + for (ft in names(gobject@expression[[su]])) { + expr_names = list_expression_names(gobject = gobject, + spat_unit = su, + feat_type = ft) + + for (en in expr_names) { + if (en == "raw") { + raw_x = get_expression_values(gobject = gobject, + values = en, + spat_unit = su, + feat_type = ft, + output = "matrix") + + adata = ad_obj(x = raw_x) + } else { + ad_layer_name = paste0(su,"_",ft,"_",en) + + x = get_expression_values(gobject = gobject, + values = en, + spat_unit = su, + feat_type = ft, + output = "matrix") + + if ("dgeMatrix" %in% class(x)) x = as(x,'array') + + adata = set_adg_layer_data(adata = adata, + lay = x, + lay_name = ad_layer_name) + } + + } + adata_list[[adata_pos]] = adata + adata_pos = adata_pos + 1 + adata = NULL + } + } + # Reset indexing variable + adata_pos = 1 + + # Spatial Locations + for (su in spat_unit){ + for (ft_ in names(gobject@expression[[su]])) { + sl = get_spatial_locations(gobject = gobject, + output = "data.table", + spat_unit = su) + n_col_sl = dim(sl)[2] + + #preallocate data.table params + sdimx = sdimy = sdimz = NULL + + if (n_col_sl == 3){ + sl = sl[, .(sdimx, sdimy)] + } else { + sl = sl[, .(sdimx, sdimy, sdimz)] + } + adata = adata_list[[adata_pos]] + adata = set_adg_spat_locs(adata = adata, + spat_locs = sl) + adata_pos = adata_pos + 1 + } + } + # Reset indexing variable + adata_pos = 1 + + # Spatial Info + + # Cell Metadata + # Feat Metadata + for (su in spat_unit){ + for (ft in names(gobject@expression[[su]])){ + + cm = get_cell_metadata(gobject = gobject, + spat_unit = su, + feat_type = ft, + output = "data.table", + set_defaults = FALSE) + + fm = get_feature_metadata(gobject = gobject, + spat_unit = su, + feat_type = ft, + output = "data.table", + set_defaults = FALSE) + + adata_list[[adata_pos]] = set_adg_metadata(adata = adata_list[[adata_pos]], + cell_meta = cm, + feat_meta = fm) + + adata_pos = adata_pos + 1 + + } + } + # Reset indexing variable + adata_pos = 1 + + # Dimension Reductions + + # error hanldling wrapper to get_dimReduction + try_get_dimReduction = function(gobject, + spat_unit, + feat_type, + reduction, + reduction_method, + name, + output, + set_defaults) { + tryCatch( + { + dim_red = get_dimReduction(gobject = gobject, + spat_unit = spat_unit, + feat_type = feat_type, + reduction = reduction, + reduction_method = reduction_method, + name = name, + output = output, + set_defaults = set_defaults) + return(dim_red) + }, + error = function(e) { + return(NULL) + } + ) + } + + ## PCA + + # pca on feats not supported by anndata because of dimensionality agreement reqs + reduction_options = c("cells", "feats") + dim_red = NULL + + for (ro in reduction_options) { + if (ro != "cells") { + warning("AnnData does not support storing PCA by features. Skipping PCA data conversion.") + break + } + for (su in spat_unit) { + for (ft in names(gobject@expression[[su]])) { + name = "pca" + if (ft != "rna") name = paste0(ft,".pca") + dim_red = try_get_dimReduction(gobject = gobject, + spat_unit = su, + feat_type = ft, + reduction = ro, + reduction_method = "pca", + name = name, + output = "dimObj", + set_defaults = FALSE) + if (is.null(dim_red)){ + adata_pos = adata_pos + 1 + next + } + pca_coord = dim_red[] + pca_loadings = data.table(dim_red@misc$loadings) + feats_used = dimnames(dim_red@misc$loadings)[[1]] + evs = dim_red@misc$eigenvalues + + adata_list[[adata_pos]] = set_adg_pca(adata = adata_list[[adata_pos]], + pca_coord = pca_coord, + loadings = pca_loadings, + eigenv = evs, + feats_used = feats_used) + adata_pos = adata_pos + 1 + } + adata_pos = 1 + } + + } + + # Reset indexing variable + adata_pos = 1 + + ## UMAP + for (ro in reduction_options) { + for (su in spat_unit) { + for (ft in names(gobject@expression[[su]])) { + name = "umap" + if (ft != "rna") name = paste0(ft,".umap") + dim_red = try_get_dimReduction(gobject = gobject, + spat_unit = su, + feat_type = ft, + reduction = ro, + reduction_method = "umap", + name = name, + output = "dimObj", + set_defaults = FALSE) + + if (is.null(dim_red)) { + adata_pos = adata_pos + 1 + next + } + umap_data = dim_red[] + adata_list[[adata_pos]] = set_adg_umap(adata = adata_list[[adata_pos]], + umap_data = umap_data) + adata_pos = adata_pos + 1 + } + } + # Reset indexing variable + adata_pos = 1 + } + + # Reset indexing variable + adata_pos = 1 + + ## T-SNE + for (ro in reduction_options) { + for (su in spat_unit) { + for (ft in names(gobject@expression[[su]])) { + name = "tsne" + if (ft != "rna") name = paste0(ft,".tsne") + dim_red = try_get_dimReduction(gobject = gobject, + spat_unit = su, + feat_type = ft, + reduction = ro, + reduction_method = "tsne", + name = name, + output = "dimObj", + set_defaults = FALSE) + + if (is.null(dim_red)) { + adata_pos = adata_pos + 1 + next + } + tsne_data = dim_red[] + adata_list[[adata_pos]] = set_adg_tsne(adata = adata_list[[adata_pos]], + tsne_data = tsne_data) + adata_pos = adata_pos + 1 + } + } + # Reset indexing variable + adata_pos = 1 + } + + # Reset indexing variable + adata_pos = 1 + + # Nearest Neighbor Network + + + # Pipe non-expression data into AnnData object + + # Write AnnData object to .h5ad file + # Verify it exists, and return upon success + wrap_msg("\n") + for (su in spat_unit) { + for (ft in names(gobject@expression[[su]])) { + adata = adata_list[[adata_pos]] + path_adata = write_ad_h5ad(adata = adata, + save_directory = save_directory, + spat_unit = su, + feat_type = ft) + if (!is.null(path_adata)) { + wrap_msg("Spatial unit", su, "and feature type", ft, "converted to:") + wrap_msg(path_adata) + adata_pos = adata_pos + 1 + } else { + wrap_msg("Unable to convert spatial unit feature type pair", su, ft) + stop(wrap_msg("File writing error. Please try again.")) + } + } + } + + wrap_msg("\nGiotto object successfully converted to .h5ad file(s)\n") + + return(path_adata) +} + + ## Seurat object #### diff --git a/inst/python/ad2g.py b/inst/python/ad2g.py index f248948ea..6beac22df 100644 --- a/inst/python/ad2g.py +++ b/inst/python/ad2g.py @@ -187,9 +187,9 @@ def extract_layered_data(adata = None, layer_name = None): print(f"Invalid Key, {layer_name}, for adata.layers") raise(KeyError) target_layer = adata.layers[layer_name] - if type(target_layer) == scipy.sparse.csr.csr_matrix: + if type(target_layer) == scipy.sparse.csr_matrix: target_layer = target_layer.T - elif type(target_layer) == scipy.sparse.csr_matrix: + elif type(target_layer) == scipy.sparse.csr.csr_matrix: target_layer = target_layer.T else: target_layer = pd.DataFrame(target_layer) diff --git a/inst/python/g2ad.py b/inst/python/g2ad.py new file mode 100644 index 000000000..29ae4fa5f --- /dev/null +++ b/inst/python/g2ad.py @@ -0,0 +1,172 @@ +import anndata as ad +import pandas as pd +import numpy as np +import os + + +def ad_guard(adata): + if type(adata) is not type(ad.AnnData()): + print("Please provide a valid AnnData object.") + raise(TypeError) + +def dir_guard(save_directory = None): + slash = save_directory[-1] + if slash != "/" and slash != '\\': + print("Argument save_directory must end in a slash character.") + print("\ti.e., save_directory = 'C:/my/save/directory/'") + print("\tAlternatively, save_directory = 'C:\\my\\save\\directory\\'") + print("Stopping conversion. Please try again.") + assert(False) + +def ad_obj(x = None): + ''' + Creates an AnnData object using expression matrix, x + + INPUT: x, an expression matrix in csr format + + OUTPUT: gad, a minimal AnnData object + ''' + if x is None: + print("Please provide an expression matrix.") + assert(False) + x = x.transpose() + gad = ad.AnnData(x, dtype=x.dtype) + return gad + +def lay_inv(lay = None): + try: + print(type(lay)) + except (ValueError, NameError, SyntaxError): + print(type(lay)) + finally: + assert(False) + +def set_adg_layer_data(adata = None, lay = None, lay_name = None):#, lay_class = None): + ''' + Sets additional expression-based information within the + layers slot of a given AnnData object + + INPUTS: + adata, an AnnData object to which the data, x will be added in the layers slot + MUST have expression data which lives in slot adata.X + lay, a matrix with the same dimensions as adata.X + lay_name, the name of the layer. By default, "'spatial_unit'_'feature_type'_'value'" + + OUTPUTS: adata, an AnnData object with additional data in the layers slot + ''' + #if type(lay_class) is type(target_layer) == scipy.sparse.csr_matrix: + #pass + ad_guard(adata) + x_size = np.shape(adata.X) + + if x_size == 0: + print("Please first load in expression data, then try again") + assert(False) + lay = lay.transpose() + lay_size = np.shape(lay) + + print("X ", x_size) + print("lay ", lay_size) + print(type(lay)) + if x_size != lay_size: + print("The provided matrix must have the same dimensions as adata.X") + print("Cannot add layer unless the dimensions agree exactly.") + assert(False) + adata.layers[lay_name] = lay + return adata + +def set_adg_spat_locs(adata = None, spat_locs = None): + ad_guard(adata) + spat_locs = pd.DataFrame(spat_locs, dtype=float) + spat_locs = np.array(spat_locs, dtype=float) + adata.obsm["spatial"] = spat_locs + return adata + +def set_adg_metadata(adata = None, cell_meta = None, feat_meta = None): + ad_guard(adata) + adata.obs_names = cell_meta["cell_ID"] + cell_meta.set_index("cell_ID", inplace = True) + + #feat_meta = pd.DataFrame(feat_meta)#, dtype = object) + adata.var_names = feat_meta["feat_ID"] + feat_meta.set_index("feat_ID", inplace = True) + + for cm_col in cell_meta.columns: + adata.obs[cm_col] = np.array(cell_meta[cm_col]) + for fm_col in feat_meta.columns: + adata.var[fm_col] = np.array(feat_meta[fm_col]) + + return adata + +def set_adg_pca(adata = None, pca_coord = None, loadings = None, eigenv = None, feats_used = None): + ad_guard(adata) + hvf = False + + if pca_coord is not None: + adata.obsm['X_pca'] = pca_coord + if feats_used is not None: + all_feats = adata.var_names + all_false = [False for i in all_feats] + highly_variable = pd.Series(all_false, index=all_feats) + for x, i in enumerate(highly_variable.index): + if i in feats_used: + highly_variable.iloc[x] = True + highly_variable.name = 'highly_variable' + adata.var['highly_variable'] = highly_variable + hvf = True + + if loadings is not None and hvf: + n_pc = loadings.shape[1] + pc_placehold = np.zeros(shape = (adata.n_vars, n_pc)) + pc_placehold = pd.DataFrame(pc_placehold, index=adata.var_names, dtype=float) + + loadings.index = feats_used + for row, i in enumerate(loadings.index): + test_pc = loadings.iloc[row,:] + pc_placehold.loc[i] = test_pc + pc_placehold = pc_placehold.to_numpy(dtype=float) + adata.varm["PCs"] = pc_placehold + + elif loadings is not None: + adata.varm["PCs"] = loadings + if eigenv is not None: + eigenv_shape = len(eigenv) + eigenv = np.array(eigenv) + adata.uns['pca'] = {} + adata.uns['pca'] = {'variance':eigenv.reshape(eigenv_shape,)} + + return adata + +def set_adg_umap(adata = None, umap_data = None): + ad_guard(adata) + if umap_data is not None: + adata.obsm['X_umap'] = umap_data + + return adata + +def set_adg_tsne(adata = None, tsne_data = None): + ad_guard(adata) + if tsne_data is not None: + adata.obsm['X_tsne'] = tsne_data + + return adata + +def write_ad_h5ad(adata = None, save_directory = None, spat_unit = None, feat_type = None): + ad_guard(adata) + if os.path.exists(save_directory): + save_path = f"{save_directory}{spat_unit}_{feat_type}_converted_gobject.h5ad" + adata.write_h5ad(save_path) + if os.path.exists(save_path): + return save_path + else: + return None + +# DEVELOPER FUNCTIONS - NO NEED TO ADD TO GLOBALS +def type_test(obj = None): + return type(obj) + +def test_ret_hvf(adata): + return adata.var["highly_variable"] + +def test_ret_pcs(adata): + return adata.varm["PCs"] \ No newline at end of file From 0feb4629e2940ffe3ba2197701e72927ca1f2ee2 Mon Sep 17 00:00:00 2001 From: mattobny Date: Wed, 14 Dec 2022 15:09:33 -0500 Subject: [PATCH 035/129] Small return value change --- R/interoperability.R | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/R/interoperability.R b/R/interoperability.R index 0de73a8cf..6e2f87804 100644 --- a/R/interoperability.R +++ b/R/interoperability.R @@ -223,7 +223,7 @@ anndataToGiotto = function(anndata_path = NULL, #' @param feat_type feature type which will be used in conversion. #' @param python_path path to python executable within a conda/miniconda environment #' @param save_directory directory in which the file will be saved. -#' @return .h5ad file path(s) +#' @return vector containing .h5ad file path(s) #' @details Function in beta. Converts a Giotto object into .h5ad file(s). #' #' If there are multiple spatial units and/or feature types, but only @@ -236,9 +236,6 @@ anndataToGiotto = function(anndata_path = NULL, #' #' The save_directory will be created if it does not already exist. #' The default save_directory is the working directory. -#' -#' -#' #' @export giottoToAnnData <- function(gobject = NULL, spat_unit = NULL, @@ -540,12 +537,13 @@ giottoToAnnData <- function(gobject = NULL, adata_pos = 1 # Nearest Neighbor Network - + # Pipe non-expression data into AnnData object # Write AnnData object to .h5ad file # Verify it exists, and return upon success + fname_list = lapply(1:su_ft_length, function(i) NULL) wrap_msg("\n") for (su in spat_unit) { for (ft in names(gobject@expression[[su]])) { @@ -557,6 +555,7 @@ giottoToAnnData <- function(gobject = NULL, if (!is.null(path_adata)) { wrap_msg("Spatial unit", su, "and feature type", ft, "converted to:") wrap_msg(path_adata) + fname_list[[adata_pos]] = path_adata adata_pos = adata_pos + 1 } else { wrap_msg("Unable to convert spatial unit feature type pair", su, ft) @@ -567,7 +566,7 @@ giottoToAnnData <- function(gobject = NULL, wrap_msg("\nGiotto object successfully converted to .h5ad file(s)\n") - return(path_adata) + return(fname_list) } From c7409263612e10973ef1b11e2f6fba5cac78dcc1 Mon Sep 17 00:00:00 2001 From: mattobny Date: Wed, 14 Dec 2022 15:13:57 -0500 Subject: [PATCH 036/129] Add Documentation for giottoToAnnData --- NAMESPACE | 1 + man/giottoToAnnData.Rd | 45 ++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 46 insertions(+) create mode 100644 man/giottoToAnnData.Rd diff --git a/NAMESPACE b/NAMESPACE index 24db23d0d..4a87756fa 100644 --- a/NAMESPACE +++ b/NAMESPACE @@ -188,6 +188,7 @@ export(giottoImage) export(giottoLargeImage) export(giottoPoints) export(giottoPolygon) +export(giottoToAnnData) export(giottoToSeurat) export(giottoToSpatialExperiment) export(heatmSpatialCorFeats) diff --git a/man/giottoToAnnData.Rd b/man/giottoToAnnData.Rd new file mode 100644 index 000000000..ebe8de892 --- /dev/null +++ b/man/giottoToAnnData.Rd @@ -0,0 +1,45 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/interoperability.R +\name{giottoToAnnData} +\alias{giottoToAnnData} +\title{Convert Giotto to anndata} +\usage{ +giottoToAnnData( + gobject = NULL, + spat_unit = NULL, + feat_type = NULL, + python_path = NULL, + save_directory = NULL +) +} +\arguments{ +\item{gobject}{giotto object to be converted} + +\item{spat_unit}{spatial unit which will be used in conversion.} + +\item{feat_type}{feature type which will be used in conversion.} + +\item{python_path}{path to python executable within a conda/miniconda environment} + +\item{save_directory}{directory in which the file will be saved.} +} +\value{ +vector containing .h5ad file path(s) +} +\description{ +Converts a Giotto object to a spatial anndata (e.g. scanpy) .h5ad file +} +\details{ +Function in beta. Converts a Giotto object into .h5ad file(s). + +If there are multiple spatial units and/or feature types, but only +one spatial unit and/or feature type is specified, then only the +specified spatial unit and/or feature type will be used. If NULL, +by default, all spatial units will be used in conversion. + +If multiple spatial units or feature types are specified, multiple +AnnData object will be created and returned. + +The save_directory will be created if it does not already exist. +The default save_directory is the working directory. +} From 0974e12ef6552459cb6ce7a4edec38a1a2535cf0 Mon Sep 17 00:00:00 2001 From: jiajic <72078254+jiajic@users.noreply.github.com> Date: Wed, 14 Dec 2022 16:10:28 -0500 Subject: [PATCH 037/129] Update general_help.R --- R/general_help.R | 10 +--------- 1 file changed, 1 insertion(+), 9 deletions(-) diff --git a/R/general_help.R b/R/general_help.R index a8a48ed51..c9c5df86f 100644 --- a/R/general_help.R +++ b/R/general_help.R @@ -1404,7 +1404,6 @@ readPolygonFilesVizgenHDF5 = function(boundaries_path, # open selected polygon files # append data from all FOVs to single list hdf5_list_length = length(hdf5_boundary_selected_list) - if(isTRUE(verbose)) files_read = c() init = proc.time() progressr::with_progress({ @@ -1416,10 +1415,7 @@ readPolygonFilesVizgenHDF5 = function(boundaries_path, fov_info = read_file$featuredata # update progress - if(isTRUE(verbose)) { - f_n = basename(hdf5_boundary_selected_list[[bound_i]][[1]]) - files_read = c(files_read, f_n) - } + print(basename(hdf5_boundary_selected_list[[bound_i]])) elapsed = (proc.time() - init)[[3L]] step_time = elapsed/bound_i est = (hdf5_list_length * step_time) - elapsed @@ -1427,10 +1423,6 @@ readPolygonFilesVizgenHDF5 = function(boundaries_path, return(fov_info) }) }) - if(isTRUE(verbose)) { - message('Files read:') - print(files_read) - } # # combine to FOV data single list read_list = Reduce('append', read_list) From e244f1db7a1a582750a424607b128c5f5ba36489 Mon Sep 17 00:00:00 2001 From: jiajic <72078254+jiajic@users.noreply.github.com> Date: Thu, 15 Dec 2022 11:45:10 -0500 Subject: [PATCH 038/129] add nnNetObj documentation and constructor --- NAMESPACE | 1 + NEWS.md | 11 +++++----- R/classes.R | 44 +++++++++++++++++++++++++++++++++++++++- man/create_nn_net_obj.Rd | 39 +++++++++++++++++++++++++++++++++++ man/nnNetObj-class.Rd | 27 ++++++++++++++++++++++++ man/time_format.Rd | 15 ++++++++++++++ 6 files changed, 131 insertions(+), 6 deletions(-) create mode 100644 man/create_nn_net_obj.Rd create mode 100644 man/nnNetObj-class.Rd create mode 100644 man/time_format.Rd diff --git a/NAMESPACE b/NAMESPACE index 4a87756fa..50b75cd7a 100644 --- a/NAMESPACE +++ b/NAMESPACE @@ -390,6 +390,7 @@ exportClasses(giottoImage) exportClasses(giottoLargeImage) exportClasses(giottoPoints) exportClasses(giottoPolygon) +exportClasses(nnNetObj) exportClasses(spatEnrObj) exportClasses(spatLocsObj) exportClasses(spatialGridObj) diff --git a/NEWS.md b/NEWS.md index 6efd091b7..6da014eb1 100644 --- a/NEWS.md +++ b/NEWS.md @@ -1,15 +1,16 @@ # TBD RELEASE ## Changes +- Add missing `create_nn_net_obj()` internal constructor function for S4 `nnNetObj` +- Move giotto object method-specific creation functions from `giotto.R` to `convenience.R` +- Add `createGiottoMerscopeObject()` +- Removed `createGiottoCosMxObject()` `aggregate` and `all` workflows until they are updated +- Add packages `exactextractr` and `sf` to "suggests" packages +- Add package `progressr` to "imports" packages - Add `id_col`, `x_col`, `y_col` params to `polyStamp()` to make stamp location input more flexible - Add `coord_fix_ratio` param to `spatFeatPlot2D()` and `spatFeatPlot2D_single()` -- Add `createGiottoMerscopeObject()` -- Move giotto object method-specific creation functions from `giotto.R` to `convenience.R` - Add `fread_colmatch()` internal for fread loading a subset of rows based on matches in a specified column - Add `optional` and `custom_msg` params to `package_check()` -- Add packages `exactextractr` and `sf` to "suggests" packages -- Add package `progressr` to "imports" packages -- Removed `createGiottoCosMxObject()` `aggregate` and `all` workflows until they are updated diff --git a/R/classes.R b/R/classes.R index 436ca30d0..0a78f9f15 100644 --- a/R/classes.R +++ b/R/classes.R @@ -862,6 +862,19 @@ S3toS4dimObj = function(object) { ## nnNetObj #### +### * Definition #### +# nnNetObj Class + +#' @title S4 nnNetObj +#' @description Framework to store nearest neighbor network information +#' @slot name name of nnNetObj +#' @slot nn_type type of nearest neighbor network +#' @slot igraph igraph object containing network information +#' @slot feat_type feature type of data +#' @slot spat_unit spatial unit of data +#' @slot provenance origin of aggregated information (if applicable) +#' @slot misc misc +#' @export setClass('nnNetObj', contains = c('nameData', 'nnData', 'spatFeatData', 'miscData')) @@ -1228,7 +1241,7 @@ S3toS4spatialGridObj = function(object) { -# * spatEnrObj class #### +## spatEnrObj class #### # * definition #### # spatEnrObj class @@ -1708,6 +1721,35 @@ create_dim_obj = function(name = 'test', } +#' @title Create S4 nnNetObj +#' @name create_nn_net_obj +#' @description Create an S4 nnNetObj +#' @param name name of nnNetObj +#' @param nn_type type of nearest neighbor network +#' @param igraph igraph object containing nearest neighbor information +#' @slot spat_unit spatial unit of data +#' @slot feat_type feature type of data +#' @slot provenance origin of aggregated information (if applicable) +#' @param misc misc +#' @keywords internal +create_nn_net_obj = function(name = 'test', + nn_type = NA_character_, + igraph = NULL, + spat_unit = 'cell', + feat_type = 'rna', + provenance = NULL, + misc = NULL) { + return(new('nnNetObj', + name = name, + nn_type = nn_type, + igraph = igraph, + spat_unit = spat_unit, + feat_type = feat_type, + provenance = provenance, + misc = misc)) +} + + #' @title Create S4 spatLocsObj #' @name create_spat_locs_obj #' @description Create an S4 spatLocsObj diff --git a/man/create_nn_net_obj.Rd b/man/create_nn_net_obj.Rd new file mode 100644 index 000000000..f8c8277b2 --- /dev/null +++ b/man/create_nn_net_obj.Rd @@ -0,0 +1,39 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/classes.R +\name{create_nn_net_obj} +\alias{create_nn_net_obj} +\title{Create S4 nnNetObj} +\usage{ +create_nn_net_obj( + name = "test", + nn_type = NA_character_, + igraph = NULL, + spat_unit = "cell", + feat_type = "rna", + provenance = NULL, + misc = NULL +) +} +\arguments{ +\item{name}{name of nnNetObj} + +\item{nn_type}{type of nearest neighbor network} + +\item{igraph}{igraph object containing nearest neighbor information} + +\item{misc}{misc} +} +\description{ +Create an S4 nnNetObj +} +\section{Slots}{ + +\describe{ +\item{\code{spat_unit}}{spatial unit of data} + +\item{\code{feat_type}}{feature type of data} + +\item{\code{provenance}}{origin of aggregated information (if applicable)} +}} + +\keyword{internal} diff --git a/man/nnNetObj-class.Rd b/man/nnNetObj-class.Rd new file mode 100644 index 000000000..12e0e54fd --- /dev/null +++ b/man/nnNetObj-class.Rd @@ -0,0 +1,27 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/classes.R +\docType{class} +\name{nnNetObj-class} +\alias{nnNetObj-class} +\title{S4 nnNetObj} +\description{ +Framework to store nearest neighbor network information +} +\section{Slots}{ + +\describe{ +\item{\code{name}}{name of nnNetObj} + +\item{\code{nn_type}}{type of nearest neighbor network} + +\item{\code{igraph}}{igraph object containing network information} + +\item{\code{feat_type}}{feature type of data} + +\item{\code{spat_unit}}{spatial unit of data} + +\item{\code{provenance}}{origin of aggregated information (if applicable)} + +\item{\code{misc}}{misc} +}} + diff --git a/man/time_format.Rd b/man/time_format.Rd new file mode 100644 index 000000000..be19f26e2 --- /dev/null +++ b/man/time_format.Rd @@ -0,0 +1,15 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/utilities.R +\name{time_format} +\alias{time_format} +\title{Format time for printing} +\usage{ +time_format(secs) +} +\description{ +Format time for printing +} +\details{ +Code from \code{\link[data.table]{timetaken}} +} +\keyword{internal} From 3444026cdea041645df46456f26b9e771fb381a9 Mon Sep 17 00:00:00 2001 From: jiajic <72078254+jiajic@users.noreply.github.com> Date: Thu, 15 Dec 2022 11:49:37 -0500 Subject: [PATCH 039/129] Update NEWS.md --- NEWS.md | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/NEWS.md b/NEWS.md index 6da014eb1..ad1c7c31c 100644 --- a/NEWS.md +++ b/NEWS.md @@ -1,10 +1,8 @@ # TBD RELEASE -## Changes +## Added - Add missing `create_nn_net_obj()` internal constructor function for S4 `nnNetObj` -- Move giotto object method-specific creation functions from `giotto.R` to `convenience.R` -- Add `createGiottoMerscopeObject()` -- Removed `createGiottoCosMxObject()` `aggregate` and `all` workflows until they are updated +- Add `createGiottoMerscopeObject()` convenience function - Add packages `exactextractr` and `sf` to "suggests" packages - Add package `progressr` to "imports" packages - Add `id_col`, `x_col`, `y_col` params to `polyStamp()` to make stamp location input more flexible @@ -12,8 +10,9 @@ - Add `fread_colmatch()` internal for fread loading a subset of rows based on matches in a specified column - Add `optional` and `custom_msg` params to `package_check()` - - +## Changes +- Move giotto object method-specific creation functions from `giotto.R` to `convenience.R` +- Removed `createGiottoCosMxObject()` `aggregate` and `all` workflows until they are updated # Giotto Suite 3.1.0 (2202-12-01) From f4cce95d756ba179a358f32cecee0c13e0595ed9 Mon Sep 17 00:00:00 2001 From: mattobny <59712683+mattobny@users.noreply.github.com> Date: Thu, 15 Dec 2022 15:41:59 -0500 Subject: [PATCH 040/129] Update NEWS.md Add giottoToAnnData to NEWS --- NEWS.md | 1 + 1 file changed, 1 insertion(+) diff --git a/NEWS.md b/NEWS.md index ad1c7c31c..83d89925c 100644 --- a/NEWS.md +++ b/NEWS.md @@ -1,6 +1,7 @@ # TBD RELEASE ## Added +- New `giottoToAnnData()` interoperability function to convert giotto object to squidpy flavor anndata .h5ad file(s) - Add missing `create_nn_net_obj()` internal constructor function for S4 `nnNetObj` - Add `createGiottoMerscopeObject()` convenience function - Add packages `exactextractr` and `sf` to "suggests" packages From 3eabe1a108fb4654690012c07c7fec5e46225892 Mon Sep 17 00:00:00 2001 From: jiajic <72078254+jiajic@users.noreply.github.com> Date: Fri, 16 Dec 2022 10:02:12 -0500 Subject: [PATCH 041/129] update smoothGiottoPolygons Remove verbose param for smoothGiottoPolygons, instead comment out print section --- R/general_help.R | 19 +++++++++++-------- R/giotto_structures.R | 21 +++++++++------------ 2 files changed, 20 insertions(+), 20 deletions(-) diff --git a/R/general_help.R b/R/general_help.R index c9c5df86f..9a0f964cf 100644 --- a/R/general_help.R +++ b/R/general_help.R @@ -1402,16 +1402,20 @@ readPolygonFilesVizgenHDF5 = function(boundaries_path, start extracting .hdf5 information') # open selected polygon files - # append data from all FOVs to single list hdf5_list_length = length(hdf5_boundary_selected_list) - init = proc.time() + read_file_list = lapply(hdf5_boundary_selected_list, function(hdf5_file) { + rhdf5::H5Fopen(hdf5_boundary_selected_list[[hdf5_file]][[1]], flags = H5Fopen_flags) + }) + # append data from all FOVs to single list + + init = proc.time() progressr::with_progress({ - pb = progressr::progressor(along = hdf5_boundary_selected_list) - read_list = lapply_flex(seq_along(hdf5_boundary_selected_list), cores = cores, function(bound_i) { + pb = progressr::progressor(along = read_file_list) + read_list = lapply_flex(seq_along(read_file_list), cores = cores, function(bound_i) { - # read file and select feature data - read_file = rhdf5::H5Fopen(hdf5_boundary_selected_list[[bound_i]][[1]], flags = H5Fopen_flags) + # get feature data + read_file = read_file_list[[bound_i]] fov_info = read_file$featuredata # update progress @@ -1476,8 +1480,7 @@ readPolygonFilesVizgenHDF5 = function(boundaries_path, if(smooth_polygons == TRUE) { return(smoothGiottoPolygons(cell_polygons, vertices = smooth_vertices, - set_neg_to_zero = set_neg_to_zero, - verbose = FALSE)) + set_neg_to_zero = set_neg_to_zero)) } else { return(cell_polygons) } diff --git a/R/giotto_structures.R b/R/giotto_structures.R index 65a6029a7..397d675e5 100644 --- a/R/giotto_structures.R +++ b/R/giotto_structures.R @@ -842,7 +842,6 @@ spline_poly <- function(xy, vertices = 20, k = 3, ...) { #' @param vertices number of vertices #' @param k k #' @param set_neg_to_zero set negative values to zero (default: TRUE) -#' @param verbose be verbose (default: TRUE) #' @param ... additional params to pass to \code{spline} #' @return Smoothed Giotto polygon object with reduced vertices #' @concept polygon @@ -901,17 +900,15 @@ smoothGiottoPolygons = function(gpolygon, new_spatvec = dt_to_spatVector_polygon(comb_res) - if(isTRUE(verbose)) { - for(ID in new_spatvec$poly_ID) { - bool = terra::is.valid(new_spatvec[new_spatvec$poly_ID == ID]) - if(!isTRUE(bool)) { - print(ID) - #plot(new_spatvec[new_spatvec$poly_ID == ID]) - #orig_spatvector = gpolygon@spatVector - #new_spatvec[new_spatvec$poly_ID == ID] = orig_spatvector[orig_spatvector$poly_ID == ID] - } - } - } + # for(ID in new_spatvec$poly_ID) { + # bool = terra::is.valid(new_spatvec[new_spatvec$poly_ID == ID]) + # if(!isTRUE(bool)) { + # print(ID) + # #plot(new_spatvec[new_spatvec$poly_ID == ID]) + # #orig_spatvector = gpolygon@spatVector + # #new_spatvec[new_spatvec$poly_ID == ID] = orig_spatvector[orig_spatvector$poly_ID == ID] + # } + # } new_gpolygon = create_giotto_polygon_object(name = gpolygon@name, spatVector = new_spatvec, From 17f13e6cb410e1c698ad43063a6980b3054547b9 Mon Sep 17 00:00:00 2001 From: jiajic <72078254+jiajic@users.noreply.github.com> Date: Fri, 16 Dec 2022 10:02:24 -0500 Subject: [PATCH 042/129] Update accessors - Remove deprecation section for old nesting in get_NearestNetwork --- NEWS.md | 3 ++ R/accessors.R | 83 +++++++++++---------------------------------------- 2 files changed, 21 insertions(+), 65 deletions(-) diff --git a/NEWS.md b/NEWS.md index 6efd091b7..12831d06e 100644 --- a/NEWS.md +++ b/NEWS.md @@ -11,6 +11,9 @@ - Add package `progressr` to "imports" packages - Removed `createGiottoCosMxObject()` `aggregate` and `all` workflows until they are updated +## Breaking Changes +- Removed support for deprecated nesting in `@nn_network` slot + diff --git a/R/accessors.R b/R/accessors.R index 7285bfd94..aab4dae4e 100644 --- a/R/accessors.R +++ b/R/accessors.R @@ -1282,96 +1282,49 @@ get_NearestNetwork = function(gobject, } # 2 Find the object - - # **to be deprecated - check for old nesting** - if(is.null(names(gobject@nn_network[[spat_unit]][[feat_type]])[[1]])) { # If gobject has nothing for this feat_type - available = list_nearest_networks(gobject, - spat_unit = spat_unit, - nn_type = nn_network_to_use) - if(!is.null(available)) { - if(nrow(available) > 0 & is.null(available$feat_type)) { # If ANY old nesting objects are discovered (only reports old nestings if detected) - if(is.null(network_name)) igraph_object = gobject@nn_network[[spat_unit]][[available$nn_type[[1]]]][[available$name[[1]]]] - else igraph_object = gobject@nn_network[[spat_unit]][[available$nn_type[[1]]]][[network_name]] - if(inherits(igraph_object, 'igraph')) { - if(is.null(nn_network_to_use)) message('The NN network type was not specified, default to the first: "', available$nn_type[[1]],'"') - if(is.null(network_name)) message('The NN network name was not specified, default to the first: "', available$name[[1]],'"') - ## convert igraph to data.table - if(output == 'data.table') { - igraph_object = data.table::as.data.table(igraph::get.data.frame(x = igraph_object)) - return(igraph_object) - } - return(igraph_object) - } else { - stop('There is currently no nearest-neighbor network created for - spatial unit: "', spat_unit, '" and feature type "', feat_type, '". - First run createNearestNetwork()\n') - } - } - } else { - stop('There is currently no nearest-neighbor network created for - spatial unit: "', spat_unit, '" and feature type "', feat_type, '". - First run createNearestNetwork()\n') - } - } # **deprecation end** - - - # automatic nearest network selection if(is.null(nn_network_to_use)) { - nn_network_to_use = names(gobject@nn_network[[spat_unit]][[feat_type]])[[1]] + nn_network_to_use = names(slot(gobject, 'nn_network')[[spat_unit]][[feat_type]])[[1]] if(is.null(nn_network_to_use)) { - stop('There is currently no nearest-neighbor network created for - spatial unit: "', spat_unit, '" and feature type "', feat_type, '". - First run createNearestNetwork()\n') + stop(wrap_txt('There is currently no nearest-neighbor network created for + spatial unit: "', spat_unit, '" and feature type "', feat_type, '". + First run createNearestNetwork()\n', sep = '')) } else { - message('The NN network type was not specified, default to the first: "', nn_network_to_use,'"') + wrap_msg('The NN network type was not specified, default to the first: "', + nn_network_to_use,'"', sep = '') } } if(is.null(network_name)) { - network_name = names(gobject@nn_network[[spat_unit]][[feat_type]][[nn_network_to_use]])[[1]] + network_name = names(slot(gobject, 'nn_network')[[spat_unit]][[feat_type]][[nn_network_to_use]])[[1]] if(is.null(network_name)) { - stop('There is currently no nearest-neighbor network built for spatial unit: "', spat_unit, - '" feature type: "', feat_type, '" and network type: "', nn_network_to_use,'"\n') + stop(wrap_txt('There is currently no nearest-neighbor network built for spatial unit: "', spat_unit, + '" feature type: "', feat_type, '" and network type: "', nn_network_to_use,'"\n', + sep = '')) }else { - message('The NN network name was not specified, default to the first: "', network_name,'"') + wrap_msg('The NN network name was not specified, default to the first: "', + network_name,'"', sep = '') } } # 3. get object in desired format - nnNet = gobject@nn_network[[spat_unit]][[feat_type]][[nn_network_to_use]][[network_name]] + nnNet = slot(gobject, 'nn_network')[[spat_unit]][[feat_type]][[nn_network_to_use]][[network_name]] if(is.null(nnNet)) { - stop('nn_network_to_use: "', nn_network_to_use, '" or network_name: "', network_name, '" does not exist. - Create a nearest-neighbor network first') + stop(wrap_txt('nn_network_to_use: "', nn_network_to_use, '" or network_name: "', network_name, '" does not exist. + Create a nearest-neighbor network first', sep = '')) } if(output == 'nnNetObj') { - if(inherits(nnNet, 'igraph')) { # ** TO BE DEPRECATED ** - nnNet = new('nnNetObj', - name = network_name, - nn_type = nn_network_to_use, - igraph = nnNet, - spat_unit = spat_unit, - feat_type = feat_type, - provenance = spat_unit, # assumed if nnNet is igraph - misc = NULL) - } - if(!inherits(nnNet, 'nnNetObj')) stop('Specified nnNet is neither igraph nor nnNetObj') - - # return nnNetObj - return(nnNet) + return(nnNet) # return nnNetObj } else if(output == 'igraph' | output == 'data.table') { - if(inherits(nnNet, 'nnNetObj')) { # ** TO BE DEPRECATED ** Will always be assumed to be the case moving forward - nnNet = slot(nnNet, 'igraph') - } + nnNet = slot(nnNet, 'igraph') if(output == 'igraph') return(nnNet) # return igraph - if(output == 'data.table') { - nnNet = data.table::as.data.table(igraph::get.data.frame(x = nnNet)) + nnNet = data.table::setDT(igraph::get.data.frame(x = nnNet)) return(nnNet) # return data.table } } From d1236cea7b0f5b46acde9a6a9799f852633fcab5 Mon Sep 17 00:00:00 2001 From: jiajic <72078254+jiajic@users.noreply.github.com> Date: Fri, 16 Dec 2022 10:49:45 -0500 Subject: [PATCH 043/129] Update general_help.R Update general_help.R test Update general_help.R --- R/classes.R | 4 ++-- R/general_help.R | 14 +++++++------- 2 files changed, 9 insertions(+), 9 deletions(-) diff --git a/R/classes.R b/R/classes.R index 0a78f9f15..3b2446c4f 100644 --- a/R/classes.R +++ b/R/classes.R @@ -31,7 +31,7 @@ setOldClass('data.table') -# BASIC CLASSES #### +# SUPERCLASSES #### # ** nameData Class #### #' @@ -241,7 +241,7 @@ setClass('miscData', -# SUPER CLASSES #### +# SUBCLASSES #### # ** spatFeatData #### #' Superclass for classes that contain both spatial and feature data diff --git a/R/general_help.R b/R/general_help.R index 9a0f964cf..bc4a4deed 100644 --- a/R/general_help.R +++ b/R/general_help.R @@ -1403,19 +1403,18 @@ readPolygonFilesVizgenHDF5 = function(boundaries_path, # open selected polygon files hdf5_list_length = length(hdf5_boundary_selected_list) - read_file_list = lapply(hdf5_boundary_selected_list, function(hdf5_file) { - rhdf5::H5Fopen(hdf5_boundary_selected_list[[hdf5_file]][[1]], flags = H5Fopen_flags) - }) # append data from all FOVs to single list - init = proc.time() progressr::with_progress({ - pb = progressr::progressor(along = read_file_list) - read_list = lapply_flex(seq_along(read_file_list), cores = cores, function(bound_i) { + pb = progressr::progressor(along = hdf5_boundary_selected_list) + read_list = lapply_flex(seq_along(hdf5_boundary_selected_list), + cores = cores, + future.packages = c('rhdf5', 'Rhdf5lib'), + function(bound_i) { # get feature data - read_file = read_file_list[[bound_i]] + read_file = rhdf5::H5Fopen(hdf5_boundary_selected_list[[bound_i]][[1]], flags = H5Fopen_flags) fov_info = read_file$featuredata # update progress @@ -1424,6 +1423,7 @@ readPolygonFilesVizgenHDF5 = function(boundaries_path, step_time = elapsed/bound_i est = (hdf5_list_length * step_time) - elapsed pb(message = c('// E:', time_format(elapsed), '| R:', time_format(est))) + rhdf5::H5Fclose(read_file) return(fov_info) }) }) From 2d5bed4f803e8d71e0b1662b8b6b4b6e02b42c55 Mon Sep 17 00:00:00 2001 From: jiajic <72078254+jiajic@users.noreply.github.com> Date: Sun, 18 Dec 2022 00:32:17 -0500 Subject: [PATCH 044/129] test new poly --- R/general_help.R | 221 +++++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 213 insertions(+), 8 deletions(-) diff --git a/R/general_help.R b/R/general_help.R index bc4a4deed..ced8d5adc 100644 --- a/R/general_help.R +++ b/R/general_help.R @@ -1323,7 +1323,7 @@ convertEnsemblToGeneSymbol = function(matrix, #' @title readPolygonFilesVizgenHDF5 -#' @name readPolygonFilesVizgenHDF5 +#' @name readPolygonFilesVizgenHDF5_old #' @description Read and create polygons for all cells, or for only selected FOVs. #' @param boundaries_path path to the cell_boundaries folder #' @param fovs subset of fovs to use @@ -1341,7 +1341,7 @@ convertEnsemblToGeneSymbol = function(matrix, #' @seealso \code{\link{smoothGiottoPolygons}} #' @details Set H5Fopen_flags to "H5F_ACC_RDONLY" if you encounter permission issues. #' @export -readPolygonFilesVizgenHDF5 = function(boundaries_path, +readPolygonFilesVizgenHDF5_old = function(boundaries_path, fovs = NULL, polygon_feat_types = 0:6, custom_polygon_names = NULL, @@ -1359,12 +1359,8 @@ readPolygonFilesVizgenHDF5 = function(boundaries_path, cores = determine_cores(cores) - # define for .() - x = NULL - y = NULL - cell_id = NULL - file_id = NULL - my_id = NULL + # data.table vars + x = y = cell_id = file_id = my_id = NULL # prepare poly feat names poly_feat_names = paste0('z', polygon_feat_types) @@ -1496,6 +1492,166 @@ readPolygonFilesVizgenHDF5 = function(boundaries_path, } + + +#' @title readPolygonFilesVizgenHDF5 +#' @name readPolygonFilesVizgenHDF5 +#' @description Read and create polygons for all cells, or for only selected FOVs. +#' @param boundaries_path path to the cell_boundaries folder +#' @param fovs subset of fovs to use +#' @param z_indices z indices of polygons to use +#' @param custom_polygon_names a character vector to provide custom polygon names +#' (optional) +#' @param polygon_feat_types deprecated. Use \code{z_indices} +#' @param flip_x_axis flip x axis of polygon coordinates (multiply by -1) +#' @param flip_y_axis flip y axis of polygon coordinates (multiply by -1) +#' @param smooth_polygons smooth polygons (default = TRUE) +#' @param smooth_vertices number of vertices for smoothing +#' @param set_neg_to_zero set negative values to zero when smoothing +#' @param H5Fopen_flags see \code{\link[rhdf5]{H5Fopen}} for more details +#' @param cores cores to use +#' @param verbose be verbose +#' @seealso \code{\link{smoothGiottoPolygons}} +#' @details Set H5Fopen_flags to "H5F_ACC_RDONLY" if you encounter permission issues. +#' @export +readPolygonFilesVizgenHDF5 = function(boundaries_path, + fovs = NULL, + z_indices = 1L:7L, + polygon_feat_types = NULL, + custom_polygon_names = NULL, + flip_x_axis = FALSE, + flip_y_axis = TRUE, + smooth_polygons = TRUE, + smooth_vertices = 60, + set_neg_to_zero = FALSE, + H5Fopen_flags = "H5F_ACC_RDWR", + cores = NA, + verbose = TRUE) { + + # necessary pkgs + package_check(pkg_name = 'rhdf5', repository = 'Bioc') + + cores = determine_cores(cores) + + # deprecation + if(!is.null(polygon_feat_names)) { + warning('polygon_feat_names is deprecated.\n Use z_indices instead') + z_indices = polygon_feat_types + 1L + } + + # data.table vars + x = y = z = cell_id = file_id = my_id = NULL + + # provide your own custom names + if(!is.null(custom_polygon_names)) { + + if(!is.character(custom_polygon_names)) { + stop(wrap_txt('If custom_polygon_names are provided, it needs to be a character vector')) + } + + if(length(custom_polygon_names) != length(poly_feat_names)) { + stop(wrap_txt('length of custom names need to be same as polygon_feat_types')) + } else { + poly_feat_names = custom_polygon_names + } + } + + if(isTRUE(verbose)) wrap_msg('Reading from:', boundaries_path) + # list all files in the folder + hdf5_boundary_list = list.files(full.names = TRUE, boundaries_path) + # only load subset of files if fov is given + if(!is.null(fovs)) { + + selected_hdf5s = paste0('feature_data_', fovs, '.hdf5') + selected_hdf5s_concatenated = paste0(selected_hdf5s, collapse = '|') + hdf5_boundary_selected_list = grep(selected_hdf5s_concatenated, x = hdf5_boundary_list, value = TRUE) + + } else { + hdf5_boundary_selected_list = hdf5_boundary_list + } + + if(isTRUE(verbose)) wrap_msg('finished listing .hdf5 files + start extracting .hdf5 information') + + # open selected polygon files + hdf5_list_length = length(hdf5_boundary_selected_list) + + # append data from all FOVs to single list + init = proc.time()[[3L]] + progressr::with_progress({ + pb = progressr::progressor(along = hdf5_boundary_selected_list) + read_list = lapply_flex(seq_along(hdf5_boundary_selected_list), + future.packages = c('rhdf5', 'Rhdf5lib'), + function(init, z_indices, bound_i) { + read_file = h5read_vizgen(h5File = hdf5_boundary_selected_list[[bound_i]][[1]], + z_indices = z_indices, + H5Fopen_flags = H5Fopen_flags) + + # update progress + print(basename(hdf5_boundary_selected_list[[bound_i]])) + elapsed = proc.time()[[3L]] - init + step_time = elapsed/bound_i + est = (hdf5_list_length * step_time) - elapsed + pb(message = c('// E:', time_format(elapsed), '| R:', time_format(est))) + + return(fov_info) + }, cores = cores, init = init, z_indices = z_indices) + }) + + # combine to FOV data single list + read_DT = data.table::rbindlist(read_list) + + # perform any necessary flips + if(flip_x_axis) read_DT[, x := -1 * x] + if(flip_y_axis) read_DT[, y := -1 * y] + + # separate polygons by z index + zvals = read_DT[, unique(z)] + z_names = paste0('z', zvals) + z_read_DT = lapply(seq_along(zvals), function(z_idx) { + read_DT[z == zvals[z_idx],] + }) + names(z_read_DT) = z_names + + + if(isTRUE(verbose)) wrap_msg('finished extracting .hdf5 files + start creating polygons') + + + # create Giotto polygons and add them to gobject + # smooth_cell_polygons_list = list() + progressr::with_progress({ + pb = progressr::progressor(along = z_read_DT) + smooth_cell_polygons_list = lapply_flex(seq_along(z_read_DT), cores = cores, function(i) { + dfr_subset = z_read_DT[[i]][,.(x, y, cell_id)] + cell_polygons = createGiottoPolygonsFromDfr(segmdfr = dfr_subset, + name = poly_feat_names[i], + verbose = verbose) + + pb(message = poly_feat_names[i]) + + if(smooth_polygons == TRUE) { + return(smoothGiottoPolygons(cell_polygons, + vertices = smooth_vertices, + set_neg_to_zero = set_neg_to_zero)) + } else { + return(cell_polygons) + } + }) + }) + + + # TODO: add spatial centroids + # needs to happen after smoothing to be correct + + return(smooth_cell_polygons_list) + +} + + + + + #' @title readPolygonFilesVizgen #' @name readPolygonFilesVizgen #' @description Read selected polygon files for the FOVs present in the Giotto @@ -1562,6 +1718,55 @@ readPolygonFilesVizgen = function(gobject, } + + +#' @describeIn readPolygonFilesVizgen (internal) Optimized .hdf5 reading for vizgen +#' merscope output. Returns a data.table of xyz coords and cell_id +#' @keywords internal +h5read_vizgen = function(h5File, z_indices = 1L:7L, H5Fopen_flags = "H5F_ACC_RDWR") { + + # data.table vars + group = name = NULL + + dset_names = data.table::setDT(rhdf5::h5ls(h5File, recursive = 3, datasetinfo = FALSE)) + cell_names = dset_names[group == '/featuredata', name] + z_names = dset_names[grep('zIndex', name), unique(name)] + + + fid = rhdf5::H5Fopen(h5File, flags = H5Fopen_flags) + contents = lapply(cell_names, function(fid, cell_name) { + + zD = rhdf5::H5Dopen(fid, name = paste0(c('/featuredata', cell_name, 'z_coordinates'), collapse = '/')) + zvals = rhdf5::H5Dread(zD) + rhdf5::H5Dclose(zD) + names(zvals) = z_names + + cell_data = lapply(z_names[z_indices], function(fid, zvals, z_idx) { + did = rhdf5::H5Dopen(fid, name = paste0(c('/featuredata', cell_name, z_idx, 'p_0', 'coordinates'), collapse = '/')) + res = t_flex(rhdf5::H5Dread(did)[,,1L]) + res = cbind(res, zvals[z_idx], cell_name) + colnames(res) = c('x', 'y', 'z', 'cell_id') + rhdf5::H5Dclose(did) + res + + }, fid = fid, zvals = zvals) + cell_data = data.table::as.data.table(do.call('rbind', cell_data)) + + + }, fid = fid) + rhdf5::H5Fclose(fid) + contents = data.table::rbindlist(contents) + + return(contents) +} + + + + + + + + #' @title getGEFtxCoords #' @name getGEFtxCoords #' @description Converts .gef file (output stereo-seq pipeline) into From de14d65f6a6c74ff07136a722defebacd74b7042 Mon Sep 17 00:00:00 2001 From: RubD Date: Sun, 18 Dec 2022 21:21:48 -0500 Subject: [PATCH 045/129] add order option for feature plotting --- R/spatial_visuals.R | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/R/spatial_visuals.R b/R/spatial_visuals.R index 007e665d7..1af7256f2 100644 --- a/R/spatial_visuals.R +++ b/R/spatial_visuals.R @@ -4968,6 +4968,7 @@ spatGenePlot = function(...) { #' @param spat_unit spatial unit #' @param expression_values gene expression values to use #' @param feats features to show +#' @param order order points according to feature expression #' @param dim_reduction_to_use dimension reduction to use #' @param dim_reduction_name dimension reduction name #' @param dim1_to_use dimension to use on x-axis @@ -5009,6 +5010,7 @@ dimFeatPlot2D <- function(gobject, feat_type = NULL, expression_values = c('normalized', 'scaled', 'custom'), feats = NULL, + order = TRUE, dim_reduction_to_use = 'umap', dim_reduction_name = NULL, dim1_to_use = 1, @@ -5157,6 +5159,11 @@ dimFeatPlot2D <- function(gobject, for(feat in selected_feats) { + # order spatial units (e.g. cell IDs) based on expression of feature + if(isTRUE(order)) { + annotated_feat_DT = annotated_feat_DT[order(get(feat))] + } + ## OLD need to be combined ## pl <- ggplot2::ggplot() @@ -5382,6 +5389,7 @@ dimGenePlot = function(...) { #' @param expression_values feat expression values to use #' @param plot_alignment direction to align plot #' @param feats features to show +#' @param order order points according to feature expression #' @param dim_reduction_to_use dimension reduction to use #' @param dim_reduction_name dimension reduction name #' @param dim1_to_use dimension to use on x-axis @@ -5446,6 +5454,7 @@ spatDimFeatPlot2D <- function(gobject, expression_values = c('normalized', 'scaled', 'custom'), plot_alignment = c('vertical', 'horizontal'), feats, + order = TRUE, dim_reduction_to_use = 'umap', dim_reduction_name = 'umap', dim1_to_use = 1, @@ -5505,6 +5514,7 @@ spatDimFeatPlot2D <- function(gobject, spat_unit = spat_unit, expression_values = expression_values, feats = feats, + order = order, dim_reduction_to_use = dim_reduction_to_use, dim_reduction_name = dim_reduction_name, dim1_to_use = dim1_to_use, From a6772c557c0fbac1af70b5b8271127783a6c9333 Mon Sep 17 00:00:00 2001 From: RubD Date: Sun, 18 Dec 2022 21:23:49 -0500 Subject: [PATCH 046/129] update documentation --- man/dimFeatPlot2D.Rd | 3 +++ man/dimGenePlot2D.Rd | 1 + man/smoothGiottoPolygons.Rd | 2 -- man/spatDimFeatPlot2D.Rd | 3 +++ man/spatDimGenePlot2D.Rd | 1 + 5 files changed, 8 insertions(+), 2 deletions(-) diff --git a/man/dimFeatPlot2D.Rd b/man/dimFeatPlot2D.Rd index 30d3dfe23..67d7c06e6 100644 --- a/man/dimFeatPlot2D.Rd +++ b/man/dimFeatPlot2D.Rd @@ -10,6 +10,7 @@ dimFeatPlot2D( feat_type = NULL, expression_values = c("normalized", "scaled", "custom"), feats = NULL, + order = TRUE, dim_reduction_to_use = "umap", dim_reduction_name = NULL, dim1_to_use = 1, @@ -55,6 +56,8 @@ dimFeatPlot2D( \item{feats}{features to show} +\item{order}{order points according to feature expression} + \item{dim_reduction_to_use}{dimension reduction to use} \item{dim_reduction_name}{dimension reduction name} diff --git a/man/dimGenePlot2D.Rd b/man/dimGenePlot2D.Rd index 8ad87bdb8..0f3997e3b 100644 --- a/man/dimGenePlot2D.Rd +++ b/man/dimGenePlot2D.Rd @@ -19,6 +19,7 @@ dimGenePlot2D(gobject, genes = NULL, default_save_name = "dimGenePlot2D", ...) \item{\code{feat_type}}{feature type} \item{\code{spat_unit}}{spatial unit} \item{\code{expression_values}}{gene expression values to use} + \item{\code{order}}{order points according to feature expression} \item{\code{dim_reduction_to_use}}{dimension reduction to use} \item{\code{dim_reduction_name}}{dimension reduction name} \item{\code{dim1_to_use}}{dimension to use on x-axis} diff --git a/man/smoothGiottoPolygons.Rd b/man/smoothGiottoPolygons.Rd index 5ac106a61..afa361016 100644 --- a/man/smoothGiottoPolygons.Rd +++ b/man/smoothGiottoPolygons.Rd @@ -22,8 +22,6 @@ smoothGiottoPolygons( \item{set_neg_to_zero}{set negative values to zero (default: TRUE)} -\item{verbose}{be verbose (default: TRUE)} - \item{...}{additional params to pass to \code{spline}} } \value{ diff --git a/man/spatDimFeatPlot2D.Rd b/man/spatDimFeatPlot2D.Rd index 85ec39e22..1ad5cfe31 100644 --- a/man/spatDimFeatPlot2D.Rd +++ b/man/spatDimFeatPlot2D.Rd @@ -15,6 +15,7 @@ spatDimFeatPlot2D( expression_values = c("normalized", "scaled", "custom"), plot_alignment = c("vertical", "horizontal"), feats, + order = TRUE, dim_reduction_to_use = "umap", dim_reduction_name = "umap", dim1_to_use = 1, @@ -88,6 +89,8 @@ spatDimFeatPlot2D( \item{feats}{features to show} +\item{order}{order points according to feature expression} + \item{dim_reduction_to_use}{dimension reduction to use} \item{dim_reduction_name}{dimension reduction name} diff --git a/man/spatDimGenePlot2D.Rd b/man/spatDimGenePlot2D.Rd index ad4b05996..09c01de62 100644 --- a/man/spatDimGenePlot2D.Rd +++ b/man/spatDimGenePlot2D.Rd @@ -24,6 +24,7 @@ spatDimGenePlot2D(gobject, genes, default_save_name = "spatDimGenePlot2D", ...) \item{\code{largeImage_name}}{name of a giottoLargeImage} \item{\code{expression_values}}{feat expression values to use} \item{\code{plot_alignment}}{direction to align plot} + \item{\code{order}}{order points according to feature expression} \item{\code{dim_reduction_to_use}}{dimension reduction to use} \item{\code{dim_reduction_name}}{dimension reduction name} \item{\code{dim1_to_use}}{dimension to use on x-axis} From e7a572de2a78ece5d7b5e799dfdb7ecd5dd965f9 Mon Sep 17 00:00:00 2001 From: RubD Date: Sun, 18 Dec 2022 21:31:57 -0500 Subject: [PATCH 047/129] update NEWS --- NEWS.md | 1 + 1 file changed, 1 insertion(+) diff --git a/NEWS.md b/NEWS.md index b77e411c6..813f987e4 100644 --- a/NEWS.md +++ b/NEWS.md @@ -13,6 +13,7 @@ - Add `coord_fix_ratio` param to `spatFeatPlot2D()` and `spatFeatPlot2D_single()` - Add `fread_colmatch()` internal for fread loading a subset of rows based on matches in a specified column - Add `optional` and `custom_msg` params to `package_check()` +- Add `order` parameter to `dimFeatPlot2D` and `spatDimFeatPlot2d` to plot and order cells according to the levels of the selected feature ([#477](https://github.com/drieslab/Giotto/issues/477)) ## Changes - Move giotto object method-specific creation functions from `giotto.R` to `convenience.R` From 85b19b2829f14ad68da3f890d1e109f0a5c3b5ce Mon Sep 17 00:00:00 2001 From: jiajic <72078254+jiajic@users.noreply.github.com> Date: Tue, 20 Dec 2022 10:12:57 -0500 Subject: [PATCH 048/129] update vizgen poly reading Add future.seed = TRUE to lapply_flex change readPolygonFilesVizgen() logic --- NEWS.md | 6 ++- R/general_help.R | 115 ++++++++++++++++++++++++++++++++--------------- R/utilities.R | 2 +- 3 files changed, 85 insertions(+), 38 deletions(-) diff --git a/NEWS.md b/NEWS.md index 813f987e4..049991d0e 100644 --- a/NEWS.md +++ b/NEWS.md @@ -6,18 +6,20 @@ ## Added - New `giottoToAnnData()` interoperability function to convert giotto object to squidpy flavor anndata .h5ad file(s) - Add missing `create_nn_net_obj()` internal constructor function for S4 `nnNetObj` -- Add `createGiottoMerscopeObject()` convenience function +- New `createGiottoMerscopeObject()` convenience function - Add packages `exactextractr` and `sf` to "suggests" packages - Add package `progressr` to "imports" packages - Add `id_col`, `x_col`, `y_col` params to `polyStamp()` to make stamp location input more flexible - Add `coord_fix_ratio` param to `spatFeatPlot2D()` and `spatFeatPlot2D_single()` -- Add `fread_colmatch()` internal for fread loading a subset of rows based on matches in a specified column +- New `fread_colmatch()` internal for fread loading a subset of rows based on matches in a specified column - Add `optional` and `custom_msg` params to `package_check()` - Add `order` parameter to `dimFeatPlot2D` and `spatDimFeatPlot2d` to plot and order cells according to the levels of the selected feature ([#477](https://github.com/drieslab/Giotto/issues/477)) ## Changes - Move giotto object method-specific creation functions from `giotto.R` to `convenience.R` - Removed `createGiottoCosMxObject()` `aggregate` and `all` workflows until they are updated +- Deprecate `polygon_feat_names` param in favor of `z_indices` in `readPolygonFilesVizgenHDF5()` +- Optimize `readPolygonFilesVizgen()` # Giotto Suite 3.1.0 (2202-12-01) diff --git a/R/general_help.R b/R/general_help.R index ced8d5adc..4bebd1161 100644 --- a/R/general_help.R +++ b/R/general_help.R @@ -1500,6 +1500,8 @@ readPolygonFilesVizgenHDF5_old = function(boundaries_path, #' @param boundaries_path path to the cell_boundaries folder #' @param fovs subset of fovs to use #' @param z_indices z indices of polygons to use +#' @param segm_to_use segmentation results to use (usually = 1. Depends on if +#' alternative segmentations were generated) #' @param custom_polygon_names a character vector to provide custom polygon names #' (optional) #' @param polygon_feat_types deprecated. Use \code{z_indices} @@ -1517,16 +1519,17 @@ readPolygonFilesVizgenHDF5_old = function(boundaries_path, readPolygonFilesVizgenHDF5 = function(boundaries_path, fovs = NULL, z_indices = 1L:7L, - polygon_feat_types = NULL, + segm_to_use = 1L, custom_polygon_names = NULL, flip_x_axis = FALSE, flip_y_axis = TRUE, smooth_polygons = TRUE, - smooth_vertices = 60, + smooth_vertices = 60L, set_neg_to_zero = FALSE, H5Fopen_flags = "H5F_ACC_RDWR", cores = NA, - verbose = TRUE) { + verbose = TRUE, + polygon_feat_types = NULL) { # necessary pkgs package_check(pkg_name = 'rhdf5', repository = 'Bioc') @@ -1534,11 +1537,13 @@ readPolygonFilesVizgenHDF5 = function(boundaries_path, cores = determine_cores(cores) # deprecation - if(!is.null(polygon_feat_names)) { - warning('polygon_feat_names is deprecated.\n Use z_indices instead') + if(!is.null(polygon_feat_types)) { + warning('polygon_feat_types is deprecated.\n Use z_indices instead') z_indices = polygon_feat_types + 1L } + segm_to_use = paste0('p_', (segm_to_use - 1L)) + # data.table vars x = y = z = cell_id = file_id = my_id = NULL @@ -1549,10 +1554,8 @@ readPolygonFilesVizgenHDF5 = function(boundaries_path, stop(wrap_txt('If custom_polygon_names are provided, it needs to be a character vector')) } - if(length(custom_polygon_names) != length(poly_feat_names)) { - stop(wrap_txt('length of custom names need to be same as polygon_feat_types')) - } else { - poly_feat_names = custom_polygon_names + if(length(custom_polygon_names) != length(z_indices)) { + stop(wrap_txt('length of custom names need to be same as z_indices')) } } @@ -1577,25 +1580,30 @@ readPolygonFilesVizgenHDF5 = function(boundaries_path, hdf5_list_length = length(hdf5_boundary_selected_list) # append data from all FOVs to single list - init = proc.time()[[3L]] + init = Sys.time() progressr::with_progress({ pb = progressr::progressor(along = hdf5_boundary_selected_list) read_list = lapply_flex(seq_along(hdf5_boundary_selected_list), future.packages = c('rhdf5', 'Rhdf5lib'), - function(init, z_indices, bound_i) { + function(init, z_indices, segm_to_use, bound_i) { read_file = h5read_vizgen(h5File = hdf5_boundary_selected_list[[bound_i]][[1]], z_indices = z_indices, + segm_to_use = segm_to_use, H5Fopen_flags = H5Fopen_flags) # update progress print(basename(hdf5_boundary_selected_list[[bound_i]])) - elapsed = proc.time()[[3L]] - init + elapsed = as.numeric(Sys.time() - init) step_time = elapsed/bound_i est = (hdf5_list_length * step_time) - elapsed pb(message = c('// E:', time_format(elapsed), '| R:', time_format(est))) - return(fov_info) - }, cores = cores, init = init, z_indices = z_indices) + return(read_file) + }, + cores = cores, + init = init, + z_indices = z_indices, + segm_to_use = segm_to_use) }) # combine to FOV data single list @@ -1612,7 +1620,8 @@ readPolygonFilesVizgenHDF5 = function(boundaries_path, read_DT[z == zvals[z_idx],] }) names(z_read_DT) = z_names - + if(!is.null(custom_polygon_names)) poly_names = custom_polygon_names + else poly_names = z_names if(isTRUE(verbose)) wrap_msg('finished extracting .hdf5 files start creating polygons') @@ -1625,10 +1634,10 @@ readPolygonFilesVizgenHDF5 = function(boundaries_path, smooth_cell_polygons_list = lapply_flex(seq_along(z_read_DT), cores = cores, function(i) { dfr_subset = z_read_DT[[i]][,.(x, y, cell_id)] cell_polygons = createGiottoPolygonsFromDfr(segmdfr = dfr_subset, - name = poly_feat_names[i], + name = poly_names[i], verbose = verbose) - pb(message = poly_feat_names[i]) + pb(message = poly_names[i]) if(smooth_polygons == TRUE) { return(smoothGiottoPolygons(cell_polygons, @@ -1723,45 +1732,81 @@ readPolygonFilesVizgen = function(gobject, #' @describeIn readPolygonFilesVizgen (internal) Optimized .hdf5 reading for vizgen #' merscope output. Returns a data.table of xyz coords and cell_id #' @keywords internal -h5read_vizgen = function(h5File, z_indices = 1L:7L, H5Fopen_flags = "H5F_ACC_RDWR") { +h5read_vizgen = function(h5File, + z_indices = 1L:7L, + segm_to_use = 'p_0', + H5Fopen_flags = "H5F_ACC_RDWR") { # data.table vars - group = name = NULL - - dset_names = data.table::setDT(rhdf5::h5ls(h5File, recursive = 3, datasetinfo = FALSE)) - cell_names = dset_names[group == '/featuredata', name] - z_names = dset_names[grep('zIndex', name), unique(name)] - + group = name = cell = z_name = NULL + + h5_ls = data.table::setDT(rhdf5::h5ls(h5File, recursive = 5, datasetinfo = FALSE)) + cell_names = h5_ls[group == '/featuredata', name] + cell_names = as.character(cell_names) + z_names = h5_ls[grep('zIndex', name), unique(name)] + + dset_names = h5_ls[otype == 'H5I_DATASET' & name == 'coordinates',] + # subset by segm_to_use + dset_names = dset_names[grep(segm_to_use, group),] + # tag cellnames + dset_names[, cell := gsub(pattern = '/featuredata/|/zIndex.*$', replacement = '', x = group)] + # tag z_names + dset_names[, z_name := gsub(pattern = '^.*/(zIndex_\\d*).*$', replacement = '\\1', x = group)] + # subset by z_indices + dset_names[z_name %in% z_names[z_indices],] + # create full file location + dset_names[, d_name := paste0(c(group, name), collapse = '/')] fid = rhdf5::H5Fopen(h5File, flags = H5Fopen_flags) + contents = lapply(cell_names, function(fid, cell_name) { - zD = rhdf5::H5Dopen(fid, name = paste0(c('/featuredata', cell_name, 'z_coordinates'), collapse = '/')) - zvals = rhdf5::H5Dread(zD) - rhdf5::H5Dclose(zD) + zD = .Call('_H5Dopen', fid, name = paste0(c('/featuredata', cell_name, 'z_coordinates'), collapse = '/'), NULL, PACKAGE = 'rhdf5') + zvals = .Call("_H5Dread", zD, NULL, NULL, NULL, TRUE, 0L, FALSE, FALSE, PACKAGE = "rhdf5") + invisible(.Call("_H5Dclose", zD, PACKAGE = "rhdf5")) names(zvals) = z_names - cell_data = lapply(z_names[z_indices], function(fid, zvals, z_idx) { - did = rhdf5::H5Dopen(fid, name = paste0(c('/featuredata', cell_name, z_idx, 'p_0', 'coordinates'), collapse = '/')) - res = t_flex(rhdf5::H5Dread(did)[,,1L]) - res = cbind(res, zvals[z_idx], cell_name) - colnames(res) = c('x', 'y', 'z', 'cell_id') - rhdf5::H5Dclose(did) + # subset to datasets related to cell + cell_dsets = dset_names[cell == cell_name,] + + cell_data = lapply(nrow(cell_dsets), function(fid, zvals, d_i) { + + res = .h5_read_bare(file = fid, name = cell_dsets[d_i, d_name]) + did = .Call("_H5Dopen", fid, name = cell_dsets[d_i, d_name], NULL, PACKAGE = "rhdf5") + res = .Call("_H5Dread", did, NULL, NULL, NULL, TRUE, 0L, FALSE, FALSE, PACKAGE = "rhdf5") + invisible(.Call("_H5Dclose", did, PACKAGE = "rhdf5")) + res = t_flex(res[,,1L]) + res = cbind(res, zvals[cell_dsets[d_i, z_name]]) + colnames(res) = c('x', 'y', 'z') res }, fid = fid, zvals = zvals) cell_data = data.table::as.data.table(do.call('rbind', cell_data)) - + cell_data[, cell_id := cell_name] + cell_data }, fid = fid) + rhdf5::H5Fclose(fid) contents = data.table::rbindlist(contents) + contents - return(contents) } +#' @name .h5_read_bare +#' @title Read dataset from opened HDF5 with C functions +#' @param file opened HDF5 file +#' @param name dataset name within HDF5 +#' @keywords internal +.h5_read_bare = function(file, name = "") { + did = .Call("_H5Dopen", file, name, NULL, PACKAGE = "rhdf5") + res = .Call("_H5Dread", did, NULL, NULL, NULL, TRUE, 0L, FALSE, FALSE, + PACKAGE = "rhdf5") + invisible(.Call("_H5Dclose", did, PACKAGE = "rhdf5")) + res +} diff --git a/R/utilities.R b/R/utilities.R index f6a6242df..3b50c945e 100644 --- a/R/utilities.R +++ b/R/utilities.R @@ -182,7 +182,7 @@ lapply_flex = function(X, # future_lapply call - save_list = future.apply::future_lapply(X = X, FUN = FUN, ...) + save_list = future.apply::future_lapply(X = X, FUN = FUN, future.seed = TRUE, ...) #if(os == 'unix') { # save_list = parallel::mclapply(X = X, mc.cores = cores, From 10e0803a050e820ccce9c4fe9711cb3226e7e5c0 Mon Sep 17 00:00:00 2001 From: jiajic <72078254+jiajic@users.noreply.github.com> Date: Tue, 20 Dec 2022 10:24:03 -0500 Subject: [PATCH 049/129] Update general_help.R --- R/general_help.R | 9 ++------- 1 file changed, 2 insertions(+), 7 deletions(-) diff --git a/R/general_help.R b/R/general_help.R index 4bebd1161..9261dd38c 100644 --- a/R/general_help.R +++ b/R/general_help.R @@ -1761,9 +1761,7 @@ h5read_vizgen = function(h5File, contents = lapply(cell_names, function(fid, cell_name) { - zD = .Call('_H5Dopen', fid, name = paste0(c('/featuredata', cell_name, 'z_coordinates'), collapse = '/'), NULL, PACKAGE = 'rhdf5') - zvals = .Call("_H5Dread", zD, NULL, NULL, NULL, TRUE, 0L, FALSE, FALSE, PACKAGE = "rhdf5") - invisible(.Call("_H5Dclose", zD, PACKAGE = "rhdf5")) + zD = .h5_read_bare(file = fid, name = paste0(c('/featuredata', cell_name, 'z_coordinates'), collapse = '/')) names(zvals) = z_names # subset to datasets related to cell @@ -1772,9 +1770,6 @@ h5read_vizgen = function(h5File, cell_data = lapply(nrow(cell_dsets), function(fid, zvals, d_i) { res = .h5_read_bare(file = fid, name = cell_dsets[d_i, d_name]) - did = .Call("_H5Dopen", fid, name = cell_dsets[d_i, d_name], NULL, PACKAGE = "rhdf5") - res = .Call("_H5Dread", did, NULL, NULL, NULL, TRUE, 0L, FALSE, FALSE, PACKAGE = "rhdf5") - invisible(.Call("_H5Dclose", did, PACKAGE = "rhdf5")) res = t_flex(res[,,1L]) res = cbind(res, zvals[cell_dsets[d_i, z_name]]) colnames(res) = c('x', 'y', 'z') @@ -1798,7 +1793,7 @@ h5read_vizgen = function(h5File, #' @name .h5_read_bare #' @title Read dataset from opened HDF5 with C functions #' @param file opened HDF5 file -#' @param name dataset name within HDF5 +#' @param name dataset name within #' @keywords internal .h5_read_bare = function(file, name = "") { did = .Call("_H5Dopen", file, name, NULL, PACKAGE = "rhdf5") From 45e62dfb3288cffc6112d0e2e50d7b26b4b09625 Mon Sep 17 00:00:00 2001 From: jiajic <72078254+jiajic@users.noreply.github.com> Date: Tue, 20 Dec 2022 11:14:04 -0500 Subject: [PATCH 050/129] Update general_help.R --- R/general_help.R | 28 ++++++++++++++++------------ 1 file changed, 16 insertions(+), 12 deletions(-) diff --git a/R/general_help.R b/R/general_help.R index 9261dd38c..07b45325e 100644 --- a/R/general_help.R +++ b/R/general_help.R @@ -1741,8 +1741,7 @@ h5read_vizgen = function(h5File, group = name = cell = z_name = NULL h5_ls = data.table::setDT(rhdf5::h5ls(h5File, recursive = 5, datasetinfo = FALSE)) - cell_names = h5_ls[group == '/featuredata', name] - cell_names = as.character(cell_names) + cell_names = as.character(h5_ls[group == '/featuredata', name]) z_names = h5_ls[grep('zIndex', name), unique(name)] dset_names = h5_ls[otype == 'H5I_DATASET' & name == 'coordinates',] @@ -1753,35 +1752,39 @@ h5read_vizgen = function(h5File, # tag z_names dset_names[, z_name := gsub(pattern = '^.*/(zIndex_\\d*).*$', replacement = '\\1', x = group)] # subset by z_indices - dset_names[z_name %in% z_names[z_indices],] + dset_names = dset_names[z_name %in% z_names[z_indices],] # create full file location - dset_names[, d_name := paste0(c(group, name), collapse = '/')] + dset_names[, d_name := paste0(group, '/', name)] fid = rhdf5::H5Fopen(h5File, flags = H5Fopen_flags) + dapl = rhdf5::H5Pcreate('H5P_DATASET_ACCESS') - contents = lapply(cell_names, function(fid, cell_name) { + contents = lapply(cell_names, function(fid, dapl, cell_name) { - zD = .h5_read_bare(file = fid, name = paste0(c('/featuredata', cell_name, 'z_coordinates'), collapse = '/')) + zD = .h5_read_bare(file = fid, + name = paste0(c('/featuredata', cell_name, 'z_coordinates'), collapse = '/'), + dapl = dapl) names(zvals) = z_names # subset to datasets related to cell cell_dsets = dset_names[cell == cell_name,] - cell_data = lapply(nrow(cell_dsets), function(fid, zvals, d_i) { + cell_data = lapply(nrow(cell_dsets), function(fid, dapl, zvals, d_i) { - res = .h5_read_bare(file = fid, name = cell_dsets[d_i, d_name]) + res = .h5_read_bare(file = fid, name = cell_dsets[d_i, d_name], dapl = dapl) res = t_flex(res[,,1L]) res = cbind(res, zvals[cell_dsets[d_i, z_name]]) colnames(res) = c('x', 'y', 'z') res - }, fid = fid, zvals = zvals) + }, fid = fid, dapl = dapl, zvals = zvals) cell_data = data.table::as.data.table(do.call('rbind', cell_data)) cell_data[, cell_id := cell_name] cell_data - }, fid = fid) + }, fid = fid, dapl = dapl) + rhdf5::H5Pclose(dapl) rhdf5::H5Fclose(fid) contents = data.table::rbindlist(contents) contents @@ -1794,9 +1797,10 @@ h5read_vizgen = function(h5File, #' @title Read dataset from opened HDF5 with C functions #' @param file opened HDF5 file #' @param name dataset name within +#' @param dapl HDF5 property list (H5Pcreate('H5P_DATASET_ACCESS')) #' @keywords internal -.h5_read_bare = function(file, name = "") { - did = .Call("_H5Dopen", file, name, NULL, PACKAGE = "rhdf5") +.h5_read_bare = function(file, name = "", dapl) { + did = .Call("_H5Dopen", file@ID, name, dapl@ID, PACKAGE = "rhdf5") res = .Call("_H5Dread", did, NULL, NULL, NULL, TRUE, 0L, FALSE, FALSE, PACKAGE = "rhdf5") invisible(.Call("_H5Dclose", did, PACKAGE = "rhdf5")) From fb011d9d86c5f6b26ee79ef0800969119ac07cd7 Mon Sep 17 00:00:00 2001 From: jiajic <72078254+jiajic@users.noreply.github.com> Date: Tue, 20 Dec 2022 12:05:25 -0500 Subject: [PATCH 051/129] Update general_help.R reduce progressr update frequency --- R/general_help.R | 18 ++++++++++-------- 1 file changed, 10 insertions(+), 8 deletions(-) diff --git a/R/general_help.R b/R/general_help.R index 07b45325e..0cad91a96 100644 --- a/R/general_help.R +++ b/R/general_help.R @@ -1582,7 +1582,7 @@ readPolygonFilesVizgenHDF5 = function(boundaries_path, # append data from all FOVs to single list init = Sys.time() progressr::with_progress({ - pb = progressr::progressor(along = hdf5_boundary_selected_list) + pb = progressr::progressor(length(hdf5_boundary_selected_list)/20) read_list = lapply_flex(seq_along(hdf5_boundary_selected_list), future.packages = c('rhdf5', 'Rhdf5lib'), function(init, z_indices, segm_to_use, bound_i) { @@ -1593,10 +1593,12 @@ readPolygonFilesVizgenHDF5 = function(boundaries_path, # update progress print(basename(hdf5_boundary_selected_list[[bound_i]])) - elapsed = as.numeric(Sys.time() - init) - step_time = elapsed/bound_i - est = (hdf5_list_length * step_time) - elapsed - pb(message = c('// E:', time_format(elapsed), '| R:', time_format(est))) + if(bound_i %% 20 == 0) { + elapsed = as.numeric(Sys.time() - init) + step_time = elapsed/bound_i/20 + est = (hdf5_list_length/20 * step_time) - elapsed + pb(message = c('// E:', time_format(elapsed), '| R:', time_format(est))) + } return(read_file) }, @@ -1761,9 +1763,9 @@ h5read_vizgen = function(h5File, contents = lapply(cell_names, function(fid, dapl, cell_name) { - zD = .h5_read_bare(file = fid, - name = paste0(c('/featuredata', cell_name, 'z_coordinates'), collapse = '/'), - dapl = dapl) + zvals = .h5_read_bare(file = fid, + name = paste0(c('/featuredata', cell_name, 'z_coordinates'), collapse = '/'), + dapl = dapl) names(zvals) = z_names # subset to datasets related to cell From cb9ffbb13c75a8175f00a2067237ef73246511fd Mon Sep 17 00:00:00 2001 From: jiajic <72078254+jiajic@users.noreply.github.com> Date: Tue, 20 Dec 2022 15:12:16 -0500 Subject: [PATCH 052/129] Update general_help.R fix logic --- R/general_help.R | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/R/general_help.R b/R/general_help.R index 0cad91a96..20471bfcc 100644 --- a/R/general_help.R +++ b/R/general_help.R @@ -1771,7 +1771,7 @@ h5read_vizgen = function(h5File, # subset to datasets related to cell cell_dsets = dset_names[cell == cell_name,] - cell_data = lapply(nrow(cell_dsets), function(fid, dapl, zvals, d_i) { + cell_data = lapply(seq(nrow(cell_dsets)), function(fid, dapl, zvals, d_i) { res = .h5_read_bare(file = fid, name = cell_dsets[d_i, d_name], dapl = dapl) res = t_flex(res[,,1L]) From 7ed3f6a228d4457b4e2dc91ca259d3f7a0ce10c6 Mon Sep 17 00:00:00 2001 From: jiajic <72078254+jiajic@users.noreply.github.com> Date: Tue, 20 Dec 2022 15:37:54 -0500 Subject: [PATCH 053/129] Update general_help.R --- R/general_help.R | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/R/general_help.R b/R/general_help.R index 20471bfcc..0ec18c6b0 100644 --- a/R/general_help.R +++ b/R/general_help.R @@ -1582,7 +1582,7 @@ readPolygonFilesVizgenHDF5 = function(boundaries_path, # append data from all FOVs to single list init = Sys.time() progressr::with_progress({ - pb = progressr::progressor(length(hdf5_boundary_selected_list)/20) + pb = progressr::progressor(length(hdf5_boundary_selected_list)/5) read_list = lapply_flex(seq_along(hdf5_boundary_selected_list), future.packages = c('rhdf5', 'Rhdf5lib'), function(init, z_indices, segm_to_use, bound_i) { @@ -1593,10 +1593,10 @@ readPolygonFilesVizgenHDF5 = function(boundaries_path, # update progress print(basename(hdf5_boundary_selected_list[[bound_i]])) - if(bound_i %% 20 == 0) { + if(bound_i %% 5 == 0) { elapsed = as.numeric(Sys.time() - init) - step_time = elapsed/bound_i/20 - est = (hdf5_list_length/20 * step_time) - elapsed + step_time = elapsed/bound_i/5 + est = (hdf5_list_length/5 * step_time) - elapsed pb(message = c('// E:', time_format(elapsed), '| R:', time_format(est))) } @@ -1630,10 +1630,10 @@ readPolygonFilesVizgenHDF5 = function(boundaries_path, # create Giotto polygons and add them to gobject - # smooth_cell_polygons_list = list() + # not possible to parallelize with external pointers progressr::with_progress({ pb = progressr::progressor(along = z_read_DT) - smooth_cell_polygons_list = lapply_flex(seq_along(z_read_DT), cores = cores, function(i) { + smooth_cell_polygons_list = lapply(seq_along(z_read_DT), function(i) { dfr_subset = z_read_DT[[i]][,.(x, y, cell_id)] cell_polygons = createGiottoPolygonsFromDfr(segmdfr = dfr_subset, name = poly_names[i], From 8581f15d932698adb1d5e1d34b2c6d9bf629ac79 Mon Sep 17 00:00:00 2001 From: RubD Date: Sat, 24 Dec 2022 10:02:28 +0100 Subject: [PATCH 054/129] add order for spatial feature plots --- R/spatial_visuals.R | 14 ++++++++++++++ man/spatFeatPlot2D.Rd | 3 +++ man/spatFeatPlot2D_single.Rd | 3 +++ man/spatGenePlot2D.Rd | 1 + 4 files changed, 21 insertions(+) diff --git a/R/spatial_visuals.R b/R/spatial_visuals.R index 1af7256f2..a928d798c 100644 --- a/R/spatial_visuals.R +++ b/R/spatial_visuals.R @@ -4139,6 +4139,7 @@ spatDimPlot = function(...) { #' @param sdimy y-axis dimension name (default = 'sdimy') #' @param expression_values gene expression values to use #' @param feats features to show +#' @param order order points according to feature expression #' @param cell_color_gradient vector with 3 colors for numeric data #' @param gradient_midpoint midpoint for color gradient #' @param gradient_limits vector with lower and upper limits @@ -4191,6 +4192,7 @@ spatFeatPlot2D_single <- function(gobject, sdimy = 'sdimy', expression_values = c('normalized', 'scaled', 'custom'), feats, + order = TRUE, cell_color_gradient = c('blue', 'white', 'red'), gradient_midpoint = NULL, gradient_limits = NULL, @@ -4359,6 +4361,13 @@ spatFeatPlot2D_single <- function(gobject, for(feat in selected_feats) { + + # order spatial units (e.g. cell IDs) based on expression of feature + if(isTRUE(order)) { + cell_locations_metadata_feats = cell_locations_metadata_feats[order(get(feat))] + } + + pl <- ggplot2::ggplot() pl <- pl + ggplot2::theme_classic() @@ -4627,6 +4636,7 @@ spatFeatPlot2D_single <- function(gobject, #' @param sdimy y-axis dimension name (default = 'sdimy') #' @param expression_values gene expression values to use #' @param feats features to show +#' @param order order points according to feature expression #' @param cell_color_gradient vector with 3 colors for numeric data #' @param gradient_midpoint midpoint for color gradient #' @param gradient_limits vector with lower and upper limits @@ -4681,6 +4691,7 @@ spatFeatPlot2D <- function(gobject, sdimy = 'sdimy', expression_values = c('normalized', 'scaled', 'custom'), feats, + order = TRUE, cell_color_gradient = c('blue', 'white', 'red'), gradient_midpoint = NULL, gradient_limits = NULL, @@ -4732,6 +4743,7 @@ spatFeatPlot2D <- function(gobject, sdimy = sdimy, expression_values = expression_values, feats = feats, + order = order, cell_color_gradient = cell_color_gradient, gradient_midpoint = gradient_midpoint, gradient_limits = gradient_limits, @@ -4839,6 +4851,7 @@ spatFeatPlot2D <- function(gobject, sdimy = sdimy, expression_values = expression_values, feats = feats, + order = order, cell_color_gradient = cell_color_gradient, gradient_midpoint = gradient_midpoint, gradient_limits = gradient_limits, @@ -5558,6 +5571,7 @@ spatDimFeatPlot2D <- function(gobject, sdimy = sdimy, expression_values = expression_values, feats = feats, + order = order, cell_color_gradient = cell_color_gradient, gradient_midpoint = gradient_midpoint, gradient_limits = gradient_limits, diff --git a/man/spatFeatPlot2D.Rd b/man/spatFeatPlot2D.Rd index 17774d417..38651bf0d 100644 --- a/man/spatFeatPlot2D.Rd +++ b/man/spatFeatPlot2D.Rd @@ -19,6 +19,7 @@ spatFeatPlot2D( sdimy = "sdimy", expression_values = c("normalized", "scaled", "custom"), feats, + order = TRUE, cell_color_gradient = c("blue", "white", "red"), gradient_midpoint = NULL, gradient_limits = NULL, @@ -85,6 +86,8 @@ spatFeatPlot2D( \item{feats}{features to show} +\item{order}{order points according to feature expression} + \item{cell_color_gradient}{vector with 3 colors for numeric data} \item{gradient_midpoint}{midpoint for color gradient} diff --git a/man/spatFeatPlot2D_single.Rd b/man/spatFeatPlot2D_single.Rd index 4191d7af0..176e10d58 100644 --- a/man/spatFeatPlot2D_single.Rd +++ b/man/spatFeatPlot2D_single.Rd @@ -17,6 +17,7 @@ spatFeatPlot2D_single( sdimy = "sdimy", expression_values = c("normalized", "scaled", "custom"), feats, + order = TRUE, cell_color_gradient = c("blue", "white", "red"), gradient_midpoint = NULL, gradient_limits = NULL, @@ -79,6 +80,8 @@ spatFeatPlot2D_single( \item{feats}{features to show} +\item{order}{order points according to feature expression} + \item{cell_color_gradient}{vector with 3 colors for numeric data} \item{gradient_midpoint}{midpoint for color gradient} diff --git a/man/spatGenePlot2D.Rd b/man/spatGenePlot2D.Rd index 297e7128f..d42cb9856 100644 --- a/man/spatGenePlot2D.Rd +++ b/man/spatGenePlot2D.Rd @@ -28,6 +28,7 @@ spatGenePlot2D(gobject, genes, default_save_name = "spatGenePlot2D", ...) \item{\code{sdimx}}{x-axis dimension name (default = 'sdimx')} \item{\code{sdimy}}{y-axis dimension name (default = 'sdimy')} \item{\code{expression_values}}{gene expression values to use} + \item{\code{order}}{order points according to feature expression} \item{\code{cell_color_gradient}}{vector with 3 colors for numeric data} \item{\code{gradient_midpoint}}{midpoint for color gradient} \item{\code{gradient_limits}}{vector with lower and upper limits} From 76fa8c03c4f158130ce42f1ae5c7853923e1261e Mon Sep 17 00:00:00 2001 From: irzamsarfraz Date: Sun, 1 Jan 2023 00:58:28 -0500 Subject: [PATCH 055/129] Updates to giottoToSpatialExperiment convertor --- R/interoperability.R | 323 +++++++++++++++++++++++-------------------- 1 file changed, 171 insertions(+), 152 deletions(-) diff --git a/R/interoperability.R b/R/interoperability.R index 6e2f87804..b64f1593e 100644 --- a/R/interoperability.R +++ b/R/interoperability.R @@ -225,14 +225,14 @@ anndataToGiotto = function(anndata_path = NULL, #' @param save_directory directory in which the file will be saved. #' @return vector containing .h5ad file path(s) #' @details Function in beta. Converts a Giotto object into .h5ad file(s). -#' +#' #' If there are multiple spatial units and/or feature types, but only #' one spatial unit and/or feature type is specified, then only the #' specified spatial unit and/or feature type will be used. If NULL, #' by default, all spatial units will be used in conversion. #' #' If multiple spatial units or feature types are specified, multiple -#' AnnData object will be created and returned. +#' AnnData object will be created and returned. #' #' The save_directory will be created if it does not already exist. #' The default save_directory is the working directory. @@ -247,12 +247,12 @@ giottoToAnnData <- function(gobject = NULL, if (is.null(gobject) || invalid_obj) { stop(wrap_msg("Please provide a valid Giotto Object for conversion.")) } - + # Python module import g2ad_path <- system.file("python","g2ad.py",package="Giotto") reticulate::source_python(g2ad_path) if (!is.null(save_directory)) dir_guard(save_directory) - + # Check directory, make it if it doesn't exist if (is.null(save_directory)) save_directory = paste0(getwd(),"/") else if (!dir.exists(save_directory)) { @@ -277,12 +277,12 @@ giottoToAnnData <- function(gobject = NULL, } else if (!is.null(spat_unit && is.null(feat_type))) { feat_type = unique(expr_dt$feat_type) } - + for (su in spat_unit) wrap_msg("Spatial unit(s)", su, "will be used in conversion.") for (ft in feat_type) wrap_msg("Feature type(s)", ft, "will be used in conversion.") # Iterate through spat_unit and feat_type to pull out expression data. - # By default, the raw expression in the slot of the first spatial unit + # By default, the raw expression in the slot of the first spatial unit # and first feature type (if multiple are present) will be transferred to # the AnnData.anndata.X slot # Any other expression data will be inserted into AnnData.anndata.layers @@ -296,7 +296,7 @@ giottoToAnnData <- function(gobject = NULL, su_ft_length = su_ft_length + 1 } } - + adata_list = lapply(1:su_ft_length, function(i) adata) adata_pos = 1 @@ -335,7 +335,7 @@ giottoToAnnData <- function(gobject = NULL, } adata_list[[adata_pos]] = adata adata_pos = adata_pos + 1 - adata = NULL + adata = NULL } } # Reset indexing variable @@ -426,7 +426,7 @@ giottoToAnnData <- function(gobject = NULL, } ## PCA - + # pca on feats not supported by anndata because of dimensionality agreement reqs reduction_options = c("cells", "feats") dim_red = NULL @@ -977,168 +977,187 @@ seuratToGiotto = function(sobject, #' @param giottoObj Input Giotto object to convert to a SpatialExperiment object. #' #' @return A SpatialExperiment object that contains data from the input Giotto object. +#' @example +#' mini_gobject = GiottoData::loadGiottoMini('vizgen') +#' #' @export giottoToSpatialExperiment <- function(giottoObj){ # Load required packages - package_check(pkg_name = "SummarizedExperiment", repository = 'Bioc') - package_check(pkg_name = "SingleCellExperiment", repository = 'Bioc') + # package_check(pkg_name = "SummarizedExperiment", repository = 'Bioc') # SP should load this? + # package_check(pkg_name = "SingleCellExperiment", repository = 'Bioc') # SP should load this? package_check(pkg_name = "SpatialExperiment", repository = 'Bioc') package_check(pkg_name = "S4Vectors", repository = 'Bioc') + # SpatialExperiment objects list (one object for each spatial unit) + speList <- list() + # Expression Matrices giottoExpr <- list_expression(giottoObj) - # Check if expression matrices exist in input object - if(!is.null(giottoExpr)){ - message("Copying expression matrix: ", giottoExpr[1]$name) - exprMat <- get_expression_values( - gobject = giottoObj, - spat_unit = giottoExpr[1]$spat_unit, - feat_type = giottoExpr[1]$feat_type, - values = giottoExpr[1]$name) - names(rownames(exprMat)) <- NULL - names(colnames(exprMat)) <- NULL - exprMat <- list(exprMat) - names(exprMat)[1] <- giottoExpr[1]$name - # Creating SPE object with first expression matrix - spe <- SpatialExperiment::SpatialExperiment(assays = exprMat) - giottoExpr <- giottoExpr[-1, ] - } else{ - stop("The input Giotto object must contain atleast one expression matrix.") - } - # Copying remaining expression matrices if they exist - if(nrow(giottoExpr) > 0){ - for(i in seq(nrow(giottoExpr))){ - message("Copying expression matrix: ", giottoExpr[i]$name) - # SPE does not have specific slots for different units, instead joining multiple unit names to identify them - SummarizedExperiment::assay( - spe, - paste0(giottoExpr[i]$name, "_", - giottoExpr[i]$feat_type, "_", - giottoExpr[i]$spat_unit), - withDimnames = FALSE) <- get_expression_values( + # Iterate over spatial units + spatialUnits <- unique(giottoExpr$spat_unit) # a function to get spat units? + for(su in seq(spatialUnits)){ + # Check if expression matrices exist in input object + if(!is.null(giottoExpr)){ + message("Copying expression matrix: '", giottoExpr[1]$name, "' for spatial unit: '", spatialUnits[su], "'") + exprMat <- get_expression_values( gobject = giottoObj, - spat_unit = giottoExpr[i]$spat_unit, - feat_type = giottoExpr[i]$feat_type, - values = giottoExpr[i]$name) + spat_unit = spatialUnits[su], + feat_type = giottoExpr[1]$feat_type, + values = giottoExpr[1]$name, + output = "matrix") + names(rownames(exprMat)) <- NULL + names(colnames(exprMat)) <- NULL + exprMat <- list(exprMat) + names(exprMat)[1] <- giottoExpr[1]$name + # Creating SPE object with first expression matrix + spe <- SpatialExperiment::SpatialExperiment(assays = exprMat) + assayNames(spe) <- paste0(giottoExpr[1]$name, "_", + giottoExpr[1]$feat_type, "_", + spatialUnits[su]) + giottoExpr <- giottoExpr[-1, ] + } else{ + stop("The input Giotto object must contain atleast one expression matrix.") } - } - - # Cell Metadata to ColData - if(nrow(pDataDT(giottoObj)) > 0){ - message("Copying phenotype data") - pData <- pDataDT(giottoObj) - SummarizedExperiment::colData(spe) <- S4Vectors::DataFrame(pData, row.names = pData$cell_ID) - } else{ - message("No phenotype data found in input Giotto object") - } - - # Feature Metadata to RowData - if(nrow(fDataDT(giottoObj)) > 0){ - message("Copying feature metadata") - SummarizedExperiment::rowData(spe) <- fDataDT(giottoObj) - } else{ - message("No feature metadata found in input Giotto object") - } - # Spatial Locations to Spatial Coordinates - if(!is.null(get_spatial_locations(giottoObj))){ - message("Copying spatial locations") - SpatialExperiment::spatialCoords(spe) <- data.matrix(get_spatial_locations(giottoObj)[, 1:2]) - } else{ - message("No spatial locations found in the input Giotto object") - } - - # DimReductions - giottoReductions <- list_dim_reductions(giottoObj) - if(!is.null(giottoReductions)){ - message("Copying reduced dimensions") - for(i in seq(nrow(giottoReductions))){ - SingleCellExperiment::reducedDim(spe, giottoReductions[i]$name) <- get_dimReduction( - gobject = giottoObj, - reduction = "cells", - spat_unit = giottoReductions[i]$spat_unit, - feat_type = giottoReductions[i]$feat_type, - reduction_method = giottoReductions[i]$dim_type, - name = giottoReductions[i]$name) - } - } else{ - message("No reduced dimensions found in the input Giotto object") - } - - # SpatialGrid - - # NN Graph - giottoNearestNetworks <- list_nearest_networks(giottoObj) - if(!is.null(giottoNearestNetworks)){ - message("Copying nearest networks") - for(i in seq(nrow(giottoNearestNetworks))){ - nn_network <- get_NearestNetwork( - gobject = giottoObj, - spat_unit = giottoNearestNetworks[i]$spat_unit, - output = "data.table", - nn_network_to_use = giottoNearestNetworks[i]$type, - network_name = giottoNearestNetworks[i]$name) - - # SPE stores in colpairs, with col indices instead of colnames - cell1 <- match(nn_network$from, pDataDT(giottoObj)$cell_ID) - cell2 <- match(nn_network$to, pDataDT(giottoObj)$cell_ID) - - SingleCellExperiment::colPair(spe, giottoNearestNetworks[i]$name) <- S4Vectors::SelfHits( - cell1, cell2, nnode=ncol(spe), nn_network[, -1:-2]) #removing from and to + # Copying remaining expression matrices if they exist + if(nrow(giottoExpr[spat_unit == spatialUnits[su]]) > 0){ + for(i in seq(nrow(giottoExpr))){ + message("Copying expression matrix: '", giottoExpr[i]$name, "' for spatial unit: '", spatialUnits[su], "'") + # SPE does not have specific slots for different units, instead joining multiple unit names to identify them + SummarizedExperiment::assay( + spe, + paste0(giottoExpr[i]$name, "_", + giottoExpr[i]$feat_type, "_", + spatialUnits[su]), + withDimnames = FALSE) <- get_expression_values( + gobject = giottoObj, + spat_unit = spatialUnits[su], + feat_type = giottoExpr[i]$feat_type, + values = giottoExpr[i]$name, + output = "matrix") + } } - } else{ - message("No nearest networks found in the input Giotto object") - } - - # Spatial Networks - giottoSpatialNetworks <- list_spatial_networks(giottoObj) - if(!is.null(giottoSpatialNetworks)){ - message("Copying spatial networks") - for(i in seq(nrow(giottoSpatialNetworks))){ - sp_network <- get_spatialNetwork(gobject = giottoObj, spat_unit = giottoSpatialNetworks[i]$spat_unit, name = giottoSpatialNetworks[i]$name) - # spe stores in colpairs, with col indices instead of colnames - cell1 <- match(sp_network$from, pDataDT(giottoObj)$cell_ID) - cell2 <- match(sp_network$to, pDataDT(giottoObj)$cell_ID) - - SingleCellExperiment::colPair(spe, giottoSpatialNetworks[i]$name) <- S4Vectors::SelfHits( - cell1, cell2, nnode=ncol(spe), sp_network[, -1:-2]) #removing from and to - } - } else{ - message("No spatial networks found in the input Giotto object") + # Add spe for current spatial unit to speList + speList[[su]] <- spe } - # SpatialImages - giottoImages <- list_images(giottoObj) - if(!is.null(giottoImages)){ - message("Copying spatial images") - for(i in seq(nrow(giottoImages))){ - img <- get_giottoImage( - gobject = giottoObj, - image_type = giottoImages[i]$img_type, - name = giottoImages[i]$name) - - if(!is.null(img@file_path)){ - spe <- SpatialExperiment::addImg(spe, - sample_id = "sample01", #TODO? different samples get appended to cell_ids - image_id = img@name, - imageSource = img@file_path, - scaleFactor = NA_real_, - load = TRUE) - } - else{ - message("\t - Skipping image with NULL file path") - } - S4Vectors::metadata(spe)[[img@name]] <- img - } - } else{ - message("No spatial images found in the input Giotto object") - } + # # Cell Metadata to ColData + # if(nrow(pDataDT(giottoObj)) > 0){ + # message("Copying phenotype data") + # pData <- pDataDT(giottoObj) + # SummarizedExperiment::colData(spe) <- S4Vectors::DataFrame(pData, row.names = pData$cell_ID) + # } else{ + # message("No phenotype data found in input Giotto object") + # } + # + # # Feature Metadata to RowData + # if(nrow(fDataDT(giottoObj)) > 0){ + # message("Copying feature metadata") + # SummarizedExperiment::rowData(spe) <- fDataDT(giottoObj) + # } else{ + # message("No feature metadata found in input Giotto object") + # } + # + # # Spatial Locations to Spatial Coordinates + # if(!is.null(get_spatial_locations(giottoObj))){ + # message("Copying spatial locations") + # SpatialExperiment::spatialCoords(spe) <- data.matrix(get_spatial_locations(giottoObj)[, 1:2]) + # } else{ + # message("No spatial locations found in the input Giotto object") + # } + # + # # DimReductions + # giottoReductions <- list_dim_reductions(giottoObj) + # if(!is.null(giottoReductions)){ + # message("Copying reduced dimensions") + # for(i in seq(nrow(giottoReductions))){ + # SingleCellExperiment::reducedDim(spe, giottoReductions[i]$name) <- get_dimReduction( + # gobject = giottoObj, + # reduction = "cells", + # spat_unit = giottoReductions[i]$spat_unit, + # feat_type = giottoReductions[i]$feat_type, + # reduction_method = giottoReductions[i]$dim_type, + # name = giottoReductions[i]$name) + # } + # } else{ + # message("No reduced dimensions found in the input Giotto object") + # } + # + # # SpatialGrid + # + # # NN Graph + # giottoNearestNetworks <- list_nearest_networks(giottoObj) + # if(!is.null(giottoNearestNetworks)){ + # message("Copying nearest networks") + # for(i in seq(nrow(giottoNearestNetworks))){ + # nn_network <- get_NearestNetwork( + # gobject = giottoObj, + # spat_unit = giottoNearestNetworks[i]$spat_unit, + # output = "data.table", + # nn_network_to_use = giottoNearestNetworks[i]$type, + # network_name = giottoNearestNetworks[i]$name) + # + # # SPE stores in colpairs, with col indices instead of colnames + # cell1 <- match(nn_network$from, pDataDT(giottoObj)$cell_ID) + # cell2 <- match(nn_network$to, pDataDT(giottoObj)$cell_ID) + # + # SingleCellExperiment::colPair(spe, giottoNearestNetworks[i]$name) <- S4Vectors::SelfHits( + # cell1, cell2, nnode=ncol(spe), nn_network[, -1:-2]) #removing from and to + # } + # } else{ + # message("No nearest networks found in the input Giotto object") + # } + # + # # Spatial Networks + # giottoSpatialNetworks <- list_spatial_networks(giottoObj) + # if(!is.null(giottoSpatialNetworks)){ + # message("Copying spatial networks") + # for(i in seq(nrow(giottoSpatialNetworks))){ + # sp_network <- get_spatialNetwork(gobject = giottoObj, spat_unit = giottoSpatialNetworks[i]$spat_unit, name = giottoSpatialNetworks[i]$name) + # + # # spe stores in colpairs, with col indices instead of colnames + # cell1 <- match(sp_network$from, pDataDT(giottoObj)$cell_ID) + # cell2 <- match(sp_network$to, pDataDT(giottoObj)$cell_ID) + # + # SingleCellExperiment::colPair(spe, giottoSpatialNetworks[i]$name) <- S4Vectors::SelfHits( + # cell1, cell2, nnode=ncol(spe), sp_network[, -1:-2]) #removing from and to + # } + # } else{ + # message("No spatial networks found in the input Giotto object") + # } + # + # # SpatialImages + # giottoImages <- list_images(giottoObj) + # if(!is.null(giottoImages)){ + # message("Copying spatial images") + # for(i in seq(nrow(giottoImages))){ + # img <- get_giottoImage( + # gobject = giottoObj, + # image_type = giottoImages[i]$img_type, + # name = giottoImages[i]$name) + # + # if(!is.null(img@file_path)){ + # spe <- SpatialExperiment::addImg(spe, + # sample_id = "sample01", #TODO? different samples get appended to cell_ids + # image_id = img@name, + # imageSource = img@file_path, + # scaleFactor = NA_real_, + # load = TRUE) + # } + # else{ + # message("\t - Skipping image with NULL file path") + # } + # S4Vectors::metadata(spe)[[img@name]] <- img + # } + # } else{ + # message("No spatial images found in the input Giotto object") + # } # return SPE - return(spe) + return(speList) } From f61ab8cf86a813e4eb518a73e57100edeb53572b Mon Sep 17 00:00:00 2001 From: irzamsarfraz Date: Sun, 1 Jan 2023 12:38:54 -0500 Subject: [PATCH 056/129] Fixed other slots for separate spe objects --- R/interoperability.R | 240 +++++++++++++++++++++++-------------------- 1 file changed, 127 insertions(+), 113 deletions(-) diff --git a/R/interoperability.R b/R/interoperability.R index b64f1593e..79226556d 100644 --- a/R/interoperability.R +++ b/R/interoperability.R @@ -998,6 +998,7 @@ giottoToSpatialExperiment <- function(giottoObj){ # Iterate over spatial units spatialUnits <- unique(giottoExpr$spat_unit) # a function to get spat units? for(su in seq(spatialUnits)){ + message("Processing spatial unit: '", spatialUnits[su], "'") # Check if expression matrices exist in input object if(!is.null(giottoExpr)){ message("Copying expression matrix: '", giottoExpr[1]$name, "' for spatial unit: '", spatialUnits[su], "'") @@ -1040,123 +1041,136 @@ giottoToSpatialExperiment <- function(giottoObj){ } } + # Cell Metadata to ColData + pData <- pDataDT(gobject = giottoObj, spat_unit = spatialUnits[su]) + if(nrow(pData) > 0){ + message("Copying phenotype data for spatial unit: '", spatialUnits[su], "'") + SummarizedExperiment::colData(spe) <- S4Vectors::DataFrame(pData, row.names = pData$cell_ID) + } else{ + message("No phenotype data found in input Giotto object") + } + + # Feature Metadata to RowData + fData <- fDataDT(gobject = giottoObj, spat_unit = spatialUnits[su]) + if(nrow(fData) > 0){ + message("Copying feature metadata for spatial unit: '", spatialUnits[su], "'") + SummarizedExperiment::rowData(spe) <- fData + } else{ + message("No feature metadata found in input Giotto object") + } + + # Spatial Locations to Spatial Coordinates + spatialLocs <- get_spatial_locations(gobject = giottoObj, + spat_unit = spatialUnits[su], + output = "data.table") + if(!is.null(spatialLocs)){ + message("Copying spatial locations for spatial unit: '", spatialUnits[su], "'") + SpatialExperiment::spatialCoords(spe) <- data.matrix(spatialLocs[, 1:2]) + } else{ + message("No spatial locations found in the input Giotto object") + } + + # DimReductions + giottoReductions <- list_dim_reductions(gobject = giottoObj, spat_unit = spatialUnits[su]) + if(!is.null(giottoReductions)){ + message("Copying reduced dimensions for spatial unit: '", spatialUnits[su], "'") + for(i in seq(nrow(giottoReductions))){ + SingleCellExperiment::reducedDim(spe, giottoReductions[i]$name) <- get_dimReduction( + gobject = giottoObj, + reduction = "cells", + spat_unit = spatialUnits[su], + feat_type = giottoReductions[i]$feat_type, + reduction_method = giottoReductions[i]$dim_type, + name = giottoReductions[i]$name, + output = "data.table") + } + } else{ + message("No reduced dimensions found in the input Giotto object") + } + + + # NN Graph + giottoNearestNetworks <- list_nearest_networks(gobject = giottoObj, spat_unit = spatialUnits[su]) + if(!is.null(giottoNearestNetworks)){ + message("Copying nearest networks for spatial unit: '", spatialUnits[su], "'") + for(i in seq(nrow(giottoNearestNetworks))){ + nn_network <- get_NearestNetwork( + gobject = giottoObj, + spat_unit = spatialUnits[su], + nn_network_to_use = giottoNearestNetworks[i]$type, + network_name = giottoNearestNetworks[i]$name, + output = "data.table") + + # SPE stores in colpairs, with col indices instead of colnames + cell1 <- match(nn_network$from, pData$cell_ID) + cell2 <- match(nn_network$to, pData$cell_ID) + + SingleCellExperiment::colPair(spe, giottoNearestNetworks[i]$name) <- S4Vectors::SelfHits( + cell1, cell2, nnode=ncol(spe), + nn_network[, -1:-2] #removing from and to + ) + } + } else{ + message("No nearest networks found in the input Giotto object") + } + + # Spatial Networks + giottoSpatialNetworks <- list_spatial_networks(gobject = giottoObj, spat_unit = spatialUnits[su]) + if(!is.null(giottoSpatialNetworks)){ + message("Copying spatial networks for spatial unit: '", spatialUnits[su], "'") + for(i in seq(nrow(giottoSpatialNetworks))){ + sp_network <- get_spatialNetwork( + gobject = giottoObj, + spat_unit = spatialUnits[su], + name = giottoSpatialNetworks[i]$name, + output = "networkDT") + + # spe stores in colpairs, with col indices instead of colnames + cell1 <- match(sp_network$from, pData$cell_ID) + cell2 <- match(sp_network$to, pData$cell_ID) + + SingleCellExperiment::colPair(spe, giottoSpatialNetworks[i]$name) <- S4Vectors::SelfHits( + cell1, cell2, nnode=ncol(spe), + sp_network[, -1:-2] #removing from and to + ) + } + } else{ + message("No spatial networks found in the input Giotto object") + } + + # SpatialImages - are these for each spatial unit? + giottoImages <- list_images(gobject = giottoObj) + if(!is.null(giottoImages)){ + message("Copying spatial images") + for(i in seq(nrow(giottoImages))){ + img <- get_giottoImage( + gobject = giottoObj, + image_type = giottoImages[i]$img_type, + name = giottoImages[i]$name) + + if(!is.null(img@file_path)){ + spe <- SpatialExperiment::addImg(spe, + sample_id = "sample01", #TODO? different samples get appended to cell_ids + image_id = img@name, + imageSource = img@file_path, + scaleFactor = NA_real_, + load = TRUE) + } + else{ + message("\t - Skipping image with NULL file path") + } + S4Vectors::metadata(spe)[[img@name]] <- img + } + } else{ + message("No spatial images found in the input Giotto object") + } + + message("") # Add spe for current spatial unit to speList speList[[su]] <- spe } - # # Cell Metadata to ColData - # if(nrow(pDataDT(giottoObj)) > 0){ - # message("Copying phenotype data") - # pData <- pDataDT(giottoObj) - # SummarizedExperiment::colData(spe) <- S4Vectors::DataFrame(pData, row.names = pData$cell_ID) - # } else{ - # message("No phenotype data found in input Giotto object") - # } - # - # # Feature Metadata to RowData - # if(nrow(fDataDT(giottoObj)) > 0){ - # message("Copying feature metadata") - # SummarizedExperiment::rowData(spe) <- fDataDT(giottoObj) - # } else{ - # message("No feature metadata found in input Giotto object") - # } - # - # # Spatial Locations to Spatial Coordinates - # if(!is.null(get_spatial_locations(giottoObj))){ - # message("Copying spatial locations") - # SpatialExperiment::spatialCoords(spe) <- data.matrix(get_spatial_locations(giottoObj)[, 1:2]) - # } else{ - # message("No spatial locations found in the input Giotto object") - # } - # - # # DimReductions - # giottoReductions <- list_dim_reductions(giottoObj) - # if(!is.null(giottoReductions)){ - # message("Copying reduced dimensions") - # for(i in seq(nrow(giottoReductions))){ - # SingleCellExperiment::reducedDim(spe, giottoReductions[i]$name) <- get_dimReduction( - # gobject = giottoObj, - # reduction = "cells", - # spat_unit = giottoReductions[i]$spat_unit, - # feat_type = giottoReductions[i]$feat_type, - # reduction_method = giottoReductions[i]$dim_type, - # name = giottoReductions[i]$name) - # } - # } else{ - # message("No reduced dimensions found in the input Giotto object") - # } - # - # # SpatialGrid - # - # # NN Graph - # giottoNearestNetworks <- list_nearest_networks(giottoObj) - # if(!is.null(giottoNearestNetworks)){ - # message("Copying nearest networks") - # for(i in seq(nrow(giottoNearestNetworks))){ - # nn_network <- get_NearestNetwork( - # gobject = giottoObj, - # spat_unit = giottoNearestNetworks[i]$spat_unit, - # output = "data.table", - # nn_network_to_use = giottoNearestNetworks[i]$type, - # network_name = giottoNearestNetworks[i]$name) - # - # # SPE stores in colpairs, with col indices instead of colnames - # cell1 <- match(nn_network$from, pDataDT(giottoObj)$cell_ID) - # cell2 <- match(nn_network$to, pDataDT(giottoObj)$cell_ID) - # - # SingleCellExperiment::colPair(spe, giottoNearestNetworks[i]$name) <- S4Vectors::SelfHits( - # cell1, cell2, nnode=ncol(spe), nn_network[, -1:-2]) #removing from and to - # } - # } else{ - # message("No nearest networks found in the input Giotto object") - # } - # - # # Spatial Networks - # giottoSpatialNetworks <- list_spatial_networks(giottoObj) - # if(!is.null(giottoSpatialNetworks)){ - # message("Copying spatial networks") - # for(i in seq(nrow(giottoSpatialNetworks))){ - # sp_network <- get_spatialNetwork(gobject = giottoObj, spat_unit = giottoSpatialNetworks[i]$spat_unit, name = giottoSpatialNetworks[i]$name) - # - # # spe stores in colpairs, with col indices instead of colnames - # cell1 <- match(sp_network$from, pDataDT(giottoObj)$cell_ID) - # cell2 <- match(sp_network$to, pDataDT(giottoObj)$cell_ID) - # - # SingleCellExperiment::colPair(spe, giottoSpatialNetworks[i]$name) <- S4Vectors::SelfHits( - # cell1, cell2, nnode=ncol(spe), sp_network[, -1:-2]) #removing from and to - # } - # } else{ - # message("No spatial networks found in the input Giotto object") - # } - # - # # SpatialImages - # giottoImages <- list_images(giottoObj) - # if(!is.null(giottoImages)){ - # message("Copying spatial images") - # for(i in seq(nrow(giottoImages))){ - # img <- get_giottoImage( - # gobject = giottoObj, - # image_type = giottoImages[i]$img_type, - # name = giottoImages[i]$name) - # - # if(!is.null(img@file_path)){ - # spe <- SpatialExperiment::addImg(spe, - # sample_id = "sample01", #TODO? different samples get appended to cell_ids - # image_id = img@name, - # imageSource = img@file_path, - # scaleFactor = NA_real_, - # load = TRUE) - # } - # else{ - # message("\t - Skipping image with NULL file path") - # } - # S4Vectors::metadata(spe)[[img@name]] <- img - # } - # } else{ - # message("No spatial images found in the input Giotto object") - # } - - # return SPE + # return list of spe objects return(speList) } From bcf0de1bc88a2dfc2106ef61e1ca921c7a86ca6b Mon Sep 17 00:00:00 2001 From: irzamsarfraz Date: Sun, 1 Jan 2023 22:45:42 -0500 Subject: [PATCH 057/129] Added spatialExperimentToGiotto convertor function --- DESCRIPTION | 2 +- NAMESPACE | 1 + R/interoperability.R | 78 +++++++++++++++++++++++++++++++- man/giottoToAnnData.Rd | 2 +- man/giottoToSpatialExperiment.Rd | 5 ++ man/spatialExperimentToGiotto.Rd | 22 +++++++++ 6 files changed, 106 insertions(+), 4 deletions(-) create mode 100644 man/spatialExperimentToGiotto.Rd diff --git a/DESCRIPTION b/DESCRIPTION index 0c62ec577..cac5e123d 100644 --- a/DESCRIPTION +++ b/DESCRIPTION @@ -20,7 +20,7 @@ Encoding: UTF-8 LazyData: true URL: https://drieslab.github.io/Giotto/, https://github.com/drieslab/Giotto BugReports: https://github.com/drieslab/Giotto/issues -RoxygenNote: 7.2.2 +RoxygenNote: 7.2.3 Depends: base (>= 3.5.0), utils (>= 3.5.0), diff --git a/NAMESPACE b/NAMESPACE index 50b75cd7a..a2a33bf25 100644 --- a/NAMESPACE +++ b/NAMESPACE @@ -360,6 +360,7 @@ export(spatPlot3D) export(spatUnit) export(spatialAEH) export(spatialDE) +export(spatialExperimentToGiotto) export(specificCellCellcommunicationScores) export(stitchFieldCoordinates) export(stitchGiottoLargeImage) diff --git a/R/interoperability.R b/R/interoperability.R index 79226556d..45f6d1f0c 100644 --- a/R/interoperability.R +++ b/R/interoperability.R @@ -977,8 +977,9 @@ seuratToGiotto = function(sobject, #' @param giottoObj Input Giotto object to convert to a SpatialExperiment object. #' #' @return A SpatialExperiment object that contains data from the input Giotto object. -#' @example -#' mini_gobject = GiottoData::loadGiottoMini('vizgen') +#' @examples +#' mini_gobject <- GiottoData::loadGiottoMini('vizgen') +#' giottoToSpatialExperiment(mini_gobject) #' #' @export giottoToSpatialExperiment <- function(giottoObj){ @@ -1175,4 +1176,77 @@ giottoToSpatialExperiment <- function(giottoObj){ } +#' Utility function to convert a SpatialExperiment object to a Giotto object +#' +#' @param spe Input SpatialExperiment object to convert to a Giotto object +#' +#' @return Output Giotto object +#' @examples +#' library(SpatialExperiment) +#' example(read10xVisium, echo = FALSE) +#' spatialExperimentToGiotto(spe) +#' @export +spatialExperimentToGiotto <- function(spe){ + # save exp matrices + exprMats <- assays(spe) + exprMatsNames <- assayNames(spe) + firstMatrix <- exprMats[[1]] + #check unique colnames + if(length(unique(colnames(firstMatrix))) != length(colnames(firstMatrix))){ + colnames(firstMatrix) <- make.names(colnames(firstMatrix), unique = TRUE) + } + giottoObj <- createGiottoObject(expression = firstMatrix) + exprMats[[1]] <- NULL + #rest of assays # how to figure out spat unit? + if(length(exprMats) > 0){ + for(i in seq(exprMats)){ + giottoObj <- set_expression_values(gobject = giottoObj, name = exprMatsNames[i], values = exprMats[[i]]) + } + } + + # save coldata + pData <- colData(spe) + if(nrow(pData) > 0){ + giottoObj <- Giotto::addCellMetadata(gobject = giottoObj, new_metadata = as.data.table(pData)) + } + + # save rowdata + fData <- rowData(spe) + if(nrow(fData) > 0){ + giottoObj <- Giotto::addFeatMetadata(gobject = giottoObj, new_metadata = as.data.table(fData)) + } + + # save reducedDims + redDims <- reducedDims(spe) + redDimsNames <- reducedDimNames(spe) + if(length(redDims) > 0){ + for(i in seq(length(redDims))){ + dimRedObj <- Giotto:::create_dimObject(name = redDimsNames[i], + coordinates = redDims[[i]], + reduction_method = redDimsNames[i]) + giottoObj <- Giotto:::set_dimReduction(gobject = giottoObj, dimObject = dimRedObj) + } + } + + # sp coordinates + spatialLocs <- spatialCoords(spe) + if(ncol(spatialLocs) > 0){ + spatialLocsDT <- data.table(sdimx = spatialLocs[, 1], sdimy = spatialLocs[, 2], cell_ID = rownames(spatialLocs)) + giottoObj <- Giotto:::set_spatial_locations(gobject = giottoObj, spatlocs = spatialLocsDT) + } + + # TODO + # images + # giottoObj <- Giotto::addGiottoImage() + + # TODO + # networks + # giottoObj <- Giotto:::set_spatialNetwork() + # giottoObj <- Giotto:::set_NearestNetwork() + + + return(giottoObj) +} + + diff --git a/man/giottoToAnnData.Rd b/man/giottoToAnnData.Rd index ebe8de892..4c865ff66 100644 --- a/man/giottoToAnnData.Rd +++ b/man/giottoToAnnData.Rd @@ -38,7 +38,7 @@ specified spatial unit and/or feature type will be used. If NULL, by default, all spatial units will be used in conversion. If multiple spatial units or feature types are specified, multiple -AnnData object will be created and returned. +AnnData object will be created and returned. The save_directory will be created if it does not already exist. The default save_directory is the working directory. diff --git a/man/giottoToSpatialExperiment.Rd b/man/giottoToSpatialExperiment.Rd index b9569d182..ff390c190 100644 --- a/man/giottoToSpatialExperiment.Rd +++ b/man/giottoToSpatialExperiment.Rd @@ -15,3 +15,8 @@ A SpatialExperiment object that contains data from the input Giotto object. \description{ Utility function to convert a Giotto object to a SpatialExperiment object. } +\examples{ +mini_gobject <- GiottoData::loadGiottoMini('vizgen') +giottoToSpatialExperiment(mini_gobject) + +} diff --git a/man/spatialExperimentToGiotto.Rd b/man/spatialExperimentToGiotto.Rd new file mode 100644 index 000000000..f60da7367 --- /dev/null +++ b/man/spatialExperimentToGiotto.Rd @@ -0,0 +1,22 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/interoperability.R +\name{spatialExperimentToGiotto} +\alias{spatialExperimentToGiotto} +\title{Utility function to convert a SpatialExperiment object to a Giotto object} +\usage{ +spatialExperimentToGiotto(spe) +} +\arguments{ +\item{spe}{Input SpatialExperiment object to convert to a Giotto object} +} +\value{ +Output Giotto object +} +\description{ +Utility function to convert a SpatialExperiment object to a Giotto object +} +\examples{ +library(SpatialExperiment) +example(read10xVisium, echo = FALSE) +spatialExperimentToGiotto(spe) +} From 565b21b535c0ad4c12eab0b6f77b417595d79093 Mon Sep 17 00:00:00 2001 From: mattobny Date: Tue, 3 Jan 2023 14:25:32 -0500 Subject: [PATCH 058/129] set NN for giottoToAnnData --- R/globals.R | 2 +- R/interoperability.R | 106 ++++++++++++++++++++++++++++++++++++------- inst/python/g2ad.py | 42 +++++++++++++++++ 3 files changed, 133 insertions(+), 17 deletions(-) diff --git a/R/globals.R b/R/globals.R index 22821f5bc..7f5262555 100644 --- a/R/globals.R +++ b/R/globals.R @@ -14,5 +14,5 @@ utils::globalVariables(names = c(":=", ".N", ".SD", ".", "cast", "extract_pca","extract_umap","extract_tsne", "parse_obsm_for_spat_locs","extract_cell_metadata", "extract_feat_metadata","extract_layer_names", - "extract_layered_data")) + "extract_layered_data","set_adg_nn")) diff --git a/R/interoperability.R b/R/interoperability.R index 6e2f87804..3160c57a3 100644 --- a/R/interoperability.R +++ b/R/interoperability.R @@ -400,23 +400,23 @@ giottoToAnnData <- function(gobject = NULL, # error hanldling wrapper to get_dimReduction try_get_dimReduction = function(gobject, - spat_unit, - feat_type, - reduction, - reduction_method, - name, - output, - set_defaults) { + spat_unit, + feat_type, + reduction, + reduction_method, + name, + output, + set_defaults) { tryCatch( { dim_red = get_dimReduction(gobject = gobject, - spat_unit = spat_unit, - feat_type = feat_type, - reduction = reduction, - reduction_method = reduction_method, - name = name, - output = output, - set_defaults = set_defaults) + spat_unit = spat_unit, + feat_type = feat_type, + reduction = reduction, + reduction_method = reduction_method, + name = name, + output = output, + set_defaults = set_defaults) return(dim_red) }, error = function(e) { @@ -428,7 +428,7 @@ giottoToAnnData <- function(gobject = NULL, ## PCA # pca on feats not supported by anndata because of dimensionality agreement reqs - reduction_options = c("cells", "feats") + reduction_options = names(gobject@dimension_reduction) dim_red = NULL for (ro in reduction_options) { @@ -464,8 +464,8 @@ giottoToAnnData <- function(gobject = NULL, feats_used = feats_used) adata_pos = adata_pos + 1 } - adata_pos = 1 } + adata_pos = 1 } @@ -538,6 +538,80 @@ giottoToAnnData <- function(gobject = NULL, # Nearest Neighbor Network + # error hanldling wrapper to get_NearestNetwork + try_get_NN = function(gobject, + spat_unit, + feat_type, + nn_network_to_use, + network_name, + output, + set_defaults) { + tryCatch( + { + nearest_net = get_NearestNetwork(gobject = gobject, + spat_unit = spat_unit, + feat_type = feat_type, + nn_network_to_use = nn_network_to_use, + network_name = network_name, + output = output, + set_defaults = set_defaults) + return(nearest_net) + }, + error = function(e) { + return(NULL) + } + ) + } + + for (su in spat_unit) { + for (ft in names(gobject@expression[[su]])) { + nn_network_to_use = c("sNN","kNN") + for (nn_net_tu in nn_network_to_use) { + network_name = list_nearest_networks_names(gobject = gobject, + spat_unit = su, + feat_type = ft, + nn_type = nn_net_tu) + if (is.null(network_name)) { + next + } + for (n_name in network_name) { + gob_NN = try_get_NN(gobject = gobject, + spat_unit = su, + feat_type = ft, + nn_network_to_use = nn_net_tu, + network_name = n_name, + output = "nnNetObj", + set_defaults = FALSE) + + #weight_mat = igraph::as_data_frame(gob_NN[])$weight + #dist_mat = igraph::as_data_frame(gob_NN[])$distance + pidx = grep("nn_network", names(gobject@parameters)) + for (p in pidx) { + if (gobject@parameters[[p]]["type"] == nn_net_tu) { + kval = gobject@parameters[[p]]["k"] + dim_red_used = gobject@parameters[[p]]["dim_red_to_use"] + } + } + + df_gob_NN = igraph::as_data_frame(gob_NN[]) + + browser() + adata_list[[adata_pos]] = set_adg_nn(adata = adata_list[[adata_pos]], + df_NN = df_gob_NN, + net_name = n_name, + n_neighbors = kval, + dim_red_used = dim_red_used) + + } + + } + adata_pos = adata_pos + 1 + } + } + + browser() + # Reset indexing variable + adata_pos = 1 # Pipe non-expression data into AnnData object diff --git a/inst/python/g2ad.py b/inst/python/g2ad.py index 29ae4fa5f..775238bc2 100644 --- a/inst/python/g2ad.py +++ b/inst/python/g2ad.py @@ -1,6 +1,7 @@ import anndata as ad import pandas as pd import numpy as np +import scipy import os @@ -151,6 +152,47 @@ def set_adg_tsne(adata = None, tsne_data = None): return adata +def set_adg_nn(adata = None, df_NN = None, net_name = None, n_neighbors = None, dim_red_used = None): + ad_guard(adata) + dim12 = len(set(df_NN['from'])) + fill_arr = np.zeros((dim12,dim12)) + w_fill_df = pd.DataFrame(fill_arr, columns = adata.obs_names, index = adata.obs_names) + d_fill_df = pd.DataFrame(fill_arr, columns = adata.obs_names, index = adata.obs_names) + + for i in df_NN.index: + tar_row = df_NN.iloc[i,:] + f_id = tar_row["from"] + t_id = tar_row["to"] + weight = tar_row["weight"] + dist = tar_row["distance"] + w_fill_df.loc[f_id, t_id] = weight + d_fill_df.loc[f_id, t_id] = dist + + weights = scipy.sparse.csr_matrix(w_fill_df) + distances = scipy.sparse.csr_matrix(d_fill_df) + dim_red_used = net_name.split(".")[-1] + + if "kNN" in net_name: + adata.obsp['connectivities'] = weights + adata.obsp['distances'] = distances + adata.uns['neighbors'] = {'connectivities_key': 'connectivities', + 'distances_key': 'distances', + 'params': {'n_neighbors': n_neighbors, + 'method': dim_red_used} + } + else: + cname = net_name + "_connectivities" + dname = net_name + "_distances" + adata.obsp[cname] = weights + adata.obsp[dname] = distances + adata.uns[net_name] = {'connectivities_key': net_name + '_connectivities', + 'distances_key': net_name + '_distances', + 'params': {'n_neighbors': n_neighbors, + 'method': dim_red_used} + } + + return adata + def write_ad_h5ad(adata = None, save_directory = None, spat_unit = None, feat_type = None): ad_guard(adata) if os.path.exists(save_directory): From 5499bd5604698bbc254497ee90e87e2e1edfd4f9 Mon Sep 17 00:00:00 2001 From: jiajic <72078254+jiajic@users.noreply.github.com> Date: Thu, 5 Jan 2023 11:04:41 -0500 Subject: [PATCH 059/129] Parallelize gpoly creation in Vizgen workflow - Update `readPolygonFilesVizgenHDF5()` with parallel `giottoPolygon` creation. - Add nameData class and generics to interact with name slots - Add rbind generic for giottoPolygons - Separate input checking for `createGiottoPolygonsFromDfr()` into a separate internal evaluation function note: `.h5_read_bare()` will need to be removed/changed. C level calls to another package are not allowed by CRAN --- NAMESPACE | 6 + NEWS.md | 2 + R/classes.R | 6 +- R/general_help.R | 131 +++++++++++--- R/generics.R | 70 ++++++++ R/giotto_structures.R | 246 +++++++++++++++++++++----- R/utilities.R | 4 +- man/createGiottoPolygonsFromDfr.Rd | 20 ++- man/dot-h5_read_bare.Rd | 19 ++ man/objName-generic.Rd | 31 ++++ man/rbind-generic.Rd | 27 +++ man/rbind2_giotto_polygon_hetero.Rd | 26 +++ man/rbind2_giotto_polygon_homo.Rd | 18 ++ man/readPolygonFilesVizgen.Rd | 15 ++ man/readPolygonFilesVizgenHDF5.Rd | 26 ++- man/readPolygonFilesVizgenHDF5_old.Rd | 56 ++++++ man/smoothGiottoPolygons.Rd | 1 - 17 files changed, 620 insertions(+), 84 deletions(-) create mode 100644 man/dot-h5_read_bare.Rd create mode 100644 man/objName-generic.Rd create mode 100644 man/rbind-generic.Rd create mode 100644 man/rbind2_giotto_polygon_hetero.Rd create mode 100644 man/rbind2_giotto_polygon_homo.Rd create mode 100644 man/readPolygonFilesVizgenHDF5_old.Rd diff --git a/NAMESPACE b/NAMESPACE index 50b75cd7a..62c20d2f0 100644 --- a/NAMESPACE +++ b/NAMESPACE @@ -209,6 +209,7 @@ export(makeSignMatrixRank) export(mergeClusters) export(normalizeGiotto) export(objHistory) +export(objName) export(overlapImagesToMatrix) export(overlapToMatrix) export(overlapToMatrixMultiPoly) @@ -258,6 +259,7 @@ export(readExprMatrix) export(readGiottoInstructions) export(readPolygonFilesVizgen) export(readPolygonFilesVizgenHDF5) +export(readPolygonFilesVizgenHDF5_old) export(reconnectGiottoImage) export(rectVertices) export(registerGiottoObjectList) @@ -400,6 +402,7 @@ exportMethods("$<-") exportMethods("[") exportMethods("[<-") exportMethods("featType<-") +exportMethods("objName<-") exportMethods("prov<-") exportMethods("spatUnit<-") exportMethods(copy) @@ -407,8 +410,10 @@ exportMethods(dim) exportMethods(featType) exportMethods(ncol) exportMethods(nrow) +exportMethods(objName) exportMethods(plot) exportMethods(prov) +exportMethods(rbind2) exportMethods(spatUnit) import(data.table) import(ggplot2) @@ -417,6 +422,7 @@ import(utils) importFrom(magrittr,"%>%") importFrom(methods,"slot<-") importFrom(methods,new) +importFrom(methods,rbind2) importFrom(methods,show) importFrom(methods,slot) importFrom(methods,validObject) diff --git a/NEWS.md b/NEWS.md index 049991d0e..a2918fa2a 100644 --- a/NEWS.md +++ b/NEWS.md @@ -14,6 +14,8 @@ - New `fread_colmatch()` internal for fread loading a subset of rows based on matches in a specified column - Add `optional` and `custom_msg` params to `package_check()` - Add `order` parameter to `dimFeatPlot2D` and `spatDimFeatPlot2d` to plot and order cells according to the levels of the selected feature ([#477](https://github.com/drieslab/Giotto/issues/477)) +- New `objName()` and `objName` generics for setting the names of relevant S4 subobjects +- New `rbind()` generic to append `giottoPolygon` objects ## Changes - Move giotto object method-specific creation functions from `giotto.R` to `convenience.R` diff --git a/R/classes.R b/R/classes.R index 3b2446c4f..fc6799627 100644 --- a/R/classes.R +++ b/R/classes.R @@ -1307,16 +1307,15 @@ setMethod( #' @export giottoPolygon = setClass( Class = "giottoPolygon", + contains = c('nameData'), slots = c( - name = "ANY", spatVector = "ANY", spatVectorCentroids = "ANY", overlaps = "ANY" ), prototype = list( - name = NULL, spatVector = NULL, spatVectorCentroids = NULL, overlaps = NULL @@ -1376,16 +1375,15 @@ giottoPoints <- setClass( #' @export featureNetwork <- setClass( Class = "featureNetwork", + contains = 'nameData', slots = c( - name = "ANY", network_datatable = "ANY", network_lookup_id = "ANY", full = "ANY" ), prototype = list( - name = NULL, network_datatable = NULL, network_lookup_id = NULL, full = NULL diff --git a/R/general_help.R b/R/general_help.R index 0ec18c6b0..4fee984db 100644 --- a/R/general_help.R +++ b/R/general_help.R @@ -1510,8 +1510,11 @@ readPolygonFilesVizgenHDF5_old = function(boundaries_path, #' @param smooth_polygons smooth polygons (default = TRUE) #' @param smooth_vertices number of vertices for smoothing #' @param set_neg_to_zero set negative values to zero when smoothing +#' @param calc_centroids calculate centroids (default = FALSE) #' @param H5Fopen_flags see \code{\link[rhdf5]{H5Fopen}} for more details #' @param cores cores to use +#' @param create_gpoly_bin (Optional, default is FALSE) Parallelization option. +#' Accepts integer values as an binning size when generating giottoPolygon objects #' @param verbose be verbose #' @seealso \code{\link{smoothGiottoPolygons}} #' @details Set H5Fopen_flags to "H5F_ACC_RDONLY" if you encounter permission issues. @@ -1523,11 +1526,13 @@ readPolygonFilesVizgenHDF5 = function(boundaries_path, custom_polygon_names = NULL, flip_x_axis = FALSE, flip_y_axis = TRUE, + calc_centroids = FALSE, smooth_polygons = TRUE, smooth_vertices = 60L, set_neg_to_zero = FALSE, H5Fopen_flags = "H5F_ACC_RDWR", cores = NA, + create_gpoly_bin = FALSE, verbose = TRUE, polygon_feat_types = NULL) { @@ -1545,7 +1550,7 @@ readPolygonFilesVizgenHDF5 = function(boundaries_path, segm_to_use = paste0('p_', (segm_to_use - 1L)) # data.table vars - x = y = z = cell_id = file_id = my_id = NULL + x = y = z = cell_id = poly_ID = file_id = my_id = NULL # provide your own custom names if(!is.null(custom_polygon_names)) { @@ -1594,10 +1599,7 @@ readPolygonFilesVizgenHDF5 = function(boundaries_path, # update progress print(basename(hdf5_boundary_selected_list[[bound_i]])) if(bound_i %% 5 == 0) { - elapsed = as.numeric(Sys.time() - init) - step_time = elapsed/bound_i/5 - est = (hdf5_list_length/5 * step_time) - elapsed - pb(message = c('// E:', time_format(elapsed), '| R:', time_format(est))) + pb() } return(read_file) @@ -1630,30 +1632,111 @@ readPolygonFilesVizgenHDF5 = function(boundaries_path, # create Giotto polygons and add them to gobject - # not possible to parallelize with external pointers - progressr::with_progress({ - pb = progressr::progressor(along = z_read_DT) - smooth_cell_polygons_list = lapply(seq_along(z_read_DT), function(i) { - dfr_subset = z_read_DT[[i]][,.(x, y, cell_id)] - cell_polygons = createGiottoPolygonsFromDfr(segmdfr = dfr_subset, - name = poly_names[i], - verbose = verbose) - - pb(message = poly_names[i]) + # no binning + if(!is.numeric(create_gpoly_bin)) { + + progressr::with_progress({ + pb = progressr::progressor(along = z_read_DT) + smooth_cell_polygons_list = lapply_flex( + seq_along(z_read_DT), + future.packages = c('terra', 'stats', 'data.table'), + function(i) { + dfr_subset = z_read_DT[[i]][,.(x, y, cell_id)] + data.table::setnames(dfr_subset, old = 'cell_id', new = 'poly_ID') + cell_polygons = gpoly_from_dfr_smoothed_wrapped( + segmdfr = dfr_subset, + name = poly_names[i], + skip_eval_dfr = TRUE, + copy_dt = FALSE, + smooth_polygons = smooth_polygons, + vertices = smooth_vertices, + set_neg_to_zero = set_neg_to_zero, + calc_centroids = calc_centroids, + verbose = verbose + ) + + pb(message = c(poly_names[i]), ' (', i, '/', length(z_read_DT), ')') + return(cell_polygons) + } + ) + }) - if(smooth_polygons == TRUE) { - return(smoothGiottoPolygons(cell_polygons, - vertices = smooth_vertices, - set_neg_to_zero = set_neg_to_zero)) - } else { - return(cell_polygons) + # unwrap results + smooth_cell_polygons_list = lapply(smooth_cell_polygons_list, function(x) { + slot(x, 'spatVector') = terra::unwrap(x, 'spatVector') + if(isTRUE(calc_centroids)) { + slot(x, 'spatVectorCentroids') = terra::unwrap(x, 'spatVectorCentroids') } + return(x) }) - }) + } else { + # with binning + + dfr_subset = lapply(z_read_DT, function(bin, DT) { + + DT = DT[,.(x, y, cell_id)] + data.table::setnames(DT, old = 'cell_id', new = 'poly_ID') + pid = DT[, unique(poly_ID)] + + bin_pid = data.table::data.table( + 'poly_ID' = pid, + 'bin_ID' = as.numeric( + cut(x = seq_along(pid), + breaks = ceiling(length(pid)/bin)) + ) + ) + DT = data.table::merge.data.table(DT, bin_pid, by = 'poly_ID', all.x = TRUE) + DT = split(DT, DT$bin_ID) + + }, bin = create_gpoly_bin) + + bin_steps = sum(unlist(lapply(dfr_subset, length))) + + progressr::with_progress({ + pb = progressr::progressor(steps = bin_steps) + smooth_cell_polygons_list = lapply( # sequential across z index + seq_along(dfr_subset), + function(i) { + lapply_flex( # parallelize across bins + dfr_subset[[i]], + future.packages = c('terra', 'stats', 'data.table'), + function(bin_DT) { + cell_polygons = gpoly_from_dfr_smoothed_wrapped( + segmdfr = bin_DT, + name = poly_names[i], + skip_eval_dfr = TRUE, + copy_dt = FALSE, + smooth_polygons = smooth_polygons, + vertices = smooth_vertices, + set_neg_to_zero = set_neg_to_zero, + calc_centroids = calc_centroids, + verbose = verbose + ) + + pb(message = c(poly_names[i]), ' (', i, '/', length(dfr_subset), ')') + return(cell_polygons) + } + ) + } + ) + }) + + # unwrap results + smooth_cell_polygons_list = lapply(smooth_cell_polygons_list, function(i) { + p_list = lapply(smooth_cell_polygons_list[[i]], function(x) { + slot(x, 'spatVector') = terra::unwrap(x, 'spatVector') + if(isTRUE(calc_centroids)) { + slot(x, 'spatVectorCentroids') = terra::unwrap(x, 'spatVectorCentroids') + } + return(x) + }) + # rbind results + return(do.call('rbind', p_list)) + }) + + } - # TODO: add spatial centroids - # needs to happen after smoothing to be correct return(smooth_cell_polygons_list) diff --git a/R/generics.R b/R/generics.R index 17dfa8eb4..1e74b553f 100644 --- a/R/generics.R +++ b/R/generics.R @@ -69,6 +69,52 @@ setMethod('dim', signature('metaData'), function(x) dim(x@metaDT)) +# rbind() generic #### + +#' @title Combine objects by rows (Giotto-related) +#' @name rbind-generic +#' @description row bind two objects +#' @include classes.R +#' @param x item 1 to rbind +#' @param y item 2 to rbind +#' @param add_list_ID whether to generate a list_ID column when giottoPolygons +#' to append have different names +#' @param \dots additional params to pass to methods +NULL + + +#' @describeIn rbind-generic Append giottoPolygon objects +#' @importFrom methods rbind2 +#' @export +setMethod('rbind2', signature(x = 'giottoPolygon', y = 'giottoPolygon'), + function(x, y, add_list_ID = TRUE, ...) { + + # determine homo or hetero + poly_names = c(slot(x, 'name'), slot(y, 'name')) + homo = identical(poly_names[[1L]], poly_names[[2L]]) + if(!isTRUE(homo)) { + new_name = paste0(sort(poly_names), collapse = '-') + return(rbind2_giotto_polygon_hetero(x = x, y = y, new_name = new_name, add_list_ID = add_list_ID)) + } else { + return(rbind2_giotto_polygon_homo(x = x, y = y)) + } +}) + + +setGeneric('rbind', signature = '...') + +setMethod("rbind", "giottoPolygon", function(..., deparse.level = 1) { + if(nargs() <= 2L) { + rbind2(...) + } else { + xs = list(...) + rbind2(xs[[1L]], do.call(Recall, xs[-1L])) + } +}) + + + + # plot() S4 Generic #### #' @title Preview a Giotto spatial object @@ -250,6 +296,30 @@ setMethod('featType<-', signature = 'featData', function(x, value) { +# objName() generic #### +#' @title Giotto object name information +#' @name objName-generic +#' @description access and set name slot fo S4 subobject +#' @param x a Giotto S4 class subobject with name data +#' @param value value to set as object name +#' @aliases objName objName<- +#' @include classes.R +#' @export +setGeneric('objName', function(x) standardGeneric('objName')) +setGeneric('objName<-', function(x, value) standardGeneric('objName<-')) + +#' @describeIn objName-generic Get name information +#' @export +setMethod('objName', signature = 'nameData', function(x) x@name) + +#' @describeIn objName-generic Set name information +#' @export +setMethod('objName<-', signature = 'nameData', function(x, value) { + x@name = value + x +}) + + #' @title Extract or replace parts of an object diff --git a/R/giotto_structures.R b/R/giotto_structures.R index 397d675e5..e519cd2b4 100644 --- a/R/giotto_structures.R +++ b/R/giotto_structures.R @@ -468,6 +468,7 @@ createGiottoPolygonsFromMask = function(maskfile, ## segmDfrToPolygon + #' @title Create giotto polygons from dataframe #' @name createGiottoPolygonsFromDfr #' @description Creates Giotto polygon object from a structured dataframe-like object. @@ -478,6 +479,9 @@ createGiottoPolygonsFromMask = function(maskfile, #' for how columns are selected for coordinate and ID information. #' @param name name for the \code{giottoPolygon} object #' @param calc_centroids (default FALSE) calculate centroids for polygons +#' @param skip_eval_dfr (default FALSE) skip evaluation of provided dataframe +#' @param copy_dt (default TRUE) if segmdfr is provided as dt, this determines +#' whether a copy is made #' @param verbose be verbose #' @return giotto polygon object #' @details When determining which column within the tabular data is intended to @@ -492,55 +496,25 @@ createGiottoPolygonsFromMask = function(maskfile, createGiottoPolygonsFromDfr = function(segmdfr, name = 'cell', calc_centroids = FALSE, - verbose = TRUE) { + verbose = TRUE, + skip_eval_dfr = FALSE, + copy_dt = TRUE) { # define for data.table geom = NULL - input_dt = data.table::as.data.table(segmdfr) - - # data.frame like object needs to have 2 coordinate columns and - # at least one other column as the feat_ID - if(ncol(input_dt) < 3) stop('At minimum, columns for xy coordinates and poly ID are needed.\n') - col_classes = sapply(input_dt, class) - ## find poly_ID as either first character col or named column - ## if neither exist, pick the 3rd column - if('poly_ID' %in% colnames(input_dt)) { - poly_ID_col = which(colnames(input_dt) == 'poly_ID') + if(!inherits(segmdfr, 'data.table')) { + if(inherits(segmdfr, 'data.frame')) input_dt = data.table::setDT(segmdfr) + else input_dt = data.table::as.data.table(segmdfr) } else { - poly_ID_col = which(col_classes == 'character') - if(length(poly_ID_col) < 1) poly_ID_col = 3 # case if no char found: default to 3rd - else poly_ID_col = poly_ID_col[[1]] # case if char is found + if(isTRUE(copy_dt)) input_dt = data.table::copy(segmdfr) + else input_dt = segmdfr } - if(isTRUE(verbose)) message(paste0(' Selecting col "',colnames(input_dt[, poly_ID_col, with = FALSE]),'" as poly_ID column')) - colnames(input_dt)[poly_ID_col] = 'poly_ID' - if(!inherits(input_dt$poly_ID, 'character')) { - input_dt$poly_ID = as.character(input_dt$poly_ID) # ensure char - } - ## find first two numeric cols as x and y respectively or named column - ## if neither exist, pick the 1st and 2nd cols respectively for x and y - if(all(c('x','y') %in% colnames(input_dt))) { - x_col = which(colnames(input_dt) == 'x') - y_col = which(colnames(input_dt) == 'y') - } else { - x_col = which(col_classes == 'numeric') - if(length(x_col) < 2) x_col = 1 # case if no/too few num found: default to 1st - else x_col = x_col[[1]] # case if num found - y_col = which(col_classes == 'numeric') - if(length(y_col) < 2) y_col = 2 # case if no/too few num found: default to 2nd - else y_col = y_col[[2]] # case if num found - } - - if(isTRUE(verbose)) message(paste0(' Selecting cols "',colnames(input_dt[, x_col, with = FALSE]),'" and "', colnames(input_dt[, y_col, with = FALSE]),'" as x and y respectively')) - colnames(input_dt)[x_col] = 'x' - colnames(input_dt)[y_col] = 'y' - if(!inherits(input_dt$x, 'numeric')) { - input_dt$x = as.numeric(input_dt$x) # ensure numeric - } - if(!inherits(input_dt$y, 'numeric')) { - input_dt$y = as.numeric(input_dt$y) # ensure numeric + if(!isTRUE(skip_eval_dfr)) { + input_dt = evaluate_gpoly_dfr(input_dt = input_dt, + verbose = verbose) } #pl = ggplot() @@ -554,7 +528,7 @@ createGiottoPolygonsFromDfr = function(segmdfr, input_dt[, geom := new_vec] input_dt[, c('part', 'hole') := list(1, 0)] - input_dt = input_dt[, c('geom', 'part', 'x', 'y', 'hole', 'poly_ID'), with =F] + input_dt = input_dt[, c('geom', 'part', 'x', 'y', 'hole', 'poly_ID'), with = FALSE] #pl = ggplot() @@ -592,9 +566,106 @@ createGiottoPolygonsFromDfr = function(segmdfr, + + +# Parallelized giottoPolygon creation workflows # + +# Internal function to create a giottoPolygon object, smooth it, then wrap it so +# that results are portable/possible to use with parallelization. +# dotparams are passed to smoothGiottoPolygons +gpoly_from_dfr_smoothed_wrapped = function(segmdfr, + name = 'cell', + calc_centroids = FALSE, + smooth_polygons = FALSE, + skip_eval_dfr = FALSE, + copy_dt = TRUE, + verbose = TRUE, + ...) { + + gpoly = createGiottoPolygonsFromDfr(segmdfr = segmdfr, + name = name, + calc_centroids = FALSE, + skip_eval_dfr = skip_eval_dfr, + copy_dt = copy_dt, + verbose = verbose) + if(isTRUE(smooth_polygons)) gpoly = smoothGiottoPolygons(gpolygon = gpoly, ...) + if(isTRUE(calc_centroids)) gpoly = calculate_centroids_polygons(gpolygon = gpoly, append_gpolygon = TRUE) + + slot(gpoly, 'spatVector') = terra::wrap(slot(gpoly, 'spatVector')) + if(isTRUE(calc_centroids)) { + slot(gpoly, 'spatVectorCentroids') = terra::wrap(slot(gpoly, 'spatVectorCentroids')) + } + return(gpoly) +} + + + + + +#' @describeIn createGiottoPolygonsFromDfr Examines provided data.frame type object +#' for columns that should correspond to x/y vertices and the polygon ID. Returns +#' a data.table with those key columns renamed to 'x', 'y', and 'poly_ID' if necessary. +#' @keywords internal +evaluate_gpoly_dfr = function(input_dt, + verbose = TRUE) { + + x = y = poly_ID = NULL + + # data.frame like object needs to have 2 coordinate columns and + # at least one other column as the feat_ID + if(ncol(input_dt) < 3) stop('At minimum, columns for xy coordinates and poly ID are needed.\n') + + col_classes = sapply(input_dt, class) + + + # 1. detect poly_ID + ## find poly_ID as either first character col or named column + ## if neither exist, pick the 3rd column + if('poly_ID' %in% colnames(input_dt)) { + poly_ID_col = which(colnames(input_dt) == 'poly_ID') + } else { + poly_ID_col = which(col_classes == 'character') + if(length(poly_ID_col) < 1) poly_ID_col = 3 # case if no char found: default to 3rd + else poly_ID_col = poly_ID_col[[1]] # case if char is found + } + + + # 2. detect x and y + ## find first two numeric cols as x and y respectively or named column + ## if neither exist, pick the 1st and 2nd cols respectively for x and y + if(all(c('x','y') %in% colnames(input_dt))) { + x_col = which(colnames(input_dt) == 'x') + y_col = which(colnames(input_dt) == 'y') + } else { + x_col = which(col_classes == 'numeric') + if(length(x_col) < 2) x_col = 1 # case if no/too few num found: default to 1st + else x_col = x_col[[1]] # case if num found + y_col = which(col_classes == 'numeric') + if(length(y_col) < 2) y_col = 2 # case if no/too few num found: default to 2nd + else y_col = y_col[[2]] # case if num found + } + + + # 3. print selections and ensure correct data type + if(isTRUE(verbose)) message(paste0(' Selecting col "',colnames(input_dt[, poly_ID_col, with = FALSE]),'" as poly_ID column')) + colnames(input_dt)[poly_ID_col] = 'poly_ID' + if(!input_dt[, inherits(poly_ID, 'character')]) input_dt[, poly_ID := as.character(poly_ID)] + + if(isTRUE(verbose)) message(paste0(' Selecting cols "',colnames(input_dt[, x_col, with = FALSE]),'" and "', colnames(input_dt[, y_col, with = FALSE]),'" as x and y respectively')) + colnames(input_dt)[x_col] = 'x' + colnames(input_dt)[y_col] = 'y' + if(!input_dt[, inherits(x, 'numeric')]) input_dt[, x := as.numeric(x)] + if(!input_dt[, inherits(y, 'numeric')]) input_dt[, y := as.numeric(y)] + + input_dt +} + + + + #' @title Extract list of polygons #' @name extract_polygon_list -#' @description to extract list of polygons +#' @description to extract list of polygons #' @keywords internal extract_polygon_list = function(polygonlist, polygon_mask_list_params, @@ -787,7 +858,6 @@ dt_to_spatVector_polygon = function(dt, other_values = other_values[other_values %in% specific_values] } - spatVec = terra::vect(x = as.matrix(dt[,geom_values, with = FALSE]), type = 'polygons', atts = unique(dt[,other_values, with = FALSE])) @@ -851,7 +921,6 @@ smoothGiottoPolygons = function(gpolygon, vertices = 20, k = 3, set_neg_to_zero = TRUE, - verbose = TRUE, ...) { # define for .() @@ -920,6 +989,91 @@ smoothGiottoPolygons = function(gpolygon, +#' @title Append giotto polygons of the same name +#' @name rbind2_giotto_polygon_homo +#' @description Append two giotto polygons together of the same name. +#' Performed recursively through \code{rbind2} and \code{rbind} +#' @param x \code{giottoPolygon} 1 +#' @param y \code{giottoPolygon} 2 +#' @keywords internal +rbind2_giotto_polygon_homo = function(x, y) { + + if(is.null(slot(x, 'spatVector'))) slot(x, 'spatVector') = slot(y, 'spatVector') + else slot(x, 'spatVector') = rbind(slot(x,'spatVector'), slot(y, 'spatVector')) + + if(is.null(slot(x, 'spatVectorCentroids'))) slot(x, 'spatVectorCentroids') = slot(y, 'spatVectorCentroids') + else slot(x, 'spatVectorCentroids') = rbind(slot(x, 'spatVectorCentroids'), slot(y, 'spatVectorCentroids')) + + if(is.null(slot(x, 'overlaps'))) slot(x, 'overlaps') = slot(y, 'overlaps') + else slot(x, 'overlaps') = rbind(slot(x, 'overlaps'), slot(y, 'overlaps')) + x +} + + +#' @title Append giotto polygons of different names +#' @name rbind2_giotto_polygon_hetero +#' @description Append two giotto polygons together of different names +#' Performed recursively through \code{rbind2} and \code{rbind}. Generates an +#' additional list_ID attribute based on the original names. The object name +#' also becomes a combination of both previous names +#' @param x \code{giottoPolygon} 1 +#' @param y \code{giottoPolygon} 2 +#' @param poly_names sorted polygon names to be used in the combined \code{giottoPolygon} +#' object +#' @param add_list_ID whether to include the name of the origin \code{giottoPolygons} +#' as a new 'list_ID' attribute +#' @keywords internal +rbind2_giotto_polygon_hetero = function(x, y, new_name, add_list_ID = TRUE) { + + # handle as homo but different name if add_list_ID = FALSE + if(!isTRUE(add_list_ID)) { + gpoly = rbind2_giotto_polygon_homo(x, y) + slot(gpoly, 'name') = new_name + return(gpoly) + } + + null_xsv = null_xsvc = null_xovlp = FALSE + + # Add list_ID + if(!is.null(slot(x, 'spatVector'))) { + if(!'list_ID' %in% names(slot(x, 'spatVector'))) slot(x, 'spatVector')$list_ID = slot(x, 'name') + } else null_xsv = TRUE + if(!is.null(y@spatVector)) { + if(!'list_ID' %in% names(slot(y, 'spatVector'))) slot(y, 'spatVector')$list_ID = slot(y, 'name') + } + + if(!is.null(slot(x, 'spatVectorCentroids'))) { + if(!'list_ID' %in% names(slot(x, 'spatVectorCentroids'))) slot(x, 'spatVectorCentroids')$list_ID = slot(x, 'name') + } else null_xsvc = TRUE + if(!is.null(y@spatVectorCentroids)) { + if(!'list_ID' %in% names(slot(y, 'spatVectorCentroids'))) slot(y, 'spatVectorCentroids')$list_ID = slot(y, 'name') + } + + if(!is.null(slot(x, 'overlaps'))) { + if(!'list_ID' %in% names(slot(x, 'overlaps'))) slot(x, 'overlaps')$list_ID = slot(x, 'name') + } else null_xovlp = TRUE + if(!is.null(y@overlaps)) { + if(!'list_ID' %in% names(slot(y, 'overlaps'))) slot(y, 'overlaps')$list_ID = slot(y, 'name') + } + + # Perform rbinds + if(isTRUE(null_xsv)) new_sv = slot(y, 'spatVector') + else new_sv = rbind(slot(x,'spatVector'), slot(y, 'spatVector')) + + if(isTRUE(null_xsvc)) new_svc = slot(y, 'spatVectorCentroids') + else new_svc = rbind(slot(x, 'spatVectorCentroids'), slot(y, 'spatVectorCentroids')) + + if(isTRUE(null_xovlp)) new_ovlp = slot(y, 'overlaps') + else new_ovlp = rbind(slot(x, 'overlaps'), slot(y, 'overlaps')) + + new_poly = create_giotto_polygon_object(name = new_name, + spatVector = new_sv, + spatVectorCentroids = new_svc, + overlaps = new_ovlp) + new_poly + +} + ### * simple polygon generation #### @@ -2978,7 +3132,7 @@ combineFeatureOverlapData = function(gobject, sel_feats = NULL, poly_info = c('cell')) { - # define for data.table [] subsetting + # data.table vars feat_ID = NULL poly_info = set_default_spat_unit(gobject = gobject, diff --git a/R/utilities.R b/R/utilities.R index 3b50c945e..db02cf5ff 100644 --- a/R/utilities.R +++ b/R/utilities.R @@ -657,13 +657,13 @@ emacs_version = function() { #' @keywords internal #' @details Code from \code{\link[data.table]{timetaken}} time_format = function(secs) { - if (secs > 60) { + if(secs > 60) { secs = as.integer(secs) sprintf("%02d:%02d:%02d", secs%/%3600L, (secs%/%60L)%%60L, secs%%60L) } else { - sprintf(if (secs >= 10) + sprintf(if(secs >= 10) "%.1fs" else "%.3fs", secs) } diff --git a/man/createGiottoPolygonsFromDfr.Rd b/man/createGiottoPolygonsFromDfr.Rd index 7b4942884..cc57377af 100644 --- a/man/createGiottoPolygonsFromDfr.Rd +++ b/man/createGiottoPolygonsFromDfr.Rd @@ -2,14 +2,19 @@ % Please edit documentation in R/giotto_structures.R \name{createGiottoPolygonsFromDfr} \alias{createGiottoPolygonsFromDfr} +\alias{evaluate_gpoly_dfr} \title{Create giotto polygons from dataframe} \usage{ createGiottoPolygonsFromDfr( segmdfr, name = "cell", calc_centroids = FALSE, - verbose = TRUE + verbose = TRUE, + skip_eval_dfr = FALSE, + copy_dt = TRUE ) + +evaluate_gpoly_dfr(input_dt, verbose = TRUE) } \arguments{ \item{segmdfr}{data.frame-like object with polygon coordinate information (x, y, poly_ID) @@ -21,6 +26,11 @@ for how columns are selected for coordinate and ID information.} \item{calc_centroids}{(default FALSE) calculate centroids for polygons} \item{verbose}{be verbose} + +\item{skip_eval_dfr}{(default FALSE) skip evaluation of provided dataframe} + +\item{copy_dt}{(default TRUE) if segmdfr is provided as dt, this determines +whether a copy is made} } \value{ giotto polygon object @@ -39,4 +49,12 @@ the first `'character'` type column to be 'poly_ID' and the first two `'numeric' columns as 'x' and 'y' respectively. If this is also unsuccessful then poly_ID defaults to the 3rd column. 'x' and 'y' then default to the 1st and 2nd columns. } +\section{Functions}{ +\itemize{ +\item \code{evaluate_gpoly_dfr()}: Examines provided data.frame type object +for columns that should correspond to x/y vertices and the polygon ID. Returns +a data.table with those key columns renamed to 'x', 'y', and 'poly_ID' if necessary. + +}} \concept{polygon} +\keyword{internal} diff --git a/man/dot-h5_read_bare.Rd b/man/dot-h5_read_bare.Rd new file mode 100644 index 000000000..a01223cf3 --- /dev/null +++ b/man/dot-h5_read_bare.Rd @@ -0,0 +1,19 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/general_help.R +\name{.h5_read_bare} +\alias{.h5_read_bare} +\title{Read dataset from opened HDF5 with C functions} +\usage{ +.h5_read_bare(file, name = "", dapl) +} +\arguments{ +\item{file}{opened HDF5 file} + +\item{name}{dataset name within} + +\item{dapl}{HDF5 property list (H5Pcreate('H5P_DATASET_ACCESS'))} +} +\description{ +Read dataset from opened HDF5 with C functions +} +\keyword{internal} diff --git a/man/objName-generic.Rd b/man/objName-generic.Rd new file mode 100644 index 000000000..44f6b31d2 --- /dev/null +++ b/man/objName-generic.Rd @@ -0,0 +1,31 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/generics.R +\name{objName-generic} +\alias{objName-generic} +\alias{objName} +\alias{objName<-} +\alias{objName,nameData-method} +\alias{objName<-,nameData-method} +\title{Giotto object name information} +\usage{ +objName(x) + +\S4method{objName}{nameData}(x) + +\S4method{objName}{nameData}(x) <- value +} +\arguments{ +\item{x}{a Giotto S4 class subobject with name data} + +\item{value}{value to set as object name} +} +\description{ +access and set name slot fo S4 subobject +} +\section{Functions}{ +\itemize{ +\item \code{objName(nameData)}: Get name information + +\item \code{objName(nameData) <- value}: Set name information + +}} diff --git a/man/rbind-generic.Rd b/man/rbind-generic.Rd new file mode 100644 index 000000000..cc59f66c9 --- /dev/null +++ b/man/rbind-generic.Rd @@ -0,0 +1,27 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/generics.R +\name{rbind-generic} +\alias{rbind-generic} +\alias{rbind2,giottoPolygon,giottoPolygon-method} +\title{Combine objects by rows (Giotto-related)} +\usage{ +\S4method{rbind2}{giottoPolygon,giottoPolygon}(x, y, add_list_ID = TRUE, ...) +} +\arguments{ +\item{x}{item 1 to rbind} + +\item{y}{item 2 to rbind} + +\item{add_list_ID}{whether to generate a list_ID column when giottoPolygons +to append have different names} + +\item{\dots}{additional params to pass to methods} +} +\description{ +row bind two objects +} +\section{Functions}{ +\itemize{ +\item \code{rbind2(x = giottoPolygon, y = giottoPolygon)}: Append giottoPolygon objects + +}} diff --git a/man/rbind2_giotto_polygon_hetero.Rd b/man/rbind2_giotto_polygon_hetero.Rd new file mode 100644 index 000000000..e5e8685b5 --- /dev/null +++ b/man/rbind2_giotto_polygon_hetero.Rd @@ -0,0 +1,26 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/giotto_structures.R +\name{rbind2_giotto_polygon_hetero} +\alias{rbind2_giotto_polygon_hetero} +\title{Append giotto polygons of different names} +\usage{ +rbind2_giotto_polygon_hetero(x, y, new_name, add_list_ID = TRUE) +} +\arguments{ +\item{x}{\code{giottoPolygon} 1} + +\item{y}{\code{giottoPolygon} 2} + +\item{add_list_ID}{whether to include the name of the origin \code{giottoPolygons} +as a new 'list_ID' attribute} + +\item{poly_names}{sorted polygon names to be used in the combined \code{giottoPolygon} +object} +} +\description{ +Append two giotto polygons together of different names +Performed recursively through \code{rbind2} and \code{rbind}. Generates an +additional list_ID attribute based on the original names. The object name +also becomes a combination of both previous names +} +\keyword{internal} diff --git a/man/rbind2_giotto_polygon_homo.Rd b/man/rbind2_giotto_polygon_homo.Rd new file mode 100644 index 000000000..efedcef86 --- /dev/null +++ b/man/rbind2_giotto_polygon_homo.Rd @@ -0,0 +1,18 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/giotto_structures.R +\name{rbind2_giotto_polygon_homo} +\alias{rbind2_giotto_polygon_homo} +\title{Append giotto polygons of the same name} +\usage{ +rbind2_giotto_polygon_homo(x, y) +} +\arguments{ +\item{x}{\code{giottoPolygon} 1} + +\item{y}{\code{giottoPolygon} 2} +} +\description{ +Append two giotto polygons together of the same name. +Performed recursively through \code{rbind2} and \code{rbind} +} +\keyword{internal} diff --git a/man/readPolygonFilesVizgen.Rd b/man/readPolygonFilesVizgen.Rd index 52d41db49..040848b03 100644 --- a/man/readPolygonFilesVizgen.Rd +++ b/man/readPolygonFilesVizgen.Rd @@ -2,6 +2,7 @@ % Please edit documentation in R/general_help.R \name{readPolygonFilesVizgen} \alias{readPolygonFilesVizgen} +\alias{h5read_vizgen} \title{readPolygonFilesVizgen} \usage{ readPolygonFilesVizgen( @@ -17,6 +18,13 @@ readPolygonFilesVizgen( return_gobject = TRUE, verbose = TRUE ) + +h5read_vizgen( + h5File, + z_indices = 1L:7L, + segm_to_use = "p_0", + H5Fopen_flags = "H5F_ACC_RDWR" +) } \arguments{ \item{gobject}{giotto object} @@ -45,6 +53,13 @@ readPolygonFilesVizgen( Read selected polygon files for the FOVs present in the Giotto object and add the smoothed polygons to the object } +\section{Functions}{ +\itemize{ +\item \code{h5read_vizgen()}: (internal) Optimized .hdf5 reading for vizgen +merscope output. Returns a data.table of xyz coords and cell_id + +}} \seealso{ \code{\link{smoothGiottoPolygons}} } +\keyword{internal} diff --git a/man/readPolygonFilesVizgenHDF5.Rd b/man/readPolygonFilesVizgenHDF5.Rd index 4573162d3..1bfcb804e 100644 --- a/man/readPolygonFilesVizgenHDF5.Rd +++ b/man/readPolygonFilesVizgenHDF5.Rd @@ -7,16 +7,20 @@ readPolygonFilesVizgenHDF5( boundaries_path, fovs = NULL, - polygon_feat_types = 0:6, + z_indices = 1L:7L, + segm_to_use = 1L, custom_polygon_names = NULL, - flip_x_axis = F, - flip_y_axis = F, + flip_x_axis = FALSE, + flip_y_axis = TRUE, + calc_centroids = FALSE, smooth_polygons = TRUE, - smooth_vertices = 60, + smooth_vertices = 60L, set_neg_to_zero = FALSE, H5Fopen_flags = "H5F_ACC_RDWR", cores = NA, - verbose = TRUE + create_gpoly_bin = FALSE, + verbose = TRUE, + polygon_feat_types = NULL ) } \arguments{ @@ -24,7 +28,10 @@ readPolygonFilesVizgenHDF5( \item{fovs}{subset of fovs to use} -\item{polygon_feat_types}{a vector containing the polygon feature types} +\item{z_indices}{z indices of polygons to use} + +\item{segm_to_use}{segmentation results to use (usually = 1. Depends on if +alternative segmentations were generated)} \item{custom_polygon_names}{a character vector to provide custom polygon names (optional)} @@ -33,6 +40,8 @@ readPolygonFilesVizgenHDF5( \item{flip_y_axis}{flip y axis of polygon coordinates (multiply by -1)} +\item{calc_centroids}{calculate centroids (default = FALSE)} + \item{smooth_polygons}{smooth polygons (default = TRUE)} \item{smooth_vertices}{number of vertices for smoothing} @@ -43,7 +52,12 @@ readPolygonFilesVizgenHDF5( \item{cores}{cores to use} +\item{create_gpoly_bin}{(Optional, default is FALSE) Parallelization option. +Accepts integer values as an binning size when generating giottoPolygon objects} + \item{verbose}{be verbose} + +\item{polygon_feat_types}{deprecated. Use \code{z_indices}} } \description{ Read and create polygons for all cells, or for only selected FOVs. diff --git a/man/readPolygonFilesVizgenHDF5_old.Rd b/man/readPolygonFilesVizgenHDF5_old.Rd new file mode 100644 index 000000000..15f1fb647 --- /dev/null +++ b/man/readPolygonFilesVizgenHDF5_old.Rd @@ -0,0 +1,56 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/general_help.R +\name{readPolygonFilesVizgenHDF5_old} +\alias{readPolygonFilesVizgenHDF5_old} +\title{readPolygonFilesVizgenHDF5} +\usage{ +readPolygonFilesVizgenHDF5_old( + boundaries_path, + fovs = NULL, + polygon_feat_types = 0:6, + custom_polygon_names = NULL, + flip_x_axis = F, + flip_y_axis = F, + smooth_polygons = TRUE, + smooth_vertices = 60, + set_neg_to_zero = FALSE, + H5Fopen_flags = "H5F_ACC_RDWR", + cores = NA, + verbose = TRUE +) +} +\arguments{ +\item{boundaries_path}{path to the cell_boundaries folder} + +\item{fovs}{subset of fovs to use} + +\item{polygon_feat_types}{a vector containing the polygon feature types} + +\item{custom_polygon_names}{a character vector to provide custom polygon names +(optional)} + +\item{flip_x_axis}{flip x axis of polygon coordinates (multiply by -1)} + +\item{flip_y_axis}{flip y axis of polygon coordinates (multiply by -1)} + +\item{smooth_polygons}{smooth polygons (default = TRUE)} + +\item{smooth_vertices}{number of vertices for smoothing} + +\item{set_neg_to_zero}{set negative values to zero when smoothing} + +\item{H5Fopen_flags}{see \code{\link[rhdf5]{H5Fopen}} for more details} + +\item{cores}{cores to use} + +\item{verbose}{be verbose} +} +\description{ +Read and create polygons for all cells, or for only selected FOVs. +} +\details{ +Set H5Fopen_flags to "H5F_ACC_RDONLY" if you encounter permission issues. +} +\seealso{ +\code{\link{smoothGiottoPolygons}} +} diff --git a/man/smoothGiottoPolygons.Rd b/man/smoothGiottoPolygons.Rd index afa361016..10e8541c8 100644 --- a/man/smoothGiottoPolygons.Rd +++ b/man/smoothGiottoPolygons.Rd @@ -9,7 +9,6 @@ smoothGiottoPolygons( vertices = 20, k = 3, set_neg_to_zero = TRUE, - verbose = TRUE, ... ) } From ebf28cda9e55d0109009934a5dcb11541fa857bb Mon Sep 17 00:00:00 2001 From: jiajic <72078254+jiajic@users.noreply.github.com> Date: Thu, 5 Jan 2023 11:38:49 -0500 Subject: [PATCH 060/129] Update giotto_structures.R --- R/giotto_structures.R | 3 +++ 1 file changed, 3 insertions(+) diff --git a/R/giotto_structures.R b/R/giotto_structures.R index e519cd2b4..44d17adb6 100644 --- a/R/giotto_structures.R +++ b/R/giotto_structures.R @@ -573,6 +573,9 @@ createGiottoPolygonsFromDfr = function(segmdfr, # Internal function to create a giottoPolygon object, smooth it, then wrap it so # that results are portable/possible to use with parallelization. # dotparams are passed to smoothGiottoPolygons +#' @title Polygon creation and smoothing for parallel +#' @name gpoly_from_dfr_smoothed_wrapped +#' @keywords internal gpoly_from_dfr_smoothed_wrapped = function(segmdfr, name = 'cell', calc_centroids = FALSE, From 4703d9d6ab9ac55458022deb44685d3b0b1e93b0 Mon Sep 17 00:00:00 2001 From: jiajic <72078254+jiajic@users.noreply.github.com> Date: Thu, 5 Jan 2023 12:02:53 -0500 Subject: [PATCH 061/129] Update giotto_structures.R fix typos Update giotto_structures.R Update general_help.R Update general_help.R Update general_help.R Update general_help.R --- R/general_help.R | 15 ++++++++------- R/giotto_structures.R | 13 +++++++++---- man/gpoly_from_dfr_smoothed_wrapped.Rd | 21 +++++++++++++++++++++ 3 files changed, 38 insertions(+), 11 deletions(-) create mode 100644 man/gpoly_from_dfr_smoothed_wrapped.Rd diff --git a/R/general_help.R b/R/general_help.R index 4fee984db..4af99153c 100644 --- a/R/general_help.R +++ b/R/general_help.R @@ -1655,7 +1655,7 @@ readPolygonFilesVizgenHDF5 = function(boundaries_path, verbose = verbose ) - pb(message = c(poly_names[i]), ' (', i, '/', length(z_read_DT), ')') + pb(message = c(poly_names[i], ' (', i, '/', length(z_read_DT), ')')) return(cell_polygons) } ) @@ -1663,9 +1663,9 @@ readPolygonFilesVizgenHDF5 = function(boundaries_path, # unwrap results smooth_cell_polygons_list = lapply(smooth_cell_polygons_list, function(x) { - slot(x, 'spatVector') = terra::unwrap(x, 'spatVector') + slot(x, 'spatVector') = terra::unwrap(slot(x, 'spatVector')) if(isTRUE(calc_centroids)) { - slot(x, 'spatVectorCentroids') = terra::unwrap(x, 'spatVectorCentroids') + slot(x, 'spatVectorCentroids') = terra::unwrap(slot(x, 'spatVectorCentroids')) } return(x) }) @@ -1714,7 +1714,7 @@ readPolygonFilesVizgenHDF5 = function(boundaries_path, verbose = verbose ) - pb(message = c(poly_names[i]), ' (', i, '/', length(dfr_subset), ')') + pb(message = c(poly_names[i], ' (', i, '/', length(dfr_subset), ')')) return(cell_polygons) } ) @@ -1723,15 +1723,16 @@ readPolygonFilesVizgenHDF5 = function(boundaries_path, }) # unwrap results - smooth_cell_polygons_list = lapply(smooth_cell_polygons_list, function(i) { + smooth_cell_polygons_list = lapply(seq_along(smooth_cell_polygons_list), function(i) { p_list = lapply(smooth_cell_polygons_list[[i]], function(x) { - slot(x, 'spatVector') = terra::unwrap(x, 'spatVector') + slot(x, 'spatVector') = terra::unwrap(slot(x, 'spatVector')) if(isTRUE(calc_centroids)) { - slot(x, 'spatVectorCentroids') = terra::unwrap(x, 'spatVectorCentroids') + slot(x, 'spatVectorCentroids') = terra::unwrap(slot(x, 'spatVectorCentroids')) } return(x) }) # rbind results + names(p_list) = NULL return(do.call('rbind', p_list)) }) diff --git a/R/giotto_structures.R b/R/giotto_structures.R index 44d17adb6..fa8e10cdf 100644 --- a/R/giotto_structures.R +++ b/R/giotto_structures.R @@ -541,7 +541,7 @@ createGiottoPolygonsFromDfr = function(segmdfr, spatvector = dt_to_spatVector_polygon(input_dt, include_values = TRUE) - hopla = spatVector_to_dt(spatvector) + # hopla = spatVector_to_dt(spatvector) #pl = ggplot() #pl = pl + geom_polygon(data = hopla[100000:200000], aes(x = x, y = y, group = geom)) @@ -580,10 +580,12 @@ gpoly_from_dfr_smoothed_wrapped = function(segmdfr, name = 'cell', calc_centroids = FALSE, smooth_polygons = FALSE, + vertices = 20L, + k = 3L, + set_neg_to_zero = TRUE, skip_eval_dfr = FALSE, copy_dt = TRUE, - verbose = TRUE, - ...) { + verbose = TRUE) { gpoly = createGiottoPolygonsFromDfr(segmdfr = segmdfr, name = name, @@ -591,7 +593,10 @@ gpoly_from_dfr_smoothed_wrapped = function(segmdfr, skip_eval_dfr = skip_eval_dfr, copy_dt = copy_dt, verbose = verbose) - if(isTRUE(smooth_polygons)) gpoly = smoothGiottoPolygons(gpolygon = gpoly, ...) + if(isTRUE(smooth_polygons)) gpoly = smoothGiottoPolygons(gpolygon = gpoly, + vertices = vertices, + k = k, + set_neg_to_zero = set_neg_to_zero) if(isTRUE(calc_centroids)) gpoly = calculate_centroids_polygons(gpolygon = gpoly, append_gpolygon = TRUE) slot(gpoly, 'spatVector') = terra::wrap(slot(gpoly, 'spatVector')) diff --git a/man/gpoly_from_dfr_smoothed_wrapped.Rd b/man/gpoly_from_dfr_smoothed_wrapped.Rd new file mode 100644 index 000000000..6dabe4aa4 --- /dev/null +++ b/man/gpoly_from_dfr_smoothed_wrapped.Rd @@ -0,0 +1,21 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/giotto_structures.R +\name{gpoly_from_dfr_smoothed_wrapped} +\alias{gpoly_from_dfr_smoothed_wrapped} +\title{Polygon creation and smoothing for parallel} +\usage{ +gpoly_from_dfr_smoothed_wrapped( + segmdfr, + name = "cell", + calc_centroids = FALSE, + smooth_polygons = FALSE, + skip_eval_dfr = FALSE, + copy_dt = TRUE, + verbose = TRUE, + ... +) +} +\description{ +Polygon creation and smoothing for parallel +} +\keyword{internal} From 9b51cb0c8a34896bc4a0ece5c124b7479fe4e12b Mon Sep 17 00:00:00 2001 From: jiajic <72078254+jiajic@users.noreply.github.com> Date: Fri, 6 Jan 2023 10:16:15 -0500 Subject: [PATCH 062/129] Update general_help.R --- R/general_help.R | 35 +++++++++++++++++++++++++++++++++-- 1 file changed, 33 insertions(+), 2 deletions(-) diff --git a/R/general_help.R b/R/general_help.R index 4af99153c..aa61dcb03 100644 --- a/R/general_help.R +++ b/R/general_help.R @@ -1513,7 +1513,9 @@ readPolygonFilesVizgenHDF5_old = function(boundaries_path, #' @param calc_centroids calculate centroids (default = FALSE) #' @param H5Fopen_flags see \code{\link[rhdf5]{H5Fopen}} for more details #' @param cores cores to use -#' @param create_gpoly_bin (Optional, default is FALSE) Parallelization option. +#' @param create_gpoly_parallel (default = TRUE) Whether to run gpoly creation in +#' parallel +#' @param create_gpoly_bin (Optional, default = FALSE) Parallelization option. #' Accepts integer values as an binning size when generating giottoPolygon objects #' @param verbose be verbose #' @seealso \code{\link{smoothGiottoPolygons}} @@ -1532,6 +1534,7 @@ readPolygonFilesVizgenHDF5 = function(boundaries_path, set_neg_to_zero = FALSE, H5Fopen_flags = "H5F_ACC_RDWR", cores = NA, + create_gpoly_parallel = TRUE, create_gpoly_bin = FALSE, verbose = TRUE, polygon_feat_types = NULL) { @@ -1630,8 +1633,36 @@ readPolygonFilesVizgenHDF5 = function(boundaries_path, if(isTRUE(verbose)) wrap_msg('finished extracting .hdf5 files start creating polygons') - # create Giotto polygons and add them to gobject + + # **** sequential method **** + if(!isTRUE(create_gpoly_parallel)) { + progressr::with_progress({ + pb = progressr::progressor(along = z_read_DT) + smooth_cell_polygons_list = lapply(seq_along(z_read_DT), function(i) { + dfr_subset = z_read_DT[[i]][,.(x, y, cell_id)] + data.table::setnames(dfr_subset, old = 'cell_id', new = 'poly_ID') + cell_polygons = createGiottoPolygonsFromDfr(segmdfr = dfr_subset, + name = poly_names[i], + calc_centroids = FALSE, + skip_eval_dfr = TRUE, + copy_dt = FALSE, + verbose = verbose) + if(isTRUE(smooth_polygons)) cell_polygons = smoothGiottoPolygons(gpolygon = cell_polygons, + vertices = smooth_vertices, + k = 3L, + set_neg_to_zero = set_neg_to_zero) + if(isTRUE(calc_centroids)) cell_polygons = calculate_centroids_polygons(gpolygon = cell_polygons, + append_gpolygon = TRUE) + pb(message = c(poly_names[i], ' (', i, '/', length(z_read_DT), ')')) + return(cell_polygons) + }) + }) + return(smooth_cell_polygons_list) + } + + + # **** parallel methods **** # no binning if(!is.numeric(create_gpoly_bin)) { From 80ee7c47b88f11e94f58147b82fe3a187514ba81 Mon Sep 17 00:00:00 2001 From: jiajic <72078254+jiajic@users.noreply.github.com> Date: Fri, 6 Jan 2023 10:35:00 -0500 Subject: [PATCH 063/129] Update classes.R Fix typo in `create_spat_net_obj()` --- R/classes.R | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/R/classes.R b/R/classes.R index fc6799627..2914ad69f 100644 --- a/R/classes.R +++ b/R/classes.R @@ -1807,7 +1807,7 @@ create_spat_net_obj = function(name = 'test', name = name, method = method, parameters = parameters, - outputObj, outputObj, + outputObj = outputObj, networkDT = networkDT, networkDT_before_filter = networkDT_before_filter, cellShapeObj = cellShapeObj, From 61a1f4b4f6b8946cc4d9b7541e4ba5a9ca80a047 Mon Sep 17 00:00:00 2001 From: jiajic <72078254+jiajic@users.noreply.github.com> Date: Mon, 9 Jan 2023 12:30:40 -0500 Subject: [PATCH 064/129] add image reconnection to loadGiotto() --- R/general_help.R | 1 + man/gpoly_from_dfr_smoothed_wrapped.Rd | 6 ++++-- man/readPolygonFilesVizgenHDF5.Rd | 6 +++++- 3 files changed, 10 insertions(+), 3 deletions(-) diff --git a/R/general_help.R b/R/general_help.R index aa61dcb03..dd8313ea9 100644 --- a/R/general_help.R +++ b/R/general_help.R @@ -920,6 +920,7 @@ loadGiotto = function(path_to_folder, gobject@largeImages[[image_name]]@raster_object = spatRaster } } + gobject = reconnectGiottoImage(gobject) identified_python_path = set_giotto_python_path(python_path = python_path) diff --git a/man/gpoly_from_dfr_smoothed_wrapped.Rd b/man/gpoly_from_dfr_smoothed_wrapped.Rd index 6dabe4aa4..83d65ce83 100644 --- a/man/gpoly_from_dfr_smoothed_wrapped.Rd +++ b/man/gpoly_from_dfr_smoothed_wrapped.Rd @@ -9,10 +9,12 @@ gpoly_from_dfr_smoothed_wrapped( name = "cell", calc_centroids = FALSE, smooth_polygons = FALSE, + vertices = 20L, + k = 3L, + set_neg_to_zero = TRUE, skip_eval_dfr = FALSE, copy_dt = TRUE, - verbose = TRUE, - ... + verbose = TRUE ) } \description{ diff --git a/man/readPolygonFilesVizgenHDF5.Rd b/man/readPolygonFilesVizgenHDF5.Rd index 1bfcb804e..072403421 100644 --- a/man/readPolygonFilesVizgenHDF5.Rd +++ b/man/readPolygonFilesVizgenHDF5.Rd @@ -18,6 +18,7 @@ readPolygonFilesVizgenHDF5( set_neg_to_zero = FALSE, H5Fopen_flags = "H5F_ACC_RDWR", cores = NA, + create_gpoly_parallel = TRUE, create_gpoly_bin = FALSE, verbose = TRUE, polygon_feat_types = NULL @@ -52,7 +53,10 @@ alternative segmentations were generated)} \item{cores}{cores to use} -\item{create_gpoly_bin}{(Optional, default is FALSE) Parallelization option. +\item{create_gpoly_parallel}{(default = TRUE) Whether to run gpoly creation in +parallel} + +\item{create_gpoly_bin}{(Optional, default = FALSE) Parallelization option. Accepts integer values as an binning size when generating giottoPolygon objects} \item{verbose}{be verbose} From e7fc1eed24f9b95a7746dffa0317538e0414e5a0 Mon Sep 17 00:00:00 2001 From: jiajic <72078254+jiajic@users.noreply.github.com> Date: Mon, 9 Jan 2023 12:54:57 -0500 Subject: [PATCH 065/129] Update differential_expression.R parallelize scran and gini --- R/differential_expression.R | 170 +++++++++++++++++++----------------- 1 file changed, 89 insertions(+), 81 deletions(-) diff --git a/R/differential_expression.R b/R/differential_expression.R index 2994f9a7b..2cdef1075 100644 --- a/R/differential_expression.R +++ b/R/differential_expression.R @@ -233,53 +233,57 @@ findScranMarkers_one_vs_all <- function(gobject, # save list - result_list = list() - - - for(clus_i in 1:length(uniq_clusters)) { - - selected_clus = uniq_clusters[clus_i] - other_clus = uniq_clusters[uniq_clusters != selected_clus] - - if(verbose == TRUE) { - cat('\n start with cluster ', selected_clus, '\n') - } - - # one vs all markers - markers = findScranMarkers(gobject = gobject, - spat_unit = spat_unit, - feat_type = feat_type, - expression_values = values, - cluster_column = cluster_column, - group_1 = selected_clus, - group_2 = other_clus, - verbose = FALSE) - - # identify list to continue with - select_bool = unlist(lapply(markers, FUN = function(x) { - unique(x$cluster) == selected_clus - })) - selected_table = data.table::as.data.table(markers[select_bool]) - - # remove summary column from scran output if present - col_ind_keep = !grepl('summary', colnames(selected_table)) - selected_table = selected_table[, col_ind_keep, with = F] - - # change logFC.xxx name to logFC - data.table::setnames(selected_table, colnames(selected_table)[4], 'logFC') - data.table::setnames(selected_table, colnames(selected_table)[5], 'feats') - - # filter selected table - filtered_table = selected_table[logFC > 0] - filtered_table[, 'ranking' := rank(-logFC)] - - # data.table variables - p.value = ranking = NULL - - filtered_table = filtered_table[(p.value <= pval & logFC >= logFC) | (ranking <= min_feats)] - - result_list[[clus_i]] = filtered_table - } + progressr::with_progress({ + pb = progressr::progressor(along = uniq_clusters) + result_list = lapply_flex( + seq_along(uniq_clusters), + future.packages = c('scran', 'data.table'), + function(clus_i) { + selected_clus = uniq_clusters[clus_i] + other_clus = uniq_clusters[uniq_clusters != selected_clus] + + if(verbose == TRUE) { + cat('\n start with cluster ', selected_clus, '\n') + } + + # one vs all markers + markers = findScranMarkers(gobject = gobject, + spat_unit = spat_unit, + feat_type = feat_type, + expression_values = values, + cluster_column = cluster_column, + group_1 = selected_clus, + group_2 = other_clus, + verbose = FALSE) + + # identify list to continue with + select_bool = unlist(lapply(markers, FUN = function(x) { + unique(x$cluster) == selected_clus + })) + selected_table = data.table::as.data.table(markers[select_bool]) + + # remove summary column from scran output if present + col_ind_keep = !grepl('summary', colnames(selected_table)) + selected_table = selected_table[, col_ind_keep, with = F] + + # change logFC.xxx name to logFC + data.table::setnames(selected_table, colnames(selected_table)[4], 'logFC') + data.table::setnames(selected_table, colnames(selected_table)[5], 'feats') + + # filter selected table + filtered_table = selected_table[logFC > 0] + filtered_table[, 'ranking' := rank(-logFC)] + + # data.table variables + p.value = ranking = NULL + + filtered_table = filtered_table[(p.value <= pval & logFC >= logFC) | (ranking <= min_feats)] + + pb() + return(filtered_table) + } + ) + }) return(do.call('rbind', result_list)) @@ -600,42 +604,46 @@ findGiniMarkers_one_vs_all <- function(gobject, uniq_clusters = sort(unique(cell_metadata[[cluster_column]])) - # save list - result_list = list() - - ## GINI - for(clus_i in 1:length(uniq_clusters)) { - - selected_clus = uniq_clusters[clus_i] - other_clus = uniq_clusters[uniq_clusters != selected_clus] - - if(verbose == TRUE) { - cat('\n start with cluster ', selected_clus, '\n') - } - - markers = findGiniMarkers(gobject = gobject, - feat_type = feat_type, - spat_unit = spat_unit, - expression_values = values, - cluster_column = cluster_column, - group_1 = selected_clus, - group_2 = other_clus, - min_expr_gini_score = min_expr_gini_score, - min_det_gini_score = min_det_gini_score, - detection_threshold = detection_threshold, - rank_score = rank_score, - min_feats = min_feats) - - # filter steps - #clus_name = paste0('cluster_', selected_clus) - - # data.table variables - cluster = NULL + # GINI + progressr::with_progress({ + pb = progressr::progressor(along = uniq_clusters) + result_list = lapply_flex( + seq_along(uniq_clusters), + future.packages = c('data.table', 'scales'), + function(clus_i) { + selected_clus = uniq_clusters[clus_i] + other_clus = uniq_clusters[uniq_clusters != selected_clus] - filtered_table = markers[cluster == selected_clus] + if(verbose == TRUE) { + cat('\n start with cluster ', selected_clus, '\n') + } - result_list[[clus_i]] = filtered_table - } + markers = findGiniMarkers(gobject = gobject, + feat_type = feat_type, + spat_unit = spat_unit, + expression_values = values, + cluster_column = cluster_column, + group_1 = selected_clus, + group_2 = other_clus, + min_expr_gini_score = min_expr_gini_score, + min_det_gini_score = min_det_gini_score, + detection_threshold = detection_threshold, + rank_score = rank_score, + min_feats = min_feats) + + # filter steps + #clus_name = paste0('cluster_', selected_clus) + + # data.table variables + cluster = NULL + + filtered_table = markers[cluster == selected_clus] + + pb() + return(filtered_table) + } + ) + }) return(do.call('rbind', result_list)) From 9041c0b723455b14e03cf3e439a9ab3748aa16ad Mon Sep 17 00:00:00 2001 From: jiajic <72078254+jiajic@users.noreply.github.com> Date: Mon, 9 Jan 2023 14:26:37 -0500 Subject: [PATCH 066/129] Update differential_expression.R --- R/differential_expression.R | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/R/differential_expression.R b/R/differential_expression.R index 2cdef1075..ca69f1535 100644 --- a/R/differential_expression.R +++ b/R/differential_expression.R @@ -235,9 +235,8 @@ findScranMarkers_one_vs_all <- function(gobject, # save list progressr::with_progress({ pb = progressr::progressor(along = uniq_clusters) - result_list = lapply_flex( + result_list = lapply( seq_along(uniq_clusters), - future.packages = c('scran', 'data.table'), function(clus_i) { selected_clus = uniq_clusters[clus_i] other_clus = uniq_clusters[uniq_clusters != selected_clus] @@ -279,7 +278,7 @@ findScranMarkers_one_vs_all <- function(gobject, filtered_table = filtered_table[(p.value <= pval & logFC >= logFC) | (ranking <= min_feats)] - pb() + pb(message = c('cluster ', clus_i, '/', length(uniq_clusters))) return(filtered_table) } ) @@ -607,9 +606,8 @@ findGiniMarkers_one_vs_all <- function(gobject, # GINI progressr::with_progress({ pb = progressr::progressor(along = uniq_clusters) - result_list = lapply_flex( + result_list = lapply( seq_along(uniq_clusters), - future.packages = c('data.table', 'scales'), function(clus_i) { selected_clus = uniq_clusters[clus_i] other_clus = uniq_clusters[uniq_clusters != selected_clus] @@ -639,7 +637,7 @@ findGiniMarkers_one_vs_all <- function(gobject, filtered_table = markers[cluster == selected_clus] - pb() + pb(message = c('cluster ', clus_i, '/', length(uniq_clusters))) return(filtered_table) } ) From 8a49f4390c9e2967db0aa42a51e6b93904066b51 Mon Sep 17 00:00:00 2001 From: jiajic <72078254+jiajic@users.noreply.github.com> Date: Mon, 9 Jan 2023 14:54:46 -0500 Subject: [PATCH 067/129] Update utilities.R --- R/utilities.R | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/R/utilities.R b/R/utilities.R index db02cf5ff..d52dabe76 100644 --- a/R/utilities.R +++ b/R/utilities.R @@ -151,12 +151,14 @@ cor_flex = function(x, ...) { #' @param X list to use #' @param FUN function to be performed #' @param cores cores to use +#' @param future.seed whether to set a seed when using future_lapply #' @param fun deprecated. Backwards compatibility for FUN #' @param ... other arguments to pass #' @keywords internal lapply_flex = function(X, FUN, cores = NA, + future.seed = TRUE, fun = NULL, ...) { @@ -182,7 +184,7 @@ lapply_flex = function(X, # future_lapply call - save_list = future.apply::future_lapply(X = X, FUN = FUN, future.seed = TRUE, ...) + save_list = future.apply::future_lapply(X = X, FUN = FUN, future.seed = future.seed, ...) #if(os == 'unix') { # save_list = parallel::mclapply(X = X, mc.cores = cores, From 1893988b9160d42e54cd391e5bedb7fa4cff0a63 Mon Sep 17 00:00:00 2001 From: jiajic <72078254+jiajic@users.noreply.github.com> Date: Mon, 9 Jan 2023 17:04:49 -0500 Subject: [PATCH 068/129] update reconnectGiottoImage() Add method to choose which image types to reconnect --- R/general_help.R | 5 ++++- R/images.R | 10 +++++++++- man/flex_lapply.Rd | 1 + man/lapply_flex.Rd | 4 +++- man/reconnectGiottoImage.Rd | 3 +++ 5 files changed, 20 insertions(+), 3 deletions(-) diff --git a/R/general_help.R b/R/general_help.R index dd8313ea9..652f77f5a 100644 --- a/R/general_help.R +++ b/R/general_help.R @@ -920,7 +920,10 @@ loadGiotto = function(path_to_folder, gobject@largeImages[[image_name]]@raster_object = spatRaster } } - gobject = reconnectGiottoImage(gobject) + + if(list_images(gobject)[img_type == 'image', .N] > 0) { + gobject = reconnectGiottoImage(gobject) + } identified_python_path = set_giotto_python_path(python_path = python_path) diff --git a/R/images.R b/R/images.R index ef419d334..b6fc9328f 100644 --- a/R/images.R +++ b/R/images.R @@ -2446,6 +2446,7 @@ reconnect_image_object = function(image_object, #' In such cases, use manual reconnection by setting \code{auto_reconnect = FALSE}. #' @param gobject giotto object #' @param auto_reconnect automatically reconnect images if TRUE. manual if FALSE +#' @param reconnect_type type of image to reconnect when auto_reconnect = TRUE #' @param image_name names of images to reconnect #' @param largeImage_name name of large images to reconnect #' @param image_path named list of paths to images to reconnect to giottoImages @@ -2456,6 +2457,7 @@ reconnect_image_object = function(image_object, #' @export reconnectGiottoImage = function(gobject, auto_reconnect = TRUE, + reconnect_type = 'all', image_name = NULL, largeImage_name = NULL, image_path = NULL, @@ -2468,7 +2470,13 @@ reconnectGiottoImage = function(gobject, if(is.null(gobject)) stop('Giotto object containing the giottoImages or giottoLargeImages to reconnect must be given \n') # 1. Find names and locations of image objects in gobject: ----------------------------# - availableImgs = list_images(gobject = gobject) + availableImgs = data.table::fcase( + reconnect_type == 'image', list_images(gobject = gobject, img_type = 'image'), + reconnect_type == 'largeImage', list_images(gobject = gobject, img_type = 'largeImage'), + reconnect_type == 'all', list_images(gobject = gobject), + default = stop('reconnect_type input unrecognized') + ) + # 2. Get reconnection info: -----------------------------------------------------------# diff --git a/man/flex_lapply.Rd b/man/flex_lapply.Rd index cbe6dfd4c..9c8770670 100644 --- a/man/flex_lapply.Rd +++ b/man/flex_lapply.Rd @@ -13,6 +13,7 @@ flex_lapply(X, FUN, cores = NA, fun = NULL, ...) \item{\code{X}}{list to use} \item{\code{FUN}}{function to be performed} \item{\code{cores}}{cores to use} + \item{\code{future.seed}}{whether to set a seed when using future_lapply} \item{\code{fun}}{deprecated. Backwards compatibility for FUN} }} } diff --git a/man/lapply_flex.Rd b/man/lapply_flex.Rd index 05e25ff38..b736c7f40 100644 --- a/man/lapply_flex.Rd +++ b/man/lapply_flex.Rd @@ -4,7 +4,7 @@ \alias{lapply_flex} \title{lapply_flex} \usage{ -lapply_flex(X, FUN, cores = NA, fun = NULL, ...) +lapply_flex(X, FUN, cores = NA, future.seed = TRUE, fun = NULL, ...) } \arguments{ \item{X}{list to use} @@ -13,6 +13,8 @@ lapply_flex(X, FUN, cores = NA, fun = NULL, ...) \item{cores}{cores to use} +\item{future.seed}{whether to set a seed when using future_lapply} + \item{fun}{deprecated. Backwards compatibility for FUN} \item{...}{other arguments to pass} diff --git a/man/reconnectGiottoImage.Rd b/man/reconnectGiottoImage.Rd index 0e64c0e93..e05e61ada 100644 --- a/man/reconnectGiottoImage.Rd +++ b/man/reconnectGiottoImage.Rd @@ -7,6 +7,7 @@ reconnectGiottoImage( gobject, auto_reconnect = TRUE, + reconnect_type = "all", image_name = NULL, largeImage_name = NULL, image_path = NULL, @@ -19,6 +20,8 @@ reconnectGiottoImage( \item{auto_reconnect}{automatically reconnect images if TRUE. manual if FALSE} +\item{reconnect_type}{type of image to reconnect when auto_reconnect = TRUE} + \item{image_name}{names of images to reconnect} \item{largeImage_name}{name of large images to reconnect} From 8e42ed345f27cbd0d6f7cf5e269debada8139712 Mon Sep 17 00:00:00 2001 From: jiajic <72078254+jiajic@users.noreply.github.com> Date: Mon, 9 Jan 2023 17:06:12 -0500 Subject: [PATCH 069/129] Update general_help.R --- R/general_help.R | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/R/general_help.R b/R/general_help.R index 652f77f5a..0c6ca5727 100644 --- a/R/general_help.R +++ b/R/general_help.R @@ -922,7 +922,7 @@ loadGiotto = function(path_to_folder, } if(list_images(gobject)[img_type == 'image', .N] > 0) { - gobject = reconnectGiottoImage(gobject) + gobject = reconnectGiottoImage(gobject, reconnect_type = 'image') } From e76f144fd5982f45252f56e7081f5b3150600fa8 Mon Sep 17 00:00:00 2001 From: irzamsarfraz Date: Tue, 10 Jan 2023 11:25:55 -0500 Subject: [PATCH 070/129] Updates to spatialExperiment function --- R/interoperability.R | 86 +++++++++++++++++++++----------- man/spatialExperimentToGiotto.Rd | 2 +- 2 files changed, 59 insertions(+), 29 deletions(-) diff --git a/R/interoperability.R b/R/interoperability.R index 45f6d1f0c..288a05429 100644 --- a/R/interoperability.R +++ b/R/interoperability.R @@ -1139,32 +1139,32 @@ giottoToSpatialExperiment <- function(giottoObj){ message("No spatial networks found in the input Giotto object") } - # SpatialImages - are these for each spatial unit? - giottoImages <- list_images(gobject = giottoObj) - if(!is.null(giottoImages)){ - message("Copying spatial images") - for(i in seq(nrow(giottoImages))){ - img <- get_giottoImage( - gobject = giottoObj, - image_type = giottoImages[i]$img_type, - name = giottoImages[i]$name) - - if(!is.null(img@file_path)){ - spe <- SpatialExperiment::addImg(spe, - sample_id = "sample01", #TODO? different samples get appended to cell_ids - image_id = img@name, - imageSource = img@file_path, - scaleFactor = NA_real_, - load = TRUE) - } - else{ - message("\t - Skipping image with NULL file path") - } - S4Vectors::metadata(spe)[[img@name]] <- img - } - } else{ - message("No spatial images found in the input Giotto object") - } + # SpatialImages - are these for each spatial unit? - PENDING George Updates + # giottoImages <- list_images(gobject = giottoObj) + # if(!is.null(giottoImages)){ + # message("Copying spatial images") + # for(i in seq(nrow(giottoImages))){ + # img <- get_giottoImage( + # gobject = giottoObj, + # image_type = giottoImages[i]$img_type, + # name = giottoImages[i]$name) + # + # if(!is.null(img@file_path)){ + # spe <- SpatialExperiment::addImg(spe, + # sample_id = "sample01", #TODO? different samples get appended to cell_ids + # image_id = img@name, + # imageSource = img@file_path, + # scaleFactor = NA_real_, + # load = TRUE) + # } + # else{ + # message("\t - Skipping image with NULL file path") + # } + # S4Vectors::metadata(spe)[[img@name]] <- img + # } + # } else{ + # message("No spatial images found in the input Giotto object") + # } message("") # Add spe for current spatial unit to speList @@ -1186,7 +1186,7 @@ giottoToSpatialExperiment <- function(giottoObj){ #' example(read10xVisium, echo = FALSE) #' spatialExperimentToGiotto(spe) #' @export -spatialExperimentToGiotto <- function(spe){ +spatialExperimentToGiotto <- function(spe, nn_network = NULL, sp_network = NULL){ # save exp matrices exprMats <- assays(spe) exprMatsNames <- assayNames(spe) @@ -1232,7 +1232,7 @@ spatialExperimentToGiotto <- function(spe){ spatialLocs <- spatialCoords(spe) if(ncol(spatialLocs) > 0){ spatialLocsDT <- data.table(sdimx = spatialLocs[, 1], sdimy = spatialLocs[, 2], cell_ID = rownames(spatialLocs)) - giottoObj <- Giotto:::set_spatial_locations(gobject = giottoObj, spatlocs = spatialLocsDT) + giottoObj <- Giotto:::set_spatial_locations(gobject = giottoObj, spatlocs = cbind(spatialLocsDT, cell_ID = colnames(spe))) } # TODO @@ -1241,9 +1241,39 @@ spatialExperimentToGiotto <- function(spe){ # TODO # networks + networks <- colPairs(spe) # giottoObj <- Giotto:::set_spatialNetwork() # giottoObj <- Giotto:::set_NearestNetwork() + if(!is.null(sp_network)){ + if(sp_network %in% names(networks)){ + for(i in seq(sp_network)){ + giottoObj <- Giotto:::set_spatialNetwork(gobject = giottoObj, + spatial_network = networks[[sp_network[i]]], + name = sp_network[i]) + networks[[sp_network[i]]] <- NULL + } + } + } + + if(!is.null(nn_network)){ + if(nn_network %in% names(networks)){ + for(i in seq(nn_network)){ + giottoObj <- Giotto:::set_NearestNetwork(gobject = giottoObj, + nn_network = networks[[nn_network[i]]], + network_name = nn_network[i]) + networks[[nn_network[i]]] <- NULL + } + } + } + + if(length(networks) > 0){ + for(i in seq(networks)){ + giottoObj <- Giotto:::set_NearestNetwork(gobject = giottoObj, + nn_network = networks[[i]], + network_name = names(networks)[i]) + } + } return(giottoObj) } diff --git a/man/spatialExperimentToGiotto.Rd b/man/spatialExperimentToGiotto.Rd index f60da7367..8284e6a09 100644 --- a/man/spatialExperimentToGiotto.Rd +++ b/man/spatialExperimentToGiotto.Rd @@ -4,7 +4,7 @@ \alias{spatialExperimentToGiotto} \title{Utility function to convert a SpatialExperiment object to a Giotto object} \usage{ -spatialExperimentToGiotto(spe) +spatialExperimentToGiotto(spe, nn_network = NULL, sp_network = NULL) } \arguments{ \item{spe}{Input SpatialExperiment object to convert to a Giotto object} From b62d174dd211335b6de3536e18a5af898df411b0 Mon Sep 17 00:00:00 2001 From: mattobny Date: Tue, 10 Jan 2023 15:43:04 -0500 Subject: [PATCH 071/129] NN implementation for ad2g --- R/interoperability.R | 67 ++++++++++++++++++++++++++++++++++++----- inst/python/ad2g.py | 71 ++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 131 insertions(+), 7 deletions(-) diff --git a/R/interoperability.R b/R/interoperability.R index 3160c57a3..f6d66b139 100644 --- a/R/interoperability.R +++ b/R/interoperability.R @@ -10,6 +10,12 @@ #' @name anndataToGiotto #' @description Converts a spatial anndata (e.g. scanpy) .h5ad file into a Giotto object #' @param anndata_path path to the .h5ad file +#' @param n_key_added equivalent of "key_added" argument from scanpy.pp.neighbors(). +#' Cannot be "spatial". This becomes the name of the nearest network in the gobject. +#' @param spatial_key_added equivalent of "key_added" argument from squidpy.gr.spatial_neighbors(). +#' Cannot be "neighbors". This becomes the name of the spatial network in the gobjet. +#' @param spat_unit desired spatial unit for conversion, default NULL +#' @param feat_type desired feature type for conversion, default NULL #' @param python_path path to python executable within a conda/miniconda environment #' @return Giotto object #' @details Function in beta. Converts a .h5ad file into a Giotto object. @@ -18,6 +24,10 @@ #' See \code{\link{changeGiottoInstructions}} to modify instructions after creation. #' @export anndataToGiotto = function(anndata_path = NULL, + n_key_added = NULL, + spatial_key_added = NULL, + spat_unit = NULL, + feat_type = NULL, python_path = NULL) { # Preliminary file checks and guard clauses @@ -74,9 +84,6 @@ anndataToGiotto = function(anndata_path = NULL, reticulate::source_python(ad2g_path) adata <- read_anndata_from_path(anndata_path) - spat_unit = NULL - feat_type = NULL - ### Set up expression matrix X <- extract_expression(adata) cID = extract_cell_IDs(adata) @@ -185,6 +192,56 @@ anndataToGiotto = function(anndata_path = NULL, dimObject = dobj) } + ### NN Network + + # Need to create nnNetObj or igraph object to use with setter for NN + + weights_ad = NULL + weights_ad = extract_NN_connectivities(adata, key_added = n_key_added) + if (!is.null(weights_ad)) { + distances_ad = extract_NN_distances(adata, key_added = n_key_added) + ij_matrix = as(distances_ad, "TsparseMatrix") + from_idx = ij_matrix@i + 1 #zero index!!! + to_idx = ij_matrix@j + 1 #zero index!!! + + #pre-allocate DT variables + from = to = weight = distance = from_cell_ID = to_cell_ID = uniq_ID = NULL + nn_dt = data.table::data.table(from = from_idx, + to = to_idx, + weight = weights_ad@x, + distance = distances_ad@x) + + nn_dt[, from_cell_ID := cID[from]] + nn_dt[, to_cell_ID := cID[to]] + nn_dt[, uniq_ID := paste0(from,to)] + nn_dt[order(uniq_ID)] + nn_dt[,uniq_ID := NULL] + vert = unique(x = c(nn_dt$from_cell_ID, nn_dt$to_cell_ID)) + nn_network_igraph = igraph::graph_from_data_frame(nn_dt[,.(from_cell_ID, to_cell_ID, weight, distance)], directed = TRUE, vertices = vert) + # og_nn = get_NearestNetwork(SS_seqfish, spat_unit = "cell", feat_type = "rna", nn_network_to_use = "kNN") + # as written, no difference found between original and above from igraph::difference() + + nn_info = extract_NN_info(adata = adata, key_added = n_key_added) + browser() + net_type = "kNN" # anndata default + if(("sNN" %in% n_key_added) & !is.null(n_key_added)){ + net_type = "sNN" + net_name = paste0(n_key_added, ".", nn_info["method"]) + } else if (!("sNN" %in% n_key_added) & !is.null(n_key_added)) { + net_name = paste0(n_key_added, ".", nn_info["method"]) + } else { + net_name = paste0(net_type, ".", nn_info["method"]) + } + + gobject = set_NearestNetwork(gobject = gobject, + nn_network = nn_network_igraph, + spat_unit = spat_unit, + feat_type = feat_type, + nn_network_to_use = net_type, + network_name = net_name, + set_defaults = FALSE) + } + ### Layers lay_names = extract_layer_names(adata) if (!is.null(lay_names)) { @@ -583,8 +640,6 @@ giottoToAnnData <- function(gobject = NULL, output = "nnNetObj", set_defaults = FALSE) - #weight_mat = igraph::as_data_frame(gob_NN[])$weight - #dist_mat = igraph::as_data_frame(gob_NN[])$distance pidx = grep("nn_network", names(gobject@parameters)) for (p in pidx) { if (gobject@parameters[[p]]["type"] == nn_net_tu) { @@ -595,7 +650,6 @@ giottoToAnnData <- function(gobject = NULL, df_gob_NN = igraph::as_data_frame(gob_NN[]) - browser() adata_list[[adata_pos]] = set_adg_nn(adata = adata_list[[adata_pos]], df_NN = df_gob_NN, net_name = n_name, @@ -609,7 +663,6 @@ giottoToAnnData <- function(gobject = NULL, } } - browser() # Reset indexing variable adata_pos = 1 diff --git a/inst/python/ad2g.py b/inst/python/ad2g.py index 6beac22df..817c19536 100644 --- a/inst/python/ad2g.py +++ b/inst/python/ad2g.py @@ -2,6 +2,7 @@ import pandas as pd import numpy as np import scipy +import warnings ### Imports and safeguards def read_anndata_from_path(ad_path = None): @@ -195,3 +196,73 @@ def extract_layered_data(adata = None, layer_name = None): target_layer = pd.DataFrame(target_layer) return target_layer +### Nearest Network + +def find_NN_keys(adata = None, key_added = None): + # No need to add to globals + nn_key_list = [] + + if key_added and key_added.casefold() != "spatial": + map_keys = adata.uns[key_added].keys() + for i in map_keys: + #if type(adata.uns[key_added][i]) == type(dict()): continue + nn_key_list.append(adata.uns[key_added][i]) + elif key_added and key_added.casefold() == "spatial": + s1 = "String 'spatial' cannot be used as n_key_added to retrieve a Nearest Neighbor Network. " + s2 = "This results from conflicting keys for nearest neighbor and spatial networks. " + s3 = "\nSee defaults here:\nhttps://scanpy.readthedocs.io/en/stable/generated/scanpy.pp.neighbors.html\nhttps://squidpy.readthedocs.io/en/stable/api/squidpy.gr.spatial_neighbors.html" + msg = s1+ s2 + s3 + warnings.warn(msg) + else: + param_keys = list(adata.uns.keys()) + for pk in param_keys: + if "neighbors" in pk and "spatial" not in pk: + tmp_keys = adata.uns[pk].keys() + for i in tmp_keys: + #if type(adata.uns[pk][i]) == type(dict()): continue + nn_key_list.append(adata.uns[pk][i]) + break # only return connectivity and distance keys for one network + + if len(nn_key_list) == 0: + nn_key_list = None + return nn_key_list + +def extract_NN_connectivities(adata = None, key_added = None): + ad_guard(adata) + + connectivities = None + nn_key_list = find_NN_keys(adata=adata, key_added=key_added) + + if type(nn_key_list) is type(None): + return connectivities + + for nk in nn_key_list: + if "connectivities" in nk: + connectivities = adata.obsp[nk] + + return connectivities + + +def extract_NN_distances(adata = None, key_added = None): + ad_guard(adata) + + distances = None + nn_key_list = find_NN_keys(adata=adata, key_added=key_added) + + if type(nn_key_list) is type(None): + return distances + + for nk in nn_key_list: + if "distances" in nk: + distances = adata.obsp[nk] + + return distances + +def extract_NN_info(adata = None, key_added = None): + ad_guard(adata) + nn_keys = find_NN_keys(adata, key_added=key_added) + nn_info = None + for nk in nn_keys: + if type(nk) is dict: + nn_info = pd.Series(nk) + return nn_info From 4da06d9387288c52e976ebc2b219e9f05ff1bc1a Mon Sep 17 00:00:00 2001 From: mattobny Date: Tue, 10 Jan 2023 15:52:07 -0500 Subject: [PATCH 072/129] Add python fxns to globals --- R/globals.R | 4 +++- inst/python/ad2g.py | 1 - 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/R/globals.R b/R/globals.R index 7f5262555..f6b46c6bf 100644 --- a/R/globals.R +++ b/R/globals.R @@ -14,5 +14,7 @@ utils::globalVariables(names = c(":=", ".N", ".SD", ".", "cast", "extract_pca","extract_umap","extract_tsne", "parse_obsm_for_spat_locs","extract_cell_metadata", "extract_feat_metadata","extract_layer_names", - "extract_layered_data","set_adg_nn")) + "extract_layered_data","set_adg_nn","find_NN_keys", + "extract_NN_connectivities","extract_NN_distances", + "extract_NN_info")) diff --git a/inst/python/ad2g.py b/inst/python/ad2g.py index 817c19536..f72a78368 100644 --- a/inst/python/ad2g.py +++ b/inst/python/ad2g.py @@ -199,7 +199,6 @@ def extract_layered_data(adata = None, layer_name = None): ### Nearest Network def find_NN_keys(adata = None, key_added = None): - # No need to add to globals nn_key_list = [] if key_added and key_added.casefold() != "spatial": From 88c6eb4721092ca6ca23eb6165f1f99afd76174e Mon Sep 17 00:00:00 2001 From: mattobny Date: Tue, 10 Jan 2023 16:03:46 -0500 Subject: [PATCH 073/129] remove yet-to-be-implemented arg --- R/interoperability.R | 2 -- 1 file changed, 2 deletions(-) diff --git a/R/interoperability.R b/R/interoperability.R index ddcd2075b..a1524e6cc 100644 --- a/R/interoperability.R +++ b/R/interoperability.R @@ -12,8 +12,6 @@ #' @param anndata_path path to the .h5ad file #' @param n_key_added equivalent of "key_added" argument from scanpy.pp.neighbors(). #' Cannot be "spatial". This becomes the name of the nearest network in the gobject. -#' @param spatial_key_added equivalent of "key_added" argument from squidpy.gr.spatial_neighbors(). -#' Cannot be "neighbors". This becomes the name of the spatial network in the gobjet. #' @param spat_unit desired spatial unit for conversion, default NULL #' @param feat_type desired feature type for conversion, default NULL #' @param python_path path to python executable within a conda/miniconda environment From 8ed77fcb1146cd558cb6716f8d1422bda661bfcc Mon Sep 17 00:00:00 2001 From: mattobny Date: Tue, 10 Jan 2023 16:04:38 -0500 Subject: [PATCH 074/129] documentation update --- man/anndataToGiotto.Rd | 16 +++++++++++++++- man/gpoly_from_dfr_smoothed_wrapped.Rd | 6 ++++-- man/readPolygonFilesVizgenHDF5.Rd | 6 +++++- 3 files changed, 24 insertions(+), 4 deletions(-) diff --git a/man/anndataToGiotto.Rd b/man/anndataToGiotto.Rd index a0888cff4..907b8e681 100644 --- a/man/anndataToGiotto.Rd +++ b/man/anndataToGiotto.Rd @@ -4,11 +4,25 @@ \alias{anndataToGiotto} \title{Convert anndata to Giotto} \usage{ -anndataToGiotto(anndata_path = NULL, python_path = NULL) +anndataToGiotto( + anndata_path = NULL, + n_key_added = NULL, + spatial_key_added = NULL, + spat_unit = NULL, + feat_type = NULL, + python_path = NULL +) } \arguments{ \item{anndata_path}{path to the .h5ad file} +\item{n_key_added}{equivalent of "key_added" argument from scanpy.pp.neighbors(). +Cannot be "spatial". This becomes the name of the nearest network in the gobject.} + +\item{spat_unit}{desired spatial unit for conversion, default NULL} + +\item{feat_type}{desired feature type for conversion, default NULL} + \item{python_path}{path to python executable within a conda/miniconda environment} } \value{ diff --git a/man/gpoly_from_dfr_smoothed_wrapped.Rd b/man/gpoly_from_dfr_smoothed_wrapped.Rd index 6dabe4aa4..83d65ce83 100644 --- a/man/gpoly_from_dfr_smoothed_wrapped.Rd +++ b/man/gpoly_from_dfr_smoothed_wrapped.Rd @@ -9,10 +9,12 @@ gpoly_from_dfr_smoothed_wrapped( name = "cell", calc_centroids = FALSE, smooth_polygons = FALSE, + vertices = 20L, + k = 3L, + set_neg_to_zero = TRUE, skip_eval_dfr = FALSE, copy_dt = TRUE, - verbose = TRUE, - ... + verbose = TRUE ) } \description{ diff --git a/man/readPolygonFilesVizgenHDF5.Rd b/man/readPolygonFilesVizgenHDF5.Rd index 1bfcb804e..072403421 100644 --- a/man/readPolygonFilesVizgenHDF5.Rd +++ b/man/readPolygonFilesVizgenHDF5.Rd @@ -18,6 +18,7 @@ readPolygonFilesVizgenHDF5( set_neg_to_zero = FALSE, H5Fopen_flags = "H5F_ACC_RDWR", cores = NA, + create_gpoly_parallel = TRUE, create_gpoly_bin = FALSE, verbose = TRUE, polygon_feat_types = NULL @@ -52,7 +53,10 @@ alternative segmentations were generated)} \item{cores}{cores to use} -\item{create_gpoly_bin}{(Optional, default is FALSE) Parallelization option. +\item{create_gpoly_parallel}{(default = TRUE) Whether to run gpoly creation in +parallel} + +\item{create_gpoly_bin}{(Optional, default = FALSE) Parallelization option. Accepts integer values as an binning size when generating giottoPolygon objects} \item{verbose}{be verbose} From 35ba707b63e5aee27e38604f592b5f36398c2b28 Mon Sep 17 00:00:00 2001 From: mattobny Date: Wed, 11 Jan 2023 12:00:53 -0500 Subject: [PATCH 075/129] Account for S4 change within filterCombinations --- R/auxiliary_giotto.R | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/R/auxiliary_giotto.R b/R/auxiliary_giotto.R index 8f3830e0a..2b8762f8c 100644 --- a/R/auxiliary_giotto.R +++ b/R/auxiliary_giotto.R @@ -1911,7 +1911,7 @@ filterCombinations <- function(gobject, expr_values = get_expression_values(gobject = gobject, spat_unit = spat_unit, feat_type = feat_type, - values = values) + values = values)[] # feat and cell minimums need to have the same length if(length(feat_det_in_min_cells) != length(min_det_feats_per_cell)) { From 6784519ad2107971422180bd3b2722a6e351b35b Mon Sep 17 00:00:00 2001 From: jiajic <72078254+jiajic@users.noreply.github.com> Date: Wed, 11 Jan 2023 14:30:28 -0500 Subject: [PATCH 076/129] Update NEWS.md --- NEWS.md | 1 + 1 file changed, 1 insertion(+) diff --git a/NEWS.md b/NEWS.md index a2918fa2a..1bee892ee 100644 --- a/NEWS.md +++ b/NEWS.md @@ -22,6 +22,7 @@ - Removed `createGiottoCosMxObject()` `aggregate` and `all` workflows until they are updated - Deprecate `polygon_feat_names` param in favor of `z_indices` in `readPolygonFilesVizgenHDF5()` - Optimize `readPolygonFilesVizgen()` +- Fix bug in `loadGiotto()` that prevents proper parsing of filenames when spat_unit or feat_type contains '_' characters # Giotto Suite 3.1.0 (2202-12-01) From 45e91cd5bdfe4c109859dcfd3a85b8fbced0aa6b Mon Sep 17 00:00:00 2001 From: jiajic <72078254+jiajic@users.noreply.github.com> Date: Wed, 11 Jan 2023 15:44:37 -0500 Subject: [PATCH 077/129] Update reconnectGiottoImages() --- R/images.R | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/R/images.R b/R/images.R index b6fc9328f..004d077e6 100644 --- a/R/images.R +++ b/R/images.R @@ -2457,7 +2457,7 @@ reconnect_image_object = function(image_object, #' @export reconnectGiottoImage = function(gobject, auto_reconnect = TRUE, - reconnect_type = 'all', + reconnect_type = c('all', 'image', 'largeImage'), image_name = NULL, largeImage_name = NULL, image_path = NULL, @@ -2468,14 +2468,16 @@ reconnectGiottoImage = function(gobject, # Manual workflow needs to be updated when adding more image types if(is.null(gobject)) stop('Giotto object containing the giottoImages or giottoLargeImages to reconnect must be given \n') + reconnect_type = match.arg(reconnect_type, choices = c('all', 'image', 'largeImage')) # 1. Find names and locations of image objects in gobject: ----------------------------# - availableImgs = data.table::fcase( - reconnect_type == 'image', list_images(gobject = gobject, img_type = 'image'), - reconnect_type == 'largeImage', list_images(gobject = gobject, img_type = 'largeImage'), - reconnect_type == 'all', list_images(gobject = gobject), + if(reconnect_type %in% c('image', largeImage)) { + availableImgs = list_images(gobject = gobject, img_type = reconnect_type) + } else if(reconnect_type == 'all') { + availableImgs = list_images(gobject = gobject) + } else { default = stop('reconnect_type input unrecognized') - ) + } # 2. Get reconnection info: -----------------------------------------------------------# From 6bd0b51bfbf0d2276a37d0ad65ff4ee0ddefb9cf Mon Sep 17 00:00:00 2001 From: jiajic <72078254+jiajic@users.noreply.github.com> Date: Wed, 11 Jan 2023 15:46:02 -0500 Subject: [PATCH 078/129] fix typo --- R/images.R | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/R/images.R b/R/images.R index 004d077e6..e6c3fcf49 100644 --- a/R/images.R +++ b/R/images.R @@ -2471,7 +2471,7 @@ reconnectGiottoImage = function(gobject, reconnect_type = match.arg(reconnect_type, choices = c('all', 'image', 'largeImage')) # 1. Find names and locations of image objects in gobject: ----------------------------# - if(reconnect_type %in% c('image', largeImage)) { + if(reconnect_type %in% c('image', 'largeImage')) { availableImgs = list_images(gobject = gobject, img_type = reconnect_type) } else if(reconnect_type == 'all') { availableImgs = list_images(gobject = gobject) From e41042d366ff704cd33503f9d84c43ea1d497d5c Mon Sep 17 00:00:00 2001 From: jiajic <72078254+jiajic@users.noreply.github.com> Date: Thu, 12 Jan 2023 00:44:57 -0500 Subject: [PATCH 079/129] Update overlapImagesToMatrix Remove warnings about not being able to set defaults --- R/giotto_structures.R | 6 +++--- man/reconnectGiottoImage.Rd | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/R/giotto_structures.R b/R/giotto_structures.R index fa8e10cdf..ab75da98d 100644 --- a/R/giotto_structures.R +++ b/R/giotto_structures.R @@ -2337,7 +2337,7 @@ calculateOverlapPolygonImages = function(gobject, image_vector_c = do.call('c', image_list) - # convert spatVectot to sf object + # convert spatVector to sf object if(!is.null(poly_subset)) { poly_info_spatvector_sf = sf::st_as_sf(poly_info@spatVector[poly_subset]) } else{ @@ -2905,11 +2905,11 @@ overlapImagesToMatrix = function(gobject, # create cell and feature metadata S4_cell_meta = create_cell_meta_obj(metaDT = data.table::data.table(cell_ID = cell_IDs), spat_unit = poly_info, feat_type = feat_info) - gobject = set_cell_metadata(gobject = gobject, S4_cell_meta) + gobject = set_cell_metadata(gobject = gobject, S4_cell_meta, set_defaults = FALSE) S4_feat_meta = create_feat_meta_obj(metaDT = data.table::data.table(feat_ID = feat_IDs), spat_unit = poly_info, feat_type = feat_info) - gobject = set_feature_metadata(gobject = gobject, S4_feat_meta) + gobject = set_feature_metadata(gobject = gobject, S4_feat_meta, set_defaults = FALSE) # add feat_ID and cell_ID diff --git a/man/reconnectGiottoImage.Rd b/man/reconnectGiottoImage.Rd index e05e61ada..446871054 100644 --- a/man/reconnectGiottoImage.Rd +++ b/man/reconnectGiottoImage.Rd @@ -7,7 +7,7 @@ reconnectGiottoImage( gobject, auto_reconnect = TRUE, - reconnect_type = "all", + reconnect_type = c("all", "image", "largeImage"), image_name = NULL, largeImage_name = NULL, image_path = NULL, From a8ff097074299c48ec8276adcd650665abe6c8d0 Mon Sep 17 00:00:00 2001 From: irzamsarfraz Date: Thu, 12 Jan 2023 13:31:31 -0500 Subject: [PATCH 080/129] Fixed spatial networks and nn networks in sptoGiotto function --- R/interoperability.R | 28 +++++++++++++++------------- man/anndataToGiotto.Rd | 2 +- 2 files changed, 16 insertions(+), 14 deletions(-) diff --git a/R/interoperability.R b/R/interoperability.R index a1524e6cc..b8820b029 100644 --- a/R/interoperability.R +++ b/R/interoperability.R @@ -10,7 +10,7 @@ #' @name anndataToGiotto #' @description Converts a spatial anndata (e.g. scanpy) .h5ad file into a Giotto object #' @param anndata_path path to the .h5ad file -#' @param n_key_added equivalent of "key_added" argument from scanpy.pp.neighbors(). +#' @param n_key_added equivalent of "key_added" argument from scanpy.pp.neighbors(). #' Cannot be "spatial". This becomes the name of the nearest network in the gobject. #' @param spat_unit desired spatial unit for conversion, default NULL #' @param feat_type desired feature type for conversion, default NULL @@ -197,7 +197,7 @@ anndataToGiotto = function(anndata_path = NULL, weights_ad = NULL weights_ad = extract_NN_connectivities(adata, key_added = n_key_added) if (!is.null(weights_ad)) { - distances_ad = extract_NN_distances(adata, key_added = n_key_added) + distances_ad = extract_NN_distances(adata, key_added = n_key_added) ij_matrix = as(distances_ad, "TsparseMatrix") from_idx = ij_matrix@i + 1 #zero index!!! to_idx = ij_matrix@j + 1 #zero index!!! @@ -208,11 +208,11 @@ anndataToGiotto = function(anndata_path = NULL, to = to_idx, weight = weights_ad@x, distance = distances_ad@x) - + nn_dt[, from_cell_ID := cID[from]] nn_dt[, to_cell_ID := cID[to]] nn_dt[, uniq_ID := paste0(from,to)] - nn_dt[order(uniq_ID)] + nn_dt[order(uniq_ID)] nn_dt[,uniq_ID := NULL] vert = unique(x = c(nn_dt$from_cell_ID, nn_dt$to_cell_ID)) nn_network_igraph = igraph::graph_from_data_frame(nn_dt[,.(from_cell_ID, to_cell_ID, weight, distance)], directed = TRUE, vertices = vert) @@ -236,7 +236,7 @@ anndataToGiotto = function(anndata_path = NULL, spat_unit = spat_unit, feat_type = feat_type, nn_network_to_use = net_type, - network_name = net_name, + network_name = net_name, set_defaults = FALSE) } @@ -520,7 +520,7 @@ giottoToAnnData <- function(gobject = NULL, adata_pos = adata_pos + 1 } } - adata_pos = 1 + adata_pos = 1 } @@ -637,7 +637,7 @@ giottoToAnnData <- function(gobject = NULL, network_name = n_name, output = "nnNetObj", set_defaults = FALSE) - + pidx = grep("nn_network", names(gobject@parameters)) for (p in pidx) { if (gobject@parameters[[p]]["type"] == nn_net_tu) { @@ -653,7 +653,7 @@ giottoToAnnData <- function(gobject = NULL, net_name = n_name, n_neighbors = kval, dim_red_used = dim_red_used) - + } } @@ -1320,7 +1320,8 @@ spatialExperimentToGiotto <- function(spe, nn_network = NULL, sp_network = NULL) if(length(unique(colnames(firstMatrix))) != length(colnames(firstMatrix))){ colnames(firstMatrix) <- make.names(colnames(firstMatrix), unique = TRUE) } - giottoObj <- createGiottoObject(expression = firstMatrix) + suppressWarnings(giottoObj <- createGiottoObject(expression = firstMatrix), + classes = c("message", "warning")) exprMats[[1]] <- NULL #rest of assays # how to figure out spat unit? if(length(exprMats) > 0){ @@ -1367,20 +1368,21 @@ spatialExperimentToGiotto <- function(spe, nn_network = NULL, sp_network = NULL) # TODO # networks networks <- colPairs(spe) - # giottoObj <- Giotto:::set_spatialNetwork() - # giottoObj <- Giotto:::set_NearestNetwork() - + # Spatial Networks if(!is.null(sp_network)){ if(sp_network %in% names(networks)){ for(i in seq(sp_network)){ + spatNetObj <- Giotto:::create_spat_net_obj( + networkDT = as.data.table(networks[[sp_network[i]]])) giottoObj <- Giotto:::set_spatialNetwork(gobject = giottoObj, - spatial_network = networks[[sp_network[i]]], + spatial_network = spatNetObj, name = sp_network[i]) networks[[sp_network[i]]] <- NULL } } } + # Nearest Neighbour Networks if(!is.null(nn_network)){ if(nn_network %in% names(networks)){ for(i in seq(nn_network)){ diff --git a/man/anndataToGiotto.Rd b/man/anndataToGiotto.Rd index 907b8e681..7866a24e0 100644 --- a/man/anndataToGiotto.Rd +++ b/man/anndataToGiotto.Rd @@ -16,7 +16,7 @@ anndataToGiotto( \arguments{ \item{anndata_path}{path to the .h5ad file} -\item{n_key_added}{equivalent of "key_added" argument from scanpy.pp.neighbors(). +\item{n_key_added}{equivalent of "key_added" argument from scanpy.pp.neighbors(). Cannot be "spatial". This becomes the name of the nearest network in the gobject.} \item{spat_unit}{desired spatial unit for conversion, default NULL} From 76ca2f86f5836c374d2ea5e147715d0b60f874d7 Mon Sep 17 00:00:00 2001 From: mattobny Date: Thu, 12 Jan 2023 14:58:22 -0500 Subject: [PATCH 081/129] gitignore --- .gitignore | 1 + 1 file changed, 1 insertion(+) diff --git a/.gitignore b/.gitignore index cfd5f1a2b..c85245010 100644 --- a/.gitignore +++ b/.gitignore @@ -8,3 +8,4 @@ inst/doc merfish_preoptic/ .vscode/* .Rprofile +inst/python/.ipynb_checkpoints/ From 11ee2a1705270aa6d506673386c7bde41ed268a2 Mon Sep 17 00:00:00 2001 From: Eddie Ruiz <32622519+Ed2uiz@users.noreply.github.com> Date: Thu, 12 Jan 2023 15:16:13 -0500 Subject: [PATCH 082/129] Update interoperability.R --- R/interoperability.R | 71 ++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 71 insertions(+) diff --git a/R/interoperability.R b/R/interoperability.R index a1524e6cc..b31b13ff3 100644 --- a/R/interoperability.R +++ b/R/interoperability.R @@ -3,6 +3,77 @@ +## gef object #### +## gef object #### +#' @title Convert gef to Giotto +#' @name gefToGiotto +#' @description Converts .gef file (output stereo-seq pipeline) into +#' giotto subcellular object +#' @param gef_file path to .gef file +#' @param bin_size bin size to select from .gef file +#' @param verbose be verbose +#' @details Function in beta. Converts .gef object to Giotto object. +#' +#' There are six possible choices for bin_size: 1, 10, 20, 50, 100, 200. +#' +#' See SAW pipeline for additional information about the gef file. +#' @export +gefToGiotto = function(gef_file, bin_size = 'bin100', verbose = TRUE){ + + # data.table vars + genes = NULL + + # package check + package_check(pkg_name = 'rhdf5', repository = 'Bioc') + if(!file.exists(gef_file)) stop('File path to .gef file does not exist') + + # check if proper bin_size is selected + bin_size_options = c('bin1', 'bin10', 'bin20', 'bin50', 'bin100', 'bin200') + if(!(bin_size %in% bin_size_options)) stop('Please select valid bin size, + see details for choices.') + + # step 1: read expression and gene data from gef file + geneExpData = rhdf5::h5read(file = gef_file, name = 'geneExp') + exprDT = data.table::as.data.table(geneExpData[[bin_size]][['expression']]) + geneDT = data.table::as.data.table(geneExpData[[bin_size]][['gene']]) + if(isTRUE(verbose)) wrap_msg('read in .gef file') + + # step 2: combine gene information from the geneDT to the exprDT + exprDT[, genes := rep(x = geneDT$gene, geneDT$count)] + + # step 3: bin coordinates according to selected bin_size + bin_size_int = as.integer(gsub("[^0-9.-]", "", bin_size)) + #TODO: update bin_shift for other shapes, not just rect_vertices + bin_shift = ceiling(bin_size_int / 2) # ceiling catches bin_1 + bincoord = unique(exprDT[,.(x,y)]) + setorder(bincoord, x, y) + setnames(bincoord, old = c('x', 'y'), new = c('sdimx', 'sdimy')) + bincoord[, c('sdimx', 'sdimy') := list(sdimx+bin_shift, sdimy+bin_shift)] + bincoord[, cell_ID := paste0('bin', 1:.N)] + tx_data = exprDT[,.(genes, x, y, count)] + tx_data[, c('x', 'y') := list(x+bin_shift, y+bin_shift)] + if(isTRUE(verbose)) wrap_msg('shift and bin coordinates') + + # step 4: create rectangular polygons (grid) starting from the bin centroids + x = polyStamp(stamp_dt = rectVertices(dims = c(x = (bin_size_int - 1), + y = (bin_size_int - 1))), + spatlocs = bincoord[,.(cell_ID, sdimx, sdimy)]) + pg = createGiottoPolygonsFromDfr(x) + if(isTRUE(verbose)) wrap_msg('create polygon stamp') + + # step 5: create giotto subcellular object + stereo = createGiottoObjectSubcellular( + gpoints = list(rna = tx_data), + gpolygons = list(cell = pg) + ) + + stereo = addSpatialCentroidLocations(gobject = stereo) + if(isTRUE(verbose)) wrap_msg('giotto subcellular object created') + + return(stereo) +} + + ## anndata object #### From b91485e547a84bf7d356b94755b33f433d2d4025 Mon Sep 17 00:00:00 2001 From: Eddie Ruiz <32622519+Ed2uiz@users.noreply.github.com> Date: Thu, 12 Jan 2023 15:17:40 -0500 Subject: [PATCH 083/129] Update NEWS.md --- NEWS.md | 1 + 1 file changed, 1 insertion(+) diff --git a/NEWS.md b/NEWS.md index a2918fa2a..ffe2ec0a9 100644 --- a/NEWS.md +++ b/NEWS.md @@ -4,6 +4,7 @@ - Removed support for deprecated nesting in `@nn_network` slot ## Added +- New `gefToGiotto()` interoperability function to convert gef object from Stereo-seq to giotto - New `giottoToAnnData()` interoperability function to convert giotto object to squidpy flavor anndata .h5ad file(s) - Add missing `create_nn_net_obj()` internal constructor function for S4 `nnNetObj` - New `createGiottoMerscopeObject()` convenience function From 20e9f5a6d33bf42d7f07ae72ccde0f2f2921cd46 Mon Sep 17 00:00:00 2001 From: Eddie Ruiz <32622519+Ed2uiz@users.noreply.github.com> Date: Thu, 12 Jan 2023 15:24:00 -0500 Subject: [PATCH 084/129] Update interoperability.R --- R/interoperability.R | 1 - 1 file changed, 1 deletion(-) diff --git a/R/interoperability.R b/R/interoperability.R index b31b13ff3..382a83388 100644 --- a/R/interoperability.R +++ b/R/interoperability.R @@ -3,7 +3,6 @@ -## gef object #### ## gef object #### #' @title Convert gef to Giotto #' @name gefToGiotto From badc99424c8114a611b5ceb21e77cfd376fb999f Mon Sep 17 00:00:00 2001 From: jiajic <72078254+jiajic@users.noreply.github.com> Date: Thu, 12 Jan 2023 17:10:52 -0500 Subject: [PATCH 085/129] Add wrap() for giottoPolygon - Added packedGiottoPoygon class - Added packedGiottoPoints class - Added wrap and unwrap generics for both --- NAMESPACE | 4 ++ R/classes.R | 45 +++++++++++++++++++++ R/generics.R | 95 +++++++++++++++++++++++++++++++++++++++++++++ man/wrap-generic.Rd | 37 ++++++++++++++++++ 4 files changed, 181 insertions(+) create mode 100644 man/wrap-generic.Rd diff --git a/NAMESPACE b/NAMESPACE index bbd67cbc9..cde0877fb 100644 --- a/NAMESPACE +++ b/NAMESPACE @@ -416,6 +416,8 @@ exportMethods(plot) exportMethods(prov) exportMethods(rbind2) exportMethods(spatUnit) +exportMethods(unwrap) +exportMethods(wrap) import(data.table) import(ggplot2) import(magrittr) @@ -427,3 +429,5 @@ importFrom(methods,rbind2) importFrom(methods,show) importFrom(methods,slot) importFrom(methods,validObject) +importMethodsFrom(terra,unwrap) +importMethodsFrom(terra,wrap) diff --git a/R/classes.R b/R/classes.R index 2914ad69f..5468fed32 100644 --- a/R/classes.R +++ b/R/classes.R @@ -1323,6 +1323,28 @@ giottoPolygon = setClass( ) +setClass('packedGiottoPolygon', + contains = c('nameData'), + + slots = c( + spatVector = 'ANY', + spatVectorCentroids = 'ANY', + overlaps = 'ANY' + ), + prototype = list( + spatVector = NULL, + spatVectorCentroids = NULL, + overlaps = NULL + )) + + +setMethod("show", signature(object='packedGiottoPolygon'), + function(object) { + print(paste("This is a", class(object), "object. Use 'Giotto::unwrap()' to unpack it")) + } +) + + ## giottoPoints class #### @@ -1356,6 +1378,29 @@ giottoPoints <- setClass( ) + +setClass('packedGiottoPoints', + + slots = c( + feat_type = 'ANY', + spatVector = 'ANY', + networks = 'ANY' + ), + prototype = list( + feat_type = NULL, + spatVector = NULL, + networks = NULL + )) + + +setMethod("show", signature(object='packedGiottoPoints'), + function(object) { + print(paste("This is a", class(object), "object. Use 'Giotto::unwrap()' to unpack it")) + } +) + + + ## featureNetwork class #### diff --git a/R/generics.R b/R/generics.R index 1e74b553f..9420c807a 100644 --- a/R/generics.R +++ b/R/generics.R @@ -68,6 +68,101 @@ setMethod('dim', signature('metaData'), function(x) dim(x@metaDT)) +# wrap() generic #### + +#' @title Wrap giotto terra pointer information +#' @name wrap-generic +#' @description Extension of wrap methods from terra for Giotto's terra-based S4 +#' objects. Allows pointer information to be packaged into memory so that it can +#' be passed over a connection (e.g. nodes on a computer cluster) +#' @param x giottoPolygon or giottoPoints +NULL + + +#' @describeIn wrap-generic Wrap giottoPolygon +#' @importMethodsFrom terra wrap +#' @export +setMethod('wrap', signature(x = 'giottoPolygon'), + function(x) { + pgp = new('packedGiottoPolygon') + pgp@name = x@name + pgp@spatVector = terra::wrap(x@spatVector) + if(!is.null(x@spatVectorCentroids)) { + pgp@spatVectorCentroids = terra::wrap(x@spatVectorCentroids) + } + if(!is.null(x@overlaps)) { + pgp@overlaps = lapply(x@overlaps, function(sv) { + if(inherits(sv, 'SpatVector')) { + terra::wrap(sv) + } else { + sv + } + }) + } + return(pgp) + } +) + + + +#' @describeIn wrap-generic Wrap giottoPoints +#' @importMethodsFrom terra wrap +#' @export +setMethod('wrap', signature(x = 'giottoPoints'), + function(x) { + pgp = new('packedGiottoPoints') + pgp@feat_type = x@feat_type + pgp@spatVector = terra::unwrap(x@spatVector) + pgp@networks = x@networks + return(pgp) + } +) + + + +#' @describeIn wrap-generic Unwrap giottoPolygon +#' @importMethodsFrom terra unwrap +#' @export +setMethod('unwrap', signature(x = 'packedGiottoPolygon'), + function(x) { + gp = new('giottoPolygon') + gp@name = x@name + gp@spatVector = terra::unwrap(x@spatVector) + if(!is.null(x@spatVectorCentroids)) { + gp@spatVectorCentroids = terra::unwrap(x@spatVectorCentroids) + } + if(!is.null(x@overlaps)) { + gp@overlaps = lapply(x@overlaps, function(sv) { + if(inherits(sv, 'PackedSpatVector')) { + terra::unwrap(sv) + } else { + sv + } + }) + } + return(gp) + } +) + + + +#' @describeIn wrap-generic Unwrap giottoPolygon +#' @importMethodsFrom terra unwrap +#' @export +setMethod('unwrap', signature(x = 'packedGiottoPoints'), + function(x) { + gp = new('giottoPoints') + gp@feat_type = x@feat_type + gp@spatVector = terra::unwrap(x@spatVector) + gp@networks = x@networks + return(gp) + } +) + + + + + # rbind() generic #### diff --git a/man/wrap-generic.Rd b/man/wrap-generic.Rd new file mode 100644 index 000000000..be5f9d00a --- /dev/null +++ b/man/wrap-generic.Rd @@ -0,0 +1,37 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/generics.R +\name{wrap-generic} +\alias{wrap-generic} +\alias{wrap,giottoPolygon-method} +\alias{wrap,giottoPoints-method} +\alias{unwrap,packedGiottoPolygon-method} +\alias{unwrap,packedGiottoPoints-method} +\title{Wrap giotto terra pointer information} +\usage{ +\S4method{wrap}{giottoPolygon}(x) + +\S4method{wrap}{giottoPoints}(x) + +\S4method{unwrap}{packedGiottoPolygon}(x) + +\S4method{unwrap}{packedGiottoPoints}(x) +} +\arguments{ +\item{x}{giottoPolygon or giottoPoints} +} +\description{ +Extension of wrap methods from terra for Giotto's terra-based S4 +objects. Allows pointer information to be packaged into memory so that it can +be passed over a connection (e.g. nodes on a computer cluster) +} +\section{Functions}{ +\itemize{ +\item \code{wrap(giottoPolygon)}: Wrap giottoPolygon + +\item \code{wrap(giottoPoints)}: Wrap giottoPoints + +\item \code{unwrap(packedGiottoPolygon)}: Unwrap giottoPolygon + +\item \code{unwrap(packedGiottoPoints)}: Unwrap giottoPolygon + +}} From 36f2a15adbf96babbfd9cc9d61c75990de92b8a2 Mon Sep 17 00:00:00 2001 From: jiajic <72078254+jiajic@users.noreply.github.com> Date: Thu, 12 Jan 2023 17:13:38 -0500 Subject: [PATCH 086/129] Update NEWS.md --- NEWS.md | 1 + 1 file changed, 1 insertion(+) diff --git a/NEWS.md b/NEWS.md index c5426703f..2ea039cfe 100644 --- a/NEWS.md +++ b/NEWS.md @@ -6,6 +6,7 @@ ## Added - New `gefToGiotto()` interoperability function to convert gef object from Stereo-seq to giotto - New `giottoToAnnData()` interoperability function to convert giotto object to squidpy flavor anndata .h5ad file(s) +- New `wrap()` and `unwrap()` generics for `giottoPoints` and `giottoPolygons` - Add missing `create_nn_net_obj()` internal constructor function for S4 `nnNetObj` - New `createGiottoMerscopeObject()` convenience function - Add packages `exactextractr` and `sf` to "suggests" packages From 626867c487bcd1961db41d353ab322cb5798a00c Mon Sep 17 00:00:00 2001 From: irzamsarfraz Date: Thu, 12 Jan 2023 17:14:06 -0500 Subject: [PATCH 087/129] Fixed minor issues in GiottoToSP --- R/interoperability.R | 94 +++++++++++++++++--------------- man/giottoToSpatialExperiment.Rd | 5 +- 2 files changed, 54 insertions(+), 45 deletions(-) diff --git a/R/interoperability.R b/R/interoperability.R index b8820b029..c46e37cd1 100644 --- a/R/interoperability.R +++ b/R/interoperability.R @@ -1100,6 +1100,8 @@ seuratToGiotto = function(sobject, #' Utility function to convert a Giotto object to a SpatialExperiment object. #' #' @param giottoObj Input Giotto object to convert to a SpatialExperiment object. +#' @param verbose A boolean value specifying if progress messages should be displayed +#' or not. Default \code{TRUE}. #' #' @return A SpatialExperiment object that contains data from the input Giotto object. #' @examples @@ -1107,7 +1109,7 @@ seuratToGiotto = function(sobject, #' giottoToSpatialExperiment(mini_gobject) #' #' @export -giottoToSpatialExperiment <- function(giottoObj){ +giottoToSpatialExperiment <- function(giottoObj, verbose = TRUE){ # Load required packages # package_check(pkg_name = "SummarizedExperiment", repository = 'Bioc') # SP should load this? @@ -1124,10 +1126,10 @@ giottoToSpatialExperiment <- function(giottoObj){ # Iterate over spatial units spatialUnits <- unique(giottoExpr$spat_unit) # a function to get spat units? for(su in seq(spatialUnits)){ - message("Processing spatial unit: '", spatialUnits[su], "'") + if(verbose) message("Processing spatial unit: '", spatialUnits[su], "'") # Check if expression matrices exist in input object if(!is.null(giottoExpr)){ - message("Copying expression matrix: '", giottoExpr[1]$name, "' for spatial unit: '", spatialUnits[su], "'") + if(verbose) message("Copying expression matrix: '", giottoExpr[1]$name, "' for spatial unit: '", spatialUnits[su], "'") exprMat <- get_expression_values( gobject = giottoObj, spat_unit = spatialUnits[su], @@ -1151,7 +1153,7 @@ giottoToSpatialExperiment <- function(giottoObj){ # Copying remaining expression matrices if they exist if(nrow(giottoExpr[spat_unit == spatialUnits[su]]) > 0){ for(i in seq(nrow(giottoExpr))){ - message("Copying expression matrix: '", giottoExpr[i]$name, "' for spatial unit: '", spatialUnits[su], "'") + if(verbose) message("Copying expression matrix: '", giottoExpr[i]$name, "' for spatial unit: '", spatialUnits[su], "'") # SPE does not have specific slots for different units, instead joining multiple unit names to identify them SummarizedExperiment::assay( spe, @@ -1170,19 +1172,19 @@ giottoToSpatialExperiment <- function(giottoObj){ # Cell Metadata to ColData pData <- pDataDT(gobject = giottoObj, spat_unit = spatialUnits[su]) if(nrow(pData) > 0){ - message("Copying phenotype data for spatial unit: '", spatialUnits[su], "'") + if(verbose) message("Copying phenotype data for spatial unit: '", spatialUnits[su], "'") SummarizedExperiment::colData(spe) <- S4Vectors::DataFrame(pData, row.names = pData$cell_ID) } else{ - message("No phenotype data found in input Giotto object") + if(verbose) message("No phenotype data found in input Giotto object") } # Feature Metadata to RowData fData <- fDataDT(gobject = giottoObj, spat_unit = spatialUnits[su]) if(nrow(fData) > 0){ - message("Copying feature metadata for spatial unit: '", spatialUnits[su], "'") + if(verbose) message("Copying feature metadata for spatial unit: '", spatialUnits[su], "'") SummarizedExperiment::rowData(spe) <- fData } else{ - message("No feature metadata found in input Giotto object") + if(verbose) message("No feature metadata found in input Giotto object") } # Spatial Locations to Spatial Coordinates @@ -1190,16 +1192,16 @@ giottoToSpatialExperiment <- function(giottoObj){ spat_unit = spatialUnits[su], output = "data.table") if(!is.null(spatialLocs)){ - message("Copying spatial locations for spatial unit: '", spatialUnits[su], "'") + if(verbose) message("Copying spatial locations for spatial unit: '", spatialUnits[su], "'") SpatialExperiment::spatialCoords(spe) <- data.matrix(spatialLocs[, 1:2]) } else{ - message("No spatial locations found in the input Giotto object") + if(verbose) message("No spatial locations found in the input Giotto object") } # DimReductions giottoReductions <- list_dim_reductions(gobject = giottoObj, spat_unit = spatialUnits[su]) if(!is.null(giottoReductions)){ - message("Copying reduced dimensions for spatial unit: '", spatialUnits[su], "'") + if(verbose) message("Copying reduced dimensions for spatial unit: '", spatialUnits[su], "'") for(i in seq(nrow(giottoReductions))){ SingleCellExperiment::reducedDim(spe, giottoReductions[i]$name) <- get_dimReduction( gobject = giottoObj, @@ -1211,14 +1213,14 @@ giottoToSpatialExperiment <- function(giottoObj){ output = "data.table") } } else{ - message("No reduced dimensions found in the input Giotto object") + if(verbose) message("No reduced dimensions found in the input Giotto object") } # NN Graph giottoNearestNetworks <- list_nearest_networks(gobject = giottoObj, spat_unit = spatialUnits[su]) if(!is.null(giottoNearestNetworks)){ - message("Copying nearest networks for spatial unit: '", spatialUnits[su], "'") + if(verbose) message("Copying nearest networks for spatial unit: '", spatialUnits[su], "'") for(i in seq(nrow(giottoNearestNetworks))){ nn_network <- get_NearestNetwork( gobject = giottoObj, @@ -1237,13 +1239,13 @@ giottoToSpatialExperiment <- function(giottoObj){ ) } } else{ - message("No nearest networks found in the input Giotto object") + if(verbose) message("No nearest networks found in the input Giotto object") } # Spatial Networks giottoSpatialNetworks <- list_spatial_networks(gobject = giottoObj, spat_unit = spatialUnits[su]) if(!is.null(giottoSpatialNetworks)){ - message("Copying spatial networks for spatial unit: '", spatialUnits[su], "'") + if(verbose) message("Copying spatial networks for spatial unit: '", spatialUnits[su], "'") for(i in seq(nrow(giottoSpatialNetworks))){ sp_network <- get_spatialNetwork( gobject = giottoObj, @@ -1261,37 +1263,41 @@ giottoToSpatialExperiment <- function(giottoObj){ ) } } else{ - message("No spatial networks found in the input Giotto object") + if(verbose) message("No spatial networks found in the input Giotto object") } - # SpatialImages - are these for each spatial unit? - PENDING George Updates - # giottoImages <- list_images(gobject = giottoObj) - # if(!is.null(giottoImages)){ - # message("Copying spatial images") - # for(i in seq(nrow(giottoImages))){ - # img <- get_giottoImage( - # gobject = giottoObj, - # image_type = giottoImages[i]$img_type, - # name = giottoImages[i]$name) - # - # if(!is.null(img@file_path)){ - # spe <- SpatialExperiment::addImg(spe, - # sample_id = "sample01", #TODO? different samples get appended to cell_ids - # image_id = img@name, - # imageSource = img@file_path, - # scaleFactor = NA_real_, - # load = TRUE) - # } - # else{ - # message("\t - Skipping image with NULL file path") - # } - # S4Vectors::metadata(spe)[[img@name]] <- img - # } - # } else{ - # message("No spatial images found in the input Giotto object") - # } - - message("") + # SpatialImages + giottoImages <- list_images(gobject = giottoObj) + if(!is.null(giottoImages)){ + for(i in seq(nrow(giottoImages))){ + + img <- get_giottoImage( + gobject = giottoObj, + image_type = giottoImages[i]$img_type, + name = giottoImages[i]$name) + + if(!is.null(img@file_path)){ + + if(verbose) message("Copying spatial image: ", img@name) + + spe <- SpatialExperiment::addImg(spe, + sample_id = spe$sample_id[i], + image_id = img@name, + imageSource = img@file_path, + scaleFactor = mean(img@scale_factor), + load = TRUE) + } + else{ + if(verbose) message("\t - Skipping image with NULL file path: ", img@name) + } + S4Vectors::metadata(spe)[[img@name]] <- img + } + } else{ + if(verbose) message("No spatial images found in the input Giotto object") + } + + if(verbose) message("") + # Add spe for current spatial unit to speList speList[[su]] <- spe } diff --git a/man/giottoToSpatialExperiment.Rd b/man/giottoToSpatialExperiment.Rd index ff390c190..79d3eda4c 100644 --- a/man/giottoToSpatialExperiment.Rd +++ b/man/giottoToSpatialExperiment.Rd @@ -4,10 +4,13 @@ \alias{giottoToSpatialExperiment} \title{Utility function to convert a Giotto object to a SpatialExperiment object.} \usage{ -giottoToSpatialExperiment(giottoObj) +giottoToSpatialExperiment(giottoObj, verbose = TRUE) } \arguments{ \item{giottoObj}{Input Giotto object to convert to a SpatialExperiment object.} + +\item{verbose}{A boolean value specifying if progress messages should be displayed +or not. Default \code{TRUE}.} } \value{ A SpatialExperiment object that contains data from the input Giotto object. From 0cae89b81c01f0edefad686bb7317caa3efa3b93 Mon Sep 17 00:00:00 2001 From: jiajic <72078254+jiajic@users.noreply.github.com> Date: Thu, 12 Jan 2023 17:39:34 -0500 Subject: [PATCH 088/129] Make loadGiotto() giottoImage reconnection optional --- R/general_help.R | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/R/general_help.R b/R/general_help.R index ffa52fb29..167be126d 100644 --- a/R/general_help.R +++ b/R/general_help.R @@ -799,6 +799,7 @@ saveGiotto = function(gobject, #' @description Saves a Giotto object to a specific folder structure #' @param path_to_folder path to folder where Giotto object was stored with \code{\link{saveGiotto}} #' @param load_params additional parameters for loading or reading giotto object +#' @param reconnect_giottoImage (default = TRUE) whether to attempt reconnection of magick based image objects #' @param python_path (optional) manually set your python path #' @param verbose be verbose #' @return Giotto object @@ -811,6 +812,7 @@ saveGiotto = function(gobject, #' @export loadGiotto = function(path_to_folder, load_params = list(), + reconnect_giottoImage = TRUE, python_path = NULL, verbose = TRUE) { @@ -938,8 +940,10 @@ loadGiotto = function(path_to_folder, } } - if(list_images(gobject)[img_type == 'image', .N] > 0) { - gobject = reconnectGiottoImage(gobject, reconnect_type = 'image') + if(isTRUE(reconnect_giottoImage)) { + if(list_images(gobject)[img_type == 'image', .N] > 0) { + gobject = reconnectGiottoImage(gobject, reconnect_type = 'image') + } } From 1cc3ddfd7951ffb84bef2e7ea7fe97da1ca089ab Mon Sep 17 00:00:00 2001 From: irzamsarfraz Date: Thu, 12 Jan 2023 18:28:42 -0500 Subject: [PATCH 089/129] Added image conversion in spToGiotto --- R/interoperability.R | 73 +++++++++++++++++++++++--------- man/spatialExperimentToGiotto.Rd | 22 ++++++++-- 2 files changed, 73 insertions(+), 22 deletions(-) diff --git a/R/interoperability.R b/R/interoperability.R index c46e37cd1..8a5d83a3e 100644 --- a/R/interoperability.R +++ b/R/interoperability.R @@ -1093,8 +1093,6 @@ seuratToGiotto = function(sobject, } - - ## SpatialExperiment object #### #' Utility function to convert a Giotto object to a SpatialExperiment object. @@ -1309,50 +1307,69 @@ giottoToSpatialExperiment <- function(giottoObj, verbose = TRUE){ #' Utility function to convert a SpatialExperiment object to a Giotto object #' -#' @param spe Input SpatialExperiment object to convert to a Giotto object -#' -#' @return Output Giotto object +#' @param spe Input SpatialExperiment object to convert to a Giotto object. +#' @param nn_network Specify the name of the nearest neighbour network(s) +#' in the input SpatialExperiment object. Default \code{NULL} will use +#' all existing networks. +#' @param sp_network Specify the name of the spatial network(s) in the input +#' SpatialExperiment object. Default \code{NULL} will use all existing +#' networks. +#' @param verbose A boolean value specifying if progress messages should +#' be displayed or not. Default \code{TRUE}. +#' @return Giotto object #' @examples #' library(SpatialExperiment) #' example(read10xVisium, echo = FALSE) #' spatialExperimentToGiotto(spe) #' @export -spatialExperimentToGiotto <- function(spe, nn_network = NULL, sp_network = NULL){ - # save exp matrices +spatialExperimentToGiotto <- function(spe, + nn_network = NULL, + sp_network = NULL, + verbose = TRUE){ + + # Create Giotto object with first matrix exprMats <- assays(spe) exprMatsNames <- assayNames(spe) firstMatrix <- exprMats[[1]] + #check unique colnames if(length(unique(colnames(firstMatrix))) != length(colnames(firstMatrix))){ colnames(firstMatrix) <- make.names(colnames(firstMatrix), unique = TRUE) } - suppressWarnings(giottoObj <- createGiottoObject(expression = firstMatrix), - classes = c("message", "warning")) + + if(verbose) message("Creating Giotto object with ", exprMatsNames[1], " matrix") + suppressWarnings(suppressMessages(giottoObj <- createGiottoObject(expression = firstMatrix))) exprMats[[1]] <- NULL - #rest of assays # how to figure out spat unit? + exprMatsNames <- exprMatsNames[-1] + + # Copying remaining matrices if(length(exprMats) > 0){ for(i in seq(exprMats)){ + if(verbose) message("Copying expression matrix: ", exprMatsNames[i]) giottoObj <- set_expression_values(gobject = giottoObj, name = exprMatsNames[i], values = exprMats[[i]]) } } - # save coldata + # Phenotype Data pData <- colData(spe) if(nrow(pData) > 0){ + if(verbose) message("Copying phenotype data") giottoObj <- Giotto::addCellMetadata(gobject = giottoObj, new_metadata = as.data.table(pData)) } - # save rowdata + # Feature Metadata fData <- rowData(spe) if(nrow(fData) > 0){ + if(verbose) message("Copying feature metadata") giottoObj <- Giotto::addFeatMetadata(gobject = giottoObj, new_metadata = as.data.table(fData)) } - # save reducedDims + # Reduced Dimensions redDims <- reducedDims(spe) redDimsNames <- reducedDimNames(spe) if(length(redDims) > 0){ for(i in seq(length(redDims))){ + if(verbose) message("Copying reduced dimensions") dimRedObj <- Giotto:::create_dimObject(name = redDimsNames[i], coordinates = redDims[[i]], reduction_method = redDimsNames[i]) @@ -1360,24 +1377,39 @@ spatialExperimentToGiotto <- function(spe, nn_network = NULL, sp_network = NULL) } } - # sp coordinates + # Spatial Locations spatialLocs <- spatialCoords(spe) if(ncol(spatialLocs) > 0){ + if(verbose) message("Copying spatial locations") spatialLocsDT <- data.table(sdimx = spatialLocs[, 1], sdimy = spatialLocs[, 2], cell_ID = rownames(spatialLocs)) giottoObj <- Giotto:::set_spatial_locations(gobject = giottoObj, spatlocs = cbind(spatialLocsDT, cell_ID = colnames(spe))) } - # TODO - # images - # giottoObj <- Giotto::addGiottoImage() + # Spatial Images + spatialImages <- imgData(spe) + if(nrow(spatialImages) > 0){ + for(i in seq(nrow(spatialImages))){ + if(verbose) message("Copying spatial images") + spImg <- getImg(spe, + spatialImages[i, "sample_id"], + spatialImages[i, "image_id"]) + mObject <- magick::image_read(as.raster(spImg)) + giottoImage <- Giotto:::createGiottoImage(gobject = giottoObj, + mg_object = mObject, + scale_factor = spatialImages[i, "scaleFactor"]) + giottoObj <- addGiottoImage(gobject = giottoObj, + images = list(giottoImage)) + + } + } - # TODO - # networks + # Networks networks <- colPairs(spe) # Spatial Networks if(!is.null(sp_network)){ if(sp_network %in% names(networks)){ for(i in seq(sp_network)){ + if(verbose) message("Copying spatial networks") spatNetObj <- Giotto:::create_spat_net_obj( networkDT = as.data.table(networks[[sp_network[i]]])) giottoObj <- Giotto:::set_spatialNetwork(gobject = giottoObj, @@ -1392,6 +1424,7 @@ spatialExperimentToGiotto <- function(spe, nn_network = NULL, sp_network = NULL) if(!is.null(nn_network)){ if(nn_network %in% names(networks)){ for(i in seq(nn_network)){ + if(verbose) message("Copying nearest neighbour networks") giottoObj <- Giotto:::set_NearestNetwork(gobject = giottoObj, nn_network = networks[[nn_network[i]]], network_name = nn_network[i]) @@ -1400,8 +1433,10 @@ spatialExperimentToGiotto <- function(spe, nn_network = NULL, sp_network = NULL) } } + # if not specified, storing remaining as NN if(length(networks) > 0){ for(i in seq(networks)){ + if(verbose) message("Copying additional networks") giottoObj <- Giotto:::set_NearestNetwork(gobject = giottoObj, nn_network = networks[[i]], network_name = names(networks)[i]) diff --git a/man/spatialExperimentToGiotto.Rd b/man/spatialExperimentToGiotto.Rd index 8284e6a09..7960db7c8 100644 --- a/man/spatialExperimentToGiotto.Rd +++ b/man/spatialExperimentToGiotto.Rd @@ -4,13 +4,29 @@ \alias{spatialExperimentToGiotto} \title{Utility function to convert a SpatialExperiment object to a Giotto object} \usage{ -spatialExperimentToGiotto(spe, nn_network = NULL, sp_network = NULL) +spatialExperimentToGiotto( + spe, + nn_network = NULL, + sp_network = NULL, + verbose = TRUE +) } \arguments{ -\item{spe}{Input SpatialExperiment object to convert to a Giotto object} +\item{spe}{Input SpatialExperiment object to convert to a Giotto object.} + +\item{nn_network}{Specify the name of the nearest neighbour network(s) +in the input SpatialExperiment object. Default \code{NULL} will use +all existing networks.} + +\item{sp_network}{Specify the name of the spatial network(s) in the input +SpatialExperiment object. Default \code{NULL} will use all existing +networks.} + +\item{verbose}{A boolean value specifying if progress messages should +be displayed or not. Default \code{TRUE}.} } \value{ -Output Giotto object +Giotto object } \description{ Utility function to convert a SpatialExperiment object to a Giotto object From c4fe3c507fb4c63c061bc7557c3cb07cf7ad3d45 Mon Sep 17 00:00:00 2001 From: jiajic <72078254+jiajic@users.noreply.github.com> Date: Fri, 13 Jan 2023 10:33:21 -0500 Subject: [PATCH 090/129] fix typo in wrap generic --- R/generics.R | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/R/generics.R b/R/generics.R index 9420c807a..3a4d8575b 100644 --- a/R/generics.R +++ b/R/generics.R @@ -112,7 +112,7 @@ setMethod('wrap', signature(x = 'giottoPoints'), function(x) { pgp = new('packedGiottoPoints') pgp@feat_type = x@feat_type - pgp@spatVector = terra::unwrap(x@spatVector) + pgp@spatVector = terra::wrap(x@spatVector) pgp@networks = x@networks return(pgp) } From 603917313b2d855f2c3378d0ccb1ae829a30f4a1 Mon Sep 17 00:00:00 2001 From: jiajic <72078254+jiajic@users.noreply.github.com> Date: Fri, 13 Jan 2023 12:45:19 -0500 Subject: [PATCH 091/129] Add wrap method for giotto Also edit slot names for packed objects Conscious decision not to inherit from giottoPolygon, giottoPoints, and giotto in order to avoid method inheritance for the packed objects. The packed objects should be unpacked first and then used normally. --- NAMESPACE | 1 + NEWS.md | 2 +- R/classes.R | 102 ++++++++++++++++++++++++++++++++++++-------- R/generics.R | 52 +++++++++++++++++----- man/gefToGiotto.Rd | 26 +++++++++++ man/loadGiotto.Rd | 3 ++ man/wrap-generic.Rd | 10 +++++ 7 files changed, 168 insertions(+), 28 deletions(-) create mode 100644 man/gefToGiotto.Rd diff --git a/NAMESPACE b/NAMESPACE index cde0877fb..f445a5c00 100644 --- a/NAMESPACE +++ b/NAMESPACE @@ -164,6 +164,7 @@ export(findMastMarkers_one_vs_all) export(findNetworkNeighbors) export(findScranMarkers) export(findScranMarkers_one_vs_all) +export(gefToGiotto) export(get10Xmatrix) export(get10Xmatrix_h5) export(getBalancedSpatCoexpressionFeats) diff --git a/NEWS.md b/NEWS.md index 2ea039cfe..cd22558d2 100644 --- a/NEWS.md +++ b/NEWS.md @@ -6,7 +6,7 @@ ## Added - New `gefToGiotto()` interoperability function to convert gef object from Stereo-seq to giotto - New `giottoToAnnData()` interoperability function to convert giotto object to squidpy flavor anndata .h5ad file(s) -- New `wrap()` and `unwrap()` generics for `giottoPoints` and `giottoPolygons` +- New `wrap()` and `unwrap()` generics for `giotto`, `giottoPoints`, and `giottoPolygons` - Add missing `create_nn_net_obj()` internal constructor function for S4 `nnNetObj` - New `createGiottoMerscopeObject()` convenience function - Add packages `exactextractr` and `sf` to "suggests" packages diff --git a/R/classes.R b/R/classes.R index 5468fed32..7688dab99 100644 --- a/R/classes.R +++ b/R/classes.R @@ -369,6 +369,7 @@ setClass('spatFeatData', ##### * Definition #### # Giotto class +# ! Any slot modifications should also be reflected in packedGiotto class ! #' @title S4 giotto Class #' @description Framework of giotto object to store and work with spatial expression data @@ -499,7 +500,70 @@ setMethod( +# for use with wrap() generic +# not intended to be used until after unwrapped to giotto class +# does not inherit giotto to avoid any method inheritance +setClass( + "packedGiotto", + slots = c( + packed_spatial_info = "ANY", + packed_feat_info = "ANY", + expression = "nullOrList", + expression_feat = "ANY", + spatial_locs = "ANY", + cell_metadata = "ANY", + feat_metadata = "ANY", + cell_ID = "ANY", + feat_ID = "ANY", + spatial_network = "ANY", + spatial_grid = "ANY", + spatial_enrichment = "ANY", + dimension_reduction = 'ANY', + nn_network = "ANY", + images = "ANY", + largeImages = "ANY", + parameters = "ANY", + instructions = "ANY", + offset_file = "ANY", + OS_platform = "ANY", + join_info = "ANY", + multiomics = "ANY" + + ), + + prototype = list( + packed_spatial_info = NULL, + packed_feat_info = NULL, + + expression = NULL, + expression_feat = NULL, + spatial_locs = NULL, + cell_metadata = NULL, + feat_metadata = NULL, + cell_ID = NULL, + feat_ID = NULL, + spatial_network = NULL, + spatial_grid = NULL, + spatial_enrichment = NULL, + dimension_reduction = NULL, + nn_network = NULL, + images = NULL, + largeImages = NULL, + parameters = NULL, + instructions = NULL, + offset_file = NULL, + OS_platform = NULL, + join_info = NULL, + multiomics = NULL + ) +) + +setMethod("show", signature(object='packedGiotto'), + function(object) { + print(paste("This is a", class(object), "object. Use 'Giotto::unwrap()' to unpack it")) + } +) @@ -1323,18 +1387,19 @@ giottoPolygon = setClass( ) +# for use with wrap() generic setClass('packedGiottoPolygon', contains = c('nameData'), slots = c( - spatVector = 'ANY', - spatVectorCentroids = 'ANY', - overlaps = 'ANY' + packed_spatVector = 'ANY', + packed_spatVectorCentroids = 'ANY', + packed_overlaps = 'ANY' ), prototype = list( - spatVector = NULL, - spatVectorCentroids = NULL, - overlaps = NULL + packed_spatVector = NULL, + packed_spatVectorCentroids = NULL, + packed_overlaps = NULL )) @@ -1379,18 +1444,21 @@ giottoPoints <- setClass( -setClass('packedGiottoPoints', +# for use with wrap() generic +setClass( + 'packedGiottoPoints', - slots = c( - feat_type = 'ANY', - spatVector = 'ANY', - networks = 'ANY' - ), - prototype = list( - feat_type = NULL, - spatVector = NULL, - networks = NULL - )) + slots = c( + feat_type = 'character', + packed_spatVector = 'ANY', + networks = 'ANY' + ), + prototype = list( + feat_type = NA_character_, + packed_spatVector = NULL, + networks = NULL + ) +) setMethod("show", signature(object='packedGiottoPoints'), diff --git a/R/generics.R b/R/generics.R index 3a4d8575b..d96f832a5 100644 --- a/R/generics.R +++ b/R/generics.R @@ -86,12 +86,12 @@ setMethod('wrap', signature(x = 'giottoPolygon'), function(x) { pgp = new('packedGiottoPolygon') pgp@name = x@name - pgp@spatVector = terra::wrap(x@spatVector) + pgp@packed_spatVector = terra::wrap(x@spatVector) if(!is.null(x@spatVectorCentroids)) { - pgp@spatVectorCentroids = terra::wrap(x@spatVectorCentroids) + pgp@packed_spatVectorCentroids = terra::wrap(x@spatVectorCentroids) } if(!is.null(x@overlaps)) { - pgp@overlaps = lapply(x@overlaps, function(sv) { + pgp@packed_overlaps = lapply(x@overlaps, function(sv) { if(inherits(sv, 'SpatVector')) { terra::wrap(sv) } else { @@ -104,6 +104,22 @@ setMethod('wrap', signature(x = 'giottoPolygon'), ) +#' @describeIn wrap-generic Wrap giotto +#' @importMethodsFrom terra wrap +#' @export +setMethod('wrap', signature(x = 'giotto'), + function(x) { + pg = new('packedGiotto') + g_slots = slotNames('giotto') + g_slots = g_slots[!g_slots %in% c('spatial_info', 'feat_info')] + for(g_slot in g_slots) { + slot(pg, g_slot) = slot(x, g_slot) + } + pg@packed_spatial_info = lapply(x@spatial_info, wrap) + pg@packed_feat_info = lapply(x@feat_info, wrap) + return(pg) + }) + #' @describeIn wrap-generic Wrap giottoPoints #' @importMethodsFrom terra wrap @@ -112,7 +128,7 @@ setMethod('wrap', signature(x = 'giottoPoints'), function(x) { pgp = new('packedGiottoPoints') pgp@feat_type = x@feat_type - pgp@spatVector = terra::wrap(x@spatVector) + pgp@packed_spatVector = terra::wrap(x@spatVector) pgp@networks = x@networks return(pgp) } @@ -127,12 +143,12 @@ setMethod('unwrap', signature(x = 'packedGiottoPolygon'), function(x) { gp = new('giottoPolygon') gp@name = x@name - gp@spatVector = terra::unwrap(x@spatVector) - if(!is.null(x@spatVectorCentroids)) { - gp@spatVectorCentroids = terra::unwrap(x@spatVectorCentroids) + gp@spatVector = terra::unwrap(x@packed_spatVector) + if(!is.null(x@packed_spatVectorCentroids)) { + gp@spatVectorCentroids = terra::unwrap(x@packed_spatVectorCentroids) } - if(!is.null(x@overlaps)) { - gp@overlaps = lapply(x@overlaps, function(sv) { + if(length(x@packed_overlaps) > 0) { + gp@overlaps = lapply(x@packed_overlaps, function(sv) { if(inherits(sv, 'PackedSpatVector')) { terra::unwrap(sv) } else { @@ -153,13 +169,29 @@ setMethod('unwrap', signature(x = 'packedGiottoPoints'), function(x) { gp = new('giottoPoints') gp@feat_type = x@feat_type - gp@spatVector = terra::unwrap(x@spatVector) + gp@spatVector = terra::unwrap(x@packed_spatVector) gp@networks = x@networks return(gp) } ) +#' @describeIn wrap-generic Unwrap giotto +#' @importMethodsFrom terra unwrap +#' @export +setMethod('unwrap', signature(x = 'packedGiotto'), + function(x) { + gobj = new('giotto') + g_slots = slotNames('giotto') + g_slots = g_slots[!g_slots %in% c('spatial_info', 'feat_info')] + for(g_slot in g_slots) { + slot(gobj, g_slot) = slot(x, g_slot) + } + gobj@spatial_info = lapply(x@packed_spatial_info, unwrap) + gobj@feat_info = lapply(x@packed_feat_info, unwrap) + return(gobj) + }) + diff --git a/man/gefToGiotto.Rd b/man/gefToGiotto.Rd new file mode 100644 index 000000000..fe6659f17 --- /dev/null +++ b/man/gefToGiotto.Rd @@ -0,0 +1,26 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/interoperability.R +\name{gefToGiotto} +\alias{gefToGiotto} +\title{Convert gef to Giotto} +\usage{ +gefToGiotto(gef_file, bin_size = "bin100", verbose = TRUE) +} +\arguments{ +\item{gef_file}{path to .gef file} + +\item{bin_size}{bin size to select from .gef file} + +\item{verbose}{be verbose} +} +\description{ +Converts .gef file (output stereo-seq pipeline) into +giotto subcellular object +} +\details{ +Function in beta. Converts .gef object to Giotto object. + +There are six possible choices for bin_size: 1, 10, 20, 50, 100, 200. + +See SAW pipeline for additional information about the gef file. +} diff --git a/man/loadGiotto.Rd b/man/loadGiotto.Rd index c426d553b..79f189e9b 100644 --- a/man/loadGiotto.Rd +++ b/man/loadGiotto.Rd @@ -7,6 +7,7 @@ loadGiotto( path_to_folder, load_params = list(), + reconnect_giottoImage = TRUE, python_path = NULL, verbose = TRUE ) @@ -16,6 +17,8 @@ loadGiotto( \item{load_params}{additional parameters for loading or reading giotto object} +\item{reconnect_giottoImage}{(default = TRUE) whether to attempt reconnection of magick based image objects} + \item{python_path}{(optional) manually set your python path} \item{verbose}{be verbose} diff --git a/man/wrap-generic.Rd b/man/wrap-generic.Rd index be5f9d00a..50cbe8245 100644 --- a/man/wrap-generic.Rd +++ b/man/wrap-generic.Rd @@ -3,18 +3,24 @@ \name{wrap-generic} \alias{wrap-generic} \alias{wrap,giottoPolygon-method} +\alias{wrap,giotto-method} \alias{wrap,giottoPoints-method} \alias{unwrap,packedGiottoPolygon-method} \alias{unwrap,packedGiottoPoints-method} +\alias{unwrap,packedGiotto-method} \title{Wrap giotto terra pointer information} \usage{ \S4method{wrap}{giottoPolygon}(x) +\S4method{wrap}{giotto}(x) + \S4method{wrap}{giottoPoints}(x) \S4method{unwrap}{packedGiottoPolygon}(x) \S4method{unwrap}{packedGiottoPoints}(x) + +\S4method{unwrap}{packedGiotto}(x) } \arguments{ \item{x}{giottoPolygon or giottoPoints} @@ -28,10 +34,14 @@ be passed over a connection (e.g. nodes on a computer cluster) \itemize{ \item \code{wrap(giottoPolygon)}: Wrap giottoPolygon +\item \code{wrap(giotto)}: Wrap giotto + \item \code{wrap(giottoPoints)}: Wrap giottoPoints \item \code{unwrap(packedGiottoPolygon)}: Unwrap giottoPolygon \item \code{unwrap(packedGiottoPoints)}: Unwrap giottoPolygon +\item \code{unwrap(packedGiotto)}: Unwrap giotto + }} From 0d923458dda1143ce6c8470782ae4e8f4eb78fb7 Mon Sep 17 00:00:00 2001 From: jiajic <72078254+jiajic@users.noreply.github.com> Date: Fri, 13 Jan 2023 14:11:36 -0500 Subject: [PATCH 092/129] Update R-CMD-check.yaml --- .github/workflows/R-CMD-check.yaml | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/.github/workflows/R-CMD-check.yaml b/.github/workflows/R-CMD-check.yaml index 7161691ad..2df60a5ac 100644 --- a/.github/workflows/R-CMD-check.yaml +++ b/.github/workflows/R-CMD-check.yaml @@ -3,11 +3,13 @@ on: push: branches: - - 'ci-unittest' + - 'ci-unittest' - 'suite' # run workflow on push to branch + - 'suite_dev' pull_request: branches: - 'suite' + - 'suite_dev' name: R-CMD-check @@ -36,9 +38,9 @@ jobs: - name: Remove vignettes dir run: rm -rf 'vignettes/' shell: bash - + # checkout repo for workflow access - - uses: actions/checkout@v2 + - uses: actions/checkout@v2 # setup R - uses: r-lib/actions/setup-r@v2 @@ -46,7 +48,7 @@ jobs: r-version: ${{ matrix.config.r }} http-user-agent: ${{ matrix.config.http-user-agent }} use-public-rspm: true - + # setup dependencies - uses: r-lib/actions/setup-r-dependencies@v2 env: @@ -61,7 +63,7 @@ jobs: with: upload-snapshots: true error-on: '"error"' # workflow errors on error only, can change to include warnings - + # show testthat output for ease of access - name: Show testthat output if: always() From 453c8a599a330989f9ff74d63fd582b15f38f30e Mon Sep 17 00:00:00 2001 From: irzamsarfraz Date: Fri, 13 Jan 2023 17:47:24 -0500 Subject: [PATCH 093/129] Removing Giotto reference from internal code --- R/interoperability.R | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/R/interoperability.R b/R/interoperability.R index 8a5d83a3e..aef56f676 100644 --- a/R/interoperability.R +++ b/R/interoperability.R @@ -1354,14 +1354,14 @@ spatialExperimentToGiotto <- function(spe, pData <- colData(spe) if(nrow(pData) > 0){ if(verbose) message("Copying phenotype data") - giottoObj <- Giotto::addCellMetadata(gobject = giottoObj, new_metadata = as.data.table(pData)) + giottoObj <- addCellMetadata(gobject = giottoObj, new_metadata = as.data.table(pData)) } # Feature Metadata fData <- rowData(spe) if(nrow(fData) > 0){ if(verbose) message("Copying feature metadata") - giottoObj <- Giotto::addFeatMetadata(gobject = giottoObj, new_metadata = as.data.table(fData)) + giottoObj <- addFeatMetadata(gobject = giottoObj, new_metadata = as.data.table(fData)) } # Reduced Dimensions @@ -1370,10 +1370,10 @@ spatialExperimentToGiotto <- function(spe, if(length(redDims) > 0){ for(i in seq(length(redDims))){ if(verbose) message("Copying reduced dimensions") - dimRedObj <- Giotto:::create_dimObject(name = redDimsNames[i], + dimRedObj <- create_dimObject(name = redDimsNames[i], coordinates = redDims[[i]], reduction_method = redDimsNames[i]) - giottoObj <- Giotto:::set_dimReduction(gobject = giottoObj, dimObject = dimRedObj) + giottoObj <- set_dimReduction(gobject = giottoObj, dimObject = dimRedObj) } } @@ -1382,7 +1382,7 @@ spatialExperimentToGiotto <- function(spe, if(ncol(spatialLocs) > 0){ if(verbose) message("Copying spatial locations") spatialLocsDT <- data.table(sdimx = spatialLocs[, 1], sdimy = spatialLocs[, 2], cell_ID = rownames(spatialLocs)) - giottoObj <- Giotto:::set_spatial_locations(gobject = giottoObj, spatlocs = cbind(spatialLocsDT, cell_ID = colnames(spe))) + giottoObj <- set_spatial_locations(gobject = giottoObj, spatlocs = cbind(spatialLocsDT, cell_ID = colnames(spe))) } # Spatial Images @@ -1394,7 +1394,7 @@ spatialExperimentToGiotto <- function(spe, spatialImages[i, "sample_id"], spatialImages[i, "image_id"]) mObject <- magick::image_read(as.raster(spImg)) - giottoImage <- Giotto:::createGiottoImage(gobject = giottoObj, + giottoImage <- createGiottoImage(gobject = giottoObj, mg_object = mObject, scale_factor = spatialImages[i, "scaleFactor"]) giottoObj <- addGiottoImage(gobject = giottoObj, @@ -1410,9 +1410,9 @@ spatialExperimentToGiotto <- function(spe, if(sp_network %in% names(networks)){ for(i in seq(sp_network)){ if(verbose) message("Copying spatial networks") - spatNetObj <- Giotto:::create_spat_net_obj( + spatNetObj <- create_spat_net_obj( networkDT = as.data.table(networks[[sp_network[i]]])) - giottoObj <- Giotto:::set_spatialNetwork(gobject = giottoObj, + giottoObj <- set_spatialNetwork(gobject = giottoObj, spatial_network = spatNetObj, name = sp_network[i]) networks[[sp_network[i]]] <- NULL @@ -1425,7 +1425,7 @@ spatialExperimentToGiotto <- function(spe, if(nn_network %in% names(networks)){ for(i in seq(nn_network)){ if(verbose) message("Copying nearest neighbour networks") - giottoObj <- Giotto:::set_NearestNetwork(gobject = giottoObj, + giottoObj <- set_NearestNetwork(gobject = giottoObj, nn_network = networks[[nn_network[i]]], network_name = nn_network[i]) networks[[nn_network[i]]] <- NULL @@ -1437,7 +1437,7 @@ spatialExperimentToGiotto <- function(spe, if(length(networks) > 0){ for(i in seq(networks)){ if(verbose) message("Copying additional networks") - giottoObj <- Giotto:::set_NearestNetwork(gobject = giottoObj, + giottoObj <- set_NearestNetwork(gobject = giottoObj, nn_network = networks[[i]], network_name = names(networks)[i]) } From 8507bada0c007356258975a0b78fafa2ac8e5d8a Mon Sep 17 00:00:00 2001 From: jiajic <72078254+jiajic@users.noreply.github.com> Date: Sat, 14 Jan 2023 20:14:04 -0500 Subject: [PATCH 094/129] Small edit for to generics.R for R cmd check --- R/generics.R | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/R/generics.R b/R/generics.R index d96f832a5..51f25a4eb 100644 --- a/R/generics.R +++ b/R/generics.R @@ -110,7 +110,7 @@ setMethod('wrap', signature(x = 'giottoPolygon'), setMethod('wrap', signature(x = 'giotto'), function(x) { pg = new('packedGiotto') - g_slots = slotNames('giotto') + g_slots = methods::slotNames('giotto') g_slots = g_slots[!g_slots %in% c('spatial_info', 'feat_info')] for(g_slot in g_slots) { slot(pg, g_slot) = slot(x, g_slot) @@ -182,7 +182,7 @@ setMethod('unwrap', signature(x = 'packedGiottoPoints'), setMethod('unwrap', signature(x = 'packedGiotto'), function(x) { gobj = new('giotto') - g_slots = slotNames('giotto') + g_slots = methods::slotNames('giotto') g_slots = g_slots[!g_slots %in% c('spatial_info', 'feat_info')] for(g_slot in g_slots) { slot(gobj, g_slot) = slot(x, g_slot) From 0d1ff7d6df688814a0da2ab2704a74441665d0bd Mon Sep 17 00:00:00 2001 From: jiajic <72078254+jiajic@users.noreply.github.com> Date: Sun, 15 Jan 2023 04:34:19 -0500 Subject: [PATCH 095/129] Virtual classes and DT object updates - Set superclasses in classes.R as virtual so that these incomplete classes cannot be instantiated. - Fixed issue in `loadGiotto()` where data.tables lose overallocation when loaded from disk --- NEWS.md | 2 + R/classes.R | 17 ++++-- R/general_help.R | 137 +++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 153 insertions(+), 3 deletions(-) diff --git a/NEWS.md b/NEWS.md index cd22558d2..4a0290f75 100644 --- a/NEWS.md +++ b/NEWS.md @@ -2,6 +2,7 @@ ## Breaking Changes - Removed support for deprecated nesting in `@nn_network` slot +- Set incomplete classes in classes.R as virtual to prevent their instantiation ## Added - New `gefToGiotto()` interoperability function to convert gef object from Stereo-seq to giotto @@ -25,6 +26,7 @@ - Deprecate `polygon_feat_names` param in favor of `z_indices` in `readPolygonFilesVizgenHDF5()` - Optimize `readPolygonFilesVizgen()` - Fix bug in `loadGiotto()` that prevents proper parsing of filenames when spat_unit or feat_type contains '_' characters +- Fix `loadGiotto()` loss of over-allocation for data.tables-based objects after loading from disk # Giotto Suite 3.1.0 (2202-12-01) diff --git a/R/classes.R b/R/classes.R index 7688dab99..e4add4486 100644 --- a/R/classes.R +++ b/R/classes.R @@ -31,11 +31,12 @@ setOldClass('data.table') -# SUPERCLASSES #### +# VIRTUAL CLASSES #### # ** nameData Class #### #' setClass('nameData', + contains = 'VIRTUAL', slots = list(name = 'character'), prototype = prototype(name = NA_character_)) @@ -43,6 +44,7 @@ setClass('nameData', #' Basic class for classes with expression information #' setClass('exprData', + contains = 'VIRTUAL', slots = list(exprMat = 'ANY'), prototype = prototype(exprMat = NULL)) @@ -56,6 +58,7 @@ setClass('exprData', #' data.table when interacting with some basic generic operators for data #' retreival and setting. setClass('coordDataDT', + contains = 'VIRTUAL', slots = list(coordinates = 'data.table'), prototype = prototype(coordinates = data.table::data.table())) @@ -81,6 +84,7 @@ setMethod('initialize', 'coordDataDT', #' information in a data.table and should work similarly to data.table when interacting #' with some basic generic operators for data retrieval and setting setClass('metaData', + contains = 'VIRTUAL', slots = list(metaDT = 'data.table', col_desc = 'character'), prototype = prototype(metaDT = data.table::data.table(), @@ -100,6 +104,7 @@ setMethod('initialize', 'metaData', # ** enrData #### setClass('enrData', + contains = 'VIRTUAL', slots = list(method = 'character', enrichDT = 'nullOrDatatable'), prototype = prototype(method = NA_character_, @@ -119,6 +124,7 @@ setMethod('initialize', 'enrData', # ** nnData #### setClass('nnData', + contains = 'VIRTUAL', slots = list(nn_type = 'character', igraph = 'ANY'), prototype = prototype(nn_type = NA_character_, @@ -127,6 +133,7 @@ setClass('nnData', # ** spatNetData #### setClass('spatNetData', + contains = 'VIRTUAL', slots = list(method = 'character', parameters = 'ANY', outputObj = 'ANY', @@ -156,6 +163,7 @@ setMethod('initialize', 'spatNetData', # ** spatGridData #### setClass('spatGridData', + contains = 'VIRTUAL', slots = list(method = 'character', parameters = 'ANY', gridDT = 'nullOrDatatable'), @@ -185,6 +193,7 @@ setMethod('initialize', 'spatGridData', #' is Giotto's method of mapping this aggregated information back to the original #' z layers that were used in its generation. setClass('provData', + contains = 'VIRTUAL', slots = list(provenance = 'ANY'), prototype = prototype(provenance = NULL)) @@ -200,7 +209,7 @@ setClass('provData', #' there is a nesting structure that first nests by spatial unit. #' setClass('spatData', - contains = c('provData'), + contains = c('provData', 'VIRTUAL'), slots = list(spat_unit = 'character'), # not allowed to be NULL prototype = prototype(spat_unit = NA_character_)) @@ -218,6 +227,7 @@ setClass('spatData', #' and then by feature type #' setClass('featData', + contains = 'VIRTUAL', slots = list(feat_type = 'character'), # not allowed to be NULL prototype = prototype(feat_type = NA_character_)) @@ -231,6 +241,7 @@ setClass('featData', #' use the misc slot to hold additional information specific to each method. #' Information may be stored within as S3 structures. setClass('miscData', + contains = 'VIRTUAL', slots = list(misc = 'ANY'), prototype = prototype(misc = NULL)) @@ -246,7 +257,7 @@ setClass('miscData', # ** spatFeatData #### #' Superclass for classes that contain both spatial and feature data setClass('spatFeatData', - contains = c('spatData', 'featData')) + contains = c('spatData', 'featData', 'VIRTUAL')) diff --git a/R/general_help.R b/R/general_help.R index 167be126d..a62c8520c 100644 --- a/R/general_help.R +++ b/R/general_help.R @@ -110,6 +110,137 @@ dt_to_matrix <- function(x) { } +#' @title Over-allocation for giotto DT-based info +#' @description Finds DT based objects, overallocates the data.tables, then sets +#' the objects back in the giotto object +#' @param gobject giotto object +#' @keywords internal +giotto_alloc_dt_slots = function(gobject) { + + # data.table vars + spat_unit = feat_type = name = NULL + + # metadata + avail_cm = list_cell_metadata(gobject) + if(!is.null(avail_cm)) { + for(cm_i in seq(nrow(avail_cm))) { + cm = get_cell_metadata(gobject = gobject, + spat_unit = avail_cm[cm_i, spat_unit], + feat_type = avail_cm[cm_i, feat_type], + output = 'cellMetaObj', + copy_obj = FALSE) + if(!is.null(cm[])) { + cm[] = data.table::setalloccol(cm[]) + gobject = set_cell_metadata(gobject = gobject, + metadata = cm, + set_defaults = FALSE, + verbose = FALSE) + } + } + } + + avail_fm = list_feat_metadata(gobject) + if(!is.null(avail_fm)) { + for(fm_i in seq(nrow(avail_fm))) { + fm = get_feature_metadata(gobject = gobject, + spat_unit = avail_fm[fm_i, spat_unit], + feat_type = avail_fm[fm_i, feat_type], + output = 'featMetaObj', + copy_obj = FALSE) + if(!is.null(fm[])) { + fm[] = data.table::setalloccol(fm[]) + gobject = set_feature_metadata(gobject = gobject, + metadata = fm, + set_defaults = FALSE, + verbose = FALSE) + } + } + } + + # spatlocs + avail_sl = list_spatial_locations(gobject) + if(!is.null(avail_sl)) { + for(sl_i in seq(nrow(avail_sl))) { + sl = get_spatial_locations(gobject = gobject, + spat_unit = avail_sl[sl_i, spat_unit], + spat_loc_name = avail_sl[sl_i, name], + output = 'spatLocsObj', + copy_obj = FALSE) + if(!is.null(sl[])) { + sl[] = data.table::setalloccol(sl[]) + gobject = set_spatial_locations(gobject = gobject, + spatlocs = sl, + set_defaults = FALSE, + verbose = FALSE) + } + } + } + + # spatial enrichment + avail_se = list_spatial_enrichments(gobject) + if(!is.null(avail_se)) { + for(se_i in seq(nrow(avail_se))) { + se = get_spatial_enrichment(gobject = gobject, + spat_unit = avail_se[se_i, spat_unit], + feat_type = avail_se[se_i, feat_type], + enrichm_name = avail_se[se_i, name], + output = 'spatEnrObj', + copy_obj = FALSE) + if(!is.null(se[])) { + se[] = data.table::setalloccol(se[]) + gobject = set_spatial_enrichment(gobject = gobject, + spatenrichment = se, + set_defaults = FALSE, + verbose = FALSE) + } + } + } + + # spatial network + avail_sn = list_spatial_networks(gobject) + if(!is.null(avail_sn)) { + for(sn_i in seq(nrow(avail_sn))) { + sn = get_spatialNetwork(gobject = gobject, + spat_unit = avail_sn[sn_i, spat_unit], + name = avail_sn[sn_i, name], + output = 'spatialNetworkObj') + if(!is.null(slot(sn, 'networkDT_before_filter'))) { + slot(sn, 'networkDT_before_filter') = data.table::setalloccol(slot(sn, 'networkDT_before_filter')) + } + if(!is.null(sn[])) { + sn[] = data.table::setalloccol(sn[]) + gobject = set_spatialNetwork(gobject = gobject, + spatial_network = sn, + verbose = FALSE, + set_defaults = FALSE) + } + } + } + + # spatial grid + avail_sg = list_spatial_grids(gobject) + if(!is.null(avail_sg)) { + for(sg_i in seq(nrow(avail_sg))) { + sg = get_spatialGrid(gobject = gobject, + spat_unit = avail_sg[sg_i, spat_unit], + feat_type = avail_sg[sg_i, feat_type], + name = avail_sg[sg_i, feat_type], + return_grid_Obj = TRUE) + if(!is.null(sg[])) { + sg[] = data.table::setalloccol(sg[]) + gobject = set_spatialGrid(gobject = gobject, + spatial_grid = sg, + verbose = FALSE, + set_defaults = FALSE) + } + } + } + return(gobject) +} + + + + #' @title mygini_fun #' @description calculate gini coefficient #' @keywords internal @@ -947,11 +1078,17 @@ loadGiotto = function(path_to_folder, } + ## 5. Update python path identified_python_path = set_giotto_python_path(python_path = python_path) gobject = changeGiottoInstructions(gobject = gobject, params = c('python_path'), new_values = c(identified_python_path)) + ## 6. overallocate for data.tables + # (data.tables when read from disk have a truelength of 0) + gobject = giotto_alloc_dt_slots(gobject) + + return(gobject) } From f0ad0f0d0a651407a9945ca669e442b76e18f098 Mon Sep 17 00:00:00 2001 From: jiajic <72078254+jiajic@users.noreply.github.com> Date: Mon, 16 Jan 2023 15:50:20 -0500 Subject: [PATCH 096/129] seurat conversion update 1 --- R/interoperability.R | 257 +++++++++++++++++++++++++++---------------- 1 file changed, 165 insertions(+), 92 deletions(-) diff --git a/R/interoperability.R b/R/interoperability.R index 64af69e49..d020a32b2 100644 --- a/R/interoperability.R +++ b/R/interoperability.R @@ -15,31 +15,31 @@ #' #' There are six possible choices for bin_size: 1, 10, 20, 50, 100, 200. #' -#' See SAW pipeline for additional information about the gef file. +#' See SAW pipeline for additional information about the gef file. #' @export -gefToGiotto = function(gef_file, bin_size = 'bin100', verbose = TRUE){ - +gefToGiotto = function(gef_file, bin_size = 'bin100', verbose = TRUE){ + # data.table vars genes = NULL - + # package check package_check(pkg_name = 'rhdf5', repository = 'Bioc') if(!file.exists(gef_file)) stop('File path to .gef file does not exist') - + # check if proper bin_size is selected bin_size_options = c('bin1', 'bin10', 'bin20', 'bin50', 'bin100', 'bin200') - if(!(bin_size %in% bin_size_options)) stop('Please select valid bin size, + if(!(bin_size %in% bin_size_options)) stop('Please select valid bin size, see details for choices.') - + # step 1: read expression and gene data from gef file geneExpData = rhdf5::h5read(file = gef_file, name = 'geneExp') exprDT = data.table::as.data.table(geneExpData[[bin_size]][['expression']]) geneDT = data.table::as.data.table(geneExpData[[bin_size]][['gene']]) if(isTRUE(verbose)) wrap_msg('read in .gef file') - + # step 2: combine gene information from the geneDT to the exprDT exprDT[, genes := rep(x = geneDT$gene, geneDT$count)] - + # step 3: bin coordinates according to selected bin_size bin_size_int = as.integer(gsub("[^0-9.-]", "", bin_size)) #TODO: update bin_shift for other shapes, not just rect_vertices @@ -52,23 +52,23 @@ gefToGiotto = function(gef_file, bin_size = 'bin100', verbose = TRUE){ tx_data = exprDT[,.(genes, x, y, count)] tx_data[, c('x', 'y') := list(x+bin_shift, y+bin_shift)] if(isTRUE(verbose)) wrap_msg('shift and bin coordinates') - + # step 4: create rectangular polygons (grid) starting from the bin centroids - x = polyStamp(stamp_dt = rectVertices(dims = c(x = (bin_size_int - 1), + x = polyStamp(stamp_dt = rectVertices(dims = c(x = (bin_size_int - 1), y = (bin_size_int - 1))), spatlocs = bincoord[,.(cell_ID, sdimx, sdimy)]) pg = createGiottoPolygonsFromDfr(x) if(isTRUE(verbose)) wrap_msg('create polygon stamp') - + # step 5: create giotto subcellular object stereo = createGiottoObjectSubcellular( gpoints = list(rna = tx_data), gpolygons = list(cell = pg) ) - + stereo = addSpatialCentroidLocations(gobject = stereo) if(isTRUE(verbose)) wrap_msg('giotto subcellular object created') - + return(stereo) } @@ -771,56 +771,87 @@ giottoToAnnData <- function(gobject = NULL, #' @title Convert Giotto to Seurat #' @name giottoToSeurat -#' @description Converts Giotto object into a Seurat object -#' @param obj_use Giotto object +#' @description Converts Giotto object into a Seurat object. This functions extracts +#' specific sets of data belonging to specified spatial unit. +#' The default values are 'cell' and 'rna' respectively. +#' @param gobject Giotto object +#' @param obj_use Giotto object (deprecated, use gobject) +#' @param spat_unit spatial unit (e.g. 'cell') +#' @param feat_type feature type (e.g. 'rna' or 'protein') #' @param ... additional params to pass to \code{\link{get_spatial_locations}} #' @return Seurat object #' @export -giottoToSeurat <- function(obj_use = NULL, +giottoToSeurat <- function(gobject, + spat_unit = NULL, + obj_use = NULL, ...){ + # data.table vars + feat_type = name = dim_type = nn_type = NULL + + if(!is.null(obj_use)) { + warning('obj_use param is deprecated. Please use "gobject') + gobject = obj_use + } + + # set default spat_unit and feat_type to be extracted as a Seurat assay + spat_unit = set_default_spat_unit(gobject = gobject, + spat_unit = spat_unit) + # verify if optional package is installed package_check(pkg_name = "Seurat", repository = "CRAN") requireNamespace('Seurat') # check whether any raw data exist -- required for Seurat - raw_exist <- sapply(obj_use@expression_feat,function(x) - 'raw' %in% names(obj_use@expression[[x]])) - if (length(raw_exist) > 0){ - assays_all <- names(raw_exist[1]) - assays_all <- union(assays_all,obj_use@expression_feat) + avail_expr = list_expression(gobject = gobject, spat_unit = spat_unit) + raw_exist = avail_expr[, 'raw' %in% name, by = feat_type] + # raw_exist <- sapply(gobject@expression_feat,function(x) + # 'raw' %in% names(gobject@expression[[x]])) + if (nrow(raw_exist) > 0){ + assays_all = raw_exist[, feat_type] + # assays_all <- names(raw_exist[1]) + # assays_all <- union(assays_all,gobject@expression_feat) } else { stop("Raw count data not found. Required for Seurat object.") } # create Seurat object when at least one raw data is available - for (i in 1:length(assays_all)){ + for (i in seq_along(assays_all)){ assay_use <- assays_all[i] - expr_use <- obj_use@expression[[assay_use]] + expr_use = lapply(avail_expr[feat_type == assay_use, name], + function(x) { + get_expression_values(gobject = gobject, + spat_unit = spat_unit, + feat_type = assay_use, + values = x, + output = 'exprObj') + }) + # expr_use <- gobject@expression[[assay_use]] + names(expr_use) = unlist(lapply(expr_use, objName)) slot_use <- names(expr_use) if (i == 1){ - data_raw <- expr_use[['raw']] + data_raw <- expr_use[['raw']][] sobj <- Seurat::CreateSeuratObject(counts = data_raw, assay = assay_use) if ('normalized' %in% slot_use){ sobj <- Seurat::SetAssayData(sobj,slot = 'data', - new.data = expr_use[['normalized']], + new.data = expr_use[['normalized']][], assay = assay_use) } if ('scaled' %in% slot_use){ sobj <- Seurat::SetAssayData(sobj,slot = 'scale.data', - new.data = expr_use[['scaled']], + new.data = expr_use[['scaled']][], assay = assay_use) } } else { if ('raw' %in% slot_use){ - data_raw <- expr_use[['raw']] + data_raw <- expr_use[['raw']][] flag_raw <- 1 } else { flag_raw <- 0 } if ('normalized' %in% slot_use){ - data_norm <- expr_use[['normalized']] + data_norm <- expr_use[['normalized']][] flag_norm <- 1 } else { flag_norm <- 0 @@ -834,7 +865,7 @@ giottoToSeurat <- function(obj_use = NULL, } sobj[[assay_use]] <- assay_obj if ('scaled' %in% slot_use){ - data_scale <- expr_use[['scaled']] + data_scale <- expr_use[['scaled']][] sobj <- Seurat::SetAssayData(sobj,slot = "scale.data", new.data = data_scale, assay = assay_use) @@ -842,28 +873,107 @@ giottoToSeurat <- function(obj_use = NULL, } # add cell metadata - meta_cells <- data.table::setDF(get_cell_metadata(obj_use, - feat_type = assay_use, - output = 'data.table', - copy_obj = TRUE)) + meta_cells <- data.table::setDF( + get_cell_metadata( + gobject = gobject, + feat_type = assay_use, + output = 'data.table', + copy_obj = TRUE + ) + ) rownames(meta_cells) <- meta_cells$cell_ID meta_cells <- meta_cells[,-which(colnames(meta_cells) == 'cell_ID')] - colnames(meta_cells) <- paste0(assay_use,"_",colnames(meta_cells)) + if(ncol(meta_cells) > 0) { + colnames(meta_cells) <- paste0(assay_use,"_",colnames(meta_cells)) + } sobj <- Seurat::AddMetaData(sobj,metadata = meta_cells[Seurat::Cells(sobj),]) # add feature metadata - meta_genes <- data.table::setDF(get_feature_metadata(obj_use, - feat_type = assay_use, - output = 'data.table', - copy_obj = TRUE)) + meta_genes <- data.table::setDF( + get_feature_metadata( + gobject = gobject, + feat_type = assay_use, + output = 'data.table', + copy_obj = TRUE + ) + ) rownames(meta_genes) <- meta_genes$feat_ID sobj[[assay_use]]@meta.features <- cbind(sobj[[assay_use]]@meta.features,meta_genes) + + + # dim reduction + # note: Seurat requires assay name specification for each dim reduc + avail_dr = list_dim_reductions(gobject = gobject, spat_unit = spat_unit, feat_type = assay_use,) + if (nrow(avail_dr) > 0){ + dr_use = avail_dr[, dim_type] + # dr_use <- names(gobject@dimension_reduction[[1]]) + for (i in dr_use){ + dr_type = i + dr_obj <- get_dimReduction( + gobject = gobject, + output = 'dimObj', + spat_unit = spat_unit, + feat_type = assay_use, + reduction_method = dr_type # allow default dim red name + ) + emb_use <- dr_obj[][Seurat::Cells(sobj),] + if (sum(c('loadings','eigenvalues') %in% names(slot(dr_obj, 'misc'))) == 2){ + loadings_use <- slot(dr_obj, 'misc')$loadings + stdev_use <- slot(dr_obj, 'misc')$eigenvalues + sobj[[dr_type]] <- Seurat::CreateDimReducObject(embeddings = as.matrix(emb_use), + loadings = loadings_use, + key = dr_type, + stdev = stdev_use, + assay = assay_use) + } else { + sobj[[dr_type]] <- Seurat::CreateDimReducObject(embeddings = as.matrix(emb_use), + key = dr_type, + assay = assay_use) + } + } + } + + + + # network objects + # expression network + avail_nn = list_nearest_networks(gobject = gobject, spat_unit = spat_unit, feat_type = assay_use) + nn_all = avail_nn[, nn_type] + # nn_all <- names(gobject@nn_network) + if (nrow(avail_nn) > 0){ + for (i in nn_all){ + nn_use <- get_NearestNetwork( + gobject = gobject, + spat_unit = spat_unit, + feat_type = assay_use, + nn_network_to_use = i, + output = 'data.table' # allow default network name selection + ) + idx1 <- match(nn_use$from,Seurat::Cells(sobj)) + idx2 <- match(nn_use$to,Seurat::Cells(sobj)) + edge_weight <- nn_use$weight + nn_mtx <- Matrix::sparseMatrix(i = idx1,j = idx2,x = edge_weight,dims = c(ncol(sobj),ncol(sobj))) + rownames(nn_mtx) <- colnames(nn_mtx) <- Seurat::Cells(sobj) + nn_name <- paste0('expr_',i) + sobj[[nn_name]] <- Seurat::as.Graph(nn_mtx) + sobj[[nn_name]]@assay.used <- assay_use + } + } + } # spatial coordinates - loc_use <- as.data.frame(select_spatial_locations(gobject = obj_use,...)) + loc_use <- data.table::setDF( + get_spatial_locations( + gobject = gobject, + spat_unit = spat_unit, + output = 'data.table', + copy_obj = TRUE, + ... # allow setting of spat_loc_name through additional params + ) + ) rownames(loc_use) <- loc_use$cell_ID - sobj <- Seurat::AddMetaData(sobj,metadata = loc_use) + sobj <- Seurat::AddMetaData(sobj, metadata = loc_use) # add spatial coordinates as new dim reduct object loc_2 <- loc_use[,c('sdimx','sdimy')] colnames(loc_2) <- c('spatial_1','spatial_2') @@ -871,58 +981,15 @@ giottoToSeurat <- function(obj_use = NULL, assay = names(sobj@assays)[1], key = 'spatial_') - # dim reduction - # note: Seurat requires assay name specification for each dim reduc - if (!is.null(obj_use@dimension_reduction)){ - dr_use <- names(obj_use@dimension_reduction[[1]]) - for (i in dr_use){ - dr_name <- i - dr_obj <- get_dimReduction(gobject = obj_use, - output = 'dimObj', - reduction_method = dr_name, - name = dr_name) - emb_use <- slot(dr_obj, 'coordinates')[Seurat::Cells(sobj),] - if (sum(c('loadings','eigenvalues') %in% names(slot(dr_obj, 'misc'))) == 2){ - loadings_use <- slot(dr_obj, 'misc')$loadings - stdev_use <- slot(dr_obj, 'misc')$eigenvalues - sobj[[dr_name]] <- Seurat::CreateDimReducObject(embeddings = as.matrix(emb_use), - loadings = loadings_use, - key = dr_name, - stdev = stdev_use, - assay = names(sobj@assays)[1]) - } else { - sobj[[dr_name]] <- Seurat::CreateDimReducObject(embeddings = as.matrix(emb_use), - key = dr_name, - assay = names(sobj@assays)[1]) - } - } - } - # network objects - # expression network - nn_all <- names(obj_use@nn_network) - if (!is.null(nn_all)){ - for (i in nn_all){ - nn_use <- select_NearestNetwork(gobject = obj_use, - nn_network_to_use = i, - output = 'data.table', - network_name = names(obj_use@nn_network[[i]])) - idx1 <- match(nn_use$from,Seurat::Cells(sobj)) - idx2 <- match(nn_use$to,Seurat::Cells(sobj)) - edge_weight <- nn_use$weight - nn_mtx <- Matrix::sparseMatrix(i = idx1,j = idx2,x = edge_weight,dims = c(ncol(sobj),ncol(sobj))) - rownames(nn_mtx) <- colnames(nn_mtx) <- Seurat::Cells(sobj) - nn_name <- paste0('expr_',i) - sobj[[nn_name]] <- Seurat::as.Graph(nn_mtx) - sobj[[nn_name]]@assay.used <- names(sobj@assays)[1] - } - } # spatial network - sn_all <- names(obj_use@spatial_network) - if (!is.null(sn_all)){ + avail_sn = list_spatial_locations(gobject = gobject, spat_unit = spat_unit) + sn_all = avail_sn[, name] + # sn_all <- names(gobject@spatial_network) + if (nrow(sn_all) > 0){ for (i in sn_all){ - snt_use <- select_spatialNetwork(gobject = obj_use,name = i) + snt_use <- get_spatialNetwork(gobject = gobject, name = i) idx1 <- match(snt_use$from,Seurat::Cells(sobj)) idx2 <- match(snt_use$to,Seurat::Cells(sobj)) edge_weight <- snt_use$weight @@ -1148,9 +1215,15 @@ seuratToGiotto = function(sobject, gobject = createGiottoObject(exp, spatial_locs = spat_loc, dimension_reduction = dimReduc_list) - if (exists('normexp') == TRUE) { - gobject@expression$cell$rna$normalized = normexp - } + if (exists('normexp') == TRUE) { + exprObj = create_expr_obj(name = 'normalized', + exprMat = normexp, + spat_unit = 'cell', + feat_type = 'rna', + provenance = 'cell') + gobject = set_expression_values(gobject = gobject, values = exprObj, set_defaults = FALSE) + # gobject@expression$cell$rna$normalized = normexp + } gobject = addCellMetadata(gobject = gobject, new_metadata = cell_metadata) From a302a02c732695614d1764a2e9254dd3626b40b8 Mon Sep 17 00:00:00 2001 From: jiajic <72078254+jiajic@users.noreply.github.com> Date: Mon, 16 Jan 2023 17:26:16 -0500 Subject: [PATCH 097/129] seurat conversion update 2 - `giottoToSeurat()` successfully creates a seurat object. - `seuratToGiotto()` needs further testing --- R/interoperability.R | 69 +++++++++++++++++++++++++------------------- 1 file changed, 39 insertions(+), 30 deletions(-) diff --git a/R/interoperability.R b/R/interoperability.R index d020a32b2..ed4079248 100644 --- a/R/interoperability.R +++ b/R/interoperability.R @@ -777,7 +777,6 @@ giottoToAnnData <- function(gobject = NULL, #' @param gobject Giotto object #' @param obj_use Giotto object (deprecated, use gobject) #' @param spat_unit spatial unit (e.g. 'cell') -#' @param feat_type feature type (e.g. 'rna' or 'protein') #' @param ... additional params to pass to \code{\link{get_spatial_locations}} #' @return Seurat object #' @export @@ -840,7 +839,8 @@ giottoToSeurat <- function(gobject, } if ('scaled' %in% slot_use){ sobj <- Seurat::SetAssayData(sobj,slot = 'scale.data', - new.data = expr_use[['scaled']][], + # does not accept 'dgeMatrix' + new.data = as.matrix(expr_use[['scaled']][]), assay = assay_use) } } else { @@ -865,7 +865,7 @@ giottoToSeurat <- function(gobject, } sobj[[assay_use]] <- assay_obj if ('scaled' %in% slot_use){ - data_scale <- expr_use[['scaled']][] + data_scale <- as.matrix(expr_use[['scaled']][]) sobj <- Seurat::SetAssayData(sobj,slot = "scale.data", new.data = data_scale, assay = assay_use) @@ -876,6 +876,7 @@ giottoToSeurat <- function(gobject, meta_cells <- data.table::setDF( get_cell_metadata( gobject = gobject, + spat_unit = spat_unit, feat_type = assay_use, output = 'data.table', copy_obj = TRUE @@ -892,6 +893,7 @@ giottoToSeurat <- function(gobject, meta_genes <- data.table::setDF( get_feature_metadata( gobject = gobject, + spat_unit = spat_unit, feat_type = assay_use, output = 'data.table', copy_obj = TRUE @@ -905,29 +907,30 @@ giottoToSeurat <- function(gobject, # note: Seurat requires assay name specification for each dim reduc avail_dr = list_dim_reductions(gobject = gobject, spat_unit = spat_unit, feat_type = assay_use,) if (nrow(avail_dr) > 0){ - dr_use = avail_dr[, dim_type] - # dr_use <- names(gobject@dimension_reduction[[1]]) - for (i in dr_use){ - dr_type = i + dr_use = avail_dr[, name] + for (i in seq(nrow(avail_dr))){ + dr_name = avail_dr[i, name] + dr_type = avail_dr[i, dim_type] dr_obj <- get_dimReduction( gobject = gobject, output = 'dimObj', spat_unit = spat_unit, feat_type = assay_use, - reduction_method = dr_type # allow default dim red name + reduction_method = dr_type, + name = dr_name ) emb_use <- dr_obj[][Seurat::Cells(sobj),] if (sum(c('loadings','eigenvalues') %in% names(slot(dr_obj, 'misc'))) == 2){ loadings_use <- slot(dr_obj, 'misc')$loadings stdev_use <- slot(dr_obj, 'misc')$eigenvalues - sobj[[dr_type]] <- Seurat::CreateDimReducObject(embeddings = as.matrix(emb_use), + sobj[[dr_name]] <- Seurat::CreateDimReducObject(embeddings = as.matrix(emb_use), loadings = loadings_use, - key = dr_type, + key = paste0(dr_name, '_'), stdev = stdev_use, assay = assay_use) } else { - sobj[[dr_type]] <- Seurat::CreateDimReducObject(embeddings = as.matrix(emb_use), - key = dr_type, + sobj[[dr_name]] <- Seurat::CreateDimReducObject(embeddings = as.matrix(emb_use), + key = paste0(dr_name, '_'), assay = assay_use) } } @@ -938,25 +941,27 @@ giottoToSeurat <- function(gobject, # network objects # expression network avail_nn = list_nearest_networks(gobject = gobject, spat_unit = spat_unit, feat_type = assay_use) - nn_all = avail_nn[, nn_type] - # nn_all <- names(gobject@nn_network) if (nrow(avail_nn) > 0){ - for (i in nn_all){ + for (i in seq(nrow(avail_nn))){ + nn_name = avail_nn[i, name] + nn_type = avail_nn[i, nn_type] nn_use <- get_NearestNetwork( gobject = gobject, spat_unit = spat_unit, feat_type = assay_use, - nn_network_to_use = i, - output = 'data.table' # allow default network name selection + nn_network_to_use = nn_type, + network_name = nn_name, + output = 'data.table' ) idx1 <- match(nn_use$from,Seurat::Cells(sobj)) idx2 <- match(nn_use$to,Seurat::Cells(sobj)) edge_weight <- nn_use$weight nn_mtx <- Matrix::sparseMatrix(i = idx1,j = idx2,x = edge_weight,dims = c(ncol(sobj),ncol(sobj))) rownames(nn_mtx) <- colnames(nn_mtx) <- Seurat::Cells(sobj) - nn_name <- paste0('expr_',i) - sobj[[nn_name]] <- Seurat::as.Graph(nn_mtx) - sobj[[nn_name]]@assay.used <- assay_use + nn_name <- paste0('expr_',nn_name) + sGraph <- Seurat::as.Graph(nn_mtx) + sGraph@assay.used = assay_use + sobj[[nn_name]] = sGraph } } @@ -984,20 +989,23 @@ giottoToSeurat <- function(gobject, # spatial network - avail_sn = list_spatial_locations(gobject = gobject, spat_unit = spat_unit) - sn_all = avail_sn[, name] - # sn_all <- names(gobject@spatial_network) - if (nrow(sn_all) > 0){ + avail_sn = list_spatial_networks(gobject = gobject, spat_unit = spat_unit) + if (nrow(avail_sn) > 0){ + sn_all = avail_sn[, name] for (i in sn_all){ - snt_use <- get_spatialNetwork(gobject = gobject, name = i) + snt_use <- get_spatialNetwork(gobject = gobject, + spat_unit = spat_unit, + name = i, + output = 'networkDT') idx1 <- match(snt_use$from,Seurat::Cells(sobj)) idx2 <- match(snt_use$to,Seurat::Cells(sobj)) edge_weight <- snt_use$weight nn_mtx <- Matrix::sparseMatrix(i = idx1,j = idx2,x = edge_weight,dims = c(ncol(sobj),ncol(sobj))) rownames(nn_mtx) <- colnames(nn_mtx) <- Seurat::Cells(sobj) nn_name <- paste0('spatial_',i) - sobj[[nn_name]] <- Seurat::as.Graph(nn_mtx) - sobj[[nn_name]]@assay.used <- names(sobj@assays)[1] + spatGraph = Seurat::as.Graph(nn_mtx) + spatGraph@assay.used = names(sobj@assays)[1] + sobj[[nn_name]] <- spatGraph } } @@ -1128,7 +1136,7 @@ seuratToGiotto = function(sobject, package_check('Seurat') if(is.null(Seurat::GetAssayData(object = sobject, slot = "counts", assay = spatial_assay))) { - cat('No raw expression values are provided in spatial_assay\n') + wrap_msg('No raw expression values are provided in spatial_assay') return(sobject) } else { @@ -1138,8 +1146,8 @@ seuratToGiotto = function(sobject, normexp = Seurat::GetAssayData(object = sobject, slot = "counts", assay = 'SCT') } - if(!is.null(sobject@assays$Spatial@data)){ - normexp = Seurat::GetAssayData(object = sobject, slot = "data", assay = 'Spatial') + if(!is.null(slot(sobject, 'assays')[[spatial_assay]]@data)){ + normexp = Seurat::GetAssayData(object = sobject, slot = "data", assay = spatial_assay) } # Cell Metadata @@ -1177,6 +1185,7 @@ seuratToGiotto = function(sobject, spat_loc = NULL } else { + # !requires image objects! spat_coord = Seurat::GetTissueCoordinates(sobject) spat_coord = cbind(rownames(spat_coord), data.frame(spat_coord, row.names=NULL)) colnames(spat_coord) = c("cell_ID", "sdimy", "sdimx") From 275306833bc6b90b2a8c2a5fb9a223269792af50 Mon Sep 17 00:00:00 2001 From: jiajic <72078254+jiajic@users.noreply.github.com> Date: Tue, 17 Jan 2023 02:16:58 -0500 Subject: [PATCH 098/129] generics update --- NAMESPACE | 2 + R/generics.R | 176 +++++++++++++++++++++++++++++++++++ R/utilities.R | 18 +++- man/cells-generic.Rd | 25 +++++ man/degrees.Rd | 27 ++++++ man/giottoToSeurat.Rd | 12 ++- man/giotto_alloc_dt_slots.Rd | 16 ++++ man/plot-generic.Rd | 5 + man/spin-generic.Rd | 55 +++++++++++ 9 files changed, 332 insertions(+), 4 deletions(-) create mode 100644 man/cells-generic.Rd create mode 100644 man/degrees.Rd create mode 100644 man/giotto_alloc_dt_slots.Rd create mode 100644 man/spin-generic.Rd diff --git a/NAMESPACE b/NAMESPACE index f445a5c00..c2398800b 100644 --- a/NAMESPACE +++ b/NAMESPACE @@ -417,6 +417,7 @@ exportMethods(plot) exportMethods(prov) exportMethods(rbind2) exportMethods(spatUnit) +exportMethods(spin) exportMethods(unwrap) exportMethods(wrap) import(data.table) @@ -430,5 +431,6 @@ importFrom(methods,rbind2) importFrom(methods,show) importFrom(methods,slot) importFrom(methods,validObject) +importMethodsFrom(terra,spin) importMethodsFrom(terra,unwrap) importMethodsFrom(terra,wrap) diff --git a/R/generics.R b/R/generics.R index 51f25a4eb..d4c2b99de 100644 --- a/R/generics.R +++ b/R/generics.R @@ -3,6 +3,174 @@ # NOTE: initialize generics are in classes.R # +#' @title Cell and feature names +#' @name cells-generic +#' @description Get the cells and feature names of a giotto object or subobject +#' @param x an object +#' @param spat_unit (optional) specify which spatial unit +#' @param feat_type (optional) specify which feature type +#' @param ... additional parameters to pass +#' @include classes.R +#' @usage +#' cells(x, spat_unit, ...) +#' +#' features(x, feat_type, ...) +#' +#' ## Default S4 method for signatures: +#' 'giotto', 'exprObj', 'spatLocsObj', 'cellMetaObj', 'spatialNetworkObj' 'dimObj' +setGeneric('cells', function(x, spat_unit, ...) standardGeneric('cells')) +setGeneric('features', function(x, feat_type, ...) standardGeneric('features')) + + +setMethod('cells', signature(x = 'giotto', spat_unit = 'missing'), + function(x, ...) { + get_cell_id(gobject = x, ...) + }) +setMethod('cells', signature(x = 'giotto', spat_unit = 'character'), + function(x, spat_unit, ...) { + get_cell_id(gobject = x, spat_unit, ...) + }) +setMethod('cells', signature(x = c('exprObj'), spat_unit = 'missing'), + function(x, ...) { + colnames(x[]) + }) +setMethod('cells', signature(x = c('spatLocsObj'), spat_unit = 'missing'), + function(x, ...) { + x[][, cell_ID] + }) +setMethod('cells', signature(x = c('cellMetaObj'), spat_unit = 'missing'), + function(x, ...) { + x[][, cell_ID] + }) +setMethod('cells', signature(x = c('spatialNetworkObj'), spat_unit = 'missing'), + function(x, ...) { + unique(c(sn[][, from], sn[][, to])) + }) +setMethod('cells', signature(x = 'dimObj', spat_unit = 'missing'), + function(x, ...) { + rownames(x@coordinates) + }) + + +setMethod('features', signature(x = 'giotto', feat_type = 'missing'), + function(x, ...) { + get_feat_id(gobject = x, ...) + }) +setMethod('features', signature(x = 'giotto', feat_type = 'character'), + function(x, feat_type, ...) { + get_feat_id(gobject = x, feat_type, ...) + }) +setMethod('features', signature(x = 'exprObj', feat_type = 'missing'), + function(x, ...) { + rownames(x[]) + }) +# no features generic for dimObj + + + + + + + +# colnames and rownames generics #### +setMethod('colnames', signature(x = 'exprObj'), + function(x) { + colnames(x[]) + }) +setMethod('rownames', signature(x = 'exprObj'), + function(x) { + rownames(x[]) + }) + + + + +# spin() S4 generic #### + +#' @title Spin an object +#' @name spin-generic +#' @description Spin (rotate) an object spatially (limited to xy rotations) +#' @param x object +#' @param angle numeric. Angle of rotation in degrees +#' @param x0 numeric. x-coordinate of the center of rotation. Defaults to center x val if not given. +#' @param y0 numeric. y-coordinate of the center of rotation. Defaults to center y val if not given. +NULL + +#' @describeIn spin-generic Spin a giottoPolygon object +#' @importMethodsFrom terra spin +#' @export +setMethod('spin', signature(x = 'giottoPolygon'), + function(x, angle, x0 = NULL, y0 = NULL) { + if(is.null(x0)) x0 = terra::mean(terra::ext(x@spatVector))[1] + if(is.null(y0)) y0 = terra::mean(terra::ext(x@spatVector))[2] + x@spatVector = terra::spin(x = x@spatVector, + angle = angle, + x0 = x0, + y0 = y0) + if(!is.null(x@spatVectorCentroids)) { + x@spatVectorCentroids = terra::spin(x = x@spatVectorCentroids, + angle = angle, + x0 = x0, + y0 = y0) + } + if(!is.null(x@overlaps)) { + lapply(x@overlaps, function(overlap) { + if(inherits(overlap, 'SpatVector')) { + terra::spin(x = overlap, + angle = angle, + x0 = x0, + y0 = y0) + } else { + overlap + } + }) + } + return(x) + }) + +#' @describeIn spin-generic Spin a giottoPoints object +#' @importMethodsFrom terra spin +#' @export +setMethod('spin', signature(x = 'giottoPoints'), + function(x, angle, x0 = NULL, y0 = NULL) { + if(is.null(x0)) x0 = terra::mean(terra::ext(x@spatVector))[1] + if(is.null(y0)) y0 = terra::mean(terra::ext(x@spatVector))[2] + x@spatVector = terra::spin(x@spatVector) + return(x) + }) + +#' @describeIn spin-generic Spin a spatLocsObj +#' @importMethodsFrom terra spin +#' @param z0 spatLocsObj specific. Numeric. z-coordinate of the center of rotation. +#' Depending on if z data is present, defaults to either 0 or center z val if not given. +#' @param xy_angle spatLocsObj specific. xy plane rotation in degrees. +#' Overrides angle param +#' @param zy_angle spatLocsObj specific. zy plane rotation +#' @param xz_angle spatLocsObj specific. xz plane rotation +#' @export +setMethod('spin', signature(x = 'spatLocsObj'), + function(x, angle = NULL, x0 = NULL, y0 = NULL, z0 = NULL, + xy_angle = NULL, zy_angle = NULL, xz_angle = NULL) { + if(!is.null(angle)) xy_angle = angle + if(is.null(xy_angle)) xy_angle = 0 + if(is.null(zy_angle)) zy_angle = 0 + if(is.null(xz_angle)) xz_angle = 0 + angles = c(xy = xy_angle, zy = zy_angle, xz = xz_angle) + angles = radians(angles) + + if(is.null(x0)) x0 = mean(c(min(x[]$sdimx), max(x[]$sdimx))) + if(is.null(y0)) y0 = mean(c(min(x[]$sdimy), max(x[]$sdimy))) + if('sdimz' %in% colnames(x[])) { + if(is.null(z0)) z0 = mean(c(min(x[]$sdimz), max(x[]$sdimz))) + else z0 = 0 + } + x[] = rotate_spatial_locations(spatlocs = x[], + rotateradians = angles, + rcenter = c(x = x0, y = y0, z = z0)) + return(x) + }) + + #' @title Dimensions of giotto objects #' @name dims-generic @@ -311,6 +479,14 @@ setMethod('plot', signature(x = 'giottoPoints', y = 'missing'), function(x, }) +#' @describeIn plot-generic Plot a spatLocsObj +#' @export +setMethod('plot', signature(x = 'spatLocsObj', y = 'missing'), function(x, ...) { + plot(x = x[]$sdimx, y = x[]$sdimy, asp = 1, ...) +}) + + + # copy() S4 generic #### #' @title Copy an entire object #' @name copy-generic diff --git a/R/utilities.R b/R/utilities.R index d52dabe76..013a744fd 100644 --- a/R/utilities.R +++ b/R/utilities.R @@ -671,7 +671,23 @@ time_format = function(secs) { } } +# radians and degrees #### +#' @title Radian/degree conversions +#' @name degrees +#' @description Convert radians to degrees and vice versa +#' @param deg degrees +#' @param rad radians +#' @keywords internal +NULL +#' @describeIn degrees Degrees to radians +radians = function(deg) { + deg * pi / 180 +} - +#' @describeIn degrees Radians to degrees +#' @keywords internal +degrees = function(rad) { + rad * 180 / pi +} diff --git a/man/cells-generic.Rd b/man/cells-generic.Rd new file mode 100644 index 000000000..5e4145d22 --- /dev/null +++ b/man/cells-generic.Rd @@ -0,0 +1,25 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/generics.R +\name{cells-generic} +\alias{cells-generic} +\title{Cell and feature names} +\usage{ +cells(x, spat_unit, ...) + +features(x, feat_type, ...) + +## Default S4 method for signatures: +'giotto', 'exprObj', 'spatLocsObj', 'cellMetaObj', 'spatialNetworkObj' 'dimObj' +} +\arguments{ +\item{x}{an object} + +\item{spat_unit}{(optional) specify which spatial unit} + +\item{...}{additional parameters to pass} + +\item{feat_type}{(optional) specify which feature type} +} +\description{ +Get the cells and feature names of a giotto object or subobject +} diff --git a/man/degrees.Rd b/man/degrees.Rd new file mode 100644 index 000000000..4e95c6607 --- /dev/null +++ b/man/degrees.Rd @@ -0,0 +1,27 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/utilities.R +\name{degrees} +\alias{degrees} +\alias{radians} +\title{Radian/degree conversions} +\usage{ +radians(deg) + +degrees(rad) +} +\arguments{ +\item{deg}{degrees} + +\item{rad}{radians} +} +\description{ +Convert radians to degrees and vice versa +} +\section{Functions}{ +\itemize{ +\item \code{radians()}: Degrees to radians + +\item \code{degrees()}: Radians to degrees + +}} +\keyword{internal} diff --git a/man/giottoToSeurat.Rd b/man/giottoToSeurat.Rd index 2377df3e5..16184cc2e 100644 --- a/man/giottoToSeurat.Rd +++ b/man/giottoToSeurat.Rd @@ -4,10 +4,14 @@ \alias{giottoToSeurat} \title{Convert Giotto to Seurat} \usage{ -giottoToSeurat(obj_use = NULL, ...) +giottoToSeurat(gobject, spat_unit = NULL, obj_use = NULL, ...) } \arguments{ -\item{obj_use}{Giotto object} +\item{gobject}{Giotto object} + +\item{spat_unit}{spatial unit (e.g. 'cell')} + +\item{obj_use}{Giotto object (deprecated, use gobject)} \item{...}{additional params to pass to \code{\link{get_spatial_locations}}} } @@ -15,5 +19,7 @@ giottoToSeurat(obj_use = NULL, ...) Seurat object } \description{ -Converts Giotto object into a Seurat object +Converts Giotto object into a Seurat object. This functions extracts +specific sets of data belonging to specified spatial unit. +The default values are 'cell' and 'rna' respectively. } diff --git a/man/giotto_alloc_dt_slots.Rd b/man/giotto_alloc_dt_slots.Rd new file mode 100644 index 000000000..a1f95ff42 --- /dev/null +++ b/man/giotto_alloc_dt_slots.Rd @@ -0,0 +1,16 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/general_help.R +\name{giotto_alloc_dt_slots} +\alias{giotto_alloc_dt_slots} +\title{Over-allocation for giotto DT-based info} +\usage{ +giotto_alloc_dt_slots(gobject) +} +\arguments{ +\item{gobject}{giotto object} +} +\description{ +Finds DT based objects, overallocates the data.tables, then sets +the objects back in the giotto object +} +\keyword{internal} diff --git a/man/plot-generic.Rd b/man/plot-generic.Rd index 205560f4e..009776121 100644 --- a/man/plot-generic.Rd +++ b/man/plot-generic.Rd @@ -7,6 +7,7 @@ \alias{plot,giottoLargeImage,missing-method} \alias{plot,giottoPolygon,missing-method} \alias{plot,giottoPoints,missing-method} +\alias{plot,spatLocsObj,missing-method} \title{Preview a Giotto spatial object} \usage{ \S4method{plot}{giottoImage,missing}(x, y, ...) @@ -16,6 +17,8 @@ \S4method{plot}{giottoPolygon,missing}(x, y, point_size = 0.1, type = c("poly", "centroid"), ...) \S4method{plot}{giottoPoints,missing}(x, y, point_size = 0.1, feats = NULL, ...) + +\S4method{plot}{spatLocsObj,missing}(x, y, ...) } \arguments{ \item{x}{giotto image, giottoPolygon, or giottoPoints object} @@ -43,5 +46,7 @@ S4 generic for previewing Giotto's image and subcellular objects. \item \code{plot(x = giottoPoints, y = missing)}: \emph{terra}-based giottoPoint object. ... param passes to \code{\link[terra]{plot}} +\item \code{plot(x = spatLocsObj, y = missing)}: Plot a spatLocsObj + }} \concept{plot} diff --git a/man/spin-generic.Rd b/man/spin-generic.Rd new file mode 100644 index 000000000..4b2533599 --- /dev/null +++ b/man/spin-generic.Rd @@ -0,0 +1,55 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/generics.R +\name{spin-generic} +\alias{spin-generic} +\alias{spin,giottoPolygon-method} +\alias{spin,giottoPoints-method} +\alias{spin,spatLocsObj-method} +\title{Spin an object} +\usage{ +\S4method{spin}{giottoPolygon}(x, angle, x0 = NULL, y0 = NULL) + +\S4method{spin}{giottoPoints}(x, angle, x0 = NULL, y0 = NULL) + +\S4method{spin}{spatLocsObj}( + x, + angle = NULL, + x0 = NULL, + y0 = NULL, + z0 = NULL, + xy_angle = NULL, + zy_angle = NULL, + xz_angle = NULL +) +} +\arguments{ +\item{x}{object} + +\item{angle}{numeric. Angle of rotation in degrees} + +\item{x0}{numeric. x-coordinate of the center of rotation. Defaults to center x val if not given.} + +\item{y0}{numeric. y-coordinate of the center of rotation. Defaults to center y val if not given.} + +\item{z0}{spatLocsObj specific. Numeric. z-coordinate of the center of rotation. +Depending on if z data is present, defaults to either 0 or center z val if not given.} + +\item{xy_angle}{spatLocsObj specific. xy plane rotation in degrees. +Overrides angle param} + +\item{zy_angle}{spatLocsObj specific. zy plane rotation} + +\item{xz_angle}{spatLocsObj specific. xz plane rotation} +} +\description{ +Spin (rotate) an object spatially (limited to xy rotations) +} +\section{Functions}{ +\itemize{ +\item \code{spin(giottoPolygon)}: Spin a giottoPolygon object + +\item \code{spin(giottoPoints)}: Spin a giottoPoints object + +\item \code{spin(spatLocsObj)}: Spin a spatLocsObj + +}} From 1bed1ebe5de9ffde44177f7d00b86b35af6f61dd Mon Sep 17 00:00:00 2001 From: jiajic <72078254+jiajic@users.noreply.github.com> Date: Tue, 17 Jan 2023 15:07:16 -0500 Subject: [PATCH 099/129] generics update --- NEWS.md | 1 + R/general_help.R | 3 + R/generics.R | 78 ++++++++++++++------ R/utilities.R | 6 ++ man/{cells-generic.Rd => spatIDs-generic.Rd} | 12 +-- 5 files changed, 74 insertions(+), 26 deletions(-) rename man/{cells-generic.Rd => spatIDs-generic.Rd} (67%) diff --git a/NEWS.md b/NEWS.md index 4a0290f75..f8ae5b6c1 100644 --- a/NEWS.md +++ b/NEWS.md @@ -8,6 +8,7 @@ - New `gefToGiotto()` interoperability function to convert gef object from Stereo-seq to giotto - New `giottoToAnnData()` interoperability function to convert giotto object to squidpy flavor anndata .h5ad file(s) - New `wrap()` and `unwrap()` generics for `giotto`, `giottoPoints`, and `giottoPolygons` +- New `spatIDs()` and `featIDs()` generics - Add missing `create_nn_net_obj()` internal constructor function for S4 `nnNetObj` - New `createGiottoMerscopeObject()` convenience function - Add packages `exactextractr` and `sf` to "suggests" packages diff --git a/R/general_help.R b/R/general_help.R index a62c8520c..a523702c8 100644 --- a/R/general_help.R +++ b/R/general_help.R @@ -947,6 +947,9 @@ loadGiotto = function(path_to_folder, python_path = NULL, verbose = TRUE) { + # data.table vars + img_type = NULL + if(!file.exists(path_to_folder)) { stop('path_to_folder does not exist \n') } diff --git a/R/generics.R b/R/generics.R index d4c2b99de..58ef7254c 100644 --- a/R/generics.R +++ b/R/generics.R @@ -4,66 +4,75 @@ #' @title Cell and feature names -#' @name cells-generic +#' @name spatIDs-generic #' @description Get the cells and feature names of a giotto object or subobject +#' @aliases spatIDs featIDs #' @param x an object #' @param spat_unit (optional) specify which spatial unit #' @param feat_type (optional) specify which feature type #' @param ... additional parameters to pass #' @include classes.R #' @usage -#' cells(x, spat_unit, ...) +#' spatIDs(x, spat_unit, ...) #' -#' features(x, feat_type, ...) +#' featIDs(x, feat_type, ...) #' #' ## Default S4 method for signatures: -#' 'giotto', 'exprObj', 'spatLocsObj', 'cellMetaObj', 'spatialNetworkObj' 'dimObj' -setGeneric('cells', function(x, spat_unit, ...) standardGeneric('cells')) -setGeneric('features', function(x, feat_type, ...) standardGeneric('features')) +#' ## 'giotto', 'exprObj', 'spatLocsObj', 'cellMetaObj', 'spatialNetworkObj' 'dimObj' +setGeneric('spatIDs', function(x, spat_unit, ...) standardGeneric('spatIDs')) +setGeneric('featIDs', function(x, feat_type, ...) standardGeneric('featIDs')) -setMethod('cells', signature(x = 'giotto', spat_unit = 'missing'), +setMethod('spatIDs', signature(x = 'giotto', spat_unit = 'missing'), function(x, ...) { get_cell_id(gobject = x, ...) }) -setMethod('cells', signature(x = 'giotto', spat_unit = 'character'), +setMethod('spatIDs', signature(x = 'giotto', spat_unit = 'character'), function(x, spat_unit, ...) { get_cell_id(gobject = x, spat_unit, ...) }) -setMethod('cells', signature(x = c('exprObj'), spat_unit = 'missing'), +setMethod('spatIDs', signature(x = c('exprObj'), spat_unit = 'missing'), function(x, ...) { colnames(x[]) }) -setMethod('cells', signature(x = c('spatLocsObj'), spat_unit = 'missing'), +setMethod('spatIDs', signature(x = c('spatLocsObj'), spat_unit = 'missing'), function(x, ...) { - x[][, cell_ID] + x[]$cell_ID }) -setMethod('cells', signature(x = c('cellMetaObj'), spat_unit = 'missing'), +setMethod('spatIDs', signature(x = c('cellMetaObj'), spat_unit = 'missing'), function(x, ...) { - x[][, cell_ID] + x[]$cell_ID }) -setMethod('cells', signature(x = c('spatialNetworkObj'), spat_unit = 'missing'), +setMethod('spatIDs', signature(x = c('spatialNetworkObj'), spat_unit = 'missing'), function(x, ...) { - unique(c(sn[][, from], sn[][, to])) + unique(c(x[]$from, x[]$to)) }) -setMethod('cells', signature(x = 'dimObj', spat_unit = 'missing'), +setMethod('spatIDs', signature(x = 'dimObj', spat_unit = 'missing'), function(x, ...) { rownames(x@coordinates) }) +setMethod('spatIDs', signature(x = 'giottoPolygon', spat_unit = 'missing'), + function(x, ...) { + unique(x@spatVector$poly_ID) + }) -setMethod('features', signature(x = 'giotto', feat_type = 'missing'), +setMethod('featIDs', signature(x = 'giotto', feat_type = 'missing'), function(x, ...) { get_feat_id(gobject = x, ...) }) -setMethod('features', signature(x = 'giotto', feat_type = 'character'), +setMethod('featIDs', signature(x = 'giotto', feat_type = 'character'), function(x, feat_type, ...) { get_feat_id(gobject = x, feat_type, ...) }) -setMethod('features', signature(x = 'exprObj', feat_type = 'missing'), +setMethod('featIDs', signature(x = 'exprObj', feat_type = 'missing'), function(x, ...) { rownames(x[]) }) +setMethod('featIDs', signature(x = 'giottoPoints', feat_type = 'missing'), + function(x, ...) { + unique(x@spatVector$feat_ID) + }) # no features generic for dimObj @@ -135,7 +144,10 @@ setMethod('spin', signature(x = 'giottoPoints'), function(x, angle, x0 = NULL, y0 = NULL) { if(is.null(x0)) x0 = terra::mean(terra::ext(x@spatVector))[1] if(is.null(y0)) y0 = terra::mean(terra::ext(x@spatVector))[2] - x@spatVector = terra::spin(x@spatVector) + x@spatVector = terra::spin(x@spatVector, + angle = angle, + x0 = x0, + y0 = y0) return(x) }) @@ -172,6 +184,21 @@ setMethod('spin', signature(x = 'spatLocsObj'), + +# t() S4 generic #### +setMethod('t', signature(x = 'spatLocsObj'), function(x) { + sdimy = sdimx = NULL + x = data.table::copy(x) + x@coordinates[, c('sdimx', 'sdimy') := .(sdimy, sdimx)] + return(x) +}) + + + + + + + #' @title Dimensions of giotto objects #' @name dims-generic #' @description Find the dimensions of an object @@ -482,7 +509,16 @@ setMethod('plot', signature(x = 'giottoPoints', y = 'missing'), function(x, #' @describeIn plot-generic Plot a spatLocsObj #' @export setMethod('plot', signature(x = 'spatLocsObj', y = 'missing'), function(x, ...) { - plot(x = x[]$sdimx, y = x[]$sdimy, asp = 1, ...) + l = list(...) + if(is.null(l$asp)) l$asp = 1 + if(is.null(l$xlab)) l$xlab = '' + if(is.null(l$ylab)) l$ylab = '' + if(is.null(l$cex)) l$cex = 0.5 + if(nrow(x) > 10000) { + if(is.null(l$pch)) l$pch = '.' + } + + do.call('plot', append(l, list(x = x[]$sdimx, y = x[]$sdimy))) }) diff --git a/R/utilities.R b/R/utilities.R index 013a744fd..b9462a5ff 100644 --- a/R/utilities.R +++ b/R/utilities.R @@ -116,6 +116,7 @@ colMeans_flex = function(mymatrix) { #' @title t_flex #' @name t_flex #' @param mymatrix matrix to use +#' @include generics.R #' @keywords internal t_flex = function(mymatrix) { @@ -125,6 +126,8 @@ t_flex = function(mymatrix) { return(Matrix::t(mymatrix)) # replace with sparseMatrixStats } else if(inherits(mymatrix, 'Matrix')) { return(Matrix::t(mymatrix)) + } else if(inherits(mymatrix, 'spatLocsObj')){ + return(t(mymatrix)) } else { mymatrix = as.matrix(mymatrix) mymatrix = base::t(mymatrix) @@ -132,6 +135,9 @@ t_flex = function(mymatrix) { } } +t.spatLocsObj = function(mymatrix) { + t(mymatrix) +} #' @title cor_flex diff --git a/man/cells-generic.Rd b/man/spatIDs-generic.Rd similarity index 67% rename from man/cells-generic.Rd rename to man/spatIDs-generic.Rd index 5e4145d22..e76112368 100644 --- a/man/cells-generic.Rd +++ b/man/spatIDs-generic.Rd @@ -1,15 +1,17 @@ % Generated by roxygen2: do not edit by hand % Please edit documentation in R/generics.R -\name{cells-generic} -\alias{cells-generic} +\name{spatIDs-generic} +\alias{spatIDs-generic} +\alias{spatIDs} +\alias{featIDs} \title{Cell and feature names} \usage{ -cells(x, spat_unit, ...) +spatIDs(x, spat_unit, ...) -features(x, feat_type, ...) +featIDs(x, feat_type, ...) ## Default S4 method for signatures: -'giotto', 'exprObj', 'spatLocsObj', 'cellMetaObj', 'spatialNetworkObj' 'dimObj' +## 'giotto', 'exprObj', 'spatLocsObj', 'cellMetaObj', 'spatialNetworkObj' 'dimObj' } \arguments{ \item{x}{an object} From 90129491a2e7e48bb114ef2559424c40af3f7bf2 Mon Sep 17 00:00:00 2001 From: mattobny Date: Tue, 17 Jan 2023 16:38:30 -0500 Subject: [PATCH 100/129] Python maintenance --- R/giotto.R | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/R/giotto.R b/R/giotto.R index 8565a2196..cd09acc2d 100644 --- a/R/giotto.R +++ b/R/giotto.R @@ -8,13 +8,13 @@ #' @name set_giotto_python_path #' @description sets the python path and/or installs miniconda and the python modules set_giotto_python_path = function(python_path = NULL, - packages_to_install = c('pandas==1.1.5', - 'networkx==2.6.3', - 'python-igraph==0.9.6', - 'leidenalg==0.8.7', - 'python-louvain==0.15', - 'python.app==2', - 'scikit-learn==0.24.2')) { + packages_to_install = c('pandas==1.5.1', + 'networkx==2.8.8', + 'python-igraph==0.10.2', + 'leidenalg==0.9.0', + 'python-louvain==0.16', + 'python.app==1.4', + 'scikit-learn==1.1.3')) { ## if a python path is provided, use that path if(!is.null(python_path)) { From 3caf8a5fe5a7da7044f40d676e10d51157fbd2ce Mon Sep 17 00:00:00 2001 From: jiajic <72078254+jiajic@users.noreply.github.com> Date: Wed, 18 Jan 2023 10:18:03 -0500 Subject: [PATCH 101/129] Add weight mtx generation --- R/auxiliary_giotto.R | 78 -------------------------------- R/generics.R | 5 +++ R/interoperability.R | 2 +- R/spatial_structures.R | 91 ++++++++++++++++++++++++++++++++++---- R/utilities.R | 4 -- man/mat_queryDT.Rd | 24 ---------- man/spatialWeightMatrix.Rd | 44 ++++++++++++++++++ 7 files changed, 133 insertions(+), 115 deletions(-) delete mode 100644 man/mat_queryDT.Rd create mode 100644 man/spatialWeightMatrix.Rd diff --git a/R/auxiliary_giotto.R b/R/auxiliary_giotto.R index 2b8762f8c..ea45178c9 100644 --- a/R/auxiliary_giotto.R +++ b/R/auxiliary_giotto.R @@ -4743,84 +4743,6 @@ combineSpatialCellMetadataInfo = function(gobject, -#' @title Query Matrix with data.table syntax -#' @name mat_queryDT -#' @description Finds the rows of the Matrix needed to perform the query, converts -#' first to matrix, transposes, then to data.table after which the query is performed -#' just as if it had been a cell_ID (rows) by gene (cols) data.table. Only works -#' when j param is provided. -#' @param i select by row -#' @param j select by column or expression to query -#' @param by return results by which column -#' @param mtx matrix to use -#' @keywords internal -mat_queryDT = function(i = NULL, - j = NULL, - by = cell_ID, - mtx) { - - # data.table vars - cell_ID = NULL - - i_sub = deparse(substitute(i)) - j_sub = deparse(substitute(j)) - by_sub = deparse(substitute(by)) - - # only i - if(i_sub != 'NULL' & j_sub == 'NULL' & by_sub == 'NULL') { - warning('Only i not supported') - return(NULL) - } - - # by only - # i,by - if(i_sub != 'NULL' & by_sub != 'NULL') { - warning(wrap_txt('Ignoring by= because j= is not supplied')) - return(NULL) - } - - query_to_match = paste(i_sub, j_sub, by_sub) - print(query_to_match) - - genes = rownames(mtx) - gene_matches = genes[sapply(genes, function(x) {grepl(x, query_to_match)})] - names(gene_matches) = NULL - - print(gene_matches) - - cell_IDs = colnames(mtx) - match_dt = data.table::as.data.table(t_flex(as.matrix(mtx[gene_matches,,drop = FALSE]))) - match_dt[, cell_ID := cell_IDs] - - print(match_dt) - - - - # only j - if(i_sub == 'NULL' & j_sub != 'NULL' & by_sub == 'NULL') { - return(match_dt[,eval(parse(text = j_sub))]) - } - - # i,j - if(i_sub != 'NULL' & j_sub != 'NULL' & by_sub == 'NULL') { - return(match_dt[eval(parse(text = i_sub)), - eval(parse(text = j_sub))]) - } - - # j,by - if(i_sub == 'NULL' & j_sub != 'NULL' & by_sub != 'NULL') { - return(match_dt[,eval(parse(text = j_sub)), c(by_sub)]) - } - - # i,j,by - if(i_sub != 'NULL' & j_sub != 'NULL' & by_sub != 'NULL') { - return(match_dt[eval(parse(text = i_sub)), - eval(parse(text = j_sub)), - c(by_sub)]) - } - -} - diff --git a/R/generics.R b/R/generics.R index 58ef7254c..b9ec14b8f 100644 --- a/R/generics.R +++ b/R/generics.R @@ -186,6 +186,7 @@ setMethod('spin', signature(x = 'spatLocsObj'), # t() S4 generic #### + setMethod('t', signature(x = 'spatLocsObj'), function(x) { sdimy = sdimx = NULL x = data.table::copy(x) @@ -193,6 +194,10 @@ setMethod('t', signature(x = 'spatLocsObj'), function(x) { return(x) }) +# S3 definition +t.spatLocsObj = function(mymatrix) { + t(mymatrix) +} diff --git a/R/interoperability.R b/R/interoperability.R index ed4079248..2b9a25d38 100644 --- a/R/interoperability.R +++ b/R/interoperability.R @@ -1155,7 +1155,7 @@ seuratToGiotto = function(sobject, # Dimension Reduction if(sum(sapply(dim_reduction,function(x) length(sobject@reductions[[x]]))) == 0) { - dim_reduc = NULL + dimReduc_list = NULL } else { dimReduc_list = lapply(dim_reduction,function(x){ dim_coord = as.matrix(Seurat::Embeddings(object = sobject,reduction = x)) diff --git a/R/spatial_structures.R b/R/spatial_structures.R index 2de6ca1f9..d831fcb08 100644 --- a/R/spatial_structures.R +++ b/R/spatial_structures.R @@ -493,6 +493,80 @@ compatible_spatial_network = function(spatial_network, + +#' @title Create a spatial weight matrix +#' @name spatialWeightMatrix +#' @description Generate spatial weight matrix based on the strength of spatial +#' interactions between nodes. Requires spatial networks to be first generated. +#' @param gobject giotto object +#' @param spat_unit spatial unit +#' @param spatial_network_to_use spatial network information to use +#' @param method type of weighted matrix to generate. See details +#' @param wm_name name to assign the weight matrix values +#' @param return_gobject (default = TRUE) whether to return as the giotto object +#' with attached results or the bare weighted matrix +#' @param verbose be verbose +#' @details +#' \itemize{ +#' \item{\code{"distance"} method is calculated using 1/(1+distance) to create an inverse +#' weighting based on the distance between nodes.} +#' \item{\code{"adjacency"} method is a binary matrix with 1 signifying that two nodes +#' are connected in the spatial network and 0 indicating that they are not.} +#' } +spatialWeightMatrix = function(gobject, + spat_unit = NULL, + spatial_network_to_use = 'kNN_network', + method = c('distance', 'adjacency'), + wm_name = 'spat_weights', + return_gobject = TRUE, + verbose = TRUE) { + + # 1. setup + spat_unit = set_default_spat_unit(spat_unit = spat_unit) + + method = match.arg(method, choices = c('distance', 'adjacency')) + + sn = get_spatialNetwork(gobject = gobject, + spat_unit = spat_unit, + name = spatial_network_to_use, + output = 'spatialNetworkObj') + if(is.null(sn)) return(NULL) + + # 2. calculate weights + if(method == 'distance') { + dist_dt = sn[][, c('from', 'to', 'weight')] # inverse distance weights already calculated + graph = igraph::graph_from_data_frame(d = dist_dt, directed = FALSE) + wm = igraph::get.adjacency(graph = graph, attr = 'weight', sparse = TRUE) + } + if(method == 'adjacency') { + adj_dt = sn[][, c('from', 'to')] + graph = igraph::graph_from_data_frame(d = adj_dt, directed = FALSE) + wm = igraph::as_adjacency_matrix(graph) + } + + # 3. return results + if(isTRUE(return_gobject)) { + + sn@misc$weight_matrix[[wm_name]] = wm + ### ### ### ### ### ### ### ### ### ### ### ### ### ### ### ### ### ### + if(isTRUE(verbose)) wrap_msg('Attaching weight matrix to', spatial_network_to_use) + gobject = set_spatialNetwork(gobject = gobject, + spatial_network = sn, + set_defaults = FALSE, + verbose = FALSE) + ### ### ### ### ### ### ### ### ### ### ### ### ### ### ### ### ### ### + return(gobject) + + } else return(wm) + +} + + + + + + + ## Delaunay network #### #' @title create_delaunayNetwork_geometry @@ -1515,14 +1589,15 @@ createSpatialKNNnetwork <- function (gobject, "k" = k, "dimensions" = dimensions) - spatial_network_Obj = new('spatialNetworkObj', - name = name, - method = method, - parameters = parameters, - outputObj = outputObj, - networkDT = spatial_network_DT, - spat_unit = spat_unit, - misc = NULL) + spatial_network_Obj = create_spat_net_obj( + name = name, + method = method, + parameters = parameters, + outputObj = outputObj, + networkDT = spatial_network_DT, + spat_unit = spat_unit, + misc = NULL + ) ### ### ### ### ### ### ### ### ### ### ### ### ### ### ### ### ### ### ### ### ### ### ### ### ### ### ### ### ### ### ### ### ### ### ### ### ### ### ### ### diff --git a/R/utilities.R b/R/utilities.R index b9462a5ff..cc3b8e8af 100644 --- a/R/utilities.R +++ b/R/utilities.R @@ -116,7 +116,6 @@ colMeans_flex = function(mymatrix) { #' @title t_flex #' @name t_flex #' @param mymatrix matrix to use -#' @include generics.R #' @keywords internal t_flex = function(mymatrix) { @@ -135,9 +134,6 @@ t_flex = function(mymatrix) { } } -t.spatLocsObj = function(mymatrix) { - t(mymatrix) -} #' @title cor_flex diff --git a/man/mat_queryDT.Rd b/man/mat_queryDT.Rd deleted file mode 100644 index b4db2ffa3..000000000 --- a/man/mat_queryDT.Rd +++ /dev/null @@ -1,24 +0,0 @@ -% Generated by roxygen2: do not edit by hand -% Please edit documentation in R/auxiliary_giotto.R -\name{mat_queryDT} -\alias{mat_queryDT} -\title{Query Matrix with data.table syntax} -\usage{ -mat_queryDT(i = NULL, j = NULL, by = cell_ID, mtx) -} -\arguments{ -\item{i}{select by row} - -\item{j}{select by column or expression to query} - -\item{by}{return results by which column} - -\item{mtx}{matrix to use} -} -\description{ -Finds the rows of the Matrix needed to perform the query, converts -first to matrix, transposes, then to data.table after which the query is performed -just as if it had been a cell_ID (rows) by gene (cols) data.table. Only works -when j param is provided. -} -\keyword{internal} diff --git a/man/spatialWeightMatrix.Rd b/man/spatialWeightMatrix.Rd new file mode 100644 index 000000000..91bd1d483 --- /dev/null +++ b/man/spatialWeightMatrix.Rd @@ -0,0 +1,44 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/spatial_structures.R +\name{spatialWeightMatrix} +\alias{spatialWeightMatrix} +\title{Create a spatial weight matrix} +\usage{ +spatialWeightMatrix( + gobject, + spat_unit = NULL, + spatial_network_to_use = "kNN_network", + method = c("distance", "adjacency"), + wm_name = "spat_weights", + return_gobject = TRUE, + verbose = TRUE +) +} +\arguments{ +\item{gobject}{giotto object} + +\item{spat_unit}{spatial unit} + +\item{spatial_network_to_use}{spatial network information to use} + +\item{method}{type of weighted matrix to generate. See details} + +\item{wm_name}{name to assign the weight matrix values} + +\item{return_gobject}{(default = TRUE) whether to return as the giotto object +with attached results or the bare weighted matrix} + +\item{verbose}{be verbose} +} +\description{ +Generate spatial weight matrix based on the strength of spatial +interactions between nodes. Requires spatial networks to be first generated. +} +\details{ +\itemize{ + \item{\code{"distance"} method is calculated using 1/(1+distance) to create an inverse +weighting based on the distance between nodes.} + \item{\code{"adjacency"} method is a binary matrix with 1 signifying that two nodes +are connected in the spatial network and 0 indicating that they are not.} +} +} From 5c59e10a4a5a67ff3b6132dad29c5deb4fa2647b Mon Sep 17 00:00:00 2001 From: mattobny Date: Wed, 18 Jan 2023 11:25:37 -0500 Subject: [PATCH 102/129] remove debugging command --- R/interoperability.R | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/R/interoperability.R b/R/interoperability.R index ed4079248..416d57149 100644 --- a/R/interoperability.R +++ b/R/interoperability.R @@ -286,11 +286,9 @@ anndataToGiotto = function(anndata_path = NULL, nn_dt[,uniq_ID := NULL] vert = unique(x = c(nn_dt$from_cell_ID, nn_dt$to_cell_ID)) nn_network_igraph = igraph::graph_from_data_frame(nn_dt[,.(from_cell_ID, to_cell_ID, weight, distance)], directed = TRUE, vertices = vert) - # og_nn = get_NearestNetwork(SS_seqfish, spat_unit = "cell", feat_type = "rna", nn_network_to_use = "kNN") - # as written, no difference found between original and above from igraph::difference() nn_info = extract_NN_info(adata = adata, key_added = n_key_added) - browser() + net_type = "kNN" # anndata default if(("sNN" %in% n_key_added) & !is.null(n_key_added)){ net_type = "sNN" From 90e07554409f5f1646f6cd345c594da47f5fca67 Mon Sep 17 00:00:00 2001 From: jiajic <72078254+jiajic@users.noreply.github.com> Date: Wed, 25 Jan 2023 02:29:30 -0500 Subject: [PATCH 103/129] spatial autocorrelation and generics spatial auto correlation - spatialAutoCorLocal() - spatialAutoCorGlobal() * needs further updates with p-val calculation and FDR corrections Generics: - spatIDs(), featIDs(), t(), spin(), spatShift() - explicitly set generics for nrow(), ncol(), dim() using setOldClass - add plot() method for spatialNetworkObj --- DESCRIPTION | 2 +- NAMESPACE | 7 + NEWS.md | 26 +- R/accessors.R | 19 +- R/auxiliary_giotto.R | 43 +- R/classes.R | 20 +- R/generics.R | 216 +++++++-- R/giotto.R | 88 +++- R/giotto_structures.R | 27 ++ R/image_registration.R | 10 +- R/spatial_enrichment.R | 650 +++++++++++++++++++++++++- R/spatial_structures.R | 129 ++--- R/utilities.R | 31 +- man/addFeatMetadata.Rd | 4 +- man/copy-generic.Rd | 2 - man/createSpatialDelaunayNetwork.Rd | 3 + man/createSpatialKNNnetwork.Rd | 3 + man/createSpatialNetwork.Rd | 3 + man/create_delaunayNetwork2D.Rd | 1 + man/create_delaunayNetwork3D.Rd | 1 + man/dims-generic.Rd | 11 +- man/do_gpoly.Rd | 19 + man/get_spatialNetwork.Rd | 8 +- man/plot-generic.Rd | 5 + man/select_spatialNetwork.Rd | 2 + man/set_row_order_dt.Rd | 17 + man/shift_spatial_locations.Rd | 38 ++ man/shift_spatial_network.Rd | 23 + man/spatShift.Rd | 31 ++ man/spatialAutoCor.Rd | 127 +++++ man/transpose-generic.Rd | 26 ++ man/wrap_txt.Rd | 4 +- man/xy_translate_spatial_locations.Rd | 26 -- 33 files changed, 1448 insertions(+), 174 deletions(-) create mode 100644 man/do_gpoly.Rd create mode 100644 man/set_row_order_dt.Rd create mode 100644 man/shift_spatial_locations.Rd create mode 100644 man/shift_spatial_network.Rd create mode 100644 man/spatShift.Rd create mode 100644 man/spatialAutoCor.Rd create mode 100644 man/transpose-generic.Rd delete mode 100644 man/xy_translate_spatial_locations.Rd diff --git a/DESCRIPTION b/DESCRIPTION index cac5e123d..07715a841 100644 --- a/DESCRIPTION +++ b/DESCRIPTION @@ -126,9 +126,9 @@ Collate: 'differential_expression.R' 'dimension_reduction.R' 'general_help.R' + 'giotto_structures.R' 'generics.R' 'giotto.R' - 'giotto_structures.R' 'giotto_viewer.R' 'globals.R' 'image_registration.R' diff --git a/NAMESPACE b/NAMESPACE index c2398800b..f006eb3fd 100644 --- a/NAMESPACE +++ b/NAMESPACE @@ -360,8 +360,11 @@ export(spatNetwDistributionsKneighbors) export(spatPlot) export(spatPlot2D) export(spatPlot3D) +export(spatShift) export(spatUnit) export(spatialAEH) +export(spatialAutoCorGlobal) +export(spatialAutoCorLocal) export(spatialDE) export(spatialExperimentToGiotto) export(specificCellCellcommunicationScores) @@ -416,8 +419,10 @@ exportMethods(objName) exportMethods(plot) exportMethods(prov) exportMethods(rbind2) +exportMethods(spatShift) exportMethods(spatUnit) exportMethods(spin) +exportMethods(t) exportMethods(unwrap) exportMethods(wrap) import(data.table) @@ -431,6 +436,8 @@ importFrom(methods,rbind2) importFrom(methods,show) importFrom(methods,slot) importFrom(methods,validObject) +importMethodsFrom(Matrix,t) importMethodsFrom(terra,spin) +importMethodsFrom(terra,t) importMethodsFrom(terra,unwrap) importMethodsFrom(terra,wrap) diff --git a/NEWS.md b/NEWS.md index f8ae5b6c1..9e01afffd 100644 --- a/NEWS.md +++ b/NEWS.md @@ -2,29 +2,37 @@ ## Breaking Changes - Removed support for deprecated nesting in `@nn_network` slot +- `createSpatialNetwork()` will now output a `spatialNetworkObj` by default when `return_gobject = FALSE`. It is possible to change this back to the data.table output by setting `output = 'data.table'` - Set incomplete classes in classes.R as virtual to prevent their instantiation +- Removed `createGiottoCosMxObject()` `aggregate` and `all` workflows until they are updated ## Added - New `gefToGiotto()` interoperability function to convert gef object from Stereo-seq to giotto - New `giottoToAnnData()` interoperability function to convert giotto object to squidpy flavor anndata .h5ad file(s) -- New `wrap()` and `unwrap()` generics for `giotto`, `giottoPoints`, and `giottoPolygons` -- New `spatIDs()` and `featIDs()` generics -- Add missing `create_nn_net_obj()` internal constructor function for S4 `nnNetObj` -- New `createGiottoMerscopeObject()` convenience function -- Add packages `exactextractr` and `sf` to "suggests" packages -- Add package `progressr` to "imports" packages -- Add `id_col`, `x_col`, `y_col` params to `polyStamp()` to make stamp location input more flexible +- New `spatialAutoCorLocal()` and `spatialAutoCorGlobal()` functions to find spatial autocorrelations from expression and cell metadata information +- New `spatialWeightMatrix()` function to generate spatial weight matrix from spatial networks for autocorrelation - Add `coord_fix_ratio` param to `spatFeatPlot2D()` and `spatFeatPlot2D_single()` +- Add `order` parameter to `dimFeatPlot2D` and `spatDimFeatPlot2d` to plot and order cells according to the levels of the selected feature ([#477](https://github.com/drieslab/Giotto/issues/477)) +- Add `plot()` method for `spatialNetworkObj` +- New `set_row_order_dt()` internal for setting `data.table` to a specific row order by reference - New `fread_colmatch()` internal for fread loading a subset of rows based on matches in a specified column +- Add missing `create_nn_net_obj()` internal constructor function for S4 `nnNetObj` +- Add `id_col`, `x_col`, `y_col` params to `polyStamp()` to make stamp location input more flexible - Add `optional` and `custom_msg` params to `package_check()` -- Add `order` parameter to `dimFeatPlot2D` and `spatDimFeatPlot2d` to plot and order cells according to the levels of the selected feature ([#477](https://github.com/drieslab/Giotto/issues/477)) +- New `wrap()` and `unwrap()` generics for `giotto`, `giottoPoints`, and `giottoPolygons` +- New `rotate()`, `t()`, and `spatShift` generics for giotto subobject spatial manipulation +- New `spatIDs()` and `featIDs()` generics - New `objName()` and `objName` generics for setting the names of relevant S4 subobjects - New `rbind()` generic to append `giottoPolygon` objects +- Add packages `exactextractr` and `sf` to "suggests" packages +- Add package `progressr` to "imports" packages ## Changes - Move giotto object method-specific creation functions from `giotto.R` to `convenience.R` -- Removed `createGiottoCosMxObject()` `aggregate` and `all` workflows until they are updated +- Update `addFeatMetadata()` to handle replacement of existing columns +- Update to `show()` method for `spatEnrObj` - Deprecate `polygon_feat_names` param in favor of `z_indices` in `readPolygonFilesVizgenHDF5()` +- Deprecate `xy_translate_spatial_locations()` in favor of `shift_spatial_locations()` - Optimize `readPolygonFilesVizgen()` - Fix bug in `loadGiotto()` that prevents proper parsing of filenames when spat_unit or feat_type contains '_' characters - Fix `loadGiotto()` loss of over-allocation for data.tables-based objects after loading from disk diff --git a/R/accessors.R b/R/accessors.R index 8682ef1ad..9d3fb8521 100644 --- a/R/accessors.R +++ b/R/accessors.R @@ -1476,6 +1476,8 @@ set_NearestNetwork = function(gobject, #' @param name name of spatial network #' @param output object type to return as. Options: 'spatialNetworkObj' (default), #' 'networkDT' and 'networkDT_before_filter' for data.table outputs. +#' @param copy_obj whether to copy/duplicate when getting the object (default = TRUE) +#' @param verbose be verbose #' @family spatial network data accessor functions #' @family functions to get data from giotto object #' @export @@ -1486,7 +1488,9 @@ get_spatialNetwork = function(gobject, 'networkDT', 'networkDT_before_filter', 'outputObj'), - set_defaults = TRUE) { + set_defaults = TRUE, + copy_obj = TRUE, + verbose = TRUE) { output = match.arg(output, choices = c('spatialNetworkObj', 'networkDT', @@ -1505,9 +1509,9 @@ get_spatialNetwork = function(gobject, # check if given name is present if (!is.element(name, names(slot(gobject, 'spatial_network')[[spat_unit]]))){ - message = sprintf("spatial network %s has not been created. Returning NULL. - check which spatial networks exist with showGiottoSpatNetworks()\n", name) - warning(message) + if(isTRUE(verbose)) msg = wrap_txt('spatial network', name, 'has not been created. Returning NULL. + check which spatial networks exist with showGiottoSpatNetworks()') + warning(msg) return(NULL) }else{ networkObj = slot(gobject, 'spatial_network')[[spat_unit]][[name]] @@ -1518,6 +1522,13 @@ get_spatialNetwork = function(gobject, } + if(copy_obj) { + networkObj@networkDT = data.table::copy(networkObj@networkDT) + if(!is.null(networkObj@networkDT_before_filter)) { + networkObj@networkDT_before_filter = data.table::copy(networkObj@networkDT_before_filter) + } + } + if (output == 'spatialNetworkObj'){ return(networkObj) } else if(output == 'networkDT'){ diff --git a/R/auxiliary_giotto.R b/R/auxiliary_giotto.R index ea45178c9..791cbc47b 100644 --- a/R/auxiliary_giotto.R +++ b/R/auxiliary_giotto.R @@ -3438,8 +3438,8 @@ addCellMetadata <- function(gobject, if(length(same_col_names) >= 1) { - cat('\n these column names were already used: ', same_col_names, '\n', - 'and will be overwritten \n') + wrap_msg('\nThese column names were already used: ', same_col_names, '\n', + 'and will be overwritten \n') cell_metadata[][, (same_col_names) := NULL] } @@ -3479,7 +3479,8 @@ addCellMetadata <- function(gobject, #' @param gobject giotto object #' @param spat_unit spatial unit #' @param feat_type feature type -#' @param new_metadata new metadata to use +#' @param new_metadata new metadata to use) +#' @param vector_name (optional) custom name if you provide a single vector #' @param by_column merge metadata based on \emph{feat_ID} column in \code{\link{fDataDT}} #' @param column_feat_ID column name of new metadata to use if by_column = TRUE #' @return giotto object @@ -3495,6 +3496,9 @@ addFeatMetadata <- function(gobject, by_column = F, column_feat_ID = NULL) { + # data.table variables + feat_ID = NULL + # Set feat_type and spat_unit spat_unit = set_default_spat_unit(gobject = gobject, spat_unit = spat_unit) @@ -3502,9 +3506,6 @@ addFeatMetadata <- function(gobject, spat_unit = spat_unit, feat_type = feat_type) - # data.table variables - feat_ID = NULL - feat_metadata = get_feature_metadata(gobject, spat_unit = spat_unit, feat_type = feat_type, @@ -3513,6 +3514,36 @@ addFeatMetadata <- function(gobject, ordered_feat_IDs = get_feat_id(gobject, feat_type = feat_type) + if(is.vector(new_metadata) | is.factor(new_metadata)) { + original_name = deparse(substitute(new_metadata)) + new_metadata = data.table::as.data.table(new_metadata) + if(!is.null(vector_name) & is.character(vector_name)) { + colnames(new_metadata) = vector_name + } else { + colnames(new_metadata) = original_name + } + } else { + new_metadata = data.table::as.data.table(new_metadata) + } + + if(is.null(column_feat_ID)) { + column_feat_ID = 'feat_ID' + } + + # overwrite columns with same name + new_col_names = colnames(new_metadata) + new_col_names = new_col_names[new_col_names != column_feat_ID] + old_col_names = colnames(feat_metadata[]) + old_col_names = old_col_names[old_col_names != 'feat_ID'] + same_col_names = new_col_names[new_col_names %in% old_col_names] + + if(length(same_col_names) >= 1) { + wrap_msg('\nThese column names were already used: ', same_col_names, '\n', + 'and will be overwritten \n') + feat_metadata[][, (same_col_names) := NULL] + } + + if(by_column == FALSE) { feat_metadata[] = cbind(feat_metadata[], new_metadata) } else { diff --git a/R/classes.R b/R/classes.R index e4add4486..77dce9b10 100644 --- a/R/classes.R +++ b/R/classes.R @@ -1120,8 +1120,8 @@ setMethod( cat("An object of class", class(object), "\n") if(!is.na(object@method)) cat('Contains spatial network generated with:', object@method, '\n') - if(!is.na(object@spat_unit)) cat(paste0('for spatial unit: "', object@spat_unit, '"\n')) - if(!is.null(object@provenance)) cat(paste0('provenance: "', object@provenance, '"\n')) + if(!is.na(object@spat_unit)) cat('for spatial unit: "', object@spat_unit, '"\n', sep = '') + if(!is.null(object@provenance)) cat('provenance:', object@provenance, '\n') if(!is.null(object@networkDT)) cat(' ', nrow(object@networkDT), 'connections (filtered)\n') if(!is.null(object@networkDT_before_filter)) cat(' ', nrow(object@networkDT_before_filter), 'connections (before filter)\n\n') @@ -1353,10 +1353,20 @@ setMethod( if(!is.null(slot(object, 'provenance'))) cat('provenance:', slot(object, 'provenance'), '\n') cat(' ------------------------\n\npreview:\n') - if(!is.null(slot(object, 'enrichDT'))) show(slot(object, 'enrichDT')[1:4]) + if(!is.null(slot(object, 'enrichDT'))) { + enr_cols = ncol(slot(object, 'enrichDT')) + if(enr_cols > 10L) { + show(slot(object, 'enrichDT')[1:4, 1:10]) + cat(rep(' ', times = getOption('width')/2.5 - 10L), rep('.', 20L),'\n', sep = '') + show(slot(object, 'enrichDT')[1:4, 'cell_ID']) + cat('...', enr_cols - 11L, ' cols omitted\n', sep = '') + } else { + show(slot(object, 'enrichDT')[1:4]) + } + } - cat('\n...remaining colnames:\n') - cat('\n', wrap_txt(colnames(slot(object, 'enrichDT'))[-c(1:4)], strWidth = 40), '\n') + cat('\n...first 20 remaining colnames:\n') + cat('\n', wrap_txt(head(colnames(slot(object, 'enrichDT'))[-c(1:10)], 20L), strWidth = 40L), '\n') cat('\n\n') diff --git a/R/generics.R b/R/generics.R index b9ec14b8f..c10124ef0 100644 --- a/R/generics.R +++ b/R/generics.R @@ -3,6 +3,8 @@ # NOTE: initialize generics are in classes.R # + +# spatIDs and featIDs generic #### #' @title Cell and feature names #' @name spatIDs-generic #' @description Get the cells and feature names of a giotto object or subobject @@ -55,6 +57,11 @@ setMethod('spatIDs', signature(x = 'giottoPolygon', spat_unit = 'missing'), function(x, ...) { unique(x@spatVector$poly_ID) }) +setMethod('spatIDs', signature(x = 'spatEnrObj', spat_unit = 'missing'), + function(x, ...) { + cell_ID = NULL + x@enrichDT[, cell_ID] + }) setMethod('featIDs', signature(x = 'giotto', feat_type = 'missing'), @@ -73,6 +80,10 @@ setMethod('featIDs', signature(x = 'giottoPoints', feat_type = 'missing'), function(x, ...) { unique(x@spatVector$feat_ID) }) +setMethod('featIDs', signature(x = 'spatEnrObj', feat_type = 'missing'), + function(x, ...) { + colnames(x@enrichDT[, -'cell_ID']) + }) # no features generic for dimObj @@ -107,34 +118,36 @@ NULL #' @describeIn spin-generic Spin a giottoPolygon object #' @importMethodsFrom terra spin +#' @include giotto_structures.R #' @export setMethod('spin', signature(x = 'giottoPolygon'), function(x, angle, x0 = NULL, y0 = NULL) { if(is.null(x0)) x0 = terra::mean(terra::ext(x@spatVector))[1] if(is.null(y0)) y0 = terra::mean(terra::ext(x@spatVector))[2] - x@spatVector = terra::spin(x = x@spatVector, - angle = angle, - x0 = x0, - y0 = y0) - if(!is.null(x@spatVectorCentroids)) { - x@spatVectorCentroids = terra::spin(x = x@spatVectorCentroids, - angle = angle, - x0 = x0, - y0 = y0) - } - if(!is.null(x@overlaps)) { - lapply(x@overlaps, function(overlap) { - if(inherits(overlap, 'SpatVector')) { - terra::spin(x = overlap, - angle = angle, - x0 = x0, - y0 = y0) - } else { - overlap - } - }) - } - return(x) + return(do_gpoly(x = x, what = 'terra'::'spin', args = list(angle = angle, x0 = x0, y0 = y0))) + # x@spatVector = terra::spin(x = x@spatVector, + # angle = angle, + # x0 = x0, + # y0 = y0) + # if(!is.null(x@spatVectorCentroids)) { + # x@spatVectorCentroids = terra::spin(x = x@spatVectorCentroids, + # angle = angle, + # x0 = x0, + # y0 = y0) + # } + # if(!is.null(x@overlaps)) { + # lapply(x@overlaps, function(overlap) { + # if(inherits(overlap, 'SpatVector')) { + # terra::spin(x = overlap, + # angle = angle, + # x0 = x0, + # y0 = y0) + # } else { + # overlap + # } + # }) + # } + # return(x) }) #' @describeIn spin-generic Spin a giottoPoints object @@ -185,21 +198,38 @@ setMethod('spin', signature(x = 'spatLocsObj'), -# t() S4 generic #### +# spatShift() S4 generic #### +#' @name spatShift +#' @title Spatially shift an object +#' @param dx numeric. The shift on the x axis +#' @param dy numeric. The shift on the y axis +#' @param dz numeric. The shift on the z axis +#' @param ... additional params to pass to methods +#' @description Shift the spatial locations of an object +#' @export +NULL -setMethod('t', signature(x = 'spatLocsObj'), function(x) { - sdimy = sdimx = NULL - x = data.table::copy(x) - x@coordinates[, c('sdimx', 'sdimy') := .(sdimy, sdimx)] +setGeneric('spatShift', function(x, ...) standardGeneric('spatShift')) + +#' @describeIn spatShift Shift the locations of a spatLocsObj +#' @export +setMethod('spatShift', signature('spatLocsObj'), function(x, dx = 0, dy = 0, dz = 0, + copy_obj = TRUE, ...) { + x[] = shift_spatial_locations(spatlocs = x[], dx = dx, dy = dy, dz = dz, ...) + return(x) +}) +#' @describeIn spatShift Shift the locations of a spatialNetworkObj +#' @export +setMethod('spatShift', signature('spatialNetworkObj'), function(x, dx = 0, dy = 0, dz = 0, + copy_obj = TRUE, ...) { + x@networkDT = shift_spatial_network(spatnet = x@networkDT, + dx = dx, dy = dy, dz = dz, ...) + if(!is.null(x@networkDT_before_filter)) { + x@networkDT_before_filter = shift_spatial_network(spatnet = x@networkDT_before_filter, + dx = dx, dy = dy, dz = dz, ...) + } return(x) }) - -# S3 definition -t.spatLocsObj = function(mymatrix) { - t(mymatrix) -} - - @@ -213,6 +243,9 @@ NULL # nrow() S4 generic #### +if(!isGeneric('nrow')) setOldClass('nrow') +if(!isGeneric('ncol')) setOldClass('ncol') +if(!isGeneric('dim')) setOldClass('dim') # setMethod('nrow', signature = 'giotto', function(x) { # avail_exp = list_expression(x) @@ -223,6 +256,7 @@ NULL # nrow() # }) + #' @describeIn dims-generic Find rows of giottoPoints object #' @export setMethod('nrow', signature('giottoPoints'), function(x) terra::nrow(x@spatVector)) @@ -233,7 +267,8 @@ setMethod('nrow', signature('giottoPolygon'), function(x) terra::nrow(x@spatVect #' @describeIn dims-generic Find rows of giotto S4s with data.table based \code{coordinates} slots #' @export -setMethod('nrow', signature('coordDataDT'), function(x) x@coordinates[,.N]) +setMethod('nrow', signature('spatLocsObj'), function(x) nrow(x@coordinates)) + # TODO # setMethod('dims', signature('coordDataMT'), function(x) nrow(x@coordinates)) @@ -246,6 +281,12 @@ setMethod('nrow', signature('exprData'), function(x) nrow(x@exprMat)) #' @export setMethod('nrow', signature('metaData'), function(x) nrow(x@metaDT)) +#' @describeIn dims-generic Find rows of spatialNetworkObj +#' @export +setMethod('nrow', signature('spatialNetworkObj'), function(x) nrow(x@networkDT)) + +setMethod('nrow', signature('enrData'), function(x) nrow(x@enrichDT)) + # ncol() generic #### #' @describeIn dims-generic Find cols of giotto S4s with Matrix based \code{exprMat} slots @@ -256,6 +297,8 @@ setMethod('ncol', signature('exprData'), function(x) ncol(x@exprMat)) #' @export setMethod('ncol', signature('metaData'), function(x) ncol(x@metaDT)) +setMethod('nrow', signature('enrData'), function(x) nrow(x@enrichDT)) + # dim() generic #### #' @describeIn dims-generic Find dimensions of giotto S4s with Matrix based \code{exprMat} slots @@ -266,6 +309,57 @@ setMethod('dim', signature('exprData'), function(x) dim(x@exprMat)) #' @export setMethod('dim', signature('metaData'), function(x) dim(x@metaDT)) +setMethod('dim', signature('enrData'), function(x) dim(x@enrichDT)) + + + +# t() generic #### + +# S4 methods +#' @title Transpose +#' @name transpose-generic +#' @param x object to be transposed +#' @importMethodsFrom Matrix t +#' @importMethodsFrom terra t +#' @aliases t +if(!isGeneric('t')) setOldClass('t', where = as.environment("package:Giotto")) + +#' @describeIn transpose-generic Transpose a spatLocObj +#' @export +setMethod('t', signature('spatLocsObj'), function(x) { + sdimy = sdimx = NULL + x = data.table::copy(x) + x@coordinates[, c('sdimx', 'sdimy') := .(sdimy, sdimx)] + return(x) +}) +#' @describeIn transpose-generic Transpose a spatialNeworkObj +#' @export +setMethod('t', signature('spatialNetworkObj'), function(x) { + sdimx_begin = sdimx_end = sdimy_begin = sdimy_end = NULL + x = data.table::copy(x) + x@networkDT[, c('sdimx_begin', 'sdimy_begin', 'sdimx_end', 'sdimy_end') := .(sdimy_begin, sdimx_begin, sdimy_end, sdimx_end)] + if(!is.null(x@networkDT_before_filter)) { + x@networkDT_before_filter[, c('sdimx_begin', 'sdimy_begin', 'sdimx_end', 'sdimy_end') := .(sdimy_begin, sdimx_begin, sdimy_end, sdimx_end)] + } + return(x) +}) + +# s3 methods +t.spatLocsObj = function(x) { + sdimy = sdimx = NULL + x = data.table::copy(x) + x@coordinates[, c('sdimx', 'sdimy') := .(sdimy, sdimx)] + return(x) +} +t.spatialNetworkObj = function(x) { + sdimx_begin = sdimx_end = sdimy_begin = sdimy_end = NULL + x = data.table::copy(x) + x@networkDT[, c('sdimx_begin', 'sdimy_begin', 'sdimx_end', 'sdimy_end') := .(sdimy_begin, sdimx_begin, sdimy_end, sdimx_end)] + if(!is.null(x@networkDT_before_filter)) { + x@networkDT_before_filter[, c('sdimx_begin', 'sdimy_begin', 'sdimx_end', 'sdimy_end') := .(sdimy_begin, sdimx_begin, sdimy_end, sdimx_end)] + } + return(x) +} # wrap() generic #### @@ -428,7 +522,7 @@ setMethod('rbind2', signature(x = 'giottoPolygon', y = 'giottoPolygon'), }) -setGeneric('rbind', signature = '...') +if(!isGeneric('rbind')) setGeneric('rbind', signature = '...') setMethod("rbind", "giottoPolygon", function(..., deparse.level = 1) { if(nargs() <= 2L) { @@ -454,7 +548,7 @@ setMethod("rbind", "giottoPolygon", function(..., deparse.level = 1) { #' @aliases plot #' @family plot #' @exportMethod plot -setOldClass('plot') +if(!isGeneric('plot')) setOldClass('plot') #' @describeIn plot-generic Plot \emph{magick}-based giottoImage object. ... param passes to \code{\link{plot_giottoImage_MG}} #' @export @@ -519,7 +613,7 @@ setMethod('plot', signature(x = 'spatLocsObj', y = 'missing'), function(x, ...) if(is.null(l$xlab)) l$xlab = '' if(is.null(l$ylab)) l$ylab = '' if(is.null(l$cex)) l$cex = 0.5 - if(nrow(x) > 10000) { + if(nrow(x@coordinates) > 10000L) { if(is.null(l$pch)) l$pch = '.' } @@ -527,6 +621,48 @@ setMethod('plot', signature(x = 'spatLocsObj', y = 'missing'), function(x, ...) }) +#' @describeIn plot-generic Plot a spatialNetworkObj +#' @export +setMethod('plot', signature(x = 'spatialNetworkObj', y = 'missing'), function(x, ...) { + l = list(...) + if(is.null(l$asp)) l$asp = 1 + if(is.null(l$xlab)) l$xlab = '' + if(is.null(l$ylab)) l$ylab = '' + if(is.null(l$cex)) l$cex = 0.5 + if(is.null(l$col)) { + line_col = 'red' + } else { + line_col = l$col + l$col = NULL + } + if(is.null(l$lwd)) { + line_width = 1L + } else { + line_width = l$lwd + l$lwd = NULL + } + if(is.null(l$lty)) { + line_type = 1L + } else { + line_type = l$lty + l$lty = NULL + } + # find nodes + nodes = unique(rbind(x[][, c('sdimx_begin', 'sdimy_begin')], + x[][, c('sdimx_end', 'sdimy_end')], + use.names = FALSE)) + if(nrow(nodes) > 10000L) { + if(is.null(l$pch)) l$pch = '.' + } + do.call('plot', append(l, list(x = nodes$sdimx_begin, y = nodes$sdimy_begin))) + segments(x0 = x[]$sdimx_begin, y0 = x[]$sdimy_begin, + x1 = x[]$sdimx_end, y1 = x[]$sdimy_end, + col = line_col, lty = line_type, lwd = line_width) +}) + + + + # copy() S4 generic #### #' @title Copy an entire object @@ -538,7 +674,7 @@ setMethod('plot', signature(x = 'spatLocsObj', y = 'missing'), function(x, ...) #' @seealso \code{\link[data.table]{copy}} \code{\link[terra]{deepcopy}} #' @aliases copy #' @exportMethod copy -setGeneric('copy', function(x) { +if(!isGeneric('copy')) setGeneric('copy', function(x) { standardGeneric('copy') }) diff --git a/R/giotto.R b/R/giotto.R index 8565a2196..75e7daaaa 100644 --- a/R/giotto.R +++ b/R/giotto.R @@ -1292,23 +1292,52 @@ scale_spatial_locations = function(spatlocs, } -# TODO deprecate in favor of name change since z axis can be involved$ -#' @title xy_translate_spatial_locations -#' @name xy_translate_spatial_locations -#' @description Translate given X Y coordinates by given x and y translation values +# internal for deprecation +xy_translate_spatial_locations = function(...) { + .Deprecated(new = 'shift_spatial_locations') + + shift_spatial_locations(...) +} + + +#' @title Shift spatial locations +#' @name shift_spatial_locations +#' @description Shift given coordinates by given translation values #' @param spatlocs spatial locations to use -#' @param xtranslate value to translate coordinates in the positive x direction -#' @param ytranslate value to translate coordinates in the positive y direction -#' @param ztranslate value to translate coordinates in the positive z direction +#' @param dx value to shift coordinates in the positive x direction +#' @param dy value to shift coordinates in the positive y direction +#' @param dz value to shift coordinates in the positive z direction +#' @param xtranslate deprecated. use dx +#' @param ytranslate deprecated. use dy +#' @param ztranslate deprecated. use dz +#' @param copy_obj copy/duplicate object (default = TRUE) #' @keywords internal -xy_translate_spatial_locations = function(spatlocs, - xtranslate = 0, - ytranslate = 0, - ztranslate = 0) { +shift_spatial_locations = function(spatlocs, + dx = 0, + dy = 0, + dz = 0, + xtranslate = NULL, + ytranslate = NULL, + ztranslate = NULL, + copy_obj = TRUE) { + sdimx = sdimy = sdimz = NULL + + if(!is.null(xtranslate)) { + warning(wrap_txt('xtranslate is deprecated. use dx')) + dx = xtranslate + } + if(!is.null(ytranslate)) { + warning(wrap_txt('ytranslate is deprecated. use dy')) + dy = ytranslate + } + if(!is.null(ztranslate)) { + warning(wrap_txt('ztranslate is deprecated. use dz')) + dz = ztranslate + } - spatlocs$sdimx = spatlocs$sdimx + xtranslate - spatlocs$sdimy = spatlocs$sdimy + ytranslate - if('sdimz' %in% names(spatlocs)) spatlocs$sdimz = spatlocs$sdimz + ztranslate + spatlocs[, sdimx := sdimx + dx] + spatlocs[, sdimy := sdimy + dy] + if('sdimz' %in% names(spatlocs)) spatlocs[, sdimz := sdimz + dz] return(spatlocs) } @@ -1433,6 +1462,37 @@ read_spatial_networks = function(gobject, } +# See function spatShift in generics.R +#' @name shift_spatial_network +#' @title Shift spatial network +#' @description Shift spatial network coordinates +#' @param spatnet spatial network data.table +#' @param dx distance to shift on x axis +#' @param dy distance to shift on y axis +#' @param dz distance to shift on z axis +#' @param copy_obj copy/duplicate object (default = TRUE) +#' @keywords internal +shift_spatial_network = function(spatnet, dx = 0, dy = 0, dz = 0, copy_obj = TRUE) { + sdimx_begin = sdimx_end = sdimy_begin = sdimy_end = sdimz_begin = sdimz_end = NULL + + # if 3D info present + is3D = FALSE + if(all(c('sdimz_begin', 'sdimz_end') %in% colnames(spatnet))) is3D = TRUE + + if(copy_obj) spatnet = data.table::copy(spatnet) + + spatnet[, `:=`(sdimx_begin = sdimx_begin + dx, + sdimx_end = sdimx_end + dx, + sdimy_begin = sdimy_begin + dy, + sdimy_end = sdimy_end + dy)] + if(is3D) { + spatnet[, `:=`(sdimz_begin = sdimz_begin + dz, + sdimz_end = sdimz_end + dz)] + } + return(spatnet) +} + + #### Giotto spatial enrichment #### diff --git a/R/giotto_structures.R b/R/giotto_structures.R index ab75da98d..201446d72 100644 --- a/R/giotto_structures.R +++ b/R/giotto_structures.R @@ -2,6 +2,33 @@ ## ** cell shape polygons #### +#' @title do_gpoly +#' @name do_gpoly +#' @description Perform function on all spatVector-based slots of giottoPolygon +#' @param x giottoPolygon +#' @param what a call to do +#' @param args a \code{list} of additional args +#' @keywords internal +do_gpoly = function(x, what, args = NULL) { + + x@spatVector = do.call(what, args = append(list(x@spatVector), args)) + if(!is.null(x@spatVectorCentroids)) { + x@spatVectorCentroids = do.call(what, args = append(list(x@spatVectorCentroids), args)) + } + if(!is.null(x@overlaps)) { + x@overlaps = lapply(x@overlaps, function(sv) { + if(inherits(sv, 'SpatVector')) { + do.call(what, args = append(list(sv), args)) + } else { + sv + } + }) + } + return(x) +} + + + #' @title Convert polygon to raster diff --git a/R/image_registration.R b/R/image_registration.R index 75e1ed815..165257fcf 100644 --- a/R/image_registration.R +++ b/R/image_registration.R @@ -69,9 +69,9 @@ rigid_transform_spatial_locations = function(spatlocs, spatlocsXY = rotate_spatial_locations(spatlocsXY, transform_values$Theta) - spatlocsXY = xy_translate_spatial_locations(spatlocsXY, - transform_values$XFinalTransform, - transform_values$YFinalTransform) + spatlocsXY = shift_spatial_locations(spatlocs = spatlocsXY, + dx = transform_values$XFinalTransform, + dy = transform_values$YFinalTransform) spatlocs$sdimx = spatlocsXY$sdimx spatlocs$sdimy = -1 * spatlocsXY$sdimy @@ -82,7 +82,9 @@ rigid_transform_spatial_locations = function(spatlocs, spatLocsXY = spatlocs[,c('sdimx','sdimy')] spatLocsXY = rotate_spatial_locations(spatLocsXY,acos(transform_values[1,1])) - spatLocsXY = xy_translate_spatial_locations(spatLocsXY,-transform_values[1,3],-transform_values[2,3]) + spatLocsXY = shift_spatial_locations(spatlocs = spatLocsXY, + dx = -transform_values[1,3], + dy = -transform_values[2,3]) spatlocs$sdimx = spatLocsXY[,1] spatlocs$sdimy = spatLocsXY[,2] diff --git a/R/spatial_enrichment.R b/R/spatial_enrichment.R index ed0acc7e0..a63ab7a78 100644 --- a/R/spatial_enrichment.R +++ b/R/spatial_enrichment.R @@ -1419,6 +1419,654 @@ createSpatialEnrich <- function(...) { +# * #### +## spatial autocorrelation functions #### + + +#' @title Spatial autocorrelation +#' @name spatialAutoCor +#' @param gobject giotto object +#' @param spat_unit spatial unit +#' @param feat_type feature type +#' @param feats features (expression) on which to run autocorrelation. +#' (leaving as NULL means that all features will be tested) +#' @param method method of autocorrelation. See details (default = 'moran') +#' @param data_to_use if using data from gobject, whether to test using expression +#' ('expression') or cell metadata ('cell_meta') +#' @param expression_values name of expression information to use +#' @param meta_cols columns in cell metadata to test +#' @param spatial_network_to_use spatial network to use +#' @param wm_method type of weight matrix to generate from spatial network if no +#' weight matrix is found attached to the spatial network +#' @param wm_name name of attached weight matrix to use +#' @param node_values alternative method of directly supplying a set of node values +#' @param weight_matrix alternative method of directly supplying a spatial weight +#' matrix +#' @param test_method method to test values for significance (default is no +#' testing) +#' @param verbose be verbose +#' @description Find spatial autocorrelation. Note that \code{spatialAutoCorGlobal} +#' will return values as a data.table instead of appending information to the gobject. +#' \code{spatialAutoCorLocal} will append the results as a spatial enrichment object +#' by default. \cr +#' If providing external data using either the \code{node_values} and/or \code{weight_matrix} +#' params, the order of values provided should be the same as the ordering of the +#' columns and rows of the weight matrix. +NULL + + +# internals for spatial autocorrelation using terra +#' @keywords internal +spat_autocor_terra_numeric = function(x, w, method) { + return(terra::autocor(x = x, w = w, method = method)) +} + +#' @keywords internal +spat_autocor_terra_raster = function(x, w, global = TRUE, method) { + return(terra::autocor(x = x, w = w, global = global, method = method)) +} + + + + + +#' @describeIn spatialAutoCor Global autocorrelation (single value returned) +#' @param mc_nsim when \code{test_method = 'monte_carlo'} this is number of simulations +#' to perform +#' @param cor_name name to assign the results in global autocorrelation output +#' @param return_gobject (default = FALSE) whether to return results appended to +#' metadata in the giotto object or as a data.table +#' @details +#' \strong{Global Methods:} +#' \itemize{ +#' \item{\emph{Moran's I} 'moran'} +#' \item{\emph{Geary's C} 'geary'} +#' } +#' @export +spatialAutoCorGlobal = function(gobject = NULL, + spat_unit = NULL, + feat_type = NULL, + feats = NULL, + method = c('moran', 'geary'), + data_to_use = c('expression', 'cell_meta'), + expression_values = c('normalized', 'scaled', 'custom'), + meta_cols = NULL, + spatial_network_to_use = 'kNN_network', + wm_method = c('distance', 'adjacency'), + wm_name = 'spat_weights', + node_values = NULL, + weight_matrix = NULL, + test_method = c('none', 'monte_carlo'), + mc_nsim = 99, + cor_name = NULL, + return_gobject = FALSE, + verbose = TRUE) { + + # 0. determine inputs + method = match.arg(method, choices = c('moran', 'geary')) + test_method = match.arg(test_method, choices = c('none', 'monte_carlo')) + data_to_use = match.arg(data_to_use, choices = c('expression', 'cell_meta')) + if(is.null(cor_name)) cor_name = method + if(!is.null(node_values)) { + if(is.numeric(node_values)) stop(wrap_txt('External "node_values" must be type numeric.', + errWidth = TRUE)) + } + + use_ext_vals = data.table::fifelse(!is.null(node_values), yes = TRUE, no = FALSE) + use_sn = data.table::fifelse(!is.null(weight_matrix), yes = FALSE, no = TRUE) + + use_expr = data.table::fcase( + isTRUE(use_ext_vals), FALSE, + data_to_use != 'expression', FALSE, + default = TRUE + ) + + use_meta = data.table::fcase( + isTRUE(use_ext_vals), FALSE, + data_to_use != 'cell_meta', FALSE, + default = TRUE + ) + + if(data_to_use == 'cell_meta') { + if(is.null(meta_cols)) { + stop(wrap_txt( + 'If "data_to_use" is "cell_meta" then a character vector of cell metadata', + 'columns to use must be provided in "meta_cols"', + errWidth = TRUE + )) + } + } + if(isTRUE(return_gobject)) { + if(data_to_use == 'cell_meta' | isTRUE(use_ext_vals)) { + stop(wrap_txt( + 'Global spatial autocorrelations on cell_meta or external data should not', + 'be returned to the gobject. + > Please set return_gobject = FALSE', + errWidth = TRUE + )) + } + } + + # 1. setup + if(!is.null(gobject)) { + spat_unit = set_default_spat_unit(gobject = gobject, + spat_unit = spat_unit) + feat_type = set_default_feat_type(gobject = gobject, + spat_unit = spat_unit, + feat_type = feat_type) + } else { # if null + if(any(!use_ext_vals, use_sn, return_gobject)) { + stop('gobject has not been provided\n') + } + } + + # select and format input + data_list = evaluate_autocor_input(gobject = gobject, + use_ext_vals = use_ext_vals, + use_sn = use_sn, + use_expr = use_expr, + use_meta = use_meta, + spat_unit = spat_unit, + feat_type = feat_type, + feats = feats, + method = method, + data_to_use = data_to_use, + expression_values = expression_values, + meta_cols = meta_cols, + spatial_network_to_use = spatial_network_to_use, + wm_method = wm_method, + wm_name = wm_name, + node_values = node_values, + weight_matrix = weight_matrix, + verbose = verbose) + # unpack formatted data + use_values = data_list$use_values + feats = data_list$feats + weight_matrix = data_list$weight_matrix + + + # 2. perform autocor + res_dt = run_spat_autocor_global(use_values = use_values, + feats = feats, + weight_matrix = weight_matrix, + method = method, + test_method = test_method, + mc_nsim = mc_nsim, + cor_name = cor_name) + + + + # if(method %in% local_methods) { + # res_dt = do.call('cbind', res_list) + # colnames(res_dt) = paste0(method, '_', colnames(res_dt)) + # res_dt[, cell_ID := wm_colnames] + # } + + + + # return info + if(isTRUE(return_gobject)) { + if(isTRUE(verbose)) wrap_msg('Appending', method, 'results to feature metadata: fDataDT()') + gobject = addFeatMetadata(gobject = gobject, + spat_unit = spat_unit, + feat_type = feat_type, + new_metadata = res_dt, + by_column = TRUE, + column_feat_ID = 'feat_ID') + + return(gobject) + } else { + return(res_dt) + } + +} + + +#' @describeIn spatialAutoCor Local autocorrelation (values generated for each spatial ID) +#' @param enrich_name name to assign local autocorrelation spatial enrichment results +#' @param return_gobject (default = FALSE) whether to return results appended to +#' metadata in the giotto object or as a data.table +#' @details +#' \strong{Local Methods:} +#' \itemize{ +#' \item{\emph{Local Moran's I} 'moran'} +#' \item{\emph{Getis-Ord Gi} 'Gi'} +#' \item{\emph{Getis-Ord Gi*} 'Gi*'} +#' \item{\emph{Local mean} 'mean'} +#' } +#' @export +spatialAutoCorLocal = function(gobject = NULL, + spat_unit = NULL, + feat_type = NULL, + feats = NULL, + method = c('moran', 'gi', 'gi*', 'mean'), + data_to_use = c('expression', 'cell_meta'), + expression_values = c('normalized', 'scaled', 'custom'), + meta_cols = NULL, + spatial_network_to_use = 'kNN_network', + wm_method = c('distance', 'adjacency'), + wm_name = 'spat_weights', + node_values = NULL, + weight_matrix = NULL, + test_method = c('none'), + # cor_name = NULL, + enrich_name = NULL, + return_gobject = TRUE, + output = c('spatEnrObj', 'data.table'), + verbose = TRUE) { + + # 0. determine inputs + method_select = match.arg(method, choices = c('moran', 'gi', 'gi*', 'mean')) + data_to_use = match.arg(data_to_use, choices = c('expression', 'cell_meta')) + output = match.arg(output, choices = c('spatEnrObj', 'data.table')) + # if(is.null(cor_name)) cor_name = method + + if(method_select == 'moran') method = 'locmor' + else method = method_select + + if(!is.null(node_values)) { + if(is.numeric(node_values)) stop(wrap_txt('External "node_values" must be type numeric', + errWidth = TRUE)) + } + + + use_ext_vals = data.table::fifelse(!is.null(node_values), yes = TRUE, no = FALSE) + use_sn = data.table::fifelse(!is.null(weight_matrix), yes = FALSE, no = TRUE) + + use_expr = data.table::fcase( + isTRUE(use_ext_vals), FALSE, + data_to_use != 'expression', FALSE, + default = TRUE + ) + + use_meta = data.table::fcase( + isTRUE(use_ext_vals), FALSE, + data_to_use != 'cell_meta', FALSE, + default = TRUE + ) + + if(is.null(enrich_name)) { # name of spatEnrObj + enrich_name = data.table::fcase( + isTRUE(use_ext_vals), method_select, + data_to_use == 'expression', paste0('expr_', method_select), + data_to_use == 'cell_meta', paste0('meta_', method_select), + default = method_select + ) + } + + + + # 1. setup + if(!is.null(gobject)) { + spat_unit = set_default_spat_unit(gobject = gobject, + spat_unit = spat_unit) + feat_type = set_default_feat_type(gobject = gobject, + spat_unit = spat_unit, + feat_type = feat_type) + } else { # if null + if(any(!use_ext_vals, use_sn, return_gobject)) { + stop('gobject has not been provided\n') + } + } + + + # select and format input + data_list = evaluate_autocor_input(gobject = gobject, + use_ext_vals = use_ext_vals, + use_sn = use_sn, + use_expr = use_expr, + use_meta = use_meta, + spat_unit = spat_unit, + feat_type = feat_type, + feats = feats, + method = method, + data_to_use = data_to_use, + expression_values = expression_values, + meta_cols = meta_cols, + spatial_network_to_use = spatial_network_to_use, + wm_method = wm_method, + wm_name = wm_name, + node_values = node_values, + weight_matrix = weight_matrix, + verbose = verbose) + # unpack formatted input + use_values = data_list$use_values + feats = data_list$feats + weight_matrix = data_list$weight_matrix + provenance = data_list$provenance + values = data_list$expr_values + IDs = data_list$IDs + + # spatIDs to use when returning autocor results + # Provide default spatIDs if missing + if(is.null(IDs)) { + IDs = seq(nrow(use_values)) + } + + # 2. perform autocor + res_dt = run_spat_autocor_local(use_values = use_values, + feats = feats, + weight_matrix = weight_matrix, + method = method, + test_method = test_method, + IDs = IDs) + + # create spatial enrichment object + enr = create_spat_enr_obj(name = enrich_name, + method = method_select, + enrichDT = res_dt, + spat_unit = spat_unit, + feat_type = feat_type, + provenance = provenance, + misc = if(use_expr) list(expr_values_used = values)) + + + # return info + if(isTRUE(return_gobject)) { + + if(isTRUE(verbose)) wrap_msg('Attaching ', method_select, ' results as spatial enrichment: "', + enrich_name, '"', sep = '') + ### ### ### ### ### ### ### ### ### ### ### ### ### ### ### ### ### ### ### + gobject = set_spatial_enrichment(gobject = gobject, + spatenrichment = enr) + ### ### ### ### ### ### ### ### ### ### ### ### ### ### ### ### ### ### ### + + return(gobject) + } else { + if(output == 'spatEnrObj') return(enr) + if(output == 'data.table') return(res_dt) + } + +} + + + + + + + +run_spat_autocor_global = function(use_values, + feats, + weight_matrix, + method, + test_method, + mc_nsim, + cor_name) { + nfeats = length(feats) + if(test_method != 'none') step_size = ceiling(nfeats/100L) + else step_size = step_size = ceiling(nfeats/10L) + + progressr::with_progress({ + if(step_size > 1) pb = progressr::progressor(steps = nfeats/step_size) + res_list = lapply_flex( + seq_along(feats), + # future.packages = c('terra', 'data.table'), + function(feat_i) { + feat = feats[feat_i] + if(inherits(use_values, 'data.table')) { + feat_vals = eval(call('[', use_values, j = as.name(feat))) + } else { + feat_vals = use_values[, feat] + } + + + spat_ac = spat_autocor_terra_numeric( + x = feat_vals, + w = weight_matrix, + method = method) + + + # test + if(test_method != 'none') { + if(test_method == 'monte_carlo') { + mc = sapply(seq(mc_nsim), function(i) spat_autocor_terra_numeric( + x = sample(feat_vals), + w = weight_matrix, + method = method)) + P = 1 - sum((spat_ac > mc) / (nsim + 1)) + } + if(test_method == 'spdep') { + wrap_msg('spdep not yet implemented') + } + } + # increment progress + if(exists('pb')) if(feat_i %% step_size == 0) pb() + + + if(test_method == 'none') return(data.table::data.table(feat, spat_ac)) + else return(data.table::data.table(feat, spat_ac, P)) + } + ) + }) + res_dt = do.call('rbind', res_list) + if(test_method == 'none') colnames(res_dt) = c('feat_ID', cor_name) + else colnames(res_dt) = c('feat_ID', cor_name, paste0(cor_name, '_', test_method)) + return(res_dt) + +} + + +run_spat_autocor_local = function(use_values, + feats, + weight_matrix, + method, + test_method, + IDs) { + nfeats = length(feats) + if(test_method != 'none') step_size = ceiling(nfeats/100L) + else step_size = step_size = ceiling(nfeats/10L) + + progressr::with_progress({ + if(step_size > 1) pb = progressr::progressor(steps = nfeats/step_size) + res_list = lapply_flex( + seq_along(feats), + # future.packages = c('terra', 'data.table'), + function(feat_i) { + feat = feats[feat_i] + if(inherits(use_values, 'data.table')) { + feat_vals = eval(call('[', use_values, j = as.name(feat))) + } else { + feat_vals = use_values[, feat] + } + + spat_ac = spat_autocor_terra_numeric( + x = feat_vals, + w = weight_matrix, + method = method) + + + # test + # if(test_method != 'none') { + # } + + # increment progress + if(exists('pb')) if(feat_i %% step_size == 0) pb() + + + out_dt = data.table::data.table(spat_ac) + colnames(out_dt) = feat + return(out_dt) + } + ) + }) + res_dt = do.call('cbind', res_list) + # append cell_ID column + res_dt[, cell_ID := IDs] + return(res_dt) + +} + + + +# Determine which information to retrieve and how to format the information +# Vars from upstream: +# use_sn - if true, extracts spatial network from gobject. Otherwise use externally provided info +# use_expr - if true, extracts expression information from gobject to use as node values +# use_meta - if true, extracts cell metadata information from gobject to use as node values +# use_ext_vals - directly use externally provided node value information + +# Expected input: +# 1. source of data per spatial ID, whether that be expression information, +# cell metadata annotations, or external data +# 2. a spatial weight matrix for defining how important spatial interactions should +# be considered. This information can either be extracted spatial networks in the +# gobject with a pre-generated spatial weight matrix or generated during this call. + +# Expected output: +# list of the following... +# 1. use_values - data per spatial ID. Formatted to be spatial ID (rows) by feats (cols) +# 2. feats - character vector of features in use_values to iterate through for autocor +# 3. weight_matrix - weight matrix (ordering checked to match with use_values if possible) +# 4, IDs - cell_IDs if available +# Some additional information about information used in specific workflows are also returned +evaluate_autocor_input = function(gobject, + use_ext_vals, + use_sn, + use_expr, + use_meta, + spat_unit, + feat_type, + feats, + method, + data_to_use, + expression_values, + meta_cols, + spatial_network_to_use, + wm_method, + wm_name, + node_values, + weight_matrix, + verbose = TRUE) { + + cell_ID = NULL + + # 1. Get spatial network to either get or generate a spatial weight matrix + # End output is weight_matrix + if(isTRUE(use_sn)) { + #SPATNET=================================================================# + sn = get_spatialNetwork(gobject = gobject, + spat_unit = spat_unit, + name = spatial_network_to_use, + output = 'spatialNetworkObj') + weight_matrix = slot(sn, 'misc')$weight_matrix[[wm_name]] + + # if no weight_matrix already generated... + if(is.null(weight_matrix)) { + wm_method = match.arg(wm_method, choices = c('distance', 'adjacency')) + if(isTRUE(verbose)) wrap_msg( + 'No spatial weight matrix found in selected spatial network + Generating', wm_method, 'matrix from', spatial_network_to_use + ) + weight_matrix = spatialWeightMatrix(gobject = gobject, + spat_unit = spat_unit, + spatial_network_to_use = spatial_network_to_use, + wm_name = wm_name, + method = wm_method, + return_gobject = FALSE, + verbose = FALSE) + } + wm_colnames = colnames(weight_matrix) + #SPATNET=================================================================# + } + if(!isTRUE(use_sn)) { + #EXTSPATNET==============================================================# + if(!is.null(colnames(weight_matrix))) { + wm_colnames = colnames(weight_matrix) + if(isTRUE(verbose)) wrap_msg( + 'colnames of externally provided weight matrix will be matched to' + ) + } + #EXTSPATNET==============================================================# + } + + + # 2. Get and format node values for use with autocorrelation function. + # End outputs are: + # - use_values for a spatID (rows) by features (cols) table or matrix + # - feats the names of selected features to use that will be iterated through downstream + if(isTRUE(use_expr)) { + #EXPR====================================================================# + values = match.arg(expression_values, unique(c('normalized', 'scaled', 'custom', expression_values))) + use_values = get_expression_values(gobject = gobject, + spat_unit = spat_unit, + feat_type = feat_type, + values = values, + output = 'matrix') + use_values = t_flex(use_values) + + # ensure identical ordering with giotto weight matrix + if(exists('wm_colnames')) use_values = use_values[wm_colnames,] + + if(is.null(feats)) feats = colnames(use_values) + IDs = rownames(use_values) + #EXPR====================================================================# + } + if(isTRUE(use_meta)) { + #META====================================================================# + if(is.null(meta_cols)) stop(wrap_txt('Metadata columns to autocorrelate must be given', + errWidth = TRUE)) + use_values = get_cell_metadata(gobject = gobject, + spat_unit = spat_unit, + feat_type = feat_type, + output = 'data.table', + copy_obj = TRUE) + + # ensure identical ordering with giotto weight matrix + if(exists('wm_colnames')) { + new_order = data.table::chmatch(wm_colnames, use_values$cell_ID) + set_row_order_dt(use_values, new_order) + } + + feats = meta_cols + IDs = use_values[, cell_ID] + #META====================================================================# + } + if(isTRUE(use_ext_vals)) { + #EXTDATA=================================================================# + use_values = data.table::as.data.table(values = node_values) + + feats = 'values' + #EXTDATA=================================================================# + } + + + # 3. general formatting and checking + ## weight matrix type + if(!inherits(weight_matrix, c('Matrix', 'matrix'))) { + stop(wrap_txt('weight_matrix must be a matrix or Matrix', + errWidth = TRUE)) + } + + ## terra autocor currently does not seem to work with sparse weight matrices + weight_matrix = as.matrix(weight_matrix) + + ## check if weight matrix dimensions match use_values + if((nrow(use_values) != ncol(weight_matrix)) | (nrow(use_values) != nrow(weight_matrix))) { + stop(wrap_txt('Number of values to correlate do not match number of weight matrix entries', + errWidth = TRUE)) + } + + + # return formatted values + # provenance included if available + return(list(use_values = use_values, + feats = feats, + weight_matrix = weight_matrix, + # method specific items: + expr_values = if(use_expr) values else NULL, + provenance = if(use_sn) prov(sn) else NULL, + IDs = if(use_expr | use_meta) IDs else NULL)) + +} + + + + + + + + + # * #### ## spatial deconvolution functions #### @@ -1746,7 +2394,7 @@ solve_OLS_internal <- function(S, A = cbind(diag(dim(S)[2])) bzero = c(rep(0,dim(S)[2])) - + out = tryCatch( expr = {quadprog::solve.QP(Dmat = D, dvec = d, diff --git a/R/spatial_structures.R b/R/spatial_structures.R index d831fcb08..2d1ecbc2b 100644 --- a/R/spatial_structures.R +++ b/R/spatial_structures.R @@ -522,7 +522,8 @@ spatialWeightMatrix = function(gobject, verbose = TRUE) { # 1. setup - spat_unit = set_default_spat_unit(spat_unit = spat_unit) + spat_unit = set_default_spat_unit(gobject = gobject, + spat_unit = spat_unit) method = match.arg(method, choices = c('distance', 'adjacency')) @@ -530,7 +531,7 @@ spatialWeightMatrix = function(gobject, spat_unit = spat_unit, name = spatial_network_to_use, output = 'spatialNetworkObj') - if(is.null(sn)) return(NULL) + if(is.null(sn)) stop('Specified spatial network not found') # 2. calculate weights if(method == 'distance') { @@ -827,12 +828,13 @@ create_delaunayNetwork2D <- function (gobject, S = 0, # RTriange verbose = T, return_gobject = TRUE, - ...) -{ + output = c('spatialNetworkObj', 'data.table'), + ...) { # get parameter values method = match.arg(method, c("delaunayn_geometry", "RTriangle", "deldir")) + output = match.arg(output, c('spatialNetworkObj', 'data.table')) # Set feat_type and spat_unit spat_unit = set_default_spat_unit(gobject = gobject, @@ -841,10 +843,10 @@ create_delaunayNetwork2D <- function (gobject, spatial_locations = get_spatial_locations(gobject, spat_unit = spat_unit, spat_loc_name = spat_loc_name, - output = 'data.table', + output = 'spatLocsObj', copy_obj = TRUE) - spatial_locations = spatial_locations[, c('cell_ID', sdimx, sdimy), with = FALSE] + spatial_locations[] = spatial_locations[][, c('cell_ID', sdimx, sdimy), with = FALSE] # 1. default is all dimensions as presented by spatial locations # 2. otherwise try to grab spatial coordinates @@ -853,7 +855,7 @@ create_delaunayNetwork2D <- function (gobject, if (method == "RTriangle"){ - delaunay_output = create_delaunayNetwork_RTriangle(spatial_locations = spatial_locations, + delaunay_output = create_delaunayNetwork_RTriangle(spatial_locations = spatial_locations[], sdimx = sdimx, sdimy = sdimy, Y = Y, @@ -876,7 +878,7 @@ create_delaunayNetwork2D <- function (gobject, }else if (method == "deldir"){ - delaunay_output = create_delaunayNetwork_deldir(spatial_locations = spatial_locations, + delaunay_output = create_delaunayNetwork_deldir(spatial_locations = spatial_locations[], sdimx = sdimx, sdimy = sdimy, ...) @@ -892,7 +894,7 @@ create_delaunayNetwork2D <- function (gobject, } else if (method == "delaunayn_geometry"){ - delaunay_output = create_delaunayNetwork_geometry(spatial_locations = spatial_locations, + delaunay_output = create_delaunayNetwork_geometry(spatial_locations = spatial_locations[], sdimx = sdimx, sdimy = sdimy, options = options, @@ -914,31 +916,33 @@ create_delaunayNetwork2D <- function (gobject, delaunay_network_DT = calculate_distance_and_weight(delaunay_network_DT, sdimx = sdimx, sdimy = sdimy, - d2_or_d3=2) + d2_or_d3 = 2L) networkDT_before_filter = delaunay_network_DT delaunay_network_DT = filter_network(delaunay_network_DT, maximum_distance = maximum_distance, minimum_k = minimum_k) ## calculate cell shape parameters ## - meanCellDistance = get_distance(delaunay_network_DT,method="mean") - medianCellDistance = get_distance(delaunay_network_DT,method="median") + meanCellDistance = get_distance(delaunay_network_DT, method = "mean") + medianCellDistance = get_distance(delaunay_network_DT, method = "median") cellShapeObj = list("meanCellDistance" = meanCellDistance, "medianCellDistance" = medianCellDistance) ### ### - delaunay_network_Obj = new('spatialNetworkObj', - name = name, - method = method, - parameters = parameters, - outputObj = outputObj, - networkDT = delaunay_network_DT, - networkDT_before_filter = networkDT_before_filter, - cellShapeObj = cellShapeObj, - spat_unit = spat_unit, - misc = NULL) + delaunay_network_Obj = create_spat_net_obj( + name = name, + method = method, + parameters = parameters, + outputObj = outputObj, + networkDT = delaunay_network_DT, + networkDT_before_filter = networkDT_before_filter, + cellShapeObj = cellShapeObj, + spat_unit = spat_unit, + provenance = prov(spatial_locations), + misc = NULL + ) ### ### @@ -985,7 +989,8 @@ create_delaunayNetwork2D <- function (gobject, return(gobject) } else { - return(delaunay_network_DT) + if(output == 'spatialNetworkObj') return(delaunay_network_Obj) + if(output == 'data.table') return(delaunay_network_DT) } } @@ -1007,11 +1012,12 @@ create_delaunayNetwork3D <- function (gobject, minimum_k = 0, # all options = "Pp", # geometry return_gobject = TRUE, - ...) -{ + output = c('spatialNetworkObj', 'data.table'), + ...) { # get parameter values method = match.arg(method, c("delaunayn_geometry", "RTriangle", "deldir")) + output = match.arg(output, c('spatialNetworkObj', 'data.table')) # Set feat_type and spat_unit spat_unit = set_default_spat_unit(gobject = gobject, @@ -1020,16 +1026,16 @@ create_delaunayNetwork3D <- function (gobject, spatial_locations = get_spatial_locations(gobject = gobject, spat_unit = spat_unit, spat_loc_name = spat_loc_name, - output = 'data.table', + output = 'spatLocsObj', copy_obj = TRUE) - spatial_locations = spatial_locations[, c('cell_ID', sdimx, sdimy, sdimz), with = F] + spatial_locations[] = spatial_locations[][, c('cell_ID', sdimx, sdimy, sdimz), with = FALSE] ## delaunay geometry method ## if (method == "delaunayn_geometry"){ - delaunay_output = create_delaunayNetwork_geometry_3D(spatial_locations = spatial_locations, + delaunay_output = create_delaunayNetwork_geometry_3D(spatial_locations = spatial_locations[], sdimx = sdimx, sdimy = sdimy, sdimz = sdimz, @@ -1064,6 +1070,19 @@ create_delaunayNetwork3D <- function (gobject, "medianCellDistance" = medianCellDistance ) + delaunay_network_Obj = create_spat_net_obj( + name = name, + method = method, + parameters = parameters, + outputObj = outputObj, + networkDT = delaunay_network_DT, + networkDT_before_filter = networkDT_before_filter, + cellShapeObj = cellShapeObj, + spat_unit = spat_unit, + provenance = prov(spatial_locations), + misc = NULL + ) + if (return_gobject == TRUE) { spn_names = list_spatial_networks_names(gobject = gobject, spat_unit = 'cell') if (name %in% spn_names) { @@ -1082,20 +1101,6 @@ create_delaunayNetwork3D <- function (gobject, gobject@parameters = parameters_list ### ### ### ### ### ### ### ### ### ### ### ### ### ### ### ### ### ### ### ### - ### - ### - delaunay_network_Obj = new('spatialNetworkObj', - name = name, - method = method, - parameters = parameters, - outputObj = outputObj, - networkDT = delaunay_network_DT, - networkDT_before_filter = networkDT_before_filter, - cellShapeObj = cellShapeObj, - spat_unit = spat_unit, - misc = NULL) - ### - ### gobject = set_spatialNetwork(gobject = gobject, spat_unit = spat_unit, name = name, @@ -1106,7 +1111,8 @@ create_delaunayNetwork3D <- function (gobject, return(gobject) } else { - return(delaunay_network_DT) + if(output == 'spatialNetworkObj') return(delaunay_network_Obj) + if(output == 'data.table') return(delaunay_network_DT) } } @@ -1134,8 +1140,7 @@ create_delaunayNetwork3D <- function (gobject, #' @param Y (RTriangle) If TRUE prohibits the insertion of Steiner points on the mesh boundary. #' @param j (RTriangle) If TRUE jettisons vertices that are not part of the final triangulation from the output. #' @param S (RTriangle) Specifies the maximum number of added Steiner points. -#' @param verbose verbose -#' @param return_gobject boolean: return giotto object (default = TRUE) +#' @inheritParams createSpatialNetwork #' @param \dots Other additional parameters #' @return giotto object with updated spatial network slot #' @details Creates a spatial Delaunay network as explained in \code{\link[geometry]{delaunayn}} (default), \code{\link[deldir]{deldir}}, or \code{\link[RTriangle]{triangulate}}. @@ -1155,6 +1160,7 @@ createSpatialDelaunayNetwork <- function(gobject, S = 0, # RTriangle verbose = T, return_gobject = TRUE, + output = c('spatialNetworkObj', 'data.table'), ...) { @@ -1167,8 +1173,9 @@ createSpatialDelaunayNetwork <- function(gobject, # get parameter values method = match.arg(method, c("deldir", "delaunayn_geometry", "RTriangle")) + output = match.arg(output, c('spatialNetworkObj', 'data.table')) - # determine the network dimesions + # determine the network dimensions spatial_locations = get_spatial_locations(gobject = gobject, spat_unit = spat_unit, spat_loc_name = spat_loc_name, @@ -1205,6 +1212,7 @@ createSpatialDelaunayNetwork <- function(gobject, S = S, verbose = verbose, return_gobject = return_gobject, + output = output, ...) }else if(d2_or_d3 == 3){ @@ -1228,6 +1236,7 @@ createSpatialDelaunayNetwork <- function(gobject, minimum_k = minimum_k, options = options, return_gobject = return_gobject, + output = output, ...) } } @@ -1295,7 +1304,8 @@ plotStatDelaunayNetwork = function(gobject, Y = Y, # RTriange j = j, # RTriange S = S, # RTriange - return_gobject = F, + return_gobject = FALSE, + output = 'data.table', ...) delaunay_network_DT_c = convert_to_full_spatial_network(reduced_spatial_network_DT = delaunay_network_DT) @@ -1485,6 +1495,7 @@ create_KNNnetwork_dbscan = function(spatial_locations, #' @param minimum_k minimum nearest neigbhours if maximum_distance != NULL #' @param verbose verbose #' @param return_gobject boolean: return giotto object (default = TRUE) +#' @inheritParams createSpatialNetwork #' @param \dots additional arguments to the selected method function #' @return giotto object with updated spatial network slot #' @@ -1508,9 +1519,11 @@ createSpatialKNNnetwork <- function (gobject, minimum_k = 0, verbose = F, return_gobject = TRUE, + output = c('spatialNetworkObj', 'data.table'), ...) { + output = match.arg(output, c('spatialNetworkObj', 'data.table')) # Set feat_type and spat_unit spat_unit = set_default_spat_unit(gobject = gobject, @@ -1519,7 +1532,7 @@ createSpatialKNNnetwork <- function (gobject, spat_unit = spat_unit, feat_type = feat_type) - # data.table variables + # data.table vars distance = rank_int = NULL # get parameter values @@ -1527,13 +1540,13 @@ createSpatialKNNnetwork <- function (gobject, spatial_locations = get_spatial_locations(gobject = gobject, spat_unit = spat_unit, spat_loc_name = spat_loc_name, - output = 'data.table', + output = 'spatLocsObj', copy_obj = TRUE) if (dimensions != "all") { - temp_spatial_locations = spatial_locations[, dimensions, with = FALSE] + temp_spatial_locations = spatial_locations[][, dimensions, with = FALSE] } else { - temp_spatial_locations = spatial_locations[, grepl('sdim', colnames(spatial_locations)), with = FALSE] + temp_spatial_locations = spatial_locations[][, grepl('sdim', colnames(spatial_locations[])), with = FALSE] } temp_spatial_locations = as.matrix(temp_spatial_locations) @@ -1547,10 +1560,10 @@ createSpatialKNNnetwork <- function (gobject, if (method == "dbscan"){ - spatial_locations = spatial_locations[, c('cell_ID', first_dimension, second_dimension, third_dimension), with = F] + spatial_locations[] = spatial_locations[][, c('cell_ID', first_dimension, second_dimension, third_dimension), with = F] - knn_output = create_KNNnetwork_dbscan(spatial_locations = spatial_locations, + knn_output = create_KNNnetwork_dbscan(spatial_locations = spatial_locations[], k = k, sdimx = first_dimension, sdimy = second_dimension, @@ -1596,6 +1609,7 @@ createSpatialKNNnetwork <- function (gobject, outputObj = outputObj, networkDT = spatial_network_DT, spat_unit = spat_unit, + provenance = prov(spatial_locations), misc = NULL ) @@ -1630,7 +1644,8 @@ createSpatialKNNnetwork <- function (gobject, return(gobject) } else { - return(spatial_network_DT) + if(output == 'spatialNetworkObj') return(spatial_network_Obj) + if(output == 'data.table') return(spatial_network_DT) } } @@ -1666,6 +1681,7 @@ createSpatialKNNnetwork <- function (gobject, #' @param maximum_distance_knn distance cuttof for nearest neighbors to consider for kNN network #' @param verbose verbose #' @param return_gobject boolean: return giotto object (default = TRUE) +#' @param output object type to return spatial network as when return_gobject = FALSE. (default: 'spatialNetworkObj') #' @param \dots Additional parameters for the selected function #' @return giotto object with updated spatial network slot #' @details Creates a spatial network connecting single-cells based on their physical distance to each other. @@ -1696,7 +1712,8 @@ createSpatialNetwork <- function(gobject, maximum_distance_knn = NULL, verbose = F, return_gobject = TRUE, - ...){ + output = c('spatialNetworkObj', 'data.table'), + ...) { # get paramters method = match.arg(method, c('Delaunay', 'kNN')) @@ -1721,6 +1738,7 @@ createSpatialNetwork <- function(gobject, name = name, verbose = verbose, return_gobject = return_gobject, + output = output, ...) } else if (method=="Delaunay"){ @@ -1744,6 +1762,7 @@ createSpatialNetwork <- function(gobject, S = S, verbose = verbose, return_gobject = return_gobject, + output = output, ...) } diff --git a/R/utilities.R b/R/utilities.R index cc3b8e8af..8891f8ff7 100644 --- a/R/utilities.R +++ b/R/utilities.R @@ -116,6 +116,7 @@ colMeans_flex = function(mymatrix) { #' @title t_flex #' @name t_flex #' @param mymatrix matrix to use +#' @include generics.R #' @keywords internal t_flex = function(mymatrix) { @@ -127,6 +128,8 @@ t_flex = function(mymatrix) { return(Matrix::t(mymatrix)) } else if(inherits(mymatrix, 'spatLocsObj')){ return(t(mymatrix)) + } else if(inherits(mymatrix, 'spatialNetworkObj')) { + return(t(mymatrix)) } else { mymatrix = as.matrix(mymatrix) mymatrix = base::t(mymatrix) @@ -310,6 +313,26 @@ list_element_exists = function(x, index) { +# Based on https://stackoverflow.com/questions/37878620/reorder-rows-in-data-table-in-a-specific-order +#' @title Set specific data.table row order +#' @param x data.table +#' @param neworder numerical vector to reorder rows +#' @keywords internal +set_row_order_dt = function(x, neworder) { + if('.r' %in% colnames(x)) { + temp_r = x[, .SD, .SDcols = '.r'] + data.table::setorderv(temp_r[, eval(call(":=", as.name(".r_alt"), call("order", neworder)))], ".r_alt")[, ".r_alt" := NULL] + data.table::setorderv(x[, eval(call(":=", as.name(".r"), call("order", neworder)))], ".r")[, ".r" := NULL] + x[, eval(call(':=', as.name('.r'), temp_r$.r))] + } else { + data.table::setorderv(x[, eval(call(":=", as.name(".r"), call("order", neworder)))], ".r")[, ".r" := NULL] + } + +} + + + + # methods/operator imports #### @@ -528,8 +551,14 @@ wrap_msg = function(..., sep = ' ') { #' @param ... additional params to pass #' @param sep how to join elements of string (default is one space) #' @param strWidth externally set wrapping width. (default value of 100 is not effected) +#' @param errWidth default = FALSE. Set strWidth to be compatible with error printout #' @keywords internal -wrap_txt = function(..., sep = ' ', strWidth = 100) { +wrap_txt = function(..., sep = ' ', strWidth = 100, errWidth = FALSE) { + custom_width = ifelse(is.null(match.call()$strWidth), yes = FALSE, no = TRUE) + if(!isTRUE(custom_width)) { + if(isTRUE(errWidth)) strWidth = getOption('width') - 6 + } + cat(..., sep = sep) %>% capture.output() %>% strwrap(., prefix = ' ', initial = '', # indent later lines, no indent first line diff --git a/man/addFeatMetadata.Rd b/man/addFeatMetadata.Rd index 1737c83f6..64b0883b0 100644 --- a/man/addFeatMetadata.Rd +++ b/man/addFeatMetadata.Rd @@ -20,11 +20,13 @@ addFeatMetadata( \item{spat_unit}{spatial unit} -\item{new_metadata}{new metadata to use} +\item{new_metadata}{new metadata to use)} \item{by_column}{merge metadata based on \emph{feat_ID} column in \code{\link{fDataDT}}} \item{column_feat_ID}{column name of new metadata to use if by_column = TRUE} + +\item{vector_name}{(optional) custom name if you provide a single vector} } \value{ giotto object diff --git a/man/copy-generic.Rd b/man/copy-generic.Rd index 26dcef9b7..2a74221e5 100644 --- a/man/copy-generic.Rd +++ b/man/copy-generic.Rd @@ -6,8 +6,6 @@ \alias{copy,coordDataDT-method} \title{Copy an entire object} \usage{ -copy(x) - \S4method{copy}{coordDataDT}(x) } \arguments{ diff --git a/man/createSpatialDelaunayNetwork.Rd b/man/createSpatialDelaunayNetwork.Rd index 6cbdd8a13..252e3843a 100644 --- a/man/createSpatialDelaunayNetwork.Rd +++ b/man/createSpatialDelaunayNetwork.Rd @@ -20,6 +20,7 @@ createSpatialDelaunayNetwork( S = 0, verbose = T, return_gobject = TRUE, + output = c("spatialNetworkObj", "data.table"), ... ) } @@ -54,6 +55,8 @@ createSpatialDelaunayNetwork( \item{return_gobject}{boolean: return giotto object (default = TRUE)} +\item{output}{object type to return spatial network as when return_gobject = FALSE. (default: 'spatialNetworkObj')} + \item{\dots}{Other additional parameters} } \value{ diff --git a/man/createSpatialKNNnetwork.Rd b/man/createSpatialKNNnetwork.Rd index 542a06573..07a7eb484 100644 --- a/man/createSpatialKNNnetwork.Rd +++ b/man/createSpatialKNNnetwork.Rd @@ -17,6 +17,7 @@ createSpatialKNNnetwork( minimum_k = 0, verbose = F, return_gobject = TRUE, + output = c("spatialNetworkObj", "data.table"), ... ) } @@ -45,6 +46,8 @@ createSpatialKNNnetwork( \item{return_gobject}{boolean: return giotto object (default = TRUE)} +\item{output}{object type to return spatial network as when return_gobject = FALSE. (default: 'spatialNetworkObj')} + \item{\dots}{additional arguments to the selected method function} } \value{ diff --git a/man/createSpatialNetwork.Rd b/man/createSpatialNetwork.Rd index 998bc88b1..41326b415 100644 --- a/man/createSpatialNetwork.Rd +++ b/man/createSpatialNetwork.Rd @@ -24,6 +24,7 @@ createSpatialNetwork( maximum_distance_knn = NULL, verbose = F, return_gobject = TRUE, + output = c("spatialNetworkObj", "data.table"), ... ) } @@ -66,6 +67,8 @@ createSpatialNetwork( \item{return_gobject}{boolean: return giotto object (default = TRUE)} +\item{output}{object type to return spatial network as when return_gobject = FALSE. (default: 'spatialNetworkObj')} + \item{\dots}{Additional parameters for the selected function} } \value{ diff --git a/man/create_delaunayNetwork2D.Rd b/man/create_delaunayNetwork2D.Rd index 14f1230d5..a796c382f 100644 --- a/man/create_delaunayNetwork2D.Rd +++ b/man/create_delaunayNetwork2D.Rd @@ -20,6 +20,7 @@ create_delaunayNetwork2D( S = 0, verbose = T, return_gobject = TRUE, + output = c("spatialNetworkObj", "data.table"), ... ) } diff --git a/man/create_delaunayNetwork3D.Rd b/man/create_delaunayNetwork3D.Rd index b9af22767..9e2269e97 100644 --- a/man/create_delaunayNetwork3D.Rd +++ b/man/create_delaunayNetwork3D.Rd @@ -17,6 +17,7 @@ create_delaunayNetwork3D( minimum_k = 0, options = "Pp", return_gobject = TRUE, + output = c("spatialNetworkObj", "data.table"), ... ) } diff --git a/man/dims-generic.Rd b/man/dims-generic.Rd index 8dc8dd001..daf0dbb05 100644 --- a/man/dims-generic.Rd +++ b/man/dims-generic.Rd @@ -4,9 +4,10 @@ \alias{dims-generic} \alias{nrow,giottoPoints-method} \alias{nrow,giottoPolygon-method} -\alias{nrow,coordDataDT-method} +\alias{nrow,spatLocsObj-method} \alias{nrow,exprData-method} \alias{nrow,metaData-method} +\alias{nrow,spatialNetworkObj-method} \alias{ncol,exprData-method} \alias{ncol,metaData-method} \alias{dim,exprData-method} @@ -17,12 +18,14 @@ \S4method{nrow}{giottoPolygon}(x) -\S4method{nrow}{coordDataDT}(x) +\S4method{nrow}{spatLocsObj}(x) \S4method{nrow}{exprData}(x) \S4method{nrow}{metaData}(x) +\S4method{nrow}{spatialNetworkObj}(x) + \S4method{ncol}{exprData}(x) \S4method{ncol}{metaData}(x) @@ -43,12 +46,14 @@ Find the dimensions of an object \item \code{nrow(giottoPolygon)}: Find rows of giottoPolygon object -\item \code{nrow(coordDataDT)}: Find rows of giotto S4s with data.table based \code{coordinates} slots +\item \code{nrow(spatLocsObj)}: Find rows of giotto S4s with data.table based \code{coordinates} slots \item \code{nrow(exprData)}: Find rows of giotto S4s with data.table based \code{coordinates} slots \item \code{nrow(metaData)}: Find rows of giotto S4s with data.table based \code{coordinates} slots +\item \code{nrow(spatialNetworkObj)}: Find rows of spatialNetworkObj + \item \code{ncol(exprData)}: Find cols of giotto S4s with Matrix based \code{exprMat} slots \item \code{ncol(metaData)}: Find cols of giotto S4s with data.table based \code{metaDT} slots diff --git a/man/do_gpoly.Rd b/man/do_gpoly.Rd new file mode 100644 index 000000000..0f6bbd804 --- /dev/null +++ b/man/do_gpoly.Rd @@ -0,0 +1,19 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/giotto_structures.R +\name{do_gpoly} +\alias{do_gpoly} +\title{do_gpoly} +\usage{ +do_gpoly(x, what, args = NULL) +} +\arguments{ +\item{x}{giottoPolygon} + +\item{what}{a call to do} + +\item{args}{a \code{list} of additional args} +} +\description{ +Perform function on all spatVector-based slots of giottoPolygon +} +\keyword{internal} diff --git a/man/get_spatialNetwork.Rd b/man/get_spatialNetwork.Rd index 2facad1b3..57f5943f5 100644 --- a/man/get_spatialNetwork.Rd +++ b/man/get_spatialNetwork.Rd @@ -9,7 +9,9 @@ get_spatialNetwork( spat_unit = NULL, name = NULL, output = c("spatialNetworkObj", "networkDT", "networkDT_before_filter", "outputObj"), - set_defaults = TRUE + set_defaults = TRUE, + copy_obj = TRUE, + verbose = TRUE ) } \arguments{ @@ -23,6 +25,10 @@ get_spatialNetwork( 'networkDT' and 'networkDT_before_filter' for data.table outputs.} \item{set_defaults}{set default spat_unit and feat_type. Change to FALSE only when} + +\item{copy_obj}{whether to copy/duplicate when getting the object (default = TRUE)} + +\item{verbose}{be verbose} } \description{ Function to get a spatial network diff --git a/man/plot-generic.Rd b/man/plot-generic.Rd index 009776121..6579d44b2 100644 --- a/man/plot-generic.Rd +++ b/man/plot-generic.Rd @@ -8,6 +8,7 @@ \alias{plot,giottoPolygon,missing-method} \alias{plot,giottoPoints,missing-method} \alias{plot,spatLocsObj,missing-method} +\alias{plot,spatialNetworkObj,missing-method} \title{Preview a Giotto spatial object} \usage{ \S4method{plot}{giottoImage,missing}(x, y, ...) @@ -19,6 +20,8 @@ \S4method{plot}{giottoPoints,missing}(x, y, point_size = 0.1, feats = NULL, ...) \S4method{plot}{spatLocsObj,missing}(x, y, ...) + +\S4method{plot}{spatialNetworkObj,missing}(x, y, ...) } \arguments{ \item{x}{giotto image, giottoPolygon, or giottoPoints object} @@ -48,5 +51,7 @@ S4 generic for previewing Giotto's image and subcellular objects. \item \code{plot(x = spatLocsObj, y = missing)}: Plot a spatLocsObj +\item \code{plot(x = spatialNetworkObj, y = missing)}: Plot a spatialNetworkObj + }} \concept{plot} diff --git a/man/select_spatialNetwork.Rd b/man/select_spatialNetwork.Rd index aaf7e09b4..479950248 100644 --- a/man/select_spatialNetwork.Rd +++ b/man/select_spatialNetwork.Rd @@ -13,6 +13,8 @@ select_spatialNetwork(...) \item{\code{name}}{name of spatial network} \item{\code{output}}{object type to return as. Options: 'spatialNetworkObj' (default), 'networkDT' and 'networkDT_before_filter' for data.table outputs.} + \item{\code{copy_obj}}{whether to copy/duplicate when getting the object (default = TRUE)} + \item{\code{verbose}}{be verbose} \item{\code{gobject}}{giotto object} \item{\code{spat_unit}}{spatial unit (e.g. "cell")} \item{\code{set_defaults}}{set default spat_unit and feat_type. Change to FALSE only when} diff --git a/man/set_row_order_dt.Rd b/man/set_row_order_dt.Rd new file mode 100644 index 000000000..68eae77ca --- /dev/null +++ b/man/set_row_order_dt.Rd @@ -0,0 +1,17 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/utilities.R +\name{set_row_order_dt} +\alias{set_row_order_dt} +\title{Set specific data.table row order} +\usage{ +set_row_order_dt(x, neworder) +} +\arguments{ +\item{x}{data.table} + +\item{neworder}{numerical vector to reorder rows} +} +\description{ +Set specific data.table row order +} +\keyword{internal} diff --git a/man/shift_spatial_locations.Rd b/man/shift_spatial_locations.Rd new file mode 100644 index 000000000..58134ee81 --- /dev/null +++ b/man/shift_spatial_locations.Rd @@ -0,0 +1,38 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/giotto.R +\name{shift_spatial_locations} +\alias{shift_spatial_locations} +\title{Shift spatial locations} +\usage{ +shift_spatial_locations( + spatlocs, + dx = 0, + dy = 0, + dz = 0, + xtranslate = NULL, + ytranslate = NULL, + ztranslate = NULL, + copy_obj = TRUE +) +} +\arguments{ +\item{spatlocs}{spatial locations to use} + +\item{dx}{value to shift coordinates in the positive x direction} + +\item{dy}{value to shift coordinates in the positive y direction} + +\item{dz}{value to shift coordinates in the positive z direction} + +\item{xtranslate}{deprecated. use dx} + +\item{ytranslate}{deprecated. use dy} + +\item{ztranslate}{deprecated. use dz} + +\item{copy_obj}{copy/duplicate object (default = TRUE)} +} +\description{ +Shift given coordinates by given translation values +} +\keyword{internal} diff --git a/man/shift_spatial_network.Rd b/man/shift_spatial_network.Rd new file mode 100644 index 000000000..55429f765 --- /dev/null +++ b/man/shift_spatial_network.Rd @@ -0,0 +1,23 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/giotto.R +\name{shift_spatial_network} +\alias{shift_spatial_network} +\title{Shift spatial network} +\usage{ +shift_spatial_network(spatnet, dx = 0, dy = 0, dz = 0, copy_obj = TRUE) +} +\arguments{ +\item{spatnet}{spatial network data.table} + +\item{dx}{distance to shift on x axis} + +\item{dy}{distance to shift on y axis} + +\item{dz}{distance to shift on z axis} + +\item{copy_obj}{copy/duplicate object (default = TRUE)} +} +\description{ +Shift spatial network coordinates +} +\keyword{internal} diff --git a/man/spatShift.Rd b/man/spatShift.Rd new file mode 100644 index 000000000..0e2a397fd --- /dev/null +++ b/man/spatShift.Rd @@ -0,0 +1,31 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/generics.R +\name{spatShift} +\alias{spatShift} +\alias{spatShift,spatLocsObj-method} +\alias{spatShift,spatialNetworkObj-method} +\title{Spatially shift an object} +\usage{ +\S4method{spatShift}{spatLocsObj}(x, dx = 0, dy = 0, dz = 0, copy_obj = TRUE, ...) + +\S4method{spatShift}{spatialNetworkObj}(x, dx = 0, dy = 0, dz = 0, copy_obj = TRUE, ...) +} +\arguments{ +\item{dx}{numeric. The shift on the x axis} + +\item{dy}{numeric. The shift on the y axis} + +\item{dz}{numeric. The shift on the z axis} + +\item{...}{additional params to pass to methods} +} +\description{ +Shift the spatial locations of an object +} +\section{Methods (by class)}{ +\itemize{ +\item \code{spatShift(spatLocsObj)}: Shift the locations of a spatLocsObj + +\item \code{spatShift(spatialNetworkObj)}: Shift the locations of a spatialNetworkObj + +}} diff --git a/man/spatialAutoCor.Rd b/man/spatialAutoCor.Rd new file mode 100644 index 000000000..2df5dbee1 --- /dev/null +++ b/man/spatialAutoCor.Rd @@ -0,0 +1,127 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/spatial_enrichment.R +\name{spatialAutoCor} +\alias{spatialAutoCor} +\alias{spatialAutoCorGlobal} +\alias{spatialAutoCorLocal} +\title{Spatial autocorrelation} +\usage{ +spatialAutoCorGlobal( + gobject = NULL, + spat_unit = NULL, + feat_type = NULL, + feats = NULL, + method = c("moran", "geary"), + data_to_use = c("expression", "cell_meta"), + expression_values = c("normalized", "scaled", "custom"), + meta_cols = NULL, + spatial_network_to_use = "kNN_network", + wm_method = c("distance", "adjacency"), + wm_name = "spat_weights", + node_values = NULL, + weight_matrix = NULL, + test_method = c("none", "monte_carlo"), + mc_nsim = 99, + cor_name = NULL, + return_gobject = FALSE, + verbose = TRUE +) + +spatialAutoCorLocal( + gobject = NULL, + spat_unit = NULL, + feat_type = NULL, + feats = NULL, + method = c("moran", "gi", "gi*", "mean"), + data_to_use = c("expression", "cell_meta"), + expression_values = c("normalized", "scaled", "custom"), + meta_cols = NULL, + spatial_network_to_use = "kNN_network", + wm_method = c("distance", "adjacency"), + wm_name = "spat_weights", + node_values = NULL, + weight_matrix = NULL, + test_method = c("none"), + enrich_name = NULL, + return_gobject = TRUE, + output = c("spatEnrObj", "data.table"), + verbose = TRUE +) +} +\arguments{ +\item{gobject}{giotto object} + +\item{spat_unit}{spatial unit} + +\item{feat_type}{feature type} + +\item{feats}{features (expression) on which to run autocorrelation. +(leaving as NULL means that all features will be tested)} + +\item{method}{method of autocorrelation. See details (default = 'moran')} + +\item{data_to_use}{if using data from gobject, whether to test using expression +('expression') or cell metadata ('cell_meta')} + +\item{expression_values}{name of expression information to use} + +\item{meta_cols}{columns in cell metadata to test} + +\item{spatial_network_to_use}{spatial network to use} + +\item{wm_method}{type of weight matrix to generate from spatial network if no +weight matrix is found attached to the spatial network} + +\item{wm_name}{name of attached weight matrix to use} + +\item{node_values}{alternative method of directly supplying a set of node values} + +\item{weight_matrix}{alternative method of directly supplying a spatial weight +matrix} + +\item{test_method}{method to test values for significance (default is no +testing)} + +\item{mc_nsim}{when \code{test_method = 'monte_carlo'} this is number of simulations +to perform} + +\item{cor_name}{name to assign the results in global autocorrelation output} + +\item{return_gobject}{(default = FALSE) whether to return results appended to +metadata in the giotto object or as a data.table} + +\item{verbose}{be verbose} + +\item{enrich_name}{name to assign local autocorrelation spatial enrichment results} +} +\description{ +Find spatial autocorrelation. Note that \code{spatialAutoCorGlobal} +will return values as a data.table instead of appending information to the gobject. +\code{spatialAutoCorLocal} will append the results as a spatial enrichment object +by default. \cr +If providing external data using either the \code{node_values} and/or \code{weight_matrix} +params, the order of values provided should be the same as the ordering of the +columns and rows of the weight matrix. +} +\details{ +\strong{Global Methods:} +\itemize{ + \item{\emph{Moran's I} 'moran'} + \item{\emph{Geary's C} 'geary'} +} + +\strong{Local Methods:} +\itemize{ + \item{\emph{Local Moran's I} 'moran'} + \item{\emph{Getis-Ord Gi} 'Gi'} + \item{\emph{Getis-Ord Gi*} 'Gi*'} + \item{\emph{Local mean} 'mean'} +} +} +\section{Functions}{ +\itemize{ +\item \code{spatialAutoCorGlobal()}: Global autocorrelation (single value returned) + +\item \code{spatialAutoCorLocal()}: Local autocorrelation (values generated for each spatial ID) + +}} diff --git a/man/transpose-generic.Rd b/man/transpose-generic.Rd new file mode 100644 index 000000000..d83ff5408 --- /dev/null +++ b/man/transpose-generic.Rd @@ -0,0 +1,26 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/generics.R +\name{transpose-generic} +\alias{transpose-generic} +\alias{t} +\alias{t,spatLocsObj-method} +\alias{t,spatialNetworkObj-method} +\title{Transpose} +\usage{ +\S4method{t}{spatLocsObj}(x) + +\S4method{t}{spatialNetworkObj}(x) +} +\arguments{ +\item{x}{object to be transposed} +} +\description{ +Transpose +} +\section{Functions}{ +\itemize{ +\item \code{t(spatLocsObj)}: Transpose a spatLocObj + +\item \code{t(spatialNetworkObj)}: Transpose a spatialNeworkObj + +}} diff --git a/man/wrap_txt.Rd b/man/wrap_txt.Rd index 9fde84815..9e3c35ff2 100644 --- a/man/wrap_txt.Rd +++ b/man/wrap_txt.Rd @@ -4,7 +4,7 @@ \alias{wrap_txt} \title{Wrap text} \usage{ -wrap_txt(..., sep = " ", strWidth = 100) +wrap_txt(..., sep = " ", strWidth = 100, errWidth = FALSE) } \arguments{ \item{...}{additional params to pass} @@ -12,6 +12,8 @@ wrap_txt(..., sep = " ", strWidth = 100) \item{sep}{how to join elements of string (default is one space)} \item{strWidth}{externally set wrapping width. (default value of 100 is not effected)} + +\item{errWidth}{default = FALSE. Set strWidth to be compatible with error printout} } \description{ Wrap text diff --git a/man/xy_translate_spatial_locations.Rd b/man/xy_translate_spatial_locations.Rd deleted file mode 100644 index 703272c13..000000000 --- a/man/xy_translate_spatial_locations.Rd +++ /dev/null @@ -1,26 +0,0 @@ -% Generated by roxygen2: do not edit by hand -% Please edit documentation in R/giotto.R -\name{xy_translate_spatial_locations} -\alias{xy_translate_spatial_locations} -\title{xy_translate_spatial_locations} -\usage{ -xy_translate_spatial_locations( - spatlocs, - xtranslate = 0, - ytranslate = 0, - ztranslate = 0 -) -} -\arguments{ -\item{spatlocs}{spatial locations to use} - -\item{xtranslate}{value to translate coordinates in the positive x direction} - -\item{ytranslate}{value to translate coordinates in the positive y direction} - -\item{ztranslate}{value to translate coordinates in the positive z direction} -} -\description{ -Translate given X Y coordinates by given x and y translation values -} -\keyword{internal} From a4739c8a8d86f80c81cbf602748634b05cfe91c9 Mon Sep 17 00:00:00 2001 From: mattobny Date: Wed, 25 Jan 2023 09:46:36 -0500 Subject: [PATCH 104/129] filterGiotto behavior explanation --- R/auxiliary_giotto.R | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/R/auxiliary_giotto.R b/R/auxiliary_giotto.R index 2b8762f8c..c83556f61 100644 --- a/R/auxiliary_giotto.R +++ b/R/auxiliary_giotto.R @@ -2039,6 +2039,11 @@ filterCombinations <- function(gobject, #' @param verbose verbose #' @return giotto object #' @details The function \code{\link{filterCombinations}} can be used to explore the effect of different parameter values. +#' Please note that this function filters data in a predefined order, features, then cells. +#' After filtering in this order, certain features may be left over in the metadata with a +#' corresponding number of cells which is less than that of the threshold value of cells, +#' feat_det_in_min_cells. This behavior is explained in detail here: +#' \url{https://github.com/drieslab/Giotto/issues/500#issuecomment-1396083446} #' @export filterGiotto = function(gobject, spat_unit = NULL, From 62e09b7b91a391a0a2f46aa8ab2c7e7e719797f0 Mon Sep 17 00:00:00 2001 From: josschavezf Date: Wed, 25 Jan 2023 13:29:38 -0500 Subject: [PATCH 105/129] add spatial_interaction_spot.R --- DESCRIPTION | 5 +- NAMESPACE | 8 + NEWS.md | 5 + R/spatial_interaction_spot.R | 1972 ++++++++++++++++++++++++ man/cal_diff_per_interaction.Rd | 20 + man/cal_expr_residual.Rd | 25 + man/cellProximityEnrichmentEachSpot.Rd | 30 + man/cellProximityEnrichmentSpots.Rd | 53 + man/cell_proximity_spots.Rd | 24 + man/cell_proximity_spots_external.Rd | 22 + man/cell_proximity_spots_internal.Rd | 22 + man/do_cell_proximity_test_spot.Rd | 25 + man/do_multi_permuttest_random_spot.Rd | 23 + man/do_permuttest_original_spot.Rd | 20 + man/do_permuttest_random_spot.Rd | 22 + man/do_permuttest_spot.Rd | 24 + man/filterGiotto.Rd | 5 + man/filterICGSpot.Rd | 46 + man/findICGSpot.Rd | 89 ++ man/findICG_per_interaction_spot.Rd | 28 + man/geneExpDWLS.Rd | 20 + man/giotto_lapply.Rd | 12 + man/plotCellProximityGenesSpot.Rd | 72 + man/plotICGSpot.Rd | 49 + man/spatCellCellcomSpots.Rd | 92 ++ man/specific_CCCScores_spots.Rd | 94 ++ 26 files changed, 2806 insertions(+), 1 deletion(-) create mode 100644 R/spatial_interaction_spot.R create mode 100644 man/cal_diff_per_interaction.Rd create mode 100644 man/cal_expr_residual.Rd create mode 100644 man/cellProximityEnrichmentEachSpot.Rd create mode 100644 man/cellProximityEnrichmentSpots.Rd create mode 100644 man/cell_proximity_spots.Rd create mode 100644 man/cell_proximity_spots_external.Rd create mode 100644 man/cell_proximity_spots_internal.Rd create mode 100644 man/do_cell_proximity_test_spot.Rd create mode 100644 man/do_multi_permuttest_random_spot.Rd create mode 100644 man/do_permuttest_original_spot.Rd create mode 100644 man/do_permuttest_random_spot.Rd create mode 100644 man/do_permuttest_spot.Rd create mode 100644 man/filterICGSpot.Rd create mode 100644 man/findICGSpot.Rd create mode 100644 man/findICG_per_interaction_spot.Rd create mode 100644 man/geneExpDWLS.Rd create mode 100644 man/giotto_lapply.Rd create mode 100644 man/plotCellProximityGenesSpot.Rd create mode 100644 man/plotICGSpot.Rd create mode 100644 man/spatCellCellcomSpots.Rd create mode 100644 man/specific_CCCScores_spots.Rd diff --git a/DESCRIPTION b/DESCRIPTION index 07715a841..a247e9f2c 100644 --- a/DESCRIPTION +++ b/DESCRIPTION @@ -1,6 +1,6 @@ Package: Giotto Title: Spatial Single-Cell Transcriptomics Toolbox -Version: 3.1 +Version: 3.1.1 Authors@R: c( person("Ruben", "Dries", email = "rubendries@gmail.com", role = c("aut", "cre")), @@ -11,6 +11,8 @@ Authors@R: c( person("Guo-Cheng", "Yuan", email = "guo-cheng.yuan@mssm.edu", role = c("aut")), person("Matthew", "O'Brien", email = "mobrien2@bu.edu", + role = c("aut")), + person("Joselyn", "Chávez", email = "joselynchavezf@gmail.com", role = c("aut")) ) Maintainer: Ruben Dries @@ -142,6 +144,7 @@ Collate: 'spatial_genes.R' 'spatial_in_situ_visuals.R' 'spatial_interaction.R' + 'spatial_interaction_spot.R' 'spatial_interaction_visuals.R' 'spatial_structures.R' 'spatial_visuals.R' diff --git a/NAMESPACE b/NAMESPACE index f006eb3fd..f2dbe5b1d 100644 --- a/NAMESPACE +++ b/NAMESPACE @@ -48,6 +48,8 @@ export(calculateOverlapRaster) export(calculateOverlapSerial) export(cellProximityBarplot) export(cellProximityEnrichment) +export(cellProximityEnrichmentEachSpot) +export(cellProximityEnrichmentSpots) export(cellProximityHeatmap) export(cellProximityNetwork) export(cellProximitySpatPlot) @@ -147,6 +149,7 @@ export(filterDistributions) export(filterGiotto) export(filterICF) export(filterICG) +export(filterICGSpot) export(filterInteractionChangedFeats) export(filterInteractionChangedGenes) export(findCPG) @@ -155,6 +158,7 @@ export(findGiniMarkers) export(findGiniMarkers_one_vs_all) export(findICF) export(findICG) +export(findICGSpot) export(findInteractionChangedFeats) export(findInteractionChangedGenes) export(findMarkers) @@ -165,6 +169,7 @@ export(findNetworkNeighbors) export(findScranMarkers) export(findScranMarkers_one_vs_all) export(gefToGiotto) +export(geneExpDWLS) export(get10Xmatrix) export(get10Xmatrix_h5) export(getBalancedSpatCoexpressionFeats) @@ -221,6 +226,7 @@ export(plotCPF) export(plotCPG) export(plotCellProximityFeats) export(plotCellProximityGenes) +export(plotCellProximityGenesSpot) export(plotCombineCCcom) export(plotCombineCPG) export(plotCombineCellCellCommunication) @@ -232,6 +238,7 @@ export(plotGiottoImage) export(plotHeatmap) export(plotICF) export(plotICG) +export(plotICGSpot) export(plotInteractionChangedFeats) export(plotInteractionChangedGenes) export(plotInteractivePolygons) @@ -334,6 +341,7 @@ export(slot) export(smoothGiottoPolygons) export(spark) export(spatCellCellcom) +export(spatCellCellcomSpots) export(spatCellPlot) export(spatCellPlot2D) export(spatDeconvPlot) diff --git a/NEWS.md b/NEWS.md index 9e01afffd..c3f17bbef 100644 --- a/NEWS.md +++ b/NEWS.md @@ -1,3 +1,8 @@ +# Giotto Suite 3.1.1 (2023-01-25) + +## Added +- Add spatial_interaction_spot.R with functions adapted from master branch for working with the Giotto suite object. + # TBD RELEASE ## Breaking Changes diff --git a/R/spatial_interaction_spot.R b/R/spatial_interaction_spot.R new file mode 100644 index 000000000..b3589e2fe --- /dev/null +++ b/R/spatial_interaction_spot.R @@ -0,0 +1,1972 @@ +## Giotto cell type enrichment for spots functions #### + +# * #### +# cell type proximity for spots #### + +#' @title cell_proximity_spots_internal +#' @name cell_proximity_spots_internal +#' @description Compute cell-cell interactions observed value inner each spot +#' @param cell_IDs cell_IDs get from gobject@cell_ID +#' @param dwls_values data.table of cell type enrichment in each spot and multiply +#' by cell number in each spot +#' @return List of cell proximity observed value in data.table format. Columns: +#' unified_int, internal value, type_int. +#' @keywords internal +cell_proximity_spots_internal = function(cell_IDs, + dwls_values){ + + proximity_dt = data.table::data.table() + # calculate proximity for each spot + for (cell_i in 1:length(cell_IDs)){ + cell_ID = cell_IDs[cell_i] + # dwls value for one spot and remove 0 cell type + dwls_spot = dwls_values[cell_ID,] + dwls_spot = dwls_spot[dwls_spot > 0] + + # calculate proximity of same cell type (A==B) + same_ct = data.table::data.table() + if (length(dwls_spot) >= 1){ + same_ct = (dwls_spot-1) * dwls_spot / 2 + # transfer format + unified_int_same = names(same_ct) + unified_int_same = paste0(unified_int_same,'--',unified_int_same) + same_ct = data.table::data.table('unified_int' = unified_int_same,'internal' = same_ct) + } + + # calculate proximity of different cell type (A==B) + diff_ct = data.table::data.table() + if (length(dwls_spot) >= 2){ + diff_ct = dwls_spot %o% dwls_spot + #modifiy duplicate value + diag(diff_ct) = NA + diff_ct[lower.tri(diff_ct)] = NA + # transfer format to data.table + diff_ct = data.table::as.data.table(reshape2::melt(diff_ct)) + diff_ct = diff_ct[value != 'NA' ] + diff_ct[, c('Var1', 'Var2') := lapply(.SD, as.character),.SDcols = c('Var1', 'Var2')] + diff_ct[, unified_int := ifelse(Var1 < Var2, paste0(Var1,'--',Var2), paste0(Var2,'--',Var1))] + diff_ct = diff_ct[, c('unified_int', 'value')] + data.table::setnames(diff_ct, old = c('value'), new = c('internal')) + } + + # merge spot proximity to proximity data.table + proximity_dt = rbind(proximity_dt, same_ct, diff_ct) + } + + proximity_dt = proximity_dt[internal > 0] + proximity_dt[, internal := sum(internal), by = c('unified_int')] + proximity_dt = unique(proximity_dt) + + return(proximity_dt) +} + + +#' @title cell_proximity_spots_external +#' @name cell_proximity_spots_external +#' @description Compute cell-cell interactions observed value for interacted spots +#' @param pairs data.table of paired spots. Format: cell_ID1, cell_ID2, N +#' @param dwls_values data.table of cell type enrichment in each spot and multiply +#' by cell number in each spot +#' @return List of cell proximity observed value in data.table format. Columns: +#' unified_int, internal value, type_int. +#' @keywords internal +cell_proximity_spots_external = function(pairs, + dwls_values){ + + cell_IDs = unique(c(pairs$from, pairs$to)) + pairs = pairs[, .N, by = c('from','to')] + # add internal pairs to make full matrix + pairs_spots = data.table::data.table(from = cell_IDs, to = cell_IDs, N = 0) + pairs_balance = data.table::data.table(from = pairs$to, to = pairs$from, N = pairs$N) + pairs_for_mat = rbind(pairs_spots, pairs, pairs_balance) + pairs_for_mat = pairs_for_mat[, .N, by = c('from','to')] + + # make square matrix of interaction between spots + pairs_mat = reshape2::acast(pairs_for_mat, from ~ to, value.var = 'N' ,fill = 0) + pairs_mat = pairs_mat[cell_IDs,cell_IDs] + + #calculate cell-tyep/cell-type interactions + dwls_sub = dwls_values[cell_IDs,] + proximity_dt = data.table::data.table() + cts = colnames(dwls_sub) + cts = sort(cts) + for (i in 1:length(cts)){ + ct1 = cts[i] + dwls_ct1 = dwls_sub[, ct1] + + for (j in i:length(cts)){ + ct2 = cts[j] + dwls_ct2 = dwls_sub[, ct2] + if (i == j ){f = 0.5}else{f=1} + proximity_2cts = dwls_ct1 %o% dwls_ct2 * pairs_mat * f + proximity_2cts = sum(proximity_2cts) + proximity_2cts = data.table::data.table(unified_int = paste0(ct1,'--',ct2), + external = proximity_2cts) + proximity_dt = rbind(proximity_dt, proximity_2cts) + } + } + return(proximity_dt) +} + + +#' @title cell_proximity_spots +#' @name cell_proximity_spots +#' @description Compute cell-cell interactions observed value for internal and external spots +#' @param cell_IDs cell_IDs to calculate internal cell-type/cell-type interactions +#' @param pairs data.table of paired spots. Format: cell_ID1, cell_ID2, N +#' @param dwls_values data.table of cell type enrichment in each spot and multiply +#' by cell number in each spot +#' @return List of cell proximity observed value in data.table format. Columns: +#' unified_int, type_int, V1, external, internal. +#' @keywords internal +cell_proximity_spots = function(cell_IDs, + pairs_external, + dwls_values){ + + # compute cell-type/cell-type interactions in each spot (internal) + if (length(cell_IDs) > 0){ + proximity_in = cell_proximity_spots_internal(cell_IDs = cell_IDs, + dwls_values = dwls_values) + } + + # compute cell-type/cell-type interactions between spots (external) + # get paired spots barcodes + proximity_ex = cell_proximity_spots_external(pairs = pairs_external, + dwls_values = dwls_values) + + if (length(cell_IDs) > 0) { + proximity_dt = merge(proximity_ex, proximity_in, by= 'unified_int', all=TRUE) + }else{ + proximity_dt = proximity_ex[, 'internal' := 0] + } + proximity_dt[is.na(proximity_dt)] = 0 + proximity_dt[, V1 := internal + external] + + proximity_dt[, s1 := strsplit(as.character(unified_int), split = '--')[[1]][1], by = 1:nrow(proximity_dt)] + proximity_dt[, s2 := strsplit(as.character(unified_int), split = '--')[[1]][2], by = 1:nrow(proximity_dt)] + proximity_dt[, type_int := ifelse(s1 == s2, 'homo', 'hetero')] + proximity_dt = proximity_dt[, c('unified_int', 'type_int', 'V1', 'external', 'internal')] + return(proximity_dt) +} + + +#' @title cellProximityEnrichmentSpots +#' @name cellProximityEnrichmentSpots +#' @description Compute cell-cell interaction enrichment for spots (observed vs expected) +#' @param gobject giotto object +#' @param spatial_network_name name of spatial network to use +#' @param cluster_column name of column to use for clusters +#' @param cells_in_spot cell number in each spot +#' @param number_of_simulations number of simulations to create expected observations +#' @param adjust_method method to adjust p.values +#' @param set_seed use of seed +#' @param seed_number seed number to use +#' @return List of cell Proximity scores (CPscores) in data.table format. The first +#' data.table (raw_sim_table) shows the raw observations of both the original and +#' simulated networks. The second data.table (enrichm_res) shows the enrichment results. +#' @details Spatial proximity enrichment or depletion between pairs of cell types +#' is calculated by calculating the observed over the expected frequency +#' of cell-cell proximity interactions. The expected frequency is the average frequency +#' calculated from a number of spatial network simulations. Each individual simulation is +#' obtained by reshuffling the cell type labels of each node (spot) +#' in the spatial network. +#' @export +cellProximityEnrichmentSpots <- function(gobject, + spat_unit = NULL, + feat_type = NULL, + spatial_network_name = 'spatial_network', + cluster_column = 'cell_ID', + cells_in_spot = 1, + number_of_simulations = 100, + adjust_method = c("none", "fdr", "bonferroni","BH", + "holm", "hochberg", "hommel", + "BY"), + set_seed = TRUE, + seed_number = 1234) { + + # p.adj test + sel_adjust_method = match.arg(adjust_method, choices = c("none", "fdr", "bonferroni","BH", + "holm", "hochberg", "hommel", + "BY")) + + spatial_network_annot = annotateSpatialNetwork(gobject = gobject, + spat_unit = spat_unit, + feat_type = feat_type, + spatial_network_name = spatial_network_name, + cluster_column = cluster_column) + + # data.table variables + unified_cells = type_int = N = NULL + + spatial_network_annot = sort_combine_two_DT_columns(spatial_network_annot, 'to', 'from', 'unified_cells') + spatial_network_annot = spatial_network_annot[!duplicated(unified_cells)] + + # exact spatial_enrichment matrix + dwls_values = get_spatial_enrichment(gobject = gobject, + spat_unit = spat_unit, + feat_type = feat_type, + enrichm_name = 'DWLS', + output = 'data.table') + data.table::setDF(dwls_values) + rownames_dwls = dwls_values[,'cell_ID'] + dwls_values = as.matrix(dwls_values[,-1]) + rownames(dwls_values) = rownames_dwls + dwls_values_adjust = dwls_values * cells_in_spot + + # compute cell-type/cell-type interactions + print("1/5 Computing cell-type/cell-type interactions") + + orig_pairs_external = spatial_network_annot[, .N, by = c('from', 'to')] + table_orig_results = cell_proximity_spots(cell_IDs = pDataDT(gobject)$cell_ID, + pairs_external = orig_pairs_external, + dwls_values = dwls_values_adjust) + table_orig_results[, orig := 'original'] + table_orig_results[, round := 'original'] + + # make simulated network + print("2/5 Make simulated network") + + sample_dt = make_simulated_network(gobject = gobject, + spat_unit = spat_unit, + feat_type = feat_type, + spatial_network_name = spatial_network_name, + cluster_column = cluster_column, + number_of_simulations = number_of_simulations, + set_seed = set_seed, + seed_number = seed_number) + + # method for get simulation cell-type/cell-type interaction for each round + data.table::setnames(sample_dt, old = c('s1', 's2'), new = c('from', 'to')) + table_sim_results = NULL + for(sim in 1:number_of_simulations) { + r = paste0('sim',sim) + sim_pairs = sample_dt[round == r, c("from","to")] + + sim_cell_IDs = unique(sim_pairs[from == to, from]) + sim_pairs_ex = sim_pairs[from != to, ] + sim_pairs_ex[, N :=1] + + sim_dt_round = cell_proximity_spots(cell_IDs = sim_cell_IDs, + pairs_external = sim_pairs_ex, + dwls_values = dwls_values_adjust) + + sim_dt_round[, orig := 'simulations'] + sim_dt_round[, round := r] + table_sim_results = rbind(table_sim_results, sim_dt_round) + } + + + table_results = rbind(table_orig_results, table_sim_results) + + # add missing combinations from original or simulations + # probably not needed anymore + all_sim_ints = as.character(unique(table_results[orig == 'simulations']$unified_int)) + all_orig_ints = as.character(unique(table_results[orig == 'original']$unified_int)) + missing_in_orig = all_sim_ints[!all_sim_ints %in% all_orig_ints] + missing_in_sim = all_orig_ints[!all_orig_ints %in% all_sim_ints] + create_missing_for_orig = table_results[unified_int %in% missing_in_orig] + create_missing_for_orig = unique(create_missing_for_orig[, c('orig', 'V1') := list('original', 0)]) + create_missing_for_sim = table_results[unified_int %in% missing_in_sim] + create_missing_for_sim = unique(create_missing_for_sim[, c('orig', 'V1') := list('simulations', 0)]) + + table_results <- do.call('rbind', list(table_results, create_missing_for_orig, create_missing_for_sim)) + + ## p-values + print("3/5 Calculating p-values") + + combo_list = rep(NA, length = length(unique(table_results$unified_int))) + p_high = rep(NA, length = length(unique(table_results$unified_int))) + p_low = rep(NA, length = length(unique(table_results$unified_int))) + + for(int_combo in 1:length(unique(table_results$unified_int))) { + + this_combo = as.character(unique(table_results$unified_int)[int_combo]) + + sub = table_results[unified_int == this_combo] + + orig_value = sub[orig == 'original']$V1 + sim_values = sub[orig == 'simulations']$V1 + + length_simulations = length(sim_values) + if(length_simulations != number_of_simulations) { + additional_length_needed = number_of_simulations-length_simulations + sim_values = c(sim_values, rep(0, additional_length_needed)) + #length_simulations = c(length_simulations, rep(0, additional_length_needed)) + } + + p_orig_higher = 1 - (sum((orig_value+1) > (sim_values+1))/number_of_simulations) + p_orig_lower = 1 - (sum((orig_value+1) < (sim_values+1))/number_of_simulations) + + combo_list[[int_combo]] = this_combo + p_high[[int_combo]] = p_orig_higher + p_low[[int_combo]] = p_orig_lower + + } + res_pvalue_DT = data.table::data.table(unified_int = as.vector(combo_list), p_higher_orig = p_high, p_lower_orig = p_low) + + + # depletion or enrichment in barplot format + print("4/5 Depletion or enrichment in barplot format") + + table_mean_results <- table_results[, .(mean(V1)), by = c('orig', 'unified_int', 'type_int')] + table_mean_results_dc <- data.table::dcast.data.table(data = table_mean_results, formula = type_int+unified_int~orig, value.var = 'V1') + table_mean_results_dc[, original := ifelse(is.na(original), 0, original)] + table_mean_results_dc[, enrichm := log2((original+1)/(simulations+1))] + + + table_mean_results_dc <- merge(table_mean_results_dc, res_pvalue_DT, by = 'unified_int') + data.table::setorder(table_mean_results_dc, enrichm) + table_mean_results_dc[, unified_int := factor(unified_int, unified_int)] + + # adjust p-values for mht + + print("5/5 Calculating adjust p-values for mht") + + # data.table variables + p.adj_higher = p.adj_lower = p_lower_orig = p_higher_orig = PI_value = int_ranking = NULL + + table_mean_results_dc[, p.adj_higher := stats::p.adjust(p_higher_orig, method = sel_adjust_method)] + table_mean_results_dc[, p.adj_lower := stats::p.adjust(p_lower_orig, method = sel_adjust_method)] + + + table_mean_results_dc[, PI_value := ifelse(p.adj_higher <= p.adj_lower, + -log10(p.adj_higher+(1/number_of_simulations))*enrichm, + -log10(p.adj_lower+(1/number_of_simulations))*enrichm)] + data.table::setorder(table_mean_results_dc, PI_value) + + # order + table_mean_results_dc <- table_mean_results_dc[order(-PI_value)] + table_mean_results_dc[, int_ranking := 1:.N] + + return(list(raw_sim_table = table_results, enrichm_res = table_mean_results_dc)) +} + + + + + +# * #### +# cell proximity with gene expression #### + +#' @title geneExpDWLS +#' @name geneExpDWLS +#' @description Compute predicted gene expression value by spatialDWSL results and +#' average gene expression for cell type +#' @param gobject gottio object +#' @param ave_celltype_exp data.table of gene expression in each cell type +#' @return matrix +#' @export +geneExpDWLS = function(gobject, + spat_unit = NULL, + feat_type = NULL, + ave_celltype_exp){ + + # exact spatial_enrichment matrix + dwls_values = get_spatial_enrichment(gobject, + spat_unit = spat_unit, + feat_type = feat_type, + enrichm_name = 'DWLS', + output = 'data.table') + + # 1. check if cell_type_vector and matrix are compatible + if(ncol(ave_celltype_exp) != ncol(dwls_values) - 1) { + stop('ncol(ave_celltype_exp) needs to be the same as ncol(dwls_values) - 1') + } + + cell_types = colnames(ave_celltype_exp) + data.table::setcolorder(dwls_values,c('cell_ID',cell_types)) + + # 2. for each spot + # calculate dwls predicted expression for genes + expMatrixDWLS = matrix(data = NA, + nrow = nrow(ave_celltype_exp), + ncol = nrow(dwls_values)) + + average_exp = as.matrix(ave_celltype_exp) + for(spot_i in 1:nrow(dwls_values)){ + spot = dwls_values[spot_i,1] + spot_dwls = dwls_values[spot_i, -1] + data.table::setDF(spot_dwls) + spot_dwls = as.vector(t(spot_dwls)[,1]) + + spot_exp = average_exp %*% spot_dwls + + expMatrixDWLS[, spot_i] = spot_exp + } + rownames(expMatrixDWLS) = rownames(ave_celltype_exp) + colnames(expMatrixDWLS) = dwls_values$cell_ID + + return(expMatrixDWLS) +} + + +#' @title cal_expr_residual +#' @name cal_expr_residual +#' @description Calculate gene expression residual (observed_exp - DWLS_predicted) +#' @param gobject giotto object +#' @param expression_values expression values to use +#' @param ave_celltype_exp average expression matrix in cell types +#' @keywords internal +cal_expr_residual <- function(gobject, + spat_unit = NULL, + feat_type = NULL, + expression_values = c('normalized', 'scaled', 'custom'), + ave_celltype_exp) { + + # expression data + values = match.arg(expression_values, choices = c('normalized', 'scaled', 'custom')) + # expr_observed = get_expression_values(gobject = gobject, + # values = expression_values, + # output = 'matrix') + expr_observed = slot(gobject@expression[[spat_unit]][[feat_type]][[values]], 'exprMat') + + # Compute predicted gene expression value + expr_predicted = geneExpDWLS(gobject = gobject, + spat_unit = spat_unit, + feat_type = feat_type, + ave_celltype_exp = ave_celltype_exp) + + # Get the difference expression matrix between observed and predicted expression + intersect_gene = intersect(rownames(expr_predicted), rownames(expr_observed)) + expr_residual = expr_observed[intersect_gene,] - expr_predicted[intersect_gene,] + expr_residual = as.matrix(expr_residual) + + return(expr_residual) +} + + +#' @title cellProximityEnrichmentEachSpot +#' @name cellProximityEnrichmentEachSpot +#' @description Compute cell-cell interaction enrichment for each spot with its +#' interacted spots (observed) +#' @param gobject giotto object +#' @param feat_type feature type +#' @param spatial_network_name name of spatial network to use +#' @param cluster_column name of column to use for clusters +#' @return matrix that rownames are cell-cell interaction pairs and colnames are cell_IDs +#' @export +cellProximityEnrichmentEachSpot <- function(gobject, + spat_unit = NULL, + feat_type = NULL, + spatial_network_name = 'spatial_network', + cluster_column = 'cell_ID') { + + + spatial_network_annot = annotateSpatialNetwork(gobject = gobject, + spat_unit = spat_unit, + feat_type = feat_type, + spatial_network_name = spatial_network_name, + cluster_column = cluster_column) + + # data.table variables + unified_cells = type_int = N = NULL + + spatial_network_annot = sort_combine_two_DT_columns(spatial_network_annot, 'to', 'from', 'unified_cells') + spatial_network_annot = spatial_network_annot[!duplicated(unified_cells)] + + # exact spatial_enrichment matrix + dwls_values = get_spatial_enrichment(gobject = gobject, + spat_unit = spat_unit, + feat_type = feat_type, + enrichm_name = 'DWLS', + output = 'data.table') + data.table::setDF(dwls_values) + rownames_dwls = dwls_values[,'cell_ID'] + dwls_values = as.matrix(dwls_values[,-1]) + rownames(dwls_values) = rownames_dwls + + # calculate cell-cell interaction with gene expression in each spot + # proximity_spots is the + # get cell-cell types pairs + cts = colnames(dwls_values) + ct_pairs = data.table::data.table(V1 = rep(cts,each = length(cts)), V2 = rep(cts,length(cts))) + ct_pairs[, unified_int := paste0(V1,'--',V2), by = 1:nrow(ct_pairs)] + unified_int = ct_pairs$unified_int + + + # get paired spots barcodes + orig_pairs = spatial_network_annot[, .N, by = c('from', 'to')] + cell_IDs = unique(c(orig_pairs$from, orig_pairs$to)) + + # make matrix that rows are cell-cell types and columns are cell_IDs + proximityMat = matrix(data = 0, + nrow = length(unified_int), + ncol = length(cell_IDs)) + + rownames(proximityMat) = unified_int + colnames(proximityMat) = cell_IDs + + # for each spot, calculate cell type proximity to it + for (cell_i in 1:length(cell_IDs)){ + cell_ID = cell_IDs[cell_i] + spot_pairs = orig_pairs[from == cell_ID | to == cell_ID] + spot_pairs[, int_cell_IDS := ifelse(from==cell_ID, to, from)] + int_num = spot_pairs$N + + dwls_target_cell = dwls_values[cell_ID,] + dwls_int_cells = dwls_values[spot_pairs$int_cell_IDS,] + + # filter 0 and kept the data type + # rowSum(dwls) = c(1,1,1,1.....) + idx1 = which(dwls_target_cell > 0) #length(idx) must > 0 + dwls_target_cell = dwls_target_cell[idx1] + + if (length(int_num) > 1){ + idx2 = which(colSums(dwls_int_cells) > 0) + dwls_int_cells = dwls_int_cells[, idx2] + + # all the interacted cells dwls have same cell type with proportion=1 + if (length(idx2) == 1){ + dwls_int_cells = matrix(dwls_int_cells, ncol = 1, + dimnames = list(spot_pairs$int_cell_IDS,names(idx2))) + } + + } else{ + # target cell only contain 1 inteacted cell + idx2 = which(dwls_int_cells > 0) + dwls_int_cells = dwls_int_cells[idx2] + dwls_int_cells = matrix(dwls_int_cells,nrow=1,byrow = TRUE, + dimnames = list(spot_pairs$int_cell_IDS,names(dwls_int_cells))) + } + + + spot_proximity = dwls_target_cell %o% (dwls_int_cells * int_num) + spot_proximity = apply(spot_proximity, 3, rowSums) + if (length(dwls_target_cell) == 1){ + # change to the right data class + spot_proximity = matrix(spot_proximity,nrow=1,byrow = TRUE, + dimnames = list(names(dwls_target_cell),names(spot_proximity))) + + } + spot_proximity = reshape2::melt(spot_proximity) + spot_proximity = data.table::data.table(spot_proximity) + spot_proximity[, c('Var1', 'Var2') := lapply(.SD, as.character),.SDcols = c('Var1', 'Var2')] + spot_proximity[, unified_int := paste0(Var1,'--',Var2)] + + # add to proximityMat(matrix) + proximityMat[spot_proximity$unified_int, cell_i] = spot_proximity$value + } + return(proximityMat) +} + +#' @title cal_diff_per_interaction +#' @name cal_diff_per_interaction +#' @description calculate correlation between expression residual and +#' cell proximity score of selected cell for spots +#' @keywords internal +cal_diff_per_interaction <- function(sel_int, + other_ints, + select_ind, + other_ind, + proximityMat, + expr_residual){ + + # get data + + prox_sel = proximityMat[sel_int, select_ind] + prox_sel = as.matrix(prox_sel) + expr_sel = expr_residual[, select_ind] + + prox_other = proximityMat[other_ints,other_ind] + prox_other = prox_other[rowSums(prox_other) != 0, ] + expr_other = expr_residual[, other_ind] + + # calculate pcc between expresidiual and proximity + pcc_sel = cor(t(expr_sel), prox_sel) + + pcc_other = cor(t(expr_other), t(prox_other)) + pcc_other = rowMeans(pcc_other) + + genes = rownames(pcc_sel) + pcc_dt = data.table::data.table(genes = genes, + pcc_sel = as.vector(pcc_sel), + pcc_other = pcc_other[genes]) + + pcc_dt[, pcc_diff := pcc_sel - pcc_other] + + # calculate mean exression residual + expr_sel_mean = rowMeans(expr_sel) + expr_other_mean = rowMeans(expr_other) + expr_residual_dt = data.table::data.table(genes = genes, + sel = expr_sel_mean[genes], + other = expr_other_mean[genes]) + expr_residual_dt[, diff := sel - other] + + results_dt = data.table::merge.data.table(expr_residual_dt, pcc_dt, by = 'genes') + + return(results_dt) +} + +#' @title do_permuttest_original_spot +#' @name do_permuttest_original_spot +#' @description calculate original values for spots +#' @keywords internal +do_permuttest_original_spot <- function(sel_int, + other_ints, + select_ind, + other_ind, + name = 'orig', + proximityMat, + expr_residual) { + + resultsDT = cal_diff_per_interaction(sel_int = sel_int, + other_ints = other_ints, + select_ind = select_ind, + other_ind = other_ind, + proximityMat = proximityMat, + expr_residual = expr_residual) + resultsDT[, name := name] + return(resultsDT) +} + +#' @title do_permuttest_random_spot +#' @name do_permuttest_random_spot +#' @description calculate random values for spots +#' @keywords internal +do_permuttest_random_spot <- function(sel_int, + other_ints, + select_ind, + other_ind, + name = 'perm_1', + proximityMat, + expr_residual, + set_seed = TRUE, + seed_number = 1234) { + + # data.table variables + genes = NULL + + l_sel_int = length(sel_int) + l_other_ints = length(other_ints) + l_select_ind = length(select_ind) + l_other_ind = length(other_ind) + + all_IDs = colnames(proximityMat) + all_ints = rownames(proximityMat) + all_ints = all_ints[!rownames(proximityMat) %in% sel_int] + + if(set_seed == TRUE) { + set.seed(seed = seed_number) + } + random_sel_int = sample(all_ints, size = l_sel_int, replace = F) + random_other_ints = sample(all_ints, size = l_other_ints, replace = F) + + # keep the random selete not all the zeros + prox = proximityMat[random_sel_int,] + prox = prox[prox>0] + random_select = c(sample(all_IDs, size = l_select_ind - 1, replace = F), names(prox[1])) + random_other = c(sample(all_IDs, size = l_other_ind, replace = F), names(prox[length(prox)])) + + resultsDT = cal_diff_per_interaction(sel_int = random_sel_int, + other_ints = random_other_ints, + select_ind = random_select, + other_ind = random_other, + proximityMat = proximityMat, + expr_residual = expr_residual) + resultsDT[, name := name] + + return(resultsDT) +} + + +#' @title do_multi_permuttest_random_spot +#' @name do_multi_permuttest_random_spot +#' @description calculate multiple random values for spots +#' @keywords internal +do_multi_permuttest_random_spot = function(sel_int, + other_ints, + select_ind, + other_ind, + proximityMat, + expr_residual, + n = 100, + cores = 2, + set_seed = TRUE, + seed_number = 1234) { + + if(set_seed == TRUE) { + seed_number_list = seed_number:(seed_number + (n-1)) + } + + result = giotto_lapply(X = 1:n, cores = cores, fun = function(x) { + + seed_number = seed_number_list[x] + + perm_rand = do_permuttest_random_spot(sel_int = sel_int, + other_ints = other_ints, + select_ind = select_ind, + other_ind = other_ind, + name = paste0('perm_', x), + proximityMat = proximityMat, + expr_residual = expr_residual, + set_seed = set_seed, + seed_number = seed_number) + + }) + + final_result = do.call('rbind', result) + +} + +#' @title do_permuttest_spot +#' @name do_permuttest_spot +#' @description Performs permutation test on subsets of a matrix for spots +#' @keywords internal +do_permuttest_spot = function(sel_int, + other_ints, + select_ind, + other_ind, + proximityMat, + expr_residual, + n_perm = 100, + adjust_method = 'fdr', + cores = 2, + set_seed = TRUE, + seed_number = 1234) { + + # data.table variables + log2fc_diff = log2fc = sel = other = genes = p_higher = p_lower = perm_sel = NULL + perm_other = perm_log2fc = perm_diff = p.value = p.adj = NULL + + ## original data + original = do_permuttest_original_spot(sel_int = sel_int, + other_ints = other_ints , + select_ind = select_ind, + other_ind = other_ind, + name = 'orig', + proximityMat = proximityMat, + expr_residual = expr_residual) + + ## random permutations + random_perms = do_multi_permuttest_random_spot(sel_int = sel_int, + other_ints = other_ints, + select_ind = select_ind, + other_ind = other_ind, + proximityMat = proximityMat, + expr_residual = expr_residual, + n = n_perm, + cores = cores, + set_seed = set_seed, + seed_number = seed_number) + + ## + #random_perms[, log2fc_diff := rep(original$log2fc, n_perm) - log2fc] + random_perms[, c('perm_sel', 'perm_other', 'perm_pcc_sel', 'perm_pcc_diff') := list(mean(sel), mean(other), mean(pcc_sel), mean(pcc_diff)), by = genes] + + ## get p-values + random_perms[, p_higher := sum(pcc_diff > 0), by = genes] + random_perms[, p_higher := 1-(p_higher/n_perm)] + random_perms[, p_lower := sum(pcc_diff < 0), by = genes] + random_perms[, p_lower := 1-(p_lower/n_perm)] + + ## combine results permutation and original + random_perms_res = unique(random_perms[,.(genes, perm_sel, perm_other, perm_pcc_sel, perm_pcc_diff, p_higher, p_lower)]) + results_m = data.table::merge.data.table(random_perms_res, original[,.(genes, sel, other, diff, pcc_sel, pcc_other, pcc_diff)], by = 'genes') + + # select lowest p-value and perform p.adj + results_m[, p.value := ifelse(p_higher <= p_lower, p_higher, p_lower)] + results_m[, p.adj := stats::p.adjust(p.value, method = adjust_method)] + + results_m = results_m[,.(genes, sel, other, pcc_sel, pcc_other, pcc_diff, p.value, p.adj, perm_sel, perm_other, perm_pcc_sel, perm_pcc_diff)] + setorder(results_m, p.adj, -pcc_diff) + + return(results_m) + +} + + +#' @title do_cell_proximity_test_spot +#' @name do_cell_proximity_test_spot +#' @description Performs a selected differential test on subsets of a matrix for spots +#' @keywords internal +do_cell_proximity_test_spot = function(sel_int, + other_ints, + select_ind, + other_ind, + proximityMat, + expr_residual, + diff_test, + n_perm = 100, + adjust_method = 'fdr', + cores = 2, + set_seed = TRUE, + seed_number = 1234) { + + # get parameters + diff_test = match.arg(diff_test, choices = c('permutation', 'limma', 't.test', 'wilcox')) + adjust_method = match.arg(adjust_method, choices = c("bonferroni","BH", "holm", "hochberg", "hommel", + "BY", "fdr", "none")) + + + if(diff_test == 'permutation') { + result = do_permuttest_spot(sel_int = sel_int, + other_ints = other_ints, + select_ind = select_ind, + other_ind = other_ind, + proximityMat = proximityMat, + expr_residual = expr_residual, + n_perm = n_perm, + adjust_method = adjust_method, + cores = cores, + set_seed = set_seed, + seed_number = seed_number) + + } + return(result) + +} + +#' @title findICG_per_interaction_spot +#' @name findICG_per_interaction_spot +#' @description Identifies genes that are differentially expressed due to proximity to other cell types for spots. +#' @keywords internal +findICG_per_interaction_spot <- function(sel_int, + all_ints, + proximityMat, + expr_residual, + dwls_values, + dwls_cutoff = 0.001, + CCI_cell_score = 0.01, + minimum_unique_cells = 1, + minimum_unique_int_cells = 1, + diff_test = 'permutation', + n_perm = 100, + adjust_method = 'fdr', + cores = 2, + set_seed = TRUE, + seed_number = 1234){ + + sel_ct = strsplit(sel_int, '--')[[1]][1] + int_ct = strsplit(sel_int, '--')[[1]][2] + + # filter out cells that without these two cellsltype + prox_sel = proximityMat[sel_int,] + prox_sel = prox_sel[which(prox_sel != 0)] + prox_sel = prox_sel[which(prox_sel > CCI_cell_score)] + spec_IDs = names(prox_sel) + + # find other cells contribution to cell type + dwls_all_cell = dwls_values[, sel_ct] + dwls_all_cell = dwls_all_cell[dwls_all_cell > dwls_cutoff] + all_IDs = intersect(names(dwls_all_cell), colnames(proximityMat)) + other_IDs = setdiff(all_IDs, spec_IDs) + + other_ints = all_ints[cell_type == sel_ct]$unified_int + other_ints = other_ints[-which(other_ints == sel_int)] + + ## do not continue if too few cells ## + if(length(spec_IDs) < minimum_unique_cells | length(other_IDs) < minimum_unique_cells) { + result = NULL + } else { + result = do_cell_proximity_test_spot(sel_int = sel_int, + other_ints = other_ints, + select_ind = spec_IDs, + other_ind = other_IDs, + proximityMat = proximityMat, + expr_residual = expr_residual, + diff_test = diff_test, + n_perm = n_perm, + adjust_method = adjust_method, + cores = cores, + set_seed = set_seed, + seed_number = seed_number) + + result[, cell_type := sel_ct] + result[, int_cell_type := int_ct] + result[, nr_select := length(spec_IDs)] + result[, int_nr_select := length(other_IDs)] + result[, unif_int := sel_int] + } + + return(result) + +} + +#' @title giotto_lapply +#' @keywords internal +giotto_lapply = function(X, cores = NA, fun, ...) { + + # get type of os + os = .Platform$OS.type + + # set number of cores automatically, but with limit of 10 + cores = determine_cores(cores) + + if(os == 'unix') { + save_list = parallel::mclapply(X = X, mc.cores = cores, + FUN = fun, ...) + } else if(os == 'windows') { + save_list = parallel::mclapply(X = X, mc.cores = 1, + FUN = fun, ...) + + # !! unexplainable errors are returned for some nodes !! # + # currently disabled # + #cl <- parallel::makeCluster(cores) + #save_list = parallel::parLapply(cl = cl, X = X, + # fun = fun, ...) + } + + return(save_list) +} + + +#' @title findICGSpot +#' @name findICGSpot +#' @description Identifies cell-to-cell Interaction Changed Genes (ICG) for spots, +#' i.e. genes expression residual that are different due to proximity to other cell types. +#' @param gobject giotto object +#' @param expression_values expression values to use +#' @param ave_celltype_exp averege gene expression in each cell type +#' @param selected_genes subset of selected genes (optional) +#' @param spatial_network_name name of spatial network to use +#' @param minimum_unique_cells minimum number of target cells required +#' @param minimum_unique_int_cells minimum number of interacting cells required +#' @param CCI_cell_score cell proximity score to filter no interacted cell +#' @param dwls_cutoff cell type proportion cutoff to label the cell +#' @param diff_test which differential expression test +#' @param adjust_method which method to adjust p-values +#' @param nr_permutations number of permutations if diff_test = permutation +#' @param do_parallel run calculations in parallel with mclapply +#' @param cores number of cores to use if do_parallel = TRUE +#' @param set_seed set a seed for reproducibility +#' @param seed_number seed number +#' @return cpgObject that contains the differential gene scores +#' @details Function to calculate if genes expreesion residual are differentially expressed in cell types +#' when they interact (approximated by physical proximity) with other cell types. +#' Gene expression residual calculated as: +#' (observed expression in spot - cell_type_proportion * average_expressed_in_cell_type) +#' The results data.table in the cpgObject contains - at least - the following columns: +#' \itemize{ +#' \item{genes:}{ All or selected list of tested genes} +#' \item{sel:}{ average gene expression residual in the interacting cells from the target cell type } +#' \item{other:}{ average gene expression residual in the NOT-interacting cells from the target cell type } +#' \item{pcc_sel:}{ correlation between cell proximity score and expression residual in the interacting cells from the target cell type} +#' \item{pcc_other:}{ correlation between cell proximity score and expression residual in the NOT-interacting cells from the target cell type } +#' \item{pcc_diff:}{ correlation difference between sel and other} +#' \item{p.value:}{ associated p-value} +#' \item{p.adj:}{ adjusted p-value} +#' \item{cell_type:}{ target cell type} +#' \item{int_cell_type:}{ interacting cell type} +#' \item{nr_select:}{ number of cells for selected target cell type} +#' \item{int_nr_select:}{ number of cells for interacting cell type} +#' \item{unif_int:}{ cell-cell interaction} +#' } +#' @export +findICGSpot <- function(gobject, + spat_unit = NULL, + feat_type = NULL, + expression_values = c('normalized', 'scaled', 'custom'), + ave_celltype_exp, + selected_genes = NULL, + spatial_network_name = 'Delaunay_network', + minimum_unique_cells = 5, + minimum_unique_int_cells = 5, + CCI_cell_score = 0.1, + dwls_cutoff = 0.001, + diff_test = 'permutation', + nr_permutations = 100, + adjust_method = 'fdr', + do_parallel = TRUE, + cores = 2, + set_seed = TRUE, + seed_number = 1234) { + + # expression data + values = match.arg(expression_values, choices = c('normalized', 'scaled', 'custom')) + genes_overlap = intersect(slot(gobject, "feat_ID")[[feat_type]], rownames(ave_celltype_exp)) + ave_celltype_exp_sel = ave_celltype_exp[genes_overlap,] + expr_residual = cal_expr_residual(gobject = gobject, + spat_unit = spat_unit, + feat_type = feat_type, + ave_celltype_exp = ave_celltype_exp_sel) + + ## test selected genes ## + if(!is.null(selected_genes)) { + expr_residual = expr_residual[rownames(expr_residual) %in% selected_genes, ] + } + + # compute cell proximity for each spot + proximityMat = cellProximityEnrichmentEachSpot(gobject = gobject, + spatial_network_name = spatial_network_name) + # select overlapped spots + #intersect_cell_IDs = intersect(colnames(expr_residual), colnames(proximityMat)) + #expr_residual = expr_residual[, intersect_cell_IDs] + #proximityMat = proximityMat[, intersect_cell_IDs] + + # compute correlation between genes and cell-types to find ICGs + all_ints = data.table::data.table(unified_int = rownames(proximityMat)) + all_ints[, cell_type := strsplit(as.character(unified_int), '--')[[1]][1], by = 1:nrow(all_ints)] + all_ints[, int_cell_type := strsplit(as.character(unified_int), '--')[[1]][2], by = 1:nrow(all_ints)] + + # exact spatial_enrichment matrix + dwls_values = get_spatial_enrichment(gobject = gobject, + spat_unit = spat_unit, + feat_type = feat_type, + output = 'data.table') + data.table::setDF(dwls_values) + rownames_dwls = dwls_values[,'cell_ID'] + dwls_values = as.matrix(dwls_values[,-1]) + rownames(dwls_values) = rownames_dwls + + + if(do_parallel == TRUE) { + + + fin_result = giotto_lapply(X = all_ints$unified_int, cores = cores, fun = function(x) { + + tempres = findICG_per_interaction_spot(sel_int = x, + all_ints = all_ints, + proximityMat = proximityMat, + expr_residual = expr_residual, + dwls_values = dwls_values, + dwls_cutoff = dwls_cutoff, + CCI_cell_score = CCI_cell_score, + minimum_unique_cells = minimum_unique_cells, + minimum_unique_int_cells = minimum_unique_int_cells, + n_perm = nr_permutations, + adjust_method = adjust_method, + cores = cores, + set_seed = set_seed, + seed_number = seed_number) + }) + + + } else { + + fin_result = list() + + for(i in 1:length(all_ints$unified_int)) { + + x = all_ints$unified_int[i] + print(x) + + tempres = findICG_per_interaction_spot(sel_int = x, + all_ints = all_ints, + proximityMat = proximityMat, + expr_residual = expr_residual, + dwls_values = dwls_values, + dwls_cutoff = dwls_cutoff, + CCI_cell_score = CCI_cell_score, + minimum_unique_cells = minimum_unique_cells, + minimum_unique_int_cells = minimum_unique_int_cells, + n_perm = nr_permutations, + adjust_method = adjust_method, + cores = 2, + set_seed = set_seed, + seed_number = seed_number) + + fin_result[[i]] = tempres + + } + + } + + final_result = do.call('rbind', fin_result) + + # data.table variables + spec_int = cell_type = int_cell_type = type_int = NULL + + final_result[, spec_int := paste0(cell_type,'--',int_cell_type)] + final_result[, type_int := ifelse(cell_type == int_cell_type, 'homo', 'hetero')] + + + #return(final_result) + + permutation_test = ifelse(diff_test == 'permutation', nr_permutations, 'no permutations') + + cpgObject = list(CPGscores = final_result, + Giotto_info = list('values' = values, + 'cluster' = 'cell_ID', + 'spatial network' = spatial_network_name), + test_info = list('test' = diff_test, + 'p.adj' = adjust_method, + 'min cells' = minimum_unique_cells, + 'min interacting cells' = minimum_unique_int_cells, + 'perm' = permutation_test)) + class(cpgObject) = append(class(cpgObject), 'cpgObject') + return(cpgObject) + +} + + +#' @title filterICGSpot +#' @name filterICGSpot +#' @description Filter Interaction Changed Gene scores for spots. +#' @param cpgObject ICG (interaction changed gene) score object +#' @param min_cells minimum number of source cell type +#' @param min_cells_expr_resi minimum expression residual level for source cell type +#' @param min_int_cells minimum number of interacting neighbor cell type +#' @param min_int_cells_expr_resi minimum expression residual level for interacting neighbor cell type +#' @param min_fdr minimum adjusted p-value +#' @param min_pcc_diff minimum absolute pcc difference difference +#' @param min_zscore minimum z-score change +#' @param zscores_column calculate z-scores over cell types or genes +#' @param direction differential expression directions to keep +#' @return cpgObject that contains the filtered differential gene scores +#' @export +filterICGSpot = function(cpgObject, + min_cells = 4, + min_cells_expr_resi = 0.05, + min_int_cells = 4, + min_int_cells_expr_resi = 0.05, + min_fdr = 0.5, + min_pcc_diff = 0.05, + min_zscore = 0.05, + zscores_column = c('cell_type', 'genes'), + direction = c('both', 'up', 'down')) { + + # data.table variables + nr_select = int_nr_select = zscores = pcc_diff = sel = other = p.adj = NULL + + if(!'cpgObject' %in% class(cpgObject)) { + stop('\n cpgObject needs to be the output from findCellProximityGenes() or findCPG() \n') + } + + zscores_column = match.arg(zscores_column, choices = c('cell_type', 'genes')) + + CPGscore = copy(cpgObject[['CPGscores']]) + + # other parameters + direction = match.arg(direction, choices = c('both', 'up', 'down')) + + + ## sequential filter steps ## + # 1. minimum number of source and target cells + selection_scores = CPGscore[nr_select >= min_cells & int_nr_select >= min_int_cells] + + # 2. create z-scores for log2fc per cell type + selection_scores[, zscores := scale(pcc_diff), by = c(zscores_column)] + + # 3. filter based on z-scores and minimum levels + comb_DT = rbind(selection_scores[zscores >= min_zscore & abs(pcc_diff) >= min_pcc_diff & sel >= min_cells_expr_resi], + selection_scores[zscores <= -min_zscore & abs(pcc_diff) >= min_pcc_diff & other >= min_int_cells_expr_resi]) + + # 4. filter based on adjusted p-value (fdr) + comb_DT = comb_DT[p.adj < min_fdr] + + + if(direction == 'both') { + selection_scores = selection_scores + } else if(direction == 'up') { + selection_scores = selection_scores[log2fc >= min_log2_fc] + } else if(direction == 'down') { + selection_scores = selection_scores[log2fc <= -min_log2_fc] + } + + + newobj = copy(cpgObject) + newobj[['CPGscores']] = comb_DT + + return(newobj) + +} + +#' @title plotICGSpot +#' @name plotICGSpot +#' @description Create barplot to visualize interaction changed genes +#' @param gobject giotto object +#' @param cpgObject ICG (interaction changed gene) score object +#' @param source_type cell type of the source cell +#' @param source_markers markers for the source cell type +#' @param ICG_genes named character vector of ICG genes +#' @param cell_color_code cell color code for the interacting cell types +#' @param show_plot show plots +#' @param return_plot return plotting object +#' @param save_plot directly save the plot [boolean] +#' @param save_param list of saving parameters from \code{\link{all_plots_save_function}} +#' @param default_save_name default save name for saving, don't change, change save_name in save_param +#' @return plot +#' @export +plotICGSpot <- function(gobject, + cpgObject, + source_type, + source_markers, + ICG_genes, + cell_color_code = NULL, + show_plot = NA, + return_plot = NA, + save_plot = NA, + save_param = list(), + default_save_name = 'plotICGSpot') { + + + # data.table variables + cell_type = int_cell_type = pcc_diff = NULL + + + if(!'cpgObject' %in% class(cpgObject)) { + stop('\n cpgObject needs to be the output from findCellProximityGenes() or findCPG() \n') + } + + CPGscores = cpgObject[['CPGscores']] + + # combine genes + names(source_markers) = rep('marker', length(source_markers)) + neighbor_types = names(ICG_genes) + all_genes = c(source_markers, ICG_genes) + + # warning if there are genes selected that are not detected + detected_genes = unique(CPGscores[['genes']]) + not_detected_genes = all_genes[!all_genes %in% detected_genes] + if(length(not_detected_genes) > 0) { + cat('These selected genes are not in the cpgObject: \n', + not_detected_genes, '\n') + } + + # data.table set column names + genes = group = NULL + + tempDT = CPGscores[genes %in% all_genes][cell_type == source_type][int_cell_type %in% neighbor_types] + tempDT[, genes := factor(genes, levels = all_genes)] + tempDT[, group := names(all_genes[all_genes == genes]), by = 1:nrow(tempDT)] + + + if(is.null(cell_color_code)) { + mycolors = getDistinctColors(n = length(unique(tempDT$int_cell_type))) + names(mycolors) = unique(tempDT$int_cell_type) + } else { + mycolors = cell_color_code + } + + + pl = ggplot2::ggplot() + pl = pl + ggplot2::theme_classic() + ggplot2::theme(axis.text.x = ggplot2::element_text(size = 14, angle = 45, vjust = 1, hjust = 1), + axis.text.y = ggplot2::element_text(size = 14), + axis.title = ggplot2::element_text(size = 14)) + pl = pl + ggplot2::geom_bar(data = tempDT, ggplot2::aes(x = genes, y = pcc_diff, fill = int_cell_type), stat = 'identity', position = ggplot2::position_dodge()) + pl = pl + ggplot2::scale_fill_manual(values = mycolors) + pl = pl + ggplot2::labs(x = '', title = paste0('fold-change z-scores in ' ,source_type)) + + + + # print, return and save parameters + show_plot = ifelse(is.na(show_plot), readGiottoInstructions(gobject, param = 'show_plot'), show_plot) + save_plot = ifelse(is.na(save_plot), readGiottoInstructions(gobject, param = 'save_plot'), save_plot) + return_plot = ifelse(is.na(return_plot), readGiottoInstructions(gobject, param = 'return_plot'), return_plot) + + + ## print plot + if(show_plot == TRUE) { + print(pl) + } + + ## save plot + if(save_plot == TRUE) { + do.call('all_plots_save_function', c(list(gobject = gobject, plot_object = pl, default_save_name = default_save_name), save_param)) + } + + ## return plot + if(return_plot == TRUE) { + return(pl) + } + +} + +#' @title plotCellProximityGenesSpot +#' @name plotCellProximityGenesSpot +#' @description Create visualization for cell proximity gene scores +#' @param gobject giotto object +#' @param cpgObject ICG (interaction changed gene) score object +#' @param method plotting method to use +#' @param min_cells minimum number of source cell type +#' @param min_cells_expr minimum expression level for source cell type +#' @param min_int_cells minimum number of interacting neighbor cell type +#' @param min_int_cells_expr minimum expression level for interacting neighbor cell type +#' @param min_fdr minimum adjusted p-value +#' @param min_spat_diff minimum absolute spatial expression difference +#' @param min_log2_fc minimum log2 fold-change +#' @param min_zscore minimum z-score change +#' @param zscores_column calculate z-scores over cell types or genes +#' @param direction differential expression directions to keep +#' @param cell_color_code vector of colors with cell types as names +#' @param show_plot show plots +#' @param return_plot return plotting object +#' @param save_plot directly save the plot [boolean] +#' @param save_param list of saving parameters from \code{\link{all_plots_save_function}} +#' @param default_save_name default save name for saving, don't change, change save_name in save_param +#' @return plot +#' @export +plotCellProximityGenesSpot = function(gobject, + cpgObject, + method = c('volcano', 'cell_barplot', 'cell-cell', 'cell_sankey', 'heatmap', 'dotplot'), + min_cells = 4, + min_cells_expr_resi = 0.05, + min_int_cells = 4, + min_int_cells_expr_resi = 0.05, + min_fdr = 0.5, + min_pcc_diff = 0.05, + min_zscore = 0.05, + zscores_column = c('cell_type', 'genes'), + direction = c('both', 'up', 'down'), + cell_color_code = NULL, + show_plot = NA, + return_plot = NA, + save_plot = NA, + save_param = list(), + default_save_name = 'plotCellProximityGenes') { + + + if(!'cpgObject' %in% class(cpgObject)) { + stop('\n cpgObject needs to be the output from findCellProximityGenes() or findCPG() \n') + } + + # print, return and save parameters + show_plot = ifelse(is.na(show_plot), readGiottoInstructions(gobject, param = 'show_plot'), show_plot) + save_plot = ifelse(is.na(save_plot), readGiottoInstructions(gobject, param = 'save_plot'), save_plot) + return_plot = ifelse(is.na(return_plot), readGiottoInstructions(gobject, param = 'return_plot'), return_plot) + + + ## first filter + filter_cpg = filterICGSpot(cpgObject, + min_cells = min_cells, + min_cells_expr_resi = min_cells_expr_resi, + min_int_cells = min_int_cells, + min_int_cells_expr_resi = min_int_cells_expr_resi, + min_fdr = min_fdr, + min_pcc_diff = min_pcc_diff, + min_zscore = min_zscore, + zscores_column = c('cell_type', 'genes'), + direction = c('both', 'up', 'down')) + + complete_part = filter_cpg[['CPGscores']] + + ## other parameters + method = match.arg(method, choices = c('volcano', 'cell_barplot', 'cell-cell', 'cell_sankey', 'heatmap', 'dotplot')) + + + # variables + pcc_diff = p.adj = unif_int = N = cell_type = int_cell_type = NULL + + ## create data.table for visualization + if(method == 'volcano') { + + ## volcanoplot + pl = ggplot2::ggplot() + pl = pl + ggplot2::geom_point(data = complete_part, ggplot2::aes(x = pcc_diff, y = ifelse(is.infinite(-log10(p.adj)), 1000, -log10(p.adj)))) + pl = pl + ggplot2::theme_classic() + pl = pl + ggplot2::geom_vline(xintercept = 0, linetype = 2) + pl = pl + ggplot2::labs(x = 'pcc diff', y = '-log10(p.adjusted)') + + + ## print plot + if(show_plot == TRUE) { + print(pl) + } + + ## save plot + if(save_plot == TRUE) { + do.call('all_plots_save_function', c(list(gobject = gobject, plot_object = pl, default_save_name = default_save_name), save_param)) + } + + ## return plot + if(return_plot == TRUE) { + return(pl) + } + + + } else if(method == 'cell-cell') { + + nr_int_selection_scores = complete_part[, .N, by = unif_int] + order_interactions = nr_int_selection_scores[order(N)]$unif_int + + complete_part[, unif_int := factor(unif_int, order_interactions)] + + pl <- ggplot2::ggplot() + pl <- pl + ggplot2::geom_bar(data = complete_part, ggplot2::aes(x = unif_int, fill = unif_int)) + pl <- pl + ggplot2::theme_classic() + ggplot2::theme(axis.text.x = ggplot2::element_text(angle = 90, hjust = 1, vjust = 1)) + pl <- pl + ggplot2::coord_flip() + + ## print plot + if(show_plot == TRUE) { + print(pl) + } + + ## save plot + if(save_plot == TRUE) { + do.call('all_plots_save_function', c(list(gobject = gobject, plot_object = pl, default_save_name = default_save_name), save_param)) + } + + ## return plot + if(return_plot == TRUE) { + return(pl) + } + + + } else if(method == 'cell_barplot') { + + + # by source cell type plot + nr_source_selection_scores = complete_part[, .N, by = cell_type] + order_source = nr_source_selection_scores[order(N)]$cell_type + + complete_part[, cell_type := factor(cell_type, order_source)] + + pl <- ggplot2::ggplot() + pl <- pl + ggplot2::geom_bar(data = complete_part, ggplot2::aes(x = cell_type, fill = int_cell_type)) + if(!is.null(cell_color_code)) { + pl <- pl + ggplot2::scale_fill_manual(values = cell_color_code) + } + pl <- pl + ggplot2::theme_classic() + ggplot2::theme(axis.text.x = element_text(angle = 45, hjust = 1, vjust = 1)) + pl <- pl + ggplot2::labs(x = '', y = '# of genes influenced by cell neighborhood') + + + ## print plot + if(show_plot == TRUE) { + print(pl) + } + + ## save plot + if(save_plot == TRUE) { + do.call('all_plots_save_function', c(list(gobject = gobject, plot_object = pl, default_save_name = default_save_name), save_param)) + } + + ## return plot + if(return_plot == TRUE) { + return(pl) + } + + } else if(method == 'cell_sankey') { + + + # package check for ggalluvial + package_check(pkg_name = 'ggalluvial', repository = 'CRAN') + + + testalluv = complete_part[, .N, by = c('int_cell_type', 'cell_type')] + + # library(ggalluvial) # this is needed for it to work, why?? + # maybe use requireNamespace() instead? + + pl <- ggplot2::ggplot(testalluv, + ggplot2::aes(y = N, axis1 = cell_type, axis2 = int_cell_type)) + + ggalluvial::geom_alluvium(aes(fill = cell_type), width = 1/12) + + ggalluvial::geom_stratum(width = 1/12, fill = "black", color = "grey") + + ggplot2::scale_x_discrete(limits = c("cell type", "neighbours"), expand = c(.05, .05)) + + ggplot2::geom_label(stat = "stratum", label.strata = TRUE, size = 3) + + ggplot2::theme_classic() + ggplot2::labs(x = '', y = '# of genes influenced by cell neighborhood') + + if(!is.null(cell_color_code)) { + pl <- pl + ggplot2::scale_fill_manual(values = cell_color_code) + } + + + + ## print plot + if(show_plot == TRUE) { + print(pl) + } + + ## save plot + if(save_plot == TRUE) { + do.call('all_plots_save_function', c(list(gobject = gobject, plot_object = pl, default_save_name = default_save_name), save_param)) + } + + ## return plot + if(return_plot == TRUE) { + return(pl) + } + + } else if(method == 'dotplot') { + + changed_genes = complete_part[, .N, by = c('cell_type', 'int_cell_type')] + + changed_genes[, cell_type := factor(cell_type, unique(cell_type))] + changed_genes[, int_cell_type := factor(int_cell_type, unique(int_cell_type))] + + pl = ggplot2::ggplot() + pl = pl + ggplot2::theme_classic() + pl = pl + ggplot2::geom_point(data = changed_genes, ggplot2::aes(x = cell_type, y = int_cell_type, size = N)) + pl = pl + ggplot2::scale_size_continuous(guide=guide_legend(title = '# of ICGs')) + pl = pl + ggplot2::theme(axis.text.x = ggplot2::element_text(angle = 90, vjust = 1, hjust = 1)) + pl = pl + ggplot2::labs(x = 'source cell type', y = 'neighbor cell type') + + ## print plot + if(show_plot == TRUE) { + print(pl) + } + + ## save plot + if(save_plot == TRUE) { + do.call('all_plots_save_function', c(list(gobject = gobject, plot_object = pl, default_save_name = default_save_name), save_param)) + } + + ## return plot + if(return_plot == TRUE) { + return(pl) + } + + } else if(method == 'heatmap') { + + changed_genes = complete_part[, .N, by = c('cell_type', 'int_cell_type')] + + changed_genes[, cell_type := factor(cell_type, unique(cell_type))] + changed_genes[, int_cell_type := factor(int_cell_type, unique(int_cell_type))] + + changed_genes_d = data.table::dcast.data.table(changed_genes, cell_type~int_cell_type, value.var = 'N', fill = 0) + changed_genes_m = dt_to_matrix(changed_genes_d) + + col_fun = circlize::colorRamp2(breaks = stats::quantile(log2(changed_genes_m+1)), + colors = c("white", 'white', "blue", "yellow", "red")) + + heatm = ComplexHeatmap::Heatmap(as.matrix(log2(changed_genes_m+1)), col = col_fun, + row_title = 'cell_type', column_title = 'int_cell_type', heatmap_legend_param = list(title = 'log2(# DEGs)')) + + ## print plot + if(show_plot == TRUE) { + print(heatm) + } + + ## save plot + if(save_plot == TRUE) { + do.call('all_plots_save_function', c(list(gobject = gobject, plot_object = heatm, default_save_name = default_save_name), save_param)) + } + + ## return plot + if(return_plot == TRUE) { + return(heatm) + } + + } +} + + +# * #### +# cell communication spots #### + +#' @title specific_CCCScores_spots +#' @name specific_CCCScores_spots +#' @description Specific Cell-Cell communication scores based on spatial expression of interacting cells at spots resulation +#' @param gobject giotto object to use +#' @param expr_residual spatial network to use for identifying interacting cells +#' @param dwls_values dwls matrix +#' @param proximityMat cell cell communication score matrix +#' @param random_iter number of iterations +#' @param cell_type_1 first cell type +#' @param cell_type_2 second cell type +#' @param gene_set_1 first specific gene set from gene pairs +#' @param gene_set_2 second specific gene set from gene pairs +#' @param min_observations minimum number of interactions needed to be considered +#' @param detailed provide more detailed information (random variance and z-score) +#' @param adjust_method which method to adjust p-values +#' @param adjust_target adjust multiple hypotheses at the cell or gene level +#' @param set_seed set a seed for reproducibility +#' @param seed_number seed number +#' @param verbose verbose +#' @return Cell-Cell communication scores for gene pairs based on spatial interaction +#' @details Statistical framework to identify if pairs of genes (such as ligand-receptor combinations) +#' are expressed at higher levels than expected based on a reshuffled null distribution +#' of gene expression values in cells that are spatially in proximity to eachother. +#' \itemize{ +#' \item{LR_comb:}{Pair of ligand and receptor} +#' \item{lig_cell_type:}{ cell type to assess expression level of ligand } +#' \item{lig_expr:}{ average expressionresidual(observed - DWLS_predicted) of ligand in lig_cell_type } +#' \item{ligand:}{ ligand name } +#' \item{rec_cell_type:}{ cell type to assess expression level of receptor } +#' \item{rec_expr:}{ average expression residual(observed - DWLS_predicted) of receptor in rec_cell_type} +#' \item{receptor:}{ receptor name } +#' \item{LR_expr:}{ combined average ligand and receptor expression } +#' \item{lig_nr:}{ total number of cells from lig_cell_type that spatially interact with cells from rec_cell_type } +#' \item{rec_nr:}{ total number of cells from rec_cell_type that spatially interact with cells from lig_cell_type } +#' \item{rand_expr:}{ average combined ligand and receptor expression residual from random spatial permutations } +#' \item{av_diff:}{ average difference between LR_expr and rand_expr over all random spatial permutations } +#' \item{sd_diff:}{ (optional) standard deviation of the difference between LR_expr and rand_expr over all random spatial permutations } +#' \item{z_score:}{ (optinal) z-score } +#' \item{log2fc:}{ LR_expr - rand_expr } +#' \item{pvalue:}{ p-value } +#' \item{LR_cell_comb:}{ cell type pair combination } +#' \item{p.adj:}{ adjusted p-value } +#' \item{PI:}{ significanc score: log2fc * -log10(p.adj) } +#' } +#' @keywords internal +specific_CCCScores_spots = function(gobject, + spat_unit = NULL, + feat_type = NULL, + expr_residual, + dwls_values, + proximityMat, + random_iter = 1000, + cell_type_1 = 'astrocytes', + cell_type_2 = 'endothelial', + gene_set_1, + gene_set_2, + min_observations = 2, + detailed = FALSE, + adjust_method = c("fdr", "bonferroni","BH", "holm", "hochberg", "hommel", + "BY", "none"), + adjust_target = c('genes', 'cells'), + set_seed = FALSE, + seed_number = 1234, + verbose = T){ + + # data.table variables + from_to = cell_ID = lig_cell_type = rec_cell_type = lig_nr = rec_nr = rand_expr = NULL + av_diff = log2fc = LR_expr = pvalue = LR_cell_comb = p.adj = LR_comb = PI = NULL + sd_diff = z_score = NULL + + # get parameters + adjust_method = match.arg(adjust_method, choices = c("fdr", "bonferroni","BH", "holm", "hochberg", "hommel", + "BY", "none")) + adjust_target = match.arg(adjust_target, choices = c('genes', 'cells')) + + # select cell_ids with cell-types + cell_direction_1 = paste0(cell_type_1,'--',cell_type_2) + cell_direction_2 = paste0(cell_type_2,'--',cell_type_1) + + print(paste0('Processing sepcific CCC Scores: ', cell_direction_1)) + + proxi_1 = proximityMat[cell_direction_1,] + proxi_2 = proximityMat[cell_direction_2,] + + ct1_cell_ids = names(proxi_1[proxi_1 > 0]) + ct2_cell_ids = names(proxi_2[proxi_2 > 0]) + + # dwls value for cell types + dwls_ct1 = dwls_values[,cell_type_1] + dwls_ct2 = dwls_values[,cell_type_2] + + # make sure that there are sufficient observations + if(length(ct1_cell_ids) <= min_observations | length(ct2_cell_ids) <= min_observations) { + + return(NULL) + + } else { + + # get gene expression residual for ligand and receptor + expr_res_L = expr_residual[gene_set_1, ct1_cell_ids] + expr_res_R = expr_residual[gene_set_2, ct2_cell_ids] + + # compute Ligand value + lig_expr = t(t(expr_res_L) * dwls_ct1[ct1_cell_ids]) + rec_expr = t(t(expr_res_R) * dwls_ct2[ct2_cell_ids]) + + lig_expr = round(rowMeans(lig_expr), 7) + rec_expr = round(rowMeans(rec_expr), 7) + + comScore = data.table::data.table(LR_comb = paste0(gene_set_1, '-', gene_set_2), + lig_cell_type = rep(cell_type_1, length(gene_set_1)), + lig_expr = lig_expr, + ligand = gene_set_1, + rec_cell_type = rep(cell_type_2, length(gene_set_2)), + rec_expr = rec_expr, + receptor = gene_set_2, + lig_nr = rep(length(ct1_cell_ids), length(gene_set_1)), + rec_nr = rep(length(ct2_cell_ids), length(gene_set_1)) + ) + + comScore[, LR_expr := lig_expr + rec_expr] + comScore = comScore[, .(LR_comb, lig_cell_type, lig_expr, ligand, + rec_cell_type, rec_expr, receptor, LR_expr, lig_nr, rec_nr)] + + # prepare for randomized scores + total_av = rep(0, nrow(comScore)) + + if(detailed == FALSE) { + total_sum = rep(0, nrow(comScore)) + } else { + total_sum = matrix(nrow = nrow(comScore), ncol = random_iter) + } + + total_bool = rep(0, nrow(comScore)) + + all_cell_ids = pDataDT(gobject = gobject, + spat_unit = spat_unit, + feat_type = feat_type)$cell_ID + ## simulations ## + for(sim in 1:random_iter) { + + if(verbose == TRUE) cat('simulation ', sim, '\n') + + # get random ids and subset + if(set_seed == TRUE) { + seed_number = seed_number+sim + set.seed(seed = seed_number) + } + random_ids_1 = all_cell_ids[sample(length(all_cell_ids), size = length(ct1_cell_ids))] + random_ids_2 = all_cell_ids[sample(length(all_cell_ids), size = length(ct2_cell_ids))] + + # get gene expression residual for ligand and receptor + random_expr_res_L = expr_residual[gene_set_1, random_ids_1] + random_expr_res_R = expr_residual[gene_set_2, random_ids_2] + + # compute Ligand value + random_lig_expr = t(t(random_expr_res_L) * dwls_ct1[random_ids_1]) + random_rec_expr = t(t(random_expr_res_R) * dwls_ct2[random_ids_2]) + + random_lig_expr = round(rowMeans(random_lig_expr), 7) + random_rec_expr = round(rowMeans(random_rec_expr), 7) + + randomScore = data.table::data.table(lig_expr = random_lig_expr, + rec_expr = random_rec_expr) + randomScore = randomScore[, LR_expr := lig_expr + rec_expr] + + # average random score + total_av = total_av + randomScore[['LR_expr']] + + # difference between observed and random + difference = comScore[['LR_expr']] - randomScore[['LR_expr']] + + # calculate total difference + if(detailed == FALSE) { + total_sum = total_sum+difference + } else { + total_sum[,sim] = difference + } + + # calculate p-values + difference[difference > 0] = 1 + difference[difference < 0] = -1 + total_bool = total_bool + difference + + } + + comScore[, rand_expr := total_av/random_iter] + + if(detailed == TRUE) { + av_difference_scores = rowMeans_giotto(total_sum) + sd_difference_scores = apply(total_sum, MARGIN = 1, FUN = stats::sd) + + comScore[, av_diff := av_difference_scores] + comScore[, sd_diff := sd_difference_scores] + comScore[, z_score := (LR_expr - rand_expr)/sd_diff] + + } else { + comScore[, av_diff := total_sum/random_iter] + } + + comScore[, log2fc := LR_expr - rand_expr] + comScore[, pvalue := total_bool/random_iter] + comScore[, pvalue := ifelse(pvalue > 0, 1-pvalue, 1+pvalue)] + comScore[, LR_cell_comb := paste0(lig_cell_type,'--',rec_cell_type)] + + if(adjust_target == 'genes') { + comScore[, p.adj := stats::p.adjust(pvalue, method = adjust_method), by = .(LR_cell_comb)] + } else if(adjust_target == 'cells'){ + comScore[, p.adj := stats::p.adjust(pvalue, method = adjust_method), by = .(LR_comb)] + } + + # get minimum adjusted p.value that is not zero + all_p.adj = comScore[['p.adj']] + lowest_p.adj = min(all_p.adj[all_p.adj != 0]) + comScore[, PI := ifelse(p.adj == 0, log2fc*(-log10(lowest_p.adj)), log2fc*(-log10(p.adj)))] + + return(comScore) + + } +} + + + +#' @title spatCellCellcomSpots +#' @name spatCellCellcomSpots +#' @description Spatial Cell-Cell communication scores based on spatial expression of interacting cells at spots resolution +#' @param gobject giotto object to use +#' @param spatial_network_name spatial network to use for identifying interacting cells +#' @param cluster_column cluster column with cell type information +#' @param random_iter number of iterations +#' @param gene_set_1 first specific gene set from gene pairs +#' @param gene_set_2 second specific gene set from gene pairs +#' @param min_observations minimum number of interactions needed to be considered +#' @param detailed provide more detailed information (random variance and z-score) +#' @param adjust_method which method to adjust p-values +#' @param adjust_target adjust multiple hypotheses at the cell or gene level +#' @param do_parallel run calculations in parallel with mclapply +#' @param cores number of cores to use if do_parallel = TRUE +#' @param set_seed set a seed for reproducibility +#' @param seed_number seed number +#' @param verbose verbose +#' @return Cell-Cell communication scores for gene pairs based on spatial interaction +#' @details Statistical framework to identify if pairs of genes (such as ligand-receptor combinations) +#' are expressed at higher levels than expected based on a reshuffled null distribution +#' of gene expression values in cells that are spatially in proximity to eachother.. +#' \itemize{ +#' \item{LR_comb:}{Pair of ligand and receptor} +#' \item{lig_cell_type:}{ cell type to assess expression level of ligand } +#' \item{lig_expr:}{ average expression residual(observed - DWLS_predicted) of ligand in lig_cell_type } +#' \item{ligand:}{ ligand name } +#' \item{rec_cell_type:}{ cell type to assess expression level of receptor } +#' \item{rec_expr:}{ average expression residual(observed - DWLS_predicted) of receptor in rec_cell_type} +#' \item{receptor:}{ receptor name } +#' \item{LR_expr:}{ combined average ligand and receptor expression residual} +#' \item{lig_nr:}{ total number of cells from lig_cell_type that spatially interact with cells from rec_cell_type } +#' \item{rec_nr:}{ total number of cells from rec_cell_type that spatially interact with cells from lig_cell_type } +#' \item{rand_expr:}{ average combined ligand and receptor expression residual from random spatial permutations } +#' \item{av_diff:}{ average difference between LR_expr and rand_expr over all random spatial permutations } +#' \item{sd_diff:}{ (optional) standard deviation of the difference between LR_expr and rand_expr over all random spatial permutations } +#' \item{z_score:}{ (optinal) z-score } +#' \item{log2fc:}{ LR_expr - rand_expr } +#' \item{pvalue:}{ p-value } +#' \item{LR_cell_comb:}{ cell type pair combination } +#' \item{p.adj:}{ adjusted p-value } +#' \item{PI:}{ significanc score: log2fc * -log10(p.adj) } +#' } +#' @export +spatCellCellcomSpots = function(gobject, + spat_unit = NULL, + feat_type = NULL, + ave_celltype_exp, + spatial_network_name = 'Delaunay_network', + cluster_column = 'cell_ID', + random_iter = 1000, + gene_set_1, + gene_set_2, + min_observations = 2, + expression_values = c('normalized', 'scaled', 'custom'), + detailed = FALSE, + adjust_method = c("fdr", "bonferroni","BH", "holm", "hochberg", "hommel", + "BY", "none"), + adjust_target = c('genes', 'cells'), + do_parallel = TRUE, + cores = NA, + set_seed = TRUE, + seed_number = 1234, + verbose = c('a little', 'a lot', 'none')){ + + + # code start + verbose = match.arg(verbose, choices = c('a little', 'a lot', 'none')) + + ## check if spatial network exists ## + spat_networks = showGiottoSpatNetworks(gobject = gobject) + if(!spatial_network_name %in% spat_networks) { + stop(spatial_network_name, ' is not an existing spatial network \n', + 'use showNetworks() to see the available networks \n', + 'or create a new spatial network with createSpatialNetwork() \n') + } + + + # expression data + values = match.arg(expression_values, choices = unique(c('normalized', 'scaled', 'custom', expression_values))) + expr_residual = cal_expr_residual(gobject = gobject, + spat_unit = spat_unit, + feat_type = feat_type, + ave_celltype_exp = ave_celltype_exp) + + # compute cell proximity for each spot + proximityMat = cellProximityEnrichmentEachSpot(gobject = gobject, + spat_unit = spat_unit, + feat_type = feat_type, + spatial_network_name = spatial_network_name) + + # select overlapped spots + intersect_cell_IDs = intersect(colnames(expr_residual), colnames(proximityMat)) + expr_residual = expr_residual[, intersect_cell_IDs] + proximityMat = proximityMat[, intersect_cell_IDs] + + # exact spatial_enrichment matrix + dwls_values = get_spatial_enrichment(gobject = gobject, + spat_unit = spat_unit, + feat_type = feat_type, + output = 'data.table') + data.table::setDF(dwls_values) + rownames_dwls = dwls_values[,'cell_ID'] + dwls_values = as.matrix(dwls_values[,-1]) + rownames(dwls_values) = rownames_dwls + + # check gene list + LR_comb = data.table::data.table(ligand = gene_set_1, receptor = gene_set_2) + # check LR pair not captured in giotto object + LR_out = LR_comb[!LR_comb$ligand %in% rownames(expr_residual) | !LR_comb$receptor %in% rownames(expr_residual)] + + if (dim(LR_out)[1] > 0){ + print('Ligand or receptor were removed after computing expresion residual.') + print(LR_out) + LR_comb = LR_comb[LR_comb$ligand %in% rownames(expr_residual) & LR_comb$receptor %in% rownames(expr_residual) ] + gene_set_1 = LR_comb$ligand + gene_set_2 = LR_comb$receptor + } + + ## get all combinations between cell types + combn_DT = data.table::data.table(LR_cell_comb = rownames(proximityMat)) + combn_DT = combn_DT[, V1 := strsplit(LR_cell_comb, '--')[[1]][1], by = 1:nrow(combn_DT)] + combn_DT = combn_DT[, V2 := strsplit(LR_cell_comb, '--')[[1]][2], by = 1:nrow(combn_DT)] + + ## parallel option ## + if(do_parallel == TRUE) { + + + savelist = giotto_lapply(X = 1:nrow(combn_DT), cores = cores, fun = function(row) { + + cell_type_1 = combn_DT[row][['V1']] + cell_type_2 = combn_DT[row][['V2']] + + + specific_scores = specific_CCCScores_spots(gobject = gobject, + spat_unit = spat_unit, + feat_type = feat_type, + expr_residual = expr_residual, + dwls_values = dwls_values, + proximityMat = proximityMat, + random_iter = random_iter, + cell_type_1 = cell_type_1, + cell_type_2 = cell_type_2, + gene_set_1 = gene_set_1, + gene_set_2 = gene_set_2, + min_observations = min_observations, + detailed = detailed, + adjust_method = adjust_method, + adjust_target = adjust_target, + set_seed = set_seed, + seed_number = seed_number) + }) + + } else { + + ## for loop over all combinations ## + savelist = list() + countdown = nrow(combn_DT) + + for(row in 1:nrow(combn_DT)) { + + cell_type_1 = combn_DT[row][['V1']] + cell_type_2 = combn_DT[row][['V2']] + + if(verbose == 'a little' | verbose == 'a lot') cat('\n\n PROCESS nr ', countdown,': ', cell_type_1, ' and ', cell_type_2, '\n\n') + + if(verbose %in% c('a little', 'none')) { + specific_verbose = F + } else { + specific_verbose = T + } + + specific_scores = specific_CCCScores_spots(gobject = gobject, + spat_unit = spat_unit, + feat_type = feat_type, + expr_residual = expr_residual, + dwls_values = dwls_values, + proximityMat = proximityMat, + random_iter = random_iter, + cell_type_1 = cell_type_1, + cell_type_2 = cell_type_2, + gene_set_1 = gene_set_1, + gene_set_2 = gene_set_2, + min_observations = min_observations, + detailed = detailed, + adjust_method = adjust_method, + adjust_target = adjust_target, + set_seed = set_seed, + seed_number = seed_number, + verbose = specific_verbose) + savelist[[row]] = specific_scores + countdown = countdown - 1 + } + + } + + finalDT = do.call('rbind', savelist) + + # data.table variables + LR_comb = LR_expr = NULL + + data.table::setorder(finalDT, LR_comb, -LR_expr) + + return(finalDT) + +} + + + + + + + + diff --git a/man/cal_diff_per_interaction.Rd b/man/cal_diff_per_interaction.Rd new file mode 100644 index 000000000..382bfab98 --- /dev/null +++ b/man/cal_diff_per_interaction.Rd @@ -0,0 +1,20 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/spatial_interaction_spot.R +\name{cal_diff_per_interaction} +\alias{cal_diff_per_interaction} +\title{cal_diff_per_interaction} +\usage{ +cal_diff_per_interaction( + sel_int, + other_ints, + select_ind, + other_ind, + proximityMat, + expr_residual +) +} +\description{ +calculate correlation between expression residual and +cell proximity score of selected cell for spots +} +\keyword{internal} diff --git a/man/cal_expr_residual.Rd b/man/cal_expr_residual.Rd new file mode 100644 index 000000000..b727b927b --- /dev/null +++ b/man/cal_expr_residual.Rd @@ -0,0 +1,25 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/spatial_interaction_spot.R +\name{cal_expr_residual} +\alias{cal_expr_residual} +\title{cal_expr_residual} +\usage{ +cal_expr_residual( + gobject, + spat_unit = NULL, + feat_type = NULL, + expression_values = c("normalized", "scaled", "custom"), + ave_celltype_exp +) +} +\arguments{ +\item{gobject}{giotto object} + +\item{expression_values}{expression values to use} + +\item{ave_celltype_exp}{average expression matrix in cell types} +} +\description{ +Calculate gene expression residual (observed_exp - DWLS_predicted) +} +\keyword{internal} diff --git a/man/cellProximityEnrichmentEachSpot.Rd b/man/cellProximityEnrichmentEachSpot.Rd new file mode 100644 index 000000000..1125cf27f --- /dev/null +++ b/man/cellProximityEnrichmentEachSpot.Rd @@ -0,0 +1,30 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/spatial_interaction_spot.R +\name{cellProximityEnrichmentEachSpot} +\alias{cellProximityEnrichmentEachSpot} +\title{cellProximityEnrichmentEachSpot} +\usage{ +cellProximityEnrichmentEachSpot( + gobject, + spat_unit = NULL, + feat_type = NULL, + spatial_network_name = "spatial_network", + cluster_column = "cell_ID" +) +} +\arguments{ +\item{gobject}{giotto object} + +\item{feat_type}{feature type} + +\item{spatial_network_name}{name of spatial network to use} + +\item{cluster_column}{name of column to use for clusters} +} +\value{ +matrix that rownames are cell-cell interaction pairs and colnames are cell_IDs +} +\description{ +Compute cell-cell interaction enrichment for each spot with its +interacted spots (observed) +} diff --git a/man/cellProximityEnrichmentSpots.Rd b/man/cellProximityEnrichmentSpots.Rd new file mode 100644 index 000000000..b356364ab --- /dev/null +++ b/man/cellProximityEnrichmentSpots.Rd @@ -0,0 +1,53 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/spatial_interaction_spot.R +\name{cellProximityEnrichmentSpots} +\alias{cellProximityEnrichmentSpots} +\title{cellProximityEnrichmentSpots} +\usage{ +cellProximityEnrichmentSpots( + gobject, + spat_unit = NULL, + feat_type = NULL, + spatial_network_name = "spatial_network", + cluster_column = "cell_ID", + cells_in_spot = 1, + number_of_simulations = 100, + adjust_method = c("none", "fdr", "bonferroni", "BH", "holm", "hochberg", "hommel", + "BY"), + set_seed = TRUE, + seed_number = 1234 +) +} +\arguments{ +\item{gobject}{giotto object} + +\item{spatial_network_name}{name of spatial network to use} + +\item{cluster_column}{name of column to use for clusters} + +\item{cells_in_spot}{cell number in each spot} + +\item{number_of_simulations}{number of simulations to create expected observations} + +\item{adjust_method}{method to adjust p.values} + +\item{set_seed}{use of seed} + +\item{seed_number}{seed number to use} +} +\value{ +List of cell Proximity scores (CPscores) in data.table format. The first +data.table (raw_sim_table) shows the raw observations of both the original and +simulated networks. The second data.table (enrichm_res) shows the enrichment results. +} +\description{ +Compute cell-cell interaction enrichment for spots (observed vs expected) +} +\details{ +Spatial proximity enrichment or depletion between pairs of cell types +is calculated by calculating the observed over the expected frequency +of cell-cell proximity interactions. The expected frequency is the average frequency +calculated from a number of spatial network simulations. Each individual simulation is +obtained by reshuffling the cell type labels of each node (spot) +in the spatial network. +} diff --git a/man/cell_proximity_spots.Rd b/man/cell_proximity_spots.Rd new file mode 100644 index 000000000..c1cd45d84 --- /dev/null +++ b/man/cell_proximity_spots.Rd @@ -0,0 +1,24 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/spatial_interaction_spot.R +\name{cell_proximity_spots} +\alias{cell_proximity_spots} +\title{cell_proximity_spots} +\usage{ +cell_proximity_spots(cell_IDs, pairs_external, dwls_values) +} +\arguments{ +\item{cell_IDs}{cell_IDs to calculate internal cell-type/cell-type interactions} + +\item{dwls_values}{data.table of cell type enrichment in each spot and multiply +by cell number in each spot} + +\item{pairs}{data.table of paired spots. Format: cell_ID1, cell_ID2, N} +} +\value{ +List of cell proximity observed value in data.table format. Columns: +unified_int, type_int, V1, external, internal. +} +\description{ +Compute cell-cell interactions observed value for internal and external spots +} +\keyword{internal} diff --git a/man/cell_proximity_spots_external.Rd b/man/cell_proximity_spots_external.Rd new file mode 100644 index 000000000..a5b581b60 --- /dev/null +++ b/man/cell_proximity_spots_external.Rd @@ -0,0 +1,22 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/spatial_interaction_spot.R +\name{cell_proximity_spots_external} +\alias{cell_proximity_spots_external} +\title{cell_proximity_spots_external} +\usage{ +cell_proximity_spots_external(pairs, dwls_values) +} +\arguments{ +\item{pairs}{data.table of paired spots. Format: cell_ID1, cell_ID2, N} + +\item{dwls_values}{data.table of cell type enrichment in each spot and multiply +by cell number in each spot} +} +\value{ +List of cell proximity observed value in data.table format. Columns: +unified_int, internal value, type_int. +} +\description{ +Compute cell-cell interactions observed value for interacted spots +} +\keyword{internal} diff --git a/man/cell_proximity_spots_internal.Rd b/man/cell_proximity_spots_internal.Rd new file mode 100644 index 000000000..5ec3641ae --- /dev/null +++ b/man/cell_proximity_spots_internal.Rd @@ -0,0 +1,22 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/spatial_interaction_spot.R +\name{cell_proximity_spots_internal} +\alias{cell_proximity_spots_internal} +\title{cell_proximity_spots_internal} +\usage{ +cell_proximity_spots_internal(cell_IDs, dwls_values) +} +\arguments{ +\item{cell_IDs}{cell_IDs get from gobject@cell_ID} + +\item{dwls_values}{data.table of cell type enrichment in each spot and multiply +by cell number in each spot} +} +\value{ +List of cell proximity observed value in data.table format. Columns: +unified_int, internal value, type_int. +} +\description{ +Compute cell-cell interactions observed value inner each spot +} +\keyword{internal} diff --git a/man/do_cell_proximity_test_spot.Rd b/man/do_cell_proximity_test_spot.Rd new file mode 100644 index 000000000..18d43f2e9 --- /dev/null +++ b/man/do_cell_proximity_test_spot.Rd @@ -0,0 +1,25 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/spatial_interaction_spot.R +\name{do_cell_proximity_test_spot} +\alias{do_cell_proximity_test_spot} +\title{do_cell_proximity_test_spot} +\usage{ +do_cell_proximity_test_spot( + sel_int, + other_ints, + select_ind, + other_ind, + proximityMat, + expr_residual, + diff_test, + n_perm = 100, + adjust_method = "fdr", + cores = 2, + set_seed = TRUE, + seed_number = 1234 +) +} +\description{ +Performs a selected differential test on subsets of a matrix for spots +} +\keyword{internal} diff --git a/man/do_multi_permuttest_random_spot.Rd b/man/do_multi_permuttest_random_spot.Rd new file mode 100644 index 000000000..7567262d0 --- /dev/null +++ b/man/do_multi_permuttest_random_spot.Rd @@ -0,0 +1,23 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/spatial_interaction_spot.R +\name{do_multi_permuttest_random_spot} +\alias{do_multi_permuttest_random_spot} +\title{do_multi_permuttest_random_spot} +\usage{ +do_multi_permuttest_random_spot( + sel_int, + other_ints, + select_ind, + other_ind, + proximityMat, + expr_residual, + n = 100, + cores = 2, + set_seed = TRUE, + seed_number = 1234 +) +} +\description{ +calculate multiple random values for spots +} +\keyword{internal} diff --git a/man/do_permuttest_original_spot.Rd b/man/do_permuttest_original_spot.Rd new file mode 100644 index 000000000..09712a464 --- /dev/null +++ b/man/do_permuttest_original_spot.Rd @@ -0,0 +1,20 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/spatial_interaction_spot.R +\name{do_permuttest_original_spot} +\alias{do_permuttest_original_spot} +\title{do_permuttest_original_spot} +\usage{ +do_permuttest_original_spot( + sel_int, + other_ints, + select_ind, + other_ind, + name = "orig", + proximityMat, + expr_residual +) +} +\description{ +calculate original values for spots +} +\keyword{internal} diff --git a/man/do_permuttest_random_spot.Rd b/man/do_permuttest_random_spot.Rd new file mode 100644 index 000000000..41e73cb2c --- /dev/null +++ b/man/do_permuttest_random_spot.Rd @@ -0,0 +1,22 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/spatial_interaction_spot.R +\name{do_permuttest_random_spot} +\alias{do_permuttest_random_spot} +\title{do_permuttest_random_spot} +\usage{ +do_permuttest_random_spot( + sel_int, + other_ints, + select_ind, + other_ind, + name = "perm_1", + proximityMat, + expr_residual, + set_seed = TRUE, + seed_number = 1234 +) +} +\description{ +calculate random values for spots +} +\keyword{internal} diff --git a/man/do_permuttest_spot.Rd b/man/do_permuttest_spot.Rd new file mode 100644 index 000000000..60b1750de --- /dev/null +++ b/man/do_permuttest_spot.Rd @@ -0,0 +1,24 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/spatial_interaction_spot.R +\name{do_permuttest_spot} +\alias{do_permuttest_spot} +\title{do_permuttest_spot} +\usage{ +do_permuttest_spot( + sel_int, + other_ints, + select_ind, + other_ind, + proximityMat, + expr_residual, + n_perm = 100, + adjust_method = "fdr", + cores = 2, + set_seed = TRUE, + seed_number = 1234 +) +} +\description{ +Performs permutation test on subsets of a matrix for spots +} +\keyword{internal} diff --git a/man/filterGiotto.Rd b/man/filterGiotto.Rd index e0cff9af0..ab3d765e1 100644 --- a/man/filterGiotto.Rd +++ b/man/filterGiotto.Rd @@ -69,4 +69,9 @@ filter Giotto object based on expression threshold } \details{ The function \code{\link{filterCombinations}} can be used to explore the effect of different parameter values. +Please note that this function filters data in a predefined order, features, then cells. +After filtering in this order, certain features may be left over in the metadata with a +corresponding number of cells which is less than that of the threshold value of cells, +feat_det_in_min_cells. This behavior is explained in detail here: +\url{https://github.com/drieslab/Giotto/issues/500#issuecomment-1396083446} } diff --git a/man/filterICGSpot.Rd b/man/filterICGSpot.Rd new file mode 100644 index 000000000..dccad7985 --- /dev/null +++ b/man/filterICGSpot.Rd @@ -0,0 +1,46 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/spatial_interaction_spot.R +\name{filterICGSpot} +\alias{filterICGSpot} +\title{filterICGSpot} +\usage{ +filterICGSpot( + cpgObject, + min_cells = 4, + min_cells_expr_resi = 0.05, + min_int_cells = 4, + min_int_cells_expr_resi = 0.05, + min_fdr = 0.5, + min_pcc_diff = 0.05, + min_zscore = 0.05, + zscores_column = c("cell_type", "genes"), + direction = c("both", "up", "down") +) +} +\arguments{ +\item{cpgObject}{ICG (interaction changed gene) score object} + +\item{min_cells}{minimum number of source cell type} + +\item{min_cells_expr_resi}{minimum expression residual level for source cell type} + +\item{min_int_cells}{minimum number of interacting neighbor cell type} + +\item{min_int_cells_expr_resi}{minimum expression residual level for interacting neighbor cell type} + +\item{min_fdr}{minimum adjusted p-value} + +\item{min_pcc_diff}{minimum absolute pcc difference difference} + +\item{min_zscore}{minimum z-score change} + +\item{zscores_column}{calculate z-scores over cell types or genes} + +\item{direction}{differential expression directions to keep} +} +\value{ +cpgObject that contains the filtered differential gene scores +} +\description{ +Filter Interaction Changed Gene scores for spots. +} diff --git a/man/findICGSpot.Rd b/man/findICGSpot.Rd new file mode 100644 index 000000000..a028a0b52 --- /dev/null +++ b/man/findICGSpot.Rd @@ -0,0 +1,89 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/spatial_interaction_spot.R +\name{findICGSpot} +\alias{findICGSpot} +\title{findICGSpot} +\usage{ +findICGSpot( + gobject, + spat_unit = NULL, + feat_type = NULL, + expression_values = c("normalized", "scaled", "custom"), + ave_celltype_exp, + selected_genes = NULL, + spatial_network_name = "Delaunay_network", + minimum_unique_cells = 5, + minimum_unique_int_cells = 5, + CCI_cell_score = 0.1, + dwls_cutoff = 0.001, + diff_test = "permutation", + nr_permutations = 100, + adjust_method = "fdr", + do_parallel = TRUE, + cores = 2, + set_seed = TRUE, + seed_number = 1234 +) +} +\arguments{ +\item{gobject}{giotto object} + +\item{expression_values}{expression values to use} + +\item{ave_celltype_exp}{averege gene expression in each cell type} + +\item{selected_genes}{subset of selected genes (optional)} + +\item{spatial_network_name}{name of spatial network to use} + +\item{minimum_unique_cells}{minimum number of target cells required} + +\item{minimum_unique_int_cells}{minimum number of interacting cells required} + +\item{CCI_cell_score}{cell proximity score to filter no interacted cell} + +\item{dwls_cutoff}{cell type proportion cutoff to label the cell} + +\item{diff_test}{which differential expression test} + +\item{nr_permutations}{number of permutations if diff_test = permutation} + +\item{adjust_method}{which method to adjust p-values} + +\item{do_parallel}{run calculations in parallel with mclapply} + +\item{cores}{number of cores to use if do_parallel = TRUE} + +\item{set_seed}{set a seed for reproducibility} + +\item{seed_number}{seed number} +} +\value{ +cpgObject that contains the differential gene scores +} +\description{ +Identifies cell-to-cell Interaction Changed Genes (ICG) for spots, +i.e. genes expression residual that are different due to proximity to other cell types. +} +\details{ +Function to calculate if genes expreesion residual are differentially expressed in cell types + when they interact (approximated by physical proximity) with other cell types. + Gene expression residual calculated as: + (observed expression in spot - cell_type_proportion * average_expressed_in_cell_type) + The results data.table in the cpgObject contains - at least - the following columns: +\itemize{ + \item{genes:}{ All or selected list of tested genes} + \item{sel:}{ average gene expression residual in the interacting cells from the target cell type } + \item{other:}{ average gene expression residual in the NOT-interacting cells from the target cell type } + \item{pcc_sel:}{ correlation between cell proximity score and expression residual in the interacting cells from the target cell type} + \item{pcc_other:}{ correlation between cell proximity score and expression residual in the NOT-interacting cells from the target cell type } + \item{pcc_diff:}{ correlation difference between sel and other} + \item{p.value:}{ associated p-value} + \item{p.adj:}{ adjusted p-value} + \item{cell_type:}{ target cell type} + \item{int_cell_type:}{ interacting cell type} + \item{nr_select:}{ number of cells for selected target cell type} + \item{int_nr_select:}{ number of cells for interacting cell type} + \item{unif_int:}{ cell-cell interaction} +} +} diff --git a/man/findICG_per_interaction_spot.Rd b/man/findICG_per_interaction_spot.Rd new file mode 100644 index 000000000..a8878c803 --- /dev/null +++ b/man/findICG_per_interaction_spot.Rd @@ -0,0 +1,28 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/spatial_interaction_spot.R +\name{findICG_per_interaction_spot} +\alias{findICG_per_interaction_spot} +\title{findICG_per_interaction_spot} +\usage{ +findICG_per_interaction_spot( + sel_int, + all_ints, + proximityMat, + expr_residual, + dwls_values, + dwls_cutoff = 0.001, + CCI_cell_score = 0.01, + minimum_unique_cells = 1, + minimum_unique_int_cells = 1, + diff_test = "permutation", + n_perm = 100, + adjust_method = "fdr", + cores = 2, + set_seed = TRUE, + seed_number = 1234 +) +} +\description{ +Identifies genes that are differentially expressed due to proximity to other cell types for spots. +} +\keyword{internal} diff --git a/man/geneExpDWLS.Rd b/man/geneExpDWLS.Rd new file mode 100644 index 000000000..668916468 --- /dev/null +++ b/man/geneExpDWLS.Rd @@ -0,0 +1,20 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/spatial_interaction_spot.R +\name{geneExpDWLS} +\alias{geneExpDWLS} +\title{geneExpDWLS} +\usage{ +geneExpDWLS(gobject, spat_unit = NULL, feat_type = NULL, ave_celltype_exp) +} +\arguments{ +\item{gobject}{gottio object} + +\item{ave_celltype_exp}{data.table of gene expression in each cell type} +} +\value{ +matrix +} +\description{ +Compute predicted gene expression value by spatialDWSL results and +average gene expression for cell type +} diff --git a/man/giotto_lapply.Rd b/man/giotto_lapply.Rd new file mode 100644 index 000000000..94ea770d1 --- /dev/null +++ b/man/giotto_lapply.Rd @@ -0,0 +1,12 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/spatial_interaction_spot.R +\name{giotto_lapply} +\alias{giotto_lapply} +\title{giotto_lapply} +\usage{ +giotto_lapply(X, cores = NA, fun, ...) +} +\description{ +giotto_lapply +} +\keyword{internal} diff --git a/man/plotCellProximityGenesSpot.Rd b/man/plotCellProximityGenesSpot.Rd new file mode 100644 index 000000000..d7d22c13a --- /dev/null +++ b/man/plotCellProximityGenesSpot.Rd @@ -0,0 +1,72 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/spatial_interaction_spot.R +\name{plotCellProximityGenesSpot} +\alias{plotCellProximityGenesSpot} +\title{plotCellProximityGenesSpot} +\usage{ +plotCellProximityGenesSpot( + gobject, + cpgObject, + method = c("volcano", "cell_barplot", "cell-cell", "cell_sankey", "heatmap", "dotplot"), + min_cells = 4, + min_cells_expr_resi = 0.05, + min_int_cells = 4, + min_int_cells_expr_resi = 0.05, + min_fdr = 0.5, + min_pcc_diff = 0.05, + min_zscore = 0.05, + zscores_column = c("cell_type", "genes"), + direction = c("both", "up", "down"), + cell_color_code = NULL, + show_plot = NA, + return_plot = NA, + save_plot = NA, + save_param = list(), + default_save_name = "plotCellProximityGenes" +) +} +\arguments{ +\item{gobject}{giotto object} + +\item{cpgObject}{ICG (interaction changed gene) score object} + +\item{method}{plotting method to use} + +\item{min_cells}{minimum number of source cell type} + +\item{min_int_cells}{minimum number of interacting neighbor cell type} + +\item{min_fdr}{minimum adjusted p-value} + +\item{min_zscore}{minimum z-score change} + +\item{zscores_column}{calculate z-scores over cell types or genes} + +\item{direction}{differential expression directions to keep} + +\item{cell_color_code}{vector of colors with cell types as names} + +\item{show_plot}{show plots} + +\item{return_plot}{return plotting object} + +\item{save_plot}{directly save the plot [boolean]} + +\item{save_param}{list of saving parameters from \code{\link{all_plots_save_function}}} + +\item{default_save_name}{default save name for saving, don't change, change save_name in save_param} + +\item{min_cells_expr}{minimum expression level for source cell type} + +\item{min_int_cells_expr}{minimum expression level for interacting neighbor cell type} + +\item{min_spat_diff}{minimum absolute spatial expression difference} + +\item{min_log2_fc}{minimum log2 fold-change} +} +\value{ +plot +} +\description{ +Create visualization for cell proximity gene scores +} diff --git a/man/plotICGSpot.Rd b/man/plotICGSpot.Rd new file mode 100644 index 000000000..b3248dc16 --- /dev/null +++ b/man/plotICGSpot.Rd @@ -0,0 +1,49 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/spatial_interaction_spot.R +\name{plotICGSpot} +\alias{plotICGSpot} +\title{plotICGSpot} +\usage{ +plotICGSpot( + gobject, + cpgObject, + source_type, + source_markers, + ICG_genes, + cell_color_code = NULL, + show_plot = NA, + return_plot = NA, + save_plot = NA, + save_param = list(), + default_save_name = "plotICGSpot" +) +} +\arguments{ +\item{gobject}{giotto object} + +\item{cpgObject}{ICG (interaction changed gene) score object} + +\item{source_type}{cell type of the source cell} + +\item{source_markers}{markers for the source cell type} + +\item{ICG_genes}{named character vector of ICG genes} + +\item{cell_color_code}{cell color code for the interacting cell types} + +\item{show_plot}{show plots} + +\item{return_plot}{return plotting object} + +\item{save_plot}{directly save the plot [boolean]} + +\item{save_param}{list of saving parameters from \code{\link{all_plots_save_function}}} + +\item{default_save_name}{default save name for saving, don't change, change save_name in save_param} +} +\value{ +plot +} +\description{ +Create barplot to visualize interaction changed genes +} diff --git a/man/spatCellCellcomSpots.Rd b/man/spatCellCellcomSpots.Rd new file mode 100644 index 000000000..8e5d2547e --- /dev/null +++ b/man/spatCellCellcomSpots.Rd @@ -0,0 +1,92 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/spatial_interaction_spot.R +\name{spatCellCellcomSpots} +\alias{spatCellCellcomSpots} +\title{spatCellCellcomSpots} +\usage{ +spatCellCellcomSpots( + gobject, + spat_unit = NULL, + feat_type = NULL, + ave_celltype_exp, + spatial_network_name = "Delaunay_network", + cluster_column = "cell_ID", + random_iter = 1000, + gene_set_1, + gene_set_2, + min_observations = 2, + expression_values = c("normalized", "scaled", "custom"), + detailed = FALSE, + adjust_method = c("fdr", "bonferroni", "BH", "holm", "hochberg", "hommel", "BY", + "none"), + adjust_target = c("genes", "cells"), + do_parallel = TRUE, + cores = NA, + set_seed = TRUE, + seed_number = 1234, + verbose = c("a little", "a lot", "none") +) +} +\arguments{ +\item{gobject}{giotto object to use} + +\item{spatial_network_name}{spatial network to use for identifying interacting cells} + +\item{cluster_column}{cluster column with cell type information} + +\item{random_iter}{number of iterations} + +\item{gene_set_1}{first specific gene set from gene pairs} + +\item{gene_set_2}{second specific gene set from gene pairs} + +\item{min_observations}{minimum number of interactions needed to be considered} + +\item{detailed}{provide more detailed information (random variance and z-score)} + +\item{adjust_method}{which method to adjust p-values} + +\item{adjust_target}{adjust multiple hypotheses at the cell or gene level} + +\item{do_parallel}{run calculations in parallel with mclapply} + +\item{cores}{number of cores to use if do_parallel = TRUE} + +\item{set_seed}{set a seed for reproducibility} + +\item{seed_number}{seed number} + +\item{verbose}{verbose} +} +\value{ +Cell-Cell communication scores for gene pairs based on spatial interaction +} +\description{ +Spatial Cell-Cell communication scores based on spatial expression of interacting cells at spots resolution +} +\details{ +Statistical framework to identify if pairs of genes (such as ligand-receptor combinations) +are expressed at higher levels than expected based on a reshuffled null distribution +of gene expression values in cells that are spatially in proximity to eachother.. +\itemize{ + \item{LR_comb:}{Pair of ligand and receptor} + \item{lig_cell_type:}{ cell type to assess expression level of ligand } + \item{lig_expr:}{ average expression residual(observed - DWLS_predicted) of ligand in lig_cell_type } + \item{ligand:}{ ligand name } + \item{rec_cell_type:}{ cell type to assess expression level of receptor } + \item{rec_expr:}{ average expression residual(observed - DWLS_predicted) of receptor in rec_cell_type} + \item{receptor:}{ receptor name } + \item{LR_expr:}{ combined average ligand and receptor expression residual} + \item{lig_nr:}{ total number of cells from lig_cell_type that spatially interact with cells from rec_cell_type } + \item{rec_nr:}{ total number of cells from rec_cell_type that spatially interact with cells from lig_cell_type } + \item{rand_expr:}{ average combined ligand and receptor expression residual from random spatial permutations } + \item{av_diff:}{ average difference between LR_expr and rand_expr over all random spatial permutations } + \item{sd_diff:}{ (optional) standard deviation of the difference between LR_expr and rand_expr over all random spatial permutations } + \item{z_score:}{ (optinal) z-score } + \item{log2fc:}{ LR_expr - rand_expr } + \item{pvalue:}{ p-value } + \item{LR_cell_comb:}{ cell type pair combination } + \item{p.adj:}{ adjusted p-value } + \item{PI:}{ significanc score: log2fc * -log10(p.adj) } +} +} diff --git a/man/specific_CCCScores_spots.Rd b/man/specific_CCCScores_spots.Rd new file mode 100644 index 000000000..6eb6ecc1c --- /dev/null +++ b/man/specific_CCCScores_spots.Rd @@ -0,0 +1,94 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/spatial_interaction_spot.R +\name{specific_CCCScores_spots} +\alias{specific_CCCScores_spots} +\title{specific_CCCScores_spots} +\usage{ +specific_CCCScores_spots( + gobject, + spat_unit = NULL, + feat_type = NULL, + expr_residual, + dwls_values, + proximityMat, + random_iter = 1000, + cell_type_1 = "astrocytes", + cell_type_2 = "endothelial", + gene_set_1, + gene_set_2, + min_observations = 2, + detailed = FALSE, + adjust_method = c("fdr", "bonferroni", "BH", "holm", "hochberg", "hommel", "BY", + "none"), + adjust_target = c("genes", "cells"), + set_seed = FALSE, + seed_number = 1234, + verbose = T +) +} +\arguments{ +\item{gobject}{giotto object to use} + +\item{expr_residual}{spatial network to use for identifying interacting cells} + +\item{dwls_values}{dwls matrix} + +\item{proximityMat}{cell cell communication score matrix} + +\item{random_iter}{number of iterations} + +\item{cell_type_1}{first cell type} + +\item{cell_type_2}{second cell type} + +\item{gene_set_1}{first specific gene set from gene pairs} + +\item{gene_set_2}{second specific gene set from gene pairs} + +\item{min_observations}{minimum number of interactions needed to be considered} + +\item{detailed}{provide more detailed information (random variance and z-score)} + +\item{adjust_method}{which method to adjust p-values} + +\item{adjust_target}{adjust multiple hypotheses at the cell or gene level} + +\item{set_seed}{set a seed for reproducibility} + +\item{seed_number}{seed number} + +\item{verbose}{verbose} +} +\value{ +Cell-Cell communication scores for gene pairs based on spatial interaction +} +\description{ +Specific Cell-Cell communication scores based on spatial expression of interacting cells at spots resulation +} +\details{ +Statistical framework to identify if pairs of genes (such as ligand-receptor combinations) +are expressed at higher levels than expected based on a reshuffled null distribution +of gene expression values in cells that are spatially in proximity to eachother. +\itemize{ + \item{LR_comb:}{Pair of ligand and receptor} + \item{lig_cell_type:}{ cell type to assess expression level of ligand } + \item{lig_expr:}{ average expressionresidual(observed - DWLS_predicted) of ligand in lig_cell_type } + \item{ligand:}{ ligand name } + \item{rec_cell_type:}{ cell type to assess expression level of receptor } + \item{rec_expr:}{ average expression residual(observed - DWLS_predicted) of receptor in rec_cell_type} + \item{receptor:}{ receptor name } + \item{LR_expr:}{ combined average ligand and receptor expression } + \item{lig_nr:}{ total number of cells from lig_cell_type that spatially interact with cells from rec_cell_type } + \item{rec_nr:}{ total number of cells from rec_cell_type that spatially interact with cells from lig_cell_type } + \item{rand_expr:}{ average combined ligand and receptor expression residual from random spatial permutations } + \item{av_diff:}{ average difference between LR_expr and rand_expr over all random spatial permutations } + \item{sd_diff:}{ (optional) standard deviation of the difference between LR_expr and rand_expr over all random spatial permutations } + \item{z_score:}{ (optinal) z-score } + \item{log2fc:}{ LR_expr - rand_expr } + \item{pvalue:}{ p-value } + \item{LR_cell_comb:}{ cell type pair combination } + \item{p.adj:}{ adjusted p-value } + \item{PI:}{ significanc score: log2fc * -log10(p.adj) } +} +} +\keyword{internal} From ce73c421163ae647a3c76ed88f6ac31b914a1a13 Mon Sep 17 00:00:00 2001 From: josschavezf Date: Wed, 25 Jan 2023 18:55:59 -0500 Subject: [PATCH 106/129] fix out of bound error in specific_CCCScores_spots --- R/spatial_interaction_spot.R | 31 +++++++++++++++++++------------ 1 file changed, 19 insertions(+), 12 deletions(-) diff --git a/R/spatial_interaction_spot.R b/R/spatial_interaction_spot.R index b3589e2fe..549f4a69e 100644 --- a/R/spatial_interaction_spot.R +++ b/R/spatial_interaction_spot.R @@ -1612,7 +1612,7 @@ specific_CCCScores_spots = function(gobject, cell_direction_1 = paste0(cell_type_1,'--',cell_type_2) cell_direction_2 = paste0(cell_type_2,'--',cell_type_1) - print(paste0('Processing sepcific CCC Scores: ', cell_direction_1)) + print(paste0('Processing specific CCC Scores: ', cell_direction_1)) proxi_1 = proximityMat[cell_direction_1,] proxi_2 = proximityMat[cell_direction_2,] @@ -1668,9 +1668,12 @@ specific_CCCScores_spots = function(gobject, total_bool = rep(0, nrow(comScore)) - all_cell_ids = pDataDT(gobject = gobject, - spat_unit = spat_unit, - feat_type = feat_type)$cell_ID + # all_cell_ids = pDataDT(gobject = gobject, + # spat_unit = spat_unit, + # feat_type = feat_type)$cell_ID + + all_cell_ids = colnames(expr_residual) + ## simulations ## for(sim in 1:random_iter) { @@ -1681,9 +1684,12 @@ specific_CCCScores_spots = function(gobject, seed_number = seed_number+sim set.seed(seed = seed_number) } - random_ids_1 = all_cell_ids[sample(length(all_cell_ids), size = length(ct1_cell_ids))] - random_ids_2 = all_cell_ids[sample(length(all_cell_ids), size = length(ct2_cell_ids))] - + #random_ids_1 = all_cell_ids[sample(length(all_cell_ids), size = length(ct1_cell_ids))] + #random_ids_2 = all_cell_ids[sample(length(all_cell_ids), size = length(ct2_cell_ids))] + + random_ids_1 = sample(all_cell_ids, size = length(ct1_cell_ids), replace = FALSE) + random_ids_2 = sample(all_cell_ids, size = length(ct2_cell_ids), replace = FALSE) + # get gene expression residual for ligand and receptor random_expr_res_L = expr_residual[gene_set_1, random_ids_1] random_expr_res_R = expr_residual[gene_set_2, random_ids_2] @@ -1826,16 +1832,17 @@ spatCellCellcomSpots = function(gobject, verbose = match.arg(verbose, choices = c('a little', 'a lot', 'none')) ## check if spatial network exists ## - spat_networks = showGiottoSpatNetworks(gobject = gobject) + spat_networks = names(gobject@spatial_network[[spat_unit]]) + if(!spatial_network_name %in% spat_networks) { stop(spatial_network_name, ' is not an existing spatial network \n', - 'use showNetworks() to see the available networks \n', + 'use showGiottoSpatNetworks() to see the available networks \n', 'or create a new spatial network with createSpatialNetwork() \n') } # expression data - values = match.arg(expression_values, choices = unique(c('normalized', 'scaled', 'custom', expression_values))) + values = match.arg(expression_values, choices = c('normalized', 'scaled', 'custom')) expr_residual = cal_expr_residual(gobject = gobject, spat_unit = spat_unit, feat_type = feat_type, @@ -1877,8 +1884,8 @@ spatCellCellcomSpots = function(gobject, ## get all combinations between cell types combn_DT = data.table::data.table(LR_cell_comb = rownames(proximityMat)) - combn_DT = combn_DT[, V1 := strsplit(LR_cell_comb, '--')[[1]][1], by = 1:nrow(combn_DT)] - combn_DT = combn_DT[, V2 := strsplit(LR_cell_comb, '--')[[1]][2], by = 1:nrow(combn_DT)] + combn_DT[, V1 := strsplit(LR_cell_comb, '--')[[1]][1], by = 1:nrow(combn_DT)] + combn_DT[, V2 := strsplit(LR_cell_comb, '--')[[1]][2], by = 1:nrow(combn_DT)] ## parallel option ## if(do_parallel == TRUE) { From 3e2b48ed6d791447fbdb228ceaee49c8140b19c9 Mon Sep 17 00:00:00 2001 From: jiajic <72078254+jiajic@users.noreply.github.com> Date: Thu, 26 Jan 2023 09:19:23 -0500 Subject: [PATCH 107/129] Generics update and add onattach message - name change for spatialWeightMatrix to createSpatialWeightMatrix - modifications on some generics in documentation and to make some exported - add zzz.r --- DESCRIPTION | 1 + NAMESPACE | 9 ++ NEWS.md | 2 +- R/generics.R | 83 ++++++++++++++----- R/spatial_enrichment.R | 14 ++-- R/spatial_structures.R | 17 ++-- R/zzz.R | 6 ++ ...Matrix.Rd => createSpatialWeightMatrix.Rd} | 6 +- man/row-plus-colnames-generic.Rd | 23 +++++ man/spatIDs-generic.Rd | 47 ++++++++++- man/transpose-generic.Rd | 13 ++- 11 files changed, 174 insertions(+), 47 deletions(-) create mode 100644 R/zzz.R rename man/{spatialWeightMatrix.Rd => createSpatialWeightMatrix.Rd} (92%) create mode 100644 man/row-plus-colnames-generic.Rd diff --git a/DESCRIPTION b/DESCRIPTION index 07715a841..a203635ed 100644 --- a/DESCRIPTION +++ b/DESCRIPTION @@ -149,6 +149,7 @@ Collate: 'utils-pipe.R' 'variable_genes.R' 'wnn.R' + 'zzz.R' biocViews: VignetteBuilder: knitr Config/testthat/edition: 3 diff --git a/NAMESPACE b/NAMESPACE index f006eb3fd..56bb0be19 100644 --- a/NAMESPACE +++ b/NAMESPACE @@ -103,6 +103,7 @@ export(createSpatialFeaturesKNNnetwork) export(createSpatialGrid) export(createSpatialKNNnetwork) export(createSpatialNetwork) +export(createSpatialWeightMatrix) export(cropGiottoLargeImage) export(crossSectionGenePlot) export(crossSectionGenePlot3D) @@ -375,6 +376,8 @@ export(subClusterCells) export(subsetGiotto) export(subsetGiottoLocs) export(subsetGiottoLocsMulti) +export(t.spatLocsObj) +export(t.spatialNetworkObj) export(trendSceek) export(updateGiottoImage) export(updateGiottoImageMG) @@ -410,8 +413,10 @@ exportMethods("featType<-") exportMethods("objName<-") exportMethods("prov<-") exportMethods("spatUnit<-") +exportMethods(colnames) exportMethods(copy) exportMethods(dim) +exportMethods(featIDs) exportMethods(featType) exportMethods(ncol) exportMethods(nrow) @@ -419,6 +424,8 @@ exportMethods(objName) exportMethods(plot) exportMethods(prov) exportMethods(rbind2) +exportMethods(rownames) +exportMethods(spatIDs) exportMethods(spatShift) exportMethods(spatUnit) exportMethods(spin) @@ -437,6 +444,8 @@ importFrom(methods,show) importFrom(methods,slot) importFrom(methods,validObject) importMethodsFrom(Matrix,t) +importMethodsFrom(terra,ncol) +importMethodsFrom(terra,nrow) importMethodsFrom(terra,spin) importMethodsFrom(terra,t) importMethodsFrom(terra,unwrap) diff --git a/NEWS.md b/NEWS.md index 9e01afffd..8cc79fea3 100644 --- a/NEWS.md +++ b/NEWS.md @@ -10,7 +10,7 @@ - New `gefToGiotto()` interoperability function to convert gef object from Stereo-seq to giotto - New `giottoToAnnData()` interoperability function to convert giotto object to squidpy flavor anndata .h5ad file(s) - New `spatialAutoCorLocal()` and `spatialAutoCorGlobal()` functions to find spatial autocorrelations from expression and cell metadata information -- New `spatialWeightMatrix()` function to generate spatial weight matrix from spatial networks for autocorrelation +- New `createSpatialWeightMatrix()` function to generate spatial weight matrix from spatial networks for autocorrelation - Add `coord_fix_ratio` param to `spatFeatPlot2D()` and `spatFeatPlot2D_single()` - Add `order` parameter to `dimFeatPlot2D` and `spatDimFeatPlot2d` to plot and order cells according to the levels of the selected feature ([#477](https://github.com/drieslab/Giotto/issues/477)) - Add `plot()` method for `spatialNetworkObj` diff --git a/R/generics.R b/R/generics.R index c10124ef0..e13032120 100644 --- a/R/generics.R +++ b/R/generics.R @@ -5,9 +5,10 @@ # spatIDs and featIDs generic #### -#' @title Cell and feature names +#' @title Spatial and feature IDs #' @name spatIDs-generic -#' @description Get the cells and feature names of a giotto object or subobject +#' @description Get the cell IDs (termed spatial IDs to better reflect when not at +#' the single-cell level) and feature IDs of a giotto object or subobject #' @aliases spatIDs featIDs #' @param x an object #' @param spat_unit (optional) specify which spatial unit @@ -24,62 +25,88 @@ setGeneric('spatIDs', function(x, spat_unit, ...) standardGeneric('spatIDs')) setGeneric('featIDs', function(x, feat_type, ...) standardGeneric('featIDs')) - +#' @rdname spatIDs-generic +#' @export setMethod('spatIDs', signature(x = 'giotto', spat_unit = 'missing'), function(x, ...) { get_cell_id(gobject = x, ...) }) +#' @rdname spatIDs-generic +#' @export setMethod('spatIDs', signature(x = 'giotto', spat_unit = 'character'), function(x, spat_unit, ...) { get_cell_id(gobject = x, spat_unit, ...) }) +#' @rdname spatIDs-generic +#' @export setMethod('spatIDs', signature(x = c('exprObj'), spat_unit = 'missing'), function(x, ...) { colnames(x[]) }) +#' @rdname spatIDs-generic +#' @export setMethod('spatIDs', signature(x = c('spatLocsObj'), spat_unit = 'missing'), function(x, ...) { x[]$cell_ID }) +#' @rdname spatIDs-generic +#' @export setMethod('spatIDs', signature(x = c('cellMetaObj'), spat_unit = 'missing'), function(x, ...) { x[]$cell_ID }) +#' @rdname spatIDs-generic +#' @export setMethod('spatIDs', signature(x = c('spatialNetworkObj'), spat_unit = 'missing'), function(x, ...) { unique(c(x[]$from, x[]$to)) }) +#' @rdname spatIDs-generic +#' @export setMethod('spatIDs', signature(x = 'dimObj', spat_unit = 'missing'), function(x, ...) { rownames(x@coordinates) }) +#' @rdname spatIDs-generic +#' @export setMethod('spatIDs', signature(x = 'giottoPolygon', spat_unit = 'missing'), function(x, ...) { unique(x@spatVector$poly_ID) }) +#' @rdname spatIDs-generic +#' @export setMethod('spatIDs', signature(x = 'spatEnrObj', spat_unit = 'missing'), function(x, ...) { cell_ID = NULL x@enrichDT[, cell_ID] }) - +#' @rdname spatIDs-generic +#' @export setMethod('featIDs', signature(x = 'giotto', feat_type = 'missing'), function(x, ...) { get_feat_id(gobject = x, ...) }) +#' @rdname spatIDs-generic +#' @export setMethod('featIDs', signature(x = 'giotto', feat_type = 'character'), function(x, feat_type, ...) { get_feat_id(gobject = x, feat_type, ...) }) +#' @rdname spatIDs-generic +#' @export setMethod('featIDs', signature(x = 'exprObj', feat_type = 'missing'), function(x, ...) { rownames(x[]) }) +#' @rdname spatIDs-generic +#' @export setMethod('featIDs', signature(x = 'giottoPoints', feat_type = 'missing'), function(x, ...) { unique(x@spatVector$feat_ID) }) +#' @rdname spatIDs-generic +#' @export setMethod('featIDs', signature(x = 'spatEnrObj', feat_type = 'missing'), function(x, ...) { colnames(x@enrichDT[, -'cell_ID']) @@ -93,14 +120,27 @@ setMethod('featIDs', signature(x = 'spatEnrObj', feat_type = 'missing'), # colnames and rownames generics #### -setMethod('colnames', signature(x = 'exprObj'), - function(x) { - colnames(x[]) - }) -setMethod('rownames', signature(x = 'exprObj'), - function(x) { - rownames(x[]) - }) +#' @title Row and column names +#' @name row-plus-colnames-generic +#' @aliases colnames rownames +#' @description Retrieve or set the row or column names of an object +#' @param x object +#' @return A character vector of row or col names +if(!isGeneric('colnames')) setOldClass('colnames') +if(!isGeneric('rownames')) setOldClass('rownames') + + +#' @rdname row-plus-colnames-generic +#' @export +setMethod('colnames', signature(x = 'exprObj'), function(x) colnames(x[])) + +#' @rdname row-plus-colnames-generic +#' @export +setMethod('rownames', signature(x = 'exprObj'), function(x) rownames(x[])) + + + + @@ -238,6 +278,7 @@ setMethod('spatShift', signature('spatialNetworkObj'), function(x, dx = 0, dy = #' @name dims-generic #' @description Find the dimensions of an object #' @include classes.R +#' @importMethodsFrom terra nrow ncol #' @param x object to check dimensions of NULL @@ -322,9 +363,10 @@ setMethod('dim', signature('enrData'), function(x) dim(x@enrichDT)) #' @importMethodsFrom Matrix t #' @importMethodsFrom terra t #' @aliases t -if(!isGeneric('t')) setOldClass('t', where = as.environment("package:Giotto")) +NULL +# if(!isGeneric('t')) setOldClass('t', where = as.environment("package:Giotto")) -#' @describeIn transpose-generic Transpose a spatLocObj +#' @rdname transpose-generic #' @export setMethod('t', signature('spatLocsObj'), function(x) { sdimy = sdimx = NULL @@ -332,7 +374,7 @@ setMethod('t', signature('spatLocsObj'), function(x) { x@coordinates[, c('sdimx', 'sdimy') := .(sdimy, sdimx)] return(x) }) -#' @describeIn transpose-generic Transpose a spatialNeworkObj +#' @rdname transpose-generic #' @export setMethod('t', signature('spatialNetworkObj'), function(x) { sdimx_begin = sdimx_end = sdimy_begin = sdimy_end = NULL @@ -345,12 +387,17 @@ setMethod('t', signature('spatialNetworkObj'), function(x) { }) # s3 methods +#' @rdname transpose-generic +#' @export t.spatLocsObj = function(x) { sdimy = sdimx = NULL x = data.table::copy(x) x@coordinates[, c('sdimx', 'sdimy') := .(sdimy, sdimx)] return(x) } + +#' @rdname transpose-generic +#' @export t.spatialNetworkObj = function(x) { sdimx_begin = sdimx_end = sdimy_begin = sdimy_end = NULL x = data.table::copy(x) @@ -547,8 +594,7 @@ setMethod("rbind", "giottoPolygon", function(..., deparse.level = 1) { #' @param \dots additional parameters to pass #' @aliases plot #' @family plot -#' @exportMethod plot -if(!isGeneric('plot')) setOldClass('plot') +NULL #' @describeIn plot-generic Plot \emph{magick}-based giottoImage object. ... param passes to \code{\link{plot_giottoImage_MG}} #' @export @@ -613,7 +659,7 @@ setMethod('plot', signature(x = 'spatLocsObj', y = 'missing'), function(x, ...) if(is.null(l$xlab)) l$xlab = '' if(is.null(l$ylab)) l$ylab = '' if(is.null(l$cex)) l$cex = 0.5 - if(nrow(x@coordinates) > 10000L) { + if(nrow(x) > 10000L) { if(is.null(l$pch)) l$pch = '.' } @@ -663,7 +709,6 @@ setMethod('plot', signature(x = 'spatialNetworkObj', y = 'missing'), function(x, - # copy() S4 generic #### #' @title Copy an entire object #' @name copy-generic diff --git a/R/spatial_enrichment.R b/R/spatial_enrichment.R index a63ab7a78..d2bee0f3e 100644 --- a/R/spatial_enrichment.R +++ b/R/spatial_enrichment.R @@ -1957,13 +1957,13 @@ evaluate_autocor_input = function(gobject, 'No spatial weight matrix found in selected spatial network Generating', wm_method, 'matrix from', spatial_network_to_use ) - weight_matrix = spatialWeightMatrix(gobject = gobject, - spat_unit = spat_unit, - spatial_network_to_use = spatial_network_to_use, - wm_name = wm_name, - method = wm_method, - return_gobject = FALSE, - verbose = FALSE) + weight_matrix = createSpatialWeightMatrix(gobject = gobject, + spat_unit = spat_unit, + spatial_network_to_use = spatial_network_to_use, + wm_name = wm_name, + method = wm_method, + return_gobject = FALSE, + verbose = FALSE) } wm_colnames = colnames(weight_matrix) #SPATNET=================================================================# diff --git a/R/spatial_structures.R b/R/spatial_structures.R index 2d1ecbc2b..66e6bb062 100644 --- a/R/spatial_structures.R +++ b/R/spatial_structures.R @@ -495,7 +495,7 @@ compatible_spatial_network = function(spatial_network, #' @title Create a spatial weight matrix -#' @name spatialWeightMatrix +#' @name createSpatialWeightMatrix #' @description Generate spatial weight matrix based on the strength of spatial #' interactions between nodes. Requires spatial networks to be first generated. #' @param gobject giotto object @@ -513,13 +513,14 @@ compatible_spatial_network = function(spatial_network, #' \item{\code{"adjacency"} method is a binary matrix with 1 signifying that two nodes #' are connected in the spatial network and 0 indicating that they are not.} #' } -spatialWeightMatrix = function(gobject, - spat_unit = NULL, - spatial_network_to_use = 'kNN_network', - method = c('distance', 'adjacency'), - wm_name = 'spat_weights', - return_gobject = TRUE, - verbose = TRUE) { +#' @export +createSpatialWeightMatrix = function(gobject, + spat_unit = NULL, + spatial_network_to_use = 'kNN_network', + method = c('distance', 'adjacency'), + wm_name = 'spat_weights', + return_gobject = TRUE, + verbose = TRUE) { # 1. setup spat_unit = set_default_spat_unit(gobject = gobject, diff --git a/R/zzz.R b/R/zzz.R new file mode 100644 index 000000000..fe471c776 --- /dev/null +++ b/R/zzz.R @@ -0,0 +1,6 @@ +# Run on library loading + +# print version number +.onAttach = function(libname, pkgname) { + packageStartupMessage('Giotto Suite ', utils::packageVersion('Giotto')) +} diff --git a/man/spatialWeightMatrix.Rd b/man/createSpatialWeightMatrix.Rd similarity index 92% rename from man/spatialWeightMatrix.Rd rename to man/createSpatialWeightMatrix.Rd index 91bd1d483..7434e1bf6 100644 --- a/man/spatialWeightMatrix.Rd +++ b/man/createSpatialWeightMatrix.Rd @@ -1,10 +1,10 @@ % Generated by roxygen2: do not edit by hand % Please edit documentation in R/spatial_structures.R -\name{spatialWeightMatrix} -\alias{spatialWeightMatrix} +\name{createSpatialWeightMatrix} +\alias{createSpatialWeightMatrix} \title{Create a spatial weight matrix} \usage{ -spatialWeightMatrix( +createSpatialWeightMatrix( gobject, spat_unit = NULL, spatial_network_to_use = "kNN_network", diff --git a/man/row-plus-colnames-generic.Rd b/man/row-plus-colnames-generic.Rd new file mode 100644 index 000000000..c0d29a682 --- /dev/null +++ b/man/row-plus-colnames-generic.Rd @@ -0,0 +1,23 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/generics.R +\name{row-plus-colnames-generic} +\alias{row-plus-colnames-generic} +\alias{colnames} +\alias{rownames} +\alias{colnames,exprObj-method} +\alias{rownames,exprObj-method} +\title{Row and column names} +\usage{ +\S4method{colnames}{exprObj}(x) + +\S4method{rownames}{exprObj}(x) +} +\arguments{ +\item{x}{object} +} +\value{ +A character vector of row or col names +} +\description{ +Retrieve or set the row or column names of an object +} diff --git a/man/spatIDs-generic.Rd b/man/spatIDs-generic.Rd index e76112368..bad1fa762 100644 --- a/man/spatIDs-generic.Rd +++ b/man/spatIDs-generic.Rd @@ -4,7 +4,21 @@ \alias{spatIDs-generic} \alias{spatIDs} \alias{featIDs} -\title{Cell and feature names} +\alias{spatIDs,giotto,missing-method} +\alias{spatIDs,giotto,character-method} +\alias{spatIDs,exprObj,missing-method} +\alias{spatIDs,spatLocsObj,missing-method} +\alias{spatIDs,cellMetaObj,missing-method} +\alias{spatIDs,spatialNetworkObj,missing-method} +\alias{spatIDs,dimObj,missing-method} +\alias{spatIDs,giottoPolygon,missing-method} +\alias{spatIDs,spatEnrObj,missing-method} +\alias{featIDs,giotto,missing-method} +\alias{featIDs,giotto,character-method} +\alias{featIDs,exprObj,missing-method} +\alias{featIDs,giottoPoints,missing-method} +\alias{featIDs,spatEnrObj,missing-method} +\title{Spatial and feature IDs} \usage{ spatIDs(x, spat_unit, ...) @@ -12,6 +26,34 @@ featIDs(x, feat_type, ...) ## Default S4 method for signatures: ## 'giotto', 'exprObj', 'spatLocsObj', 'cellMetaObj', 'spatialNetworkObj' 'dimObj' + +\S4method{spatIDs}{giotto,missing}(x, spat_unit, ...) + +\S4method{spatIDs}{giotto,character}(x, spat_unit, ...) + +\S4method{spatIDs}{exprObj,missing}(x, spat_unit, ...) + +\S4method{spatIDs}{spatLocsObj,missing}(x, spat_unit, ...) + +\S4method{spatIDs}{cellMetaObj,missing}(x, spat_unit, ...) + +\S4method{spatIDs}{spatialNetworkObj,missing}(x, spat_unit, ...) + +\S4method{spatIDs}{dimObj,missing}(x, spat_unit, ...) + +\S4method{spatIDs}{giottoPolygon,missing}(x, spat_unit, ...) + +\S4method{spatIDs}{spatEnrObj,missing}(x, spat_unit, ...) + +\S4method{featIDs}{giotto,missing}(x, feat_type, ...) + +\S4method{featIDs}{giotto,character}(x, feat_type, ...) + +\S4method{featIDs}{exprObj,missing}(x, feat_type, ...) + +\S4method{featIDs}{giottoPoints,missing}(x, feat_type, ...) + +\S4method{featIDs}{spatEnrObj,missing}(x, feat_type, ...) } \arguments{ \item{x}{an object} @@ -23,5 +65,6 @@ featIDs(x, feat_type, ...) \item{feat_type}{(optional) specify which feature type} } \description{ -Get the cells and feature names of a giotto object or subobject +Get the cell IDs (termed spatial IDs to better reflect when not at +the single-cell level) and feature IDs of a giotto object or subobject } diff --git a/man/transpose-generic.Rd b/man/transpose-generic.Rd index d83ff5408..987f00655 100644 --- a/man/transpose-generic.Rd +++ b/man/transpose-generic.Rd @@ -5,11 +5,17 @@ \alias{t} \alias{t,spatLocsObj-method} \alias{t,spatialNetworkObj-method} +\alias{t.spatLocsObj} +\alias{t.spatialNetworkObj} \title{Transpose} \usage{ \S4method{t}{spatLocsObj}(x) \S4method{t}{spatialNetworkObj}(x) + +t.spatLocsObj(x) + +t.spatialNetworkObj(x) } \arguments{ \item{x}{object to be transposed} @@ -17,10 +23,3 @@ \description{ Transpose } -\section{Functions}{ -\itemize{ -\item \code{t(spatLocsObj)}: Transpose a spatLocObj - -\item \code{t(spatialNetworkObj)}: Transpose a spatialNeworkObj - -}} From 4cf4ede86de6713530dcaefcfbb1445d40a0e7ad Mon Sep 17 00:00:00 2001 From: josschavezf Date: Thu, 26 Jan 2023 10:17:23 -0500 Subject: [PATCH 108/129] update spatial_interaction_visuals.R --- R/spatial_interaction_visuals.R | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/R/spatial_interaction_visuals.R b/R/spatial_interaction_visuals.R index 0a0a6fc36..7ac418f4a 100644 --- a/R/spatial_interaction_visuals.R +++ b/R/spatial_interaction_visuals.R @@ -2241,7 +2241,7 @@ plotCCcomHeatmap = function(gobject, #' @name plotCCcomDotplot #' @description Plots dotplot for ligand-receptor communication scores in cell-cell interactions #' @param gobject giotto object -#' @param comScores communinication scores from \code{\link{exprCellCellcom}} or \code{\link{spatCellCellcom}} +#' @param comScores communication scores from \code{\link{exprCellCellcom}} or \code{\link{spatCellCellcom}} #' @param selected_LR selected ligand-receptor combinations #' @param selected_cell_LR selected cell-cell combinations for ligand-receptor combinations #' @param show_LR_names show ligand-receptor names From 24cce6a325618f02a0b4c09e1a012a06481518f8 Mon Sep 17 00:00:00 2001 From: jiajic <72078254+jiajic@users.noreply.github.com> Date: Fri, 27 Jan 2023 11:30:20 -0500 Subject: [PATCH 109/129] Older terra compatibility Change unwrap usage to vect. Can also add unwrap generic later as a wrapper of this. --- NAMESPACE | 4 ++-- R/general_help.R | 8 ++++---- R/generics.R | 26 ++++++++++++++------------ man/wrap-generic.Rd | 18 +++++++++--------- 4 files changed, 29 insertions(+), 27 deletions(-) diff --git a/NAMESPACE b/NAMESPACE index 56bb0be19..9fbeef2bf 100644 --- a/NAMESPACE +++ b/NAMESPACE @@ -430,7 +430,7 @@ exportMethods(spatShift) exportMethods(spatUnit) exportMethods(spin) exportMethods(t) -exportMethods(unwrap) +exportMethods(vect) exportMethods(wrap) import(data.table) import(ggplot2) @@ -448,5 +448,5 @@ importMethodsFrom(terra,ncol) importMethodsFrom(terra,nrow) importMethodsFrom(terra,spin) importMethodsFrom(terra,t) -importMethodsFrom(terra,unwrap) +importMethodsFrom(terra,vect) importMethodsFrom(terra,wrap) diff --git a/R/general_help.R b/R/general_help.R index a523702c8..384af4955 100644 --- a/R/general_help.R +++ b/R/general_help.R @@ -1859,9 +1859,9 @@ readPolygonFilesVizgenHDF5 = function(boundaries_path, # unwrap results smooth_cell_polygons_list = lapply(smooth_cell_polygons_list, function(x) { - slot(x, 'spatVector') = terra::unwrap(slot(x, 'spatVector')) + slot(x, 'spatVector') = terra::vect(slot(x, 'spatVector')) if(isTRUE(calc_centroids)) { - slot(x, 'spatVectorCentroids') = terra::unwrap(slot(x, 'spatVectorCentroids')) + slot(x, 'spatVectorCentroids') = terra::vect(slot(x, 'spatVectorCentroids')) } return(x) }) @@ -1921,9 +1921,9 @@ readPolygonFilesVizgenHDF5 = function(boundaries_path, # unwrap results smooth_cell_polygons_list = lapply(seq_along(smooth_cell_polygons_list), function(i) { p_list = lapply(smooth_cell_polygons_list[[i]], function(x) { - slot(x, 'spatVector') = terra::unwrap(slot(x, 'spatVector')) + slot(x, 'spatVector') = terra::vect(slot(x, 'spatVector')) if(isTRUE(calc_centroids)) { - slot(x, 'spatVectorCentroids') = terra::unwrap(slot(x, 'spatVectorCentroids')) + slot(x, 'spatVectorCentroids') = terra::vect(slot(x, 'spatVectorCentroids')) } return(x) }) diff --git a/R/generics.R b/R/generics.R index e13032120..c9202a6ce 100644 --- a/R/generics.R +++ b/R/generics.R @@ -476,22 +476,24 @@ setMethod('wrap', signature(x = 'giottoPoints'), ) +# unwrap methods #### +# For compatibility before terra 1.6.41, vect will be used #' @describeIn wrap-generic Unwrap giottoPolygon -#' @importMethodsFrom terra unwrap +#' @importMethodsFrom terra vect #' @export -setMethod('unwrap', signature(x = 'packedGiottoPolygon'), +setMethod('vect', signature(x = 'packedGiottoPolygon'), function(x) { gp = new('giottoPolygon') gp@name = x@name - gp@spatVector = terra::unwrap(x@packed_spatVector) + gp@spatVector = terra::vect(x@packed_spatVector) if(!is.null(x@packed_spatVectorCentroids)) { - gp@spatVectorCentroids = terra::unwrap(x@packed_spatVectorCentroids) + gp@spatVectorCentroids = terra::vect(x@packed_spatVectorCentroids) } if(length(x@packed_overlaps) > 0) { gp@overlaps = lapply(x@packed_overlaps, function(sv) { if(inherits(sv, 'PackedSpatVector')) { - terra::unwrap(sv) + terra::vect(sv) } else { sv } @@ -504,13 +506,13 @@ setMethod('unwrap', signature(x = 'packedGiottoPolygon'), #' @describeIn wrap-generic Unwrap giottoPolygon -#' @importMethodsFrom terra unwrap +#' @importMethodsFrom terra vect #' @export -setMethod('unwrap', signature(x = 'packedGiottoPoints'), +setMethod('vect', signature(x = 'packedGiottoPoints'), function(x) { gp = new('giottoPoints') gp@feat_type = x@feat_type - gp@spatVector = terra::unwrap(x@packed_spatVector) + gp@spatVector = terra::vect(x@packed_spatVector) gp@networks = x@networks return(gp) } @@ -518,9 +520,9 @@ setMethod('unwrap', signature(x = 'packedGiottoPoints'), #' @describeIn wrap-generic Unwrap giotto -#' @importMethodsFrom terra unwrap +#' @importMethodsFrom terra vect #' @export -setMethod('unwrap', signature(x = 'packedGiotto'), +setMethod('vect', signature(x = 'packedGiotto'), function(x) { gobj = new('giotto') g_slots = methods::slotNames('giotto') @@ -528,8 +530,8 @@ setMethod('unwrap', signature(x = 'packedGiotto'), for(g_slot in g_slots) { slot(gobj, g_slot) = slot(x, g_slot) } - gobj@spatial_info = lapply(x@packed_spatial_info, unwrap) - gobj@feat_info = lapply(x@packed_feat_info, unwrap) + gobj@spatial_info = lapply(x@packed_spatial_info, vect) + gobj@feat_info = lapply(x@packed_feat_info, vect) return(gobj) }) diff --git a/man/wrap-generic.Rd b/man/wrap-generic.Rd index 50cbe8245..1bfdcce5e 100644 --- a/man/wrap-generic.Rd +++ b/man/wrap-generic.Rd @@ -5,9 +5,9 @@ \alias{wrap,giottoPolygon-method} \alias{wrap,giotto-method} \alias{wrap,giottoPoints-method} -\alias{unwrap,packedGiottoPolygon-method} -\alias{unwrap,packedGiottoPoints-method} -\alias{unwrap,packedGiotto-method} +\alias{vect,packedGiottoPolygon-method} +\alias{vect,packedGiottoPoints-method} +\alias{vect,packedGiotto-method} \title{Wrap giotto terra pointer information} \usage{ \S4method{wrap}{giottoPolygon}(x) @@ -16,11 +16,11 @@ \S4method{wrap}{giottoPoints}(x) -\S4method{unwrap}{packedGiottoPolygon}(x) +\S4method{vect}{packedGiottoPolygon}(x) -\S4method{unwrap}{packedGiottoPoints}(x) +\S4method{vect}{packedGiottoPoints}(x) -\S4method{unwrap}{packedGiotto}(x) +\S4method{vect}{packedGiotto}(x) } \arguments{ \item{x}{giottoPolygon or giottoPoints} @@ -38,10 +38,10 @@ be passed over a connection (e.g. nodes on a computer cluster) \item \code{wrap(giottoPoints)}: Wrap giottoPoints -\item \code{unwrap(packedGiottoPolygon)}: Unwrap giottoPolygon +\item \code{vect(packedGiottoPolygon)}: Unwrap giottoPolygon -\item \code{unwrap(packedGiottoPoints)}: Unwrap giottoPolygon +\item \code{vect(packedGiottoPoints)}: Unwrap giottoPolygon -\item \code{unwrap(packedGiotto)}: Unwrap giotto +\item \code{vect(packedGiotto)}: Unwrap giotto }} From 3cd8c23c2438036c618397f2b10dbdf92757385b Mon Sep 17 00:00:00 2001 From: RubD Date: Fri, 27 Jan 2023 11:35:40 -0500 Subject: [PATCH 110/129] fix feat shape code --- R/spatial_in_situ_visuals.R | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/R/spatial_in_situ_visuals.R b/R/spatial_in_situ_visuals.R index 8dae8f1d9..6b44f66e3 100644 --- a/R/spatial_in_situ_visuals.R +++ b/R/spatial_in_situ_visuals.R @@ -273,6 +273,7 @@ plot_feature_points_layer = function(ggobject, + # manually set feature color code if(!is.null(feats_color_code)) { pl = pl + ggplot2::scale_color_manual(values = feats_color_code) } else { @@ -282,6 +283,11 @@ plot_feature_points_layer = function(ggobject, pl = pl + ggplot2::scale_color_manual(values = feats_color_code) } + # manually set feature shape color code + if(!is.null(feat_shape_code)) { + pl = pl + ggplot2::scale_shape_manual(values = feat_shape_code) + } + return(pl) } From e779c19e3c56470055b10e5b557a272a5d6d2643 Mon Sep 17 00:00:00 2001 From: jiajic <72078254+jiajic@users.noreply.github.com> Date: Fri, 27 Jan 2023 14:20:31 -0500 Subject: [PATCH 111/129] Update NEWS.md reflect the change from unwrap to vect --- NEWS.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/NEWS.md b/NEWS.md index 5b7fd5ad1..9fddefa45 100644 --- a/NEWS.md +++ b/NEWS.md @@ -24,7 +24,7 @@ - Add missing `create_nn_net_obj()` internal constructor function for S4 `nnNetObj` - Add `id_col`, `x_col`, `y_col` params to `polyStamp()` to make stamp location input more flexible - Add `optional` and `custom_msg` params to `package_check()` -- New `wrap()` and `unwrap()` generics for `giotto`, `giottoPoints`, and `giottoPolygons` +- New `wrap()` and `vect()` generics for `giotto`, `giottoPoints`, and `giottoPolygons` - New `rotate()`, `t()`, and `spatShift` generics for giotto subobject spatial manipulation - New `spatIDs()` and `featIDs()` generics - New `objName()` and `objName` generics for setting the names of relevant S4 subobjects From bc127d10e69a5b8ab33fb09e04367180dc3d7d6c Mon Sep 17 00:00:00 2001 From: jiajic <72078254+jiajic@users.noreply.github.com> Date: Fri, 27 Jan 2023 15:19:26 -0500 Subject: [PATCH 112/129] Update news.md --- DESCRIPTION | 2 +- NEWS.md | 9 +++------ R/giotto_structures.R | 4 ++-- R/spatial_in_situ_visuals.R | 8 ++++---- man/plotCCcomDotplot.Rd | 2 +- 5 files changed, 11 insertions(+), 14 deletions(-) diff --git a/DESCRIPTION b/DESCRIPTION index 750bb2991..818849712 100644 --- a/DESCRIPTION +++ b/DESCRIPTION @@ -1,6 +1,6 @@ Package: Giotto Title: Spatial Single-Cell Transcriptomics Toolbox -Version: 3.1.1 +Version: 3.2 Authors@R: c( person("Ruben", "Dries", email = "rubendries@gmail.com", role = c("aut", "cre")), diff --git a/NEWS.md b/NEWS.md index 9fddefa45..0b664ef9a 100644 --- a/NEWS.md +++ b/NEWS.md @@ -1,9 +1,4 @@ -# Giotto Suite 3.1.1 (2023-01-25) - -## Added -- Add spatial_interaction_spot.R with functions adapted from master branch for working with the Giotto suite object. - -# TBD RELEASE +# Giotto Suite 3.2 (RELEASE TBD) ## Breaking Changes - Removed support for deprecated nesting in `@nn_network` slot @@ -14,8 +9,10 @@ ## Added - New `gefToGiotto()` interoperability function to convert gef object from Stereo-seq to giotto - New `giottoToAnnData()` interoperability function to convert giotto object to squidpy flavor anndata .h5ad file(s) +- New `giottoToSpatialExperiment()` and `spatialExperimentToGiotto()` to convert between Giotto and SpatialExperiment - New `spatialAutoCorLocal()` and `spatialAutoCorGlobal()` functions to find spatial autocorrelations from expression and cell metadata information - New `createSpatialWeightMatrix()` function to generate spatial weight matrix from spatial networks for autocorrelation +- Add spatial_interaction_spot.R with functions adapted from master branch for working with the Giotto suite object. - Add `coord_fix_ratio` param to `spatFeatPlot2D()` and `spatFeatPlot2D_single()` - Add `order` parameter to `dimFeatPlot2D` and `spatDimFeatPlot2d` to plot and order cells according to the levels of the selected feature ([#477](https://github.com/drieslab/Giotto/issues/477)) - Add `plot()` method for `spatialNetworkObj` diff --git a/R/giotto_structures.R b/R/giotto_structures.R index 201446d72..37da30864 100644 --- a/R/giotto_structures.R +++ b/R/giotto_structures.R @@ -3190,7 +3190,7 @@ combineFeatureOverlapData = function(gobject, feat_type = feat, output = 'data.table') - print(feat_meta) + # print(feat_meta) if(!is.null(sel_feats[[feat_type]])) { selected_features = sel_feats[[feat_type]] @@ -3222,7 +3222,7 @@ combineFeatureOverlapData = function(gobject, } - print(comb_dt) + # print(comb_dt) comb_dt[, 'feat' := feat] res_list[[feat]] = comb_dt diff --git a/R/spatial_in_situ_visuals.R b/R/spatial_in_situ_visuals.R index 6b44f66e3..36c76534e 100644 --- a/R/spatial_in_situ_visuals.R +++ b/R/spatial_in_situ_visuals.R @@ -240,12 +240,12 @@ plot_feature_points_layer = function(ggobject, jitter = c(0,0), verbose = TRUE) { - # data.table variables + # data.table vars feat_ID = NULL spatial_feat_info_subset = spatial_feat_info[feat_ID %in% unlist(feats)] - # expand feature coordinates and/or add jitter to coordiantes + # expand feature coordinates and/or add jitter to coordinates if(isTRUE(expand_counts) | !identical(c(0,0), jitter)) { spatial_feat_info_subset = expand_feature_info(spatial_feat_info = spatial_feat_info_subset, expand_counts = expand_counts, @@ -254,7 +254,7 @@ plot_feature_points_layer = function(ggobject, verbose = verbose) } - cat(' --| Plotting ', nrow(spatial_feat_info_subset), ' feature points\n') + wrap_msg(' --| Plotting ', nrow(spatial_feat_info_subset), ' feature points') if(!is.null(ggobject) & inherits(ggobject, 'ggplot')) { pl = ggobject @@ -554,7 +554,7 @@ spatInSituPlotPoints = function(gobject, do.call('all_plots_save_function', c(list(gobject = gobject, plot_object = plot, default_save_name = default_save_name), - save_param)) + save_param)) } ## return plot diff --git a/man/plotCCcomDotplot.Rd b/man/plotCCcomDotplot.Rd index 6a8eb20f0..fc6095fae 100644 --- a/man/plotCCcomDotplot.Rd +++ b/man/plotCCcomDotplot.Rd @@ -25,7 +25,7 @@ plotCCcomDotplot( \arguments{ \item{gobject}{giotto object} -\item{comScores}{communinication scores from \code{\link{exprCellCellcom}} or \code{\link{spatCellCellcom}}} +\item{comScores}{communication scores from \code{\link{exprCellCellcom}} or \code{\link{spatCellCellcom}}} \item{selected_LR}{selected ligand-receptor combinations} From 8f88ae848aa0c0a15049f0dcc6dcb341f49f995c Mon Sep 17 00:00:00 2001 From: jiajic <72078254+jiajic@users.noreply.github.com> Date: Mon, 30 Jan 2023 10:39:30 -0500 Subject: [PATCH 113/129] instructions and onattach update - define giottoInstructions as S3 class - add `create_giotto_instructions()` to make more accessible what the desired entries of a giottoInstructions object are --- R/general_help.R | 22 ++++++++++++++++++ R/giotto.R | 58 ++++++++++++++++++++++++++++++++++++++++-------- R/zzz.R | 7 ++++++ 3 files changed, 78 insertions(+), 9 deletions(-) diff --git a/R/general_help.R b/R/general_help.R index 384af4955..c6ea67576 100644 --- a/R/general_help.R +++ b/R/general_help.R @@ -687,6 +687,28 @@ sort_combine_two_DT_columns = function(DT, ## package checks #### + +#' @title Check for updates to Giotto Suite +#' @name check_github_suite_ver +#' @description Checks the Giotto Suite github repository and compares the version +#' number to the currently installed. +#' @keywords internal +check_github_suite_ver = function() { + current_ver = utils::packageVersion('Giotto') + url = paste0('https://raw.githubusercontent.com/drieslab/Giotto/suite/DESCRIPTION') + x = readLines(url) + gh_ver = x[grep(pattern = 'Version:', x)] + gh_ver = gsub(pattern = 'Version: ', replacement = '', gh_ver) + ver_compare = utils::compareVersion(gh_ver, as.character(current_ver)) + + if(ver_compare == 1) wrap_msg('Newer devel version of Giotto on GitHub:', gh_ver) +} + + + + + + #' @title package_check #' @name package_check #' @param pkg_name name of package diff --git a/R/giotto.R b/R/giotto.R index 88a0ed5c4..6ee969e0a 100644 --- a/R/giotto.R +++ b/R/giotto.R @@ -261,16 +261,54 @@ createGiottoInstructions <- function(python_path = NULL, # return instructions list - instructions_list = list(python_path, show_plot, return_plot, - save_plot, save_dir, plot_format, dpi, - units, height, width, is_docker) - names(instructions_list) = c('python_path', 'show_plot', 'return_plot', - 'save_plot', 'save_dir', 'plot_format', 'dpi', - 'units', 'height', 'width', 'is_docker') + + instructions_list = create_giotto_instructions( + python_path = python_path, + show_plot = show_plot, + return_plot = return_plot, + save_plot = save_plot, + save_dir = save_dir, + plot_format = plot_format, + dpi = dpi, + units = units, + height = height, + width = width, + is_docker = is_docker + ) + return(instructions_list) } + +#' @keywords internal +create_giotto_instructions = function(python_path = NULL, + show_plot = NULL, + return_plot = NULL, + save_plot = NULL, + save_dir = NULL, + plot_format = NULL, + dpi = NULL, + units = NULL, + height = NULL, + width = NULL, + is_docker = NULL) { + instructions_list = list(python_path = python_path, + show_plot = show_plot, + return_plot = return_plot, + save_plot = save_plot, + save_dir = save_dir, + plot_format = plot_format, + dpi = dpi, + units = units, + height = height, + width = width, + is_docker = is_docker) + class(instructions_list) = c('giottoInstructions', 'list') + return(instructions_list) +} + + #' @title Read giotto instructions associated with giotto object #' @name readGiottoInstructions #' @description Retrieves the instruction associated with the provided parameter @@ -378,11 +416,13 @@ changeGiottoInstructions = function(gobject, replaceGiottoInstructions = function(gobject, instructions = NULL) { - old_instrs_list = gobject@instructions + instrs_needed = names(create_giotto_instructions()) # validate new instructions - if(!all(names(instructions) %in% names(old_instrs_list)) | is.null(instructions)) { - stop('\n You need to provide a named list for all instructions, like the outcome of createGiottoInstructions \n') + if(!all(instrs_needed %in% names(instructions)) | is.null(instructions)) { + stop(wrap_txt('You need to provide a named list for all instructions,', + 'like the outcome of createGiottoInstructions', + errWidth = TRUE)) } else { gobject@instructions = instructions return(gobject) diff --git a/R/zzz.R b/R/zzz.R index fe471c776..2c0130f6a 100644 --- a/R/zzz.R +++ b/R/zzz.R @@ -3,4 +3,11 @@ # print version number .onAttach = function(libname, pkgname) { packageStartupMessage('Giotto Suite ', utils::packageVersion('Giotto')) + + check_ver = getOption('giotto.check_version', TRUE) + if(!isTRUE(check_ver)) { + check_github_suite_ver() + options('giotto.check_version' = FALSE) + } + } From 0e9ff8d2903edced90249e0ea13d64e9aa305fe9 Mon Sep 17 00:00:00 2001 From: Eddie Ruiz <32622519+Ed2uiz@users.noreply.github.com> Date: Mon, 30 Jan 2023 22:10:07 -0500 Subject: [PATCH 114/129] update wrap_msg pos and include scope res ops --- R/interoperability.R | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/R/interoperability.R b/R/interoperability.R index c1a41d786..d788507d8 100644 --- a/R/interoperability.R +++ b/R/interoperability.R @@ -26,7 +26,7 @@ gefToGiotto = function(gef_file, bin_size = 'bin100', verbose = TRUE){ package_check(pkg_name = 'rhdf5', repository = 'Bioc') if(!file.exists(gef_file)) stop('File path to .gef file does not exist') - # check if proper bin_size is selected + # check if proper bin_size is selected. These are determined in SAW pipeline. bin_size_options = c('bin1', 'bin10', 'bin20', 'bin50', 'bin100', 'bin200') if(!(bin_size %in% bin_size_options)) stop('Please select valid bin size, see details for choices.') @@ -45,8 +45,8 @@ gefToGiotto = function(gef_file, bin_size = 'bin100', verbose = TRUE){ #TODO: update bin_shift for other shapes, not just rect_vertices bin_shift = ceiling(bin_size_int / 2) # ceiling catches bin_1 bincoord = unique(exprDT[,.(x,y)]) - setorder(bincoord, x, y) - setnames(bincoord, old = c('x', 'y'), new = c('sdimx', 'sdimy')) + data.table::setorder(bincoord, x, y) + data.table::setnames(bincoord, old = c('x', 'y'), new = c('sdimx', 'sdimy')) bincoord[, c('sdimx', 'sdimy') := list(sdimx+bin_shift, sdimy+bin_shift)] bincoord[, cell_ID := paste0('bin', 1:.N)] tx_data = exprDT[,.(genes, x, y, count)] From 8648ce2f8b3222ccc9c9d6c97a4df172af2927ed Mon Sep 17 00:00:00 2001 From: Eddie Ruiz <32622519+Ed2uiz@users.noreply.github.com> Date: Mon, 30 Jan 2023 22:16:29 -0500 Subject: [PATCH 115/129] update wrap_msg and add scope res operators --- R/interoperability.R | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/R/interoperability.R b/R/interoperability.R index d788507d8..77a738d4f 100644 --- a/R/interoperability.R +++ b/R/interoperability.R @@ -32,33 +32,33 @@ gefToGiotto = function(gef_file, bin_size = 'bin100', verbose = TRUE){ see details for choices.') # step 1: read expression and gene data from gef file + if(isTRUE(verbose)) wrap_msg('reading in .gef file') geneExpData = rhdf5::h5read(file = gef_file, name = 'geneExp') exprDT = data.table::as.data.table(geneExpData[[bin_size]][['expression']]) geneDT = data.table::as.data.table(geneExpData[[bin_size]][['gene']]) - if(isTRUE(verbose)) wrap_msg('read in .gef file') # step 2: combine gene information from the geneDT to the exprDT exprDT[, genes := rep(x = geneDT$gene, geneDT$count)] # step 3: bin coordinates according to selected bin_size - bin_size_int = as.integer(gsub("[^0-9.-]", "", bin_size)) #TODO: update bin_shift for other shapes, not just rect_vertices + bin_size_int = as.integer(gsub("[^0-9.-]", "", bin_size)) bin_shift = ceiling(bin_size_int / 2) # ceiling catches bin_1 bincoord = unique(exprDT[,.(x,y)]) + if(isTRUE(verbose)) wrap_msg('shifting and binning coordinates') data.table::setorder(bincoord, x, y) data.table::setnames(bincoord, old = c('x', 'y'), new = c('sdimx', 'sdimy')) bincoord[, c('sdimx', 'sdimy') := list(sdimx+bin_shift, sdimy+bin_shift)] bincoord[, cell_ID := paste0('bin', 1:.N)] tx_data = exprDT[,.(genes, x, y, count)] tx_data[, c('x', 'y') := list(x+bin_shift, y+bin_shift)] - if(isTRUE(verbose)) wrap_msg('shift and bin coordinates') # step 4: create rectangular polygons (grid) starting from the bin centroids + if(isTRUE(verbose)) wrap_msg('creating polygon stamp') x = polyStamp(stamp_dt = rectVertices(dims = c(x = (bin_size_int - 1), y = (bin_size_int - 1))), spatlocs = bincoord[,.(cell_ID, sdimx, sdimy)]) pg = createGiottoPolygonsFromDfr(x) - if(isTRUE(verbose)) wrap_msg('create polygon stamp') # step 5: create giotto subcellular object stereo = createGiottoObjectSubcellular( From 5b4273165a7e9678330a43789c4145b6718b1804 Mon Sep 17 00:00:00 2001 From: Eddie Ruiz <32622519+Ed2uiz@users.noreply.github.com> Date: Tue, 31 Jan 2023 14:59:53 -0500 Subject: [PATCH 116/129] Update accessors.R --- R/accessors.R | 268 ++++++++++++++++++++++++++++++++++++++++++++------ 1 file changed, 236 insertions(+), 32 deletions(-) diff --git a/R/accessors.R b/R/accessors.R index 9d3fb8521..60de97007 100644 --- a/R/accessors.R +++ b/R/accessors.R @@ -988,14 +988,42 @@ get_spatial_locations = function(gobject, #' @keywords internal select_spatial_locations = function(...) { - .Deprecated(new = "get_spatial_locations") + .Deprecated(new = "getSpatialLocations") - get_spatial_locations(...) + getSpatialLocations(...) } +#' @title Get spatial locations +#' @name getSpatialLocations +#' @description Function to get a spatial location data.table +#' @inheritParams data_access +#' @param spat_loc_name name of spatial locations (defaults to first name in spatial_locs slot, e.g. "raw") +#' @param output what object type to get the spatial locations as. Default is as +#' a 'spatLocsObj'. Returning as 'data.table' is also possible. +#' @param copy_obj whether to copy/duplicate when getting the object (default = TRUE) +#' @param verbose be verbose +#' @return data.table with coordinates or spatLocsObj depending on \code{output} +#' @family spatial location data accessor functions +#' @family functions to get data from giotto object +#' @export +getSpatialLocations = function(gobject, + spat_unit = NULL, + spat_loc_name = NULL, + output = c('spatLocsObj', 'data.table'), + copy_obj = TRUE, + verbose = TRUE, + set_defaults = TRUE) { - + # Pass to internal function + get_spatial_locations(gobject = gobject, + spat_unit = spat_unit, + spat_loc_name = spat_loc_name, + output = output, + copy_obj = copy_obj, + verbose = verbose, + set_defaults = set_defaults) +} #' @title Set spatial locations #' @name set_spatial_locations @@ -1086,10 +1114,45 @@ set_spatial_locations = function(gobject, } +#' @title Set spatial locations +#' @name setSpatialLocations +#' @description Function to set a spatial location slot +#' @inheritParams data_access +#' @param spatlocs spatial locations (accepts either \code{data.table} or +#' \code{spatLocsObj}) +#' @param spat_loc_name name of spatial locations, default "raw" +#' @param provenance provenance information (optional) +#' @param verbose be verbose +#' @details If a \code{spatLocsObj} is provided to \code{spatlocs} param then any +#' attached name and spat_unit info will be used for input to this function's +#' \code{spat_loc_name} and \code{spat_unit}params, BUT will be overridden by any +#' alternative specific inputs to those params. \cr +#' ie: a \code{spatLocsObj} with spat_unit slot == 'cell' will be automatically +#' nested by spat_unit 'cell' when using \code{setSpatialLocations} as long as +#' param \code{spat_unit = NULL}. BUT if param \code{spat_unit = 'nucleus'} then +#' the \code{spatLocsObj} will be nested by spat_unit 'nucleus' instead and +#' its spat_unit slot will be changed to 'nucleus' +#' @return giotto object +#' @family spatial location data accessor functions +#' @family functions to set data in giotto object +#' @export +setSpatialLocations = function(gobject, + spatlocs, + spat_unit = NULL, + spat_loc_name = 'raw', + provenance = NULL, + verbose = TRUE, + set_defaults = TRUE) { - - - + # Pass to internal function + set_spatial_locations(gobject = gobject, + spatlocs = spatlocs, + spat_unit = spat_unit, + spat_loc_name = spat_loc_name, + provenance = provenance, + verbose = verbose, + set_defaults = set_defaults) +} ## dimension reduction slot #### @@ -1243,12 +1306,6 @@ set_dimReduction = function(gobject, } - - - - - - ## nearest neighbor network slot #### #' @title Get nearest network @@ -1359,7 +1416,6 @@ select_NearestNetwork = function(...) { } - #' @title Set nearest network #' @name set_NearestNetwork #' @description Set a NN-network for a Giotto object @@ -1462,11 +1518,6 @@ set_NearestNetwork = function(gobject, } - - - - - ## spatial network slot #### #' @title Get spatial network @@ -1491,7 +1542,7 @@ get_spatialNetwork = function(gobject, set_defaults = TRUE, copy_obj = TRUE, verbose = TRUE) { - + output = match.arg(output, choices = c('spatialNetworkObj', 'networkDT', 'networkDT_before_filter', @@ -1546,12 +1597,44 @@ get_spatialNetwork = function(gobject, #' @keywords internal select_spatialNetwork = function(...) { - .Deprecated(new = "get_spatialNetwork") + .Deprecated(new = "getSpatialNetwork") - get_spatialNetwork(...) + getSpatialNetwork(...) } +#' @title Get spatial network +#' @name getSpatialNetwork +#' @description Function to get a spatial network +#' @inheritParams data_access +#' @param name name of spatial network +#' @param output object type to return as. Options: 'spatialNetworkObj' (default), +#' 'networkDT' and 'networkDT_before_filter' for data.table outputs. +#' @param copy_obj whether to copy/duplicate when getting the object (default = TRUE) +#' @param verbose be verbose +#' @family spatial network data accessor functions +#' @family functions to get data from giotto object +#' @export +getSpatialNetwork = function(gobject, + spat_unit = NULL, + name = NULL, + output = c('spatialNetworkObj', + 'networkDT', + 'networkDT_before_filter', + 'outputObj'), + set_defaults = TRUE, + copy_obj = TRUE, + verbose = TRUE) { + + # Pass to internal function + get_spatialNetwork(gobject = gobject, + spat_unit = spat_unit, + name = name, + output = output, + set_defaults = set_defaults, + copy_obj = copy_obj, + verbose = verbose) +} #' @title Set spatial network #' @name set_spatialNetwork @@ -1632,8 +1715,32 @@ set_spatialNetwork = function(gobject, } +#' @title Set spatial network +#' @name setSpatialNetwork +#' @description Function to set a spatial network +#' @inheritParams data_access +#' @param name name of spatial network +#' @param spatial_network spatial network +#' @param verbose be verbose +#' @return giotto object +#' @family spatial network data accessor functions +#' @family functions to set data in giotto object +#' @export +setSpatialNetwork = function(gobject, + spat_unit = NULL, + name = NULL, + spatial_network, + verbose = TRUE, + set_defaults = TRUE) { - + # Pass to internal function + set_spatialNetwork(gobject = gobject, + spat_unit = spat_unit, + name = name, + spatial_network = spatial_network, + verbose = verbose, + set_defaults = set_defaults) +} ## spatial grid slot #### @@ -1717,7 +1824,6 @@ get_spatialGrid = function(gobject, } } - #' @title Select spatial grid #' @name select_spatialGrid #' @inheritDotParams get_spatialGrid @@ -1725,12 +1831,36 @@ get_spatialGrid = function(gobject, #' @keywords internal select_spatialGrid = function(...) { - .Deprecated(new = "get_spatialGrid") + .Deprecated(new = "getSpatialGrid") - get_spatialGrid(...) + getSpatialGrid(...) } +#' @title Get spatial grid +#' @name getSpatialGrid +#' @description Function to get spatial grid +#' @inheritParams data_access +#' @param name name of spatial grid +#' @param return_grid_Obj return grid object (default = FALSE) +#' @family spatial grid data accessor functions +#' @family functions to get data from giotto object +#' @export +getSpatialGrid = function(gobject, + spat_unit = NULL, + feat_type = NULL, + name = NULL, + return_grid_Obj = FALSE, + set_defaults = TRUE) { + + # Pass to internal function + get_spatialGrid(gobject = gobject, + spat_unit = spat_unit, + feat_type = feat_type, + name = name, + return_grid_Obj = return_grid_Obj, + set_defaults = set_defaults) +} #' @title Set spatial grid #' @name set_spatialGrid @@ -1814,12 +1944,34 @@ set_spatialGrid = function(gobject, } +#' @title Set spatial grid +#' @name setSpatialGrid +#' @description Function to set a spatial grid +#' @inheritParams data_access +#' @param spatial_grid spatial grid object +#' @param name name of spatial grid +#' @param verbose be verbose +#' @return giotto object +#' @family spatial grid data accessor functions +#' @family functions to set data in giotto object +#' @export +setSpatialGrid = function(gobject, + spatial_grid, + spat_unit = NULL, + feat_type = NULL, + name = NULL, + verbose = TRUE, + set_defaults = TRUE) { - - - - - + # Pass to internal function + set_spatialGrid(gobject = gobject, + spatial_grid = spatial_grid, + spat_unit = spat_unit, + feat_type = feat_type, + name = name, + verbose = verbose, + set_defaults = set_defaults) +} ## polygon cell info #### @@ -2074,6 +2226,33 @@ get_spatial_enrichment = function(gobject, } } +#' @title Get spatial enrichment +#' @name getSpatialEnrichment +#' @description Function to get a spatial enrichment data.table +#' @inheritParams data_access +#' @param enrichm_name name of spatial enrichment results. Default "DWLS" +#' @return data.table with fractions +#' @family spatial enrichment data accessor functions +#' @family functions to get data from giotto object +#' @export +getSpatialEnrichment = function(gobject, + spat_unit = NULL, + feat_type = NULL, + enrichm_name = 'DWLS', + output = c('spatEnrObj', 'data.table'), + copy_obj = TRUE, + set_defaults = TRUE) { + + # Pass to internal function + get_spatial_enrichment(gobject, + spat_unit = NULL, + feat_type = NULL, + enrichm_name = 'DWLS', + output = c('spatEnrObj', 'data.table'), + copy_obj = TRUE, + set_defaults = TRUE) + +} #' @title Set spatial enrichment #' @name set_spatial_enrichment @@ -2155,12 +2334,37 @@ set_spatial_enrichment = function(gobject, } +#' @title Set spatial enrichment +#' @name setSpatialEnrichment +#' @description Function to set a spatial enrichment slot +#' @inheritParams data_access +#' @param enrichm_name name of spatial enrichment results. Default "DWLS" +#' @param spatenrichment spatial enrichment results +#' @param verbose be verbose +#' @return giotto object +#' @family spatial enrichment data accessor functions +#' @family functions to set data in giotto object +#' @export +setSpatialEnrichment = function(gobject, + spatenrichment, + spat_unit = NULL, + feat_type = NULL, + enrichm_name = 'enrichment', + verbose = TRUE, + set_defaults = TRUE) { + # Pass to internal function + set_spatial_enrichment(gobject = gobject, + spatenrichment = spatenrichment, + spat_unit = spat_unit, + feat_type = feat_type, + enrichm_name = enrichm_name, + verbose = verbose, + set_defaults = set_defaults) +} ## MG image slot #### - - #' @title Get \emph{magick}-based giotto \code{image} #' @name get_giottoImage_MG #' @description Get a giottoImage from a giotto object From 64d889a88d33beb3c7432c57a75288c13cda13c0 Mon Sep 17 00:00:00 2001 From: jiajic <72078254+jiajic@users.noreply.github.com> Date: Tue, 31 Jan 2023 15:30:58 -0500 Subject: [PATCH 117/129] Catch up to suite --- R/python_scrublet.R | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/R/python_scrublet.R b/R/python_scrublet.R index 1ed599f91..82bcab150 100644 --- a/R/python_scrublet.R +++ b/R/python_scrublet.R @@ -66,7 +66,8 @@ doScrubletDetect = function(gobject, expr_values = get_expression_values(gobject = gobject, spat_unit = spat_unit, feat_type = feat_type, - values = expression_values) + values = expression_values, + output = 'matrix') # input is a sparse matrix with cells as rows and genes as columns data.table::as.data.table() scr_input = expr_values From d6cb18296233ea9286768715532cbc1a1b6af7f3 Mon Sep 17 00:00:00 2001 From: jiajic <72078254+jiajic@users.noreply.github.com> Date: Tue, 31 Jan 2023 15:41:35 -0500 Subject: [PATCH 118/129] Update convenience.R --- R/convenience.R | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/R/convenience.R b/R/convenience.R index 45b1cb830..f6b1c799d 100644 --- a/R/convenience.R +++ b/R/convenience.R @@ -1371,6 +1371,7 @@ read_xenium_folder = function(xenium_dir, load_merscope_folder = function(dir_items, data_to_use, fovs = NULL, + poly_z_indices = 0:6, cores = NA, verbose = TRUE) { @@ -1379,6 +1380,7 @@ load_merscope_folder = function(dir_items, data_list = load_merscope_folder_subcellular(dir_items = dir_items, data_to_use = data_to_use, fovs = fovs, + poly_z_indices = poly_z_indices, cores = cores, verbose = verbose) } else if(data_to_use == 'aggregate') { @@ -1429,6 +1431,7 @@ load_merscope_folder = function(dir_items, load_merscope_folder_subcellular = function(dir_items, data_to_use, cores = NA, + poly_z_indices = 0:6, verbose = TRUE, fovs = NULL) { @@ -1448,7 +1451,7 @@ load_merscope_folder_subcellular = function(dir_items, if(isTRUE(verbose)) wrap_msg('Loading polygon info...') poly_info = readPolygonFilesVizgenHDF5(boundaries_path = dir_items$`boundary info`, - polygon_feat_types = c(0,6), + z_indices = poly_z_indices, flip_y_axis = TRUE, fovs = fovs) From c63b3a40342b6868eb09946c189410468e19d2d2 Mon Sep 17 00:00:00 2001 From: jiajic <72078254+jiajic@users.noreply.github.com> Date: Tue, 31 Jan 2023 18:49:16 -0500 Subject: [PATCH 119/129] Update convenience.R --- R/convenience.R | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/R/convenience.R b/R/convenience.R index f6b1c799d..4f01d918a 100644 --- a/R/convenience.R +++ b/R/convenience.R @@ -1371,7 +1371,7 @@ read_xenium_folder = function(xenium_dir, load_merscope_folder = function(dir_items, data_to_use, fovs = NULL, - poly_z_indices = 0:6, + poly_z_indices = 1L:7L, cores = NA, verbose = TRUE) { @@ -1431,7 +1431,7 @@ load_merscope_folder = function(dir_items, load_merscope_folder_subcellular = function(dir_items, data_to_use, cores = NA, - poly_z_indices = 0:6, + poly_z_indices = 1L:7L, verbose = TRUE, fovs = NULL) { From c03ef7e001fa8fb2eeb8b98f6139c2132ac05a07 Mon Sep 17 00:00:00 2001 From: jiajic <72078254+jiajic@users.noreply.github.com> Date: Wed, 1 Feb 2023 13:43:59 -0500 Subject: [PATCH 120/129] Update giotto show fxn - also slight updates to merscope pipeline --- R/classes.R | 104 ++++++++++++++++++++++++++++++++++++++---------- R/convenience.R | 8 ++++ 2 files changed, 91 insertions(+), 21 deletions(-) diff --git a/R/classes.R b/R/classes.R index 77dce9b10..bb7240f39 100644 --- a/R/classes.R +++ b/R/classes.R @@ -317,13 +317,6 @@ setClass('spatFeatData', # # # -# # Check for nesting issues (due to updates) - to be deprecated -# available_nn = list_nearest_networks(object) -# available_grids = list_spatial_grids(object) -# -# -# -# # ## Match spatial units and feature types ## # # # Find existing spat_units in source data @@ -375,8 +368,28 @@ setClass('spatFeatData', # if(length(errors) == 0) TRUE else errors # } +## Test Functions +# test_valid = function(object) { +# print('valid_run') +# return(TRUE) +# } +# +# setMethod('initialize', signature = 'giotto', +# function(.Object, ...) { +# .Object = methods::callNextMethod() +# print('init_run') +# .Object +# }) - +# TODO +# updateGiottoObject = function(gobject) { +# if(is.null(attr(gobject, 'multiomics'))) { +# attr(gobject, 'multiomics') = NA +# gobject@multiomics = NULL +# } +# +# return(gobject) +# } ##### * Definition #### # Giotto class @@ -488,23 +501,72 @@ setMethod( cat("An object of class", class(object), "\n") - for(spat_unit in names(object@expression_feat)) { - cat('spatial units = ', spat_unit, '\n') - for(feat_type in unique(object@expression_feat)) { - cat("features = ", feat_type, "\n") - - cat( - nrow(x = object@expression[[spat_unit]][[feat_type]][['raw']]), - "features across", - ncol(x = object@expression[[spat_unit]][[feat_type]][['raw']]), - "samples.\n \n" - ) + + cat('[SUBCELLULAR INFO]\n') + if(!is.null(object@spatial_info)) cat('polygons :', wrap_txt(list_spatial_info_names(object)), '\n') + if(!is.null(object@feat_info)) cat('features :', wrap_txt(list_feature_info_names(object)), '\n') + + + mini_avail_print = function(avail_dt) { + if(!'spat_unit' %in% colnames(avail_dt)) { + avail_dt[, spat_unit := ''] + } else avail_dt[, spat_unit := paste0('[', spat_unit, ']')] + if(!'feat_type' %in% colnames(avail_dt)) { + avail_dt[, feat_type := ''] + } else avail_dt[, feat_type := paste0('[', feat_type, ']')] + avail_dt[, prints := paste0(spat_unit, feat_type)] + + unique_entry = avail_dt[, unique(prints)] + for(entry in unique_entry) { + cat(' ', entry, paste0(' ', wrap_txt(avail_dt[prints == entry, name])), '\n', sep = '') + } + } + + + cat('[AGGREGATE INFO]\n') + avail_expr = list_expression(object) + if(!is.null(avail_expr)) { + cat('expression -----------------------\n') + mini_avail_print(avail_expr) + } + + avail_sl = list_spatial_locations(object) + if(!is.null(avail_sl)) { + cat('spatial locations ----------------\n') + mini_avail_print(avail_sl) + } + + avail_sn = list_spatial_networks(object) + if(!is.null(avail_sn)) { + cat('spatial networks -----------------\n') + mini_avail_print(avail_sn) + } + + avail_dim = list_dim_reductions(object) + if(!is.null(avail_dim)) { + cat('dim reduction --------------------\n') + mini_avail_print(avail_dim) + } + + avail_nn = list_nearest_networks(object) + if(!is.null(avail_nn)) { + cat('nearest neighbor networks --------\n') + mini_avail_print(avail_nn) + } + + avail_im = list_images(object) + if(!is.null(avail_im)) { + cat('attached images ------------------\n') + if('image' %in% avail_im$img_type) { + cat('giottoImage :', wrap_txt(avail_im[img_type == 'image', name]), '\n') + } + if('largeImage' %in% avail_im$img_type) { + cat( 'giottoLargeImage :', wrap_txt(avail_im[img_type == 'largeImage', name]), '\n') } } - cat('Steps and parameters used: \n \n') - print(object@parameters) + cat(wrap_txt('\n\nUse objHistory() to see steps and params used\n\n')) invisible(x = NULL) } ) diff --git a/R/convenience.R b/R/convenience.R index 4f01d918a..d23fcc6ff 100644 --- a/R/convenience.R +++ b/R/convenience.R @@ -149,6 +149,7 @@ read_data_folder = function(spat_method = NULL, createGiottoMerscopeObject = function(merscope_dir, data_to_use = c('subcellular', 'aggregate'), FOVs = NULL, + poly_z_indices = 1:7, calculate_overlap = TRUE, overlap_to_matrix = TRUE, aggregate_stack = TRUE, @@ -164,6 +165,12 @@ createGiottoMerscopeObject = function(merscope_dir, cores = determine_cores(cores) data.table::setDTthreads(threads = cores) + poly_z_indices = as.integer(poly_z_indices) + if(any(poly_z_indices < 1)) stop(wrap_txt( + 'poly_z_indices is a vector of one or more integers starting from 1.', + errWidth = TRUE + )) + # determine data to use data_to_use = match.arg(arg = data_to_use, choices = c('subcellular','aggregate')) @@ -176,6 +183,7 @@ createGiottoMerscopeObject = function(merscope_dir, # 2. load in directory items data_list = load_merscope_folder(dir_items = dir_items, data_to_use = data_to_use, + poly_z_indices = poly_z_indices, fovs = fovs, cores = cores, verbose = verbose) From 92a9db054418b73660f9c1866524544d865439b9 Mon Sep 17 00:00:00 2001 From: jiajic <72078254+jiajic@users.noreply.github.com> Date: Wed, 1 Feb 2023 15:35:41 -0500 Subject: [PATCH 121/129] update giotto show fxn --- NEWS.md | 5 +++-- R/accessors.R | 20 ++++++++++---------- R/classes.R | 12 ++++++++++-- 3 files changed, 23 insertions(+), 14 deletions(-) diff --git a/NEWS.md b/NEWS.md index 0b664ef9a..aa1b4627a 100644 --- a/NEWS.md +++ b/NEWS.md @@ -1,4 +1,4 @@ -# Giotto Suite 3.2 (RELEASE TBD) +# Giotto Suite 3.2.0 (RELEASE TBD) ## Breaking Changes - Removed support for deprecated nesting in `@nn_network` slot @@ -32,7 +32,8 @@ ## Changes - Move giotto object method-specific creation functions from `giotto.R` to `convenience.R` - Update `addFeatMetadata()` to handle replacement of existing columns -- Update to `show()` method for `spatEnrObj` +- Update `show()` method for `giotto` +- Update `show()` method for `spatEnrObj` - Deprecate `polygon_feat_names` param in favor of `z_indices` in `readPolygonFilesVizgenHDF5()` - Deprecate `xy_translate_spatial_locations()` in favor of `shift_spatial_locations()` - Optimize `readPolygonFilesVizgen()` diff --git a/R/accessors.R b/R/accessors.R index 60de97007..df94e629a 100644 --- a/R/accessors.R +++ b/R/accessors.R @@ -1008,12 +1008,12 @@ select_spatial_locations = function(...) { #' @family functions to get data from giotto object #' @export getSpatialLocations = function(gobject, - spat_unit = NULL, - spat_loc_name = NULL, - output = c('spatLocsObj', 'data.table'), - copy_obj = TRUE, - verbose = TRUE, - set_defaults = TRUE) { + spat_unit = NULL, + spat_loc_name = NULL, + output = c('spatLocsObj', 'data.table'), + copy_obj = TRUE, + verbose = TRUE, + set_defaults = TRUE) { # Pass to internal function get_spatial_locations(gobject = gobject, @@ -1542,7 +1542,7 @@ get_spatialNetwork = function(gobject, set_defaults = TRUE, copy_obj = TRUE, verbose = TRUE) { - + output = match.arg(output, choices = c('spatialNetworkObj', 'networkDT', 'networkDT_before_filter', @@ -1739,7 +1739,7 @@ setSpatialNetwork = function(gobject, name = name, spatial_network = spatial_network, verbose = verbose, - set_defaults = set_defaults) + set_defaults = set_defaults) } ## spatial grid slot #### @@ -1854,7 +1854,7 @@ getSpatialGrid = function(gobject, set_defaults = TRUE) { # Pass to internal function - get_spatialGrid(gobject = gobject, + get_spatialGrid(gobject = gobject, spat_unit = spat_unit, feat_type = feat_type, name = name, @@ -2251,7 +2251,7 @@ getSpatialEnrichment = function(gobject, output = c('spatEnrObj', 'data.table'), copy_obj = TRUE, set_defaults = TRUE) - + } #' @title Set spatial enrichment diff --git a/R/classes.R b/R/classes.R index bb7240f39..d32082a73 100644 --- a/R/classes.R +++ b/R/classes.R @@ -558,10 +558,18 @@ setMethod( if(!is.null(avail_im)) { cat('attached images ------------------\n') if('image' %in% avail_im$img_type) { - cat('giottoImage :', wrap_txt(avail_im[img_type == 'image', name]), '\n') + if(sum(avail_im$img_type == 'image') > 3) { + cat( 'giottoLargeImage :', sum(avail_im$img_type == 'image'), 'items...\n') + } else { + cat('giottoImage :', wrap_txt(avail_im[img_type == 'image', name]), '\n') + } } if('largeImage' %in% avail_im$img_type) { - cat( 'giottoLargeImage :', wrap_txt(avail_im[img_type == 'largeImage', name]), '\n') + if(sum(avail_im$img_type == 'largeImage') > 3) { + cat( 'giottoLargeImage :', sum(avail_im$img_type == 'largeImage'), 'items...\n') + } else { + cat( 'giottoLargeImage :', wrap_txt(avail_im[img_type == 'largeImage', name]), '\n') + } } } From 9240bdfc9b7c14cd090ca49933a0b466000cde53 Mon Sep 17 00:00:00 2001 From: mattobny Date: Wed, 1 Feb 2023 16:05:58 -0500 Subject: [PATCH 122/129] Accessor updates --- R/accessors.R | 181 +++++++++++++++++++++++++++++++++++++++++++++++++- R/wnn.R | 69 +++++++++++++++++++ 2 files changed, 248 insertions(+), 2 deletions(-) diff --git a/R/accessors.R b/R/accessors.R index 60de97007..131243a91 100644 --- a/R/accessors.R +++ b/R/accessors.R @@ -2024,6 +2024,32 @@ get_polygon_info = function(gobject, } } +#' @title Get polygon info +#' @name getPolygonInfo +#' @description Get giotto polygon spatVector +#' @param gobject giotto object +#' @param polygon_name name of polygons. Default is "cell" +#' @param polygon_overlap include polygon overlap information +#' @param return_giottoPolygon (Defaults to FALSE) Return as giottoPolygon S4 object +#' @family polygon info data accessor functions +#' @family functions to get data from giotto object +#' @export +getPolygonInfo = function(gobject = NULL, + polygon_name = NULL, + polygon_overlap = NULL, + return_giottoPolygon = FALSE){ + if (!"giotto" %in% class(gobject)){ + wrap_msg("Unable to get polygon spatVector from non-Giotto object.") + stop(wrap_msg("Please provide a Giotto object to the gobject argument.")) + } + + poly_info = get_polygon_info(gobject = gobject, + polygon_name = polygon_name, + polygon_overlap = polygon_overlap, + return_giottoPolygon = return_giottoPolygon) + + return (poly_info) +} #' @title Select polygon info #' @name select_polygon_info @@ -2073,13 +2099,61 @@ set_polygon_info = function(gobject, } - - +#' @title Set polygon info +#' @name setPolygonInfo +#' @description Set giotto polygon spatVector +#' @param gobject giotto object +#' @param polygon_name name of polygons. Default "cell" +#' @param gpolygon giotto polygon +#' @param verbose verbosity +#' @return giotto object +#' @family polygon info data accessor functions +#' @family functions to set data in giotto object +#' @export +setPolygonInfo = function(gobject = NULL, + polygon_name = 'cell', + gpolygon = NULL, + verbose = TRUE) { + if (!"giotto" %in% class(gobject)){ + wrap_msg("Unable to set polygon spatVector to non-Giotto object.") + stop(wrap_msg("Please provide a Giotto object to the gobject argument.")) + } + + if (!"giottoPolygon" %in% class(gpolygon)){ + wrap_msg("Unable to set non-spatVector object to Giotto object.") + stop(wrap_msg("Please provide a giotto polygon to the gpolygon argument.")) + } + gobject = set_polygon_info(gobject = gobject, + polygon_name = polygon_name, + gpolygon = gpolygon, + verbose = verbose) + return (gobject) +} ## feature info #### +#' @title Get feature info +#' @name getFeatureInfo +#' @description Get giotto points spatVector +#' @inheritParams data_access +#' @family feature info data accessor functions +#' @family functions to get data from giotto object +#' @export +getFeatureInfo = function(gobject = gobject, + feat_type = NULL, + set_defaults = TRUE) { + if (!"giotto" %in% class(gobject)){ + wrap_msg("Unable to get giotto points spatVector feature info from non-Giotto object.") + stop(wrap_msg("Please provide a Giotto object to the gobject argument.")) + } + feat_info = get_feature_info(gobject = gobject, + feat_type = feat_type, + set_defaults = set_defaults) + return (feat_info) +} + #' @title Get feature info #' @name get_feature_info #' @description Get giotto points spatVector @@ -2156,6 +2230,39 @@ set_feature_info = function(gobject, } +#' @title Set feature info +#' @name setFeatureInfo +#' @description Set giotto polygon spatVector for features +#' @inheritParams data_access +#' @param gobject giotto object containing a the given giottopolygon +#' @param gpolygon giotto polygon +#' @param feat_type feature slot information (e.g. "rna") +#' @param verbose be verbose +#' @return giotto object +#' @family feature info data accessor functions +#' @family functions to set data in giotto object +#' @export +setFeatureInfo = function(gobject = NULL, + feat_type = NULL, + gpolygon = NULL, + verbose = TRUE){ + if (!"giotto" %in% class(gobject)){ + wrap_msg("Unable to set giotto points spatVector feature info to non-Giotto object.") + stop(wrap_msg("Please provide a Giotto object to the gobject argument.")) + } + + if (!"giottoPolygon" %in% class(gpolygon)){ + wrap_msg("Unable to set non-giotto points spatVector feature info to Giotto object.") + stop(wrap_msg("Please provide a giotto polygon to the gpolygon argument.")) + } + + gobject = set_feature_info(gobject = gobject, + feat_type = feat_type, + gpolygon = gpolygon, + verbose = verbose) + return (gobject) + +} ## spatial enrichment slot #### @@ -2529,6 +2636,31 @@ get_giottoImage = function(gobject = NULL, return(g_img) } +#' @title Get giotto image object +#' @name getGiottoImage +#' @description Get giotto image object from gobject +#' @param gobject giotto object +#' @param image_type type of giotto image object. Either "image" or "largeImage" +#' @param name name of a giotto image object \code{\link{showGiottoImageNames}} +#' @return a giotto image object +#' @family image data accessor functions +#' @family functions to get data from giotto object +#' @export +getGiottoImage = function(gobject = NULL, + image_type = c('image','largeImage'), + name = NULL) { + if (!"giotto" %in% class(gobject)){ + wrap_msg("Unable to get Giotto Image from non-Giotto object.") + stop(wrap_msg("Please provide a Giotto object to the gobject argument.")) + } + + g_img = get_giottoImage(gobject = gobject, + image_type = image_type, + name = name) + + return (g_img) + +} #' @title Set giotto image object @@ -2575,6 +2707,51 @@ set_giottoImage = function(gobject = NULL, return(gobject) } +#' @title Set giotto image object +#' @name setGiottoImage +#' @description Directly attach a giotto image to giotto object +#' @details \emph{\strong{Use with care!}} This function directly attaches giotto image +#' objects to the gobject without further modifications of spatial positioning values +#' within the image object that are generally needed in order for them to +#' plot in the correct location relative to the other modalities of spatial data. \cr +#' For the more general-purpose method of attaching image objects, see \code{\link{addGiottoImage}} +#' @param gobject giotto object +#' @param image giotto image object to be attached without modification to the +#' giotto object +#' @param image_type type of giotto image object. Either "image" or "largeImage" +#' @param name name of giotto image object +#' @param verbose be verbose +#' @return giotto object +#' @family image data accessor functions +#' @family functions to set data in giotto object +#' @seealso \code{\link{addGiottoImage}} +#' @export +setGiottoImage = function(gobject = NULL, + image = NULL, + image_type = NULL, + name = NULL, + verbose = TRUE){ + + if (!"giotto" %in% class(gobject)){ + wrap_msg("Unable to set Giotto Image to non-Giotto object.") + stop(wrap_msg("Please provide a Giotto object to the gobject argument.")) + } else if (is.null(image)) { + wrap_msg("Warning: image argument set to NULL. Replacing current image slot with NULL will remove the image.") + } else if( !"giottoImage" %in% image || !"giottoLargeImage" %in% image) { + wrap_msg("Unable to set non-giottoImage objects. Please ensure a giottoImage or giottoLargeImage is provided to this function.") + wrap_msg("See createGiottoImage or createGiottoLargeImage for more details.") + stop(wrap_msg("Unable to set non-giottoImage object.")) + } + + gobject = set_giottoImage(gobject = gobject, + image = image, + image_type = image_type, + name = name, + verbose = verbose) + + return (gobject) + +} ## Show functions #### diff --git a/R/wnn.R b/R/wnn.R index bf784c54f..44bad5f0e 100644 --- a/R/wnn.R +++ b/R/wnn.R @@ -599,6 +599,45 @@ set_multiomics = function(gobject, } +#' @title Set multiomics integration results +#' @name setMultiomics +#' @description Set a multiomics integration result in a Giotto object +#' +#' @param gobject A Giotto object +#' @param spat_unit spatial unit (e.g. 'cell') +#' @param feat_type (e.g. 'rna_protein') +#' @param result A matrix or result from multiomics integration (e.g. theta weighted values from runWNN) +#' @param integration_method multiomics integration method used. Default = 'WNN' +#' @param result_name Default = 'theta_weighted_matrix' +#' @param verbose be verbose +#' +#' @return A giotto object +#' @family multiomics accessor functions +#' @family functions to set data in giotto object +#' @export +setMultiomics = function(gobject = NULL, + result, + spat_unit = NULL, + feat_type = NULL, + integration_method = 'WNN', + result_name = 'theta_weighted_matrix', + verbose = TRUE){ + if (!"giotto" %in% class(gobject)){ + wrap_msg("Unable to set multiomics info to non-Giotto object.") + stop(wrap_msg("Please provide a Giotto object to the gobject argument.")) + } + + gobject = set_multiomics(gobject = gobject, + result = result, + spat_unit = spat_unit, + feat_type = feat_type, + result = result, + integration_method = integration_method) + + return (gobject) + +} + #' @title Get multiomics integration results #' @name get_multiomics #' @description Get a multiomics integration result from a Giotto object @@ -654,3 +693,33 @@ get_multiomics = function(gobject, } +#' @title Get multiomics integration results +#' @name getMultiomics +#' @description Get a multiomics integration result from a Giotto object +#' +#' @param gobject A Giotto object +#' @param spat_unit spatial unit (e.g. 'cell') +#' @param feat_type integrated feature type (e.g. 'rna_protein') +#' @param integration_method multiomics integration method used. Default = 'WNN' +#' @param result_name Default = 'theta_weighted_matrix' +#' +#' @return A multiomics integration result (e.g. theta_weighted_matrix from WNN) +#' @family multiomics accessor functions +#' @family functions to get data from giotto object +#' @export +getMultiomics = function(gobject = NULL, + spat_unit = NULL, + feat_type = NULL, + integration_method = "WNN", + result_name = "theta_weighted_matrix") { + if (!"giotto" %in% class(gobject)){ + wrap_msg("Unable to get multiomics info from non-Giotto object.") + stop(wrap_msg("Please provide a Giotto object to the gobject argument.")) + } + multiomics_result = get_multiomics(gobject = gobject, + spat_unit = spat_unit, + feat_type = feat_type, + integration_method = integration_method, + result_name = result_name) + return (multiomics_result) +} \ No newline at end of file From 7f4f2c2c32d0cb25b9974c973a6b26b203730862 Mon Sep 17 00:00:00 2001 From: Eddie Ruiz <32622519+Ed2uiz@users.noreply.github.com> Date: Wed, 1 Feb 2023 17:05:31 -0500 Subject: [PATCH 123/129] update accessors --- R/accessors.R | 154 ++++++++++++++++++++++++++++---------------------- 1 file changed, 85 insertions(+), 69 deletions(-) diff --git a/R/accessors.R b/R/accessors.R index 131243a91..dde983a4f 100644 --- a/R/accessors.R +++ b/R/accessors.R @@ -1008,21 +1008,23 @@ select_spatial_locations = function(...) { #' @family functions to get data from giotto object #' @export getSpatialLocations = function(gobject, - spat_unit = NULL, - spat_loc_name = NULL, - output = c('spatLocsObj', 'data.table'), - copy_obj = TRUE, - verbose = TRUE, - set_defaults = TRUE) { + spat_unit = NULL, + spat_loc_name = NULL, + output = c('spatLocsObj', 'data.table'), + copy_obj = TRUE, + verbose = TRUE, + set_defaults = TRUE) { # Pass to internal function - get_spatial_locations(gobject = gobject, - spat_unit = spat_unit, - spat_loc_name = spat_loc_name, - output = output, - copy_obj = copy_obj, - verbose = verbose, - set_defaults = set_defaults) + spatloc = get_spatial_locations(gobject = gobject, + spat_unit = spat_unit, + spat_loc_name = spat_loc_name, + output = output, + copy_obj = copy_obj, + verbose = verbose, + set_defaults = set_defaults) + + return(spatloc) } #' @title Set spatial locations @@ -1145,13 +1147,15 @@ setSpatialLocations = function(gobject, set_defaults = TRUE) { # Pass to internal function - set_spatial_locations(gobject = gobject, - spatlocs = spatlocs, - spat_unit = spat_unit, - spat_loc_name = spat_loc_name, - provenance = provenance, - verbose = verbose, - set_defaults = set_defaults) + gobject = set_spatial_locations(gobject = gobject, + spatlocs = spatlocs, + spat_unit = spat_unit, + spat_loc_name = spat_loc_name, + provenance = provenance, + verbose = verbose, + set_defaults = set_defaults) + + return(gobject) } ## dimension reduction slot #### @@ -1616,24 +1620,26 @@ select_spatialNetwork = function(...) { #' @family functions to get data from giotto object #' @export getSpatialNetwork = function(gobject, - spat_unit = NULL, - name = NULL, - output = c('spatialNetworkObj', - 'networkDT', - 'networkDT_before_filter', - 'outputObj'), - set_defaults = TRUE, - copy_obj = TRUE, - verbose = TRUE) { + spat_unit = NULL, + name = NULL, + output = c('spatialNetworkObj', + 'networkDT', + 'networkDT_before_filter', + 'outputObj'), + set_defaults = TRUE, + copy_obj = TRUE, + verbose = TRUE) { # Pass to internal function - get_spatialNetwork(gobject = gobject, - spat_unit = spat_unit, - name = name, - output = output, - set_defaults = set_defaults, - copy_obj = copy_obj, - verbose = verbose) + network = get_spatialNetwork(gobject = gobject, + spat_unit = spat_unit, + name = name, + output = output, + set_defaults = set_defaults, + copy_obj = copy_obj, + verbose = verbose) + + return(network) } #' @title Set spatial network @@ -1734,12 +1740,14 @@ setSpatialNetwork = function(gobject, set_defaults = TRUE) { # Pass to internal function - set_spatialNetwork(gobject = gobject, - spat_unit = spat_unit, - name = name, - spatial_network = spatial_network, - verbose = verbose, - set_defaults = set_defaults) + gobject = set_spatialNetwork(gobject = gobject, + spat_unit = spat_unit, + name = name, + spatial_network = spatial_network, + verbose = verbose, + set_defaults = set_defaults) + + return(gobject) } ## spatial grid slot #### @@ -1854,12 +1862,14 @@ getSpatialGrid = function(gobject, set_defaults = TRUE) { # Pass to internal function - get_spatialGrid(gobject = gobject, - spat_unit = spat_unit, - feat_type = feat_type, - name = name, - return_grid_Obj = return_grid_Obj, - set_defaults = set_defaults) + grid = get_spatialGrid(gobject = gobject, + spat_unit = spat_unit, + feat_type = feat_type, + name = name, + return_grid_Obj = return_grid_Obj, + set_defaults = set_defaults) + + return(grid) } #' @title Set spatial grid @@ -1964,13 +1974,15 @@ setSpatialGrid = function(gobject, set_defaults = TRUE) { # Pass to internal function - set_spatialGrid(gobject = gobject, - spatial_grid = spatial_grid, - spat_unit = spat_unit, - feat_type = feat_type, - name = name, - verbose = verbose, - set_defaults = set_defaults) + gobject = set_spatialGrid(gobject = gobject, + spatial_grid = spatial_grid, + spat_unit = spat_unit, + feat_type = feat_type, + name = name, + verbose = verbose, + set_defaults = set_defaults) + + return(gobject) } ## polygon cell info #### @@ -2351,13 +2363,15 @@ getSpatialEnrichment = function(gobject, set_defaults = TRUE) { # Pass to internal function - get_spatial_enrichment(gobject, - spat_unit = NULL, - feat_type = NULL, - enrichm_name = 'DWLS', - output = c('spatEnrObj', 'data.table'), - copy_obj = TRUE, - set_defaults = TRUE) + enr_res = get_spatial_enrichment(gobject, + spat_unit = NULL, + feat_type = NULL, + enrichm_name = 'DWLS', + output = c('spatEnrObj', 'data.table'), + copy_obj = TRUE, + set_defaults = TRUE) + + return(enr_res) } @@ -2461,13 +2475,15 @@ setSpatialEnrichment = function(gobject, set_defaults = TRUE) { # Pass to internal function - set_spatial_enrichment(gobject = gobject, - spatenrichment = spatenrichment, - spat_unit = spat_unit, - feat_type = feat_type, - enrichm_name = enrichm_name, - verbose = verbose, - set_defaults = set_defaults) + gobject = set_spatial_enrichment(gobject = gobject, + spatenrichment = spatenrichment, + spat_unit = spat_unit, + feat_type = feat_type, + enrichm_name = enrichm_name, + verbose = verbose, + set_defaults = set_defaults) + + return(gobject) } ## MG image slot #### From f3242f4efcc237c0df464cb59081f91f2c86ac48 Mon Sep 17 00:00:00 2001 From: Eddie Ruiz <32622519+Ed2uiz@users.noreply.github.com> Date: Wed, 1 Feb 2023 17:17:13 -0500 Subject: [PATCH 124/129] Update getSpatialEnrichment accessor --- R/accessors.R | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/R/accessors.R b/R/accessors.R index dde983a4f..bfbed7b45 100644 --- a/R/accessors.R +++ b/R/accessors.R @@ -2363,13 +2363,13 @@ getSpatialEnrichment = function(gobject, set_defaults = TRUE) { # Pass to internal function - enr_res = get_spatial_enrichment(gobject, - spat_unit = NULL, - feat_type = NULL, - enrichm_name = 'DWLS', - output = c('spatEnrObj', 'data.table'), - copy_obj = TRUE, - set_defaults = TRUE) + enr_res = get_spatial_enrichment(gobject = gobject, + spat_unit = spat_unit, + feat_type = feat_type, + enrichm_name = enrichm_name, + output = output, + copy_obj = copy_obj, + set_defaults = set_defaults) return(enr_res) From f1eecff02c1a9f7560fb1ae80550df836536ffd1 Mon Sep 17 00:00:00 2001 From: jiajic <72078254+jiajic@users.noreply.github.com> Date: Wed, 1 Feb 2023 17:26:05 -0500 Subject: [PATCH 125/129] Merge branch 'suite_dev' of https://github.com/drieslab/Giotto into suite_dev --- R/accessors.R | 148 ++++++++++++++++++++++++++++---------------------- 1 file changed, 82 insertions(+), 66 deletions(-) diff --git a/R/accessors.R b/R/accessors.R index 49fb4dbd9..de46e6468 100644 --- a/R/accessors.R +++ b/R/accessors.R @@ -1016,13 +1016,15 @@ getSpatialLocations = function(gobject, set_defaults = TRUE) { # Pass to internal function - get_spatial_locations(gobject = gobject, - spat_unit = spat_unit, - spat_loc_name = spat_loc_name, - output = output, - copy_obj = copy_obj, - verbose = verbose, - set_defaults = set_defaults) + spatloc = get_spatial_locations(gobject = gobject, + spat_unit = spat_unit, + spat_loc_name = spat_loc_name, + output = output, + copy_obj = copy_obj, + verbose = verbose, + set_defaults = set_defaults) + + return(spatloc) } #' @title Set spatial locations @@ -1145,13 +1147,15 @@ setSpatialLocations = function(gobject, set_defaults = TRUE) { # Pass to internal function - set_spatial_locations(gobject = gobject, - spatlocs = spatlocs, - spat_unit = spat_unit, - spat_loc_name = spat_loc_name, - provenance = provenance, - verbose = verbose, - set_defaults = set_defaults) + gobject = set_spatial_locations(gobject = gobject, + spatlocs = spatlocs, + spat_unit = spat_unit, + spat_loc_name = spat_loc_name, + provenance = provenance, + verbose = verbose, + set_defaults = set_defaults) + + return(gobject) } ## dimension reduction slot #### @@ -1616,24 +1620,26 @@ select_spatialNetwork = function(...) { #' @family functions to get data from giotto object #' @export getSpatialNetwork = function(gobject, - spat_unit = NULL, - name = NULL, - output = c('spatialNetworkObj', - 'networkDT', - 'networkDT_before_filter', - 'outputObj'), - set_defaults = TRUE, - copy_obj = TRUE, - verbose = TRUE) { + spat_unit = NULL, + name = NULL, + output = c('spatialNetworkObj', + 'networkDT', + 'networkDT_before_filter', + 'outputObj'), + set_defaults = TRUE, + copy_obj = TRUE, + verbose = TRUE) { # Pass to internal function - get_spatialNetwork(gobject = gobject, - spat_unit = spat_unit, - name = name, - output = output, - set_defaults = set_defaults, - copy_obj = copy_obj, - verbose = verbose) + network = get_spatialNetwork(gobject = gobject, + spat_unit = spat_unit, + name = name, + output = output, + set_defaults = set_defaults, + copy_obj = copy_obj, + verbose = verbose) + + return(network) } #' @title Set spatial network @@ -1734,12 +1740,14 @@ setSpatialNetwork = function(gobject, set_defaults = TRUE) { # Pass to internal function - set_spatialNetwork(gobject = gobject, - spat_unit = spat_unit, - name = name, - spatial_network = spatial_network, - verbose = verbose, - set_defaults = set_defaults) + gobject = set_spatialNetwork(gobject = gobject, + spat_unit = spat_unit, + name = name, + spatial_network = spatial_network, + verbose = verbose, + set_defaults = set_defaults) + + return(gobject) } ## spatial grid slot #### @@ -1854,12 +1862,14 @@ getSpatialGrid = function(gobject, set_defaults = TRUE) { # Pass to internal function - get_spatialGrid(gobject = gobject, - spat_unit = spat_unit, - feat_type = feat_type, - name = name, - return_grid_Obj = return_grid_Obj, - set_defaults = set_defaults) + grid = get_spatialGrid(gobject = gobject, + spat_unit = spat_unit, + feat_type = feat_type, + name = name, + return_grid_Obj = return_grid_Obj, + set_defaults = set_defaults) + + return(grid) } #' @title Set spatial grid @@ -1964,13 +1974,15 @@ setSpatialGrid = function(gobject, set_defaults = TRUE) { # Pass to internal function - set_spatialGrid(gobject = gobject, - spatial_grid = spatial_grid, - spat_unit = spat_unit, - feat_type = feat_type, - name = name, - verbose = verbose, - set_defaults = set_defaults) + gobject = set_spatialGrid(gobject = gobject, + spatial_grid = spatial_grid, + spat_unit = spat_unit, + feat_type = feat_type, + name = name, + verbose = verbose, + set_defaults = set_defaults) + + return(gobject) } ## polygon cell info #### @@ -2118,7 +2130,7 @@ setPolygonInfo = function(gobject = NULL, wrap_msg("Unable to set polygon spatVector to non-Giotto object.") stop(wrap_msg("Please provide a Giotto object to the gobject argument.")) } - + if (!"giottoPolygon" %in% class(gpolygon)){ wrap_msg("Unable to set non-spatVector object to Giotto object.") stop(wrap_msg("Please provide a giotto polygon to the gpolygon argument.")) @@ -2250,7 +2262,7 @@ setFeatureInfo = function(gobject = NULL, wrap_msg("Unable to set giotto points spatVector feature info to non-Giotto object.") stop(wrap_msg("Please provide a Giotto object to the gobject argument.")) } - + if (!"giottoPolygon" %in% class(gpolygon)){ wrap_msg("Unable to set non-giotto points spatVector feature info to Giotto object.") stop(wrap_msg("Please provide a giotto polygon to the gpolygon argument.")) @@ -2351,13 +2363,15 @@ getSpatialEnrichment = function(gobject, set_defaults = TRUE) { # Pass to internal function - get_spatial_enrichment(gobject, - spat_unit = NULL, - feat_type = NULL, - enrichm_name = 'DWLS', - output = c('spatEnrObj', 'data.table'), - copy_obj = TRUE, - set_defaults = TRUE) + enr_res = get_spatial_enrichment(gobject, + spat_unit = NULL, + feat_type = NULL, + enrichm_name = 'DWLS', + output = c('spatEnrObj', 'data.table'), + copy_obj = TRUE, + set_defaults = TRUE) + + return(enr_res) } @@ -2461,13 +2475,15 @@ setSpatialEnrichment = function(gobject, set_defaults = TRUE) { # Pass to internal function - set_spatial_enrichment(gobject = gobject, - spatenrichment = spatenrichment, - spat_unit = spat_unit, - feat_type = feat_type, - enrichm_name = enrichm_name, - verbose = verbose, - set_defaults = set_defaults) + gobject = set_spatial_enrichment(gobject = gobject, + spatenrichment = spatenrichment, + spat_unit = spat_unit, + feat_type = feat_type, + enrichm_name = enrichm_name, + verbose = verbose, + set_defaults = set_defaults) + + return(gobject) } ## MG image slot #### @@ -2645,7 +2661,7 @@ get_giottoImage = function(gobject = NULL, #' @return a giotto image object #' @family image data accessor functions #' @family functions to get data from giotto object -#' @export +#' @export getGiottoImage = function(gobject = NULL, image_type = c('image','largeImage'), name = NULL) { From 954ec51122bf91e055bc9c391341a1d0fa36b14c Mon Sep 17 00:00:00 2001 From: jiajic <72078254+jiajic@users.noreply.github.com> Date: Thu, 2 Feb 2023 00:35:17 -0500 Subject: [PATCH 126/129] update accessors --- NAMESPACE | 22 ++ NEWS.md | 2 + R/accessors.R | 623 ++++++++++++++++++++++++++---- R/generics.R | 6 + R/utilities.R | 15 + R/wnn.R | 10 +- man/check_github_suite_ver.Rd | 13 + man/createGiottoMerscopeObject.Rd | 1 + man/getDimReduction.Rd | 72 ++++ man/getExpression.Rd | 67 ++++ man/getFeatureInfo.Rd | 49 +++ man/getGiottoImage.Rd | 56 +++ man/getMultiomics.Rd | 62 +++ man/getNearestNetwork.Rd | 68 ++++ man/getPolygonInfo.Rd | 56 +++ man/getSpatialEnrichment.Rd | 69 ++++ man/getSpatialGrid.Rd | 62 +++ man/getSpatialLocations.Rd | 69 ++++ man/getSpatialNetwork.Rd | 66 ++++ man/get_NearestNetwork.Rd | 13 + man/get_cell_id.Rd | 11 + man/get_dimReduction.Rd | 13 + man/get_expression_values.Rd | 13 + man/get_feat_id.Rd | 11 + man/get_feature_info.Rd | 13 + man/get_giottoImage.Rd | 13 + man/get_multiomics.Rd | 13 + man/get_polygon_info.Rd | 13 + man/get_spatialGrid.Rd | 13 + man/get_spatialNetwork.Rd | 13 + man/get_spatial_enrichment.Rd | 13 + man/get_spatial_locations.Rd | 13 + man/load_merscope_folder.Rd | 2 + man/setDimReduction.Rd | 83 ++++ man/setExpression.Rd | 84 ++++ man/setFeatureInfo.Rd | 60 +++ man/setGiottoImage.Rd | 78 ++++ man/setMultiomics.Rd | 74 ++++ man/setNearestNetwork.Rd | 81 ++++ man/setPolygonInfo.Rd | 65 ++++ man/setSpatialEnrichment.Rd | 74 ++++ man/setSpatialGrid.Rd | 74 ++++ man/setSpatialLocations.Rd | 86 +++++ man/setSpatialNetwork.Rd | 72 ++++ man/set_NearestNetwork.Rd | 15 +- man/set_cell_id.Rd | 15 +- man/set_cell_metadata.Rd | 12 + man/set_dimReduction.Rd | 15 +- man/set_expression_values.Rd | 15 +- man/set_feat_id.Rd | 11 + man/set_feature_info.Rd | 27 +- man/set_feature_metadata.Rd | 12 + man/set_giottoImage.Rd | 15 +- man/set_multiomics.Rd | 15 +- man/set_polygon_info.Rd | 15 +- man/set_spatialGrid.Rd | 15 +- man/set_spatialNetwork.Rd | 22 +- man/set_spatial_enrichment.Rd | 15 +- man/set_spatial_locations.Rd | 15 +- 59 files changed, 2531 insertions(+), 89 deletions(-) create mode 100644 man/check_github_suite_ver.Rd create mode 100644 man/getDimReduction.Rd create mode 100644 man/getExpression.Rd create mode 100644 man/getFeatureInfo.Rd create mode 100644 man/getGiottoImage.Rd create mode 100644 man/getMultiomics.Rd create mode 100644 man/getNearestNetwork.Rd create mode 100644 man/getPolygonInfo.Rd create mode 100644 man/getSpatialEnrichment.Rd create mode 100644 man/getSpatialGrid.Rd create mode 100644 man/getSpatialLocations.Rd create mode 100644 man/getSpatialNetwork.Rd create mode 100644 man/setDimReduction.Rd create mode 100644 man/setExpression.Rd create mode 100644 man/setFeatureInfo.Rd create mode 100644 man/setGiottoImage.Rd create mode 100644 man/setMultiomics.Rd create mode 100644 man/setNearestNetwork.Rd create mode 100644 man/setPolygonInfo.Rd create mode 100644 man/setSpatialEnrichment.Rd create mode 100644 man/setSpatialGrid.Rd create mode 100644 man/setSpatialLocations.Rd create mode 100644 man/setSpatialNetwork.Rd diff --git a/NAMESPACE b/NAMESPACE index 3187cc494..1e1ffb9e4 100644 --- a/NAMESPACE +++ b/NAMESPACE @@ -177,8 +177,19 @@ export(getBalancedSpatCoexpressionFeats) export(getCellsFromPolygon) export(getClusterSimilarity) export(getDendrogramSplits) +export(getDimReduction) export(getDistinctColors) +export(getExpression) +export(getFeatureInfo) export(getGEFtxCoords) +export(getGiottoImage) +export(getMultiomics) +export(getNearestNetwork) +export(getPolygonInfo) +export(getSpatialEnrichment) +export(getSpatialGrid) +export(getSpatialLocations) +export(getSpatialNetwork) export(get_NearestNetwork) export(get_dimReduction) export(get_expression_values) @@ -296,6 +307,17 @@ export(runtSNE) export(saveGiotto) export(screePlot) export(selectPatternGenes) +export(setDimReduction) +export(setExpression) +export(setFeatureInfo) +export(setGiottoImage) +export(setMultiomics) +export(setNearestNetwork) +export(setPolygonInfo) +export(setSpatialEnrichment) +export(setSpatialGrid) +export(setSpatialLocations) +export(setSpatialNetwork) export(set_NearestNetwork) export(set_dimReduction) export(set_expression_values) diff --git a/NEWS.md b/NEWS.md index aa1b4627a..bc6b4076b 100644 --- a/NEWS.md +++ b/NEWS.md @@ -13,6 +13,7 @@ - New `spatialAutoCorLocal()` and `spatialAutoCorGlobal()` functions to find spatial autocorrelations from expression and cell metadata information - New `createSpatialWeightMatrix()` function to generate spatial weight matrix from spatial networks for autocorrelation - Add spatial_interaction_spot.R with functions adapted from master branch for working with the Giotto suite object. +- New exported accessors for slots (experimental) - Add `coord_fix_ratio` param to `spatFeatPlot2D()` and `spatFeatPlot2D_single()` - Add `order` parameter to `dimFeatPlot2D` and `spatDimFeatPlot2d` to plot and order cells according to the levels of the selected feature ([#477](https://github.com/drieslab/Giotto/issues/477)) - Add `plot()` method for `spatialNetworkObj` @@ -34,6 +35,7 @@ - Update `addFeatMetadata()` to handle replacement of existing columns - Update `show()` method for `giotto` - Update `show()` method for `spatEnrObj` +- Deprecate older snake_case accessors - Deprecate `polygon_feat_names` param in favor of `z_indices` in `readPolygonFilesVizgenHDF5()` - Deprecate `xy_translate_spatial_locations()` in favor of `shift_spatial_locations()` - Optimize `readPolygonFilesVizgen()` diff --git a/R/accessors.R b/R/accessors.R index 8630f12cc..e7542e606 100644 --- a/R/accessors.R +++ b/R/accessors.R @@ -57,7 +57,9 @@ get_cell_id = function(gobject, #' @title Set cell IDs for a given spatial unit #' @name set_cell_id #' @inheritParams data_access -#' @param cell_IDs character vector of cell IDs to set +#' @param cell_IDs character vector of cell IDs to set. Passing 'initialize' will +#' reset the slot based on in order of preference: spatial_info then expression +#' slots #' @description Data for each spatial unit is expected to agree on a single set of cell_IDs #' that are shared across any feature types. These cell_IDs are stored within the #' giotto object's \code{cell_ID} slot. Getters and setters for this slot directly @@ -81,6 +83,32 @@ set_cell_id = function(gobject, if(!inherits(cell_IDs, 'character')) stop('cell_IDs must be a character vector.') } + # initialize cell_IDs + if(identical(cell_IDs, 'initialize')) { + si_avail = list_spatial_info(gobject) + expr_avail = list_expression(gobject, spat_unit = spat_unit) + + if(!is.null(expr_avail)) { # preferred from expression + IDs = lapply(seq(nrow(expr_avail)), function(expr_i) { + ex_ID = spatIDs( + get_expression_values( + gobject = gobject, + spat_unit = spat_unit, + feat_type = expr_avail$feat_type[[expr_i]], + values = expr_avail$name[[expr_i]], + output = 'exprObj' + ) + ) + }) + cell_IDs = unique(unlist(IDs)) + } else if(!is.null(si_avail)) { + cell_IDs = unique(spatIDs(get_polygon_info(gobject = gobject, + polygon_name = spat_unit, + return_giottoPolygon = TRUE))) + } + } + + slot(gobject, 'cell_ID')[[spat_unit]] = cell_IDs return(gobject) @@ -145,6 +173,30 @@ set_feat_id = function(gobject, if(!inherits(feat_IDs, 'character')) stop('feat_IDs must be a character vector.') } + # initialize feat_ID + if(identical(feat_IDs, 'initialize')) { + fi_avail = list_feature_info(gobject = gobject) + expr_avail = list_expression(gobject = gobject, feat_type = feat_type) + + if(!is.null(expr_avail)) { # preferred from expression + IDs = lapply(seq(nrow(expr_avail)), function(expr_i) { + ex_ID = featIDs( + get_expression_values(gobject = gobject, + spat_unit = expr_avail$spat_unit[[expr_i]], + feat_type = feat_type, + values = expr_avail$name[[expr_i]], + output = 'exprObj') + ) + }) + feat_IDs = unique(unlist(IDs)) + } else if(!is.null(fi_avail)) { + feat_IDs = unique(featIDs(get_feature_info(gobject = gobject, + feat_type = feat_type, + set_defaults = FALSE))) + } + } + + slot(gobject, 'feat_ID')[[feat_type]] = feat_IDs return(gobject) @@ -315,6 +367,7 @@ get_cell_metadata = function(gobject, #' @param verbose be verbose #' @return giotto object #' @family functions to set data in giotto object +#' @keywords internal set_cell_metadata = function(gobject, metadata, spat_unit = NULL, @@ -352,13 +405,14 @@ set_cell_metadata = function(gobject, if(inherits(metadata, 'character')) { if(metadata == 'initialize') { if(isTRUE(verbose)) message('Initializing specified metadata.') - gobject@cell_metadata[[spat_unit]][[feat_type]] = new('cellMetaObj', - metaDT = data.table::data.table(cell_ID = get_cell_id(gobject, - spat_unit = spat_unit)), - col_desc = c(cell_ID = 'cell-specific unique ID value'), - spat_unit = spat_unit, - feat_type = feat_type, - provenance = if(is.null(provenance)) spat_unit else provenance) + gobject@cell_metadata[[spat_unit]][[feat_type]] = create_cell_meta_obj( + metaDT = data.table::data.table(cell_ID = get_cell_id(gobject, + spat_unit = spat_unit)), + col_desc = c(cell_ID = 'cell-specific unique ID value'), + spat_unit = spat_unit, + feat_type = feat_type, + provenance = if(is.null(provenance)) spat_unit else provenance + ) return(gobject) } } @@ -545,6 +599,7 @@ get_feature_metadata = function(gobject, #' @param verbose be verbose #' @return giotto object #' @family functions to set data in giotto object +#' @keywords internal set_feature_metadata = function(gobject, metadata, spat_unit = NULL, @@ -582,13 +637,14 @@ set_feature_metadata = function(gobject, if(inherits(metadata, 'character')) { if(metadata == 'initialize') { if(isTRUE(verbose)) message('Initializing specified metadata.') - gobject@feat_metadata[[spat_unit]][[feat_type]] = new('featMetaObj', - metaDT = data.table::data.table(feat_ID = get_feat_id(gobject, - feat_type = feat_type)), - col_desc = c(feat_ID = 'feature-specific unique ID value'), - spat_unit = spat_unit, - feat_type = feat_type, - provenance = if(is.null(provenance)) spat_unit else provenance) + gobject@feat_metadata[[spat_unit]][[feat_type]] = create_feat_meta_obj( + metaDT = data.table::data.table(feat_ID = get_feat_id(gobject, + feat_type = feat_type)), + col_desc = c(feat_ID = 'feature-specific unique ID value'), + spat_unit = spat_unit, + feat_type = feat_type, + provenance = if(is.null(provenance)) spat_unit else provenance + ) return(gobject) } } @@ -691,6 +747,7 @@ get_expression_values = function(gobject, output = c('exprObj', 'matrix'), set_defaults = TRUE) { + if(direct_call()) .Deprecated(new = 'getExpression') output = match.arg(output, choices = c('exprObj', 'matrix')) @@ -760,6 +817,41 @@ get_expression_values = function(gobject, } + + +#' @title Get expression values +#' @name getExpression +#' @description Function to get expression values from giotto object +#' @inheritParams data_access +#' @param values expression values to extract (e.g. "raw", "normalized", "scaled") +#' @param output what object type to retrieve the expression as. Currently either +#' 'matrix' for the matrix object contained in the exprObj or 'exprObj' (default) for +#' the exprObj itself are allowed. +#' @return exprObj or matrix depending on output param +#' @family expression accessor functions +#' @family functions to get data from giotto object +#' @export +getExpression = function(gobject, + values = NULL, + spat_unit = NULL, + feat_type = NULL, + output = c('exprObj', 'matrix'), + set_defaults = TRUE) { + + # pass to internal + expr_vals = get_expression_values(gobject = gobject, + values = values, + spat_unit = spat_unit, + feat_type = feat_type, + output = output, + set_defaults = set_defaults) + + return(expr_vals) +} + + + + #' @title select_expression_values #' @name select_expression_values #' @inheritDotParams get_expression_values @@ -796,6 +888,8 @@ set_expression_values = function(gobject, verbose = TRUE, set_defaults = TRUE) { + if(direct_call()) .Deprecated(new = 'setExpression') + if(!inherits(gobject, 'giotto')) stop('Only Giotto objects are supported for this function.') # 1. Determine user inputs @@ -824,22 +918,24 @@ set_expression_values = function(gobject, if(inherits(values, 'exprObj')) { if(isTRUE(nospec_unit)) { - if(!is.na(slot(values, 'spat_unit'))) spat_unit = slot(values, 'spat_unit') + if(!is.na(spatUnit(values))) spat_unit = spatUnit(values) } else { - slot(values, 'spat_unit') = spat_unit + spatUnit(values) = spat_unit } if(isTRUE(nospec_feat)) { - if(!is.na(slot(values, 'feat_type'))) feat_type = slot(values, 'feat_type') + if(!is.na(featType(values))) feat_type = featType(values) } else { - slot(values, 'feat_type') = feat_type + featType(values) = feat_type } if(isTRUE(nospec_name)) { - if(!is.na(slot(values, 'name'))) name = slot(values, 'name') + if(!is.na(objName(values))) name = objName(values) } else { - slot(values, 'name') = name + objName(values) = name } - if(!is.null(provenance)) { - slot(values, 'provenance') = provenance + if(is.null(provenance)) { + if(!is.null(prov(values))) provenance = prov(values) + } else { + prov(values) = provenance } } else { @@ -888,6 +984,168 @@ set_expression_values = function(gobject, +#' @title Set expression values +#' @name setExpression +#' @description Function to set expression values for giotto object +#' @inheritParams data_access +#' @param name name for the expression slot +#' @param provenance provenance information (optional) +#' @param values exprObj or matrix of expression values. If NULL, then the object +#' will be removed. +#' @param verbose be verbose +#' @return giotto object +#' @details If cell_ID, feat_ID, cell_metadata, or feat_metadata objects have not +#' been initialized yet, they will be initialized by this function. Note that +#' initialization based on feature info or spatial info is preferred if they exist +#' for this spatial unit and feature type. +#' @family expression accessor functions +#' @family functions to set data in giotto object +#' @export +setExpression = function(gobject, + values, + spat_unit = NULL, + feat_type = NULL, + name = 'test', + provenance = NULL, + verbose = TRUE, + set_defaults = TRUE) { + + if(!inherits(gobject, 'giotto')) stop('Only Giotto objects are supported for this function.') + + # 1. Determine user inputs + nospec_unit = ifelse(is.null(spat_unit), yes = TRUE, no = FALSE) + nospec_feat = ifelse(is.null(feat_type), yes = TRUE, no = FALSE) + nospec_name = ifelse(is.null(match.call()$name), yes = TRUE, no = FALSE) + + # 2. Set feat_type and spat_unit + if(isTRUE(set_defaults)) { + spat_unit = set_default_spat_unit(gobject = gobject, + spat_unit = spat_unit) + feat_type = set_default_feat_type(gobject = gobject, + spat_unit = spat_unit, + feat_type = feat_type) + } + + + # 3. if input is NULL, remove object (no initialize option) + if(is.null(values)) { + if(isTRUE(verbose)) wrap_msg('NULL passed to values param. + Removing specified expression') + gobject@expression[[spat_unit]][[feat_type]][[name]] = values #TODO replace this with internal + return(gobject) + } + + # 4.1 import data from S4 if available, else generate S4 + if(inherits(values, 'exprObj')) { + + if(isTRUE(nospec_unit)) { + if(!is.na(spatUnit(values))) spat_unit = spatUnit(values) + } else { + spatUnit(values) = spat_unit + } + if(isTRUE(nospec_feat)) { + if(!is.na(featType(values))) feat_type = featType(values) + } else { + featType(values) = feat_type + } + if(isTRUE(nospec_name)) { + if(!is.na(objName(values))) name = objName(values) + } else { + objName(values) = name + } + if(is.null(provenance)) { + if(!is.null(prov(values))) provenance = prov(values) + } else { + prov(values) = provenance + } + + } else { + + # 4.2 if nested list structure, extract spat_unit/feat_type + if(inherits(values, 'list')) { + cores = determine_cores(NA) + + exprObj_list = read_expression_data(expr_list = values, + sparse = TRUE, + cores = cores, + default_feat_type = feat_type, + provenance = if(is.null(provenance)) spat_unit else provenance) + # recursively run + for(obj_i in seq_along(exprObj_list)) { + # provenance info set during prev. step + gobject = set_expression_values(gobject, + values = exprObj_list[[obj_i]]) + } + return(gobject) + } + + # 4.3 otherwise assume matrix type object and create S4 + # TODO run this through read_expression_values as well to determine appropriate data type? + values = create_expr_obj( + name = name, + exprMat = values, + spat_unit = spat_unit, + feat_type = feat_type, + provenance = if(is.null(provenance)) spat_unit else provenance, # assumed + misc = NULL + ) + } + + ## 5. check if specified name has already been used + potential_names = list_expression_names(gobject, spat_unit = spat_unit, feat_type = feat_type) + if(name %in% potential_names) { + if(isTRUE(verbose)) wrap_msg('> ', name, ' already exists and will be replaced with new values \n') + } + + ## 6. update and return giotto object + gobject@expression[[spat_unit]][[feat_type]][[name]] = values #TODO replace with internal + + + ## 7. Initialize ID and metadata slots if needed + spatID_exist = spat_unit %in% list_cell_id_names(gobject) + featID_exist = feat_type %in% list_feat_id_names(gobject) + + cm_avail = is.null(list_cell_metadata(gobject = gobject, spat_unit = spat_unit, feat_type = feat_type)) + fm_avail = is.null(list_feat_metadata(gobject = gobject, spat_unit = spat_unit, feat_type = feat_type)) + + if(!spatID_exist) gobject = set_cell_id(gobject = gobject, + spat_unit = spat_unit, + cell_IDs = 'initialize', + set_defaults = FALSE) + if(!featID_exist) gobject = set_feat_id(gobject = gobject, + feat_type = feat_type, + feat_IDs = 'initialize', + set_defaults = FALSE) + + # initialize metadata values based on cell_ID and feat_ID slots (if needed) + if(!is.null(cm_avail)) gobject = set_cell_metadata( + gobject = gobject, + metadata = 'initialize', + spat_unit = spat_unit, + feat_type = feat_type, + provenance = if(is.null(provenance)) spat_unit else provenance, # assumed + verbose = FALSE, + set_defaults = FALSE + ) + if(!is.null(fm_avail)) gobject = set_feature_metadata( + gobject = gobject, + metadata = 'initialize', + spat_unit = spat_unit, + feat_type = feat_type, + provenance = if(is.null(provenance)) spat_unit else provenance, # assumed + verbose = FALSE, + set_defaults = FALSE + ) + + # do not generate faux spatial coords + + return(gobject) + +} + + + + ## spatial locations slot #### @@ -912,6 +1170,8 @@ get_spatial_locations = function(gobject, verbose = TRUE, set_defaults = TRUE) { + if(direct_call()) .Deprecated(new = 'getSpatialLocations') + output = match.arg(output, choices = c('spatLocsObj', 'data.table')) if(!is.null(spat_unit)) { @@ -1057,6 +1317,8 @@ set_spatial_locations = function(gobject, verbose = TRUE, set_defaults = TRUE) { + if(direct_call()) .Deprecated(new = 'setSpatialLocations') + # 1. determine if input was supplied to spat_unit and spat_loc_name nospec_unit = ifelse(is.null(spat_unit), yes = TRUE, no = FALSE) nospec_name = ifelse(is.null(match.call()$spat_loc_name), yes = TRUE, no = FALSE) @@ -1090,16 +1352,19 @@ set_spatial_locations = function(gobject, } else { # case if input given - use input slot(spatlocs, 'name') = spat_loc_name } - if(!is.null(provenance)) { - slot(spatlocs, 'provenance') = provenance + if(is.null(provenance)) { + if(!is.null(prov(spatlocs))) provenance = prov(spatlocs) + } else { + prov(spatlocs) = provenance } } else { - spatlocs = new('spatLocsObj', - name = spat_loc_name, - spat_unit = spat_unit, - coordinates = spatlocs, - provenance = if(is.null(provenance)) spat_unit else provenance) + spatlocs = create_spat_locs_obj( + name = spat_loc_name, + spat_unit = spat_unit, + coordinates = spatlocs, + provenance = if(is.null(provenance)) spat_unit else provenance + ) } # 5. check if specified name has already been used @@ -1182,6 +1447,8 @@ get_dimReduction = function(gobject, output = c('dimObj', 'data.table'), set_defaults = TRUE) { + if(direct_call()) .Deprecated(new = 'getDimReduction') + output = match.arg(output, choices = c('dimObj', 'data.table')) # Set feat_type and spat_unit @@ -1231,6 +1498,47 @@ get_dimReduction = function(gobject, } + +#' @title Get dimension reduction +#' @name getDimReduction +#' @inheritParams data_access +#' @param reduction reduction on cells or features (e.g. "cells", "feats") +#' @param reduction_method reduction method (e.g. "pca", "umap", "tsne") +#' @param name name of reduction results +#' @param output object type to return as. Either 'dimObj' (default) or 'data.table +#' of the embedding coordinates. +#' @description Function to get a dimension reduction object +#' @return dim reduction object (default) or dim reduction coordinates +#' @family dimensional reduction data accessor functions +#' @family functions to get data from giotto object +#' @export +getDimReduction = function(gobject, + spat_unit = NULL, + feat_type = NULL, + reduction = c('cells', 'feats'), + reduction_method = c('pca', 'umap', 'tsne'), + name = 'pca', + output = c('dimObj', 'data.table'), + set_defaults = TRUE) { + + # pass to internal + dimRed = get_dimReduction(gobject = gobject, + spat_unit = spat_unit, + feat_type = feat_type, + reduction = reduction, + reduction_method = reduction_method, + name = name, + output = output, + set_defaults = set_defaults) + + return(dimRed) +} + + + + + + #' @title select_dimReduction #' @name select_dimReduction #' @inheritDotParams get_dimReduction @@ -1271,6 +1579,8 @@ set_dimReduction = function(gobject, set_defaults = TRUE) { + if(direct_call()) .Deprecated(new = 'setDimReduction') + # Set feat_type and spat_unit # if(isTRUE(set_defaults)) { # spat_unit = set_default_spat_unit(gobject = gobject, @@ -1300,7 +1610,9 @@ set_dimReduction = function(gobject, # set provenance information if given if(is.null(provenance)) { - slot(dimObject, 'provenance') = provenance + if(!is.null(prov(dimObject))) provenance = prov(dimObject) + } else { + prov(dimObject) = provenance } ## 3. update and return giotto object @@ -1310,6 +1622,49 @@ set_dimReduction = function(gobject, } + +#' @title Set dimension reduction +#' @name setDimReduction +#' @description Function to set a dimension reduction slot +#' @inheritParams data_access +#' @param reduction reduction on cells or features +#' @param reduction_method reduction method (e.g. "pca") +#' @param name name of reduction results +#' @param dimObject dimension object result to set +#' @param provenance provenance information (optional) +#' @param verbose be verbose +#' @return giotto object +#' @family dimensional reduction data accessor functions +#' @family functions to set data in giotto object +#' @export +setDimReduction = function(gobject, + dimObject, + spat_unit = NULL, + feat_type = NULL, + reduction = c('cells', 'genes'), + reduction_method = c('pca', 'umap', 'tsne'), + name = 'pca', + provenance = NULL, + verbose = TRUE, + set_defaults = TRUE) { + + # pass to internal + gobject = set_dimReduction(gobject = gobject, + dimObject = dimObject, + spat_unit = spat_unit, + feat_type = feat_type, + reduction = reduction, + reduction_method = reduction_method, + name = name, + provenance = provenance, + verbose = verbose, + set_defaults = set_defaults) + + return(gobject) +} + + + ## nearest neighbor network slot #### #' @title Get nearest network @@ -1331,6 +1686,8 @@ get_NearestNetwork = function(gobject, output = c('nnNetObj', 'igraph', 'data.table'), set_defaults = TRUE) { + if(direct_call()) .Deprecated(new = 'getNearestNetwork') + output = match.arg(arg = output, choices = c('nnNetObj', 'igraph', 'data.table')) # 1. Set feat_type and spat_unit @@ -1393,6 +1750,42 @@ get_NearestNetwork = function(gobject, } + + +#' @title Get nearest neighbor network +#' @name getNearestNetwork +#' @description Get a NN-network from a Giotto object +#' @inheritParams data_access +#' @param nn_network_to_use "kNN" or "sNN" +#' @param network_name name of NN network to be used +#' @param output return a igraph or data.table object. Default 'igraph' +#' @return igraph or data.table object +#' @family expression space nearest network accessor functions +#' @family functions to get data from giotto object +#' @export +getNearestNetwork = function(gobject, + spat_unit = NULL, + feat_type = NULL, + nn_network_to_use = NULL, + network_name = NULL, + output = c('nnNetObj', 'igraph', 'data.table'), + set_defaults = TRUE) { + + # pass to internal + nn = get_NearestNetwork(gobject = gobject, + spat_unit = spat_unit, + feat_type = feat_type, + nn_network_to_use = nn_network_to_use, + network_name = network_name, + output = output, + set_defaults = set_defaults) + + return(nn) +} + + + + #' @title Extract nearest network #' @name extractNearestNetwork #' @inheritDotParams get_NearestNetwork @@ -1444,6 +1837,8 @@ set_NearestNetwork = function(gobject, verbose = TRUE, set_defaults = TRUE) { + if(direct_call()) .Deprecated(new = 'setNearestNetwork') + # 1. determine user input nospec_unit = ifelse(is.null(spat_unit), yes = TRUE, no = FALSE) nospec_feat = ifelse(is.null(feat_type), yes = TRUE, no = FALSE) @@ -1489,8 +1884,10 @@ set_NearestNetwork = function(gobject, } else { slot(nn_network, 'name') = network_name } - if(!is.null(provenance)) { - slot(nn_network, 'provenance') = provenance + if(is.null(provenance)) { + if(!is.null(prov(nn_network))) provenance = prov(nn_network) + } else { + prov(nn_network) = provenance } } else { @@ -1522,6 +1919,52 @@ set_NearestNetwork = function(gobject, } + + + +#' @title Set nearest neighbor network +#' @name setNearestNetwork +#' @description Set a NN-network for a Giotto object +#' @inheritParams data_access +#' @param nn_network_to_use "kNN" or "sNN" +#' @param network_name name of NN network to be used +#' @param nn_network nnNetObj or igraph nearest network object. Data.table not +#' yet supported. +#' @param provenance provenance information (optional) +#' @param verbose be verbose +#' @return giotto object +#' @family expression space nearest network accessor functions +#' @family functions to set data in giotto object +#' @export +setNearestNetwork = function(gobject, + nn_network, + spat_unit = NULL, + feat_type = NULL, + nn_network_to_use = 'sNN', + network_name = 'sNN.pca', + provenance = NULL, + verbose = TRUE, + set_defaults = TRUE) { + + # pass to internal + gobject = set_NearestNetwork(gobject = gobject, + nn_network = nn_network, + spat_unit = spat_unit, + feat_type = feat_type, + nn_network_to_use = nn_network_to_use, + network_name = network_name, + provenance = provenance, + verbose = verbose, + set_defaults = set_defaults) + + return(gobject) +} + + + + + + ## spatial network slot #### #' @title Get spatial network @@ -1547,6 +1990,8 @@ get_spatialNetwork = function(gobject, copy_obj = TRUE, verbose = TRUE) { + if(direct_call()) .Deprecated(new = 'getSpatialNetwork') + output = match.arg(output, choices = c('spatialNetworkObj', 'networkDT', 'networkDT_before_filter', @@ -1654,12 +2099,15 @@ getSpatialNetwork = function(gobject, #' @family functions to set data in giotto object #' @export set_spatialNetwork = function(gobject, + spatial_network, spat_unit = NULL, name = NULL, - spatial_network, + provenance = NULL, verbose = TRUE, set_defaults = TRUE) { + if(direct_call()) .Deprecated(new = 'setSpatialNetwork') + # 1. determmine if input was supplied to spat_unit and name if(is.null(spat_unit)) { nospec_unit = TRUE @@ -1697,6 +2145,11 @@ set_spatialNetwork = function(gobject, else { slot(spatial_network, 'name') = name } + if(is.null(provenance)) { + if(!is.null(prov(spatial_network))) provenance = prov(spatial_network) + } else { + prov(spatial_network) = provenance + } } else { stop('Object to set must be a spatialNetworkObj') @@ -1733,17 +2186,19 @@ set_spatialNetwork = function(gobject, #' @family functions to set data in giotto object #' @export setSpatialNetwork = function(gobject, - spat_unit = NULL, - name = NULL, - spatial_network, - verbose = TRUE, - set_defaults = TRUE) { + spatial_network, + spat_unit = NULL, + name = NULL, + provenance = NULL, + verbose = TRUE, + set_defaults = TRUE) { # Pass to internal function gobject = set_spatialNetwork(gobject = gobject, + spatial_network = spatial_network, spat_unit = spat_unit, name = name, - spatial_network = spatial_network, + provenance = provenance, verbose = verbose, set_defaults = set_defaults) @@ -1768,6 +2223,8 @@ get_spatialGrid = function(gobject, return_grid_Obj = FALSE, set_defaults = TRUE) { + if(direct_call()) .Deprecated(new = 'getSpatialGrid') + # Set feat_type and spat_unit if(isTRUE(set_defaults)) { spat_unit = set_default_spat_unit(gobject = gobject, @@ -1891,6 +2348,8 @@ set_spatialGrid = function(gobject, verbose = TRUE, set_defaults = TRUE) { + if(direct_call()) .Deprecated(new = 'setSpatialGrid') + # 1. check input nospec_unit = ifelse(is.null(spat_unit), yes = TRUE, no = FALSE) nospec_feat = ifelse(is.null(feat_type), yes = TRUE, no = FALSE) @@ -2002,6 +2461,8 @@ get_polygon_info = function(gobject, polygon_overlap = NULL, return_giottoPolygon = FALSE) { + if(direct_call()) .Deprecated(new = 'getPolygonInfo') + potential_names = names(slot(gobject, 'spatial_info')) if(is.null(potential_names)) stop('Giotto object contains no polygon information') @@ -2050,9 +2511,10 @@ getPolygonInfo = function(gobject = NULL, polygon_name = NULL, polygon_overlap = NULL, return_giottoPolygon = FALSE){ - if (!"giotto" %in% class(gobject)){ + if (!inherits(gobject, 'giotto')){ wrap_msg("Unable to get polygon spatVector from non-Giotto object.") - stop(wrap_msg("Please provide a Giotto object to the gobject argument.")) + stop(wrap_txt("Please provide a Giotto object to the gobject argument.", + errWidth = TRUE)) } poly_info = get_polygon_info(gobject = gobject, @@ -2094,7 +2556,7 @@ set_polygon_info = function(gobject, gpolygon, verbose = TRUE) { - + if(direct_call()) .Deprecated(new = 'setPolygonInfo') ## 1. check if specified name has already been used potential_names = names(gobject@spatial_info) @@ -2126,14 +2588,16 @@ setPolygonInfo = function(gobject = NULL, polygon_name = 'cell', gpolygon = NULL, verbose = TRUE) { - if (!"giotto" %in% class(gobject)){ + if (!inherits(gobject, 'giotto')){ wrap_msg("Unable to set polygon spatVector to non-Giotto object.") - stop(wrap_msg("Please provide a Giotto object to the gobject argument.")) + stop(wrap_txt("Please provide a Giotto object to the gobject argument.", + errWidth = TRUE)) } - if (!"giottoPolygon" %in% class(gpolygon)){ + if (!inherits(gpolygon, 'giottoPolygon')){ wrap_msg("Unable to set non-spatVector object to Giotto object.") - stop(wrap_msg("Please provide a giotto polygon to the gpolygon argument.")) + stop(wrap_txt("Please provide a giotto polygon to the gpolygon argument.", + errWidth = TRUE)) } gobject = set_polygon_info(gobject = gobject, polygon_name = polygon_name, @@ -2156,14 +2620,15 @@ setPolygonInfo = function(gobject = NULL, getFeatureInfo = function(gobject = gobject, feat_type = NULL, set_defaults = TRUE) { - if (!"giotto" %in% class(gobject)){ + if (!inherits(gobject, 'giotto')){ wrap_msg("Unable to get giotto points spatVector feature info from non-Giotto object.") - stop(wrap_msg("Please provide a Giotto object to the gobject argument.")) + stop(wrap_txt("Please provide a Giotto object to the gobject argument.", + errWidth = TRUE)) } feat_info = get_feature_info(gobject = gobject, feat_type = feat_type, set_defaults = set_defaults) - return (feat_info) + return(feat_info) } #' @title Get feature info @@ -2177,6 +2642,8 @@ get_feature_info = function(gobject, feat_type = NULL, set_defaults = TRUE) { + if(direct_call()) .Deprecated(new = 'getFeatureInfo') + # specify feat_type if(isTRUE(set_defaults)) { feat_type = set_default_feat_type(gobject = gobject, @@ -2200,7 +2667,7 @@ get_feature_info = function(gobject, #' @keywords internal select_feature_info = function(...) { - .Deprecated(new = "get_feature_info") + .Deprecated(new = "getFeatureInfo") get_feature_info(...) @@ -2211,7 +2678,8 @@ select_feature_info = function(...) { #' @name set_feature_info #' @description Set giotto polygon spatVector for features #' @inheritParams data_access -#' @param gpolygon giotto polygon +#' @param gpoints giotto points object +#' @param gpolygon typo do not use #' @param verbose be verbose #' @return giotto object #' @family feature info data accessor functions @@ -2219,9 +2687,16 @@ select_feature_info = function(...) { #' @export set_feature_info = function(gobject, feat_type = NULL, - gpolygon, + gpoints, + gpolygon = NULL, verbose = TRUE) { + if(direct_call()) .Deprecated(new = 'setFeatureInfo') + if(!is.null(gpolygon)) { # deprecation + warning(wrap_txt('do not use gpolygon param. Use gpoints')) + if(is.null(gpoints)) gpoints = gpolygon + } + # specify feat_type if(is.null(feat_type)) { feat_type = gobject@expression_feat[[1]] @@ -2246,31 +2721,32 @@ set_feature_info = function(gobject, #' @name setFeatureInfo #' @description Set giotto polygon spatVector for features #' @inheritParams data_access -#' @param gobject giotto object containing a the given giottopolygon -#' @param gpolygon giotto polygon -#' @param feat_type feature slot information (e.g. "rna") +#' @param gpoints giotto points object #' @param verbose be verbose #' @return giotto object #' @family feature info data accessor functions #' @family functions to set data in giotto object #' @export setFeatureInfo = function(gobject = NULL, + gpoints, feat_type = NULL, - gpolygon = NULL, - verbose = TRUE){ - if (!"giotto" %in% class(gobject)){ + verbose = TRUE) { + + if (!inherits(gobject, 'giotto')){ wrap_msg("Unable to set giotto points spatVector feature info to non-Giotto object.") - stop(wrap_msg("Please provide a Giotto object to the gobject argument.")) + stop(wrap_txt("Please provide a Giotto object to the gobject argument.", + errWidth = TRUE)) } - if (!"giottoPolygon" %in% class(gpolygon)){ + if (!inherits(gpoints, 'giottoPoints')){ wrap_msg("Unable to set non-giotto points spatVector feature info to Giotto object.") - stop(wrap_msg("Please provide a giotto polygon to the gpolygon argument.")) + stop(wrap_txt("Please provide a giotto polygon to the gpolygon argument.", + errWidth = TRUE)) } gobject = set_feature_info(gobject = gobject, feat_type = feat_type, - gpolygon = gpolygon, + gpoints = gpoints, verbose = verbose) return (gobject) @@ -2297,6 +2773,8 @@ get_spatial_enrichment = function(gobject, copy_obj = TRUE, set_defaults = TRUE) { + if(direct_call()) .Deprecated(new = 'getSpatialEnrichment') + output = match.arg(output, choices = c('spatEnrObj', 'data.table')) # Set feat_type and spat_unit @@ -2393,6 +2871,8 @@ set_spatial_enrichment = function(gobject, verbose = TRUE, set_defaults = TRUE) { + if(direct_call()) .Deprecated(new = 'setSpatialEnrichment') + # 1. Check user input nospec_unit = ifelse(is.null(spat_unit), yes = TRUE, no = FALSE) nospec_feat = ifelse(is.null(feat_type), yes = TRUE, no = FALSE) @@ -2636,6 +3116,8 @@ get_giottoImage = function(gobject = NULL, image_type = c('image','largeImage'), name = NULL) { + if(direct_call()) .Deprecated(new = 'getGiottoImage') + # Check image type image_type = match.arg(image_type, choices = c('image','largeImage')) @@ -2664,9 +3146,10 @@ get_giottoImage = function(gobject = NULL, getGiottoImage = function(gobject = NULL, image_type = c('image','largeImage'), name = NULL) { - if (!"giotto" %in% class(gobject)){ + if (!inherits(gobject, 'giotto')){ wrap_msg("Unable to get Giotto Image from non-Giotto object.") - stop(wrap_msg("Please provide a Giotto object to the gobject argument.")) + stop(wrap_txt("Please provide a Giotto object to the gobject argument.", + errWidth = TRUE)) } g_img = get_giottoImage(gobject = gobject, @@ -2703,6 +3186,8 @@ set_giottoImage = function(gobject = NULL, name = NULL, verbose = TRUE) { + if(direct_call()) .Deprecated(new = 'setGiottoImage') + # Check image type image_type = match.arg(image_type, choices = c('image','largeImage')) @@ -2747,15 +3232,17 @@ setGiottoImage = function(gobject = NULL, name = NULL, verbose = TRUE){ - if (!"giotto" %in% class(gobject)){ + if (!inherits(gobject, 'giotto')){ wrap_msg("Unable to set Giotto Image to non-Giotto object.") - stop(wrap_msg("Please provide a Giotto object to the gobject argument.")) + stop(wrap_txt("Please provide a Giotto object to the gobject argument.", + errWidth = TRUE)) } else if (is.null(image)) { wrap_msg("Warning: image argument set to NULL. Replacing current image slot with NULL will remove the image.") } else if( !"giottoImage" %in% image || !"giottoLargeImage" %in% image) { wrap_msg("Unable to set non-giottoImage objects. Please ensure a giottoImage or giottoLargeImage is provided to this function.") wrap_msg("See createGiottoImage or createGiottoLargeImage for more details.") - stop(wrap_msg("Unable to set non-giottoImage object.")) + stop(wrap_txt("Unable to set non-giottoImage object.", + errWidth = TRUE)) } gobject = set_giottoImage(gobject = gobject, diff --git a/R/generics.R b/R/generics.R index c9202a6ce..e425e6181 100644 --- a/R/generics.R +++ b/R/generics.R @@ -81,6 +81,12 @@ setMethod('spatIDs', signature(x = 'spatEnrObj', spat_unit = 'missing'), x@enrichDT[, cell_ID] }) + + + + +# feat IDs + #' @rdname spatIDs-generic #' @export setMethod('featIDs', signature(x = 'giotto', feat_type = 'missing'), diff --git a/R/utilities.R b/R/utilities.R index 8891f8ff7..bba6e47c4 100644 --- a/R/utilities.R +++ b/R/utilities.R @@ -722,3 +722,18 @@ degrees = function(rad) { rad * 180 / pi } + + +# deprecation helpers #### + +# determine if a function has been called directly +direct_call = function() { + ifelse(sys.nframe() == 2L, yes = TRUE, no = FALSE) +} + + + + + + + diff --git a/R/wnn.R b/R/wnn.R index 44bad5f0e..38e1c08b0 100644 --- a/R/wnn.R +++ b/R/wnn.R @@ -624,15 +624,17 @@ setMultiomics = function(gobject = NULL, verbose = TRUE){ if (!"giotto" %in% class(gobject)){ wrap_msg("Unable to set multiomics info to non-Giotto object.") - stop(wrap_msg("Please provide a Giotto object to the gobject argument.")) + stop(wrap_txt("Please provide a Giotto object to the gobject argument.", + errWidth = TRUE)) } gobject = set_multiomics(gobject = gobject, result = result, spat_unit = spat_unit, feat_type = feat_type, - result = result, - integration_method = integration_method) + result_name = result_name, + integration_method = integration_method, + verbose = verbose) return (gobject) @@ -722,4 +724,4 @@ getMultiomics = function(gobject = NULL, integration_method = integration_method, result_name = result_name) return (multiomics_result) -} \ No newline at end of file +} diff --git a/man/check_github_suite_ver.Rd b/man/check_github_suite_ver.Rd new file mode 100644 index 000000000..b79c1eaac --- /dev/null +++ b/man/check_github_suite_ver.Rd @@ -0,0 +1,13 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/general_help.R +\name{check_github_suite_ver} +\alias{check_github_suite_ver} +\title{Check for updates to Giotto Suite} +\usage{ +check_github_suite_ver() +} +\description{ +Checks the Giotto Suite github repository and compares the version +number to the currently installed. +} +\keyword{internal} diff --git a/man/createGiottoMerscopeObject.Rd b/man/createGiottoMerscopeObject.Rd index 9067de42c..ebcd5a155 100644 --- a/man/createGiottoMerscopeObject.Rd +++ b/man/createGiottoMerscopeObject.Rd @@ -10,6 +10,7 @@ createGiottoMerscopeObject( merscope_dir, data_to_use = c("subcellular", "aggregate"), FOVs = NULL, + poly_z_indices = 1:7, calculate_overlap = TRUE, overlap_to_matrix = TRUE, aggregate_stack = TRUE, diff --git a/man/getDimReduction.Rd b/man/getDimReduction.Rd new file mode 100644 index 000000000..6e6dda8ea --- /dev/null +++ b/man/getDimReduction.Rd @@ -0,0 +1,72 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/accessors.R +\name{getDimReduction} +\alias{getDimReduction} +\title{Get dimension reduction} +\usage{ +getDimReduction( + gobject, + spat_unit = NULL, + feat_type = NULL, + reduction = c("cells", "feats"), + reduction_method = c("pca", "umap", "tsne"), + name = "pca", + output = c("dimObj", "data.table"), + set_defaults = TRUE +) +} +\arguments{ +\item{gobject}{giotto object} + +\item{spat_unit}{spatial unit (e.g. "cell")} + +\item{feat_type}{feature type (e.g. "rna", "dna", "protein")} + +\item{reduction}{reduction on cells or features (e.g. "cells", "feats")} + +\item{reduction_method}{reduction method (e.g. "pca", "umap", "tsne")} + +\item{name}{name of reduction results} + +\item{output}{object type to return as. Either 'dimObj' (default) or 'data.table +of the embedding coordinates.} + +\item{set_defaults}{set default spat_unit and feat_type. Change to FALSE only when} +} +\value{ +dim reduction object (default) or dim reduction coordinates +} +\description{ +Function to get a dimension reduction object +} +\seealso{ +Other dimensional reduction data accessor functions: +\code{\link{get_dimReduction}()}, +\code{\link{setDimReduction}()}, +\code{\link{set_dimReduction}()} + +Other functions to get data from giotto object: +\code{\link{getExpression}()}, +\code{\link{getFeatureInfo}()}, +\code{\link{getGiottoImage}()}, +\code{\link{getMultiomics}()}, +\code{\link{getNearestNetwork}()}, +\code{\link{getPolygonInfo}()}, +\code{\link{getSpatialEnrichment}()}, +\code{\link{getSpatialGrid}()}, +\code{\link{getSpatialLocations}()}, +\code{\link{getSpatialNetwork}()}, +\code{\link{get_NearestNetwork}()}, +\code{\link{get_dimReduction}()}, +\code{\link{get_expression_values}()}, +\code{\link{get_feature_info}()}, +\code{\link{get_giottoImage}()}, +\code{\link{get_multiomics}()}, +\code{\link{get_polygon_info}()}, +\code{\link{get_spatialGrid}()}, +\code{\link{get_spatialNetwork}()}, +\code{\link{get_spatial_enrichment}()}, +\code{\link{get_spatial_locations}()} +} +\concept{dimensional reduction data accessor functions} +\concept{functions to get data from giotto object} diff --git a/man/getExpression.Rd b/man/getExpression.Rd new file mode 100644 index 000000000..beb41098a --- /dev/null +++ b/man/getExpression.Rd @@ -0,0 +1,67 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/accessors.R +\name{getExpression} +\alias{getExpression} +\title{Get expression values} +\usage{ +getExpression( + gobject, + values = NULL, + spat_unit = NULL, + feat_type = NULL, + output = c("exprObj", "matrix"), + set_defaults = TRUE +) +} +\arguments{ +\item{gobject}{giotto object} + +\item{values}{expression values to extract (e.g. "raw", "normalized", "scaled")} + +\item{spat_unit}{spatial unit (e.g. "cell")} + +\item{feat_type}{feature type (e.g. "rna", "dna", "protein")} + +\item{output}{what object type to retrieve the expression as. Currently either +'matrix' for the matrix object contained in the exprObj or 'exprObj' (default) for +the exprObj itself are allowed.} + +\item{set_defaults}{set default spat_unit and feat_type. Change to FALSE only when} +} +\value{ +exprObj or matrix depending on output param +} +\description{ +Function to get expression values from giotto object +} +\seealso{ +Other expression accessor functions: +\code{\link{get_expression_values}()}, +\code{\link{setExpression}()}, +\code{\link{set_expression_values}()} + +Other functions to get data from giotto object: +\code{\link{getDimReduction}()}, +\code{\link{getFeatureInfo}()}, +\code{\link{getGiottoImage}()}, +\code{\link{getMultiomics}()}, +\code{\link{getNearestNetwork}()}, +\code{\link{getPolygonInfo}()}, +\code{\link{getSpatialEnrichment}()}, +\code{\link{getSpatialGrid}()}, +\code{\link{getSpatialLocations}()}, +\code{\link{getSpatialNetwork}()}, +\code{\link{get_NearestNetwork}()}, +\code{\link{get_dimReduction}()}, +\code{\link{get_expression_values}()}, +\code{\link{get_feature_info}()}, +\code{\link{get_giottoImage}()}, +\code{\link{get_multiomics}()}, +\code{\link{get_polygon_info}()}, +\code{\link{get_spatialGrid}()}, +\code{\link{get_spatialNetwork}()}, +\code{\link{get_spatial_enrichment}()}, +\code{\link{get_spatial_locations}()} +} +\concept{expression accessor functions} +\concept{functions to get data from giotto object} diff --git a/man/getFeatureInfo.Rd b/man/getFeatureInfo.Rd new file mode 100644 index 000000000..d286ac7af --- /dev/null +++ b/man/getFeatureInfo.Rd @@ -0,0 +1,49 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/accessors.R +\name{getFeatureInfo} +\alias{getFeatureInfo} +\title{Get feature info} +\usage{ +getFeatureInfo(gobject = gobject, feat_type = NULL, set_defaults = TRUE) +} +\arguments{ +\item{gobject}{giotto object} + +\item{feat_type}{feature type (e.g. "rna", "dna", "protein")} + +\item{set_defaults}{set default spat_unit and feat_type. Change to FALSE only when} +} +\description{ +Get giotto points spatVector +} +\seealso{ +Other feature info data accessor functions: +\code{\link{get_feature_info}()}, +\code{\link{setFeatureInfo}()}, +\code{\link{set_feature_info}()} + +Other functions to get data from giotto object: +\code{\link{getDimReduction}()}, +\code{\link{getExpression}()}, +\code{\link{getGiottoImage}()}, +\code{\link{getMultiomics}()}, +\code{\link{getNearestNetwork}()}, +\code{\link{getPolygonInfo}()}, +\code{\link{getSpatialEnrichment}()}, +\code{\link{getSpatialGrid}()}, +\code{\link{getSpatialLocations}()}, +\code{\link{getSpatialNetwork}()}, +\code{\link{get_NearestNetwork}()}, +\code{\link{get_dimReduction}()}, +\code{\link{get_expression_values}()}, +\code{\link{get_feature_info}()}, +\code{\link{get_giottoImage}()}, +\code{\link{get_multiomics}()}, +\code{\link{get_polygon_info}()}, +\code{\link{get_spatialGrid}()}, +\code{\link{get_spatialNetwork}()}, +\code{\link{get_spatial_enrichment}()}, +\code{\link{get_spatial_locations}()} +} +\concept{feature info data accessor functions} +\concept{functions to get data from giotto object} diff --git a/man/getGiottoImage.Rd b/man/getGiottoImage.Rd new file mode 100644 index 000000000..6b65011ea --- /dev/null +++ b/man/getGiottoImage.Rd @@ -0,0 +1,56 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/accessors.R +\name{getGiottoImage} +\alias{getGiottoImage} +\title{Get giotto image object} +\usage{ +getGiottoImage( + gobject = NULL, + image_type = c("image", "largeImage"), + name = NULL +) +} +\arguments{ +\item{gobject}{giotto object} + +\item{image_type}{type of giotto image object. Either "image" or "largeImage"} + +\item{name}{name of a giotto image object \code{\link{showGiottoImageNames}}} +} +\value{ +a giotto image object +} +\description{ +Get giotto image object from gobject +} +\seealso{ +Other image data accessor functions: +\code{\link{get_giottoImage}()}, +\code{\link{setGiottoImage}()}, +\code{\link{set_giottoImage}()} + +Other functions to get data from giotto object: +\code{\link{getDimReduction}()}, +\code{\link{getExpression}()}, +\code{\link{getFeatureInfo}()}, +\code{\link{getMultiomics}()}, +\code{\link{getNearestNetwork}()}, +\code{\link{getPolygonInfo}()}, +\code{\link{getSpatialEnrichment}()}, +\code{\link{getSpatialGrid}()}, +\code{\link{getSpatialLocations}()}, +\code{\link{getSpatialNetwork}()}, +\code{\link{get_NearestNetwork}()}, +\code{\link{get_dimReduction}()}, +\code{\link{get_expression_values}()}, +\code{\link{get_feature_info}()}, +\code{\link{get_giottoImage}()}, +\code{\link{get_multiomics}()}, +\code{\link{get_polygon_info}()}, +\code{\link{get_spatialGrid}()}, +\code{\link{get_spatialNetwork}()}, +\code{\link{get_spatial_enrichment}()}, +\code{\link{get_spatial_locations}()} +} +\concept{functions to get data from giotto object} +\concept{image data accessor functions} diff --git a/man/getMultiomics.Rd b/man/getMultiomics.Rd new file mode 100644 index 000000000..8301b59d9 --- /dev/null +++ b/man/getMultiomics.Rd @@ -0,0 +1,62 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/wnn.R +\name{getMultiomics} +\alias{getMultiomics} +\title{Get multiomics integration results} +\usage{ +getMultiomics( + gobject = NULL, + spat_unit = NULL, + feat_type = NULL, + integration_method = "WNN", + result_name = "theta_weighted_matrix" +) +} +\arguments{ +\item{gobject}{A Giotto object} + +\item{spat_unit}{spatial unit (e.g. 'cell')} + +\item{feat_type}{integrated feature type (e.g. 'rna_protein')} + +\item{integration_method}{multiomics integration method used. Default = 'WNN'} + +\item{result_name}{Default = 'theta_weighted_matrix'} +} +\value{ +A multiomics integration result (e.g. theta_weighted_matrix from WNN) +} +\description{ +Get a multiomics integration result from a Giotto object +} +\seealso{ +Other multiomics accessor functions: +\code{\link{get_multiomics}()}, +\code{\link{setMultiomics}()}, +\code{\link{set_multiomics}()} + +Other functions to get data from giotto object: +\code{\link{getDimReduction}()}, +\code{\link{getExpression}()}, +\code{\link{getFeatureInfo}()}, +\code{\link{getGiottoImage}()}, +\code{\link{getNearestNetwork}()}, +\code{\link{getPolygonInfo}()}, +\code{\link{getSpatialEnrichment}()}, +\code{\link{getSpatialGrid}()}, +\code{\link{getSpatialLocations}()}, +\code{\link{getSpatialNetwork}()}, +\code{\link{get_NearestNetwork}()}, +\code{\link{get_dimReduction}()}, +\code{\link{get_expression_values}()}, +\code{\link{get_feature_info}()}, +\code{\link{get_giottoImage}()}, +\code{\link{get_multiomics}()}, +\code{\link{get_polygon_info}()}, +\code{\link{get_spatialGrid}()}, +\code{\link{get_spatialNetwork}()}, +\code{\link{get_spatial_enrichment}()}, +\code{\link{get_spatial_locations}()} +} +\concept{functions to get data from giotto object} +\concept{multiomics accessor functions} diff --git a/man/getNearestNetwork.Rd b/man/getNearestNetwork.Rd new file mode 100644 index 000000000..0d093d525 --- /dev/null +++ b/man/getNearestNetwork.Rd @@ -0,0 +1,68 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/accessors.R +\name{getNearestNetwork} +\alias{getNearestNetwork} +\title{Get nearest neighbor network} +\usage{ +getNearestNetwork( + gobject, + spat_unit = NULL, + feat_type = NULL, + nn_network_to_use = NULL, + network_name = NULL, + output = c("nnNetObj", "igraph", "data.table"), + set_defaults = TRUE +) +} +\arguments{ +\item{gobject}{giotto object} + +\item{spat_unit}{spatial unit (e.g. "cell")} + +\item{feat_type}{feature type (e.g. "rna", "dna", "protein")} + +\item{nn_network_to_use}{"kNN" or "sNN"} + +\item{network_name}{name of NN network to be used} + +\item{output}{return a igraph or data.table object. Default 'igraph'} + +\item{set_defaults}{set default spat_unit and feat_type. Change to FALSE only when} +} +\value{ +igraph or data.table object +} +\description{ +Get a NN-network from a Giotto object +} +\seealso{ +Other expression space nearest network accessor functions: +\code{\link{get_NearestNetwork}()}, +\code{\link{setNearestNetwork}()}, +\code{\link{set_NearestNetwork}()} + +Other functions to get data from giotto object: +\code{\link{getDimReduction}()}, +\code{\link{getExpression}()}, +\code{\link{getFeatureInfo}()}, +\code{\link{getGiottoImage}()}, +\code{\link{getMultiomics}()}, +\code{\link{getPolygonInfo}()}, +\code{\link{getSpatialEnrichment}()}, +\code{\link{getSpatialGrid}()}, +\code{\link{getSpatialLocations}()}, +\code{\link{getSpatialNetwork}()}, +\code{\link{get_NearestNetwork}()}, +\code{\link{get_dimReduction}()}, +\code{\link{get_expression_values}()}, +\code{\link{get_feature_info}()}, +\code{\link{get_giottoImage}()}, +\code{\link{get_multiomics}()}, +\code{\link{get_polygon_info}()}, +\code{\link{get_spatialGrid}()}, +\code{\link{get_spatialNetwork}()}, +\code{\link{get_spatial_enrichment}()}, +\code{\link{get_spatial_locations}()} +} +\concept{expression space nearest network accessor functions} +\concept{functions to get data from giotto object} diff --git a/man/getPolygonInfo.Rd b/man/getPolygonInfo.Rd new file mode 100644 index 000000000..554277595 --- /dev/null +++ b/man/getPolygonInfo.Rd @@ -0,0 +1,56 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/accessors.R +\name{getPolygonInfo} +\alias{getPolygonInfo} +\title{Get polygon info} +\usage{ +getPolygonInfo( + gobject = NULL, + polygon_name = NULL, + polygon_overlap = NULL, + return_giottoPolygon = FALSE +) +} +\arguments{ +\item{gobject}{giotto object} + +\item{polygon_name}{name of polygons. Default is "cell"} + +\item{polygon_overlap}{include polygon overlap information} + +\item{return_giottoPolygon}{(Defaults to FALSE) Return as giottoPolygon S4 object} +} +\description{ +Get giotto polygon spatVector +} +\seealso{ +Other polygon info data accessor functions: +\code{\link{get_polygon_info}()}, +\code{\link{setPolygonInfo}()}, +\code{\link{set_polygon_info}()} + +Other functions to get data from giotto object: +\code{\link{getDimReduction}()}, +\code{\link{getExpression}()}, +\code{\link{getFeatureInfo}()}, +\code{\link{getGiottoImage}()}, +\code{\link{getMultiomics}()}, +\code{\link{getNearestNetwork}()}, +\code{\link{getSpatialEnrichment}()}, +\code{\link{getSpatialGrid}()}, +\code{\link{getSpatialLocations}()}, +\code{\link{getSpatialNetwork}()}, +\code{\link{get_NearestNetwork}()}, +\code{\link{get_dimReduction}()}, +\code{\link{get_expression_values}()}, +\code{\link{get_feature_info}()}, +\code{\link{get_giottoImage}()}, +\code{\link{get_multiomics}()}, +\code{\link{get_polygon_info}()}, +\code{\link{get_spatialGrid}()}, +\code{\link{get_spatialNetwork}()}, +\code{\link{get_spatial_enrichment}()}, +\code{\link{get_spatial_locations}()} +} +\concept{functions to get data from giotto object} +\concept{polygon info data accessor functions} diff --git a/man/getSpatialEnrichment.Rd b/man/getSpatialEnrichment.Rd new file mode 100644 index 000000000..2e6b38d43 --- /dev/null +++ b/man/getSpatialEnrichment.Rd @@ -0,0 +1,69 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/accessors.R +\name{getSpatialEnrichment} +\alias{getSpatialEnrichment} +\title{Get spatial enrichment} +\usage{ +getSpatialEnrichment( + gobject, + spat_unit = NULL, + feat_type = NULL, + enrichm_name = "DWLS", + output = c("spatEnrObj", "data.table"), + copy_obj = TRUE, + set_defaults = TRUE +) +} +\arguments{ +\item{gobject}{giotto object} + +\item{spat_unit}{spatial unit (e.g. "cell")} + +\item{feat_type}{feature type (e.g. "rna", "dna", "protein")} + +\item{enrichm_name}{name of spatial enrichment results. Default "DWLS"} + +\item{output}{what format in which to get information (e.g. "data.table")} + +\item{copy_obj}{whether to deep copy/duplicate when getting the object (default = TRUE) +expression and spat_info are not expected to exist.} + +\item{set_defaults}{set default spat_unit and feat_type. Change to FALSE only when} +} +\value{ +data.table with fractions +} +\description{ +Function to get a spatial enrichment data.table +} +\seealso{ +Other spatial enrichment data accessor functions: +\code{\link{get_spatial_enrichment}()}, +\code{\link{setSpatialEnrichment}()}, +\code{\link{set_spatial_enrichment}()} + +Other functions to get data from giotto object: +\code{\link{getDimReduction}()}, +\code{\link{getExpression}()}, +\code{\link{getFeatureInfo}()}, +\code{\link{getGiottoImage}()}, +\code{\link{getMultiomics}()}, +\code{\link{getNearestNetwork}()}, +\code{\link{getPolygonInfo}()}, +\code{\link{getSpatialGrid}()}, +\code{\link{getSpatialLocations}()}, +\code{\link{getSpatialNetwork}()}, +\code{\link{get_NearestNetwork}()}, +\code{\link{get_dimReduction}()}, +\code{\link{get_expression_values}()}, +\code{\link{get_feature_info}()}, +\code{\link{get_giottoImage}()}, +\code{\link{get_multiomics}()}, +\code{\link{get_polygon_info}()}, +\code{\link{get_spatialGrid}()}, +\code{\link{get_spatialNetwork}()}, +\code{\link{get_spatial_enrichment}()}, +\code{\link{get_spatial_locations}()} +} +\concept{functions to get data from giotto object} +\concept{spatial enrichment data accessor functions} diff --git a/man/getSpatialGrid.Rd b/man/getSpatialGrid.Rd new file mode 100644 index 000000000..ce1ea3288 --- /dev/null +++ b/man/getSpatialGrid.Rd @@ -0,0 +1,62 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/accessors.R +\name{getSpatialGrid} +\alias{getSpatialGrid} +\title{Get spatial grid} +\usage{ +getSpatialGrid( + gobject, + spat_unit = NULL, + feat_type = NULL, + name = NULL, + return_grid_Obj = FALSE, + set_defaults = TRUE +) +} +\arguments{ +\item{gobject}{giotto object} + +\item{spat_unit}{spatial unit (e.g. "cell")} + +\item{feat_type}{feature type (e.g. "rna", "dna", "protein")} + +\item{name}{name of spatial grid} + +\item{return_grid_Obj}{return grid object (default = FALSE)} + +\item{set_defaults}{set default spat_unit and feat_type. Change to FALSE only when} +} +\description{ +Function to get spatial grid +} +\seealso{ +Other spatial grid data accessor functions: +\code{\link{get_spatialGrid}()}, +\code{\link{setSpatialGrid}()}, +\code{\link{set_spatialGrid}()} + +Other functions to get data from giotto object: +\code{\link{getDimReduction}()}, +\code{\link{getExpression}()}, +\code{\link{getFeatureInfo}()}, +\code{\link{getGiottoImage}()}, +\code{\link{getMultiomics}()}, +\code{\link{getNearestNetwork}()}, +\code{\link{getPolygonInfo}()}, +\code{\link{getSpatialEnrichment}()}, +\code{\link{getSpatialLocations}()}, +\code{\link{getSpatialNetwork}()}, +\code{\link{get_NearestNetwork}()}, +\code{\link{get_dimReduction}()}, +\code{\link{get_expression_values}()}, +\code{\link{get_feature_info}()}, +\code{\link{get_giottoImage}()}, +\code{\link{get_multiomics}()}, +\code{\link{get_polygon_info}()}, +\code{\link{get_spatialGrid}()}, +\code{\link{get_spatialNetwork}()}, +\code{\link{get_spatial_enrichment}()}, +\code{\link{get_spatial_locations}()} +} +\concept{functions to get data from giotto object} +\concept{spatial grid data accessor functions} diff --git a/man/getSpatialLocations.Rd b/man/getSpatialLocations.Rd new file mode 100644 index 000000000..e5c437b57 --- /dev/null +++ b/man/getSpatialLocations.Rd @@ -0,0 +1,69 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/accessors.R +\name{getSpatialLocations} +\alias{getSpatialLocations} +\title{Get spatial locations} +\usage{ +getSpatialLocations( + gobject, + spat_unit = NULL, + spat_loc_name = NULL, + output = c("spatLocsObj", "data.table"), + copy_obj = TRUE, + verbose = TRUE, + set_defaults = TRUE +) +} +\arguments{ +\item{gobject}{giotto object} + +\item{spat_unit}{spatial unit (e.g. "cell")} + +\item{spat_loc_name}{name of spatial locations (defaults to first name in spatial_locs slot, e.g. "raw")} + +\item{output}{what object type to get the spatial locations as. Default is as +a 'spatLocsObj'. Returning as 'data.table' is also possible.} + +\item{copy_obj}{whether to copy/duplicate when getting the object (default = TRUE)} + +\item{verbose}{be verbose} + +\item{set_defaults}{set default spat_unit and feat_type. Change to FALSE only when} +} +\value{ +data.table with coordinates or spatLocsObj depending on \code{output} +} +\description{ +Function to get a spatial location data.table +} +\seealso{ +Other spatial location data accessor functions: +\code{\link{get_spatial_locations}()}, +\code{\link{setSpatialLocations}()}, +\code{\link{set_spatial_locations}()} + +Other functions to get data from giotto object: +\code{\link{getDimReduction}()}, +\code{\link{getExpression}()}, +\code{\link{getFeatureInfo}()}, +\code{\link{getGiottoImage}()}, +\code{\link{getMultiomics}()}, +\code{\link{getNearestNetwork}()}, +\code{\link{getPolygonInfo}()}, +\code{\link{getSpatialEnrichment}()}, +\code{\link{getSpatialGrid}()}, +\code{\link{getSpatialNetwork}()}, +\code{\link{get_NearestNetwork}()}, +\code{\link{get_dimReduction}()}, +\code{\link{get_expression_values}()}, +\code{\link{get_feature_info}()}, +\code{\link{get_giottoImage}()}, +\code{\link{get_multiomics}()}, +\code{\link{get_polygon_info}()}, +\code{\link{get_spatialGrid}()}, +\code{\link{get_spatialNetwork}()}, +\code{\link{get_spatial_enrichment}()}, +\code{\link{get_spatial_locations}()} +} +\concept{functions to get data from giotto object} +\concept{spatial location data accessor functions} diff --git a/man/getSpatialNetwork.Rd b/man/getSpatialNetwork.Rd new file mode 100644 index 000000000..9b5a09ac4 --- /dev/null +++ b/man/getSpatialNetwork.Rd @@ -0,0 +1,66 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/accessors.R +\name{getSpatialNetwork} +\alias{getSpatialNetwork} +\title{Get spatial network} +\usage{ +getSpatialNetwork( + gobject, + spat_unit = NULL, + name = NULL, + output = c("spatialNetworkObj", "networkDT", "networkDT_before_filter", "outputObj"), + set_defaults = TRUE, + copy_obj = TRUE, + verbose = TRUE +) +} +\arguments{ +\item{gobject}{giotto object} + +\item{spat_unit}{spatial unit (e.g. "cell")} + +\item{name}{name of spatial network} + +\item{output}{object type to return as. Options: 'spatialNetworkObj' (default), +'networkDT' and 'networkDT_before_filter' for data.table outputs.} + +\item{set_defaults}{set default spat_unit and feat_type. Change to FALSE only when} + +\item{copy_obj}{whether to copy/duplicate when getting the object (default = TRUE)} + +\item{verbose}{be verbose} +} +\description{ +Function to get a spatial network +} +\seealso{ +Other spatial network data accessor functions: +\code{\link{get_spatialNetwork}()}, +\code{\link{setSpatialNetwork}()}, +\code{\link{set_spatialNetwork}()} + +Other functions to get data from giotto object: +\code{\link{getDimReduction}()}, +\code{\link{getExpression}()}, +\code{\link{getFeatureInfo}()}, +\code{\link{getGiottoImage}()}, +\code{\link{getMultiomics}()}, +\code{\link{getNearestNetwork}()}, +\code{\link{getPolygonInfo}()}, +\code{\link{getSpatialEnrichment}()}, +\code{\link{getSpatialGrid}()}, +\code{\link{getSpatialLocations}()}, +\code{\link{get_NearestNetwork}()}, +\code{\link{get_dimReduction}()}, +\code{\link{get_expression_values}()}, +\code{\link{get_feature_info}()}, +\code{\link{get_giottoImage}()}, +\code{\link{get_multiomics}()}, +\code{\link{get_polygon_info}()}, +\code{\link{get_spatialGrid}()}, +\code{\link{get_spatialNetwork}()}, +\code{\link{get_spatial_enrichment}()}, +\code{\link{get_spatial_locations}()} +} +\concept{functions to get data from giotto object} +\concept{spatial network data accessor functions} diff --git a/man/get_NearestNetwork.Rd b/man/get_NearestNetwork.Rd index eef6c5585..8e294fa10 100644 --- a/man/get_NearestNetwork.Rd +++ b/man/get_NearestNetwork.Rd @@ -37,9 +37,22 @@ Get a NN-network from a Giotto object } \seealso{ Other expression space nearest network accessor functions: +\code{\link{getNearestNetwork}()}, +\code{\link{setNearestNetwork}()}, \code{\link{set_NearestNetwork}()} Other functions to get data from giotto object: +\code{\link{getDimReduction}()}, +\code{\link{getExpression}()}, +\code{\link{getFeatureInfo}()}, +\code{\link{getGiottoImage}()}, +\code{\link{getMultiomics}()}, +\code{\link{getNearestNetwork}()}, +\code{\link{getPolygonInfo}()}, +\code{\link{getSpatialEnrichment}()}, +\code{\link{getSpatialGrid}()}, +\code{\link{getSpatialLocations}()}, +\code{\link{getSpatialNetwork}()}, \code{\link{get_dimReduction}()}, \code{\link{get_expression_values}()}, \code{\link{get_feature_info}()}, diff --git a/man/get_cell_id.Rd b/man/get_cell_id.Rd index 7496baa61..d7e09f253 100644 --- a/man/get_cell_id.Rd +++ b/man/get_cell_id.Rd @@ -27,6 +27,17 @@ set_cell_id Other functions to set data in giotto object: \code{\link{get_feat_id}()}, +\code{\link{setDimReduction}()}, +\code{\link{setExpression}()}, +\code{\link{setFeatureInfo}()}, +\code{\link{setGiottoImage}()}, +\code{\link{setMultiomics}()}, +\code{\link{setNearestNetwork}()}, +\code{\link{setPolygonInfo}()}, +\code{\link{setSpatialEnrichment}()}, +\code{\link{setSpatialGrid}()}, +\code{\link{setSpatialLocations}()}, +\code{\link{setSpatialNetwork}()}, \code{\link{set_NearestNetwork}()}, \code{\link{set_cell_id}()}, \code{\link{set_cell_metadata}()}, diff --git a/man/get_dimReduction.Rd b/man/get_dimReduction.Rd index c383a2310..60c8d568b 100644 --- a/man/get_dimReduction.Rd +++ b/man/get_dimReduction.Rd @@ -41,9 +41,22 @@ Function to get a dimension reduction object } \seealso{ Other dimensional reduction data accessor functions: +\code{\link{getDimReduction}()}, +\code{\link{setDimReduction}()}, \code{\link{set_dimReduction}()} Other functions to get data from giotto object: +\code{\link{getDimReduction}()}, +\code{\link{getExpression}()}, +\code{\link{getFeatureInfo}()}, +\code{\link{getGiottoImage}()}, +\code{\link{getMultiomics}()}, +\code{\link{getNearestNetwork}()}, +\code{\link{getPolygonInfo}()}, +\code{\link{getSpatialEnrichment}()}, +\code{\link{getSpatialGrid}()}, +\code{\link{getSpatialLocations}()}, +\code{\link{getSpatialNetwork}()}, \code{\link{get_NearestNetwork}()}, \code{\link{get_expression_values}()}, \code{\link{get_feature_info}()}, diff --git a/man/get_expression_values.Rd b/man/get_expression_values.Rd index 00b332610..ec6aa1809 100644 --- a/man/get_expression_values.Rd +++ b/man/get_expression_values.Rd @@ -36,9 +36,22 @@ Function to get expression values from giotto object } \seealso{ Other expression accessor functions: +\code{\link{getExpression}()}, +\code{\link{setExpression}()}, \code{\link{set_expression_values}()} Other functions to get data from giotto object: +\code{\link{getDimReduction}()}, +\code{\link{getExpression}()}, +\code{\link{getFeatureInfo}()}, +\code{\link{getGiottoImage}()}, +\code{\link{getMultiomics}()}, +\code{\link{getNearestNetwork}()}, +\code{\link{getPolygonInfo}()}, +\code{\link{getSpatialEnrichment}()}, +\code{\link{getSpatialGrid}()}, +\code{\link{getSpatialLocations}()}, +\code{\link{getSpatialNetwork}()}, \code{\link{get_NearestNetwork}()}, \code{\link{get_dimReduction}()}, \code{\link{get_feature_info}()}, diff --git a/man/get_feat_id.Rd b/man/get_feat_id.Rd index 5c19d2d22..3431dcf71 100644 --- a/man/get_feat_id.Rd +++ b/man/get_feat_id.Rd @@ -24,6 +24,17 @@ set_feat_id Other functions to set data in giotto object: \code{\link{get_cell_id}()}, +\code{\link{setDimReduction}()}, +\code{\link{setExpression}()}, +\code{\link{setFeatureInfo}()}, +\code{\link{setGiottoImage}()}, +\code{\link{setMultiomics}()}, +\code{\link{setNearestNetwork}()}, +\code{\link{setPolygonInfo}()}, +\code{\link{setSpatialEnrichment}()}, +\code{\link{setSpatialGrid}()}, +\code{\link{setSpatialLocations}()}, +\code{\link{setSpatialNetwork}()}, \code{\link{set_NearestNetwork}()}, \code{\link{set_cell_id}()}, \code{\link{set_cell_metadata}()}, diff --git a/man/get_feature_info.Rd b/man/get_feature_info.Rd index 7ec35ab55..1646e7daa 100644 --- a/man/get_feature_info.Rd +++ b/man/get_feature_info.Rd @@ -18,9 +18,22 @@ Get giotto points spatVector } \seealso{ Other feature info data accessor functions: +\code{\link{getFeatureInfo}()}, +\code{\link{setFeatureInfo}()}, \code{\link{set_feature_info}()} Other functions to get data from giotto object: +\code{\link{getDimReduction}()}, +\code{\link{getExpression}()}, +\code{\link{getFeatureInfo}()}, +\code{\link{getGiottoImage}()}, +\code{\link{getMultiomics}()}, +\code{\link{getNearestNetwork}()}, +\code{\link{getPolygonInfo}()}, +\code{\link{getSpatialEnrichment}()}, +\code{\link{getSpatialGrid}()}, +\code{\link{getSpatialLocations}()}, +\code{\link{getSpatialNetwork}()}, \code{\link{get_NearestNetwork}()}, \code{\link{get_dimReduction}()}, \code{\link{get_expression_values}()}, diff --git a/man/get_giottoImage.Rd b/man/get_giottoImage.Rd index c246355ed..0846aee7b 100644 --- a/man/get_giottoImage.Rd +++ b/man/get_giottoImage.Rd @@ -25,9 +25,22 @@ Get giotto image object from gobject } \seealso{ Other image data accessor functions: +\code{\link{getGiottoImage}()}, +\code{\link{setGiottoImage}()}, \code{\link{set_giottoImage}()} Other functions to get data from giotto object: +\code{\link{getDimReduction}()}, +\code{\link{getExpression}()}, +\code{\link{getFeatureInfo}()}, +\code{\link{getGiottoImage}()}, +\code{\link{getMultiomics}()}, +\code{\link{getNearestNetwork}()}, +\code{\link{getPolygonInfo}()}, +\code{\link{getSpatialEnrichment}()}, +\code{\link{getSpatialGrid}()}, +\code{\link{getSpatialLocations}()}, +\code{\link{getSpatialNetwork}()}, \code{\link{get_NearestNetwork}()}, \code{\link{get_dimReduction}()}, \code{\link{get_expression_values}()}, diff --git a/man/get_multiomics.Rd b/man/get_multiomics.Rd index b2ea389b5..ff80a910f 100644 --- a/man/get_multiomics.Rd +++ b/man/get_multiomics.Rd @@ -31,9 +31,22 @@ Get a multiomics integration result from a Giotto object } \seealso{ Other multiomics accessor functions: +\code{\link{getMultiomics}()}, +\code{\link{setMultiomics}()}, \code{\link{set_multiomics}()} Other functions to get data from giotto object: +\code{\link{getDimReduction}()}, +\code{\link{getExpression}()}, +\code{\link{getFeatureInfo}()}, +\code{\link{getGiottoImage}()}, +\code{\link{getMultiomics}()}, +\code{\link{getNearestNetwork}()}, +\code{\link{getPolygonInfo}()}, +\code{\link{getSpatialEnrichment}()}, +\code{\link{getSpatialGrid}()}, +\code{\link{getSpatialLocations}()}, +\code{\link{getSpatialNetwork}()}, \code{\link{get_NearestNetwork}()}, \code{\link{get_dimReduction}()}, \code{\link{get_expression_values}()}, diff --git a/man/get_polygon_info.Rd b/man/get_polygon_info.Rd index 50275afaf..89523e8fd 100644 --- a/man/get_polygon_info.Rd +++ b/man/get_polygon_info.Rd @@ -25,9 +25,22 @@ Get giotto polygon spatVector } \seealso{ Other polygon info data accessor functions: +\code{\link{getPolygonInfo}()}, +\code{\link{setPolygonInfo}()}, \code{\link{set_polygon_info}()} Other functions to get data from giotto object: +\code{\link{getDimReduction}()}, +\code{\link{getExpression}()}, +\code{\link{getFeatureInfo}()}, +\code{\link{getGiottoImage}()}, +\code{\link{getMultiomics}()}, +\code{\link{getNearestNetwork}()}, +\code{\link{getPolygonInfo}()}, +\code{\link{getSpatialEnrichment}()}, +\code{\link{getSpatialGrid}()}, +\code{\link{getSpatialLocations}()}, +\code{\link{getSpatialNetwork}()}, \code{\link{get_NearestNetwork}()}, \code{\link{get_dimReduction}()}, \code{\link{get_expression_values}()}, diff --git a/man/get_spatialGrid.Rd b/man/get_spatialGrid.Rd index fcb4a6136..2876e5ee5 100644 --- a/man/get_spatialGrid.Rd +++ b/man/get_spatialGrid.Rd @@ -31,9 +31,22 @@ Function to get spatial grid } \seealso{ Other spatial grid data accessor functions: +\code{\link{getSpatialGrid}()}, +\code{\link{setSpatialGrid}()}, \code{\link{set_spatialGrid}()} Other functions to get data from giotto object: +\code{\link{getDimReduction}()}, +\code{\link{getExpression}()}, +\code{\link{getFeatureInfo}()}, +\code{\link{getGiottoImage}()}, +\code{\link{getMultiomics}()}, +\code{\link{getNearestNetwork}()}, +\code{\link{getPolygonInfo}()}, +\code{\link{getSpatialEnrichment}()}, +\code{\link{getSpatialGrid}()}, +\code{\link{getSpatialLocations}()}, +\code{\link{getSpatialNetwork}()}, \code{\link{get_NearestNetwork}()}, \code{\link{get_dimReduction}()}, \code{\link{get_expression_values}()}, diff --git a/man/get_spatialNetwork.Rd b/man/get_spatialNetwork.Rd index 57f5943f5..2ad3789dd 100644 --- a/man/get_spatialNetwork.Rd +++ b/man/get_spatialNetwork.Rd @@ -35,9 +35,22 @@ Function to get a spatial network } \seealso{ Other spatial network data accessor functions: +\code{\link{getSpatialNetwork}()}, +\code{\link{setSpatialNetwork}()}, \code{\link{set_spatialNetwork}()} Other functions to get data from giotto object: +\code{\link{getDimReduction}()}, +\code{\link{getExpression}()}, +\code{\link{getFeatureInfo}()}, +\code{\link{getGiottoImage}()}, +\code{\link{getMultiomics}()}, +\code{\link{getNearestNetwork}()}, +\code{\link{getPolygonInfo}()}, +\code{\link{getSpatialEnrichment}()}, +\code{\link{getSpatialGrid}()}, +\code{\link{getSpatialLocations}()}, +\code{\link{getSpatialNetwork}()}, \code{\link{get_NearestNetwork}()}, \code{\link{get_dimReduction}()}, \code{\link{get_expression_values}()}, diff --git a/man/get_spatial_enrichment.Rd b/man/get_spatial_enrichment.Rd index b26d30d4e..77b0b2a42 100644 --- a/man/get_spatial_enrichment.Rd +++ b/man/get_spatial_enrichment.Rd @@ -38,9 +38,22 @@ Function to get a spatial enrichment data.table } \seealso{ Other spatial enrichment data accessor functions: +\code{\link{getSpatialEnrichment}()}, +\code{\link{setSpatialEnrichment}()}, \code{\link{set_spatial_enrichment}()} Other functions to get data from giotto object: +\code{\link{getDimReduction}()}, +\code{\link{getExpression}()}, +\code{\link{getFeatureInfo}()}, +\code{\link{getGiottoImage}()}, +\code{\link{getMultiomics}()}, +\code{\link{getNearestNetwork}()}, +\code{\link{getPolygonInfo}()}, +\code{\link{getSpatialEnrichment}()}, +\code{\link{getSpatialGrid}()}, +\code{\link{getSpatialLocations}()}, +\code{\link{getSpatialNetwork}()}, \code{\link{get_NearestNetwork}()}, \code{\link{get_dimReduction}()}, \code{\link{get_expression_values}()}, diff --git a/man/get_spatial_locations.Rd b/man/get_spatial_locations.Rd index 84d28c6dd..b8d433243 100644 --- a/man/get_spatial_locations.Rd +++ b/man/get_spatial_locations.Rd @@ -38,9 +38,22 @@ Function to get a spatial location data.table } \seealso{ Other spatial location data accessor functions: +\code{\link{getSpatialLocations}()}, +\code{\link{setSpatialLocations}()}, \code{\link{set_spatial_locations}()} Other functions to get data from giotto object: +\code{\link{getDimReduction}()}, +\code{\link{getExpression}()}, +\code{\link{getFeatureInfo}()}, +\code{\link{getGiottoImage}()}, +\code{\link{getMultiomics}()}, +\code{\link{getNearestNetwork}()}, +\code{\link{getPolygonInfo}()}, +\code{\link{getSpatialEnrichment}()}, +\code{\link{getSpatialGrid}()}, +\code{\link{getSpatialLocations}()}, +\code{\link{getSpatialNetwork}()}, \code{\link{get_NearestNetwork}()}, \code{\link{get_dimReduction}()}, \code{\link{get_expression_values}()}, diff --git a/man/load_merscope_folder.Rd b/man/load_merscope_folder.Rd index 03938691f..56292bfea 100644 --- a/man/load_merscope_folder.Rd +++ b/man/load_merscope_folder.Rd @@ -10,6 +10,7 @@ load_merscope_folder( dir_items, data_to_use, fovs = NULL, + poly_z_indices = 1L:7L, cores = NA, verbose = TRUE ) @@ -18,6 +19,7 @@ load_merscope_folder_subcellular( dir_items, data_to_use, cores = NA, + poly_z_indices = 1L:7L, verbose = TRUE, fovs = NULL ) diff --git a/man/setDimReduction.Rd b/man/setDimReduction.Rd new file mode 100644 index 000000000..4648a2035 --- /dev/null +++ b/man/setDimReduction.Rd @@ -0,0 +1,83 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/accessors.R +\name{setDimReduction} +\alias{setDimReduction} +\title{Set dimension reduction} +\usage{ +setDimReduction( + gobject, + dimObject, + spat_unit = NULL, + feat_type = NULL, + reduction = c("cells", "genes"), + reduction_method = c("pca", "umap", "tsne"), + name = "pca", + provenance = NULL, + verbose = TRUE, + set_defaults = TRUE +) +} +\arguments{ +\item{gobject}{giotto object} + +\item{dimObject}{dimension object result to set} + +\item{spat_unit}{spatial unit (e.g. "cell")} + +\item{feat_type}{feature type (e.g. "rna", "dna", "protein")} + +\item{reduction}{reduction on cells or features} + +\item{reduction_method}{reduction method (e.g. "pca")} + +\item{name}{name of reduction results} + +\item{provenance}{provenance information (optional)} + +\item{verbose}{be verbose} + +\item{set_defaults}{set default spat_unit and feat_type. Change to FALSE only when} +} +\value{ +giotto object +} +\description{ +Function to set a dimension reduction slot +} +\seealso{ +Other dimensional reduction data accessor functions: +\code{\link{getDimReduction}()}, +\code{\link{get_dimReduction}()}, +\code{\link{set_dimReduction}()} + +Other functions to set data in giotto object: +\code{\link{get_cell_id}()}, +\code{\link{get_feat_id}()}, +\code{\link{setExpression}()}, +\code{\link{setFeatureInfo}()}, +\code{\link{setGiottoImage}()}, +\code{\link{setMultiomics}()}, +\code{\link{setNearestNetwork}()}, +\code{\link{setPolygonInfo}()}, +\code{\link{setSpatialEnrichment}()}, +\code{\link{setSpatialGrid}()}, +\code{\link{setSpatialLocations}()}, +\code{\link{setSpatialNetwork}()}, +\code{\link{set_NearestNetwork}()}, +\code{\link{set_cell_id}()}, +\code{\link{set_cell_metadata}()}, +\code{\link{set_dimReduction}()}, +\code{\link{set_expression_values}()}, +\code{\link{set_feat_id}()}, +\code{\link{set_feature_info}()}, +\code{\link{set_feature_metadata}()}, +\code{\link{set_giottoImage}()}, +\code{\link{set_multiomics}()}, +\code{\link{set_polygon_info}()}, +\code{\link{set_spatialGrid}()}, +\code{\link{set_spatialNetwork}()}, +\code{\link{set_spatial_enrichment}()}, +\code{\link{set_spatial_locations}()} +} +\concept{dimensional reduction data accessor functions} +\concept{functions to set data in giotto object} diff --git a/man/setExpression.Rd b/man/setExpression.Rd new file mode 100644 index 000000000..d1499ec2f --- /dev/null +++ b/man/setExpression.Rd @@ -0,0 +1,84 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/accessors.R +\name{setExpression} +\alias{setExpression} +\title{Set expression values} +\usage{ +setExpression( + gobject, + values, + spat_unit = NULL, + feat_type = NULL, + name = "test", + provenance = NULL, + verbose = TRUE, + set_defaults = TRUE +) +} +\arguments{ +\item{gobject}{giotto object} + +\item{values}{exprObj or matrix of expression values. If NULL, then the object +will be removed.} + +\item{spat_unit}{spatial unit (e.g. "cell")} + +\item{feat_type}{feature type (e.g. "rna", "dna", "protein")} + +\item{name}{name for the expression slot} + +\item{provenance}{provenance information (optional)} + +\item{verbose}{be verbose} + +\item{set_defaults}{set default spat_unit and feat_type. Change to FALSE only when} +} +\value{ +giotto object +} +\description{ +Function to set expression values for giotto object +} +\details{ +If cell_ID, feat_ID, cell_metadata, or feat_metadata objects have not +been initialized yet, they will be initialized by this function. Note that +initialization based on feature info or spatial info is preferred if they exist +for this spatial unit and feature type. +} +\seealso{ +Other expression accessor functions: +\code{\link{getExpression}()}, +\code{\link{get_expression_values}()}, +\code{\link{set_expression_values}()} + +Other functions to set data in giotto object: +\code{\link{get_cell_id}()}, +\code{\link{get_feat_id}()}, +\code{\link{setDimReduction}()}, +\code{\link{setFeatureInfo}()}, +\code{\link{setGiottoImage}()}, +\code{\link{setMultiomics}()}, +\code{\link{setNearestNetwork}()}, +\code{\link{setPolygonInfo}()}, +\code{\link{setSpatialEnrichment}()}, +\code{\link{setSpatialGrid}()}, +\code{\link{setSpatialLocations}()}, +\code{\link{setSpatialNetwork}()}, +\code{\link{set_NearestNetwork}()}, +\code{\link{set_cell_id}()}, +\code{\link{set_cell_metadata}()}, +\code{\link{set_dimReduction}()}, +\code{\link{set_expression_values}()}, +\code{\link{set_feat_id}()}, +\code{\link{set_feature_info}()}, +\code{\link{set_feature_metadata}()}, +\code{\link{set_giottoImage}()}, +\code{\link{set_multiomics}()}, +\code{\link{set_polygon_info}()}, +\code{\link{set_spatialGrid}()}, +\code{\link{set_spatialNetwork}()}, +\code{\link{set_spatial_enrichment}()}, +\code{\link{set_spatial_locations}()} +} +\concept{expression accessor functions} +\concept{functions to set data in giotto object} diff --git a/man/setFeatureInfo.Rd b/man/setFeatureInfo.Rd new file mode 100644 index 000000000..ceb99e10c --- /dev/null +++ b/man/setFeatureInfo.Rd @@ -0,0 +1,60 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/accessors.R +\name{setFeatureInfo} +\alias{setFeatureInfo} +\title{Set feature info} +\usage{ +setFeatureInfo(gobject = NULL, gpoints, feat_type = NULL, verbose = TRUE) +} +\arguments{ +\item{gobject}{giotto object} + +\item{gpoints}{giotto points object} + +\item{feat_type}{feature type (e.g. "rna", "dna", "protein")} + +\item{verbose}{be verbose} +} +\value{ +giotto object +} +\description{ +Set giotto polygon spatVector for features +} +\seealso{ +Other feature info data accessor functions: +\code{\link{getFeatureInfo}()}, +\code{\link{get_feature_info}()}, +\code{\link{set_feature_info}()} + +Other functions to set data in giotto object: +\code{\link{get_cell_id}()}, +\code{\link{get_feat_id}()}, +\code{\link{setDimReduction}()}, +\code{\link{setExpression}()}, +\code{\link{setGiottoImage}()}, +\code{\link{setMultiomics}()}, +\code{\link{setNearestNetwork}()}, +\code{\link{setPolygonInfo}()}, +\code{\link{setSpatialEnrichment}()}, +\code{\link{setSpatialGrid}()}, +\code{\link{setSpatialLocations}()}, +\code{\link{setSpatialNetwork}()}, +\code{\link{set_NearestNetwork}()}, +\code{\link{set_cell_id}()}, +\code{\link{set_cell_metadata}()}, +\code{\link{set_dimReduction}()}, +\code{\link{set_expression_values}()}, +\code{\link{set_feat_id}()}, +\code{\link{set_feature_info}()}, +\code{\link{set_feature_metadata}()}, +\code{\link{set_giottoImage}()}, +\code{\link{set_multiomics}()}, +\code{\link{set_polygon_info}()}, +\code{\link{set_spatialGrid}()}, +\code{\link{set_spatialNetwork}()}, +\code{\link{set_spatial_enrichment}()}, +\code{\link{set_spatial_locations}()} +} +\concept{feature info data accessor functions} +\concept{functions to set data in giotto object} diff --git a/man/setGiottoImage.Rd b/man/setGiottoImage.Rd new file mode 100644 index 000000000..a560c13c5 --- /dev/null +++ b/man/setGiottoImage.Rd @@ -0,0 +1,78 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/accessors.R +\name{setGiottoImage} +\alias{setGiottoImage} +\title{Set giotto image object} +\usage{ +setGiottoImage( + gobject = NULL, + image = NULL, + image_type = NULL, + name = NULL, + verbose = TRUE +) +} +\arguments{ +\item{gobject}{giotto object} + +\item{image}{giotto image object to be attached without modification to the +giotto object} + +\item{image_type}{type of giotto image object. Either "image" or "largeImage"} + +\item{name}{name of giotto image object} + +\item{verbose}{be verbose} +} +\value{ +giotto object +} +\description{ +Directly attach a giotto image to giotto object +} +\details{ +\emph{\strong{Use with care!}} This function directly attaches giotto image + objects to the gobject without further modifications of spatial positioning values + within the image object that are generally needed in order for them to + plot in the correct location relative to the other modalities of spatial data. \cr + For the more general-purpose method of attaching image objects, see \code{\link{addGiottoImage}} +} +\seealso{ +\code{\link{addGiottoImage}} + +Other image data accessor functions: +\code{\link{getGiottoImage}()}, +\code{\link{get_giottoImage}()}, +\code{\link{set_giottoImage}()} + +Other functions to set data in giotto object: +\code{\link{get_cell_id}()}, +\code{\link{get_feat_id}()}, +\code{\link{setDimReduction}()}, +\code{\link{setExpression}()}, +\code{\link{setFeatureInfo}()}, +\code{\link{setMultiomics}()}, +\code{\link{setNearestNetwork}()}, +\code{\link{setPolygonInfo}()}, +\code{\link{setSpatialEnrichment}()}, +\code{\link{setSpatialGrid}()}, +\code{\link{setSpatialLocations}()}, +\code{\link{setSpatialNetwork}()}, +\code{\link{set_NearestNetwork}()}, +\code{\link{set_cell_id}()}, +\code{\link{set_cell_metadata}()}, +\code{\link{set_dimReduction}()}, +\code{\link{set_expression_values}()}, +\code{\link{set_feat_id}()}, +\code{\link{set_feature_info}()}, +\code{\link{set_feature_metadata}()}, +\code{\link{set_giottoImage}()}, +\code{\link{set_multiomics}()}, +\code{\link{set_polygon_info}()}, +\code{\link{set_spatialGrid}()}, +\code{\link{set_spatialNetwork}()}, +\code{\link{set_spatial_enrichment}()}, +\code{\link{set_spatial_locations}()} +} +\concept{functions to set data in giotto object} +\concept{image data accessor functions} diff --git a/man/setMultiomics.Rd b/man/setMultiomics.Rd new file mode 100644 index 000000000..7dc87632c --- /dev/null +++ b/man/setMultiomics.Rd @@ -0,0 +1,74 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/wnn.R +\name{setMultiomics} +\alias{setMultiomics} +\title{Set multiomics integration results} +\usage{ +setMultiomics( + gobject = NULL, + result, + spat_unit = NULL, + feat_type = NULL, + integration_method = "WNN", + result_name = "theta_weighted_matrix", + verbose = TRUE +) +} +\arguments{ +\item{gobject}{A Giotto object} + +\item{result}{A matrix or result from multiomics integration (e.g. theta weighted values from runWNN)} + +\item{spat_unit}{spatial unit (e.g. 'cell')} + +\item{feat_type}{(e.g. 'rna_protein')} + +\item{integration_method}{multiomics integration method used. Default = 'WNN'} + +\item{result_name}{Default = 'theta_weighted_matrix'} + +\item{verbose}{be verbose} +} +\value{ +A giotto object +} +\description{ +Set a multiomics integration result in a Giotto object +} +\seealso{ +Other multiomics accessor functions: +\code{\link{getMultiomics}()}, +\code{\link{get_multiomics}()}, +\code{\link{set_multiomics}()} + +Other functions to set data in giotto object: +\code{\link{get_cell_id}()}, +\code{\link{get_feat_id}()}, +\code{\link{setDimReduction}()}, +\code{\link{setExpression}()}, +\code{\link{setFeatureInfo}()}, +\code{\link{setGiottoImage}()}, +\code{\link{setNearestNetwork}()}, +\code{\link{setPolygonInfo}()}, +\code{\link{setSpatialEnrichment}()}, +\code{\link{setSpatialGrid}()}, +\code{\link{setSpatialLocations}()}, +\code{\link{setSpatialNetwork}()}, +\code{\link{set_NearestNetwork}()}, +\code{\link{set_cell_id}()}, +\code{\link{set_cell_metadata}()}, +\code{\link{set_dimReduction}()}, +\code{\link{set_expression_values}()}, +\code{\link{set_feat_id}()}, +\code{\link{set_feature_info}()}, +\code{\link{set_feature_metadata}()}, +\code{\link{set_giottoImage}()}, +\code{\link{set_multiomics}()}, +\code{\link{set_polygon_info}()}, +\code{\link{set_spatialGrid}()}, +\code{\link{set_spatialNetwork}()}, +\code{\link{set_spatial_enrichment}()}, +\code{\link{set_spatial_locations}()} +} +\concept{functions to set data in giotto object} +\concept{multiomics accessor functions} diff --git a/man/setNearestNetwork.Rd b/man/setNearestNetwork.Rd new file mode 100644 index 000000000..518b3dbf2 --- /dev/null +++ b/man/setNearestNetwork.Rd @@ -0,0 +1,81 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/accessors.R +\name{setNearestNetwork} +\alias{setNearestNetwork} +\title{Set nearest neighbor network} +\usage{ +setNearestNetwork( + gobject, + nn_network, + spat_unit = NULL, + feat_type = NULL, + nn_network_to_use = "sNN", + network_name = "sNN.pca", + provenance = NULL, + verbose = TRUE, + set_defaults = TRUE +) +} +\arguments{ +\item{gobject}{giotto object} + +\item{nn_network}{nnNetObj or igraph nearest network object. Data.table not +yet supported.} + +\item{spat_unit}{spatial unit (e.g. "cell")} + +\item{feat_type}{feature type (e.g. "rna", "dna", "protein")} + +\item{nn_network_to_use}{"kNN" or "sNN"} + +\item{network_name}{name of NN network to be used} + +\item{provenance}{provenance information (optional)} + +\item{verbose}{be verbose} + +\item{set_defaults}{set default spat_unit and feat_type. Change to FALSE only when} +} +\value{ +giotto object +} +\description{ +Set a NN-network for a Giotto object +} +\seealso{ +Other expression space nearest network accessor functions: +\code{\link{getNearestNetwork}()}, +\code{\link{get_NearestNetwork}()}, +\code{\link{set_NearestNetwork}()} + +Other functions to set data in giotto object: +\code{\link{get_cell_id}()}, +\code{\link{get_feat_id}()}, +\code{\link{setDimReduction}()}, +\code{\link{setExpression}()}, +\code{\link{setFeatureInfo}()}, +\code{\link{setGiottoImage}()}, +\code{\link{setMultiomics}()}, +\code{\link{setPolygonInfo}()}, +\code{\link{setSpatialEnrichment}()}, +\code{\link{setSpatialGrid}()}, +\code{\link{setSpatialLocations}()}, +\code{\link{setSpatialNetwork}()}, +\code{\link{set_NearestNetwork}()}, +\code{\link{set_cell_id}()}, +\code{\link{set_cell_metadata}()}, +\code{\link{set_dimReduction}()}, +\code{\link{set_expression_values}()}, +\code{\link{set_feat_id}()}, +\code{\link{set_feature_info}()}, +\code{\link{set_feature_metadata}()}, +\code{\link{set_giottoImage}()}, +\code{\link{set_multiomics}()}, +\code{\link{set_polygon_info}()}, +\code{\link{set_spatialGrid}()}, +\code{\link{set_spatialNetwork}()}, +\code{\link{set_spatial_enrichment}()}, +\code{\link{set_spatial_locations}()} +} +\concept{expression space nearest network accessor functions} +\concept{functions to set data in giotto object} diff --git a/man/setPolygonInfo.Rd b/man/setPolygonInfo.Rd new file mode 100644 index 000000000..4c23ede6c --- /dev/null +++ b/man/setPolygonInfo.Rd @@ -0,0 +1,65 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/accessors.R +\name{setPolygonInfo} +\alias{setPolygonInfo} +\title{Set polygon info} +\usage{ +setPolygonInfo( + gobject = NULL, + polygon_name = "cell", + gpolygon = NULL, + verbose = TRUE +) +} +\arguments{ +\item{gobject}{giotto object} + +\item{polygon_name}{name of polygons. Default "cell"} + +\item{gpolygon}{giotto polygon} + +\item{verbose}{verbosity} +} +\value{ +giotto object +} +\description{ +Set giotto polygon spatVector +} +\seealso{ +Other polygon info data accessor functions: +\code{\link{getPolygonInfo}()}, +\code{\link{get_polygon_info}()}, +\code{\link{set_polygon_info}()} + +Other functions to set data in giotto object: +\code{\link{get_cell_id}()}, +\code{\link{get_feat_id}()}, +\code{\link{setDimReduction}()}, +\code{\link{setExpression}()}, +\code{\link{setFeatureInfo}()}, +\code{\link{setGiottoImage}()}, +\code{\link{setMultiomics}()}, +\code{\link{setNearestNetwork}()}, +\code{\link{setSpatialEnrichment}()}, +\code{\link{setSpatialGrid}()}, +\code{\link{setSpatialLocations}()}, +\code{\link{setSpatialNetwork}()}, +\code{\link{set_NearestNetwork}()}, +\code{\link{set_cell_id}()}, +\code{\link{set_cell_metadata}()}, +\code{\link{set_dimReduction}()}, +\code{\link{set_expression_values}()}, +\code{\link{set_feat_id}()}, +\code{\link{set_feature_info}()}, +\code{\link{set_feature_metadata}()}, +\code{\link{set_giottoImage}()}, +\code{\link{set_multiomics}()}, +\code{\link{set_polygon_info}()}, +\code{\link{set_spatialGrid}()}, +\code{\link{set_spatialNetwork}()}, +\code{\link{set_spatial_enrichment}()}, +\code{\link{set_spatial_locations}()} +} +\concept{functions to set data in giotto object} +\concept{polygon info data accessor functions} diff --git a/man/setSpatialEnrichment.Rd b/man/setSpatialEnrichment.Rd new file mode 100644 index 000000000..aa6acfbd9 --- /dev/null +++ b/man/setSpatialEnrichment.Rd @@ -0,0 +1,74 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/accessors.R +\name{setSpatialEnrichment} +\alias{setSpatialEnrichment} +\title{Set spatial enrichment} +\usage{ +setSpatialEnrichment( + gobject, + spatenrichment, + spat_unit = NULL, + feat_type = NULL, + enrichm_name = "enrichment", + verbose = TRUE, + set_defaults = TRUE +) +} +\arguments{ +\item{gobject}{giotto object} + +\item{spatenrichment}{spatial enrichment results} + +\item{spat_unit}{spatial unit (e.g. "cell")} + +\item{feat_type}{feature type (e.g. "rna", "dna", "protein")} + +\item{enrichm_name}{name of spatial enrichment results. Default "DWLS"} + +\item{verbose}{be verbose} + +\item{set_defaults}{set default spat_unit and feat_type. Change to FALSE only when} +} +\value{ +giotto object +} +\description{ +Function to set a spatial enrichment slot +} +\seealso{ +Other spatial enrichment data accessor functions: +\code{\link{getSpatialEnrichment}()}, +\code{\link{get_spatial_enrichment}()}, +\code{\link{set_spatial_enrichment}()} + +Other functions to set data in giotto object: +\code{\link{get_cell_id}()}, +\code{\link{get_feat_id}()}, +\code{\link{setDimReduction}()}, +\code{\link{setExpression}()}, +\code{\link{setFeatureInfo}()}, +\code{\link{setGiottoImage}()}, +\code{\link{setMultiomics}()}, +\code{\link{setNearestNetwork}()}, +\code{\link{setPolygonInfo}()}, +\code{\link{setSpatialGrid}()}, +\code{\link{setSpatialLocations}()}, +\code{\link{setSpatialNetwork}()}, +\code{\link{set_NearestNetwork}()}, +\code{\link{set_cell_id}()}, +\code{\link{set_cell_metadata}()}, +\code{\link{set_dimReduction}()}, +\code{\link{set_expression_values}()}, +\code{\link{set_feat_id}()}, +\code{\link{set_feature_info}()}, +\code{\link{set_feature_metadata}()}, +\code{\link{set_giottoImage}()}, +\code{\link{set_multiomics}()}, +\code{\link{set_polygon_info}()}, +\code{\link{set_spatialGrid}()}, +\code{\link{set_spatialNetwork}()}, +\code{\link{set_spatial_enrichment}()}, +\code{\link{set_spatial_locations}()} +} +\concept{functions to set data in giotto object} +\concept{spatial enrichment data accessor functions} diff --git a/man/setSpatialGrid.Rd b/man/setSpatialGrid.Rd new file mode 100644 index 000000000..60dbc2066 --- /dev/null +++ b/man/setSpatialGrid.Rd @@ -0,0 +1,74 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/accessors.R +\name{setSpatialGrid} +\alias{setSpatialGrid} +\title{Set spatial grid} +\usage{ +setSpatialGrid( + gobject, + spatial_grid, + spat_unit = NULL, + feat_type = NULL, + name = NULL, + verbose = TRUE, + set_defaults = TRUE +) +} +\arguments{ +\item{gobject}{giotto object} + +\item{spatial_grid}{spatial grid object} + +\item{spat_unit}{spatial unit (e.g. "cell")} + +\item{feat_type}{feature type (e.g. "rna", "dna", "protein")} + +\item{name}{name of spatial grid} + +\item{verbose}{be verbose} + +\item{set_defaults}{set default spat_unit and feat_type. Change to FALSE only when} +} +\value{ +giotto object +} +\description{ +Function to set a spatial grid +} +\seealso{ +Other spatial grid data accessor functions: +\code{\link{getSpatialGrid}()}, +\code{\link{get_spatialGrid}()}, +\code{\link{set_spatialGrid}()} + +Other functions to set data in giotto object: +\code{\link{get_cell_id}()}, +\code{\link{get_feat_id}()}, +\code{\link{setDimReduction}()}, +\code{\link{setExpression}()}, +\code{\link{setFeatureInfo}()}, +\code{\link{setGiottoImage}()}, +\code{\link{setMultiomics}()}, +\code{\link{setNearestNetwork}()}, +\code{\link{setPolygonInfo}()}, +\code{\link{setSpatialEnrichment}()}, +\code{\link{setSpatialLocations}()}, +\code{\link{setSpatialNetwork}()}, +\code{\link{set_NearestNetwork}()}, +\code{\link{set_cell_id}()}, +\code{\link{set_cell_metadata}()}, +\code{\link{set_dimReduction}()}, +\code{\link{set_expression_values}()}, +\code{\link{set_feat_id}()}, +\code{\link{set_feature_info}()}, +\code{\link{set_feature_metadata}()}, +\code{\link{set_giottoImage}()}, +\code{\link{set_multiomics}()}, +\code{\link{set_polygon_info}()}, +\code{\link{set_spatialGrid}()}, +\code{\link{set_spatialNetwork}()}, +\code{\link{set_spatial_enrichment}()}, +\code{\link{set_spatial_locations}()} +} +\concept{functions to set data in giotto object} +\concept{spatial grid data accessor functions} diff --git a/man/setSpatialLocations.Rd b/man/setSpatialLocations.Rd new file mode 100644 index 000000000..a067c47f6 --- /dev/null +++ b/man/setSpatialLocations.Rd @@ -0,0 +1,86 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/accessors.R +\name{setSpatialLocations} +\alias{setSpatialLocations} +\title{Set spatial locations} +\usage{ +setSpatialLocations( + gobject, + spatlocs, + spat_unit = NULL, + spat_loc_name = "raw", + provenance = NULL, + verbose = TRUE, + set_defaults = TRUE +) +} +\arguments{ +\item{gobject}{giotto object} + +\item{spatlocs}{spatial locations (accepts either \code{data.table} or +\code{spatLocsObj})} + +\item{spat_unit}{spatial unit (e.g. "cell")} + +\item{spat_loc_name}{name of spatial locations, default "raw"} + +\item{provenance}{provenance information (optional)} + +\item{verbose}{be verbose} + +\item{set_defaults}{set default spat_unit and feat_type. Change to FALSE only when} +} +\value{ +giotto object +} +\description{ +Function to set a spatial location slot +} +\details{ +If a \code{spatLocsObj} is provided to \code{spatlocs} param then any +attached name and spat_unit info will be used for input to this function's +\code{spat_loc_name} and \code{spat_unit}params, BUT will be overridden by any +alternative specific inputs to those params. \cr +ie: a \code{spatLocsObj} with spat_unit slot == 'cell' will be automatically +nested by spat_unit 'cell' when using \code{setSpatialLocations} as long as +param \code{spat_unit = NULL}. BUT if param \code{spat_unit = 'nucleus'} then +the \code{spatLocsObj} will be nested by spat_unit 'nucleus' instead and +its spat_unit slot will be changed to 'nucleus' +} +\seealso{ +Other spatial location data accessor functions: +\code{\link{getSpatialLocations}()}, +\code{\link{get_spatial_locations}()}, +\code{\link{set_spatial_locations}()} + +Other functions to set data in giotto object: +\code{\link{get_cell_id}()}, +\code{\link{get_feat_id}()}, +\code{\link{setDimReduction}()}, +\code{\link{setExpression}()}, +\code{\link{setFeatureInfo}()}, +\code{\link{setGiottoImage}()}, +\code{\link{setMultiomics}()}, +\code{\link{setNearestNetwork}()}, +\code{\link{setPolygonInfo}()}, +\code{\link{setSpatialEnrichment}()}, +\code{\link{setSpatialGrid}()}, +\code{\link{setSpatialNetwork}()}, +\code{\link{set_NearestNetwork}()}, +\code{\link{set_cell_id}()}, +\code{\link{set_cell_metadata}()}, +\code{\link{set_dimReduction}()}, +\code{\link{set_expression_values}()}, +\code{\link{set_feat_id}()}, +\code{\link{set_feature_info}()}, +\code{\link{set_feature_metadata}()}, +\code{\link{set_giottoImage}()}, +\code{\link{set_multiomics}()}, +\code{\link{set_polygon_info}()}, +\code{\link{set_spatialGrid}()}, +\code{\link{set_spatialNetwork}()}, +\code{\link{set_spatial_enrichment}()}, +\code{\link{set_spatial_locations}()} +} +\concept{functions to set data in giotto object} +\concept{spatial location data accessor functions} diff --git a/man/setSpatialNetwork.Rd b/man/setSpatialNetwork.Rd new file mode 100644 index 000000000..65aabf1da --- /dev/null +++ b/man/setSpatialNetwork.Rd @@ -0,0 +1,72 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/accessors.R +\name{setSpatialNetwork} +\alias{setSpatialNetwork} +\title{Set spatial network} +\usage{ +setSpatialNetwork( + gobject, + spatial_network, + spat_unit = NULL, + name = NULL, + provenance = NULL, + verbose = TRUE, + set_defaults = TRUE +) +} +\arguments{ +\item{gobject}{giotto object} + +\item{spatial_network}{spatial network} + +\item{spat_unit}{spatial unit (e.g. "cell")} + +\item{name}{name of spatial network} + +\item{verbose}{be verbose} + +\item{set_defaults}{set default spat_unit and feat_type. Change to FALSE only when} +} +\value{ +giotto object +} +\description{ +Function to set a spatial network +} +\seealso{ +Other spatial network data accessor functions: +\code{\link{getSpatialNetwork}()}, +\code{\link{get_spatialNetwork}()}, +\code{\link{set_spatialNetwork}()} + +Other functions to set data in giotto object: +\code{\link{get_cell_id}()}, +\code{\link{get_feat_id}()}, +\code{\link{setDimReduction}()}, +\code{\link{setExpression}()}, +\code{\link{setFeatureInfo}()}, +\code{\link{setGiottoImage}()}, +\code{\link{setMultiomics}()}, +\code{\link{setNearestNetwork}()}, +\code{\link{setPolygonInfo}()}, +\code{\link{setSpatialEnrichment}()}, +\code{\link{setSpatialGrid}()}, +\code{\link{setSpatialLocations}()}, +\code{\link{set_NearestNetwork}()}, +\code{\link{set_cell_id}()}, +\code{\link{set_cell_metadata}()}, +\code{\link{set_dimReduction}()}, +\code{\link{set_expression_values}()}, +\code{\link{set_feat_id}()}, +\code{\link{set_feature_info}()}, +\code{\link{set_feature_metadata}()}, +\code{\link{set_giottoImage}()}, +\code{\link{set_multiomics}()}, +\code{\link{set_polygon_info}()}, +\code{\link{set_spatialGrid}()}, +\code{\link{set_spatialNetwork}()}, +\code{\link{set_spatial_enrichment}()}, +\code{\link{set_spatial_locations}()} +} +\concept{functions to set data in giotto object} +\concept{spatial network data accessor functions} diff --git a/man/set_NearestNetwork.Rd b/man/set_NearestNetwork.Rd index df25d5fef..11df3b2e5 100644 --- a/man/set_NearestNetwork.Rd +++ b/man/set_NearestNetwork.Rd @@ -44,11 +44,24 @@ Set a NN-network for a Giotto object } \seealso{ Other expression space nearest network accessor functions: -\code{\link{get_NearestNetwork}()} +\code{\link{getNearestNetwork}()}, +\code{\link{get_NearestNetwork}()}, +\code{\link{setNearestNetwork}()} Other functions to set data in giotto object: \code{\link{get_cell_id}()}, \code{\link{get_feat_id}()}, +\code{\link{setDimReduction}()}, +\code{\link{setExpression}()}, +\code{\link{setFeatureInfo}()}, +\code{\link{setGiottoImage}()}, +\code{\link{setMultiomics}()}, +\code{\link{setNearestNetwork}()}, +\code{\link{setPolygonInfo}()}, +\code{\link{setSpatialEnrichment}()}, +\code{\link{setSpatialGrid}()}, +\code{\link{setSpatialLocations}()}, +\code{\link{setSpatialNetwork}()}, \code{\link{set_cell_id}()}, \code{\link{set_cell_metadata}()}, \code{\link{set_dimReduction}()}, diff --git a/man/set_cell_id.Rd b/man/set_cell_id.Rd index 5dcec625c..57e20176d 100644 --- a/man/set_cell_id.Rd +++ b/man/set_cell_id.Rd @@ -11,7 +11,9 @@ set_cell_id(gobject, spat_unit = NULL, cell_IDs, set_defaults = TRUE) \item{spat_unit}{spatial unit (e.g. "cell")} -\item{cell_IDs}{character vector of cell IDs to set} +\item{cell_IDs}{character vector of cell IDs to set. Passing 'initialize' will +reset the slot based on in order of preference: spatial_info then expression +slots} \item{set_defaults}{set default spat_unit and feat_type. Change to FALSE only when} } @@ -31,6 +33,17 @@ get_cell_id Other functions to set data in giotto object: \code{\link{get_cell_id}()}, \code{\link{get_feat_id}()}, +\code{\link{setDimReduction}()}, +\code{\link{setExpression}()}, +\code{\link{setFeatureInfo}()}, +\code{\link{setGiottoImage}()}, +\code{\link{setMultiomics}()}, +\code{\link{setNearestNetwork}()}, +\code{\link{setPolygonInfo}()}, +\code{\link{setSpatialEnrichment}()}, +\code{\link{setSpatialGrid}()}, +\code{\link{setSpatialLocations}()}, +\code{\link{setSpatialNetwork}()}, \code{\link{set_NearestNetwork}()}, \code{\link{set_cell_metadata}()}, \code{\link{set_dimReduction}()}, diff --git a/man/set_cell_metadata.Rd b/man/set_cell_metadata.Rd index 43864656a..71973f65f 100644 --- a/man/set_cell_metadata.Rd +++ b/man/set_cell_metadata.Rd @@ -40,6 +40,17 @@ Function to set cell metadata information into giotto object Other functions to set data in giotto object: \code{\link{get_cell_id}()}, \code{\link{get_feat_id}()}, +\code{\link{setDimReduction}()}, +\code{\link{setExpression}()}, +\code{\link{setFeatureInfo}()}, +\code{\link{setGiottoImage}()}, +\code{\link{setMultiomics}()}, +\code{\link{setNearestNetwork}()}, +\code{\link{setPolygonInfo}()}, +\code{\link{setSpatialEnrichment}()}, +\code{\link{setSpatialGrid}()}, +\code{\link{setSpatialLocations}()}, +\code{\link{setSpatialNetwork}()}, \code{\link{set_NearestNetwork}()}, \code{\link{set_cell_id}()}, \code{\link{set_dimReduction}()}, @@ -56,3 +67,4 @@ Other functions to set data in giotto object: \code{\link{set_spatial_locations}()} } \concept{functions to set data in giotto object} +\keyword{internal} diff --git a/man/set_dimReduction.Rd b/man/set_dimReduction.Rd index c522653d6..0096e8390 100644 --- a/man/set_dimReduction.Rd +++ b/man/set_dimReduction.Rd @@ -46,11 +46,24 @@ Function to set a dimension reduction slot } \seealso{ Other dimensional reduction data accessor functions: -\code{\link{get_dimReduction}()} +\code{\link{getDimReduction}()}, +\code{\link{get_dimReduction}()}, +\code{\link{setDimReduction}()} Other functions to set data in giotto object: \code{\link{get_cell_id}()}, \code{\link{get_feat_id}()}, +\code{\link{setDimReduction}()}, +\code{\link{setExpression}()}, +\code{\link{setFeatureInfo}()}, +\code{\link{setGiottoImage}()}, +\code{\link{setMultiomics}()}, +\code{\link{setNearestNetwork}()}, +\code{\link{setPolygonInfo}()}, +\code{\link{setSpatialEnrichment}()}, +\code{\link{setSpatialGrid}()}, +\code{\link{setSpatialLocations}()}, +\code{\link{setSpatialNetwork}()}, \code{\link{set_NearestNetwork}()}, \code{\link{set_cell_id}()}, \code{\link{set_cell_metadata}()}, diff --git a/man/set_expression_values.Rd b/man/set_expression_values.Rd index ef7a433a1..3e4d7cc6a 100644 --- a/man/set_expression_values.Rd +++ b/man/set_expression_values.Rd @@ -41,11 +41,24 @@ Function to set expression values for giotto object } \seealso{ Other expression accessor functions: -\code{\link{get_expression_values}()} +\code{\link{getExpression}()}, +\code{\link{get_expression_values}()}, +\code{\link{setExpression}()} Other functions to set data in giotto object: \code{\link{get_cell_id}()}, \code{\link{get_feat_id}()}, +\code{\link{setDimReduction}()}, +\code{\link{setExpression}()}, +\code{\link{setFeatureInfo}()}, +\code{\link{setGiottoImage}()}, +\code{\link{setMultiomics}()}, +\code{\link{setNearestNetwork}()}, +\code{\link{setPolygonInfo}()}, +\code{\link{setSpatialEnrichment}()}, +\code{\link{setSpatialGrid}()}, +\code{\link{setSpatialLocations}()}, +\code{\link{setSpatialNetwork}()}, \code{\link{set_NearestNetwork}()}, \code{\link{set_cell_id}()}, \code{\link{set_cell_metadata}()}, diff --git a/man/set_feat_id.Rd b/man/set_feat_id.Rd index 527d83aed..c78e4d812 100644 --- a/man/set_feat_id.Rd +++ b/man/set_feat_id.Rd @@ -28,6 +28,17 @@ get_feat_id Other functions to set data in giotto object: \code{\link{get_cell_id}()}, \code{\link{get_feat_id}()}, +\code{\link{setDimReduction}()}, +\code{\link{setExpression}()}, +\code{\link{setFeatureInfo}()}, +\code{\link{setGiottoImage}()}, +\code{\link{setMultiomics}()}, +\code{\link{setNearestNetwork}()}, +\code{\link{setPolygonInfo}()}, +\code{\link{setSpatialEnrichment}()}, +\code{\link{setSpatialGrid}()}, +\code{\link{setSpatialLocations}()}, +\code{\link{setSpatialNetwork}()}, \code{\link{set_NearestNetwork}()}, \code{\link{set_cell_id}()}, \code{\link{set_cell_metadata}()}, diff --git a/man/set_feature_info.Rd b/man/set_feature_info.Rd index 856491b84..bd343ec04 100644 --- a/man/set_feature_info.Rd +++ b/man/set_feature_info.Rd @@ -4,14 +4,22 @@ \alias{set_feature_info} \title{Set feature info} \usage{ -set_feature_info(gobject, feat_type = NULL, gpolygon, verbose = TRUE) +set_feature_info( + gobject, + feat_type = NULL, + gpoints, + gpolygon = NULL, + verbose = TRUE +) } \arguments{ \item{gobject}{giotto object} \item{feat_type}{feature type (e.g. "rna", "dna", "protein")} -\item{gpolygon}{giotto polygon} +\item{gpoints}{giotto points object} + +\item{gpolygon}{typo do not use} \item{verbose}{be verbose} } @@ -23,11 +31,24 @@ Set giotto polygon spatVector for features } \seealso{ Other feature info data accessor functions: -\code{\link{get_feature_info}()} +\code{\link{getFeatureInfo}()}, +\code{\link{get_feature_info}()}, +\code{\link{setFeatureInfo}()} Other functions to set data in giotto object: \code{\link{get_cell_id}()}, \code{\link{get_feat_id}()}, +\code{\link{setDimReduction}()}, +\code{\link{setExpression}()}, +\code{\link{setFeatureInfo}()}, +\code{\link{setGiottoImage}()}, +\code{\link{setMultiomics}()}, +\code{\link{setNearestNetwork}()}, +\code{\link{setPolygonInfo}()}, +\code{\link{setSpatialEnrichment}()}, +\code{\link{setSpatialGrid}()}, +\code{\link{setSpatialLocations}()}, +\code{\link{setSpatialNetwork}()}, \code{\link{set_NearestNetwork}()}, \code{\link{set_cell_id}()}, \code{\link{set_cell_metadata}()}, diff --git a/man/set_feature_metadata.Rd b/man/set_feature_metadata.Rd index eb7366e4e..096639943 100644 --- a/man/set_feature_metadata.Rd +++ b/man/set_feature_metadata.Rd @@ -40,6 +40,17 @@ Function to set feature metadata into giotto object Other functions to set data in giotto object: \code{\link{get_cell_id}()}, \code{\link{get_feat_id}()}, +\code{\link{setDimReduction}()}, +\code{\link{setExpression}()}, +\code{\link{setFeatureInfo}()}, +\code{\link{setGiottoImage}()}, +\code{\link{setMultiomics}()}, +\code{\link{setNearestNetwork}()}, +\code{\link{setPolygonInfo}()}, +\code{\link{setSpatialEnrichment}()}, +\code{\link{setSpatialGrid}()}, +\code{\link{setSpatialLocations}()}, +\code{\link{setSpatialNetwork}()}, \code{\link{set_NearestNetwork}()}, \code{\link{set_cell_id}()}, \code{\link{set_cell_metadata}()}, @@ -56,3 +67,4 @@ Other functions to set data in giotto object: \code{\link{set_spatial_locations}()} } \concept{functions to set data in giotto object} +\keyword{internal} diff --git a/man/set_giottoImage.Rd b/man/set_giottoImage.Rd index 9c11093d0..8f62852cc 100644 --- a/man/set_giottoImage.Rd +++ b/man/set_giottoImage.Rd @@ -41,11 +41,24 @@ Directly attach a giotto image to giotto object \code{\link{addGiottoImage}} Other image data accessor functions: -\code{\link{get_giottoImage}()} +\code{\link{getGiottoImage}()}, +\code{\link{get_giottoImage}()}, +\code{\link{setGiottoImage}()} Other functions to set data in giotto object: \code{\link{get_cell_id}()}, \code{\link{get_feat_id}()}, +\code{\link{setDimReduction}()}, +\code{\link{setExpression}()}, +\code{\link{setFeatureInfo}()}, +\code{\link{setGiottoImage}()}, +\code{\link{setMultiomics}()}, +\code{\link{setNearestNetwork}()}, +\code{\link{setPolygonInfo}()}, +\code{\link{setSpatialEnrichment}()}, +\code{\link{setSpatialGrid}()}, +\code{\link{setSpatialLocations}()}, +\code{\link{setSpatialNetwork}()}, \code{\link{set_NearestNetwork}()}, \code{\link{set_cell_id}()}, \code{\link{set_cell_metadata}()}, diff --git a/man/set_multiomics.Rd b/man/set_multiomics.Rd index a4a65bb24..c4b5ef34c 100644 --- a/man/set_multiomics.Rd +++ b/man/set_multiomics.Rd @@ -37,11 +37,24 @@ Set a multiomics integration result in a Giotto object } \seealso{ Other multiomics accessor functions: -\code{\link{get_multiomics}()} +\code{\link{getMultiomics}()}, +\code{\link{get_multiomics}()}, +\code{\link{setMultiomics}()} Other functions to set data in giotto object: \code{\link{get_cell_id}()}, \code{\link{get_feat_id}()}, +\code{\link{setDimReduction}()}, +\code{\link{setExpression}()}, +\code{\link{setFeatureInfo}()}, +\code{\link{setGiottoImage}()}, +\code{\link{setMultiomics}()}, +\code{\link{setNearestNetwork}()}, +\code{\link{setPolygonInfo}()}, +\code{\link{setSpatialEnrichment}()}, +\code{\link{setSpatialGrid}()}, +\code{\link{setSpatialLocations}()}, +\code{\link{setSpatialNetwork}()}, \code{\link{set_NearestNetwork}()}, \code{\link{set_cell_id}()}, \code{\link{set_cell_metadata}()}, diff --git a/man/set_polygon_info.Rd b/man/set_polygon_info.Rd index 859f1de5a..1424f485a 100644 --- a/man/set_polygon_info.Rd +++ b/man/set_polygon_info.Rd @@ -23,11 +23,24 @@ Set giotto polygon spatVector } \seealso{ Other polygon info data accessor functions: -\code{\link{get_polygon_info}()} +\code{\link{getPolygonInfo}()}, +\code{\link{get_polygon_info}()}, +\code{\link{setPolygonInfo}()} Other functions to set data in giotto object: \code{\link{get_cell_id}()}, \code{\link{get_feat_id}()}, +\code{\link{setDimReduction}()}, +\code{\link{setExpression}()}, +\code{\link{setFeatureInfo}()}, +\code{\link{setGiottoImage}()}, +\code{\link{setMultiomics}()}, +\code{\link{setNearestNetwork}()}, +\code{\link{setPolygonInfo}()}, +\code{\link{setSpatialEnrichment}()}, +\code{\link{setSpatialGrid}()}, +\code{\link{setSpatialLocations}()}, +\code{\link{setSpatialNetwork}()}, \code{\link{set_NearestNetwork}()}, \code{\link{set_cell_id}()}, \code{\link{set_cell_metadata}()}, diff --git a/man/set_spatialGrid.Rd b/man/set_spatialGrid.Rd index 1be3f849a..da2ffd2d2 100644 --- a/man/set_spatialGrid.Rd +++ b/man/set_spatialGrid.Rd @@ -37,11 +37,24 @@ Function to set a spatial grid } \seealso{ Other spatial grid data accessor functions: -\code{\link{get_spatialGrid}()} +\code{\link{getSpatialGrid}()}, +\code{\link{get_spatialGrid}()}, +\code{\link{setSpatialGrid}()} Other functions to set data in giotto object: \code{\link{get_cell_id}()}, \code{\link{get_feat_id}()}, +\code{\link{setDimReduction}()}, +\code{\link{setExpression}()}, +\code{\link{setFeatureInfo}()}, +\code{\link{setGiottoImage}()}, +\code{\link{setMultiomics}()}, +\code{\link{setNearestNetwork}()}, +\code{\link{setPolygonInfo}()}, +\code{\link{setSpatialEnrichment}()}, +\code{\link{setSpatialGrid}()}, +\code{\link{setSpatialLocations}()}, +\code{\link{setSpatialNetwork}()}, \code{\link{set_NearestNetwork}()}, \code{\link{set_cell_id}()}, \code{\link{set_cell_metadata}()}, diff --git a/man/set_spatialNetwork.Rd b/man/set_spatialNetwork.Rd index d189dc99f..f32049a0a 100644 --- a/man/set_spatialNetwork.Rd +++ b/man/set_spatialNetwork.Rd @@ -6,9 +6,10 @@ \usage{ set_spatialNetwork( gobject, + spatial_network, spat_unit = NULL, name = NULL, - spatial_network, + provenance = NULL, verbose = TRUE, set_defaults = TRUE ) @@ -16,12 +17,12 @@ set_spatialNetwork( \arguments{ \item{gobject}{giotto object} +\item{spatial_network}{spatial network} + \item{spat_unit}{spatial unit (e.g. "cell")} \item{name}{name of spatial network} -\item{spatial_network}{spatial network} - \item{verbose}{be verbose} \item{set_defaults}{set default spat_unit and feat_type. Change to FALSE only when} @@ -34,11 +35,24 @@ Function to set a spatial network } \seealso{ Other spatial network data accessor functions: -\code{\link{get_spatialNetwork}()} +\code{\link{getSpatialNetwork}()}, +\code{\link{get_spatialNetwork}()}, +\code{\link{setSpatialNetwork}()} Other functions to set data in giotto object: \code{\link{get_cell_id}()}, \code{\link{get_feat_id}()}, +\code{\link{setDimReduction}()}, +\code{\link{setExpression}()}, +\code{\link{setFeatureInfo}()}, +\code{\link{setGiottoImage}()}, +\code{\link{setMultiomics}()}, +\code{\link{setNearestNetwork}()}, +\code{\link{setPolygonInfo}()}, +\code{\link{setSpatialEnrichment}()}, +\code{\link{setSpatialGrid}()}, +\code{\link{setSpatialLocations}()}, +\code{\link{setSpatialNetwork}()}, \code{\link{set_NearestNetwork}()}, \code{\link{set_cell_id}()}, \code{\link{set_cell_metadata}()}, diff --git a/man/set_spatial_enrichment.Rd b/man/set_spatial_enrichment.Rd index fcb8d828a..c05ebed93 100644 --- a/man/set_spatial_enrichment.Rd +++ b/man/set_spatial_enrichment.Rd @@ -37,11 +37,24 @@ Function to set a spatial enrichment slot } \seealso{ Other spatial enrichment data accessor functions: -\code{\link{get_spatial_enrichment}()} +\code{\link{getSpatialEnrichment}()}, +\code{\link{get_spatial_enrichment}()}, +\code{\link{setSpatialEnrichment}()} Other functions to set data in giotto object: \code{\link{get_cell_id}()}, \code{\link{get_feat_id}()}, +\code{\link{setDimReduction}()}, +\code{\link{setExpression}()}, +\code{\link{setFeatureInfo}()}, +\code{\link{setGiottoImage}()}, +\code{\link{setMultiomics}()}, +\code{\link{setNearestNetwork}()}, +\code{\link{setPolygonInfo}()}, +\code{\link{setSpatialEnrichment}()}, +\code{\link{setSpatialGrid}()}, +\code{\link{setSpatialLocations}()}, +\code{\link{setSpatialNetwork}()}, \code{\link{set_NearestNetwork}()}, \code{\link{set_cell_id}()}, \code{\link{set_cell_metadata}()}, diff --git a/man/set_spatial_locations.Rd b/man/set_spatial_locations.Rd index 058a77a10..77390ec85 100644 --- a/man/set_spatial_locations.Rd +++ b/man/set_spatial_locations.Rd @@ -49,11 +49,24 @@ its spat_unit slot will be changed to 'nucleus' } \seealso{ Other spatial location data accessor functions: -\code{\link{get_spatial_locations}()} +\code{\link{getSpatialLocations}()}, +\code{\link{get_spatial_locations}()}, +\code{\link{setSpatialLocations}()} Other functions to set data in giotto object: \code{\link{get_cell_id}()}, \code{\link{get_feat_id}()}, +\code{\link{setDimReduction}()}, +\code{\link{setExpression}()}, +\code{\link{setFeatureInfo}()}, +\code{\link{setGiottoImage}()}, +\code{\link{setMultiomics}()}, +\code{\link{setNearestNetwork}()}, +\code{\link{setPolygonInfo}()}, +\code{\link{setSpatialEnrichment}()}, +\code{\link{setSpatialGrid}()}, +\code{\link{setSpatialLocations}()}, +\code{\link{setSpatialNetwork}()}, \code{\link{set_NearestNetwork}()}, \code{\link{set_cell_id}()}, \code{\link{set_cell_metadata}()}, From 59b30c4cb07ac83b5fad3677459b4bb5083378e0 Mon Sep 17 00:00:00 2001 From: jiajic <72078254+jiajic@users.noreply.github.com> Date: Thu, 2 Feb 2023 00:36:54 -0500 Subject: [PATCH 127/129] Update NEWS.md --- NEWS.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/NEWS.md b/NEWS.md index bc6b4076b..b462d56fa 100644 --- a/NEWS.md +++ b/NEWS.md @@ -1,4 +1,4 @@ -# Giotto Suite 3.2.0 (RELEASE TBD) +# Giotto Suite 3.2.0 (2023-02-02) ## Breaking Changes - Removed support for deprecated nesting in `@nn_network` slot From 5b16233bec6e3d3fe6aa5dcce183484fd8af1abd Mon Sep 17 00:00:00 2001 From: jiajic <72078254+jiajic@users.noreply.github.com> Date: Thu, 2 Feb 2023 00:47:13 -0500 Subject: [PATCH 128/129] Update convenience.R --- R/convenience.R | 3 +++ 1 file changed, 3 insertions(+) diff --git a/R/convenience.R b/R/convenience.R index d23fcc6ff..55c319af3 100644 --- a/R/convenience.R +++ b/R/convenience.R @@ -373,6 +373,9 @@ createGiottoCosMxObject = function(cosmx_dir = NULL, # determine data to use data_to_use = match.arg(arg = data_to_use, choices = c('all','subcellular','aggregate')) + if(data_to_use %in% c('all', 'aggregate')) { + stop(wrap_txt('Convenience workflows "all" and "aggregate" are not available yet')) + } # Define for data.table fov = target = x_local_px = y_local_px = z = cell_ID = CenterX_global_px = CenterY_global_px = From 3867a14d20823a96afb7d5d1692ce11f7b6c9c39 Mon Sep 17 00:00:00 2001 From: jiajic <72078254+jiajic@users.noreply.github.com> Date: Thu, 2 Feb 2023 00:54:58 -0500 Subject: [PATCH 129/129] Update NEWS.md --- NEWS.md | 1 + 1 file changed, 1 insertion(+) diff --git a/NEWS.md b/NEWS.md index b462d56fa..f6e071d13 100644 --- a/NEWS.md +++ b/NEWS.md @@ -39,6 +39,7 @@ - Deprecate `polygon_feat_names` param in favor of `z_indices` in `readPolygonFilesVizgenHDF5()` - Deprecate `xy_translate_spatial_locations()` in favor of `shift_spatial_locations()` - Optimize `readPolygonFilesVizgen()` +- Fix bug in `replaceGiottoInstructions()` where instructions with more slots than previous are not allowed - Fix bug in `loadGiotto()` that prevents proper parsing of filenames when spat_unit or feat_type contains '_' characters - Fix `loadGiotto()` loss of over-allocation for data.tables-based objects after loading from disk