imagej / imagej-common

ImageJ core data model
https://imagej.net/libs/imagej-common
BSD 2-Clause "Simplified" License
9 stars 18 forks source link

Unify Dataset and ImgPlus #46

Open ctrueden opened 9 years ago

ctrueden commented 9 years ago

These two classes should be one thing.

This is one primary goal of the "rich image" work. Relevant related resources are:

rejsmont commented 7 years ago

+1 I have been recently thinking about the fact that DefaultDataset is in large part a wrapper for ImgPlus and plenty of methods are just decorators. Would you rather merge DefaultDataset and ImgPlus (or just make ImgPlus implement Dataset) or go with something like AbstractDataset that both Dataset and ImgPlus extend?

ctrueden commented 7 years ago

@rejsmont To get an broader idea of what is planned for these type hierarchies in ImageJ Common and SciJava Common, see the data-model label as well as scijava/scijava-common#157 and this news post, and this topic branch and this git repository.

This data model work is currently priority 5 on my primary priority list.

Regarding Dataset and ImgPlus specifically: the current plan is for Dataset to become a container of multiple images (e.g. Img, RandomAccessibleInterval, and/or IterableInterval... left intentionally open-ended). That way, reading a file with SCIFIO for example can always return a single Dataset which may contain multiple N-dimensional structures, or just one. And these structures can all have open-ended metadata attached, both structural and otherwise. The metadata will be accessible from some interface Rich... we may end up with e.g. RichImg extends Rich, Img and RichRAI extends Rich, RandomAccessibleInterval, RichII extends Rich, IterableInterval etc... although one goal is to avoid proliferating too many interfaces like that. Regardless, Dataset will remain an interface, and be much thinner than it is now.

One thorny issue is how to "recover" the generic parameter (e.g. T extends RealType<T>) in code—how to go from Dataset dataset to RichImg<T> img = dataset.image(0) or some such. It may not be possible to do this without some kind of unchecked warning.

All of this will be a few more months (at least) in coming, but should hopefully be much nicer than what we have now. Once we have this, imagej-common will finally be able to graduate from 0.x to 1.0.0, and ImageJ2 as a whole can stop being 2.0.0-rc-xyz and graduate to 2.0.0.

rejsmont commented 7 years ago

@ctrueden if I understand correctly this means then that one should already avoid passing Dataset as a parameter for ops directly, as once refactoring is done, it may result in unexpected behavior... Imagine a Dataset from LIF file with multiple images in there - what would ops do if you pass such a dataset to it?

EDIT: I could imagine it taking dataset.image(0) as a sane default and giving a warning on the console.

ctrueden commented 7 years ago

@rejsmont Absolutely; this will be a quite serious breaking change in backward compatibility. The Dataset interface will probably not even implement any of the ImgLib2 image interfaces anymore, so existing ops typed on Dataset will need to be massaged to either: A) accept a type like Img or RichImg instead; or B) extract the image(s) of interest from the dataset via something like dataset.image(0).

In general, if you are concerned about things working in the future with no code changes, then it is crucial to use only components released at 1.x or later. Components versioned at 0.x are still incubating and subject to disruptive changes. We will of course do what we can to minimize it, but the fact is that the ImageJ2 data model needs substantial changes to work well into the future.

Both imglib2 and scijava-common are stable, so you can write e.g. a Command plugin which uses @Parameter RandomAccessibleInterval<T> image or whatnot and that should continue to work for a long time. Alternately, you can write @Parameter private ImagePlus imp and that will also work, although then of course you tie yourself to ImageJ 1.x, which has its own downsides. Please be aware that ImageJ Ops is also still at 0.x, and there are going to be changes to that project as well, including the Op interface itself no longer extending Command. Ops written now will need massaging in the future to adapt to changing APIs. However, Ops is fundamentally based on ImgLib2, so I do not expect people will need to "rewrite from scratch" ops which are written now... only that you might need to change e.g. extends AbstractUnaryFunctionOp<T, T> to implements FunctionOp<T, T> and rename T calculate(T in) to T apply(T in) instead. The main issue is with code written now, published, and then never updated again—that sort of code will not keep working for the next 10 years with no maintenance.

imagesc-bot commented 3 years ago

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

https://forum.image.sc/t/autodiscoverable-plugins-in-sci-java/43613/15