diff --git a/DESCRIPTION b/DESCRIPTION index 6249a500..d51816e0 100644 --- a/DESCRIPTION +++ b/DESCRIPTION @@ -1,6 +1,6 @@ Package: anndataR Title: AnnData interoperability in R -Version: 1.3.1 +Version: 1.3.2 Authors@R: c( person("Robrecht", "Cannoodt", , "rcannood@gmail.com", role = c("aut", "cre"), comment = c(ORCID = "0000-0003-3641-729X", github = "rcannood")), @@ -56,7 +56,7 @@ Suggests: knitr, processx, rhdf5 (>= 2.52.1), - Rarr (>= 2.1.13), + Rarr (>= 2.1.31), rmarkdown, S4Vectors, Seurat, diff --git a/NEWS.md b/NEWS.md index a466544a..8dbf38c9 100644 --- a/NEWS.md +++ b/NEWS.md @@ -3,6 +3,7 @@ - Add support for `nullable-string-array` elements in H5AD and Zarr (PR #480) - Check `RELEASE_*` branches against Bioconductor release and `devel` against Bioconductor devel, instead of checking `devel` against both (PR #502). - Run BiocCheck on `RELEASE_*` branches as well as on `devel` (PR #504). +- Write consolidated metadata on non-readonly anndata stores. Consolidated metadata is used to read encoding type and version of elements one level deep into the store (PR #492). # anndataR 1.3.1 diff --git a/R/ZarrAnnData.R b/R/ZarrAnnData.R index dcf515b2..2b0b5bfb 100644 --- a/R/ZarrAnnData.R +++ b/R/ZarrAnnData.R @@ -21,6 +21,7 @@ ZarrAnnData <- R6::R6Class( private = list( .zarrobj = NULL, .zarrformat = NULL, + .consolidated_metadata = NULL, .compression = NULL, .readonly = NULL, @@ -39,6 +40,10 @@ ZarrAnnData <- R6::R6Class( call = rlang::caller_env() ) } + }, + + .get_attrs_from_consolidated = function(slot, attr) { + private$.consolidated_metadata[[slot]]$attributes[[attr]] } ), active = list( @@ -48,7 +53,12 @@ ZarrAnnData <- R6::R6Class( if (missing(value)) { # trackstatus: class=ZarrAnnData, feature=get_X, status=done - read_zarr_element(private$.zarrobj, "X") |> + read_zarr_element( + private$.zarrobj, + "X", + private$.get_attrs_from_consolidated("X", "encoding-type"), + private$.get_attrs_from_consolidated("X", "encoding-version") + ) |> private$.add_matrix_dimnames("X") } else { private$.check_writeable() @@ -74,7 +84,12 @@ ZarrAnnData <- R6::R6Class( if (missing(value)) { # trackstatus: class=ZarrAnnData, feature=get_layers, status=done - read_zarr_element(private$.zarrobj, "layers") |> + read_zarr_element( + private$.zarrobj, + "layers", + private$.get_attrs_from_consolidated("layers", "encoding-type"), + private$.get_attrs_from_consolidated("layers", "encoding-version") + ) |> private$.add_mapping_dimnames("layers") } else { private$.check_writeable() @@ -100,7 +115,12 @@ ZarrAnnData <- R6::R6Class( if (missing(value)) { # trackstatus: class=ZarrAnnData, feature=get_obsm, status=done - read_zarr_element(private$.zarrobj, "obsm") |> + read_zarr_element( + private$.zarrobj, + "obsm", + private$.get_attrs_from_consolidated("obsm", "encoding-type"), + private$.get_attrs_from_consolidated("obsm", "encoding-version") + ) |> private$.add_mapping_dimnames("obsm") } else { private$.check_writeable() @@ -128,7 +148,12 @@ ZarrAnnData <- R6::R6Class( if (missing(value)) { # trackstatus: class=ZarrAnnData, feature=get_varm, status=done - read_zarr_element(private$.zarrobj, "varm") |> + read_zarr_element( + private$.zarrobj, + "varm", + private$.get_attrs_from_consolidated("varm", "encoding-type"), + private$.get_attrs_from_consolidated("varm", "encoding-version") + ) |> private$.add_mapping_dimnames("varm") } else { private$.check_writeable() @@ -156,7 +181,12 @@ ZarrAnnData <- R6::R6Class( if (missing(value)) { # trackstatus: class=ZarrAnnData, feature=get_obsp, status=done - read_zarr_element(private$.zarrobj, "obsp") |> + read_zarr_element( + private$.zarrobj, + "obsp", + private$.get_attrs_from_consolidated("obsp", "encoding-type"), + private$.get_attrs_from_consolidated("obsp", "encoding-version") + ) |> private$.add_mapping_dimnames("obsp") } else { private$.check_writeable() @@ -182,7 +212,12 @@ ZarrAnnData <- R6::R6Class( if (missing(value)) { # trackstatus: class=ZarrAnnData, feature=get_varp, status=done - read_zarr_element(private$.zarrobj, "varp") |> + read_zarr_element( + private$.zarrobj, + "varp", + private$.get_attrs_from_consolidated("varp", "encoding-type"), + private$.get_attrs_from_consolidated("varp", "encoding-version") + ) |> private$.add_mapping_dimnames("varp") } else { private$.check_writeable() @@ -208,7 +243,12 @@ ZarrAnnData <- R6::R6Class( if (missing(value)) { # trackstatus: class=ZarrAnnData, feature=get_obs, status=done - read_zarr_element(private$.zarrobj, "obs") + read_zarr_element( + private$.zarrobj, + "obs", + private$.get_attrs_from_consolidated("obs", "encoding-type"), + private$.get_attrs_from_consolidated("obs", "encoding-version") + ) } else { private$.check_writeable() # trackstatus: class=ZarrAnnData, feature=set_obs, status=done @@ -227,7 +267,12 @@ ZarrAnnData <- R6::R6Class( if (missing(value)) { # trackstatus: class=ZarrAnnData, feature=get_var, status=done - read_zarr_element(private$.zarrobj, "var") + read_zarr_element( + private$.zarrobj, + "var", + private$.get_attrs_from_consolidated("var", "encoding-type"), + private$.get_attrs_from_consolidated("var", "encoding-version") + ) } else { private$.check_writeable() # trackstatus: class=ZarrAnnData, feature=set_var, status=done @@ -246,7 +291,13 @@ ZarrAnnData <- R6::R6Class( if (missing(value)) { # trackstatus: class=ZarrAnnData, feature=get_obs_names, status=done - read_zarr_element_keys(private$.zarrobj, "obs", dim = "rows") + read_zarr_element_keys( + private$.zarrobj, + "obs", + private$.get_attrs_from_consolidated("obs", "encoding-type"), + private$.get_attrs_from_consolidated("obs", "encoding-version"), + dim = "rows" + ) } else { private$.check_writeable() # trackstatus: class=ZarrAnnData, feature=set_obs_names, status=done @@ -259,7 +310,13 @@ ZarrAnnData <- R6::R6Class( if (missing(value)) { # trackstatus: class=ZarrAnnData, feature=get_var_names, status=done - read_zarr_element_keys(private$.zarrobj, "var", dim = "rows") + read_zarr_element_keys( + private$.zarrobj, + "var", + private$.get_attrs_from_consolidated("var", "encoding-type"), + private$.get_attrs_from_consolidated("var", "encoding-version"), + dim = "rows" + ) } else { private$.check_writeable() # trackstatus: class=ZarrAnnData, feature=set_var_names, status=done @@ -272,7 +329,12 @@ ZarrAnnData <- R6::R6Class( if (missing(value)) { # trackstatus: class=ZarrAnnData, feature=get_uns, status=done - read_zarr_element(private$.zarrobj, "uns") + read_zarr_element( + private$.zarrobj, + "uns", + private$.get_attrs_from_consolidated("uns", "encoding-type"), + private$.get_attrs_from_consolidated("uns", "encoding-version") + ) } else { private$.check_writeable() # trackstatus: class=ZarrAnnData, feature=set_uns, status=done @@ -493,8 +555,17 @@ ZarrAnnData <- R6::R6Class( self[[slot]] <- value } } + Rarr::zarr_consolidate_metadata(file) } + # Create consolidated metadata on the fly, in memory, + # if it doesn't exist on disk (only happens for readonly stores). + private$.consolidated_metadata <- Rarr::read_zarr_consolidated_metadata( + file, + consolidate = "missing" + ) |> + list2env(hash = TRUE, parent = emptyenv()) + self },