Classifier with stromal cell intensities

Hello! I am trying to set up a classifier that detects tumour and stroma and classifies the cells as one of the two. I have been able to utilize the intensity features to set up the tumour cell intensities, but I was wondering how I would be able to do so for the stromal cells too? (I’m using v0.1.3 and can’t update to a new version as I’ve already run multiple analyses and want to keep it consistent.)

Is this possible? If so, how would I go about implementing it? If not, what might be another option for me (ex. scripting?)?

Thank you so much for all of your help!

Sample images would be helpful, along with some indication of what is or is not working. Otherwise we are working blind :slight_smile:

Oh, sorry! I’ve attached a picture. I created a detection classifier and ran it using tumour and stromal parameters. I added the thresholds under the intensity features of the classifier based on the Nucleus OD mean. It ran on the tumour cells (blue, yellow, orange, and red).

I want to also be able to classify the stromal cells (in green) with intensity features to be able to differentiate between light, intermediate, and high stain intensity. However, I am not sure how to go about this. Let me know if there’s anything else you’d like me to provide!

1 Like

Ah, perfect. That was discussed here:
https://forum.image.sc/t/setcellintensityclassifications-for-a-certain-class/33347/3?u=research_associate
Another way to write the script would be:

def measurementName = "Nucleus: Hematoxylin OD min";
def thresholds = [0.05, 0.2] as double[];

pathObjects = getCellObjects().findAll{it.getPathClass() == getPathClass("Stroma")}

setIntensityClassifications(pathObjects, measurementName, thresholds);

And if you are having trouble with stromal cytoplasmic staining classification, it might be worth taking a look at:

1 Like

Oh, thank you!

I tried the script and it works (thank you again!) but is it possible to modify the script to add stroma: num 3+?

I’ve attached a picture of the measurements that I get.
image

There were only 2 thresholds for stroma, so there are only 1+ and 2+ stromal cells. You can adjust the script to do that if you want, and you should be adjusting the thresholds anyway!

Thank you! I already adjusted the thresholds in the script that you wrote up.

I also did add another threshold to the list, but it didn’t reflect in the measurements. When I run it, I am still only getting stroma: num 1+ and stroma: num 2+.

Not sure without seeing the code. The other possibility is that it worked, but you just are not seeing it. Can try adding an update line to the end, but I was able to see 1 2 and 3+ in my image.

def measurementName = "Nucleus: DAPI mean";
def thresholds = [2000, 3000, 4000] as double[];

pathObjects = getCellObjects().findAll{it.getPathClass() == getPathClass("Tumor")}

setIntensityClassifications(pathObjects, measurementName, thresholds);
fireHierarchyUpdate()

*And by “just not seeing it,” I want to be clear that means the results are not updating in the interface :slight_smile: But if you check the classifications of the cells in the Detections output or otherwise, they should be accurate.

Thank you! I tried the script but it still doesn’t show me the num 3+ in the interface or in the output.

The script below is the one I used that worked but only provided stroma: num 1+ and num 2+.

def measurementName = "Nucleus: DAB OD mean";
def thresholds = [0.05, 0.27, 0.42] as double[];

pathObjects = getCellObjects().findAll{it.getPathClass() == getPathClass("Stroma")}

setIntensityClassifications(pathObjects, measurementName, thresholds);

Thank you again!

I’m not sure at this point. I copied your script in and added the update line, and it gave me 3+ cells. It should work in 0.1.3 (and 1.2, and 0.2.0M8, really)


I assume you have some cells you know should be above your 3+ threshold. What are they being classified as when you select them?

Oh, okay. The cells above the 3+ threshold are being classified as 2+.

If the cells are already classified as 2+ then the script as it is written above won’t reclassify them.

1 Like

Oh? For me it has been. I can swap any of the numbers around, re run it, and all of the cells update. Again, with the update line included.

Hmm, yep, Pete is right. It works if I don’t pick out a base class! I wasn’t working with tumor/stroma.

Which I guess means you only get one shot at it, or you need to reset the thresholds by setting any class that is stroma back to stroma.


pathObjects = getCellObjects().findAll{it.getPathClass().toString().contains("Stroma")}
pathObjects.each{it.setPathClass(getPathClass("Stroma"))}

Try that first, then run the script with 3 levels.

Alternatively, the above script could be modified to include that line:

def measurementName = "Nucleus: DAB OD mean";
def thresholds = [0.05, 0.27, 0.42] as double[];

pathObjects = getCellObjects().findAll{it.getPathClass().toString().contains("Stroma")}

setIntensityClassifications(pathObjects, measurementName, thresholds);

The easiest solution is if you apply the same intensity classifications to all ‘base’ classes, then just use

setCellIntensityClassifications('Nucleus: DAB OD mean', 0.2, 0.4, 0.6)

or similar, as described here.

Otherwise I suspect you’ll need to replace it.getPathClass() with it.getBaseClass().getPathClass() (although I don’t recall if that existing already in v0.1.3 or not… if not then @Research_Associate’s String trick should also work, unless you have ‘Stroma’ turning up in other classification names somehow).

2 Likes

Yeah, I missed that no cells were being picked up after the first run due to the pathObjects line. My fault.

getBaseClass does not seem to exist in 1.3

1 Like

It works! Thank you so much for all of your help!

1 Like