Calculating nuclei/cytoplasmic ratio in tissue sections

I have a question regarding the analysis of nuclear and cytoplasmic fluorescence intensity.

I have acquired confocal images of a tissue, stained with DAPI (nuclei) and red fluorescence staining of a protein. This protein can be localized to the cytoplasm, nucleus or both, and my aim is to quantify the nuclei-cytoplasm ratio in each cell.

I’ve constructed a pipeline that identify the primary object (Nuclei), secondary object (cells, defined as the distance of 5 pixels from the nucleus) and tertiary object (cells minus nuclei = cytoplasm).

First, I have to say that CellProfiler handle the nuclei segmentation really well!
The only problem is that since this is a tissue section, the neighboring cells are not homogeneous and are very proximate to one another. So, it seems that my definition of cytoplasm include the nuclei of proximate cells.

How can I define to CellProfiler to ignore the parts of the secondary objects that are overlapping with the primary objects?

Also, after the analysis is done, can I go back form the spreadsheet data of a specific cell to it’s image (for quality control)?


nuc cyto ratio test.cpproj (429 KB)


I took a look at your pipeline, and from all I can see, the IdentifySecondaryObjects won’t overlap with each other. So if you IdentifyPrimaryObjects segmentation is reliable, then your IDSecondary objects should not include any previously identified primary objects. Perhaps I am misunderstanding - possibly supply an annotated zoomed-in image if it would clarify.

One tangential suggestion - did you try ColorToGray with the “Split” option instead of Combine? It looks like your RGB images are different channels of nuclei, and cytoplasm. (However, these “*Merge.tif” images are apparently not the originals, I guess? The pipeline would not run as supplied since the NamesAndTypes was expecting “DAPI” and NFAT1", so maybe this is moot.) Even better, see if you can export your images not as RGB, but as the individual, unmixed channels rather than this pseudo-color.


Thank you, David!
I have attached the original images - DAPI and protein staining (red) for the control and the stimulated tissue (‘bacteria’).

Just to make sure I’m on the same page… :smile: Once I define the primary objects (nuclei), definition of the secondary object around it will not overlap with another neighboring nuclei?

I am asking because the Math_Ratio value (mean intensity in the nucleus divided by the cytoplasm) for many of the objects is bigger than 1 in the control images, although there is no nuclear localization of the protein. Analyzing the ‘Bacteria’ images, I do get more objects with Math_Ratio bigger than 1, in agreement with the nuclear localization seen.

How can I further improve my pipeline, so it will better capture the cytoplasmic vs. nuclear localization of the protein, seen in the images?

Thanks for your help!
Nissan Yissachar

Hi Nissan,

See my attached pipeline. I added some notes in the Module notes section, but I will copy them here too.

[quote]Just to make sure I’m on the same page… :smile: Once I define the primary objects (nuclei), definition of the secondary object around it will not overlap with another neighboring nuclei?

Yes, primary objects cannot overlap with other primary objects and the same goes for secondary. HOWEVER, if what you see as a nucleus in the image is not segmented as a primary object, or it is excluded because it is too big or doesn’t meet some other criteria, then there is nothing to stop the IDSecondary from overlapping a nucleus. I am saying that because your pipeline’s IDPrimary shows this behavior as configured – many “nuclei” are outlined in red, meaning that they fall outside the 15-40 pixel diameter range you et, and so they are not considered as primary objects. I changed your IDPrimary settings to attempt to alleviate those restrictions. See how they work for you.

OK, some notes on the modules in order:

  • ColorToGray: I changed these to SPLIT. COMBINE was needlessly reducing the intensity by a factor of 3, since these images are only purely red or blue.
  • IDPrimary: Adaptive is probably better for tissue, with so much intensity variation. You could also try three-class thresholding. I expanded the size range to 8-50 pixels, since many objects fell outside this range. Including all the primary objects here is critical for the next step (IDSecondary) that you were concerned with. The other way to approach this is to not discard objects outside the size range. I also raised the threshold correction factor a little, but you should adjust this as you inspect both pos and neg control images.
  • IDSecondary: The new primary objects were named “FilteredCells”. But this seems wrong to me – these should be FilteredNuclei, since they are primary objects.
  • IDTertiary: Changed the old “FilteredCells” (which were actually Filtered Nuclei) to “Cells”. The smaller objects are now FilteredNuclei.
    Previously the Cytoplasm was restricted to a single pixel width (and maybe not even that?).
  • Measure(Object|Image)Intensity: Changed to only measure from FilteredNuclei, excluding the nuclei associated with excluded Cells that touch the border of the images.
  • CalculateMath: Note that the Ratio as you have defined it is Nuclear intensity divided by cytoplasm (which I renamed RatioNucDivByCyto to be clear for others who might use this).

Hopefully this helps!

P.S. There are a couple objects that show NaN’s for some of their measurements, which seems odd to me. This was brought to my attention because the displayed Ratio was “nan”, but that is only because of the average of all the many objects includes a small number of “Not A Number”. It looks like they are some objects that are discarded because they touch the border, so it only affects a very few objects. Nevertheless, I’ll see if I can track this issue down, and we may already have a fix, not sure.
DLpipeline.cppipe (15.6 KB)

Thanks a lot, David!
It was very helpful!!

Glad to help!

And as a followup to my P.S., there was a somewhat obscure bug that we found (details here for posterity). And Lee fixed it already!
The latest trunk build should contain the fix if needed.

This issue has been addressed with the 2.1.1 release.