Login  Register

Using System.out and System.err from ImageJ plugins (Java)

Previous Topic Next Topic
 
classic Classic list List threaded Threaded
10 messages Options Options
Embed post
Permalink
Reply | Threaded
Open this post in threaded view
| More
Print post
Permalink

Using System.out and System.err from ImageJ plugins (Java)

Burger Wilhelm
130 posts
Hello all,

I would like to share a piece of Java code for ImageJ that I wrote out of need and perhaps others might find useful too:

This small library facilitates the redirection of output to System.out and System.err to the ImageJ Log-console. Typically in ImageJ output sent to the standard system streams by calls such as System.out.println(...) are suppressed. Redirecting the standard output streams makes this output appear in ImageJ's log console, analogous to using the IJ.log() method. This is particularly useful for debugging imported code and for writing classes that are independent of ImageJ.

More details and the complete code with examples can be found here:
http://staff.fh-hagenberg.at/burger/imagej/index.html

Comments and suggestions for improvements are welcome.

Best regards,
Wilhelm

www.imagingbook.com
--
ImageJ mailing list: http://imagej.nih.gov/ij/list.html
Reply | Threaded
Open this post in threaded view
| More
Print post
Permalink

Re: Using System.out and System.err from ImageJ plugins (Java)

dscho
1631 posts
Hi Wilhelm,

On Mon, 18 Feb 2013, Burger Wilhelm wrote:

> I would like to share a piece of Java code for ImageJ that I wrote out
> of need and perhaps others might find useful too:
>
> This small library facilitates the redirection of output to System.out
> and System.err to the ImageJ Log-console. Typically in ImageJ output
> sent to the standard system streams by calls such as
> System.out.println(...) are suppressed. Redirecting the standard output
> streams makes this output appear in ImageJ's log console, analogous to
> using the IJ.log() method. This is particularly useful for debugging
> imported code and for writing classes that are independent of ImageJ.

Note that Fiji writes stdout and stderr to the ImageJ Log window in
addition to the console (if there is one) if you switch on debug mode via
Edit>Options>Misc...

Ciao,
Johannes

--
ImageJ mailing list: http://imagej.nih.gov/ij/list.html
Reply | Threaded
Open this post in threaded view
| More
Print post
Permalink

Re: Using System.out and System.err from ImageJ plugins (Java)

Burger Wilhelm
130 posts
Good to know! -- suppose this would have saved me some troubles ...

Thanks much,
Wilhelm

________________________________________
From: Johannes Schindelin [[hidden email]]
Sent: Monday, February 18, 2013 16:18
To: Burger Wilhelm
Cc: [hidden email]
Subject: Re: Using System.out and System.err from ImageJ plugins (Java)

Hi Wilhelm,

On Mon, 18 Feb 2013, Burger Wilhelm wrote:

> I would like to share a piece of Java code for ImageJ that I wrote out
> of need and perhaps others might find useful too:
>
> This small library facilitates the redirection of output to System.out
> and System.err to the ImageJ Log-console. Typically in ImageJ output
> sent to the standard system streams by calls such as
> System.out.println(...) are suppressed. Redirecting the standard output
> streams makes this output appear in ImageJ's log console, analogous to
> using the IJ.log() method. This is particularly useful for debugging
> imported code and for writing classes that are independent of ImageJ.

Note that Fiji writes stdout and stderr to the ImageJ Log window in
addition to the console (if there is one) if you switch on debug mode via
Edit>Options>Misc...

Ciao,
Johannes
--
ImageJ mailing list: http://imagej.nih.gov/ij/list.html
Reply | Threaded
Open this post in threaded view
| More
Print post
Permalink

Re: Using System.out and System.err from ImageJ plugins (Java)

Rasband, Wayne (NIH/NIMH) [E]
1064 posts
In reply to this post by Burger Wilhelm
On Feb 18, 2013, at 7:46 AM, Burger Wilhelm wrote:

> Hello all,
>
> I would like to share a piece of Java code for ImageJ that I wrote out of need and perhaps others might find useful too:
>
> This small library facilitates the redirection of output to System.out and System.err to the ImageJ Log-console. Typically in ImageJ output sent to the standard system streams by calls such as System.out.println(...) are suppressed. Redirecting the standard output streams makes this output appear in ImageJ's log console, analogous to using the IJ.log() method. This is particularly useful for debugging imported code and for writing classes that are independent of ImageJ.
>
> More details and the complete code with examples can be found here:
> http://staff.fh-hagenberg.at/burger/imagej/index.html
>
> Comments and suggestions for improvements are welcome.

This library is built into the ImageJ 1.47m daily build as the ij.io.LogStream class. You can redirect System.out and System.err messages to the Log window by enabling debug mode in Edit>Options>Misc.

-wayne
--
ImageJ mailing list: http://imagej.nih.gov/ij/list.html
Reply | Threaded
Open this post in threaded view
| More
Print post
Permalink

Re: Using System.out and System.err from ImageJ plugins (Java)

dscho
1631 posts
Hi,

On Wed, 27 Feb 2013, Rasband, Wayne (NIH/NIMH) [E] wrote:

> On Feb 18, 2013, at 7:46 AM, Burger Wilhelm wrote:
>
> > I would like to share a piece of Java code for ImageJ that I wrote out
> > of need and perhaps others might find useful too:
> >
> > This small library facilitates the redirection of output to System.out
> > and System.err to the ImageJ Log-console. Typically in ImageJ output
> > sent to the standard system streams by calls such as
> > System.out.println(...) are suppressed. Redirecting the standard
> > output streams makes this output appear in ImageJ's log console,
> > analogous to using the IJ.log() method. This is particularly useful
> > for debugging imported code and for writing classes that are
> > independent of ImageJ.
> >
> > More details and the complete code with examples can be found here:
> > http://staff.fh-hagenberg.at/burger/imagej/index.html
> >
> > Comments and suggestions for improvements are welcome.
>
> This library is built into the ImageJ 1.47m daily build as the
> ij.io.LogStream class. You can redirect System.out and System.err
> messages to the Log window by enabling debug mode in Edit>Options>Misc.

I am glad you liked my approach, but I would have preferred it if my code
had just been reused... it was unnecessary to reinvent the wheel.

In any case, this interferes with Fiji's stdout/stderr handling. I am
fixing it as we speak.

Note also that the non-standard naming and location of the scripting
languages' .jar files are incompatible with Fiji's well-established
conventions. It would have been nice to avoid that.

Likewise, we, too, hardcoded languages into Fiji's scripting core. There
was a lesson in that, and we learnt from it: ImageJ2's scripting core is
completely independent of language-specific .jar files. I would strongly
suggest to learn that lesson from Fiji and not repeat the mistake in
ImageJ1.

Ciao,
Johannes

--
ImageJ mailing list: http://imagej.nih.gov/ij/list.html
Reply | Threaded
Open this post in threaded view
| More
Print post
Permalink

Re: Using System.out and System.err from ImageJ plugins (Java)

dscho
1631 posts
Dear Wayne,

On Wed, 27 Feb 2013, Johannes Schindelin wrote:

> On Wed, 27 Feb 2013, Rasband, Wayne (NIH/NIMH) [E] wrote:
>
> > You can redirect System.out and System.err messages to the Log window
> > by enabling debug mode in Edit>Options>Misc.
>
> [...] this interferes with Fiji's stdout/stderr handling. I am fixing it
> as we speak.

I just tested this Javascript after downloading and starting
http://imagej.net/ij.jar:

        importClass(Packages.java.lang.System);
        System.err.println("Hello");

It did not interfere with Fiji's redirection -- unexpectedly.

I tried to find out by studying the source code, but the newest commit did
not show how the redirection works:

http://fiji.sc/cgi-bin/gitweb.cgi?p=imagej.git;a=commitdiff;h=83f7efc605f666626f5f78d10bbe5c7d52b75e61

Indeed, building from the current 'master' of your repository does not
redirect stdout/stderr when the debug mode is enabled.

Ciao,
Johannes

--
ImageJ mailing list: http://imagej.nih.gov/ij/list.html
Reply | Threaded
Open this post in threaded view
| More
Print post
Permalink

Re: Using System.out and System.err from ImageJ plugins (Java)

dscho
1631 posts
Dear Wayne,

On Wed, 27 Feb 2013, Johannes Schindelin wrote:

> On Wed, 27 Feb 2013, Johannes Schindelin wrote:
>
> > On Wed, 27 Feb 2013, Rasband, Wayne (NIH/NIMH) [E] wrote:
> >
> > > You can redirect System.out and System.err messages to the Log
> > > window by enabling debug mode in Edit>Options>Misc.
> >
> > [...] this interferes with Fiji's stdout/stderr handling. I am fixing
> > it as we speak.
>
> I just tested this Javascript after downloading and starting
> http://imagej.net/ij.jar:
>
> importClass(Packages.java.lang.System);
> System.err.println("Hello");
>
> It did not interfere with Fiji's redirection -- unexpectedly.

I found out why it did not work in my test: I activated the debug mode
using the -debug command-line option. And while it seems that the very
same code was added in three places (ij.macro.Functions#setOption(),
ij.plugin.Options#miscOptions() and ij.text.TextWindow#close(boolean)), it
was not added at the two other places in ij.jar where debugMode can be
activated: ij.macro.Functions#restoreSettings() and
ij.ImageJ#main(String[]).

And of course, all 3rd-party plugins setting IJ.debugMode directly cannot
trigger the redirection automatically. That is why I took pains of
switching on the redirection at all times, mirroring the text to the Log
window only when IJ.debugMode == true.

This is unfortunately not the only issue I fixed in Fiji's redirection and
that frustratingly now crops up again in ImageJ 1.x' reimplementation:

In batch mode, one needs to take great pains to avoid the redirection.
Otherwise, IJ#log(String) will detect that ImageJ is running in batch mode
and print to stdout instead. Which will ask IJ#log(String) to output
again, causing an infinite loop. You can easily reproduce that issue with
this command-line:

        java -jar ij.jar -eval \
                'setOption("debugmode", 1); eval("script", "importClass(Packages.java.lang.System); System.err.println(\"Hello\");");' \
                -batch

Ciao,
Johannes

--
ImageJ mailing list: http://imagej.nih.gov/ij/list.html
Reply | Threaded
Open this post in threaded view
| More
Print post
Permalink

Re: Using System.out and System.err from ImageJ plugins (Java)

dscho
1631 posts
Dear Wayne,

On Wed, 27 Feb 2013, Johannes Schindelin wrote:

> [...] causing an infinite loop. You can easily reproduce that issue with
> this command-line:
>
> java -jar ij.jar -eval \
> 'setOption("debugmode", 1); eval("script", "importClass(Packages.java.lang.System); System.err.println(\"Hello\");");' \
> -batch

An easier command-line that also demonstrates that this is not some looney
idea of mine but a real-world scenario:

        java -jar ij.jar -eval \
                'setOption("debugmode", 1); print("Hello, Wayne");' -batch

I also failed to mention that this just exits without an error message
(but exit code 1) because the exception that is thrown when stack space is
up is swallowed by the fact that Macro_Runner#runMacro(String, String)
cannot print to stderr due to the very infinte loop.

Ciao,
Johannes

--
ImageJ mailing list: http://imagej.nih.gov/ij/list.html
Reply | Threaded
Open this post in threaded view
| More
Print post
Permalink

Re: Using System.out and System.err from ImageJ plugins (Java)

dscho
1631 posts
In reply to this post by dscho
Dear Wayne,

On Wed, 27 Feb 2013, Rasband Wayne wrote:

> On Feb 27, 2013, at 3:29 PM, Johannes Schindelin <[hidden email]> wrote:
>
> > On Wed, 27 Feb 2013, Rasband, Wayne (NIH/NIMH) [E] wrote:
> >
> > I am glad you liked my approach, but I would have preferred it if my
> > code had just been reused... it was unnecessary to reinvent the wheel.
>
> Could you please point me to your code for redirecting System.out and
> System.err? It is not too late to switch.

You can find it here:

http://fiji.sc/cgi-bin/gitweb.cgi?p=fiji.git;a=blob;f=src-plugins/Fiji_Plugins/src/main/java/fiji/util/RedirectErrAndOut.java;h=f3583afdf50183f8351efb87a4583d084b7a0299;hb=refs/heads/master

It does require a class from ij-core:

http://fiji.sc/cgi-bin/gitweb.cgi?p=imagej2/.git;a=blob;f=core/core/src/main/java/imagej/util/LineOutputStream.java;h=9ad0cc2df522504a5455a4d14daf1bb348ce9c56;hb=refs/heads/master

While the first is licensed under GPL (by virtue of being part of the
Fiji_Plugins bundle) and the latter under BSD (2-clause, by virtue of
being part of ImageJ2), both classes were authored by Curtis Rueden
(Cc:ed) and yours truly. I am almost certain that Curtis is okay with
releasing both into the public domain, as required by ImageJ 1.x. I only
humbly request that both be moved into the "ij.*" package structure *1*.

Ciao,
Johannes

Footnote *1*: There is one hack I made to prevent multiple
re-redirections, where RedirectErrAndOut#isRedirected(PrintStream) asks
for the class name of the existing redirection and checks for the prefix
"fiji.". I would really like it if it could ask for both "ij." and "fiji."
and will change it in Fiji's source code right away.

--
ImageJ mailing list: http://imagej.nih.gov/ij/list.html
Reply | Threaded
Open this post in threaded view
| More
Print post
Permalink

Re: Using System.out and System.err from ImageJ plugins (Java)

dscho
1631 posts
In reply to this post by dscho
Dear Wayne,

On Wed, 27 Feb 2013, Rasband, Wayne (NIH/NIMH) [E] wrote:

> On Feb 27, 2013, at 4:24 PM, Johannes Schindelin wrote:
>
> > On Wed, 27 Feb 2013, Johannes Schindelin wrote:
> >
> >> On Wed, 27 Feb 2013, Johannes Schindelin wrote:
> >>
> >>> On Wed, 27 Feb 2013, Rasband, Wayne (NIH/NIMH) [E] wrote:
> >>>
> >>>> You can redirect System.out and System.err messages to the Log
> >>>> window by enabling debug mode in Edit>Options>Misc.
> >>>
> >>> [...] this interferes with Fiji's stdout/stderr handling. I am fixing
> >>> it as we speak.
> >>
> >> I just tested this Javascript after downloading and starting
> >> http://imagej.net/ij.jar:
> >>
> >> importClass(Packages.java.lang.System);
> >> System.err.println("Hello");
> >>
> >> It did not interfere with Fiji's redirection -- unexpectedly.
> >
> > I found out why it did not work in my test: I activated the debug mode
> > using the -debug command-line option. And while it seems that the very
> > same code was added in three places (ij.macro.Functions#setOption(),
> > ij.plugin.Options#miscOptions() and
> > ij.text.TextWindow#close(boolean)), it was not added at the two other
> > places in ij.jar where debugMode can be activated:
> > ij.macro.Functions#restoreSettings() and ij.ImageJ#main(String[]).
>
> I think I fixed these problems (in ImageJ 1.47m9) by adding a
> IJ.setDebugMode(boolean) method and replacing all instances of
> "IJ.debugMode=b" with "IJ.setDebugMode(b)". I also updated the Git
> repository.

Great!

> > And of course, all 3rd-party plugins setting IJ.debugMode directly
> > cannot trigger the redirection automatically. That is why I took pains
> > of switching on the redirection at all times, mirroring the text to
> > the Log window only when IJ.debugMode == true.
>
> Plugins can use IJ.setDebugMode(true).

Of course plugins using newer ij.jar can, but as you know, not everybody
has the luxury of being able to upgrade.

And for backwards-compatibility, the public static boolean needs to be
preserved and it will be all-too-easy to set it directly for plugin
developers.

Nevertheless, I really like that setDebugMode() was added!

> > This is unfortunately not the only issue I fixed in Fiji's redirection
> > and that frustratingly now crops up again in ImageJ 1.x'
> > reimplementation:
> >
> > In batch mode, one needs to take great pains to avoid the redirection.
> > Otherwise, IJ#log(String) will detect that ImageJ is running in batch
> > mode and print to stdout instead. Which will ask IJ#log(String) to
> > output again, causing an infinite loop.
>
> I fixed this, I think, by changing
>
>    } else
>       System.out.println(s);
>
> to
>
>    } else {
>       LogStream.redirectSystem(false);
>       System.out.println(s);
>    }
>
> in the IJ.log() method.

Without having tested it, I fear that this switches off the redirection if
somebody runs a macro that prints anything to the log, even if the debug
mode was not switched off. And even redirecting again after calling
System.out.println() would be dangerous: it is not at all thread-safe.

Hence my insistence on a way to detect whether stdout/stderr is already
redirected.

Ciao,
Johannes

--
ImageJ mailing list: http://imagej.nih.gov/ij/list.html