Number of particles in clusters

I am looking for a method to quantify the number of particles formed in a cluster with previously defined thresholds (e.g. detect every particle that is in a cluster with more than 8 particles within a diameter of less than 90 px). I tried the cluster indicator of the biovoxxel plugin (but I can only define x-fold of overall density and I need to apply the same settings to different images with different overall densities). Is there an easy way to do this in ImageJ or is it better to use R or Bio7 with spatstat. It would be nice to display the selection after all in the original image.

Any suggestions?

Thanks a lot for your help

I played a little bit with the pattern in Bio7 and spatstat. I tried to identy the clusters according to a certain threshold (nearest neighbour distances). In my script I plot a few things (see images below).

  • A density plot (where size can be varied)
  • The L function to identify the clumbed patterns and possible cluster size (see the beginning of the first plateau over the blue line)
  • A subset data plot where the nearest neighbour distances are <30 (can be varied)
  • And a plot with arrows from the same subset data to identify the k nearest neighbours from each point (in this example k=1)

Here the script:

#Load the spatstat library!
library(spatstat)

#Create a spatstat point pattern from a ImageJ Particle analysis!
X<- ppp(Particles$X, Particles$Y, c(0,imageSizeX), c(0,imageSizeY))
W <- Window(X)
#Plot is visualized in ImageJ (Java) coordinates so we need an inverted coordinate parent plot!
plot(W, ylim=rev(W$yrange),main=NULL)
#Add a density plot
plot(density(X,adjust=0.2),add=T)
#Add the points!
plot(X, add=T)
#Add axis and title in custom font size!
axis(1,cex.axis=2)
axis(2, cex.axis=2)
title(main="Density",xlab="Width", ylab="Height", cex.lab=1.5,cex.main=3) 

#Plot L function, see: http://rpackages.ianhowson.com/cran/spatstat/man/Lest.html
L<-Lest(X)
plot(L,cex.axis=2,cex.main=3)

#Plot is visualized in ImageJ (Java) coordinates so we need an inverted coordinate parent plot!
plot(W, ylim=rev(W$yrange), main=NULL)
#Create a subset from nearest neighbour distances!
subX<-subset(X, nndist(X) <30)
#Plot the subset!
plot(subX,add=T)
#Add axis and title in custom font size!
axis(1,cex.axis=2)
axis(2, cex.axis=2)
title(main="Subset Distance < 30",xlab="Width", ylab="Height",cex.lab=1.5,cex.main=3) 

#Select the k nearest neighbours of the subset!
nnwhichX<-nnwhich(subX, k=1)
b <- subX[nnwhichX]

#Plot is visualized in ImageJ (Java) coordinates so we need an inverted coordinate parent plot!
plot(W, ylim=rev(W$yrange), main=NULL)
#Plot the k nearest neighbour of the subset with an arrow!
plot(subX,add=T)
arrows(subX$x, subX$y, b$x, b$y, angle=15, length=0.15, col="red")
#Add axis and title in custom font size!
axis(1,cex.axis=2)
axis(2, cex.axis=2)
title(main="Nearest Neighbour Visualization",xlab="Width", ylab="Height",cex.lab=1.5, cex.main=3) 

Please note that I increased the plot fonts (cex) for this forum. All plots are visualized in ImageJ coordinates!

And here is a video how you can transfer a point pattern to Bio7. All relevant variables will be automatically transferred:

You might also be interested in the spatstat example script which came to my mind. It has an example to count nearest neighbour points in a defined radius (a visualization how Ripley’s K works) which is maybe a more direct answer to your question:

Here the code from: https://github.com/spatstat/spatstat/blob/master/demo/spatstat.R

showoffK <- function(Y, current, ..., fullpicture,rad) { 
    plot(fullpicture,
             main=c("Animation using `applynbd'", "explaining the K function"))
    points(Y, cex=2)
        u <- current
    points(u[1],u[2],pch="+",cex=3)
    theta <- seq(0,2*pi,length=100)
    polygon(u[1]+ rad * cos(theta),u[2]+rad*sin(theta))
    text(u[1]+rad/3,u[2]+rad/2,Y$n,cex=3)
        if(runif(1) < 0.2) Sys.sleep(runif(1, max=0.4))
    return(Y$n)
}
   
applynbd(redwood, R=0.2, showoffK, fullpicture=redwood, rad=0.2, exclude=TRUE)

And here the changed plot with your data (90px - please control):

Code:

X <- ppp(Particles$X, Particles$Y, c(0, imageSizeX), c(0, imageSizeY))
W <- Window(X)
showoffK <- function(Y, current, ..., fullpicture, rad) {
    
    # Plot is visualized in ImageJ (Java) coordinates so we need an inverted
    # coordinate parent plot!
    plot(W, ylim = rev(W$yrange), main = c("Image"))
    plot(fullpicture, 
        add = T)
    points(Y, cex = 2)
    u <- current
    points(u[1], u[2], pch = "+", cex = 3)
    theta <- seq(0, 2 * pi, length = 100)
    polygon(u[1] + rad * cos(theta), u[2] + rad * sin(theta))
    text(u[1] + rad/3, u[2] + rad/2, Y$n, cex = 3)
    if (runif(1) < 0.2) 
        Sys.sleep(runif(1, max = 0.4))
    return(Y$n)
}
applynbd(X, R = 90, showoffK, fullpicture = X, rad = 90, exclude = TRUE)

Other resources:

Here a link to a short tutorial I created for the last ImageJ conference:

http://bio7.org/?p=2618

If you have further questions I would also consult the spatstat StackOverflow list:

5 Likes

Wow, thanks a lot. That is more than I expected. I am sure this will solve my problem

In addition to @Bio7’s quite comprehensive answer, you might also want to have a look at the Density Counting workflow in ilastik, depending on how your raw data look like and what your scientific question is.