void Contrast(ImagePlus imp, int radius, double par1, double par2, boolean doIwhite) { // G. Landini, 2013 // Based on a simple contrast toggle. This procedure does not have user-provided paramters other // than the kernel radius // Sets the pixel value to either white or black depending on whether its current value is // closest to the local Max or Min respectively // The procedure is similar to Toggle Contrast Enhancement (see Soille, Morphological Image // Analysis (2004), p. 259 ImagePlus Maximp, Minimp; ImageProcessor ip = imp.getProcessor(), ipMax, ipMin; int c_value = 0; int mid_gray; byte object; byte backg; if (doIwhite) { object = (byte) 0xff; backg = (byte) 0; } else { object = (byte) 0; backg = (byte) 0xff; } Maximp = duplicateImage(ip); ipMax = Maximp.getProcessor(); RankFilters rf = new RankFilters(); rf.rank(ipMax, radius, rf.MAX); // Maximum // Maximp.show(); Minimp = duplicateImage(ip); ipMin = Minimp.getProcessor(); rf.rank(ipMin, radius, rf.MIN); // Minimum // Minimp.show(); byte[] pixels = (byte[]) ip.getPixels(); byte[] max = (byte[]) ipMax.getPixels(); byte[] min = (byte[]) ipMin.getPixels(); for (int i = 0; i < pixels.length; i++) { pixels[i] = ((Math.abs((int) (max[i] & 0xff - pixels[i] & 0xff)) <= Math.abs((int) (pixels[i] & 0xff - min[i] & 0xff)))) ? object : backg; } // imp.updateAndDraw(); return; }
/*------------------------------------------------------------------*/ double getInitialCausalCoefficientMirrorOnBounds(double[] c, double z, double tolerance) { double z1 = z, zn = Math.pow(z, c.length - 1); double sum = c[0] + zn * c[c.length - 1]; int horizon = c.length; if (0.0 < tolerance) { horizon = 2 + (int) (Math.log(tolerance) / Math.log(Math.abs(z))); horizon = (horizon < c.length) ? (horizon) : (c.length); } zn = zn * zn; for (int n = 1; (n < (horizon - 1)); n++) { zn = zn / z; sum = sum + (z1 + zn) * c[n]; z1 = z1 * z; } return (sum / (1.0 - Math.pow(z, 2 * c.length - 2))); } /* end getInitialCausalCoefficientMirrorOnBounds */
/* if selection is closed shape, create a circle with the same area and centroid, otherwise use<br> the Pratt method to fit a circle to the points that define the line or multi-point selection.<br> Reference: Pratt V., Direct least-squares fitting of algebraic surfaces", Computer Graphics, Vol. 21, pages 145-152 (1987).<br> Original code: Nikolai Chernov's MATLAB script for Newton-based Pratt fit.<br> (http://www.math.uab.edu/~chernov/cl/MATLABcircle.html)<br> Java version: https://github.com/mdoube/BoneJ/blob/master/src/org/doube/geometry/FitCircle.java<br> @authors Nikolai Chernov, Michael Doube, Ved Sharma */ void fitCircle(ImagePlus imp) { Roi roi = imp.getRoi(); if (roi == null) { noRoi("Fit Circle"); return; } if (roi.isArea()) { // create circle with the same area and centroid ImageProcessor ip = imp.getProcessor(); ip.setRoi(roi); ImageStatistics stats = ImageStatistics.getStatistics(ip, Measurements.AREA + Measurements.CENTROID, null); double r = Math.sqrt(stats.pixelCount / Math.PI); imp.killRoi(); int d = (int) Math.round(2.0 * r); IJ.makeOval( (int) Math.round(stats.xCentroid - r), (int) Math.round(stats.yCentroid - r), d, d); return; } Polygon poly = roi.getPolygon(); int n = poly.npoints; int[] x = poly.xpoints; int[] y = poly.ypoints; if (n < 3) { IJ.error("Fit Circle", "At least 3 points are required to fit a circle."); return; } // calculate point centroid double sumx = 0, sumy = 0; for (int i = 0; i < n; i++) { sumx = sumx + poly.xpoints[i]; sumy = sumy + poly.ypoints[i]; } double meanx = sumx / n; double meany = sumy / n; // calculate moments double[] X = new double[n], Y = new double[n]; double Mxx = 0, Myy = 0, Mxy = 0, Mxz = 0, Myz = 0, Mzz = 0; for (int i = 0; i < n; i++) { X[i] = x[i] - meanx; Y[i] = y[i] - meany; double Zi = X[i] * X[i] + Y[i] * Y[i]; Mxy = Mxy + X[i] * Y[i]; Mxx = Mxx + X[i] * X[i]; Myy = Myy + Y[i] * Y[i]; Mxz = Mxz + X[i] * Zi; Myz = Myz + Y[i] * Zi; Mzz = Mzz + Zi * Zi; } Mxx = Mxx / n; Myy = Myy / n; Mxy = Mxy / n; Mxz = Mxz / n; Myz = Myz / n; Mzz = Mzz / n; // calculate the coefficients of the characteristic polynomial double Mz = Mxx + Myy; double Cov_xy = Mxx * Myy - Mxy * Mxy; double Mxz2 = Mxz * Mxz; double Myz2 = Myz * Myz; double A2 = 4 * Cov_xy - 3 * Mz * Mz - Mzz; double A1 = Mzz * Mz + 4 * Cov_xy * Mz - Mxz2 - Myz2 - Mz * Mz * Mz; double A0 = Mxz2 * Myy + Myz2 * Mxx - Mzz * Cov_xy - 2 * Mxz * Myz * Mxy + Mz * Mz * Cov_xy; double A22 = A2 + A2; double epsilon = 1e-12; double ynew = 1e+20; int IterMax = 20; double xnew = 0; int iterations = 0; // Newton's method starting at x=0 for (int iter = 1; iter <= IterMax; iter++) { iterations = iter; double yold = ynew; ynew = A0 + xnew * (A1 + xnew * (A2 + 4. * xnew * xnew)); if (Math.abs(ynew) > Math.abs(yold)) { if (IJ.debugMode) IJ.log("Fit Circle: wrong direction: |ynew| > |yold|"); xnew = 0; break; } double Dy = A1 + xnew * (A22 + 16 * xnew * xnew); double xold = xnew; xnew = xold - ynew / Dy; if (Math.abs((xnew - xold) / xnew) < epsilon) break; if (iter >= IterMax) { if (IJ.debugMode) IJ.log("Fit Circle: will not converge"); xnew = 0; } if (xnew < 0) { if (IJ.debugMode) IJ.log("Fit Circle: negative root: x = " + xnew); xnew = 0; } } if (IJ.debugMode) IJ.log("Fit Circle: n=" + n + ", xnew=" + IJ.d2s(xnew, 2) + ", iterations=" + iterations); // calculate the circle parameters double DET = xnew * xnew - xnew * Mz + Cov_xy; double CenterX = (Mxz * (Myy - xnew) - Myz * Mxy) / (2 * DET); double CenterY = (Myz * (Mxx - xnew) - Mxz * Mxy) / (2 * DET); double radius = Math.sqrt(CenterX * CenterX + CenterY * CenterY + Mz + 2 * xnew); if (Double.isNaN(radius)) { IJ.error("Fit Circle", "Points are collinear."); return; } CenterX = CenterX + meanx; CenterY = CenterY + meany; imp.killRoi(); IJ.makeOval( (int) Math.round(CenterX - radius), (int) Math.round(CenterY - radius), (int) Math.round(2 * radius), (int) Math.round(2 * radius)); }
String getInfo(ImagePlus imp, ImageProcessor ip) { String s = new String("\n"); s += "Title: " + imp.getTitle() + "\n"; Calibration cal = imp.getCalibration(); int stackSize = imp.getStackSize(); int channels = imp.getNChannels(); int slices = imp.getNSlices(); int frames = imp.getNFrames(); int digits = imp.getBitDepth() == 32 ? 4 : 0; if (cal.scaled()) { String unit = cal.getUnit(); String units = cal.getUnits(); s += "Width: " + IJ.d2s(imp.getWidth() * cal.pixelWidth, 2) + " " + units + " (" + imp.getWidth() + ")\n"; s += "Height: " + IJ.d2s(imp.getHeight() * cal.pixelHeight, 2) + " " + units + " (" + imp.getHeight() + ")\n"; if (slices > 1) s += "Depth: " + IJ.d2s(slices * cal.pixelDepth, 2) + " " + units + " (" + slices + ")\n"; double xResolution = 1.0 / cal.pixelWidth; double yResolution = 1.0 / cal.pixelHeight; int places = Tools.getDecimalPlaces(xResolution, yResolution); if (xResolution == yResolution) s += "Resolution: " + IJ.d2s(xResolution, places) + " pixels per " + unit + "\n"; else { s += "X Resolution: " + IJ.d2s(xResolution, places) + " pixels per " + unit + "\n"; s += "Y Resolution: " + IJ.d2s(yResolution, places) + " pixels per " + unit + "\n"; } } else { s += "Width: " + imp.getWidth() + " pixels\n"; s += "Height: " + imp.getHeight() + " pixels\n"; if (stackSize > 1) s += "Depth: " + slices + " pixels\n"; } if (stackSize > 1) s += "Voxel size: " + d2s(cal.pixelWidth) + "x" + d2s(cal.pixelHeight) + "x" + d2s(cal.pixelDepth) + " " + cal.getUnit() + "\n"; else s += "Pixel size: " + d2s(cal.pixelWidth) + "x" + d2s(cal.pixelHeight) + " " + cal.getUnit() + "\n"; s += "ID: " + imp.getID() + "\n"; String zOrigin = stackSize > 1 || cal.zOrigin != 0.0 ? "," + d2s(cal.zOrigin) : ""; s += "Coordinate origin: " + d2s(cal.xOrigin) + "," + d2s(cal.yOrigin) + zOrigin + "\n"; int type = imp.getType(); switch (type) { case ImagePlus.GRAY8: s += "Bits per pixel: 8 "; String lut = "LUT"; if (imp.getProcessor().isColorLut()) lut = "color " + lut; else lut = "grayscale " + lut; if (imp.isInvertedLut()) lut = "inverting " + lut; s += "(" + lut + ")\n"; if (imp.getNChannels() > 1) s += displayRanges(imp); else s += "Display range: " + (int) ip.getMin() + "-" + (int) ip.getMax() + "\n"; break; case ImagePlus.GRAY16: case ImagePlus.GRAY32: if (type == ImagePlus.GRAY16) { String sign = cal.isSigned16Bit() ? "signed" : "unsigned"; s += "Bits per pixel: 16 (" + sign + ")\n"; } else s += "Bits per pixel: 32 (float)\n"; if (imp.getNChannels() > 1) s += displayRanges(imp); else { s += "Display range: "; double min = ip.getMin(); double max = ip.getMax(); if (cal.calibrated()) { min = cal.getCValue((int) min); max = cal.getCValue((int) max); } s += IJ.d2s(min, digits) + " - " + IJ.d2s(max, digits) + "\n"; } break; case ImagePlus.COLOR_256: s += "Bits per pixel: 8 (color LUT)\n"; break; case ImagePlus.COLOR_RGB: s += "Bits per pixel: 32 (RGB)\n"; break; } double interval = cal.frameInterval; double fps = cal.fps; if (stackSize > 1) { ImageStack stack = imp.getStack(); int slice = imp.getCurrentSlice(); String number = slice + "/" + stackSize; String label = stack.getShortSliceLabel(slice); if (label != null && label.length() > 0) label = " (" + label + ")"; else label = ""; if (interval > 0.0 || fps != 0.0) { s += "Frame: " + number + label + "\n"; if (fps != 0.0) { String sRate = Math.abs(fps - Math.round(fps)) < 0.00001 ? IJ.d2s(fps, 0) : IJ.d2s(fps, 5); s += "Frame rate: " + sRate + " fps\n"; } if (interval != 0.0) s += "Frame interval: " + ((int) interval == interval ? IJ.d2s(interval, 0) : IJ.d2s(interval, 5)) + " " + cal.getTimeUnit() + "\n"; } else s += "Image: " + number + label + "\n"; if (imp.isHyperStack()) { if (channels > 1) s += " Channel: " + imp.getChannel() + "/" + channels + "\n"; if (slices > 1) s += " Slice: " + imp.getSlice() + "/" + slices + "\n"; if (frames > 1) s += " Frame: " + imp.getFrame() + "/" + frames + "\n"; } if (imp.isComposite()) { if (!imp.isHyperStack() && channels > 1) s += " Channels: " + channels + "\n"; String mode = ((CompositeImage) imp).getModeAsString(); s += " Composite mode: \"" + mode + "\"\n"; } } if (ip.getMinThreshold() == ImageProcessor.NO_THRESHOLD) s += "No Threshold\n"; else { double lower = ip.getMinThreshold(); double upper = ip.getMaxThreshold(); int dp = digits; if (cal.calibrated()) { lower = cal.getCValue((int) lower); upper = cal.getCValue((int) upper); dp = cal.isSigned16Bit() ? 0 : 4; } s += "Threshold: " + IJ.d2s(lower, dp) + "-" + IJ.d2s(upper, dp) + "\n"; } ImageCanvas ic = imp.getCanvas(); double mag = ic != null ? ic.getMagnification() : 1.0; if (mag != 1.0) s += "Magnification: " + IJ.d2s(mag, 2) + "\n"; if (cal.calibrated()) { s += " \n"; int curveFit = cal.getFunction(); s += "Calibration Function: "; if (curveFit == Calibration.UNCALIBRATED_OD) s += "Uncalibrated OD\n"; else if (curveFit == Calibration.CUSTOM) s += "Custom lookup table\n"; else s += CurveFitter.fList[curveFit] + "\n"; double[] c = cal.getCoefficients(); if (c != null) { s += " a: " + IJ.d2s(c[0], 6) + "\n"; s += " b: " + IJ.d2s(c[1], 6) + "\n"; if (c.length >= 3) s += " c: " + IJ.d2s(c[2], 6) + "\n"; if (c.length >= 4) s += " c: " + IJ.d2s(c[3], 6) + "\n"; if (c.length >= 5) s += " c: " + IJ.d2s(c[4], 6) + "\n"; } s += " Unit: \"" + cal.getValueUnit() + "\"\n"; } else s += "Uncalibrated\n"; FileInfo fi = imp.getOriginalFileInfo(); if (fi != null) { if (fi.url != null && !fi.url.equals("")) s += "URL: " + fi.url + "\n"; else if (fi.directory != null && fi.fileName != null) s += "Path: " + fi.directory + fi.fileName + "\n"; } ImageWindow win = imp.getWindow(); if (win != null) { Point loc = win.getLocation(); Dimension screen = IJ.getScreenSize(); s += "Screen location: " + loc.x + "," + loc.y + " (" + screen.width + "x" + screen.height + ")\n"; } Overlay overlay = imp.getOverlay(); if (overlay != null) { String hidden = imp.getHideOverlay() ? " (hidden)" : " "; int n = overlay.size(); String elements = n == 1 ? " element" : " elements"; s += "Overlay: " + n + elements + (imp.getHideOverlay() ? " (hidden)" : "") + "\n"; } else s += "No Overlay\n"; Roi roi = imp.getRoi(); if (roi == null) { if (cal.calibrated()) s += " \n"; s += "No Selection\n"; } else if (roi instanceof EllipseRoi) { s += "\nElliptical Selection\n"; double[] p = ((EllipseRoi) roi).getParams(); double dx = p[2] - p[0]; double dy = p[3] - p[1]; double major = Math.sqrt(dx * dx + dy * dy); s += " Major: " + IJ.d2s(major, 2) + "\n"; s += " Minor: " + IJ.d2s(major * p[4], 2) + "\n"; s += " X1: " + IJ.d2s(p[0], 2) + "\n"; s += " Y1: " + IJ.d2s(p[1], 2) + "\n"; s += " X2: " + IJ.d2s(p[2], 2) + "\n"; s += " Y2: " + IJ.d2s(p[3], 2) + "\n"; s += " Aspect ratio: " + IJ.d2s(p[4], 2) + "\n"; } else { s += " \n"; s += roi.getTypeAsString() + " Selection"; String points = null; if (roi instanceof PointRoi) { int npoints = ((PolygonRoi) roi).getNCoordinates(); String suffix = npoints > 1 ? "s)" : ")"; points = " (" + npoints + " point" + suffix; } String name = roi.getName(); if (name != null) { s += " (\"" + name + "\")"; if (points != null) s += "\n " + points; } else if (points != null) s += points; s += "\n"; Rectangle r = roi.getBounds(); if (roi instanceof Line) { Line line = (Line) roi; s += " X1: " + IJ.d2s(line.x1d * cal.pixelWidth) + "\n"; s += " Y1: " + IJ.d2s(yy(line.y1d, imp) * cal.pixelHeight) + "\n"; s += " X2: " + IJ.d2s(line.x2d * cal.pixelWidth) + "\n"; s += " Y2: " + IJ.d2s(yy(line.y2d, imp) * cal.pixelHeight) + "\n"; } else if (cal.scaled()) { s += " X: " + IJ.d2s(cal.getX(r.x)) + " (" + r.x + ")\n"; s += " Y: " + IJ.d2s(cal.getY(r.y, imp.getHeight())) + " (" + r.y + ")\n"; s += " Width: " + IJ.d2s(r.width * cal.pixelWidth) + " (" + r.width + ")\n"; s += " Height: " + IJ.d2s(r.height * cal.pixelHeight) + " (" + r.height + ")\n"; } else { s += " X: " + r.x + "\n"; s += " Y: " + yy(r.y, imp) + "\n"; s += " Width: " + r.width + "\n"; s += " Height: " + r.height + "\n"; } } return s; }
private void geterrors() { GenericDialog gd = new GenericDialog("Options"); float conf = 0.67f; gd.addNumericField("Confidence Limit", (int) (conf * 100.0f), 5, 10, null); gd.addChoice("Error Parameter", paramsnames, paramsnames[0]); double spacing = 0.01; gd.addNumericField("Chi^2 plot spacing (% of value)?", spacing * 100.0, 2, 10, null); boolean globalerror = false; gd.addCheckbox("Global Fit Error?", globalerror); int dataset = 0; gd.addNumericField("Data Set (for Global Error)", dataset, 0); gd.showDialog(); if (gd.wasCanceled()) { return; } conf = 0.01f * (float) gd.getNextNumber(); int paramindex = (int) gd.getNextChoiceIndex(); spacing = 0.01 * gd.getNextNumber(); globalerror = gd.getNextBoolean(); dataset = (int) gd.getNextNumber(); if (globalerror) { support_plane_errors erclass = new support_plane_errors(this, 0.0001, 50, true, 0.1); int[] erindeces = {paramindex, dataset}; // need to set up all the matrices int nsel = 0; int nparams = 11; for (int i = 0; i < ncurves; i++) { if (include[i]) { nsel++; } } double[][] params = new double[nsel][nparams]; String[][] tempformulas = new String[nsel][nparams]; double[][][] constraints = new double[2][nsel][nparams]; int[][] vflmatrix = new int[nsel][nparams]; float[][] tempdata = new float[nsel][xpts * ypts]; float[][] tempweights = new float[nsel][xpts * ypts]; int nfit = 0; int counter = 0; for (int i = 0; i < ncurves; i++) { if (include[i]) { for (int j = 0; j < nparams; j++) { params[counter][j] = globalparams[i][j]; tempformulas[counter][j] = globalformulas[i][j]; constraints[0][counter][j] = globalconstraints[0][i][j]; constraints[1][counter][j] = globalconstraints[1][i][j]; vflmatrix[counter][j] = globalvflmatrix[i][j]; if (vflmatrix[counter][j] == 0 || (j == 0 && vflmatrix[counter][j] == 2)) { nfit++; } } for (int j = 0; j < xpts; j++) { for (int k = 0; k < ypts; k++) { tempdata[counter][j + k * xpts] = (float) ((double) pch[i][j][k] / (double) nmeas[i]); tempweights[counter][j + k * xpts] = weights[i][j][k]; } } counter++; } } int dofnum = xpts * ypts * nsel - (nfit - 1) - 1; int dofden = xpts * ypts * nsel - nfit - 1; // double flim=FLimit(dofnum,dofden,(double)conf); double flim = (new jdist()).FLimit(dofnum, dofden, (double) conf); IJ.log("FLimit = " + (float) flim); if (flim == Double.NaN && flim < 1.0) { IJ.showMessage("Invalid Limiting F Value"); return; } double truespacing = Math.abs(params[erindeces[1]][erindeces[0]] * spacing); double[][] c2plot = erclass.geterrorsglobal( params, vflmatrix, tempformulas, paramsnames, constraints, tempdata, tempweights, flim, truespacing, erindeces); IJ.log("upper limit = " + c2plot[1][0] + " lower limit = " + c2plot[0][0]); int templength = c2plot[0].length; float[][] c2plotf = new float[2][templength - 1]; for (int i = 0; i < (templength - 1); i++) { c2plotf[0][i] = (float) c2plot[0][i + 1]; c2plotf[1][i] = (float) c2plot[1][i + 1]; } new PlotWindow4( "c2 plot", paramsnames[paramindex] + "[" + dataset + "]", "Chi^2", c2plotf[0], c2plotf[1]) .draw(); } else { support_plane_errors erclass = new support_plane_errors(this, 0.0001, 50, false, 0.1); int errindex = paramindex; float[] tempdata = new float[xpts * ypts]; float[] tempweights = new float[xpts * ypts]; for (int i = 0; i < xpts; i++) { for (int j = 0; j < ypts; j++) { tempdata[i + j * xpts] = (float) ((double) avg[i][j] / (double) nmeas[ncurves]); tempweights[i + j * xpts] = avgweights[i][j]; } } int nfit = 0; for (int i = 0; i < 7; i++) { if (avgfixes[i] == 0) { nfit++; } } int dofnum = xpts * ypts - (nfit - 1) - 1; int dofden = xpts * ypts - nfit - 1; double flim = (new jdist()).FLimit(dofnum, dofden, (double) conf); IJ.log("FLimit = " + (float) flim); if (flim == Double.NaN && flim < 1.0) { IJ.showMessage("Invalid Limiting F Value"); return; } double truespacing = Math.abs(avgparams[errindex] * spacing); double[][] c2plot = erclass.geterrors( avgparams, avgfixes, avgconstraints, tempdata, tempweights, flim, truespacing, errindex); IJ.log("upper limit = " + c2plot[1][0] + " lower limit = " + c2plot[0][0]); int templength = c2plot[0].length; float[][] c2plotf = new float[2][templength - 1]; for (int i = 0; i < (templength - 1); i++) { c2plotf[0][i] = (float) c2plot[0][i + 1]; c2plotf[1][i] = (float) c2plot[1][i + 1]; } new PlotWindow4("c2 plot", paramsnames[errindex], "Chi^2", c2plotf[0], c2plotf[1]).draw(); } }
private boolean track( ImagePlus siPlus, ArrayList<Point2D.Double> xyPoints, ArrayList<Double> timePoints) { GaussianFit gs = new GaussianFit(shape_, fitMode_); double cPCF = photonConversionFactor_ / gain_; // for now, take the active ImageJ image // (this should be an image of a difraction limited spot) Roi originalRoi = siPlus.getRoi(); if (null == originalRoi) { if (!silent_) IJ.error("Please draw a Roi around the spot you want to track"); return false; } Polygon pol = FindLocalMaxima.FindMax(siPlus, halfSize_, noiseTolerance_, preFilterType_); if (pol.npoints == 0) { if (!silent_) ReportingUtils.showError("No local maxima found in ROI"); else ReportingUtils.logError("No local maxima found in ROI"); return false; } int xc = pol.xpoints[0]; int yc = pol.ypoints[0]; // not sure if needed, but look for the maximum local maximum int max = siPlus.getProcessor().getPixel(pol.xpoints[0], pol.ypoints[0]); if (pol.npoints > 1) { for (int i = 1; i < pol.npoints; i++) { if (siPlus.getProcessor().getPixel(pol.xpoints[i], pol.ypoints[i]) > max) { max = siPlus.getProcessor().getPixel(pol.xpoints[i], pol.ypoints[i]); xc = pol.xpoints[i]; yc = pol.ypoints[i]; } } } long startTime = System.nanoTime(); // This is confusing. We like to accomodate stacks with multiple slices // and stacks with multiple frames (which is actually the correct way int ch = siPlus.getChannel(); Boolean useSlices = siPlus.getNSlices() > siPlus.getNFrames(); int n = siPlus.getSlice(); int nMax = siPlus.getNSlices(); if (!useSlices) { n = siPlus.getFrame(); nMax = siPlus.getNFrames(); } boolean stop = false; int missedFrames = 0; int size = 2 * halfSize_; for (int i = n; i <= nMax && !stop; i++) { SpotData spot; // Give user feedback ij.IJ.showStatus("Tracking..."); ij.IJ.showProgress(i, nMax); // Search in next slice in same Roi for local maximum Roi searchRoi = new Roi(xc - size, yc - size, 2 * size + 1, 2 * size + 1); if (useSlices) { siPlus.setSliceWithoutUpdate(siPlus.getStackIndex(ch, i, 1)); } else { siPlus.setSliceWithoutUpdate(siPlus.getStackIndex(ch, 1, i)); } siPlus.setRoi(searchRoi, false); // Find maximum in Roi, might not be needed.... pol = FindLocalMaxima.FindMax(siPlus, 2 * halfSize_, noiseTolerance_, preFilterType_); // do not stray more than 2 pixels in x or y. // This velocity maximum parameter should be tunable by the user if (pol.npoints >= 1) { if (Math.abs(xc - pol.xpoints[0]) < 2 && Math.abs(yc - pol.ypoints[0]) < 2) { xc = pol.xpoints[0]; yc = pol.ypoints[0]; } } // Reset ROI to the original if (i == n) { firstX_ = xc; firstY_ = yc; } // Set Roi for fitting centered around maximum Roi spotRoi = new Roi(xc - halfSize_, yc - halfSize_, 2 * halfSize_, 2 * halfSize_); siPlus.setRoi(spotRoi, false); ImageProcessor ip; try { if (siPlus.getRoi() != spotRoi) { ReportingUtils.logError( "There seems to be a thread synchronization issue going on that causes this weirdness"); } ip = siPlus.getProcessor().crop(); } catch (ArrayIndexOutOfBoundsException aex) { ReportingUtils.logError(aex, "ImageJ failed to crop the image, not sure why"); siPlus.setRoi(spotRoi, true); ip = siPlus.getProcessor().crop(); } spot = new SpotData(ip, ch, 1, i, 1, i, xc, yc); double[] paramsOut = gs.dogaussianfit(ip, maxIterations_); double sx; double sy; double a = 1.0; double theta = 0.0; if (paramsOut.length >= 4) { // anormalize the intensity from the Gaussian fit double N = cPCF * paramsOut[GaussianFit.INT] * (2 * Math.PI * paramsOut[GaussianFit.S] * paramsOut[GaussianFit.S]); double xpc = paramsOut[GaussianFit.XC]; double ypc = paramsOut[GaussianFit.YC]; double x = (xpc - halfSize_ + xc) * pixelSize_; double y = (ypc - halfSize_ + yc) * pixelSize_; double s = paramsOut[GaussianFit.S] * pixelSize_; // express background in photons after base level correction double bgr = cPCF * (paramsOut[GaussianFit.BGR] - baseLevel_); // calculate error using formular from Thompson et al (2002) // (dx)2 = (s*s + (a*a/12)) / N + (8*pi*s*s*s*s * b*b) / (a*a*N*N) double sigma = (s * s + (pixelSize_ * pixelSize_) / 12) / N + (8 * Math.PI * s * s * s * s * bgr * bgr) / (pixelSize_ * pixelSize_ * N * N); sigma = Math.sqrt(sigma); double width = 2 * s; if (paramsOut.length >= 6) { sx = paramsOut[GaussianFit.S1] * pixelSize_; sy = paramsOut[GaussianFit.S2] * pixelSize_; a = sx / sy; } if (paramsOut.length >= 7) { theta = paramsOut[GaussianFit.S3]; } if ((!useWidthFilter_ || (width > widthMin_ && width < widthMax_)) && (!useNrPhotonsFilter_ || (N > nrPhotonsMin_ && N < nrPhotonsMax_))) { // If we have a good fit, update position of the box if (xpc > 0 && xpc < (2 * halfSize_) && ypc > 0 && ypc < (2 * halfSize_)) { xc += (int) xpc - halfSize_; yc += (int) ypc - halfSize_; } spot.setData(N, bgr, x, y, 0.0, 2 * s, a, theta, sigma); xyPoints.add(new Point2D.Double(x, y)); timePoints.add(i * timeIntervalMs_); resultList_.add(spot); missedFrames = 0; } else { missedFrames += 1; } } else { missedFrames += 1; } if (endTrackAfterBadFrames_) { if (missedFrames >= this.endTrackAfterNBadFrames_) { stop = true; } } } long endTime = System.nanoTime(); double took = (endTime - startTime) / 1E6; print("Calculation took: " + took + " milli seconds"); ij.IJ.showStatus(""); siPlus.setSlice(n); siPlus.setRoi(originalRoi); return true; }
public boolean get_errors(double[] params, int[] fixes) { GenericDialog gd = new GenericDialog("Error Options"); String[] methods = {"Support Plane", "Monte Carlo"}; gd.addChoice("Method", methods, methods[0]); float conf = 0.67f; gd.addNumericField("SP_Confidence Limit (%)", (int) (conf * 100.0f), 5, 10, null); String[] labels = {"P1", "P2", "P3", "P4", "P5", "P6", "P7", "P8", "P9", "P10"}; gd.addChoice("SP_Parameter", labels, labels[0]); double spacing = 0.01; gd.addNumericField("SP_Chi^2_plot_spacing (% of value)?", spacing * 100.0, 2, 10, null); int ntrials = 100; gd.addNumericField("MC_#_Trials", ntrials, 0); gd.showDialog(); if (gd.wasCanceled()) { return false; } int methodindex = gd.getNextChoiceIndex(); conf = 0.01f * (float) gd.getNextNumber(); int paramindex = gd.getNextChoiceIndex(); spacing = 0.01 * gd.getNextNumber(); ntrials = (int) gd.getNextNumber(); if (methodindex == 0) { support_plane_errors_v2 erclass = new support_plane_errors_v2(this, 0.0001, 50, false, 0.1); int errindex = paramindex; int nfit = 0; for (int i = 0; i < labels.length; i++) { if (fixes[i] == 0) { nfit++; } } int npts = tempdata.length; int dofnum = npts - (nfit - 1) - 1; int dofden = npts - nfit - 1; double flim = (new jdist()).FLimit(dofnum, dofden, (double) conf); IJ.log("FLimit = " + (float) flim); if (flim == Double.NaN && flim < 1.0) { IJ.showMessage("Invalid Limiting F Value"); return false; } double truespacing = Math.abs(params[errindex] * spacing); double[][] c2plot = erclass.geterrors( params, fixes, constraints, tempdata, weights, flim, truespacing, errindex); IJ.log("upper limit = " + c2plot[1][0] + " lower limit = " + c2plot[0][0]); IJ.log( "upper error = " + (c2plot[1][0] - params[errindex]) + " lower error = " + (params[errindex] - c2plot[0][0])); int templength = c2plot[0].length; float[][] c2plotf = new float[2][templength - 1]; for (int i = 0; i < (templength - 1); i++) { c2plotf[0][i] = (float) c2plot[0][i + 1]; c2plotf[1][i] = (float) c2plot[1][i + 1]; } new PlotWindow4("c2 plot", labels[errindex], "Chi^2", c2plotf[0], c2plotf[1]).draw(); } else { StringBuffer sb = new StringBuffer(); sb.append("Trial\t"); for (int i = 0; i < labels.length; i++) { if (fixes[i] == 0) sb.append(labels[i] + "\t"); } sb.append("chi^2"); tw = new TextWindow("Monte Carlo Results", sb.toString(), "", 400, 400); redirect = true; monte_carlo_errors_v2 erclass = new monte_carlo_errors_v2(this, 0.0001, 50, false, 0.1); double[][] errors = erclass.geterrors(params, fixes, constraints, tempdata, weights, ntrials); sb = new StringBuffer(); sb.append("StDev\t"); for (int i = 0; i < errors.length; i++) { float[] ferr = new float[errors[0].length]; for (int j = 0; j < ferr.length; j++) ferr[j] = (float) errors[i][j]; float stdev = jstatistics.getstatistic("StDev", ferr, null); sb.append("" + stdev); if (i < (errors.length - 1)) sb.append("\t"); } tw.append(sb.toString()); redirect = false; } return true; }
public void Calc_5Fr(ImagePlus imp1, ImagePlus imp2) { if (imp1.getType() != imp2.getType()) { error(); return; } if (imp1.getType() == 0) { // getType returns 0 for 8-bit, 1 for 16-bit bitDepth = "8-bit"; Prefs.set("ps.bitDepth", bitDepth); } else { bitDepth = "16-bit"; Prefs.set("ps.bitDepth", bitDepth); } int width = imp1.getWidth(); int height = imp1.getHeight(); if (width != imp2.getWidth() || height != imp2.getHeight()) { error(); return; } ImageStack stack1 = imp1.getStack(); // if (bgStackTitle != "NoBg") ImageStack stack2 = imp2.getStack(); ImageStack stack2 = imp2.getStack(); ImageProcessor ip = imp1.getProcessor(); int dimension = width * height; byte[] pixB; short[] pixS; float[][] pixF = new float[5][dimension]; float[][] pixFBg = new float[5][dimension]; float a; float b; float den; float aSmp; float bSmp; float denSmp; float aBg; float bBg; float denBg; float retF; float azimF; byte[] retB = new byte[dimension]; short[] retS = new short[dimension]; byte[] azimB = new byte[dimension]; short[] azimS = new short[dimension]; // Derived Variables: float swingAngle = 2f * (float) Math.PI * swing; float tanSwingAngleDiv2 = (float) Math.tan(swingAngle / 2.f); float tanSwingAngleDiv2DivSqrt2 = (float) (Math.tan(swingAngle / 2.f) / Math.sqrt(2)); float wavelengthDiv2Pi = wavelength / (2f * (float) Math.PI); // get the pixels of each slice in the stack and convert to float for (int i = 0; i < 5; i++) { if (bitDepth == "8-bit") { pixB = (byte[]) stack1.getPixels(i + 3); for (int j = 0; j < dimension; j++) pixF[i][j] = 0xff & pixB[j]; if (bgStackTitle != "NoBg") { pixB = (byte[]) stack2.getPixels(i + 3); for (int j = 0; j < dimension; j++) pixFBg[i][j] = 0xff & pixB[j]; } } else { pixS = (short[]) stack1.getPixels(i + 3); for (int j = 0; j < dimension; j++) pixF[i][j] = (float) pixS[j]; if (bgStackTitle != "NoBg") { pixS = (short[]) stack2.getPixels(i + 3); for (int j = 0; j < dimension; j++) pixFBg[i][j] = (float) pixS[j]; } } } // Algorithm // terms a and b for (int j = 0; j < dimension; j++) { denSmp = (pixF[1][j] + pixF[2][j] + pixF[3][j] + pixF[4][j] - 4 * pixF[0][j]) / 2; denBg = denSmp; a = (pixF[4][j] - pixF[1][j]); aSmp = a; aBg = a; b = (pixF[2][j] - pixF[3][j]); bSmp = b; bBg = b; if (bgStackTitle != "NoBg") { denBg = (pixFBg[1][j] + pixFBg[2][j] + pixFBg[3][j] + pixFBg[4][j] - 4 * pixFBg[0][j]) / 2; aBg = pixFBg[4][j] - pixFBg[1][j]; bBg = pixFBg[2][j] - pixFBg[3][j]; } // Special case of sample retardance half wave, denSmp = 0 if (denSmp == 0) { retF = (float) wavelength / 4; azimF = (float) (a == 0 & b == 0 ? 0 : (azimRef + 90 + 90 * Math.atan2(a, b) / Math.PI) % 180); } else { // Retardance, the background correction can be improved by separately considering sample // retardance values larger than a quarter wave if (bgStackTitle != "NoBg") { a = aSmp / denSmp - aBg / denBg; b = bSmp / denSmp - bBg / denBg; } else { a = aSmp / denSmp; b = bSmp / denSmp; } retF = (float) Math.atan(tanSwingAngleDiv2 * Math.sqrt(a * a + b * b)); if (denSmp < 0) retF = (float) Math.PI - retF; retF = retF * wavelengthDiv2Pi; // convert to nm if (retF > retCeiling) retF = retCeiling; // Orientation if ((bgStackTitle == "NoBg") || ((bgStackTitle != "NoBg") && (Math.abs(denSmp) < 1))) { a = aSmp; b = bSmp; } azimF = (float) (a == 0 & b == 0 ? 0 : (azimRef + 90 + 90 * Math.atan2(a, b) / Math.PI) % 180); } if (bitDepth == "8-bit") retB[j] = (byte) (((int) (255 * retF / retCeiling)) & 0xff); else retS[j] = (short) (4095 * retF / retCeiling); if (mirror == "Yes") azimF = 180 - azimF; if (bitDepth == "8-bit") azimB[j] = (byte) (((int) azimF) & 0xff); else azimS[j] = (short) (azimF * 10f); } // show the resulting images in slice 1 and 2 imp1.setSlice(3); if (bitDepth == "8-bit") { stack1.setPixels(retB, 1); stack1.setPixels(azimB, 2); } else { stack1.setPixels(retS, 1); stack1.setPixels(azimS, 2); } imp1.setSlice(1); IJ.selectWindow(imp1.getTitle()); Prefs.set("ps.sampleStackTitle", sampleStackTitle); Prefs.set("ps.bgStackTitle", bgStackTitle); Prefs.set("ps.mirror", mirror); Prefs.set("ps.wavelength", wavelength); Prefs.set("ps.swing", swing); Prefs.set("ps.retCeiling", retCeiling); Prefs.set("ps.azimRef", azimRef); Prefs.savePreferences(); }