diff --git a/render-ws-java-client/src/main/java/org/janelia/render/client/newsolver/BlockData.java b/render-ws-java-client/src/main/java/org/janelia/render/client/newsolver/BlockData.java index a6970dc37..ed6efc2aa 100644 --- a/render-ws-java-client/src/main/java/org/janelia/render/client/newsolver/BlockData.java +++ b/render-ws-java-client/src/main/java/org/janelia/render/client/newsolver/BlockData.java @@ -1,6 +1,7 @@ package org.janelia.render.client.newsolver; import java.io.Serializable; +import java.util.ArrayList; import java.util.Collection; import java.util.HashMap; import java.util.HashSet; @@ -14,6 +15,8 @@ import org.janelia.render.client.newsolver.solvers.Worker; import mpicbg.models.CoordinateTransform; +import net.imglib2.util.Pair; +import net.imglib2.util.ValuePair; /** * Should contain only geometric data, nothing specific to the type of solve @@ -47,6 +50,12 @@ public class BlockData< M extends CoordinateTransform, P extends BlockDataSolveP // contains the model as determined by the local solve final private HashMap idToNewModel = new HashMap<>(); + // what z-range this block covers + final protected int minZ, maxZ; + + // all z-layers as String map to List that only contains the z-layer as double + final protected Map> sectionIdToZMap; + public BlockData( final F blockFactory, // knows how it was created for assembly later? final P solveTypeParameters, @@ -61,8 +70,18 @@ public BlockData( this.allTileIds = new HashSet<>( allTileIds ); this.idToTileSpec = idToTileSpec; this.weightF = weightF; + + this.sectionIdToZMap = new HashMap<>(); + final Pair minmax = fetchRenderDetails( idToTileSpec().values(), sectionIdToZMap ); + + this.minZ = minmax.getA(); + this.maxZ = minmax.getB(); } + public int minZ() { return minZ; } + public int maxZ() { return maxZ; } + public Map> sectionIdToZMap() { return sectionIdToZMap; } + public int getId() { return id; } public double getWeight( final double location, final int dim ) { return weightF.get( dim ).apply( location ); } @@ -80,5 +99,52 @@ public Worker< M, P, F > createWorker() // should maybe ask the solveTypeParamters to create the object I think return null; } - + + /** + * Fetches basic data for all TileSpecs + * + * @param allTileSpecs - all TileSpec objects that are part of this solve + * @param sectionIdToZMap - will be filled + * @return a Pair< minZ, maxZ > + */ + public static Pair< Integer, Integer > fetchRenderDetails( + final Collection< TileSpec > allTileSpecs, + final Map> sectionIdToZMap ) + { + int minZ = Integer.MAX_VALUE; + int maxZ = Integer.MIN_VALUE; + + for ( final TileSpec t : allTileSpecs) //blockData.idToTileSpec().values() ) + { + if ( sectionIdToZMap.containsKey( t.getSectionId() )) + { + final ArrayList z = sectionIdToZMap.get( t.getSectionId() ); + + if ( !z.contains( t.getZ() ) ) + z.add( t.getZ() ); + } + else + { + final ArrayList z = new ArrayList<>(); + z.add( t.getZ() ); + sectionIdToZMap.put( t.getSectionId(), z ); + } + + final int z = (int)Math.round( t.getZ() ); + minZ = Math.min( z, minZ ); + maxZ = Math.max( z, maxZ ); + } + + return new ValuePair<>( minZ, maxZ ); + + //final private HashSet allTileIds; + //final private Map idToTileSpec; + + // tileId > String (this is the pId, qId) + // sectionId > String (this is the pGroupId, qGroupId) + + //TileSpec ts = blockData.idToTileSpec().values().iterator().next(); + //String sectionId = ts.getLayout().getSectionId(); // + + } } diff --git a/render-ws-java-client/src/main/java/org/janelia/render/client/newsolver/solvers/Worker.java b/render-ws-java-client/src/main/java/org/janelia/render/client/newsolver/solvers/Worker.java index 84b9e434f..73d6a714e 100644 --- a/render-ws-java-client/src/main/java/org/janelia/render/client/newsolver/solvers/Worker.java +++ b/render-ws-java-client/src/main/java/org/janelia/render/client/newsolver/solvers/Worker.java @@ -1,14 +1,9 @@ package org.janelia.render.client.newsolver.solvers; import java.io.IOException; -import java.util.ArrayList; -import java.util.Collection; -import java.util.HashMap; import java.util.List; -import java.util.Map; import java.util.concurrent.ExecutionException; -import org.janelia.alignment.spec.TileSpec; import org.janelia.render.client.RenderDataClient; import org.janelia.render.client.newsolver.BlockData; import org.janelia.render.client.newsolver.blockfactories.BlockFactory; @@ -16,8 +11,6 @@ import mpicbg.models.CoordinateTransform; import mpicbg.models.NoninvertibleModelException; -import net.imglib2.util.Pair; -import net.imglib2.util.ValuePair; public abstract class Worker < M extends CoordinateTransform, P extends BlockDataSolveParameters< M, P >, F extends BlockFactory< F > > { @@ -28,12 +21,6 @@ public abstract class Worker < M extends CoordinateTransform, P extends BlockDat final protected RenderDataClient renderDataClient; final protected String renderStack; - // what z-range this block covers - final protected int minZ, maxZ; - - // all z-layers as String map to List that only contains the z-layer as double - final protected Map> sectionIdToZMap; - final protected int numThreads; public Worker( @@ -49,19 +36,10 @@ public Worker( blockData.solveTypeParameters().owner(), blockData.solveTypeParameters().project() ); this.renderStack = blockData.solveTypeParameters().stack(); - this.sectionIdToZMap = new HashMap<>(); - - final Pair minmax = fetchRenderDetails( blockData.idToTileSpec().values(), sectionIdToZMap ); - - this.minZ = minmax.getA(); - this.maxZ = minmax.getB(); this.numThreads = numThreads; } - public int minZ() { return minZ; } - public int maxZ() { return maxZ; } - /** * runs the Worker */ @@ -71,45 +49,4 @@ public Worker( * @return - the result(s) of the solve, multiple ones if they were not connected */ public abstract List< BlockData< M, P, F > > getBlockDataList(); - - public static Pair< Integer, Integer > fetchRenderDetails( - final Collection< TileSpec > allTileSpecs, - final Map> sectionIdToZMap ) - { - int minZ = Integer.MAX_VALUE; - int maxZ = Integer.MIN_VALUE; - - for ( final TileSpec t : allTileSpecs) //blockData.idToTileSpec().values() ) - { - if ( sectionIdToZMap.containsKey( t.getSectionId() )) - { - final ArrayList z = sectionIdToZMap.get( t.getSectionId() ); - - if ( !z.contains( t.getZ() ) ) - z.add( t.getZ() ); - } - else - { - final ArrayList z = new ArrayList<>(); - z.add( t.getZ() ); - sectionIdToZMap.put( t.getSectionId(), z ); - } - - final int z = (int)Math.round( t.getZ() ); - minZ = Math.min( z, minZ ); - maxZ = Math.max( z, maxZ ); - } - - return new ValuePair<>( minZ, maxZ ); - - //final private HashSet allTileIds; - //final private Map idToTileSpec; - - // tileId > String (this is the pId, qId) - // sectionId > String (this is the pGroupId, qGroupId) - - //TileSpec ts = blockData.idToTileSpec().values().iterator().next(); - //String sectionId = ts.getLayout().getSectionId(); // - - } } diff --git a/render-ws-java-client/src/main/java/org/janelia/render/client/newsolver/solvers/affine/AffineAlignBlockWorker.java b/render-ws-java-client/src/main/java/org/janelia/render/client/newsolver/solvers/affine/AffineAlignBlockWorker.java index 3c53e92e5..e77962715 100644 --- a/render-ws-java-client/src/main/java/org/janelia/render/client/newsolver/solvers/affine/AffineAlignBlockWorker.java +++ b/render-ws-java-client/src/main/java/org/janelia/render/client/newsolver/solvers/affine/AffineAlignBlockWorker.java @@ -140,25 +140,17 @@ public List< BlockData< M, FIBSEMAlignmentParameters< M, S >, F > > getBlockData @Override public void run() throws IOException, ExecutionException, InterruptedException, NoninvertibleModelException { - this.canvasMatches = assembleMatchData( - inputSolveItem, sectionIdToZMap, matchFilter, minZ, maxZ, matchDataClient, renderDataClient, renderStack, - pairs, zToPairs, blockData.solveTypeParameters().maxZRangeMatches() ); + this.canvasMatches = assembleMatchData( inputSolveItem, matchFilter, matchDataClient, renderDataClient, renderStack, pairs, zToPairs ); // minStitchingInliersSupplier: // how many stitching inliers are needed to stitch first // reason: if tiles are rarely connected and it is stitched first, a useful // common alignment model after stitching cannot be found - stitchSectionsAndCreateGroupedTiles( - inputSolveItem, pairs, zToPairs, - blockData.solveTypeParameters().maxPlateauWidthStitching(), - blockData.solveTypeParameters().maxAllowedErrorStitching(), - blockData.solveTypeParameters().maxIterationsStitching(), - blockData.solveTypeParameters().minStitchingInliersSupplier(), - stitchFirst, numThreads ); + stitchSectionsAndCreateGroupedTiles( inputSolveItem, pairs, zToPairs, stitchFirst, numThreads ); connectGroupedTiles( pairs, inputSolveItem ); - this.solveItems = splitSolveItem( inputSolveItem, startId, minZ, maxZ ); + this.solveItems = splitSolveItem( inputSolveItem, startId ); for ( final AffineBlockDataWrapper< M, S, F > solveItem : solveItems ) { @@ -187,23 +179,24 @@ public void run() throws IOException, ExecutionException, InterruptedException, protected ArrayList< CanvasMatches > assembleMatchData( final AffineBlockDataWrapper< M, S, F > inputSolveItem, - final Map> sectionIdToZMap, final MatchFilter matchFilter, - final int minZ, - final int maxZ, final RenderDataClient matchDataClient, final RenderDataClient renderDataClient, final String renderStack, final ArrayList< Pair< Pair< Tile< ? >, Tile< ? > >, List< PointMatch > > > pairs, - final HashMap< Integer, List< Integer > > zToPairs, - final double maxZRangeMatches ) throws IOException + final HashMap< Integer, List< Integer > > zToPairs ) throws IOException { + final Map> sectionIdToZMap = inputSolveItem.blockData().sectionIdToZMap(); + final int minZ = inputSolveItem.blockData().minZ(); + final int maxZ = inputSolveItem.blockData().maxZ(); + final int maxZRangeMatches = inputSolveItem.blockData().solveTypeParameters().maxZRangeMatches(); + final ArrayList< CanvasMatches > canvasMatches = new ArrayList<>(); final Map zToTileSpecsMap = new HashMap<>(); - LOG.info( "block " + inputSolveItem.blockData().getId() + ": Loading transforms and matches for " + inputSolveItem.blockData().allTileIds().size() + "tiles, from " + this.minZ + " to layer " + this.maxZ ); + LOG.info( "block " + inputSolveItem.blockData().getId() + ": Loading transforms and matches for " + inputSolveItem.blockData().allTileIds().size() + "tiles, from " + minZ + " to layer " + maxZ ); - if ( !Double.isNaN( maxZRangeMatches ) ) + if ( maxZRangeMatches >= 0 ) LOG.info( "block " + inputSolveItem.blockData().getId() + ": WARNING! max z range for matching is " + maxZRangeMatches ); // Note: this is not sorted anymore @@ -247,7 +240,7 @@ protected ArrayList< CanvasMatches > assembleMatchData( } // max range - if ( !Double.isNaN( maxZRangeMatches ) && Math.abs( pTileSpec.getZ() - qTileSpec.getZ() ) > maxZRangeMatches ) + if ( maxZRangeMatches >= 0 && Math.abs( pTileSpec.getZ() - qTileSpec.getZ() ) > maxZRangeMatches ) continue; final Tile p = getOrBuildTile(pId, pTileSpec); @@ -600,13 +593,14 @@ protected void stitchSectionsAndCreateGroupedTiles( final AffineBlockDataWrapper< M, S, F > solveItem, final ArrayList< Pair< Pair< Tile< ? >, Tile< ? > >, List< PointMatch > > > pairs, final HashMap< Integer, List< Integer > > zToPairs, - final int maxPlateauWidthStitching, - final double maxAllowedErrorStitching, - final int maxIterationsStitching, - final Function< Integer, Integer > minStitchingInliersSupplier, final boolean stitchFirst, final int numThreads ) { + final int maxPlateauWidthStitching = solveItem.blockData().solveTypeParameters().maxPlateauWidthStitching(); + final double maxAllowedErrorStitching = solveItem.blockData().solveTypeParameters().maxAllowedErrorStitching(); + final int maxIterationsStitching = solveItem.blockData().solveTypeParameters().maxIterationsStitching(); + final Function< Integer, Integer > minStitchingInliersSupplier = solveItem.blockData().solveTypeParameters().minStitchingInliersSupplier(); + //final S model = solveItem.stitchingSolveModelInstance(); // combine tiles per layer that are be stitched first, but iterate over all z's @@ -815,7 +809,7 @@ protected void stitchSectionsAndCreateGroupedTiles( } } - protected List< AffineBlockDataWrapper< M, S, F > > splitSolveItem( final AffineBlockDataWrapper< M, S, F > inputSolveItem, final int startId, final int minZ, final int maxZ ) + protected List< AffineBlockDataWrapper< M, S, F > > splitSolveItem( final AffineBlockDataWrapper< M, S, F > inputSolveItem, final int startId ) { // assigning new id's to the solve items (they collide for now with other workers, fix upon merging) int id = startId + 1;