1010# ' @param k index of the scale of an image; by default (NULL), will auto-select
1111# ' scale in order to minimize memory-usage and blurring for a target size of
1212# ' 800 x 800px; use Inf to plot the lowest resolution available.
13+ # ' @param ch image channel(s) to be used for plotting (defaults to
14+ # ' the first channel(s) available); use \code{channels()} to see
15+ # ' which channels are available for a given \code{ImageArray}
16+ # '
17+ # ' @param c plotting aesthetics; color
1318# '
1419# ' @return ggplot
1520# '
3136# ' @export
3237plotSpatialData <- \() ggplot() + scale_y_reverse() + .theme
3338
39+ # merge/manage image channels
40+ # if no colors and channels defined, return the first channel
41+ # ' @importFrom grDevices col2rgb
42+ # ' @noRd
43+ .manage_channels <- \(a , ch , c = NULL ){
44+ if (length(ch ) > (n <- length(.DEFAULT_COLORS )) && is.null(c ))
45+ stop(" Only " , n , " default colors available, but" ,
46+ length(ch ), " are needed; please specify 'c'" )
47+ if (! is.null(c ) || (is.null(c ) && length(ch ) > 1 )) {
48+ if (is.null(c )) c <- .DEFAULT_COLORS [seq_along(ch )]
49+ c <- col2rgb(c )/ 255
50+ b <- array (0 , dim = c(3 , dim(a )[- 1 ]))
51+ for (i in seq_len(dim(a )[1 ])) {
52+ b [1 ,,] <- b [1 ,,,drop = FALSE ] + a [i ,,,drop = FALSE ]* c [1 ,i ]
53+ b [2 ,,] <- b [2 ,,,drop = FALSE ] + a [i ,,,drop = FALSE ]* c [2 ,i ]
54+ b [3 ,,] <- b [3 ,,,drop = FALSE ] + a [i ,,,drop = FALSE ]* c [3 ,i ]
55+ }
56+ a <- pmin(b , 1 )
57+ } else {
58+ a <- a [rep(1 , 3 ), , ]
59+ }
60+ return (a )
61+ }
62+
63+ # check if an image is rgb or not
64+ # ' @importFrom SpatialData getZarrArrayPath
65+ # ' @importFrom Rarr zarr_overview
66+ # ' @noRd
67+ .get_image_dtype <- \(a ) {
68+ pa <- getZarrArrayPath(a )
69+ df <- zarr_overview(pa , as_data_frame = TRUE )
70+ if (! is.null(dt <- df $ data_type )) return (dt )
71+ }
72+
73+ # normalize the image data given its data type
74+ # ' @noRd
75+ .normalize_image_array <- \(a , dt ){
76+ if (dt %in% names(.DTYPE_MAX_VALUES )) {
77+ a <- a / .DTYPE_MAX_VALUES [dt ]
78+ } else if (max(a ) > 1 ) {
79+ for (i in seq_len(dim(a )[1 ]))
80+ a [i ,,] <- a [i ,,]/ max(a [i ,,])
81+ }
82+ return (a )
83+ }
84+
85+ # check if an image is RGB or not
86+ # (NOTE: some RGB channels are named 0, 1, 2)
87+ # ' @importFrom methods is
88+ # ' @noRd
89+ .is_rgb <- \(x ) {
90+ if (is(x , " ImageArray" ) &&
91+ ! is.null(md <- meta(x )))
92+ x <- md $ omero $ channels $ label
93+ if (! is.vector(x )) stop(" invalid 'x'" )
94+ is_len <- length(x ) == 3
95+ is_012 <- setequal(x , seq(0 , 2 ))
96+ is_rgb <- setequal(x , c(" r" , " g" , " b" ))
97+ return (is_len && (is_012 || is_rgb ))
98+ }
99+
100+ # check if channels are indices or channel names
101+ # ' @importFrom SpatialData channels
102+ # ' @noRd
103+ .ch_idx <- \(x , ch ) {
104+ if (is.null(ch ))
105+ return (1 )
106+ lbs <- channels(x )
107+ if (all(ch %in% lbs )) {
108+ return (match(ch , lbs ))
109+ } else if (! any(ch %in% lbs )) {
110+ warning(" Couldn't find some channels; picking first one(s)!" )
111+ return (1 )
112+ } else {
113+ warning(" Couldn't find channels; picking first one(s)!" )
114+ return (1 )
115+ }
116+ return (NULL )
117+ }
118+
34119.guess_scale <- \(x , w , h ) {
35120 n <- length(dim(x ))
36121 i <- ifelse(n == 3 , - 1 , TRUE )
@@ -47,14 +132,17 @@ plotSpatialData <- \() ggplot() + scale_y_reverse() + .theme
47132# ' @importFrom methods as
48133# ' @importFrom grDevices rgb
49134# ' @importFrom DelayedArray realize
50- .df_i <- \(x , k = NULL ) {
135+ .df_i <- \(x , k = NULL , ch = NULL , c = NULL ) {
51136 a <- .get_plot_data(x , k )
52- a <- if (dim(a )[1 ] == 1 ) a [rep(1 ,3 ),,] else a
137+ ch_i <- .ch_idx(x , ch )
138+ if (! .is_rgb(x ))
139+ a <- a [ch_i , , , drop = FALSE ]
140+ dt <- .get_image_dtype(a )
53141 a <- realize(as(a , " DelayedArray" ))
54- img <- rgb(
55- maxColorValue = max( a ),
56- c( a [ 1 ,,]), c( a [ 2 ,,]), c( a [ 3 ,,]) )
57- array ( img , dim( a )[ - 1 ])
142+ a <- .normalize_image_array( a , dt )
143+ if ( ! .is_rgb( x ))
144+ a <- .manage_channels( a , ch_i , c )
145+ apply( a , c( 2 , 3 ), \( . ) do.call( rgb , as.list( . )))
58146}
59147
60148.get_wh <- \(x , i , j ) {
@@ -75,13 +163,13 @@ plotSpatialData <- \() ggplot() + scale_y_reverse() + .theme
75163
76164# ' @rdname plotImage
77165# ' @export
78- setMethod ("plotImage ", "SpatialData", \(x, i=1, j=1, k=NULL) {
79- if (is.numeric(i ))
166+ setMethod ("plotImage ", "SpatialData", \(x, i=1, j=1, k=NULL, ch=NULL, c=NULL ) {
167+ if (is.numeric(i ))
80168 i <- imageNames(x )[i ]
81169 y <- image(x , i )
82- if (is.numeric(j ))
170+ if (is.numeric(j ))
83171 j <- CTname(y )[j ]
84- df <- .df_i(y , k )
172+ df <- .df_i(y , k , ch , c )
85173 wh <- .get_wh(x , i , j )
86174 .gg_i(df , wh $ w , wh $ h )
87175})
0 commit comments