use of ini.trakem2.display.Coordinate in project TrakEM2 by trakem2.
the class Segmentation method fastMarching.
public static Bureaucrat fastMarching(final AreaWrapper aw, final Layer layer, final Rectangle srcRect, final int x_p_w, final int y_p_w, final List<Runnable> post_tasks) {
// Capture pointers before they are set to null
final AreaContainer ac = (AreaContainer) aw.getSource();
final AffineTransform source_aff = aw.getSource().getAffineTransform();
final Rectangle box = new Rectangle(x_p_w - Segmentation.fmp.width / 2, y_p_w - Segmentation.fmp.height / 2, Segmentation.fmp.width, Segmentation.fmp.height);
Bureaucrat burro = Bureaucrat.create(new Worker.Task("Fast marching") {
public void exec() {
// Capture image as large as the fmp width,height centered on x_p_w,y_p_w
Utils.log2("fmp box is " + box);
ImagePlus imp = new ImagePlus("", Patch.makeFlatImage(ImagePlus.GRAY8, layer, box, 1.0, (Collection) layer.getDisplayables(Patch.class, new Area(box), true), Color.black));
// Bandpass filter
if (fmp.apply_bandpass_filter) {
IJ.run(imp, "Bandpass Filter...", "filter_large=" + fmp.low_frequency_threshold + " filter_small=" + fmp.high_frequency_threshold + " suppress=None tolerance=5" + (fmp.autoscale_after_filtering ? " autoscale" : "") + (fmp.saturate_when_autoscaling ? " saturate" : ""));
}
// Setup seed point
PointRoi roi = new PointRoi(box.width / 2, box.height / 2);
imp.setRoi(roi);
Utils.log2("imp: " + imp);
Utils.log2("proi: " + imp.getRoi() + " " + Utils.toString(new int[] { x_p_w - srcRect.x, y_p_w - srcRect.y }));
// Setup state
ImageContainer ic = new ImageContainer(imp);
StateContainer state = new StateContainer();
state.setROI(roi, ic.getWidth(), ic.getHeight(), ic.getImageCount(), imp.getCurrentSlice());
state.setExpansionToInside(false);
// Run FastMarching
final FastMarching fm = new FastMarching(ic, null, state, true, fmp.fm_grey, fmp.fm_dist, fmp.apply_grey_value_erosion);
final int max_iterations = fmp.max_iterations;
final int iter_inc = fmp.iter_inc;
for (int i = 0; i < max_iterations; i++) {
if (Thread.currentThread().isInterrupted()) {
return;
}
if (!fm.step(iter_inc))
break;
}
// Extract ROI
setTaskName("Adding area");
final ArrayList<Coordinate> vc = fm.getStateContainer().getXYZ(false);
if (0 == vc.size()) {
Utils.log("No area growth.");
return;
}
final Area area = new Area();
Coordinate first = vc.remove(0);
final Rectangle r = new Rectangle(first.x, first.y, 1, 1);
int count = 0;
// Scan and add line-wise
for (final Coordinate c : vc) {
count++;
if (c.y == r.y && c.x == r.x + 1) {
// same line:
r.width += 1;
continue;
} else {
// add previous one
area.add(new Area(r));
}
// start new line:
r.x = c.x;
r.y = c.y;
r.width = 1;
if (0 == count % 1024 && Thread.currentThread().isInterrupted()) {
return;
}
}
// add last:
area.add(new Area(r));
/*
// Trying from the image mask: JUST AS SLOW
final byte[] b = (byte[]) fm.getStateContainer().getIPMask()[0].getPixels();
final int w = imp.getWidth();
for (int i=0; i<b.length; i++) {
if (0 == b[i]) {
r.x = i%w;
r.y = i/w;
area.add(new Area(r));
}
}
*/
/* // DOESN'T FILL?
// Trying to just get the contour, and then filling holes
for (final Coordinate c : fm.getStateContainer().getXYZ(true)) {
r.x = c.x;
r.y = c.y;
area.add(new Area(r));
}
Polygon pol = new Polygon();
final float[] coords = new float[6];
for (PathIterator pit = area.getPathIterator(null); !pit.isDone(); ) {
switch (pit.currentSegment(coords)) {
case PathIterator.SEG_MOVETO:
case PathIterator.SEG_LINETO:
pol.addPoint((int)coords[0], (int)coords[1]);
break;
case PathIterator.SEG_CLOSE:
area.add(new Area(pol));
// prepare next:
pol = new Polygon();
break;
default:
Utils.log2("WARNING: unhandled seg type.");
break;
}
pit.next();
if (pit.isDone()) {
break;
}
}
*/
// / FAILS because by now AreaWrapper's source is null
// aw.add(area, new AffineTransform(1, 0, 0, 1, box.x, box.y));
// Instead, compose an Area that is local to the AreaWrapper's area
final AffineTransform aff = new AffineTransform(1, 0, 0, 1, box.x, box.y);
try {
aff.preConcatenate(source_aff.createInverse());
} catch (NoninvertibleTransformException nite) {
IJError.print(nite);
return;
}
aw.getArea().add(area.createTransformedArea(aff));
ac.calculateBoundingBox(layer);
Display.repaint(layer);
}
}, layer.getProject());
if (null != post_tasks)
for (Runnable task : post_tasks) burro.addPostTask(task);
burro.goHaveBreakfast();
return burro;
}
use of ini.trakem2.display.Coordinate in project TrakEM2 by trakem2.
the class Blending method blendPatches.
public static final void blendPatches(final Set<Patch> patches, final boolean respect_current_mask) {
ExecutorService exe = null;
try {
if (null == patches || patches.size() < 2)
return;
final Layer layer = patches.iterator().next().getLayer();
for (final Patch p : patches) {
if (null != p.getCoordinateTransform()) {
Utils.log("CANNOT blend: at least one image has a coordinate transform.\nBlending of coordinate-transformed images will be enabled in the near future.");
return;
}
if (p.getLayer() != layer) {
Utils.log("CANNOT blend: all images must belong to the same layer!\n Otherwise the overlap cannot be computed.");
return;
}
}
final HashMap<Patch, TransformMesh> meshes = new HashMap<Patch, TransformMesh>();
for (final Patch p : patches) {
meshes.put(p, null == p.getCoordinateTransform() ? null : new TransformMesh(p.getCoordinateTransform(), p.getMeshResolution(), p.getOWidth(), p.getOHeight()));
}
exe = Executors.newFixedThreadPool(Runtime.getRuntime().availableProcessors());
final List<Future<?>> futures = Collections.synchronizedList(new ArrayList<Future<?>>());
final List<Future<?>> futures2 = Collections.synchronizedList(new ArrayList<Future<?>>());
// Cache the indices that determine overlap order within the layer
final HashMap<Patch, Integer> indices = new HashMap<Patch, Integer>();
int i = 0;
for (final Displayable d : layer.getDisplayables()) {
if (d.getClass() == Patch.class && patches.contains((Patch) d)) {
indices.put((Patch) d, i);
}
i += 1;
}
for (final Patch p : patches) {
if (Thread.currentThread().isInterrupted())
break;
futures.add(exe.submit(new Runnable() {
@Override
public void run() {
final int pLayerIndex = indices.get(p);
final Set<Patch> overlapping = new HashSet<Patch>();
for (final Patch op : patches) {
if (indices.get(op) < pLayerIndex)
overlapping.add(op);
}
if (setBlendingMask(p, overlapping, meshes, respect_current_mask)) {
futures2.add(p.updateMipMaps());
}
}
}, null));
}
// join all:
Utils.waitIfAlive(futures, false);
Utils.waitIfAlive(futures2, false);
} catch (final Exception e) {
IJError.print(e);
} finally {
if (null != exe)
exe.shutdown();
Display.repaint();
}
}
use of ini.trakem2.display.Coordinate in project TrakEM2 by trakem2.
the class ElasticMontage method exec.
@SuppressWarnings("deprecation")
public final void exec(final Param param, final List<Patch> patches, final Set<Patch> fixedPatches) throws Exception {
/* free memory */
patches.get(0).getProject().getLoader().releaseAll();
/* create tiles and models for all patches */
final ArrayList<AbstractAffineTile2D<?>> tiles = new ArrayList<AbstractAffineTile2D<?>>();
final ArrayList<AbstractAffineTile2D<?>> fixedTiles = new ArrayList<AbstractAffineTile2D<?>>();
Align.tilesFromPatches(param.po, patches, fixedPatches, tiles, fixedTiles);
if (!param.isAligned) {
Align.alignTiles(param.po, tiles, fixedTiles, param.tilesAreInPlace, param.maxNumThreads);
/* Apply the estimated affine transform to patches */
for (final AbstractAffineTile2D<?> t : tiles) t.getPatch().setAffineTransform(t.createAffine());
Display.update();
}
/* generate tile pairs for all by now overlapping tiles */
final ArrayList<AbstractAffineTile2D<?>[]> tilePairs = new ArrayList<AbstractAffineTile2D<?>[]>();
AbstractAffineTile2D.pairOverlappingTiles(tiles, tilePairs);
/* check if there was any pair */
if (tilePairs.size() == 0) {
Utils.log("Elastic montage could not find any overlapping patches after pre-montaging.");
return;
}
Utils.log(tilePairs.size() + " pairs of patches will be block-matched...");
/* make pairwise global models local */
final ArrayList<Triple<AbstractAffineTile2D<?>, AbstractAffineTile2D<?>, InvertibleCoordinateTransform>> pairs = new ArrayList<Triple<AbstractAffineTile2D<?>, AbstractAffineTile2D<?>, InvertibleCoordinateTransform>>();
/*
* The following casting madness is necessary to get this code compiled
* with Sun/Oracle Java 6 which otherwise generates an inconvertible
* type exception.
*
* TODO Remove as soon as this bug is fixed in Sun/Oracle javac.
*/
for (final AbstractAffineTile2D<?>[] pair : tilePairs) {
final AbstractAffineModel2D<?> m;
switch(param.po.desiredModelIndex) {
case 0:
final TranslationModel2D t = (TranslationModel2D) (Object) pair[1].getModel().createInverse();
t.concatenate((TranslationModel2D) (Object) pair[0].getModel());
m = t;
break;
case 1:
final RigidModel2D r = (RigidModel2D) (Object) pair[1].getModel().createInverse();
r.concatenate((RigidModel2D) (Object) pair[0].getModel());
m = r;
break;
case 2:
final SimilarityModel2D s = (SimilarityModel2D) (Object) pair[1].getModel().createInverse();
s.concatenate((SimilarityModel2D) (Object) pair[0].getModel());
m = s;
break;
case 3:
final AffineModel2D a = (AffineModel2D) (Object) pair[1].getModel().createInverse();
a.concatenate((AffineModel2D) (Object) pair[0].getModel());
m = a;
break;
default:
m = null;
}
pairs.add(new Triple<AbstractAffineTile2D<?>, AbstractAffineTile2D<?>, InvertibleCoordinateTransform>(pair[0], pair[1], m));
}
/* Elastic alignment */
/* Initialization */
final double springTriangleHeightTwice = 2 * Math.sqrt(0.75 * param.springLengthSpringMesh * param.springLengthSpringMesh);
final ArrayList<SpringMesh> meshes = new ArrayList<SpringMesh>(tiles.size());
final HashMap<AbstractAffineTile2D<?>, SpringMesh> tileMeshMap = new HashMap<AbstractAffineTile2D<?>, SpringMesh>();
for (final AbstractAffineTile2D<?> tile : tiles) {
final double w = tile.getWidth();
final double h = tile.getHeight();
final int numX = Math.max(2, (int) Math.ceil(w / param.springLengthSpringMesh) + 1);
final int numY = Math.max(2, (int) Math.ceil(h / springTriangleHeightTwice) + 1);
final double wMesh = (numX - 1) * param.springLengthSpringMesh;
final double hMesh = (numY - 1) * springTriangleHeightTwice;
final SpringMesh mesh = new SpringMesh(numX, numY, wMesh, hMesh, param.stiffnessSpringMesh, param.maxStretchSpringMesh * param.bmScale, param.dampSpringMesh);
meshes.add(mesh);
tileMeshMap.put(tile, mesh);
}
// final int blockRadius = Math.max( 32, Util.roundPos( param.springLengthSpringMesh / 2 ) );
final int blockRadius = Math.max(Util.roundPos(16 / param.bmScale), param.bmBlockRadius);
/**
* TODO set this something more than the largest error by the approximate model
*/
final int searchRadius = param.bmSearchRadius;
final AbstractModel<?> localSmoothnessFilterModel = mpicbg.trakem2.align.Util.createModel(param.bmLocalModelIndex);
for (final Triple<AbstractAffineTile2D<?>, AbstractAffineTile2D<?>, InvertibleCoordinateTransform> pair : pairs) {
final AbstractAffineTile2D<?> t1 = pair.a;
final AbstractAffineTile2D<?> t2 = pair.b;
final SpringMesh m1 = tileMeshMap.get(t1);
final SpringMesh m2 = tileMeshMap.get(t2);
final ArrayList<PointMatch> pm12 = new ArrayList<PointMatch>();
final ArrayList<PointMatch> pm21 = new ArrayList<PointMatch>();
final ArrayList<Vertex> v1 = m1.getVertices();
final ArrayList<Vertex> v2 = m2.getVertices();
final String patchName1 = patchName(t1.getPatch());
final String patchName2 = patchName(t2.getPatch());
final PatchImage pi1 = t1.getPatch().createTransformedImage();
if (pi1 == null) {
Utils.log("Patch `" + patchName1 + "' failed generating a transformed image. Skipping...");
continue;
}
final PatchImage pi2 = t2.getPatch().createTransformedImage();
if (pi2 == null) {
Utils.log("Patch `" + patchName2 + "' failed generating a transformed image. Skipping...");
continue;
}
final FloatProcessor fp1 = (FloatProcessor) pi1.target.convertToFloat();
final ByteProcessor mask1 = pi1.getMask();
final FloatProcessor fpMask1 = mask1 == null ? null : scaleByte(mask1);
final FloatProcessor fp2 = (FloatProcessor) pi2.target.convertToFloat();
final ByteProcessor mask2 = pi2.getMask();
final FloatProcessor fpMask2 = mask2 == null ? null : scaleByte(mask2);
if (!fixedTiles.contains(t1)) {
BlockMatching.matchByMaximalPMCC(fp1, fp2, fpMask1, fpMask2, param.bmScale, pair.c, blockRadius, blockRadius, searchRadius, searchRadius, param.bmMinR, param.bmRodR, param.bmMaxCurvatureR, v1, pm12, new ErrorStatistic(1));
if (param.bmUseLocalSmoothnessFilter) {
Utils.log("`" + patchName1 + "' > `" + patchName2 + "': found " + pm12.size() + " correspondence candidates.");
localSmoothnessFilterModel.localSmoothnessFilter(pm12, pm12, param.bmLocalRegionSigma, param.bmMaxLocalEpsilon, param.bmMaxLocalTrust);
Utils.log("`" + patchName1 + "' > `" + patchName2 + "': " + pm12.size() + " candidates passed local smoothness filter.");
} else {
Utils.log("`" + patchName1 + "' > `" + patchName2 + "': found " + pm12.size() + " correspondences.");
}
} else {
Utils.log("Skipping fixed patch `" + patchName1 + "'.");
}
if (!fixedTiles.contains(t2)) {
BlockMatching.matchByMaximalPMCC(fp2, fp1, fpMask2, fpMask1, param.bmScale, pair.c.createInverse(), blockRadius, blockRadius, searchRadius, searchRadius, param.bmMinR, param.bmRodR, param.bmMaxCurvatureR, v2, pm21, new ErrorStatistic(1));
if (param.bmUseLocalSmoothnessFilter) {
Utils.log("`" + patchName1 + "' < `" + patchName2 + "': found " + pm21.size() + " correspondence candidates.");
localSmoothnessFilterModel.localSmoothnessFilter(pm21, pm21, param.bmLocalRegionSigma, param.bmMaxLocalEpsilon, param.bmMaxLocalTrust);
Utils.log("`" + patchName1 + "' < `" + patchName2 + "': " + pm21.size() + " candidates passed local smoothness filter.");
} else {
Utils.log("`" + patchName1 + "' < `" + patchName2 + "': found " + pm21.size() + " correspondences.");
}
} else {
Utils.log("Skipping fixed patch `" + patchName2 + "'.");
}
for (final PointMatch pm : pm12) {
final Vertex p1 = (Vertex) pm.getP1();
final Vertex p2 = new Vertex(pm.getP2());
p1.addSpring(p2, new Spring(0, 1.0f));
m2.addPassiveVertex(p2);
}
for (final PointMatch pm : pm21) {
final Vertex p1 = (Vertex) pm.getP1();
final Vertex p2 = new Vertex(pm.getP2());
p1.addSpring(p2, new Spring(0, 1.0f));
m1.addPassiveVertex(p2);
}
}
/* initialize */
for (final Map.Entry<AbstractAffineTile2D<?>, SpringMesh> entry : tileMeshMap.entrySet()) entry.getValue().init(entry.getKey().getModel());
/* optimize the meshes */
try {
final long t0 = System.currentTimeMillis();
IJ.log("Optimizing spring meshes...");
if (param.useLegacyOptimizer) {
Utils.log(" ...using legacy optimizer...");
SpringMesh.optimizeMeshes2(meshes, param.po.maxEpsilon, param.maxIterationsSpringMesh, param.maxPlateauwidthSpringMesh, param.visualize);
} else {
SpringMesh.optimizeMeshes(meshes, param.po.maxEpsilon, param.maxIterationsSpringMesh, param.maxPlateauwidthSpringMesh, param.visualize);
}
IJ.log("Done optimizing spring meshes. Took " + (System.currentTimeMillis() - t0) + " ms");
} catch (final NotEnoughDataPointsException e) {
Utils.log("There were not enough data points to get the spring mesh optimizing.");
e.printStackTrace();
return;
}
/* apply */
for (final Map.Entry<AbstractAffineTile2D<?>, SpringMesh> entry : tileMeshMap.entrySet()) {
final AbstractAffineTile2D<?> tile = entry.getKey();
if (!fixedTiles.contains(tile)) {
final Patch patch = tile.getPatch();
final SpringMesh mesh = entry.getValue();
final Set<PointMatch> matches = mesh.getVA().keySet();
Rectangle box = patch.getCoordinateTransformBoundingBox();
/* compensate for existing coordinate transform bounding box */
for (final PointMatch pm : matches) {
final Point p1 = pm.getP1();
final double[] l = p1.getL();
l[0] += box.x;
l[1] += box.y;
}
final ThinPlateSplineTransform mlt = ElasticLayerAlignment.makeTPS(matches);
patch.appendCoordinateTransform(mlt);
box = patch.getCoordinateTransformBoundingBox();
patch.getAffineTransform().setToTranslation(box.x, box.y);
patch.updateInDatabase("transform");
patch.updateBucket();
patch.updateMipMaps();
}
}
Utils.log("Done.");
}
use of ini.trakem2.display.Coordinate in project TrakEM2 by trakem2.
the class AbstractAffineTile2D method pairOverlappingTiles.
/**
* Search a {@link List} of {@link AbstractAffineTile2D Tiles} for
* overlapping pairs. Adds the pairs into tilePairs.
*
* @param tiles
* @param tilePairs
*/
public static final <AAT extends AbstractAffineTile2D<?>> void pairOverlappingTiles(final List<AAT> tiles, final List<AbstractAffineTile2D<?>[]> tilePairs, final boolean sloppyOverlapTest) {
final HashSet<Patch> visited = new HashSet<Patch>();
final ArrayList<AbstractAffineTile2D<?>[]> tilePairCandidates = new ArrayList<AbstractAffineTile2D<?>[]>();
/* LUT for tiles */
final Hashtable<Patch, AAT> lut = new Hashtable<Patch, AAT>();
for (final AAT tile : tiles) lut.put(tile.patch, tile);
for (int a = 0; a < tiles.size(); ++a) {
final AbstractAffineTile2D<?> ta = tiles.get(a);
final Patch pa = ta.patch;
visited.add(pa);
final Layer la = pa.getLayer();
for (final Displayable d : la.getDisplayables(Patch.class, pa.getBoundingBox())) {
final Patch pb = (Patch) d;
if (visited.contains(pb))
continue;
final AAT tb = lut.get(pb);
if (tb == null)
continue;
tilePairCandidates.add(new AbstractAffineTile2D<?>[] { ta, tb });
}
}
if (sloppyOverlapTest)
tilePairs.addAll(tilePairCandidates);
else {
// TODO Fix this and use what the user wants to provide
final ExecutorService exec = Executors.newFixedThreadPool(Runtime.getRuntime().availableProcessors());
final ArrayList<Future<?>> futures = new ArrayList<Future<?>>();
for (final AbstractAffineTile2D<?>[] tatb : tilePairCandidates) {
futures.add(exec.submit(new Runnable() {
@Override
public void run() {
if (tatb[0].intersects(tatb[1]))
synchronized (tilePairs) {
tilePairs.add(tatb);
}
}
}));
}
try {
for (final Future<?> f : futures) f.get();
} catch (final InterruptedException e) {
e.printStackTrace();
} catch (final ExecutionException e) {
e.printStackTrace();
} finally {
exec.shutdown();
}
}
// // 1. Precompute the Area of each tile's Patch
// final HashMap< Patch, Pair< AAT, Area > > m = new HashMap< Patch, Pair< AAT, Area > >();
// // A lazy collection of pairs, computed in parallel ahead of consumption
// final Iterable< Pair< AAT, Area > > ts =
// new ParallelMapping< AAT, Pair< AAT, Area > >(
// tiles,
// new TaskFactory< AAT, Pair< AAT, Area > >() {
// @Override
// public Pair< AAT, Area > process( final AAT tile ) {
// return new Pair< AAT, Area >( tile, tile.patch.getArea() );
// }
// }
// );
// for ( final Pair< AAT, Area > t : ts) {
// m.put( t.a.patch, t );
// }
//
// // 2. Obtain the list of tile pairs, at one list per tile
// final Iterable< List<AbstractAffineTile2D< ? >[]> > pairsList =
// new ParallelMapping< AAT, List<AbstractAffineTile2D< ? >[]> >(
// tiles,
// new TaskFactory< AAT, List<AbstractAffineTile2D< ? >[]> >() {
// @Override
// public List<AbstractAffineTile2D< ? >[]> process( final AAT ta ) {
// final Area a;
// synchronized (m) {
// a = m.get( ta.patch ).b;
// }
// final ArrayList<AbstractAffineTile2D< ? >[]> seq = new ArrayList<AbstractAffineTile2D< ? >[]>();
// for ( final Patch p : ta.patch.getLayer().getIntersecting( ta.patch, Patch.class ) ) {
// if ( p == ta.patch )
// continue;
// final Pair< AAT, Area > pair;
// synchronized (m) {
// pair = m.get(p);
// }
// // Check that the Patch is among those to consider in the alignment
// if ( null != pair ) {
// // Check that the Patch visible pixels overlap -- may not if it has an alpha mask or coordinate transform
// if ( M.intersects( a, pair.b ) ) {
// seq.add( new AbstractAffineTile2D< ? >[]{ ta, pair.a });
// }
// }
// }
// return seq;
// }
// }
// );
//
// for (final List<AbstractAffineTile2D<?>[]> list: pairsList) {
// tilePairs.addAll(list);
// }
}
use of ini.trakem2.display.Coordinate 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;
}
Aggregations