Why stain? And why DAB is not quantitative

Brightfield images, or at least the ones I will be discussing here, are originally fairly colorless pieces of tissue that have been stained with one or more dyes (I am not covering DIC/phase contrast or other unstained live cell analyses). The stains themselves vary greatly in terms of their functionality. Most brightfield images are three images in one, Red, Green and Blue all dropped on top of each other and presented to you on your screen via tiny Red Green and Blue lights. But these colors are usually not what we are interested in, unlike in fluorescence. There are no pure color channels in brightfield, unless you manage to have a perfectly blue, red, or green dye. As far as I know of, that does not exist, and the color of the lighting can impact the color of the stains we see on the screen, as can the color shading of the monitor.

Trying to analyze an image, though, we are interested in stains, not the original RGB values. Color deconvoution gives us a way to ESTIMATE the amount of stain in a given pixel. It will never be perfect. The tissue itself will have some small absorbance, as will the mounting media. The color of the incoming light is unlikely to be perfectly uniform, even from an LED. Bulbs will age, darken, and their color warmth will shift. We do the best we can, but generally brightfield analyses are much less quantitative than other types of imaging. That does not mean Fluorescence is perfectly quantitative - it is not for a variety of reasons - but brightfield is usually less so. As such, the standard method of analyzing brightfield images is to attempt to isolate regions where your stain is present in sufficient quantities to meet some threshold, and then calculate the area of that stain. You may be counting nuclei or cells via a stain like hematoxylin, or DAB nearby the nucleus via an expansion away from that nucleus, but the presence or absence of a stain, and in how many places is what most analyses will come down to.

DAB - ignore this section if you are lucky enough to not work with DAB

One of the most difficult stains, and yet most common, is DAB (DAB Wiki entry) ( DAB IHC description from abcam), which, in addition to being brown and thus crossing all three of the Red, Green and Blue channels for an RGB image, is a precipitate, which means it will not follow Lambert-Beer law and stoichiometrically absorb light that passes through it. DAB is commonly used both for historical reason (compare your staining vs other staining done with DAB), accessibility, and because it is usually dark and easy to see. None of these reasons are particularly helpful from a quantitative analysis standpoint. The take home message here is "be careful with what you think your analysis means." Twice the DAB "intensity" does not mean twice the protein.
Additionally, because DAB shows up in the red green and blue channels, it is much harder to untangle from stains like hematoxylin, which are primarily blue. If you have access to red and green stains, those work much better with the hematoxylin as a counterstain since they will primarily - though not perfectly - affect information in different channels.

symbol DAB: TLDR

DAB is a non-quantitative stain, though easily accessible. Twice the stain “darkness” or intensity does NOT mean twice the amount of protein. Use DAB to determine percent area, or, in certain circumstances, sets of thresholds for 1+, 2+ and 3+, provided those categories are fairly broad. Consider fluorescence or other stains if the relative amounts of protein expression in your samples are important, but be aware that factors like consistent slice thickness or monoclonal vs polyclonal antibodies may play important roles in the accuracy of any sample’s intensity.

 

Quote from the van der Loos paper below, from a summary of such information on the Image.sc forum.

“The brown DAB reaction product is not a true absorber of light, but a scatterer of light, and has a very broad, featureless spectrum. This means that DAB does not follow the Beer-Lambert law, which describes the linear relationship between the concentration of a compound and its absorbance, or optical density. As a consequence, darkly stained DAB has a different spectral shape than lightly stained DAB.”

Back to stains in general

It is always best to generate your stain vectors from SINGLE stain samples. In this case I would need an Eosin only, and a Hematoxylin only stained sample - which I do not have. So I will have to make an estimate. For stains like H&E, it is very important to keep the staining conditions constant. That means equal timing on the dips and washes per slide, and changing out the hematoxylin (and everything else) frequently enough. Even in a perfect world, with thin tissue slices, perfect staining procedures, and well separated stains (red, green, and hematoxylin), information is lost as the stains get darker. A black pixel allows no light, and therefor you have no idea what dyes were present. It could be 100% DAB, 100% hematoxylin, or something else. Titrating your antibodies/dyes so that the stains are not extremely dark can be very helpful if you need to deal with overlapping stains.

Another option is exporting a subsection of the image into Fiji to use ColorDeconvolution2 or other plugins to more carefully refine the vector values.

Estimating stain vectors in QuPath

Use the ImageJ button to send the selected region at full resolution (1) to ImageJ with no modifications

Use the ImageJ button to send the selected region at full resolution (1) to ImageJ with no modifications

For the moment, we will use the Analyze->Preprocessing->Estimate stain vectors method, as it gives the most control over the stain vectors. Creating small ROIs for specific stains can be very problematic as you are sampling a small number of pixels, and any blemish or small stain variation can have a major impact on your results. In addition, if you notice that your microscope or slide scanner has tiling artifacts (each image tile position is very apparent due to shading), you may want to take an elongated sample box to try and cover as much of the variation as possible. The best option is always to improve the image at the scanner, though, and fix whatever is wrong with the scanner so that you are working with nice, even images!

The first question QuPath asks is whether to set the background values, with a dialog that looks like the following.

Set background
 

As long as enough blank space was included in the selected area, QuPath should do a fairly good job of estimating the background color intensity. As stated in the question, it takes the mode, or most common pixel value. Another way to think about this, is QuPath is determining the amount of light that is blocked by the slide and mounting media itself. Here I usually select “Yes”, provided I am convinced the background values are correct (mouse over empty areas of the image and look at the R G and B values in the lower right corner of the Viewer).

symbol Note

The background estimation step CAN be done separately from setting the stain vectors themselves. You can select an area in the background, run the stain estimation, choose “Yes” in the image above to save the background value, and then ignore the next step (click Okay or Cancel without changing anything). You will see that the background values in the Image tab are updated, but the stain vectors are unchanged. You can then choose another region to perform the actual stain separation - just do not update the background values a second time when selecting an area that has no background!
Alternatively, after creating a background annotation, you can double click on the Background line in the Image tab on the left. Just make sure not to change the background yet again when performing the stain deconvolution!

Next, you are presented with the Visual Stain Editor, which is a set of 2D representations of the 3D color space volume. I have placed an image of it side by side with the Color Inspector 3D plugin from Fiji, showing the 3D color space. QuPath’s three charts are each a view from one side of the cube.

visual stain editor
color inspector 3D in Fiji
Fiji’s equivalent of the middle, Red-Blue panel. Blue values go from 0 in the upper right (closest to black) to 255 as pixels reach the “bottom” of the 3D plot.

Fiji’s equivalent of the middle, Red-Blue panel. Blue values go from 0 in the upper right (closest to black) to 255 as pixels reach the “bottom” of the 3D plot.

 

The “after adjustments” image below shows what I obtained after first clicking Auto, which usually does a fairly good job, and then adjusting things slightly more to catch more of the “outside” pixels. In well mixed stains like Hematoxylin and Eosin (dyes where most pixels will have at least a little bit of both stains), I have often found that moving my color vectors a bit farther away from each other improves my separation. How would you check? Well, qualitatively, you can use the 2 and 3 keys to look at the Hematoxylin and Eosin channels (or the Brightness & Contrast dialog).

Stain vectors after some adjustments. Feel free to use the Exclude checkbox, though I usually prefer to choose to take a little bit of time and annotate areas that are fairly clean.

Stain vectors after some adjustments. Feel free to use the Exclude checkbox, though I usually prefer to choose to take a little bit of time and annotate areas that are fairly clean.

The renamed color vector sets can be seen in the Workflow tab, and the currently selected one can be found in the Image tab. Another naming scheme might be using the name of the Image where the color deconvolution is performed - so that you can compare between images later.

The renamed color vector sets can be seen in the Workflow tab, and the currently selected one can be found in the Image tab. Another naming scheme might be using the name of the Image where the color deconvolution is performed - so that you can compare between images later.

View->Mini viewers->Channel viewer showing the top row. There are 3 main regions of interest to me here. 1. The darker blue tissue shows both hematoxylin and eosin. 2. The fibrotic tissue shows primarily eosin and is almost white in the hematoxylin image. 3. The residual channel (what is left over and not used by the two stain channels) shows some of the highest intensity in the adipocytes, or white space. That is good, because it means there is relatively little error in the tissue itself. I usually find that values of between -0.05 and 0.05 in the residual channel are reasonable, though darker samples (poor scanner illumination) and darker staining tend to lead to higher values.

View->Mini viewers->Channel viewer showing the top row. There are 3 main regions of interest to me here. 1. The darker blue tissue shows both hematoxylin and eosin. 2. The fibrotic tissue shows primarily eosin and is almost white in the hematoxylin image. 3. The residual channel (what is left over and not used by the two stain channels) shows some of the highest intensity in the adipocytes, or white space. That is good, because it means there is relatively little error in the tissue itself. I usually find that values of between -0.05 and 0.05 in the residual channel are reasonable, though darker samples (poor scanner illumination) and darker staining tend to lead to higher values.

Once I am happy with the results, I can create a short script using the Workflow tab, isolate the line that has the new color deconvolution stain, and verify in several other images that the color deconvolution settings work there as well. Do not simply assume that your first try will work well across the bulk of your project. Also, some areas with other kinds of staining will definitely show up strongly in the residual channel, do not be surprised by this. In the case of the test project, there are areas of teal staining and brown staining that will show up very strongly in the residual channel as they are neither hematoxylin or eosin.

Brown staining on the left, and teal staining on the right will show up strongly in the Residual channel.

Brown staining on the left, and teal staining on the right will show up strongly in the Residual channel.

 

Final Step: save to script

At this point, we have the first lines of our script - the Workflow tab can be used to extract the color deconvolution vectors for later use.

  1. Up in the menus, Automate->Project scripts->New script…

  2. Name the script

  3. Go to the Workflow tab, and at the bottom, Create script

  4. From the created script (should be called Untitled*), copy the setImageType and the last (not the original!) setColorDeconvolutionVectors lines, and paste them into your new script.

  5. Use either File->Save or CTRL+S to save the script, you should see the * at the end of the file name on the left disappear once the file is saved.

stain vectors as script.PNG