Adjusting CP parameters to count dots within cells

Hi! I am new at the community and also a new user of CellProfiler :slight_smile:

I am having some doubts and troubles with the analysis of RNAscope images. I would like to count dots within a population of neurons, so I select the expressing cells first and then I count specific dots only in these cells.

My starting images are in .nd2, but I am using a pipeline that starts with TIFF RGB images, so I first convert my images to this format using ImageJ software. When I establish the parameters to detect dots (IdentifyPrimaryObjects), I tell the program to detect objects with a typical diameter of 2-8 pixel units, to avoid large clusters of dots and background. I also choose “the method to distinguish clumped objetcs” as “Intensity”. When I run the pipeline in my images, it detects dots of different size within these cells that are all counted as dots. I mean, for example, for one cell, it detects 45 dots, but not all of them have the same size. This does not happen in all cells, because some of them have less expression than others; in that case, the “objects” are more separated and are counted as smaller dots.

At this point, I have several concerns:

  1. Which is a pixel unit in an image? Every square is a pixel? Because when I established a 2-8 threshold for object size, I realize that some of the clusters that the program detects are bigger than this threshold (8). How could it be possible? Is “object” a synonym of “pixel” and “dot” is a group of these objects/pixels based on the method I choose: by intensity? If this is the case, what I set to the program is the size of pixel units, so it makes sense that some dots were bigger than 8, because they are formed by several pixels/objects.

  2. Something similar also happen with nuclei, the program is not able to detect all the nuclei in my images. In this case, in IdentifyPrimaryObjects I am using the “Minimum cross entropy” method, but changing to another one remains the same or similar. The “typical diameter of objects” in this case was set to 10-80, and increasing the last threshold does not change the results. “The method to distinguish clumped object” is by “shape”. It seems not to be related to differences in DAPI expression o nuclei size, because several of the nuclei that are not detected are the biggest ones or even have the highest expression.

  3. Maybe when converting images to TIFF, they lose resolution, so the separation into “single” dots is more dificult, although I think it would not be possible to separate them neither with the original .nd2 image, because there is a high expression in several cells. Any idea to improve clusters separation not to get so large dots?

  4. I do not know if the differences in dot size are normal and assumable, or if people usually count these different dots and include all of them as “dots”, “foci” or “expression” when representing data. In papers using RNAscope, it seems that they include all dots when counting dots/expression, because I find in their images dots/foci with different sizes.

Any idea or help would be really appreciated. Thanks a lot!
I attach examples of dot detection with different sizes (and those large dots), and also nuclei detection.
Examples.zip (104.1 KB)

You can actually just use .nd2 files straight in CellProfiler. Relevant information can be extracted using the “Extract from image file headers” metadata module.

A pixel is a ‘square’, yes. The object size settings are for diameter across rather than area. CellProfiler will detect all the objects in the image and then filter down to those within the size range you set, provided that “Discard objects outside the diamater range” is enabled. It’s worth mentioning that this also isn’t considering the maximum diameter, as per the help text:

Based on the zoomed in image you sent it doesn’t look like any of the clusters are larger than the 8px threshold once this is considered.

Looking at your nuclei segmentation, it appears that the missing objects are being discarded for touching a border. Did you apply a mask to this image prior to running IdentifyPrimaryObjects? Masked areas are considered as being off the image and so may cause this. If that’s the case, try disabling the ‘Discard objects touching border’ option. Otherwise it’d be helpful if you could upload a copy of your pipeline.

Don’t try to convert them if you can avoid it, although switching to tiff shouldn’t be reducing resolution at all. How are you doing this? Another option is to preprocess the images using the EnhanceOrSuppressFeatures module in ‘speckles’ mode, which should attempt to make those spots easier to detect. That said, if the intensity of multiple spots together is already saturated there may not be much you can do to separate them. Another approach would be to calculate the average intensity of a single spot and see if you can deduce the number of spots in a merged object using that value.

With most RNA staining methods you can have variable numbers of fluorophores attached to a single target, depending on how effective amplification was. Some therefore view it as unsafe to assume a single spot represents a single molecule, and so they’re referred to as spots or foci instead. If multiple spots close together are impossible to segment than it’s reasonable to consider the total or average intensity per cell as a surrogate for an absolute expression level.

Hope that helps!

Hi @DStirling
Thank you very much for your recommendations and help. It has been very useful to me!
Yes, I have applied a mask to my image prior to IdentifyPrimaryObjects because I need only to quantify dots in a specific cell type only. I have changed now the “Discard objects touching border” to NO and now it recognizes all the nuclei :slight_smile:
On the other hand, having into account your recommendation of not converting my images to TIFF (I do it by ImageJ, just converting images to 8 bits and then merge channels and convert to RGB, and save as tiff), I change my pipeline to read the metadata from .nd2 files. I think I was successfull, but when I run the Mask, no image appears in the screen, all was black, although the analysis continues without any problem. However, at the end, the colors of channels appears changed, DAPI is in red and dots in blue, although at the begining they were correctly separated. Maybe the second ColorToGray was wrong. Could you specify which numbers and colors are the channels from a .nd2 file? I set channel 1 to DAPI (blue), 2 to green and 3 to cyan.

I attach the pipeline (for TIFF and for .nd2).
RNAscope Pvalb-Npy ND2 pipeline.cppipe (75.1 KB)
RNAscope Pvalb-Npy TIFF pipeline.cppipe (74.5 KB)

I would also measure mean intensity to compare if both analysis give the same result despite the intrinsic differences in values mesaured (one is number and the other intensity, but they could show the same result: upregulation).
Thanks a lot!!

Hi @Marinavv,

Looking at your pipeline, I don’t think MaskImage with objects is designed to be applied to RGB images and then split, that might confuse the software. A better approach might be to apply the mask to the images you already split with the first ColorToGray module. This would require 3 copies of the MaskImage module but should be more consistent.

In terms of measurements, you can also combine your MeasureObjectIntensity modules by just adding multiple images to a single module.

Without any example images I can’t really test how the pipeline runs, but I hope that helps.

Looking at this further, this is likely to be a result of using the original image in the OverlayOutlines module. CellProfiler has been told this is a colour image with 3 channels, but it doesn’t actually know which channel should be mapped to which colour and so assumes the order is Red, Green, Blue. A solution to this may be to re-combine the split channels from the first ColorToGray module with a GrayToColor module, which will let you specify each channel’s colour (use ‘channels’ mode if you don’t want the colours to be red, green and blue).

Hi @DStirling,
Thanks a lot for your help. I made the changes you mentioned but I still have problems with MaskImage. Maybe I do not understand well what you suggested. Here is the modified pipeline and I would like to send you an example image but it is not allowed by the site to upload .nd2 images (sorry!).
PD: There are some erros at the end in the pipeline because I have changed or removed some names, I already know.
RNAscope Pvalb-Npy ND2 pipeline.cppipe (77.9 KB)

Another thing… I am trying to measure dots size using MeasureObjectSizeShape and the pipeline does it correctly but I cannot save the results en the datasheet exported. I am selecting AreaShape quadrants (only area, perimeter and mean) but it does not save these data in the exported sheet. Any solution? I attach the pipeline, this time is the one for TIFF images.
Thanks a lot!
RNAscope Pvalb-Npy TIFF pipeline.cppipe (71.3 KB)

Hi @Marinavv,

I’ve attached what I believe should be a working version of your first pipeline. It’s difficult to test without images, but it looks like you still had ‘discard border objects’ active when trying to find nuclei, which caused it to discard everything due to the mask. I’ve also removed some redundant colour merging/splitting.

Regarding the issues with later modules, it’s important to perform your measurements before running RelateObjects, as RelateObjects can only link measurements which already exist at the point it runs.

Regarding your second issue, it looks like you’ve not set the ExportToSpreadsheet module to output files for the particular objects you’re performing size and shape measurements on. You’ll likely want to use ‘Add another data set’ at the bottom of the module to generate the extra sheets with statistics for the objects you’re measuring.

Hope that helps!

RNAscope Pvalb-Npy ND2 pipeline2_fixed.cppipe (78.4 KB)

Hi @DStirling,

It still finds the same error: once I run MaskImage, it suddenly turns into a black image, for all channels, and anything could be neither measure.I wish I could send you an example image. On the other hand, I had set the ExportToSpreadsheet module to output files for size (Area, perimeter, etc.), that is the reason why I asked that I don’t understand why these data don’t appear at the sheet later. But now I realize that the problem is in what you mentioned: I haven’t select “Add another data set” to generate two extra sheets for Npy and Pvalb dots. I was hoping to obtain these data in Pvalb_cells sheet, sorry!

Now I have my TIFF pipeline correct, but the nd2 pipeline is still mising the MaskImage module functioning well… I don’t know if you still recommend me to switch to nd2 images. If that is the case… anything more to fix this problem with the mask? Both nd2 and tiff images at CellProfiler look similar in resolution when using the zoom tool, so maybe it is not so important to use nd2 images.

On the other hand, my initial concern was about dot clusters regarding quantification. I can provide data representing dot number, dot intensity in each cell and dot size. I think it is enough in case people don’t believe the result of dot number because of having several clusters. Moreover, I have seen papers presenting dot number quantification with different sizes, actually, almost all of them. I think it is imposible not having dot clusters and so dots will always be of different sizes. I guess these differences will be maintained across genotypes/conditions, so the quantification would be appropriate. What do you think?

Thank you very much for your kindness. It is being very helpful :slight_smile:

Sorry to hear you’re still having trouble. Tifs should also be fine, but there’s no particular reason ND2 would specifically cause a problem.

Without seeing the images I can’t do much, but I suspect it’ll most likely be a thresholding issue, I noticed that you’re using manual thresholding for the other two IdentifyPrimaryObjects modules. What you might be able to do is compress an ND2 file into .zip format and upload that if you’d like further assistance.

This sounds like it should be fine. It’s probably best to capture all the measurements you can think of and then figure out what makes the most sense to present.

That’s a good idea! Here you have two of my images :slight_smile:
Thanks a lot!
Example images.zip (3.4 MB)

Hi @Marinavv,

Thanks for that, it makes much more sense with the images. I’m attaching a modified version of the pipeline which should have the masks working. You were using the original image as a mask instead of your object set, which resulted in the entire image being masked off.

RNAscope Pvalb-Npy ND2 pipeline2_fixed2.cppipe (80.1 KB)

On that subject though, I think this approach is somewhat over-complicated for what you’re trying to do. Below is a simpler pipeline which should allow you to achieve similar results. You may want to switch around some of the overlays and exports depending on what’s of interest.

RNAscope Pvalb-Npy ND2 pipeline2_simplified.cppipe (86.3 KB)

Hope that helps

Hi @DStirling,
Thank you very much!! A lot of effort and help from you!! Thanks a lot!
But (sorry!), the NamesandTypes module does not work properly. It says that " the pipeline cannot be started because of a configuration problem: the pipeline did not identify any image sets". If I change this module to “All images” instead of “Images matching rules”, and then I add an “ColorToGray” modeule as I did before, it works. But at the end I have found another problem that I don’t know if it is caused by this change or not: the overlay is not over the ColorImage from “GrayToColor”, it appears in a black image, and so the “DisplayDataOnImage” too. Any idea? I guess it was functioning well in your hands!

Hi @Marinavv,

That’s most likely because you need to extract the individual channels from the image file headers in the metadata section, otherwise CellProfiler won’t consider them as separate images. After populating the file list, head into ‘Metadata’ and click ‘Update metadata’ beneath the extraction method options. Note that this is separate from the ‘Update’ button for the table at the bottom of the screen. This allows CellProfiler to scan the files and identify the channels within them instead of using colour splitting modules.

Hopefully getting that working as intended will also correct the colour issues.

If such issues do persist, perhaps try running a RescaleIntensity module.

Hi @DStirling,

That’s good to know! Now it works :slight_smile: But the ColorImage in the overlapping step takes still place over a black image, not over the RGB one created by GrayToColor. I don’t understand what happens. I will now try to run the RescaleIntensity module as you mentioned and I will let you know.

I have a question regarding the simplified pipeline you sent to me. It contains two RelateObjects modules to count Npy and Pvalb dots. The Npy one is after the FilterObjects module, which makes sense because I need only to quantify Npy dots within Pvalb cells, but the Pvalb RelateObjects module is before the filtering, and the parent objects is “Pvalb_cells”, not “Positive_Pvalb_cells” as in Npy dots quantification. I mean, with no filtering at all, I will be counting every cell with Pvalb dots, which is a Pvalb positive cell, but why don’t we run this RelateObjects after filtering (as with Npy dots)? I don’t know whether I may be quantifying the right object.

Thank you very very much!