Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fluent API for chaining views #364

Merged
merged 35 commits into from
Aug 9, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
35 commits
Select commit Hold shift + click to select a range
e9b6eb9
First version of stream-like API for views
minnerbe Oct 12, 2023
8b9fb0c
relax InterpolatorFactory generics
tpietzsch Apr 26, 2024
1606a47
Alternative architecture with multiple wrapper interfaces
tpietzsch Oct 13, 2023
1f856df
WIP javadoc
tpietzsch Apr 26, 2024
fc75f35
minor fixes
tpietzsch Apr 27, 2024
75f3026
Add recursive generic to RaView.
tpietzsch May 7, 2024
8f0c4ef
Handle RaView in PrimitiveBlocks
tpietzsch Apr 28, 2024
b05e0f4
javadoc
tpietzsch Apr 28, 2024
ebd22d0
clean up
tpietzsch Apr 28, 2024
d863ce0
Add RandomAccessible.view()
tpietzsch Apr 28, 2024
aaa1f37
javadoc
tpietzsch Apr 28, 2024
3b401db
Make RandomAccessible[Interval]::view idempotent
tpietzsch Apr 28, 2024
e38e946
clean up
tpietzsch Apr 28, 2024
8875a39
Add RealRandomAccessible::view
tpietzsch Apr 28, 2024
a1b8987
clean up
tpietzsch Apr 28, 2024
8e1c3ea
javadoc
tpietzsch Apr 28, 2024
f923fb0
Example to convince myself that RaView<T,?>.apply() works as intented
tpietzsch Apr 28, 2024
a0878b4
Move to net.imglib2.fluent package. Start systematically implementing…
tpietzsch Apr 29, 2024
bede12b
Implement more relevant Views methods
tpietzsch Apr 30, 2024
926b1fe
Tweak RaiView.extend() API
tpietzsch Apr 30, 2024
7ef517b
Fix RaiView.expand
tpietzsch May 6, 2024
e92a1d3
Revise RaView.interpolate and add javadoc
tpietzsch May 6, 2024
acbb37c
Add javadoc
tpietzsch May 6, 2024
7f2e05c
Use Util.expandArray instead of ViewUtils.expand
tpietzsch May 6, 2024
8e56475
Add Converters methods to RaView, RaiView, RraView
tpietzsch May 6, 2024
6ff79e0
javadoc
tpietzsch May 6, 2024
1a65297
Implement a few more forwarding methods and clean up
tpietzsch May 6, 2024
0f64524
Don't override default methods in RaiView that are already default in…
tpietzsch May 6, 2024
416739c
Replace RaiWrapper etc classes by lambdas
tpietzsch May 6, 2024
3c90c41
handle OutOfBoundsZeroFactory in PrimitiveBlocks
tpietzsch May 8, 2024
f0ecd86
Add .convert() example
tpietzsch May 8, 2024
8e5ea9f
flip argument order for convert()
tpietzsch May 14, 2024
8478d01
Rename apply(Function) to use(Function)
tpietzsch Aug 9, 2024
895ce92
Rename RraView to RealRandomAccessibleIntervalView, etc
tpietzsch Aug 9, 2024
25e0c0c
Update license headers
tpietzsch Aug 9, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
35 changes: 29 additions & 6 deletions src/main/java/net/imglib2/RandomAccessible.java
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@

package net.imglib2;

import net.imglib2.view.fluent.RandomAccessibleView;
import net.imglib2.view.Views;

/**
Expand Down Expand Up @@ -135,10 +136,10 @@ public interface RandomAccessible< T > extends EuclideanSpace, Typed< T >
* loops, or called many times!!! Use {@link #randomAccess()} when efficiency
* is important.
* <p>
* This method is a short cut for {@code randomAccess().setPositionAndGet( position );}
* This method is a short-cut for {@code randomAccess().setPositionAndGet( position );}
*
* @param position, length must be &ge; {@link #numDimensions()}
* @return value of the the {@link RandomAccessible} at {@code position}.
* @return value of the {@link RandomAccessible} at {@code position}.
*/
default T getAt( final long... position )
{
Expand All @@ -153,10 +154,10 @@ default T getAt( final long... position )
* loops, or called many times!!! Use {@link #randomAccess()} when efficiency
* is important.
* <p>
* This method is a short cut for {@code randomAccess().setPositionAndGet( position );}
* This method is a short-cut for {@code randomAccess().setPositionAndGet( position );}
*
* @param position, length must be &ge; {@link #numDimensions()}
* @return value of the the {@link RandomAccessible} at {@code position}.
* @return value of the {@link RandomAccessible} at {@code position}.
*/
default T getAt( final int... position )
{
Expand All @@ -171,16 +172,38 @@ default T getAt( final int... position )
* loops, or called many times!!! Use {@link #randomAccess()} when efficiency
* is important.
* <p>
* This method is a short cut for {@code randomAccess().setPositionAndGet( position );}
* This method is a short-cut for {@code randomAccess().setPositionAndGet( position );}
*
* @param position, {@link Localizable#numDimensions()} must be &ge; {@link #numDimensions()}
* @return value of the the {@link RandomAccessible} at {@code position}.
* @return value of the {@link RandomAccessible} at {@code position}.
*/
default T getAt( final Localizable position )
{
return randomAccess().setPositionAndGet( position );
}

/**
* Provides a gateway for creating light-weight {@link net.imglib2.view.Views
* views} into this {@code RandomAccessible}.
* <p>
* A view is itself a {@code RandomAccessible} or {@code
* RandomAccessibleInterval} whose accessors transform coordinates and/or
* values on-the-fly without copying the underlying data. Consecutive
* transformations are concatenated and simplified to provide optimally
* efficient accessors.
* <p>
* Note, that accessors provided by a view are read/write. Changing pixels
* in a view changes the underlying image data. (Value converters are an
* exception.)
*
* @return gateway for creating light-weight {@link net.imglib2.view.Views
* views} into this {@code RandomAccessible}.
*/
default RandomAccessibleView< T, ? > view()
{
return RandomAccessibleView.wrap( this );
}

/*
* NB: We cannot have a default implementation here because of
* https://bugs.openjdk.org/browse/JDK-7120669
Expand Down
24 changes: 24 additions & 0 deletions src/main/java/net/imglib2/RandomAccessibleInterval.java
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@

import net.imglib2.util.Intervals;
import net.imglib2.view.RandomAccessibleIntervalCursor;
import net.imglib2.view.fluent.RandomAccessibleIntervalView;

/**
* <p>
Expand Down Expand Up @@ -98,4 +99,27 @@ default Object iterationOrder()
{
return new FlatIterationOrder( this );
}

/**
* Provides a gateway for creating light-weight {@link net.imglib2.view.Views
* views} into this {@code RandomAccessibleInterval}.
* <p>
* A view is itself a {@code RandomAccessibleInterval} or {@code
* RandomAccessible} whose accessors transform coordinates and/or values
* on-the-fly without copying the underlying data. Consecutive
* transformations are concatenated and simplified to provide optimally
* efficient accessors.
* <p>
* Note, that accessors provided by a view are read/write. Changing pixels
* in a view changes the underlying image data. (Value converters are an
* exception.)
*
* @return gateway for creating light-weight {@link net.imglib2.view.Views
* views} into this {@code RandomAccessibleInterval}.
*/
@Override
default RandomAccessibleIntervalView< T > view()
{
return RandomAccessibleIntervalView.wrap( this );
}
}
24 changes: 24 additions & 0 deletions src/main/java/net/imglib2/RealRandomAccessible.java
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,8 @@

package net.imglib2;

import net.imglib2.view.fluent.RealRandomAccessibleView;

/**
* <p>
* <em>f:R<sup>n</sup>&rarr;T</em>
Expand Down Expand Up @@ -120,6 +122,28 @@ default T getAt( final RealLocalizable position )
return realRandomAccess().setPositionAndGet( position );
}

/**
* Provides a gateway for creating light-weight {@link net.imglib2.view.Views
* views} into this {@code RealRandomAccessible}.
* <p>
* A view is itself a {@code RealRandomAccessible} or {@code
* RandomAccessible} whose accessors transform coordinates and/or
* values on-the-fly without copying the underlying data. Consecutive
* transformations are concatenated and simplified to provide optimally
* efficient accessors.
* <p>
* Note, that accessors provided by a view are read/write. Changing pixels
* in a view changes the underlying image data. (Value converters are an
* exception.)
*
* @return gateway for creating light-weight views into this {@code
* RealRandomAccessible}.
*/
default RealRandomAccessibleView< T > realView()
{
return RealRandomAccessibleView.wrap( this );
}

/*
* NB: We cannot have a default implementation here because of
* https://bugs.openjdk.org/browse/JDK-7120669
Expand Down
21 changes: 19 additions & 2 deletions src/main/java/net/imglib2/blocks/Extension.java
Original file line number Diff line number Diff line change
Expand Up @@ -33,12 +33,16 @@
*/
package net.imglib2.blocks;

import static net.imglib2.outofbounds.OutOfBoundsMirrorFactory.Boundary.SINGLE;

import net.imglib2.blocks.ViewNode.ExtensionViewNode;
import net.imglib2.outofbounds.OutOfBoundsBorderFactory;
import net.imglib2.outofbounds.OutOfBoundsConstantValueFactory;
import net.imglib2.outofbounds.OutOfBoundsFactory;
import net.imglib2.outofbounds.OutOfBoundsMirrorFactory;

import static net.imglib2.outofbounds.OutOfBoundsMirrorFactory.Boundary.SINGLE;
import net.imglib2.outofbounds.OutOfBoundsZeroFactory;
import net.imglib2.type.operators.SetZero;
import net.imglib2.util.Cast;

interface Extension
{
Expand Down Expand Up @@ -112,4 +116,17 @@ else if ( oobFactory instanceof OutOfBoundsConstantValueFactory )
return new ExtensionImpl.UnknownExtension<>( oobFactory );
}
}

static Extension of( ExtensionViewNode node )
{
OutOfBoundsFactory< ?, ? > oobFactory = node.getOutOfBoundsFactory();
if ( oobFactory instanceof OutOfBoundsZeroFactory )
{
final net.imglib2.type.Type< ? > type = Cast.unchecked( node.view().getType() );
final SetZero zero = Cast.unchecked( type.createVariable() );
zero.setZero();
oobFactory = new OutOfBoundsConstantValueFactory<>( zero );
}
return of( oobFactory );
}
}
7 changes: 7 additions & 0 deletions src/main/java/net/imglib2/blocks/ViewAnalyzer.java
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,7 @@
import net.imglib2.img.array.ArrayImg;
import net.imglib2.img.cell.AbstractCellImg;
import net.imglib2.img.planar.PlanarImg;
import net.imglib2.view.fluent.RandomAccessibleView;
import net.imglib2.transform.integer.BoundingBox;
import net.imglib2.transform.integer.MixedTransform;
import net.imglib2.type.NativeType;
Expand Down Expand Up @@ -136,6 +137,12 @@ else if ( source instanceof ImgView )
nodes.add( new DefaultViewNode( ViewNode.ViewType.IDENTITY, view ) );
source = view.getSource();
}
else if ( source instanceof RandomAccessibleView )
{
final RandomAccessibleView< ?, ? > view = ( RandomAccessibleView< ?, ? > ) source;
nodes.add( new DefaultViewNode( ViewNode.ViewType.IDENTITY, view ) );
source = view.delegate();
}
// INTERVAL,
else if ( source instanceof IntervalView )
{
Expand Down
6 changes: 3 additions & 3 deletions src/main/java/net/imglib2/interpolation/Interpolant.java
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,7 @@ final public class Interpolant< T, F > implements RealRandomAccessible< T >, Vie

protected final int n;

final InterpolatorFactory< T, F > factory;
final InterpolatorFactory< T, ? super F > factory;

/**
*
Expand All @@ -79,7 +79,7 @@ public Interpolant( final EuclideanSpace source, final InterpolatorFactory< T, F
* @param factory
* @param n
*/
public Interpolant( final F source, final InterpolatorFactory< T, F > factory, final int n )
public Interpolant( final F source, final InterpolatorFactory< T, ? super F > factory, final int n )
{
this.source = source;
this.factory = factory;
Expand Down Expand Up @@ -118,7 +118,7 @@ public T getType()
/**
* @return {@link InterpolatorFactory} used for interpolation
*/
public InterpolatorFactory< T, F > getInterpolatorFactory()
public InterpolatorFactory< T, ? super F > getInterpolatorFactory()
{
return factory;
}
Expand Down
59 changes: 59 additions & 0 deletions src/main/java/net/imglib2/outofbounds/OutOfBoundsZeroFactory.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
/*-
* #%L
* ImgLib2: a general-purpose, multidimensional image processing library.
* %%
* Copyright (C) 2009 - 2024 Tobias Pietzsch, Stephan Preibisch, Stephan Saalfeld,
* John Bogovic, Albert Cardona, Barry DeZonia, Christian Dietz, Jan Funke,
* Aivar Grislis, Jonathan Hale, Grant Harris, Stefan Helfrich, Mark Hiner,
* Martin Horn, Steffen Jaensch, Lee Kamentsky, Larry Lindsey, Melissa Linkert,
* Mark Longair, Brian Northan, Nick Perry, Curtis Rueden, Johannes Schindelin,
* Jean-Yves Tinevez and Michael Zinsmaier.
* %%
* 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 net.imglib2.outofbounds;

import net.imglib2.Interval;
import net.imglib2.RandomAccessible;
import net.imglib2.type.Type;
import net.imglib2.type.operators.SetZero;

/**
* Return the zero value of {@code T} when out of bounds.
*
* @param <T>
* pixel type
*
* @author Tobias Pietzsch
*/
public class OutOfBoundsZeroFactory< T extends Type< T > & SetZero, F extends Interval & RandomAccessible< T > >
implements OutOfBoundsFactory< T, F >
{
@Override
public OutOfBoundsConstantValue< T > create( final F f )
{
final T zero = f.getType().createVariable();
zero.setZero();
return new OutOfBoundsConstantValue<>( f, zero );
}
}
12 changes: 6 additions & 6 deletions src/main/java/net/imglib2/view/IntervalView.java
Original file line number Diff line number Diff line change
Expand Up @@ -66,7 +66,7 @@ public class IntervalView< T > extends AbstractInterval implements RandomAccessi
* TODO Javadoc
*/
protected RandomAccessible< T > fullViewRandomAccessible;

/**
* TODO Javadoc
*/
Expand All @@ -76,7 +76,7 @@ public class IntervalView< T > extends AbstractInterval implements RandomAccessi
* Create a view that defines an interval on a source. It is the callers
* responsibility to ensure that the source is defined in the specified
* interval.
*
*
* @see Views#interval(RandomAccessible, Interval)
*/
public IntervalView( final RandomAccessible< T > source, final Interval interval )
Expand All @@ -92,9 +92,9 @@ public IntervalView( final RandomAccessible< T > source, final Interval interval
* Create a view that defines an interval on a source. It is the callers
* responsibility to ensure that the source is defined in the specified
* interval.
*
*
* @see Views#interval(RandomAccessible, Interval)
*
*
* @param min
* minimum coordinate of the interval.
* @param max
Expand All @@ -107,7 +107,7 @@ public IntervalView( final RandomAccessible< T > source, final long[] min, final

/**
* Gets the underlying source {@link RandomAccessible}.
*
*
* @return the source {@link RandomAccessible}.
*/
public RandomAccessible< T > getSource()
Expand All @@ -128,7 +128,7 @@ public RandomAccess< T > randomAccess()
fullViewRandomAccessible = TransformBuilder.getEfficientRandomAccessible( this, this );
return fullViewRandomAccessible.randomAccess();
}

protected IterableInterval< T > getFullViewIterableInterval()
{
if ( fullViewIterableInterval == null )
Expand Down
5 changes: 2 additions & 3 deletions src/main/java/net/imglib2/view/Views.java
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,6 @@

import java.util.ArrayList;
import java.util.Arrays;
import java.util.Iterator;
import java.util.List;

import net.imglib2.EuclideanSpace;
Expand Down Expand Up @@ -85,7 +84,7 @@

/**
* Create light-weight views into {@link RandomAccessible RandomAccessibles}.
*
* <p>
* A view is itself a {@link RandomAccessible} or
* {@link RandomAccessibleInterval} that provides {@link RandomAccess accessors}
* that transform coordinates on-the-fly without copying the underlying data.
Expand All @@ -109,7 +108,7 @@ public class Views
* source
* @return
*/
public static < T, F extends EuclideanSpace > RealRandomAccessible< T > interpolate( final F source, final InterpolatorFactory< T, F > factory )
public static < T, F extends EuclideanSpace > RealRandomAccessible< T > interpolate( final F source, final InterpolatorFactory< T, ? super F > factory )
{
return new Interpolant<>( source, factory, source.numDimensions() );
}
Expand Down
Loading
Loading