diff --git a/src/main/java/org/janelia/saalfeldlab/n5/shard/Shard.java b/src/main/java/org/janelia/saalfeldlab/n5/shard/Shard.java index a90a2b1..b0e551a 100644 --- a/src/main/java/org/janelia/saalfeldlab/n5/shard/Shard.java +++ b/src/main/java/org/janelia/saalfeldlab/n5/shard/Shard.java @@ -116,6 +116,18 @@ default List> getBlocks() { return blocks; } + /** + * Returns an {@link Iterator} over block positions contained in this shard. + * + * @return + */ + default Iterator blockPositionIterator() { + + final int nd = getSize().length; + long[] min = getDatasetAttributes().getBlockPositionFromShardPosition( getGridPosition(), new long[nd]); + return new GridIterator(GridIterator.int2long(getBlockGridSize()), min); + } + public ShardIndex getIndex(); public static Shard createEmpty(final A attributes, long... shardPosition) { @@ -158,4 +170,5 @@ public DataBlock next() { return shard.getBlock(it.next()); } } + } diff --git a/src/main/java/org/janelia/saalfeldlab/n5/shard/ShardParameters.java b/src/main/java/org/janelia/saalfeldlab/n5/shard/ShardParameters.java index 27e9bf5..31d385f 100644 --- a/src/main/java/org/janelia/saalfeldlab/n5/shard/ShardParameters.java +++ b/src/main/java/org/janelia/saalfeldlab/n5/shard/ShardParameters.java @@ -97,8 +97,10 @@ default int[] getBlockPositionInShard(final long[] shardPosition, final long[] b /** * Given a block's position relative to a shard, returns its position in pixels * relative to the image. - * - * @return the block position + * + * @param shardPosition shard position in the shard grid + * @param blockPosition block position the + * @return the block's min pixel coordinate */ default long[] getBlockMinFromShardPosition(final long[] shardPosition, final long[] blockPosition) { @@ -117,7 +119,9 @@ default long[] getBlockMinFromShardPosition(final long[] shardPosition, final lo * Given a block's position relative to a shard, returns its position relative * to the image. * - * @return the block position + * @param shardPosition shard position in the shard grid + * @param blockPosition block position relative to the shard + * @return the block position in the block grid */ default long[] getBlockPositionFromShardPosition(final long[] shardPosition, final long[] blockPosition) { diff --git a/src/main/java/org/janelia/saalfeldlab/n5/util/GridIterator.java b/src/main/java/org/janelia/saalfeldlab/n5/util/GridIterator.java index 1ea16ef..299fda8 100644 --- a/src/main/java/org/janelia/saalfeldlab/n5/util/GridIterator.java +++ b/src/main/java/org/janelia/saalfeldlab/n5/util/GridIterator.java @@ -1,6 +1,5 @@ package org.janelia.saalfeldlab.n5.util; -import java.util.Arrays; import java.util.Iterator; /** @@ -14,15 +13,18 @@ public class GridIterator implements Iterator { final protected long[] position; + final protected long[] min; + final protected int lastIndex; protected int index = -1; - public GridIterator(final long[] dimensions) { + public GridIterator(final long[] dimensions, final long[] min) { final int n = dimensions.length; this.dimensions = new long[n]; this.position = new long[n]; + this.min = min; steps = new long[n]; final int m = n - 1; @@ -38,6 +40,11 @@ public GridIterator(final long[] dimensions) { lastIndex = (int)(k * dimm - 1); } + public GridIterator(final long[] dimensions) { + + this(dimensions, new long[dimensions.length]); + } + public GridIterator(final int[] dimensions) { this(int2long(dimensions)); @@ -59,7 +66,7 @@ public boolean hasNext() { @Override public long[] next() { fwd(); - indexToPosition(index, dimensions, position); + indexToPosition(index, dimensions, min, position); return position; } @@ -71,10 +78,10 @@ public int getIndex() { return index; } - final static public void indexToPosition(long index, final long[] dimensions, final long[] position) { + final static public void indexToPosition(long index, final long[] dimensions, final long[] min, final long[] position) { final int maxDim = dimensions.length - 1; for (int dim = maxDim; dim >= 0; dim--) { - position[dim] = index % dimensions[dim]; + position[dim] = index % dimensions[dim] + min[dim]; index /= dimensions[dim]; } } diff --git a/src/test/java/org/janelia/saalfeldlab/n5/shard/ShardPropertiesTests.java b/src/test/java/org/janelia/saalfeldlab/n5/shard/ShardPropertiesTests.java new file mode 100644 index 0000000..5f661f0 --- /dev/null +++ b/src/test/java/org/janelia/saalfeldlab/n5/shard/ShardPropertiesTests.java @@ -0,0 +1,90 @@ +package org.janelia.saalfeldlab.n5.shard; + +import static org.junit.Assert.assertArrayEquals; +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNull; + +import java.util.Iterator; + +import org.janelia.saalfeldlab.n5.DataType; +import org.janelia.saalfeldlab.n5.ShardedDatasetAttributes; +import org.janelia.saalfeldlab.n5.codec.Codec; +import org.janelia.saalfeldlab.n5.codec.DeterministicSizeCodec; +import org.janelia.saalfeldlab.n5.shard.ShardingCodec.IndexLocation; +import org.junit.Test; + +public class ShardPropertiesTests { + + @Test + public void testShardProperties() throws Exception { + + final long[] arraySize = new long[]{16, 16}; + final int[] shardSize = new int[]{16, 16}; + final long[] shardPosition = new long[]{1, 1}; + final int[] blkSize = new int[]{4, 4}; + + final ShardedDatasetAttributes dsetAttrs = new ShardedDatasetAttributes( + arraySize, + shardSize, + blkSize, + DataType.UINT8, + new Codec[]{}, + new DeterministicSizeCodec[]{}, + IndexLocation.END); + + @SuppressWarnings({"rawtypes", "unchecked"}) + final InMemoryShard shard = new InMemoryShard(dsetAttrs, shardPosition, null); + + assertArrayEquals(new int[]{4, 4}, shard.getBlockGridSize()); + + assertArrayEquals(new long[]{0, 0}, shard.getShard(0, 0)); + assertArrayEquals(new long[]{1, 1}, shard.getShard(5, 5)); + assertArrayEquals(new long[]{1, 0}, shard.getShard(5, 0)); + assertArrayEquals(new long[]{0, 1}, shard.getShard(0, 5)); + +// assertNull(shard.getBlockPosition(0, 0)); +// assertNull(shard.getBlockPosition(3, 3)); + + assertArrayEquals(new int[]{0, 0}, shard.getBlockPosition(4, 4)); + assertArrayEquals(new int[]{1, 1}, shard.getBlockPosition(5, 5)); + assertArrayEquals(new int[]{2, 2}, shard.getBlockPosition(6, 6)); + assertArrayEquals(new int[]{3, 3}, shard.getBlockPosition(7, 7)); + } + + @Test + public void testShardBlockPositionIterator() throws Exception { + + final long[] arraySize = new long[]{16, 16}; + final int[] shardSize = new int[]{16, 16}; + final long[] shardPosition = new long[]{1, 1}; + final int[] blkSize = new int[]{4, 4}; + + final ShardedDatasetAttributes dsetAttrs = new ShardedDatasetAttributes( + arraySize, + shardSize, + blkSize, + DataType.UINT8, + new Codec[]{}, + new DeterministicSizeCodec[]{}, + IndexLocation.END); + + @SuppressWarnings({"rawtypes", "unchecked"}) + final InMemoryShard shard = new InMemoryShard(dsetAttrs, shardPosition, null); + + int i = 0; + Iterator it = shard.blockPositionIterator(); + long[] p = null; + while (it.hasNext()) { + + p = it.next(); + if( i == 0 ) + assertArrayEquals(new long[]{4,4}, p); + + i++; + } + assertEquals(16,i); + assertArrayEquals(new long[]{7,7}, p); + + } + +}