use of ini.trakem2.display.Displayable in project TrakEM2 by trakem2.
the class FilterEditor method GUI.
public static final void GUI(final Collection<Patch> patches, final Patch reference) {
final ArrayList<FilterWrapper> filters = new ArrayList<FilterWrapper>();
// Find out if all images have the exact same filters
final StringBuilder sb = new StringBuilder();
final Patch ref = (null == reference ? patches.iterator().next() : reference);
final IFilter[] refFilters = ref.getFilters();
if (null != refFilters) {
// makes a copy of the IFilter
for (final IFilter f : refFilters) filters.add(new FilterWrapper(f));
}
//
for (final Patch p : patches) {
if (ref == p)
continue;
final IFilter[] fs = p.getFilters();
// ok
if (null == fs && null == refFilters)
continue;
if ((null != refFilters && null == fs) || (null == refFilters && null != fs) || (null != refFilters && null != fs && fs.length != refFilters.length)) {
sb.append("WARNING: patch #" + p.getId() + " has a different number of filters than reference patch #" + ref.getId());
continue;
}
// Compare each
for (int i = 0; i < refFilters.length; ++i) {
if (fs[i].getClass() != refFilters[i].getClass()) {
sb.append("WARNING: patch #" + p.getId() + " has a different filters than reference patch #" + ref.getId());
break;
}
// Does the filter have the same parameters?
if (!filters.get(i).sameParameterValues(new FilterWrapper(fs[i]))) {
sb.append("WARNING: patch #" + p.getId() + " has filter '" + fs[i].getClass().getSimpleName() + "' with different parameters than the reference patch #" + ref.getId());
}
}
}
if (sb.length() > 0) {
final GenericDialog gd = new GenericDialog("WARNING", null == Display.getFront() ? IJ.getInstance() : Display.getFront().getFrame());
gd.addMessage("Filters are not all the same for all images:");
gd.addTextAreas(sb.toString(), null, 20, 30);
final String[] s = new String[] { "Use the filters of the reference image", "Start from an empty list of filters" };
gd.addChoice("Do:", s, s[0]);
gd.showDialog();
if (gd.wasCanceled())
return;
if (1 == gd.getNextChoiceIndex())
filters.clear();
}
final TableChosenFilters tcf = new TableChosenFilters(filters);
final TableParameters tp = new TableParameters(tcf);
tcf.setupListener(tp);
final TableAvailableFilters taf = new TableAvailableFilters(tcf);
if (filters.size() > 0) {
tcf.getSelectionModel().setSelectionInterval(0, 0);
}
final JFrame frame = new JFrame("Image filters");
final JButton set = new JButton("Set");
final JComboBox pulldown = new JComboBox(new String[] { "Selected images (" + patches.size() + ")", "All images in layer " + (ref.getLayer().getParent().indexOf(ref.getLayer()) + 1), "All images in layer range..." });
final Component[] cs = new Component[] { set, pulldown, tcf, tp, taf };
set.addActionListener(new ActionListener() {
@Override
public void actionPerformed(final ActionEvent e) {
if (check(frame, filters)) {
final ArrayList<Patch> ps = new ArrayList<Patch>();
switch(pulldown.getSelectedIndex()) {
case 0:
ps.addAll(patches);
break;
case 1:
for (final Displayable d : ref.getLayer().getDisplayables(Patch.class)) {
ps.add((Patch) d);
}
break;
case 2:
final GenericDialog gd = new GenericDialog("Apply filters");
Utils.addLayerRangeChoices(ref.getLayer(), gd);
gd.addStringField("Image title matches:", "", 30);
gd.addCheckbox("Visible images only", true);
gd.showDialog();
if (gd.wasCanceled())
return;
final String regex = gd.getNextString();
final boolean visible_only = gd.getNextBoolean();
Pattern pattern = null;
if (0 != regex.length()) {
pattern = Pattern.compile(regex);
}
for (final Layer l : ref.getLayer().getParent().getLayers(gd.getNextChoiceIndex(), gd.getNextChoiceIndex())) {
for (final Displayable d : l.getDisplayables(Patch.class, visible_only)) {
if (null != pattern && !pattern.matcher(d.getTitle()).matches()) {
continue;
}
ps.add((Patch) d);
}
}
}
apply(ps, filters, cs, false);
}
}
});
final JPanel buttons = new JPanel();
final JLabel label = new JLabel("Push F1 for help");
final GridBagConstraints c2 = new GridBagConstraints();
final GridBagLayout gb2 = new GridBagLayout();
buttons.setLayout(gb2);
c2.anchor = GridBagConstraints.WEST;
c2.gridx = 0;
gb2.setConstraints(label, c2);
buttons.add(label);
c2.gridx = 1;
c2.weightx = 1;
final JPanel empty = new JPanel();
gb2.setConstraints(empty, c2);
buttons.add(empty);
c2.gridx = 2;
c2.weightx = 0;
c2.anchor = GridBagConstraints.EAST;
final JLabel a = new JLabel("Apply to:");
gb2.setConstraints(a, c2);
buttons.add(a);
c2.gridx = 3;
c2.insets = new Insets(4, 10, 4, 0);
gb2.setConstraints(pulldown, c2);
buttons.add(pulldown);
c2.gridx = 4;
gb2.setConstraints(set, c2);
buttons.add(set);
//
taf.setPreferredSize(new Dimension(350, 500));
tcf.setPreferredSize(new Dimension(350, 250));
tp.setPreferredSize(new Dimension(350, 250));
//
final GridBagLayout gb = new GridBagLayout();
final GridBagConstraints c = new GridBagConstraints();
final JPanel all = new JPanel();
all.setBackground(Color.white);
all.setPreferredSize(new Dimension(700, 500));
all.setLayout(gb);
c.gridx = 0;
c.gridy = 0;
c.anchor = GridBagConstraints.NORTHWEST;
c.fill = GridBagConstraints.BOTH;
c.gridheight = 2;
c.weightx = 0.5;
final JScrollPane p1 = new JScrollPane(taf);
p1.setPreferredSize(taf.getPreferredSize());
gb.setConstraints(p1, c);
all.add(p1);
c.gridx = 1;
c.gridy = 0;
c.gridheight = 1;
c.weighty = 0.7;
final JScrollPane p2 = new JScrollPane(tcf);
p2.setPreferredSize(tcf.getPreferredSize());
gb.setConstraints(p2, c);
all.add(p2);
c.gridx = 1;
c.gridy = 1;
c.weighty = 0.3;
final JScrollPane p3 = new JScrollPane(tp);
p3.setPreferredSize(tp.getPreferredSize());
gb.setConstraints(p3, c);
all.add(p3);
c.gridx = 0;
c.gridy = 2;
c.gridwidth = 2;
c.weightx = 1;
c.weighty = 0;
gb.setConstraints(buttons, c);
all.add(buttons);
final KeyAdapter help = new KeyAdapter() {
@Override
public void keyPressed(final KeyEvent ke) {
if (ke.getKeyCode() == KeyEvent.VK_F1) {
final GenericDialog gd = new GenericDialog("Help :: image filters");
gd.addMessage("In the table 'Available Filters':\n" + " - double-click a filter to add it to the table of 'Chosen Filters'\n \n" + "In the table 'Chosen Filters':\n" + " - double-click a filter to remove it.\n" + " - PAGE UP/DOWN keys move the filter up/down in the list.\n" + " - 'Delete' key removes the selected filter.\n \n" + "In the table of parameter names and values:\n" + " - double-click a value to edit it. Then push enter to set the new value.\n \n" + "What you need to know:\n" + " - filters are set and applied in order, so order matters.\n" + " - filters with parameters for which you entered a value of zero\nwill result in a warning message.\n" + " - when applying the filters, if you choose 'Selected images', these are the images\nthat were selected when the filter editor was opened.\n" + " - when applying the filters, if you want to filter for a regular expression pattern\nin the image name, use the 'All images in layer range...' option,\nwhere a range of one single layer is also possible.");
gd.hideCancelButton();
gd.setModal(false);
gd.showDialog();
}
}
};
taf.addKeyListener(help);
tcf.addKeyListener(help);
tp.addKeyListener(help);
all.addKeyListener(help);
buttons.addKeyListener(help);
empty.addKeyListener(help);
a.addKeyListener(help);
frame.getContentPane().add(all);
frame.pack();
frame.setVisible(true);
}
use of ini.trakem2.display.Displayable in project TrakEM2 by trakem2.
the class DefaultGraphicsSource method paintOnTop.
/**
* Paints bounding boxes of selected objects as pink and active object as white.
*/
public void paintOnTop(final Graphics2D g, final Display display, final Rectangle srcRect, final double magnification) {
if (ProjectToolbar.getToolId() >= ProjectToolbar.PENCIL) {
// PENCIL == SPARE2
return;
}
g.setColor(Color.pink);
Displayable active = display.getActive();
final Rectangle bbox = new Rectangle();
for (final Displayable d : display.getSelection().getSelected()) {
d.getBoundingBox(bbox);
if (d == active) {
g.setColor(Color.white);
// g.drawPolygon(d.getPerimeter());
g.drawRect(bbox.x, bbox.y, bbox.width, bbox.height);
g.setColor(Color.pink);
} else {
// g.drawPolygon(d.getPerimeter());
g.drawRect(bbox.x, bbox.y, bbox.width, bbox.height);
}
}
}
use of ini.trakem2.display.Displayable in project TrakEM2 by trakem2.
the class AlignTask method createTransformPropertiesTable.
/**
* Creates a map only for visible patches that intersect vdata.
* @param src_vdata represents the VectorData instances in original form, of the original project and layer set.
* @param tgt_vdata if not null, it must have the same size as src_data and their elements correspond one-to-one (as in, tgt element a clone of src element at the same index).
* @param lids_to_operate The id of the layers on which any operation will be done
* tgt_data enables transformVectorData to apply the transforms to copies of the src_vdata in another project.
*/
public static final ReferenceData createTransformPropertiesTable(final List<Displayable> src_vdata, final List<Displayable> tgt_vdata, final Set<Long> lids_to_operate) {
if (src_vdata.isEmpty())
return null;
final Map<Long, Patch.TransformProperties> tp = new HashMap<Long, Patch.TransformProperties>();
// A map of Displayable vs a map of Layer id vs list of Patch ids in that Layer that lay under the Patch, sorted by stack index
final Map<Displayable, Map<Long, TreeMap<Integer, Long>>> underlying = new HashMap<Displayable, Map<Long, TreeMap<Integer, Long>>>();
// The set of layers used
final Set<Long> src_layer_lids_used = new HashSet<Long>();
// Parallelize! This operation can be insanely expensive
final int nproc = Runtime.getRuntime().availableProcessors();
final ExecutorService exec = Utils.newFixedThreadPool(nproc, "AlignTask-createTransformPropertiesTable");
final List<Future<?>> dtasks = new ArrayList<Future<?>>();
final List<Future<?>> ltasks = new ArrayList<Future<?>>();
final Thread current = Thread.currentThread();
try {
for (int i = src_vdata.size() - 1; i > -1; i--) {
final Displayable src_d = src_vdata.get(i);
// filter out
if (!(src_d instanceof VectorData))
continue;
// use src_d if tgt_vdata is null
final Displayable tgt_d = null == tgt_vdata ? src_d : tgt_vdata.get(i);
// Some checking
if (!(tgt_d instanceof VectorData)) {
Utils.log("WARNING ignoring provided tgt_vdata " + tgt_d + " which is NOT a VectorData instance!");
continue;
}
if (src_d.getClass() != tgt_d.getClass()) {
Utils.log("WARNING src_d and tgt_d are instances of different classes:\n src_d :: " + src_d + "\n tgt_d :: " + tgt_d);
}
dtasks.add(exec.submit(new Runnable() {
@SuppressWarnings({ "unchecked", "rawtypes" })
@Override
public void run() {
final Map<Long, TreeMap<Integer, Long>> under = new HashMap<Long, TreeMap<Integer, Long>>();
synchronized (underlying) {
underlying.put(tgt_d, under);
}
if (current.isInterrupted())
return;
// Iterate the layers in which this VectorData has any data AND which have to be transformed
for (final Long olid : src_d.getLayerIds()) {
final long lid = olid.longValue();
// layer with id 'lid' is not affected
if (!lids_to_operate.contains(lid))
continue;
final Layer la = src_d.getLayerSet().getLayer(lid);
final Area a = src_d.getAreaAt(la);
if (null == a || a.isEmpty()) {
// does not paint in the layer
continue;
}
// The list of patches that lay under VectorData d, sorted by their stack index in the layer
final TreeMap<Integer, Long> stacked_patch_ids = new TreeMap<Integer, Long>();
synchronized (under) {
under.put(lid, stacked_patch_ids);
}
final boolean[] layer_visited = new boolean[] { false };
// Iterate source patches
for (final Patch patch : (Collection<Patch>) (Collection) la.getDisplayables(Patch.class, a, true)) {
// pick visible patches only
if (current.isInterrupted())
return;
try {
ltasks.add(exec.submit(new Runnable() {
@Override
public void run() {
if (current.isInterrupted())
return;
synchronized (patch) {
Patch.TransformProperties props;
synchronized (tp) {
props = tp.get(patch.getId());
}
if (null == props) {
props = patch.getTransformPropertiesCopy();
// Cache the props
synchronized (tp) {
tp.put(patch.getId(), props);
}
}
// Cache this patch as under the VectorData d
synchronized (stacked_patch_ids) {
// sorted by stack index
stacked_patch_ids.put(la.indexOf(patch), patch.getId());
// Utils.log("Added patch for layer " + la + " with stack index " + la.indexOf(patch) + ", patch " + patch);
}
if (!layer_visited[0]) {
// synch may fail to avoid adding it twice
// but it's ok since it's a Set anyway
layer_visited[0] = true;
synchronized (src_layer_lids_used) {
src_layer_lids_used.add(la.getId());
}
}
}
}
}));
} catch (final Throwable t) {
IJError.print(t);
return;
}
}
}
}
}));
}
Utils.wait(dtasks);
Utils.wait(ltasks);
} catch (final Throwable t) {
IJError.print(t);
} finally {
exec.shutdownNow();
}
return new ReferenceData(tp, underlying, src_layer_lids_used);
}
use of ini.trakem2.display.Displayable in project TrakEM2 by trakem2.
the class AlignTask method alignSelection.
public static final void alignSelection(final Selection selection, final int m) throws Exception {
final List<Patch> patches = new ArrayList<Patch>();
for (final Displayable d : selection.getSelected()) if (d instanceof Patch)
patches.add((Patch) d);
final HashSet<Patch> fixedPatches = new HashSet<Patch>();
// Add active Patch, if any, as the nail
final Displayable active = selection.getActive();
if (null != active && active instanceof Patch)
fixedPatches.add((Patch) active);
// Add all locked Patch instances to fixedPatches
for (final Patch patch : patches) if (patch.isLocked())
fixedPatches.add(patch);
alignPatches(patches, fixedPatches, m);
}
use of ini.trakem2.display.Displayable in project TrakEM2 by trakem2.
the class AlignTask method transformPatchesAndVectorData.
/**
* For registering within the same project instance.
*/
public static final void transformPatchesAndVectorData(final Collection<Patch> patches, final Runnable alignment) {
if (patches.isEmpty()) {
Utils.log("No patches to align!");
return;
}
// 1 - Collect all VectorData to transform
final ArrayList<Displayable> vdata = new ArrayList<Displayable>();
final LayerSet ls = patches.iterator().next().getLayerSet();
for (final Layer layer : ls.getLayers()) {
vdata.addAll(layer.getDisplayables(VectorData.class, false, true));
}
vdata.addAll(ls.getZDisplayables(VectorData.class, true));
// Perhaps none:
if (vdata.isEmpty()) {
alignment.run();
return;
}
// 2 - Store current transformation of each Patch under any VectorData
final HashSet<Long> lids = new HashSet<Long>();
for (final Patch p : patches) lids.add(p.getLayer().getId());
final ReferenceData rd = createTransformPropertiesTable(vdata, null, lids);
// 3 - Align:
alignment.run();
// 4 - Transform VectorData instances to match the position of the Patch instances over which they were defined
if (null != rd && !vdata.isEmpty())
transformVectorData(rd, vdata, ls);
}
Aggregations