Skip to content

Conversation

rcannood
Copy link
Member

@rcannood rcannood commented Sep 29, 2025

Related to: Fixes #349

Description

  • Added S4 as() coercions linking AnnData implementations with SingleCellExperiment and Seurat objects
  • Fix inconsistency in output_class argument values across conversion functions

When as(...) is possible, the conversion function displays a warning. If it's not possible (e.g. HDF5AnnData, because an additional path argument is needed), an error is thrown instead. In both cases, the message lets the user know which function to use instead.

Example:

library(anndataR)
dummy_anndata <- generate_dataset(format = "AnnData", example = TRUE)

as(dummy_anndata, "Seurat")
## Warning: Data is of class matrix. Coercing to dgCMatrix.
## An object of class Seurat 
## 20 features across 10 samples within 1 assay 
## Active assay: RNA (20 features, 0 variable features)
##  4 layers present: numeric_matrix, numeric_dense, numeric_csparse, X
##  3 dimensional reductions calculated: numeric_matrix, numeric_dense, numeric_csparse
## Warning messages:
## 1: In asMethod(object) :
##   Using `as()` limits control over data mapping.
## ℹ Prefer `adata$as_Seurat(...)` for fine-grained control over data mapping.
## 2: No "counts" or "data" layer found in `names(layers_mapping)`, this may lead to unexpected results when using the resulting <Seurat> object. 

as(dummy_anndata, "SingleCellExperiment")
## class: SingleCellExperiment 
## dim: 20 10 
## metadata(4): scalar_character vec_integer df_logical mat_numeric_matrix
## assays(4): numeric_matrix numeric_dense numeric_csparse X
## rownames(20): gene1 gene2 ... gene19 gene20
## rowData names(3): character integer factor
## colnames(10): cell1 cell2 ... cell9 cell10
## colData names(3): character integer factor
## reducedDimNames(3): numeric_matrix numeric_dense numeric_csparse
## mainExpName: NULL
## altExpNames(0):
## Warning message:
## In asMethod(object) : Using `as()` limits control over data mapping.
## ℹ Prefer `adata$as_SingleCellExperiment(...)` for fine-grained control over data mapping.

as(dummy_anndata, "ReticulateAnnData")
## Error in py_set_attr(x, name, value) : 
##   AttributeError: 'PyCapsule' object has no attribute 'shape'
## Run `reticulate::py_last_error()` for details.
## In addition: Warning message:
## In asMethod(object) : Using `as()` limits control over data mapping.
## ℹ Prefer `adata$as_ReticulateAnnData(...)` for fine-grained control over data mapping.

as(dummy_anndata, "HDF5AnnData")
## Error in `asMethod()`:
## ! Can't coerce <AbstractAnnData> to <HDF5AnnData> with `as()()`.
## ℹ Use `adata$as_HDF5AnnData(file = <path>)` to provide the output file.
## Run `rlang::last_trace()` to see where the error occurred.

Edit: currently checking why as(dummy_anndata, "ReticulateAnnData") fails!

Checklist

Before review

  • Update and regenerate man pages
  • Add/update tests
  • Add/update examples in vignettes
  • Pass CI checks

Before merge

  • Update NEWS
  • Bump devel version

@rcannood rcannood requested a review from lazappi September 29, 2025 13:40
Copy link
Collaborator

@lazappi lazappi left a comment

Choose a reason for hiding this comment

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

Few formatting suggestions but looks good

Comment on lines +53 to +54
force(warn)
force(pre)
Copy link
Collaborator

Choose a reason for hiding this comment

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

Why do you need this (just curious)?

Copy link
Member Author

Choose a reason for hiding this comment

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

It causes these arguments to be evaluated eagerly instead of lazily

Copy link
Collaborator

Choose a reason for hiding this comment

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

I figured that, I just wasn't sure why that was needed 😸

R/as-coercions.R Outdated
handler = .make_abort_handler(
from_class = "SingleCellExperiment",
to_class = "HDF5AnnData",
helper = "Use `as_AnnData(from, output_class = \"HDF5AnnData\", filename = <path>)` to provide the output file."
Copy link
Collaborator

Choose a reason for hiding this comment

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

For AnnData the argument is file but here it is filename. Maybe we should make that consistent?

@lazappi lazappi mentioned this pull request Oct 8, 2025
6 tasks
Copy link
Collaborator

@lazappi lazappi left a comment

Choose a reason for hiding this comment

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

I thought the tests might be failing because the classes aren't exported but I tried that in #365 and got the same errors 😿

rcannood and others added 2 commits October 8, 2025 10:22
Co-authored-by: Luke Zappia <[email protected]>
* Export AnnData classes

* Add register_anndata_coersions function

Move coercions here so it can be called in different ways

Co-authored-by: GitHub Copilot <[email protected]>

* Register coercions on package load

Co-authored-by: GitHub Copilot <[email protected]>

* Style

---------

Co-authored-by: GitHub Copilot <[email protected]>
@lazappi lazappi mentioned this pull request Oct 17, 2025
11 tasks
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Add as() coercion methods

2 participants