-
Notifications
You must be signed in to change notification settings - Fork 91
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
Add stream methods to IterableRealInterval #336
Conversation
The default implementations are backed by RealCursorSpliterator. Subclasses may override spliterator() to use something more efficient.
@tpietzsch This is awesome! Too bad about the performance, but still good to have. 😀 About the For the localizable stream elements: I like this idea. The method could just be public static < T > Stream< RealCursor< T >> localizingStream( IterableRealInterval< T > iri ) { ... }
public static < T > Stream< Cursor< T >> localizingStream( IterableInterval< T > ii ) { ... } This avoids the hairiness of incompatible return type of an overridden method in And the code could read almost as nicely: Img< DoubleType > myImg = ...;
List< Double > valuesPast123 = Streams.localizing( myImg )
.filter( c -> c.getDoublePosition( 0 ) > 123.0 )
.map( c -> c.get().getRealDouble() )
.collect( Collectors.toList() ); |
RealPositionable is Positionable, so just forward to localize(Positionable) instead of going dimension by dimension.
These are Spliterator<T>, that can additionally provide location of the last T that was visited in tryAdvance().
…rator The methods have default implementations that are backed by (Real)Cursor.
The default implementation goes dimension-by-dimension or forwards to Positionable.setPosition(Localizable), which is also often implemented to go dimension-by-dimension
Default implementation builds on localizingCursor()
(possibly setting index to -1)
This PR adds
IterableRealInterval.stream()
and.parallelStream()
default methods to access the pixel values in an image as aStream<T>
.The stream methods rely on a default implementation of
IterableRealInterval.spliterator()
backed byRealCursor
.Encounter order of the streams matches that of cursors, i.e.
Views.flatIterable(img).stream()
yields elements in flat iteration order.Usage examples:
true
pixels in a binary imagePitfalls
Note that the
T
elements of the stream are proxies and reused (as usual).The
RealCursorSpliterator
implementation takes care that a new proxy is used for each split-off prefix, soparallelStream()
works as expected.However, explicit copying operations must be added, if stream elements are supposed to be retained (by stateful intermediate or terminal operations).
For example, to collect all
DoubleType
values between0
and1
into a list:The
.map(DoubleType::copy)
operation is necessary, otherwise thevalues
list will contain many duplicates of the sameDoubleType
object (which may not even have to a value between0
and1
). The copy could also be done before the.filter(...)
operation, but it's better to do it as late as possible to avoid unnecessary creation of objects.Performance
Initial benchmarks show that using streams (even without copying) is a lot slower than explicit
for
loops, for example.Running the following benchmark
results in
Not ideal... It may be possible to improve performance, but so far I didn't find anything that works.
However, I think this is anyway more a quality-of-life feature. (Like the
RandomAccessible.getAt(...)
convenience methods (#246) which I find myself using more often then I expected, despite the performance overhead.)Ideas
There is more to explore in this direction.
Stream<LocalizableSampler<T>>
instead ofStream<T>
.The implementation would be simple, basically just use
Cursor<T>
instead ofCursor<T>.get()
for the stream elements. However, the generics are a bit hairy.ImgLibStream
wrapper aroundjava.util.stream.Stream
?With this we could add additional operations, for example the previously mentioned
.map(DoubleType::copy)
could be.materialize()
. We could decorate operations like.distinct()
and.sort()
to make sure that copies have been made before, etc.Spliterator
s improve performance over iterators, for example forCellImg
?Views
/Converters
framework?