Skip to content
Snippets Groups Projects
Commit 12f59331 authored by Tobias Pietzsch's avatar Tobias Pietzsch
Browse files

Add SimpleCacheArrayLoader (variant of CacheArrayLoader more suited to N5)

parent 2b4cab74
No related branches found
No related tags found
No related merge requests found
...@@ -7,13 +7,13 @@ ...@@ -7,13 +7,13 @@
* %% * %%
* Redistribution and use in source and binary forms, with or without * Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met: * modification, are permitted provided that the following conditions are met:
* *
* 1. Redistributions of source code must retain the above copyright notice, * 1. Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer. * this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright notice, * 2. Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation * this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution. * and/or other materials provided with the distribution.
* *
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
...@@ -30,7 +30,6 @@ ...@@ -30,7 +30,6 @@
package bdv.img.cache; package bdv.img.cache;
import bdv.ViewerImgLoader; import bdv.ViewerImgLoader;
import bdv.img.catmaid.CatmaidImageLoader;
import net.imglib2.img.basictypeaccess.volatiles.VolatileAccess; import net.imglib2.img.basictypeaccess.volatiles.VolatileAccess;
import net.imglib2.img.basictypeaccess.volatiles.VolatileArrayDataAccess; import net.imglib2.img.basictypeaccess.volatiles.VolatileArrayDataAccess;
import net.imglib2.img.basictypeaccess.volatiles.array.DirtyVolatileByteArray; import net.imglib2.img.basictypeaccess.volatiles.array.DirtyVolatileByteArray;
...@@ -58,7 +57,7 @@ import net.imglib2.type.NativeType; ...@@ -58,7 +57,7 @@ import net.imglib2.type.NativeType;
* type of access to cell data, currently always a * type of access to cell data, currently always a
* {@link VolatileAccess}. * {@link VolatileAccess}.
* *
* @author Tobias Pietzsch <tobias.pietzsch@gmail.com> * @author Tobias Pietzsch
*/ */
public interface CacheArrayLoader< A > public interface CacheArrayLoader< A >
{ {
...@@ -69,7 +68,7 @@ public interface CacheArrayLoader< A > ...@@ -69,7 +68,7 @@ public interface CacheArrayLoader< A >
* *
* @return number of bytes required to store one element. * @return number of bytes required to store one element.
*/ */
public default int getBytesPerElement() default int getBytesPerElement()
{ {
return 1; return 1;
} }
...@@ -103,7 +102,7 @@ public interface CacheArrayLoader< A > ...@@ -103,7 +102,7 @@ public interface CacheArrayLoader< A >
* *
* @return an {@link EmptyArrayCreator} for {@code A} or null. * @return an {@link EmptyArrayCreator} for {@code A} or null.
*/ */
public default EmptyArrayCreator< A > getEmptyArrayCreator() default EmptyArrayCreator< A > getEmptyArrayCreator()
{ {
return null; return null;
} }
...@@ -128,10 +127,10 @@ public interface CacheArrayLoader< A > ...@@ -128,10 +127,10 @@ public interface CacheArrayLoader< A >
* back-end. You do not need to be able to load blocks of arbitrary sizes * back-end. You do not need to be able to load blocks of arbitrary sizes
* and offsets here -- just the ones that you will use from the images * and offsets here -- just the ones that you will use from the images
* returned by your {@link ViewerImgLoader}. For an example, look at * returned by your {@link ViewerImgLoader}. For an example, look at
* {@link CatmaidImageLoader}. There, the blockDimensions are defined in the * {@code CatmaidImageLoader}. There, the blockDimensions are defined in the
* constructor, according to the tile size of the data set. These * constructor, according to the tile size of the data set. These
* blockDimensions are then used for every image that the * blockDimensions are then used for every image that the
* {@link CatmaidImageLoader} provides. Therefore, all calls to * {@code CatmaidImageLoader} provides. Therefore, all calls to
* {@link #loadArray(int, int, int, int[], long[])} will have predictable * {@link #loadArray(int, int, int, int[], long[])} will have predictable
* {@code dimensions} (corresponding to tile size of the data set) and * {@code dimensions} (corresponding to tile size of the data set) and
* {@code min} offsets (multiples of the tile size). * {@code min} offsets (multiples of the tile size).
...@@ -156,5 +155,6 @@ public interface CacheArrayLoader< A > ...@@ -156,5 +155,6 @@ public interface CacheArrayLoader< A >
* the min coordinate of the block in the stack (in voxels). * the min coordinate of the block in the stack (in voxels).
* @return loaded cell data. * @return loaded cell data.
*/ */
public A loadArray( final int timepoint, final int setup, final int level, int[] dimensions, long[] min ) throws InterruptedException; // TODO: It would make more sense to throw IOException here. Declare both IOException and InterruptedException. Throw IOException in bdv-core implementations.
A loadArray( final int timepoint, final int setup, final int level, int[] dimensions, long[] min ) throws InterruptedException;
} }
/*
* #%L
* BigDataViewer core classes with minimal dependencies
* %%
* Copyright (C) 2012 - 2016 Tobias Pietzsch, Stephan Saalfeld, Stephan Preibisch,
* Jean-Yves Tinevez, HongKee Moon, Johannes Schindelin, Curtis Rueden, John Bogovic
* %%
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
* #L%
*/
package bdv.img.cache;
import java.io.IOException;
import net.imglib2.img.basictypeaccess.volatiles.VolatileAccess;
import net.imglib2.img.basictypeaccess.volatiles.VolatileArrayDataAccess;
import net.imglib2.img.basictypeaccess.volatiles.array.DirtyVolatileByteArray;
import net.imglib2.img.basictypeaccess.volatiles.array.DirtyVolatileCharArray;
import net.imglib2.img.basictypeaccess.volatiles.array.DirtyVolatileDoubleArray;
import net.imglib2.img.basictypeaccess.volatiles.array.DirtyVolatileFloatArray;
import net.imglib2.img.basictypeaccess.volatiles.array.DirtyVolatileIntArray;
import net.imglib2.img.basictypeaccess.volatiles.array.DirtyVolatileLongArray;
import net.imglib2.img.basictypeaccess.volatiles.array.DirtyVolatileShortArray;
import net.imglib2.img.basictypeaccess.volatiles.array.VolatileByteArray;
import net.imglib2.img.basictypeaccess.volatiles.array.VolatileCharArray;
import net.imglib2.img.basictypeaccess.volatiles.array.VolatileDoubleArray;
import net.imglib2.img.basictypeaccess.volatiles.array.VolatileFloatArray;
import net.imglib2.img.basictypeaccess.volatiles.array.VolatileIntArray;
import net.imglib2.img.basictypeaccess.volatiles.array.VolatileLongArray;
import net.imglib2.img.basictypeaccess.volatiles.array.VolatileShortArray;
import net.imglib2.img.cell.CellGrid;
import net.imglib2.type.NativeType;
/**
* Provider of volatile {@link net.imglib2.img.cell.Cell} data. This is
* implemented by data back-ends to the {@link VolatileGlobalCellCache}.
* <p>
* {@code SimpleCacheArrayLoader} is supposed to load data one specific image.
* {@code loadArray()} will not get information about which timepoint,
* resolution level, etc a requested block belongs to, and also the appropriate
* block size is supposed to be known.
* <p>
* This is in contrast to {@link CacheArrayLoader}, where all information to
* identify a particular block in a whole dataset is provided. Whether it makes
* more sense to implement {@code CacheArrayLoader} or
* {@code SimpleCacheArrayLoader} depends on the particular back-end.
*
* @param <A>
* type of access to cell data, currently always a
* {@link VolatileAccess}.
*
* @author Tobias Pietzsch
*/
public interface SimpleCacheArrayLoader< A >
{
/**
* Implementing classes must override this if {@code A} is not a standard
* {@link VolatileArrayDataAccess} type. The default implementation returns
* {@code null}, which will let
* {@link CreateInvalidVolatileCell#get(CellGrid, NativeType, boolean)
* CreateInvalidVolatileCell.get(...)} try to figure out the appropriate
* {@link DefaultEmptyArrayCreator}.
* <p>
* Default access types are
* </p>
* <ul>
* <li>{@link DirtyVolatileByteArray}</li>
* <li>{@link VolatileByteArray}</li>
* <li>{@link DirtyVolatileCharArray}</li>
* <li>{@link VolatileCharArray}</li>
* <li>{@link DirtyVolatileDoubleArray}</li>
* <li>{@link VolatileDoubleArray}</li>
* <li>{@link DirtyVolatileFloatArray}</li>
* <li>{@link VolatileFloatArray}</li>
* <li>{@link DirtyVolatileIntArray}</li>
* <li>{@link VolatileIntArray}</li>
* <li>{@link DirtyVolatileLongArray}</li>
* <li>{@link VolatileLongArray}</li>
* <li>{@link DirtyVolatileShortArray}</li>
* <li>{@link VolatileShortArray}</li>
* </ul>
*
* @return an {@link EmptyArrayCreator} for {@code A} or null.
*/
default EmptyArrayCreator< A > getEmptyArrayCreator()
{
return null;
}
/**
* Load cell data into memory. This method blocks until data is successfully
* loaded. If it completes normally, the returned data is always valid. If
* anything goes wrong, an {@link IOException} is thrown.
* <p>
* {@code SimpleCacheArrayLoader} is supposed to load data one specific
* image. {@code loadArray()} will not get information about which
* timepoint, resolution level, etc a requested block belongs to. Also the
* appropriate block size is supposed to be known to the
* {@code SimpleCacheArrayLoader}.
* <p>
* This is in contrast to
* {@link CacheArrayLoader#loadArray(int, int, int, int[], long[])}, where
* all information to identify a particular block in a whole dataset is
* provided.
*
* @param gridPosition
* the coordinate of the cell in the cell grid.
*
* @return loaded cell data.
*/
A loadArray( long[] gridPosition ) throws IOException;
}
...@@ -202,22 +202,63 @@ public class VolatileGlobalCellCache implements CacheControl ...@@ -202,22 +202,63 @@ public class VolatileGlobalCellCache implements CacheControl
final CacheArrayLoader< A > cacheArrayLoader, final CacheArrayLoader< A > cacheArrayLoader,
final T type ) final T type )
{ {
final CacheLoader< Long, Cell< ? > > loader = new CacheLoader< Long, Cell< ? > >() final CacheLoader< Long, Cell< ? > > loader = key -> {
{ final int n = grid.numDimensions();
@Override final long[] cellMin = new long[ n ];
public Cell< A > get( final Long key ) throws Exception final int[] cellDims = new int[ n ];
{ grid.getCellDimensions( key, cellMin, cellDims );
final int n = grid.numDimensions(); return new Cell<>(
final long[] cellMin = new long[ n ]; cellDims,
final int[] cellDims = new int[ n ]; cellMin,
grid.getCellDimensions( key, cellMin, cellDims ); cacheArrayLoader.loadArray( timepoint, setup, level, cellDims, cellMin ) );
return new Cell<>( };
cellDims, return createImg( grid, timepoint, setup, level, cacheHints, loader, cacheArrayLoader.getEmptyArrayCreator(), type );
cellMin, }
cacheArrayLoader.loadArray( timepoint, setup, level, cellDims, cellMin ) );
} /**
* Create a {@link VolatileCachedCellImg} backed by this {@link VolatileGlobalCellCache},
* using the provided {@link SimpleCacheArrayLoader} to load data.
*
* @param grid
* @param timepoint
* @param setup
* @param level
* @param cacheHints
* @param cacheArrayLoader
* @param type
* @return
*/
public < T extends NativeType< T >, A > VolatileCachedCellImg< T, A > createImg(
final CellGrid grid,
final int timepoint,
final int setup,
final int level,
final CacheHints cacheHints,
final SimpleCacheArrayLoader< A > cacheArrayLoader,
final T type )
{
final CacheLoader< Long, Cell< ? > > loader = key -> {
final int n = grid.numDimensions();
final long[] cellMin = new long[ n ];
final int[] cellDims = new int[ n ];
final long[] cellGridPosition = new long[ n ];
grid.getCellDimensions( key, cellMin, cellDims );
grid.getCellGridPositionFlat( key, cellGridPosition );
return new Cell<>( cellDims, cellMin, cacheArrayLoader.loadArray( cellGridPosition ) );
}; };
return createImg( grid, timepoint, setup, level, cacheHints, loader, cacheArrayLoader.getEmptyArrayCreator(), type );
}
private < T extends NativeType< T >, A > VolatileCachedCellImg< T, A > createImg(
final CellGrid grid,
final int timepoint,
final int setup,
final int level,
final CacheHints cacheHints,
final CacheLoader< Long, Cell< ? > > loader,
final EmptyArrayCreator< A > emptyArrayCreator, // optional, can be null
final T type )
{
final KeyBimap< Long, Key > bimap = KeyBimap.build( final KeyBimap< Long, Key > bimap = KeyBimap.build(
index -> new Key( timepoint, setup, level, index ), index -> new Key( timepoint, setup, level, index ),
key -> ( key.timepoint == timepoint && key.setup == setup && key.level == level ) key -> ( key.timepoint == timepoint && key.setup == setup && key.level == level )
...@@ -228,14 +269,13 @@ public class VolatileGlobalCellCache implements CacheControl ...@@ -228,14 +269,13 @@ public class VolatileGlobalCellCache implements CacheControl
.mapKeys( bimap ) .mapKeys( bimap )
.withLoader( loader ); .withLoader( loader );
final EmptyArrayCreator< A > emptyArrayCreator = cacheArrayLoader.getEmptyArrayCreator();
final CreateInvalidVolatileCell< ? > createInvalid = ( emptyArrayCreator == null ) final CreateInvalidVolatileCell< ? > createInvalid = ( emptyArrayCreator == null )
? CreateInvalidVolatileCell.get( grid, type, false ) ? CreateInvalidVolatileCell.get( grid, type, false )
: new CreateInvalidVolatileCell<>( grid, type.getEntitiesPerPixel(), emptyArrayCreator ); : new CreateInvalidVolatileCell<>( grid, type.getEntitiesPerPixel(), emptyArrayCreator );
final UncheckedVolatileCache< Long, Cell< ? > > vcache = new WeakRefVolatileCache<>( final UncheckedVolatileCache< Long, Cell< ? > > vcache = new WeakRefVolatileCache<>(
cache, queue, createInvalid ) cache, queue, createInvalid )
.unchecked(); .unchecked();
@SuppressWarnings( "unchecked" ) @SuppressWarnings( "unchecked" )
final VolatileCachedCellImg< T, A > img = new VolatileCachedCellImg<>( grid, type, cacheHints, final VolatileCachedCellImg< T, A > img = new VolatileCachedCellImg<>( grid, type, cacheHints,
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment