Skip to content

Commit

Permalink
generalize SplitViewerImgLoader
Browse files Browse the repository at this point in the history
  • Loading branch information
StephanPreibisch committed Nov 2, 2024
1 parent e19d832 commit aaaedc4
Show file tree
Hide file tree
Showing 2 changed files with 17 additions and 181 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -35,8 +35,6 @@
import mpicbg.spim.data.sequence.SequenceDescription;
import net.imglib2.Interval;
import net.imglib2.cache.queue.BlockingFetchQueues;
import net.imglib2.type.numeric.integer.UnsignedShortType;
import net.imglib2.type.volatiles.VolatileUnsignedShortType;

public class SplitViewerImgLoader implements ViewerImgLoader, MultiResolutionImgLoader
{
Expand Down Expand Up @@ -94,11 +92,11 @@ private final synchronized SplitViewerSetupImgLoader getSplitViewerSetupImgLoade
if ( sil == null )
{
final ViewerSetupImgLoader setupLoader = underlyingImgLoader.getSetupImgLoader( oldSetupId );
final Object imgType = setupLoader.getImageType();
final Object volTyoe = setupLoader.getVolatileImageType();
//final Object imgType = setupLoader.getImageType();
//final Object volTyoe = setupLoader.getVolatileImageType();

if ( !imgType.getClass().isInstance( new UnsignedShortType() ) || !volTyoe.getClass().isInstance( new VolatileUnsignedShortType() ) )
throw new RuntimeException( "The underlying ViewerSetupImgLoader is not typed for <UnsignedShortType, VolatileUnsignedShortType>, cannot split up for BDV." );
//if ( !imgType.getClass().isInstance( new UnsignedShortType() ) || !volTyoe.getClass().isInstance( new VolatileUnsignedShortType() ) )
// throw new RuntimeException( "The underlying ViewerSetupImgLoader is not typed for <UnsignedShortType, VolatileUnsignedShortType>, cannot split up for BDV." );

sil = createNewSetupImgLoader( (ViewerSetupImgLoader)underlyingImgLoader.getSetupImgLoader( oldSetupId ), interval );
splitSetupImgLoaders.put( newSetupId, sil );
Expand All @@ -107,7 +105,7 @@ private final synchronized SplitViewerSetupImgLoader getSplitViewerSetupImgLoade
}

private final synchronized SplitViewerSetupImgLoader createNewSetupImgLoader(
final ViewerSetupImgLoader< UnsignedShortType, VolatileUnsignedShortType > setupImgLoader,
final ViewerSetupImgLoader setupImgLoader,
final Interval interval )
{
return new SplitViewerSetupImgLoader( setupImgLoader, interval );
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,39 +22,24 @@
*/
package net.preibisch.mvrecon.fiji.spimdata.imgloaders.splitting;

import java.util.ArrayList;
import java.util.concurrent.Callable;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

import bdv.ViewerSetupImgLoader;
import mpicbg.spim.data.generic.sequence.ImgLoaderHint;
import mpicbg.spim.data.sequence.MultiResolutionSetupImgLoader;
import mpicbg.spim.data.sequence.VoxelDimensions;
import net.imglib2.Cursor;
import net.imglib2.Dimensions;
import net.imglib2.FinalDimensions;
import net.imglib2.FinalInterval;
import net.imglib2.Interval;
import net.imglib2.IterableInterval;
import net.imglib2.RandomAccess;
import net.imglib2.RandomAccessibleInterval;
import net.imglib2.img.Img;
import net.imglib2.img.ImgFactory;
import net.imglib2.img.array.ArrayImgFactory;
import net.imglib2.img.cell.CellImgFactory;
import net.imglib2.Volatile;
import net.imglib2.realtransform.AffineTransform3D;
import net.imglib2.type.numeric.integer.UnsignedShortType;
import net.imglib2.type.numeric.real.FloatType;
import net.imglib2.type.volatiles.VolatileUnsignedShortType;
import net.imglib2.util.Intervals;
import net.imglib2.type.NativeType;
import net.imglib2.view.Views;
import net.preibisch.legacy.io.IOFunctions;
import util.ImgLib2Tools;

public class SplitViewerSetupImgLoader implements ViewerSetupImgLoader< UnsignedShortType, VolatileUnsignedShortType >, MultiResolutionSetupImgLoader< UnsignedShortType >
public class SplitViewerSetupImgLoader< T extends NativeType< T >, V extends Volatile< T > & NativeType< V > > implements ViewerSetupImgLoader< T, V >, MultiResolutionSetupImgLoader< T >
{
final ViewerSetupImgLoader< UnsignedShortType, VolatileUnsignedShortType > underlyingSetupImgLoader;
final ViewerSetupImgLoader< T, V > underlyingSetupImgLoader;
final Interval interval;
final Dimensions size;
final int n;
Expand All @@ -66,7 +51,7 @@ public class SplitViewerSetupImgLoader implements ViewerSetupImgLoader< Unsigned

private boolean[] isUpdated;

public SplitViewerSetupImgLoader( final ViewerSetupImgLoader< UnsignedShortType, VolatileUnsignedShortType > underlyingSetupImgLoader, final Interval interval )
public SplitViewerSetupImgLoader( final ViewerSetupImgLoader< T, V > underlyingSetupImgLoader, final Interval interval )
{
this.underlyingSetupImgLoader = underlyingSetupImgLoader;
this.interval = interval;
Expand Down Expand Up @@ -144,28 +129,19 @@ protected static final void setUpMultiRes(
}

@Override
public RandomAccessibleInterval< UnsignedShortType > getImage( final int timepointId, final ImgLoaderHint... hints )
public RandomAccessibleInterval< T > getImage( final int timepointId, final ImgLoaderHint... hints )
{
IOFunctions.println( "requesting full size: " );

return Views.zeroMin( Views.interval( underlyingSetupImgLoader.getImage( timepointId, hints ), interval ) );
}

@Override
public UnsignedShortType getImageType()
public T getImageType()
{
return underlyingSetupImgLoader.getImageType();
}

@Override
public RandomAccessibleInterval< FloatType > getFloatImage( final int timepointId, final boolean normalize, final ImgLoaderHint... hints )
{
if ( normalize )
return ImgLib2Tools.normalizeVirtualRAI( getImage( timepointId, hints ) );
else
return ImgLib2Tools.convertVirtualRAI( getImage( timepointId, hints ) );
}

@Override
public Dimensions getImageSize( final int timepointId )
{
Expand All @@ -179,7 +155,7 @@ public VoxelDimensions getVoxelSize( final int timepointId )
}

@Override
public RandomAccessibleInterval< UnsignedShortType > getImage( final int timepointId, final int level, final ImgLoaderHint... hints )
public RandomAccessibleInterval< T > getImage( final int timepointId, final int level, final ImgLoaderHint... hints )
{
/*
System.out.println( "requesting: " + level );
Expand Down Expand Up @@ -210,7 +186,7 @@ public RandomAccessibleInterval< UnsignedShortType > getImage( final int timepoi
System.out.println( "size: " + Util.printInterval( img ) );
System.out.println( "interval: " + Util.printInterval( scaledIntervals[ level ] ) ); */

final RandomAccessibleInterval< UnsignedShortType > full = underlyingSetupImgLoader.getImage( timepointId, level, hints );
final RandomAccessibleInterval< T > full = underlyingSetupImgLoader.getImage( timepointId, level, hints );

updateScaledIntervals( this.scaledIntervals, level, n, full );

Expand Down Expand Up @@ -260,9 +236,9 @@ protected final void updateScaledIntervals( final Interval[] scaledIntervals, fi
}

@Override
public RandomAccessibleInterval< VolatileUnsignedShortType > getVolatileImage( final int timepointId, final int level, final ImgLoaderHint... hints )
public RandomAccessibleInterval< V > getVolatileImage( final int timepointId, final int level, final ImgLoaderHint... hints )
{
final RandomAccessibleInterval< VolatileUnsignedShortType > full = underlyingSetupImgLoader.getVolatileImage( timepointId, level, hints );
final RandomAccessibleInterval< V > full = underlyingSetupImgLoader.getVolatileImage( timepointId, level, hints );

updateScaledIntervals( this.scaledIntervals, level, n, full );

Expand All @@ -287,152 +263,14 @@ public int numMipmapLevels()
return underlyingSetupImgLoader.numMipmapLevels();
}

@Override
public RandomAccessibleInterval< FloatType > getFloatImage( final int timepointId, final int level, final boolean normalize, final ImgLoaderHint... hints )
{
final RandomAccessibleInterval< UnsignedShortType > ushortImg = getImage( timepointId, level, hints );

// copy unsigned short img to float img

// create float img
final FloatType f = new FloatType();
final ImgFactory< FloatType > imgFactory;
if ( Intervals.numElements( ushortImg ) <= Integer.MAX_VALUE )
{
imgFactory = new ArrayImgFactory<>( f );
}
else
{
final long[] dimsLong = new long[ ushortImg.numDimensions() ];
ushortImg.dimensions( dimsLong );
final int[] cellDimensions = new int[ dimsLong.length ];
for ( int i = 0; i < cellDimensions.length; ++i )
cellDimensions[ i ] = 64;

imgFactory = new CellImgFactory<>( f, cellDimensions );
}
final Img< FloatType > floatImg = imgFactory.create( ushortImg );

// set up executor service
final int numProcessors = Runtime.getRuntime().availableProcessors();
final ExecutorService taskExecutor = Executors.newFixedThreadPool( numProcessors );
final ArrayList< Callable< Void > > tasks = new ArrayList<>();

// set up all tasks
final int numPortions = numProcessors * 2;
final long threadChunkSize = floatImg.size() / numPortions;
final long threadChunkMod = floatImg.size() % numPortions;

for ( int portionID = 0; portionID < numPortions; ++portionID )
{
// move to the starting position of the current thread
final long startPosition = portionID * threadChunkSize;

// the last thread may has to run longer if the number of pixels cannot be divided by the number of threads
final long loopSize = ( portionID == numPortions - 1 ) ? threadChunkSize + threadChunkMod : threadChunkSize;

if ( Views.iterable( ushortImg ).iterationOrder().equals( floatImg.iterationOrder() ) )
{
tasks.add( new Callable< Void >()
{
@Override
public Void call() throws Exception
{
final Cursor< UnsignedShortType > in = Views.iterable( ushortImg ).cursor();
final Cursor< FloatType > out = floatImg.cursor();

in.jumpFwd( startPosition );
out.jumpFwd( startPosition );

for ( long j = 0; j < loopSize; ++j )
out.next().set( in.next().getRealFloat() );

return null;
}
} );
}
else
{
tasks.add( new Callable< Void >()
{
@Override
public Void call() throws Exception
{
final Cursor< UnsignedShortType > in = Views.iterable( ushortImg ).localizingCursor();
final RandomAccess< FloatType > out = floatImg.randomAccess();

in.jumpFwd( startPosition );

for ( long j = 0; j < loopSize; ++j )
{
final UnsignedShortType vin = in.next();
out.setPosition( in );
out.get().set( vin.getRealFloat() );
}

return null;
}
} );
}
}

try
{
// invokeAll() returns when all tasks are complete
taskExecutor.invokeAll( tasks );
taskExecutor.shutdown();
}
catch ( final InterruptedException e )
{
return null;
}

if ( normalize )
// normalize the image to 0...1
normalize( floatImg );

return floatImg;
}

/*
* normalize img to 0...1
*/
protected static void normalize( final IterableInterval< FloatType > img )
{
float currentMax = img.firstElement().get();
float currentMin = currentMax;
for ( final FloatType t : img )
{
final float f = t.get();
if ( f > currentMax )
currentMax = f;
else if ( f < currentMin )
currentMin = f;
}

final float scale = ( float ) ( 1.0 / ( currentMax - currentMin ) );
for ( final FloatType t : img )
t.set( ( t.get() - currentMin ) * scale );

/*
* Once we do not need Img's for DoG anymore ....
final RandomAccessibleInterval< UnsignedShortType > image = getImage( timepointId, level, hints );
final RandomAccessibleInterval< FloatType > floatImg = Converters.convert( image, new RealFloatConverter< UnsignedShortType >(), new FloatType() );
if (normalize)
AbstractImgLoader.normalize( floatImg );
return floatImg;
*/
}

@Override
public Dimensions getImageSize( final int timepointId, final int level )
{
return sizes[ level ];
}

@Override
public VolatileUnsignedShortType getVolatileImageType()
public V getVolatileImageType()
{
return underlyingSetupImgLoader.getVolatileImageType();
}
Expand Down

0 comments on commit aaaedc4

Please sign in to comment.