diff --git a/src/test/fiji/macros/jython/README.md b/src/test/fiji/macros/jython/README.md new file mode 100644 index 00000000..bbabbd94 --- /dev/null +++ b/src/test/fiji/macros/jython/README.md @@ -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() +``` + diff --git a/src/test/fiji/macros/jython/create_Dataset_and_show.py b/src/test/fiji/macros/jython/create_Dataset_and_show.py new file mode 100644 index 00000000..2f1d5380 --- /dev/null +++ b/src/test/fiji/macros/jython/create_Dataset_and_show.py @@ -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) diff --git a/src/test/fiji/macros/jython/create_ImagePlus_and_show.py b/src/test/fiji/macros/jython/create_ImagePlus_and_show.py new file mode 100644 index 00000000..c8b4189b --- /dev/null +++ b/src/test/fiji/macros/jython/create_ImagePlus_and_show.py @@ -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))) \ No newline at end of file diff --git a/src/test/fiji/macros/jython/create_img_and_show_via_ImageJFunctions.py b/src/test/fiji/macros/jython/create_img_and_show_via_ImageJFunctions.py new file mode 100644 index 00000000..19e9bfc9 --- /dev/null +++ b/src/test/fiji/macros/jython/create_img_and_show_via_ImageJFunctions.py @@ -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))) \ No newline at end of file diff --git a/src/test/fiji/macros/jython/create_img_and_show_via_UIService.py b/src/test/fiji/macros/jython/create_img_and_show_via_UIService.py new file mode 100644 index 00000000..2a16d142 --- /dev/null +++ b/src/test/fiji/macros/jython/create_img_and_show_via_UIService.py @@ -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))) \ No newline at end of file diff --git a/src/test/fiji/macros/jython/list_known_datasets_and_pyramidals.py b/src/test/fiji/macros/jython/list_known_datasets_and_pyramidals.py new file mode 100644 index 00000000..f4aaa9db --- /dev/null +++ b/src/test/fiji/macros/jython/list_known_datasets_and_pyramidals.py @@ -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("----") diff --git a/src/test/fiji/macros/jython/list_known_image_windows.py b/src/test/fiji/macros/jython/list_known_image_windows.py new file mode 100644 index 00000000..325b0468 --- /dev/null +++ b/src/test/fiji/macros/jython/list_known_image_windows.py @@ -0,0 +1,6 @@ +from ij import WindowManager + +print("----") +for s in WindowManager.getImageTitles(): + print(s) +print("----") \ No newline at end of file diff --git a/src/test/fiji/macros/jython/test_ImagePlus_presence.py b/src/test/fiji/macros/jython/test_ImagePlus_presence.py new file mode 100644 index 00000000..6f8b79b9 --- /dev/null +++ b/src/test/fiji/macros/jython/test_ImagePlus_presence.py @@ -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())) \ No newline at end of file diff --git a/src/test/fiji/macros/jython/test_dataset_presence.py b/src/test/fiji/macros/jython/test_dataset_presence.py new file mode 100644 index 00000000..1f7bee4b --- /dev/null +++ b/src/test/fiji/macros/jython/test_dataset_presence.py @@ -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())) \ No newline at end of file