Search in sources :

Example 31 with Stack

use of ini.trakem2.display.Stack in project TrakEM2 by trakem2.

the class LayerTree method actionPerformed.

public void actionPerformed(ActionEvent ae) {
    try {
        String command = ae.getActionCommand();
        // commands for multiple selections:
        TreePath[] paths = this.getSelectionPaths();
        if (null != paths && paths.length > 1) {
            if (command.equals("Reverse layer Z coords")) {
                // check that all layers belong to the same layer set
                // just do it
                Layer[] layer = new Layer[paths.length];
                LayerSet ls = null;
                for (int i = 0; i < paths.length; i++) {
                    layer[i] = (Layer) ((LayerThing) ((DefaultMutableTreeNode) paths[i].getLastPathComponent()).getUserObject()).getObject();
                    if (null == ls)
                        ls = layer[i].getParent();
                    else if (!ls.equals(layer[i].getParent())) {
                        Utils.showMessage("To reverse, all layers must belong to the same layer set");
                        return;
                    }
                }
                final ArrayList<Layer> al = new ArrayList<Layer>();
                for (int i = 0; i < layer.length; i++) al.add(layer[i]);
                ls.addLayerEditedStep(al);
                // ASSSUMING layers are already Z ordered! CHECK
                for (int i = 0, j = layer.length - 1; i < layer.length / 2; i++, j--) {
                    double z = layer[i].getZ();
                    layer[i].setZ(layer[j].getZ());
                    layer[j].setZ(z);
                }
                updateList(ls);
                ls.addLayerEditedStep(al);
                Display.updateLayerScroller(ls);
            } else if (command.equals("Translate layers in Z...")) {
                GenericDialog gd = ControlWindow.makeGenericDialog("Range");
                gd.addMessage("Translate selected range in the Z axis:");
                gd.addNumericField("by: ", 0, 4);
                gd.showDialog();
                if (gd.wasCanceled())
                    return;
                // else, displace
                double dz = gd.getNextNumber();
                if (Double.isNaN(dz)) {
                    Utils.showMessage("Invalid number");
                    return;
                }
                HashSet<LayerSet> hs_parents = new HashSet<LayerSet>();
                for (int i = 0; i < paths.length; i++) {
                    Layer layer = (Layer) ((LayerThing) ((DefaultMutableTreeNode) paths[i].getLastPathComponent()).getUserObject()).getObject();
                    layer.setZ(layer.getZ() + dz);
                    hs_parents.add(layer.getParent());
                }
                for (LayerSet ls : hs_parents) {
                    updateList(ls);
                }
                // now update all profile's Z ordering in the ProjectTree
                ProjectThing root_pt = project.getRootProjectThing();
                for (final ProjectThing pt : root_pt.findChildrenOfType("profile_list")) {
                    pt.fixZOrdering();
                    project.getProjectTree().updateList(pt);
                }
                project.getProjectTree().updateUILater();
            // Display.updateLayerScroller((LayerSet)((DefaultMutableTreeNode)getModel().getRoot()).getUserObject());
            } else if (command.equals("Delete...")) {
                if (!Utils.check("Really remove all selected layers?"))
                    return;
                for (int i = 0; i < paths.length; i++) {
                    DefaultMutableTreeNode lnode = (DefaultMutableTreeNode) paths[i].getLastPathComponent();
                    LayerThing lt = (LayerThing) lnode.getUserObject();
                    Layer layer = (Layer) lt.getObject();
                    if (!layer.remove(false)) {
                        Utils.showMessage("Could not delete layer " + layer);
                        this.updateUILater();
                        return;
                    }
                    if (lt.remove(false)) {
                        ((DefaultTreeModel) this.getModel()).removeNodeFromParent(lnode);
                    }
                }
                this.updateUILater();
            } else if (command.equals("Scale Z and thickness...")) {
                GenericDialog gd = new GenericDialog("Scale Z");
                gd.addNumericField("scale: ", 1.0, 2);
                gd.showDialog();
                double scale = gd.getNextNumber();
                if (Double.isNaN(scale) || 0 == scale) {
                    Utils.showMessage("Imvalid scaling factor: " + scale);
                    return;
                }
                for (int i = 0; i < paths.length; i++) {
                    DefaultMutableTreeNode lnode = (DefaultMutableTreeNode) paths[i].getLastPathComponent();
                    LayerThing lt = (LayerThing) lnode.getUserObject();
                    Layer layer = (Layer) lt.getObject();
                    layer.setZ(layer.getZ() * scale);
                    layer.setThickness(layer.getThickness() * scale);
                }
                this.updateUILater();
            } else {
                Utils.showMessage("Don't know what to do with command " + command + " for multiple selected nodes");
            }
            return;
        }
        // commands for single selection:
        if (null == selected_node)
            return;
        LayerThing thing = (LayerThing) selected_node.getUserObject();
        LayerThing new_thing = null;
        TemplateThing tt = null;
        Object ob = null;
        int i_position = -1;
        if (command.startsWith("new ")) {
            String name = command.substring(4).toLowerCase();
            if (name.equals("layer")) {
                // Create new Layer and add it to the selected node
                LayerSet set = (LayerSet) thing.getObject();
                Layer new_layer = Layer.create(thing.getProject(), set);
                if (null == new_layer)
                    return;
                tt = thing.getChildTemplate("layer");
                ob = new_layer;
                Display.updateTitle(set);
            } else if (name.equals("layer set")) {
                // with space in the middle
                // Create a new LayerSet and add it in the middle
                Layer layer = (Layer) thing.getObject();
                LayerSet new_set = layer.getParent().create(layer);
                if (null == new_set)
                    return;
                layer.add(new_set);
                // add it at the end of the list
                // with space, not underscore
                tt = thing.getChildTemplate("layer set");
                ob = new_set;
                i_position = selected_node.getChildCount();
                Display.update(layer);
            } else {
                Utils.log("LayerTree.actionPerformed: don't know what to do with the command: " + command);
                return;
            }
        } else if (command.equals("many new layers...")) {
            LayerSet set = (LayerSet) thing.getObject();
            List<Layer> layers = Layer.createMany(set.getProject(), set);
            // add them to the tree as LayerThing
            if (null == layers)
                return;
            for (Layer la : layers) {
                // null layers will be skipped
                addLayer(set, la);
            }
            Display.updateTitle(set);
            return;
        } else if (command.equals("Show")) {
            // create a new Display
            DBObject dbo = (DBObject) thing.getObject();
            // the top level LayerSet
            if (thing.getType().equals("layer_set") && null == ((LayerSet) dbo).getParent())
                return;
            Display.createDisplay(dbo.getProject(), thing.getType().equals("layer") ? (Layer) dbo : ((LayerSet) dbo).getParent());
            return;
        } else if (command.equals("Show centered in Display")) {
            LayerSet ls = (LayerSet) thing.getObject();
            Display.showCentered(ls.getParent(), ls, false, false);
        } else if (command.equals("Delete...")) {
            remove(true, thing, selected_node);
            return;
        } else if (command.equals("Import stack...")) {
            if (thing.getObject() instanceof LayerSet) {
                LayerSet set = (LayerSet) thing.getObject();
                Layer layer = null;
                if (0 == set.getLayers().size()) {
                    layer = Layer.create(set.getProject(), set);
                    if (null == layer)
                        return;
                    tt = thing.getChildTemplate("Layer");
                    ob = layer;
                } else
                    // click on a desired, existing layer.
                    return;
                layer.getProject().getLoader().importStack(layer, null, true);
            } else if (thing.getObject() instanceof Layer) {
                Layer layer = (Layer) thing.getObject();
                layer.getProject().getLoader().importStack(layer, null, true);
                return;
            }
        } else if (command.equals("Import grid...")) {
            if (thing.getObject() instanceof Layer) {
                Layer layer = (Layer) thing.getObject();
                layer.getProject().getLoader().importGrid(layer);
            }
        } else if (command.equals("Import sequence as grid...")) {
            if (thing.getObject() instanceof Layer) {
                Layer layer = (Layer) thing.getObject();
                layer.getProject().getLoader().importSequenceAsGrid(layer);
            }
        } else if (command.equals("Import from text file...")) {
            if (thing.getObject() instanceof Layer) {
                Layer layer = (Layer) thing.getObject();
                layer.getProject().getLoader().importImages(layer);
            }
        } else if (command.equals("Resize LayerSet...")) {
            if (thing.getObject() instanceof LayerSet) {
                LayerSet ls = (LayerSet) thing.getObject();
                ij.gui.GenericDialog gd = ControlWindow.makeGenericDialog("Resize LayerSet");
                gd.addNumericField("new width: ", ls.getLayerWidth(), 3);
                gd.addNumericField("new height: ", ls.getLayerHeight(), 3);
                gd.addChoice("Anchor: ", LayerSet.ANCHORS, LayerSet.ANCHORS[0]);
                gd.showDialog();
                if (gd.wasCanceled())
                    return;
                float new_width = (float) gd.getNextNumber(), new_height = (float) gd.getNextNumber();
                // will complain and prevent cropping existing Displayable objects
                ls.setDimensions(new_width, new_height, gd.getNextChoiceIndex());
            }
        } else if (command.equals("Autoresize LayerSet")) {
            if (thing.getObject() instanceof LayerSet) {
                LayerSet ls = (LayerSet) thing.getObject();
                ls.setMinimumDimensions();
            }
        } else if (command.equals("Adjust...")) {
            if (thing.getObject() instanceof Layer) {
                Layer layer = (Layer) thing.getObject();
                ij.gui.GenericDialog gd = ControlWindow.makeGenericDialog("Adjust Layer");
                gd.addNumericField("new z: ", layer.getZ(), 4);
                gd.addNumericField("new thickness: ", layer.getThickness(), 4);
                gd.showDialog();
                if (gd.wasCanceled())
                    return;
                double new_z = gd.getNextNumber();
                layer.setThickness(gd.getNextNumber());
                if (new_z != layer.getZ()) {
                    layer.setZ(new_z);
                    // move in the tree
                    /*
						DefaultMutableTreeNode child = findNode(thing, this);
						DefaultMutableTreeNode parent = (DefaultMutableTreeNode)child.getParent();
						parent.remove(child);
						// reinsert
						int n = parent.getChildCount();
						int i = 0;
						for (; i < n; i++) {
							DefaultMutableTreeNode child_node = (DefaultMutableTreeNode)parent.getChildAt(i);
							LayerThing child_thing = (LayerThing)child_node.getUserObject();
							if (!child_thing.getType().equals("Layer")) continue;
							double iz = ((Layer)child_thing.getObject()).getZ();
							if (iz < new_z) continue;
							// else, add the layer here, after this one
							break;
						}
						((DefaultTreeModel)this.getModel()).insertNodeInto(child, parent, i);
						*/
                    // fix tree crappiness (empty slot ?!?)
                    /* // the fix doesn't work. ARGH TODO
						Enumeration e = parent.children();
						parent.removeAllChildren();
						i = 0;
						while (e.hasMoreElements()) {
							//parent.add((DefaultMutableTreeNode)e.nextElement());
							((DefaultTreeModel)this.getModel()).insertNodeInto(child, parent, i);
							i++;
						}*/
                    // easier and correct: overkill
                    updateList(layer.getParent());
                    // set selected
                    DefaultMutableTreeNode child = findNode(thing, this);
                    TreePath treePath = new TreePath(child.getPath());
                    this.scrollPathToVisible(treePath);
                    this.setSelectionPath(treePath);
                }
            }
            return;
        } else if (command.equals("Rename...")) {
            GenericDialog gd = ControlWindow.makeGenericDialog("Rename");
            gd.addStringField("new name: ", thing.getTitle());
            gd.showDialog();
            if (gd.wasCanceled())
                return;
            project.getRootLayerSet().addUndoStep(new RenameThingStep(thing));
            thing.setTitle(gd.getNextString());
            project.getRootLayerSet().addUndoStep(new RenameThingStep(thing));
        } else if (command.equals("Translate layers in Z...")) {
            // / TODO: this method should use multiple selections directly on the tree
            if (thing.getObject() instanceof LayerSet) {
                LayerSet ls = (LayerSet) thing.getObject();
                ArrayList<Layer> al_layers = ls.getLayers();
                String[] layer_names = new String[al_layers.size()];
                for (int i = 0; i < layer_names.length; i++) {
                    layer_names[i] = ls.getProject().findLayerThing(al_layers.get(i)).toString();
                }
                GenericDialog gd = ControlWindow.makeGenericDialog("Range");
                gd.addMessage("Translate selected range in the Z axis:");
                gd.addChoice("from: ", layer_names, layer_names[0]);
                gd.addChoice("to: ", layer_names, layer_names[layer_names.length - 1]);
                gd.addNumericField("by: ", 0, 4);
                gd.showDialog();
                if (gd.wasCanceled())
                    return;
                // else, displace
                double dz = gd.getNextNumber();
                if (Double.isNaN(dz)) {
                    Utils.showMessage("Invalid number");
                    return;
                }
                int i_start = gd.getNextChoiceIndex();
                int i_end = gd.getNextChoiceIndex();
                for (int i = i_start; i <= i_end; i++) {
                    Layer layer = (Layer) al_layers.get(i);
                    layer.setZ(layer.getZ() + dz);
                }
                // update node labels and position
                updateList(ls);
            }
        } else if (command.equals("Reverse layer Z coords...")) {
            // / TODO: this method should use multiple selections directly on the tree
            if (thing.getObject() instanceof LayerSet) {
                LayerSet ls = (LayerSet) thing.getObject();
                ArrayList<Layer> al_layers = ls.getLayers();
                String[] layer_names = new String[al_layers.size()];
                for (int i = 0; i < layer_names.length; i++) {
                    layer_names[i] = ls.getProject().findLayerThing(al_layers.get(i)).toString();
                }
                GenericDialog gd = ControlWindow.makeGenericDialog("Range");
                gd.addMessage("Reverse Z coordinates of selected range:");
                gd.addChoice("from: ", layer_names, layer_names[0]);
                gd.addChoice("to: ", layer_names, layer_names[layer_names.length - 1]);
                gd.showDialog();
                if (gd.wasCanceled())
                    return;
                int i_start = gd.getNextChoiceIndex();
                int i_end = gd.getNextChoiceIndex();
                for (int i = i_start, j = i_end; i < i_end / 2; i++, j--) {
                    Layer layer1 = (Layer) al_layers.get(i);
                    double z1 = layer1.getZ();
                    Layer layer2 = (Layer) al_layers.get(j);
                    layer1.setZ(layer2.getZ());
                    layer2.setZ(z1);
                }
                // update node labels and position
                updateList(ls);
            }
        } else if (command.equals("Search...")) {
            Search.showWindow();
        } else if (command.equals("Reset layer Z and thickness")) {
            LayerSet ls = ((LayerSet) thing.getObject());
            List<Layer> layers = ls.getLayers();
            ls.addLayerEditedStep(layers);
            int i = 0;
            for (final Layer la : ls.getLayers()) {
                la.setZ(i++);
                la.setThickness(1);
            }
            ls.addLayerEditedStep(layers);
        } else {
            Utils.log("LayerTree.actionPerformed: don't know what to do with the command: " + command);
            return;
        }
        if (null == tt)
            return;
        new_thing = new LayerThing(tt, thing.getProject(), ob);
        if (-1 == i_position && new_thing.getType().equals("layer")) {
            // find the node whose 'z' is larger than z, and add the Layer before that.
            // (just because there could be objects other than LayerThing with a Layer in it in the future, so set.getLayers().indexOf(layer) may not be useful)
            double z = ((Layer) ob).getZ();
            int n = selected_node.getChildCount();
            int i = 0;
            for (; i < n; i++) {
                DefaultMutableTreeNode child_node = (DefaultMutableTreeNode) selected_node.getChildAt(i);
                LayerThing child_thing = (LayerThing) child_node.getUserObject();
                if (!child_thing.getType().equals("layer")) {
                    continue;
                }
                double iz = ((Layer) child_thing.getObject()).getZ();
                if (iz < z) {
                    continue;
                }
                // else, add the layer here, after this one
                break;
            }
            i_position = i;
        }
        thing.addChild(new_thing);
        DefaultMutableTreeNode new_node = new DefaultMutableTreeNode(new_thing);
        ((DefaultTreeModel) this.getModel()).insertNodeInto(new_node, selected_node, i_position);
        TreePath treePath = new TreePath(new_node.getPath());
        this.scrollPathToVisible(treePath);
        this.setSelectionPath(treePath);
        if (new_thing.getType().equals("layer set")) {
            // add the first layer to it, and open it in a Display
            LayerSet newls = (LayerSet) new_thing.getObject();
            Layer la = new Layer(newls.getProject(), 0, 1, newls);
            addLayer(newls, la);
            new Display(newls.getProject(), la);
        }
    } catch (Exception e) {
        IJError.print(e);
    }
}
Also used : DefaultMutableTreeNode(javax.swing.tree.DefaultMutableTreeNode) ArrayList(java.util.ArrayList) DBObject(ini.trakem2.persistence.DBObject) GenericDialog(ij.gui.GenericDialog) ArrayList(java.util.ArrayList) List(java.util.List) HashSet(java.util.HashSet) LayerSet(ini.trakem2.display.LayerSet) DefaultTreeModel(javax.swing.tree.DefaultTreeModel) Layer(ini.trakem2.display.Layer) TreePath(javax.swing.tree.TreePath) DBObject(ini.trakem2.persistence.DBObject) Display(ini.trakem2.display.Display)

Example 32 with Stack

use of ini.trakem2.display.Stack in project TrakEM2 by trakem2.

the class DBLoader method fetchLayer.

/**
 * Load all objects into the Layer: Profile and Pipe from the hs_pt (full of ProjectThing wrapping them), and Patch, LayerSet, DLabel, etc from the database.
 */
private Layer fetchLayer(Project project, long id, HashMap hs_pt) throws Exception {
    ResultSet r = connection.prepareStatement("SELECT * FROM ab_layers WHERE id=" + id).executeQuery();
    Layer layer = null;
    if (r.next()) {
        long layer_id = r.getLong("id");
        layer = new Layer(project, layer_id, r.getDouble("z"), r.getDouble("thickness"));
        // find the Layer's parent
        long parent_id = r.getLong("layer_set_id");
        Object set = hs_pt.get(new Long(parent_id));
        if (null != set) {
            ((LayerSet) set).addSilently(layer);
        } else {
            Utils.log("Loader.fetchLayer: WARNING no parent for layer " + layer);
        }
        // add the displayables from hs_pt that correspond to this layer (and all other objects that belong to the layer)
        HashMap hs_d = new HashMap();
        ResultSet rd = connection.prepareStatement("SELECT ab_displayables.id, ab_profiles.id, layer_id, stack_index FROM ab_displayables,ab_profiles WHERE ab_displayables.id=ab_profiles.id AND layer_id=" + layer_id).executeQuery();
        while (rd.next()) {
            Long idd = new Long(rd.getLong("id"));
            Object ob = hs_pt.get(idd);
            // Utils.log("Found profile with id=" + idd + " and ob = " + ob);
            if (null != ob) {
                hs_d.put(new Integer(rd.getInt("stack_index")), ob);
            }
        }
        rd.close();
        // fetch LayerSet objects (which are also Displayable), and put them in the hs_pt (this is hackerous)
        ResultSet rls = connection.prepareStatement("SELECT * FROM ab_layer_sets, ab_displayables WHERE ab_layer_sets.id=ab_displayables.id AND ab_layer_sets.parent_layer_id=" + id).executeQuery();
        while (rls.next()) {
            long ls_id = rls.getLong("id");
            LayerSet layer_set = new LayerSet(project, ls_id, rls.getString("title"), (float) rls.getDouble("width"), (float) rls.getDouble("height"), rls.getDouble("rot_x"), rls.getDouble("rot_y"), rls.getDouble("rot_z"), (float) rls.getDouble("layer_width"), (float) rls.getDouble("layer_height"), rls.getBoolean("locked"), rls.getInt("snapshots_mode"), new AffineTransform(rls.getDouble("m00"), rls.getDouble("m10"), rls.getDouble("m01"), rls.getDouble("m11"), rls.getDouble("m02"), rls.getDouble("m12")));
            hs_pt.put(new Long(ls_id), layer_set);
            hs_d.put(new Integer(rls.getInt("stack_index")), layer_set);
            layer_set.setLayer(layer, false);
            // find the pipes (or other possible ZDisplayable objects) in the hs_pt that belong to this LayerSet and add them silently
            ResultSet rpi = connection.prepareStatement("SELECT ab_displayables.id, ab_zdisplayables.id, layer_id, layer_set_id, stack_index FROM ab_displayables,ab_zdisplayables WHERE ab_displayables.id=ab_zdisplayables.id AND layer_set_id=" + ls_id + " ORDER BY stack_index ASC").executeQuery();
            while (rpi.next()) {
                Long idd = new Long(rpi.getLong("id"));
                Object ob = hs_pt.get(idd);
                if (null != ob && ob instanceof ZDisplayable) {
                    layer_set.addSilently((ZDisplayable) ob);
                } else {
                    Utils.log("fetchLayer: failed to add a ZDisplayable to the layer_set. zdispl id = " + idd);
                }
            }
            rpi.close();
        }
        rls.close();
        // add Patch objects from ab_patches joint-called with ab_displayables
        ResultSet rp = connection.prepareStatement("SELECT ab_patches.id, ab_displayables.id, layer_id, title, width, height, stack_index, imp_type, locked, min, max, m00, m10, m01, m11, m02, m12 FROM ab_patches,ab_displayables WHERE ab_patches.id=ab_displayables.id AND ab_displayables.layer_id=" + layer_id).executeQuery();
        while (rp.next()) {
            long patch_id = rp.getLong("id");
            Patch patch = new Patch(project, patch_id, rp.getString("title"), (float) rp.getDouble("width"), (float) rp.getDouble("height"), rp.getInt("o_width"), rp.getInt("o_height"), rp.getInt("imp_type"), rp.getBoolean("locked"), rp.getDouble("min"), rp.getDouble("max"), new AffineTransform(rp.getDouble("m00"), rp.getDouble("m10"), rp.getDouble("m01"), rp.getDouble("m11"), rp.getDouble("m02"), rp.getDouble("m12")));
            // collecting all Displayable objects to reconstruct links
            hs_pt.put(new Long(patch_id), patch);
            hs_d.put(new Integer(rp.getInt("stack_index")), patch);
        }
        rp.close();
        // add DLabel objects
        ResultSet rl = connection.prepareStatement("SELECT ab_labels.id, ab_displayables.id, layer_id, title, width, height, m00, m10, m01, m11, m02, m12, stack_index, font_name, font_style, font_size, ab_labels.type, locked FROM ab_labels,ab_displayables WHERE ab_labels.id=ab_displayables.id AND ab_displayables.layer_id=" + layer_id).executeQuery();
        while (rl.next()) {
            long label_id = rl.getLong("id");
            DLabel label = new DLabel(project, label_id, rl.getString("title"), (float) rl.getDouble("width"), (float) rl.getDouble("height"), rl.getInt("type"), rl.getString("font_name"), rl.getInt("font_style"), rl.getInt("font_size"), rl.getBoolean("locked"), new AffineTransform(rl.getDouble("m00"), rl.getDouble("m10"), rl.getDouble("m01"), rl.getDouble("m11"), rl.getDouble("m02"), rl.getDouble("m12")));
            // collecting all Displayable objects to reconstruct links
            hs_pt.put(new Long(label_id), label);
            hs_d.put(new Integer(rl.getInt("stack_index")), label);
        }
        rl.close();
        // Add silently to the Layer ordered by stack index
        Set e = hs_d.keySet();
        Object[] si = new Object[hs_d.size()];
        si = e.toArray(si);
        // will it sort an array of integers correctly? Who knows!
        Arrays.sort(si);
        for (int i = 0; i < si.length; i++) {
            // Utils.log("Loader layer.addSilently: adding " + (DBObject)hs_d.get(si[i]));
            layer.addSilently((DBObject) hs_d.get(si[i]));
        }
        // find displays and open later, when fully loaded.
        ResultSet rdi = connection.prepareStatement("SELECT * FROM ab_displays WHERE layer_id=" + layer.getId()).executeQuery();
        while (rdi.next()) {
            fetchDisplay(rdi, layer);
        }
        rdi.close();
    }
    r.close();
    return layer;
}
Also used : ResultSet(java.sql.ResultSet) Set(java.util.Set) LayerSet(ini.trakem2.display.LayerSet) LayerSet(ini.trakem2.display.LayerSet) HashMap(java.util.HashMap) Layer(ini.trakem2.display.Layer) Point(java.awt.Point) PGpoint(org.postgresql.geometric.PGpoint) ZDisplayable(ini.trakem2.display.ZDisplayable) DLabel(ini.trakem2.display.DLabel) ResultSet(java.sql.ResultSet) AffineTransform(java.awt.geom.AffineTransform) Patch(ini.trakem2.display.Patch)

Example 33 with Stack

use of ini.trakem2.display.Stack in project TrakEM2 by trakem2.

the class FilePathRepair method fixStack.

private static int fixStack(final PathTableModel data, final Set<Patch> fixed, final Collection<Patch> slices, final String wrong_path, final String new_path, final boolean update_mipmaps) {
    int n_fixed = 0;
    Dimension dim = null;
    Loader loader = null;
    for (final Patch ps : slices) {
        if (fixed.contains(ps))
            continue;
        final String slicepath = ps.getFilePath();
        final int isl = slicepath.lastIndexOf("-----#slice=");
        if (-1 == isl) {
            Utils.log2("Not a stack path: " + slicepath);
            // someone linked an image...
            continue;
        }
        // same: // ps.getImageFilePath();
        final String ps_path = slicepath.substring(0, isl);
        if (!ps_path.substring(0, isl).equals(wrong_path)) {
            Utils.log2("Not the same stack path:\n  i=" + ps_path + "\n  ref=" + wrong_path);
            // not the same stack!
            continue;
        }
        if (null == dim) {
            loader = ps.getProject().getLoader();
            loader.releaseToFit(Math.max(Loader.MIN_FREE_BYTES, ps.getOWidth() * ps.getOHeight() * 10));
            dim = loader.getDimensions(new_path);
            if (null == dim) {
                // preserving backslashes
                Utils.log(new StringBuilder("ERROR: could not open image at ").append(new_path).toString());
                return n_fixed;
            }
            // Check dimensions
            if (dim.width != ps.getOWidth() || dim.height != ps.getOHeight()) {
                Utils.log("ERROR different o_width,o_height for patch " + ps + "\n  at new path " + new_path + "\nold o_width,o_height: " + ps.getOWidth() + "," + ps.getOHeight() + "\nnew o_width,o_height: " + dim.width + "," + dim.height);
                return n_fixed;
            }
        }
        // flag as good
        fixed.add(ps);
        loader.removeFromUnloadable(ps);
        // Assign new image path with slice info appended
        loader.addedPatchFrom(new_path + slicepath.substring(isl), ps);
        // submit job to regenerate mipmaps in the background
        if (update_mipmaps)
            loader.regenerateMipMaps(ps);
        // 
        data.remove(ps);
        n_fixed++;
    }
    return n_fixed;
}
Also used : Dimension(java.awt.Dimension) Patch(ini.trakem2.display.Patch)

Example 34 with Stack

use of ini.trakem2.display.Stack in project TrakEM2 by trakem2.

the class AreaUtils method generateTriangles.

/**
 * Expects areas in local coordinates to the Displayable @param d.
 *  @param d
 *  @param scale The scaling of the entire universe, to limit the overall box
 *  @param resample_ The optimization parameter for marching cubes (i.e. a value of 2 will scale down to half, then apply marching cubes, then scale up by 2 the vertices coordinates).
 *  @param areas
 *  @return The List of triangles involved, specified as three consecutive vertices. A list of Point3f vertices.
 */
public static List<Point3f> generateTriangles(final Displayable d, final double scale, final int resample_, final Map<Layer, Area> areas) {
    // in the LayerSet, layers are ordered by Z already.
    try {
        int n = areas.size();
        if (0 == n)
            return null;
        final int resample;
        if (resample_ <= 0) {
            resample = 1;
            Utils.log2("Fixing zero or negative resampling value to 1.");
        } else
            resample = resample_;
        final LayerSet layer_set = d.getLayerSet();
        final AffineTransform aff = d.getAffineTransformCopy();
        final Rectangle r = d.getBoundingBox(null);
        // remove translation from a copy of the Displayable's AffineTransform
        final AffineTransform at_translate = new AffineTransform();
        at_translate.translate(-r.x, -r.y);
        aff.preConcatenate(at_translate);
        // incorporate resampling scaling into the transform
        final AffineTransform atK = new AffineTransform();
        // Utils.log("resample: " + resample + "  scale: " + scale);
        // 'scale' is there to limit gigantic universes
        final double K = (1.0 / resample) * scale;
        atK.scale(K, K);
        aff.preConcatenate(atK);
        final Calibration cal = layer_set.getCalibrationCopy();
        // Find first layer, compute depth, and fill in the depth vs area map
        Layer first_layer = null, last_layer = null;
        final int w = (int) Math.ceil(r.width * K);
        final int h = (int) Math.ceil(r.height * K);
        int depth = 0;
        final Map<Integer, Area> ma = new HashMap<Integer, Area>();
        for (final Layer la : layer_set.getLayers()) {
            // layers sorted by Z ASC
            final Area area = areas.get(la);
            if (null != area) {
                ma.put(depth, area);
                if (null == first_layer) {
                    first_layer = la;
                }
                // Utils.log("area at depth " + depth + " for layer " + la);
                depth++;
                n--;
            } else if (0 != depth) {
                // Utils.log("Empty area at depth " + depth);
                // an empty layer
                depth++;
            }
            if (0 == n) {
                last_layer = la;
                // no more areas to paint
                break;
            }
        }
        if (0 == depth) {
            Utils.log("ERROR could not find any areas for " + d);
            return null;
        }
        if (0 != n) {
            Utils.log("WARNING could not find all areas for " + d);
        }
        // No zero-padding: Marching Cubes now can handle edges
        final ShapeList<ByteType> shapeList = new ShapeListCached<ByteType>(new int[] { w, h, depth }, new ByteType(), 32);
        final Image<ByteType> shapeListImage = new Image<ByteType>(shapeList, shapeList.getBackground(), "ShapeListContainer");
        // 255 or -1 don't work !? So, giving the highest value (127) that is both a byte and an int.
        final ByteType intensity = new ByteType((byte) 127);
        for (final Map.Entry<Integer, Area> e : ma.entrySet()) {
            Area a = e.getValue();
            if (!aff.isIdentity()) {
                a = M.areaInIntsByRounding(a.createTransformedArea(aff));
            }
            shapeList.addShape(a, intensity, new int[] { e.getKey() });
        }
        // debug:
        // ImagePlus imp = ImageJFunctions.displayAsVirtualStack(shapeListImage);
        // imp.getProcessor().setMinAndMax( 0, 255 );
        // imp.show();
        // Utils.log2("Using imglib Shape List Image Container");
        // Now marching cubes
        // origins at 0,0,0: uncalibrated
        final List<Point3f> list = new MCTriangulator().getTriangles(shapeListImage, 1, new float[3]);
        // The list of triangles has coordinates:
        // - in x,y: in pixels, scaled by K = (1 / resample) * scale,
        // translated by r.x, r.y (the top-left coordinate of this AreaList bounding box)
        // - in z: in stack slice indices
        // So all x,y,z must be corrected in x,y and z of the proper layer
        // final double offset = first_layer.getZ();
        final int i_first_layer = layer_set.indexOf(first_layer);
        // The x,y translation to correct each point by:
        final float dx = (float) (r.x * scale * cal.pixelWidth);
        final float dy = (float) (r.y * scale * cal.pixelHeight);
        // Correct x,y by resampling and calibration, but not scale
        // scale is already in the pixel coordinates
        final float rsw = (float) (resample * cal.pixelWidth);
        final float rsh = (float) (resample * cal.pixelHeight);
        // no resampling in Z. and Uses pixelWidth, not pixelDepth.
        final double sz = scale * cal.pixelWidth;
        // debug:
        /*
			// which p.z types exist?
			final TreeSet<Float> ts = new TreeSet<Float>();
			for (final Iterator it = list.iterator(); it.hasNext(); ) {
				ts.add(((Point3f)it.next()).z);
			}
			for (final Float pz : ts) Utils.log2("A z: " + pz);
			*/
        // debug: How many different Z?
        /*
			HashSet<Float> zs = new HashSet<Float>();
			for (Point3f p : list) {
				zs.add(p.z);
			}
			ArrayList<Float> a = new ArrayList<Float>(zs);
			java.util.Collections.sort(a);
			for (Float f : a) {
				Utils.log("f: " + f);
			}
			*/
        // Utils.log2("Number of slices: " + imp.getNSlices());
        // Fix all points:
        // Read from list, modify and put into verts
        // and don't modify it if the verts already has it (it's just coincident)
        final Point3f[] verts = new Point3f[list.size()];
        // Utils.log("number of verts: " + verts.length + " mod 3: " + (verts.length % 3));
        final TreeMap<Integer, Point3f> output = new TreeMap<Integer, Point3f>();
        // The first section generates vertices at -1 and 0
        // The last section generates them at last_section_index and last_section_index +1
        // Capture from -1 to 0
        fix3DPoints(list, output, verts, first_layer.getZ(), 0, -1, dx, dy, rsw, rsh, sz, 1);
        int slice_index = 0;
        for (final Layer la : layer_set.getLayers().subList(i_first_layer, i_first_layer + depth)) {
            // If layer is empty, continue
            /* // YEAH don't! At least the immediate next layer would have points, like the extra Z level after last layer, to account for the thickness of the layer!
				if (empty_layers.contains(la)) {
					slice_index++;
					continue;
				}
				*/
            fix3DPoints(list, output, verts, la.getZ(), la.getThickness(), slice_index, dx, dy, rsw, rsh, sz, 1);
            slice_index++;
        }
        // Do the last layer again. The last layer has two Z planes in which it has pixels:
        try {
            // Capture from last_section_index to last_section_index+1, inclusive
            fix3DPoints(list, output, verts, last_layer.getZ() + last_layer.getThickness(), 0, slice_index, dx, dy, rsw, rsh, sz, 2);
        } catch (final Exception ee) {
            IJError.print(ee);
        }
        // Handle potential errors:
        if (0 != list.size() - output.size()) {
            Utils.log2("Unprocessed/unused points: " + (list.size() - output.size()));
            for (int i = 0; i < verts.length; i++) {
                if (null == verts[i]) {
                    final Point3f p = (Point3f) list.get(i);
                    Utils.log2("verts[" + i + "] = " + p.x + ", " + p.y + ", " + p.z + "  p.z as int: " + ((int) (p.z + 0.05f)));
                }
            }
            return new ArrayList<Point3f>(output.values());
        } else {
            return java.util.Arrays.asList(verts);
        }
    } catch (final Exception e) {
        e.printStackTrace();
    }
    return null;
}
Also used : HashMap(java.util.HashMap) Rectangle(java.awt.Rectangle) ArrayList(java.util.ArrayList) ShapeListCached(mpicbg.imglib.container.shapelist.ShapeListCached) ByteType(mpicbg.imglib.type.numeric.integer.ByteType) Image(mpicbg.imglib.image.Image) Point3f(org.scijava.vecmath.Point3f) LayerSet(ini.trakem2.display.LayerSet) Calibration(ij.measure.Calibration) TreeMap(java.util.TreeMap) Layer(ini.trakem2.display.Layer) ExecutionException(java.util.concurrent.ExecutionException) Area(java.awt.geom.Area) AffineTransform(java.awt.geom.AffineTransform) HashMap(java.util.HashMap) Map(java.util.Map) TreeMap(java.util.TreeMap)

Example 35 with Stack

use of ini.trakem2.display.Stack in project TrakEM2 by trakem2.

the class Polyline method mousePressed.

@Override
public void mousePressed(final MouseEvent me, final Layer layer, int x_p, int y_p, final double mag) {
    // transform the x_p, y_p to the local coordinates
    final int x_pd = x_p;
    final int y_pd = y_p;
    if (!this.at.isIdentity()) {
        final Point2D.Double po = inverseTransformPoint(x_p, y_p);
        x_p = (int) po.x;
        y_p = (int) po.y;
    }
    final int tool = ProjectToolbar.getToolId();
    final Display display = ((DisplayCanvas) me.getSource()).getDisplay();
    final long layer_id = layer.getId();
    index = findPoint(x_p, y_p, layer_id, mag);
    if (ProjectToolbar.PENCIL == tool && n_points > 0 && -1 == index && !me.isShiftDown() && !Utils.isControlDown(me)) {
        // Check that there are any images -- otherwise may hang. TODO
        if (layer_set.getDisplayables(Patch.class).isEmpty()) {
            Utils.log("No images are present!");
            return;
        }
        final double scale = layer_set.getVirtualizationScale();
        // Ok now with all found images, create a virtual stack that provides access to them all, with caching.
        final Worker[] worker = new Worker[2];
        final TraceParameters tr_ = tr_map.get(layer_set);
        final TraceParameters tr = null == tr_ ? new TraceParameters() : tr_;
        if (null == tr_) {
            synchronized (tr_map) {
                tr_map.put(layer_set, tr);
            }
        }
        if (tr.update) {
            worker[0] = new Worker("Preparing Hessian...") {

                @Override
                public void run() {
                    startedWorking();
                    try {
                        Utils.log("Push ESCAPE key to cancel autotrace anytime.");
                        final ImagePlus virtual = new LayerStack(layer_set, scale, ImagePlus.GRAY8, Patch.class, display.getDisplayChannelAlphas(), Segmentation.fmp.SNT_invert_image).getImagePlus();
                        // virtual.show();
                        final Calibration cal = virtual.getCalibration();
                        double minimumSeparation = 1;
                        if (cal != null)
                            minimumSeparation = Math.min(cal.pixelWidth, Math.min(cal.pixelHeight, cal.pixelDepth));
                        final ComputeCurvatures hessian = new ComputeCurvatures(virtual, minimumSeparation, null, cal != null);
                        hessian.run();
                        tr.virtual = virtual;
                        // tr.scale = scale;
                        tr.hessian = hessian;
                        tr.update = false;
                    } catch (final Exception e) {
                        IJError.print(e);
                    }
                    finishedWorking();
                }
            };
            Bureaucrat.createAndStart(worker[0], project);
        }
        final Point2D.Double po = transformPoint(p[0][n_points - 1], p[1][n_points - 1]);
        final int start_x = (int) po.x;
        final int start_y = (int) po.y;
        // 0-based
        final int start_z = layer_set.indexOf(layer_set.getLayer(p_layer[n_points - 1]));
        // must transform into virtual space
        final int goal_x = (int) (x_pd * scale);
        final int goal_y = (int) (y_pd * scale);
        final int goal_z = layer_set.indexOf(layer);
        /*
			Utils.log2("x_pd, y_pd : " + x_pd + ", " + y_pd);
			Utils.log2("scale: " + scale);
			Utils.log2("start: " + start_x + "," + start_y + ", " + start_z);
			Utils.log2("goal: " + goal_x + "," + goal_y + ", " + goal_z);
			Utils.log2("virtual: " + tr.virtual);
			*/
        final boolean simplify = me.isAltDown();
        worker[1] = new Worker("Tracer - waiting on hessian") {

            @Override
            public void run() {
                startedWorking();
                try {
                    if (null != worker[0]) {
                        // Wait until hessian is ready
                        worker[0].join();
                    }
                    setTaskName("Tracing path");
                    final int reportEveryMilliseconds = 2000;
                    tr.tracer = new TracerThread(tr.virtual, 0, 255, // timeout seconds
                    120, reportEveryMilliseconds, start_x, start_y, start_z, goal_x, goal_y, goal_z, // reciproal pix values at start and goal
                    true, tr.virtual.getStackSize() == 1, tr.hessian, null == tr.hessian ? 1 : 4, null, null != tr.hessian);
                    tr.tracer.addProgressListener(new SearchProgressCallback() {

                        @Override
                        public void pointsInSearch(final SearchInterface source, final int inOpen, final int inClosed) {
                            worker[1].setTaskName("Tracing path: open=" + inOpen + " closed=" + inClosed);
                        }

                        @Override
                        public void finished(final SearchInterface source, final boolean success) {
                            if (!success) {
                                Utils.logAll("Could NOT trace a path");
                            }
                        }

                        @Override
                        public void threadStatus(final SearchInterface source, final int currentStatus) {
                            // This method gets called every reportEveryMilliseconds
                            if (worker[1].hasQuitted()) {
                                source.requestStop();
                            }
                        }
                    });
                    tr.tracer.run();
                    final Path result = tr.tracer.getResult();
                    tr.tracer = null;
                    if (null == result) {
                        // : "+
                        Utils.log("Finding a path failed");
                        // not public //SearchThread.exitReasonStrings[tracer.getExitReason()]);
                        return;
                    }
                    // TODO: precise_x_positions etc are likely to be broken (calibrated or something)
                    // Remove bogus points: those at the end with 0,0 coords
                    int len = result.points;
                    final double[][] pos = result.getXYZUnscaled();
                    for (int i = len - 1; i > -1; i--) {
                        if (0 == pos[0][i] && 0 == pos[1][i]) {
                            len--;
                        } else
                            break;
                    }
                    // Transform points: undo scale, and bring to this Polyline AffineTransform:
                    final AffineTransform aff = new AffineTransform();
                    /* Inverse order: */
                    /* 2 */
                    aff.concatenate(Polyline.this.at.createInverse());
                    /* 1 */
                    aff.scale(1 / scale, 1 / scale);
                    final double[] po = new double[len * 2];
                    for (int i = 0, j = 0; i < len; i++, j += 2) {
                        po[j] = pos[0][i];
                        po[j + 1] = pos[1][i];
                    }
                    final double[] po2 = new double[len * 2];
                    // what a stupid format: consecutive x,y pairs
                    aff.transform(po, 0, po2, 0, len);
                    long[] p_layer_ids = new long[len];
                    double[] pox = new double[len];
                    double[] poy = new double[len];
                    for (int i = 0, j = 0; i < len; i++, j += 2) {
                        // z_positions in 0-(N-1), not in 1-N like slices!
                        p_layer_ids[i] = layer_set.getLayer((int) pos[2][i]).getId();
                        pox[i] = po2[j];
                        poy[i] = po2[j + 1];
                    }
                    // Simplify path: to steps of 5 calibration units, or 5 pixels when not calibrated.
                    if (simplify) {
                        setTaskName("Simplifying path");
                        final Object[] ob = Polyline.simplify(pox, poy, p_layer_ids, 10000, layer_set);
                        pox = (double[]) ob[0];
                        poy = (double[]) ob[1];
                        p_layer_ids = (long[]) ob[2];
                        len = pox.length;
                    }
                    // Record the first newly-added autotraced point index:
                    last_autotrace_start = Polyline.this.n_points;
                    Polyline.this.appendPoints(pox, poy, p_layer_ids, len);
                    Polyline.this.repaint(true, null);
                    Utils.logAll("Added " + len + " new points.");
                } catch (final Exception e) {
                    IJError.print(e);
                }
                finishedWorking();
            }
        };
        Bureaucrat.createAndStart(worker[1], project);
        index = -1;
        return;
    }
    if (ProjectToolbar.PEN == tool || ProjectToolbar.PENCIL == tool) {
        if (Utils.isControlDown(me) && me.isShiftDown()) {
            final long lid = Display.getFrontLayer(this.project).getId();
            if (-1 == index || lid != p_layer[index]) {
                index = findNearestPoint(x_p, y_p, layer_id);
            }
            if (-1 != index) {
                // delete point
                removePoint(index);
                index = -1;
                repaint(false, null);
            }
            // In any case, terminate
            return;
        }
        if (// disable!
        -1 != index && layer_id != p_layer[index])
            // disable!
            index = -1;
        else // if no conditions are met, attempt to add point
        if (-1 == index && !me.isShiftDown() && !me.isAltDown()) {
            // add a new point
            index = addPoint(x_p, y_p, layer_id, mag);
            is_new_point = true;
            repaint(false, null);
            return;
        }
    }
}
Also used : Path(tracing.Path) SearchInterface(tracing.SearchInterface) ComputeCurvatures(features.ComputeCurvatures) Calibration(ij.measure.Calibration) ImagePlus(ij.ImagePlus) NoninvertibleTransformException(java.awt.geom.NoninvertibleTransformException) Point2D(java.awt.geom.Point2D) LayerStack(ini.trakem2.imaging.LayerStack) TracerThread(tracing.TracerThread) Worker(ini.trakem2.utils.Worker) AffineTransform(java.awt.geom.AffineTransform) SearchProgressCallback(tracing.SearchProgressCallback)

Aggregations

ImagePlus (ij.ImagePlus)21 Layer (ini.trakem2.display.Layer)16 ArrayList (java.util.ArrayList)15 Rectangle (java.awt.Rectangle)13 Patch (ini.trakem2.display.Patch)12 ImageStack (ij.ImageStack)11 AffineTransform (java.awt.geom.AffineTransform)11 ImageProcessor (ij.process.ImageProcessor)8 Area (java.awt.geom.Area)8 File (java.io.File)8 HashMap (java.util.HashMap)8 TreeMap (java.util.TreeMap)8 Point (java.awt.Point)7 HashSet (java.util.HashSet)7 Map (java.util.Map)7 GenericDialog (ij.gui.GenericDialog)6 Calibration (ij.measure.Calibration)6 Displayable (ini.trakem2.display.Displayable)6 Worker (ini.trakem2.utils.Worker)6 DirectoryChooser (ij.io.DirectoryChooser)5