Last active
January 29, 2019 14:45
-
-
Save tinevez/522d0db6ba895625cb054b274d73fdd2 to your computer and use it in GitHub Desktop.
A binning op based on Image-Ops.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
@Plugin( type = BinningOp.class ) | |
public class BinningOp< T extends RealType< T > > extends AbstractUnaryFunctionOp< RandomAccessibleInterval< T >, Img< T > > | |
{ | |
@Parameter( type = ItemIO.INPUT ) | |
private int[] binfactors; | |
@Parameter( type = ItemIO.INPUT, required = false ) | |
private Class< ? extends Op > ocClass = Ops.Stats.Mean.class; | |
@Override | |
public Img< T > calculate( final RandomAccessibleInterval< T > input ) | |
{ | |
final int numDimensions = input.numDimensions(); | |
if ( numDimensions != binfactors.length ) | |
throw new IllegalArgumentException( "Bin n-dimensions and input n-dimensions must be equal. Bins have " | |
+ binfactors.length + " dimensions and input has " + numDimensions + " dimensions." ); | |
// Prepare output. | |
final long[] imgSize = new long[ numDimensions ]; | |
input.dimensions( imgSize ); | |
final long[] newSize = new long[ numDimensions ]; | |
for ( int d = 0; d < input.numDimensions(); ++d ) | |
newSize[ d ] = input.dimension( d ) / binfactors[ d ]; | |
final ImgFactory< T > factory = Util.getSuitableImgFactory( FinalDimensions.wrap( newSize ), | |
Util.getTypeFromInterval( input ) ); | |
final Img< T > binned = factory.create( FinalDimensions.wrap( newSize ) ); | |
final NotCenteredRectangleShape shape = new NotCenteredRectangleShape( binfactors ); | |
final RandomAccessible< Neighborhood< T > > ran = shape.neighborhoodsRandomAccessible( Views.extendMirrorSingle( input ) ); | |
@SuppressWarnings( { "rawtypes", "unchecked" } ) | |
final UnaryComputerOp< Iterable< T >, T > op = ( UnaryComputerOp ) Computers.unary( ops(), ocClass, binned.firstElement().getClass(), Iterable.class ); | |
// Multithread. | |
ops().run( ChunkerOp.class, new CursorBasedChunk() | |
{ | |
@Override | |
public void execute( final int startIndex, final int stepSize, final int numSteps ) | |
{ | |
final RandomAccess< Neighborhood< T > > ra = ran.randomAccess( input ); | |
final long[] currPos = new long[ input.numDimensions() ]; | |
final Cursor< T > cursor = binned.localizingCursor(); | |
cursor.jumpFwd( startIndex ); | |
for ( int i = 0; i < numSteps; ++i ) | |
{ | |
cursor.next(); | |
cursor.localize( currPos ); | |
// 'Transform' coordinates. | |
for ( int d = 0; d < numDimensions; d++ ) | |
currPos[ d ] *= binfactors[ d ]; | |
// Iterate and compute. | |
ra.setPosition( currPos ); | |
op.compute( ra.get(), cursor.get() ); | |
} | |
} | |
}, binned.size() ); | |
return binned; | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment