use of ini.trakem2.utils.Filter in project TrakEM2 by trakem2.
the class Display method actionPerformed.
@Override
public void actionPerformed(final ActionEvent ae) {
dispatcher.exec(new Runnable() {
@Override
public void run() {
final String command = ae.getActionCommand();
if (command.startsWith("Job")) {
if (Utils.checkYN("Really cancel job?")) {
project.getLoader().quitJob(command);
repairGUI();
}
return;
} else if (command.equals("Move to top")) {
if (null == active)
return;
canvas.setUpdateGraphics(true);
getLayerSet().addUndoMoveStep(active);
layer.getParent().move(LayerSet.TOP, active);
getLayerSet().addUndoMoveStep(active);
Display.repaint(layer.getParent(), active, 5);
// Display.updatePanelIndex(layer, active);
} else if (command.equals("Move up")) {
if (null == active)
return;
canvas.setUpdateGraphics(true);
getLayerSet().addUndoMoveStep(active);
layer.getParent().move(LayerSet.UP, active);
getLayerSet().addUndoMoveStep(active);
Display.repaint(layer.getParent(), active, 5);
// Display.updatePanelIndex(layer, active);
} else if (command.equals("Move down")) {
if (null == active)
return;
canvas.setUpdateGraphics(true);
getLayerSet().addUndoMoveStep(active);
layer.getParent().move(LayerSet.DOWN, active);
getLayerSet().addUndoMoveStep(active);
Display.repaint(layer.getParent(), active, 5);
// Display.updatePanelIndex(layer, active);
} else if (command.equals("Move to bottom")) {
if (null == active)
return;
canvas.setUpdateGraphics(true);
getLayerSet().addUndoMoveStep(active);
layer.getParent().move(LayerSet.BOTTOM, active);
getLayerSet().addUndoMoveStep(active);
Display.repaint(layer.getParent(), active, 5);
// Display.updatePanelIndex(layer, active);
} else if (command.equals("Duplicate, link and send to next layer")) {
duplicateLinkAndSendTo(active, 1, layer.getParent().next(layer));
} else if (command.equals("Duplicate, link and send to previous layer")) {
duplicateLinkAndSendTo(active, 0, layer.getParent().previous(layer));
} else if (command.equals("Duplicate, link and send to...")) {
// fix non-scrolling popup menu
Utils.invokeLater(new Runnable() {
@Override
public void run() {
final GenericDialog gd = new GenericDialog("Send to");
gd.addMessage("Duplicate, link and send to...");
final String[] sl = new String[layer.getParent().size()];
int next = 0;
for (final Layer la : layer.getParent().getLayers()) {
sl[next++] = project.findLayerThing(la).toString();
}
gd.addChoice("Layer: ", sl, sl[layer.getParent().indexOf(layer)]);
gd.showDialog();
if (gd.wasCanceled())
return;
final Layer la = layer.getParent().getLayer(gd.getNextChoiceIndex());
if (layer == la) {
Utils.showMessage("Can't duplicate, link and send to the same layer.");
return;
}
duplicateLinkAndSendTo(active, 0, la);
}
});
} else if (-1 != command.indexOf("z = ")) {
// this is an item from the "Duplicate, link and send to" menu of layer z's
final Layer target_layer = layer.getParent().getLayer(Double.parseDouble(command.substring(command.lastIndexOf(' ') + 1)));
Utils.log2("layer: __" + command.substring(command.lastIndexOf(' ') + 1) + "__");
if (null == target_layer)
return;
duplicateLinkAndSendTo(active, 0, target_layer);
} else if (-1 != command.indexOf("z=")) {
// WARNING the indexOf is very similar to the previous one
// Send the linked group to the selected layer
final int iz = command.indexOf("z=") + 2;
Utils.log2("iz=" + iz + " other: " + command.indexOf(' ', iz + 2));
int end = command.indexOf(' ', iz);
if (-1 == end)
end = command.length();
final double lz = Double.parseDouble(command.substring(iz, end));
final Layer target = layer.getParent().getLayer(lz);
// TODO what happens when ZDisplayable are selected?
layer.getParent().move(selection.getAffected(), active.getLayer(), target);
} else if (command.equals("Unlink")) {
if (null == active || active instanceof Patch)
return;
active.unlink();
// selection.update();
updateSelection();
} else if (command.equals("Unlink from images")) {
if (null == active)
return;
try {
for (final Displayable displ : selection.getSelected()) {
displ.unlinkAll(Patch.class);
}
// selection.update();
updateSelection();
} catch (final Exception e) {
IJError.print(e);
}
} else if (command.equals("Unlink slices")) {
final YesNoCancelDialog yn = new YesNoCancelDialog(frame, "Attention", "Really unlink all slices from each other?\nThere is no undo.");
if (!yn.yesPressed())
return;
final ArrayList<Patch> pa = ((Patch) active).getStackPatches();
for (int i = pa.size() - 1; i > 0; i--) {
pa.get(i).unlink(pa.get(i - 1));
}
} else if (command.equals("Send to next layer")) {
final Rectangle box = selection.getBox();
try {
// unlink Patch instances
for (final Displayable displ : selection.getSelected()) {
displ.unlinkAll(Patch.class);
}
// selection.update();
updateSelection();
} catch (final Exception e) {
IJError.print(e);
}
// layer.getParent().moveDown(layer, active); // will repaint whatever appropriate layers
selection.moveDown();
repaint(layer.getParent(), box);
} else if (command.equals("Send to previous layer")) {
final Rectangle box = selection.getBox();
try {
// unlink Patch instances
for (final Displayable displ : selection.getSelected()) {
displ.unlinkAll(Patch.class);
}
// selection.update();
updateSelection();
} catch (final Exception e) {
IJError.print(e);
}
// layer.getParent().moveUp(layer, active); // will repaint whatever appropriate layers
selection.moveUp();
repaint(layer.getParent(), box);
} else if (command.equals("Show centered")) {
if (active == null)
return;
showCentered(active);
} else if (command.equals("Delete...")) {
// remove all selected objects
selection.deleteAll();
} else if (command.equals("Color...")) {
IJ.doCommand("Color Picker...");
} else if (command.equals("Revert")) {
if (null == active || active.getClass() != Patch.class)
return;
final Patch p = (Patch) active;
if (!p.revert()) {
if (null == p.getOriginalPath())
Utils.log("No editions to save for patch " + p.getTitle() + " #" + p.getId());
else
Utils.log("Could not revert Patch " + p.getTitle() + " #" + p.getId());
}
} else if (command.equals("Remove alpha mask")) {
Display.removeAlphaMasks(selection.get(Patch.class));
} else if (command.equals("Undo")) {
Bureaucrat.createAndStart(new Worker.Task("Undo") {
@Override
public void exec() {
layer.getParent().undoOneStep();
Display.repaint(layer.getParent());
}
}, project);
} else if (command.equals("Redo")) {
Bureaucrat.createAndStart(new Worker.Task("Redo") {
@Override
public void exec() {
layer.getParent().redoOneStep();
Display.repaint(layer.getParent());
}
}, project);
} else if (command.equals("Apply transform")) {
canvas.applyTransform();
} else if (command.equals("Apply transform propagating to last layer")) {
if (mode.getClass() == AffineTransformMode.class || mode.getClass() == NonLinearTransformMode.class) {
final LayerSet ls = getLayerSet();
// +1 to exclude current layer
final HashSet<Layer> subset = new HashSet<Layer>(ls.getLayers(ls.indexOf(Display.this.layer) + 1, ls.size() - 1));
if (mode.getClass() == AffineTransformMode.class)
((AffineTransformMode) mode).applyAndPropagate(subset);
else if (mode.getClass() == NonLinearTransformMode.class)
((NonLinearTransformMode) mode).apply(subset);
setMode(new DefaultMode(Display.this));
}
} else if (command.equals("Apply transform propagating to first layer")) {
if (mode.getClass() == AffineTransformMode.class || mode.getClass() == NonLinearTransformMode.class) {
final LayerSet ls = getLayerSet();
// -1 to exclude current layer
final HashSet<Layer> subset = new HashSet<Layer>(ls.getLayers(0, ls.indexOf(Display.this.layer) - 1));
if (mode.getClass() == AffineTransformMode.class)
((AffineTransformMode) mode).applyAndPropagate(subset);
else if (mode.getClass() == NonLinearTransformMode.class)
((NonLinearTransformMode) mode).apply(subset);
setMode(new DefaultMode(Display.this));
}
} else if (command.equals("Cancel transform")) {
// calls getMode().cancel()
canvas.cancelTransform();
} else if (command.equals("Specify transform...")) {
if (null == active)
return;
selection.specify();
} else if (command.equals("Exit inspection")) {
getMode().cancel();
setMode(new DefaultMode(Display.this));
} else if (command.equals("Inspect image mesh triangles")) {
setMode(new InspectPatchTrianglesMode(Display.this));
} else if (command.equals("Hide all but images")) {
final ArrayList<Class<?>> type = new ArrayList<Class<?>>();
type.add(Patch.class);
type.add(Stack.class);
final Collection<Displayable> col = layer.getParent().hideExcept(type, false);
selection.removeAll(col);
Display.updateCheckboxes(col, DisplayablePanel.VISIBILITY_STATE);
Display.update(layer.getParent(), false);
} else if (command.equals("Unhide all")) {
Display.updateCheckboxes(layer.getParent().setAllVisible(false), DisplayablePanel.VISIBILITY_STATE);
Display.update(layer.getParent(), false);
} else if (command.startsWith("Hide all ")) {
// skip the ending plural 's'
final String type = command.substring(9, command.length() - 1);
final Collection<Displayable> col = layer.getParent().setVisible(type, false, true);
selection.removeAll(col);
Display.updateCheckboxes(col, DisplayablePanel.VISIBILITY_STATE);
} else if (command.startsWith("Unhide all ")) {
// skip the ending plural 's'
String type = command.substring(11, command.length() - 1);
type = type.substring(0, 1).toUpperCase() + type.substring(1);
updateCheckboxes(layer.getParent().setVisible(type, true, true), DisplayablePanel.VISIBILITY_STATE);
} else if (command.equals("Hide deselected")) {
hideDeselected(0 != (ActionEvent.ALT_MASK & ae.getModifiers()));
} else if (command.equals("Hide deselected except images")) {
hideDeselected(true);
} else if (command.equals("Hide selected")) {
// TODO should deselect them too? I don't think so.
selection.setVisible(false);
Display.updateCheckboxes(selection.getSelected(), DisplayablePanel.VISIBILITY_STATE);
} else if (command.equals("Resize canvas/LayerSet...")) {
resizeCanvas();
} else if (command.equals("Autoresize canvas/LayerSet")) {
layer.getParent().setMinimumDimensions();
} else if (command.equals("Resize canvas/LayerSet to ROI")) {
final Roi roi = canvas.getFakeImagePlus().getRoi();
if (null == roi) {
Utils.log("No ROI present!");
return;
}
resizeCanvas(roi.getBounds());
} else if (command.equals("Import image")) {
importImage();
} else if (command.equals("Import next image")) {
importNextImage();
} else if (command.equals("Import stack...")) {
Display.this.getLayerSet().addChangeTreesStep();
final Rectangle sr = getCanvas().getSrcRect();
final Bureaucrat burro = project.getLoader().importStack(layer, sr.x + sr.width / 2, sr.y + sr.height / 2, null, true, null, false);
burro.addPostTask(new Runnable() {
@Override
public void run() {
Display.this.getLayerSet().addChangeTreesStep();
}
});
} else if (command.equals("Import stack with landmarks...")) {
// 1 - Find out if there's any other project open
final List<Project> pr = Project.getProjects();
if (1 == pr.size()) {
Utils.logAll("Need another project open!");
return;
}
// 2 - Ask for a "landmarks" type
final GenericDialog gd = new GenericDialog("Landmarks");
gd.addStringField("landmarks type:", "landmarks");
final String[] none = { "-- None --" };
final Hashtable<String, Project> mpr = new Hashtable<String, Project>();
for (final Project p : pr) {
if (p == project)
continue;
mpr.put(p.toString(), p);
}
final String[] project_titles = mpr.keySet().toArray(new String[0]);
final Hashtable<String, ProjectThing> map_target = findLandmarkNodes(project, "landmarks");
final String[] target_landmark_titles = map_target.isEmpty() ? none : map_target.keySet().toArray(new String[0]);
gd.addChoice("Landmarks node in this project:", target_landmark_titles, target_landmark_titles[0]);
gd.addMessage("");
gd.addChoice("Source project:", project_titles, project_titles[0]);
final Hashtable<String, ProjectThing> map_source = findLandmarkNodes(mpr.get(project_titles[0]), "landmarks");
final String[] source_landmark_titles = map_source.isEmpty() ? none : map_source.keySet().toArray(new String[0]);
gd.addChoice("Landmarks node in source project:", source_landmark_titles, source_landmark_titles[0]);
final List<Patch> stacks = Display.getPatchStacks(mpr.get(project_titles[0]).getRootLayerSet());
String[] stack_titles;
if (stacks.isEmpty()) {
if (1 == mpr.size()) {
IJ.showMessage("Project " + project_titles[0] + " does not contain any Stack.");
return;
}
stack_titles = none;
} else {
stack_titles = new String[stacks.size()];
int next = 0;
for (final Patch pa : stacks) stack_titles[next++] = pa.toString();
}
gd.addChoice("Stacks:", stack_titles, stack_titles[0]);
final Vector<?> vc = gd.getChoices();
final Choice choice_target_landmarks = (Choice) vc.get(0);
final Choice choice_source_projects = (Choice) vc.get(1);
final Choice choice_source_landmarks = (Choice) vc.get(2);
final Choice choice_stacks = (Choice) vc.get(3);
final TextField input = (TextField) gd.getStringFields().get(0);
input.addTextListener(new TextListener() {
@Override
public void textValueChanged(final TextEvent te) {
final String text = input.getText();
update(choice_target_landmarks, Display.this.project, text, map_target);
update(choice_source_landmarks, mpr.get(choice_source_projects.getSelectedItem()), text, map_source);
}
private void update(final Choice c, final Project p, final String type, final Hashtable<String, ProjectThing> table) {
table.clear();
table.putAll(findLandmarkNodes(p, type));
c.removeAll();
if (table.isEmpty())
c.add(none[0]);
else
for (final String t : table.keySet()) c.add(t);
}
});
choice_source_projects.addItemListener(new ItemListener() {
@Override
public void itemStateChanged(final ItemEvent e) {
final String item = (String) e.getItem();
final Project p = mpr.get(choice_source_projects.getSelectedItem());
// 1 - Update choice of landmark items
map_source.clear();
map_source.putAll(findLandmarkNodes(p, input.getText()));
choice_target_landmarks.removeAll();
if (map_source.isEmpty())
choice_target_landmarks.add(none[0]);
else
for (final String t : map_source.keySet()) choice_target_landmarks.add(t);
// 2 - Update choice of Stack items
stacks.clear();
choice_stacks.removeAll();
stacks.addAll(Display.getPatchStacks(mpr.get(project_titles[0]).getRootLayerSet()));
if (stacks.isEmpty())
choice_stacks.add(none[0]);
else
for (final Patch pa : stacks) choice_stacks.add(pa.toString());
}
});
gd.showDialog();
if (gd.wasCanceled())
return;
final String type = gd.getNextString();
if (null == type || 0 == type.trim().length()) {
Utils.log("Invalid landmarks node type!");
return;
}
final ProjectThing target_landmarks_node = map_target.get(gd.getNextChoice());
final Project source = mpr.get(gd.getNextChoice());
final ProjectThing source_landmarks_node = map_source.get(gd.getNextChoice());
final Patch stack_patch = stacks.get(gd.getNextChoiceIndex());
// Store current state
Display.this.getLayerSet().addLayerContentStep(layer);
// Insert stack
insertStack(target_landmarks_node, source, source_landmarks_node, stack_patch);
// Store new state
Display.this.getLayerSet().addChangeTreesStep();
} else if (command.equals("Import grid...")) {
Display.this.getLayerSet().addLayerContentStep(layer);
final Bureaucrat burro = project.getLoader().importGrid(layer);
if (null != burro)
burro.addPostTask(new Runnable() {
@Override
public void run() {
Display.this.getLayerSet().addLayerContentStep(layer);
}
});
} else if (command.equals("Import sequence as grid...")) {
Display.this.getLayerSet().addChangeTreesStep();
final Bureaucrat burro = project.getLoader().importSequenceAsGrid(layer);
if (null != burro)
burro.addPostTask(new Runnable() {
@Override
public void run() {
Display.this.getLayerSet().addChangeTreesStep();
}
});
} else if (command.equals("Import from text file...")) {
Display.this.getLayerSet().addChangeTreesStep();
final Bureaucrat burro = project.getLoader().importImages(layer);
if (null != burro)
burro.addPostTask(new Runnable() {
@Override
public void run() {
Display.this.getLayerSet().addChangeTreesStep();
}
});
} else if (command.equals("Import labels as arealists...")) {
Display.this.getLayerSet().addChangeTreesStep();
final Bureaucrat burro = project.getLoader().importLabelsAsAreaLists(layer, null, Double.MAX_VALUE, 0, 0.4f, false);
burro.addPostTask(new Runnable() {
@Override
public void run() {
Display.this.getLayerSet().addChangeTreesStep();
}
});
} else if (command.equals("Make flat image...")) {
// if there's a ROI, just use that as cropping rectangle
Rectangle srcRect = null;
final Roi roi = canvas.getFakeImagePlus().getRoi();
if (null != roi) {
srcRect = roi.getBounds();
} else {
// otherwise, whatever is visible
// srcRect = canvas.getSrcRect();
// The above is confusing. That is what ROIs are for. So paint all:
srcRect = new Rectangle(0, 0, (int) Math.ceil(layer.getParent().getLayerWidth()), (int) Math.ceil(layer.getParent().getLayerHeight()));
}
double scale = 1.0;
final String[] types = new String[] { "8-bit grayscale", "RGB Color" };
int the_type = ImagePlus.GRAY8;
final GenericDialog gd = new GenericDialog("Choose", frame);
gd.addSlider("Scale: ", 1, 100, 100);
gd.addNumericField("Width: ", srcRect.width, 0);
gd.addNumericField("height: ", srcRect.height, 0);
// connect the above 3 fields:
final Vector<?> numfields = gd.getNumericFields();
final UpdateDimensionField udf = new UpdateDimensionField(srcRect.width, srcRect.height, (TextField) numfields.get(1), (TextField) numfields.get(2), (TextField) numfields.get(0), (Scrollbar) gd.getSliders().get(0));
for (final Object ob : numfields) ((TextField) ob).addTextListener(udf);
gd.addChoice("Type: ", types, types[0]);
if (layer.getParent().size() > 1) {
// / $#%! where are my lisp macros
Utils.addLayerRangeChoices(Display.this.layer, gd);
gd.addCheckbox("Include non-empty layers only", true);
}
gd.addMessage("Background color:");
Utils.addRGBColorSliders(gd, Color.black);
gd.addCheckbox("Best quality", false);
gd.addMessage("");
final String[] choices = new String[] { "Show", "Save to file", "Save for web (CATMAID)" };
gd.addChoice("Export:", choices, choices[0]);
final String[] formats = Saver.formats();
gd.addChoice("Format:", formats, formats[0]);
gd.addNumericField("Tile_side", 256, 0);
final Choice cformats = (Choice) gd.getChoices().get(gd.getChoices().size() - 1);
cformats.setEnabled(false);
final Choice cchoices = (Choice) gd.getChoices().get(gd.getChoices().size() - 2);
final TextField tf = (TextField) gd.getNumericFields().get(gd.getNumericFields().size() - 1);
tf.setEnabled(false);
cchoices.addItemListener(new ItemListener() {
@Override
public void itemStateChanged(final ItemEvent e) {
cformats.setEnabled(cchoices.getSelectedIndex() > 0);
if (2 == cchoices.getSelectedIndex()) {
cformats.select(".jpg");
tf.setEnabled(true);
} else {
tf.setEnabled(false);
}
}
});
gd.addCheckbox("Use original images", true);
gd.showDialog();
if (gd.wasCanceled())
return;
scale = gd.getNextNumber() / 100;
the_type = (0 == gd.getNextChoiceIndex() ? ImagePlus.GRAY8 : ImagePlus.COLOR_RGB);
if (Double.isNaN(scale) || scale <= 0.0) {
Utils.showMessage("Invalid scale.");
return;
}
// consuming and ignoring width and height:
gd.getNextNumber();
gd.getNextNumber();
Layer[] layer_array = null;
boolean non_empty_only = false;
if (layer.getParent().size() > 1) {
non_empty_only = gd.getNextBoolean();
final int i_start = gd.getNextChoiceIndex();
final int i_end = gd.getNextChoiceIndex();
final ArrayList<Layer> al = new ArrayList<Layer>();
final ArrayList<ZDisplayable> al_zd = layer.getParent().getZDisplayables();
final ZDisplayable[] zd = new ZDisplayable[al_zd.size()];
al_zd.toArray(zd);
for (int i = i_start, j = 0; i <= i_end; i++, j++) {
final Layer la = layer.getParent().getLayer(i);
// checks both the Layer and the ZDisplayable objects in the parent LayerSet
if (!la.isEmpty() || !non_empty_only)
al.add(la);
}
if (0 == al.size()) {
Utils.showMessage("All layers are empty!");
return;
}
layer_array = new Layer[al.size()];
al.toArray(layer_array);
} else {
layer_array = new Layer[] { Display.this.layer };
}
final Color background = new Color((int) gd.getNextNumber(), (int) gd.getNextNumber(), (int) gd.getNextNumber());
final boolean quality = gd.getNextBoolean();
final int choice = gd.getNextChoiceIndex();
final boolean save_to_file = 1 == choice;
final boolean save_for_web = 2 == choice;
final String format = gd.getNextChoice();
final Saver saver = new Saver(format);
final int tile_side = (int) gd.getNextNumber();
final boolean use_original_images = gd.getNextBoolean();
// in its own thread
if (save_for_web)
project.getLoader().makePrescaledTiles(layer_array, Patch.class, srcRect, scale, c_alphas, the_type, null, use_original_images, saver, tile_side);
else
project.getLoader().makeFlatImage(layer_array, srcRect, scale, c_alphas, the_type, save_to_file, format, quality, background);
} else if (command.equals("Lock")) {
selection.setLocked(true);
Utils.revalidateComponent(tabs.getSelectedComponent());
} else if (command.equals("Unlock")) {
selection.setLocked(false);
Utils.revalidateComponent(tabs.getSelectedComponent());
} else if (command.equals("Properties...")) {
switch(selection.getSelected().size()) {
case 0:
return;
case 1:
active.adjustProperties();
break;
default:
adjustGroupProperties(selection.getSelected());
break;
}
updateSelection();
} else if (command.equals("Measurement options...")) {
adjustMeasurementOptions();
} else if (command.equals("Show current 2D position in 3D")) {
final Point p = canvas.consumeLastPopupPoint();
if (null == p)
return;
Display3D.addFatPoint("Current 2D Position", getLayerSet(), p.x, p.y, layer.getZ(), 10, Color.magenta);
} else if (command.equals("Show layers as orthoslices in 3D")) {
final GenericDialog gd = new GenericDialog("Options");
final Roi roi = canvas.getFakeImagePlus().getRoi();
final Rectangle r = null == roi ? getLayerSet().get2DBounds() : roi.getBounds();
gd.addMessage("ROI 2D bounds:");
gd.addNumericField("x:", r.x, 0, 30, "pixels");
gd.addNumericField("y:", r.y, 0, 30, "pixels");
gd.addNumericField("width:", r.width, 0, 30, "pixels");
gd.addNumericField("height:", r.height, 0, 30, "pixels");
gd.addMessage("Layers to include:");
Utils.addLayerRangeChoices(layer, gd);
gd.addMessage("Constrain dimensions to:");
gd.addNumericField("max width and height:", getLayerSet().getPixelsMaxDimension(), 0, 30, "pixels");
gd.addMessage("Options:");
final String[] types = { "Greyscale", "Color RGB" };
gd.addChoice("Image type:", types, types[0]);
gd.addCheckbox("Invert images", false);
gd.showDialog();
if (gd.wasCanceled())
return;
final int x = (int) gd.getNextNumber(), y = (int) gd.getNextNumber(), width = (int) gd.getNextNumber(), height = (int) gd.getNextNumber();
final int first = gd.getNextChoiceIndex(), last = gd.getNextChoiceIndex();
final List<Layer> layers = getLayerSet().getLayers(first, last);
final int max_dim = Math.min((int) gd.getNextNumber(), Math.max(width, height));
float scale = 1;
if (max_dim < Math.max(width, height)) {
scale = max_dim / (float) Math.max(width, height);
}
final int type = 0 == gd.getNextChoiceIndex() ? ImagePlus.GRAY8 : ImagePlus.COLOR_RGB;
final boolean invert = gd.getNextBoolean();
final LayerStack stack = new LayerStack(layers, new Rectangle(x, y, width, height), scale, type, Patch.class, max_dim, invert);
Display3D.showOrthoslices(stack.getImagePlus(), "LayerSet [" + x + "," + y + "," + width + "," + height + "] " + first + "--" + last, x, y, scale, layers.get(0));
} else if (command.equals("Align stack slices")) {
if (getActive() instanceof Patch) {
final Patch slice = (Patch) getActive();
if (slice.isStack()) {
// check linked group
final HashSet hs = slice.getLinkedGroup(new HashSet());
for (final Iterator it = hs.iterator(); it.hasNext(); ) {
if (it.next().getClass() != Patch.class) {
// labels should be fine, need to check that
Utils.showMessage("Images are linked to other objects, can't proceed to cross-correlate them.");
return;
}
}
final LayerSet ls = slice.getLayerSet();
final HashSet<Displayable> linked = slice.getLinkedGroup(null);
ls.addTransformStepWithData(linked);
// will repaint
final Bureaucrat burro = AlignTask.registerStackSlices((Patch) getActive());
burro.addPostTask(new Runnable() {
@Override
public void run() {
ls.enlargeToFit(linked);
// The current state when done
ls.addTransformStepWithData(linked);
}
});
} else {
Utils.log("Align stack slices: selected image is not part of a stack.");
}
}
} else if (command.equals("Align layers manually with landmarks")) {
setMode(new ManualAlignMode(Display.this));
} else if (command.equals("Align layers")) {
Roi roi = canvas.getFakeImagePlus().getRoi();
if (null != roi) {
final YesNoCancelDialog yn = new YesNoCancelDialog(frame, "Use ROI?", "Snapshot layers using the ROI bounds?\n" + roi.getBounds());
if (yn.cancelPressed())
return;
if (!yn.yesPressed()) {
roi = null;
}
}
// caching, since scroll wheel may change it
final Layer la = layer;
la.getParent().addTransformStep(la.getParent().getLayers());
final Bureaucrat burro = AlignLayersTask.alignLayersTask(la, null == roi ? null : roi.getBounds());
burro.addPostTask(new Runnable() {
@Override
public void run() {
getLayerSet().enlargeToFit(getLayerSet().getDisplayables(Patch.class));
la.getParent().addTransformStep(la.getParent().getLayers());
}
});
} else if (command.equals("Align multi-layer mosaic")) {
// caching, since scroll wheel may change it
final Layer la = layer;
la.getParent().addTransformStep();
final Bureaucrat burro = AlignTask.alignMultiLayerMosaicTask(la, active instanceof Patch ? (Patch) active : null);
burro.addPostTask(new Runnable() {
@Override
public void run() {
getLayerSet().enlargeToFit(getLayerSet().getDisplayables(Patch.class));
la.getParent().addTransformStep();
}
});
} else if (command.equals("Montage all images in this layer")) {
final Layer la = layer;
final List<Patch> patches = new ArrayList<Patch>((List<Patch>) (List) la.getDisplayables(Patch.class, true));
if (patches.size() < 2) {
Utils.showMessage("Montage needs 2 or more visible images");
return;
}
final Collection<Displayable> col = la.getParent().addTransformStepWithDataForAll(Arrays.asList(new Layer[] { la }));
// find any locked or selected patches
final HashSet<Patch> fixed = new HashSet<Patch>();
for (final Patch p : patches) {
if (p.isLocked2() || selection.contains(p))
fixed.add(p);
}
if (patches.size() == fixed.size()) {
Utils.showMessage("Can't do", "No montage possible: all images are selected,\nand hence all are considered locked.\nSelect only one image to be used as reference, or none.");
return;
}
Utils.log("Using " + fixed.size() + " image" + (fixed.size() == 1 ? "" : "s") + " as reference.");
final Bureaucrat burro = AlignTask.alignPatchesTask(patches, fixed);
burro.addPostTask(new Runnable() {
@Override
public void run() {
getLayerSet().enlargeToFit(patches);
la.getParent().addTransformStepWithData(col);
}
});
} else if (command.equals("Montage selected images")) {
final Layer la = layer;
if (selection.getSelected(Patch.class).size() < 2) {
Utils.showMessage("Montage needs 2 or more images selected");
return;
}
final Collection<Displayable> col = la.getParent().addTransformStepWithDataForAll(Arrays.asList(new Layer[] { la }));
final Bureaucrat burro = AlignTask.alignSelectionTask(selection);
if (null == burro)
return;
burro.addPostTask(new Runnable() {
@Override
public void run() {
la.getParent().enlargeToFit(selection.getAffected());
la.getParent().addTransformStepWithData(col);
}
});
} else if (command.equals("Montage multiple layers")) {
final GenericDialog gd = new GenericDialog("Choose range");
Utils.addLayerRangeChoices(Display.this.layer, gd);
gd.showDialog();
if (gd.wasCanceled())
return;
final List<Layer> layers = getLayerSet().getLayers(gd.getNextChoiceIndex(), gd.getNextChoiceIndex());
final Collection<Displayable> col = getLayerSet().addTransformStepWithDataForAll(layers);
final Bureaucrat burro = AlignTask.montageLayersTask(layers);
burro.addPostTask(new Runnable() {
@Override
public void run() {
final Collection<Displayable> ds = new ArrayList<Displayable>();
for (final Layer la : layers) ds.addAll(la.getDisplayables(Patch.class));
getLayerSet().enlargeToFit(ds);
getLayerSet().addTransformStepWithData(col);
}
});
} else if (command.equals("Properties ...")) {
// NOTE the space before the dots, to distinguish from the "Properties..." command that works on Displayable objects.
adjustProperties();
} else if (command.equals("Adjust snapping parameters...")) {
AlignTask.p_snap.setup("Snap");
} else if (command.equals("Adjust fast-marching parameters...")) {
Segmentation.fmp.setup();
} else if (command.equals("Adjust arealist paint parameters...")) {
AreaWrapper.PP.setup();
} else if (command.equals("Fill ROI in alpha mask")) {
if (active.getClass() == Patch.class) {
((Patch) active).keyPressed(new KeyEvent(getCanvas(), -1, System.currentTimeMillis(), 0, KeyEvent.VK_F, 'f'));
}
} else if (command.equals("Fill inverse ROI in alpha mask")) {
if (active.getClass() == Patch.class) {
((Patch) active).keyPressed(new KeyEvent(getCanvas(), -1, System.currentTimeMillis(), Event.SHIFT_MASK, KeyEvent.VK_F, 'f'));
}
} else if (command.equals("Search...")) {
Search.showWindow();
} else if (command.equals("Select all")) {
selection.selectAll();
repaint(Display.this.layer, selection.getBox(), 0);
} else if (command.equals("Select all visible")) {
selection.selectAllVisible();
repaint(Display.this.layer, selection.getBox(), 0);
} else if (command.equals("Select all that match...")) {
final List<Displayable> ds = find();
selection.selectAll(ds);
Utils.showStatus("Added " + ds.size() + " to selection.");
} else if (command.equals("Select none")) {
final Rectangle box = selection.getBox();
selection.clear();
repaint(Display.this.layer, box, 0);
} else if (command.equals("Restore selection")) {
selection.restore();
} else if (command.equals("Select under ROI")) {
final Roi roi = canvas.getFakeImagePlus().getRoi();
if (null == roi)
return;
selection.selectAll(roi, true);
} else if (command.equals("Merge") || command.equals("Split")) {
final Bureaucrat burro = Bureaucrat.create(new Worker.Task(command + "ing AreaLists") {
@Override
public void exec() {
final ArrayList<Displayable> al_sel = selection.getSelected(AreaList.class);
// put active at the beginning, to work as the base on which other's will get merged
al_sel.remove(Display.this.active);
al_sel.add(0, Display.this.active);
final Set<DoStep> dataedits = new HashSet<DoStep>();
if (command.equals("Merge")) {
// Add data undo for active only, which will be edited
dataedits.add(new Displayable.DoEdit(Display.this.active).init(Display.this.active, new String[] { "data" }));
getLayerSet().addChangeTreesStep(dataedits);
final AreaList ali = AreaList.merge(al_sel);
if (null != ali) {
// remove all but the first from the selection
for (int i = 1; i < al_sel.size(); i++) {
final Object ob = al_sel.get(i);
if (ob.getClass() == AreaList.class) {
selection.remove((Displayable) ob);
}
}
selection.updateTransform(ali);
repaint(ali.getLayerSet(), ali, 0);
}
} else if (command.equals("Split")) {
// Add data undo for every AreaList
for (final Displayable d : al_sel) {
if (d.getClass() != AreaList.class)
continue;
dataedits.add(new Displayable.DoEdit(d).init(d, new String[] { "data" }));
}
getLayerSet().addChangeTreesStep(dataedits);
try {
List<AreaList> alis = AreaList.split(al_sel);
for (AreaList ali : alis) {
if (selection.contains(ali))
continue;
selection.add(ali);
}
} catch (Exception e) {
IJError.print(e);
getLayerSet().undoOneStep();
}
}
}
}, Display.this.project);
burro.addPostTask(new Runnable() {
@Override
public void run() {
final Set<DoStep> dataedits = new HashSet<DoStep>();
dataedits.add(new Displayable.DoEdit(Display.this.active).init(Display.this.active, new String[] { "data" }));
getLayerSet().addChangeTreesStep(dataedits);
}
});
burro.goHaveBreakfast();
} else if (command.equals("Reroot")) {
if (!(active instanceof Tree<?>))
return;
getLayerSet().addDataEditStep(active);
if (((Tree) active).reRoot(((Tree) active).getLastVisited())) {
getLayerSet().addDataEditStep(active);
Display.repaint(getLayerSet());
} else {
getLayerSet().removeLastUndoStep();
}
} else if (command.equals("Part subtree")) {
if (!(active instanceof Tree<?>))
return;
if (!Utils.check("Really part the subtree?"))
return;
final LayerSet.DoChangeTrees step = getLayerSet().addChangeTreesStep();
final Set<DoStep> deps = new HashSet<DoStep>();
// I hate java
deps.add(new Displayable.DoEdit(active).init(active, new String[] { "data" }));
step.addDependents(deps);
final List<ZDisplayable> ts = ((Tree) active).splitAt(((Tree) active).getLastVisited());
if (null == ts) {
getLayerSet().removeLastUndoStep();
return;
}
final Displayable elder = Display.this.active;
final HashSet<DoStep> deps2 = new HashSet<DoStep>();
for (final ZDisplayable t : ts) {
deps2.add(new Displayable.DoEdit(t).init(t, new String[] { "data" }));
if (t == elder)
continue;
// will change Display.this.active !
getLayerSet().add(t);
project.getProjectTree().addSibling(elder, t);
}
selection.clear();
selection.selectAll(ts);
selection.add(elder);
final LayerSet.DoChangeTrees step2 = getLayerSet().addChangeTreesStep();
step2.addDependents(deps2);
Display.repaint(getLayerSet());
} else if (command.equals("Show tabular view")) {
if (!(active instanceof Tree<?>))
return;
((Tree<?>) active).createMultiTableView();
} else if (command.equals("Mark")) {
if (!(active instanceof Tree<?>))
return;
final Point p = canvas.consumeLastPopupPoint();
if (null == p)
return;
if (((Tree<?>) active).markNear(p.x, p.y, layer, canvas.getMagnification())) {
Display.repaint(getLayerSet());
}
} else if (command.equals("Clear marks (selected Trees)")) {
for (final Tree<?> t : selection.get(Tree.class)) {
t.unmark();
}
Display.repaint(getLayerSet());
} else if (command.equals("Join")) {
if (!(active instanceof Tree<?>))
return;
final List<Tree<?>> tlines = (List<Tree<?>>) selection.get(active.getClass());
if (((Tree) active).canJoin(tlines)) {
final int nNodes_active = ((Tree) active).getRoot().getSubtreeNodes().size();
String warning = "";
for (final Tree<?> t : tlines) {
if (active == t)
continue;
if (null == t.getRoot()) {
Utils.log("Removed empty tree #" + t.getId() + " from those to join.");
tlines.remove(t);
continue;
}
if (t.getRoot().getSubtreeNodes().size() > nNodes_active) {
warning = "\nWARNING joining into a tree that is not the largest!";
break;
}
}
if (!Utils.check("Join these " + tlines.size() + " trees into the tree " + active + " ?" + warning))
return;
// Record current state
final Set<DoStep> dataedits = new HashSet<DoStep>(tlines.size());
for (final Tree<?> tl : tlines) {
dataedits.add(new Displayable.DoEdit(tl).init(tl, new String[] { "data" }));
}
getLayerSet().addChangeTreesStep(dataedits);
//
((Tree) active).join(tlines);
for (final Tree<?> tl : tlines) {
if (tl == active)
continue;
tl.remove2(false);
}
Display.repaint(getLayerSet());
// Again, to record current state (just the joined tree this time)
final Set<DoStep> dataedits2 = new HashSet<DoStep>(1);
dataedits2.add(new Displayable.DoEdit(active).init(active, new String[] { "data" }));
getLayerSet().addChangeTreesStep(dataedits2);
} else {
Utils.showMessage("Can't do", "Only one tree is selected.\nSelect more than one tree to perform a join operation!");
}
} else if (command.equals("Previous branch node or start")) {
if (!(active instanceof Tree<?>))
return;
final Point p = canvas.consumeLastPopupPoint();
if (null == p)
return;
center(((Treeline) active).findPreviousBranchOrRootPoint(p.x, p.y, layer, canvas));
} else if (command.equals("Next branch node or end")) {
if (!(active instanceof Tree<?>))
return;
final Point p = canvas.consumeLastPopupPoint();
if (null == p)
return;
center(((Tree<?>) active).findNextBranchOrEndPoint(p.x, p.y, layer, canvas));
} else if (command.equals("Root")) {
if (!(active instanceof Tree<?>))
return;
final Point p = canvas.consumeLastPopupPoint();
if (null == p)
return;
center(((Tree) active).createCoordinate(((Tree<?>) active).getRoot()));
} else if (command.equals("Last added node")) {
if (!(active instanceof Tree<?>))
return;
center(((Treeline) active).getLastAdded());
} else if (command.equals("Last edited node")) {
if (!(active instanceof Tree<?>))
return;
center(((Treeline) active).getLastEdited());
} else if (command.equals("Reverse point order")) {
if (!(active instanceof Pipe))
return;
getLayerSet().addDataEditStep(active);
((Pipe) active).reverse();
Display.repaint(Display.this.layer);
getLayerSet().addDataEditStep(active);
} else if (command.equals("View orthoslices")) {
if (!(active instanceof Patch))
return;
Display3D.showOrthoslices(((Patch) active));
} else if (command.equals("View volume")) {
if (!(active instanceof Patch))
return;
Display3D.showVolume(((Patch) active));
} else if (command.equals("Show in 3D")) {
for (final ZDisplayable zd : selection.get(ZDisplayable.class)) {
Display3D.show(zd.getProject().findProjectThing(zd));
}
// handle profile lists ...
final HashSet<ProjectThing> hs = new HashSet<ProjectThing>();
for (final Profile d : selection.get(Profile.class)) {
final ProjectThing profile_list = (ProjectThing) d.getProject().findProjectThing(d).getParent();
if (!hs.contains(profile_list)) {
Display3D.show(profile_list);
hs.add(profile_list);
}
}
} else if (command.equals("Snap")) {
// Take the active if it's a Patch
if (!(active instanceof Patch))
return;
Display.snap((Patch) active);
} else if (command.equals("Blend") || command.equals("Blend (selected images)...")) {
final HashSet<Patch> patches = new HashSet<Patch>(selection.get(Patch.class));
if (patches.size() > 1) {
final GenericDialog gd = new GenericDialog("Blending");
gd.addCheckbox("Respect current alpha mask", true);
gd.showDialog();
if (gd.wasCanceled())
return;
Blending.blend(patches, gd.getNextBoolean());
} else {
IJ.log("Please select more than one overlapping image.");
}
} else if (command.equals("Blend (layer-wise)...")) {
final GenericDialog gd = new GenericDialog("Blending");
Utils.addLayerRangeChoices(Display.this.layer, gd);
gd.addCheckbox("Respect current alpha mask", true);
gd.addMessage("Filter:");
gd.addStringField("Use only images whose title matches:", "", 30);
gd.addCheckbox("Blend visible patches only", true);
gd.showDialog();
if (gd.wasCanceled())
return;
final boolean respect_alpha_mask = gd.getNextBoolean();
final String toMatch = gd.getNextString().trim();
final String regex = 0 == toMatch.length() ? null : ".*" + toMatch + ".*";
final boolean visible_only = gd.getNextBoolean();
Blending.blendLayerWise(getLayerSet().getLayers(gd.getNextChoiceIndex(), gd.getNextChoiceIndex()), respect_alpha_mask, new Filter<Patch>() {
@Override
public final boolean accept(final Patch patch) {
if (visible_only && !patch.isVisible())
return false;
if (null == regex)
return true;
return patch.getTitle().matches(regex);
}
});
} else if (command.equals("Match intensities (layer-wise)...")) {
Bureaucrat.createAndStart(new Worker.Task("Match intensities") {
@Override
public void exec() {
final MatchIntensities matching = new MatchIntensities();
matching.invoke(getActive());
}
}, project);
} else if (command.equals("Remove intensity maps (layer-wise)...")) {
final GenericDialog gd = new GenericDialog("Remove intensity maps");
Utils.addLayerRangeChoices(Display.this.layer, gd);
gd.showDialog();
if (gd.wasCanceled())
return;
Bureaucrat.createAndStart(new Worker.Task("Match intensities") {
@Override
public void exec() {
for (final Layer layer : getLayerSet().getLayers(gd.getNextChoiceIndex(), gd.getNextChoiceIndex())) {
for (final Displayable p : layer.getDisplayables(Patch.class)) {
final Patch patch = (Patch) p;
if (patch.clearIntensityMap()) {
patch.updateMipMaps();
}
}
}
}
}, project);
} else if (command.equals("Montage")) {
final Set<Displayable> affected = new HashSet<Displayable>(selection.getAffected());
// make an undo step!
final LayerSet ls = layer.getParent();
ls.addTransformStepWithData(affected);
final Bureaucrat burro = AlignTask.alignSelectionTask(selection);
burro.addPostTask(new Runnable() {
@Override
public void run() {
ls.enlargeToFit(affected);
ls.addTransformStepWithData(affected);
}
});
} else if (command.equals("Lens correction")) {
final Layer la = layer;
la.getParent().addDataEditStep(new HashSet<Displayable>(la.getParent().getDisplayables()));
final Bureaucrat burro = DistortionCorrectionTask.correctDistortionFromSelection(selection);
burro.addPostTask(new Runnable() {
@Override
public void run() {
// no means to know which where modified and from which layers!
la.getParent().addDataEditStep(new HashSet<Displayable>(la.getParent().getDisplayables()));
}
});
} else if (command.equals("Link images...")) {
final GenericDialog gd = new GenericDialog("Options");
gd.addMessage("Linking images to images (within their own layer only):");
final String[] options = { "all images to all images", "each image with any other overlapping image" };
gd.addChoice("Link: ", options, options[1]);
final String[] options2 = { "selected images only", "all images in this layer", "all images in all layers, within the layer only", "all images in all layers, within and across consecutive layers" };
gd.addChoice("Apply to: ", options2, options2[0]);
gd.showDialog();
if (gd.wasCanceled())
return;
final Layer lay = layer;
final HashSet<Displayable> ds = new HashSet<Displayable>(lay.getParent().getDisplayables());
lay.getParent().addDataEditStep(ds, new String[] { "data" });
final boolean overlapping_only = 1 == gd.getNextChoiceIndex();
Collection<Displayable> coll = null;
switch(gd.getNextChoiceIndex()) {
case 0:
coll = selection.getSelected(Patch.class);
Patch.crosslink(coll, overlapping_only);
break;
case 1:
coll = lay.getDisplayables(Patch.class);
Patch.crosslink(coll, overlapping_only);
break;
case 2:
coll = new ArrayList<Displayable>();
for (final Layer la : lay.getParent().getLayers()) {
final Collection<Displayable> acoll = la.getDisplayables(Patch.class);
Patch.crosslink(acoll, overlapping_only);
coll.addAll(acoll);
}
break;
case 3:
final ArrayList<Layer> layers = lay.getParent().getLayers();
Collection<Displayable> lc1 = layers.get(0).getDisplayables(Patch.class);
if (lay == layers.get(0))
coll = lc1;
for (int i = 1; i < layers.size(); i++) {
final Collection<Displayable> lc2 = layers.get(i).getDisplayables(Patch.class);
if (null == coll && Display.this.layer == layers.get(i))
coll = lc2;
final Collection<Displayable> both = new ArrayList<Displayable>();
both.addAll(lc1);
both.addAll(lc2);
Patch.crosslink(both, overlapping_only);
lc1 = lc2;
}
break;
}
if (null != coll)
Display.updateCheckboxes(coll, DisplayablePanel.LINK_STATE, true);
lay.getParent().addDataEditStep(ds);
} else if (command.equals("Unlink all selected images")) {
if (Utils.check("Really unlink selected images?")) {
final Collection<Displayable> ds = selection.getSelected(Patch.class);
for (final Displayable d : ds) {
d.unlink();
}
Display.updateCheckboxes(ds, DisplayablePanel.LINK_STATE);
}
} else if (command.equals("Unlink all")) {
if (Utils.check("Really unlink all objects from all layers?")) {
final Collection<Displayable> ds = layer.getParent().getDisplayables();
for (final Displayable d : ds) {
d.unlink();
}
Display.updateCheckboxes(ds, DisplayablePanel.LINK_STATE);
}
} else if (command.equals("Calibration...")) {
try {
IJ.run(canvas.getFakeImagePlus(), "Properties...", "");
Display.updateTitle(getLayerSet());
// repaint layer names
project.getLayerTree().updateUILater();
} catch (final RuntimeException re) {
Utils.log2("Calibration dialog canceled.");
}
} else if (command.equals("Grid overlay...")) {
if (null == gridoverlay)
gridoverlay = new GridOverlay();
gridoverlay.setup(canvas.getFakeImagePlus().getRoi());
canvas.repaint(false);
} else if (command.equals("Enhance contrast (selected images)...")) {
final Layer la = layer;
final ArrayList<Displayable> selected = selection.getSelected(Patch.class);
final HashSet<Displayable> ds = new HashSet<Displayable>(selected);
la.getParent().addDataEditStep(ds);
final Displayable active = Display.this.getActive();
final Patch ref = active.getClass() == Patch.class ? (Patch) active : null;
final Bureaucrat burro = getProject().getLoader().enhanceContrast(selected, ref);
burro.addPostTask(new Runnable() {
@Override
public void run() {
la.getParent().addDataEditStep(ds);
}
});
} else if (command.equals("Enhance contrast layer-wise...")) {
// ask for range of layers
final GenericDialog gd = new GenericDialog("Choose range");
Utils.addLayerRangeChoices(Display.this.layer, gd);
gd.showDialog();
if (gd.wasCanceled())
return;
// exclusive end
final java.util.List<Layer> layers = layer.getParent().getLayers().subList(gd.getNextChoiceIndex(), gd.getNextChoiceIndex() + 1);
final HashSet<Displayable> ds = new HashSet<Displayable>();
for (final Layer l : layers) ds.addAll(l.getDisplayables(Patch.class));
getLayerSet().addDataEditStep(ds);
final Bureaucrat burro = project.getLoader().enhanceContrast(layers);
burro.addPostTask(new Runnable() {
@Override
public void run() {
getLayerSet().addDataEditStep(ds);
}
});
} else if (command.equals("Adjust image filters (selected images)")) {
if (selection.isEmpty() || !(active instanceof Patch))
return;
FilterEditor.GUI(selection.get(Patch.class), (Patch) active);
} else if (command.equals("Set Min and Max layer-wise...")) {
final Displayable active = getActive();
double min = 0;
double max = 0;
if (null != active && active.getClass() == Patch.class) {
min = ((Patch) active).getMin();
max = ((Patch) active).getMax();
}
final GenericDialog gd = new GenericDialog("Min and Max");
gd.addMessage("Set min and max to all images in the layer range");
Utils.addLayerRangeChoices(Display.this.layer, gd);
gd.addNumericField("min: ", min, 2);
gd.addNumericField("max: ", max, 2);
gd.showDialog();
if (gd.wasCanceled())
return;
//
min = gd.getNextNumber();
max = gd.getNextNumber();
final ArrayList<Displayable> al = new ArrayList<Displayable>();
for (final Layer la : layer.getParent().getLayers().subList(gd.getNextChoiceIndex(), gd.getNextChoiceIndex() + 1)) {
// exclusive end
al.addAll(la.getDisplayables(Patch.class));
}
final HashSet<Displayable> ds = new HashSet<Displayable>(al);
getLayerSet().addDataEditStep(ds);
final Bureaucrat burro = project.getLoader().setMinAndMax(al, min, max);
burro.addPostTask(new Runnable() {
@Override
public void run() {
getLayerSet().addDataEditStep(ds);
}
});
} else if (command.equals("Set Min and Max (selected images)...")) {
final Displayable active = getActive();
double min = 0;
double max = 0;
if (null != active && active.getClass() == Patch.class) {
min = ((Patch) active).getMin();
max = ((Patch) active).getMax();
}
final GenericDialog gd = new GenericDialog("Min and Max");
gd.addMessage("Set min and max to all selected images");
gd.addNumericField("min: ", min, 2);
gd.addNumericField("max: ", max, 2);
gd.showDialog();
if (gd.wasCanceled())
return;
//
min = gd.getNextNumber();
max = gd.getNextNumber();
final HashSet<Displayable> ds = new HashSet<Displayable>(selection.getSelected(Patch.class));
getLayerSet().addDataEditStep(ds);
final Bureaucrat burro = project.getLoader().setMinAndMax(selection.getSelected(Patch.class), min, max);
burro.addPostTask(new Runnable() {
@Override
public void run() {
getLayerSet().addDataEditStep(ds);
}
});
} else if (command.equals("Adjust min and max (selected images)...")) {
adjustMinAndMaxGUI();
} else if (command.equals("Mask image borders (layer-wise)...")) {
final GenericDialog gd = new GenericDialog("Mask borders");
Utils.addLayerRangeChoices(Display.this.layer, gd);
gd.addMessage("Borders:");
gd.addNumericField("left: ", 6, 2);
gd.addNumericField("top: ", 6, 2);
gd.addNumericField("right: ", 6, 2);
gd.addNumericField("bottom: ", 6, 2);
gd.showDialog();
if (gd.wasCanceled())
return;
final Collection<Layer> layers = layer.getParent().getLayers().subList(gd.getNextChoiceIndex(), gd.getNextChoiceIndex() + 1);
final HashSet<Displayable> ds = new HashSet<Displayable>();
for (final Layer l : layers) ds.addAll(l.getDisplayables(Patch.class));
getLayerSet().addDataEditStep(ds);
final Bureaucrat burro = project.getLoader().maskBordersLayerWise(layers, (int) gd.getNextNumber(), (int) gd.getNextNumber(), (int) gd.getNextNumber(), (int) gd.getNextNumber());
burro.addPostTask(new Runnable() {
@Override
public void run() {
getLayerSet().addDataEditStep(ds);
}
});
} else if (command.equals("Mask image borders (selected images)...")) {
final GenericDialog gd = new GenericDialog("Mask borders");
gd.addMessage("Borders:");
gd.addNumericField("left: ", 6, 2);
gd.addNumericField("top: ", 6, 2);
gd.addNumericField("right: ", 6, 2);
gd.addNumericField("bottom: ", 6, 2);
gd.showDialog();
if (gd.wasCanceled())
return;
final Collection<Displayable> patches = selection.getSelected(Patch.class);
final HashSet<Displayable> ds = new HashSet<Displayable>(patches);
getLayerSet().addDataEditStep(ds);
final Bureaucrat burro = project.getLoader().maskBorders(patches, (int) gd.getNextNumber(), (int) gd.getNextNumber(), (int) gd.getNextNumber(), (int) gd.getNextNumber());
burro.addPostTask(new Runnable() {
@Override
public void run() {
getLayerSet().addDataEditStep(ds);
}
});
} else if (command.equals("Remove alpha masks (layer-wise)...")) {
final GenericDialog gd = new GenericDialog("Remove alpha masks");
Utils.addLayerRangeChoices(Display.this.layer, gd);
gd.addCheckbox("Visible only", true);
gd.showDialog();
if (gd.wasCanceled())
return;
final Collection<Layer> layers = layer.getParent().getLayers().subList(gd.getNextChoiceIndex(), gd.getNextChoiceIndex() + 1);
final boolean visible_only = gd.getNextBoolean();
final Collection<Patch> patches = new ArrayList<Patch>();
for (final Layer l : layers) {
patches.addAll((Collection<Patch>) (Collection) l.getDisplayables(Patch.class, visible_only));
}
Display.removeAlphaMasks(patches);
} else if (command.equals("Remove alpha masks (selected images)...")) {
Display.removeAlphaMasks(selection.get(Patch.class));
} else if (command.equals("Split images under polyline ROI")) {
final Roi roi = canvas.getFakeImagePlus().getRoi();
if (null == roi)
return;
if (!(roi.getType() == Roi.POLYLINE || roi.getType() == Roi.FREELINE)) {
Utils.showMessage("Need a polyline or freeline ROI, not just any ROI!");
return;
}
if (!Utils.check("Really split images under the ROI?")) {
return;
}
// OK identify images whose contour intersects the ROI
final Set<Displayable> col = new HashSet<Displayable>();
// FreehandRoi is a subclass of PolygonRoi
final PolygonRoi proi = (PolygonRoi) roi;
final int[] x = proi.getXCoordinates(), y = proi.getYCoordinates();
final Rectangle b = proi.getBounds();
final Polygon[] pols = new Polygon[proi.getNCoordinates() - 1];
for (int i = 0; i < pols.length; i++) {
pols[i] = new Polygon(new int[] { b.x + x[i], b.x + x[i] + 1, b.x + x[i + 1], b.x + x[i + 1] + 1 }, new int[] { b.y + y[i], b.y + y[i], b.y + y[i + 1], b.y + y[i + 1] }, 4);
}
for (final Patch p : getLayer().getAll(Patch.class)) {
if (!p.isVisible())
continue;
final Area a = p.getArea();
for (int i = 0; i < pols.length; i++) {
final Area c = new Area(pols[i]);
c.intersect(a);
if (M.isEmpty(c))
continue;
// Else, add it:
col.add(p);
break;
}
}
if (col.isEmpty()) {
Utils.showMessage("No images intersect the ROI!");
return;
}
for (int i = 1; i < proi.getNCoordinates(); i++) {
for (int k = i + 2; k < proi.getNCoordinates(); k++) {
// check if the two segments intersect
if (null != M.computeSegmentsIntersection(x[i - 1], y[i - 1], x[i], y[i], x[k - 1], y[k - 1], x[k], y[k])) {
Utils.showMessage("Cannot split images with a polygon ROI that intersects itself!");
return;
}
}
}
final Area[] as = M.splitArea(new Area(getLayerSet().get2DBounds()), proi, getLayerSet().get2DBounds());
final Color[] c = new Color[] { Color.blue, Color.red };
int i = 0;
for (final Area a : as) {
// Utils.log2("Added overlay " + i + " with color " + c[i] + " and area " + AreaCalculations.area(a.getPathIterator(null)));
getLayer().getOverlay().add(a, c[i++], null, true, false, 0.4f);
}
Display.repaint(getLayer());
final YesNoDialog yn = new YesNoDialog(frame, "Check", "Does the splitting match your expectations?\nPush 'yes' to split the images.", false);
yn.setModal(false);
for (final WindowListener wl : yn.getWindowListeners()) yn.removeWindowListener(wl);
yn.setClosingTask(new Runnable() {
@Override
public void run() {
try {
// Remove overlay shapes
for (final Area a : as) {
getLayer().getOverlay().remove(a);
}
if (!yn.yesPressed()) {
Utils.log2("Pushed 'no'");
return;
}
// Split intersecting patches
// Duplicate each intersecting patch, and assign a[0] to the original and a[1] to the copy, as mask.
Bureaucrat.createAndStart(new Worker.Task("Spliting images") {
@Override
public void exec() {
final Roi r1 = new ShapeRoi(as[0]), r2 = new ShapeRoi(as[1]);
final ArrayList<Future<?>> fus = new ArrayList<Future<?>>();
for (final Patch p : (Collection<Patch>) (Collection) col) {
final Patch copy = (Patch) p.clone(p.getProject(), false);
p.addAlphaMask(r1, 0);
copy.addAlphaMask(r2, 0);
fus.add(p.updateMipMaps());
fus.add(copy.updateMipMaps());
// after submitting mipmaps, since it will get added to all Displays and repainted.
p.getLayer().add(copy);
}
Utils.wait(fus);
}
}, project);
} catch (final Throwable t) {
IJError.print(t);
} finally {
yn.dispose();
Display.repaint(getLayer());
}
}
});
yn.setVisible(true);
} else if (command.equals("Duplicate")) {
// only Patch and DLabel, i.e. Layer-only resident objects that don't exist in the Project Tree
final HashSet<Class> accepted = new HashSet<Class>();
accepted.add(Patch.class);
accepted.add(DLabel.class);
accepted.add(Stack.class);
final ArrayList<Displayable> originals = new ArrayList<Displayable>();
final ArrayList<Displayable> selected = selection.getSelected();
for (final Displayable d : selected) {
if (accepted.contains(d.getClass())) {
originals.add(d);
}
}
if (originals.size() > 0) {
getLayerSet().addChangeTreesStep();
for (final Displayable d : originals) {
if (d instanceof ZDisplayable) {
d.getLayerSet().add((ZDisplayable) d.clone());
} else {
d.getLayer().add(d.clone());
}
}
getLayerSet().addChangeTreesStep();
} else if (selected.size() > 0) {
Utils.log("Can only duplicate images and text labels.\nDuplicate *other* objects in the Project Tree.\n");
}
} else if (command.equals("Create subproject")) {
// Choose a 2D rectangle
final Roi roi = canvas.getFakeImagePlus().getRoi();
Rectangle bounds;
if (null != roi) {
if (!Utils.check("Use bounds as defined by the ROI:\n" + roi.getBounds() + " ?"))
return;
bounds = roi.getBounds();
} else
bounds = getLayerSet().get2DBounds();
// Choose a layer range, and whether to ignore hidden images
final GenericDialog gd = new GenericDialog("Choose layer range");
Utils.addLayerRangeChoices(layer, gd);
gd.addCheckbox("Ignore hidden images", true);
gd.showDialog();
if (gd.wasCanceled())
return;
final Layer first = layer.getParent().getLayer(gd.getNextChoiceIndex());
final Layer last = layer.getParent().getLayer(gd.getNextChoiceIndex());
final boolean ignore_hidden_patches = gd.getNextBoolean();
final Project sub = getProject().createSubproject(bounds, first, last, ignore_hidden_patches);
if (null == sub) {
Utils.log("ERROR: failed to create subproject.");
return;
}
final LayerSet subls = sub.getRootLayerSet();
Display.createDisplay(sub, subls.getLayer(0));
} else if (command.startsWith("Image stack under selected Arealist")) {
if (null == active || active.getClass() != AreaList.class)
return;
final GenericDialog gd = new GenericDialog("Stack options");
final String[] types = { "8-bit", "16-bit", "32-bit", "RGB" };
gd.addChoice("type:", types, types[0]);
gd.addSlider("Scale: ", 1, 100, 100);
gd.showDialog();
if (gd.wasCanceled())
return;
final int type;
switch(gd.getNextChoiceIndex()) {
case 0:
type = ImagePlus.GRAY8;
break;
case 1:
type = ImagePlus.GRAY16;
break;
case 2:
type = ImagePlus.GRAY32;
break;
case 3:
type = ImagePlus.COLOR_RGB;
break;
default:
type = ImagePlus.GRAY8;
break;
}
final ImagePlus imp = ((AreaList) active).getStack(type, gd.getNextNumber() / 100);
if (null != imp)
imp.show();
} else if (command.equals("Fly through selected Treeline/AreaTree")) {
if (null == active || !(active instanceof Tree<?>))
return;
Bureaucrat.createAndStart(new Worker.Task("Creating fly through", true) {
@Override
public void exec() {
final GenericDialog gd = new GenericDialog("Fly through");
gd.addNumericField("Width", 512, 0);
gd.addNumericField("Height", 512, 0);
final String[] types = new String[] { "8-bit gray", "Color RGB" };
gd.addChoice("Image type", types, types[0]);
gd.addSlider("scale", 0, 100, 100);
gd.addCheckbox("save to file", false);
gd.showDialog();
if (gd.wasCanceled())
return;
final int w = (int) gd.getNextNumber();
final int h = (int) gd.getNextNumber();
final int type = 0 == gd.getNextChoiceIndex() ? ImagePlus.GRAY8 : ImagePlus.COLOR_RGB;
final double scale = gd.getNextNumber();
if (w <= 0 || h <= 0) {
Utils.log("Invalid width or height: " + w + ", " + h);
return;
}
if (0 == scale || Double.isNaN(scale)) {
Utils.log("Invalid scale: " + scale);
return;
}
String dir = null;
if (gd.getNextBoolean()) {
final DirectoryChooser dc = new DirectoryChooser("Target directory");
dir = dc.getDirectory();
// canceled
if (null == dir)
return;
dir = Utils.fixDir(dir);
}
final ImagePlus imp = ((Tree<?>) active).flyThroughMarked(w, h, scale / 100, type, dir);
if (null == imp) {
Utils.log("Mark a node first!");
return;
}
imp.show();
}
}, project);
} else if (command.startsWith("Arealists as labels")) {
final GenericDialog gd = new GenericDialog("Export labels");
gd.addSlider("Scale: ", 1, 100, 100);
final String[] options = { "All area list", "Selected area lists" };
gd.addChoice("Export: ", options, options[0]);
Utils.addLayerRangeChoices(layer, gd);
gd.addCheckbox("Visible only", true);
gd.showDialog();
if (gd.wasCanceled())
return;
final float scale = (float) (gd.getNextNumber() / 100);
final java.util.List<Displayable> al = (java.util.List<Displayable>) (0 == gd.getNextChoiceIndex() ? layer.getParent().getZDisplayables(AreaList.class) : selection.getSelectedSorted(AreaList.class));
if (null == al) {
Utils.log("No area lists found to export.");
return;
}
// Generics are ... a pain? I don't understand them? They fail when they shouldn't? And so easy to workaround that they are a shame?
final int first = gd.getNextChoiceIndex();
final int last = gd.getNextChoiceIndex();
final boolean visible_only = gd.getNextBoolean();
if (-1 != command.indexOf("(amira)")) {
AreaList.exportAsLabels(al, canvas.getFakeImagePlus().getRoi(), scale, first, last, visible_only, true, true);
} else if (-1 != command.indexOf("(tif)")) {
AreaList.exportAsLabels(al, canvas.getFakeImagePlus().getRoi(), scale, first, last, visible_only, false, false);
}
} else if (command.equals("Project properties...")) {
project.adjustProperties();
} else if (command.equals("Release memory...")) {
Bureaucrat.createAndStart(new Worker("Releasing memory") {
@Override
public void run() {
startedWorking();
try {
final GenericDialog gd = new GenericDialog("Release Memory");
final int max = (int) (IJ.maxMemory() / 1000000);
gd.addSlider("Megabytes: ", 0, max, max / 2);
gd.showDialog();
if (!gd.wasCanceled()) {
final int n_mb = (int) gd.getNextNumber();
project.getLoader().releaseToFit((long) n_mb * 1000000);
}
} catch (final Throwable e) {
IJError.print(e);
} finally {
finishedWorking();
}
}
}, project);
} else if (command.equals("Create sibling project with retiled layers")) {
final GenericDialog gd = new GenericDialog("Export flattened layers");
gd.addNumericField("Tile_width", 2048, 0);
gd.addNumericField("Tile_height", 2048, 0);
final String[] types = new String[] { "16-bit", "RGB color" };
gd.addChoice("Export_image_type", types, types[0]);
gd.addCheckbox("Create mipmaps", true);
gd.addNumericField("Number_of_threads_to_use", Runtime.getRuntime().availableProcessors(), 0);
gd.showDialog();
if (gd.wasCanceled())
return;
final DirectoryChooser dc = new DirectoryChooser("Choose target folder");
final String folder = dc.getDirectory();
if (null == folder)
return;
final int tileWidth = (int) gd.getNextNumber(), tileHeight = (int) gd.getNextNumber();
if (tileWidth < 0 || tileHeight < 0) {
Utils.showMessage("Invalid tile sizes: " + tileWidth + ", " + tileHeight);
return;
}
if (tileWidth != tileHeight) {
if (!Utils.check("The tile width (" + tileWidth + ") differs from the tile height (" + tileHeight + ").\nContinue anyway?")) {
return;
}
}
final int imageType = 0 == gd.getNextChoiceIndex() ? ImagePlus.GRAY16 : ImagePlus.COLOR_RGB;
final boolean createMipMaps = gd.getNextBoolean();
final int nThreads = (int) gd.getNextNumber();
Bureaucrat.createAndStart(new Worker.Task("Export flattened sibling project") {
@Override
public void exec() {
try {
ProjectTiler.createRetiledSibling(project, folder, tileWidth, tileHeight, imageType, true, nThreads, createMipMaps);
} catch (final Throwable t) {
Utils.showMessage("ERROR: " + t);
IJError.print(t);
}
}
}, project);
} else if (command.equals("Flush image cache")) {
Loader.releaseAllCaches();
} else if (command.equals("Regenerate all mipmaps")) {
project.getLoader().regenerateMipMaps(getLayerSet().getDisplayables(Patch.class));
} else if (command.equals("Regenerate mipmaps (selected images)")) {
project.getLoader().regenerateMipMaps(selection.getSelected(Patch.class));
} else if (command.equals("Tags...")) {
// get a file first
final File f = Utils.chooseFile(null, "tags", ".xml");
if (null == f)
return;
if (!Utils.saveToFile(f, getLayerSet().exportTags())) {
Utils.logAll("ERROR when saving tags to file " + f.getAbsolutePath());
}
} else if (command.equals("Tags ...")) {
final String[] ff = Utils.selectFile("Import tags");
if (null == ff)
return;
final GenericDialog gd = new GenericDialog("Import tags");
final String[] modes = new String[] { "Append to current tags", "Replace current tags" };
gd.addChoice("Import tags mode:", modes, modes[0]);
gd.addMessage("Replacing current tags\nwill remove all tags\n from all nodes first!");
gd.showDialog();
if (gd.wasCanceled())
return;
getLayerSet().importTags(new StringBuilder(ff[0]).append('/').append(ff[1]).toString(), 1 == gd.getNextChoiceIndex());
} else if (command.equals("Connectivity graph...")) {
Bureaucrat.createAndStart(new Worker.Task("Connectivity graph") {
@Override
public void exec() {
Graph.extractAndShowGraph(getLayerSet());
}
}, getProject());
} else if (command.equals("NeuroML...")) {
final GenericDialog gd = new GenericDialog("Export NeuroML");
final String[] a = new String[] { "NeuroML (arbors and synapses)", "MorphML (arbors)" };
gd.addChoice("Type:", a, a[0]);
final String[] b = new String[] { "All treelines and areatrees", "Selected treelines and areatrees" };
gd.addChoice("Export:", b, b[0]);
gd.showDialog();
if (gd.wasCanceled())
return;
final int type = gd.getNextChoiceIndex();
final int export = gd.getNextChoiceIndex();
//
final SaveDialog sd = new SaveDialog("Choose .mml file", null, ".mml");
final String filename = sd.getFileName();
// canceled
if (null == filename)
return;
final File f = new File(sd.getDirectory() + filename);
//
Bureaucrat.createAndStart(new Worker.Task("Export NeuroML") {
@Override
public void exec() {
OutputStreamWriter w = null;
try {
final Set<Tree<?>> trees = new HashSet<Tree<?>>();
Collection<? extends Displayable> ds = null;
switch(export) {
case 0:
ds = getLayerSet().getZDisplayables();
break;
case 1:
ds = selection.getSelected();
break;
}
for (final Displayable d : ds) {
if (d.getClass() == Treeline.class || d.getClass() == AreaTree.class) {
trees.add((Tree<?>) d);
}
}
if (trees.isEmpty()) {
Utils.showMessage("No trees to export!");
return;
}
//
// encoding in Latin 1 (for macosx not to mess around
w = new OutputStreamWriter(new BufferedOutputStream(new FileOutputStream(f), 65536), "8859_1");
//
switch(type) {
case 0:
NeuroML.exportNeuroML(trees, w);
break;
case 1:
NeuroML.exportMorphML(trees, w);
break;
}
//
w.flush();
w.close();
//
} catch (final Throwable t) {
IJError.print(t);
try {
if (null != w)
w.close();
} catch (final Exception ee) {
IJError.print(ee);
}
}
}
}, getProject());
} else if (command.equals("Measure")) {
if (selection.isEmpty()) {
Utils.log("Nothing selected to measure!");
return;
}
selection.measure();
} else if (command.equals("Area interpolation options...")) {
final GenericDialog gd = new GenericDialog("Area interpolation");
final boolean a = project.getBooleanProperty(AreaUtils.always_interpolate_areas_with_distance_map);
gd.addCheckbox("Always use distance map method", a);
gd.showDialog();
if (gd.wasCanceled())
return;
project.setProperty(AreaUtils.always_interpolate_areas_with_distance_map, gd.getNextBoolean() ? "true" : null);
} else {
Utils.log2("Display: don't know what to do with command " + command);
}
}
});
}
use of ini.trakem2.utils.Filter in project TrakEM2 by trakem2.
the class Display method makeGUI.
private void makeGUI(final Layer layer, final Object[] props) {
// gather properties
final Point p;
double mag = 1.0D;
Rectangle srcRect = null;
if (null != props) {
p = (Point) props[0];
mag = ((Double) props[1]).doubleValue();
srcRect = (Rectangle) props[2];
} else {
p = null;
}
// transparency slider
this.transp_slider = new JSlider(javax.swing.SwingConstants.HORIZONTAL, 0, 100, 100);
this.transp_slider.setBackground(Color.white);
this.transp_slider.setMinimumSize(new Dimension(250, 20));
this.transp_slider.setMaximumSize(new Dimension(250, 20));
this.transp_slider.setPreferredSize(new Dimension(250, 20));
final TransparencySliderListener tsl = new TransparencySliderListener();
this.transp_slider.addChangeListener(tsl);
this.transp_slider.addMouseListener(tsl);
for (final KeyListener kl : this.transp_slider.getKeyListeners()) {
this.transp_slider.removeKeyListener(kl);
}
// Tabbed pane on the left
this.tabs = new JTabbedPane();
this.tabs.setMinimumSize(new Dimension(250, 300));
this.tabs.setBackground(Color.white);
this.tabs.addChangeListener(tabs_listener);
// Tab 1: Patches
this.panel_patches = new RollingPanel(this, Patch.class);
this.addTab("Patches", panel_patches);
// Tab 2: Profiles
this.panel_profiles = new RollingPanel(this, Profile.class);
this.addTab("Profiles", panel_profiles);
// Tab 3: ZDisplayables
this.panel_zdispl = new RollingPanel(this, ZDisplayable.class);
this.addTab("Z space", panel_zdispl);
// Tab 4: channels
this.panel_channels = makeTabPanel();
this.scroll_channels = makeScrollPane(panel_channels);
this.channels = new Channel[4];
this.channels[0] = new Channel(this, Channel.MONO);
this.channels[1] = new Channel(this, Channel.RED);
this.channels[2] = new Channel(this, Channel.GREEN);
this.channels[3] = new Channel(this, Channel.BLUE);
// this.panel_channels.add(this.channels[0]);
addGBRow(this.panel_channels, this.channels[1], null);
addGBRow(this.panel_channels, this.channels[2], this.channels[1]);
addGBRow(this.panel_channels, this.channels[3], this.channels[2]);
this.addTab("Opacity", scroll_channels);
// Tab 5: labels
this.panel_labels = new RollingPanel(this, DLabel.class);
this.addTab("Labels", panel_labels);
// Tab 6: layers
this.panel_layers = makeTabPanel();
this.scroll_layers = makeScrollPane(panel_layers);
recreateLayerPanels(layer);
this.scroll_layers.addMouseWheelListener(canvas);
this.addTab("Layers", scroll_layers);
// Tab 7: tool options
// empty
this.tool_options = new OptionPanel();
this.scroll_options = makeScrollPane(this.tool_options);
this.scroll_options.setHorizontalScrollBarPolicy(JScrollPane.HORIZONTAL_SCROLLBAR_AS_NEEDED);
this.addTab("Tool options", this.scroll_options);
// Tab 8: annotations
this.annot_editor = new JEditorPane();
// by default, nothing is selected
this.annot_editor.setEnabled(false);
this.annot_editor.setMinimumSize(new Dimension(200, 50));
this.annot_label = new JLabel("(No selected object)");
this.annot_panel = makeAnnotationsPanel(this.annot_editor, this.annot_label);
this.addTab("Annotations", this.annot_panel);
// Tab 9: filter options
this.filter_options = createFilterOptionPanel();
this.scroll_filter_options = makeScrollPane(this.filter_options);
this.scroll_filter_options.setHorizontalScrollBarPolicy(JScrollPane.HORIZONTAL_SCROLLBAR_AS_NEEDED);
this.addTab("Live filter", this.scroll_filter_options);
this.ht_tabs = new Hashtable<Class<?>, RollingPanel>();
this.ht_tabs.put(Patch.class, panel_patches);
this.ht_tabs.put(Profile.class, panel_profiles);
this.ht_tabs.put(ZDisplayable.class, panel_zdispl);
this.ht_tabs.put(AreaList.class, panel_zdispl);
this.ht_tabs.put(Pipe.class, panel_zdispl);
this.ht_tabs.put(Polyline.class, panel_zdispl);
this.ht_tabs.put(Treeline.class, panel_zdispl);
this.ht_tabs.put(AreaTree.class, panel_zdispl);
this.ht_tabs.put(Connector.class, panel_zdispl);
this.ht_tabs.put(Ball.class, panel_zdispl);
this.ht_tabs.put(Dissector.class, panel_zdispl);
this.ht_tabs.put(DLabel.class, panel_labels);
this.ht_tabs.put(Stack.class, panel_zdispl);
// channels not included
// layers not included
// tools not included
// annotations not included
// Navigator
this.navigator = new DisplayNavigator(this, layer.getLayerWidth(), layer.getLayerHeight());
// Layer scroller (to scroll slices)
int extent = (int) (250.0 / layer.getParent().size());
if (extent < 10)
extent = 10;
this.scroller = new JScrollBar(JScrollBar.HORIZONTAL);
this.scroller.setModel(new ScrollerModel(layer));
updateLayerScroller(layer);
this.scroller.addAdjustmentListener(scroller_listener);
// LAYOUT
final GridBagLayout layout = new GridBagLayout();
final GridBagConstraints c = new GridBagConstraints();
c.anchor = GridBagConstraints.NORTHWEST;
c.fill = GridBagConstraints.NONE;
c.weightx = 0;
c.weighty = 0;
c.gridx = 0;
c.gridy = 0;
c.ipadx = 0;
c.ipady = 0;
c.gridwidth = 1;
c.gridheight = 1;
Display.this.all = new JPanel();
all.setBackground(Color.white);
all.setLayout(layout);
c.insets = new Insets(0, 0, 0, 5);
// 1
// fixed dimensions
toolbar_panel = new ToolbarPanel();
layout.setConstraints(toolbar_panel, c);
all.add(toolbar_panel);
// 2
c.gridy++;
c.fill = GridBagConstraints.HORIZONTAL;
layout.setConstraints(transp_slider, c);
all.add(transp_slider);
// 3
c.gridy++;
c.weighty = 1;
c.fill = GridBagConstraints.BOTH;
layout.setConstraints(tabs, c);
all.add(tabs);
// 4
c.gridy++;
c.weighty = 0;
c.fill = GridBagConstraints.NONE;
layout.setConstraints(navigator, c);
all.add(navigator);
// 5
c.gridy++;
c.fill = GridBagConstraints.HORIZONTAL;
layout.setConstraints(scroller, c);
all.add(scroller);
// Canvas
this.canvas = new DisplayCanvas(this, (int) Math.ceil(layer.getLayerWidth()), (int) Math.ceil(layer.getLayerHeight()));
c.insets = new Insets(0, 0, 0, 0);
c.fill = GridBagConstraints.BOTH;
c.anchor = GridBagConstraints.NORTHWEST;
c.gridx = 1;
c.gridy = 0;
c.gridheight = GridBagConstraints.REMAINDER;
c.weightx = 1;
c.weighty = 1;
layout.setConstraints(Display.this.canvas, c);
all.add(canvas);
// prevent new Displays from screwing up if input is globally disabled
if (!project.isInputEnabled())
Display.this.canvas.setReceivesInput(false);
this.canvas.addComponentListener(canvas_size_listener);
this.navigator.addMouseWheelListener(canvas);
this.transp_slider.addKeyListener(canvas);
// JFrame to show the split pane
this.frame = ControlWindow.createJFrame(layer.toString());
this.frame.setBackground(Color.white);
this.frame.getContentPane().setBackground(Color.white);
if (IJ.isMacintosh() && IJ.getInstance() != null) {
// may be needed for Java 1.4 on OS X
IJ.wait(10);
this.frame.setMenuBar(ij.Menus.getMenuBar());
}
this.frame.addWindowListener(window_listener);
// this.frame.addComponentListener(display_frame_listener);
this.frame.getContentPane().add(all);
if (null != props) {
// restore canvas
canvas.setup(mag, srcRect);
// restore visibility of each channel
// aka c_alphas_state
final int cs = ((Integer) props[5]).intValue();
final int[] sel = new int[4];
sel[0] = ((cs & 0xff000000) >> 24);
sel[1] = ((cs & 0xff0000) >> 16);
sel[2] = ((cs & 0xff00) >> 8);
sel[3] = (cs & 0xff);
// restore channel alphas
Display.this.c_alphas = ((Integer) props[4]).intValue();
channels[0].setAlpha((float) ((c_alphas & 0xff000000) >> 24) / 255.0f, 0 != sel[0]);
channels[1].setAlpha((float) ((c_alphas & 0xff0000) >> 16) / 255.0f, 0 != sel[1]);
channels[2].setAlpha((float) ((c_alphas & 0xff00) >> 8) / 255.0f, 0 != sel[2]);
channels[3].setAlpha((float) (c_alphas & 0xff) / 255.0f, 0 != sel[3]);
// restore visibility in the working c_alphas
Display.this.c_alphas = ((0 != sel[0] ? (int) (255 * channels[0].getAlpha()) : 0) << 24) + ((0 != sel[1] ? (int) (255 * channels[1].getAlpha()) : 0) << 16) + ((0 != sel[2] ? (int) (255 * channels[2].getAlpha()) : 0) << 8) + (0 != sel[3] ? (int) (255 * channels[3].getAlpha()) : 0);
}
if (null != active && null != layer) {
final Rectangle r = active.getBoundingBox();
r.x -= r.width / 2;
r.y -= r.height / 2;
r.width += r.width;
r.height += r.height;
if (r.x < 0)
r.x = 0;
if (r.y < 0)
r.y = 0;
if (r.width > layer.getLayerWidth())
r.width = (int) layer.getLayerWidth();
if (r.height > layer.getLayerHeight())
r.height = (int) layer.getLayerHeight();
final double magn = layer.getLayerWidth() / (double) r.width;
canvas.setup(magn, r);
}
// add keyListener to the whole frame
this.tabs.addKeyListener(canvas);
this.frame.addKeyListener(canvas);
// create a drag and drop listener
dnd = new DNDInsertImage(Display.this);
Utils.invokeLater(new Runnable() {
@Override
public void run() {
Display.this.frame.pack();
ij.gui.GUI.center(Display.this.frame);
Display.this.frame.setVisible(true);
// doesn't get it through events
ProjectToolbar.setProjectToolbar();
final Dimension screen = Toolkit.getDefaultToolkit().getScreenSize();
if (null != props) {
// fix positioning outside the screen (dual to single monitor)
if (p.x >= 0 && p.x < screen.width - 50 && p.y >= 0 && p.y <= screen.height - 50)
Display.this.frame.setLocation(p);
else
frame.setLocation(0, 0);
}
// fix excessive size
final Rectangle box = Display.this.frame.getBounds();
int x = box.x;
int y = box.y;
int width = box.width;
int height = box.height;
if (box.width > screen.width) {
x = 0;
width = screen.width;
}
if (box.height > screen.height) {
y = 0;
height = screen.height;
}
if (x != box.x || y != box.y) {
// added insets for bad window managers
Display.this.frame.setLocation(x, y + (0 == y ? 30 : 0));
}
if (width != box.width || height != box.height) {
// added insets for bad window managers
Display.this.frame.setSize(new Dimension(width - 10, height - 30));
}
if (null == props) {
// try to optimize canvas dimensions and magn
double magn = layer.getLayerHeight() / screen.height;
if (magn > 1.0)
magn = 1.0;
long size = 0;
// limit magnification if appropriate
for (final Displayable pa : layer.getDisplayables(Patch.class)) {
final Rectangle ba = pa.getBoundingBox();
size += (long) (ba.width * ba.height);
}
if (// 10 Mb
size > 10000000)
// 10 Mb
canvas.setInitialMagnification(0.25);
else {
Display.this.frame.setSize(new Dimension((int) (screen.width * 0.66), (int) (screen.height * 0.66)));
}
}
updateTab(panel_patches);
// re-layout:
tabs.validate();
// Set the calibration of the FakeImagePlus to that of the LayerSet
((FakeImagePlus) canvas.getFakeImagePlus()).setCalibrationSuper(layer.getParent().getCalibrationCopy());
updateFrameTitle(layer);
// Set the FakeImagePlus as the current image
setTempCurrentImage();
// start a repainting thread
if (null != props) {
// repaint() is unreliable
canvas.repaint(true);
}
ControlWindow.setLookAndFeel();
}
});
}
use of ini.trakem2.utils.Filter in project TrakEM2 by trakem2.
the class ImageJCommandListener method commandExecuting.
// I know, I could create a hashtable and then map methods of this class to each command key ... this is just easier, and performance-wise nobody cares
// Or even a hastable with String command keys and then a number as value, and use a gigantic switch block. So much pain to write. WHAT I REALLY WANT is a switch that takes a String and is fast because it has its own hash setup.
public String commandExecuting(final String command) {
// Utils.log2("Command: " + command);
// 1 - check source
ImagePlus current = WindowManager.getCurrentImage();
// not a trakem2 display: continue happily
if (!(current instanceof FakeImagePlus))
return command;
// 2 - identify project
final FakeImagePlus fimp = (FakeImagePlus) current;
final Display display = fimp.getDisplay();
final LayerSet layer_set = display.getLayer().getParent();
final Project project = display.getProject();
final ProjectTree ptree = project.getProjectTree();
final Displayable active = display.getActive();
final Selection selection = display.getSelection();
// FILE menu
if (command.equals("Save")) {
project.save();
return null;
} else // EDIT menu
if (command.equals("Undo")) {
// TODO forward to the active image, if any
niy(command);
return null;
} else if (command.equals("Cut")) {
// TODO forward to the active image, if any
niy(command);
return null;
} else if (command.equals("Copy")) {
// TODO forward to the active image, if any
niy(command);
return null;
} else if (command.equals("Copy to System")) {
// TODO forward to the active image, if any
niy(command);
return null;
} else if (command.equals("Paste")) {
// TODO forward to the active image, if any
niy(command);
return null;
} else if (command.equals("Clear")) {
// TODO forward to the active image, if any
niy(command);
return null;
} else if (command.equals("Clear Outside")) {
// TODO forward to the active image, if any
niy(command);
return null;
} else if (command.equals("Fill")) {
// TODO forward to the active image, if any
niy(command);
return null;
} else if (command.equals("Draw")) {
// TODO forward to the active image, if any
niy(command);
return null;
} else if (command.equals("Invert")) {
// TODO forward to the active image, if any
niy(command);
return null;
} else // EDIT - SELECTION menu
if (command.equals("Select All")) {
if (ProjectToolbar.SELECT == Toolbar.getToolId()) {
selection.selectAll();
return null;
}
return command;
} else if (command.equals("Select None")) {
if (ProjectToolbar.SELECT == Toolbar.getToolId()) {
display.select(null);
return null;
}
return command;
} else if (command.equals("Restore Selection")) {
if (ProjectToolbar.SELECT == Toolbar.getToolId()) {
selection.restore();
return null;
}
return command;
} else // IMAGE - TYPE menu
if (command.equals("8-bit")) {
// TODO forward to the active image, if any
niy(command);
return null;
} else if (command.equals("16-bit")) {
// TODO forward to the active image, if any
niy(command);
return null;
} else if (command.equals("32-bit")) {
// TODO forward to the active image, if any
niy(command);
return null;
} else if (command.equals("8-bit Color")) {
// TODO forward to the active image, if any
niy(command);
return null;
} else if (command.equals("RGB Color")) {
// TODO forward to the active image, if any
niy(command);
return null;
} else if (command.equals("RGB Stack") || command.equals("HSB Stack")) {
Utils.showMessage("Can't convert to " + command);
return null;
} else // IMAGE - ADJUST menu
if (command.equals("Brightness/Contrast...")) {
// TODO forward to the active image, if any
niy(command);
return null;
} else if (command.equals("Window/Level...")) {
// TODO forward to the active image, if any
niy(command);
return null;
} else if (command.equals("Color Balance...")) {
// TODO forward to the active image, if any
niy(command);
return null;
} else if (command.equals("Threshold...")) {
// TODO forward to the active image, if any
niy(command);
return null;
} else if (command.equals("Size...")) {
if (null != active)
selection.specify();
return null;
} else if (command.equals("Canvas Size...")) {
display.resizeCanvas();
return null;
} else // IMAGE menu
if (command.equals("Show Info...")) {
// TODO perhaps it should show only for images ...
if (null == active) {
ptree.showInfo(project.getRootProjectThing());
} else {
ProjectThing pt = project.findProjectThing(active);
if (null != pt)
ptree.showInfo(pt);
}
return null;
} else // IMAGE - COLOR menu
if (in(command, new String[] { "RGB Split", "RGB Merge...", "Stack to RGB", "Make Composite" })) {
notAvailable(command);
return null;
} else if (command.equals("Show LUT")) {
return setTempCurrentImage(command, active);
} else if (command.equals("Edit LUT...")) {
// TODO forward to the active image, if any
niy(command);
return null;
} else if (command.equals("Average Color")) {
// TODO forward to the active image, if any
niy(command);
return null;
} else if (command.equals("RGB to CIELAB")) {
// TODO forward to the active image, if any
niy(command);
return null;
} else if (command.equals("RGB to Luminance")) {
// TODO forward to the active image, if any
niy(command);
return null;
} else // IMAGE STACK menu
if (in(command, new String[] { "Add Slice", "Delete Slice" })) {
Utils.showMessage("Go to the Layer Tree and right-click to add/delete a layer.");
return null;
} else if (command.equals("Next Slice [>]")) {
display.nextLayer(IJ.shiftKeyDown() ? Event.SHIFT_MASK : 0);
return null;
} else if (command.equals("Previous Slice [<]")) {
display.previousLayer(IJ.shiftKeyDown() ? Event.SHIFT_MASK : 0);
return null;
} else if (in(command, new String[] { "Set Slice", "Images to Stack", "Stack to Images", "Make Montage..." })) {
notAvailable(command);
return null;
} else if (command.equals("Reslice [/]...")) {
// TODO
niy(command);
return null;
} else if (command.equals("Z Project...")) {
// TODO
niy(command);
return null;
} else if (command.equals("3D Project...")) {
// TODO
niy(command);
return null;
} else if (command.equals("Plot Z-axis Profile")) {
// TODO
niy(command);
return null;
} else if (command.equals("Start Animation [\\]")) {
// TODO
niy(command);
return null;
} else if (command.equals("Stop Animation")) {
// TODO
niy(command);
return null;
} else // IMAGE menu again
if (command.equals("Crop")) {
notAvailable(command);
return null;
} else if (in(command, new String[] { "Translate...", "Scale..." })) {
if (null != active)
selection.specify();
return null;
} else if (command.equals("Duplicate...")) {
if (null != active && active.getClass().equals(Patch.class)) {
// TODO stacks?
// 2.5 security factor: for awt in non-1.6.0 machines
project.getLoader().releaseToFit((long) (project.getLoader().estimateImageFileSize((Patch) active, 0) * 2.5));
new ImagePlus(active.getTitle(), ((Patch) active).getImageProcessor().duplicate()).show();
}
return null;
} else if (command.equals("Rename...")) {
if (null != active) {
active.adjustProperties();
Display.updateSelection();
}
return null;
} else // IMAGE ROTATE menu
if (command.equals("Flip Horizontally")) {
selection.apply(2, new double[] { -1, 1 });
return null;
} else if (command.equals("Flip Vertically")) {
selection.apply(2, new double[] { 1, -1 });
return null;
} else if (command.equals("Rotate 90 Degrees Right")) {
selection.apply(1, new double[] { 90 });
return null;
} else if (command.equals("Rotate 90 Degrees Left")) {
selection.apply(1, new double[] { -90 });
return null;
} else if (command.equals("Arbitrarily...")) {
if (null != active)
selection.specify();
return null;
} else // IMAGE ZOOM menu
if (command.equals("To Selection")) {
Roi roi = fimp.getRoi();
if (null != roi) {
Rectangle b = roi.getBounds();
b.x -= b.width / 2;
b.y -= b.height / 2;
b.width *= 2;
b.height *= 2;
display.getCanvas().showCentered(b);
}
return null;
} else if (command.equals("View 100%")) {
// TODO
niy(command);
return null;
} else // ANALYZE menu
if (command.equals("Measure")) {
// Minimal measurement: area of closed ROIs, length of unclosed ROIs, calibrated.
Roi roi = fimp.getRoi();
if (null != roi) {
Calibration cal = fimp.getCalibration();
AffineTransform caff = new AffineTransform();
caff.scale(cal.pixelWidth, cal.pixelHeight);
if (M.isAreaROI(roi)) {
Area area = M.getArea(roi);
area = area.createTransformedArea(caff);
ResultsTable rt = Utils.createResultsTable("ROI area", new String[] { "area", "perimeter" });
rt.incrementCounter();
rt.addLabel("units", cal.getUnit());
rt.addValue(0, Math.abs(AreaCalculations.area(area.getPathIterator(null))));
rt.addValue(1, roi.getLength());
rt.show("ROI area");
} else {
ResultsTable rt = Utils.createResultsTable("ROI length", new String[] { "length" });
rt.incrementCounter();
rt.addLabel("units", cal.getUnit());
rt.addValue(0, roi.getLength());
rt.show("ROI length");
}
return null;
} else if (null != active) {
// Measure the active displayable
if (active.getClass() == Patch.class) {
// measure like 'm' would in ImageJ for an image
ImagePlus imp = ((Patch) active).getImagePlus();
imp.setCalibration(active.getLayer().getParent().getCalibrationCopy());
IJ.run(imp, "Measure", "");
} else {
// Call measure like ProjectThing does
ProjectThing pt = active.getProject().findProjectThing(active);
if (active instanceof Profile)
((ProjectThing) pt.getParent()).measure();
else
pt.measure();
}
return null;
}
Utils.log("Draw a ROI or select an object!");
return null;
} else if (in(command, new String[] { "Analyze Particles...", "Histogram", "Plot Profile", "Surface Plot...", "Color Inspector 3D", "3D Surface Plot", "Color Histogram" })) {
return setTempCurrentImage(command, active);
} else if (command.equals("Label")) {
notAvailable(command);
return null;
} else // PLUGINS menu
if (command.equals("Volume Viewer")) {
return runOnVirtualLayerSet(command, layer_set, display);
} else if (command.equals("3D Viewer")) {
// it's virtual and non-caching, will appear as a regular ImageJ stack
layer_set.createLayerStack(Displayable.class, ImagePlus.COLOR_RGB, display.getDisplayChannelAlphas()).getImagePlus().show();
return command;
} else // PROCESS menu and submenus
if (in(command, new String[] { "FFT", "Fast FFT (2D/3D)" })) {
return setTempCurrentImage(command, active);
} else if (in(command, new String[] { "Bandpass Filter...", "Custom Filter...", "FD Math...", "Swap Quadrants", "Convolve...", "Gaussian Blur...", "Median...", "Mean...", "Minimum...", "Maximum...", "Unsharp Mask...", "Variance...", "Show Circular Masks...", "Subtract Background..." })) {
return duplicate(command, active);
} else if (in(command, new String[] { "Smooth", "Sharpen", "Find Edges", "Enhance Contrast", "Add Noise", "Add Specified Noise...", "Salt and Pepper", "Despeckle", "Remove Outliers...", "North", "Northeast", "East", "Southeast", "South", "Southwest", "West", "Northwest", "Make Binary", "Convert to Mask", "Find Maxima...", "Erode", "Dilate", "Open ", "Close-", "Outline", "Fill Holes", "Skeletonize", "Distance Map", "Ultimate Points", "Watershed", "Add...", "Subtract...", "Multiply...", "Divide...", "AND...", "OR...", "XOR...", "Min...", "Max...", "Gamma...", "Log", "Exp", "Square", "Square Root", "Reciprocal", "NaN Background", "Abs" })) {
return duplicate(command, active);
}
/*else {
// continue happily
//Utils.log2("Skipping " + command);
}*/
// If it's part of "Save As", ignore it
Menu menu = Menus.getSaveAsMenu();
for (int i = menu.getItemCount() - 1; i > -1; i--) {
if (command.equals(menu.getItem(i).getActionCommand())) {
notAvailable(command);
return null;
}
}
// Give it back to ImageJ
return command;
}
use of ini.trakem2.utils.Filter in project TrakEM2 by trakem2.
the class DNDInsertImage method importImageFile.
private boolean importImageFile(File f, String path, Point point) throws Exception {
if (f.exists()) {
final Layer layer = display.getLayer();
Bureaucrat burro = null;
if (f.isDirectory()) {
// ask:
GenericDialog gd = new GenericDialog("Import directory");
String[] choice = new String[] { "Stack", "Grid", "Sequence as grid" };
gd.addChoice("Directory as: ", choice, choice[0]);
gd.showDialog();
if (gd.wasCanceled()) {
// the user cancel it, so all is ok.
return true;
}
display.getLayerSet().addLayerContentStep(layer);
switch(gd.getNextChoiceIndex()) {
case // as stack
0:
// if importing image sequence as a stack:
// don't filter by name "^[^\\.].*[\\.][a-zA-Z1-9_]{3,4}$"
String[] names = f.list(new ImageFileFilter());
Utils.log2("stack size: " + names.length);
for (int i = 0; i < names.length; i++) {
Utils.log2(names[i]);
}
Arrays.sort(names);
// I don't care about the dimensions
VirtualStack stack = new VirtualStack(10, 10, null, f.getAbsolutePath().replace('\\', '/'));
for (int k = 0; k < names.length; k++) {
IJ.redirectErrorMessages();
// ignore trakem2 files
if (names[k].toLowerCase().endsWith(".xml"))
continue;
stack.addSlice(names[k]);
}
if (stack.getSize() > 0) {
burro = display.getProject().getLoader().importStack(layer, point.x, point.y, new ImagePlus("stack", stack), true, path, false);
}
break;
case // as grid
1:
burro = display.getProject().getLoader().importGrid(layer, path);
break;
case // sequence as grid
2:
burro = display.getProject().getLoader().importSequenceAsGrid(layer, path);
break;
}
} else {
layer.getParent().addLayerContentStep(layer);
// single image file (single image or a stack)
burro = display.getProject().getLoader().importImage(layer, point.x, point.y, path, false);
}
if (null != burro) {
burro.addPostTask(new Runnable() {
public void run() {
// The current state
layer.getParent().addLayerContentStep(layer);
}
});
}
return true;
} else {
Utils.log("File not found: " + path);
return false;
}
}
use of ini.trakem2.utils.Filter in project TrakEM2 by trakem2.
the class Compare method variabilityAnalysis.
/**
* @param reference_project If null, then the first one found in the Project.getProjects() lists is used.
* @param regex A String (can be null) to filter objects by, to limit what gets processed.
* If regex is not null, then only ProjectThing nodes with the matching regex are analyzed (shallow: none of their children are questioned, but pipes will be built from them all).
* @param generate_plots Whether to generate the variability plots at all.
* @param show_plots If generate_plots, whether to show the plots in a stack image window or to save them.
* @param show_3D Whether to show any 3D data.
* @param show_condensed_3D If show_3D, whether to show the condensed vector strings, i.e. the "average" pipes.
* @param show_sources_3D If show_3D, whether to show the source pipes from which the condensed vector string was generated.
* @param sources_color_table Which colors to give to the pipes of which Project.
* @param show_envelope_3D If show_3D, whether to generate the variability envelope.
* @param envelope_alpha If show_envelope_3D, the envelope takes an alpha value between 0 (total transparency) and 1 (total opacity)
* @param delta_envelope The delta to resample the envelope to. When smaller than or equal to 1, no envelope resampling occurs.
* @param show_axes_3D If show_3D, whether to display the reference axes as well.
* @param heat_map If show_3D, whether to color the variability with a Fire LUT.
* If not show_condensed_3D, then the variability is shown in color-coded 3D spheres placed at the entry point to the neuropile.
* @param map_condensed If not null, all VectorString3D are put into this map.
* @param projects The projects to use.
*/
public static Bureaucrat variabilityAnalysis(final Project reference_project, final String regex, final String[] ignore, final boolean show_cata_dialog, final boolean generate_plots, final boolean show_plots, final String plot_dir_, final boolean show_3D, final boolean show_condensed_3D, final boolean show_sources_3D, final Map<Project, Color> sources_color_table, final boolean show_envelope_3D, final float envelope_alpha, final double delta_envelope, final int envelope_type, final boolean show_axes_3D, final boolean heat_map, final Map<String, VectorString3D> map_condensed, final Project[] projects) {
// gather all open projects
final Project[] p = null == projects ? Project.getProjects().toArray(new Project[0]) : projects;
// make the reference_project be the first in the array
if (null != reference_project && reference_project != p[0]) {
for (int i = 0; i < p.length; i++) {
if (reference_project == p[i]) {
p[i] = p[0];
p[0] = reference_project;
break;
}
}
}
final Worker worker = new Worker("Comparing all to all") {
@Override
public void run() {
startedWorking();
try {
Utils.log2("Asking for CATAParameters...");
final CATAParameters cp = new CATAParameters();
cp.regex = regex;
cp.delta_envelope = delta_envelope;
cp.envelope_type = envelope_type;
if (show_cata_dialog && !cp.setup(false, regex, true, true)) {
finishedWorking();
return;
}
// so source points are stored in VectorString3D for each resampled and interpolated point
cp.with_source = true;
// Store a series of results, depending on options
final HashMap<String, Display3D> results = new HashMap<String, Display3D>();
String plot_dir = plot_dir_;
if (generate_plots && !show_plots) {
// Save plots
if (null == plot_dir) {
final DirectoryChooser dc = new DirectoryChooser("Choose plots directory");
plot_dir = dc.getDirectory();
if (null == plot_dir) {
finishedWorking();
return;
}
}
if (IJ.isWindows())
plot_dir = plot_dir.replace('\\', '/');
if (!plot_dir.endsWith("/"))
plot_dir += "/";
}
Utils.log2("Gathering chains...");
// Gather chains that do not match the ignore regexes
// will transform them as well to the reference found in the first project in the p array
Object[] ob = gatherChains(p, cp, ignore);
ArrayList<Chain> chains = (ArrayList<Chain>) ob[0];
// to keep track of each project's chains
final ArrayList[] p_chains = (ArrayList[]) ob[1];
ob = null;
if (null == chains) {
finishedWorking();
return;
}
Utils.log2("Collecting bundles...");
final HashMap<Project, HashMap<String, VectorString3D>> axes = new HashMap<Project, HashMap<String, VectorString3D>>();
// Sort out into groups by unique names of lineage bundles
final HashMap<String, ArrayList<Chain>> bundles = new HashMap<String, ArrayList<Chain>>();
for (final Chain chain : chains) {
String title = chain.getCellTitle();
final String t = title.toLowerCase();
// unnamed
if (0 == t.indexOf('[') || 0 == t.indexOf('#'))
continue;
Utils.log("Accepting " + title);
title = title.substring(0, title.indexOf(' '));
// lineage bundle instance chains
ArrayList<Chain> bc = bundles.get(title);
if (null == bc) {
bc = new ArrayList<Chain>();
bundles.put(title, bc);
}
bc.add(chain);
}
Utils.log2("Found " + bundles.size() + " bundles.");
chains = null;
if (null != cp.regex && show_axes_3D && axes.size() < 3) {
// Must find the Mushroom Body lobes separately
final String cp_regex = cp.regex;
cp.regex = "mb";
final Object[] o = gatherChains(p, cp, ignore);
final ArrayList<Chain> lobes = (ArrayList<Chain>) o[0];
Utils.logAll("Found " + lobes.size() + " chains for lobes");
for (final Chain chain : lobes) {
final String t = chain.getCellTitle().toLowerCase();
if (-1 != t.indexOf("peduncle") || -1 != t.indexOf("medial lobe") || -1 != t.indexOf("dorsal lobe")) {
Utils.logAll("adding " + t);
final Project pr = chain.pipes.get(0).getProject();
HashMap<String, VectorString3D> m = axes.get(pr);
if (null == m) {
m = new HashMap<String, VectorString3D>();
axes.put(pr, m);
}
m.put(t, chain.vs);
continue;
}
}
cp.regex = cp_regex;
} else {
Utils.logAll("Not: cp.regex = " + cp.regex + " show_axes_3D = " + show_axes_3D + " axes.size() = " + axes.size());
}
final HashMap<String, VectorString3D> condensed = new HashMap<String, VectorString3D>();
Utils.log2("Condensing each bundle...");
// Condense each into a single VectorString3D
for (final Map.Entry<String, ArrayList<Chain>> entry : bundles.entrySet()) {
final ArrayList<Chain> bc = entry.getValue();
if (bc.size() < 2) {
Utils.log2("Skipping single: " + entry.getKey());
continue;
}
final VectorString3D[] vs = new VectorString3D[bc.size()];
for (int i = 0; i < vs.length; i++) vs[i] = bc.get(i).vs;
final VectorString3D c = condense(cp, vs, this);
c.setCalibration(p[0].getRootLayerSet().getCalibrationCopy());
condensed.put(entry.getKey(), c);
if (this.hasQuitted())
return;
}
// Store:
if (null != map_condensed) {
map_condensed.putAll(condensed);
}
if (generate_plots) {
Utils.log2("Plotting stdDev for each condensed bundle...");
// Y axis: the stdDev at each point, computed from the group of points that contribute to each
for (final Map.Entry<String, VectorString3D> e : condensed.entrySet()) {
final String name = e.getKey();
final VectorString3D c = e.getValue();
final Plot plot = makePlot(cp, name, c);
// FAILS//plot.addLabel(10, cp.plot_height-5, name); // must be added after setting size
if (show_plots)
plot.show();
else if (null != plot_dir)
new FileSaver(plot.getImagePlus()).saveAsPng(plot_dir + name.replace('/', '-') + ".png");
}
}
if (show_3D) {
final HashMap<String, Color> heat_table = new HashMap<String, Color>();
if (heat_map || show_envelope_3D) {
// Create a Fire LUT
final ImagePlus lutimp = new ImagePlus("lut", new ByteProcessor(4, 4));
IJ.run(lutimp, "Fire", "");
final IndexColorModel icm = (IndexColorModel) lutimp.getProcessor().getColorModel();
final byte[] reds = new byte[256];
final byte[] greens = new byte[256];
final byte[] blues = new byte[256];
icm.getReds(reds);
icm.getGreens(greens);
icm.getBlues(blues);
final List<String> names = new ArrayList<String>(bundles.keySet());
Collections.sort(names);
// find max stdDev
double max = 0;
final HashMap<String, Double> heats = new HashMap<String, Double>();
for (final String name : names) {
final VectorString3D vs_merged = condensed.get(name);
if (null == vs_merged) {
Utils.logAll("WARNING could not find a condensed pipe for " + name);
continue;
}
final double[] stdDev = vs_merged.getStdDevAtEachPoint();
// double avg = 0;
// for (int i=0; i<stdDev.length; i++) avg += stdDev[i];
// avg = avg/stdDev.length;
Arrays.sort(stdDev);
// median is more representative than average
final double median = stdDev[stdDev.length / 2];
if (max < median)
max = median;
heats.put(name, median);
}
for (final Map.Entry<String, Double> e : heats.entrySet()) {
final String name = e.getKey();
final double median = e.getValue();
// scale between 0 and max to get a Fire LUT color:
int index = (int) ((median / max) * 255);
if (index > 255)
index = 255;
final Color color = new Color(0xff & reds[index], 0xff & greens[index], 0xff & blues[index]);
Utils.log2(new StringBuilder(name).append('\t').append(median).append('\t').append(reds[index]).append('\t').append(greens[index]).append('\t').append(blues[index]).toString());
heat_table.put(name, color);
}
}
final LayerSet common_ls = new LayerSet(p[0], -1, "Common", 10, 10, 0, 0, 0, 512, 512, false, 2, new AffineTransform());
final Display3D d3d = Display3D.get(common_ls);
float env_alpha = envelope_alpha;
if (env_alpha < 0) {
Utils.log2("WARNING envelope_alpha is invalid: " + envelope_alpha + "\n Using 0.4f instead");
env_alpha = 0.4f;
} else if (env_alpha > 1)
env_alpha = 1.0f;
for (final String name : bundles.keySet()) {
final ArrayList<Chain> bc = bundles.get(name);
final VectorString3D vs_merged = condensed.get(name);
if (null == vs_merged) {
Utils.logAll("WARNING: could not find a condensed vs for " + name);
continue;
}
if (show_sources_3D) {
if (null != sources_color_table) {
final HashSet<String> titles = new HashSet<String>();
for (final Chain chain : bc) {
final Color c = sources_color_table.get(chain.getRoot().getProject());
final String title = chain.getCellTitle();
String t = title;
int i = 2;
while (titles.contains(t)) {
t = title + "-" + i;
i += 1;
}
titles.add(t);
Display3D.addMesh(common_ls, chain.vs, t, null != c ? c : Color.gray);
}
} else {
for (final Chain chain : bc) Display3D.addMesh(common_ls, chain.vs, chain.getCellTitle(), Color.gray);
}
}
if (show_condensed_3D) {
Display3D.addMesh(common_ls, vs_merged, name + "-condensed", heat_map ? heat_table.get(name) : Color.red);
}
if (show_envelope_3D) {
double[] widths = makeEnvelope(cp, vs_merged);
if (cp.delta_envelope > 1) {
vs_merged.addDependent(widths);
vs_merged.resample(cp.delta_envelope);
widths = vs_merged.getDependent(0);
}
Display3D.addMesh(common_ls, vs_merged, name + "-envelope", heat_map ? heat_table.get(name) : Color.red, widths, env_alpha);
} else if (heat_map) {
// Show spheres in place of envelopes, at the starting tip (neuropile entry point)
final double x = vs_merged.getPoints(0)[0];
final double y = vs_merged.getPoints(1)[0];
final double z = vs_merged.getPoints(2)[0];
final double r = 10;
final Color color = heat_table.get(name);
if (null == color) {
Utils.logAll("WARNING: heat table does not have a color for " + name);
continue;
}
final Content sphere = d3d.getUniverse().addMesh(ij3d.Mesh_Maker.createSphere(x, y, z, r), new Color3f(heat_table.get(name)), name + "-sphere", 1);
}
}
if (show_axes_3D) {
for (int i = 0; i < p.length; i++) {
final Map<String, VectorString3D> m = axes.get(p[i]);
if (null == m) {
Utils.log2("No axes found for project " + p[i]);
continue;
}
for (final Map.Entry<String, VectorString3D> e : m.entrySet()) {
Display3D.addMesh(common_ls, e.getValue(), e.getKey() + "-" + i, Color.gray);
}
}
}
results.put("d3d", Display3D.get(common_ls));
}
this.result = results;
Utils.log2("Done.");
} catch (final Exception e) {
IJError.print(e);
} finally {
finishedWorking();
}
}
};
return Bureaucrat.createAndStart(worker, p[0]);
}
Aggregations