How to make a point over the centroid of an ROI, and determine whether or not it is inside another ROI

I’v written FIJI macro that analyzed muscle fiber area and nuclei per fiber. Right now the code simply determines if the the ROI from the nuclei and the ROI from the muscle fiber overlap. The problem is that it overestimates nuclei per fiber, so instead of counting any overlap at all, I want to determine whether or not the centroid of the nuclei is with in the fiber, and only count those nuclei. Any help is appreciated. Below is a portion of the code that determines this overlap. FYI, DAPI is the nuclei channel, i refers to the ROIs from DAPI, and “j” are the ROIs for the muscle fibers.

if (isOpen(“DAPI”)) {
counts=roiManager(“count”);
nuclei_counts = newArray(counts);
if (isOpen(“DAPI”)) {
selectWindow(“DAPI”);
run(“Duplicate…”, “title=[DAPI Temp]”);
selectWindow(“DAPI Temp”);
setAutoThreshold(“Otsu dark”);
setOption(“BlackBackground”, true);
run(“Analyze Particles…”, “size=1.0–Infinity circularity=0-1.00 display exclude summarize add”);
roiManager(“Show All without labels”);
}
selectWindow(“DAPI”);
for (i=0;i<counts; i++){
nuclei_counts[i] = 0;
for (j=0;j<roiManager(“count”);j++){
roiManager(‘select’,newArray(i,j));
roiManager(“AND”);
if ((i!=j)&&(selectionType>-1)) {
nuclei_counts[i]++;
}
}
}
roiManager(“show all”);
selectWindow(“DAPI Temp”);
rename(“Myonuclei Analysis”);
run(“Flatten”);
saveAs(".tif", Results+getTitle());
run(“Clear Results”);
roiManager(“reset”);
}

Hello Lyle -

Does Roi.contains() do what you are looking for?

You can get the centroid of a measured ROI from the “X” and “Y”
columns of the Results Table (assuming you have “Centroid”
checked in “Set Measurements” when you run “Measure”).

Thanks, mm

I was able to get the centroids of each nuclei, just don’t know how to make those centroids into ROIs.

Hello Lyle -

Good. So what I had in mind for the next step would be for a given
nucleus make the ROI of the corresponding fiber the current selection.

You can see from the Roi.contains() documentation, that this function
takes the x and y coordinates of a point as its arguments. So pass the
x and y of the centroid of the nucleus in question to Roi.contains()
(with the fiber ROI set active).

As an aside, if you prefer not to use the above approach, makePoint()
creates a PointRoi from an (x, y) pair.

Thanks, mm

So this is what I have so far:

if (isOpen(“DAPI”)) {
selectWindow(“DAPI”);
run(“Duplicate…”, “title=[DAPI Temp]”);
selectWindow(“DAPI Temp”);
setAutoThreshold(“Otsu dark”);
setOption(“BlackBackground”, true);
run(“Set Measurements…”, “area centroid redirect=None decimal=3”);
run(“Analyze Particles…”, “size=1.0–Infinity circularity=0-1.00 display exclude summarize add”);
roiManager(“Show All without labels”);
counts=roiManager(“count”);
nuclei_counts = newArray(counts);

}
for (i=0;i<counts; i++) {
CntrdX = getResult(“X”, i);
CntrdY = getResult(“Y”, i);
makePoint(CntrdX, CntrdY, “cross”);
roiManager(“add”);
}
roiManager(“Show All without labels”);

Problem now is, the crosses made from the centroid coordinates do not line up with the nuclei. It looks like the crosses were overplayed on another image that is 75% to scale. Any idea?!

Thanks again

Hello Lyle -

Please check whether you have a scale set for your image, e.g.,
Analyze > Set Scale.... See also Spatial Calibration.

If you have a scale set, your centroids will be measured in
scaled units, but makePoint() will create the PointRoi
using a location based on unscaled, pixel coordinates.

If this is the case, toUnscaled() might be helpful.

Thanks, mm

Thanks mm, I’ve figured out a solution for the scaling. New code below. When I use this portion of the code by itself it works and the crosses are added where they are supposed to be. When I add this portion to the rest of the macro, it doesn’t add the new ROIs. This seems to be the only problem I’m having now, is that the ROIs simply aren’t added (even though I used the roiManager(“add”) function.

if (isOpen(“DAPI”)) {
selectWindow(“DAPI”);
run(“Duplicate…”, “title=[DAPI Temp]”);
selectWindow(“DAPI Temp”);
setAutoThreshold(“Otsu dark”);
setOption(“BlackBackground”, true);
run(“Set Measurements…”, “area centroid redirect=None decimal=3”);
run(“Analyze Particles…”, “size=1.0–Infinity circularity=0-1.00 display exclude summarize add”);
getPixelSize(unit, pixelWidth, pixelHeight);
ScaleFactor = 1/pixelWidth;
roiManager(“reset”);
roiManager(“open”, Results+“ROISet.zip”);
counts=roiManager(“count”);
nuclei_counts = newArray(counts);

for (i=0;i<counts; i++) {
CntrdX = getResult(“X”, i);
CntrdY = getResult(“Y”, i);
X = CntrdXScaleFactor;
Y = CntrdY
ScaleFactor;
makePoint(X, Y, “cross”);
roiManager(“add”);
}

roiManager("Show All without labels");

When I use ROI.contains() I keep getting an error saying that no selection has been made. Below is the code I tried. Also this code did not add the new point ROIs to the ROI Manager either.

for (i=0;i<counts; i++) {
CntrdX = getResult(“X”, i);
CntrdY = getResult(“Y”, i);
X = CntrdXScaleFactor;
Y = CntrdY
ScaleFactor;
makePoint(X, Y, “cross”);
roiManager(“add”);
}

roiManager("Show All without labels");

for (i=0;i<counts; i++){
nuclei_counts[i] = 0;
for (j=0;j<roiManager(“count”);j++){
roiManager(‘select’,newArray(i,j));
roiManager(“AND”);
if ((i!=j)&&(selectionType>-1)&&(Roi.contains(X, Y))) {
nuclei_counts[i]++;
}
}
}

Hello Lyle -

Please strip down your macro to the simplest version that reproduces
your issue. Then post a single, self-contained, runnable macro so we
can look into what is going on. Ideally your macro will reproduce your
issue using one of the sample images that ships with Fiji / ImageJ, but
if you can’t make this happen, please post an example image that can
be used to reproduce your issue.

When you post your macro, please enclose it in a code block
delineated by a pair of otherwise empty lines containing three
backticks.

Here is an example:

<some_ijm_code>

(Using <backtick><backtick><backtick>java or
<backtick><backtick><backtick>javascript seems
to do okay on formatting ijm code.)

Let us know what specifically your posted macro does wrong. What
result do you get and what result do you want?

Thanks, mm

The macro analyzes fluorescent images of sketelat muscle cross sections for fiber cross sectional area, fiber type, peri-nuclei (nuclei on the perimeter) and central nuclei. After the macro has analyzed fiber area and type, it grabs the image of the nuclei (called DAPI); makes an ROI for each nuclei (by thresholding and analyze particles) and determines whether or not it intersects with an ROI from a fiber. The problem is that it counts nuclei that are just outside the fiber that are barely touching it, therefore over estimating the real number. What I want to do is instead of counting the nuclei who’s ROI intersects a fibers’ ROI, count the nuclei who’s centroid is inside the fibers’ ROI.

I wish I could include an image and a testable section of the code, but its a small part of a much larger Marco and only works with the whole program.

In the following section I’m turning all nuclei into ROIs, getting their centroids, clearing all ROIs from the nuclei (to replace them later with pointROIs corresponding to their centroid), opening another set of ROIs previously saved by the macro and getting the scaling factor.

if (isOpen(“DAPI”)) {
selectWindow(“DAPI”);
run(“Duplicate…”, “title=[DAPI Temp]”);
selectWindow(“DAPI Temp”);
setAutoThreshold(“Otsu dark”);
setOption(“BlackBackground”, true);
run(“Set Measurements…”, “area centroid redirect=None decimal=3”);
run(“Analyze Particles…”, “size=1.0–Infinity circularity=0-1.00 display exclude summarize add”);
getPixelSize(unit, pixelWidth, pixelHeight);
ScaleFactor = 1/pixelWidth;
roiManager(“reset”);
roiManager(“open”, Results+“ROISet.zip”);
counts=roiManager(“count”);
nuclei_counts = newArray(counts);

This next section puts crosses over all nuclei centroids and displays them on DAPI Temp window (or should).

for (i=0;i<counts; i++) {
CntrdX = getResult(“X”, i);
CntrdY = getResult(“Y”, i);
X = CntrdXScaleFactor;
Y = CntrdY
ScaleFactor;
makePoint(X, Y, “cross”);
roiManager(“add”);
}
roiManager(“Show All without labels”);

When the previous two sections are run together separate from the rest of the code (manually performing all other operations), they produce what I want. When they are run with the rest of the code the crosses are never displayed, the ROIs corresponding to each nuclei are missing, and the results read 0 nuclei for all fibers.

This section the ROIs from the nuclei and fibers and determines any overlap. I added the Roi.countains() function with the x and y coordinates from each centroid, but I get an error message saying “Error:No selection in line 438:
if ( ( i != j ) && ( selectionType > - 1 ) && ( Roi .<“contains”>( X , Y ) ) ) {”

for (i=0;i<counts; i++){
nuclei_counts[i] = 0;
for (j=0;j<roiManager(“count”);j++){
roiManager(‘select’,newArray(i,j));
roiManager(“AND”);
if ((i!=j)&&(selectionType>-1)&&(Roi.contains(X, Y))) {
nuclei_counts[i]++;
}
}
}

Overall, I can’t get the program to display the crosses over the nuclei centroids, add the pointROIs to the ROImanager, or use the ROIs.contains() function. Sorry I can’t provide small independently working sections of the code, and thanks again.