imglib2 PointCollection, Localizable vs RealLocalizable

@tpietzsch? Quick question about PointCollection. Could the PointCollection (and thus the internal private class PointCollectionCursor also) be based upon RealLocalizable instead of Localizable?. It doesn’t necessarily seem like PointCollection or the KDTree stuff rely on the discrete nature of the point locations. Is that right?

@jaywarrick The PointCollection was introduced together with @dietzc to be able to represent a set of rasterized points along RasterizedPolygonalChain. (Maybe @dietzc can give more rationale?) As such it is naturally discrete and this is necessary to be able to implement IterableRegion

The whole ROI stuff is work in progress and currently the interfaces focus on discrete ROIs. The hierarchy there is RandomAccessibleInterval<T extends BooleanType<T>> :arrow_left: IterableRegion<T> :arrow_left: PositionableIterableRegion<T>. The idea is that as soon as you have, e.g., a RandomAccessibleInterval<BitType>, you can use static methods Regions.iterable(), Regions.positionable() (doesn’t exist yet) to add these capabilities to your ROI. And you want to be able to use Regions.sample() to bind an IterableRegion to an image.

There is no corresponding RealIterableRegion interface so far. The RealPointCollection should implement this. I’m not sure whether we need that interface though. The adding of capabilities as described above will not in general work. Usually, if you have a continuous region, it is not possible to iterate it. Also, it would in my opinion make little sense to implement RealRandomAccessibleInterval in RealPointCollection because the probability of an arbitrary location being inside the region is 0. If you for example Views.raster() it (as you might want to do to paint it) that will not work properly.

So, to summarize:
1.) The discrete PointCollection is needed and should stay discrete.
2.) There could be a RealPointCollection that is an IterableRealInterval<Void>. Whether it is worth making that depends on your use-case. Can you give more background on that? For most scenarios, a simple ArrayList<RealLocalizable> might be enough?

Thanks @tpietzsch. Everything you say makes sense. I see the need to keep as Localizable.

In the end, I think I have what I need but thought I would give you the background in case the feedback helps in the future.

I think my perception of a PointCollection was a bit off initially (i.e., I was thinking more of a basic collection rather than a representation of a region). I had been looking for something more like a collection because, in my own project, I found that a List of points which allows the ability to add points, remove points, get nearest neighbor in, iterate over, union, intersect, and transform to be extremely useful in many contexts. It forms the base class for my ROIs in my project and other data analysis (e.g., tracking). Each ROI or extension just “interprets/utilizes” the point list differently.

One reason to have a “real” version of a point list for representing a region or ROI would be to keep precision upon multiple manipulations (e.g., rotate + scale + translate + intersect), performing rounding / rasterizing only at the end of all manipulations. This sort of assumes that the “real” locations are still representing pixels that have a quantized area/spacing/region. In other words, I would like a high precision point collection class for calculations but want to eventually get out either the continuous or discrete representations of the high precision data held within the class (i.e., always both and not one or the other). Thus the reason to snoop around the API and ask questions about all this stuff :slightly_smiling: Thanks for your help.

Along these lines I then noticed the PointSampleList and RealPointSampleList classes. They offer the ability to associate data with each point such as an “Id”, which I ended up finding to be necessary for many of my applications of the point list class. So to create an imglib2 based version of this point list class I ended up creating something like RealPointSampleList class but implemented slightly differently so that I could keep the data and coordinates more closely linked. I added the transformation capabilities to it via conversions to and from java.awt.Polygon2D.Double’s for now. It’s pretty rough for the time being but working.

P.S. I like your approach with the Regions.xxxx(). Should be very flexible.

Best,

Jay

Yes, I see that this would be useful. We don’t have this in imglib2 yet, but would be great to have.

For fast neighbor search etc. maybe https://github.com/fiji/TrackMate3/tree/master/src/main/java/net/trackmate/spatial is related. In the upcoming version of TrackMate/MaMuT we have spatial indices that stay up to date when adding/removing/moving points. It’s basically kD-tree (infrequently rebuilt) plus list of modifications on top. Maybe that approach is worth adopting for your solution?

Yes, I could imagine that you either have an explicit rasterize() operation that does the rounding for the real-points in your collection and creates a PointCollection. Or you could provide a “rasterized view” of the real-points collection (implementing IterableRegion<BoolType>) that does it on the fly.

Yes, RealPointSampleList as well as KDTree are not perfectly suited. They are made for lookup from coordinates to values. In your case it sounds like you also need fast lookup in the opposite direction.

Do you plan on going beyond 2D at some point? In any case, it might be worth looking at AffineTransform2D (in imglib2-realtransform) etc to do transformation instead of java.awt…

best regards,
Tobias

Super helpful. Thanks @tpietzsch. I was looking for the affiine transform stuff and didn’t come across it. Thanks for pointing it out. No plans or bandwidth to go to n-D at the moment but with these very general interfaces all around, if I write it for 2D it probably won’t be bad to expand to n-D. I’ll try to do so when that time comes.

Cheers,

Jay