scConvert converts between single-cell data formats entirely in R, with no Python dependency. This vignette walks through the core API in under five minutes. For real-data demos, Python interop, and CLI performance benchmarks see the full articles.
Supported formats
| Format | Extension | Ecosystem | Read | Write |
|---|---|---|---|---|
| AnnData | .h5ad |
scanpy, CELLxGENE | yes | yes |
| h5Seurat | .h5seurat |
Seurat | yes | yes |
| MuData | .h5mu |
muon (multimodal) | yes | yes |
| Loom | .loom |
loompy, scVelo | yes | yes |
| Zarr | .zarr |
cloud AnnData | yes | yes |
| TileDB-SOMA | soma:// |
CELLxGENE Census | yes | yes |
| SpatialData | .zarr |
scverse spatial | yes | yes |
| RDS | .rds |
R native | yes | yes |
| SingleCellExperiment | in-memory | Bioconductor | yes | – |
Quick conversion with scConvert()
scConvert() is a universal dispatcher: give it a source
and a destination path and it picks the fastest conversion path
automatically.
h5ad_file <- system.file("testdata", "pbmc_small.h5ad", package = "scConvert")
h5seurat_out <- file.path(tempdir(), "pbmc.h5seurat")
zarr_out <- file.path(tempdir(), "pbmc.zarr")
t0 <- proc.time()
scConvert(h5ad_file, dest = h5seurat_out, overwrite = TRUE)
cat(sprintf("h5ad -> h5seurat: %.2fs\n", (proc.time() - t0)[["elapsed"]]))
#> h5ad -> h5seurat: 1.23s
t0 <- proc.time()
scConvert(h5ad_file, dest = zarr_out, overwrite = TRUE)
cat(sprintf("h5ad -> zarr: %.2fs\n", (proc.time() - t0)[["elapsed"]]))
#> h5ad -> zarr: 1.23sLoading files into Seurat
Each reader returns a standard Seurat object.
obj <- readH5AD(h5ad_file)
cat(sprintf("Loaded: %d cells x %d genes\n", ncol(obj), nrow(obj)))
#> Loaded: 214 cells x 2000 genes
cat(sprintf("Reductions: %s\n", paste(names(obj@reductions), collapse = ", ")))
#> Reductions: pca, umap
obj2 <- readH5Seurat(h5seurat_out)
cat(sprintf("h5seurat: %d cells x %d genes\n", ncol(obj2), nrow(obj2)))
#> h5seurat: 214 cells x 2000 genesWriting files from Seurat
h5ad_out <- file.path(tempdir(), "output.h5ad")
h5s_out <- file.path(tempdir(), "output.h5seurat")
zarr_out2 <- file.path(tempdir(), "output.zarr")
t0 <- proc.time(); writeH5AD(obj, h5ad_out, verbose = FALSE)
cat(sprintf("writeH5AD: %.2fs\n", (proc.time() - t0)[["elapsed"]]))
#> writeH5AD: 1.51s
t0 <- proc.time(); writeH5Seurat(obj, h5s_out, overwrite = TRUE, verbose = FALSE)
cat(sprintf("writeH5Seurat: %.2fs\n", (proc.time() - t0)[["elapsed"]]))
#> writeH5Seurat: 1.21s
sizes <- data.frame(
Format = c("h5ad", "h5Seurat"),
Size_MB = round(c(file.size(h5ad_out), file.size(h5s_out)) / 1024^2, 2)
)
knitr::kable(sizes, col.names = c("Format", "Size (MB)"))| Format | Size (MB) |
|---|---|
| h5ad | 0.48 |
| h5Seurat | 0.59 |
Next steps
- Convert Between Seurat and AnnData – real PBMC3k data, full Seurat pipeline, and live Python scanpy validation.
- CLI & Atlas-Scale Conversion – the C binary converts 592K cells in under a second.
-
Zarr
Format – cloud-native storage with live
zarr.open()Python validation. - Spatial Visium – real mouse brain data, Seurat spatial plots, and squidpy validation.
- Compare Tools – benchmark vs anndataR, schard, zellkonverter, scNT.