-
Notifications
You must be signed in to change notification settings - Fork 889
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
Support to handle .parquet
output from Vizgen
#7190
base: develop
Are you sure you want to change the base?
Changes from 11 commits
5fe5b89
aa32cc6
56d983c
115e45d
eff89e9
87d9303
089740a
547000e
f73dbdb
5ca1069
9389ce9
dc029ac
8f7153e
799323d
9ea4458
38fad2a
bf15b6e
f8461ca
a7be25a
6352d56
f43fed0
69ba89d
038271f
9db188a
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -20,11 +20,11 @@ NULL | |
#' @rdname ReadAkoya | ||
#' | ||
LoadAkoya <- function( | ||
filename, | ||
type = c('inform', 'processor', 'qupath'), | ||
fov, | ||
assay = 'Akoya', | ||
... | ||
filename, | ||
type = c('inform', 'processor', 'qupath'), | ||
fov, | ||
assay = 'Akoya', | ||
... | ||
) { | ||
# read in matrix and centroids | ||
data <- ReadAkoya(filename = filename, type = type) | ||
|
@@ -115,7 +115,7 @@ LoadNanostring <- function(data.dir, fov, assay = 'Nanostring') { | |
assay = assay | ||
) | ||
obj <- CreateSeuratObject(counts = data$matrix, assay = assay) | ||
|
||
# subset both object and coords based on the cells shared by both | ||
cells <- intersect( | ||
Cells(x = coords, boundary = "segmentation"), | ||
|
@@ -129,45 +129,106 @@ LoadNanostring <- function(data.dir, fov, assay = 'Nanostring') { | |
|
||
#' @return \code{LoadVizgen}: A \code{\link[SeuratObject]{Seurat}} object | ||
#' | ||
#' @param add.zIndex If to add \code{z} slice index to a cell | ||
#' @param update.object If to update final object, default to TRUE. | ||
#' @param ... Arguments passed to \code{ReadVizgen} | ||
#' | ||
#' @importFrom SeuratObject Cells CreateCentroids CreateFOV | ||
#' CreateSegmentation CreateSeuratObject | ||
#' @import dplyr | ||
#' | ||
#' @export | ||
#' | ||
#' @rdname ReadVizgen | ||
#' | ||
LoadVizgen <- function(data.dir, fov, assay = 'Vizgen', z = 3L) { | ||
data <- ReadVizgen( | ||
data.dir = data.dir, | ||
filter = "^Blank-", | ||
type = c("centroids", "segmentations"), | ||
z = z | ||
) | ||
segs <- CreateSegmentation(data$segmentations) | ||
cents <- CreateCentroids(data$centroids) | ||
segmentations.data <- list( | ||
"centroids" = cents, | ||
"segmentation" = segs | ||
) | ||
coords <- CreateFOV( | ||
coords = segmentations.data, | ||
type = c("segmentation", "centroids"), | ||
molecules = data$microns, | ||
assay = assay | ||
) | ||
obj <- CreateSeuratObject(counts = data$transcripts, assay = assay) | ||
# only consider the cells we have counts and a segmentation for | ||
# Cells which don't have a segmentation are probably found in other z slices. | ||
coords <- subset( | ||
x = coords, | ||
cells = intersect( | ||
x = Cells(x = coords[["segmentation"]]), | ||
y = Cells(x = obj) | ||
) | ||
) | ||
# add coords to seurat object | ||
LoadVizgen <- function(data.dir, fov = "vz", assay = 'Vizgen', | ||
add.zIndex = TRUE, update.object = TRUE, | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. It would useful to include the filter = '^Blank-' to filter out the blank genes. Also, need to have mol.type = 'microns' as an input variable. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. ..could add optionally There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I agree some users may want to look at them, but they should be removed before downstream analysis (and this way it works with the current Seurat Vizgen tutorial). mol.type is also called outside of ReadVizgen() and it's producing errors for me when not loaded into the function. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. sounds good, will add ..will make sure that There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Working off your latest commit I added it There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Great! For the next commit, I will make sure |
||
...) { | ||
data <- ReadVizgen(data.dir = data.dir, ...) | ||
|
||
#gc() %>% invisible() | ||
message("Creating Seurat object..") | ||
obj <- CreateSeuratObject(counts = data[["transcripts"]], assay = assay) | ||
|
||
# in case no segmentation is present, use boxes | ||
if (!"segmentations" %in% names(data)) { | ||
if ("boxes" %in% names(data)) { | ||
bound.boxes <- CreateSegmentation(data[["boxes"]]) | ||
cents <- CreateCentroids(data[["centroids"]]) | ||
bound.boxes.data <- list(centroids = cents, | ||
boxes = bound.boxes) | ||
message("Creating FOVs..", "\n", | ||
">>> using box coordinates instead of segmentations") | ||
coords <- CreateFOV(coords = bound.boxes.data, | ||
type = c("boxes", "centroids"), | ||
molecules = data[[mol.type]], | ||
assay = assay) | ||
} else { # in case no segmentation & no boxes are present, use centroids only | ||
cents <- CreateCentroids(data[["centroids"]]) | ||
message("Creating FOVs..", "\n", | ||
">>> using only centroids") | ||
coords <- CreateFOV(coords = list(centroids = cents), | ||
type = c("centroids"), | ||
molecules = data[[mol.type]], | ||
assay = assay) | ||
} | ||
# only consider the cells we have counts and a segmentation for | ||
# Cells which don't have a segmentation are probably found in other z slices. | ||
coords <- subset(x = coords, | ||
cells = intersect(x = Cells(x = coords[["boxes"]]), | ||
alikhuseynov marked this conversation as resolved.
Show resolved
Hide resolved
|
||
y = Cells(x = obj))) | ||
} else { | ||
segs <- CreateSegmentation(data[["segmentations"]]) | ||
cents <- CreateCentroids(data[["centroids"]]) | ||
segmentations.data <- list(centroids = cents, segmentation = segs) | ||
message("Creating FOVs..", "\n", | ||
">>> using segmentations") | ||
coords <- CreateFOV(coords = segmentations.data, | ||
type = c("segmentation", "centroids"), | ||
molecules = data[[mol.type]], | ||
assay = assay) | ||
coords <- subset(x = coords, | ||
cells = intersect(x = Cells(x = coords[["segmentation"]]), | ||
y = Cells(x = obj))) | ||
} | ||
|
||
# add z-stack index for cells | ||
if (add.zIndex) { obj$z <- data$zIndex %>% pull(z) } | ||
|
||
# add metadata vars | ||
message(">>> adding metadata infos") | ||
if (c("metadata" %in% names(data))) { | ||
metadata <- match.arg(arg = "metadata", choices = names(data), several.ok = TRUE) | ||
meta.vars <- names(data[[metadata]]) | ||
for (i in meta.vars %>% seq) { | ||
obj %<>% AddMetaData(metadata = data[[metadata]][[meta.vars[i]]], | ||
col.name = meta.vars[i]) | ||
} | ||
} | ||
|
||
# sanity on fov name | ||
fov %<>% gsub("_|-", ".", .) | ||
|
||
message(">>> adding FOV") | ||
obj[[fov]] <- coords | ||
|
||
## filter - keep cells with counts > 0 | ||
# small helper function to return metadata | ||
callmeta <- function (object = NULL) { return(object@meta.data) } | ||
nCount <- grep("nCount", callmeta(obj) %>% names, value = TRUE) | ||
if (any(obj[[nCount]] > 0)) { | ||
message(">>> filtering object - keep cells with counts > 0") | ||
obj %<>% subset(subset = !!base::as.symbol(nCount) > 0) | ||
} | ||
|
||
if (update.object) { | ||
message("Updating object..") | ||
obj %<>% UpdateSeuratObject() } | ||
|
||
message("Object is ready!") | ||
return(obj) | ||
|
||
gc() %>% invisible() | ||
} | ||
|
||
#' @return \code{LoadXenium}: A \code{\link[SeuratObject]{Seurat}} object | ||
|
@@ -188,7 +249,7 @@ LoadXenium <- function(data.dir, fov = 'fov', assay = 'Xenium') { | |
data.dir = data.dir, | ||
type = c("centroids", "segmentations"), | ||
) | ||
|
||
segmentations.data <- list( | ||
"centroids" = CreateCentroids(data$centroids), | ||
"segmentation" = CreateSegmentation(data$segmentations) | ||
|
@@ -199,15 +260,15 @@ LoadXenium <- function(data.dir, fov = 'fov', assay = 'Xenium') { | |
molecules = data$microns, | ||
assay = assay | ||
) | ||
|
||
xenium.obj <- CreateSeuratObject(counts = data$matrix[["Gene Expression"]], assay = assay) | ||
if("Blank Codeword" %in% names(data$matrix)) | ||
xenium.obj[["BlankCodeword"]] <- CreateAssayObject(counts = data$matrix[["Blank Codeword"]]) | ||
else | ||
xenium.obj[["BlankCodeword"]] <- CreateAssayObject(counts = data$matrix[["Unassigned Codeword"]]) | ||
xenium.obj[["ControlCodeword"]] <- CreateAssayObject(counts = data$matrix[["Negative Control Codeword"]]) | ||
xenium.obj[["ControlProbe"]] <- CreateAssayObject(counts = data$matrix[["Negative Control Probe"]]) | ||
|
||
xenium.obj[[fov]] <- coords | ||
return(xenium.obj) | ||
} | ||
|
@@ -241,27 +302,27 @@ PCAPlot <- function(object, ...) { | |
#' @export | ||
#' | ||
SpatialDimPlot <- function( | ||
object, | ||
group.by = NULL, | ||
images = NULL, | ||
cols = NULL, | ||
crop = TRUE, | ||
cells.highlight = NULL, | ||
cols.highlight = c('#DE2D26', 'grey50'), | ||
facet.highlight = FALSE, | ||
label = FALSE, | ||
label.size = 7, | ||
label.color = 'white', | ||
repel = FALSE, | ||
ncol = NULL, | ||
combine = TRUE, | ||
pt.size.factor = 1.6, | ||
alpha = c(1, 1), | ||
image.alpha = 1, | ||
stroke = 0.25, | ||
label.box = TRUE, | ||
interactive = FALSE, | ||
information = NULL | ||
object, | ||
group.by = NULL, | ||
images = NULL, | ||
cols = NULL, | ||
crop = TRUE, | ||
cells.highlight = NULL, | ||
cols.highlight = c('#DE2D26', 'grey50'), | ||
facet.highlight = FALSE, | ||
label = FALSE, | ||
label.size = 7, | ||
label.color = 'white', | ||
repel = FALSE, | ||
ncol = NULL, | ||
combine = TRUE, | ||
pt.size.factor = 1.6, | ||
alpha = c(1, 1), | ||
image.alpha = 1, | ||
stroke = 0.25, | ||
label.box = TRUE, | ||
interactive = FALSE, | ||
information = NULL | ||
) { | ||
return(SpatialPlot( | ||
object = object, | ||
|
@@ -294,22 +355,22 @@ SpatialDimPlot <- function( | |
#' @export | ||
#' | ||
SpatialFeaturePlot <- function( | ||
object, | ||
features, | ||
images = NULL, | ||
crop = TRUE, | ||
slot = 'data', | ||
keep.scale = "feature", | ||
min.cutoff = NA, | ||
max.cutoff = NA, | ||
ncol = NULL, | ||
combine = TRUE, | ||
pt.size.factor = 1.6, | ||
alpha = c(1, 1), | ||
image.alpha = 1, | ||
stroke = 0.25, | ||
interactive = FALSE, | ||
information = NULL | ||
object, | ||
features, | ||
images = NULL, | ||
crop = TRUE, | ||
slot = 'data', | ||
keep.scale = "feature", | ||
min.cutoff = NA, | ||
max.cutoff = NA, | ||
ncol = NULL, | ||
combine = TRUE, | ||
pt.size.factor = 1.6, | ||
alpha = c(1, 1), | ||
image.alpha = 1, | ||
stroke = 0.25, | ||
interactive = FALSE, | ||
information = NULL | ||
) { | ||
return(SpatialPlot( | ||
object = object, | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I recommend removing all of the space-only changes so that reviewers can focus on changes that actually make a functional difference. Thank you so much for all of your work on this!
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
ok, I think most of the space-only changes are now removed. Thanks