vignettes/reading_image_files.Rmd
reading_image_files.Rmd
inForm writes a variety of image files in JPEG and TIFF format. This tutorial shows how to read the image files in R.
The R packages tiff
and jpeg
provide functions readTIFF
and readJPEG
which read image data into R matrices. phenoptr
expands on these with read_components
and read_maps
which read multiple images and extract useful metadata from the Image Description fields.
A variety of functions can display image data including plot.raster
, ggplot2::annotation_raster
and EBImage::display
.
A few items to note:
Images have the origin (0, 0) at the top left. This is consistent with the Cell X Position
and Cell Y Position
columns of an inForm cell seg table. The row (first) dimension of an array corresponds to the \(y\) axis and Cell Y Position
column. The column (second) array dimension corresponds to the \(x\) axis and the Cell X Position
column.
Image dimensions are in pixels. Cell seg tables are written with pixel dimensions and converted to microns when read by phenoptr::read_cell_seg_data
.
Image display methods differ in their orientation; some show \(x\) and \(y\) as described above; others transpose the image.
Each of these items easily causes confusion; be careful and verify your work!
Color (RGB) images output from inForm, such as the composite image and segmentation images, can be read directly using tiff::readTIFF()
or jpeg::readJPEG()
. For example,
path <- system.file("extdata", "sample",
"Set4_1-6plex_[16142,55840]_composite_image.jpg",
package = "phenoptr")
img <- jpeg::readJPEG(path)
dim(img)
[1] 1400 1868 3
Color images are read as 3D arrays. They can be displayed by converting to a raster.
EBImage::display
will display an array in a web browser. RGB images are shown as three grayscale planes unless converted to an EBImage::Image
first. EBImage::display
shows the first coordinate horizontally and the second coordinate vertically so the image must be flipped to display in the expected orientation.
img_transposed <- aperm(img, c(2, 1, 3))
EBImage::display(img_transposed)
EBImage::display(EBImage::Image(img_transposed, colormode='Color'))
inForm saves component data as multiple 32-bit floating-point images within a single TIFF file. Images smaller than 2K by 2K pixels are saved in “strip” format and may be read by tiff::readTIFF()
. Larger images are saved in “tiled” format which is not supported by readTIFF()
. Single fields from Vectra Polaris, Vectra 3 and Mantra are all smaller than 2K by 2K and may be read by these functions; larger fields may not read. Install the Akoya Biosciences fork of the tiff package to support tiled images and remove this limitation.
phenoptr::read_components()
is a wrapper around readTIFF()
which reads the individual component images from a component_data.tif
file. It keeps the full-resolution component images, extracts the component names from the image descriptions, and returns a named list of image matrices.
Component data may be displayed using plot.raster
or EBImage::display
. See the next section for examples of displaying grayscale images such as these.
inForm saves segmentation maps (nuclear segmentation, etc.) as multiple 16-bit grayscale images within a single TIFF file. Most segmentation images are label images, where each object is represented by a region whose value is the object number. The membrane map is a binary image where the presence of membrane is indicated with a “1” value.
phenoptr::read_maps()
is a wrapper around readTIFF()
which reads map files. It returns a named list of integer-valued matrices. The list names reflect the content of the individual images, e.g. Nucleus, Cytoplasm, etc.
map_path <- system.file("extdata", "sample",
"Set4_1-6plex_[16142,55840]_binary_seg_maps.tif", package = "phenoptr")
maps <- phenoptr::read_maps(map_path)
names(maps)
[1] "Nucleus" "Cytoplasm" "Membrane" "Tissue"
The Nucleus label image contains values for background (0) and each Cell ID.
nucleus <- maps[['Nucleus']]
dim(nucleus)
[1] 1400 1868
range(nucleus)
[1] 0 6183
range(phenoptr::sample_cell_seg_data$`Cell ID`)
[1] 11 6183
Label images may be displayed with plot.raster
or EBImage::display
(which requires swapping axes).
nucleus_snippet <- nucleus[800:1000, 1200:1500]
plot(as.raster(nucleus_snippet, max=max(nucleus_snippet)))
Images have the origin (0, 0) at the top left. This is consistent with the Cell X Position
and Cell Y Position
columns of an inForm cell seg table but it is reversed (in \(y\)) from the usual plotting conventions. If you plot images and points together, you will have to reverse one or the other.
Here is an example using ggplot2
. The \(y\)-axis is reversed using ggplot2::scale_y_reverse()
and the image is then un-reversed by negating its \(y\) limits.
library(ggplot2)
csd <- phenoptr::sample_cell_seg_data
csd <- subset(csd, `Cell X Position`>=600 & `Cell X Position`<=750 &
`Cell Y Position`>=400 & `Cell Y Position`<=500)
ggplot(data=csd, aes(`Cell X Position`, `Cell Y Position`, color=Phenotype)) +
scale_x_continuous(limits=c(600, 750)) +
scale_y_reverse(limits=c(500, 400)) +
annotation_raster(snippet, 600, 750, -400, -500) +
geom_point(size=2) + coord_equal() +
scale_color_manual(values=c("CK+"="cyan", "CD8+"="yellow",
"other"="blue", "CD68+"="magenta",
"FoxP3+"="orange")) +
theme_minimal()