Loading... |
Reply to author |
Edit post |
Move post |
Delete this post |
Delete this post and replies |
Change post date |
Print post |
Permalink |
Raw mail |
Is there a simple way to check if a stored image is open?
For example, isOpen("/Users/norbert/Desktop/blobs.gif") would be nice, but seems not to be supported, nor did I find anything in the File.* commands. ( I know that I could travel through all open windows and compare paths..) Norbert Vischer -- ImageJ mailing list: http://imagej.nih.gov/ij/list.html |
Loading... |
Reply to author |
Edit post |
Move post |
Delete this post |
Delete this post and replies |
Change post date |
Print post |
Permalink |
Raw mail |
Hi Norbert,
On Sat, 16 Mar 2013, Norbert Vischer wrote: > Is there a simple way to check if a stored image is open? Unfortunately, no simple way (the macro language is too simple for true object-oriented programming and that's what you essentially require). > For example, > > isOpen("/Users/norbert/Desktop/blobs.gif") > > would be nice, but seems not to be supported, nor did I find anything in > the File.* commands. > > ( I know that I could travel through all open windows and compare paths..) That would work, of course, but it would be slow: -- snip -- // This function detects path -> image-index pairs // You can use List.get(path) to get the image-index // and selectImage(index + 1) to make it the active image function getOpenedPaths() { List.clear(); count = nImages(); for (i = 0; i < count; i++) { selectImage(1 + i); path = getInfo("image.directory") + getInfo("image.filename"); List.set(path, i); } } -- snap -- You would use it that way: -- snip -- getOpenedPaths(); path = "/path/to/my/file.tiff"; id = List.get(path); if (id == "") { print("Not open: " + path); } else { selectImage(1 + id); } -- snap -- This would be slow and you would want to make sure that you run this only in batch mode. Unfortunately, there are some obstacles if you want to accelerate it, e.g. by going Javascript: -- snip -- // This function detects path -> image-index pairs // You can use List.get(path) to get the image-index // and selectImage(index + 1) to make it the active image function getOpenedPaths() { // we need to use a system property since returning values from // eval("script", script) is broken in ImageJ 1.47m unused = call("java.lang.System.setProperty", "hopefully.unused", ""); script = 'importClass(Packages.ij.IJ);' + 'importClass(Packages.ij.WindowManager);' + '' + 'var result = [];' + 'var count = WindowManager.getImageCount();' + 'for (var i = 0; i < count; i++) {' + ' image = WindowManager.getImage(1 + i);' + ' info = image.getOriginalFileInfo();' + ' if (info != null) {' + ' result.push(info.directory + info.fileName + "=" + i); + ' }' + '}' + '' + 'System.setProperty("hopefully.unused", result.join("\\n"));'; x = eval('script', script); List.setList(call("java.lang.System.getProperty", "hopefully.unused")); } -- snap -- Ciao, Johannes -- ImageJ mailing list: http://imagej.nih.gov/ij/list.html |
Loading... |
Reply to author |
Edit post |
Move post |
Delete this post |
Delete this post and replies |
Change post date |
Print post |
Permalink |
Raw mail |
Hi Wayne,
On Sat, 16 Mar 2013, Johannes Schindelin wrote: > function getOpenedPaths() { > // we need to use a system property since returning values from > // eval("script", script) is broken in ImageJ 1.47m > unused = call("java.lang.System.setProperty", "hopefully.unused", ""); > [...] The problem is that even after the attempt to imitate the Fiji scripting framework by introducing the PlugInInterpreter class, Macro_Runner#runJavaScript(String, String) still returns always null, never an evaluated value: https://github.com/fiji/imagej1/blob/master/ij/plugin/Macro_Runner.java#L233 sets 's', but a couple of lines later, it still just returns null in every case. Can you please fix that bug? Ciao, Johannes -- ImageJ mailing list: http://imagej.nih.gov/ij/list.html |
Loading... |
Reply to author |
Edit post |
Move post |
Delete this post |
Delete this post and replies |
Change post date |
Print post |
Permalink |
Raw mail |
Dear Wayne,
On Sat, 16 Mar 2013, Rasband, Wayne (NIH/NIMH) [E] wrote: > Hi Johannes, > > On Mar 16, 2013, at 2:57 PM, Johannes Schindelin wrote: > > > Hi Wayne, > > > > On Sat, 16 Mar 2013, Johannes Schindelin wrote: > > > >> function getOpenedPaths() { > >> // we need to use a system property since returning values from > >> // eval("script", script) is broken in ImageJ 1.47m > >> unused = call("java.lang.System.setProperty", "hopefully.unused", ""); > >> [...] > > > > The problem is that even after the attempt to imitate the Fiji > > scripting framework by introducing the PlugInInterpreter class, > > Macro_Runner#runJavaScript(String, String) still returns always null, > > never an evaluated value: > > > > https://github.com/fiji/imagej1/blob/master/ij/plugin/Macro_Runner.java#L233 > > > > sets 's', but a couple of lines later, it still just returns null in > > every case. > > > > Can you please fix that bug? > > The PlugInInterpreter class is currently not used to run JavaScript > scrips and Macro_Runner.runJavaScript() has always returned null. ... [show rest of quote] That matches exactly what I reported ;-) > How would you propose returning a value from a JavaScript script? We > can't use the return statement because it is only allowed in functions. > The only thing I can think of is assigning the return value to a > variable and then retrieving the value of that variable. The trick is not to use a 'return' statement (because -- as you pointed out correctly -- the top-level script is not a function), but an unassigned expression: eval("script", "1;"); This patch (which you can conveniently get into your working directory by calling "git pull git://github.com/dscho/imagej1 fix-js-return") makes that work: -- snip -- diff --git a/ij/plugin/Macro_Runner.java b/ij/plugin/Macro_Runner.java index 257ac6d..254f7d6 100644 --- a/ij/plugin/Macro_Runner.java +++ b/ij/plugin/Macro_Runner.java @@ -236,7 +236,7 @@ private static String runScript(Object plugin, String script, String arg) { IJ.runPlugIn("Jython", script); } } - return null; + return "" + js; } /** Runs a BeanShell script the on current thread. Uses the plugin at diff --git a/plugins/JavaScriptEvaluator.source b/plugins/JavaScriptEvaluator.source index f72064a..37341c5 100644 --- a/plugins/JavaScriptEvaluator.source +++ b/plugins/JavaScriptEvaluator.source @@ -13,6 +13,7 @@ import javax.script.*; public class JavaScriptEvaluator implements PlugIn, Runnable { Thread thread; String script; + private Object result; // run script in separate thread public void run(String script) { @@ -33,12 +34,13 @@ public class JavaScriptEvaluator implements PlugIn, Runnable { } public void run() { + result = null; try { ScriptEngineManager scriptEngineManager = new ScriptEngineManager(); ScriptEngine engine = scriptEngineManager.getEngineByName("ECMAScript"); if (engine == null) {IJ.error("Could not find JavaScript engine"); return;} - engine.eval(script); + result = engine.eval(script); } catch(Throwable e) { String msg = e.getMessage(); if (msg.startsWith("sun.org.mozilla.javascript.internal.EcmaError: ")) @@ -50,4 +52,8 @@ public class JavaScriptEvaluator implements PlugIn, Runnable { } } + @Override + public String toString() { + return "" + result; + } } -- snap -- > Passing of arguments to JavaScript scripts also needs to be fixed. How > would you propose doing that? I do not think that there is a lot to fix. Last time I tried (with Fiji's scripting framework, which I would have been happy to contribute to ImageJ 1.x), using GenericDialog instances (and calling the scripts via run(..., args);) worked just fine. If you want a solution that is safe to execute in headless mode, and that allows easily for adding new interpreters without having to reference those interpreters in ImageJ 1.x' core explicitly, I am afraid that you would have to either use ImageJ2's scripting framework or replicate the complete functionality thereof. If you want to benefit from my work, I would be delighted to discuss how to adjust it to be able to use it from vanilla ImageJ 1.x. Ciao, Johannes -- ImageJ mailing list: http://imagej.nih.gov/ij/list.html |
Loading... |
Reply to author |
Edit post |
Move post |
Delete this post |
Delete this post and replies |
Change post date |
Print post |
Permalink |
Raw mail |
Thanks Johannes for your contribution. My mail was more a suggestion to accept paths in isOpen(string), and I had solved my problem already somehow, but I tried your macro and it worked as expected.
However, there is a basic problem as ImageJ in my opinion has no straight-forward concept to identify images and paths. It automatically can create duplicates which is confusing. In Image>Show Info>, "title" and the end of "path" do not match after "Rename" or after loading the same image a second time. In the latter case, ImageJ opens a duplicate with a new name ("clown-1.tif") but still maintains the old path ending with "clown.tif". Assume another case where "clown.tif" is on the dock - ImageJ will behave different depending on whether the clown was there as minimized window, or as file associated to ImageJ. In the latter case, each click creates a new duplicate. When ImageJ chooses a new name for a duplicate, this name may already be occupied by a different file in the same folder, although this is not likely. The danger of unwanted overwriting is "solved" by warning "File already exists" before each attempt to "Save". (I routinely confirm without thinking). It would be nice if ImageJ would behave like other applications: - If the user gives any type of "Open" command to a file which is already open, its window should be brought to the front, rather than being duplicated with a different name. If it was edited meanwhile, the user should be asked which version to use. - If the user gives a "Save" command and the path is known, the old file should be overwritten without additional confirmation But may be it is to late to change all this? Norbert -- ImageJ mailing list: http://imagej.nih.gov/ij/list.html |
Loading... |
Reply to author |
Edit post |
Move post |
Delete this post |
Delete this post and replies |
Change post date |
Print post |
Permalink |
Raw mail |
In reply to this post by dscho
Dear Wayne,
On Mon, 18 Mar 2013, Rasband, Wayne (NIH/NIMH) [E] wrote: > On Mar 17, 2013, at 11:00 AM, Johannes Schindelin wrote: > > > The trick is not to use a 'return' statement (because -- as you > > pointed out correctly -- the top-level script is not a function), but > > an unassigned expression: > > > > eval("script", "1;"); > > > > This patch (which you can conveniently get into your working directory > > by calling "git pull git://github.com/dscho/imagej1 fix-js-return") > > makes that work: > > It does work and it is in today's ImageJ 1.47n daily build. Thanks for > providing this solution. You're welcome. Although I'd like to mention that it would have been easier to simply pull than to reapply things by hand. > >> Passing of arguments to JavaScript scripts also needs to be fixed. > >> How would you propose doing that? > > > > I do not think that there is a lot to fix. Last time I tried (with > > Fiji's scripting framework, which I would have been happy to > > contribute to ImageJ 1.x), using GenericDialog instances (and calling > > the scripts via run(..., args);) worked just fine. > > Sorry, I should have been more specific. I am trying to figure out how > this method > > public String runJavaScript(String script, String arg) > > in the Macro_Runner class should pass the string argument to the script. > The only thing I can think of is to append a line of code something like > > arg = "value of 'arg'"; > > to the script before it is evaluated. The script could then retrieve the > argument by accessing the 'arg' variable. That would work but it doesn't > seem like a very elegant solution. ... [show rest of quote] Well, when you call the script, you can prepend it with anything anyway. However, if you use the Java scripting API (as we already do in ImageJ2's scripting framework -- hence my offer to help you avoid reinventing the wheel with ImageJ 1.x), you can call ScriptEngine#put(String, Object) to set local variables: http://docs.oracle.com/javase/6/docs/api/javax/script/ScriptEngine.html#put%28java.lang.String,%20java.lang.Object%29 I can easily make a pull'able branch to implement that, but I have the impression that you want to implement it yourself anyway. If you would like me to provide an easy-to-integrate change, however, please just let me know! I'll be more than happy to contribute it! Ciao, Johannes -- ImageJ mailing list: http://imagej.nih.gov/ij/list.html |
Loading... |
Reply to author |
Edit post |
Move post |
Delete this post |
Delete this post and replies |
Change post date |
Print post |
Permalink |
Raw mail |
Dear Wayne,
On Wed, 20 Mar 2013, Johannes Schindelin wrote: > http://docs.oracle.com/javase/6/docs/api/javax/script/ScriptEngine.html#put%28java.lang.String,%20java.lang.Object%29 > > I can easily make a pull'able branch to implement that, but I have the > impression that you want to implement it yourself anyway. If you would > like me to provide an easy-to-integrate change, however, please just let > me know! I'll be more than happy to contribute it! I made the change, tested it, and you can easily pull it like this: git pull git://github.com/dscho/imagej1 javascript-arg Ciao, Johannes -- ImageJ mailing list: http://imagej.nih.gov/ij/list.html |
Loading... |
Reply to author |
Edit post |
Move post |
Delete this post |
Delete this post and replies |
Change post date |
Print post |
Permalink |
Raw mail |
Hi Wayne,
On Thu, 21 Mar 2013, Rasband, Wayne (NIH/NIMH) [E] wrote: > On Mar 20, 2013, at 1:45 PM, Johannes Schindelin wrote: > > > On Wed, 20 Mar 2013, Johannes Schindelin wrote: > > > >> http://docs.oracle.com/javase/6/docs/api/javax/script/ScriptEngine.html#put%28java.lang.String,%20java.lang.Object%29 > >> > >> I can easily make a pull'able branch to implement that, but I have > >> the impression that you want to implement it yourself anyway. If you > >> would like me to provide an easy-to-integrate change, however, please > >> just let me know! I'll be more than happy to contribute it! > > > > I made the change, tested it, and you can easily pull it like this: > > > > git pull git://github.com/dscho/imagej1 javascript-arg > > I decided to prepend a getArgument() function to the script in order to > be consistent with the way arguments are passed to macros. This make it > easier to document how the Macro_Runner.runMacroFile() method works: > > /** Opens and runs the specified macro or script file on the current > thread. The file is assumed to be in the ImageJ/macros folder > unless 'name' is a full path. ".txt" is added if 'name' does not > have an extension. The macro or script can use the getArgument() > function to retrieve the string argument. > */ > public String runMacroFile(String name, String arg) { ... [show rest of quote] Nice! It is even thread-safe (in contrast to the macro function, but then, too many things in macros are thread-unsafe already to allow for concurrent execution). At least if ScriptEngines are not reused (I vaguely remember reading someething about this not being guaranteed, but in that case, my put() approach would be thread-unsafe, too). The only problem I see with the current getArgument approach is that it does not adhere to Postel's law by leaving the arg unquoted. Ciao, Johannes -- ImageJ mailing list: http://imagej.nih.gov/ij/list.html |
Free forum by Nabble | Disable Popup Ads | Edit this page |