From 9ee333c9312fc662442fd9768805e55623f1fd69 Mon Sep 17 00:00:00 2001 From: Artur-man Date: Tue, 13 Oct 2026 09:48:58 +0200 Subject: [PATCH 01/10] initial version support --- DESCRIPTION | 2 +- NAMESPACE | 230 +++++++++++++++++++++++++++--------------------- R/AllGenerics.R | 2 + R/version.R | 70 +++++++++++++++ 4 files changed, 202 insertions(+), 102 deletions(-) create mode 100644 R/version.R diff --git a/DESCRIPTION b/DESCRIPTION index 71b51a75..b05954ee 100644 --- a/DESCRIPTION +++ b/DESCRIPTION @@ -66,5 +66,5 @@ Encoding: UTF-8 VignetteBuilder: knitr BugReports: https://github.com/HelenaLC/spatialdataR/issues URL: https://helenalc.github.io/spatialdataR, https://github.com/HelenaLC/spatialdataR -Config/roxygen2/version: 8.0.0 +Config/roxygen2/version: 8.1.0 Config/testthat/edition: 3 diff --git a/NAMESPACE b/NAMESPACE index cde8cefe..2725413c 100644 --- a/NAMESPACE +++ b/NAMESPACE @@ -111,109 +111,137 @@ exportMethods(tableNames) exportMethods(tables) exportMethods(transform) exportMethods(translation) -importFrom(BiocGenerics,as.data.frame) -importFrom(BiocGenerics,colnames) -importFrom(BiocGenerics,combine) -importFrom(BiocGenerics,data) -importFrom(BiocGenerics,path) -importFrom(BiocGenerics,rotate) -importFrom(BiocGenerics,rownames) -importFrom(BiocGenerics,scale) -importFrom(BiocGenerics,sequence) -importFrom(BiocGenerics,table) -importFrom(BiocGenerics,transform) +importFrom(BiocGenerics, + as.data.frame, + colnames, + combine, + data, + path, + rotate, + rownames, + scale, + sequence, + table, + transform +) importFrom(DBI,dbIsValid) importFrom(DelayedArray,DelayedArray) -importFrom(Matrix,sparseMatrix) -importFrom(Matrix,sparseVector) -importFrom(Matrix,summary) -importFrom(Matrix,t) +importFrom(Matrix, + sparseMatrix, + sparseVector, + summary, + t +) importFrom(RBGL,sp.between) -importFrom(Rarr,read_zarr_attributes) -importFrom(Rarr,zarr_overview) -importFrom(S4Vectors,"metadata<-") -importFrom(S4Vectors,DataFrame) -importFrom(S4Vectors,SimpleList) -importFrom(S4Vectors,coolcat) -importFrom(S4Vectors,make_zero_col_DFrame) -importFrom(S4Vectors,metadata) -importFrom(S4Vectors,setValidity2) -importFrom(SingleCellExperiment,"int_colData<-") -importFrom(SingleCellExperiment,"int_metadata<-") -importFrom(SingleCellExperiment,SingleCellExperiment) -importFrom(SingleCellExperiment,int_colData) -importFrom(SingleCellExperiment,int_metadata) +importFrom(Rarr, + read_zarr_attributes, + zarr_overview +) +importFrom(S4Vectors, + "metadata<-", + DataFrame, + SimpleList, + coolcat, + make_zero_col_DFrame, + metadata, + setValidity2 +) +importFrom(SingleCellExperiment, + "int_colData<-", + "int_metadata<-", + SingleCellExperiment, + int_colData, + int_metadata +) importFrom(SparseArray,colSums) -importFrom(SummarizedExperiment,"assay<-") -importFrom(SummarizedExperiment,"assayNames<-") -importFrom(SummarizedExperiment,"colData<-") -importFrom(SummarizedExperiment,assay) -importFrom(SummarizedExperiment,assayNames) -importFrom(SummarizedExperiment,colData) -importFrom(ZarrArray,ZarrArray) -importFrom(ZarrArray,path) -importFrom(ZarrArray,type) +importFrom(SummarizedExperiment, + "assay<-", + "assayNames<-", + "colData<-", + assay, + assayNames, + colData +) +importFrom(ZarrArray, + ZarrArray, + path, + type +) importFrom(anndataR,read_zarr) -importFrom(dplyr,.data) -importFrom(dplyr,all_of) -importFrom(dplyr,coalesce) -importFrom(dplyr,collect) -importFrom(dplyr,count) -importFrom(dplyr,filter) -importFrom(dplyr,join_by) -importFrom(dplyr,left_join) -importFrom(dplyr,mutate) -importFrom(dplyr,pull) -importFrom(dplyr,right_join) -importFrom(dplyr,row_number) -importFrom(dplyr,select) -importFrom(dplyr,slice) -importFrom(dplyr,sql) -importFrom(dplyr,tally) -importFrom(dplyr,tibble) -importFrom(duckspatial,as_duckspatial_df) -importFrom(duckspatial,ddbs_bbox) -importFrom(duckspatial,ddbs_create_conn) -importFrom(duckspatial,ddbs_intersects) -importFrom(duckspatial,ddbs_open_dataset) -importFrom(duckspatial,ddbs_write_table) -importFrom(graph,"edgeData<-") -importFrom(graph,"edgeDataDefaults<-") -importFrom(graph,"nodeData<-") -importFrom(graph,"nodeDataDefaults<-") -importFrom(graph,"nodes<-") -importFrom(graph,addEdge) -importFrom(graph,addNode) -importFrom(graph,edgeData) -importFrom(graph,graph.par) -importFrom(graph,graphAM) -importFrom(graph,nodeData) -importFrom(graph,nodes) -importFrom(methods,"slot<-") -importFrom(methods,as) -importFrom(methods,callNextMethod) -importFrom(methods,is) -importFrom(methods,new) -importFrom(methods,setClass) -importFrom(methods,setClassUnion) -importFrom(methods,setMethod) -importFrom(methods,setOldClass) -importFrom(methods,setReplaceMethod) -importFrom(methods,slot) -importFrom(rlang,"!!") -importFrom(rlang,.data) -importFrom(rlang,call2) -importFrom(sf,"st_geometry<-") -importFrom(sf,st_as_sf) -importFrom(sf,st_as_sfc) -importFrom(sf,st_bbox) -importFrom(sf,st_centroid) -importFrom(sf,st_coordinates) -importFrom(sf,st_geometry_type) -importFrom(sf,st_point) -importFrom(sf,st_polygon) -importFrom(sf,st_sf) -importFrom(sf,st_sfc) -importFrom(utils,.DollarNames) -importFrom(utils,head) -importFrom(utils,tail) +importFrom(dplyr, + .data, + all_of, + coalesce, + collect, + count, + filter, + join_by, + left_join, + mutate, + pull, + right_join, + row_number, + select, + slice, + sql, + tally, + tibble +) +importFrom(duckspatial, + as_duckspatial_df, + ddbs_bbox, + ddbs_create_conn, + ddbs_intersects, + ddbs_open_dataset, + ddbs_write_table +) +importFrom(graph, + "edgeData<-", + "edgeDataDefaults<-", + "nodeData<-", + "nodeDataDefaults<-", + "nodes<-", + addEdge, + addNode, + edgeData, + graph.par, + graphAM, + nodeData, + nodes +) +importFrom(methods, + "slot<-", + as, + callNextMethod, + is, + new, + setClass, + setClassUnion, + setMethod, + setOldClass, + setReplaceMethod, + slot +) +importFrom(rlang, + "!!", + .data, + call2 +) +importFrom(sf, + "st_geometry<-", + st_as_sf, + st_as_sfc, + st_bbox, + st_centroid, + st_coordinates, + st_geometry_type, + st_point, + st_polygon, + st_sf, + st_sfc +) +importFrom(utils, + .DollarNames, + head, + tail +) diff --git a/R/AllGenerics.R b/R/AllGenerics.R index 8d7901ea..b5cf754a 100644 --- a/R/AllGenerics.R +++ b/R/AllGenerics.R @@ -101,6 +101,8 @@ setGeneric("geom_type", \(x, ...) standardGeneric("geom_type")) setGeneric("multiscales", \(x, ...) standardGeneric("multiscales")) setGeneric("datasets", \(x, ...) standardGeneric("datasets")) +setGeneric("version", \(x, ...) standardGeneric("version")) + # tbl ---- setGeneric("hasTable", \(x, i, ...) standardGeneric("hasTable")) diff --git a/R/version.R b/R/version.R new file mode 100644 index 00000000..10e9266f --- /dev/null +++ b/R/version.R @@ -0,0 +1,70 @@ +#' @name version +#' @title Retrieve versions of \code{SpatialData} elements +#' +#' @param object \code{\link{SpatialData}} object or one of its elements. +#' @param simplify logical scalar; whether to flatten paths into a tibble. +#' @param ... ignored. +#' +#' @returns +#' for single elements, a character string; +#' for \link{SpatialData} objects, if \code{simplify=TRUE} (default), +#' a \code{tibble} where rows=elements and columns=layers/elements/paths. +#' if \code{simplify=FALSE}, a depth-3 list where levels=layers/elements/paths. +#' +#' @examples +#' zs <- file.path("extdata", "blobs.zarr") +#' zs <- system.file(zs, package="spatialdataR") +#' sd <- readSpatialData(zs) +#' +#' # element-wise +#' version(shape(sd)) +#' +#' # object-wide +#' version(sd) +#' version(sd, FALSE)$labels +#' +NULL + +#' @export +#' @rdname version +setMethod("version", "SpatialDataArray", \(x, ...) { + pa <- tryCatch(version(data(x)), error=\(e) NULL) + if (is.null(pa)) return(NA_character_) + dirname(pa) +}) + +#' @export +#' @rdname version +setMethod("version", "SpatialDataFrame", \(x, ...) { + pa <- attr(data(x), "source_path") + if (is.null(pa)) return(NA_character_) + pa +}) + +#' @export +#' @rdname version +#' @importFrom SingleCellExperiment int_metadata +setMethod("version", "SingleCellExperiment", \(x, ...) { + pa <- int_metadata(x)$source_path + if (is.null(pa)) return(NA_character_) + pa +}) + +#' @export +#' @rdname version +#' @importFrom dplyr tibble +setMethod("version", "SpatialData", \(x, simplify=TRUE, ...) { + names(ls) <- ls <- rownames(x) + ps <- lapply(ls, \(l) { + names(es) <- es <- names(x[[l]]) + lapply(es, \(e) version(x[[l]][[e]])) + }) + + if (!simplify) return(ps) + + do.call(rbind, lapply(names(ps), \(l) + do.call(rbind, lapply(names(ps[[l]]), \(e) + tibble(layer = l, element = e, version = ps[[l]][[e]]) + )) + )) +}) From 253c7d342eb5ab9ed810a88ede9933a5e2efffac Mon Sep 17 00:00:00 2001 From: Artur-man Date: Fri, 23 Oct 2026 17:59:36 +0200 Subject: [PATCH 02/10] generic and methods for sd format --- NAMESPACE | 1 + R/AllGenerics.R | 3 +- R/sdAttrs.R | 60 +++++++++++++++++++++++++++++++++++++++ R/version.R | 70 ---------------------------------------------- man/SpatialData.Rd | 6 ++-- man/format.Rd | 47 +++++++++++++++++++++++++++++++ 6 files changed, 111 insertions(+), 76 deletions(-) delete mode 100644 R/version.R create mode 100644 man/format.Rd diff --git a/NAMESPACE b/NAMESPACE index e2d9d22e..1ea9f276 100644 --- a/NAMESPACE +++ b/NAMESPACE @@ -74,6 +74,7 @@ exportMethods(extent) exportMethods(feature_key) exportMethods(flip) exportMethods(flop) +exportMethods(format) exportMethods(geom_type) exportMethods(getTable) exportMethods(hasTable) diff --git a/R/AllGenerics.R b/R/AllGenerics.R index 57da9ef2..22a3e0c9 100644 --- a/R/AllGenerics.R +++ b/R/AllGenerics.R @@ -78,6 +78,7 @@ setGeneric("feature_key", \(x, ...) standardGeneric("feature_key")) setGeneric("feature_key<-", \(x, value) standardGeneric("feature_key<-")) setGeneric("instance_key", \(x, ...) standardGeneric("instance_key")) setGeneric("instance_key<-", \(x, value) standardGeneric("instance_key<-")) +setGeneric("format", \(x, ...) standardGeneric("format")) # uts ---- @@ -103,8 +104,6 @@ setGeneric("geom_type", \(x, ...) standardGeneric("geom_type")) setGeneric("multiscales", \(x, ...) standardGeneric("multiscales")) setGeneric("datasets", \(x, ...) standardGeneric("datasets")) -setGeneric("version", \(x, ...) standardGeneric("version")) - # tbl ---- setGeneric("hasTable", \(x, i, ...) standardGeneric("hasTable")) diff --git a/R/sdAttrs.R b/R/sdAttrs.R index 3cfb32b4..e1149cdc 100644 --- a/R/sdAttrs.R +++ b/R/sdAttrs.R @@ -396,3 +396,63 @@ setReplaceMethod("instances", c("SingleCellExperiment", "ANY"), \(x, value) { int_colData(x)[[ik]] <- value return(x) }) + +# version ---- + +#' @name format +#' @title Retrieve versions of \code{SpatialData} elements +#' +#' @param object \code{\link{SpatialData}} object or one of its elements. +#' @param simplify logical scalar; whether to flatten paths into a tibble. +#' @param ... ignored. +#' +#' @returns +#' for single elements, a character string; +#' for \link{SpatialData} objects, if \code{simplify=TRUE} (default), +#' a \code{tibble} where rows=elements and columns=layers/elements/paths. +#' if \code{simplify=FALSE}, a depth-3 list where levels=layers/elements/paths. +#' +#' @examples +#' zs <- file.path("extdata", "blobs.zarr") +#' zs <- system.file(zs, package="spatialdataR") +#' sd <- readSpatialData(zs) +#' +#' # element-wise +#' format(shape(sd)) +#' +#' # object-wide +#' format(sd) +#' format(sd, FALSE)$labels +#' +NULL + +#' @export +#' @rdname format +setMethod("format", "SpatialDataElement", \(x) format(meta(x))) + +#' @export +#' @rdname format +setMethod("format", "SpatialDataAttrs", \(x) x$spatialdata_attrs$version) + +#' @export +#' @rdname format +setMethod("format", "SingleCellExperiment", \(x) meta(x)$version) + +#' @export +#' @rdname format +#' @importFrom dplyr tibble +setMethod("format", "SpatialData", \(x, simplify=TRUE, ...) { + names(ls) <- ls <- rownames(x) + ps <- lapply(ls, \(l) { + names(es) <- es <- names(x[[l]]) + lapply(es, \(e) format(x[[l]][[e]])) + }) + + if (!simplify) return(ps) + + do.call(rbind, lapply(names(ps), \(l) + do.call(rbind, lapply(names(ps[[l]]), \(e) + tibble(layer = l, element = e, format = ps[[l]][[e]]) + )) + )) +}) diff --git a/R/version.R b/R/version.R deleted file mode 100644 index 10e9266f..00000000 --- a/R/version.R +++ /dev/null @@ -1,70 +0,0 @@ -#' @name version -#' @title Retrieve versions of \code{SpatialData} elements -#' -#' @param object \code{\link{SpatialData}} object or one of its elements. -#' @param simplify logical scalar; whether to flatten paths into a tibble. -#' @param ... ignored. -#' -#' @returns -#' for single elements, a character string; -#' for \link{SpatialData} objects, if \code{simplify=TRUE} (default), -#' a \code{tibble} where rows=elements and columns=layers/elements/paths. -#' if \code{simplify=FALSE}, a depth-3 list where levels=layers/elements/paths. -#' -#' @examples -#' zs <- file.path("extdata", "blobs.zarr") -#' zs <- system.file(zs, package="spatialdataR") -#' sd <- readSpatialData(zs) -#' -#' # element-wise -#' version(shape(sd)) -#' -#' # object-wide -#' version(sd) -#' version(sd, FALSE)$labels -#' -NULL - -#' @export -#' @rdname version -setMethod("version", "SpatialDataArray", \(x, ...) { - pa <- tryCatch(version(data(x)), error=\(e) NULL) - if (is.null(pa)) return(NA_character_) - dirname(pa) -}) - -#' @export -#' @rdname version -setMethod("version", "SpatialDataFrame", \(x, ...) { - pa <- attr(data(x), "source_path") - if (is.null(pa)) return(NA_character_) - pa -}) - -#' @export -#' @rdname version -#' @importFrom SingleCellExperiment int_metadata -setMethod("version", "SingleCellExperiment", \(x, ...) { - pa <- int_metadata(x)$source_path - if (is.null(pa)) return(NA_character_) - pa -}) - -#' @export -#' @rdname version -#' @importFrom dplyr tibble -setMethod("version", "SpatialData", \(x, simplify=TRUE, ...) { - names(ls) <- ls <- rownames(x) - ps <- lapply(ls, \(l) { - names(es) <- es <- names(x[[l]]) - lapply(es, \(e) version(x[[l]][[e]])) - }) - - if (!simplify) return(ps) - - do.call(rbind, lapply(names(ps), \(l) - do.call(rbind, lapply(names(ps[[l]]), \(e) - tibble(layer = l, element = e, version = ps[[l]][[e]]) - )) - )) -}) diff --git a/man/SpatialData.Rd b/man/SpatialData.Rd index 9a4c6c34..520da91e 100644 --- a/man/SpatialData.Rd +++ b/man/SpatialData.Rd @@ -63,8 +63,6 @@ \alias{points,SpatialData-method} \alias{shapes,SpatialData-method} \alias{tables,SpatialData-method} -\alias{[[<-,SpatialData,character,ANY,ANY-method} -\alias{[[<-,SpatialData,ANY,ANY,ANY-method} \title{The `SpatialData` class} \usage{ SpatialData( @@ -117,9 +115,9 @@ SpatialData( \S4method{tables}{SpatialData}(x) -\S4method{[[}{SpatialData,character,ANY,ANY}(x, i) <- value +\S4method{[[}{SpatialData,character,ANY}(x, i) <- value -\S4method{[[}{SpatialData,ANY,ANY,ANY}(x, i) <- value +\S4method{[[}{SpatialData,ANY,ANY}(x, i) <- value } \arguments{ \item{images}{list of \code{\link{SpatialDataImage}}s} diff --git a/man/format.Rd b/man/format.Rd new file mode 100644 index 00000000..0ca48c33 --- /dev/null +++ b/man/format.Rd @@ -0,0 +1,47 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/sdAttrs.R +\name{format} +\alias{format} +\alias{format,SpatialDataElement-method} +\alias{format,SpatialDataAttrs-method} +\alias{format,SingleCellExperiment-method} +\alias{format,SpatialData-method} +\title{Retrieve versions of \code{SpatialData} elements} +\usage{ +\S4method{format}{SpatialDataElement}(x) + +\S4method{format}{SpatialDataAttrs}(x) + +\S4method{format}{SingleCellExperiment}(x) + +\S4method{format}{SpatialData}(x, simplify = TRUE, ...) +} +\arguments{ +\item{simplify}{logical scalar; whether to flatten paths into a tibble.} + +\item{...}{ignored.} + +\item{object}{\code{\link{SpatialData}} object or one of its elements.} +} +\value{ +for single elements, a character string; +for \link{SpatialData} objects, if \code{simplify=TRUE} (default), +a \code{tibble} where rows=elements and columns=layers/elements/paths. +if \code{simplify=FALSE}, a depth-3 list where levels=layers/elements/paths. +} +\description{ +Retrieve versions of \code{SpatialData} elements +} +\examples{ +zs <- file.path("extdata", "blobs.zarr") +zs <- system.file(zs, package="spatialdataR") +sd <- readSpatialData(zs) + +# element-wise +format(shape(sd)) + +# object-wide +format(sd) +format(sd, FALSE)$labels + +} From 360c6dc971e4b1198b5cec9b542357f2aea69b3f Mon Sep 17 00:00:00 2001 From: Artur-man Date: Fri, 23 Oct 2026 21:06:08 +0200 Subject: [PATCH 03/10] more generics and clean up --- R/path.R | 18 ++---------------- R/sdAttrs.R | 18 ++---------------- R/utils.R | 23 +++++++++++++++++++++++ 3 files changed, 27 insertions(+), 32 deletions(-) diff --git a/R/path.R b/R/path.R index a6c798cb..5851ba21 100644 --- a/R/path.R +++ b/R/path.R @@ -54,19 +54,5 @@ setMethod("path", "SingleCellExperiment", \(object, ...) { #' @export #' @rdname path -#' @importFrom dplyr tibble -setMethod("path", "SpatialData", \(object, simplify=TRUE, ...) { - names(ls) <- ls <- rownames(object) - ps <- lapply(ls, \(l) { - names(es) <- es <- names(object[[l]]) - lapply(es, \(e) path(object[[l]][[e]])) - }) - - if (!simplify) return(ps) - - do.call(rbind, lapply(names(ps), \(l) - do.call(rbind, lapply(names(ps[[l]]), \(e) - tibble(layer = l, element = e, path = ps[[l]][[e]]) - )) - )) -}) +setMethod("path", "SpatialData", \(object, simplify=TRUE, ...) + .element_apply(object, path, "path", simplify)) diff --git a/R/sdAttrs.R b/R/sdAttrs.R index e1149cdc..b9fdb22f 100644 --- a/R/sdAttrs.R +++ b/R/sdAttrs.R @@ -440,19 +440,5 @@ setMethod("format", "SingleCellExperiment", \(x) meta(x)$version) #' @export #' @rdname format -#' @importFrom dplyr tibble -setMethod("format", "SpatialData", \(x, simplify=TRUE, ...) { - names(ls) <- ls <- rownames(x) - ps <- lapply(ls, \(l) { - names(es) <- es <- names(x[[l]]) - lapply(es, \(e) format(x[[l]][[e]])) - }) - - if (!simplify) return(ps) - - do.call(rbind, lapply(names(ps), \(l) - do.call(rbind, lapply(names(ps[[l]]), \(e) - tibble(layer = l, element = e, format = ps[[l]][[e]]) - )) - )) -}) +setMethod("format", "SpatialData", \(x, simplify=TRUE, ...) + .element_apply(x, format, "format", simplify)) diff --git a/R/utils.R b/R/utils.R index 486500a9..900a0269 100644 --- a/R/utils.R +++ b/R/utils.R @@ -220,3 +220,26 @@ " least one data() pair with identical dimensions") return(ks) } + +# path/version ---- + +#' @importFrom dplyr tibble +#' @noRd +.element_apply <- function(x, FUN, col, simplify=TRUE) { + names(ls) <- ls <- rownames(x) + ps <- lapply(ls, \(l) { + names(es) <- es <- names(x[[l]]) + lapply(es, \(e) FUN(x[[l]][[e]])) + }) + + if (!simplify) return(ps) + + df <- do.call(rbind, lapply(names(ps), \(l) + do.call(rbind, lapply(names(ps[[l]]), \(e) + tibble(layer=l, element=e, value=ps[[l]][[e]]) + )) + )) + + if (!is.null(df)) names(df)[3] <- col + df +} \ No newline at end of file From 66a70deeef4fd84d26dcca3c6dc2e503ed6fc9b8 Mon Sep 17 00:00:00 2001 From: Artur-man Date: Sat, 24 Oct 2026 16:25:24 +0200 Subject: [PATCH 04/10] format -> version --- NAMESPACE | 2 +- R/AllGenerics.R | 2 +- R/sdAttrs.R | 28 ++++++++++++++-------------- man/{format.Rd => version.Rd} | 26 +++++++++++++------------- 4 files changed, 29 insertions(+), 29 deletions(-) rename man/{format.Rd => version.Rd} (65%) diff --git a/NAMESPACE b/NAMESPACE index 1ea9f276..5e8d79f8 100644 --- a/NAMESPACE +++ b/NAMESPACE @@ -74,7 +74,6 @@ exportMethods(extent) exportMethods(feature_key) exportMethods(flip) exportMethods(flop) -exportMethods(format) exportMethods(geom_type) exportMethods(getTable) exportMethods(hasTable) @@ -114,6 +113,7 @@ exportMethods(tableNames) exportMethods(tables) exportMethods(transform) exportMethods(translation) +exportMethods(version) importFrom(BiocGenerics, as.data.frame, colnames, diff --git a/R/AllGenerics.R b/R/AllGenerics.R index 22a3e0c9..1cf99050 100644 --- a/R/AllGenerics.R +++ b/R/AllGenerics.R @@ -78,7 +78,7 @@ setGeneric("feature_key", \(x, ...) standardGeneric("feature_key")) setGeneric("feature_key<-", \(x, value) standardGeneric("feature_key<-")) setGeneric("instance_key", \(x, ...) standardGeneric("instance_key")) setGeneric("instance_key<-", \(x, value) standardGeneric("instance_key<-")) -setGeneric("format", \(x, ...) standardGeneric("format")) +setGeneric("version", \(x, ...) standardGeneric("version")) # uts ---- diff --git a/R/sdAttrs.R b/R/sdAttrs.R index b9fdb22f..2a9b1263 100644 --- a/R/sdAttrs.R +++ b/R/sdAttrs.R @@ -220,7 +220,7 @@ setMethod("$", "SpatialDataAttrs", \(x, name) x[[name]]) "0.1" = "0.4", "0.2" = "0.4-dev-spatialdata", "0.3" = "0.5-dev-spatialdata", - stop("Invalid SpatialDataImage/Label format! ", + stop("Invalid SpatialDataImage/Label format/version! ", "Must be 0.1, 0.2, or 0.3")) } @@ -399,7 +399,7 @@ setReplaceMethod("instances", c("SingleCellExperiment", "ANY"), \(x, value) { # version ---- -#' @name format +#' @name version #' @title Retrieve versions of \code{SpatialData} elements #' #' @param object \code{\link{SpatialData}} object or one of its elements. @@ -418,27 +418,27 @@ setReplaceMethod("instances", c("SingleCellExperiment", "ANY"), \(x, value) { #' sd <- readSpatialData(zs) #' #' # element-wise -#' format(shape(sd)) +#' version(shape(sd)) #' #' # object-wide -#' format(sd) -#' format(sd, FALSE)$labels +#' version(sd) +#' version(sd, FALSE)$labels #' NULL #' @export -#' @rdname format -setMethod("format", "SpatialDataElement", \(x) format(meta(x))) +#' @rdname version +setMethod("version", "SpatialDataElement", \(x) version(meta(x))) #' @export -#' @rdname format -setMethod("format", "SpatialDataAttrs", \(x) x$spatialdata_attrs$version) +#' @rdname version +setMethod("version", "SpatialDataAttrs", \(x) x$spatialdata_attrs$version) #' @export -#' @rdname format -setMethod("format", "SingleCellExperiment", \(x) meta(x)$version) +#' @rdname version +setMethod("version", "SingleCellExperiment", \(x) meta(x)$version) #' @export -#' @rdname format -setMethod("format", "SpatialData", \(x, simplify=TRUE, ...) - .element_apply(x, format, "format", simplify)) +#' @rdname version +setMethod("version", "SpatialData", \(x, simplify=TRUE, ...) + .element_apply(x, version, "version", simplify)) diff --git a/man/format.Rd b/man/version.Rd similarity index 65% rename from man/format.Rd rename to man/version.Rd index 0ca48c33..f91de9fb 100644 --- a/man/format.Rd +++ b/man/version.Rd @@ -1,20 +1,20 @@ % Generated by roxygen2: do not edit by hand % Please edit documentation in R/sdAttrs.R -\name{format} -\alias{format} -\alias{format,SpatialDataElement-method} -\alias{format,SpatialDataAttrs-method} -\alias{format,SingleCellExperiment-method} -\alias{format,SpatialData-method} +\name{version} +\alias{version} +\alias{version,SpatialDataElement-method} +\alias{version,SpatialDataAttrs-method} +\alias{version,SingleCellExperiment-method} +\alias{version,SpatialData-method} \title{Retrieve versions of \code{SpatialData} elements} \usage{ -\S4method{format}{SpatialDataElement}(x) +\S4method{version}{SpatialDataElement}(x) -\S4method{format}{SpatialDataAttrs}(x) +\S4method{version}{SpatialDataAttrs}(x) -\S4method{format}{SingleCellExperiment}(x) +\S4method{version}{SingleCellExperiment}(x) -\S4method{format}{SpatialData}(x, simplify = TRUE, ...) +\S4method{version}{SpatialData}(x, simplify = TRUE, ...) } \arguments{ \item{simplify}{logical scalar; whether to flatten paths into a tibble.} @@ -38,10 +38,10 @@ zs <- system.file(zs, package="spatialdataR") sd <- readSpatialData(zs) # element-wise -format(shape(sd)) +version(shape(sd)) # object-wide -format(sd) -format(sd, FALSE)$labels +version(sd) +version(sd, FALSE)$labels } From c73c5ed4e91e7b84dbd82dee47cab9d202f69e93 Mon Sep 17 00:00:00 2001 From: Artur-man Date: Sat, 24 Oct 2026 16:43:21 +0200 Subject: [PATCH 05/10] consistent versioning validation for OME and SD --- R/sdAttrs.R | 10 +++++----- R/utils.R | 8 ++++---- 2 files changed, 9 insertions(+), 9 deletions(-) diff --git a/R/sdAttrs.R b/R/sdAttrs.R index 2a9b1263..b716b3f9 100644 --- a/R/sdAttrs.R +++ b/R/sdAttrs.R @@ -94,7 +94,7 @@ SpatialDataAttrs <- \(x, type=c("image", "label", "point", "shape"), \(.) list(label = .))))) res <- c(res, list( - version=.get_ome_version(ver), + version=.ome_ver_from_sd(ver), multiscales= list( list( @@ -199,7 +199,7 @@ setMethod("$", "SpatialDataAttrs", \(x, name) x[[name]]) x$multiscales[[1]]$version %||% x$omero$version %||% x$ome$version - if (!length(v)) stop("couldn't find 'version' in 'spatialdata_attrs'") + if (!length(v)) stop("couldn't find OME-NGFF (OME-Zarr) version") .val_ome_ver(v) } @@ -215,13 +215,13 @@ setMethod("$", "SpatialDataAttrs", \(x, name) x[[name]]) x } -.get_ome_version <- \(x) { +.ome_ver_from_sd <- \(x) { switch(as.character(x), "0.1" = "0.4", "0.2" = "0.4-dev-spatialdata", "0.3" = "0.5-dev-spatialdata", - stop("Invalid SpatialDataImage/Label format/version! ", - "Must be 0.1, 0.2, or 0.3")) + stop("Invalid SpatialData Image/Label element version; ", + "expected '0.x' where x is 1-3")) } # internal use only! diff --git a/R/utils.R b/R/utils.R index 900a0269..c4f6df16 100644 --- a/R/utils.R +++ b/R/utils.R @@ -167,18 +167,18 @@ # validate OME version .val_ome_ver <- \(v) { ok <- length(v) == 1 && is.character(v) && (v <- gsub("-.*", "", v)) %in% sprintf("0.%d", seq_len(6)) - if (!ok) stop("invalid OME 'version'; expected '0.x' where x is 1-6") + if (!ok) stop("invalid OME-NGFF (OME-Zarr) 'version'; expected '0.x' where x is 1-6") return(v) } # validate SpatialData version .val_sd_ver <- \(v, type) { - type <- match.arg(type, c("image", "label", "point", "shape")) + type <- match.arg(type, c("table", "image", "label", "point", "shape")) ok <- length(v) == 1 && is.character(v) && v %in% sprintf("0.%d", seq_len(if(type == "point") 2 else 3)) - if (!ok) stop("invalid SpatialData 'version'; expected '0.x' where x is 1-3 ", - "for image/label/shape and 1-2 for point") + if (!ok) stop("invalid SpatialData element version; expected '0.x' where x is 1-3 ", + "for image/label/shape and 1-2 for point and tables") return(v) } From ea1ec28121876d5466dd2f50698ad60419fcc828 Mon Sep 17 00:00:00 2001 From: Artur-man Date: Sat, 24 Oct 2026 17:16:25 +0200 Subject: [PATCH 06/10] implement tests --- R/utils.R | 2 +- tests/testthat/test-sdattrs.R | 36 +++++++++++++++++++++++++++++++++-- 2 files changed, 35 insertions(+), 3 deletions(-) diff --git a/R/utils.R b/R/utils.R index c4f6df16..688b042d 100644 --- a/R/utils.R +++ b/R/utils.R @@ -178,7 +178,7 @@ is.character(v) && v %in% sprintf("0.%d", seq_len(if(type == "point") 2 else 3)) if (!ok) stop("invalid SpatialData element version; expected '0.x' where x is 1-3 ", - "for image/label/shape and 1-2 for point and tables") + "for image/label/shape and 1-2 for point and table") return(v) } diff --git a/tests/testthat/test-sdattrs.R b/tests/testthat/test-sdattrs.R index 3e75e086..ad2b4413 100644 --- a/tests/testthat/test-sdattrs.R +++ b/tests/testthat/test-sdattrs.R @@ -1,4 +1,21 @@ -z <- list(v1="blobs.zarr", v3="blobs_v3.zarr") +# testing for both SpatialData container versions 0.1 and 0.2 +z <- list(v01="blobs.zarr", v02="blobs_v3.zarr") +zv <- list( + v01 = list( + image = "0.1", + label = "0.1", + point = "0.1", + shape = "0.2", + table = "0.1" + ), + v02 = list( + image = "0.3", + label = "0.3", + point = "0.2", + shape = "0.3", + table = "0.2" + ) +) for (v in names(z)) { @@ -35,7 +52,7 @@ for (v in names(z)) { # missing y <- image(x) switch(v, - "v3"=y@meta$ome$multiscales[[1]]$axes <- NULL, + "v02"=y@meta$ome$multiscales[[1]]$axes <- NULL, y@meta$multiscales[[1]]$axes <- NULL) expect_error(axes(y)) }) @@ -45,6 +62,20 @@ for (v in names(z)) { expect_silent(z <- channels(y <- image(x))) expect_length(z, dim(y)[1]) }) + + test_that("version()", { + vx <- version(x) + expect_s3_class(vx, c("tbl_df", "tbl", "data.frame")) + expect_equal(colnames(vx), + c("layer", "element", "version")) + expect_all_true(vx$layer %in% paste0(names(zv[[v]]), "s")) + for (el in names(zv[[v]])[1:4]) { + f <- match.fun(el) + expect_equal(version(f(x)), zv[[v]][[el]]) + } + # TODO: match.fun matches with base::table + expect_equal(version(table(x)), zv[[v]][["table"]]) + }) } test_that(".val_ome_ver()", { @@ -79,6 +110,7 @@ test_that(".val_sd_ver()", { expect_length(x, 1) expect_identical(x, v) }) + test_that("SpatialDataAttrs()", { # invalid expect_error(SpatialDataAttrs(nch=0)) From 1da270392a3be94307fda7e6cd02fae1397c5480 Mon Sep 17 00:00:00 2001 From: Artur-man Date: Sat, 24 Oct 2026 17:53:28 +0200 Subject: [PATCH 07/10] update NEWS --- inst/NEWS | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/inst/NEWS b/inst/NEWS index 70babde7..fd4d68be 100644 --- a/inst/NEWS +++ b/inst/NEWS @@ -2,6 +2,7 @@ changes in version 0.99.47 - support 'affine' coordinate transformations for point/shape elements via 'duckspatial::ST_affine' +- added 'version()' to retrieve versions of SpatialData container and elements changes in version 0.99.46 @@ -14,7 +15,6 @@ changes in version 0.99.45 - setup auto-benchmarks - add contribution guidelines - code style and efficiency improvements -<<<<<<< HEAD - added read support from S3 object storage for "images", "labels", "points", "shapes" elements - added new 'CTunit()' helper function From 0142a5f2042f1bf64000acd7fbcafc61412a1479 Mon Sep 17 00:00:00 2001 From: Artur-man Date: Sat, 24 Oct 2026 18:10:24 +0200 Subject: [PATCH 08/10] claude review --- R/sdAttrs.R | 2 +- R/utils.R | 6 +++--- man/version.Rd | 4 ++-- tests/testthat/test-sdattrs.R | 2 ++ 4 files changed, 8 insertions(+), 6 deletions(-) diff --git a/R/sdAttrs.R b/R/sdAttrs.R index b716b3f9..dced71ab 100644 --- a/R/sdAttrs.R +++ b/R/sdAttrs.R @@ -402,7 +402,7 @@ setReplaceMethod("instances", c("SingleCellExperiment", "ANY"), \(x, value) { #' @name version #' @title Retrieve versions of \code{SpatialData} elements #' -#' @param object \code{\link{SpatialData}} object or one of its elements. +#' @param x \code{\link{SpatialData}} object or one of its elements. #' @param simplify logical scalar; whether to flatten paths into a tibble. #' @param ... ignored. #' diff --git a/R/utils.R b/R/utils.R index 688b042d..3a6d26a0 100644 --- a/R/utils.R +++ b/R/utils.R @@ -176,9 +176,9 @@ type <- match.arg(type, c("table", "image", "label", "point", "shape")) ok <- length(v) == 1 && is.character(v) && - v %in% sprintf("0.%d", seq_len(if(type == "point") 2 else 3)) - if (!ok) stop("invalid SpatialData element version; expected '0.x' where x is 1-3 ", - "for image/label/shape and 1-2 for point and table") + v %in% sprintf("0.%d", seq_len(if(type %in% c("point", "table")) 2 else 3)) + if (!ok) stop("invalid SpatialData element version; expected '0.x' where ", + "x is 1-3 for image/label/shape and 1-2 for point and table") return(v) } diff --git a/man/version.Rd b/man/version.Rd index f91de9fb..a4013cac 100644 --- a/man/version.Rd +++ b/man/version.Rd @@ -17,11 +17,11 @@ \S4method{version}{SpatialData}(x, simplify = TRUE, ...) } \arguments{ +\item{x}{\code{\link{SpatialData}} object or one of its elements.} + \item{simplify}{logical scalar; whether to flatten paths into a tibble.} \item{...}{ignored.} - -\item{object}{\code{\link{SpatialData}} object or one of its elements.} } \value{ for single elements, a character string; diff --git a/tests/testthat/test-sdattrs.R b/tests/testthat/test-sdattrs.R index ad2b4413..aafe4ee7 100644 --- a/tests/testthat/test-sdattrs.R +++ b/tests/testthat/test-sdattrs.R @@ -101,11 +101,13 @@ test_that(".val_sd_ver()", { expect_error(.val_sd_ver("0.30", "image")) expect_error(.val_sd_ver(c("0.3", "0.4"), "image")) expect_error(.val_sd_ver("0.3", "point")) + expect_error(.val_sd_ver("0.3", "table")) # valid expect_silent(x <- .val_sd_ver(v <- "0.3", "image")) expect_silent(x <- .val_sd_ver(v <- "0.3", "label")) expect_silent(x <- .val_sd_ver(v <- "0.3", "shape")) expect_silent(x <- .val_sd_ver(v <- "0.2", "point")) + expect_silent(x <- .val_sd_ver(v <- "0.2", "table")) expect_type(x, "character") expect_length(x, 1) expect_identical(x, v) From 415e5d5cb947279ca1733b48c4efa2bb38712240 Mon Sep 17 00:00:00 2001 From: Artur-man Date: Sat, 24 Oct 2026 21:44:44 +0200 Subject: [PATCH 09/10] more review --- R/sdAttrs.R | 4 ++-- R/utils.R | 2 +- inst/NEWS | 4 ++-- man/version.Rd | 4 ++-- tests/testthat/test-sdattrs.R | 14 +++----------- 5 files changed, 10 insertions(+), 18 deletions(-) diff --git a/R/sdAttrs.R b/R/sdAttrs.R index dced71ab..2db2cdb8 100644 --- a/R/sdAttrs.R +++ b/R/sdAttrs.R @@ -409,8 +409,8 @@ setReplaceMethod("instances", c("SingleCellExperiment", "ANY"), \(x, value) { #' @returns #' for single elements, a character string; #' for \link{SpatialData} objects, if \code{simplify=TRUE} (default), -#' a \code{tibble} where rows=elements and columns=layers/elements/paths. -#' if \code{simplify=FALSE}, a depth-3 list where levels=layers/elements/paths. +#' a \code{tibble} where rows=elements and columns=layers/elements/versions. +#' if \code{simplify=FALSE}, a depth-3 list where levels=layers/elements/versions. #' #' @examples #' zs <- file.path("extdata", "blobs.zarr") diff --git a/R/utils.R b/R/utils.R index 3a6d26a0..ba7dfb8b 100644 --- a/R/utils.R +++ b/R/utils.R @@ -242,4 +242,4 @@ if (!is.null(df)) names(df)[3] <- col df -} \ No newline at end of file +} diff --git a/inst/NEWS b/inst/NEWS index fd4d68be..7cdbec57 100644 --- a/inst/NEWS +++ b/inst/NEWS @@ -2,7 +2,7 @@ changes in version 0.99.47 - support 'affine' coordinate transformations for point/shape elements via 'duckspatial::ST_affine' -- added 'version()' to retrieve versions of SpatialData container and elements +- added 'version()' to retrieve format versions of SpatialData elements changes in version 0.99.46 @@ -54,7 +54,7 @@ changes in version 0.99.39 - class revision: SpatialData slots were base::list, now prototyped S4Vectors::SimpleList with layer-specific properties & validation -- added 'path()' to retrieve on-disk paths of spatial data elements +- added 'path()' to retrieve on-disk paths of SpatialData elements changes in version 0.99.38 diff --git a/man/version.Rd b/man/version.Rd index a4013cac..1bc09b6e 100644 --- a/man/version.Rd +++ b/man/version.Rd @@ -26,8 +26,8 @@ \value{ for single elements, a character string; for \link{SpatialData} objects, if \code{simplify=TRUE} (default), -a \code{tibble} where rows=elements and columns=layers/elements/paths. -if \code{simplify=FALSE}, a depth-3 list where levels=layers/elements/paths. +a \code{tibble} where rows=elements and columns=layers/elements/versions. +if \code{simplify=FALSE}, a depth-3 list where levels=layers/elements/versions. } \description{ Retrieve versions of \code{SpatialData} elements diff --git a/tests/testthat/test-sdattrs.R b/tests/testthat/test-sdattrs.R index aafe4ee7..7df6db1a 100644 --- a/tests/testthat/test-sdattrs.R +++ b/tests/testthat/test-sdattrs.R @@ -2,18 +2,10 @@ z <- list(v01="blobs.zarr", v02="blobs_v3.zarr") zv <- list( v01 = list( - image = "0.1", - label = "0.1", - point = "0.1", - shape = "0.2", - table = "0.1" + image="0.1", label="0.1", point="0.1", shape="0.2", table="0.1" ), v02 = list( - image = "0.3", - label = "0.3", - point = "0.2", - shape = "0.3", - table = "0.2" + image="0.3", label="0.3", point="0.2", shape="0.3", table="0.2" ) ) @@ -73,7 +65,7 @@ for (v in names(z)) { f <- match.fun(el) expect_equal(version(f(x)), zv[[v]][[el]]) } - # TODO: match.fun matches with base::table + # match.fun matches with base::table expect_equal(version(table(x)), zv[[v]][["table"]]) }) } From 5699a41f0e49ae36a04f5f70b5451ab2c11832a6 Mon Sep 17 00:00:00 2001 From: Artur-man Date: Thu, 29 Oct 2026 10:23:05 +0100 Subject: [PATCH 10/10] add PR tags to NEWS --- inst/NEWS | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/inst/NEWS b/inst/NEWS index 7cdbec57..c347c882 100644 --- a/inst/NEWS +++ b/inst/NEWS @@ -1,8 +1,8 @@ changes in version 0.99.47 - support 'affine' coordinate transformations for - point/shape elements via 'duckspatial::ST_affine' -- added 'version()' to retrieve format versions of SpatialData elements + point/shape elements via 'duckspatial::ST_affine' (#276) +- added 'version()' to retrieve format versions of SpatialData elements (#288) changes in version 0.99.46