use of uk.ac.sussex.gdsc.smlm.filters.BlockMeanFilter in project GDSC-SMLM by aherbert.
the class GaussianFit method runFinal.
/**
* Perform fitting using the chosen maxima. Update the overlay if successful.
*
* @param ip The input image
*/
private void runFinal(ImageProcessor ip) {
ip.reset();
final Rectangle bounds = ip.getRoi();
// Crop to the ROI
final float[] data = ImageJImageConverter.getData(ip);
final int width = bounds.width;
final int height = bounds.height;
// Sort the maxima
float[] smoothData = data;
if (getSmooth() > 0) {
// Smoothing destructively modifies the data so create a copy
smoothData = Arrays.copyOf(data, width * height);
final BlockMeanFilter filter = new BlockMeanFilter();
if (settings.smooth <= settings.border) {
filter.stripedBlockFilterInternal(smoothData, width, height, (float) settings.smooth);
} else {
filter.stripedBlockFilter(smoothData, width, height, (float) settings.smooth);
}
}
SortUtils.sortIndices(maxIndices, smoothData, true);
// Show the candidate peaks
if (maxIndices.length > 0) {
final String message = String.format("Identified %d peaks", maxIndices.length);
if (isLogProgress()) {
IJ.log(message);
for (final int index : maxIndices) {
IJ.log(String.format(" %.2f @ [%d,%d]", data[index], bounds.x + index % width, bounds.y + index / width));
}
}
// Check whether to run if the number of peaks is large
if (maxIndices.length > 10) {
final GenericDialog gd = new GenericDialog("Warning");
gd.addMessage(message + "\nDo you want to fit?");
gd.showDialog();
if (gd.wasCanceled()) {
return;
}
}
} else {
IJ.log("No maxima identified");
return;
}
results = new ImageJTablePeakResults(settings.showDeviations, imp.getTitle() + " [" + imp.getCurrentSlice() + "]");
final CalibrationWriter cw = new CalibrationWriter();
cw.setIntensityUnit(IntensityUnit.COUNT);
cw.setDistanceUnit(DistanceUnit.PIXEL);
cw.setAngleUnit(AngleUnit.RADIAN);
results.setCalibration(cw.getCalibration());
results.setPsf(PsfProtosHelper.getDefaultPsf(getPsfType()));
results.setShowFittingData(true);
results.setAngleUnit(AngleUnit.DEGREE);
results.begin();
// Perform the Gaussian fit
long ellapsed = 0;
final FloatProcessor renderedImage = settings.showFit ? new FloatProcessor(ip.getWidth(), ip.getHeight()) : null;
if (!settings.singleFit) {
if (isLogProgress()) {
IJ.log("Combined fit");
}
// Estimate height from smoothed data
final double[] estimatedHeights = new double[maxIndices.length];
for (int i = 0; i < estimatedHeights.length; i++) {
estimatedHeights[i] = smoothData[maxIndices[i]];
}
final FitConfiguration config = new FitConfiguration();
setupPeakFiltering(config);
final long time = System.nanoTime();
final double[] params = fitMultiple(data, width, height, maxIndices, estimatedHeights);
ellapsed = System.nanoTime() - time;
if (params != null) {
// Copy all the valid parameters into a new array
final double[] validParams = new double[params.length];
int count = 0;
int validPeaks = 0;
validParams[count++] = params[0];
final double[] initialParams = convertParameters(fitResult.getInitialParameters());
final double[] paramsDev = convertParameters(fitResult.getParameterDeviations());
final Rectangle regionBounds = new Rectangle();
final float[] xpoints = new float[maxIndices.length];
final float[] ypoints = new float[maxIndices.length];
int npoints = 0;
for (int i = 1, n = 0; i < params.length; i += Gaussian2DFunction.PARAMETERS_PER_PEAK, n++) {
final int y = maxIndices[n] / width;
final int x = maxIndices[n] % width;
// Check the peak is a good fit
if (settings.filterResults && config.validatePeak(n, initialParams, params, paramsDev) != FitStatus.OK) {
continue;
}
if (settings.showFit) {
// Copy the valid parameters before there are adjusted to global bounds
validPeaks++;
for (int ii = i, j = 0; j < Gaussian2DFunction.PARAMETERS_PER_PEAK; ii++, j++) {
validParams[count++] = params[ii];
}
}
final double[] peakParams = extractParams(params, i);
final double[] peakParamsDev = extractParams(paramsDev, i);
addResult(bounds, regionBounds, peakParams, peakParamsDev, npoints, x, y, data[maxIndices[n]]);
// Add fit result to the overlay - Coords are updated with the region offsets in addResult
final double xf = peakParams[Gaussian2DFunction.X_POSITION];
final double yf = peakParams[Gaussian2DFunction.Y_POSITION];
xpoints[npoints] = (float) xf;
ypoints[npoints] = (float) yf;
npoints++;
}
setOverlay(npoints, xpoints, ypoints);
// Draw the fit
if (validPeaks != 0) {
addToImage(bounds.x, bounds.y, renderedImage, validParams, validPeaks, width, height);
}
} else {
if (isLogProgress()) {
IJ.log("Failed to fit " + TextUtils.pleural(maxIndices.length, "peak") + ": " + getReason(fitResult));
}
imp.setOverlay(null);
}
} else {
if (isLogProgress()) {
IJ.log("Individual fit");
}
int npoints = 0;
final float[] xpoints = new float[maxIndices.length];
final float[] ypoints = new float[maxIndices.length];
// Extract each peak and fit individually
final ImageExtractor ie = ImageExtractor.wrap(data, width, height);
float[] region = null;
final Gaussian2DFitter gf = createGaussianFitter(settings.filterResults);
double[] validParams = null;
final ShortProcessor renderedImageCount = settings.showFit ? new ShortProcessor(ip.getWidth(), ip.getHeight()) : null;
for (int n = 0; n < maxIndices.length; n++) {
final int y = maxIndices[n] / width;
final int x = maxIndices[n] % width;
final long time = System.nanoTime();
final Rectangle regionBounds = ie.getBoxRegionBounds(x, y, settings.singleRegionSize);
region = ie.crop(regionBounds, region);
final int newIndex = (y - regionBounds.y) * regionBounds.width + x - regionBounds.x;
if (isLogProgress()) {
IJ.log("Fitting peak " + (n + 1));
}
final double[] peakParams = fitSingle(gf, region, regionBounds.width, regionBounds.height, newIndex, smoothData[maxIndices[n]]);
ellapsed += System.nanoTime() - time;
// Output fit result
if (peakParams != null) {
if (settings.showFit) {
// Copy the valid parameters before there are adjusted to global bounds
validParams = peakParams.clone();
}
double[] peakParamsDev = null;
if (settings.showDeviations) {
peakParamsDev = convertParameters(fitResult.getParameterDeviations());
}
addResult(bounds, regionBounds, peakParams, peakParamsDev, n, x, y, data[maxIndices[n]]);
// Add fit result to the overlay - Coords are updated with the region offsets in addResult
final double xf = peakParams[Gaussian2DFunction.X_POSITION];
final double yf = peakParams[Gaussian2DFunction.Y_POSITION];
xpoints[npoints] = (float) xf;
ypoints[npoints] = (float) yf;
npoints++;
// Draw the fit
if (settings.showDeviations) {
final int ox = bounds.x + regionBounds.x;
final int oy = bounds.y + regionBounds.y;
addToImage(ox, oy, renderedImage, validParams, 1, regionBounds.width, regionBounds.height);
addCount(ox, oy, renderedImageCount, regionBounds.width, regionBounds.height);
}
} else if (isLogProgress()) {
IJ.log("Failed to fit peak " + (n + 1) + ": " + getReason(fitResult));
}
}
// Update the overlay
if (npoints > 0) {
setOverlay(npoints, xpoints, ypoints);
} else {
imp.setOverlay(null);
}
// Create the mean
if (settings.showFit) {
for (int i = renderedImageCount.getPixelCount(); i-- > 0; ) {
final int count = renderedImageCount.get(i);
if (count > 1) {
renderedImage.setf(i, renderedImage.getf(i) / count);
}
}
}
}
results.end();
if (renderedImage != null) {
ImageJUtils.display(TITLE, renderedImage);
}
if (isLogProgress()) {
IJ.log("Time = " + (ellapsed / 1000000.0) + "ms");
}
}
use of uk.ac.sussex.gdsc.smlm.filters.BlockMeanFilter in project GDSC-SMLM by aherbert.
the class GaussianFit method run.
@Override
public void run(ImageProcessor ip) {
final Rectangle bounds = ip.getRoi();
// Crop to the ROI
final float[] data = ImageJImageConverter.getData(ip);
final int width = bounds.width;
final int height = bounds.height;
if (getSmooth() > 0) {
// No need for a copy since we are using a snapshot buffer
final BlockMeanFilter filter = new BlockMeanFilter();
filter.stripedBlockFilter(data, width, height, (float) getSmooth());
}
maxIndices = getMaxima(data, width, height);
if (settings.topN > 0 && maxIndices.length > settings.topN) {
SortUtils.sortIndices(maxIndices, data, true);
maxIndices = Arrays.copyOf(maxIndices, settings.topN);
}
// Show an overlay of the indices
if (maxIndices.length > 0) {
final int nMaxima = maxIndices.length;
final float[] xpoints = new float[nMaxima];
final float[] ypoints = new float[nMaxima];
int count = 0;
for (final int index : maxIndices) {
final int x = index % width;
final int y = index / width;
xpoints[count] = 0.5f + bounds.x + x;
ypoints[count] = 0.5f + bounds.y + y;
count++;
}
setOverlay(nMaxima, xpoints, ypoints);
} else {
imp.setOverlay(null);
}
for (int index = data.length; index-- > 0; ) {
ip.setf(bounds.x + index % width, bounds.y + index / width, data[index]);
}
}
use of uk.ac.sussex.gdsc.smlm.filters.BlockMeanFilter in project GDSC-SMLM by aherbert.
the class PsfCreator method getLimitsPerSlice.
/**
* Gets the min and max limits per slice.
*
* <p>Smooths the PSF block region data before analysis.
*
* @param psf the psf
* @param maxx the maxx
* @param maxy the maxy
* @param n the block size of the region
* @return the limits per slice
*/
private static float[][] getLimitsPerSlice(float[][] psf, int maxx, int maxy, int n) {
final BlockMeanFilter filter = new BlockMeanFilter();
final float[][] limits = new float[2][psf.length];
for (int zz = 0; zz < psf.length; zz++) {
float[] data = psf[zz];
if (n > 0) {
data = data.clone();
filter.rollingBlockFilterInternal(data, maxx, maxy, n);
}
final float[] l = findLimits(data, maxx, maxy, n);
limits[0][zz] = l[0];
limits[1][zz] = l[1];
// float[] l2 = Maths.limits(data);
// System.out.printf("%f - %f vs %f - %f\n", l[0], l[1], l2[0], l2[1]);
}
return limits;
}
Aggregations