diff --git a/DESCRIPTION b/DESCRIPTION index c444cccf..060be803 100644 --- a/DESCRIPTION +++ b/DESCRIPTION @@ -37,7 +37,7 @@ Imports: graph, Matrix, methods, - Rarr, + Rarr (>= 2.1.9), RBGL, rlang, sf, diff --git a/R/read.R b/R/read.R index d59a5215..f56e0054 100644 --- a/R/read.R +++ b/R/read.R @@ -51,8 +51,15 @@ NULL # https://ngff.openmicroscopy.org/specifications/0.5/index.html#images # The name of the array is arbitrary with the ordering defined by # by the "multiscales" metadata, but is often a sequence starting at 0. - ds <- .validate_multiscales_paths(x, datasets(mdattr)) - ds <- file.path(x, as.character(ds)) + if (!any(startsWith(x, c("http://", "https://", "s3://")))) { + # Until we have a complete store interface (https://github.com/Huber-group-EMBL/Rarr/pull/176), + # only local objects can be fully validated. + ds <- .validate_multiscales_paths(x, datasets(mdattr)) + } else { + # For remote objects, we skip validation and assume that the datasets are in the expected location. + ds <- datasets(mdattr) + } + ds <- paste0(x, ds) as <- lapply(ds, ZarrArray) list(array=as, mdattr=mdattr) } @@ -77,7 +84,7 @@ readLabel <- function(x, ...) { #' @importFrom dplyr sql #' @export readPoint <- function(x, ...) { - pq <- list.files(x, "\\.parquet$", full.names=TRUE) + pq <- paste0(x, file.path("points.parquet", "part.0.parquet")) md <- read_zarr_attributes(x) ax <- unlist(md$axes) df <- ddbs_open_dataset(pq, conn=.conn()) |> @@ -94,7 +101,8 @@ readPoint <- function(x, ...) { #' @export readShape <- function(x, ...) { md <- read_zarr_attributes(x) - pq <- list.files(x, "\\.parquet$", full.names=TRUE) + # "shapes.parquet" currently hardcoded in SpatialData.io + pq <- paste0(x, "shapes.parquet") df <- ddbs_open_dataset(pq, conn=.conn(), crs=NA_character_) attr(df, "source_path") <- pq SpatialDataShape(data=df, meta=SpatialDataAttrs(md)) @@ -134,11 +142,26 @@ readSpatialData <- function(x, args <- as.list(environment())[.LAYERS] skip <- vapply(args, isFALSE, logical(1)) + x <- Rarr:::.normalize_array_path(x) + store_meta <- Rarr:::.read_consolidated_metadata(x)$metadata + if (is.null(store_meta)) { + store_meta <- Rarr::consolidate_metadata(x, action = "return") + } + + # We have to treat v2 and v3 separately in the next 3 lines but we unify them again as `store_groups`. + store_groups_v3 <- store_meta[vapply(store_meta, \(.) !is.null(.$node_type) && .$node_type == "group", logical(1))] + store_groups_v2 <- store_meta[endsWith(names(store_meta), ".zgroup")] + names(store_groups_v2) <- dirname(names(store_groups_v2)) + store_groups <- names(c(store_groups_v3, store_groups_v2)) + # helper for layer reading .readLayer <- \(l) { - # 'j' are the paths on disk, 'nms' are their basenames - j <- list.dirs(file.path(x, l), recursive=FALSE, full.names=TRUE) - nms <- names(j) <- basename(j) + j <- store_groups[startsWith(store_groups, paste0(l, "/"))] + j <- setNames( + paste0(x, j, "/", recycle0 = TRUE), + basename(j) + ) + opt <- args[[l]] if (!isTRUE(opt)) { # validate each requested element diff --git a/inst/extdata/blobs.zarr/zmetadata b/inst/extdata/blobs.zarr/.zmetadata similarity index 100% rename from inst/extdata/blobs.zarr/zmetadata rename to inst/extdata/blobs.zarr/.zmetadata diff --git a/tests/testthat/test-read.R b/tests/testthat/test-read.R index 433342d1..367a3a6d 100644 --- a/tests/testthat/test-read.R +++ b/tests/testthat/test-read.R @@ -11,6 +11,7 @@ test_that("readElement()", { for (l in names(typ)) { f <- paste0(toupper(substr(l, 1, 1)), substr(l, 2, nchar(l)-1)) y <- list.files(file.path(x, l), full.names=TRUE)[1] + y <- paste0(y, "/", recycle0 = TRUE) expect_is(get(paste0("read", f))(y), typ[l]) } })