Quantifying DAB Stain Intensity Across Whole Slides

Hello All,

Long time user, new poster!

I’m looking into how different tissue processing techniques affect the final outcomes of immunohistochemistry. One of the parameters I’m looking at will be DAB staining intensity. I thought QuPath could help solve this quickly with a batch process.

My idea is to create a script that performs automated tissue detection, cell detection, then exports the detection measurements. I’ll then look at the range (Max and Min) of all measurements on each slide. I’ll have a range and a mean DAB Max to use per technique.

I have hundreds of slides to analyse, so I’m hopeful that even though I’m not analysing serial sections, I can get an idea of if the DAB staining is in any way impacted by these different techniques. I also have multiple antibodies to test and on several different tissue types.

I have a few questions:

  1. Should I set the stain vectors automatically per slide, set the stain vectors to a specific slide, or not assign them at all? I’m wondering if not assigning the stain vectors would give an arbitrary baseline, as all I’m looking at is DAB intensity.

  2. Is cell detection the best way to define the detection area? Could a pixel or SLIC based ‘tiling’ give me better workflows or more streamlined data?

I’m currently working on the old version of QuPath as I’m on a University computer and can’t update with without IT Permissions, so I’m appreciate legacy type instructions. Suggestions for the new milestone QuPath version obviously welcome for when I get it updated but just a note to say I can’t test these methods at this point…

Many thanks!

See point 2 in this post:


Provided you are scanning everything on the same scanner at approximately the same time (lenses get dirty, light sources die out, calibrations can have a major impact on brightness and evenness of the field), I would recommend keeping one set of color vectors for all of your images, regardless of how you settle on them.

You might consider the Create Cytokeratin annotations command in Analyze -> Region Identification to isolate areas of darker tissues, or go with SLICs. If time is not a huge concern, I would go SLICs, with the reasoning being that you are interested in the DAB staining, and light cytoplasmic DAB staining pretty much requires hematoxylin cell detection in order to not pick up a lot of weird background, while dark DAB staining on, for example, T-Cells, usually requires some kind of OD sum due to the nucleus being mostly obscured in many of the cells. I am not sure what all the variety of antibodies you are testing are targeting, so hard to make much more of a recommendation.

While it is somewhat unfortunate in terms of “picking a threshold,” I would recommend getting a negative control to use as a baseline and classify the SLICs that way as positive or negative, and then either use a +1, +2, +3 scheme (blech) or find the distribution of intensities as you mentioned. While @gabriel is correct that chromogenic staining is not quantitative (the links are well worth going through), how dark the stain is has been used to measure expression for quite some time. Pathologists pretty much depend on it. Just be sure to state your assumptions and that you know your results are not indicative of actual protein concentration, and that any comparison between antibodies is almost meaningless (other than, “it looks like it stains better, here’s some numbers”) :slight_smile:

*Not an expert, all advice here open to being refuted!

1 Like

Some of the comments above need clarification. IHC intensity is not about protein expression directly, but only indirectly after antigen detection and an amplification chain ending up in chromogen precipitation (all of those non-stoichiometric).
Pathogists do not really “pretty much depend on measuring expression”. Only a handful of very much controlled monoclonal antibodies sold for “clinical use” are batch tested and retested and finally “scored” after observer calibration (but still not properly “intensity quantified” in the sense of videodensitometry).
In tumour pathology IHC is of course heavily used for various things including typing tumours, but not really quantitatively (most antibodies clearly state “not for clinical use”). There is a big difference between assigning arbitrary -, +, ++ and +++ and extracting optical density values and doing stats on those numbers.


I suppose the aim here is to prove to a pathology lab that changing tissue processing techniques won’t change what a pathologist sees through their microscope. I’m under no illusions that IHC itself is a quantitative technique, only that our new tissue processing techniques do not re-characterise the interactions between antibody and antigen. As far as we can see, the staining seems to be uniform across treatment groups, but I’m looking at a way to show this through the (relatively) impartial eye of QuPath. I think people would prefer some indicative numbers rather than to trust their own eyes sometimes.

I’ve been playing round with SLIC’s here RA, I think it seems like the way to go. I think will be adding intensity features for mean, max and min DAB staining intensity. Is there a best way to work out the preferred pixel size when adding the intensity features?

You know that it is not quantitative… but want to show others “indicative numbers”? That makes no sense at all.
Changing processing techniques is most likely to change results. There is a reason why there are standard protocols for everything and to try to achieve reproducibility.

Thanks, Gabriel. I’m trying to think of a way of quantifying or inferring the change in results, to see if the change in technique has any deleterious effects.

Do you think it is inherently not possible?

Unless you are in a particular rush, I would use the actual pixel size listed in the Image tab metadata.

If you are doing this in bulk and want relatively simple calculations, it might be cleanest to do the calculations within QuPath. Though it depends on how comfortable you are coding :slight_smile:

  1. Tissue detection/color vectors
  2. Generate SLICs
  3. Add measurements
  4. Classify SLICs using a one line code; this could allow you to use a +1,+2,+3 split on your data at this point if you want. Or only include a single value for positive/negative.
    setIntensityClassifications(qupath.lib.objects.PathTileObject, "Nucleus: DAB OD mean" , 0.22, 0.25, 0.33);
  5. Calculate your mean/min/max for your positive SLICs, more on creating measurements and applying them to annotations here.
  6. Export using two of Pete’s scripts from this blog post and the next one.

The second script in step 6 would be run separately, while the first tacked on to the end of the larger script that runs everything else. The result would be a multiline file you could open in Excel with a set of values for your summary measurements for an annotation/tissue slice.

Or if you are exporting the detection measurements, you can strip out most of the values by listing the measurements of interest after the string targeting the save.

saveDetectionMeasurements(“C://mypathhere”, “Nucleus: DAB OD mean”, “Nucleus: DAB OD max”)

Thanks @Research_Associate, that’s pretty much exactly what I was hoping to do. I hadn’t seen Pete’s blog posts about how to collate the data afterwards, that will be incredibly helpful.

Can you set intensity classifications by ROI measurements, like you have done for Detections (nucleus) there? I attempted it with:

setIntensityClassifications(qupath.lib.objects.PathTileObject, “ROI: 0.50 μm per pixel: DAB: Median” , 0.1,);

but to no avail. Is it a different type of object?

Interesting topic! Some thoughts…

  • I’d be uneasy about doing much with the DAB ‘intensity’ values QuPath is able to provide because of all the concerns raised by @gabriel - I do occasionally wonder if QuPath makes more things possible than it should…
  • Even if you do decide to report some measurements alongside lots of caveats*, I’d want to avoid basing much on min/max measurements since these are easily influenced by outliers. Even for fluorescence or something more quantitative, min and max likely aren’t robust enough…
  • The ‘noninferiority’ of using whole slide images rather than microscopy is an active topic, quite apart from your tissue preparation, e.g. here.
  • It sounds like what you actually want to measure isn’t really a direct property of the image, but perception of a pathologist… right?

If the last point is correct, might it be more meaningful/less objectionable to present a pathologist with different images and for them in some way / attempt to distinguish any ‘abnormal’ appearance in terms of staining?

Note that if you have a project in v0.2.0-m2, under Edit → Preferences… you can choose to Mask image names in project to help perform a more blinded evaluation.

From your description, this sounds to me like what you want to really assess: can pathologists tell the difference, and/or does their interpretation change with changes in preparation.

*-I’d still prefer to avoid this, since caveats are so easily forgotten or ignored…

1 Like

Thanks @petebankhead, I see the reasoning, obviously. I can’t disagree. Question is, as Gabriel said, we keep processing and staining protocols consistent to minimise variations in the final results, but is it possible to quantify these variations?

They are obviously there, and we can pick up on them using our/a pathologist’s eyes.Would it be disingenuous to put a number to that difference because of the issues with quantification vs illustration? It seems the answer is yes, but I had hoped with some tweaks to the design it could be no.

My aim was less to talk about quantification of the specific epitope, and more to see if I could identify a staining pattern or signature. To see if the staining could be diminished or if antigen retrieval/unmasking was inhibited by alternate sample preparation.

For your second point, I am aiming to take a median of the min/max values in positively stained SLIC’s, although this plan isn’t without its downsides.

And your fourth point; yes, perhaps.I thought maybe the perceptions of a pathologist could be aided by some numbers. We have access to the perceptions of pathologists already, thankfully :).

You can, however it can be tricky. The spacing can be inconsistent when splicing together various parts of the name, so it is best to copy it out from the measurements list. Also, if you are using 0.1.2, you will probably want to replace the micrometer symbol since reloading the script will mangle it. See the very bottom line of that non-script table of contents. This is no longer the case in 0.1.3 or 0.2.0.

And I’m glad gabriel and Pete have brought up all of the other points, but you seem to have a good grasp of what is going on. I will repeat Pete’s point recommending not using the min/max values, even in bulk, though. There is the option for creating a Median measurement when you are making your detection measurements. It does remind me of the QuPath workshop in San Diego where we spent a few talks looking at how various conditions could impact H&E staining, and I think it is a good idea to have an unbiased idea about what is going on to back up the pathologist’s review. The human eye/brain is a terrible and powerful thing, prone to all sorts of nonsense :slight_smile:

@petebankhead Interesting link!