From 9f572c6d6328687d5e66c8edde3bdb2cd6493193 Mon Sep 17 00:00:00 2001 From: Pierre Pouchin Date: Tue, 29 Mar 2022 10:52:45 +0200 Subject: [PATCH] Print list of available functions (#12) * Print functions list, as requested in #11 --- .../igred/ij/plugin/OMEROMacroExtension.java | 26 ++- src/main/resources/helper.md | 148 ++++++++++++++++++ .../ij/plugin/OMEROExtensionErrorTest.java | 22 ++- .../igred/ij/plugin/OMEROExtensionTest.java | 4 - 4 files changed, 187 insertions(+), 13 deletions(-) create mode 100644 src/main/resources/helper.md diff --git a/src/main/java/fr/igred/ij/plugin/OMEROMacroExtension.java b/src/main/java/fr/igred/ij/plugin/OMEROMacroExtension.java index e551fde..baa9143 100644 --- a/src/main/java/fr/igred/ij/plugin/OMEROMacroExtension.java +++ b/src/main/java/fr/igred/ij/plugin/OMEROMacroExtension.java @@ -40,12 +40,13 @@ import ij.plugin.PlugIn; import ij.plugin.frame.RoiManager; +import java.io.ByteArrayOutputStream; import java.io.File; import java.io.IOException; +import java.io.InputStream; import java.nio.file.Files; import java.time.ZonedDateTime; import java.time.format.DateTimeFormatter; - import java.util.ArrayList; import java.util.Arrays; import java.util.Collection; @@ -979,8 +980,8 @@ public int removeROIs(long id) { int removed = 0; try { - ImageWrapper image = client.getImage(id); - List rois = image.getROIs(client); + ImageWrapper image = client.getImage(id); + List rois = image.getROIs(client); for (ROIWrapper roi : rois) { client.delete(roi); removed++; @@ -1007,8 +1008,23 @@ public void disconnect() { @Override public void run(String arg) { if (!IJ.macroRunning()) { - IJ.error("Cannot install extensions from outside a macro!"); - //TODO print API + IJ.showMessage("OMERO extensions for ImageJ", + String.format("The macro extensions are designed to be used within a macro.%n" + + "Instructions on doing so will be printed to the Log window.")); + try (InputStream is = this.getClass().getResourceAsStream("/helper.md")) { + if(is != null) { + ByteArrayOutputStream result = new ByteArrayOutputStream(); + byte[] buffer = new byte[2 ^ 10]; + int length = is.read(buffer); + while (length != -1) { + result.write(buffer, 0, length); + length = is.read(buffer); + } + IJ.log(result.toString("UTF-8")); + } + } catch (IOException e) { + IJ.error("Could not retrieve commands."); + } return; } Functions.registerExtensions(this); diff --git a/src/main/resources/helper.md b/src/main/resources/helper.md new file mode 100644 index 0000000..fdebdbf --- /dev/null +++ b/src/main/resources/helper.md @@ -0,0 +1,148 @@ +To gain access to more advanced features of OMERO +from within a macro, put the following line at the +beginning of your macro: + +run("OMERO Extensions"); + +This will enable the following macro functions: + + +### Handles connection (should be used first/last) ### + +Ext.connectToOMERO(host, port, username, password) +> Connects to the given OMERO `host` (and `port`) +> using the provided `username` and `password`. + +Ext.disconnect() +> Disconnects from the server. + + +### Changes the context for other commands ### + +Ext.switchGroup(groupId) +> Switches to the given group on OMERO. + +Ext.listForUser(username) +> Filters listings to only include data from the given user. + +Ext.sudo(username) +> Runs subsequent commands as the specified user, +> if the logged-in user has sudo rights. + +Ext.endSudo() +> Switches back to the logged-in user. + + +### Retrieves data from OMERO ### + +Ext.list(type) +> Gets the IDs for objects of the given `type`, +> separated by commas. + +Ext.list(type, name); +> Gets the IDs for objects with the given `type` and `name`, +> separated by commas. + +Ext.list(type, parentType, parentId) +> Gets the IDs for objects of the given `type` +> inside a parent container with type `parentType` and ID `parentId`, +> separated by commas. + +Ext.getName(type, id) +> Gets the name of the specified object, given its `type` and `id`. + +Ext.getImage(id) +> Opens the image with the given `id`. +> Returns the image ID in ImageJ. + +Ext.getROIs(imageId, toOverlay, property) +> Retrieves the ROIs for the image with the given `imageId`. +> These are added to the ROI manager by default. +> +> If `toOverlay` (optional) is true, +> they are added to the overlay instead. +> +> Moreover, shapes from 3D/4D ROIs will share the same values +> in the "ROI" and "ROI_ID" properties. +> The properties names can be optionally changed: +> `property` will store local indices, +> while `property + "_ID"` will store OMERO IDs. +> +> Returns the number of ROIs in ImageJ. + + +### Saves data ### + +Ext.createTag(name, description) +> Creates a new tag with the given `name` and `description`. +> Returns the new tag ID. + +Ext.createProject(name, description) +> Creates a new project with the given `name` and `description`. +> Returns the new project ID. + +Ext.createDataset(name, description, projectId) +> Creates a new dataset with the given `name` and `description`, +> inside the project with the specified `projectId`. +> Returns the new dataset ID. + +Ext.importImage(datasetId) +> Saves the current image to the dataset with the given `datasetId`. +> Returns the new image ID. + +Ext.saveROIs(imageId, property) +> Saves ImageJ ROIs to the image with the given `imageId` on OMERO. +> The (optional) `property` is used to group ImageJ shapes +> into a single 3D/4D ROI in OMERO. +> The default value for this (if empty or absent) is "ROI". +> +> Returns the number of 3D/4D ROIs saved to OMERO. + +Ext.addFile(type, id, path) +> Attach a file on the given `path` +> to the object with the given `type` and `id` on OMERO. +> Returns the new file ID. + +Ext.link(type1, id1, type2, id2) +> Links two objects together, using their types and IDs. +> The order does not matter. +> Possible types are: +> * Project and Dataset +> * Dataset and Image +> * Tag and Project, Dataset or Image + + +### Removes data on OMERO ### + +Ext.unlink(type1, id1, type2, id2) +> Unlinks two objects, using their types and IDs (see `link`). + +Ext.delete(type, id) +> Deletes the object with the given `type` and `id` from OMERO. + +Ext.deleteFile(id) +> Delete the attached file with the given `id` on OMERO. + + +### Table functions ### + +Ext.addToTable(tableName, resultsName, imageId, roiProperty) +> Creates or updates a local table using ImageJ results, where: +> * `tableName` is the name of the table +> * `resultsName` (optional) is the IJ results name +> * `imageId` (optional) is the image ID on OMERO +> * `roiProperty` (optional) is the ROI property used +> for grouping 2D shapes in 3D/4D ROIs. +> +> If ROIs that were saved to OMERO are in the ROI Manager +> and if their name appears in the labels +> or is in a column named "ROI", they will be added too. + +Ext.saveTable(tableName, type, id) +> Saves the table with the name `tableName` to OMERO, +> and attaches it to the object with the given `type` and `id`. + +Ext.saveTableAsFile(tableName, path, delimiter) +> Saves the table to a delimited text file locally (`path`). +> The default separator is ',' but can be changed with +> the optional `delimiter`. diff --git a/src/test/java/fr/igred/ij/plugin/OMEROExtensionErrorTest.java b/src/test/java/fr/igred/ij/plugin/OMEROExtensionErrorTest.java index f11effe..6e9a248 100644 --- a/src/test/java/fr/igred/ij/plugin/OMEROExtensionErrorTest.java +++ b/src/test/java/fr/igred/ij/plugin/OMEROExtensionErrorTest.java @@ -27,6 +27,7 @@ import java.io.ByteArrayOutputStream; import java.io.File; import java.io.IOException; +import java.io.InputStream; import java.io.PrintStream; import java.nio.file.Files; @@ -68,10 +69,23 @@ public void tearDown() { @Test - void testRun() { + void testRun() throws IOException { ext.run(""); - String expected = "Cannot install extensions from outside a macro!"; - assertEquals(expected, outContent.toString().trim()); + String expected = String.format("The macro extensions are designed to be used within a macro.%n" + + "Instructions on doing so will be printed to the Log window.%n"); + try (InputStream is = ext.getClass().getResourceAsStream("/helper.md")) { + if (is != null) { + ByteArrayOutputStream result = new ByteArrayOutputStream(); + byte[] buffer = new byte[2 ^ 10]; + int length = is.read(buffer); + while (length != -1) { + result.write(buffer, 0, length); + length = is.read(buffer); + } + expected += result.toString("UTF-8"); + } + } + assertEquals(expected.trim(), outContent.toString().trim()); } @@ -158,7 +172,7 @@ void testEndSudoError() { @Test void testListInvalidArgs() { final double datasetId = 2; - Object[] args = {"dataset", null, datasetId}; + Object[] args = {"dataset", null, datasetId}; ext.handleExtension("list", args); String expected = "Second argument should not be null."; assertEquals(expected, outContent.toString().trim()); diff --git a/src/test/java/fr/igred/ij/plugin/OMEROExtensionTest.java b/src/test/java/fr/igred/ij/plugin/OMEROExtensionTest.java index c4d3c77..2bae1f8 100644 --- a/src/test/java/fr/igred/ij/plugin/OMEROExtensionTest.java +++ b/src/test/java/fr/igred/ij/plugin/OMEROExtensionTest.java @@ -18,9 +18,6 @@ import fr.igred.omero.Client; import fr.igred.omero.annotations.TableWrapper; -import fr.igred.omero.exception.AccessException; -import fr.igred.omero.exception.OMEROServerError; -import fr.igred.omero.exception.ServiceException; import ij.ImagePlus; import ij.gui.Overlay; import ij.gui.Roi; @@ -42,7 +39,6 @@ import java.util.ArrayList; import java.util.Arrays; import java.util.List; -import java.util.concurrent.ExecutionException; import java.util.stream.Collectors; import static org.junit.jupiter.api.Assertions.assertEquals;