package cz.cuni.lf1.lge.ThunderSTORM.estimators; import cz.cuni.lf1.lge.ThunderSTORM.UI.StoppedByUserException; import cz.cuni.lf1.lge.ThunderSTORM.estimators.PSF.Molecule; import cz.cuni.lf1.lge.ThunderSTORM.util.Point; import ij.process.FloatProcessor; import java.util.ArrayList; import java.util.List; /** * This is used for MFA PSF fitting on the entire image. */ public class FullImageFitting implements IEstimator { IOneLocationFitter fitter; double[] xgrid; double[] ygrid; public FullImageFitting(IOneLocationFitter fitter) { this.fitter = fitter; } @Override public List<Molecule> estimateParameters(FloatProcessor image, List<Point> detections) throws StoppedByUserException { List<Molecule> results = new ArrayList<Molecule>(); try { int w = image.getWidth(); int h = image.getHeight(); int x0 = w / 2; int y0 = h / 2; initializeGrid(x0, y0, w, h); int maxI = getBestDetection(detections); SubImage subImage = new SubImage( image.getWidth(), image.getHeight(), xgrid, ygrid, getImageData(image), detections.get(maxI).x.doubleValue() - x0, detections.get(maxI).y.doubleValue() - y0); Molecule psf = fitter.fit(subImage); if(psf.isSingleMolecule()) { if(checkIsInSubimage(psf.getX(), psf.getY(), image.getWidth(), image.getHeight())) { psf.setX(psf.getX() + x0 + 0.5); psf.setY(psf.getY() + y0 + 0.5); psf.setDetections(null); MultipleLocationsImageFitting.appendGoodnessOfFit(psf, fitter, subImage); MultipleLocationsImageFitting.appendCalculatedUncertainty(psf); results.add(psf); } } else { for(Molecule m : psf.getDetections()) { if(checkIsInSubimage(m.getX(), m.getY(), image.getWidth(), image.getHeight())) { m.setX(m.getX() + x0 + 0.5); m.setY(m.getY() + y0 + 0.5); MultipleLocationsImageFitting.appendGoodnessOfFit(m, fitter, subImage); MultipleLocationsImageFitting.appendCalculatedUncertainty(m); results.add(m); } } psf.setDetections(null); } } catch(Exception ex) { // } return results; } private void initializeGrid(int x0, int y0, int w, int h) { xgrid = new double[w * h]; ygrid = new double[w * h]; int idx = 0; for(int y = 0; y < h; y++) { for(int x = 0; x < w; x++) { xgrid[idx] = x - x0; ygrid[idx] = y - y0; idx++; } } } private boolean checkIsInSubimage(double x, double y, double w, double h) { return Math.abs(x) <= w && Math.abs(y) <= h; } private double [] getImageData(FloatProcessor img) { float[] pixels = (float[]) img.getPixels(); double[] imgData = new double[pixels.length]; for(int i = 0; i < pixels.length; i++) { imgData[i] = (double)pixels[i]; } return imgData; } private int getBestDetection(List<Point> detections) { int maxI = 0; for(int i = 1, im = detections.size(); i < im; i++) { if(detections.get(i).val.doubleValue() > detections.get(maxI).val.doubleValue()) { maxI = i; } } return maxI; } }