Search in sources :

Example 1 with VectorData

use of ini.trakem2.display.VectorData 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);
}
Also used : HashMap(java.util.HashMap) ArrayList(java.util.ArrayList) VectorData(ini.trakem2.display.VectorData) HashSet(java.util.HashSet) Displayable(ini.trakem2.display.Displayable) TreeMap(java.util.TreeMap) Layer(ini.trakem2.display.Layer) Point(mpicbg.models.Point) Area(java.awt.geom.Area) ExecutorService(java.util.concurrent.ExecutorService) Future(java.util.concurrent.Future) Collection(java.util.Collection) Patch(ini.trakem2.display.Patch) Map(java.util.Map) HashMap(java.util.HashMap) TreeMap(java.util.TreeMap)

Example 2 with VectorData

use of ini.trakem2.display.VectorData 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);
}
Also used : Displayable(ini.trakem2.display.Displayable) LayerSet(ini.trakem2.display.LayerSet) ArrayList(java.util.ArrayList) Layer(ini.trakem2.display.Layer) Patch(ini.trakem2.display.Patch) VectorData(ini.trakem2.display.VectorData) HashSet(java.util.HashSet)

Example 3 with VectorData

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

the class ElasticLayerAlignment method exec.

/**
 * @param param
 * @param layerRange
 * @param fixedLayers
 * @param emptyLayers
 * @param box
 * @param filter
 * @param useTps true if using TPS transforms, otherwise MLS
 * @throws Exception
 */
@SuppressWarnings("deprecation")
public final void exec(final Param param, final Project project, final List<Layer> layerRange, final Set<Layer> fixedLayers, final Set<Layer> emptyLayers, final Rectangle box, final boolean propagateTransformBefore, final boolean propagateTransformAfter, final Filter<Patch> filter) throws Exception {
    final ExecutorService service = ExecutorProvider.getExecutorService(1.0f);
    /* create tiles and models for all layers */
    final ArrayList<Tile<?>> tiles = new ArrayList<Tile<?>>();
    for (int i = 0; i < layerRange.size(); ++i) {
        switch(param.desiredModelIndex) {
            case 0:
                tiles.add(new Tile<TranslationModel2D>(new TranslationModel2D()));
                break;
            case 1:
                tiles.add(new Tile<RigidModel2D>(new RigidModel2D()));
                break;
            case 2:
                tiles.add(new Tile<SimilarityModel2D>(new SimilarityModel2D()));
                break;
            case 3:
                tiles.add(new Tile<AffineModel2D>(new AffineModel2D()));
                break;
            case 4:
                tiles.add(new Tile<HomographyModel2D>(new HomographyModel2D()));
                break;
            default:
                return;
        }
    }
    /* collect all pairs of slices for which a model could be found */
    final ArrayList<Triple<Integer, Integer, AbstractModel<?>>> pairs = new ArrayList<Triple<Integer, Integer, AbstractModel<?>>>();
    if (!param.isAligned) {
        preAlignStack(param, project, layerRange, box, filter, pairs);
    } else {
        for (int i = 0; i < layerRange.size(); ++i) {
            final int range = Math.min(layerRange.size(), i + param.maxNumNeighbors + 1);
            for (int j = i + 1; j < range; ++j) {
                pairs.add(new Triple<Integer, Integer, AbstractModel<?>>(i, j, new TranslationModel2D()));
            }
        }
    }
    /* Elastic alignment */
    /* Initialization */
    final TileConfiguration initMeshes = new TileConfiguration();
    final int meshWidth = (int) Math.ceil(box.width * param.layerScale);
    final int meshHeight = (int) Math.ceil(box.height * param.layerScale);
    final ArrayList<SpringMesh> meshes = new ArrayList<SpringMesh>(layerRange.size());
    for (int i = 0; i < layerRange.size(); ++i) {
        meshes.add(new SpringMesh(param.resolutionSpringMesh, meshWidth, meshHeight, param.stiffnessSpringMesh, param.maxStretchSpringMesh * param.layerScale, param.dampSpringMesh));
    }
    // final int blockRadius = Math.max( 32, meshWidth / p.resolutionSpringMesh / 2 );
    final int blockRadius = Math.max(16, mpicbg.util.Util.roundPos(param.layerScale * param.blockRadius));
    Utils.log("effective block radius = " + blockRadius);
    final ArrayList<Future<BlockMatchPairCallable.BlockMatchResults>> futures = new ArrayList<Future<BlockMatchPairCallable.BlockMatchResults>>(pairs.size());
    for (final Triple<Integer, Integer, AbstractModel<?>> pair : pairs) {
        /* free memory */
        project.getLoader().releaseAll();
        final SpringMesh m1 = meshes.get(pair.a);
        final SpringMesh m2 = meshes.get(pair.b);
        final ArrayList<Vertex> v1 = m1.getVertices();
        final ArrayList<Vertex> v2 = m2.getVertices();
        final Layer layer1 = layerRange.get(pair.a);
        final Layer layer2 = layerRange.get(pair.b);
        final boolean layer1Fixed = fixedLayers.contains(layer1);
        final boolean layer2Fixed = fixedLayers.contains(layer2);
        if (!(layer1Fixed && layer2Fixed)) {
            final BlockMatchPairCallable bmpc = new BlockMatchPairCallable(pair, layerRange, layer1Fixed, layer2Fixed, filter, param, v1, v2, box);
            futures.add(service.submit(bmpc));
        }
    }
    for (final Future<BlockMatchPairCallable.BlockMatchResults> future : futures) {
        final BlockMatchPairCallable.BlockMatchResults results = future.get();
        final Collection<PointMatch> pm12 = results.pm12, pm21 = results.pm21;
        final Triple<Integer, Integer, AbstractModel<?>> pair = results.pair;
        final Tile<?> t1 = tiles.get(pair.a);
        final Tile<?> t2 = tiles.get(pair.b);
        final SpringMesh m1 = meshes.get(pair.a);
        final SpringMesh m2 = meshes.get(pair.b);
        final double springConstant = 1.0 / (pair.b - pair.a);
        final boolean layer1Fixed = results.layer1Fixed;
        final boolean layer2Fixed = results.layer2Fixed;
        if (layer1Fixed) {
            initMeshes.fixTile(t1);
        } else {
            if (param.useLocalSmoothnessFilter) {
                Utils.log(pair.a + " > " + pair.b + ": " + pm12.size() + " candidates passed local smoothness filter.");
            } else {
                Utils.log(pair.a + " > " + pair.b + ": found " + pm12.size() + " correspondences.");
            }
            for (final PointMatch pm : pm12) {
                final Vertex p1 = (Vertex) pm.getP1();
                final Vertex p2 = new Vertex(pm.getP2());
                p1.addSpring(p2, new Spring(0, springConstant));
                m2.addPassiveVertex(p2);
            }
            /*
                * adding Tiles to the initialing TileConfiguration, adding a Tile
                * multiple times does not harm because the TileConfiguration is
                * backed by a Set.
                */
            if (pm12.size() > pair.c.getMinNumMatches()) {
                initMeshes.addTile(t1);
                initMeshes.addTile(t2);
                t1.connect(t2, pm12);
            }
        }
        if (layer2Fixed)
            initMeshes.fixTile(t2);
        else {
            if (param.useLocalSmoothnessFilter) {
                Utils.log(pair.a + " < " + pair.b + ": " + pm21.size() + " candidates passed local smoothness filter.");
            } else {
                Utils.log(pair.a + " < " + pair.b + ": found " + pm21.size() + " correspondences.");
            }
            for (final PointMatch pm : pm21) {
                final Vertex p1 = (Vertex) pm.getP1();
                final Vertex p2 = new Vertex(pm.getP2());
                p1.addSpring(p2, new Spring(0, springConstant));
                m1.addPassiveVertex(p2);
            }
            /*
                * adding Tiles to the initialing TileConfiguration, adding a Tile
                * multiple times does not harm because the TileConfiguration is
                * backed by a Set.
                */
            if (pm21.size() > pair.c.getMinNumMatches()) {
                initMeshes.addTile(t1);
                initMeshes.addTile(t2);
                t2.connect(t1, pm21);
            }
        }
        Utils.log(pair.a + " <> " + pair.b + " spring constant = " + springConstant);
    }
    /* pre-align by optimizing a piecewise linear model */
    initMeshes.optimize(param.maxEpsilon * param.layerScale, param.maxIterationsSpringMesh, param.maxPlateauwidthSpringMesh);
    for (int i = 0; i < layerRange.size(); ++i) meshes.get(i).init(tiles.get(i).getModel());
    /* optimize the meshes */
    try {
        final long t0 = System.currentTimeMillis();
        Utils.log("Optimizing spring meshes...");
        if (param.useLegacyOptimizer) {
            Utils.log("  ...using legacy optimizer...");
            SpringMesh.optimizeMeshes2(meshes, param.maxEpsilon * param.layerScale, param.maxIterationsSpringMesh, param.maxPlateauwidthSpringMesh, param.visualize);
        } else {
            SpringMesh.optimizeMeshes(meshes, param.maxEpsilon * param.layerScale, param.maxIterationsSpringMesh, param.maxPlateauwidthSpringMesh, param.visualize);
        }
        Utils.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;
    }
    /* translate relative to bounding box */
    for (final SpringMesh mesh : meshes) {
        for (final PointMatch pm : mesh.getVA().keySet()) {
            final Point p1 = pm.getP1();
            final Point p2 = pm.getP2();
            final double[] l = p1.getL();
            final double[] w = p2.getW();
            l[0] = l[0] / param.layerScale + box.x;
            l[1] = l[1] / param.layerScale + box.y;
            w[0] = w[0] / param.layerScale + box.x;
            w[1] = w[1] / param.layerScale + box.y;
        }
    }
    /* free memory */
    project.getLoader().releaseAll();
    final Layer first = layerRange.get(0);
    final List<Layer> layers = first.getParent().getLayers();
    final LayerSet ls = first.getParent();
    final Area infArea = AreaUtils.infiniteArea();
    final List<VectorData> vectorData = new ArrayList<VectorData>();
    for (final Layer layer : ls.getLayers()) {
        vectorData.addAll(Utils.castCollection(layer.getDisplayables(VectorData.class, false, true), VectorData.class, true));
    }
    vectorData.addAll(Utils.castCollection(ls.getZDisplayables(VectorData.class, true), VectorData.class, true));
    /* transfer layer transform into patch transforms and append to patches */
    if (propagateTransformBefore || propagateTransformAfter) {
        if (propagateTransformBefore) {
            final ThinPlateSplineTransform tps = makeTPS(meshes.get(0).getVA().keySet());
            final int firstLayerIndex = first.getParent().getLayerIndex(first.getId());
            for (int i = 0; i < firstLayerIndex; ++i) {
                applyTransformToLayer(layers.get(i), tps, filter);
                for (final VectorData vd : vectorData) {
                    vd.apply(layers.get(i), infArea, tps);
                }
            }
        }
        if (propagateTransformAfter) {
            final Layer last = layerRange.get(layerRange.size() - 1);
            final CoordinateTransform ct;
            if (param.useTps)
                ct = makeTPS(meshes.get(meshes.size() - 1).getVA().keySet());
            else {
                final MovingLeastSquaresTransform2 mls = new MovingLeastSquaresTransform2();
                mls.setMatches(meshes.get(meshes.size() - 1).getVA().keySet());
                ct = mls;
            }
            final int lastLayerIndex = last.getParent().getLayerIndex(last.getId());
            for (int i = lastLayerIndex + 1; i < layers.size(); ++i) {
                applyTransformToLayer(layers.get(i), ct, filter);
                for (final VectorData vd : vectorData) {
                    vd.apply(layers.get(i), infArea, ct);
                }
            }
        }
    }
    for (int l = 0; l < layerRange.size(); ++l) {
        IJ.showStatus("Applying transformation to patches ...");
        IJ.showProgress(0, layerRange.size());
        final Layer layer = layerRange.get(l);
        final ThinPlateSplineTransform tps = makeTPS(meshes.get(l).getVA().keySet());
        applyTransformToLayer(layer, tps, filter);
        for (final VectorData vd : vectorData) {
            vd.apply(layer, infArea, tps);
        }
        if (Thread.interrupted()) {
            Utils.log("Interrupted during applying transformations to patches.  No all patches have been updated.  Re-generate mipmaps manually.");
        }
        IJ.showProgress(l + 1, layerRange.size());
    }
    /* update patch mipmaps */
    final int firstLayerIndex;
    final int lastLayerIndex;
    if (propagateTransformBefore)
        firstLayerIndex = 0;
    else {
        firstLayerIndex = first.getParent().getLayerIndex(first.getId());
    }
    if (propagateTransformAfter)
        lastLayerIndex = layers.size() - 1;
    else {
        final Layer last = layerRange.get(layerRange.size() - 1);
        lastLayerIndex = last.getParent().getLayerIndex(last.getId());
    }
    for (int i = firstLayerIndex; i <= lastLayerIndex; ++i) {
        final Layer layer = layers.get(i);
        if (!(emptyLayers.contains(layer) || fixedLayers.contains(layer))) {
            for (final Patch patch : AlignmentUtils.filterPatches(layer, filter)) patch.updateMipMaps();
        }
    }
    Utils.log("Done.");
}
Also used : AbstractModel(mpicbg.models.AbstractModel) BlockMatchPairCallable(mpicbg.trakem2.align.concurrent.BlockMatchPairCallable) ArrayList(java.util.ArrayList) RigidModel2D(mpicbg.models.RigidModel2D) SimilarityModel2D(mpicbg.models.SimilarityModel2D) LayerSet(ini.trakem2.display.LayerSet) HomographyModel2D(mpicbg.models.HomographyModel2D) Spring(mpicbg.models.Spring) Triple(mpicbg.trakem2.util.Triple) Area(java.awt.geom.Area) TranslationModel2D(mpicbg.models.TranslationModel2D) TileConfiguration(mpicbg.models.TileConfiguration) CoordinateTransform(mpicbg.trakem2.transform.CoordinateTransform) Patch(ini.trakem2.display.Patch) NotEnoughDataPointsException(mpicbg.models.NotEnoughDataPointsException) Vertex(mpicbg.models.Vertex) SpringMesh(mpicbg.models.SpringMesh) ThinPlateSplineTransform(mpicbg.trakem2.transform.ThinPlateSplineTransform) VectorData(ini.trakem2.display.VectorData) AffineModel2D(mpicbg.models.AffineModel2D) Tile(mpicbg.models.Tile) Point(mpicbg.models.Point) Layer(ini.trakem2.display.Layer) Point(mpicbg.models.Point) AtomicInteger(java.util.concurrent.atomic.AtomicInteger) PointMatch(mpicbg.models.PointMatch) MovingLeastSquaresTransform2(mpicbg.trakem2.transform.MovingLeastSquaresTransform2) ExecutorService(java.util.concurrent.ExecutorService) Future(java.util.concurrent.Future)

Example 4 with VectorData

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

the class ProjectTree method sendToSiblingProject.

/**
 * When two or more people work on the same XML file, images may be the same but segmentations and the transformations of the images may diverge.
 *  This function provides the means to send VectorData instances, wrapped in tree nodes, from one project to another,
 *  transforming the VectorData as appropriate to fall onto the same locations on the images.
 *  The ids of the copied objects will be new and unique for the target project.
 *  A dialog opens asking for options.
 */
@SuppressWarnings("unchecked")
public boolean sendToSiblingProject(final DefaultMutableTreeNode node) {
    ArrayList<Project> ps = Project.getProjects();
    if (1 == ps.size()) {
        Utils.log("There aren't any other projects open!");
        return false;
    }
    final ProjectThing pt = (ProjectThing) node.getUserObject();
    if (pt.getTemplate().getType().equals("project")) {
        Utils.log("Cannot transfer the project node.");
        return false;
    }
    final ArrayList<Project> psother = new ArrayList<Project>(ps);
    psother.remove(this.project);
    ps = null;
    // Find all potential landing nodes for this node: those with a TemplateThing type like the parent of node:
    final String parent_type = ((ProjectThing) pt.getParent()).getTemplate().getType();
    final List<ProjectThing> landing_pt = new ArrayList<ProjectThing>(psother.get(0).getRootProjectThing().findChildrenOfTypeR(parent_type));
    final Comparator<ProjectThing> comparator = new Comparator<ProjectThing>() {

        public int compare(ProjectThing t1, ProjectThing t2) {
            return t1.toString().compareTo(t2.toString());
        }

        public boolean equals(Object o) {
            return this == o;
        }
    };
    Collections.sort(landing_pt, comparator);
    String[] landing = new String[landing_pt.size()];
    int next = 0;
    if (landing_pt.isEmpty()) {
        landing = new String[] { "-- NONE --" };
    } else
        for (ProjectThing t : landing_pt) landing[next++] = t.toString();
    // Suggest the first potential landing node that has the same title
    String parentTitle = pt.getParent().toString();
    int k = 0;
    boolean matched = false;
    // First search for exact match
    for (final String candidate : landing) {
        if (candidate.equals(parentTitle)) {
            matched = true;
            break;
        }
        k += 1;
    }
    // If not matched, find one that contains the string
    if (!matched) {
        k = 0;
        for (final String candidate : landing) {
            if (-1 != candidate.indexOf(parentTitle)) {
                matched = true;
                break;
            }
            k += 1;
        }
    }
    if (!matched) {
        k = 0;
    }
    // Ask:
    GenericDialog gd = new GenericDialog("Send to sibling project");
    gd.addMessage("Transfering node: " + pt);
    final String[] trmode = new String[] { "As is", "Transformed as the images" };
    gd.addChoice("Transfer:", trmode, trmode[0]);
    String[] ptitles = new String[psother.size()];
    for (int i = 0; i < ptitles.length; i++) ptitles[i] = psother.get(i).toString();
    gd.addChoice("Target project:", ptitles, ptitles[0]);
    gd.addChoice("Landing node:", landing, landing[k]);
    final Vector<Choice> vc = (Vector<Choice>) gd.getChoices();
    final Choice choice_project = vc.get(vc.size() - 2);
    final Choice choice_landing = vc.get(vc.size() - 1);
    choice_project.addItemListener(new ItemListener() {

        public void itemStateChanged(ItemEvent ie) {
            landing_pt.clear();
            landing_pt.addAll(psother.get(choice_project.getSelectedIndex()).getRootProjectThing().findChildrenOfTypeR(parent_type));
            Collections.sort(landing_pt, comparator);
            choice_landing.removeAll();
            if (landing_pt.isEmpty()) {
                choice_landing.add("-- NONE --");
            } else
                for (ProjectThing t : landing_pt) choice_landing.add(t.toString());
        }
    });
    gd.showDialog();
    if (gd.wasCanceled())
        return false;
    if (choice_landing.getSelectedItem().equals("-- NONE --")) {
        Utils.log("No valid landing nodes!");
        return false;
    }
    final int transfer_mode = gd.getNextChoiceIndex();
    final Project target_project = psother.get(gd.getNextChoiceIndex());
    final ProjectThing landing_parent = landing_pt.get(gd.getNextChoiceIndex());
    return rawSendToSiblingProject(pt, transfer_mode, target_project, landing_parent);
}
Also used : ItemEvent(java.awt.event.ItemEvent) Choice(java.awt.Choice) ArrayList(java.util.ArrayList) Comparator(java.util.Comparator) Project(ini.trakem2.Project) GenericDialog(ij.gui.GenericDialog) DBObject(ini.trakem2.persistence.DBObject) ItemListener(java.awt.event.ItemListener) Vector(java.util.Vector)

Example 5 with VectorData

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

the class ProjectTree method rawSendToSiblingProject.

/**
 * Assumes that both projects have the same TemplateThing structure,
 * and assumes that the parent of the ({@code source_pt} and the {@code landing_parent}
 * instances are of the same type.
 *
 * @param source_pt The {@link ProjectThing} to be cloned.
 * @param transfer_mode Either 0 ("As is") or 1 ("Transformed with the images").
 * @param target_project The sibling project into which insert a clone of the {@code source_pt}.
 * @param landing_parent The ProjectThing in the sibling project that receives the cloned {@code source_pt}.
 */
public boolean rawSendToSiblingProject(// the source ProjectThing to copy to the target project
final ProjectThing source_pt, final int transfer_mode, final Project target_project, final ProjectThing landing_parent) {
    try {
        // Check that all the Layers used by the objects to transfer also exist in the target project!
        // 1 - Cheap way: check if all layers in the target project exist in the source project, by id
        HashSet<Long> lids = new HashSet<Long>();
        for (final Layer layer : this.project.getRootLayerSet().getLayers()) {
            lids.add(layer.getId());
        }
        HashSet<Long> tgt_lids = new HashSet<Long>(lids);
        for (final Layer layer : target_project.getRootLayerSet().getLayers()) {
            lids.remove(layer.getId());
            tgt_lids.add(layer.getId());
        }
        List<Displayable> original_vdata = null;
        final Set<Long> lids_to_operate = new HashSet<Long>();
        if (0 != lids.size()) {
            original_vdata = new ArrayList<Displayable>();
            // All their layers MUST be in the target project.
            for (final ProjectThing child : source_pt.findChildrenOfTypeR(Displayable.class)) {
                final Displayable d = (Displayable) child.getObject();
                if (!tgt_lids.containsAll(d.getLayerIds())) {
                    Utils.log("CANNOT transfer: not all required layers are present in the target project!\n  First object that couldn't be transfered: \n    " + d);
                    return false;
                }
                if (d instanceof VectorData) {
                    original_vdata.add(d);
                    lids_to_operate.addAll(d.getLayerIds());
                }
            }
        }
        // Deep cloning of the ProjectThing to transfer, then added to the landing_parent in the other tree.
        ProjectThing copy;
        try {
            // new ids, taken from target_project
            copy = source_pt.deepClone(target_project, false);
        } catch (Exception ee) {
            Utils.logAll("Can't send: " + ee.getMessage());
            IJError.print(ee);
            return false;
        }
        if (null == landing_parent.getChildTemplate(copy.getTemplate().getType())) {
            // ensure a copy is there
            landing_parent.getTemplate().addChild(copy.getTemplate().shallowCopy());
        }
        if (!landing_parent.addChild(copy)) {
            Utils.log("Could NOT transfer the node!");
            return false;
        }
        // Get the list of Profile instances in the source Project, in the same order
        // that they will be in the target project:
        final List<Profile> srcProfiles = new ArrayList<Profile>();
        for (final ProjectThing profile_pt : source_pt.findChildrenOfTypeR(Profile.class)) {
            srcProfiles.add((Profile) profile_pt.getObject());
        }
        final List<ProjectThing> copies = copy.findChildrenOfTypeR(Displayable.class);
        final List<Profile> newProfiles = new ArrayList<Profile>();
        // Utils.log2("copies size: " + copies.size());
        final List<Displayable> vdata = new ArrayList<Displayable>();
        final List<ZDisplayable> zd = new ArrayList<ZDisplayable>();
        for (final ProjectThing t : copies) {
            final Displayable d = (Displayable) t.getObject();
            // all should be, this is just future-proof code.
            if (d instanceof VectorData)
                vdata.add(d);
            if (d instanceof ZDisplayable) {
                zd.add((ZDisplayable) d);
            } else {
                // profile: always special
                newProfiles.add((Profile) d);
            }
        }
        // Fix Profile instances: exploit that the order as been conserved when copying.
        int profileIndex = 0;
        for (final Profile newProfile : newProfiles) {
            // Corresponding Profile:
            final Profile srcProfile = srcProfiles.get(profileIndex++);
            // Corresponding layer: layers have the same IDs by definition of what a sibling Project is.
            final Layer newLayer = target_project.getRootLayerSet().getLayer(srcProfile.getLayer().getId());
            newLayer.add(newProfile);
            // Corresponding links
            for (final Displayable srcLinkedProfile : srcProfile.getLinked(Profile.class)) {
                newProfile.link(newProfiles.get(srcProfiles.indexOf(srcLinkedProfile)));
            }
        }
        // add them all in one shot
        target_project.getRootLayerSet().addAll(zd);
        // could have changed
        target_project.getTemplateTree().rebuild();
        // When trying to rebuild just the landing_parent, it doesn't always work. Needs checking TODO
        target_project.getProjectTree().rebuild();
        // Open up the path to the landing parent node
        final TreePath tp = new TreePath(DNDTree.findNode(landing_parent, target_project.getProjectTree()).getPath());
        Utils.invokeLater(new Runnable() {

            public void run() {
                target_project.getProjectTree().scrollPathToVisible(tp);
                target_project.getProjectTree().setSelectionPath(tp);
            }
        });
        if (1 == transfer_mode) {
            // Collect original vdata
            if (null == original_vdata) {
                original_vdata = new ArrayList<Displayable>();
                for (final ProjectThing child : source_pt.findChildrenOfTypeR(Displayable.class)) {
                    final Displayable d = (Displayable) child.getObject();
                    if (d instanceof VectorData) {
                        original_vdata.add(d);
                        lids_to_operate.addAll(d.getLayerIds());
                    }
                }
            }
            // Utils.log2("original vdata:", original_vdata);
            // Utils.log2("vdata:", vdata);
            // Transform with images
            AlignTask.transformVectorData(AlignTask.createTransformPropertiesTable(original_vdata, vdata, lids_to_operate), vdata, target_project.getRootLayerSet());
        }
        return true;
    } catch (Exception e) {
        IJError.print(e);
    }
    return false;
}
Also used : Displayable(ini.trakem2.display.Displayable) ZDisplayable(ini.trakem2.display.ZDisplayable) ArrayList(java.util.ArrayList) Layer(ini.trakem2.display.Layer) VectorData(ini.trakem2.display.VectorData) Profile(ini.trakem2.display.Profile) ZDisplayable(ini.trakem2.display.ZDisplayable) TreePath(javax.swing.tree.TreePath) HashSet(java.util.HashSet)

Aggregations

ArrayList (java.util.ArrayList)6 Layer (ini.trakem2.display.Layer)5 VectorData (ini.trakem2.display.VectorData)5 Displayable (ini.trakem2.display.Displayable)4 Patch (ini.trakem2.display.Patch)4 Area (java.awt.geom.Area)3 HashSet (java.util.HashSet)3 ExecutorService (java.util.concurrent.ExecutorService)3 Future (java.util.concurrent.Future)3 LayerSet (ini.trakem2.display.LayerSet)2 DBObject (ini.trakem2.persistence.DBObject)2 HashMap (java.util.HashMap)2 Map (java.util.Map)2 TreeMap (java.util.TreeMap)2 AffineModel2D (mpicbg.models.AffineModel2D)2 NotEnoughDataPointsException (mpicbg.models.NotEnoughDataPointsException)2 Point (mpicbg.models.Point)2 CoordinateTransform (mpicbg.trakem2.transform.CoordinateTransform)2 GenericDialog (ij.gui.GenericDialog)1 Project (ini.trakem2.Project)1