BinarySegmentationView.java
package com.github.celldynamics.quimp.plugin.binaryseg;
import java.awt.Choice;
import java.awt.Dimension;
import java.awt.event.ActionListener;
import java.awt.event.ItemListener;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import java.awt.event.WindowFocusListener;
import javax.swing.JButton;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import com.github.celldynamics.quimp.BOA_;
import com.github.celldynamics.quimp.plugin.ParamList;
import com.github.celldynamics.quimp.plugin.utils.QWindowBuilder;
import ij.WindowManager;
/**
* Show UI for segmentation from masks and run it.
*
* <p>Modifies provided Nest reference on Apply. Update BOA screen on Apply button.
*
* <p>This is front end of {@link BinarySegmentation} used in BOA.
*
* @author p.baniukiewicz
* @see com.github.celldynamics.quimp.plugin.utils.QWindowBuilder
* @see BinarySegmentation_
*/
public class BinarySegmentationView extends QWindowBuilder {
// these fields code names of UI elements are are related to BinarySegmentationOptions#options
static final String NAME = "name";
static final String RESTORE_SNAKE = "Restore_Snake";
static final String CLEAR_NEST = "Clear_nest";
static final String SMOOTHING2 = "smoothing";
static final String STEP2 = "step";
static final String SELECT_MASK = "select_mask";
static final String SELECT_ORIGINAL_IMAGE = "select_original";
static final String LOAD_MASK = "load_mask";
// this is not part of UI, just store name for BOA (only ParamList by getPluginConfig() is stored
// in QCONF)
static final String LOADED_FILE = "loaded_file";
/**
* The Constant LOGGER.
*/
static final Logger LOGGER = LoggerFactory.getLogger(BinarySegmentationView.class.getName());
// default parameters
private int step = 1; // discretization step
private boolean smoothing = false; // use smoothing?
private boolean clearnest = true; // clear nest before adding next outline
private boolean restoreFields = true; // if true internal Snake fields will be restored
private ParamList uiDefinition; // window definition
/**
* Construct object.
*
* @see com.github.celldynamics.quimp.plugin.utils.QWindowBuilder
*/
public BinarySegmentationView() {
// define window controls (selecter filled in buildWindow
uiDefinition = new ParamList(); // will hold ui definitions
uiDefinition.put(NAME, "BinarySegmentation"); // name of window
uiDefinition.put(LOAD_MASK, "button: Load mask");
uiDefinition.put(SELECT_MASK, "choice:" + BOA_.NONE);
uiDefinition.put(SELECT_ORIGINAL_IMAGE, "choice:" + BOA_.NONE);
// start, end, step, default
uiDefinition.put(STEP2, "spinner: 1: 10001: 1:" + Integer.toString(step));
// name
uiDefinition.put(SMOOTHING2, "checkbox: interpolation:" + Boolean.toString(smoothing));
// clear nest
uiDefinition.put(CLEAR_NEST, "checkbox: clear:" + Boolean.toString(clearnest));
// restore
uiDefinition.put(RESTORE_SNAKE, "checkbox: restore:" + Boolean.toString(restoreFields));
// use http://www.freeformatter.com/java-dotnet-escape.html#ad-output for escaping
//!>
uiDefinition.put("help", "<font size=\"3\">If you use this plugin in standalone mode"
+ " (run from QuimP Toolbar, not from BOA), make sure that frame interval and pixel "
+ "scale are correct"
+ "<p><strong>Load Mask</strong> - Load mask file. "
+ "It should be 8-bit image of size of original stack with <span style=\"color:"
+ " #ffffff; background-color: #000000;\">black background</span> and"
+ " grayscale objects. If specified image is binary, cells will be tracked by testing "
+ "overlapping between frames. For grayscale images plugin will use gray levels to "
+ "assign cells to the same tracks."
+ "</p>\r\n<p><strong>Select Mask</strong> - Select mask already opened in"
+ " ImageJ."
+ " Alternative to <em>Load Mask</em>, will override loaded file.</p>\r\n<p>"
+ "<strong>Select Original</strong> - Ignore this field if you run plugin"
+ " within BOA. Otherwise you need to set here original image "
+ "(matching the mask) which will be used for computing statistics and produce complete"
+ " QCONF file.</p>\r\n<p>"
+ "<strong>step</strong> - stand for discretisation density, 1.0 means that every"
+ " pixel of the outline will be mapped to Snake node.</p>"
+ "\r\n<p><strong>smoothing</strong> "
+ "- add extra Spline interpolation to the shape</p>"
+ "\r\n<p><strong>Clear nest</strong> "
+ "- Delete all other snakes from view. If disabled, each use of <i>Apply</i> "
+ "will create new snake "
+ "\r\n<p><strong>Restore Snake</strong> "
+ "- Try to compute some internal data stored in Snake which are ususally obtained"
+ " if regular Active Contour method is used. Current AC options are used."
+ "</p></font>");
//!<
buildWindow(uiDefinition);
}
/**
* Add listener to apply button.
*
* @param action listener
* @see QWindowBuilder
*/
void addApplyListener(ActionListener action) {
applyB.addActionListener(action);
}
/**
* Add listener to load mask button.
*
* @param action listener
*/
void addLoadMaskListener(ActionListener action) {
((JButton) ui.get(LOAD_MASK)).addActionListener(action);
}
/**
* Add listener to image selector.
*
* @param action listener
*/
void addSelectImageListener(ItemListener action) {
((Choice) ui.get(SELECT_MASK)).addItemListener(action);
}
/*
* (non-Javadoc)
*
* @see QWindowBuilder#buildWindow(com.github.celldynamics.quimp.
* plugin.ParamList)
*/
@Override
public void buildWindow(ParamList def) {
super.buildWindow(def);
// add preffered size to this window
pluginWnd.setPreferredSize(new Dimension(450, 450));
pluginWnd.pack();
pluginWnd.setVisible(false);
// Destroy window on exit
pluginWnd.addWindowListener(new WindowAdapter() {
/*
* (non-Javadoc)
*
* @see java.awt.event.WindowAdapter#windowClosing(java.awt.event.WindowEvent)
*/
@Override
public void windowClosing(WindowEvent we) {
LOGGER.debug("Window closed");
pluginWnd.dispose();
}
}); // close not hide
// update selector
pluginWnd.addWindowFocusListener(new WindowFocusListener() {
private Choice getImage = (Choice) ui.get(SELECT_MASK);
private Choice getOrgImage = (Choice) ui.get(SELECT_ORIGINAL_IMAGE);
private String lastSelected = "";
private String lastOrgSelected = "";
@Override
public void windowLostFocus(WindowEvent e) {
lastSelected = getImage.getSelectedItem(); // remember on defocus. Will be restored on focus
lastOrgSelected = getOrgImage.getSelectedItem();
}
@Override
public void windowGainedFocus(WindowEvent e) {
String[] str = WindowManager.getImageTitles(); // get opened windows
getImage.removeAll();
getOrgImage.removeAll();
getImage.add(BOA_.NONE); // add default position
getOrgImage.add(BOA_.NONE);
for (String s : str) {
getImage.add(s);
getOrgImage.add(s);
}
getImage.select(lastSelected); // restore previous. If not available already, 0 position is
getOrgImage.select(lastOrgSelected);
}
});
}
}