Skip to content

Commit 7618f09

Browse files
authored
Update app.R
fixed an issue with H5AD upload
1 parent fc5ed57 commit 7618f09

File tree

1 file changed

+187
-21
lines changed

1 file changed

+187
-21
lines changed

inst/webApp/app.R

Lines changed: 187 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,6 @@ library(shinyhelper)
1111
library(shinycssloaders)
1212
library(shinyBS)
1313
library(Seurat)
14-
library(SeuratDisk)
1514
library(SeuratObject)
1615
library(scCustomize)
1716
library(sp)
@@ -36,6 +35,9 @@ library(stringr)
3635
library(reshape2)
3736
library(htmltools)
3837
library(cicerone)
38+
library(hdf5r)
39+
library(qs)
40+
library(SingleCellExperiment)
3941

4042
# Moved to R/, because stuff in `R` gets sourced automatically when in package/project
4143
#source("./Data/get_expressed_genes_mod.R")
@@ -1150,6 +1152,169 @@ filtres <- function(data,
11501152
}
11511153
}
11521154

1155+
load_to_seurat <- function(filepath){
1156+
ext <- tools::file_ext(filepath)
1157+
1158+
if (ext == "qs") {
1159+
obj <- qread(filepath)
1160+
}else if (ext == "QS") {
1161+
obj <- qread(filepath)
1162+
}else if (ext == "Qs") {
1163+
obj <- qread(filepath)
1164+
}
1165+
1166+
else if (ext == "rds") {
1167+
obj <- readRDS(filepath)
1168+
} else if (ext == "RDS") {
1169+
obj <- readRDS(filepath)
1170+
} else if (ext == "Rds") {
1171+
obj <- readRDS(filepath)
1172+
}
1173+
1174+
else if (ext == "h5ad") {
1175+
obj <- load_h5ad_to_list(filepath)
1176+
1177+
} else if (ext == "H5AD") {
1178+
obj <- load_h5ad_to_list(filepath)
1179+
1180+
}else if (ext == "H5ad") {
1181+
obj <- load_h5ad_to_list(filepath)
1182+
} else {
1183+
stop("Unsupported file type.")
1184+
}
1185+
1186+
# Convert depending on object type
1187+
if (inherits(obj, "Seurat")) {
1188+
return(obj)
1189+
1190+
} else if (inherits(obj, "SingleCellExperiment")) {
1191+
return(sce_to_seurat(obj))
1192+
1193+
} else if (is.list(obj) && all(c("X", "obs", "var") %in% names(obj))) {
1194+
return(list_to_seurat(obj))
1195+
1196+
} else {
1197+
stop("Unknown object structure.")
1198+
}
1199+
}
1200+
1201+
load_h5ad_to_list <- function(filepath){
1202+
library(Matrix)
1203+
library(hdf5r)
1204+
library(Seurat)
1205+
1206+
h5 <- H5File$new(filepath, mode = "r")
1207+
X_entry <- h5[["X"]]
1208+
1209+
if (inherits(X_entry, "H5Group")) {
1210+
message("Loading sparse X matrix from h5ad")
1211+
data <- X_entry[["data"]]$read()
1212+
indices <- X_entry[["indices"]]$read()
1213+
indptr <- X_entry[["indptr"]]$read()
1214+
1215+
n_rows <- length(indptr) - 1
1216+
n_cols <- max(indices) + 1
1217+
1218+
i <- integer(length(data))
1219+
j <- integer(length(data))
1220+
1221+
for (row in seq_len(n_rows)) {
1222+
start <- indptr[row] + 1
1223+
end <- indptr[row + 1]
1224+
if (start <= end) {
1225+
idx <- start:end
1226+
i[idx] <- row
1227+
j[idx] <- indices[idx] + 1
1228+
}
1229+
}
1230+
1231+
counts <- sparseMatrix(
1232+
i = i,
1233+
j = j,
1234+
x = data,
1235+
dims = c(n_rows, n_cols)
1236+
)
1237+
} else if (inherits(X_entry, "H5D")) {
1238+
message("Loading dense X matrix from h5ad")
1239+
counts <- X_entry$read()
1240+
} else {
1241+
stop("Unknown X format.")
1242+
}
1243+
1244+
# obs and var
1245+
obs <- tryCatch({
1246+
if ("obs" %in% names(h5)) {
1247+
df <- as.data.frame(h5[["obs"]]$read())
1248+
rownames(df) <- rownames(h5[["obs"]]) # <- important: set rownames
1249+
df
1250+
} else {
1251+
NULL
1252+
}
1253+
}, error = function(e) NULL)
1254+
1255+
var <- tryCatch({
1256+
if ("var" %in% names(h5)) {
1257+
df <- as.data.frame(h5[["var"]]$read())
1258+
rownames(df) <- rownames(h5[["var"]]) # <- important: set rownames
1259+
df
1260+
} else {
1261+
NULL
1262+
}
1263+
}, error = function(e) NULL)
1264+
1265+
h5$close_all()
1266+
1267+
# Add names to matrix
1268+
if (!is.null(obs)) {
1269+
colnames(counts) <- rownames(obs)
1270+
}
1271+
if (!is.null(var)) {
1272+
rownames(counts) <- rownames(var)
1273+
}
1274+
1275+
# Now create Seurat object
1276+
seurat_obj <- CreateSeuratObject(counts = counts, meta.data = obs)
1277+
1278+
return(seurat_obj)
1279+
}
1280+
1281+
list_to_seurat <- function(lst){
1282+
counts <- lst$X
1283+
metadata <- lst$obs
1284+
features <- lst$var
1285+
1286+
seu <- CreateSeuratObject(counts = counts, meta.data = metadata)
1287+
1288+
# Set feature names if available
1289+
if (!is.null(features) && "gene_ids" %in% colnames(features)) {
1290+
rownames(seu) <- features$gene_ids
1291+
} else if (!is.null(features) && "index" %in% colnames(features)) {
1292+
rownames(seu) <- features$index
1293+
}
1294+
1295+
return(seu)
1296+
}
1297+
1298+
sce_to_seurat <- function(sce){
1299+
counts <- counts(sce)
1300+
metadata <- as.data.frame(colData(sce))
1301+
1302+
seu <- CreateSeuratObject(counts = counts, meta.data = metadata)
1303+
1304+
# Transfer reducedDims if they exist
1305+
if (length(reducedDims(sce)) > 0) {
1306+
for (rd in names(reducedDims(sce))) {
1307+
seu[[paste0("pca_", rd)]] <- CreateDimReducObject(
1308+
embeddings = reducedDims(sce)[[rd]],
1309+
key = paste0(toupper(rd), "_"),
1310+
assay = DefaultAssay(seu)
1311+
)
1312+
}
1313+
}
1314+
1315+
return(seu)
1316+
}
1317+
11531318

11541319
# Define UI for application
11551320
ui <- fluidPage(
@@ -1230,7 +1395,7 @@ ui <- fluidPage(
12301395
".QS"
12311396
)) %>% helper(type = "inline",
12321397
title = "Accepted file types",
1233-
content = c("MatriCom accepts scRNA-seq files of up to 1 GB from Seurat (RDS or QS format) and ScanPy/Loom (H5AD format).",
1398+
content = c("MatriCom accepts scRNA-seq files of up to 1 GB from Seurat or SingleCellExperiment (RDS or QS format), and ScanPy/Loom (H5AD format).",
12341399
" ",
12351400
"IMPORTANT: MatriCom currently only accepts human and mouse datasets. If your file contains Ensembl gene IDs, you must convert them to HGCN (human) or MGI (mouse) Gene Symbols by activating the conversion button."),
12361401
buttonLabel = "OK")),
@@ -1535,26 +1700,27 @@ server <- function(input,output,session) {
15351700

15361701
du <- reactive({
15371702
req(input$file1)
1538-
1539-
dp <- input$file1$datapath
1540-
1541-
if(isTruthy(length(dp[grepl(".RDS",dp,ignore.case = T)])>0)){
1542-
df <- readRDS(input$file1$datapath)
1543-
1544-
if(strsplit(as.character(df@version),split="\\.")[[1]][1] != 3){
1545-
def <- DefaultAssay(df)
1546-
mat <- df@assays[[def]]$counts
1547-
rownames(mat) <- rownames(df@assays[[def]]$counts)
1548-
colnames(mat) <- colnames(df@assays[[def]]$counts)
1549-
mat <- CreateAssayObject(counts=mat)
1550-
mat2 <- CreateSeuratObject(counts=mat,meta.data = df@meta.data)
1551-
mat2 <- NormalizeData(mat2)
1552-
#df[["RNA"]] <- as(object = df[["RNA"]], Class = "Assay")
1553-
}
1554-
1555-
value(1)
1556-
return(mat2)
1703+
df <- load_to_seurat(input$file1$datapath)
1704+
1705+
if(strsplit(as.character(df@version),split="\\.")[[1]][1] != 3){
1706+
def <- DefaultAssay(df)
1707+
mat <- df@assays[[def]]$counts
1708+
rownames(mat) <- rownames(df@assays[[def]]$counts)
1709+
colnames(mat) <- colnames(df@assays[[def]]$counts)
1710+
mat <- CreateAssayObject(counts=mat)
1711+
mat2 <- CreateSeuratObject(counts=mat,meta.data = df@meta.data)
1712+
mat2 <- NormalizeData(mat2)
1713+
DefaultAssay(mat2) <- "RNA"
1714+
# df[["RNA"]] <- as(object = df[["RNA"]], Class = "Assay")
1715+
}else{
1716+
mat2 <- df
1717+
DefaultAssay(mat2) <- "RNA"
15571718
}
1719+
1720+
value(1)
1721+
return(mat2)
1722+
1723+
}) #user-specific FILE READ-IN
15581724

15591725
if(isTruthy(length(dp[grepl(".qs",dp,ignore.case = T)])>0)){
15601726
df <- qread(input$file1$datapath)

0 commit comments

Comments
 (0)