use of gdsc.smlm.function.SkewNormalFunction in project GDSC-SMLM by aherbert.
the class PCPALMMolecules method addToPlot.
/**
* Add the skewed gaussian to the histogram plot
*
* @param plot
* @param x
* @param parameters
* Gaussian parameters
* @param alpha
* @param shape
*/
private void addToPlot(Plot2 plot, float[] x, double[] parameters, int shape) {
SkewNormalFunction sn = new SkewNormalFunction(parameters);
float[] y = new float[x.length];
for (int i = 0; i < x.length; i++) y[i] = (float) sn.evaluate(x[i]);
plot.addPoints(x, y, shape);
}
use of gdsc.smlm.function.SkewNormalFunction in project GDSC-SMLM by aherbert.
the class PCPALMMolecules method calculateAveragePrecision.
/**
* Calculate the average precision by fitting a skewed Gaussian to the histogram of the precision distribution.
* <p>
* A simple mean and SD of the histogram is computed. If the mean of the Skewed Gaussian does not fit within 3 SDs
* of the simple mean then the simple mean is returned.
*
* @param molecules
* @param title
* the plot title (null if no plot should be displayed)
* @param histogramBins
* @param logFitParameters
* Record the fit parameters to the ImageJ log
* @param removeOutliers
* The distribution is created using all values within 1.5x the inter-quartile range (IQR) of the data
* @return The average precision
*/
public double calculateAveragePrecision(ArrayList<Molecule> molecules, String title, int histogramBins, boolean logFitParameters, boolean removeOutliers) {
// Plot histogram of the precision
float[] data = new float[molecules.size()];
DescriptiveStatistics stats = new DescriptiveStatistics();
double yMin = Double.NEGATIVE_INFINITY, yMax = 0;
for (int i = 0; i < data.length; i++) {
data[i] = (float) molecules.get(i).precision;
stats.addValue(data[i]);
}
// Set the min and max y-values using 1.5 x IQR
if (removeOutliers) {
double lower = stats.getPercentile(25);
double upper = stats.getPercentile(75);
if (Double.isNaN(lower) || Double.isNaN(upper)) {
if (logFitParameters)
Utils.log("Error computing IQR: %f - %f", lower, upper);
} else {
double iqr = upper - lower;
yMin = FastMath.max(lower - iqr, stats.getMin());
yMax = FastMath.min(upper + iqr, stats.getMax());
if (logFitParameters)
Utils.log(" Data range: %f - %f. Plotting 1.5x IQR: %f - %f", stats.getMin(), stats.getMax(), yMin, yMax);
}
}
if (yMin == Double.NEGATIVE_INFINITY) {
yMin = stats.getMin();
yMax = stats.getMax();
if (logFitParameters)
Utils.log(" Data range: %f - %f", yMin, yMax);
}
float[][] hist = Utils.calcHistogram(data, yMin, yMax, histogramBins);
Plot2 plot = null;
if (title != null) {
plot = new Plot2(title, "Precision", "Frequency");
float[] xValues = hist[0];
float[] yValues = hist[1];
if (xValues.length > 0) {
double xPadding = 0.05 * (xValues[xValues.length - 1] - xValues[0]);
plot.setLimits(xValues[0] - xPadding, xValues[xValues.length - 1] + xPadding, 0, Maths.max(yValues) * 1.05);
}
plot.addPoints(xValues, yValues, Plot2.BAR);
Utils.display(title, plot);
}
// Extract non-zero data
float[] x = Arrays.copyOf(hist[0], hist[0].length);
float[] y = hist[1];
int count = 0;
float dx = (x[1] - x[0]) * 0.5f;
for (int i = 0; i < y.length; i++) if (y[i] > 0) {
x[count] = x[i] + dx;
y[count] = y[i];
count++;
}
x = Arrays.copyOf(x, count);
y = Arrays.copyOf(y, count);
// Sense check to fitted data. Get mean and SD of histogram
double[] stats2 = Utils.getHistogramStatistics(x, y);
double mean = stats2[0];
if (logFitParameters)
log(" Initial Statistics: %f +/- %f", stats2[0], stats2[1]);
// Standard Gaussian fit
double[] parameters = fitGaussian(x, y);
if (parameters == null) {
log(" Failed to fit initial Gaussian");
return mean;
}
double newMean = parameters[1];
double error = Math.abs(stats2[0] - newMean) / stats2[1];
if (error > 3) {
log(" Failed to fit Gaussian: %f standard deviations from histogram mean", error);
return mean;
}
if (newMean < yMin || newMean > yMax) {
log(" Failed to fit Gaussian: %f outside data range %f - %f", newMean, yMin, yMax);
return mean;
}
mean = newMean;
if (logFitParameters)
log(" Initial Gaussian: %f @ %f +/- %f", parameters[0], parameters[1], parameters[2]);
double[] initialSolution = new double[] { parameters[0], parameters[1], parameters[2], -1 };
// Fit to a skewed Gaussian (or appropriate function)
double[] skewParameters = fitSkewGaussian(x, y, initialSolution);
if (skewParameters == null) {
log(" Failed to fit Skewed Gaussian");
return mean;
}
SkewNormalFunction sn = new SkewNormalFunction(skewParameters);
if (logFitParameters)
log(" Skewed Gaussian: %f @ %f +/- %f (a = %f) => %f +/- %f", skewParameters[0], skewParameters[1], skewParameters[2], skewParameters[3], sn.getMean(), Math.sqrt(sn.getVariance()));
newMean = sn.getMean();
error = Math.abs(stats2[0] - newMean) / stats2[1];
if (error > 3) {
log(" Failed to fit Skewed Gaussian: %f standard deviations from histogram mean", error);
return mean;
}
if (newMean < yMin || newMean > yMax) {
log(" Failed to fit Skewed Gaussian: %f outside data range %f - %f", newMean, yMin, yMax);
return mean;
}
// Use original histogram x-axis to maintain all the bins
if (plot != null) {
x = hist[0];
for (int i = 0; i < y.length; i++) x[i] += dx;
plot.setColor(Color.red);
addToPlot(plot, x, skewParameters, Plot2.LINE);
plot.setColor(Color.black);
Utils.display(title, plot);
}
// Return the average precision from the fitted curve
return newMean;
}
Aggregations