Skip to content
Draft
66 changes: 66 additions & 0 deletions src/test/fiji/macros/jython/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
remarks:


# Use `Dataset` over `ImagePlus` in scripts

This refers to the situation when a Jython script has (among others) this input:

```python
#@ ImagePlus imp

def somework_over_imageplus(imp):
pass
```

Such script will also work with pure `Datasets`, in which case
Fiji (most likely the ImageJ2-flavour of it) will internally prepare
a new `ImagePlus` that is wrapped around the `Dataset`, and *increases its
internal usage counter*. In fact, `ImageJFunctions.wrap()` does similar thing:
It also constructs a new `ImagePlus` that's around a virtual stack that's
around the given Imglib2's `img`. Coming back to the script example, the
auto-conversion happens only once, that said, executing the script again
will re-use the previously constructed `ImagePlus`.

If ever a "system" auto-conversion of a `Dataset` to `ImagePlus` has taken
place, the created `ImagePlus` *blocks* releasing/freeing of the `Dataset`,
and one has to call `ImagePlus.close()` or similar function to effectively
loose this `ImagePlus` that in turn will unlock (*decrease the internal
usage counter*) the `Dataset`. **However**, if `ImagePlus` is created from
a `Dataset` (e.g., see below), this new `ImagePlus` is not blocking anything.

Take home message for script programmers is to design their Zarr-expecting
scripts to consume

```python
#@ Dataset dimg
```

and possibly build `ImagePlus` (if they really need it) in their script.
They could explicitly `ImagePlus.close()` before the end of their script,
but it doesn't seem to be any important.

## Example

```python
#@ Dataset dimg

from net.imglib2.img.display.imagej import ImageJFunctions

def get_imageplus(dataset):
img = dataset.getImgPlus()
return ImageJFunctions.wrap(img, img.getName())


def somework_over_imageplus(imp):
# 2D Python-native array mapped over pixels from the current xy plane
pixels = imp.getProcessor().getPixels()
pass


imp = get_imageplus(dimg)
somework_over_imageplus(imp)

# optional clean up:
imp.close()
```

43 changes: 43 additions & 0 deletions src/test/fiji/macros/jython/create_Dataset_and_show.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
#@ DatasetService dsService
#@ UIService ui
#@ string image_label (label="Title of the created image:", value="ImgPlus turned into Dataset #1")
#@ boolean show_in_IJ (label="Display in ImageJ window:")
#@ boolean show_in_BDV (label="Display in BigDataViewer:")

from net.imagej import ImgPlus
from net.imglib2.img.planar import PlanarImgs
from bdv.util import BdvFunctions

# ------- standard creation of `img` and wrapping it "till it becomes" a `Dataset` -------
img = PlanarImgs.bytes(303, 302)
imp = ImgPlus(img, image_label)
ds = dsService.create(imp)

print("Created img of id: "+str(id(img)))
print("Created ImgPlus of id: "+str(id(imp)))
print("Created dataset of id: "+str(id(ds)))


# ------- this is a Jython version of attaching a listener to "onWindowClose" event in BDV -------
from java.awt.event import WindowAdapter

def register_datasetDecrement_onBdvCloseWindow(bdv_handle, dataset):
viewer_panel = bdv_handle.getViewerPanel()
win = viewer_panel.getRootPane().getParent()

class OnClose(WindowAdapter):
def windowClosed(self, event):
print("BDV window closed, decrementing id: "+str(id(dataset)))
dataset.decrementReferences()

win.addWindowListener(OnClose())


# ------- finally show the `Dataset` either way(s) -------
if show_in_IJ:
ui.show(ds)

if show_in_BDV:
ds.incrementReferences()
bdv_stack_source = BdvFunctions.show(ds.getImgPlus(), image_label)
register_datasetDecrement_onBdvCloseWindow(bdv_stack_source.getBdvHandle(), ds)
8 changes: 8 additions & 0 deletions src/test/fiji/macros/jython/create_ImagePlus_and_show.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
from ij.process import ByteProcessor
from ij import ImagePlus

p = ByteProcessor(303, 302)
imp = ImagePlus("pure ImagePlus", p)
imp.show()

print("Created image of id: "+str(id(imp)))
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
from net.imglib2.img.planar import PlanarImgs
from net.imglib2.img.display.imagej import ImageJFunctions

img = PlanarImgs.bytes(303, 302)
ImageJFunctions.show(img, "img via ImageJFunctions")
# NB: ImageJFunctions internally create new ImagePlus around VirtualStack that's wrapping around this 'img'

print("Created image of id: "+str(id(img)))
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
#@ UIService ui

from net.imglib2.img.planar import PlanarImgs

img = PlanarImgs.bytes(303, 302)
ui.show("img via UIService", img)

print("Created image of id: "+str(id(img)))
10 changes: 10 additions & 0 deletions src/test/fiji/macros/jython/list_known_datasets_and_pyramidals.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
# @ DatasetService ds
# @ PyramidalService ps

print("----")
for dimg in ds.getDatasets():
print("image '" + dimg.getImgPlus().getName() + "' (id: " + str(id(dimg)) + \
") of width x height: " + str(dimg.getWidth()) + 'x' + str(dimg.getHeight()))
for pyramidal in ps.getPyramidals():
print("pyramidal '" + pyramidal.getPyramidName() + "' (id: " + str(id(pyramidal)) + ")")
print("----")
6 changes: 6 additions & 0 deletions src/test/fiji/macros/jython/list_known_image_windows.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
from ij import WindowManager

print("----")
for s in WindowManager.getImageTitles():
print(s)
print("----")
3 changes: 3 additions & 0 deletions src/test/fiji/macros/jython/test_ImagePlus_presence.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
#@ ImagePlus imp

print("image '"+imp.getTitle()+"' (id: "+str(id(imp))+") of width x height: "+str(imp.getWidth())+'x'+str(imp.getHeight()))
4 changes: 4 additions & 0 deletions src/test/fiji/macros/jython/test_dataset_presence.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
#@ Dataset dimg

print("image '"+dimg.getImgPlus().getName()+"' (id: "+str(id(dimg))+\
") of width x height: "+str(dimg.getWidth())+'x'+str(dimg.getHeight()))
Loading