List of usage examples for org.apache.commons.math3.exception ConvergenceException getMessage
@Override
public String getMessage()
From source file:edu.stanford.cfuller.imageanalysistools.fitting.GaussianImageObject.java
/** * Fits this object to a 3-dimensional gaussian, and estimates error and goodness of fit. * @param p The parameters for the current analysis. *///from ww w .java 2 s . com public void fitPosition(ParameterDictionary p) { if (this.sizeInPixels == 0) { this.nullifyImages(); return; } this.fitParametersByChannel = new java.util.ArrayList<FitParameters>(); this.fitR2ByChannel = new java.util.ArrayList<Double>(); this.fitErrorByChannel = new java.util.ArrayList<Double>(); this.nPhotonsByChannel = new java.util.ArrayList<Double>(); GaussianFitter3D gf = new GaussianFitter3D(); //System.out.println(this.parent.getDimensionSizes().getZ()); int numChannels = 0; if (p.hasKey(NUM_WAVELENGTHS_PARAM)) { numChannels = p.getIntValueForKey(NUM_WAVELENGTHS_PARAM); } else { numChannels = this.parent.getDimensionSizes().get(ImageCoordinate.C); } for (int channelIndex = 0; channelIndex < numChannels; channelIndex++) { RealVector fitParameters = new ArrayRealVector(7, 0.0); double ppg = p.getDoubleValueForKey(PHOTONS_PER_LEVEL_PARAM); this.parentBoxMin.set(ImageCoordinate.C, channelIndex); this.parentBoxMax.set(ImageCoordinate.C, channelIndex + 1); this.boxImages(); List<Double> x = new java.util.ArrayList<Double>(); List<Double> y = new java.util.ArrayList<Double>(); List<Double> z = new java.util.ArrayList<Double>(); List<Double> f = new java.util.ArrayList<Double>(); for (ImageCoordinate ic : this.parent) { x.add((double) ic.get(ImageCoordinate.X)); y.add((double) ic.get(ImageCoordinate.Y)); z.add((double) ic.get(ImageCoordinate.Z)); f.add((double) parent.getValue(ic)); } xValues = new double[x.size()]; yValues = new double[y.size()]; zValues = new double[z.size()]; functionValues = new double[f.size()]; double xCentroid = 0; double yCentroid = 0; double zCentroid = 0; double totalCounts = 0; for (int i = 0; i < x.size(); i++) { xValues[i] = x.get(i); yValues[i] = y.get(i); zValues[i] = z.get(i); functionValues[i] = f.get(i) * ppg; xCentroid += xValues[i] * functionValues[i]; yCentroid += yValues[i] * functionValues[i]; zCentroid += zValues[i] * functionValues[i]; totalCounts += functionValues[i]; } xCentroid /= totalCounts; yCentroid /= totalCounts; zCentroid /= totalCounts; //z sometimes seems to be a bit off... trying (20110415) to go back to max value pixel at x,y centroid int xRound = (int) Math.round(xCentroid); int yRound = (int) Math.round(yCentroid); double maxVal = 0; int maxInd = 0; double minZ = Double.MAX_VALUE; double maxZ = 0; for (int i = 0; i < x.size(); i++) { if (zValues[i] < minZ) minZ = zValues[i]; if (zValues[i] > maxZ) maxZ = zValues[i]; if (xValues[i] == xRound && yValues[i] == yRound) { if (functionValues[i] > maxVal) { maxVal = functionValues[i]; maxInd = (int) zValues[i]; } } } zCentroid = maxInd; //parameter ordering: amplitude, var x-y, var z, x/y/z coords, background //amplitude: find the max value; background: find the min value double maxValue = 0; double minValue = Double.MAX_VALUE; for (ImageCoordinate ic : this.parent) { if (parent.getValue(ic) > maxValue) maxValue = parent.getValue(ic); if (parent.getValue(ic) < minValue) minValue = parent.getValue(ic); } fitParameters.setEntry(0, (maxValue - minValue) * 0.95); fitParameters.setEntry(6, minValue + 0.05 * (maxValue - minValue)); //positions fitParameters.setEntry(3, xCentroid); fitParameters.setEntry(4, yCentroid); fitParameters.setEntry(5, zCentroid); //variances final double limitedWidthxy = 200; final double limitedWidthz = 500; double sizex = limitedWidthxy / p.getDoubleValueForKey(PIXELSIZE_PARAM); double sizez = limitedWidthz / p.getDoubleValueForKey(SECTIONSIZE_PARAM); if (p.hasKey(Z_WIDTH_PARAM)) { sizez = p.getDoubleValueForKey(Z_WIDTH_PARAM); } if (p.hasKey(XY_WIDTH_PARAM)) { sizex = p.getDoubleValueForKey(XY_WIDTH_PARAM); } fitParameters.setEntry(1, sizex / 2); fitParameters.setEntry(2, sizez / 2); //amplitude and background are in arbitrary intensity units; convert to photon counts fitParameters.setEntry(0, fitParameters.getEntry(0) * ppg); fitParameters.setEntry(6, fitParameters.getEntry(6) * ppg); //System.out.println("guess: " + fitParameters); //do the fit fitParameters = gf.fit(this, fitParameters, ppg); //System.out.println("fit: " + fitParameters); FitParameters fp = new FitParameters(); fp.setPosition(ImageCoordinate.X, fitParameters.getEntry(3)); fp.setPosition(ImageCoordinate.Y, fitParameters.getEntry(4)); fp.setPosition(ImageCoordinate.Z, fitParameters.getEntry(5)); fp.setSize(ImageCoordinate.X, fitParameters.getEntry(1)); fp.setSize(ImageCoordinate.Y, fitParameters.getEntry(1)); fp.setSize(ImageCoordinate.Z, fitParameters.getEntry(2)); fp.setAmplitude(fitParameters.getEntry(0)); fp.setBackground(fitParameters.getEntry(6)); fitParametersByChannel.add(fp); //calculate R2 double residualSumSquared = 0; double mean = 0; double variance = 0; double R2 = 0; double n_photons = 0; for (int i = 0; i < this.xValues.length; i++) { residualSumSquared += Math.pow(GaussianFitter3D.fitResidual(functionValues[i], xValues[i], yValues[i], zValues[i], fitParameters), 2); mean += functionValues[i]; n_photons += functionValues[i] - fitParameters.getEntry(6); } mean /= functionValues.length; for (int i = 0; i < this.xValues.length; i++) { variance += Math.pow(functionValues[i] - mean, 2); } R2 = 1 - (residualSumSquared / variance); this.fitR2ByChannel.add(R2); this.unboxImages(); //calculate fit error double s_xy = fitParameters.getEntry(1) * fitParameters.getEntry(1) * Math.pow(p.getDoubleValueForKey(PIXELSIZE_PARAM), 2); double s_z = fitParameters.getEntry(2) * fitParameters.getEntry(2) * Math.pow(p.getDoubleValueForKey(SECTIONSIZE_PARAM), 2); //s_z = 0; //remove!! double error = (2 * s_xy + s_z) / (n_photons - 1);// + 4*Math.sqrt(Math.PI) * Math.pow(2*s_xy,1.5)*Math.pow(fitParameters.getEntry(6),2)/(p.getDoubleValueForKey("pixelsize_nm")*n_photons*n_photons); double b = fitParameters.getEntry(6); double a = p.getDoubleValueForKey(PIXELSIZE_PARAM); double alpha = p.getDoubleValueForKey(SECTIONSIZE_PARAM); double sa_x = s_xy + Math.pow(a, 2) / 12; double sa_z = s_z + Math.pow(alpha, 2) / 12; //System.out.printf("b = %f, a = %f, alpha = %f, s_xy = %f, s_z = %f, n= %f\n", b, a, alpha, s_xy, s_z, n_photons); double error_x = sa_x / n_photons * (16.0 / 9.0 + 8 * Math.PI * sa_x * b * b / (n_photons * Math.pow(p.getDoubleValueForKey(PIXELSIZE_PARAM), 2))); double error_z = sa_z / n_photons * (16.0 / 9.0 + 8 * Math.PI * sa_z * b * b / (n_photons * Math.pow(p.getDoubleValueForKey(SECTIONSIZE_PARAM), 2))); double A = 1.0 / (2 * Math.sqrt(2) * Math.pow(Math.PI, 1.5) * Math.sqrt(sa_z) * sa_x); ErrIntFunc eif = new ErrIntFunc(); eif.setParams(b, n_photons, A, sa_z, sa_x, a, alpha); LegendreGaussIntegrator lgi = new LegendreGaussIntegrator(5, 10, 1000); //integrate over 10*width of PSF in z double size = 10 * Math.sqrt(sa_z); double intpart = 0; try { if (b < 0) throw new ConvergenceException(new DummyLocalizable("negative background!")); // a negative value for b seems to cause the integration to hang, preventing the program from progressing intpart = lgi.integrate(10000, eif, -size, size); double fullIntPart = intpart + Math.pow(2 * Math.PI, 1.5) * sa_x * A / Math.sqrt(sa_z); error_x = Math.sqrt(2 / (n_photons * sa_z / (2 * sa_z + sa_x) * fullIntPart)); error_z = Math.sqrt(2 / (n_photons * sa_x / (2 * sa_z + sa_x) * fullIntPart)); } catch (ConvergenceException e) { LoggingUtilities.getLogger().severe("Integration error: " + e.getMessage()); error_x = -1; error_z = -1; } if (error_x > 0 && error_z > 0) { error = Math.sqrt(2 * error_x * error_x + error_z * error_z); } else { error = Double.NaN; } this.fitErrorByChannel.add(error); this.positionsByChannel.add(fitParameters.getSubVector(3, 3)); this.nPhotonsByChannel.add(n_photons); } this.hadFittingError = false; }