/**
*Fit Sphere
*Takes point selections from ROI manager and returns the
*centroid and radius of a best fit sphere
*Ported from Angelo Tardugno's C++
*And based on a paper that we can't locate right now...
*
*This program is free software: you can redistribute it and/or modify
*it under the terms of the GNU General Public License as published by
*the Free Software Foundation, either version 3 of the License, or
*(at your option) any later version.
*
*This program is distributed in the hope that it will be useful,
*but WITHOUT ANY WARRANTY; without even the implied warranty of
*MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
*GNU General Public License for more details.
*
*You should have received a copy of the GNU General Public License
*along with this program. If not, see .
*
*@author Michael Doube and Angelo Tardugno
*@version 0.1
*/
import Jama.Matrix;
import ij.IJ;
import ij.ImagePlus;
import ij.process.ImageProcessor;
import ij.plugin.filter.PlugInFilter;
import ij.gui.*;
import ij.plugin.frame.*;
import ij.measure.Calibration;
import java.awt.Rectangle;
import java.awt.List;
public class Fit_Sphere implements PlugInFilter {
ImagePlus imp;
RoiManager roiMan = RoiManager.getInstance();
public int setup(String arg, ImagePlus imp) {
this.imp = imp;
if (roiMan == null){
IJ.run("ROI Manager...");
IJ.error("Please populate ROI Manager with point ROIs");
}
return DOES_ALL + STACK_REQUIRED;
}
public void run(ImageProcessor ip) {
Calibration cal = imp.getCalibration();
double vW = cal.pixelWidth;
double vH = cal.pixelHeight;
double vD = cal.pixelDepth;
String units = cal.getUnit();
int no_p = roiMan.getCount();
List listRoi = roiMan.getList();
double[] datapoints = new double[3*no_p];
double xSum = 0, ySum = 0, zSum = 0;
Roi[] roiList = roiMan.getRoisAsArray();
int j = 0;
for (int i = 0; i 1e-10){
Matrix J = new Matrix(no_p, 4);
double[][] Jp = J.getArray();
Matrix d = new Matrix(no_p, 1);
double[][] dp = d.getArray(); //dp is a pointer to d's values
g_old = g_new;
for (int i = 0; i < no_p; i++){
r[i] = Math.sqrt(Math.pow(datapoints[3*i]-centroid[0],2) + Math.pow(datapoints[3*i+1]-centroid[1],2)
+ Math.pow(datapoints[3*i+2]-centroid[2],2));
dp[i][0] = r[i] - radius;
Jp[i][0] = -(datapoints[3*i]-centroid[0])/r[i];
Jp[i][1] = -(datapoints[3*i+1]-centroid[1])/r[i];
Jp[i][2] = -(datapoints[3*i+2]-centroid[2])/r[i];
Jp[i][3] = -1;
}
d = d.times(-1);
Matrix J1 = J;
J = J.transpose();
Matrix J2 = J.times(J1);
Matrix Jd = J.times(d);
Matrix x = J2.inverse().times(Jd);
double[][] xp = x.getArray();
centroid[0] += xp[0][0];
centroid[1] += xp[1][0];
centroid[2] += xp[2][0];
radius += xp[3][0];
d = d.times(-1);
Matrix G = J.times(d);
double[][] Gp = G.getArray();
g_new = 0.0;
for (int i = 0; i < 4; i++)
g_new += Gp[i][0];
}
IJ.write("Centroid = ("+centroid[0]+", "+centroid[1]+", "+centroid[2]+"): Radius = "+radius+" "+units);
}
}