[ImageJ-devel] API-breaking change in SpimData and BigDataViewer projects

Tobias Pietzsch pietzsch at mpi-cbg.de
Thu Oct 1 12:41:43 CDT 2015


very long email coming. Here is to quickly find out if you should bother reading it:
I’m preparing an update to the spim-data and bigdataviewer-core projects, that might break your code if you are using BigDataViewer or SpimData APIs.
If you are not using these APIs, then you can stop reading now -- nothing will change for users of the plugin.
If you only use BDV as a visualization frontend, then most likely you will be not affected by the changes.
If you wrote a BDV backend and/or SpimData ImgLoader, you WILL be affected. In the following I will describe how to fix your ImgLoaders.

First some motivation, for why this API break is necessary:

The basic idea of the API change is the following:
So far, all BasicImgLoader<T> and derived interfaces have been generically typed on T, meaning that the ImgLoader would deliver images of type T for all timepoints and setups (angles, channels, etc).
The new API moves the generic parameter one level deeper, to the setups. Now BasicImgLoader is not generic. It provides one BasicSetupImgLoader<T> for each setup.  T can be different for each setup.

This will enable in the future to mix different types in one dataset. For example, in a multi-angle lightsheet dataset, raw you could have 16bit integer for the raw stacks of each angle, 32bit floating point for the multi-angle fusion and deconvolution result, and maybe 64 bit integers for some label fields that describe segmentation results etc. This could now all be stored in the same dataset.
The introduction of this additional  BasicSetupImgLoader<T> interface level will also make it easy to merge datasets, where you combine in one dataset data from different sources (for example, raw data somewhere on a server, deconvolved data on a different sertver, segmentation result in local files, etc).

Where is the code?

The new API is implemented in the “types” branch of projects
https://github.com/bigdataviewer/spimdata and

In addition, I already fixed the following projects that are using the API:

Everything is on branch “types”, with SNAPSHOT couplings between these projects.
I plan to release it all in one go.

What changed exactly?

Basically, from a ImgLoader user perspective, instead of calling
ViewId view = new ViewId( timepointId, setupId );
imgloader.getImage( view );
you will now call
imgloader.getSetupImgLoader( setupId ).getImage( timepointId );

There is one more change, which is unrelated (but I think this is a good time to put it in, while breaking API anyways).
All  getImage() variants have additional optional parameter ImgLoaderHint... hints.
This is used to pass hints to the ImgLoader implementations about how to best load the data. Currently, the only existing hint is ImgLoaderHints.LOAD_COMPLETELY. This is used in certain places in SPIM_Registration to tell BDV’s hdf5 ImgLoader that it should read the full image completely in one go (because this is faster than using a cached image when we already know that we will need to access every single pixel of the image). Of course, hints are just hints, and most ImgLoaders will just ignore them.

ImgLoaders and SetupImgLoaders have been put into an interface hierarchy:

BasicSetupImgLoader can give a T image for every timepoint.
SetupImgLoader can additionally give a image converted to FloatType for every timepoint, and provide some metadata (this is required for SPIM_Reconstruction).
BasicMultiResolutionSetupImgLoader has multiple resolutions of every T image for every timepoint.
MultiResolutionSetupImgLoader provides both multi-resolution and float-converted data.
ViewerSetupImgLoader is multi-resolution and provides additionally Volatile versions of each image (this is implemented by most bdv cached images)

This hierarchy is paralleled by ImgLoaders:

How can you fix your ImgLoader implementation?

I tried to make that easy. The basic idea is the following:
The old interface ImgLoader<T> (etc) is still available as LegacyImgLoader<T> (etc). You just use your old implementation and change "implements ImgLoader<T>" to "implements LegacyImgLoader<T>”.
There is a LegacyImgLoaderWrapper<T> (etc) class that you can extends to wrap your (old) implementation as a ImgLoader conforming to the new API.
More detailed instructions below.

To test, get the “types” branch of projects
https://github.com/bigdataviewer/spimdata and
Add SNAPSHOT dependencies in your projects pom.xml:
and make the enforcer rules shut up about it:
Now you should get compile errors...
Fix them as indicated above, and detailed in the following.

To adapt an "old" ImgLoader:

Assume for example OldImageLoader

1.) copy OldImageLoader to LegacyOldImageLoader

2.) in LegacyOldImageLoader: change implements ImgLoader<...> to implements LegacyImgLoader<...>

3.) Let OldImageLoader extends LegacyImgLoaderWrapper.
	For each public constructor, just call super( new LegacyOldImageLoader( ... constructor parameters ... )
	Remove the rest of the code.
	This satisfies all requirements of the ImgLoader interface. If you need to expose additional public API from your OldImageLoader, you can forward to the LegacyOldImageLoader which is available as member variable legacyImgLoader.

To adapt an "old" ViewerImgLoader:

For example CatmaidImageLoader

1.) copy CatmaidImageLoader to LegacyCatmaidImageLoader

2.) in LegacyCatmaidImageLoader:

2.1) change extends AbstractViewerImgLoader to extends AbstractLegacyViewerImgLoader:

import bdv.AbstractViewerImgLoader;
public class CatmaidImageLoader extends AbstractViewerImgLoader< ARGBType, VolatileARGBType >

import bdv.spimdata.legacy.AbstractLegacyViewerImgLoader;
public class LegacyCatmaidImageLoader extends AbstractLegacyViewerImgLoader< ARGBType, VolatileARGBType >

2.2) if you use VolatileGlobalCellCache in your ImgLoader:
VolatileGlobalCellCache no longer has generic parameters. The generic parameter moved to the per-image CellCache.
Also VolatileGlobalCellCache is no longer constructed with an CacheArrayLoader. This also moved to the per-image CellCache.
-> Remove generics from VolatileGlobalCellCache
-> Add generic parameter to per-image CellCache
-> remove CacheArrayLoader parameter fron VolatileGlobalCellCache constructor. Instead, store your CacheArrayLoader into a member variable and use it to construct per-image CellCache.

Here are all the lines that needed to be changed in LegacyCatmaidImageLoader:

	private final VolatileGlobalCellCache< VolatileIntArray > cache;
		cache = new VolatileGlobalCellCache< VolatileIntArray >(
			new CatmaidVolatileIntArrayLoader( urlFormat, tileWidth, tileHeight, zScales ), 1, 1, numScales, 10 );
		final CellCache< VolatileIntArray > c = cache.new VolatileCellCache< VolatileIntArray >( view.getTimePointId(), view.getViewSetupId(), level, cacheHints, loader );
	public VolatileGlobalCellCache< VolatileIntArray > getCache()

And here is what they changed to:

	private final VolatileGlobalCellCache cache;

	private final CatmaidVolatileIntArrayLoader loader;
		cache = new VolatileGlobalCellCache( 1, 1, numScales, 10 );
		loader = new CatmaidVolatileIntArrayLoader( urlFormat, tileWidth, tileHeight, zScales );
		final CellCache< VolatileIntArray > c = cache.new VolatileCellCache< VolatileIntArray >( view.getTimePointId(), view.getViewSetupId(), level, cacheHints, loader );
	public VolatileGlobalCellCache getCache()

3.) Let CatmaidImageLoader extend LegacyViewerImgLoaderWrapper< ARGBType, VolatileARGBType, LegacyCatmaidImageLoader >
	For each public constructor, just call super( new LegacyCatmaidImageLoader( ... constructor parameters ... )
	Remove the rest of the code.

	The full CatmaidImageLoader looks like this:

package bdv.img.catmaid;

import net.imglib2.type.numeric.ARGBType;
import net.imglib2.type.volatiles.VolatileARGBType;
import bdv.spimdata.legacy.LegacyViewerImgLoaderWrapper;

public class CatmaidImageLoader extends LegacyViewerImgLoaderWrapper< ARGBType, VolatileARGBType, LegacyCatmaidImageLoader >
	public CatmaidImageLoader(
			final long width,
			final long height,
			final long depth,
			final double zScale,
			final int numScales,
			final String urlFormat,
			final int tileWidth,
			final int tileHeight )
		super( new LegacyCatmaidImageLoader( width, height, depth, zScale, numScales, urlFormat, tileWidth, tileHeight ) );

It would be cool if you could update your ImgLoaders as soon as possible. If there are any problems I’ll be happy to help. If your project is on github, I can also just fix it for you. Just let me know!
I plan to merge the types branches of the above mentioned projects into the respective masters and release artifacts next Monday (5. October), and unless there are objections I would upload to Fiji updater next Friday (9. October).

best regards,

-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://imagej.net/pipermail/imagej-devel/attachments/20151001/5d4debe9/attachment-0001.html>
-------------- next part --------------
A non-text attachment was scrubbed...
Name: setupimgloaders.png
Type: image/png
Size: 18537 bytes
Desc: not available
URL: <http://imagej.net/pipermail/imagej-devel/attachments/20151001/5d4debe9/attachment-0002.png>
-------------- next part --------------
A non-text attachment was scrubbed...
Name: imgloaders.png
Type: image/png
Size: 11683 bytes
Desc: not available
URL: <http://imagej.net/pipermail/imagej-devel/attachments/20151001/5d4debe9/attachment-0003.png>
-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 455 bytes
Desc: Message signed with OpenPGP using GPGMail
URL: <http://imagej.net/pipermail/imagej-devel/attachments/20151001/5d4debe9/attachment-0001.pgp>

More information about the ImageJ-devel mailing list