use of ini.trakem2.utils.Montage in project TrakEM2 by trakem2.
the class Display method getPopupMenu.
/**
* Return a context-sensitive popup menu.
*/
protected JPopupMenu getPopupMenu() {
// get the job canceling dialog
if (!canvas.isInputEnabled()) {
return project.getLoader().getJobsPopup(this);
}
// create new
this.popup = new JPopupMenu();
JMenuItem item = null;
JMenu menu = null;
if (mode instanceof InspectPatchTrianglesMode) {
item = new JMenuItem("Exit inspection");
item.addActionListener(this);
popup.add(item);
item.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_ESCAPE, 0, true));
return popup;
} else if (canvas.isTransforming()) {
item = new JMenuItem("Apply transform");
item.addActionListener(this);
popup.add(item);
// dummy, for I don't add a MenuKeyListener, but "works" through the normal key listener. It's here to provide a visual cue
item.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_ENTER, 0, true));
item = new JMenuItem("Apply transform propagating to last layer");
item.addActionListener(this);
popup.add(item);
if (layer.getParent().indexOf(layer) == layer.getParent().size() - 1)
item.setEnabled(false);
if (!(getMode().getClass() == AffineTransformMode.class || getMode().getClass() == NonLinearTransformMode.class))
item.setEnabled(false);
item = new JMenuItem("Apply transform propagating to first layer");
item.addActionListener(this);
popup.add(item);
if (0 == layer.getParent().indexOf(layer))
item.setEnabled(false);
if (!(getMode().getClass() == AffineTransformMode.class || getMode().getClass() == NonLinearTransformMode.class))
item.setEnabled(false);
item = new JMenuItem("Cancel transform");
item.addActionListener(this);
popup.add(item);
item.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_ESCAPE, 0, true));
item = new JMenuItem("Specify transform...");
item.addActionListener(this);
popup.add(item);
if (getMode().getClass() != AffineTransformMode.class)
item.setEnabled(false);
if (getMode().getClass() == ManualAlignMode.class) {
final JMenuItem lexport = new JMenuItem("Export landmarks");
popup.add(lexport);
final JMenuItem limport = new JMenuItem("Import landmarks");
popup.add(limport);
final ActionListener a = new ActionListener() {
@Override
public void actionPerformed(final ActionEvent ae) {
final ManualAlignMode mam = (ManualAlignMode) getMode();
final Object source = ae.getSource();
if (lexport == source) {
mam.exportLandmarks();
} else if (limport == source) {
mam.importLandmarks();
}
}
};
lexport.addActionListener(a);
limport.addActionListener(a);
}
return popup;
}
final Class<?> aclass = null == active ? null : active.getClass();
if (null != active) {
if (Profile.class == aclass) {
item = new JMenuItem("Duplicate, link and send to next layer");
item.addActionListener(this);
popup.add(item);
Layer nl = layer.getParent().next(layer);
if (nl == layer)
item.setEnabled(false);
item = new JMenuItem("Duplicate, link and send to previous layer");
item.addActionListener(this);
popup.add(item);
nl = layer.getParent().previous(layer);
if (nl == layer)
item.setEnabled(false);
menu = new JMenu("Duplicate, link and send to");
int i = 1;
for (final Layer la : layer.getParent().getLayers()) {
// TODO should label which layers contain Profile instances linked to the one being duplicated
item = new JMenuItem(i + ": z = " + la.getZ());
// TODO should label which layers contain Profile instances linked to the one being duplicated
item.addActionListener(this);
// TODO should label which layers contain Profile instances linked to the one being duplicated
menu.add(item);
if (la == this.layer)
item.setEnabled(false);
i++;
}
popup.add(menu);
item = new JMenuItem("Duplicate, link and send to...");
item.addActionListener(this);
popup.add(item);
popup.addSeparator();
item = new JMenuItem("Unlink from images");
item.addActionListener(this);
popup.add(item);
// isLinked() checks if it's linked to a Patch in its own layer
if (!active.isLinked())
item.setEnabled(false);
item = new JMenuItem("Show in 3D");
item.addActionListener(this);
popup.add(item);
popup.addSeparator();
} else if (Patch.class == aclass) {
final JMenu m = new JMenu("Patch");
item = new JMenuItem("Fill ROI in alpha mask");
item.addActionListener(this);
m.add(item);
item.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_F, 0));
item.setEnabled(null != getRoi());
item = new JMenuItem("Fill inverse ROI in alpha mask");
item.addActionListener(this);
m.add(item);
item.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_F, Event.SHIFT_MASK));
item.setEnabled(null != getRoi());
item = new JMenuItem("Remove alpha mask");
item.addActionListener(this);
m.add(item);
if (!((Patch) active).hasAlphaMask())
item.setEnabled(false);
item = new JMenuItem("Unlink from images");
item.addActionListener(this);
m.add(item);
if (!active.isLinked(Patch.class))
item.setEnabled(false);
if (((Patch) active).isStack()) {
item = new JMenuItem("Unlink slices");
item.addActionListener(this);
m.add(item);
}
final int n_sel_patches = selection.getSelected(Patch.class).size();
item = new JMenuItem("Snap");
item.addActionListener(this);
m.add(item);
item.setEnabled(1 == n_sel_patches);
item = new JMenuItem("Montage");
item.addActionListener(this);
m.add(item);
item.setEnabled(n_sel_patches > 1);
item = new JMenuItem("Lens correction");
item.addActionListener(this);
m.add(item);
item.setEnabled(n_sel_patches > 1);
item = new JMenuItem("Blend");
item.addActionListener(this);
m.add(item);
item.setEnabled(n_sel_patches > 1);
item = new JMenuItem("Open image");
item.addActionListener(new ActionListener() {
@Override
public void actionPerformed(final ActionEvent e) {
for (final Patch p : selection.get(Patch.class)) {
p.getImagePlus().show();
}
}
});
m.add(item);
item.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_D, KeyEvent.SHIFT_MASK, true));
item = new JMenuItem("Open original image");
item.addActionListener(new ActionListener() {
@Override
public void actionPerformed(final ActionEvent e) {
for (final Patch p : selection.get(Patch.class)) {
p.getProject().getLoader().releaseToFit(p.getOWidth(), p.getOHeight(), p.getType(), 5);
p.getProject().getLoader().openImagePlus(p.getImageFilePath()).show();
}
}
});
item = new JMenuItem("View volume");
item.addActionListener(this);
m.add(item);
final HashSet<Displayable> hs = active.getLinked(Patch.class);
if (null == hs || 0 == hs.size())
item.setEnabled(false);
item = new JMenuItem("View orthoslices");
item.addActionListener(this);
m.add(item);
// if no Patch instances among the directly linked, then it's not a stack
if (null == hs || 0 == hs.size())
item.setEnabled(false);
popup.add(m);
popup.addSeparator();
} else {
item = new JMenuItem("Unlink");
item.addActionListener(this);
popup.add(item);
item = new JMenuItem("Show in 3D");
item.addActionListener(this);
popup.add(item);
popup.addSeparator();
}
if (AreaList.class == aclass) {
final ArrayList<?> al = selection.getSelected();
int n = 0;
for (final Iterator<?> it = al.iterator(); it.hasNext(); ) {
if (it.next().getClass() == AreaList.class)
n++;
}
item = new JMenuItem("Merge");
item.addActionListener(this);
popup.add(item);
if (n < 2)
item.setEnabled(false);
item = new JMenuItem("Split");
item.addActionListener(this);
popup.add(item);
if (n < 1)
item.setEnabled(false);
addAreaListAreasMenu(popup, active);
popup.addSeparator();
} else if (Pipe.class == aclass) {
item = new JMenuItem("Reverse point order");
item.addActionListener(this);
popup.add(item);
popup.addSeparator();
} else if (Treeline.class == aclass || AreaTree.class == aclass) {
if (AreaTree.class == aclass)
addAreaTreeAreasMenu(popup, (AreaTree) active);
item = new JMenuItem("Reroot");
item.addActionListener(this);
popup.add(item);
item = new JMenuItem("Part subtree");
item.addActionListener(this);
popup.add(item);
item = new JMenuItem("Join");
item.addActionListener(this);
popup.add(item);
item = new JMenuItem("Show tabular view");
item.addActionListener(this);
popup.add(item);
final Collection<Tree> trees = selection.get(Tree.class);
//
final JMenu nodeMenu = new JMenu("Nodes");
item = new JMenuItem("Mark");
item.addActionListener(this);
nodeMenu.add(item);
item = new JMenuItem("Clear marks (selected Trees)");
item.addActionListener(this);
nodeMenu.add(item);
final JMenuItem nodeColor = new JMenuItem("Color...");
nodeMenu.add(nodeColor);
nodeColor.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_C, KeyEvent.SHIFT_MASK, true));
final JMenuItem nodePairColor = new JMenuItem("Color path between two nodes tagged as...");
nodeMenu.add(nodePairColor);
final JMenuItem nodeRadius = active instanceof Treeline ? new JMenuItem("Radius...") : null;
if (null != nodeRadius) {
nodeMenu.add(nodeRadius);
nodeRadius.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_O, 0, true));
}
final JMenuItem removeAllTags = new JMenuItem("Drop all tags (selected trees)");
nodeMenu.add(removeAllTags);
final JMenuItem removeTag = new JMenuItem("Drop all occurrences of tag...");
nodeMenu.add(removeTag);
final JMenuItem colorizeByNodeCentrality = new JMenuItem("Colorize by node betweenness centrality");
nodeMenu.add(colorizeByNodeCentrality);
final JMenuItem colorizeByBranchCentrality = new JMenuItem("Colorize by branch betweenness centrality");
nodeMenu.add(colorizeByBranchCentrality);
popup.add(nodeMenu);
final ActionListener ln = new ActionListener() {
@Override
public void actionPerformed(final ActionEvent ae) {
if (null == active) {
Utils.showMessage("No tree selected!");
return;
}
if (!(active instanceof Tree)) {
Utils.showMessage("The selected object is not a Tree!");
return;
}
final Tree tree = (Tree) active;
final Object src = ae.getSource();
//
if (src == nodeColor) {
final Node nd = tree.getLastVisited();
if (null == nd) {
Utils.showMessage("Select a node first by clicking on it\nor moving the mouse over it and pushing 'g'.");
return;
}
// sets an undo step
tree.adjustNodeColors(nd);
} else if (src == nodePairColor) {
final TreeMap<String, Tag> sm = getTags(tree);
if (null == sm)
return;
if (1 == sm.size()) {
Utils.showMessage("Need at least two different tags in the tree!");
return;
}
final Color color = tree.getColor();
final GenericDialog gd = new GenericDialog("Node colors");
gd.addSlider("Red: ", 0, 255, color.getRed());
gd.addSlider("Green: ", 0, 255, color.getGreen());
gd.addSlider("Blue: ", 0, 255, color.getBlue());
final String[] stags = asStrings(sm);
sm.keySet().toArray(stags);
gd.addChoice("Upstream tag:", stags, stags[0]);
gd.addChoice("Downstream tag:", stags, stags[1]);
gd.showDialog();
if (gd.wasCanceled())
return;
final Color newColor = new Color((int) gd.getNextNumber(), (int) gd.getNextNumber(), (int) gd.getNextNumber());
final Tag upstreamTag = sm.get(gd.getNextChoice());
final Tag downstreamTag = sm.get(gd.getNextChoice());
final List<Tree<?>.NodePath> pairs = tree.findTaggedPairs(upstreamTag, downstreamTag);
if (null == pairs || pairs.isEmpty()) {
Utils.showMessage("No pairs found for '" + upstreamTag + "' and '" + downstreamTag + "'");
return;
}
getLayerSet().addDataEditStep(tree);
for (final Tree<?>.NodePath pair : pairs) {
for (final Node<?> nd : pair.path) {
nd.setColor(newColor);
}
}
getLayerSet().addDataEditStep(tree);
Display.repaint();
} else if (src == nodeRadius) {
if (!(tree instanceof Treeline))
return;
final Node nd = tree.getLastVisited();
if (null == nd) {
Utils.showMessage("Select a node first by clicking on it\nor moving the mouse over it and pushing 'g'.");
return;
}
// sets an undo step
((Treeline) tree).askAdjustRadius(nd);
} else if (src == removeAllTags) {
if (!Utils.check("Really remove all tags from all selected trees?"))
return;
final List<Tree> sel = selection.get(Tree.class);
getLayerSet().addDataEditStep(new HashSet<Displayable>(sel));
try {
for (final Tree t : sel) {
t.dropAllTags();
}
// current state
getLayerSet().addDataEditStep(new HashSet<Displayable>(sel));
} catch (final Exception e) {
getLayerSet().undoOneStep();
IJError.print(e);
}
Display.repaint();
} else if (src == removeTag) {
final TreeMap<String, Tag> tags = getTags(tree);
final String[] ts = asStrings(tags);
final GenericDialog gd = new GenericDialog("Remove tags");
gd.addChoice("Tag:", ts, ts[0]);
final String[] c = new String[] { "Active tree", "All selected trees and connectors", "All trees and connectors" };
gd.addChoice("From: ", c, c[0]);
gd.showDialog();
if (gd.wasCanceled())
return;
final HashSet<Displayable> ds = new HashSet<Displayable>();
final Tag tag = tags.get(gd.getNextChoice());
switch(gd.getNextChoiceIndex()) {
case 0:
ds.add(tree);
break;
case 1:
ds.addAll(selection.get(Tree.class));
case 2:
ds.addAll(getLayerSet().getZDisplayables(Tree.class, true));
}
getLayerSet().addDataEditStep(ds);
try {
for (final Displayable d : ds) {
final Tree t = (Tree) d;
t.removeTag(tag);
}
getLayerSet().addDataEditStep(ds);
} catch (final Exception e) {
getLayerSet().undoOneStep();
IJError.print(e);
}
Display.repaint();
} else if (src == colorizeByNodeCentrality) {
final List<Tree> ts = selection.get(Tree.class);
final HashSet<Tree> ds = new HashSet<Tree>(ts);
getLayerSet().addDataEditStep(ds);
try {
for (final Tree t : ts) {
t.colorizeByNodeBetweennessCentrality();
}
getLayerSet().addDataEditStep(ds);
Display.repaint();
} catch (final Exception e) {
getLayerSet().undoOneStep();
IJError.print(e);
}
} else if (src == colorizeByBranchCentrality) {
final List<Tree> ts = selection.get(Tree.class);
final HashSet<Tree> ds = new HashSet<Tree>(ts);
getLayerSet().addDataEditStep(ds);
try {
for (final Tree t : ts) {
t.colorizeByBranchBetweennessCentrality(2);
}
getLayerSet().addDataEditStep(ds);
Display.repaint();
} catch (final Exception e) {
getLayerSet().undoOneStep();
IJError.print(e);
}
}
}
};
for (final JMenuItem a : new JMenuItem[] { nodeColor, nodePairColor, nodeRadius, removeAllTags, removeTag, colorizeByNodeCentrality, colorizeByBranchCentrality }) {
if (null == a)
continue;
a.addActionListener(ln);
}
//
final JMenu review = new JMenu("Review");
final JMenuItem tgenerate = new JMenuItem("Generate review stacks (selected Trees)");
review.add(tgenerate);
tgenerate.setEnabled(trees.size() > 0);
final JMenuItem tslab = new JMenuItem("Generate review stack for current slab");
review.add(tslab);
final JMenuItem tsubtree = new JMenuItem("Generate review stacks for subtree");
review.add(tsubtree);
final JMenuItem tremove = new JMenuItem("Remove reviews (selected Trees)");
review.add(tremove);
tremove.setEnabled(trees.size() > 0);
final JMenuItem tconnectors = new JMenuItem("View table of outgoing/incoming connectors");
review.add(tconnectors);
final ActionListener l = new ActionListener() {
@Override
public void actionPerformed(final ActionEvent ae) {
if (!Utils.check("Really " + ae.getActionCommand())) {
return;
}
dispatcher.exec(new Runnable() {
@Override
public void run() {
int count = 0;
for (final Tree<?> t : trees) {
Utils.log("Processing " + (++count) + "/" + trees.size());
Bureaucrat bu = null;
if (ae.getSource() == tgenerate)
bu = t.generateAllReviewStacks();
else if (ae.getSource() == tremove)
bu = t.removeReviews();
else if (ae.getSource() == tslab) {
final Point po = canvas.consumeLastPopupPoint();
Utils.log2(po, layer, 1.0);
bu = t.generateReviewStackForSlab(po.x, po.y, Display.this.layer, 1.0);
} else if (ae.getSource() == tsubtree) {
final Point po = canvas.consumeLastPopupPoint();
bu = t.generateSubtreeReviewStacks(po.x, po.y, Display.this.layer, 1.0);
}
if (null != bu)
try {
bu.getWorker().join();
} catch (final InterruptedException ie) {
return;
}
}
}
});
}
};
for (final JMenuItem c : new JMenuItem[] { tgenerate, tslab, tsubtree, tremove }) c.addActionListener(l);
tconnectors.addActionListener(new ActionListener() {
@Override
public void actionPerformed(final ActionEvent ae) {
for (final Tree<?> t : trees) TreeConnectorsView.create(t);
}
});
popup.add(review);
final JMenu go = new JMenu("Go");
item = new JMenuItem("Previous branch node or start");
item.addActionListener(this);
go.add(item);
item.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_B, 0, true));
item = new JMenuItem("Next branch node or end");
item.addActionListener(this);
go.add(item);
item.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_N, 0, true));
item = new JMenuItem("Root");
item.addActionListener(this);
go.add(item);
item.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_R, 0, true));
go.addSeparator();
item = new JMenuItem("Last added node");
item.addActionListener(this);
go.add(item);
item.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_L, 0, true));
item = new JMenuItem("Last edited node");
item.addActionListener(this);
go.add(item);
item.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_E, 0, true));
popup.add(go);
final JMenu tmeasure = new JMenu("Measure");
final JMenuItem dist_to_root = new JMenuItem("Distance from this node to root");
tmeasure.add(dist_to_root);
final JMenuItem dist_to_tag = new JMenuItem("Distance from this node to all nodes tagged as...");
tmeasure.add(dist_to_tag);
final JMenuItem dist_to_mark = new JMenuItem("Distance from this node to the marked node");
tmeasure.add(dist_to_mark);
final JMenuItem dist_pairs = new JMenuItem("Shortest distances between all pairs of nodes tagged as...");
tmeasure.add(dist_pairs);
final ActionListener tma = getTreePathMeasureListener((Tree<?>) active);
for (final JMenuItem mi : new JMenuItem[] { dist_to_root, dist_to_tag, dist_to_mark, dist_pairs }) {
mi.addActionListener(tma);
}
popup.add(tmeasure);
final String[] name = new String[] { AreaTree.class.getSimpleName(), Treeline.class.getSimpleName() };
if (Treeline.class == aclass) {
final String a = name[0];
name[0] = name[1];
name[1] = a;
}
item = new JMenuItem("Duplicate " + name[0] + " as " + name[1]);
item.addActionListener(new ActionListener() {
@Override
public void actionPerformed(final ActionEvent e) {
Bureaucrat.createAndStart(new Worker.Task("Converting") {
@Override
public void exec() {
try {
getLayerSet().addChangeTreesStep();
final Map<Tree<?>, Tree<?>> m = Tree.duplicateAs(selection.getSelected(), (Class<Tree<?>>) (Treeline.class == aclass ? AreaTree.class : Treeline.class));
if (m.isEmpty()) {
getLayerSet().removeLastUndoStep();
} else {
getLayerSet().addChangeTreesStep();
}
} catch (final Exception e) {
IJError.print(e);
}
}
}, getProject());
}
});
popup.add(item);
popup.addSeparator();
} else if (Connector.class == aclass) {
item = new JMenuItem("Merge");
item.addActionListener(new ActionListener() {
@Override
public void actionPerformed(final ActionEvent ae) {
if (null == getActive() || getActive().getClass() != Connector.class) {
Utils.log("Active object must be a Connector!");
return;
}
final List<Connector> col = selection.get(Connector.class);
if (col.size() < 2) {
Utils.log("Select more than one Connector!");
return;
}
if (col.get(0) != getActive()) {
if (col.remove(getActive())) {
col.add(0, (Connector) getActive());
} else {
Utils.log("ERROR: cannot find active object in selection list!");
return;
}
}
Bureaucrat.createAndStart(new Worker.Task("Merging connectors") {
@Override
public void exec() {
getLayerSet().addChangeTreesStep();
Connector base = null;
try {
base = Connector.merge(col);
} catch (final Exception e) {
IJError.print(e);
}
if (null == base) {
Utils.log("ERROR: could not merge connectors!");
getLayerSet().undoOneStep();
} else {
getLayerSet().addChangeTreesStep();
}
Display.repaint();
}
}, getProject());
}
});
popup.add(item);
item.setEnabled(selection.getSelected(Connector.class).size() > 1);
popup.addSeparator();
}
item = new JMenuItem("Duplicate");
item.addActionListener(this);
popup.add(item);
item = new JMenuItem("Color...");
item.addActionListener(this);
popup.add(item);
if (active instanceof LayerSet)
item.setEnabled(false);
if (active.isLocked()) {
item = new JMenuItem("Unlock");
item.addActionListener(this);
popup.add(item);
} else {
item = new JMenuItem("Lock");
item.addActionListener(this);
popup.add(item);
}
menu = new JMenu("Move");
popup.addSeparator();
final LayerSet ls = layer.getParent();
item = new JMenuItem("Move to top");
item.addActionListener(this);
menu.add(item);
// this is just to draw the key name by the menu; it does not incur on any event being generated (that I know if), and certainly not any event being listened to by TrakEM2.
item.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_HOME, 0, true));
if (ls.isTop(active))
item.setEnabled(false);
item = new JMenuItem("Move up");
item.addActionListener(this);
menu.add(item);
item.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_PAGE_UP, 0, true));
if (ls.isTop(active))
item.setEnabled(false);
item = new JMenuItem("Move down");
item.addActionListener(this);
menu.add(item);
item.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_PAGE_DOWN, 0, true));
if (ls.isBottom(active))
item.setEnabled(false);
item = new JMenuItem("Move to bottom");
item.addActionListener(this);
menu.add(item);
item.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_END, 0, true));
if (ls.isBottom(active))
item.setEnabled(false);
popup.add(menu);
popup.addSeparator();
item = new JMenuItem("Delete...");
item.addActionListener(this);
popup.add(item);
try {
if (Patch.class == aclass) {
if (!active.isOnlyLinkedTo(Patch.class)) {
item.setEnabled(false);
}
}
} catch (final Exception e) {
IJError.print(e);
item.setEnabled(false);
}
if (Patch.class == aclass) {
item = new JMenuItem("Revert");
item.addActionListener(this);
popup.add(item);
if (null == ((Patch) active).getOriginalPath())
item.setEnabled(false);
popup.addSeparator();
}
item = new JMenuItem("Properties...");
item.addActionListener(this);
popup.add(item);
item = new JMenuItem("Show centered");
item.addActionListener(this);
popup.add(item);
popup.addSeparator();
if (!(active instanceof ZDisplayable)) {
final int i_layer = layer.getParent().indexOf(layer);
final int n_layers = layer.getParent().size();
item = new JMenuItem("Send to previous layer");
item.addActionListener(this);
popup.add(item);
if (1 == n_layers || 0 == i_layer || active.isLinked())
item.setEnabled(false);
else // check if the active is a profile and contains a link to another profile in the layer it is going to be sent to, or it is linked
if (active instanceof Profile && !active.canSendTo(layer.getParent().previous(layer)))
item.setEnabled(false);
item = new JMenuItem("Send to next layer");
item.addActionListener(this);
popup.add(item);
if (1 == n_layers || n_layers - 1 == i_layer || active.isLinked())
item.setEnabled(false);
else if (active instanceof Profile && !active.canSendTo(layer.getParent().next(layer)))
item.setEnabled(false);
menu = new JMenu("Send linked group to...");
if (active.hasLinkedGroupWithinLayer(this.layer)) {
int i = 1;
for (final Layer la : ls.getLayers()) {
String layer_title = i + ": " + la.getTitle();
if (-1 == layer_title.indexOf(' '))
layer_title += " ";
item = new JMenuItem(layer_title);
item.addActionListener(this);
menu.add(item);
if (la == this.layer)
item.setEnabled(false);
i++;
}
popup.add(menu);
} else {
menu.setEnabled(false);
// Utils.log("Active's linked group not within layer.");
}
popup.add(menu);
popup.addSeparator();
}
}
item = new JMenuItem("Undo");
item.addActionListener(this);
popup.add(item);
if (!layer.getParent().canUndo() || canvas.isTransforming())
item.setEnabled(false);
item.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_Z, Utils.getControlModifier(), true));
item = new JMenuItem("Redo");
item.addActionListener(this);
popup.add(item);
if (!layer.getParent().canRedo() || canvas.isTransforming())
item.setEnabled(false);
item.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_Z, Event.SHIFT_MASK | Utils.getControlModifier(), true));
popup.addSeparator();
try {
menu = new JMenu("Hide/Unhide");
item = new JMenuItem("Hide deselected");
item.addActionListener(this);
menu.add(item);
item.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_H, Event.SHIFT_MASK, true));
boolean none = 0 == selection.getNSelected();
if (none)
item.setEnabled(false);
item = new JMenuItem("Hide deselected except images");
item.addActionListener(this);
menu.add(item);
item.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_H, Event.SHIFT_MASK | Event.ALT_MASK, true));
if (none)
item.setEnabled(false);
item = new JMenuItem("Hide selected");
item.addActionListener(this);
menu.add(item);
item.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_H, 0, true));
if (none)
item.setEnabled(false);
none = !layer.getParent().containsDisplayable(DLabel.class);
item = new JMenuItem("Hide all labels");
item.addActionListener(this);
menu.add(item);
if (none)
item.setEnabled(false);
item = new JMenuItem("Unhide all labels");
item.addActionListener(this);
menu.add(item);
if (none)
item.setEnabled(false);
none = !layer.getParent().contains(AreaList.class);
item = new JMenuItem("Hide all arealists");
item.addActionListener(this);
menu.add(item);
if (none)
item.setEnabled(false);
item = new JMenuItem("Unhide all arealists");
item.addActionListener(this);
menu.add(item);
if (none)
item.setEnabled(false);
none = !layer.contains(Profile.class);
item = new JMenuItem("Hide all profiles");
item.addActionListener(this);
menu.add(item);
if (none)
item.setEnabled(false);
item = new JMenuItem("Unhide all profiles");
item.addActionListener(this);
menu.add(item);
if (none)
item.setEnabled(false);
none = !layer.getParent().contains(Pipe.class);
item = new JMenuItem("Hide all pipes");
item.addActionListener(this);
menu.add(item);
if (none)
item.setEnabled(false);
item = new JMenuItem("Unhide all pipes");
item.addActionListener(this);
menu.add(item);
if (none)
item.setEnabled(false);
none = !layer.getParent().contains(Polyline.class);
item = new JMenuItem("Hide all polylines");
item.addActionListener(this);
menu.add(item);
if (none)
item.setEnabled(false);
item = new JMenuItem("Unhide all polylines");
item.addActionListener(this);
menu.add(item);
if (none)
item.setEnabled(false);
none = !layer.getParent().contains(Treeline.class);
item = new JMenuItem("Hide all treelines");
item.addActionListener(this);
menu.add(item);
if (none)
item.setEnabled(false);
item = new JMenuItem("Unhide all treelines");
item.addActionListener(this);
menu.add(item);
if (none)
item.setEnabled(false);
none = !layer.getParent().contains(AreaTree.class);
item = new JMenuItem("Hide all areatrees");
item.addActionListener(this);
menu.add(item);
if (none)
item.setEnabled(false);
item = new JMenuItem("Unhide all areatrees");
item.addActionListener(this);
menu.add(item);
if (none)
item.setEnabled(false);
none = !layer.getParent().contains(Ball.class);
item = new JMenuItem("Hide all balls");
item.addActionListener(this);
menu.add(item);
if (none)
item.setEnabled(false);
item = new JMenuItem("Unhide all balls");
item.addActionListener(this);
menu.add(item);
if (none)
item.setEnabled(false);
none = !layer.getParent().contains(Connector.class);
item = new JMenuItem("Hide all connectors");
item.addActionListener(this);
menu.add(item);
if (none)
item.setEnabled(false);
item = new JMenuItem("Unhide all connectors");
item.addActionListener(this);
menu.add(item);
if (none)
item.setEnabled(false);
none = !layer.getParent().containsDisplayable(Patch.class);
item = new JMenuItem("Hide all images");
item.addActionListener(this);
menu.add(item);
if (none)
item.setEnabled(false);
item = new JMenuItem("Unhide all images");
item.addActionListener(this);
menu.add(item);
if (none)
item.setEnabled(false);
item = new JMenuItem("Hide all but images");
item.addActionListener(this);
menu.add(item);
item = new JMenuItem("Unhide all");
item.addActionListener(this);
menu.add(item);
item.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_H, Event.ALT_MASK, true));
popup.add(menu);
} catch (final Exception e) {
IJError.print(e);
}
// plugins, if any
Utils.addPlugIns(popup, "Display", project, new Callable<Displayable>() {
@Override
public Displayable call() {
return Display.this.getActive();
}
});
final JMenu align_menu = new JMenu("Align");
item = new JMenuItem("Align stack slices");
item.addActionListener(this);
align_menu.add(item);
if (selection.isEmpty() || !(getActive().getClass() == Patch.class && ((Patch) getActive()).isStack()))
item.setEnabled(false);
item = new JMenuItem("Align layers");
item.addActionListener(this);
align_menu.add(item);
if (1 == layer.getParent().size())
item.setEnabled(false);
item = new JMenuItem("Align layers manually with landmarks");
item.addActionListener(this);
align_menu.add(item);
if (1 == layer.getParent().size())
item.setEnabled(false);
item = new JMenuItem("Align multi-layer mosaic");
item.addActionListener(this);
align_menu.add(item);
if (1 == layer.getParent().size())
item.setEnabled(false);
item = new JMenuItem("Montage all images in this layer");
item.addActionListener(this);
align_menu.add(item);
if (layer.getDisplayables(Patch.class).size() < 2)
item.setEnabled(false);
item = new JMenuItem("Montage selected images");
item.addActionListener(this);
align_menu.add(item);
if (selection.getSelected(Patch.class).size() < 2)
item.setEnabled(false);
item = new JMenuItem("Montage multiple layers");
item.addActionListener(this);
align_menu.add(item);
popup.add(align_menu);
final JMenuItem st = new JMenu("Transform");
final StartTransformMenuListener tml = new StartTransformMenuListener();
item = new JMenuItem("Transform (affine)");
item.addActionListener(tml);
st.add(item);
item.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_T, 0, true));
if (null == active)
item.setEnabled(false);
item = new JMenuItem("Transform (non-linear)");
item.addActionListener(tml);
st.add(item);
if (null == active)
item.setEnabled(false);
item.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_T, Event.SHIFT_MASK, true));
item = new JMenuItem("Cancel transform");
st.add(item);
item.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_ESCAPE, 0, true));
// just added as a self-documenting cue; no listener
item.setEnabled(false);
item = new JMenuItem("Remove rotation, scaling and shear (selected images)");
item.addActionListener(tml);
st.add(item);
if (null == active)
item.setEnabled(false);
item = new JMenuItem("Remove rotation, scaling and shear layer-wise");
item.addActionListener(tml);
st.add(item);
item = new JMenuItem("Remove coordinate transforms (selected images)");
item.addActionListener(tml);
st.add(item);
if (null == active)
item.setEnabled(false);
item = new JMenuItem("Remove coordinate transforms layer-wise");
item.addActionListener(tml);
st.add(item);
item = new JMenuItem("Adjust mesh resolution (selected images)");
item.addActionListener(tml);
st.add(item);
if (null == active)
item.setEnabled(false);
item = new JMenuItem("Adjust mesh resolution layer-wise");
item.addActionListener(tml);
st.add(item);
item = new JMenuItem("Set coordinate transform of selected image to other selected images");
item.addActionListener(tml);
st.add(item);
if (null == active)
item.setEnabled(false);
item = new JMenuItem("Set coordinate transform of selected image layer-wise");
item.addActionListener(tml);
st.add(item);
if (null == active)
item.setEnabled(false);
item = new JMenuItem("Set affine transform of selected image to other selected images");
item.addActionListener(tml);
st.add(item);
if (null == active)
item.setEnabled(false);
item = new JMenuItem("Set affine transform of selected image layer-wise");
item.addActionListener(tml);
st.add(item);
if (null == active)
item.setEnabled(false);
popup.add(st);
final JMenu link_menu = new JMenu("Link");
item = new JMenuItem("Link images...");
item.addActionListener(this);
link_menu.add(item);
item = new JMenuItem("Unlink all selected images");
item.addActionListener(this);
link_menu.add(item);
item.setEnabled(selection.getSelected(Patch.class).size() > 0);
item = new JMenuItem("Unlink all");
item.addActionListener(this);
link_menu.add(item);
popup.add(link_menu);
final JMenu adjust_menu = new JMenu("Adjust images");
item = new JMenuItem("Enhance contrast layer-wise...");
item.addActionListener(this);
adjust_menu.add(item);
item = new JMenuItem("Enhance contrast (selected images)...");
item.addActionListener(this);
adjust_menu.add(item);
if (selection.isEmpty())
item.setEnabled(false);
item = new JMenuItem("Adjust image filters (selected images)");
item.addActionListener(this);
adjust_menu.add(item);
if (selection.isEmpty())
item.setEnabled(false);
item = new JMenuItem("Set Min and Max layer-wise...");
item.addActionListener(this);
adjust_menu.add(item);
item = new JMenuItem("Set Min and Max (selected images)...");
item.addActionListener(this);
adjust_menu.add(item);
if (selection.isEmpty())
item.setEnabled(false);
item = new JMenuItem("Adjust min and max (selected images)...");
item.addActionListener(this);
adjust_menu.add(item);
item.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_J, 0));
if (selection.isEmpty())
item.setEnabled(false);
item = new JMenuItem("Mask image borders (layer-wise)...");
item.addActionListener(this);
adjust_menu.add(item);
item = new JMenuItem("Mask image borders (selected images)...");
item.addActionListener(this);
adjust_menu.add(item);
if (selection.isEmpty())
item.setEnabled(false);
item = new JMenuItem("Remove alpha masks (layer-wise)...");
item.addActionListener(this);
adjust_menu.add(item);
item = new JMenuItem("Remove alpha masks (selected images)...");
item.addActionListener(this);
adjust_menu.add(item);
if (selection.isEmpty())
item.setEnabled(false);
item = new JMenuItem("Split images under polyline ROI");
item.addActionListener(this);
adjust_menu.add(item);
final Roi roi = canvas.getFakeImagePlus().getRoi();
if (null == roi || !(roi.getType() == Roi.POLYLINE || roi.getType() == Roi.FREELINE))
item.setEnabled(false);
item = new JMenuItem("Blend (layer-wise)...");
item.addActionListener(this);
adjust_menu.add(item);
item = new JMenuItem("Blend (selected images)...");
item.addActionListener(this);
adjust_menu.add(item);
if (selection.isEmpty())
item.setEnabled(false);
item = new JMenuItem("Match intensities (layer-wise)...");
item.addActionListener(this);
adjust_menu.add(item);
item = new JMenuItem("Remove intensity maps (layer-wise)...");
item.addActionListener(this);
adjust_menu.add(item);
popup.add(adjust_menu);
final JMenu script = new JMenu("Script");
final MenuScriptListener msl = new MenuScriptListener();
item = new JMenuItem("Set preprocessor script layer-wise...");
item.addActionListener(msl);
script.add(item);
item = new JMenuItem("Set preprocessor script (selected images)...");
item.addActionListener(msl);
script.add(item);
if (selection.isEmpty())
item.setEnabled(false);
item = new JMenuItem("Remove preprocessor script layer-wise...");
item.addActionListener(msl);
script.add(item);
item = new JMenuItem("Remove preprocessor script (selected images)...");
item.addActionListener(msl);
script.add(item);
if (selection.isEmpty())
item.setEnabled(false);
popup.add(script);
menu = new JMenu("Import");
item = new JMenuItem("Import image");
item.addActionListener(this);
menu.add(item);
item.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_I, Event.ALT_MASK & Event.SHIFT_MASK, true));
item = new JMenuItem("Import stack...");
item.addActionListener(this);
menu.add(item);
item = new JMenuItem("Import stack with landmarks...");
item.addActionListener(this);
menu.add(item);
item = new JMenuItem("Import grid...");
item.addActionListener(this);
menu.add(item);
item = new JMenuItem("Import sequence as grid...");
item.addActionListener(this);
menu.add(item);
item = new JMenuItem("Import from text file...");
item.addActionListener(this);
menu.add(item);
item = new JMenuItem("Import labels as arealists...");
item.addActionListener(this);
menu.add(item);
item = new JMenuItem("Tags ...");
item.addActionListener(this);
menu.add(item);
popup.add(menu);
menu = new JMenu("Export");
final boolean has_arealists = layer.getParent().contains(AreaList.class);
item = new JMenuItem("Make flat image...");
item.addActionListener(this);
menu.add(item);
item = new JMenuItem("Arealists as labels (tif)");
item.addActionListener(this);
menu.add(item);
item.setEnabled(has_arealists);
item = new JMenuItem("Arealists as labels (amira)");
item.addActionListener(this);
menu.add(item);
item.setEnabled(has_arealists);
item = new JMenuItem("Image stack under selected Arealist");
item.addActionListener(this);
menu.add(item);
item.setEnabled(null != active && AreaList.class == active.getClass());
item = new JMenuItem("Fly through selected Treeline/AreaTree");
item.addActionListener(this);
menu.add(item);
item.setEnabled(null != active && Tree.class.isInstance(active));
item = new JMenuItem("Tags...");
item.addActionListener(this);
menu.add(item);
item = new JMenuItem("Connectivity graph...");
item.addActionListener(this);
menu.add(item);
item = new JMenuItem("NeuroML...");
item.addActionListener(this);
menu.add(item);
popup.add(menu);
menu = new JMenu("Display");
item = new JMenuItem("Resize canvas/LayerSet...");
item.addActionListener(this);
menu.add(item);
item = new JMenuItem("Autoresize canvas/LayerSet");
item.addActionListener(this);
menu.add(item);
item = new JMenuItem("Resize canvas/LayerSet to ROI");
item.addActionListener(this);
menu.add(item);
item.setEnabled(null != canvas.getFakeImagePlus().getRoi());
item = new JMenuItem("Properties ...");
item.addActionListener(this);
menu.add(item);
item = new JMenuItem("Calibration...");
item.addActionListener(this);
menu.add(item);
item = new JMenuItem("Grid overlay...");
item.addActionListener(this);
menu.add(item);
item = new JMenuItem("Adjust snapping parameters...");
item.addActionListener(this);
menu.add(item);
item = new JMenuItem("Adjust fast-marching parameters...");
item.addActionListener(this);
menu.add(item);
item = new JMenuItem("Adjust arealist paint parameters...");
item.addActionListener(this);
menu.add(item);
item = new JMenuItem("Show current 2D position in 3D");
item.addActionListener(this);
menu.add(item);
item = new JMenuItem("Show layers as orthoslices in 3D");
item.addActionListener(this);
menu.add(item);
item = new JMenuItem("Inspect image mesh triangles");
item.addActionListener(this);
menu.add(item);
popup.add(menu);
menu = new JMenu("Project");
this.project.getLoader().setupMenuItems(menu, this.getProject());
item = new JMenuItem("Project properties...");
item.addActionListener(this);
menu.add(item);
item = new JMenuItem("Create subproject");
item.addActionListener(this);
menu.add(item);
item = new JMenuItem("Create sibling project with retiled layers");
item.addActionListener(this);
menu.add(item);
item = new JMenuItem("Release memory...");
item.addActionListener(this);
menu.add(item);
item = new JMenuItem("Flush image cache");
item.addActionListener(this);
menu.add(item);
item = new JMenuItem("Regenerate all mipmaps");
item.addActionListener(this);
menu.add(item);
item = new JMenuItem("Regenerate mipmaps (selected images)");
item.addActionListener(this);
menu.add(item);
menu.addSeparator();
item = new JMenuItem("Measurement options...");
item.addActionListener(this);
menu.add(item);
popup.add(menu);
menu = new JMenu("Selection");
item = new JMenuItem("Select all");
item.addActionListener(this);
menu.add(item);
item = new JMenuItem("Select all visible");
item.addActionListener(this);
menu.add(item);
item.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_A, Utils.getControlModifier(), true));
if (0 == layer.getDisplayableList().size() && 0 == layer.getParent().getDisplayableList().size())
item.setEnabled(false);
item = new JMenuItem("Select all that match...");
item.addActionListener(this);
menu.add(item);
item = new JMenuItem("Select none");
item.addActionListener(this);
menu.add(item);
if (0 == selection.getNSelected())
item.setEnabled(false);
item.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_ESCAPE, 0, true));
final JMenu bytype = new JMenu("Select all by type");
item = new JMenuItem("AreaList");
item.addActionListener(bytypelistener);
bytype.add(item);
item = new JMenuItem("AreaTree");
item.addActionListener(bytypelistener);
bytype.add(item);
item = new JMenuItem("Ball");
item.addActionListener(bytypelistener);
bytype.add(item);
item = new JMenuItem("Connector");
item.addActionListener(bytypelistener);
bytype.add(item);
item = new JMenuItem("Dissector");
item.addActionListener(bytypelistener);
bytype.add(item);
item = new JMenuItem("Image");
item.addActionListener(bytypelistener);
bytype.add(item);
item = new JMenuItem("Pipe");
item.addActionListener(bytypelistener);
bytype.add(item);
item = new JMenuItem("Polyline");
item.addActionListener(bytypelistener);
bytype.add(item);
item = new JMenuItem("Profile");
item.addActionListener(bytypelistener);
bytype.add(item);
item = new JMenuItem("Text");
item.addActionListener(bytypelistener);
bytype.add(item);
item = new JMenuItem("Treeline");
item.addActionListener(bytypelistener);
bytype.add(item);
menu.add(bytype);
item = new JMenuItem("Restore selection");
item.addActionListener(this);
menu.add(item);
item = new JMenuItem("Select under ROI");
item.addActionListener(this);
menu.add(item);
if (canvas.getFakeImagePlus().getRoi() == null)
item.setEnabled(false);
final JMenu graph = new JMenu("Graph");
final GraphMenuListener gl = new GraphMenuListener();
item = new JMenuItem("Select outgoing Connectors");
item.addActionListener(gl);
graph.add(item);
item = new JMenuItem("Select incoming Connectors");
item.addActionListener(gl);
graph.add(item);
item = new JMenuItem("Select downstream targets");
item.addActionListener(gl);
graph.add(item);
item = new JMenuItem("Select upstream targets");
item.addActionListener(gl);
graph.add(item);
graph.setEnabled(!selection.isEmpty());
menu.add(graph);
item = new JMenuItem("Measure");
item.addActionListener(this);
menu.add(item);
item.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_M, 0, true));
item.setEnabled(!selection.isEmpty());
popup.add(menu);
menu = new JMenu("Tool");
item = new JMenuItem("Rectangular ROI");
item.addActionListener(new SetToolListener(Toolbar.RECTANGLE));
menu.add(item);
item.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_F1, 0, true));
item = new JMenuItem("Polygon ROI");
item.addActionListener(new SetToolListener(Toolbar.POLYGON));
menu.add(item);
item.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_F2, 0, true));
item = new JMenuItem("Freehand ROI");
item.addActionListener(new SetToolListener(Toolbar.FREEROI));
menu.add(item);
item.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_F3, 0, true));
item = new JMenuItem("Text");
item.addActionListener(new SetToolListener(Toolbar.TEXT));
menu.add(item);
item.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_F4, 0, true));
item = new JMenuItem("Magnifier glass");
item.addActionListener(new SetToolListener(Toolbar.MAGNIFIER));
menu.add(item);
item.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_F5, 0, true));
item = new JMenuItem("Hand");
item.addActionListener(new SetToolListener(Toolbar.HAND));
menu.add(item);
item.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_F6, 0, true));
item = new JMenuItem("Select");
item.addActionListener(new SetToolListener(ProjectToolbar.SELECT));
menu.add(item);
item.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_F9, 0, true));
item = new JMenuItem("Pencil");
item.addActionListener(new SetToolListener(ProjectToolbar.PENCIL));
menu.add(item);
item.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_F10, 0, true));
item = new JMenuItem("Pen");
item.addActionListener(new SetToolListener(ProjectToolbar.PEN));
menu.add(item);
item.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_F11, 0, true));
popup.add(menu);
item = new JMenuItem("Search...");
item.addActionListener(this);
popup.add(item);
item.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_F, Utils.getControlModifier(), true));
// canvas.add(popup);
return popup;
}
use of ini.trakem2.utils.Montage 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.Montage 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.Montage in project TrakEM2 by trakem2.
the class Loader method insertGrid.
/**
* Insert grid in layer (with optional stitching)
*
* @param layer The Layer to inser the grid into
* @param dir The base dir of the images to open
* @param first_image_name name of the first image in the list
* @param cols The list of columns, containing each an array of String file names in each column.
* @param bx The top-left X coordinate of the grid to insert
* @param by The top-left Y coordinate of the grid to insert
* @param bt_overlap bottom-top overlap of the images
* @param lr_overlap left-right overlap of the images
* @param link_images Link images to their neighbors
* @param stitch_tiles montage option
* @param cc_percent_overlap tiles overlap
* @param cc_scale tiles scaling previous to stitching (1 = no scaling)
* @param min_R regression threshold (minimum acceptable R)
* @param homogenize_contrast contrast homogenization option
* @param stitching_rule stitching rule (upper left corner or free)
*/
private void insertGrid(final Layer layer, final String dir_, final String first_image_name, final int n_images, final ArrayList<String[]> cols, final double bx, final double by, final double bt_overlap, final double lr_overlap, final boolean link_images, final boolean stitch_tiles, final boolean homogenize_contrast, final StitchingTEM.PhaseCorrelationParam pc_param, final Worker worker) {
// create a Worker, then give it to the Bureaucrat
try {
String dir = dir_;
final ArrayList<Patch> al = new ArrayList<Patch>();
Utils.showProgress(0.0D);
// less repaints on IJ status bar
opener.setSilentMode(true);
int x = 0;
int y = 0;
int largest_y = 0;
ImagePlus img = null;
// open the selected image, to use as reference for width and height
// w1nd0wz safe
dir = dir.replace('\\', '/');
if (!dir.endsWith("/"))
dir += "/";
String path = dir + first_image_name;
// TODO arbitrary x3 factor
releaseToFit(new File(path).length() * 3);
IJ.redirectErrorMessages();
ImagePlus first_img = openImagePlus(path);
if (null == first_img) {
Utils.log("Selected image to open first is null.");
return;
}
if (null == first_img)
return;
final int first_image_width = first_img.getWidth();
final int first_image_height = first_img.getHeight();
final int first_image_type = first_img.getType();
// start
final Patch[][] pall = new Patch[cols.size()][((String[]) cols.get(0)).length];
int width, height;
// counter
int k = 0;
boolean auto_fix_all = false;
boolean ignore_all = false;
boolean resize = false;
if (!ControlWindow.isGUIEnabled()) {
// headless mode: autofix all
auto_fix_all = true;
resize = true;
}
// Accumulate mipmap generation tasks
final ArrayList<Future<?>> fus = new ArrayList<Future<?>>();
startLargeUpdate();
for (int i = 0; i < cols.size(); i++) {
final String[] rows = (String[]) cols.get(i);
if (i > 0) {
x -= lr_overlap;
}
for (int j = 0; j < rows.length; j++) {
if (Thread.currentThread().isInterrupted()) {
Display.repaint(layer);
rollback();
return;
}
if (j > 0) {
y -= bt_overlap;
}
// get file name
final String file_name = (String) rows[j];
path = dir + file_name;
if (null != first_img && file_name.equals(first_image_name)) {
img = first_img;
// release pointer
first_img = null;
} else {
// open image
releaseToFit(first_image_width, first_image_height, first_image_type, 1.5f);
try {
IJ.redirectErrorMessages();
img = openImagePlus(path);
} catch (final OutOfMemoryError oome) {
printMemState();
throw oome;
}
}
if (null == img) {
Utils.log("null image! skipping.");
pall[i][j] = null;
continue;
}
width = img.getWidth();
height = img.getHeight();
int rw = width;
int rh = height;
if (width != first_image_width || height != first_image_height) {
int new_width = first_image_width;
int new_height = first_image_height;
if (!auto_fix_all && !ignore_all) {
final GenericDialog gdr = new GenericDialog("Size mismatch!");
gdr.addMessage("The size of " + file_name + " is " + width + " x " + height);
gdr.addMessage("but the selected image was " + first_image_width + " x " + first_image_height);
gdr.addMessage("Adjust to selected image dimensions?");
gdr.addNumericField("width: ", (double) first_image_width, 0);
// should not be editable ... or at least, explain in some way that the dimensions can be edited just for this image --> done below
gdr.addNumericField("height: ", (double) first_image_height, 0);
gdr.addMessage("[If dimensions are changed they will apply only to this image]");
gdr.addMessage("");
final String[] au = new String[] { "fix all", "ignore all" };
gdr.addChoice("Automate:", au, au[1]);
gdr.addMessage("Cancel == NO OK = YES");
gdr.showDialog();
if (gdr.wasCanceled()) {
resize = false;
// do nothing: don't fix/resize
}
resize = true;
// catch values
new_width = (int) gdr.getNextNumber();
new_height = (int) gdr.getNextNumber();
final int iau = gdr.getNextChoiceIndex();
if (new_width != first_image_width || new_height != first_image_height) {
auto_fix_all = false;
} else {
auto_fix_all = (0 == iau);
}
ignore_all = (1 == iau);
if (ignore_all)
resize = false;
}
if (resize) {
// resize Patch dimensions
rw = first_image_width;
rh = first_image_height;
}
}
// add new Patch at base bx,by plus the x,y of the grid
// will call back and cache the image
final Patch patch = new Patch(layer.getProject(), img.getTitle(), bx + x, by + y, img);
if (width != rw || height != rh)
patch.setDimensions(rw, rh, false);
addedPatchFrom(path, patch);
if (// prevent it
homogenize_contrast)
// prevent it
setMipMapsRegeneration(false);
else
fus.add(regenerateMipMaps(patch));
//
// after the above two lines! Otherwise it will paint fine, but throw exceptions on the way
layer.add(patch, true);
// otherwise when reopening it has to fetch all ImagePlus and scale and zip them all! This method though creates the awt and the snap, thus filling up memory and slowing down, but it's worth it.
patch.updateInDatabase("tiff_snapshot");
pall[i][j] = patch;
al.add(patch);
if (ControlWindow.isGUIEnabled()) {
// northwest to prevent screwing up Patch coordinates.
layer.getParent().enlargeToFit(patch, LayerSet.NORTHWEST);
}
y += img.getHeight();
Utils.showProgress((double) k / n_images);
k++;
}
x += img.getWidth();
if (largest_y < y) {
largest_y = y;
}
// resetting!
y = 0;
}
// build list
final Patch[] pa = new Patch[al.size()];
int f = 0;
// list in row-first order
for (int j = 0; j < pall[0].length; j++) {
// 'j' is row
for (int i = 0; i < pall.length; i++) {
// 'i' is column
pa[f++] = pall[i][j];
}
}
// optimize repaints: all to background image
Display.clearSelection(layer);
// make the first one be top, and the rest under it in left-right and top-bottom order
for (int j = 0; j < pa.length; j++) {
layer.moveBottom(pa[j]);
}
// make picture
// getFlatImage(layer, layer.getMinimalBoundingBox(Patch.class), 0.25, 1, ImagePlus.GRAY8, Patch.class, null, false).show();
// optimize repaints: all to background image
Display.clearSelection(layer);
if (homogenize_contrast) {
if (null != worker)
worker.setTaskName("Enhancing contrast");
// 0 - check that all images are of the same type
int tmp_type = pa[0].getType();
for (int e = 1; e < pa.length; e++) {
if (pa[e].getType() != tmp_type) {
// can't continue
tmp_type = Integer.MAX_VALUE;
Utils.log("Can't homogenize histograms: images are not all of the same type.\nFirst offending image is: " + al.get(e));
break;
}
}
if (Integer.MAX_VALUE != tmp_type) {
// checking on error flag
// Set min and max for all images
// 1 - fetch statistics for each image
final ArrayList<ImageStatistics> al_st = new ArrayList<ImageStatistics>();
// list of Patch ordered by stdDev ASC
final ArrayList<Patch> al_p = new ArrayList<Patch>();
int type = -1;
for (int i = 0; i < pa.length; i++) {
if (Thread.currentThread().isInterrupted()) {
Display.repaint(layer);
rollback();
return;
}
ImagePlus imp = fetchImagePlus(pa[i]);
// speed-up trick: extract data from smaller image
if (imp.getWidth() > 1024) {
releaseToFit(1024, (int) ((imp.getHeight() * 1024) / imp.getWidth()), imp.getType(), 1.1f);
// cheap and fast nearest-point resizing
imp = new ImagePlus(imp.getTitle(), imp.getProcessor().resize(1024));
}
if (-1 == type)
type = imp.getType();
final ImageStatistics i_st = imp.getStatistics();
// order by stdDev, from small to big
int q = 0;
for (final ImageStatistics st : al_st) {
q++;
if (st.stdDev > i_st.stdDev)
break;
}
if (q == al.size()) {
// append at the end. WARNING if importing thousands of images, this is a potential source of out of memory errors. I could just recompute it when I needed it again below
al_st.add(i_st);
al_p.add(pa[i]);
} else {
al_st.add(q, i_st);
al_p.add(q, pa[i]);
}
}
// shallow copy of the ordered list
final ArrayList<Patch> al_p2 = new ArrayList<Patch>(al_p);
// 2 - discard the first and last 25% (TODO: a proper histogram clustering analysis and histogram examination should apply here)
if (pa.length > 3) {
// under 4 images, use them all
int i = 0;
while (i <= pa.length * 0.25) {
al_p.remove(i);
i++;
}
final int count = i;
i = pa.length - 1 - count;
while (i > (pa.length * 0.75) - count) {
al_p.remove(i);
i--;
}
}
// 3 - compute common histogram for the middle 50% images
final Patch[] p50 = new Patch[al_p.size()];
al_p.toArray(p50);
final StackStatistics stats = new StackStatistics(new PatchStack(p50, 1));
// 4 - compute autoAdjust min and max values
// extracting code from ij.plugin.frame.ContrastAdjuster, method autoAdjust
int autoThreshold = 0;
double min = 0;
double max = 0;
// once for 8-bit and color, twice for 16 and 32-bit (thus the 2501 autoThreshold value)
final int limit = stats.pixelCount / 10;
final int[] histogram = stats.histogram;
// else autoThreshold /= 2;
if (ImagePlus.GRAY16 == type || ImagePlus.GRAY32 == type)
autoThreshold = 2500;
else
autoThreshold = 5000;
final int threshold = stats.pixelCount / autoThreshold;
int i = -1;
boolean found = false;
int count;
do {
i++;
count = histogram[i];
if (count > limit)
count = 0;
found = count > threshold;
} while (!found && i < 255);
final int hmin = i;
i = 256;
do {
i--;
count = histogram[i];
if (count > limit)
count = 0;
found = count > threshold;
} while (!found && i > 0);
final int hmax = i;
if (hmax >= hmin) {
min = stats.histMin + hmin * stats.binSize;
max = stats.histMin + hmax * stats.binSize;
if (min == max) {
min = stats.min;
max = stats.max;
}
}
// 5 - compute common mean within min,max range
final double target_mean = getMeanOfRange(stats, min, max);
Utils.log2("Loader min,max: " + min + ", " + max + ", target mean: " + target_mean);
// 6 - apply to all
for (i = al_p2.size() - 1; i > -1; i--) {
// the order is different, thus getting it from the proper list
final Patch p = (Patch) al_p2.get(i);
final double dm = target_mean - getMeanOfRange((ImageStatistics) al_st.get(i), min, max);
// displacing in the opposite direction, makes sense, so that the range is drifted upwards and thus the target 256 range for an awt.Image will be closer to the ideal target_mean
p.setMinAndMax(min - dm, max - dm);
// OBSOLETE and wrong //p.putMinAndMax(fetchImagePlus(p));
}
setMipMapsRegeneration(true);
if (isMipMapsRegenerationEnabled()) {
// recreate files
for (final Patch p : al) fus.add(regenerateMipMaps(p));
}
Display.repaint(layer, new Rectangle(0, 0, (int) layer.getParent().getLayerWidth(), (int) layer.getParent().getLayerHeight()), 0);
// make picture
// getFlatImage(layer, layer.getMinimalBoundingBox(Patch.class), 0.25, 1, ImagePlus.GRAY8, Patch.class, null, false).show();
}
}
if (stitch_tiles) {
// Wait until all mipmaps for the new images have been generated before attempting to register
Utils.wait(fus);
// create undo
layer.getParent().addTransformStep(new HashSet<Displayable>(layer.getDisplayables(Patch.class)));
// wait until repainting operations have finished (otherwise, calling crop on an ImageProcessor fails with out of bounds exception sometimes)
if (null != Display.getFront())
Display.getFront().getCanvas().waitForRepaint();
if (null != worker)
worker.setTaskName("Stitching");
StitchingTEM.stitch(pa, cols.size(), bt_overlap, lr_overlap, true, pc_param).run();
}
// link with images on top, bottom, left and right.
if (link_images) {
if (null != worker)
worker.setTaskName("Linking");
for (int i = 0; i < pall.length; i++) {
// 'i' is column
for (int j = 0; j < pall[0].length; j++) {
// 'j' is row
final Patch p = pall[i][j];
// can happen if a slot is empty
if (null == p)
continue;
if (i > 0 && null != pall[i - 1][j])
p.link(pall[i - 1][j]);
if (i < pall.length - 1 && null != pall[i + 1][j])
p.link(pall[i + 1][j]);
if (j > 0 && null != pall[i][j - 1])
p.link(pall[i][j - 1]);
if (j < pall[0].length - 1 && null != pall[i][j + 1])
p.link(pall[i][j + 1]);
}
}
}
commitLargeUpdate();
// resize LayerSet
// int new_width = x;
// int new_height = largest_y;
// Math.abs(bx) + new_width, Math.abs(by) + new_height);
layer.getParent().setMinimumDimensions();
// update indexes
// so its done once only
layer.updateInDatabase("stack_index");
// create panels in all Displays showing this layer
/* // not needed anymore
Iterator it = al.iterator();
while (it.hasNext()) {
Display.add(layer, (Displayable)it.next(), false); // don't set it active, don't want to reload the ImagePlus!
}
*/
// update Displays
Display.update(layer);
layer.recreateBuckets();
// debug:
} catch (final Throwable t) {
IJError.print(t);
rollback();
setMipMapsRegeneration(true);
}
}
use of ini.trakem2.utils.Montage in project TrakEM2 by trakem2.
the class Loader method importSequenceAsGrid.
/**
* Open one of the images to find out the dimensions, and get a good guess at what is the desirable scale for doing phase- and cross-correlations with about 512x512 images.
*/
/*
private int getCCScaleGuess(final File images_dir, final String[] all_images) {
try {
if (null != all_images && all_images.length > 0) {
Utils.showStatus("Opening one image ... ", false);
String sdir = images_dir.getAbsolutePath().replace('\\', '/');
if (!sdir.endsWith("/")) sdir += "/";
IJ.redirectErrorMessages();
ImagePlus imp = openImagePlus(sdir + all_images[0]);
if (null != imp) {
int w = imp.getWidth();
int h = imp.getHeight();
flush(imp);
imp = null;
int cc_scale = (int)((512.0 / (w > h ? w : h)) * 100);
if (cc_scale > 100) return 100;
return cc_scale;
}
}
} catch (Exception e) {
Utils.log2("Could not get an estimate for the optimal scale.");
}
return 25;
}
*/
/**
* Import a sequence of images as a grid, and put them in the layer. If the directory (@param dir) is null, it'll be asked for. The image_file_names can be null, and in any case it's only the names, not the paths.
*/
public Bureaucrat importSequenceAsGrid(final Layer first_layer, String dir, final String[] image_file_names) {
String[] all_images = null;
// first file
String file = null;
File images_dir = null;
if (null != dir && null != image_file_names) {
all_images = image_file_names;
images_dir = new File(dir);
} else if (null == dir) {
final String[] dn = Utils.selectFile("Select first image");
if (null == dn)
return null;
dir = dn[0];
file = dn[1];
images_dir = new File(dir);
} else {
images_dir = new File(dir);
if (!(images_dir.exists() && images_dir.isDirectory())) {
Utils.showMessage("Something went wrong:\n\tCan't find directory " + dir);
return null;
}
}
if (null == image_file_names)
all_images = images_dir.list(new ini.trakem2.io.ImageFileFilter("", null));
if (null == file && all_images.length > 0) {
file = all_images[0];
}
final int n_max = all_images.length;
// reasonable estimate
final int side = (int) Math.floor(Math.sqrt(n_max));
final GenericDialog gd = new GenericDialog("Conventions");
gd.addStringField("file_name_matches: ", "");
gd.addNumericField("first_image: ", 1, 0);
gd.addNumericField("last_image: ", n_max, 0);
gd.addCheckbox("Reverse list order", false);
gd.addNumericField("number_of_rows: ", side, 0);
gd.addNumericField("number_of_columns: ", side, 0);
gd.addNumericField("number_of_slices: ", 1, 0);
gd.addMessage("The top left coordinate for the imported grid:");
gd.addNumericField("base_x: ", 0, 3);
gd.addNumericField("base_y: ", 0, 3);
gd.addMessage("Amount of image overlap, in pixels");
// as asked by Joachim Walter
gd.addNumericField("bottom-top overlap: ", 0, 2);
gd.addNumericField("left-right overlap: ", 0, 2);
gd.addCheckbox("link images", false);
gd.addCheckbox("montage with phase correlation", true);
gd.addCheckbox("homogenize_contrast", false);
gd.showDialog();
if (gd.wasCanceled())
return null;
final String regex = gd.getNextString();
// avoid destroying backslashes
Utils.log2(new StringBuilder("using regex: ").append(regex).toString());
int first = (int) gd.getNextNumber();
if (first < 1)
first = 1;
int last = (int) gd.getNextNumber();
if (last < 1)
last = 1;
if (last < first) {
Utils.showMessage("Last is smaller that first!");
return null;
}
final boolean reverse_order = gd.getNextBoolean();
final int n_rows = (int) gd.getNextNumber();
final int n_cols = (int) gd.getNextNumber();
final int n_slices = (int) gd.getNextNumber();
final double bx = gd.getNextNumber();
final double by = gd.getNextNumber();
final double bt_overlap = gd.getNextNumber();
final double lr_overlap = gd.getNextNumber();
final boolean link_images = gd.getNextBoolean();
final boolean stitch_tiles = gd.getNextBoolean();
final boolean homogenize_contrast = gd.getNextBoolean();
String[] file_names = null;
if (null == image_file_names) {
file_names = images_dir.list(new ini.trakem2.io.ImageFileFilter(regex, null));
// assumes 001, 002, 003 ... that style, since it does binary sorting of strings
Arrays.sort(file_names);
if (reverse_order) {
// flip in place
for (int i = file_names.length / 2; i > -1; i--) {
final String tmp = file_names[i];
final int j = file_names.length - 1 - i;
file_names[i] = file_names[j];
file_names[j] = tmp;
}
}
} else {
file_names = all_images;
}
if (0 == file_names.length) {
Utils.showMessage("No images found.");
return null;
}
// check if the selected image is in the list. Otherwise, shift selected image to the first of the included ones.
boolean found_first = false;
for (int i = 0; i < file_names.length; i++) {
if (file.equals(file_names[i])) {
found_first = true;
break;
}
}
if (!found_first) {
file = file_names[0];
Utils.log("Using " + file + " as the reference image for size.");
}
// crop list
if (last > file_names.length)
last = file_names.length - 1;
if (first < 1)
first = 1;
if (1 != first || last != file_names.length) {
Utils.log("Cropping list.");
final String[] file_names2 = new String[last - first + 1];
System.arraycopy(file_names, first - 1, file_names2, 0, file_names2.length);
file_names = file_names2;
}
// should be multiple of rows and cols and slices
if (file_names.length != n_rows * n_cols * n_slices) {
Utils.log("ERROR: rows * cols * slices does not match with the number of selected images.");
Utils.log("n_images:" + file_names.length + " rows,cols,slices : " + n_rows + "," + n_cols + "," + n_slices + " total=" + n_rows * n_cols * n_slices);
return null;
}
// I luv java
final String[] file_names_ = file_names;
final String dir_ = dir;
// the first file
final String file_ = file;
final double bt_overlap_ = bt_overlap;
final double lr_overlap_ = lr_overlap;
return Bureaucrat.createAndStart(new Worker.Task("Importing", true) {
@Override
public void exec() {
StitchingTEM.PhaseCorrelationParam pc_param = null;
// Slice up list:
for (int sl = 0; sl < n_slices; sl++) {
if (Thread.currentThread().isInterrupted() || hasQuitted())
return;
Utils.log("Importing " + (sl + 1) + "/" + n_slices);
final int start = sl * n_rows * n_cols;
final ArrayList<String[]> cols = new ArrayList<String[]>();
for (int i = 0; i < n_cols; i++) {
final String[] col = new String[n_rows];
for (int j = 0; j < n_rows; j++) {
col[j] = file_names_[start + j * n_cols + i];
}
cols.add(col);
}
final Layer layer = 0 == sl ? first_layer : first_layer.getParent().getLayer(first_layer.getZ() + first_layer.getThickness() * sl, first_layer.getThickness(), true);
if (stitch_tiles && null == pc_param) {
pc_param = new StitchingTEM.PhaseCorrelationParam();
pc_param.setup(layer);
}
insertGrid(layer, dir_, file_, n_rows * n_cols, cols, bx, by, bt_overlap_, lr_overlap_, link_images, stitch_tiles, homogenize_contrast, pc_param, this);
}
}
}, first_layer.getProject());
}
Aggregations