예제 #1
0
  private void drawGraph(
      final double[] params, final double[] boxSizes, final double[] boxCountSums) {

    final int samples = 100;
    final float[] px = new float[samples];
    final float[] py = new float[samples];
    double[] a = Tools.getMinMax(boxSizes);
    final double xmin = a[0], xmax = a[1];

    a = Tools.getMinMax(boxCountSums);
    double ymin = a[0], ymax = a[1];
    final double inc = (xmax - xmin) / ((double) samples - 1);
    double tmp = xmin;

    for (int i = 0; i < samples; i++) {
      px[i] = (float) tmp;
      tmp += inc;
    }
    for (int i = 0; i < samples; i++) {
      py[i] = (float) CurveFitter.f(CurveFitter.STRAIGHT_LINE, params, px[i]);
    }
    a = Tools.getMinMax(py);
    ymin = Math.min(ymin, a[0]);
    ymax = Math.max(ymax, a[1]);
    final Plot plot = new Plot("Plot", "-log(box size)", "log(box count)", px, py);
    plot.setLimits(xmin, xmax * 0.9, ymin, ymax * 1.1);
    plot.draw();
    plot.addPoints(boxSizes, boxCountSums, Plot.CIRCLE);
    plot.addPoints(px, py, Plot.LINE);
    final CurveFitter cf = new CurveFitter(boxSizes, boxCountSums);
    cf.doFit(CurveFitter.STRAIGHT_LINE);
    plot.addLabel(
        0.1, 0.1, "Slope: " + IJ.d2s(params[1], 4) + "\n" + "R²: " + IJ.d2s(cf.getRSquared(), 4));
    final ImagePlus plotImage = new ImagePlus("Plot", plot.getProcessor());
    plotImage.show();
    return;
  }
예제 #2
0
  // TODO split run method into more sensible methods
  public void run(final String arg) {
    if (!ImageCheck.checkEnvironment()) return;
    final ImagePlus imp = IJ.getImage();
    if (null == imp) {
      IJ.noImage();
      return;
    }
    final ImageCheck ic = new ImageCheck();
    if (!ImageCheck.isBinary(imp)) {
      IJ.showMessage("Fractal Count requires a binary image.");
      return;
    }
    if (noGo) return;
    final ImagePlus surfaceImp = findSurfaceVoxels(imp);
    try {
      // Fetch data
      final int width = imp.getWidth();
      final int height = imp.getHeight();
      final int depth = imp.getStackSize();

      if (autoParam) {
        maxBox = Math.max(width, Math.max(height, depth)) / autoDiv;
        if (verboseOutput) {
          IJ.log("Automatic max box size " + maxBox + " selected");
        }
      }

      // Create variables we need and set them
      long bestCount; // keep track of best count so far
      long count = 0; // current count
      final ArrayList<Double> xList = new ArrayList<Double>();
      final ArrayList<Double> yList = new ArrayList<Double>();
      int xPos, yPos, zPos, yPart;
      int xGrid, yGrid, zGrid;
      int xStart, yStart, zStart;
      int xEnd, yEnd, zEnd;

      // Start timer
      final long startTime = System.currentTimeMillis();

      for (int boxSize = maxBox; boxSize >= minBox; boxSize /= divBox) {
        if (verboseOutput) {
          IJ.showStatus("Estimating dimension, box size: " + boxSize);
        }

        bestCount = Long.MAX_VALUE; // init count for this boxSize

        final int increment = Math.max(1, boxSize / numOffsets);

        for (int gridOffsetX = 0;
            (gridOffsetX < boxSize) && (gridOffsetX < width);
            gridOffsetX += increment) {

          for (int gridOffsetY = 0;
              (gridOffsetY < boxSize) && (gridOffsetY < height);
              gridOffsetY += increment) {

            for (int gridOffsetZ = 0;
                (gridOffsetZ < boxSize) && (gridOffsetZ < depth);
                gridOffsetZ += increment) {

              count = 0;

              final int iMax = width + gridOffsetX;
              final int jMax = height + gridOffsetY;
              final int kMax = depth + gridOffsetZ;

              // Iterate over box-grid
              for (int i = 0; i <= iMax; i += boxSize) {
                xGrid = -gridOffsetX + i;
                for (int j = 0; j <= jMax; j += boxSize) {
                  yGrid = -gridOffsetY + j;
                  for (int k = 0; k <= kMax; k += boxSize) {
                    zGrid = -gridOffsetZ + k;

                    xStart = 0;
                    if (xGrid < 0) {
                      xStart = -xGrid;
                    }
                    if ((boxSize + xGrid) >= width) {
                      xEnd = Math.min(width, (width - xGrid));
                    } else {
                      xEnd = boxSize;
                    }

                    yStart = 0;
                    if (yGrid < 0) {
                      yStart = -yGrid;
                    }
                    if ((boxSize + yGrid) >= height) {
                      yEnd = Math.min(height, (height - yGrid));
                    } else {
                      yEnd = boxSize;
                    }

                    zStart = 0;
                    if (zGrid < 0) {
                      zStart = -zGrid;
                    }
                    if ((boxSize + zGrid) >= depth) {
                      zEnd = Math.min(depth, (depth - zGrid));
                    } else {
                      zEnd = boxSize;
                    }

                    for (int x = xStart; x < xEnd; x++) {
                      xPos = x + xGrid;

                      for (int y = yStart; y < yEnd; y++) {
                        yPos = (y + yGrid);
                        yPart = yPos * width;

                        for (int z = zStart; z < zEnd; z++) {
                          zPos = z + zGrid;

                          // If pixel inside region,
                          // count it

                          if ((0xff
                                  & ((byte[]) surfaceImp.getStack().getPixels(zPos + 1))
                                      [xPos + yPart])
                              >= threshold) {
                            count++;
                            z = x = y = boxSize; // stops
                            // things
                          }
                        }
                      }
                    }
                  }
                }
              }
              if (count < bestCount) {
                bestCount = count;
              }
            }
          }
        }
        xList.add(new Double(boxSize));
        yList.add(new Double(bestCount));
      }

      if (verboseOutput) {
        IJ.log("\nDuration: " + (System.currentTimeMillis() - startTime) / 1000.0 + " seconds\n");
      }

      final double[] boxSizes = new double[xList.size()];
      final double[] boxCountSums = new double[yList.size()];
      for (int i = 0; i < boxSizes.length; i++) {
        boxSizes[i] = -Math.log((xList.get(i)).doubleValue());
        boxCountSums[i] = Math.log((yList.get(i)).doubleValue());
      }

      if (verboseOutput) {
        IJ.log(
            "Used " + boxSizes.length + " different box sizes, from " + maxBox + " to " + minBox);
        IJ.log(
            "with a reduction rate of "
                + divBox
                + " and "
                + numOffsets
                + " translations of each box.");
      }

      if (boxSizes.length == 0) {
        IJ.error(
            "\nError: No boxes!\n"
                + "Make sure that starting and ending box size and"
                + "reduction rate allow for at least one"
                + " box size to exist!");
        return;
      }

      final CurveFitter cf = new CurveFitter(boxSizes, boxCountSums);
      cf.doFit(CurveFitter.STRAIGHT_LINE);
      final double[] p = cf.getParams();
      final double RSq = cf.getRSquared();

      if (verboseOutput) {
        IJ.log(
            imp.getTitle()
                + ": Dimension estimate: "
                + IJ.d2s(p[1], 4)
                + ": R²: "
                + RSq
                + ": Settings: "
                + maxBox
                + ":"
                + minBox
                + ":"
                + divBox
                + ":"
                + numOffsets);
      }

      if (verboseOutput) {
        IJ.log("Box Size    Box Count");
        for (int i = 0; i < boxSizes.length; i++) {
          IJ.log(IJ.d2s(xList.get(i), 0) + "            " + IJ.d2s(yList.get(i), 0));
        }
      }

      final ResultInserter ri = ResultInserter.getInstance();
      ri.setResultInRow(imp, "Fractal Dimension", p[1]);
      ri.setResultInRow(imp, "R²", RSq);
      ri.updateTable();

      if (plotGraph && !Interpreter.isBatchMode()) {
        drawGraph(p, boxSizes, boxCountSums);
      }
    } catch (final Exception e) {
      e.printStackTrace();
    }
    UsageReporter.reportEvent(this).send();
  }