Search in sources :

Example 86 with Displayable

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

the class DistortionCorrectionTask method correctDistortionFromSelection.

public static final Bureaucrat correctDistortionFromSelection(final Selection selection) {
    final List<Patch> patches = new ArrayList<Patch>();
    for (final Displayable d : Display.getFront().getSelection().getSelected()) if (d instanceof Patch)
        patches.add((Patch) d);
    if (patches.size() < 2) {
        Utils.log("No images in the selection.");
        return null;
    }
    final Worker worker = new Worker("Lens correction") {

        @Override
        public final void run() {
            try {
                startedWorking();
                if (!correctDistortionFromSelectionParam.setup(selection))
                    return;
                DistortionCorrectionTask.run(correctDistortionFromSelectionParam.clone(), patches, selection.getActive(), selection.getLayer(), null);
                Display.repaint();
            } catch (final Exception e) {
                IJError.print(e);
            } finally {
                finishedWorking();
            }
        }
    };
    return Bureaucrat.createAndStart(worker, selection.getProject());
}
Also used : Displayable(ini.trakem2.display.Displayable) ArrayList(java.util.ArrayList) Worker(ini.trakem2.utils.Worker) Patch(ini.trakem2.display.Patch)

Example 87 with Displayable

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

the class ExportUnsignedShort method makeFlatImage.

public static final Pair<ShortProcessor, ByteProcessor> makeFlatImage(final List<Patch> patches, final Rectangle roi, final double backgroundValue, final double scale, final boolean makeAlphaMask) {
    final ArrayList<PatchIntensityRange> patchIntensityRanges = new ArrayList<PatchIntensityRange>();
    double min = Double.MAX_VALUE;
    double max = -Double.MAX_VALUE;
    for (final Displayable d : patches) {
        final Patch patch = (Patch) d;
        final PatchIntensityRange pir = new PatchIntensityRange(patch);
        if (pir.min < min)
            min = pir.min;
        if (pir.max > max)
            max = pir.max;
        patchIntensityRanges.add(pir);
    }
    final double minI = -min * 65535.0 / (max - min);
    final double maxI = (1.0 - min) * 65535.0 / (max - min);
    final ShortProcessor sp;
    if (Double.isNaN(scale)) {
        sp = new ShortProcessor(roi.width, roi.height);
    } else {
        sp = new ShortProcessor((int) (roi.width * scale + 0.5), (int) (roi.height * scale + 0.5));
    }
    sp.setMinAndMax(minI, maxI);
    if (0 != backgroundValue) {
        sp.setValue(backgroundValue);
        sp.setRoi(0, 0, roi.width, roi.height);
        sp.fill();
    }
    final ByteProcessor alphaTarget = makeAlphaMask ? new ByteProcessor(sp.getWidth(), sp.getHeight()) : null;
    for (final PatchIntensityRange pir : patchIntensityRanges) {
        map(new PatchTransform(pir), roi.x, roi.y, scale, mapIntensities(pir, min, max), sp, alphaTarget);
    }
    return new Pair<ShortProcessor, ByteProcessor>(sp, alphaTarget);
}
Also used : ByteProcessor(ij.process.ByteProcessor) Displayable(ini.trakem2.display.Displayable) ArrayList(java.util.ArrayList) Patch(ini.trakem2.display.Patch) ShortProcessor(ij.process.ShortProcessor) Pair(mpicbg.trakem2.util.Pair)

Example 88 with Displayable

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

the class AlignTask method alignMultiLayerMosaicTask.

@SuppressWarnings({ "unchecked", "rawtypes" })
public static final void alignMultiLayerMosaicTask(final List<Layer> layerRange, final Patch nail, final Align.Param cp, final Align.ParamOptimize p, final Align.ParamOptimize pcp, final boolean tilesAreInPlaceIn, final boolean largestGraphOnlyIn, final boolean hideDisconnectedTilesIn, final boolean deleteDisconnectedTilesIn, final boolean deformIn) {
    /* register */
    final List<AbstractAffineTile2D<?>> allTiles = new ArrayList<AbstractAffineTile2D<?>>();
    final List<AbstractAffineTile2D<?>> allFixedTiles = new ArrayList<AbstractAffineTile2D<?>>();
    final List<AbstractAffineTile2D<?>> previousLayerTiles = new ArrayList<AbstractAffineTile2D<?>>();
    final HashMap<Patch, PointMatch> tileCenterPoints = new HashMap<Patch, PointMatch>();
    final Collection<Patch> fixedPatches = new HashSet<Patch>();
    if (null != nail)
        fixedPatches.add(nail);
    Layer previousLayer = null;
    for (final Layer layer : layerRange) {
        /* align all tiles in the layer */
        final List<Patch> patches = new ArrayList<Patch>();
        for (// ignore hidden tiles
        final Displayable a : // ignore hidden tiles
        layer.getDisplayables(Patch.class, true)) if (a instanceof Patch)
            patches.add((Patch) a);
        final List<AbstractAffineTile2D<?>> currentLayerTiles = new ArrayList<AbstractAffineTile2D<?>>();
        final List<AbstractAffineTile2D<?>> fixedTiles = new ArrayList<AbstractAffineTile2D<?>>();
        Align.tilesFromPatches(p, patches, fixedPatches, currentLayerTiles, fixedTiles);
        // Will consider graphs and hide/delete tiles when all cross-layer graphs are found.
        alignTiles(p, currentLayerTiles, fixedTiles, tilesAreInPlaceIn, false, false, false);
        if (Thread.currentThread().isInterrupted())
            return;
        /* connect to the previous layer */
        /* generate tiles with the cross-section model from the current layer tiles */
        /* ------------------------------------------------------------------------ */
        /* TODO step back and make tiles bare containers for a patch and a model such that by changing the model the tile can be reused */
        final HashMap<Patch, AbstractAffineTile2D<?>> currentLayerPatchTiles = new HashMap<Patch, AbstractAffineTile2D<?>>();
        for (final AbstractAffineTile2D<?> t : currentLayerTiles) currentLayerPatchTiles.put(t.getPatch(), t);
        final List<AbstractAffineTile2D<?>> csCurrentLayerTiles = new ArrayList<AbstractAffineTile2D<?>>();
        final Set<AbstractAffineTile2D<?>> csFixedTiles = new HashSet<AbstractAffineTile2D<?>>();
        Align.tilesFromPatches(cp, patches, fixedPatches, csCurrentLayerTiles, csFixedTiles);
        final HashMap<Tile<?>, AbstractAffineTile2D<?>> tileTiles = new HashMap<Tile<?>, AbstractAffineTile2D<?>>();
        for (final AbstractAffineTile2D<?> t : csCurrentLayerTiles) tileTiles.put(currentLayerPatchTiles.get(t.getPatch()), t);
        for (final AbstractAffineTile2D<?> t : currentLayerTiles) {
            final AbstractAffineTile2D<?> csLayerTile = tileTiles.get(t);
            csLayerTile.addMatches(t.getMatches());
            for (final Tile<?> ct : t.getConnectedTiles()) csLayerTile.addConnectedTile(tileTiles.get(ct));
        }
        /* add a fixed tile only if there was a Patch selected */
        allFixedTiles.addAll(csFixedTiles);
        /* first, align connected graphs to each other */
        /* graphs in the current layer */
        final List<Set<Tile<?>>> currentLayerGraphs = AbstractAffineTile2D.identifyConnectedGraphs(csCurrentLayerTiles);
        if (Thread.currentThread().isInterrupted())
            return;
        // /* TODO just for visualization */
        // for ( final Set< Tile< ? > > graph : currentLayerGraphs )
        // {
        // Display.getFront().getSelection().clear();
        // Display.getFront().setLayer( ( ( AbstractAffineTile2D< ? > )graph.iterator().next() ).getPatch().getLayer() );
        // 
        // for ( final Tile< ? > tile : graph )
        // {
        // Display.getFront().getSelection().add( ( ( AbstractAffineTile2D< ? > )tile ).getPatch() );
        // Display.repaint();
        // }
        // Utils.showMessage( "OK" );
        // }
        /* graphs from the whole system that are present in the previous layer */
        final List<Set<Tile<?>>> graphs = AbstractAffineTile2D.identifyConnectedGraphs(allTiles);
        final HashMap<Set<Tile<?>>, Set<Tile<?>>> graphGraphs = new HashMap<Set<Tile<?>>, Set<Tile<?>>>();
        for (final Set<Tile<?>> graph : graphs) {
            if (Thread.currentThread().isInterrupted())
                return;
            final Set<Tile<?>> previousLayerGraph = new HashSet<Tile<?>>();
            for (final Tile<?> tile : previousLayerTiles) {
                if (graph.contains(tile)) {
                    graphGraphs.put(graph, previousLayerGraph);
                    previousLayerGraph.add(tile);
                }
            }
        }
        final Collection<Set<Tile<?>>> previousLayerGraphs = graphGraphs.values();
        // /* TODO just for visualization */
        // for ( final Set< Tile< ? > > graph : previousLayerGraphs )
        // {
        // Display.getFront().getSelection().clear();
        // Display.getFront().setLayer( ( ( AbstractAffineTile2D< ? > )graph.iterator().next() ).getPatch().getLayer() );
        // 
        // for ( final Tile< ? > tile : graph )
        // {
        // Display.getFront().getSelection().add( ( ( AbstractAffineTile2D< ? > )tile ).getPatch() );
        // Display.repaint();
        // }
        // Utils.showMessage( "OK" );
        // }
        /* generate snapshots of the graphs and preregister them using the parameters defined in cp */
        final List<AbstractAffineTile2D<?>[]> crossLayerTilePairs = new ArrayList<AbstractAffineTile2D<?>[]>();
        for (final Set<Tile<?>> currentLayerGraph : currentLayerGraphs) {
            for (final Set<Tile<?>> previousLayerGraph : previousLayerGraphs) {
                if (Thread.currentThread().isInterrupted())
                    return;
                alignGraphs(cp, layer, previousLayer, currentLayerGraph, previousLayerGraph);
                /* TODO this is pointless data shuffling just for type incompatibility---fix this at the root */
                final ArrayList<AbstractAffineTile2D<?>> previousLayerGraphTiles = new ArrayList<AbstractAffineTile2D<?>>();
                previousLayerGraphTiles.addAll((Set) previousLayerGraph);
                final ArrayList<AbstractAffineTile2D<?>> currentLayerGraphTiles = new ArrayList<AbstractAffineTile2D<?>>();
                currentLayerGraphTiles.addAll((Set) currentLayerGraph);
                AbstractAffineTile2D.pairOverlappingTiles(previousLayerGraphTiles, currentLayerGraphTiles, crossLayerTilePairs);
            }
        }
        /* ------------------------------------------------------------------------ */
        /* this is without the affine/rigid approximation per graph */
        // AbstractAffineTile2D.pairTiles( previousLayerTiles, csCurrentLayerTiles, crossLayerTilePairs );
        Align.connectTilePairs(cp, csCurrentLayerTiles, crossLayerTilePairs, Runtime.getRuntime().availableProcessors());
        if (Thread.currentThread().isInterrupted())
            return;
        // for ( final AbstractAffineTile2D< ? >[] tilePair : crossLayerTilePairs )
        // {
        // Display.getFront().setLayer( tilePair[ 0 ].getPatch().getLayer() );
        // Display.getFront().getSelection().clear();
        // Display.getFront().getSelection().add( tilePair[ 0 ].getPatch() );
        // Display.getFront().getSelection().add( tilePair[ 1 ].getPatch() );
        // 
        // Utils.showMessage( "1: OK?" );
        // 
        // Display.getFront().setLayer( tilePair[ 1 ].getPatch().getLayer() );
        // Display.getFront().getSelection().clear();
        // Display.getFront().getSelection().add( tilePair[ 0 ].getPatch() );
        // Display.getFront().getSelection().add( tilePair[ 1 ].getPatch() );
        // 
        // Utils.showMessage( "2: OK?" );
        // }
        /* prepare the next loop */
        allTiles.addAll(csCurrentLayerTiles);
        previousLayerTiles.clear();
        previousLayerTiles.addAll(csCurrentLayerTiles);
        /* optimize */
        Align.optimizeTileConfiguration(pcp, allTiles, allFixedTiles);
        if (Thread.currentThread().isInterrupted())
            return;
        for (final AbstractAffineTile2D<?> t : allTiles) t.getPatch().setAffineTransform(t.getModel().createAffine());
        previousLayer = layer;
    }
    final List<Set<Tile<?>>> graphs = AbstractAffineTile2D.identifyConnectedGraphs(allTiles);
    final List<AbstractAffineTile2D<?>> interestingTiles = new ArrayList<AbstractAffineTile2D<?>>();
    if (largestGraphOnlyIn && (hideDisconnectedTilesIn || deleteDisconnectedTilesIn)) {
        if (Thread.currentThread().isInterrupted())
            return;
        /* find largest graph. */
        Set<Tile<?>> largestGraph = null;
        for (final Set<Tile<?>> graph : graphs) if (largestGraph == null || largestGraph.size() < graph.size())
            largestGraph = graph;
        final Set<AbstractAffineTile2D<?>> tiles_to_keep = new HashSet<AbstractAffineTile2D<?>>();
        for (final Tile<?> t : largestGraph) tiles_to_keep.add((AbstractAffineTile2D<?>) t);
        if (hideDisconnectedTilesIn)
            for (final AbstractAffineTile2D<?> t : allTiles) if (!tiles_to_keep.contains(t))
                t.getPatch().setVisible(false);
        if (deleteDisconnectedTilesIn)
            for (final AbstractAffineTile2D<?> t : allTiles) if (!tiles_to_keep.contains(t))
                t.getPatch().remove(false);
        interestingTiles.addAll(tiles_to_keep);
    } else
        interestingTiles.addAll(allTiles);
    if (deformIn) {
        /* ############################################ */
        /* experimental: use the center points of all tiles to define a MLS deformation from the pure intra-layer registration to the globally optimal */
        Utils.log("deforming...");
        /* store the center location of each single tile for later deformation */
        for (final AbstractAffineTile2D<?> t : interestingTiles) {
            final double[] c = new double[] { t.getWidth() / 2.0, t.getHeight() / 2.0 };
            t.getModel().applyInPlace(c);
            final Point q = new Point(c);
            tileCenterPoints.put(t.getPatch(), new PointMatch(q.clone(), q));
        }
        for (final Layer layer : layerRange) {
            Utils.log("layer" + layer);
            if (Thread.currentThread().isInterrupted())
                return;
            /* again, align all tiles in the layer */
            final List<Patch> patches = new ArrayList<Patch>();
            for (final Displayable a : layer.getDisplayables(Patch.class)) if (a instanceof Patch)
                patches.add((Patch) a);
            final List<AbstractAffineTile2D<?>> currentLayerTiles = new ArrayList<AbstractAffineTile2D<?>>();
            final List<AbstractAffineTile2D<?>> fixedTiles = new ArrayList<AbstractAffineTile2D<?>>();
            Align.tilesFromPatches(p, patches, fixedPatches, currentLayerTiles, fixedTiles);
            /* add a fixed tile only if there was a Patch selected */
            allFixedTiles.addAll(fixedTiles);
            // will consider graphs and hide/delete tiles when all cross-layer graphs are found
            alignTiles(p, currentLayerTiles, fixedTiles, true, false, false, false);
            /* for each independent graph do an independent transform */
            final List<Set<Tile<?>>> currentLayerGraphs = AbstractAffineTile2D.identifyConnectedGraphs(currentLayerTiles);
            for (final Set<Tile<?>> graph : currentLayerGraphs) {
                /* update the tile-center pointmatches */
                final Collection<PointMatch> matches = new ArrayList<PointMatch>();
                final Collection<AbstractAffineTile2D<?>> toBeDeformedTiles = new ArrayList<AbstractAffineTile2D<?>>();
                for (final AbstractAffineTile2D<?> t : (Collection<AbstractAffineTile2D<?>>) (Collection) graph) {
                    final PointMatch pm = tileCenterPoints.get(t.getPatch());
                    if (pm == null)
                        continue;
                    final double[] pl = pm.getP1().getL();
                    pl[0] = t.getWidth() / 2.0;
                    pl[1] = t.getHeight() / 2.0;
                    t.getModel().applyInPlace(pl);
                    matches.add(pm);
                    toBeDeformedTiles.add(t);
                }
                for (final AbstractAffineTile2D<?> t : toBeDeformedTiles) {
                    if (Thread.currentThread().isInterrupted())
                        return;
                    try {
                        final Patch patch = t.getPatch();
                        final Rectangle pbox = patch.getCoordinateTransformBoundingBox();
                        final AffineTransform pat = new AffineTransform();
                        pat.translate(-pbox.x, -pbox.y);
                        pat.preConcatenate(patch.getAffineTransform());
                        final mpicbg.trakem2.transform.AffineModel2D toWorld = new mpicbg.trakem2.transform.AffineModel2D();
                        toWorld.set(pat);
                        final MovingLeastSquaresTransform2 mlst = Align.createMLST(matches, 1.0f);
                        final CoordinateTransformList<CoordinateTransform> ctl = new CoordinateTransformList<CoordinateTransform>();
                        ctl.add(toWorld);
                        ctl.add(mlst);
                        ctl.add(toWorld.createInverse());
                        patch.appendCoordinateTransform(ctl);
                        patch.getProject().getLoader().regenerateMipMaps(patch);
                    } catch (final Exception e) {
                        e.printStackTrace();
                    }
                }
            }
        }
    }
    layerRange.get(0).getParent().setMinimumDimensions();
    IJ.log("Done: register multi-layer mosaic.");
    return;
}
Also used : Set(java.util.Set) HashSet(java.util.HashSet) LayerSet(ini.trakem2.display.LayerSet) HashMap(java.util.HashMap) CoordinateTransformList(mpicbg.trakem2.transform.CoordinateTransformList) ArrayList(java.util.ArrayList) Rectangle(java.awt.Rectangle) AbstractAffineModel2D(mpicbg.models.AbstractAffineModel2D) AffineModel2D(mpicbg.models.AffineModel2D) HashSet(java.util.HashSet) Displayable(ini.trakem2.display.Displayable) Tile(mpicbg.models.Tile) Point(mpicbg.models.Point) Layer(ini.trakem2.display.Layer) NotEnoughDataPointsException(mpicbg.models.NotEnoughDataPointsException) NoninvertibleModelException(mpicbg.models.NoninvertibleModelException) NoninvertibleTransformException(java.awt.geom.NoninvertibleTransformException) PointMatch(mpicbg.models.PointMatch) MovingLeastSquaresTransform2(mpicbg.trakem2.transform.MovingLeastSquaresTransform2) Collection(java.util.Collection) AffineTransform(java.awt.geom.AffineTransform) Patch(ini.trakem2.display.Patch) CoordinateTransform(mpicbg.trakem2.transform.CoordinateTransform) InvertibleCoordinateTransform(mpicbg.trakem2.transform.InvertibleCoordinateTransform)

Example 89 with Displayable

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

the class AlignTask method montageLayers.

@SuppressWarnings({ "rawtypes", "unchecked" })
public static final void montageLayers(final Align.ParamOptimize p, final List<Layer> layers, final boolean tilesAreInPlaceIn, final boolean largestGraphOnlyIn, final boolean hideDisconnectedTilesIn, final boolean deleteDisconnectedTilesIn, final boolean sloppyOverlapTest) {
    int i = 0;
    for (final Layer layer : layers) {
        if (Thread.currentThread().isInterrupted())
            return;
        final Collection<Displayable> patches = layer.getDisplayables(Patch.class, true);
        if (patches.isEmpty())
            continue;
        for (final Displayable patch : patches) {
            if (patch.isLinked() && !patch.isOnlyLinkedTo(Patch.class)) {
                Utils.log("Cannot montage layer " + layer + "\nReason: at least one Patch is linked to non-image data: " + patch);
                continue;
            }
        }
        Utils.log("====\nMontaging layer " + layer);
        Utils.showProgress(((double) i) / layers.size());
        i++;
        alignPatches(p, new ArrayList<Patch>((Collection<Patch>) (Collection) patches), new ArrayList<Patch>(), tilesAreInPlaceIn, largestGraphOnlyIn, hideDisconnectedTilesIn, deleteDisconnectedTilesIn, sloppyOverlapTest);
        Display.repaint(layer);
    }
}
Also used : Displayable(ini.trakem2.display.Displayable) Collection(java.util.Collection) Layer(ini.trakem2.display.Layer) Patch(ini.trakem2.display.Patch) Point(mpicbg.models.Point)

Example 90 with Displayable

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

the class AlignTask method transformVectorData.

public static final void transformVectorData(final ReferenceData rd, /* The transformations of patches before alignment. */
final Collection<Displayable> vdata, /* The VectorData instances to transform along with images. */
final LayerSet target_layerset) /* The LayerSet in which the vdata and the transformed images exist. */
{
    final ExecutorService exec = Utils.newFixedThreadPool("AlignTask-transformVectorData");
    try {
        final Collection<Future<?>> fus = new ArrayList<Future<?>>();
        final HashMap<Long, Layer> lidm = new HashMap<Long, Layer>();
        for (final Long lid : rd.src_layer_lids_used) {
            final Layer la = target_layerset.getLayer(lid.longValue());
            if (null == la) {
                Utils.log("ERROR layer with id " + lid + " NOT FOUND in target layerset!");
                continue;
            }
            lidm.put(lid, la);
        }
        for (final Map.Entry<Displayable, Map<Long, TreeMap<Integer, Long>>> ed : rd.underlying.entrySet()) {
            // The VectorData instance to transform
            final Displayable d = ed.getKey();
            // Process Displayables concurrently:
            fus.add(exec.submit(new Runnable() {

                @SuppressWarnings({ "rawtypes", "unchecked" })
                @Override
                public void run() {
                    for (final Map.Entry<Long, TreeMap<Integer, Long>> el : ed.getValue().entrySet()) {
                        // The entry has the id of the layer and the stack-index-ordered list of Patch that intersect VectorData d in that Layer
                        final Layer layer = lidm.get(el.getKey());
                        if (null == layer) {
                            Utils.log("ERROR layer with id " + el.getKey() + " NOT FOUND in target layerset!");
                            continue;
                        }
                        // Utils.log("Editing Displayable " + d + " at layer " + layer);
                        // list of Patch ids affecting VectorData/Displayable d
                        final ArrayList<Long> pids = new ArrayList<Long>(el.getValue().values());
                        // so now Patch ids are sorted from top to bottom
                        Collections.reverse(pids);
                        // The area already processed in the layer
                        final Area used_area = new Area();
                        // The map of areas vs transforms for each area to apply to the VectorData, to its data within the layer only
                        final VectorDataTransform vdt = new VectorDataTransform(layer);
                        // The list of transforms to apply to each VectorData
                        for (final long pid : pids) {
                            // Find the Patch with id 'pid' in Layer 'la' of the target LayerSet:
                            final DBObject ob = layer.findById(pid);
                            if (null == ob || !(ob instanceof Patch)) {
                                Utils.log("ERROR layer with id " + layer.getId() + " DOES NOT CONTAIN a Patch with id " + pid);
                                continue;
                            }
                            final Patch patch = (Patch) ob;
                            // no need to synch, read only from now on
                            final Patch.TransformProperties props = rd.tp.get(pid);
                            if (null == props) {
                                Utils.log("ERROR: could not find any Patch.TransformProperties for patch " + patch);
                                continue;
                            }
                            final Area a = new Area(props.area);
                            a.subtract(used_area);
                            if (M.isEmpty(a)) {
                                // skipping fully occluded Patch
                                continue;
                            }
                            // Accumulate:
                            used_area.add(props.area);
                            // For the remaining area within this Layer, define a transform
                            // Generate a CoordinateTransformList that includes:
                            // 1 - an inverted transform from Patch coords to world coords
                            // 2 - the CoordinateTransform of the Patch, if any
                            // 3 - the AffineTransform of the Patch
                            // 
                            // The idea is to first send the data from world to pixel space of the Patch, using the old transfroms,
                            // and then from pixel space of the Patch to world, using the new transforms.
                            final CoordinateTransformList tlist = new CoordinateTransformList();
                            // 1. Inverse of the old affine: from world into the old patch mipmap
                            final mpicbg.models.AffineModel2D aff_inv = new mpicbg.models.AffineModel2D();
                            try {
                                aff_inv.set(props.at.createInverse());
                            } catch (final NoninvertibleTransformException nite) {
                                Utils.log("ERROR: could not invert the affine transform for Patch " + patch);
                                IJError.print(nite);
                                continue;
                            }
                            tlist.add(aff_inv);
                            // 2. Inverse of the old coordinate transform of the Patch: from old mipmap to pixels in original image
                            if (null != props.ct) {
                                // The props.ct is a CoordinateTransform, not necessarily an InvertibleCoordinateTransform
                                // So the mesh is necessary to ensure the invertibility
                                final mpicbg.trakem2.transform.TransformMesh mesh = new mpicbg.trakem2.transform.TransformMesh(props.ct, props.meshResolution, props.o_width, props.o_height);
                                /* // Apparently not needed; the inverse affine in step 1 took care of it.
								 * // (the affine of step 1 includes the mesh translation)
							Rectangle box = mesh.getBoundingBox();
							AffineModel2D aff = new AffineModel2D();
							aff.set(new AffineTransform(1, 0, 0, 1, box.x, box.y));
							tlist.add(aff);
								 */
                                tlist.add(new InverseICT(mesh));
                            }
                            // 3. New coordinate transform of the Patch: from original image to new mipmap
                            final mpicbg.trakem2.transform.CoordinateTransform ct = patch.getCoordinateTransform();
                            if (null != ct) {
                                tlist.add(ct);
                                final mpicbg.trakem2.transform.TransformMesh mesh = new mpicbg.trakem2.transform.TransformMesh(ct, patch.getMeshResolution(), patch.getOWidth(), patch.getOHeight());
                                // correct for mesh bounds -- Necessary because it comes from the other side, and the removal of the translation here is re-added by the affine in step 4!
                                final Rectangle box = mesh.getBoundingBox();
                                final AffineModel2D aff = new AffineModel2D();
                                aff.set(new AffineTransform(1, 0, 0, 1, -box.x, -box.y));
                                tlist.add(aff);
                            }
                            // 4. New affine transform of the Patch: from mipmap to world
                            final mpicbg.models.AffineModel2D new_aff = new mpicbg.models.AffineModel2D();
                            new_aff.set(patch.getAffineTransform());
                            tlist.add(new_aff);
                            /*
						// TODO Consider caching the tlist for each Patch, or for a few thousand of them maximum.
						//      But it could blow up memory astronomically.

						// The old part:
						final mpicbg.models.InvertibleCoordinateTransformList old = new mpicbg.models.InvertibleCoordinateTransformList();
						if (null != props.ct) {
							mpicbg.trakem2.transform.TransformMesh mesh = new mpicbg.trakem2.transform.TransformMesh(props.ct, props.meshResolution, props.o_width, props.o_height);
							old.add(mesh);
						}
						final mpicbg.models.AffineModel2D old_aff = new mpicbg.models.AffineModel2D();
						old_aff.set(props.at);
						old.add(old_aff);

						tlist.add(new InverseICT(old));

						// The new part:
						final mpicbg.models.AffineModel2D new_aff = new mpicbg.models.AffineModel2D();
						new_aff.set(patch.getAffineTransform());
						tlist.add(new_aff);
						final mpicbg.trakem2.transform.CoordinateTransform ct = patch.getCoordinateTransform();
						if (null != ct) tlist.add(ct);
							 */
                            vdt.add(a, tlist);
                        }
                        // Apply the map of area vs tlist for the data section of d within the layer:
                        try {
                            ((VectorData) d).apply(vdt);
                        } catch (final Exception t) {
                            Utils.log("ERROR transformation failed for " + d + " at layer " + layer);
                            IJError.print(t);
                        }
                    }
                }
            }));
        }
        Utils.wait(fus);
        Display.repaint();
    } finally {
        exec.shutdown();
    }
}
Also used : VectorDataTransform(ini.trakem2.display.VectorDataTransform) HashMap(java.util.HashMap) CoordinateTransformList(mpicbg.trakem2.transform.CoordinateTransformList) ArrayList(java.util.ArrayList) Rectangle(java.awt.Rectangle) DBObject(ini.trakem2.persistence.DBObject) VectorData(ini.trakem2.display.VectorData) AffineModel2D(mpicbg.models.AffineModel2D) CoordinateTransform(mpicbg.trakem2.transform.CoordinateTransform) AbstractAffineModel2D(mpicbg.models.AbstractAffineModel2D) AffineModel2D(mpicbg.models.AffineModel2D) Displayable(ini.trakem2.display.Displayable) TreeMap(java.util.TreeMap) Layer(ini.trakem2.display.Layer) NotEnoughDataPointsException(mpicbg.models.NotEnoughDataPointsException) NoninvertibleModelException(mpicbg.models.NoninvertibleModelException) NoninvertibleTransformException(java.awt.geom.NoninvertibleTransformException) NoninvertibleTransformException(java.awt.geom.NoninvertibleTransformException) Area(java.awt.geom.Area) ExecutorService(java.util.concurrent.ExecutorService) Future(java.util.concurrent.Future) AffineTransform(java.awt.geom.AffineTransform) Map(java.util.Map) HashMap(java.util.HashMap) TreeMap(java.util.TreeMap) Patch(ini.trakem2.display.Patch)

Aggregations

Displayable (ini.trakem2.display.Displayable)50 ArrayList (java.util.ArrayList)36 ZDisplayable (ini.trakem2.display.ZDisplayable)29 Patch (ini.trakem2.display.Patch)27 HashMap (java.util.HashMap)24 HashSet (java.util.HashSet)23 Layer (ini.trakem2.display.Layer)21 Rectangle (java.awt.Rectangle)17 ProjectThing (ini.trakem2.tree.ProjectThing)15 DBObject (ini.trakem2.persistence.DBObject)14 ImagePlus (ij.ImagePlus)13 LayerSet (ini.trakem2.display.LayerSet)12 Point (java.awt.Point)11 AffineTransform (java.awt.geom.AffineTransform)11 Map (java.util.Map)11 GenericDialog (ij.gui.GenericDialog)10 Collection (java.util.Collection)10 Worker (ini.trakem2.utils.Worker)9 Area (java.awt.geom.Area)9 TreeMap (java.util.TreeMap)9