How to calculate mean and standard deviation for particle sizes in multiple ROI's

I have approximately 350 hexagonal grids spread across an image of particles using a macro. Is there a way I could calculate the mean and standard deviation of the particle sizes in each hexagon?

I know you can use the summarise tab to get mean and SD values from the results but it does it for the entire image and not for each separate grid. Is there anything I could add to the code to analyse the particles in each hexagonal grid, and calculate the mean and SD size, then export the ,mean and SD values somewhere else, (maybe the log) and move onto the next grid and do the same? I’ve tried a few things but can’t seem to get it to work.

Any help would be greatly appreciated

My current code is:

l = 230;  // length of hexagon side (pixels)

// hexagon geometry parameters
xIni = 1.0;
yIni = sqrt (3.0) / 2.0;
xSiz = xIni;
ySiz = yIni;
xDel = 3.0;
yDel = yIni;
xOff = 1.5;  // offset for every other row of hexagons

// scale up to get desired size
xIni *= l;
yIni *= l;
xSiz *= l;
ySiz *= l;
xDel *= l;
yDel *= l;
xOff *= l;

getDimensions (width, height, dummy, dummy, dummy);

// loop over rows of hexagons
iOff = 0;  // which staggered row of hexagons
y = yIni;
while (y + ySiz < height) {
  // loop over hexagons in a row
  x = xIni + (iOff % 2) * xOff;
  while (x + xSiz < width) {
      // build hexagonal ROI
      x1 = x + xSiz;
      y1 = y;
      x2 = x + xSiz / 2.0;
      y2 = y - ySiz;
      x3 = x - xSiz / 2.0;
      y3 = y - ySiz;
      x4 = x - xSiz;
      y4 = y;
      x5 = x - xSiz / 2.0;
      y5 = y + ySiz;
      x6 = x + xSiz / 2.0;
      y6 = y + ySiz;
      makePolygon (x1, y1, x2, y2, x3, y3, x4, y4, x5, y5, x6, y6);
      // add to ROI Manager
      roiManager ("add");
	  
      
      x += xDel;
  }

  iOff++;
  y += yDel;
}

// display all hexagonal ROIs
roiManager ("deselect");
roiManager ("show all");
run("Analyze Particles...", "include");


numROIs= roiManager("Count");
for (j=0; j<numROIs; j++)
{
	imgID= getImageID();
	roiManager("select",j);	
	run("Analyze Particles...", "include");
}



Hi,
I dont know how your hexagone looks like, but if you could crop each of them to have them in separate images then you can run the particle detection for each hexagone image separatly.

350 images can sound like a lot but if the images are relatively small and all the same size, it should not be a big deal to have them in a stack.

Ultimately you might not even need to crop if the particle analyzer can be restricted to the succesive hexagone ROI.
If the hexagone looks similar, you can give a try to template matching to find automatically the hexagones. See the youtube tutorials for more documentation.

1 Like

Ah, a nice application of this code!

In your hexagon loop, after the makePolygon, do a run("Duplicate...", "title=hexagon");, do your analysis of particles on the hexagon. After you have collected the particle results of this hexagon, you can calculate their mean and standard deviation and put these in the results table. Close the window and proceed to the next hexagon. In the Analyse Particles command, make sure you clear the results in the ROI Manager…

There is no need to store the hexagon in ROIs as you can recreate them at will.

If it is absolutely necessary to know which ROI was in which polygon, you could add two columns to the results table indicating the bounding box of the hexagon just before the Duplicate. As all polygons are created equal, there is no need to store their size, as that too is parametric.

@sgericeb please put a link to the related topics as @eljonco did next time you open a new post, .
There was some useful information to answer this new question
Thanks :wink:

2 Likes

Thanks a lot for the help @eljonco. This looks promising from what I have tried so far. However, I am running into problems when I try to add this to the code. Would you be able to provide an example? I am essentially trying to automate as much of this process as possible as I have over 350 polygons to extract data from.
Thanks!

Very good @sgericeb, show us what you’ve tried so far. I guess you know how to edit code and how to step through that code to inspect the variables (hint: Plugins>Macro>New Macro, followed by pasting code and choosing Debug from the menu (ImageJ1) or Plugins>Macros>Interactive Interpreter... (FIJI))

I have added the code you suggested beneath makePolygon, however, it only brings up the first polygon as a duplicate and after that it encounters an error ‘ROI is outside the image’. Another issue is that I will still have to manually extract the mean and SD values from each polygon anyway which will take too long, unless there is a way to script that.

@sgericeb,

I don’t see your code, but the run("Duplicate...", "title=hexagon"); should make a duplicate of the selection in a different window with the hexagon as an active selection, ready to do some particle analyses.

Since you didn’t post an image as far as I could find, it is hard to test you code.
So I tried with the run("AuPbSn 40"); image. This gives me a perfect duplicate, with the hexagon selected in the duplicate.

If you need stdev and mean, make sure you run("Set Measurements...", "area mean standard modal min redirect=None decimal=3");

And experiment with some settings in the Analyse Partcles command if you need to have the summary.
run("Analyze Particles...", "display clear summarize");

I’ll wait for your code.

I just keep getting the same error as I mentioned above. Any ideas?

l = 230;  // length of hexagon side (pixels)

// hexagon geometry parameters
xIni = 1.0;
yIni = sqrt (3.0) / 2.0;
xSiz = xIni;
ySiz = yIni;
xDel = 3.0;
yDel = yIni;
xOff = 1.5;  // offset for every other row of hexagons

// scale up to get desired size
xIni *= l;
yIni *= l;
xSiz *= l;
ySiz *= l;
xDel *= l;
yDel *= l;
xOff *= l;

getDimensions (width, height, dummy, dummy, dummy);

// loop over rows of hexagons
iOff = 0;  // which staggered row of hexagons
y = yIni;
while (y + ySiz < height) {
  // loop over hexagons in a row
  x = xIni + (iOff % 2) * xOff;
  while (x + xSiz < width) {
      // build hexagonal ROI
      x1 = x + xSiz;
      y1 = y;
      x2 = x + xSiz / 2.0;
      y2 = y - ySiz;
      x3 = x - xSiz / 2.0;
      y3 = y - ySiz;
      x4 = x - xSiz;
      y4 = y;
      x5 = x - xSiz / 2.0;
      y5 = y + ySiz;
      x6 = x + xSiz / 2.0;
      y6 = y + ySiz;
      makePolygon (x1, y1, x2, y2, x3, y3, x4, y4, x5, y5, x6, y6); 
	  run("Duplicate...", "title=hexagon");
	  roiManager("add");
      // add to ROI Manager
    
      
      x += xDel;
  }

  iOff++;
  y += yDel;
}

// display all hexagonal ROIs
roiManager ("deselect");
roiManager ("show all");
run("Analyze Particles...", "include");


numROIs= roiManager("Count");
for (j=0; j<numROIs; j++)
{
	imgID= getImageID();
	roiManager("select",j);	
	run("Analyze Particles...", "include");
}



Hi @sgericeb,

please read my reply above again carefully. In particular you might have missed this:

There is no need to store the hexagon in ROIs as you can recreate them at will.

So while in the duplicate, don’t add the roi to the manager.

The analyse particles may/could create ROIs in the Roi Manager, but even that may not be necessary, depending on what you get as the Summary.

1 Like