예제 #1
0
 public void run(String arg) {
   ImageJ ij = IJ.getInstance();
   ij.setDropTarget(null);
   new DropTarget(ij, this);
   new DropTarget(Toolbar.getInstance(), this);
   new DropTarget(ij.getStatusBar(), this);
 }
예제 #2
0
 public void dragOver(DropTargetDragEvent e) {
   if (IJ.debugMode) IJ.log("DragOver: " + e.getLocation());
   Point loc = e.getLocation();
   int buttonSize = Toolbar.getButtonSize();
   int width = IJ.getInstance().getSize().width;
   openAsVirtualStack = width - loc.x <= buttonSize;
   if (openAsVirtualStack) IJ.showStatus("<<Open as Virtual Stack>>");
   else IJ.showStatus("<<Drag and Drop>>");
 }
예제 #3
0
  // Miscellaneous Options
  void miscOptions() {
    String key = IJ.isMacintosh() ? "command" : "control";
    GenericDialog gd = new GenericDialog("Miscellaneous Options", IJ.getInstance());
    gd.addStringField("Divide by zero value:", "" + FloatBlitter.divideByZeroValue, 10);
    gd.addCheckbox("Use pointer cursor", Prefs.usePointerCursor);
    gd.addCheckbox("Hide \"Process Stack?\" dialog", IJ.hideProcessStackDialog);
    gd.addCheckbox("Require " + key + " key for shortcuts", Prefs.requireControlKey);
    gd.addCheckbox("Move isolated plugins to Misc. menu", Prefs.moveToMisc);
    if (!IJ.isMacOSX()) gd.addCheckbox("Run single instance listener", Prefs.runSocketListener);
    gd.addCheckbox("Enhanced line tool", Prefs.enhancedLineTool);
    gd.addCheckbox("Reverse CZT order of \">\" and \"<\"", Prefs.reverseNextPreviousOrder);
    gd.addCheckbox("Debug mode", IJ.debugMode);
    gd.addHelp(IJ.URL + "/docs/menus/edit.html#misc");
    gd.showDialog();
    if (gd.wasCanceled()) return;

    String divValue = gd.getNextString();
    if (divValue.equalsIgnoreCase("infinity") || divValue.equalsIgnoreCase("infinite"))
      FloatBlitter.divideByZeroValue = Float.POSITIVE_INFINITY;
    else if (divValue.equalsIgnoreCase("NaN")) FloatBlitter.divideByZeroValue = Float.NaN;
    else if (divValue.equalsIgnoreCase("max")) FloatBlitter.divideByZeroValue = Float.MAX_VALUE;
    else {
      Float f;
      try {
        f = new Float(divValue);
      } catch (NumberFormatException e) {
        f = null;
      }
      if (f != null) FloatBlitter.divideByZeroValue = f.floatValue();
    }
    IJ.register(FloatBlitter.class);

    Prefs.usePointerCursor = gd.getNextBoolean();
    IJ.hideProcessStackDialog = gd.getNextBoolean();
    Prefs.requireControlKey = gd.getNextBoolean();
    Prefs.moveToMisc = gd.getNextBoolean();
    if (!IJ.isMacOSX()) Prefs.runSocketListener = gd.getNextBoolean();
    Prefs.enhancedLineTool = gd.getNextBoolean();
    Prefs.reverseNextPreviousOrder = gd.getNextBoolean();
    IJ.setDebugMode(gd.getNextBoolean());
  }
예제 #4
0
  public void run(String arg) {
    GenericDialog gd = new GenericDialog("Options");
    double sfreq = 20000.0;
    gd.addNumericField("Sampling Frequency?", sfreq, 1, 10, null);
    String[] psfchoice = {"3D Gaussian", "Gaus-Lorentz^2", "2D Gaussian"};
    gd.addChoice("PSF Type?", psfchoice, psfchoice[0]);
    String[] filetypechoice = {
      "Confocor 3 raw", "Short binary trajectory", "PlotWindow trajectory", "Ascii Text File"
    };
    gd.addChoice("File Type?", filetypechoice, filetypechoice[0]);
    boolean ch2green = true;
    gd.addCheckbox("Ch2 is green?", ch2green);
    gd.showDialog();
    if (gd.wasCanceled()) {
      return;
    }
    sfreq = gd.getNextNumber();
    int psfflag = gd.getNextChoiceIndex();
    int fileflag = gd.getNextChoiceIndex();
    ch2green = gd.getNextBoolean();
    int nfiles = 0;
    Object[] histograms = null;
    int xmax = 0;
    int ymax = 0;
    String[] names = null;
    if (fileflag < 2) {
      jdataio ioclass = new jdataio();
      File[] filearray = ioclass.openfiles(OpenDialog.getDefaultDirectory(), IJ.getInstance());
      if (filearray.length == 0) {
        return;
      }
      String dir = filearray[0].getAbsolutePath();
      int sepindex = dir.lastIndexOf(File.separator);
      String newdir = dir.substring(0, sepindex + 1);
      OpenDialog.setDefaultDirectory(newdir);
      nfiles = filearray.length / 2;
      if (nfiles > 25) {
        nfiles = 25;
      }
      histograms = new Object[nfiles];
      names = organize_c3_files(filearray);
      for (int i = 0; i < nfiles; i++) {
        try {
          int length1 = (int) (((double) filearray[2 * i].length() - 128.0) / 4.0);
          int length2 = (int) (((double) filearray[2 * i + 1].length() - 128.0) / 4.0);
          int length3 = (int) (((double) filearray[2 * i].length()) / 2.0);
          int length4 = (int) (((double) filearray[2 * i + 1].length()) / 2.0);
          InputStream instream = new BufferedInputStream(new FileInputStream(filearray[2 * i]));
          InputStream instream2 =
              new BufferedInputStream(new FileInputStream(filearray[2 * i + 1]));
          if (fileflag == 0) {
            int[] pmdata = new int[length1];
            int[] pmdata2 = new int[length2];
            if (!ioclass.skipstreambytes(instream, 128)) {
              showioerror();
              instream.close();
              return;
            }
            if (!ioclass.skipstreambytes(instream2, 128)) {
              showioerror();
              instream2.close();
              return;
            }
            if (!ioclass.readintelintfile(instream, length1, pmdata)) {
              showioerror();
              instream.close();
              return;
            }
            if (!ioclass.readintelintfile(instream2, length2, pmdata2)) {
              showioerror();
              instream2.close();
              return;
            }
            if (ch2green) {
              histograms[i] = (new pmodeconvert()).pm2pch(pmdata2, pmdata, sfreq, 20000000);
            } else {
              histograms[i] = (new pmodeconvert()).pm2pch(pmdata, pmdata2, sfreq, 20000000);
            }
          } else {
            float[] tmdata = new float[length3];
            float[] tmdata2 = new float[length4];
            if (!ioclass.readintelshortfile(instream, length3, tmdata)) {
              showioerror();
              instream.close();
              return;
            }
            if (!ioclass.readintelshortfile(instream2, length4, tmdata2)) {
              showioerror();
              instream2.close();
              return;
            }
            if (ch2green) {
              histograms[i] = (new pmodeconvert()).create_2Dhistogram(tmdata2, tmdata);
            } else {
              histograms[i] = (new pmodeconvert()).create_2Dhistogram(tmdata, tmdata2);
            }
          }
          if (((float[][]) histograms[i]).length > xmax) {
            xmax = ((float[][]) histograms[i]).length;
          }
          if (((float[][]) histograms[i])[0].length > ymax) {
            ymax = ((float[][]) histograms[i])[0].length;
          }
          instream.close();
          instream2.close();
        } catch (IOException e) {
          showioerror();
          return;
        }
      }
    } else {
      if (fileflag == 2) {
        ImageWindow iw = WindowManager.getCurrentWindow();
        float[][] trajectories = (float[][]) jutils.runPW4VoidMethod(iw, "getYValues");
        float[][] tempxvals = (float[][]) jutils.runPW4VoidMethod(iw, "getXValues");
        sfreq = 1.0 / ((double) tempxvals[0][1]);
        nfiles = trajectories.length / 2;
        if (nfiles > 25) {
          nfiles = 25;
        }
        names = new String[nfiles + 1];
        names[nfiles] = "avg";
        histograms = new Object[nfiles];
        for (int i = 0; i < nfiles; i++) {
          names[i] = "trajectory " + (i + 1);
          if (ch2green) {
            histograms[i] =
                (new pmodeconvert())
                    .create_2Dhistogram(trajectories[2 * i + 1], trajectories[2 * i]);
          } else {
            histograms[i] =
                (new pmodeconvert())
                    .create_2Dhistogram(trajectories[2 * i], trajectories[2 * i + 1]);
          }
          if (((float[][]) histograms[i]).length > xmax) {
            xmax = ((float[][]) histograms[i]).length;
          }
          if (((float[][]) histograms[i])[0].length > ymax) {
            ymax = ((float[][]) histograms[i])[0].length;
          }
        }
      } else {
        // here we read tab delimited lines from files
        jdataio ioclass = new jdataio();
        File[] filearray = ioclass.openfiles(OpenDialog.getDefaultDirectory(), IJ.getInstance());
        if (filearray.length == 0) {
          return;
        }
        String dir = filearray[0].getAbsolutePath();
        int sepindex = dir.lastIndexOf(File.separator);
        String newdir = dir.substring(0, sepindex + 1);
        OpenDialog.setDefaultDirectory(newdir);
        nfiles = filearray.length;
        if (nfiles > 25) {
          nfiles = 25;
        }
        histograms = new Object[nfiles];
        names = new String[nfiles + 1];
        names[nfiles] = "avg";
        for (int i = 0; i < nfiles; i++) {
          try {
            names[i] = filearray[i].getName();
            BufferedReader d = new BufferedReader(new FileReader(filearray[i]));
            String[] lines = new String[256];
            int counter = 0;
            do {
              lines[counter] = d.readLine();
              counter++;
            } while ((lines[counter - 1] != null && lines[counter - 1] != "") && counter < 256);
            int numcolumns = 0;
            for (int j = 0; j < counter - 1; j++) {
              int temp = getncolumns(lines[j]);
              if (temp > numcolumns) {
                numcolumns = temp;
              }
            }
            float[][] temphist2 = null;
            if (ch2green) {
              temphist2 = new float[numcolumns][counter - 1];
            } else {
              temphist2 = new float[counter - 1][numcolumns];
            }
            for (int k = 0; k < counter - 1; k++) {
              float[] temp = tab_delim2float(lines[k]);
              for (int j = 0; j < numcolumns; j++) {
                if (ch2green) {
                  temphist2[j][k] = temp[j];
                } else {
                  temphist2[k][j] = temp[j];
                }
              }
            }
            histograms[i] = temphist2;
            d.close();
          } catch (IOException e) {
            showioerror();
            return;
          }
        }
        for (int i = 0; i < nfiles; i++) {
          if (((float[][]) histograms[i]).length > xmax) {
            xmax = ((float[][]) histograms[i]).length;
          }
          if (((float[][]) histograms[i])[0].length > ymax) {
            ymax = ((float[][]) histograms[i])[0].length;
          }
        }
      }
    }
    // note that here x is green and y is red
    float[][][] pch = new float[nfiles][xmax][ymax];
    for (int i = 0; i < nfiles; i++) {
      for (int j = 0; j < ((float[][]) histograms[i]).length; j++) {
        for (int k = 0; k < ((float[][]) histograms[i])[j].length; k++) {
          pch[i][j][k] = ((float[][]) histograms[i])[j][k];
        }
      }
    }

    final PCH2DFitWindow cw = new PCH2DFitWindow();
    cw.init(names, pch, psfflag);

    final Frame f = new Frame("PCH 2D Analysis");
    f.setLocation(10, 10);
    f.addWindowListener(
        new WindowAdapter() {
          public void windowClosing(WindowEvent e) {
            f.dispose();
          }
        });

    f.add(cw);
    f.pack();
    f.setResizable(false);
    Insets ins = f.getInsets();
    cw.totalSize.height = PCH2DFitWindow.H + ins.bottom + ins.top + 65;
    cw.totalSize.width = PCH2DFitWindow.WR + ins.left + ins.right;
    f.setSize(cw.totalSize);
    f.setVisible(true);
    cw.requestFocus();
  }
예제 #5
0
 public static void main(String args[]) {
   if (System.getProperty("java.version").substring(0, 3).compareTo("1.5") < 0) {
     javax.swing.JOptionPane.showMessageDialog(
         null, "ImageJ " + VERSION + " requires Java 1.5 or later.");
     System.exit(0);
   }
   boolean noGUI = false;
   int mode = STANDALONE;
   arguments = args;
   // System.setProperty("file.encoding", "UTF-8");
   int nArgs = args != null ? args.length : 0;
   boolean commandLine = false;
   for (int i = 0; i < nArgs; i++) {
     String arg = args[i];
     if (arg == null) continue;
     if (args[i].startsWith("-")) {
       if (args[i].startsWith("-batch")) noGUI = true;
       else if (args[i].startsWith("-debug")) IJ.setDebugMode(true);
       else if (args[i].startsWith("-ijpath") && i + 1 < nArgs) {
         if (IJ.debugMode) IJ.log("-ijpath: " + args[i + 1]);
         Prefs.setHomeDir(args[i + 1]);
         commandLine = true;
         args[i + 1] = null;
       } else if (args[i].startsWith("-port")) {
         int delta = (int) Tools.parseDouble(args[i].substring(5, args[i].length()), 0.0);
         commandLine = true;
         if (delta == 0) mode = EMBEDDED;
         else if (delta > 0 && DEFAULT_PORT + delta < 65536) port = DEFAULT_PORT + delta;
       }
     }
   }
   // If existing ImageJ instance, pass arguments to it and quit.
   boolean passArgs = mode == STANDALONE && !noGUI;
   if (IJ.isMacOSX() && !commandLine) passArgs = false;
   if (passArgs && isRunning(args)) return;
   ImageJ ij = IJ.getInstance();
   if (!noGUI && (ij == null || (ij != null && !ij.isShowing()))) {
     ij = new ImageJ(null, mode);
     ij.exitWhenQuitting = true;
   }
   int macros = 0;
   for (int i = 0; i < nArgs; i++) {
     String arg = args[i];
     if (arg == null) continue;
     if (arg.startsWith("-")) {
       if ((arg.startsWith("-macro") || arg.startsWith("-batch")) && i + 1 < nArgs) {
         String arg2 = i + 2 < nArgs ? args[i + 2] : null;
         Prefs.commandLineMacro = true;
         if (noGUI && args[i + 1].endsWith(".js")) Interpreter.batchMode = true;
         IJ.runMacroFile(args[i + 1], arg2);
         break;
       } else if (arg.startsWith("-eval") && i + 1 < nArgs) {
         String rtn = IJ.runMacro(args[i + 1]);
         if (rtn != null) System.out.print(rtn);
         args[i + 1] = null;
       } else if (arg.startsWith("-run") && i + 1 < nArgs) {
         IJ.run(args[i + 1]);
         args[i + 1] = null;
       }
     } else if (macros == 0 && (arg.endsWith(".ijm") || arg.endsWith(".txt"))) {
       IJ.runMacroFile(arg);
       macros++;
     } else if (arg.length() > 0 && arg.indexOf("ij.ImageJ") == -1) {
       File file = new File(arg);
       IJ.open(file.getAbsolutePath());
     }
   }
   if (IJ.debugMode && IJ.getInstance() == null) new JavaProperties().run("");
   if (noGUI) System.exit(0);
 }
예제 #6
0
  String getInfo(ImagePlus imp, ImageProcessor ip) {
    String s = new String("");
    if (IJ.getInstance() != null) s += IJ.getInstance().getInfo() + "\n \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;
    int dp, dp2;
    boolean nonUniformUnits = !cal.getXUnit().equals(cal.getYUnit());
    String xunit = cal.getXUnit();
    String yunit = cal.getYUnit();
    String zunit = cal.getZUnit();
    if (cal.scaled()) {
      String xunits = cal.getUnits();
      String yunits = xunits;
      String zunits = xunits;
      if (nonUniformUnits) {
        xunits = xunit;
        yunits = yunit;
        zunits = zunit;
      }
      double pw = imp.getWidth() * cal.pixelWidth;
      double ph = imp.getHeight() * cal.pixelHeight;
      s += "Width:  " + d2s(pw) + " " + xunits + " (" + imp.getWidth() + ")\n";
      s += "Height:  " + d2s(ph) + " " + yunits + " (" + imp.getHeight() + ")\n";
      if (slices > 1) {
        double pd = slices * cal.pixelDepth;
        s += "Depth:  " + d2s(pd) + " " + zunits + " (" + slices + ")\n";
      }
      s += "Size:  " + ImageWindow.getImageSize(imp) + "\n";
      double xResolution = 1.0 / cal.pixelWidth;
      double yResolution = 1.0 / cal.pixelHeight;
      if (xResolution == yResolution)
        s += "Resolution:  " + d2s(xResolution) + " pixels per " + xunit + "\n";
      else {
        s += "X Resolution:  " + d2s(xResolution) + " pixels per " + xunit + "\n";
        s += "Y Resolution:  " + d2s(yResolution) + " pixels per " + yunit + "\n";
      }
    } else {
      s += "Width:  " + imp.getWidth() + " pixels\n";
      s += "Height:  " + imp.getHeight() + " pixels\n";
      if (stackSize > 1) s += "Depth:  " + slices + " pixels\n";
      s += "Size:  " + ImageWindow.getImageSize(imp) + "\n";
    }
    if (stackSize > 1) {
      String vunit = cal.getUnit() + "^3";
      if (nonUniformUnits) vunit = "(" + xunit + " x " + yunit + " x " + zunit + ")";
      s +=
          "Voxel size: "
              + d2s(cal.pixelWidth)
              + "x"
              + d2s(cal.pixelHeight)
              + "x"
              + d2s(cal.pixelDepth)
              + " "
              + vunit
              + "\n";
    } else {
      String punit = cal.getUnit() + "^2";
      if (nonUniformUnits) punit = "(" + xunit + " x " + yunit + ")";
      dp = Tools.getDecimalPlaces(cal.pixelWidth, cal.pixelHeight);
      s += "Pixel size: " + d2s(cal.pixelWidth) + "x" + d2s(cal.pixelHeight) + " " + punit + "\n";
    }

    s += "ID: " + imp.getID() + "\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 += d2s(min) + " - " + d2s(max) + "\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();
      if (cal.calibrated()) {
        lower = cal.getCValue((int) lower);
        upper = cal.getCValue((int) upper);
      }
      s += "Threshold: " + d2s(lower) + "-" + d2s(upper) + "\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";
    }

    String zOrigin = stackSize > 1 || cal.zOrigin != 0.0 ? "," + d2s(cal.zOrigin) : "";
    String origin = d2s(cal.xOrigin) + "," + d2s(cal.yOrigin) + zOrigin;
    if (!origin.equals("0,0") || cal.getInvertY()) s += "Coordinate origin:  " + origin + "\n";
    if (cal.getInvertY()) s += "Inverted y coordinates\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;
  }