Opening multi-image Aperio .scn files


We have a number of Aperio VERSA .scn files that we are trying to open with QuPath. I’ve attached the OME-XML header below of a representative scn file.


The problem we’ve encountered is that because of a tissue detection step to minimize imaging empty areas during the acquisition process, the resulting scanned areas are stored as separate pyramids in the header (Images 13 to 19 for the first sample, vs Images 20 to 26 for the second sample). These images can be opened as a single overall pyramid with Aperio ImageScope, but opening in QuPath results in four new pyramids (macro, overall grayscale, sample1, sample 2), and opening in ImageJ results in 28 different images (not pyramids).

Interestingly, the rendered output in ImageScope somehow properly overlays the sub-images on top of the overall grayscale pyramid (Images 6 to 12, possibly from the tissue detection step), which seems to get assigned to the first spectral channel (any dust in the overall grayscale pyramid is colored as if it were in the DAPI channel of the sub-images). The overall grayscale pyramid’s microns-per-pixel values also align with that of the sub-images’ pyramids.

ImageScope is also able to get spectral channel names, which are not in the OME-XML header, but that seems a bit too deep of a dive for now.

As for the offsets, there is a Plane tag within the sub-images’ Pixel tags that contains information about the offset from some origin in ‘reference frame’ units ((7,141,569, 15,485,926) for sample 1, (9,401,199, 30,563,639) for sample 2). I’m wondering if it’d be possible to somehow leverage this information to render the scn file like ImageScope does.

This wouldn’t normally be a big deal, but because we are now generating dozens of multiplexed IF slides a month, we would like to be able to analyze these slides at moderate throughput through QuPath. I’d appreciate any guidance on how to support this in QuPath and if I’ve missed any important details here.

Thank you,
Sebastian Ahn

I would recommend hosting the file itself somewhere free so that a developer can take a look at it. If there are similar problems in BioFormats in FIJI, I’m not sure QuPath will be able to do much here, as it relies on BioFormats to interpret the files, mostly.

Other important questions:
Which version of QuPath?
If 1.2, which version of BioFormats, or is it using OpenSlide? Essentially, which server?
If 0.2.0M#, are you opening it in a project vs as an individual file?

I am using QuPath 0.2.0-m8, which according to the gradle build file uses bioformats 6.3.0. I made a dummy project with an empty folder, and used the Bioformats builder to import the scn file. The openslide builder throws an error during import.

I was thinking of writing something in a qupath extension to help me display multiple images with offsets in the QuPathViewer(Plus). I’m just not sure at this point if that is technically feasible.

Here’s a dropbox link to an scn file with only one identified region, but the principle is the same. Opening this in ImageJ using the bioformats plugin gives 22 images, and opening this in QuPath gives 3 pyramids (macro, overall grayscale, and sample 1). I unfortunately don’t have any scn files with more than one sample that I can provide publicly at the moment.

1 Like

Hmm, ok, this is what I am seeing, which, as far as I know, is the expected output from a .scn whole slide image:
If you want to run scripts on specific subsets of files, you will need to control that by metadata. For example, in this case, I would put an if statement at the beginning of the script that checked whether the pixel size was smaller than 0.5 um. Though it is weird that your pixel sizes aren’t square, and that could cause problems with other aspects of QuPath down the line. I seem to remember running into a problem with that somewhere else, but I can’t remember exactly where.

Running this for project with a group of such SCN files should show scenes you want to avoid as ignored.

def imageData = getCurrentImageData()
def server = getCurrentServer()
def cal = server.getPixelCalibration()

if( cal.getAveragedPixelSizeMicrons() < 0.5){
    print imageData
} else{println(imageData.toString()+" ignored")}

Yup, that’s what I see as well, but if there are, say, two sub-images, what I see is the following:
which is not ideal. What I’d like to have is both Series 2 and 3 open at the same time and in the same viewer, but offset by the distance specified in the Position{X,Y} attributes in the Plane tag in the OME-XML header, so that what I am seeing looks like this:
This is how ImageScope renders the two-sample scn. I hope that clears things up.

Thanks for the code snippet!

Should be possible through
I once wrote a script to try this out and have considered adding ‘scene positioning’ as a feature but haven’t got around to it yet… figuring out exactly where things should go (and how ‘empty’ regions should be handled) is a bit tricky.

See also Y coordinate direction for plane position and image pixels are not consistent across formats

Provided they are fairly close and in the same units, I’m not aware of/don’t recall any issues with this (beyond the fact it’s weird).


Excellent! I’ll take a look at those links.
That’s pretty great that you already have classes for this.

Ah, it was the NAN eccentricities showing up for all cell measurements through some ImageJ calculation.