void showResults() {
   int count = rt.getCounter();
   // if (count==0) return;
   boolean lastSlice = !processStack || slice == imp.getStackSize();
   if ((showChoice == OVERLAY_OUTLINES || showChoice == OVERLAY_MASKS) && slice == 1 && count > 0)
     imp.setOverlay(overlay);
   else if (outlines != null && lastSlice) {
     String title = imp != null ? imp.getTitle() : "Outlines";
     String prefix;
     if (showChoice == MASKS) prefix = "Mask of ";
     else if (showChoice == ROI_MASKS) prefix = "Count Masks of ";
     else prefix = "Drawing of ";
     outlines.update(drawIP);
     outputImage = new ImagePlus(prefix + title, outlines);
     if (inSituShow) {
       if (imp.getStackSize() == 1) Undo.setup(Undo.TRANSFORM, imp);
       imp.setStack(null, outputImage.getStack());
     } else if (!hideOutputImage) outputImage.show();
   }
   if (showResults && !processStack) {
     TextPanel tp = IJ.getTextPanel();
     if (beginningCount > 0 && tp != null && tp.getLineCount() != count) rt.show("Results");
     Analyzer.firstParticle = beginningCount;
     Analyzer.lastParticle = Analyzer.getCounter() - 1;
   } else Analyzer.firstParticle = Analyzer.lastParticle = 0;
 }
 void updateSliceSummary() {
   int slices = imp.getStackSize();
   float[] areas = rt.getColumn(ResultsTable.AREA);
   if (areas == null) areas = new float[0];
   String label = imp.getTitle();
   if (slices > 1) {
     label = imp.getStack().getShortSliceLabel(slice);
     label = label != null && !label.equals("") ? label : "" + slice;
   }
   String aLine = null;
   double sum = 0.0;
   int start = areas.length - particleCount;
   if (start < 0) return;
   for (int i = start; i < areas.length; i++) sum += areas[i];
   int places = Analyzer.getPrecision();
   Calibration cal = imp.getCalibration();
   String total = "\t" + ResultsTable.d2s(sum, places);
   String average = "\t" + ResultsTable.d2s(sum / particleCount, places);
   String fraction = "\t" + ResultsTable.d2s(sum * 100.0 / totalArea, 1);
   aLine = label + "\t" + particleCount + total + average + fraction;
   aLine = addMeans(aLine, areas.length > 0 ? start : -1);
   if (slices == 1) {
     Frame frame = WindowManager.getFrame("Summary");
     if (frame != null && (frame instanceof TextWindow) && summaryHdr.equals(prevHdr))
       tw = (TextWindow) frame;
   }
   if (tw == null) {
     String title = slices == 1 ? "Summary" : "Summary of " + imp.getTitle();
     tw = new TextWindow(title, summaryHdr, aLine, 450, 300);
     prevHdr = summaryHdr;
   } else tw.append(aLine);
 }
 /**
  * Saves statistics for one particle in a results table. This is a method subclasses may want to
  * override.
  */
 protected void saveResults(ImageStatistics stats, Roi roi) {
   analyzer.saveResults(stats, roi);
   if (recordStarts) {
     rt.addValue("XStart", stats.xstart);
     rt.addValue("YStart", stats.ystart);
   }
   if (addToManager) {
     if (roiManager == null) {
       if (Macro.getOptions() != null && Interpreter.isBatchMode())
         roiManager = Interpreter.getBatchModeRoiManager();
       if (roiManager == null) {
         Frame frame = WindowManager.getFrame("ROI Manager");
         if (frame == null) IJ.run("ROI Manager...");
         frame = WindowManager.getFrame("ROI Manager");
         if (frame == null || !(frame instanceof RoiManager)) {
           addToManager = false;
           return;
         }
         roiManager = (RoiManager) frame;
       }
       if (resetCounter) roiManager.runCommand("reset");
     }
     if (imp.getStackSize() > 1) roi.setPosition(imp.getCurrentSlice());
     if (lineWidth != 1) roi.setStrokeWidth(lineWidth);
     roiManager.add(imp, roi, rt.getCounter());
   }
   if (showResults) rt.addResults();
 }
Esempio n. 4
0
  public static void main(String[] args) {
    String mriImage = args[0];
    String outImage = args[1];
    String segArgs = args[2];
    String outTable = args[3];
    String pdxArgs = args[4];

    System.out.println("Open: " + mriImage);
    IJ.open(mriImage);
    COPD_LungSegment tjPlug = new COPD_LungSegment();
    ImagePlus cImage = IJ.getImage();
    tjPlug.setup(segArgs, cImage);
    tjPlug.run(cImage.getProcessor());
    IJ.save(cImage, outImage);
    COPD_PDxLAAx pdxPlug = new COPD_PDxLAAx();
    pdxPlug.setup("", cImage);
    pdxPlug.run(cImage.getProcessor());
    ResultsTable rt = Analyzer.getResultsTable();
    try {
      rt.saveAs(outTable);
    } catch (IOException e) {
      e.printStackTrace();
    }

    System.out.println("Results Table\n");
    String prefix = "rtout, ";

    for (int i = 0; i < ResultsTable.MAX_COLUMNS; i++) {
      if (!rt.columnExists(i)) break;
      String tempOut = rt.getColumnHeading(i);
      for (double d : rt.getColumnAsDoubles(i)) {
        tempOut += ", " + d;
      }
      System.out.println(prefix + tempOut);
    }
  }
Esempio n. 5
0
  /* Method takes roi and substract its mean value from each frame in the image*/
  public static ImagePlus DarkNoiseRemoval(ImagePlus imp_in, Roi noise_roi) {
    ImagePlus imp_out = imp_in.duplicate();
    int size = imp_in.getImageStackSize();
    ImageProcessor ip = imp_out.getProcessor();
    double minThreshold = ip.getMinThreshold();
    double maxThreshold = ip.getMaxThreshold();
    Calibration cal = imp_in.getCalibration();
    int measurements = Analyzer.getMeasurements();
    int current = imp_in.getCurrentSlice();
    ImageStack stack = imp_in.getStack();
    for (int i = 1; i <= size; i++) {
      ip = stack.getProcessor(i);
      if (minThreshold != ImageProcessor.NO_THRESHOLD)
        ip.setThreshold(minThreshold, maxThreshold, ImageProcessor.NO_LUT_UPDATE);
      ip.setRoi(noise_roi);
      ImageStatistics stats = ImageStatistics.getStatistics(ip, measurements, cal);
      ip.resetRoi();
      ip.subtract(stats.mean);
      stack.setProcessor(ip, i);
    }

    imp_out.setStack(stack);
    return imp_out;
  }
  public void run(ImageProcessor ip) {
    String[] imageNames = getOpenImageNames();
    if (imageNames[0] == "None") {
      IJ.error("need at least 2 binary open images");
      return;
    }
    double previousMinOverlap = Prefs.get("BVTB.BinaryFeatureExtractor.minOverlap", 0);
    boolean previousCombine = Prefs.get("BVTB.BinaryFeatureExtractor.combine", false);

    GenericDialog gd = new GenericDialog("Binary Feature Extractor");
    gd.addChoice("Objects image", imageNames, imageNames[0]);
    gd.addChoice("Selector image", imageNames, imageNames[1]);
    gd.addNumericField("Object_overlap in % (0=off)", previousMinOverlap, 0, 9, "");
    gd.addCheckbox("Combine objects and selectors", previousCombine);
    gd.addCheckbox("Count output", true);
    gd.addCheckbox("Analysis tables", false);
    gd.showDialog();
    if (gd.wasCanceled()) {
      return;
    }
    String objectsImgTitle = gd.getNextChoice();
    String selectorsImgTitle = gd.getNextChoice();
    double minOverlap = gd.getNextNumber();
    boolean combineImages = gd.getNextBoolean();
    boolean showCountOutput = gd.getNextBoolean();
    boolean showAnalysis = gd.getNextBoolean();
    if (gd.invalidNumber() || minOverlap < 0 || minOverlap > 100) {
      IJ.error("invalid number");
      return;
    }
    Prefs.set("BVTB.BinaryFeatureExtractor.minOverlap", minOverlap);
    Prefs.set("BVTB.BinaryFeatureExtractor.combine", combineImages);

    if (objectsImgTitle.equals(selectorsImgTitle)) {
      IJ.error("images need to be different");
      return;
    }

    ImagePlus objectsImp = WindowManager.getImage(objectsImgTitle);
    ImageProcessor objectsIP = objectsImp.getProcessor();
    ImagePlus selectorsImp = WindowManager.getImage(selectorsImgTitle);
    ImageProcessor selectorsIP = selectorsImp.getProcessor();

    if (!objectsIP.isBinary() || !selectorsIP.isBinary()) {
      IJ.error("works with 8-bit binary images only");
      return;
    }

    if ((objectsImp.getWidth() != selectorsImp.getWidth())
        || objectsImp.getHeight() != selectorsImp.getHeight()) {
      IJ.error("images need to be of the same size");
      return;
    }

    // close any existing RoiManager before instantiating a new one for this analysis
    RoiManager oldRM = RoiManager.getInstance2();
    if (oldRM != null) {
      oldRM.close();
    }

    RoiManager objectsRM = new RoiManager(true);
    ResultsTable objectsRT = new ResultsTable();
    ParticleAnalyzer analyzeObjects =
        new ParticleAnalyzer(analyzerOptions, measurementFlags, objectsRT, 0.0, 999999999.9);
    analyzeObjects.setRoiManager(objectsRM);

    analyzeObjects.analyze(objectsImp);
    objectsRM.runCommand("Show None");
    int objectNumber = objectsRT.getCounter();

    Roi[] objectRoi = objectsRM.getRoisAsArray();

    ResultsTable measureSelectorsRT = new ResultsTable();
    Analyzer overlapAnalyzer = new Analyzer(selectorsImp, measurementFlags, measureSelectorsRT);

    ImagePlus outputImp =
        IJ.createImage("output", "8-bit black", objectsImp.getWidth(), objectsImp.getHeight(), 1);
    ImageProcessor outputIP = outputImp.getProcessor();

    double[] measuredOverlap = new double[objectNumber];

    outputIP.setValue(255.0);
    for (int o = 0; o < objectNumber; o++) {
      selectorsImp.killRoi();
      selectorsImp.setRoi(objectRoi[o]);
      overlapAnalyzer.measure();
      measuredOverlap[o] = measureSelectorsRT.getValue("%Area", o);
      if (minOverlap != 0.0 && measuredOverlap[o] >= minOverlap) {
        outputIP.fill(objectRoi[o]);
        finalCount++;
      } else if (minOverlap == 0.0 && measuredOverlap[o] > 0.0) {
        outputIP.fill(objectRoi[o]);
        finalCount++;
      }
    }
    // measureSelectorsRT.show("Objects");

    selectorsImp.killRoi();
    RoiManager selectorRM = new RoiManager(true);
    ResultsTable selectorRT = new ResultsTable();
    ParticleAnalyzer.setRoiManager(selectorRM);
    ParticleAnalyzer analyzeSelectors =
        new ParticleAnalyzer(analyzerOptions, measurementFlags, selectorRT, 0.0, 999999999.9);
    analyzeSelectors.analyze(selectorsImp);
    selectorRM.runCommand("Show None");
    int selectorNumber = selectorRT.getCounter();

    if (combineImages) {
      outputImp.updateAndDraw();
      Roi[] selectorRoi = selectorRM.getRoisAsArray();

      ResultsTable measureObjectsRT = new ResultsTable();
      Analyzer selectorAnalyzer = new Analyzer(outputImp, measurementFlags, measureObjectsRT);

      double[] selectorOverlap = new double[selectorNumber];
      outputIP.setValue(255.0);
      for (int s = 0; s < selectorNumber; s++) {
        outputImp.killRoi();
        outputImp.setRoi(selectorRoi[s]);
        selectorAnalyzer.measure();
        selectorOverlap[s] = measureObjectsRT.getValue("%Area", s);
        if (selectorOverlap[s] > 0.0d) {
          outputIP.fill(selectorRoi[s]);
        }
      }
      selectorRoi = null;
      selectorAnalyzer = null;
      measureObjectsRT = null;
    }
    // selectorRT.show("Selectors");
    outputImp.killRoi();
    String outputImageTitle = WindowManager.getUniqueName("Extracted_" + objectsImgTitle);
    outputImp.setTitle(outputImageTitle);
    outputImp.show();
    outputImp.changes = true;

    if (showCountOutput) {
      String[] openTextWindows = WindowManager.getNonImageTitles();
      boolean makeNewTable = true;
      for (int w = 0; w < openTextWindows.length; w++) {
        if (openTextWindows[w].equals("BFE_Results")) {
          makeNewTable = false;
        }
      }

      TextWindow existingCountTable = ResultsTable.getResultsWindow();
      if (makeNewTable) {
        countTable = new ResultsTable();
        countTable.setPrecision(0);
        countTable.setValue("Image", 0, outputImageTitle);
        countTable.setValue("Objects", 0, objectNumber);
        countTable.setValue("Selectors", 0, selectorNumber);
        countTable.setValue("Extracted", 0, finalCount);
        countTable.show("BFE_Results");
      } else {
        IJ.renameResults("BFE_Results", "Results");
        countTable = ResultsTable.getResultsTable();
        countTable.setPrecision(0);
        countTable.incrementCounter();
        countTable.addValue("Image", outputImageTitle);
        countTable.addValue("Objects", objectNumber);
        countTable.addValue("Selectors", selectorNumber);
        countTable.addValue("Extracted", finalCount);
        IJ.renameResults("Results", "BFE_Results");
        countTable.show("BFE_Results");
      }
    }

    if (showAnalysis) {
      ResultsTable extractedRT = new ResultsTable();
      ParticleAnalyzer analyzeExtracted =
          new ParticleAnalyzer(
              ParticleAnalyzer.CLEAR_WORKSHEET | ParticleAnalyzer.RECORD_STARTS,
              measurementFlags,
              extractedRT,
              0.0,
              999999999.9);
      analyzeExtracted.analyze(outputImp);
      objectsRT.show("Objects");
      selectorRT.show("Selectors");
      extractedRT.show("Extracted");
    } else {
      objectsRT = null;
      selectorRT = null;
    }

    objectsRM = null;
    measureSelectorsRT = null;
    analyzeObjects = null;
    overlapAnalyzer = null;
    objectRoi = null;
    selectorRM = null;

    objectsImp.killRoi();
    objectsImp.changes = false;
    selectorsImp.changes = false;
  }
 String n(double n) {
   String s;
   if (Math.round(n) == n) s = ResultsTable.d2s(n, 0);
   else s = ResultsTable.d2s(n, Analyzer.getPrecision());
   return "\t" + s;
 }
  /**
   * Performs particle analysis on the specified ImagePlus and ImageProcessor. Returns false if
   * there is an error.
   */
  public boolean analyze(ImagePlus imp, ImageProcessor ip) {
    if (this.imp == null) this.imp = imp;
    showResults = (options & SHOW_RESULTS) != 0;
    excludeEdgeParticles = (options & EXCLUDE_EDGE_PARTICLES) != 0;
    resetCounter = (options & CLEAR_WORKSHEET) != 0;
    showProgress = (options & SHOW_PROGRESS) != 0;
    floodFill = (options & INCLUDE_HOLES) == 0;
    recordStarts = (options & RECORD_STARTS) != 0;
    addToManager = (options & ADD_TO_MANAGER) != 0;
    displaySummary = (options & DISPLAY_SUMMARY) != 0;
    inSituShow = (options & IN_SITU_SHOW) != 0;
    outputImage = null;
    ip.snapshot();
    ip.setProgressBar(null);
    if (Analyzer.isRedirectImage()) {
      redirectImp = Analyzer.getRedirectImage(imp);
      if (redirectImp == null) return false;
      int depth = redirectImp.getStackSize();
      if (depth > 1 && depth == imp.getStackSize()) {
        ImageStack redirectStack = redirectImp.getStack();
        redirectIP = redirectStack.getProcessor(imp.getCurrentSlice());
      } else redirectIP = redirectImp.getProcessor();
    } else if (imp.getType() == ImagePlus.COLOR_RGB) {
      ImagePlus original = (ImagePlus) imp.getProperty("OriginalImage");
      if (original != null
          && original.getWidth() == imp.getWidth()
          && original.getHeight() == imp.getHeight()) {
        redirectImp = original;
        redirectIP = original.getProcessor();
      }
    }
    if (!setThresholdLevels(imp, ip)) return false;
    width = ip.getWidth();
    height = ip.getHeight();
    if (!(showChoice == NOTHING || showChoice == OVERLAY_OUTLINES || showChoice == OVERLAY_MASKS)) {
      blackBackground = Prefs.blackBackground && inSituShow;
      if (slice == 1) outlines = new ImageStack(width, height);
      if (showChoice == ROI_MASKS) drawIP = new ShortProcessor(width, height);
      else drawIP = new ByteProcessor(width, height);
      drawIP.setLineWidth(lineWidth);
      if (showChoice == ROI_MASKS) {
      } // Place holder for now...
      else if (showChoice == MASKS && !blackBackground) drawIP.invertLut();
      else if (showChoice == OUTLINES) {
        if (!inSituShow) {
          if (customLut == null) makeCustomLut();
          drawIP.setColorModel(customLut);
        }
        drawIP.setFont(new Font("SansSerif", Font.PLAIN, fontSize));
        if (fontSize > 12 && inSituShow) drawIP.setAntialiasedText(true);
      }
      outlines.addSlice(null, drawIP);

      if (showChoice == ROI_MASKS || blackBackground) {
        drawIP.setColor(Color.black);
        drawIP.fill();
        drawIP.setColor(Color.white);
      } else {
        drawIP.setColor(Color.white);
        drawIP.fill();
        drawIP.setColor(Color.black);
      }
    }
    calibration = redirectImp != null ? redirectImp.getCalibration() : imp.getCalibration();

    if (rt == null) {
      rt = Analyzer.getResultsTable();
      analyzer = new Analyzer(imp);
    } else analyzer = new Analyzer(imp, measurements, rt);
    if (resetCounter && slice == 1) {
      if (!Analyzer.resetCounter()) return false;
    }
    beginningCount = Analyzer.getCounter();

    byte[] pixels = null;
    if (ip instanceof ByteProcessor) pixels = (byte[]) ip.getPixels();
    if (r == null) {
      r = ip.getRoi();
      mask = ip.getMask();
      if (displaySummary) {
        if (mask != null) totalArea = ImageStatistics.getStatistics(ip, AREA, calibration).area;
        else totalArea = r.width * calibration.pixelWidth * r.height * calibration.pixelHeight;
      }
    }
    minX = r.x;
    maxX = r.x + r.width;
    minY = r.y;
    maxY = r.y + r.height;
    if (r.width < width || r.height < height || mask != null) {
      if (!eraseOutsideRoi(ip, r, mask)) return false;
    }
    int offset;
    double value;
    int inc = Math.max(r.height / 25, 1);
    int mi = 0;
    ImageWindow win = imp.getWindow();
    if (win != null) win.running = true;
    if (measurements == 0) measurements = Analyzer.getMeasurements();
    if (showChoice == ELLIPSES) measurements |= ELLIPSE;
    measurements &= ~LIMIT; // ignore "Limit to Threshold"
    roiNeedsImage =
        (measurements & PERIMETER) != 0
            || (measurements & SHAPE_DESCRIPTORS) != 0
            || (measurements & FERET) != 0;
    particleCount = 0;
    wand = new Wand(ip);
    pf = new PolygonFiller();
    if (floodFill) {
      ImageProcessor ipf = ip.duplicate();
      ipf.setValue(fillColor);
      ff = new FloodFiller(ipf);
    }
    roiType = Wand.allPoints() ? Roi.FREEROI : Roi.TRACED_ROI;

    for (int y = r.y; y < (r.y + r.height); y++) {
      offset = y * width;
      for (int x = r.x; x < (r.x + r.width); x++) {
        if (pixels != null) value = pixels[offset + x] & 255;
        else if (imageType == SHORT) value = ip.getPixel(x, y);
        else value = ip.getPixelValue(x, y);
        if (value >= level1 && value <= level2) analyzeParticle(x, y, imp, ip);
      }
      if (showProgress && ((y % inc) == 0)) IJ.showProgress((double) (y - r.y) / r.height);
      if (win != null) canceled = !win.running;
      if (canceled) {
        Macro.abort();
        break;
      }
    }
    if (showProgress) IJ.showProgress(1.0);
    if (showResults) rt.updateResults();
    imp.killRoi();
    ip.resetRoi();
    ip.reset();
    if (displaySummary && IJ.getInstance() != null) updateSliceSummary();
    if (addToManager && roiManager != null) roiManager.setEditMode(imp, true);
    maxParticleCount = (particleCount > maxParticleCount) ? particleCount : maxParticleCount;
    totalCount += particleCount;
    if (!canceled) showResults();
    return true;
  }
  /** 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;
  }