\(•ᴗ•)/ QuPath scripting (#6): Customized 3 stain color deconvolution

Triggered by the post

I create the following short script to prepare the current image entry for a 3-stain color deconvolution and assign custom stain vectors:

// **************************************************************************
//    File : Setup3ColorDeconvolution.groovy
//    Author: Peter Haub
//    March 2021
//    Copyright (C) 2021 Peter Haub
//    This script prepares a brightfield image for 3 color deconvolution with customized stain vectors.
// **************************************************************************

import qupath.lib.color.ColorDeconvolutionStains
import qupath.lib.color.StainVector
import qupath.lib.gui.QuPathGUI
import qupath.lib.gui.viewer.QuPathViewer
import qupath.lib.images.ImageData
import qupath.lib.gui.scripting.QPEx

QuPathViewer viewer = QuPathGUI.getInstance().getViewer()

def imageData = QPEx.getCurrentViewer().getImageData()


// Customize your 3 stains here (vector will be normalized)
StainVector stain1 = StainVector.createStainVector("Stain1", 0.7110,  0.6300,  0.3080)
StainVector stain2 = StainVector.createStainVector("Stain2", 0.3250,  0.6070,  0.7250)
StainVector stain3 = StainVector.createStainVector("Stain3", 0.3000,  0.9100,  0.2850)
// Customize your RGB background values here
double maxR = 255
double maxG = 255
double maxB = 255

ColorDeconvolutionStains stains = new ColorDeconvolutionStains("CustomStains", stain1, stain2, stain3, maxR, maxG, maxB)



Here is the output for the test image from the post mentioned above:


Hi @phaub ,

Firstly, thank you for sharing this script!

I have some analysis to perform on triple stained brightfield sections (H-DAB + red stain), and I’d like to do a 3 stain deconvolution as you did here.

I was wondering how did you come to estimating the stain vectors almost perfectly in the example you provided? At the moment, I could not find any method to objectively measure/estimate and obtain the stain vectors to input into your script, other than dragging the points in the Estimate stain vector in QuPath, which is of course extremely subjective and inaccurate.

Your advice and guidance is very much appreciated!

Best wishes,

Hi Yau @ym.lim
have you seen @petebankhead 's very helpful hints on Separating stains — QuPath 0.2.3 documentation

And have you seen @gabriel 's content on Colour Deconvolution 2 – Novel context-based segmentation algorithms for intelligent microscopy

There you can find:

Determining new vectors

  1. Grab images of tissues stained with single dyes to ensure that the colour vectors are pure. …

That is the most correct answer to your question:
Ideally the stain vectors are determined on images of samples stained with single dyes.

If you want or need to determine the stain vectors on images stain with multiple dyes the result will be always subjective and inaccurate. There is no way to objectively determine the vectors in such cases, AFAIK. It is always a kind of guess or estimate.


I have been setting stain vectors for H&E or H-DAB images in QuPath comfortably so far, it’s just that trying 3-stain deconvolution is something I have not tried before!

Thank you so much for sharing the information from @gabriel 's post. I’ll see if I can get my hands on single stained images.