From 6aa8dda55ce312330e3307849815d9b16736c360 Mon Sep 17 00:00:00 2001 From: Uwe Schmidt Date: Wed, 1 Apr 2020 23:06:36 +0200 Subject: [PATCH 1/5] Add 'CommandFromMacro' to call any Command from an ImageJ1 macro Also add custrom macro recorder (thanks to @haesleinhuepf) to take advantage of 'CommandFromMacro' --- pom.xml | 12 ++ .../java/de/csbdresden/CommandFromMacro.java | 203 ++++++++++++++++++ .../de/csbdresden/stardist/StarDist2D.java | 15 +- .../csbdresden/stardist/StarDist2DBase.java | 35 ++- .../de/csbdresden/stardist/StarDist2DNMS.java | 4 + 5 files changed, 264 insertions(+), 5 deletions(-) create mode 100644 src/main/java/de/csbdresden/CommandFromMacro.java diff --git a/pom.xml b/pom.xml index dd24c93..550cad5 100644 --- a/pom.xml +++ b/pom.xml @@ -134,5 +134,17 @@ csbdeep 0.3.5-SNAPSHOT + + com.google.code.gson + gson + + + org.apache.commons + commons-lang3 + + + org.apache.commons + commons-text + diff --git a/src/main/java/de/csbdresden/CommandFromMacro.java b/src/main/java/de/csbdresden/CommandFromMacro.java new file mode 100644 index 0000000..3fd0e63 --- /dev/null +++ b/src/main/java/de/csbdresden/CommandFromMacro.java @@ -0,0 +1,203 @@ +package de.csbdresden; + +import java.io.File; +import java.lang.reflect.Field; +import java.lang.reflect.InvocationTargetException; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.LinkedHashMap; +import java.util.List; +import java.util.Map; +import java.util.concurrent.ExecutionException; + +import org.apache.commons.lang3.ClassUtils; +import org.apache.commons.text.StringEscapeUtils; +import org.scijava.ItemVisibility; +import org.scijava.Named; +import org.scijava.command.Command; +import org.scijava.command.CommandInfo; +import org.scijava.command.CommandModule; +import org.scijava.command.CommandService; +import org.scijava.log.LogService; +import org.scijava.module.ModuleItem; +import org.scijava.plugin.Parameter; +import org.scijava.plugin.Plugin; +import org.scijava.service.Service; +import org.scijava.ui.UIService; + +import com.google.gson.Gson; + +import de.csbdresden.stardist.StarDist2D; +import ij.IJ; +import ij.ImagePlus; +import ij.WindowManager; +import net.imagej.Dataset; +import net.imagej.ImageJ; +import net.imglib2.RandomAccessibleInterval; + + +@Plugin(type = Command.class, label = "CommandFromMacro", menuPath = "Plugins > StarDist > Other > CommandFromMacro") +public class CommandFromMacro implements Command { + + private static final List SKIP_VISIBILITY = Arrays.asList(ItemVisibility.MESSAGE, ItemVisibility.INVISIBLE); + + @Parameter + private String command; + + @Parameter + private boolean process; + + @Parameter + private String args; + + // --------- + + @Parameter + private UIService ui; + + @Parameter + private CommandService cmd; + + @Parameter + private LogService log; + + // --------- + + @Override + public void run() { + + final CommandInfo info = cmd.getCommand(command); + if (info == null) { + log.warn(String.format("Command \"%s\" not found.", command)); + return; + } + + final Map params = new LinkedHashMap<>(); + final List outputs = new ArrayList<>(); + + Map argsMap = new Gson().fromJson("{"+args+"}", Map.class); + // System.out.println(argsMap); + + for (Object keyO : argsMap.keySet()) { + final String key = String.valueOf(keyO); + final String value = String.valueOf(argsMap.get(keyO)); + ModuleItem item = null; + + item = info.getInput(key); + if (item != null) { + Class clazz = item.getType(); + if (clazz.isPrimitive()) + clazz = ClassUtils.primitiveToWrapper(clazz); + params.put(key, toParameter(value, clazz)); + } else { + item = info.getOutput(key); + if (item != null) { + outputs.add(key); + } else { + log.warn(String.format("Ignoring argument \"%s\" since neither an input or output of this command.", key)); + } + } + } + + try { + final CommandModule result = cmd.run(command, process, params).get(); + for (String name : outputs) { + final Object output = result.getOutput(name); + if (output != null) ui.show(output); + } + } catch (InterruptedException | ExecutionException e) { + e.printStackTrace(); + } + } + + + private Object toParameter(final String value, final Class clazz) { + // some special classes (TODO: incomplete) + if (clazz == String.class) + return value; + if (clazz == File.class) + return new File(value); + // all typical number types and boolean are covered by this + if (clazz.getName().startsWith("java.lang.")) { + try { + return clazz.getDeclaredMethod("valueOf", String.class).invoke(null, value); + } catch (NoSuchMethodException | SecurityException | IllegalAccessException | IllegalArgumentException | InvocationTargetException e) { + e.printStackTrace(); + } + } + // ImagePlus and typical imagej2 image types (all that implement RAI) + if (clazz == ImagePlus.class || RandomAccessibleInterval.class.isAssignableFrom(clazz)) { + final ImagePlus imp = WindowManager.getImage(value); + if (imp == null) + log.error(String.format("Could not find input image with name/title \"%s\".", value)); + return imp; + } + log.error(String.format("Cannot process arguments of class \"%s\".", clazz.getName())); + return null; + } + + + public static String getMacroString(final Command command, final CommandInfo info, final String... outputs) { + return getMacroString(command, info, false, outputs); + } + + public static String getMacroString(final Command command, final CommandInfo info, final boolean process, final String... outputs) { + final Class commandClass = command.getClass(); + final Map args = new LinkedHashMap<>(); + + for (final ModuleItem item : info.inputs()) { + final String name = item.getName(); + final Class clazz = item.getType(); + if (SKIP_VISIBILITY.contains(item.getVisibility()) || // skip items that shouldn't be recorded + Service.class.isAssignableFrom(clazz)) // skip all (injected) services + continue; + try { + final Field field = commandClass.getDeclaredField(name); + if (!field.isAccessible()) field.setAccessible(true); + final Object value = field.get(command); + // skip unassigned items (includes buttons) + if (value == null) + continue; + if (Named.class.isAssignableFrom(clazz)) // ImgPlus and Dataset + args.put(name, ((Named)value).getName()); + else if (clazz == ImagePlus.class) + args.put(name, ((ImagePlus)value).getTitle()); + else + args.put(name, String.valueOf(value)); + } catch (NoSuchFieldException | SecurityException | IllegalArgumentException | IllegalAccessException e) { + e.printStackTrace(); + } + } + + for (final String name : outputs) { + if (info.getOutput(name) != null) + args.put(name, ""); + } + + String argsStr = new Gson().toJson(args); + argsStr = argsStr.substring(1, argsStr.length()-1); // remove curly braces + argsStr = StringEscapeUtils.escapeJava(argsStr); // escape all quotes, etc. + return String.format("run(\"%s\", \"command=[%s], process=[%s], args=[%s]\");\n", + CommandFromMacro.class.getSimpleName(), commandClass.getName(), String.valueOf(process), argsStr); + } + + + public static void main(final String... args) throws Exception { + + final ImageJ ij = new ImageJ(); + ij.launch(args); + + Dataset input = ij.scifio().datasetIO().open(StarDist2D.class.getClassLoader().getResource("yeast_crop.tif").getFile()); + ij.ui().show(input); + +// Dataset input2 = ij.scifio().datasetIO().open(StarDist2D.class.getClassLoader().getResource("yeast_timelapse.tif").getFile()); +// ij.ui().show(input2); + +// Recorder recorder = new Recorder(); +// recorder.show(); + + IJ.run("CommandFromMacro", "args=[\"input\":\"yeast_crop.tif\", \"label\":\"\"], process=[false], command=[de.csbdresden.stardist.StarDist2D]"); + } + + +} diff --git a/src/main/java/de/csbdresden/stardist/StarDist2D.java b/src/main/java/de/csbdresden/stardist/StarDist2D.java index 2e9789e..bf41bec 100644 --- a/src/main/java/de/csbdresden/stardist/StarDist2D.java +++ b/src/main/java/de/csbdresden/stardist/StarDist2D.java @@ -46,7 +46,7 @@ @Menu(label = MenuConstants.PLUGINS_LABEL, weight = MenuConstants.PLUGINS_WEIGHT, mnemonic = MenuConstants.PLUGINS_MNEMONIC), @Menu(label = "StarDist"), @Menu(label = "StarDist 2D", weight = 1) -}) +}) public class StarDist2D extends StarDist2DBase implements Command { @Parameter(label="", visibility=ItemVisibility.MESSAGE, initializer="checkForCSBDeep") @@ -280,6 +280,10 @@ public void run() { status.showProgress(1+t, (int)numFrames); } label = labelImageToDataset(outputType); + if (labelIsOutput(outputType)) + record("label"); + else + record(); } else { // note: the code below supports timelapse data too. differences to above: @@ -298,6 +302,15 @@ public void run() { if (showProbAndDist) { prob = probDS; dist = distDS; + if (labelIsOutput(outputType)) + record("label","prob","dist"); + else + record("prob","dist"); + } else { + if (labelIsOutput(outputType)) + record("label"); + else + record(); } final Future futureNMS = command.run(StarDist2DNMS.class, false, paramsNMS); diff --git a/src/main/java/de/csbdresden/stardist/StarDist2DBase.java b/src/main/java/de/csbdresden/stardist/StarDist2DBase.java index a6da4ef..c4533d1 100644 --- a/src/main/java/de/csbdresden/stardist/StarDist2DBase.java +++ b/src/main/java/de/csbdresden/stardist/StarDist2DBase.java @@ -4,10 +4,15 @@ import java.util.List; import org.scijava.app.StatusService; +import org.scijava.command.Command; +import org.scijava.command.CommandInfo; import org.scijava.command.CommandService; import org.scijava.log.LogService; import org.scijava.plugin.Parameter; import org.scijava.ui.DialogPrompt.MessageType; + +import de.csbdresden.CommandFromMacro; + import org.scijava.ui.UIService; import ij.IJ; @@ -15,6 +20,7 @@ import ij.gui.PointRoi; import ij.gui.PolygonRoi; import ij.gui.Roi; +import ij.plugin.frame.Recorder; import ij.plugin.frame.RoiManager; import ij.process.ImageProcessor; import net.imagej.Dataset; @@ -24,7 +30,7 @@ import net.imglib2.img.Img; import net.imglib2.img.display.imagej.ImageJFunctions; -public abstract class StarDist2DBase { +public abstract class StarDist2DBase implements Command { @Parameter protected LogService log; @@ -145,7 +151,7 @@ protected void exportLabelImage(Candidates polygons, int framePosition) { abstract protected ImagePlus createLabelImage(); protected Dataset labelImageToDataset(String outputType) { - if (outputType.equals(Opt.OUTPUT_LABEL_IMAGE) || outputType.equals(Opt.OUTPUT_BOTH)) { + if (labelIsOutput(outputType)) { if (labelCount > MAX_LABEL_ID) { log.error(String.format("Found more than %d segments -> label image does contain some repetitive IDs.\n(\"%s\" output instead does not have this problem).", MAX_LABEL_ID, Opt.OUTPUT_ROI_MANAGER)); } @@ -156,7 +162,28 @@ protected Dataset labelImageToDataset(String outputType) { return Utils.raiToDataset(dataset, Opt.LABEL_IMAGE, labelImg, axes); } else { return null; - } - + } + } + + protected boolean labelIsOutput(String outputType) { + return outputType.equals(Opt.OUTPUT_LABEL_IMAGE) || outputType.equals(Opt.OUTPUT_BOTH); + } + + protected void record(String... outputs) { + if (Recorder.getInstance() == null) + return; + final String recorded = Recorder.getCommand(); + // System.out.println("RECORDED: " + recorded); + final CommandInfo info = command.getCommand(this.getClass()); + // only proceed if this command is being recorded + final String cmdName = info.getMenuPath().getLeaf().getName(); + // final String cmdName = info.getLabel(); + if (recorded==null || !recorded.equals(cmdName)) + return; + // prevent automatic recording + Recorder.setCommand(null); + // record manually + Recorder.recordString(CommandFromMacro.getMacroCall(this, info, outputs)); } + } diff --git a/src/main/java/de/csbdresden/stardist/StarDist2DNMS.java b/src/main/java/de/csbdresden/stardist/StarDist2DNMS.java index d15ab9f..5fb12d3 100644 --- a/src/main/java/de/csbdresden/stardist/StarDist2DNMS.java +++ b/src/main/java/de/csbdresden/stardist/StarDist2DNMS.java @@ -113,6 +113,10 @@ public void run() { } label = labelImageToDataset(outputType); + if (labelIsOutput(outputType)) + record("label"); + else + record(); } From e3d6706f88f4328f217e832b92d2f3519f6057e6 Mon Sep 17 00:00:00 2001 From: Martin Weigert Date: Thu, 2 Apr 2020 00:52:23 +0200 Subject: [PATCH 2/5] Fix typo --- src/main/java/de/csbdresden/stardist/StarDist2DBase.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/de/csbdresden/stardist/StarDist2DBase.java b/src/main/java/de/csbdresden/stardist/StarDist2DBase.java index c4533d1..410db0d 100644 --- a/src/main/java/de/csbdresden/stardist/StarDist2DBase.java +++ b/src/main/java/de/csbdresden/stardist/StarDist2DBase.java @@ -183,7 +183,7 @@ protected void record(String... outputs) { // prevent automatic recording Recorder.setCommand(null); // record manually - Recorder.recordString(CommandFromMacro.getMacroCall(this, info, outputs)); + Recorder.recordString(CommandFromMacro.getMacroString(this, info, outputs)); } } From 3c14fb3bd8358af398074b4eea3a50c9ed222185 Mon Sep 17 00:00:00 2001 From: Uwe Schmidt Date: Thu, 2 Apr 2020 12:20:16 +0200 Subject: [PATCH 3/5] Simplify macro-recording and make macro call string nicer --- .../java/de/csbdresden/CommandFromMacro.java | 101 ++++++++++++++---- .../de/csbdresden/stardist/StarDist2D.java | 22 ++-- .../csbdresden/stardist/StarDist2DBase.java | 24 ----- .../de/csbdresden/stardist/StarDist2DNMS.java | 8 +- 4 files changed, 95 insertions(+), 60 deletions(-) diff --git a/src/main/java/de/csbdresden/CommandFromMacro.java b/src/main/java/de/csbdresden/CommandFromMacro.java index 3fd0e63..122ceb1 100644 --- a/src/main/java/de/csbdresden/CommandFromMacro.java +++ b/src/main/java/de/csbdresden/CommandFromMacro.java @@ -8,6 +8,7 @@ import java.util.LinkedHashMap; import java.util.List; import java.util.Map; +import java.util.Map.Entry; import java.util.concurrent.ExecutionException; import org.apache.commons.lang3.ClassUtils; @@ -28,9 +29,9 @@ import com.google.gson.Gson; import de.csbdresden.stardist.StarDist2D; -import ij.IJ; import ij.ImagePlus; import ij.WindowManager; +import ij.plugin.frame.Recorder; import net.imagej.Dataset; import net.imagej.ImageJ; import net.imglib2.RandomAccessibleInterval; @@ -66,10 +67,21 @@ public class CommandFromMacro implements Command { @Override public void run() { - final CommandInfo info = cmd.getCommand(command); + CommandInfo info = cmd.getCommand(command); if (info == null) { - log.warn(String.format("Command \"%s\" not found.", command)); - return; + for (CommandInfo c: cmd.getCommands()) { + try { + if (command.equals(c.getMenuPath().getLeaf().getName())) { + info = c; + command = info.getClassName(); + break; + } + } catch (NullPointerException e) {} + } + if (info == null) { + log.error(String.format("Command \"%s\" not found.", command)); + return; + } } final Map params = new LinkedHashMap<>(); @@ -135,16 +147,37 @@ private Object toParameter(final String value, final Class clazz) { log.error(String.format("Cannot process arguments of class \"%s\".", clazz.getName())); return null; } - - - public static String getMacroString(final Command command, final CommandInfo info, final String... outputs) { - return getMacroString(command, info, false, outputs); + + + public static boolean record(final Command command, final CommandService commandService) { + return record(command, commandService, false); + } + + public static boolean record(final Command command, final CommandService commandService, final boolean process) { + if (Recorder.getInstance() == null) + return false; + final String recorded = Recorder.getCommand(); + // System.out.println("RECORDED: " + recorded); + final CommandInfo info = commandService.getCommand(command.getClass()); + // only proceed if this command is being recorded + final String name = info.getMenuPath().getLeaf().getName(); + // final String cmdName = info.getLabel(); + if (recorded==null || !recorded.equals(name)) + return false; + // prevent automatic recording + Recorder.setCommand(null); + // record manually + Recorder.recordString(getMacroString(command, commandService, process)); + return true; } - - public static String getMacroString(final Command command, final CommandInfo info, final boolean process, final String... outputs) { + + + private static String getMacroString(final Command command, final CommandService commandService, final boolean process) { final Class commandClass = command.getClass(); + final CommandInfo info = commandService.getCommand(command.getClass()); final Map args = new LinkedHashMap<>(); + // add input parameters as arguments for (final ModuleItem item : info.inputs()) { final String name = item.getName(); final Class clazz = item.getType(); @@ -169,16 +202,43 @@ else if (clazz == ImagePlus.class) } } - for (final String name : outputs) { - if (info.getOutput(name) != null) + // designate assigned outputs to be shown + for (final ModuleItem item : info.outputs()) { + final String name = item.getName(); + try { + final Field field = commandClass.getDeclaredField(name); + if (!field.isAccessible()) field.setAccessible(true); + final Object value = field.get(command); + // skip unassigned outputs + if (value == null) + continue; args.put(name, ""); + } catch (NoSuchFieldException | SecurityException | IllegalArgumentException | IllegalAccessException e) { + e.printStackTrace(); + } } + // convert to json and remove curly braces String argsStr = new Gson().toJson(args); - argsStr = argsStr.substring(1, argsStr.length()-1); // remove curly braces - argsStr = StringEscapeUtils.escapeJava(argsStr); // escape all quotes, etc. + argsStr = argsStr.substring(1, argsStr.length()-1); + // to make the macro string look nicer (otherwise have to escape all double quotes): + // replace double quotes around json keys/values with single quotes + // technically not correct json, but can be parsed by Gson + final StringBuilder sb = new StringBuilder(argsStr); + int p = 0; + for (Entry arg: args.entrySet()) { + final int k = StringEscapeUtils.escapeJava(arg.getKey()).length(); + final int v = StringEscapeUtils.escapeJava(arg.getValue()).length(); + sb.replace(p, p+1, "'"); p+=1+k; + sb.replace(p, p+1, "'"); p+=2; + sb.replace(p, p+1, "'"); p+=1+v; + sb.replace(p, p+1, "'"); p+=2; + } + argsStr = sb.toString(); + + final String execName = commandService.getCommand(CommandFromMacro.class).getMenuPath().getLeaf().getName(); return String.format("run(\"%s\", \"command=[%s], process=[%s], args=[%s]\");\n", - CommandFromMacro.class.getSimpleName(), commandClass.getName(), String.valueOf(process), argsStr); + execName, commandClass.getName(), String.valueOf(process), argsStr); } @@ -193,10 +253,15 @@ public static void main(final String... args) throws Exception { // Dataset input2 = ij.scifio().datasetIO().open(StarDist2D.class.getClassLoader().getResource("yeast_timelapse.tif").getFile()); // ij.ui().show(input2); -// Recorder recorder = new Recorder(); -// recorder.show(); + Recorder recorder = new Recorder(); + recorder.show(); + + final Map params = new LinkedHashMap<>(); + // params.put("input", input); + ij.command().run(StarDist2D.class, true, params); + - IJ.run("CommandFromMacro", "args=[\"input\":\"yeast_crop.tif\", \"label\":\"\"], process=[false], command=[de.csbdresden.stardist.StarDist2D]"); +// IJ.run("CommandFromMacro", "args=[\"input\":\"yeast_crop.tif\", \"label\":\"\"], process=[false], command=[de.csbdresden.stardist.StarDist2D]"); } diff --git a/src/main/java/de/csbdresden/stardist/StarDist2D.java b/src/main/java/de/csbdresden/stardist/StarDist2D.java index bf41bec..d076778 100644 --- a/src/main/java/de/csbdresden/stardist/StarDist2D.java +++ b/src/main/java/de/csbdresden/stardist/StarDist2D.java @@ -28,6 +28,7 @@ import org.scijava.widget.ChoiceWidget; import org.scijava.widget.NumberWidget; +import de.csbdresden.CommandFromMacro; import ij.IJ; import ij.ImagePlus; import net.imagej.Dataset; @@ -280,10 +281,6 @@ public void run() { status.showProgress(1+t, (int)numFrames); } label = labelImageToDataset(outputType); - if (labelIsOutput(outputType)) - record("label"); - else - record(); } else { // note: the code below supports timelapse data too. differences to above: @@ -302,19 +299,13 @@ public void run() { if (showProbAndDist) { prob = probDS; dist = distDS; - if (labelIsOutput(outputType)) - record("label","prob","dist"); - else - record("prob","dist"); - } else { - if (labelIsOutput(outputType)) - record("label"); - else - record(); } final Future futureNMS = command.run(StarDist2DNMS.class, false, paramsNMS); - label = (Dataset) futureNMS.get().getOutput("label"); + label = (Dataset) futureNMS.get().getOutput("label"); + + // call at the end of the run() method + CommandFromMacro.record(this, this.command); } } catch (InterruptedException | ExecutionException | IOException e) { e.printStackTrace(); @@ -383,6 +374,9 @@ public static void main(final String... args) throws Exception { // Dataset input = ij.scifio().datasetIO().open(StarDist2D.class.getClassLoader().getResource("yeast_timelapse.tif").getFile()); Dataset input = ij.scifio().datasetIO().open(StarDist2D.class.getClassLoader().getResource("yeast_crop.tif").getFile()); ij.ui().show(input); + +// Recorder recorder = new Recorder(); +// recorder.show(); final HashMap params = new HashMap<>(); ij.command().run(StarDist2D.class, true, params); diff --git a/src/main/java/de/csbdresden/stardist/StarDist2DBase.java b/src/main/java/de/csbdresden/stardist/StarDist2DBase.java index 410db0d..6f7e142 100644 --- a/src/main/java/de/csbdresden/stardist/StarDist2DBase.java +++ b/src/main/java/de/csbdresden/stardist/StarDist2DBase.java @@ -5,22 +5,16 @@ import org.scijava.app.StatusService; import org.scijava.command.Command; -import org.scijava.command.CommandInfo; import org.scijava.command.CommandService; import org.scijava.log.LogService; import org.scijava.plugin.Parameter; import org.scijava.ui.DialogPrompt.MessageType; - -import de.csbdresden.CommandFromMacro; - import org.scijava.ui.UIService; -import ij.IJ; import ij.ImagePlus; import ij.gui.PointRoi; import ij.gui.PolygonRoi; import ij.gui.Roi; -import ij.plugin.frame.Recorder; import ij.plugin.frame.RoiManager; import ij.process.ImageProcessor; import net.imagej.Dataset; @@ -168,22 +162,4 @@ protected Dataset labelImageToDataset(String outputType) { protected boolean labelIsOutput(String outputType) { return outputType.equals(Opt.OUTPUT_LABEL_IMAGE) || outputType.equals(Opt.OUTPUT_BOTH); } - - protected void record(String... outputs) { - if (Recorder.getInstance() == null) - return; - final String recorded = Recorder.getCommand(); - // System.out.println("RECORDED: " + recorded); - final CommandInfo info = command.getCommand(this.getClass()); - // only proceed if this command is being recorded - final String cmdName = info.getMenuPath().getLeaf().getName(); - // final String cmdName = info.getLabel(); - if (recorded==null || !recorded.equals(cmdName)) - return; - // prevent automatic recording - Recorder.setCommand(null); - // record manually - Recorder.recordString(CommandFromMacro.getMacroString(this, info, outputs)); - } - } diff --git a/src/main/java/de/csbdresden/stardist/StarDist2DNMS.java b/src/main/java/de/csbdresden/stardist/StarDist2DNMS.java index 5fb12d3..525cbb5 100644 --- a/src/main/java/de/csbdresden/stardist/StarDist2DNMS.java +++ b/src/main/java/de/csbdresden/stardist/StarDist2DNMS.java @@ -16,6 +16,7 @@ import org.scijava.widget.ChoiceWidget; import org.scijava.widget.NumberWidget; +import de.csbdresden.CommandFromMacro; import ij.IJ; import ij.ImagePlus; import net.imagej.Dataset; @@ -113,10 +114,9 @@ public void run() { } label = labelImageToDataset(outputType); - if (labelIsOutput(outputType)) - record("label"); - else - record(); + + // call at the end of the run() method + CommandFromMacro.record(this, this.command); } From f290dc61089a8177415d9f27df3bb6fe48f56289 Mon Sep 17 00:00:00 2001 From: Uwe Schmidt Date: Thu, 2 Apr 2020 23:45:36 +0200 Subject: [PATCH 4/5] Undo some small changes in StarDist2DBase --- src/main/java/de/csbdresden/stardist/StarDist2DBase.java | 9 ++------- 1 file changed, 2 insertions(+), 7 deletions(-) diff --git a/src/main/java/de/csbdresden/stardist/StarDist2DBase.java b/src/main/java/de/csbdresden/stardist/StarDist2DBase.java index 6f7e142..3b805f8 100644 --- a/src/main/java/de/csbdresden/stardist/StarDist2DBase.java +++ b/src/main/java/de/csbdresden/stardist/StarDist2DBase.java @@ -4,7 +4,6 @@ import java.util.List; import org.scijava.app.StatusService; -import org.scijava.command.Command; import org.scijava.command.CommandService; import org.scijava.log.LogService; import org.scijava.plugin.Parameter; @@ -24,7 +23,7 @@ import net.imglib2.img.Img; import net.imglib2.img.display.imagej.ImageJFunctions; -public abstract class StarDist2DBase implements Command { +public abstract class StarDist2DBase { @Parameter protected LogService log; @@ -145,7 +144,7 @@ protected void exportLabelImage(Candidates polygons, int framePosition) { abstract protected ImagePlus createLabelImage(); protected Dataset labelImageToDataset(String outputType) { - if (labelIsOutput(outputType)) { + if (outputType.equals(Opt.OUTPUT_LABEL_IMAGE) || outputType.equals(Opt.OUTPUT_BOTH)) { if (labelCount > MAX_LABEL_ID) { log.error(String.format("Found more than %d segments -> label image does contain some repetitive IDs.\n(\"%s\" output instead does not have this problem).", MAX_LABEL_ID, Opt.OUTPUT_ROI_MANAGER)); } @@ -158,8 +157,4 @@ protected Dataset labelImageToDataset(String outputType) { return null; } } - - protected boolean labelIsOutput(String outputType) { - return outputType.equals(Opt.OUTPUT_LABEL_IMAGE) || outputType.equals(Opt.OUTPUT_BOTH); - } } From bd98a4eea2655d2fb8d470c28316cba1795df787 Mon Sep 17 00:00:00 2001 From: Uwe Schmidt Date: Wed, 8 Apr 2020 00:25:11 +0200 Subject: [PATCH 5/5] Fix bug (macro not recorded for timelapse) --- src/main/java/de/csbdresden/CommandFromMacro.java | 13 ++++++------- .../java/de/csbdresden/stardist/StarDist2D.java | 6 +++--- 2 files changed, 9 insertions(+), 10 deletions(-) diff --git a/src/main/java/de/csbdresden/CommandFromMacro.java b/src/main/java/de/csbdresden/CommandFromMacro.java index 122ceb1..de4b09c 100644 --- a/src/main/java/de/csbdresden/CommandFromMacro.java +++ b/src/main/java/de/csbdresden/CommandFromMacro.java @@ -37,7 +37,7 @@ import net.imglib2.RandomAccessibleInterval; -@Plugin(type = Command.class, label = "CommandFromMacro", menuPath = "Plugins > StarDist > Other > CommandFromMacro") +@Plugin(type = Command.class, label = "Command From Macro", menuPath = "Plugins > StarDist > Other > Command From Macro") public class CommandFromMacro implements Command { private static final List SKIP_VISIBILITY = Arrays.asList(ItemVisibility.MESSAGE, ItemVisibility.INVISIBLE); @@ -46,10 +46,10 @@ public class CommandFromMacro implements Command { private String command; @Parameter - private boolean process; + private String args; @Parameter - private String args; + private boolean process; // --------- @@ -157,11 +157,10 @@ public static boolean record(final Command command, final CommandService command if (Recorder.getInstance() == null) return false; final String recorded = Recorder.getCommand(); - // System.out.println("RECORDED: " + recorded); final CommandInfo info = commandService.getCommand(command.getClass()); // only proceed if this command is being recorded final String name = info.getMenuPath().getLeaf().getName(); - // final String cmdName = info.getLabel(); + // System.out.printf("RECORDED: %s, COMMAND: %s\n", recorded, name); if (recorded==null || !recorded.equals(name)) return false; // prevent automatic recording @@ -237,8 +236,8 @@ else if (clazz == ImagePlus.class) argsStr = sb.toString(); final String execName = commandService.getCommand(CommandFromMacro.class).getMenuPath().getLeaf().getName(); - return String.format("run(\"%s\", \"command=[%s], process=[%s], args=[%s]\");\n", - execName, commandClass.getName(), String.valueOf(process), argsStr); + return String.format("run(\"%s\", \"command=[%s], args=[%s], process=[%s]\");\n", + execName, commandClass.getName(), argsStr, String.valueOf(process)); } diff --git a/src/main/java/de/csbdresden/stardist/StarDist2D.java b/src/main/java/de/csbdresden/stardist/StarDist2D.java index 35289a5..8c490d3 100644 --- a/src/main/java/de/csbdresden/stardist/StarDist2D.java +++ b/src/main/java/de/csbdresden/stardist/StarDist2D.java @@ -317,10 +317,10 @@ public void run() { final Future futureNMS = command.run(StarDist2DNMS.class, false, paramsNMS); label = (Dataset) futureNMS.get().getOutput("label"); - - // call at the end of the run() method - CommandFromMacro.record(this, this.command); } + // call at the end of the run() method + CommandFromMacro.record(this, this.command); + } catch (InterruptedException | ExecutionException | IOException e) { e.printStackTrace(); } finally {