Skip to content

Instantly share code, notes, and snippets.

@dwaithe
Last active May 18, 2020 08:45
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save dwaithe/2b9581324e3c8caf9238765ce50127fb to your computer and use it in GitHub Desktop.
Save dwaithe/2b9581324e3c8caf9238765ce50127fb to your computer and use it in GitHub Desktop.
A bulk FWHM measuring algorithm was designed and written using ImageJ macro language. For full details and example file please see here: https://github.com/dwaithe/generalMacros
/Macro written by Dominic Waithe for Victoria Zilles, Erdinc Sezgin and Falk Schneider.
//Measure FWHM at multiple points along a user-defined line
//Fits intensity profile using Gaussian Fitting
//Outputs data from STED and CONFOCAL in log.
//Dominic Waithe 2016, University of Oxford.
//Find the coordinates of the selection.
getSelectionCoordinates(xr, yr);
//Add the coordinates to the roi manager.
roiManager("Add");
//Remove any overlays(lines) which might exist.
run("Remove Overlay");
//Close the log so any printed data is fresh and not old.
close("log");
//Create memory of arrays.
fx = newArray(100000);
fy = newArray(100000);
c =0;
//Main loop for array.
for(g=0;g<xr.length-1;g++){
nX = newArray(51);
nY = newArray(51);
nX[0] = xr[g];
nY[0] = yr[g];
nX[50] = xr[g+1];
nY[50] = yr[g+1];
//Interpolates between points on line.
for(v=1;v<50;v++){
nX[v] = round((xr[g+1]*(v/50))+(xr[g]*((50-v)/50)));
nY[v] = round((yr[g+1]*(v/50))+(yr[g]*((50-v)/50)));
//We compare the second data with the first.
if(v>0 ){
dist = sqrt(((nX[v] - nX[v-1])*(nX[v] - nX[v-1])) + ((nY[v] - nY[v-1])*(nY[v] - nY[v-1])));
//removes any identical data-points.
if (dist <0.1){
}else{
fx[c] = nX[v];
fy[c] = nY[v];
c++;
}
}
}
}
gx = Array.trim(fx,c-1);
gy = Array.trim(fy,c-1);
dx = newArray(gx.length);
dy = newArray(gy.length);
c = 1;
d = 0
col =0
//Takes samples at a certain distance away in pixels.Should be three pixels apart.
for (h=0;h<gx.length-10;h=h+1){
//setPixel(gx[h],gy[h], 128);
for(c=h;c<h+10;c++){
dist = sqrt((gx[c]-gx[h])*(gx[c]-gx[h])+(gy[c]-gy[h])*(gy[c]-gy[h]));
//I set this as three pixels can be higher to a point.
//If much higher might not find on specificed range.
//You can change this:
if (dist > 3){
dx[d] = gx[c];
dy[d] = gy[c];
col++;
d++;
h=c;
break;
}}
}
xl = Array.trim(dx,d);
yl = Array.trim(dy,d);
slope = newArray(xl.length-10);
yint = newArray(xl.length-10);
title = getTitle();
//Sets batchmode to make the line plotting super-quick.
setBatchMode(true);
for(sl=1;sl<3;sl++){
c = 0;
roiManager("Select",roiManager("Count")-1);
setSlice(sl);
//Takes the input pixels and calculates best fit line and then perpendicular line.
for(i=5;i<xl.length-5;i=i+1){
sumX = 0;
sumY = 0;
count = 5.0;
for(b=-2;b<3;b++){
sumX += xl[i+b];
sumY += yl[i+b];
}
//Calculate the mean coordinate.
XMean = sumX/count;
YMean = sumY/count;
up = 0;
up = 0;
bot = 0;
//Calculates sums of top and bottom lines
for(b=-2;b<3;b++){
up += ((xl[i+b]-XMean)*(yl[i+b]-YMean));
bot += ((xl[i+b]-XMean)*(xl[i+b]-XMean));
}
//Calculates the gradient in the perpendicular direction to the line gradient.
slope[c] = -1/(up/bot);
//We calculate the Yintercept
yint[c] = YMean-(slope[c]*XMean);
//If the line is horizontal we catch as follows
if(slope[c] <-9999999){
nopp = 20;
nadj = 0;
}
//If the line is vertical we catch as follows
else if(isNaN(slope[c]) == true){
nopp = 0;
nadj = 20;
}else{
//We calculate the the points based on our gradient and y-intercept.
x0 = xl[i-2];
x1 = (xl[i+2]);
y0 =(slope[c]*xl[i-2])+yint[c];
y1 = (slope[c]*xl[i+2])+yint[c];
//Calculate the opp and adj of triangle.
opp = y1-y0;
adj = x1-x0;
if (opp ==0){
opp = 0.000001;
}
if (adj ==0){
adj = 0.000001;
}
//We calculate the angle from the opp and adj.
theta = atan(opp/adj);
//We then calculate the opp and adj
nopp = 20*sin(theta);
nadj = 20*cos(theta);
//See, A-level geometry did have a use!
}
//Calculates where each of the lines should start adn end.
a0 =(xl[i]);
a1 = (yl[i]);
b0 = (xl[i]+nadj);
b1 = (yl[i]+nopp);
c0 = (xl[i]-nadj);
c1 = (yl[i]-nopp);
//Makes the line and plots a hidden plot.
makeLine(b0,b1,c0,c1);
run("Plot Profile");
Plot.getValues(x, y);
//Fits the gaussian
Fit.doFit("Gaussian", x, y);
if(sl==1){
mtext = "conf";
}
else{
mtext = "sted";
}
//Calculates the FWHM
sigma=Fit.p(3);
FWHM=abs(2*sqrt(2*log(2))*sigma);
//Prints to log.
print(mtext+"\ta=\t"+d2s(Fit.p(0),6)+"\tb\t"+d2s(Fit.p(1),6)+"\tc\t"+d2s(Fit.p(2),6)+"\td=\t"+d2s(Fit.p(3),6)+"\tFWHM\t"+FWHM);
selectWindow(title);
//Draws line on image as overlay.
Overlay.drawLine(a0,a1,b0,b1);
Overlay.drawLine(a0,a1,c0,c1);
Overlay.show()
c = c+1;
}
}
setBatchMode(false);
//Restores the original line.
roiManager("Select",roiManager("Count")-1);
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment