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

Add support for assays stored as SeuratObject::Assay5 #23

Merged
merged 3 commits into from
Dec 6, 2023
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
3 changes: 2 additions & 1 deletion DESCRIPTION
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,8 @@ Roxygen: list(markdown = TRUE)
RoxygenNote: 7.2.3
Suggests:
testthat (>= 3.0.0),
Matrix
Matrix,
SeuratObject (>= 5.0.0)
Config/testthat/edition: 3
Imports:
methods,
Expand Down
1 change: 1 addition & 0 deletions NAMESPACE
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
# Generated by roxygen2: do not edit by hand

export(counts_matrix_from_assay)
export(create_bugreport)
export(create_bugreport_from_seurat)
export(create_loupe)
Expand Down
3 changes: 2 additions & 1 deletion R/err.R
Original file line number Diff line number Diff line change
Expand Up @@ -60,9 +60,10 @@ create_bugreport_from_seurat <- function(obj) {
assay <- namedAssay[[1]]
clusters <- select_clusters(obj)
projections <- select_projections(obj)
counts <- counts_matrix_from_assay(assay)

create_bugreport(
assay@counts,
counts,
clusters,
projections,
assay_name = assay_name,
Expand Down
3 changes: 2 additions & 1 deletion R/lib.R
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,7 @@ create_loupe_from_seurat <- function(

assay_name <- names(namedAssay)
assay <- namedAssay[[1]]
counts <- counts_matrix_from_assay(assay)

clusters <- select_clusters(obj, dedup=dedup_clusters)
projections <- select_projections(obj)
Expand All @@ -58,7 +59,7 @@ create_loupe_from_seurat <- function(
}

success <- create_loupe(
assay@counts,
counts,
clusters=clusters,
projections=projections,
output_dir=output_dir,
Expand Down
22 changes: 21 additions & 1 deletion R/util.R
Original file line number Diff line number Diff line change
Expand Up @@ -56,8 +56,9 @@ select_assay <- function(obj) {
for (i in seq_along(assay_priority)) {
name <- names(assay_priority[i])
assay <- Seurat::GetAssay(obj, assay=name)
counts <- counts_matrix_from_assay(assay)

if (length(assay@counts) > 0) {
if (length(counts) > 0) {
result = list()
result[[name]] = assay
return(result)
Expand All @@ -67,6 +68,25 @@ select_assay <- function(obj) {
NULL
}

#' Extract the counts matrix from the Assay
#'
#' @param assay A SeuratObject::Assay or SeuratObject::Assay5
#'
#' @return A sparse counts matrix
#'
#' @export
counts_matrix_from_assay <- function(assay) {
Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Adding this method to get the counts matrix from either of the assay versions instead of updating the select_assay method to just return the counts matrix directly. Doing this so that I don't break anyone's code if they are relying on select_assay

if (packageVersion("Seurat") >= 5) {
return(assay$counts)
} else {
if (is(assay, 'Assay5')) {
stop("Cannot get count matrix: Please upgrade to Seurat > 5 to support dataset")
}

return(assay@counts)
}
}

#' Select clusters from the assay
#'
#' @param obj A Seurat Object
Expand Down
5 changes: 4 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -37,9 +37,12 @@ library("loupeR")
# Gene Expression RNA assay
assay <- seurat_obj[["RNA"]]

# get counts matrix from either the old or newer formats of assay
counts <- counts_matrix_from_assay(assay)

# convert the count matrix, clusters, and projections into a Loupe file
create_loupe(
assay@counts,
counts,
clusters = select_clusters(seurat_obj),
projections = select_projections(seurat_obj)
)
Expand Down
17 changes: 17 additions & 0 deletions man/counts_matrix_from_assay.Rd

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

24 changes: 19 additions & 5 deletions tests/testthat/test-util.R
Original file line number Diff line number Diff line change
Expand Up @@ -4,15 +4,29 @@ test_that("select_assay selects active assay", {
rna3 <- create_count_mat(5, 5)

obj <- Seurat::CreateSeuratObject(rna1, assay="rna1")
obj[["rna2_"]] = Seurat::CreateAssayObject(rna2, key="rna2_")
obj[["rna3_"]] = Seurat::CreateAssayObject(rna3, key="rna3_")
obj[["rna2"]] = Seurat::CreateAssayObject(rna2, key="rna2_")
Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Unrelated change, but the names here didn't need to have an underscore even though the key parameter to CreateAssayObject requires it

obj[["rna3"]] = Seurat::CreateAssayObject(rna3, key="rna3_")

expect_equal(Seurat::DefaultAssay(object = obj), "rna1")
Seurat::DefaultAssay(object = obj) <- "rna2_"
expect_equal(Seurat::DefaultAssay(object = obj), "rna2_")
Seurat::DefaultAssay(object = obj) <- "rna2"
expect_equal(Seurat::DefaultAssay(object = obj), "rna2")

assay <- select_assay(obj)
expect_equal(names(assay), "rna2_")
expect_equal(names(assay), "rna2")
})

test_that("counts_matrix_from_assay works on different assay version", {
rna1 <- create_count_mat(5, 5)
rna2 <- create_count_mat(5, 5)
rna3 <- create_count_mat(5, 5)

obj <- Seurat::CreateSeuratObject(rna1, assay="rna1")
obj[["rna2"]] = Seurat::CreateAssayObject(rna2, key="rna2_")
obj[["rna3"]] = SeuratObject::CreateAssay5Object(rna3, key="rna3_")
Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The Seurat package doesn't export the underlying v5 create method like it does with the non v5.

Comment on lines +19 to +25
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
rna1 <- create_count_mat(5, 5)
rna2 <- create_count_mat(5, 5)
rna3 <- create_count_mat(5, 5)
obj <- Seurat::CreateSeuratObject(rna1, assay="rna1")
obj[["rna2"]] = Seurat::CreateAssayObject(rna2, key="rna2_")
obj[["rna3"]] = SeuratObject::CreateAssay5Object(rna3, key="rna3_")
rna <- create_count_mat(5, 5)
obj <- Seurat::CreateSeuratObject(rna, assay="rna1")
obj[["rna2"]] = Seurat::CreateAssayObject(rna, key="rna2_")
obj[["rna3"]] = SeuratObject::CreateAssay5Object(rna, key="rna3_")

R will pass function arguments by value rather than reference so you shouldn't need to construct multiple instances yourself

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I actually want to create three different matrices because I want their values to be different for the tests. Turns out R is copy by value, but only if the value is modified.


expect_equal(counts_matrix_from_assay(obj[["rna1"]]), rna1)
expect_equal(counts_matrix_from_assay(obj[["rna2"]]), rna2)
expect_equal(counts_matrix_from_assay(obj[["rna3"]]), rna3)
})

test_that("select_clusters selects Idents", {
Expand Down