These are chat archives for fiji/fiji

5th
Aug 2016
Stefan Helfrich
@stelfrich
Aug 05 2016 06:09

@fjug It should be as simple as:

import io.scif.img.IO;
ImgPlus<?> img = IO.openImgs("myInputImage.tif").get(0);
IO.saveImg("myOutputImage.tif", img);

@ctrueden I did some debugging on @fjug's issue yesterday and found out, that the snippet above is not going to work. The IO.open/IO.save methods explicitly create a new context and try to execute in that context which raises

Caused by: java.lang.UnsupportedOperationException: Cannot instantiate more than one LegacyService
(if executed with a context already available..)
Florian Jug
@fjug
Aug 05 2016 10:23
@ctrueden @stelfrich I work around this at the moment with some pretty shady construct that I capsuled in some ImageSaver class of mine. As soon as there is a better (official) way to save images I will be happy to test… so… just ping me, ok?
Curtis Rueden
@ctrueden
Aug 05 2016 12:59
If you are running inside ImageJ already then just use DatasetIOService!
Florian Jug
@fjug
Aug 05 2016 13:03
How would I write code that runs form eclipse and as IJ2 Command then?
Curtis Rueden
@ctrueden
Aug 05 2016 13:07
See simple-commands tutorial.
Florian Jug
@fjug
Aug 05 2016 14:18
Not google nor the search field on imagej.net would lead to to such a tutorial… :(
is search.imagej.net what I should use now?
Florian Jug
@fjug
Aug 05 2016 14:21
Not sure if we understood each other before (sorry for being so imprecise)
Florian Jug
@fjug
Aug 05 2016 14:22
My question really was about how to best write code to save tiff images if I should use DatasetIOService if I am a running ImageJ2 Command and by using IO.save if I am started out of Eclipse...
Curtis Rueden
@ctrueden
Aug 05 2016 14:22
Of course, since you have your own application, you will need to instead instantiate that (rather than net.imagej.ImageJ) and then call its command service.
Florian Jug
@fjug
Aug 05 2016 14:22
ok
Curtis Rueden
@ctrueden
Aug 05 2016 14:22
Do not use the IO utility class at all, since you already have a context.
Instead, use DatasetIOService of that context.
This will avoid the legacy service woes.
That said: I am at this very moment working on loosening the restrictions surrounding the LegacyService.
The next couple of hours will be telling for whether I can do it.
If it works, it will become easier to create additional simultaneous Context objects when the LegacyService is on the classpath.
Right now, as everyone knows, this is a huge PITA.
Florian Jug
@fjug
Aug 05 2016 14:25
I see… alright… I do currently use the ‘hack’ I received yesterday from @stelfrich… depending on your next couple of hours I would then switch to using the DatasetIOService or whatever you’d tell me to have just become state of the art… ;)
Thanks for your precious help Curtis!
Curtis Rueden
@ctrueden
Aug 05 2016 14:28
My pleasure, Florian.
Which "hack" do you mean? I couldn't see it, reading the above.
Stefan Helfrich
@stelfrich
Aug 05 2016 14:28
(using DatasetIOService basically..)
Curtis Rueden
@ctrueden
Aug 05 2016 14:28
The "state of the art" is DatasetIOService of your context, for sure.
And it will continue to be so. You should always use the services of your application context, to do stuff.
Really, it is IO that is a hack -- for convenience, if you have no context and don't want to be bothered to make one.
Stefan Helfrich
@stelfrich
Aug 05 2016 14:29
And it is clearly stated in the javadocs so
Florian Jug
@fjug
Aug 05 2016 14:37
True… the javadocs state it clearly… the hack:
        final DatasetService datasetService = context.getService( DatasetService.class );
        final Dataset dataset = datasetService.create( rai );
        final DatasetIOService service = context.getService( DatasetIOService.class );
        try {
            service.save( dataset, filename );
        } catch ( final IOException exc ) {
            exc.printStackTrace();
        }
(Which might not be a hack… (?))
Curtis Rueden
@ctrueden
Aug 05 2016 14:38
That looks great to me, @fjug.
Except for the printStackTrace part...
I would at minimum use LogService. And better is to handle the exception in your UI somehow.
Florian Jug
@fjug
Aug 05 2016 14:38
Good! :sun_with_face:
True… I have to switch to using LogService soon… (but that is a general problem of my project at the moment)
Curtis Rueden
@ctrueden
Aug 05 2016 14:39
BTW, the alternative to making getService calls is to use @Parameter fields in your objects.
Florian Jug
@fjug
Aug 05 2016 14:40
But they would only get injected if they are run from within Fiji/Imagej2...
Curtis Rueden
@ctrueden
Aug 05 2016 14:40
Aesthetically, I prefer it. And functionally, the difference boils down to when things will fail—early or late—if services are missing.
You can all context.inject(mySpiffyObject) any time.
Florian Jug
@fjug
Aug 05 2016 14:40
Ohhhh...
Curtis Rueden
@ctrueden
Aug 05 2016 14:40
And if you make your object extend AbstractContextual then you can make the constructor take the Context and call setContext(context) there.
Florian Jug
@fjug
Aug 05 2016 14:40
I will have to metabolize this option...
Curtis Rueden
@ctrueden
Aug 05 2016 14:40
And it will do the injection.
The advantage of this is that it is explicit in the object's construction that a context is required for it.
But if you don't really need certain services, it is best to mark them as required = false and then null test them when you use them.
Otherwise, the constructor will fail with "required service not found"
Make sense?
Florian Jug
@fjug
Aug 05 2016 14:41
Yes.
making notes
;)
Curtis Rueden
@ctrueden
Aug 05 2016 14:42
(And if you cannot extend AbstractContextual because you already need to extend something else, then you can still pass the Context in the constructor and call context.inject(this) in the constructor. Works just fine.)
Starting next week, @etarena and I are going to work on a unified development manual / tutorial which covers this stuff more explicitly.
Florian Jug
@fjug
Aug 05 2016 14:46
Sounds great! Random idea: write a Command that loads an tiff, scales that tiff, saves it.
Such that the App can be called directly from Eclipse...
…then deployed to fiji via mvn...
…uploaded to personal update site...
…and runs there as well.
That would have helped me a lot in the last 2 days.
I’m happy to contribute (e.g. by test-running it).
Just let me know.
Curtis Rueden
@ctrueden
Aug 05 2016 15:57
@fjug For you: imagej/imagej-tutorials@0676466
Sorry about the Dataset/Img conversion crap. This will become easier as the ImageJ data model work progresses.
This example also demonstrates a couple of other areas where improvement would be nice: 1) interpolators as SciJava plugins, so we don't need case logic; 2) simpler transform.scale method signature(s).
Curtis Rueden
@ctrueden
Aug 05 2016 16:12
And 3) The fact that strangely, we are missing a converter plugin from Img and ImgPlus to Dataset (we have it in the other direction).
Curtis Rueden
@ctrueden
Aug 05 2016 16:33
Woo hoo! imagej/imagej-legacy@c0c40bf
It works! You can write IO.openImg from a script inside ImageJ now, without the horrible LegacyService error!
Florian Jug
@fjug
Aug 05 2016 17:08
@ctrueden YEAH!!! I need to run now (or I will get divorced instantly), but I will check that out ASAP!!! :clap:
Have a nice weekend!!!