void handleMouseMove(int sx, int sy) { // Do rubber banding int tool = Toolbar.getToolId(); if (!(tool == Toolbar.POLYGON || tool == Toolbar.POLYLINE || tool == Toolbar.ANGLE)) { imp.deleteRoi(); imp.draw(); return; } drawRubberBand(sx, sy); degrees = Double.NaN; double len = -1; if (nPoints > 1) { double x1, y1, x2, y2; if (xpf != null) { x1 = xpf[nPoints - 2]; y1 = ypf[nPoints - 2]; x2 = xpf[nPoints - 1]; y2 = ypf[nPoints - 1]; } else { x1 = xp[nPoints - 2]; y1 = yp[nPoints - 2]; x2 = xp[nPoints - 1]; y2 = yp[nPoints - 1]; } degrees = getAngle( (int) Math.round(x1), (int) Math.round(y1), (int) Math.round(x2), (int) Math.round(y2)); if (tool != Toolbar.ANGLE) { Calibration cal = imp.getCalibration(); double pw = cal.pixelWidth, ph = cal.pixelHeight; if (IJ.altKeyDown()) { pw = 1.0; ph = 1.0; } len = Math.sqrt((x2 - x1) * pw * (x2 - x1) * pw + (y2 - y1) * ph * (y2 - y1) * ph); } } if (tool == Toolbar.ANGLE) { if (nPoints == 2) angle1 = degrees; else if (nPoints == 3) { double angle2 = getAngle(xp[1], yp[1], xp[2], yp[2]); degrees = Math.abs(180 - Math.abs(angle1 - angle2)); if (degrees > 180.0) degrees = 360.0 - degrees; } } String length = len != -1 ? ", length=" + IJ.d2s(len) : ""; double degrees2 = tool == Toolbar.ANGLE && nPoints == 3 && Prefs.reflexAngle ? 360.0 - degrees : degrees; String angle = !Double.isNaN(degrees) ? ", angle=" + IJ.d2s(degrees2) : ""; int ox = ic != null ? ic.offScreenX(sx) : sx; int oy = ic != null ? ic.offScreenY(sy) : sy; IJ.showStatus(imp.getLocationAsString(ox, oy) + length + angle); }
private String displayRanges(ImagePlus imp) { LUT[] luts = imp.getLuts(); if (luts == null) return ""; String s = "Display ranges\n"; int n = luts.length; if (n > 7) n = 7; for (int i = 0; i < n; i++) { double min = luts[i].min; double max = luts[i].max; int digits = (int) min == min && (int) max == max ? 0 : 2; s += " " + (i + 1) + ": " + IJ.d2s(min, digits) + "-" + IJ.d2s(max, digits) + "\n"; } return s; }
/* Are we tracing a one pixel wide line? Makes Legacy mode 8-connected instead of 4-connected */ private boolean isLine(int xs, int ys) { int r = 5; int xmin = xs; int xmax = xs + 2 * r; if (xmax >= width) xmax = width - 1; int ymin = ys - r; if (ymin < 0) ymin = 0; int ymax = ys + r; if (ymax >= height) ymax = height - 1; int area = 0; int insideCount = 0; for (int x = xmin; (x <= xmax); x++) for (int y = ymin; y <= ymax; y++) { area++; if (inside(x, y)) insideCount++; } if (IJ.debugMode) IJ.log( (((double) insideCount) / area < 0.25 ? "line " : "blob ") + insideCount + " " + area + " " + IJ.d2s(((double) insideCount) / area)); return ((double) insideCount) / area < 0.25; }
byte[] getJar(String address) { // System.out.println("getJar: "+address); byte[] data; try { URL url = new URL(address); IJ.showStatus("Connecting to " + IJ.URL); URLConnection uc = url.openConnection(); int len = uc.getContentLength(); if (IJ.debugMode) IJ.log("Updater (url): " + address + " " + len); if (len <= 0) return null; String name = address.contains("wsr") ? "daily build (" : "ij.jar ("; IJ.showStatus("Downloading " + name + IJ.d2s((double) len / 1048576, 1) + "MB)"); InputStream in = uc.getInputStream(); data = new byte[len]; int n = 0; while (n < len) { int count = in.read(data, n, len - n); if (count < 0) throw new EOFException(); n += count; IJ.showProgress(n, len); } in.close(); } catch (IOException e) { if (IJ.debugMode) IJ.log("" + e); return null; } if (IJ.debugMode) IJ.wait(6000); return data; }
public synchronized void adjustmentValueChanged(AdjustmentEvent e) { Object source = e.getSource(); for (int i = 0; i < slider.size(); i++) { if (source == slider.elementAt(i)) { Scrollbar sb = (Scrollbar) source; TextField tf = (TextField) numberField.elementAt(sliderIndexes[i]); int digits = sliderScales[i] == 1.0 ? 0 : 2; tf.setText("" + IJ.d2s(sb.getValue() / sliderScales[i], digits)); } } }
// Conversion Options void conversions() { double[] weights = ColorProcessor.getWeightingFactors(); boolean weighted = !(weights[0] == 1d / 3d && weights[1] == 1d / 3d && weights[2] == 1d / 3d); // boolean weighted = !(Math.abs(weights[0]-1d/3d)<0.0001 && Math.abs(weights[1]-1d/3d)<0.0001 // && Math.abs(weights[2]-1d/3d)<0.0001); GenericDialog gd = new GenericDialog("Conversion Options"); gd.addCheckbox("Scale when converting", ImageConverter.getDoScaling()); String prompt = "Weighted RGB conversions"; if (weighted) prompt += " (" + IJ.d2s(weights[0]) + "," + IJ.d2s(weights[1]) + "," + IJ.d2s(weights[2]) + ")"; gd.addCheckbox(prompt, weighted); gd.showDialog(); if (gd.wasCanceled()) return; ImageConverter.setDoScaling(gd.getNextBoolean()); Prefs.weightedColor = gd.getNextBoolean(); if (!Prefs.weightedColor) ColorProcessor.setWeightingFactors(1d / 3d, 1d / 3d, 1d / 3d); else if (Prefs.weightedColor && !weighted) ColorProcessor.setWeightingFactors(0.299, 0.587, 0.114); return; }
/** * Adds a numeric field. The first word of the label must be unique or command recording will not * work. * * @param label the label * @param defaultValue value to be initially displayed * @param digits number of digits to right of decimal point * @param columns width of field in characters * @param units a string displayed to the right of the field */ public void addNumericField( String label, double defaultValue, int digits, int columns, String units) { String label2 = label; if (label2.indexOf('_') != -1) label2 = label2.replace('_', ' '); Label theLabel = makeLabel(label2); c.gridx = 0; c.gridy = y; c.anchor = GridBagConstraints.EAST; c.gridwidth = 1; if (firstNumericField) c.insets = getInsets(5, 0, 3, 0); else c.insets = getInsets(0, 0, 3, 0); grid.setConstraints(theLabel, c); add(theLabel); if (numberField == null) { numberField = new Vector(5); defaultValues = new Vector(5); defaultText = new Vector(5); } if (IJ.isWindows()) columns -= 2; if (columns < 1) columns = 1; String defaultString = IJ.d2s(defaultValue, digits); if (Double.isNaN(defaultValue)) defaultString = ""; TextField tf = new TextField(defaultString, columns); if (IJ.isLinux()) tf.setBackground(Color.white); tf.addActionListener(this); tf.addTextListener(this); tf.addFocusListener(this); tf.addKeyListener(this); numberField.addElement(tf); defaultValues.addElement(new Double(defaultValue)); defaultText.addElement(tf.getText()); c.gridx = 1; c.gridy = y; c.anchor = GridBagConstraints.WEST; tf.setEditable(true); // if (firstNumericField) tf.selectAll(); firstNumericField = false; if (units == null || units.equals("")) { grid.setConstraints(tf, c); add(tf); } else { Panel panel = new Panel(); panel.setLayout(new FlowLayout(FlowLayout.LEFT, 0, 0)); panel.add(tf); panel.add(new Label(" " + units)); grid.setConstraints(panel, c); add(panel); } if (Recorder.record || macro) saveLabel(tf, label); y++; }
String getAngleAsString() { double angle1 = 0.0; double angle2 = 0.0; if (xpf != null) { angle1 = getFloatAngle(xpf[0], ypf[0], xpf[1], ypf[1]); angle2 = getFloatAngle(xpf[1], ypf[1], xpf[2], ypf[2]); } else { angle1 = getFloatAngle(xp[0], yp[0], xp[1], yp[1]); angle2 = getFloatAngle(xp[1], yp[1], xp[2], yp[2]); } degrees = Math.abs(180 - Math.abs(angle1 - angle2)); if (degrees > 180.0) degrees = 360.0 - degrees; double degrees2 = Prefs.reflexAngle && type == ANGLE ? 360.0 - degrees : degrees; return ", angle=" + IJ.d2s(degrees2); }
byte[] getJar(String address) { byte[] data; boolean gte133 = version().compareTo("1.33u") >= 0; try { URL url = new URL(address); URLConnection uc = url.openConnection(); int len = uc.getContentLength(); String name = address.endsWith("ij/ij.jar") ? "daily build" : "ij.jar"; IJ.showStatus("Downloading ij.jar (" + IJ.d2s((double) len / 1048576, 1) + "MB)"); InputStream in = uc.getInputStream(); data = new byte[len]; int n = 0; while (n < len) { int count = in.read(data, n, len - n); if (count < 0) throw new EOFException(); n += count; if (gte133) IJ.showProgress(n, len); } in.close(); } catch (IOException e) { return null; } return data; }
String d2s(double n) { return n == (int) n ? Integer.toString((int) n) : IJ.d2s(n); }
public void run(String arg) { ImageCheck ic = new ImageCheck(); if (!ImageCheck.checkEnvironment()) return; ImagePlus imp = IJ.getImage(); if (!ic.isBinary(imp)) { IJ.error("8-bit binary (black and white only) image required."); return; } if (!ic.isVoxelIsotropic(imp, 1E-3)) { if (IJ.showMessageWithCancel( "Anisotropic voxels", "This image contains anisotropic voxels, which will\n" + "result in incorrect thickness calculation.\n\n" + "Consider rescaling your data so that voxels are isotropic\n" + "(Image > Scale...).\n\n" + "Continue anyway?")) { } else return; } GenericDialog gd = new GenericDialog("Options"); gd.addCheckbox("Thickness", true); gd.addCheckbox("Spacing", false); gd.addCheckbox("Graphic Result", true); gd.addCheckbox("Use_ROI_Manager", false); gd.addCheckbox("Mask thickness map", true); gd.addHelp("http://bonej.org/thickness"); gd.showDialog(); if (gd.wasCanceled()) { return; } boolean doThickness = gd.getNextBoolean(); boolean doSpacing = gd.getNextBoolean(); boolean doGraphic = gd.getNextBoolean(); boolean doRoi = gd.getNextBoolean(); boolean doMask = gd.getNextBoolean(); long startTime = System.currentTimeMillis(); String title = stripExtension(imp.getTitle()); RoiManager roiMan = RoiManager.getInstance(); // calculate trabecular thickness (Tb.Th) if (doThickness) { boolean inverse = false; ImagePlus impLTC = new ImagePlus(); if (doRoi && roiMan != null) { ImageStack stack = RoiMan.cropStack(roiMan, imp.getStack(), true, 0, 1); ImagePlus crop = new ImagePlus(imp.getTitle(), stack); crop.setCalibration(imp.getCalibration()); impLTC = getLocalThickness(crop, inverse, doMask); } else impLTC = getLocalThickness(imp, inverse, doMask); impLTC.setTitle(title + "_Tb.Th"); impLTC.setCalibration(imp.getCalibration()); double[] stats = StackStats.meanStdDev(impLTC); insertResults(imp, stats, inverse); if (doGraphic && !Interpreter.isBatchMode()) { impLTC.show(); impLTC.setSlice(1); impLTC.getProcessor().setMinAndMax(0, stats[2]); IJ.run("Fire"); } } if (doSpacing) { boolean inverse = true; ImagePlus impLTCi = new ImagePlus(); if (doRoi && roiMan != null) { ImageStack stack = RoiMan.cropStack(roiMan, imp.getStack(), true, 255, 1); ImagePlus crop = new ImagePlus(imp.getTitle(), stack); crop.setCalibration(imp.getCalibration()); impLTCi = getLocalThickness(crop, inverse, doMask); } else impLTCi = getLocalThickness(imp, inverse, doMask); // check marrow cavity size (i.e. trabcular separation, Tb.Sp) impLTCi.setTitle(title + "_Tb.Sp"); impLTCi.setCalibration(imp.getCalibration()); double[] stats = StackStats.meanStdDev(impLTCi); insertResults(imp, stats, inverse); if (doGraphic && !Interpreter.isBatchMode()) { impLTCi.show(); impLTCi.setSlice(1); impLTCi.getProcessor().setMinAndMax(0, stats[2]); IJ.run("Fire"); } } IJ.showProgress(1.0); IJ.showStatus("Done"); double duration = ((double) System.currentTimeMillis() - (double) startTime) / (double) 1000; IJ.log("Duration = " + IJ.d2s(duration, 3) + " s"); UsageReporter.reportEvent(this).send(); return; }
public boolean dialogItemChanged(GenericDialog gd, AWTEvent e) { if (IJ.isMacOSX()) IJ.wait(50); Calibration cal = imp.getCalibration(); width = gd.getNextNumber(); height = gd.getNextNumber(); xRoi = gd.getNextNumber(); yRoi = gd.getNextNumber(); if (stackSize > 1) iSlice = (int) gd.getNextNumber(); oval = gd.getNextBoolean(); square = gd.getNextBoolean(); centered = gd.getNextBoolean(); if (cal.scaled()) scaledUnits = gd.getNextBoolean(); if (gd.invalidNumber() || width <= 0 || height <= 0) return false; // Vector numFields = gd.getNumericFields(); Vector checkboxes = gd.getCheckboxes(); boolean newWidth = false, newHeight = false, newXY = false; if (e != null && e.getSource() == checkboxes.get(SQUARE) && square) { width = 0.5 * (width + height); // make square: same width&height height = width; newWidth = true; newHeight = true; } if (e != null && e.getSource() == checkboxes.get(CENTERED)) { double shiftBy = centered ? 0.5 : -0.5; // 'centered' changed: xRoi += shiftBy * width; // shift x, y to keep roi the same yRoi += shiftBy * height; newXY = true; } if (square && width != height && e != null) { // in 'square' mode, synchronize width&height if (e.getSource() == numFields.get(WIDTH)) { height = width; newHeight = true; } else if (e.getSource() == numFields.get(HEIGHT)) { width = height; newWidth = true; } } if (e != null && cal.scaled() && e.getSource() == checkboxes.get(SCALED_UNITS)) { double xFactor = scaledUnits ? cal.pixelWidth : 1. / cal.pixelWidth; double yFactor = scaledUnits ? cal.pixelHeight : 1. / cal.pixelHeight; width *= xFactor; // transform everything to keep roi the same height *= yFactor; xRoi *= xFactor; yRoi *= yFactor; newWidth = true; newHeight = true; newXY = true; } int digits = (scaledUnits || (int) width != width) ? 2 : 0; if (newWidth) ((TextField) (numFields.get(WIDTH))).setText(IJ.d2s(width, digits)); if (newHeight) ((TextField) (numFields.get(HEIGHT))).setText(IJ.d2s(height, digits)); digits = (scaledUnits || (int) xRoi != xRoi || (int) yRoi != yRoi) ? 2 : 0; if (newXY) { ((TextField) (numFields.get(X_ROI))).setText(IJ.d2s(xRoi, digits)); ((TextField) (numFields.get(Y_ROI))).setText(IJ.d2s(yRoi, digits)); } if (stackSize > 1 && iSlice > 0 && iSlice <= stackSize) imp.setSlice(iSlice); if (!newWidth && !newHeight && !newXY) // don't draw if an update will come immediately drawRoi(); return true; }
/** * Adds a slider (scroll bar) to the dialog box. Floating point values will be used if * (maxValue-minValue)<=5.0 and either minValue or maxValue are non-integer. * * @param label the label * @param minValue the minimum value of the slider * @param maxValue the maximum value of the slider * @param defaultValue the initial value of the slider */ public void addSlider(String label, double minValue, double maxValue, double defaultValue) { if (defaultValue < minValue) defaultValue = minValue; if (defaultValue > maxValue) defaultValue = maxValue; int columns = 4; int digits = 0; double scale = 1.0; if ((maxValue - minValue) <= 5.0 && (minValue != (int) minValue || maxValue != (int) maxValue || defaultValue != (int) defaultValue)) { scale = 20.0; minValue *= scale; maxValue *= scale; defaultValue *= scale; digits = 2; } String label2 = label; if (label2.indexOf('_') != -1) label2 = label2.replace('_', ' '); Label theLabel = makeLabel(label2); c.gridx = 0; c.gridy = y; c.anchor = GridBagConstraints.EAST; c.gridwidth = 1; c.insets = new Insets(0, 0, 3, 0); grid.setConstraints(theLabel, c); add(theLabel); if (slider == null) { slider = new Vector(5); sliderIndexes = new int[MAX_SLIDERS]; sliderScales = new double[MAX_SLIDERS]; } Scrollbar s = new Scrollbar( Scrollbar.HORIZONTAL, (int) defaultValue, 1, (int) minValue, (int) maxValue + 1); GUI.fix(s); slider.addElement(s); s.addAdjustmentListener(this); s.setUnitIncrement(1); if (numberField == null) { numberField = new Vector(5); defaultValues = new Vector(5); defaultText = new Vector(5); } if (IJ.isWindows()) columns -= 2; if (columns < 1) columns = 1; TextField tf = new TextField(IJ.d2s(defaultValue / scale, digits), columns); if (IJ.isLinux()) tf.setBackground(Color.white); tf.addActionListener(this); tf.addTextListener(this); tf.addFocusListener(this); tf.addKeyListener(this); numberField.addElement(tf); sliderIndexes[slider.size() - 1] = numberField.size() - 1; sliderScales[slider.size() - 1] = scale; defaultValues.addElement(new Double(defaultValue / scale)); defaultText.addElement(tf.getText()); tf.setEditable(true); firstSlider = false; Panel panel = new Panel(); GridBagLayout pgrid = new GridBagLayout(); GridBagConstraints pc = new GridBagConstraints(); panel.setLayout(pgrid); pc.gridx = 0; pc.gridy = 0; pc.gridwidth = 1; pc.ipadx = 85; pc.anchor = GridBagConstraints.WEST; pgrid.setConstraints(s, pc); panel.add(s); pc.ipadx = 0; // reset // text field pc.gridx = 1; pc.insets = new Insets(5, 5, 0, 0); pc.anchor = GridBagConstraints.EAST; pgrid.setConstraints(tf, pc); panel.add(tf); grid.setConstraints(panel, c); c.gridx = 1; c.gridy = y; c.gridwidth = 1; c.anchor = GridBagConstraints.WEST; c.insets = new Insets(0, 0, 0, 0); grid.setConstraints(panel, c); add(panel); y++; if (Recorder.record || macro) saveLabel(tf, label); }
private String d2s(double n) { return IJ.d2s(n, Tools.getDecimalPlaces(n)); }
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; }
/** Displays a modal options dialog. */ public boolean showDialog() { Calibration cal = imp != null ? imp.getCalibration() : (new Calibration()); double unitSquared = cal.pixelWidth * cal.pixelHeight; if (pixelUnits) unitSquared = 1.0; if (Macro.getOptions() != null) { boolean oldMacro = updateMacroOptions(); if (oldMacro) unitSquared = 1.0; staticMinSize = 0.0; staticMaxSize = DEFAULT_MAX_SIZE; staticMinCircularity = 0.0; staticMaxCircularity = 1.0; staticShowChoice = NOTHING; } GenericDialog gd = new GenericDialog("Analyze Particles"); minSize = staticMinSize; maxSize = staticMaxSize; minCircularity = staticMinCircularity; maxCircularity = staticMaxCircularity; showChoice = staticShowChoice; if (maxSize == 999999) maxSize = DEFAULT_MAX_SIZE; options = staticOptions; String unit = cal.getUnit(); boolean scaled = cal.scaled(); if (unit.equals("inch")) { unit = "pixel"; unitSquared = 1.0; scaled = false; pixelUnits = true; } String units = unit + "^2"; int places = 0; double cmin = minSize * unitSquared; if ((int) cmin != cmin) places = 2; double cmax = maxSize * unitSquared; if ((int) cmax != cmax && cmax != DEFAULT_MAX_SIZE) places = 2; String minStr = ResultsTable.d2s(cmin, places); if (minStr.indexOf("-") != -1) { for (int i = places; i <= 6; i++) { minStr = ResultsTable.d2s(cmin, i); if (minStr.indexOf("-") == -1) break; } } String maxStr = ResultsTable.d2s(cmax, places); if (maxStr.indexOf("-") != -1) { for (int i = places; i <= 6; i++) { maxStr = ResultsTable.d2s(cmax, i); if (maxStr.indexOf("-") == -1) break; } } if (scaled) gd.setInsets(5, 0, 0); gd.addStringField("Size (" + units + "):", minStr + "-" + maxStr, 12); if (scaled) { gd.setInsets(0, 40, 5); gd.addCheckbox("Pixel units", pixelUnits); } gd.addStringField("Circularity:", IJ.d2s(minCircularity) + "-" + IJ.d2s(maxCircularity), 12); gd.addChoice("Show:", showStrings, showStrings[showChoice]); String[] labels = new String[8]; boolean[] states = new boolean[8]; labels[0] = "Display results"; states[0] = (options & SHOW_RESULTS) != 0; labels[1] = "Exclude on edges"; states[1] = (options & EXCLUDE_EDGE_PARTICLES) != 0; labels[2] = "Clear results"; states[2] = (options & CLEAR_WORKSHEET) != 0; labels[3] = "Include holes"; states[3] = (options & INCLUDE_HOLES) != 0; labels[4] = "Summarize"; states[4] = (options & DISPLAY_SUMMARY) != 0; labels[5] = "Record starts"; states[5] = (options & RECORD_STARTS) != 0; labels[6] = "Add to Manager"; states[6] = (options & ADD_TO_MANAGER) != 0; labels[7] = "In_situ Show"; states[7] = (options & IN_SITU_SHOW) != 0; gd.addCheckboxGroup(4, 2, labels, states); gd.addHelp(IJ.URL + "/docs/menus/analyze.html#ap"); gd.showDialog(); if (gd.wasCanceled()) return false; String size = gd.getNextString(); // min-max size if (scaled) pixelUnits = gd.getNextBoolean(); if (pixelUnits) unitSquared = 1.0; else unitSquared = cal.pixelWidth * cal.pixelHeight; String[] minAndMax = Tools.split(size, " -"); double mins = gd.parseDouble(minAndMax[0]); double maxs = minAndMax.length == 2 ? gd.parseDouble(minAndMax[1]) : Double.NaN; minSize = Double.isNaN(mins) ? DEFAULT_MIN_SIZE : mins / unitSquared; maxSize = Double.isNaN(maxs) ? DEFAULT_MAX_SIZE : maxs / unitSquared; if (minSize < DEFAULT_MIN_SIZE) minSize = DEFAULT_MIN_SIZE; if (maxSize < minSize) maxSize = DEFAULT_MAX_SIZE; staticMinSize = minSize; staticMaxSize = maxSize; minAndMax = Tools.split(gd.getNextString(), " -"); // min-max circularity double minc = gd.parseDouble(minAndMax[0]); double maxc = minAndMax.length == 2 ? gd.parseDouble(minAndMax[1]) : Double.NaN; minCircularity = Double.isNaN(minc) ? 0.0 : minc; maxCircularity = Double.isNaN(maxc) ? 1.0 : maxc; if (minCircularity < 0.0 || minCircularity > 1.0) minCircularity = 0.0; if (maxCircularity < minCircularity || maxCircularity > 1.0) maxCircularity = 1.0; if (minCircularity == 1.0 && maxCircularity == 1.0) minCircularity = 0.0; staticMinCircularity = minCircularity; staticMaxCircularity = maxCircularity; if (gd.invalidNumber()) { IJ.error("Bins invalid."); canceled = true; return false; } showChoice = gd.getNextChoiceIndex(); staticShowChoice = showChoice; if (gd.getNextBoolean()) options |= SHOW_RESULTS; else options &= ~SHOW_RESULTS; if (gd.getNextBoolean()) options |= EXCLUDE_EDGE_PARTICLES; else options &= ~EXCLUDE_EDGE_PARTICLES; if (gd.getNextBoolean()) options |= CLEAR_WORKSHEET; else options &= ~CLEAR_WORKSHEET; if (gd.getNextBoolean()) options |= INCLUDE_HOLES; else options &= ~INCLUDE_HOLES; if (gd.getNextBoolean()) options |= DISPLAY_SUMMARY; else options &= ~DISPLAY_SUMMARY; if (gd.getNextBoolean()) options |= RECORD_STARTS; else options &= ~RECORD_STARTS; if (gd.getNextBoolean()) options |= ADD_TO_MANAGER; else options &= ~ADD_TO_MANAGER; if (gd.getNextBoolean()) options |= IN_SITU_SHOW; else options &= ~IN_SITU_SHOW; staticOptions = options; options |= SHOW_PROGRESS; if ((options & DISPLAY_SUMMARY) != 0) Analyzer.setMeasurements(Analyzer.getMeasurements() | AREA); return true; }
public void run(String arg) { int[] wList = WindowManager.getIDList(); if (wList==null) { IJ.error("No images are open."); return; } double kernel=3; double kernelsum = 0; double kernelvarsum =0; double kernalvar = 0; double sigmawidth = 2; int kernelindex, minpixnumber; String[] kernelsize = { "3�,"5�, "7�, "9�}; GenericDialog gd = new GenericDialog("Sigma Filter"); gd.addChoice("Kernel size", kernelsize, kernelsize[0]); gd.addNumericField("Sigma width",sigmawidth , 2); gd.addNumericField("Minimum number of pixels", 1, 0); gd.addCheckbox("Keep source:",true); gd.addCheckbox("Do all stack:",true); gd.addCheckbox("Modified Lee's FIlter:",true); gd.showDialog(); if (gd.wasCanceled()) return ; kernelindex = gd.getNextChoiceIndex(); sigmawidth = gd.getNextNumber(); minpixnumber = ((int)gd.getNextNumber()); boolean keep = gd.getNextBoolean(); boolean doallstack = gd.getNextBoolean(); boolean modified = gd.getNextBoolean(); if (kernelindex==0) kernel = 3; if (kernelindex==1) kernel = 5; if (kernelindex==2) kernel = 7; if (kernelindex==3) kernel = 9; long start = System.currentTimeMillis(); if (minpixnumber> (kernel*kernel)){ IJ.showMessage("Sigma filter", "There must be more pixels in the kernel than+\n" + "the minimum number to be included"); return; } double v, midintensity; int x, y, ix, iy; double sum = 0; double backupsum =0; int count = 0; int n = 0; if (keep) {IJ.run("Select All"); IJ.run("Duplicate...", "title='Sigma filtered' duplicate");} int radius = (int)(kernel-1)/2; ImagePlus imp = WindowManager.getCurrentImage(); ImageStack stack1 = imp.getStack(); int width = imp.getWidth(); int height = imp.getHeight(); int nslices = stack1.getSize(); int cslice = imp.getCurrentSlice(); double status = width*height*nslices; ImageProcessor ip = imp.getProcessor(); int sstart = 1; if (!doallstack) {sstart = cslice; nslices=sstart;status = status/nslices;}; for (int i=sstart; i<=nslices; i++) { imp.setSlice(i); for (x=radius;x<width+radius;x++) { for (y=radius;y<height+radius;y++) { midintensity = ip.getPixelValue(x,y); count = 0; sum = 0; kernelsum =0; kernalvar =0; kernelvarsum =0; backupsum = 0; //calculate mean of kernel value for (ix=0;ix<kernel;ix++) { for (iy=0;iy<kernel;iy++) { v = ip.getPixelValue(x+ix-radius,y+iy-radius); kernelsum = kernelsum+v; } } double sigmacalcmean = (kernelsum/(kernel*kernel)); //calculate variance of kernel for (ix=0;ix<kernel;ix++) { for (iy=0;iy<kernel;iy++) { v = ip.getPixelValue(x+ix-radius,y+iy-radius); kernalvar = (v-sigmacalcmean)*(v-sigmacalcmean); kernelvarsum = kernelvarsum + kernalvar; } } //double variance = kernelvarsum/kernel; double sigmacalcvar = kernelvarsum/((kernel*kernel)-1); //calcuate sigma range = sqrt(variance/(mean^2)) � sigmawidth double sigmarange = sigmawidth*(Math.sqrt((sigmacalcvar) /(sigmacalcmean*sigmacalcmean))); //calulate sigma top value and bottom value double sigmatop = midintensity*(1+sigmarange); double sigmabottom = midintensity*(1-sigmarange); //calculate mean of values that differ are in sigma range. for (ix=0;ix<kernel;ix++) { for (iy=0;iy<kernel;iy++) { v = ip.getPixelValue(x+ix-radius,y+iy-radius); if ((v>=sigmabottom)&&(v<=sigmatop)){ sum = sum+v; count = count+1; } backupsum = v+ backupsum; } } //if there are too few pixels in the kernal that are within sigma range, the //mean of the entire kernal is taken. My modification of Lee's filter is to exclude the central value //from the calculation of the mean as I assume it to be spuriously high or low if (!(count>(minpixnumber))) {sum = (backupsum-midintensity); count = (int)((kernel*kernel)-1); if (!modified) {sum = (backupsum); count = (int)(kernel*kernel);} } double val = (sum/count); ip.putPixelValue(x,y, val); n = n+1; double percentage = (((double)n/status)*100); IJ.showStatus(IJ.d2s(percentage,0) +"% done"); } // IJ.showProgress(i, status); }} imp.updateAndDraw(); IJ.showStatus(IJ.d2s((System.currentTimeMillis()-start)/1000.0, 2)+" seconds"); }
/* 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)); }
public void run(String arg) { imp = IJ.getImage(); int stackSize = imp.getStackSize(); if (imp == null) { IJ.noImage(); return; } // Make sure input image is a stack. if (stackSize == 1) { IJ.error("Z Project", "Stack required"); return; } // Check for inverting LUT. if (imp.getProcessor().isInvertedLut()) { if (!IJ.showMessageWithCancel("ZProjection", lutMessage)) return; } // Set default bounds. int channels = imp.getNChannels(); int frames = imp.getNFrames(); int slices = imp.getNSlices(); isHyperstack = imp.isHyperStack() || (ij.macro.Interpreter.isBatchMode() && ((frames > 1 && frames < stackSize) || (slices > 1 && slices < stackSize))); boolean simpleComposite = channels == stackSize; if (simpleComposite) isHyperstack = false; startSlice = 1; if (isHyperstack) { int nSlices = imp.getNSlices(); if (nSlices > 1) stopSlice = nSlices; else stopSlice = imp.getNFrames(); } else stopSlice = stackSize; // Build control dialog GenericDialog gd = buildControlDialog(startSlice, stopSlice); gd.showDialog(); if (gd.wasCanceled()) return; if (!imp.lock()) return; // exit if in use long tstart = System.currentTimeMillis(); setStartSlice((int) gd.getNextNumber()); setStopSlice((int) gd.getNextNumber()); method = gd.getNextChoiceIndex(); Prefs.set(METHOD_KEY, method); if (isHyperstack) { allTimeFrames = imp.getNFrames() > 1 && imp.getNSlices() > 1 ? gd.getNextBoolean() : false; doHyperStackProjection(allTimeFrames); } else if (imp.getType() == ImagePlus.COLOR_RGB) doRGBProjection(true); else doProjection(true); if (arg.equals("") && projImage != null) { long tstop = System.currentTimeMillis(); projImage.setCalibration(imp.getCalibration()); if (simpleComposite) IJ.run(projImage, "Grays", ""); projImage.show("ZProjector: " + IJ.d2s((tstop - tstart) / 1000.0, 2) + " seconds"); } imp.unlock(); IJ.register(ZProjector.class); return; }