Skip to content

Conversation

@gselzer
Copy link
Member

@gselzer gselzer commented Aug 19, 2024

This PR makes a few changes that improve the thresholding Ops:

  • Thresholding on RAI, instead of on Iterable - I'm not terribly sure about this change, as it limits the scope of what we can threshold, however it enables better efficiency and I don't think we ever really needed the Iterables capability...what do you think @hinerm?
  • Expand Interval -> RAI creation capabilities - now leans on dependencies to create RAIs of many different element types.

@gselzer gselzer requested a review from hinerm August 19, 2024 17:02
@gselzer gselzer linked an issue Aug 19, 2024 that may be closed by this pull request
Copy link
Member

@ctrueden ctrueden left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Before we plunge ahead with this, I'd like to better understand why we need to move away from allowing thresholding on Iterable.

*/
public abstract class AbstractApplyThresholdIterable<T> implements
Computers.Arity1<Iterable<T>, Iterable<BitType>>
Computers.Arity1<RandomAccessibleInterval<T>, RandomAccessibleInterval<BitType>>
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why does the change from Iterable to RAI enable better efficiency?

Does the fact that RAI implements IterableInterval in ImgLib2 v7 make a difference in our decision here?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why does the change from Iterable to RAI enable better efficiency?

Well, I haven't tested, so better efficiency is probably a stretch to say, however this dependency can now make use of LoopBuilder, which is nice.

Does the fact that RAI implements IterableInterval in ImgLib2 v7 make a difference in our decision here?

Probably not? There are likely some changes (like this) that could be reverted, but I can't imagine this would break?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I can't imagine this would break?

I wasn't suggesting that this change, together with the ImgLib2 v7 update, would break anything. Rather, I'm wondering if the ImgLib2 v7 update would somehow obviate the need to narrow the scope of the threshold ops from Iterable to RAI.

this dependency can now make use of LoopBuilder, which is nice.

Yep, that's good. But for Iterables generally, there is the spliterator() subsystem, which could potentially enable multithreaded thresholding over any Iterable. Though I suppose the "proxy" behavior of T instances might preclude the ability to loop in parallel that way...

Another option would be to keep the existing thresholding Ops for Iterable and simply add the RAI-specific ones at higher priority. Then we wouldn't need to bump scijava-ops-image to 2.0.0 in response to the backwards incompatibility.

@gselzer
Copy link
Member Author

gselzer commented Aug 19, 2024

Before we plunge ahead with this, I'd like to better understand why we need to move away from allowing thresholding on Iterable.

The main problem here is that, for Computer to Function adaptation to work here, we need a Function<T, U> engine.create Op to produce the output, where T is a supertype of Iterable<T> and U is a subtype of Iterable<BitType>. The former is problematic here, as no supertype of Iterable<T> would contain enough information to make an Img<BitType>, for example.

What I realized we could do, though, is something like I did here. The additions of type variables U and V are ugly, however they do let us circumvent the Iterable<T> problem by asking for a Function<U, V>, where U is now Img<ShortType>. The only unfortunate things now are that:

  1. The error message is ugly (note that if you just call ops.help("threshold.mean"), you'll get the simple descriptions which remove the type variables):
org.scijava.ops.api.OpMatchingException: No Ops found matching this request.

Name: "threshold.mean", Types: java.util.function.Function<net.imglib2.img.array.ArrayImg<net.imglib2.type.numeric.integer.UnsignedShortType, net.imglib2.img.basictypeaccess.array.ShortArray>, net.imglib2.RandomAccessibleInterval<net.imglib2.type.logic.BitType>>
Input Types: 
		* net.imglib2.img.array.ArrayImg<net.imglib2.type.numeric.integer.UnsignedShortType, net.imglib2.img.basictypeaccess.array.ShortArray>
Output Type: 
		* net.imglib2.RandomAccessibleInterval<net.imglib2.type.logic.BitType>

Perhaps you meant one of these:
threshold.mean:
	- org.scijava.ops.image.threshold.ApplyThresholdMethod$Mean
		> input : U
		> output : @CONTAINER V
	- org.scijava.ops.image.threshold.mean.ComputeMeanThreshold
		 Implements a mean threshold method by Glasbey.
		> input : net.imglib2.histogram.Histogram1d<T extends net.imglib2.type.numeric.RealType<T>>
		> output : @CONTAINER T
  1. Still doesn't work if you request a RandomAccessibleInterval output, however that would be fixed with ImgLib2 v7.

@imagesc-bot
Copy link

This pull request has been mentioned on Image.sc Forum. There might be relevant details there:

https://forum.image.sc/t/fiji-friends-weekly-dev-update-thread/103718/52

@gselzer gselzer force-pushed the scijava-ops-image/improved-thresholding branch from f827f68 to d3c820e Compare February 7, 2025 19:42
By using generics, these Ops are much more flexible
Broadened type variables allow for more efficient iteration over e.g.
images
@gselzer gselzer force-pushed the scijava-ops-image/improved-thresholding branch from d3c820e to d061c4d Compare February 7, 2025 23:22
@gselzer gselzer marked this pull request as ready for review February 7, 2025 23:27
@gselzer
Copy link
Member Author

gselzer commented Feb 7, 2025

I've given this PR some TLC - I'm much happier with how things work:

  • Thresholding on RAI, instead of on Iterable - I'm not terribly sure about this change, as it limits the scope of what we can threshold, however it enables better efficiency and I don't think we ever really needed the Iterables capability...what do you think @hinerm?

This is no longer the case - I used type variables for more powerful dependency resolution, as I alluded to here:

What I realized we could do, though, is something like I did here. The additions of type variables U and V are ugly, however they do let us circumvent the Iterable<T> problem by asking for a Function<U, V>, where U is now Img<ShortType>. The only unfortunate things now are that:

The ops.helpVerbose calls are still a bit confusing, but this should be solved in another PR:

	- org.scijava.ops.image.threshold.ApplyThresholdMethod$Mean
		> input : I
		> output : @CONTAINER J

@gselzer gselzer force-pushed the scijava-ops-image/improved-thresholding branch from edefad2 to ad83c3a Compare February 10, 2025 14:55
@gselzer gselzer merged commit 28fcdd4 into main Feb 10, 2025
1 check passed
@gselzer gselzer deleted the scijava-ops-image/improved-thresholding branch February 10, 2025 15:04
@imagesc-bot
Copy link

This pull request has been mentioned on Image.sc Forum. There might be relevant details there:

https://forum.image.sc/t/fiji-friends-weekly-dev-update-thread/103718/60

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Can't threshold as a function

4 participants