Automated counting of multipoints within defined ROIs. Roi.contains(x,y) not behaving as expected?

I am trying to automate my analysis workflow for analysis of manually placed multipoints in various ROIs within demyelinated lesions. So far, I have written a script that starts off by the user defining the total lesion area, and then calculating several other ROIs based on this manually-defined ROI and the fluorescence of a single channel. Briefly, the algorithm is to:

  1. Duplicate channel 4, apply a Gaussian filter, and autothreshold it to generate a binary image.
  2. Create an ROI from the resulting binary image, which will contain all the pixels that are positive for this label.
  3. Invert that selection, and create another ROI which contains all the pixels that are negative for this label.
  4. Use the AND operator with the original, manually drawn ROI and my positive label ROI to create an ROI that represents positive labeling within my lesion.
  5. Use the AND operator with the original, manually drawn ROI and my negative label ROI to create an ROI that represents negative labeling within my lesion.

Next, I want to manually count structures of interest using the multipoint tool, then calculate the amount of multipoints that reside within the ROI that I created in steps 4 & 5.

I then wrote a second script that measures the X,Y positions of my multipoints and stores them in two arrays. I use the arrays to compare whether each set of X,Y positions resides within the ROIs I defined in the first script. I know that my X,Y positions are being stored and read correctly, and the automatic generation of my ROIs is correct, as far as I can tell. However, Roi.contains(x,y) almost always returns 0 (no colocalization) even though I am placing points well within my ROIs. For example, I tested it out by drawing an ROI that almost completely fills the image, but even then several points that were visually within this ROI were read out as not colocalizing. So, I am stuck here. I can’t seem to determine why points that are clearly residing within a ROI are not being assessed as overlapping? Is there something about Roi.contains(x,y) for which I need to take special consideration? I have also tried selectionContains(x,y) with similarly frustrating results. Any help would be greatly appreciated!

Script for calculating multipoint overlap with ROIs (This is run after the ROIs are generated, and the multipoints are manually added):

// Automated computation of particles within defined ROIs. 
// For lyso lesions, intended for use after ROIs are generated with ROI_generator_lys.ijm
// To use this macro, use multipoint tool to define particles for counting, then run the script

// Load multipoints into results table
run("Clear Results");
run("Measure");

// Next segment fills an array with the corresponding X and Y values of each point by successive concatenation

x = newArray();
y = newArray();

for (i=0; i < nResults; i++) {	
	x = Array.concat(x, getResult("X", i));
	y = Array.concat(y, getResult("Y", i));
}


counter_lesionTotal = 0
counter_lesionMyelinated = 0
counter_lesionDemyelinated = 0

// Computes the number of points that reside within the entire lesion
roiManager("Select", 0)
for (i=0; i < nResults; i++) {
	x_coord = (x[i]);
	y_coord = (y[i]);
	boolean = Roi.contains(x_coord, y_coord);
	print("total :" + boolean);
	print("total :" + x_coord);
	print("total :" + y_coord);
	if (boolean == 1) {
		counter_lesionTotal = counter_lesionTotal + 1;
	}
}

// Computes the number of points that reside within the lesion area that contains MOG labeling
roiManager("Select", 3)
for (i=0; i < nResults; i++) {
	x_coord = (x[i]);
	y_coord = (y[i]);
	boolean = Roi.contains(x_coord, y_coord);
	print("myelinated :" + boolean);
	print("myelinated :" + x_coord);
	print("myelinated :" + y_coord);
	if (boolean == 1) {
		counter_lesionMyelinated = counter_lesionMyelinated + 1;
	}
}

// Computes the number of points that reside within the lesion area that does not contain MOG labeling
roiManager("Select", 4)
for (i=0; i < nResults; i++) {
	x_coord = (x[i]);
	y_coord = (y[i]);
	boolean = Roi.contains(x_coord, y_coord);
	print("demyelinated :" + boolean);
	print("demyelinated :" + x_coord);
	print("demyelinated :" + y_coord);
	if (boolean == 1) {
		counter_lesionDemyelinated = counter_lesionDemyelinated + 1;
	}
}

// Compute results

fraction_Myelinated = (counter_lesionMyelinated/counter_lesionTotal);
fraction_Demyelinated = (counter_lesionDemyelinated/counter_lesionTotal);

print("Total number in lesion: " + counter_lesionTotal);
print("Total number in lesion, myelinated: " + counter_lesionMyelinated);
print("Total number in lesion, demyelinated: " + counter_lesionDemyelinated);
print("Fraction within myelinated lesion: " + fraction_Myelinated);
print("Fraction within demyelinated lesion: " + fraction_Demyelinated);

Script for generating ROIs:

// Automated ROI analysis that delineates the total lesion area (as defined by DAPI) and myelinated area within the lesion
// to perform computation within these regions.
// This script is meant to be run after manually drawing an ROI of the total lesion area in the DAPI channel and adding it
// to ROI manager.

// Creation of ROI from manual drawing representing the total lesion area defined by DAPI, lesion_area
run("ROI Manager...");
roiManager("Add");
roiManager("Select", 0);
roiManager("Rename", "lesion_area");
run("Select None");
run("Duplicate...", "title=binary_overlay duplicate channels=4");
run("Gaussian Blur...", "sigma=2 scaled"); // can afjust the sigma factor to change the faithfulness of the MOG binarization
run("Auto Threshold", "method=Default white");

//ROI: Total MOG-negative area, MOG_negative
run("Create Selection");
roiManager("Add");
roiManager("Select", 1);
roiManager("Rename", "MOG_negative");

// ROI: Total MOG area, MOG_total
run("Make Inverse");
roiManager("Add");
roiManager("Select", 2); // this will only work if the DAPI ROI is in position 0 of the ROI manager
roiManager("Rename", "MOG_total");

// ROI: MOG within lesion, lesion_myelinated
roiManager("Select", newArray(0,2)); // again, dependent on correct positioning within ROI manager
roiManager("AND");
roiManager("Add");
roiManager("Select", 3);
roiManager("Rename", "lesion_myelinated");

// ROI: Total area of the lesion without MOG, lesion_demyelinated
roiManager("Select", newArray(0,1));
roiManager("AND");
roiManager("Add");
roiManager("Select", 4);
roiManager("Rename", "lesion_demyelinated");

selectWindow("binary_overlay");
close();
selectWindow(imageName);

Example image that I would like to analyze, showing that my ROIs are being correctly generated. In this case, the ROI I have selected is an area within the lesion that is negative for my label.

Hi.

The issue you have is due to the fact that you are getting the coordinates of the points from the results table.

for (i=0; i < nResults; i++) { x = Array.concat(x, getResult("X", i)); y = Array.concat(y, getResult("Y", i)); }

Looking at your image, your X and Y coordinates taken this way are in calibrated units (microns).

Roi.contains() expects pixel coordinates and not calibrated coordinates.

To solve this, you have two choices.

  1. use getSelectionCoordinates(x,y) to grab the coordinates of each point ROI. This function returns them as uncalibrated coordinates.

  2. Divide your results from the Results Table by the calibration, like this

getVoxelSize(vx,vy,vz,unit);
for (i=0; i < nResults; i++) {	
	x = Array.concat(x, getResult("X", i)  / vx );
	y = Array.concat(y, getResult("Y", i)  / vx );
}

You should find that Roi.contains() will work as expected with these modifications.

Best

Oli

3 Likes

Applying a conversion factor from microns to pixels worked well - thank you so much!