/**
   * Use the GUI results to set up the variables needed to run the algorithm.
   *
   * @return <code>true</code> if parameters set successfully, <code>false</code> otherwise.
   */
  private boolean setVariables() {
    String tmpStr;

    System.gc();

    if (replaceImage.isSelected()) {
      displayLoc = REPLACE;
    } else if (newImage.isSelected()) {
      displayLoc = NEW;
    }

    tmpStr = textSearchWindowSide.getText();

    if (testParameter(tmpStr, 5, 101)) {
      searchWindowSide = Integer.valueOf(tmpStr).intValue();
    } else {
      MipavUtil.displayError("Search window side must be between 5 and 101");
      textSearchWindowSide.requestFocus();
      textSearchWindowSide.selectAll();

      return false;
    }

    if ((searchWindowSide % 2) == 0) {
      MipavUtil.displayError("Search window side must be an odd number");
      textSearchWindowSide.requestFocus();
      textSearchWindowSide.selectAll();
      return false;
    }

    tmpStr = textSimilarityWindowSide.getText();

    if (testParameter(tmpStr, 3, 99)) {
      similarityWindowSide = Integer.valueOf(tmpStr).intValue();
    } else {
      MipavUtil.displayError("Similarity window side must be between 3 and 99");
      textSimilarityWindowSide.requestFocus();
      textSimilarityWindowSide.selectAll();

      return false;
    }

    if ((similarityWindowSide % 2) == 0) {
      MipavUtil.displayError("Similarity window side must be an odd number");
      textSimilarityWindowSide.requestFocus();
      textSimilarityWindowSide.selectAll();
      return false;
    }

    if (similarityWindowSide >= searchWindowSide) {
      MipavUtil.displayError("Similarity window side must be less than search window side");
      textSimilarityWindowSide.requestFocus();
      textSimilarityWindowSide.selectAll();
      return false;
    }

    tmpStr = textNoiseStandardDeviation.getText();

    if (testParameter(tmpStr, 0.001, 1000.0)) {
      noiseStandardDeviation = Float.valueOf(tmpStr).floatValue();
    } else {
      MipavUtil.displayError("Radius must be between 0.001 and 1000.0");
      textNoiseStandardDeviation.requestFocus();
      textNoiseStandardDeviation.selectAll();

      return false;
    }

    doRician = doRicianCheckBox.isSelected();

    if (doRician) {
      tmpStr = textDegree.getText();
      if (testParameter(tmpStr, 1.0, 10.0)) {
        degreeOfFiltering = Float.valueOf(tmpStr).floatValue();
      } else {
        MipavUtil.displayError("Degree of filtering must be between 1.0 and 10.0");
        textDegree.requestFocus();
        textDegree.selectAll();
      }
    }

    if (image.getNDims() > 2) {
      image25D = image25DCheckBox.isSelected();
    }

    return true;
  }
  /**
   * Initializes the GUI by creating the components, placing them in the dialog, and displaying
   * them.
   */
  private void init() {
    setForeground(Color.black);

    setTitle("Nonlocal Means Filter");

    JPanel mainPanel;
    mainPanel = new JPanel();
    mainPanel.setBorder(BorderFactory.createEmptyBorder(3, 3, 3, 3));
    mainPanel.setLayout(new GridBagLayout());

    GridBagConstraints gbc = new GridBagConstraints();
    gbc.gridwidth = 1;
    gbc.gridheight = 1;
    gbc.anchor = GridBagConstraints.WEST;
    gbc.weightx = 1;
    gbc.insets = new Insets(3, 3, 3, 3);
    gbc.gridx = 0;
    gbc.gridy = 0;
    gbc.fill = GridBagConstraints.HORIZONTAL;

    paramPanel = new JPanel(new GridBagLayout());
    paramPanel.setForeground(Color.black);
    paramPanel.setBorder(buildTitledBorder("Parameters"));
    mainPanel.add(paramPanel, gbc);

    GridBagConstraints gbc2 = new GridBagConstraints();
    gbc2.gridwidth = 1;
    gbc2.gridheight = 1;
    gbc2.anchor = GridBagConstraints.WEST;
    gbc2.weightx = 1;
    gbc2.insets = new Insets(3, 3, 3, 3);
    gbc2.gridx = 0;
    gbc2.gridy = 0;
    gbc2.fill = GridBagConstraints.HORIZONTAL;

    labelSearchWindowSide = createLabel("Search window side (odd)");

    paramPanel.add(labelSearchWindowSide, gbc2);

    gbc2.gridx = 1;
    textSearchWindowSide = createTextField("15");
    paramPanel.add(textSearchWindowSide, gbc2);

    gbc2.gridx = 0;
    gbc2.gridy = 1;
    labelSimilarityWindowSide = createLabel("Similarity window side (odd) ");
    paramPanel.add(labelSimilarityWindowSide, gbc2);

    gbc2.gridx = 1;
    textSimilarityWindowSide = createTextField("7");
    paramPanel.add(textSimilarityWindowSide, gbc2);

    gbc2.gridx = 0;
    gbc2.gridy = 2;
    labelNoiseStandardDeviation = createLabel("Noise standard deviation ");
    paramPanel.add(labelNoiseStandardDeviation, gbc2);

    gbc2.gridx = 1;
    textNoiseStandardDeviation = createTextField("10.0");
    paramPanel.add(textNoiseStandardDeviation, gbc2);

    gbc2.gridx = 0;
    gbc2.gridy = 3;
    labelDegree = createLabel("Degree of filtering ");
    labelDegree.setEnabled(doRician);
    paramPanel.add(labelDegree, gbc2);

    gbc2.gridx = 1;
    textDegree = createTextField("1.414");
    textDegree.setEnabled(doRician);
    paramPanel.add(textDegree, gbc2);

    gbc2.gridx = 0;
    gbc2.gridy = 4;
    doRicianCheckBox = new JCheckBox("Deal with Rician noise in MRI");
    doRicianCheckBox.setFont(serif12);
    doRicianCheckBox.setSelected(false);
    doRicianCheckBox.addActionListener(this);
    paramPanel.add(doRicianCheckBox, gbc2);

    if (image.getNDims() > 2) {
      gbc2.gridx = 0;
      gbc2.gridy = 5;
      gbc2.gridwidth = 2;

      image25DCheckBox = new JCheckBox("Process each slice independently (2.5D)");
      image25DCheckBox.setFont(serif12);
      paramPanel.add(image25DCheckBox, gbc2);
      image25DCheckBox.setSelected(false);
    } // if (image.getNDims > 2)

    JPanel outputOptPanel = new JPanel(new GridLayout(1, 2));
    destinationPanel = new JPanel(new BorderLayout());
    destinationPanel.setForeground(Color.black);
    destinationPanel.setBorder(buildTitledBorder("Destination"));
    outputOptPanel.add(destinationPanel);

    destinationGroup = new ButtonGroup();
    newImage = new JRadioButton("New image", true);
    newImage.setBounds(10, 16, 120, 25);
    newImage.setFont(serif12);
    destinationGroup.add(newImage);
    destinationPanel.add(newImage, BorderLayout.NORTH);

    replaceImage = new JRadioButton("Replace image", false);
    replaceImage.setFont(serif12);
    destinationGroup.add(replaceImage);
    destinationPanel.add(replaceImage, BorderLayout.CENTER);

    // Only if the image is unlocked can it be replaced.
    if (image.getLockStatus() == ModelStorageBase.UNLOCKED) {
      replaceImage.setEnabled(true);
    } else {
      replaceImage.setEnabled(false);
    }

    gbc.gridx = 0;
    gbc.gridy = 1;
    mainPanel.add(outputOptPanel, gbc);

    mainDialogPanel.add(mainPanel, BorderLayout.CENTER);
    mainDialogPanel.add(buildButtons(), BorderLayout.SOUTH);

    getContentPane().add(mainDialogPanel);

    pack();
    setResizable(true);
    // setVisible(true);

    System.gc();
  }
  /**
   * Once all the necessary variables are set, call the Concat algorithm based on what type of image
   * this is and whether or not there is a separate destination image.
   */
  protected void callAlgorithm() {
    int destExtents[] = new int[3];
    ModelImage destImage = null;

    destExtents[0] = subXDim;
    destExtents[1] = subYDim;
    destExtents[2] = numberOfImagesInMosaic;

    destImage =
        new ModelImage(
            image.getType(), destExtents, makeImageName(image.getImageName(), "_mosaic_to_slices"));

    try {

      // Make algorithm
      mathAlgo = new AlgorithmMosaicToSlices(image, destImage);

      // This is very important. Adding this object as a listener allows the algorithm to
      // notify this object when it has completed of failed. See algorithm performed event.
      // This is made possible by implementing AlgorithmedPerformed interface
      mathAlgo.addListener(this);

      createProgressBar(image.getImageName(), mathAlgo);

      // Hide dialog
      setVisible(false);

      if (displayLoc == REPLACE) {

        // These next lines set the titles in all frames where the source image is displayed to
        // "locked - " image name so as to indicate that the image is now read/write locked!
        // The image frames are disabled and then unregisted from the userinterface until the
        // algorithm has completed.
        Vector<ViewImageUpdateInterface> imageFrames = image.getImageFrameVector();
        titles = new String[imageFrames.size()];

        for (int i = 0; i < imageFrames.size(); i++) {
          titles[i] = ((Frame) (imageFrames.elementAt(i))).getTitle();
          ((Frame) (imageFrames.elementAt(i))).setTitle("Locked: " + titles[i]);
          ((Frame) (imageFrames.elementAt(i))).setEnabled(false);
          userInterface.unregisterFrame((Frame) (imageFrames.elementAt(i)));
        }
      }

      if (isRunInSeparateThread()) {

        // Start the thread as a low priority because we wish to still have user interface work
        // fast.
        if (mathAlgo.startMethod(Thread.MIN_PRIORITY) == false) {
          MipavUtil.displayError("A thread is already running on this object");
        }

      } else {

        mathAlgo.run();
      }
    } catch (OutOfMemoryError x) {
      System.gc();
      MipavUtil.displayError("Dialog Concatenation: unable to allocate enough memory");

      return;
    }
  }
  /** Sets up the GUI (panels, buttons, etc) and displays it on the screen. */
  private void init() {
    DecimalFormat df;
    int xUnits;
    String unitStr;
    String distStr;
    setForeground(Color.black);
    setTitle("Center Distances version 2  07/14/08");

    df = new DecimalFormat("0.000E0");

    GridBagConstraints gbc = new GridBagConstraints();
    int yPos = 0;
    gbc.gridwidth = 1;
    gbc.gridheight = 1;
    gbc.anchor = GridBagConstraints.WEST;
    gbc.weightx = 1;
    gbc.insets = new Insets(3, 3, 3, 3);
    gbc.fill = GridBagConstraints.HORIZONTAL;
    gbc.gridx = 0;
    gbc.gridy = yPos++;

    JPanel mainPanel = new JPanel(new GridBagLayout());
    mainPanel.setForeground(Color.black);
    mainPanel.setBorder(buildTitledBorder("Input parameters"));

    blueMinLabel = new JLabel("Minimum number of blue pixels per nucleus");
    blueMinLabel.setForeground(Color.black);
    blueMinLabel.setFont(serif12);
    gbc.gridx = 0;
    gbc.gridy = yPos;
    mainPanel.add(blueMinLabel, gbc);

    blueMinText = new JTextField(5);
    if (image.getNDims() == 2) {
      blueMinText.setText("1000");
    } else {
      blueMinText.setText("20000");
    }
    blueMinText.setFont(serif12);
    gbc.gridx = 1;
    gbc.gridy = yPos++;
    mainPanel.add(blueMinText, gbc);

    redMinLabel = new JLabel("Minimum red pixel count");
    redMinLabel.setForeground(Color.black);
    redMinLabel.setFont(serif12);
    gbc.gridx = 0;
    gbc.gridy = yPos;
    mainPanel.add(redMinLabel, gbc);

    redMinText = new JTextField(5);
    redMinText.setText("50");
    redMinText.setFont(serif12);
    gbc.gridx = 1;
    gbc.gridy = yPos++;
    mainPanel.add(redMinText, gbc);

    redFractionLabel = new JLabel("Fraction of red pixels to consider");
    redFractionLabel.setForeground(Color.black);
    redFractionLabel.setFont(serif12);
    gbc.gridx = 0;
    gbc.gridy = yPos;
    mainPanel.add(redFractionLabel, gbc);

    redFractionText = new JTextField(5);
    redFractionText.setText("0.15");
    redFractionText.setFont(serif12);
    gbc.gridx = 1;
    gbc.gridy = yPos++;
    mainPanel.add(redFractionText, gbc);

    xUnits = image.getFileInfo(0).getUnitsOfMeasure()[0];
    if (xUnits != Unit.UNKNOWN_MEASURE.getLegacyNum()) {
      unitStr = (Unit.getUnitFromLegacyNum(xUnits)).toString();
      greenMergingLabel = new JLabel("Green merging radius around peak (" + unitStr + ")");
    } else {
      greenMergingLabel = new JLabel("Green merging radius around peak");
    }
    greenMergingLabel.setForeground(Color.black);
    greenMergingLabel.setFont(serif12);
    gbc.gridx = 0;
    gbc.gridy = yPos;
    mainPanel.add(greenMergingLabel, gbc);

    if (image.getNDims() == 2) {
      // mergingDistance = 8.0f * image.getFileInfo(0).getResolutions()[0];
      mergingDistance = 0.0f;
    } else {
      // mergingDistance = 4.0f * image.getFileInfo(0).getResolutions()[0];
      mergingDistance = 0.0f;
    }
    distStr = df.format(mergingDistance);
    greenMergingText = new JTextField(10);
    greenMergingText.setText(distStr);
    greenMergingText.setFont(serif12);
    gbc.gridx = 1;
    gbc.gridy = yPos++;
    mainPanel.add(greenMergingText, gbc);

    greenMinLabel = new JLabel("Minimum green pixel count");
    greenMinLabel.setForeground(Color.black);
    greenMinLabel.setFont(serif12);
    gbc.gridx = 0;
    gbc.gridy = yPos;
    mainPanel.add(greenMinLabel, gbc);

    greenMinText = new JTextField(5);
    greenMinText.setText("10");
    greenMinText.setFont(serif12);
    gbc.gridx = 1;
    gbc.gridy = yPos++;
    mainPanel.add(greenMinText, gbc);

    greenFractionLabel = new JLabel("Fraction of green pixels to consider");
    greenFractionLabel.setForeground(Color.black);
    greenFractionLabel.setFont(serif12);
    gbc.gridx = 0;
    gbc.gridy = yPos;
    mainPanel.add(greenFractionLabel, gbc);

    greenFractionText = new JTextField(5);
    greenFractionText.setText("0.01");
    greenFractionText.setFont(serif12);
    gbc.gridx = 1;
    gbc.gridy = yPos++;
    mainPanel.add(greenFractionText, gbc);

    greenRegionsLabel = new JLabel("Green regions per cell");
    greenRegionsLabel.setForeground(Color.black);
    greenRegionsLabel.setFont(serif12);
    gbc.gridx = 0;
    gbc.gridy = yPos;
    mainPanel.add(greenRegionsLabel, gbc);

    JPanel buttonPanel = new JPanel(new GridBagLayout());

    greenGroup = new ButtonGroup();

    oneButton = new JRadioButton("1", false);
    oneButton.setForeground(Color.black);
    oneButton.setFont(serif12);
    greenGroup.add(oneButton);
    gbc.gridx = 0;
    gbc.gridy = 0;
    buttonPanel.add(oneButton, gbc);

    twoButton = new JRadioButton("2", true);
    twoButton.setForeground(Color.black);
    twoButton.setFont(serif12);
    greenGroup.add(twoButton);
    gbc.gridx = 1;
    gbc.gridy = 0;
    buttonPanel.add(twoButton, gbc);

    threeButton = new JRadioButton("3", false);
    threeButton.setForeground(Color.black);
    threeButton.setFont(serif12);
    greenGroup.add(threeButton);
    gbc.gridx = 2;
    gbc.gridy = 0;
    buttonPanel.add(threeButton, gbc);

    fourButton = new JRadioButton("4", false);
    fourButton.setForeground(Color.black);
    fourButton.setFont(serif12);
    greenGroup.add(fourButton);
    gbc.gridx = 3;
    gbc.gridy = 0;
    buttonPanel.add(fourButton, gbc);

    gbc.gridx = 1;
    gbc.gridy = yPos++;
    mainPanel.add(buttonPanel, gbc);

    twoBox = new JCheckBox("Use 2 top gray levels in green segmentation", true);
    twoBox.setForeground(Color.black);
    twoBox.setFont(serif12);
    gbc.gridx = 0;
    gbc.gridy = yPos++;
    mainPanel.add(twoBox, gbc);

    blueValueLabel =
        new JLabel("Fraction of blue transition from image min to max at nucleus boundary");
    blueValueLabel.setForeground(Color.black);
    blueValueLabel.setFont(serif12);
    gbc.gridx = 0;
    gbc.gridy = yPos;
    mainPanel.add(blueValueLabel, gbc);

    blueValueText = new JTextField(5);
    blueValueText.setText("0.15");
    blueValueText.setFont(serif12);
    gbc.gridx = 1;
    gbc.gridy = yPos++;
    mainPanel.add(blueValueText, gbc);

    blueSmoothBox = new JCheckBox("Smooth blue VOI contours with AlgorithmBSmooth", true);
    blueSmoothBox.setForeground(Color.black);
    blueSmoothBox.setFont(serif12);
    blueSmoothBox.addActionListener(this);
    gbc.gridx = 0;
    gbc.gridy = yPos++;
    mainPanel.add(blueSmoothBox, gbc);

    interpolationLabel = new JLabel("Number of interpolation points determined by divisor (> 1.0)");
    interpolationLabel.setForeground(Color.black);
    interpolationLabel.setFont(serif12);
    gbc.gridx = 0;
    gbc.gridy = yPos;
    mainPanel.add(interpolationLabel, gbc);

    interpolationText = new JTextField(5);
    interpolationText.setText("24.0");
    interpolationText.setFont(serif12);
    gbc.gridx = 1;
    gbc.gridy = yPos++;
    mainPanel.add(interpolationText, gbc);

    getContentPane().add(mainPanel, BorderLayout.CENTER);
    getContentPane().add(buildButtons(), BorderLayout.SOUTH);

    pack();
    setVisible(true);
    setResizable(false);
    System.gc();
  } // end init()
  /**
   * This method is required if the AlgorithmPerformed interface is implemented. It is called by the
   * algorithms when it has completed or failed to to complete, so that the dialog can be display
   * the result image and/or clean up.
   *
   * @param algorithm Algorithm that caused the event.
   */
  public void algorithmPerformed(AlgorithmBase algorithm) {
    ViewJFrameImage imageFrame = null;

    if (algorithm instanceof AlgorithmMosaicToSlices) {

      if ((mathAlgo.isCompleted() == true) && (mathAlgo.getResultImage() != null)) {

        // The algorithm has completed and produced a new image to be displayed.
        if (displayLoc == NEW) {

          try {
            resultImage = mathAlgo.getResultImage();

            new ViewJFrameImage(resultImage, null, new Dimension(610, 200));
          } catch (OutOfMemoryError error) {
            System.gc();
            MipavUtil.displayError("Out of memory: unable to open new frame");
          }
        } else {

          // These next lines set the titles in all frames where the source image is displayed to
          // image name so as to indicate that the image is now unlocked!
          // The image frames are enabled and then registed to the userinterface.
          resultImage = mathAlgo.getResultImage();

          Vector<ViewImageUpdateInterface> imageFrames = image.getImageFrameVector();

          for (int i = 0; i < imageFrames.size(); i++) {
            ((Frame) (imageFrames.elementAt(i))).setTitle(titles[i]);
            ((Frame) (imageFrames.elementAt(i))).setEnabled(true);

            if ((((Frame) (imageFrames.elementAt(i))) != parentFrame) && (parentFrame != null)) {
              userInterface.registerFrame((Frame) (imageFrames.elementAt(i)));
            }
          }

          Point pt;

          if (parentFrame != null) {
            pt = ((ViewJFrameBase) parentFrame).getLocation();
          } else {
            pt =
                new Point(
                    Toolkit.getDefaultToolkit().getScreenSize().width / 2,
                    Toolkit.getDefaultToolkit().getScreenSize().height / 2);
          }

          imageFrame = new ViewJFrameImage(resultImage, null, new Dimension(pt.x, pt.y));

          if (parentFrame != null) {
            ((ViewJFrameBase) parentFrame).close();
          } else {
            ((ViewJFrameBase) image.getParentFrame()).close();
          }

          // Not so sure about this.
          if (image.getLightBoxFrame() != null) {

            try {
              pt = image.getLightBoxFrame().getLocation();
              image.getLightBoxFrame().close();
              new ViewJFrameLightBox(
                  imageFrame,
                  "LightBox",
                  resultImage,
                  imageFrame.getComponentImage().getLUTa(),
                  imageFrame.getComponentImage().getImageB(),
                  imageFrame.getComponentImage().getLUTb(),
                  imageFrame.getComponentImage().getResolutionX(),
                  imageFrame.getComponentImage().getResolutionY(),
                  new Dimension(pt.x, pt.y),
                  imageFrame.getControls(),
                  imageFrame.getVOIManager());
            } catch (OutOfMemoryError error) {
              MipavUtil.displayError("Out of memory: unable to open new frame");
            }
          }
        }
      } else if (resultImage == null) {

        // These next lines set the titles in all frames where the source image is displayed to
        // image name so as to indicate that the image is now unlocked!
        // The image frames are enabled and then registered to the userinterface.
        /*Vector imageFrames = imageA.getImageFrameVector();

        for (int i = 0; i < imageFrames.size(); i++) {
            ((Frame) (imageFrames.elementAt(i))).setTitle(titles[i]);
            ((Frame) (imageFrames.elementAt(i))).setEnabled(true);

            if (((Frame) (imageFrames.elementAt(i))) != parentFrame) {
                userInterface.registerFrame((Frame) (imageFrames.elementAt(i)));

            }
        }*/

        if (parentFrame != null) {
          userInterface.registerFrame(parentFrame);
        }

        image.notifyImageDisplayListeners(null, true);
      } else if (resultImage != null) {

        // algorithm failed but result image still has garbage
        resultImage.disposeLocal(); // clean up memory
        System.gc();
      }
    }

    if (algorithm.isCompleted()) {
      insertScriptLine();
    }

    mathAlgo.finalize();
    mathAlgo = null;
    dispose();
  }