|
1 | | -# convenience functions until this is fixed/exported by 'SpatialData' |
| 1 | +# internal helper for null-coalescing |
| 2 | +`%||%` <- \(a, b) if (is.null(a)) b else a |
2 | 3 |
|
3 | 4 | #' @importFrom methods is |
4 | 5 | #' @importFrom SingleCellExperiment int_metadata |
|
65 | 66 | .project <- \(x, y, z=NULL) { |
66 | 67 | # max-projection over z-stacks |
67 | 68 | axisNames <- axes(x, y="name") |
68 | | - zidx <- which(axisNames=="z") |
69 | | - if (length(zidx)>0) { |
| 69 | + zidx <- which(axisNames == "z") |
| 70 | + if (length(zidx) > 0) { |
70 | 71 | if (is.null(z)) { |
71 | 72 | # max-projection across z-slices |
72 | 73 | y <- apply(y, seq_along(dim(x))[-zidx], max) |
73 | 74 | } else { |
74 | | - if (length(z)>1) { |
75 | | - stop("Only a single z-plane can be selected") |
76 | | - } |
| 75 | + if (length(z) > 1) stop("only a single z-plane can be selected") |
77 | 76 | # subset target z-slice |
78 | | - y <- .subset_array_by_axes(a=y, axisNames=axisNames, |
79 | | - z=z, drop=FALSE) |
80 | | - dim(y) <- dim(y)[axisNames!="z"] |
| 77 | + y <- .subset_array_by_axes(a=y, axisNames=axisNames, z=z, drop=FALSE) |
| 78 | + dim(y) <- dim(y)[axisNames != "z"] |
81 | 79 | } |
82 | 80 | } |
83 | 81 | y |
|
116 | 114 | } |
117 | 115 |
|
118 | 116 | .subset_array_by_axes <- \(a, axisNames, ..., drop=FALSE) { |
119 | | - if (length(dim(a)) != length(axisNames)) { |
120 | | - stop("axisNames must have the same length as the number of dimensions of x") |
121 | | - } |
| 117 | + # this should never be trigger as object validity should prevent it |
| 118 | + ok <- length(dim(a)) == length(axisNames) |
| 119 | + if (!ok) stop("'length(axes(x))' must equal 'length(dim(x))'") |
122 | 120 | specs <- list(...) |
123 | 121 | idx <- lapply(axisNames, \(nm) { |
124 | 122 | if (!is.null(specs[[nm]])) { |
|
130 | 128 | do.call("[", c(list(a), idx, list(drop=drop))) |
131 | 129 | } |
132 | 130 |
|
133 | | -.unit_map <- c(micrometer="\U03BCm", |
134 | | - micron="\U03BCm") |
135 | | - |
136 | | -#' Create scalebar for image |
137 | | -#' |
138 | | -#' @param x A \code{SpatialDataArray} object. |
139 | | -#' @param l A numeric scalar giving the length of the scalebar (in global |
140 | | -#' coordinates). The unit will be extracted from the metadata of \code{x}. |
141 | | -#' @param xrel,yrel Numeric scalars between 0 and 1 indicating the relative |
142 | | -#' x and y position of the scalebar. |
143 | | -#' @param color Character scalar indicating the color to use for the scalebar. |
144 | | -#' @param linewidth Numeric scalar indicating the line width to use for the |
145 | | -#' scalebar. |
146 | | -#' |
147 | | -#' @examples |
148 | | -#' x <- file.path("extdata", "blobs.zarr") |
149 | | -#' x <- system.file(x, package="spatialdataR") |
150 | | -#' x <- readSpatialData(x, tables=FALSE) |
151 | | -#' plotSpatialData() + |
152 | | -#' plotImage(x, i=2) + |
153 | | -#' scalebar(image(x, i=2), l=10) |
154 | | -#' |
155 | | -#' @importFrom ggplot2 annotate |
156 | | -#' @export |
157 | | -scalebar <- function(x, l, xrel=0.05, yrel=0.05, |
158 | | - color="red", linewidth=1) { |
159 | | - unit <- axes(x)[[which(axes(x, y="name")=="x")]]$unit |
160 | | - if (unit %in% names(.unit_map)) { |
161 | | - unit <- .unit_map[unit] |
162 | | - } |
163 | | - wh <- .get_wh(x) |
164 | | - if (xrel<=0.5) { |
165 | | - xmin <- diff(wh$w) * xrel + wh$w[1] |
166 | | - xmax <- diff(wh$w) * xrel + wh$w[1] + l |
167 | | - } else { |
168 | | - xmin <- wh$w[2] - diff(wh$w) * (1 - xrel) - l |
169 | | - xmax <- wh$w[2] - diff(wh$w) * (1 - xrel) |
170 | | - } |
171 | | - y <- wh$h[2] - diff(wh$h) * yrel |
172 | | - list(annotate(geom="segment", x=xmin, xend=xmax, y=y, yend=y, |
173 | | - color=color, linewidth=linewidth), |
174 | | - annotate(geom="text", x=(xmin+xmax)/2, y=y, |
175 | | - vjust=ifelse(yrel>0.5,1.5,-0.5), |
176 | | - color=color, label=paste0(l, unit))) |
177 | | -} |
178 | | - |
| 131 | +.unit_map <- c(micrometer="\U03BCm", micron="\U03BCm") |
0 commit comments