Writes a QPTIFFImage as a multi-page 16-bit grayscale
OME-TIFF (one page per channel). The first page carries an OME-XML
ImageDescription (tag 270) that declares the pages as channels
(SizeC = nChannels, SizeZ = SizeT = 1), so viewers such as
QuPath / Bio-Formats interpret each page as a channel rather than a
timepoint. Per-channel bgnorm results are embedded so the file is
self-documenting and round-trips through read_qptiff.
Arguments
- x
A
QPTIFFImage(eager or lazy).- path
Output file path (character scalar). The directory must exist.
Intensity transform
- bgnorm-adjusted images
The QPTIFFImage stores background-adjusted log\(_2\)-intensities. These are inverted with \(2^x\) before writing so the output values are in a linear intensity scale.
- Raw images (no bgnorm results)
Written as-is; values are assumed to be in
[0, 65535].
All output values are rounded to the nearest integer and clamped to the
[0, 65535] range before being written as 16-bit unsigned integers.
The native, Java-free TIFF/QPTIFF reader and writer implemented here was translated from the bioio-tifffile fork by Rafael Tubelleza.
Metadata
The first page's ImageDescription tag (TIFF tag 270) is an OME-XML
document. Its <Pixels> element declares SizeC = nChannels
with one <Channel Name="..."> per channel and an explicit
<TiffData> page-to-channel mapping, which is what makes downstream
viewers read the pages as channels. Channel 0's bgnorm metadata is appended
to the OME root as no-namespace elements (ignored by OME readers but read
back by read_qptiff); pages 1..n each carry a minimal
PerkinElmerQPI block:
<PerkinElmerQPI>
<Biomarker>CD20</Biomarker>
<transform>2^x</transform>
<bgnorm>{"level":"pixel","jsd":0.35,...}</bgnorm>
</PerkinElmerQPI>
The <Biomarker> element is the channel name; <bgnorm> holds a
JSON object with GMM parameters, JSD, threshold, and normalisation flags
(only present for bgnorm-adjusted images). If jsonlite is not
installed, the <bgnorm> element is omitted.
Examples
path <- system.file("extdata", "PA_HNC_sample.ome.tiff", package = "bgnormR")
img <- read_qptiff(path)
#> Reading TIFF directory structure ...
#> Reading OME-TIFF metadata ...
#> Reading IFD page layouts ...
#> Loading 5 channel(s) ...
#> Loading 5 channel(s) ...
res <- bgnorm_pixels(img, sample_prop = 0.1)
out <- file.path(tempdir(), "PA_HNC_bgnorm.tif")
write_qptiff(res, out)
# Round-trip: channel names and dimensions are preserved
img2 <- read_qptiff(out)
#> Reading TIFF directory structure ...
#> Reading OME-TIFF metadata ...
#> Reading IFD page layouts ...
#> Loading 5 channel(s) ...
#> Loading 5 channel(s) ...
names(img2)
#> [1] "CD20" "CD3e" "CD8" "PanCK" "Vimentin"
dim(img2)
#> [1] 550 800 5