Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Enhance Seurat interoperability for Xenium dataset support #235

Merged
merged 1 commit into from
Sep 23, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
53 changes: 32 additions & 21 deletions R/interoperability.R
Original file line number Diff line number Diff line change
Expand Up @@ -767,15 +767,15 @@ giottoToAnnData <- function(gobject = NULL,
# Feat Metadata
for (su in spat_unit) {
for (ft in names(gobject@expression[[su]])) {
cmeta <- get_cell_metadata(
cmeta <- getCellMetadata(
gobject = gobject,
spat_unit = su,
feat_type = ft,
output = "data.table",
set_defaults = FALSE
)

fm <- get_feature_metadata(
fm <- getFeatureMetadata(
gobject = gobject,
spat_unit = su,
feat_type = ft,
Expand Down Expand Up @@ -1289,7 +1289,7 @@ giottoToSeuratV4 <- function(gobject,
}
# add cell metadata
meta_cells <- data.table::setDF(
get_cell_metadata(
getCellMetadata(
gobject = gobject,
spat_unit = spat_unit,
feat_type = assay_use,
Expand All @@ -1307,7 +1307,7 @@ giottoToSeuratV4 <- function(gobject,
)
# add feature metadata
meta_genes <- data.table::setDF(
get_feature_metadata(
getFeatureMetadata(
gobject = gobject,
spat_unit = spat_unit,
feat_type = assay_use,
Expand Down Expand Up @@ -1477,7 +1477,14 @@ giottoToSeuratV5 <- function(gobject,
gobject = gobject,
spat_unit = spat_unit
)

assay_names <- names(gobject@expression$cell)

# Identify assays with spaces and replace with underscores
new_assay_names <- gsub(" ", "_", assay_names)

# Apply the new names to the gobject expression slot
names(gobject@expression$cell) <- new_assay_names

# verify if optional package is installed
package_check(pkg_name = "Seurat", repository = "CRAN")
loadNamespace("Seurat")
Expand Down Expand Up @@ -1569,8 +1576,9 @@ giottoToSeuratV5 <- function(gobject,
}

# add cell metadata
names(gobject@cell_metadata$cell) <- gsub(" ", "_", names(gobject@cell_metadata$cell))
meta_cells <- data.table::setDF(
get_cell_metadata(
getCellMetadata(
gobject = gobject,
spat_unit = spat_unit,
feat_type = assay_use,
Expand All @@ -1579,21 +1587,22 @@ giottoToSeuratV5 <- function(gobject,
)
)
rownames(meta_cells) <- meta_cells$cell_ID
meta_cells <- meta_cells[, -which(colnames(meta_cells) == "cell_ID")]
meta_cells <- meta_cells[, -which(colnames(meta_cells) == "cell_ID"), drop = FALSE]
if (ncol(meta_cells) > 0) {
colnames(meta_cells) <- paste0(
assay_use, "_",
colnames(meta_cells)
)
}
sobj <- Seurat::AddMetaData(sobj,
metadata = meta_cells[Seurat::Cells(sobj), ],
col.name = names(meta_cells)
)

}

# add feature metadata
names(gobject@feat_metadata$cell) <- gsub(" ", "_", names(gobject@feat_metadata$cell))
meta_genes <- data.table::setDF(
get_feature_metadata(
getFeatureMetadata(
gobject = gobject,
spat_unit = spat_unit,
feat_type = assay_use,
Expand All @@ -1602,15 +1611,14 @@ giottoToSeuratV5 <- function(gobject,
)
)
rownames(meta_genes) <- meta_genes$feat_ID
for (i in seq_along(sobj@assays)) {
# Check if assay_slot has @meta.data or @meta.features
if ("meta.data" %in% slotNames(sobj@assays[[i]])) {
sobj@assays[[i]]@meta.data <- meta_genes
} else if ("meta.features" %in% slotNames(sobj@assays[[i]])) {
sobj@assays[[i]]@meta.features <- meta_genes
} else {
warning(paste("No suitable metadata slot found for assay", i))
}
if ("meta.data" %in% slotNames(sobj@assays[[assay_use]])) {
sobj@assays[[assay_use]]@meta.data <- meta_genes
message(paste("Meta data updated for assay:", assay_use))
} else if ("meta.features" %in% slotNames(sobj@assays[[assay_use]])) {
sobj@assays[[assay_use]]@meta.features <- meta_genes
message(paste("Meta features updated for assay:", assay_use))
} else {
warning(paste("No suitable metadata slot found for assay", assay_use))
}

# dim reduction
Expand Down Expand Up @@ -2331,15 +2339,18 @@ seuratToGiottoV5 <- function(sobject,
}
# Subcellular
name <- names(sobject@images)
# if (!is.null(subcellular_assay)){
if (length(sobject@assays[[subcellular_assay]]) == 1) {
if (!is.null(Seurat::Images(
object = sobject,
assay = spatial_assay
))) {
spat_coord <- Seurat::GetTissueCoordinates(sobject)
colnames(spat_coord) <- c("sdimx", "sdimy")
spat_coord$cell_ID <- rownames(spat_coord)
exp <- exp[, c(intersect(spat_coord$cell_ID, colnames(exp)))]
spat_loc <- spat_coord
}
}
# }
if (!length(sobject@images) == 0) {
for (i in names(sobject@images)) {
if ("molecules" %in% names(sobject@images[[i]]) == TRUE) {
Expand Down
69 changes: 69 additions & 0 deletions tests/testthat/test-interoperability.R
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
library(testthat)
library(Giotto)
library(Seurat)

giotto_obj <- GiottoData::loadGiottoMini("visium")
seurat_obj <- giottoToSeuratV5(giotto_obj)
spe_obj <- giottoToSpatialExperiment(giotto_obj)

Seurat_obj2 <- SeuratData::LoadData("stxBrain", type = "anterior1" )
giotto_obj2 <- seuratToGiottoV5(Seurat_obj2)

giotto_obj_roundtrip <- seuratToGiottoV5(seurat_obj, "rna")

test_that("giottotoseurat function handles basic conversion", {

# Basic checks
expect_s4_class(seurat_obj, "Seurat")
expect_true(!is.null([email protected]))
expect_equal(nrow([email protected]),
nrow(giotto_obj@cell_metadata$cell$rna@metaDT))

# Check if image slots are handled correctly
if ("images" %in% slotNames(giotto_obj)) {
expect_true(length(seurat_obj@images) > 0)
expect_equal(length(seurat_obj@images), length(giotto_obj@images))
expect_s4_class(giotto_obj_roundtrip@images$alignment, "giottoLargeImage")
expect_s4_class(seurat_obj@images$alignment, "VisiumV1")
}
})

test_that("Giotto to Seurat Conversion Works",{
expect_s4_class(seurat_obj, "Seurat")
})

test_that("Seurat to Giotto Conversion Works",{
expect_s4_class(giotto_obj, "giotto")
})

test_that("Assay names are converted correctly (no spaces)", {
# Check for spaces in Seurat assay names
assay_names <- names(seurat_obj@assays)
expect_false(any(grepl(" ", assay_names))) # No spaces should be present
})

test_that("Data is consistent after roundtrip conversion", {

identical(giotto_obj_roundtrip@expression, giotto_obj@expression)
# Check consistency of expression data
expect_equal(dim(giotto_obj@expression$cell$rna$raw),
dim(giotto_obj_roundtrip@expression$cell$rna$raw))

# Check consistency of cell metadata
expect_equal(nrow(giotto_obj@cell_metadata$cell$rna@metaDT),
nrow(giotto_obj_roundtrip@cell_metadata$cell$rna@metaDT))
})

test_that("Feature metadata is transferred correctly", {
# Check if feature metadata (e.g., gene names) is correctly transferred
expect_equal(rownames(seurat_obj@assays$rna),
rownames(giotto_obj@expression$cell$rna$raw))
})

test_that("Giotto to SpatialExperiment Conversion Works",{
expect_s4_class(spe_obj[[1]], "SpatialExperiment")
})

#TODO
#spe
#annData