diff --git a/README.md b/README.md index 2e18718..6bb969f 100644 --- a/README.md +++ b/README.md @@ -1,14 +1,16 @@ -[![Java CI with Maven](https://github.com/GReD-Clermont/omero_macroextensions/actions/workflows/maven.yml/badge.svg)](https://github.com/GReD-Clermont/omero_macroextensions/actions/workflows/maven.yml) +[![Java CI with Maven](https://github.com/GReD-Clermont/omero_macro-extensions/actions/workflows/maven.yml/badge.svg)](https://github.com/GReD-Clermont/omero_macro-extensions/actions/workflows/maven.yml) -# omero_macroextensions +# OMERO Macro Extensions A plugin for ImageJ to provide macro extensions to access OMERO. ## How to install -1. Install the [OMERO.insight plugin for Fiji](https://omero-guides.readthedocs.io/en/latest/fiji/docs/installation.html) (if you haven't already). +1. Install + the [OMERO.insight plugin for Fiji](https://omero-guides.readthedocs.io/en/latest/fiji/docs/installation.html) (if + you haven't already). 2. Download the JAR file for this [library](https://github.com/GReD-Clermont/simple-omero-client/releases/latest/). -3. Download the JAR file ([for this plugin](https://github.com/GReD-Clermont/omero_macroextensions/releases/latest/)). +3. Download the JAR file ([for this plugin](https://github.com/GReD-Clermont/omero_macro-extensions/releases/latest/)). 4. Place these JAR files in your plugins folder. ## How to use @@ -156,7 +158,7 @@ projectId = Ext.createProject(name, description); Datasets can be created with *Ext.createDataset*: ``` -datasetId = Ext.createDataset(projectId, name, description); +datasetId = Ext.createDataset(name, description, projectId); ``` Tags can be created with *Ext.createTag*: @@ -189,14 +191,17 @@ Pixel intensities can be retrieved from images: imageplusID = Ext.getImage(imageIds[0]); ``` -ROIs from OMERO can also be added to the ROI manager (and the current image): +ROIs from OMERO can also be added to the ROI manager (and the current image). ROIs composed of multiple shapes (eg +3D/4D) will share the same values in the "ROI" and "ROI_ID" properties in ImageJ. These can be optionnally changed with +the "property" parameter: local indices will be in "property" while OMERO IDs will be in "property + _ID". +This is achieved through: ``` -nIJROIs = Ext.getROIs(imageIds[0]); +nIJROIs = Ext.getROIs(imageIds[0], property); ``` Conversely, ImageJ ROIs can also be saved to OMERO (the property is used to group ImageJ shapes into a single 3D/4D ROI -on OMERO): +on OMERO, if the string is empty, "ROI" is used): ``` nROIS = Ext.saveROIs(imageId, property); @@ -229,7 +234,7 @@ Ext.deleteFile(fileId); A table can be created/updated using the results with *Ext.addToTable*: ``` -Ext.addToTable(tableName, resultsName, imageId); +Ext.addToTable(tableName, resultsName, imageId, roiProperty); ``` If a column named ROI containing ROI IDs is present, these will be added to the table. Alternatively, if ROIs that were @@ -240,14 +245,12 @@ The table can then be saved to a project/dataset/image through *Ext.saveTable*: ``` Ext.saveTable(tableName, 'dataset', datasetId); - ``` It can then be saved to a tab-separated text file through *Ext.saveTableAsTXT*: ``` Ext.saveTableAsTXT(tableName, pathToTXT); - ``` ### Work as another user (sudo) diff --git a/pom.xml b/pom.xml index 26a7f2d..bb263ec 100644 --- a/pom.xml +++ b/pom.xml @@ -10,12 +10,12 @@ fr.igred - omero_macroextensions + omero_macro-extensions 1.0.1 ImageJ OMERO macro extensions Plugin providing macro extensions for OMERO. - https://github.com/GReD-Clermont/omero_macroextensions + https://github.com/GReD-Clermont/omero_macro-extensions 2021 @@ -63,24 +63,24 @@ - scm:git:git://github.com/GReD-Clermont/omero_macroextensions - scm:git:git@github.com:GReD-Clermont/omero_macroextensions + scm:git:git://github.com/GReD-Clermont/omero_macro-extensions + scm:git:git@github.com:GReD-Clermont/omero_macro-extensions HEAD - https://github.com/GReD-Clermont/omero_macroextensions + https://github.com/GReD-Clermont/omero_macro-extensions GitHub Issues - https://github.com/GReD-Clermont/omero_macroextensions/issues + https://github.com/GReD-Clermont/omero_macro-extensions/issues GitHub Actions - https://github.com/GReD-Clermont/omero_macroextensions/actions + https://github.com/GReD-Clermont/omero_macro-extensions/actions github GitHub GReD-Clermont Apache Maven Packages - https://maven.pkg.github.com/GReD-Clermont/omero_macroextensions + https://maven.pkg.github.com/GReD-Clermont/omero_macro-extensions @@ -91,7 +91,7 @@ gpl_v2 GReD com.esotericsoftware.kryo.*,com.esotericsoftware.minlog.*,com.esotericsoftware.reflectasm.* - 5.8.2 + 5.8.3 @@ -122,7 +122,6 @@ net.imagej ij - 1.53c provided diff --git a/src/main/java/fr/igred/ij/plugin/OMEROExtension.java b/src/main/java/fr/igred/ij/plugin/OMEROMacroExtension.java similarity index 93% rename from src/main/java/fr/igred/ij/plugin/OMEROExtension.java rename to src/main/java/fr/igred/ij/plugin/OMEROMacroExtension.java index e40f64b..e49dafc 100644 --- a/src/main/java/fr/igred/ij/plugin/OMEROExtension.java +++ b/src/main/java/fr/igred/ij/plugin/OMEROMacroExtension.java @@ -52,7 +52,7 @@ import static ij.macro.ExtensionDescriptor.newDescriptor; -public class OMEROExtension implements PlugIn, MacroExtension { +public class OMEROMacroExtension implements PlugIn, MacroExtension { private static final String PROJECT = "project"; private static final String DATASET = "dataset"; @@ -65,11 +65,12 @@ public class OMEROExtension implements PlugIn, MacroExtension { newDescriptor("switchGroup", this, ARG_NUMBER), newDescriptor("list", this, ARG_STRING, ARG_STRING + ARG_OPTIONAL, ARG_NUMBER + ARG_OPTIONAL), newDescriptor("createDataset", this, ARG_STRING, ARG_STRING, ARG_NUMBER + ARG_OPTIONAL), - newDescriptor("createProject", this, ARG_NUMBER, ARG_STRING, ARG_STRING), + newDescriptor("createProject", this, ARG_STRING, ARG_STRING), newDescriptor("createTag", this, ARG_STRING, ARG_STRING), newDescriptor("link", this, ARG_STRING, ARG_NUMBER, ARG_STRING, ARG_NUMBER), newDescriptor("addFile", this, ARG_STRING, ARG_NUMBER, ARG_STRING), - newDescriptor("addToTable", this, ARG_STRING, ARG_STRING + ARG_OPTIONAL, ARG_NUMBER + ARG_OPTIONAL), + newDescriptor("addToTable", this, ARG_STRING, + ARG_STRING + ARG_OPTIONAL, ARG_NUMBER + ARG_OPTIONAL, ARG_STRING + ARG_OPTIONAL), newDescriptor("saveTable", this, ARG_STRING, ARG_STRING, ARG_NUMBER), newDescriptor("saveTableAsTXT", this, ARG_STRING, ARG_STRING), newDescriptor("clearTable", this, ARG_STRING), @@ -78,8 +79,8 @@ public class OMEROExtension implements PlugIn, MacroExtension { newDescriptor("delete", this, ARG_STRING, ARG_NUMBER), newDescriptor("getName", this, ARG_STRING, ARG_NUMBER), newDescriptor("getImage", this, ARG_NUMBER), - newDescriptor("getROIs", this, ARG_NUMBER), - newDescriptor("saveROIs", this, ARG_NUMBER, ARG_STRING), + newDescriptor("getROIs", this, ARG_NUMBER, ARG_STRING + ARG_OPTIONAL), + newDescriptor("saveROIs", this, ARG_NUMBER, ARG_STRING + ARG_OPTIONAL), newDescriptor("sudo", this, ARG_STRING), newDescriptor("endSudo", this), newDescriptor("disconnect", this), @@ -109,6 +110,18 @@ private static String singularType(String type) { } + private static Long doubleToLong(Double d) { + if (d != null) return d.longValue(); + else return null; + } + + + private static ResultsTable getTable(String resultsName) { + if (resultsName == null) return ResultsTable.getResultsTable(); + else return ResultsTable.getResultsTable(resultsName); + } + + private GenericObjectWrapper getObject(String type, long id) { String singularType = singularType(type); @@ -144,7 +157,7 @@ private GenericRepositoryObjectWrapper getRepositoryObject(String type, long default: IJ.error(INVALID + ": " + type + "."); } - } catch (ServiceException | AccessException e) { + } catch (ServiceException | AccessException | ExecutionException e) { IJ.error("Could not retrieve object: " + e.getMessage()); } return object; @@ -156,7 +169,7 @@ public boolean connect(String host, int port, String username, String password) try { client.connect(host, port, username, password.toCharArray()); connected = true; - } catch (ServiceException | ExecutionException e) { + } catch (ServiceException e) { IJ.error("Could not connect: " + e.getMessage()); } return connected; @@ -167,7 +180,7 @@ public String downloadImage(long imageId, String path) { List files = new ArrayList<>(); try { files = client.getImage(imageId).download(client, path); - } catch (ServiceException | AccessException | OMEROServerError e) { + } catch (ServiceException | AccessException | OMEROServerError | ExecutionException e) { IJ.error("Could not download image: " + e.getMessage()); } return files.stream().map(File::toString).collect(Collectors.joining(",")); @@ -227,23 +240,16 @@ public void deleteFile(long fileId) { } - public void addToTable(String tableName, String resultsName, Long imageId) { - ResultsTable rt; - if (tableName == null) rt = ResultsTable.getResultsTable(); - else rt = ResultsTable.getResultsTable(resultsName); - - RoiManager rm = RoiManager.getRoiManager(); - List ijRois = Arrays.asList(rm.getRoisAsArray()); - + public void addToTable(String tableName, ResultsTable results, Long imageId, List ijRois, String property) { TableWrapper table = tables.get(tableName); try { if (table == null) { - table = new TableWrapper(client, rt, imageId, ijRois, ROIWrapper.IJ_PROPERTY); + table = new TableWrapper(client, results, imageId, ijRois, property); table.setName(tableName); tables.put(tableName, table); } else { - table.addRows(client, rt, imageId, ijRois, ROIWrapper.IJ_PROPERTY); + table.addRows(client, results, imageId, ijRois, property); } } catch (ExecutionException | ServiceException | AccessException e) { IJ.error("Could not add results to table: " + e.getMessage()); @@ -384,7 +390,7 @@ public String list(String type) { default: IJ.error(INVALID + ": " + type + ". Possible values are: projects, datasets, images or tags."); } - } catch (ServiceException | AccessException | OMEROServerError e) { + } catch (ServiceException | AccessException | OMEROServerError | ExecutionException e) { IJ.error("Could not retrieve " + type + ": " + e.getMessage()); } return results; @@ -416,7 +422,7 @@ public String list(String type, String name) { default: IJ.error(INVALID + ": " + type + ". Possible values are: projects, datasets, images or tags."); } - } catch (ServiceException | AccessException | OMEROServerError e) { + } catch (ServiceException | AccessException | OMEROServerError | ExecutionException e) { IJ.error("Could not retrieve project name: " + e.getMessage()); } return results; @@ -585,7 +591,7 @@ public ImagePlus getImage(long id) { } - public int getROIs(long id) { + public int getROIs(long id, String property) { List rois = new ArrayList<>(); try { ImageWrapper image = client.getImage(id); @@ -596,7 +602,7 @@ public int getROIs(long id) { ImagePlus imp = IJ.getImage(); - List ijRois = ROIWrapper.toImageJ(rois); + List ijRois = ROIWrapper.toImageJ(rois, property); RoiManager rm = RoiManager.getInstance(); if (rm == null) rm = RoiManager.getRoiManager(); @@ -631,7 +637,7 @@ public int saveROIs(long id, String property) { } result = rois.size(); rm.reset(); - this.getROIs(id); + this.getROIs(id, property); } catch (ServiceException | AccessException | ExecutionException e) { IJ.error("Could not save ROIs to image: " + e.getMessage()); } @@ -707,8 +713,7 @@ public String handleExtension(String name, Object[] args) { break; case "createDataset": - Long projectId = null; - if (args[2] != null) projectId = ((Double) args[2]).longValue(); + Long projectId = doubleToLong((Double) args[2]); id = createDataset((String) args[0], (String) args[1], projectId); results = String.valueOf(id); break; @@ -726,13 +731,20 @@ public String handleExtension(String name, Object[] args) { case "addToTable": tableName = (String) args[0]; String resultsName = (String) args[1]; - Long imageId = null; - if (args[2] != null) imageId = ((Double) args[2]).longValue(); - addToTable(tableName, resultsName, imageId); + Long imageId = doubleToLong((Double) args[2]); + String property = (String) args[3]; + + ResultsTable rt = getTable(resultsName); + RoiManager rm = RoiManager.getRoiManager(); + List ijRois = Arrays.asList(rm.getRoisAsArray()); + + addToTable(tableName, rt, imageId, ijRois, property); break; case "saveTableAsTXT": - saveTableAsTXT((String) args[0], (String) args[1]); + tableName = (String) args[0]; + path = (String) args[1]; + saveTableAsTXT(tableName, path); break; case "saveTable": @@ -791,13 +803,15 @@ public String handleExtension(String name, Object[] args) { break; case "getROIs": - int nIJRois = getROIs(((Double) args[0]).longValue()); + id = ((Double) args[0]).longValue(); + property = (String) args[1]; + int nIJRois = getROIs(id, property); results = String.valueOf(nIJRois); break; case "saveROIs": id = ((Double) args[0]).longValue(); - String property = ((String) args[1]); + property = (String) args[1]; int nROIs = saveROIs(id, property); results = String.valueOf(nROIs); break; diff --git a/src/main/resources/omero.extensions.plugins.config b/src/main/resources/omero.extensions.plugins.config index 64c7984..0557728 100644 --- a/src/main/resources/omero.extensions.plugins.config +++ b/src/main/resources/omero.extensions.plugins.config @@ -1 +1 @@ -Plugins>OMERO, "OMERO Extensions", fr.igred.ij.plugin.OMEROExtension("") \ No newline at end of file +Plugins>OMERO, "OMERO Extensions", fr.igred.ij.plugin.OMEROMacroExtension("") \ No newline at end of file diff --git a/src/test/java/fr/igred/ij/plugin/OMEROExtensionTest.java b/src/test/java/fr/igred/ij/plugin/OMEROExtensionTest.java index 91cc75a..844e9fe 100644 --- a/src/test/java/fr/igred/ij/plugin/OMEROExtensionTest.java +++ b/src/test/java/fr/igred/ij/plugin/OMEROExtensionTest.java @@ -22,7 +22,6 @@ import ij.measure.ResultsTable; import org.junit.jupiter.api.AfterEach; import org.junit.jupiter.api.BeforeEach; -import org.junit.jupiter.api.Disabled; import org.junit.jupiter.api.Test; import org.junit.jupiter.params.ParameterizedTest; import org.junit.jupiter.params.provider.CsvSource; @@ -32,6 +31,7 @@ import java.io.IOException; import java.io.PrintStream; import java.nio.charset.StandardCharsets; +import java.util.ArrayList; import java.util.Arrays; import java.util.List; import java.util.Random; @@ -41,12 +41,12 @@ class OMEROExtensionTest { - private OMEROExtension ext; + private OMEROMacroExtension ext; @BeforeEach public void setUp() { - ext = new OMEROExtension(); + ext = new OMEROMacroExtension(); Object[] args = {"omero", 4064d, "testUser", "password"}; ext.handleExtension("connectToOMERO", args); } @@ -253,25 +253,32 @@ void testSudo() { @Test - @Disabled("Requires X11") void testTable() throws Exception { - ResultsTable rt = new ResultsTable(); - rt.incrementCounter(); - rt.setLabel("test", 0); - rt.setValue("Size", 0, 25.0); + ResultsTable rt1 = new ResultsTable(); + rt1.incrementCounter(); + rt1.setLabel("test", 0); + rt1.setValue("Size", 0, 25.0); + rt1.show("test"); - Object[] args = {"test_table", "test", 1.0d}; - ext.handleExtension("addToTable", args); + ResultsTable rt2 = new ResultsTable(); + rt2.incrementCounter(); + rt2.setLabel("test", 0); + rt2.setValue("Size", 0, 50.0); + + ext.addToTable("test_table", rt1, 1L, new ArrayList<>(0), null); + ext.addToTable("test_table", rt2, 1L, new ArrayList<>(0), null); Object[] args2 = {"test_table", "dataset", 1.0d}; ext.handleExtension("saveTable", args2); Client client = new Client(); client.connect("omero", 4064, "testUser", "password".toCharArray()); - List tables = client.getImage(1L).getTables(client); + List tables = client.getDataset(1L).getTables(client); client.disconnect(); assertEquals(1, tables.size()); - assertEquals(1, tables.get(0).getRowCount()); + assertEquals(2, tables.get(0).getRowCount()); + assertEquals(25.0, tables.get(0).getData(0, 2)); + assertEquals(50.0, tables.get(0).getData(1, 2)); } }