Well-known Image processing and visualization packages like ImageJ/FIJI and Icy use it as default I/O.
Briefly, it is indispensible there, and if a convenient bridge to Bioformats existed in Julia, that would be great invitation to Bioimaging community.
I looked at JavaCall project but found that it isn’t enough, as it can’t keep Java objects.
We work with Bioformats basic OME.tiff format that Julia can open, but unfortunately without access to the metadata.
So I even think about compiling some standalone metadata grabbing command-line utility in Java or Matlab, to save metadata to file and then open it in Julia. This is clumsy.
I’m new to Julia, so maybe I’m missing something very crucial, here?
I think sooner or later, the Bioformats question would appear anyway from someone else.
Yes, getting support for Bioformats seems quite important. There was some discussion about this at last year’s JuliaCon, but I don’t think anything has moved forward yet and I haven’t looked at this myself. I’ve never used JavaCall (or Java, for that matter), but do the JavaObjects not provide a mechanism to achieve this?
I’ve also heard rumors that a rewrite of BioFormats in C++ was in the works, but I haven’t followed its development.
haven’t heard about that.
In Matlab you simply get Java objects and voila.
Bioformats C++ covers OME.tiff only.
BTW would be enough for me, but, as they only added support for crucial pieces of metadata couple of weeks ago? risky…
Microscopy uses tons of other formats.
and my intention was exactly the opposite, to escape horrors of C++ syntax while designing algorithms.
…
If you look at the usage demo in JavaCall.jl -- Call Java from Julia, gurl appears to be a stateful Java object. You can read more about JavaObject on the Types and Methods pages. Will those do what you want?
not sure.
as I understand, the whole set of recipes, is it named API, for creating Java objects is stored in corresponding jar files.
they have that magic single file now, named “bioformats_package.jar” AFAIR.
if access to what is inside is supported then yes.
maybe I just don’t know how to call it correctly. would be good.
…
Given my lack of any kind of Java experience, I’m afraid I’m not going to be much help here. If you don’t get an answer from someone who knows more, maybe try opening an issue over at JavaCall.
Also, I suspect you’re familiar with these already, but in case not: FileIO may be useful towards the end stages of this project, and if you encounter trouble ImageMagick might be a useful model.
these packages do open images as XYZ arrays, but the problem is metadata.
the same image Bioformats interpret as having 5 dimensions - XYZCT (+channel, +time)
and we have additional attributes/indices for FLIM time gate delay, and tomography projection angle, packed into T and Z.
I’ll open issue at JavaCall in Monday.
…
JavaCall.jl works by creating an instance of JVM and calling Java through JNI. Except for a few corner cases, you can do from Julia whatever you can do from Java itself. Do you have example code in Java to read image and metadata?
Encoding the “meaning” of the axes is no sweat; among programming languages, I suspect we’re in unusually good shape. See ImageAxes, ImageMetadata, and AxisArrays. For a model, you can check NRRD to see how it handles metadata. We need to get color-channel information as the first dimension, but you can always use permutedims or, for images too big to store in memory at once, permuteddimsview. For now, things like FLIM parameters and tomography projection angle are probably best stored in an ImageMeta.
Also, ImageMagick does have a magickinfo function for querying metadata. It’s pretty simple, but the general idea of having some kind of info function seems almost necessary for Bio-Formats.
yes certainly - but I have it actually in Matlab. https://github.com/yalexand/Imperial-OMEkit
(in project itself there are lot of garbage, but also a functional feature, too… hidden…)
here is the function reading angles:
function ret = get_angles(obj,full_filename,~)
ret = [];
try
r = loci.formats.ChannelFiller();
r = loci.formats.ChannelSeparator(r);
OMEXMLService = loci.formats.services.OMEXMLServiceImpl();
r.setMetadataStore(OMEXMLService.createOMEXMLMetadata());
r.setId(full_filename);
%
modlo = r.getModuloZ();
if ~isempty(modlo)
if ~isempty(modlo.labels)
ret = str2num(modlo.labels)';
end
if ~isempty(modlo.start)
if modlo.end > modlo.start
nsteps = round((modlo.end - modlo.start)/modlo.step);
ret = 0:nsteps;
ret = ret*modlo.step;
ret = ret + modlo.start;
end
end
end
catch
end
end
to open OME.tiff file, we do something like in this excerpt:
try
omedata = bfopen(full_filename);
catch err
%
end
if ~isempty(omedata)
r = loci.formats.ChannelFiller();
r = loci.formats.ChannelSeparator(r);
OMEXMLService = loci.formats.services.OMEXMLServiceImpl();
r.setMetadataStore(OMEXMLService.createOMEXMLMetadata());
r.setId(full_filename);
r.setSeries(0);
omeMeta = r.getMetadataStore();
obj.PixelsPhysicalSizeX = 1;
obj.PixelsPhysicalSizeY = 1;
try
obj.PixelsPhysicalSizeX = omeMeta.getPixelsPhysicalSizeX(0).getValue;
obj.PixelsPhysicalSizeY = omeMeta.getPixelsPhysicalSizeY(0).getValue;
catch
disp('no PixelsPhysicalSize info, set to 1');
end
imgdata = omedata{1,1}; % actual stack of XY planes
n_planes = length(imgdata(:,1));
% etc. etc.
here “r” is the “reader” object that also may be returned by bfGetReader function, which is the part of “bfmatlab.zip” package, as well as “bfopen”.
The package was designed by Sebastien Besson.
I think some of our file opening excerpts may be in Java, but the whole idea is that in any place in the code you can create reader like here
the matter is, our acquisition software uses tools like MicroManager and LabView, the convention on output is OME.tiff and Bioformats and for now I don’t see how that can change. but always good to know about alternatives, thanks.
…
using JavaCall
try
# init JVM wtih bioformats_package.jar on classpath
JavaCall.init(["-ea", "-Xmx1024M", "-Djava.class.path=bioformats_package.jar"])
end
# import java classes
const JChannelFiller = @jimport loci.formats.ChannelFiller
const JChannelSeparator = @jimport loci.formats.ChannelSeparator
const JOMEXMLServiceImpl = @jimport loci.formats.services.OMEXMLServiceImpl
const JOMEXMLMetadata = @jimport loci.formats.ome.OMEXMLMetadata
const JOMEXMLService = @jimport loci.formats.services.OMEXMLService
const JMetadataStore = @jimport loci.formats.meta.MetadataStore
# example of how get_angles function may look like
function get_angles(obj, full_filename)
ret = []
try
# same as `new ChannelFiller()`
# empty tuple `()` here means that constructor doesn't take any args
r = JChannelFiller(())
# same as new ChannelSeparator(r)
# again, first argument - `(JChannelFiller,)` - a tuple of input types
# the rest - `r` - is a list of actual arguments
r = JChannelSeparator((JChannelFiller,), r)
# same as `new OMEXMLServiceImpl()`
OMEXMLService = JOMEXMLServiceImpl(())
# same as `meta = OMEXMLService.createMEXMLMetadata()`
meta = jcall(OMEXMLService, "createOMEXMLMetadata", JOMEXMLMetadata, ())
# same as `r.setMetadataStore(meta)`
jcall(r, "setMetadataStore", Void, (JMetadataStore,), meta)
...
end
end
As you may guess, I know nothing about the domain or BioFormats, so it’s mostly just a hint for you to see how it may look like. Basically, you need to learn how to:
Add .jar files using JavaCall.init()
Import Java classes using @jimport.
Create new objects using constructor syntax, e.g. r = JChannelFiller(()).
Call methods using jcall, e.g. jcall(r, "setMetadataStore", Void, (JMetadataStore,), meta).
So I think it’s pretty doable.
Note that this example requires bioformats_package.jar and some other lib because creating ChannelFiller throws:
I didn’t mean you should use that function, I just meant there’s a precedent for having a separate function to query metadata (i.e., outside the load/save API of FileIO).
this is superb!!
albeit, when I think about amount of work Sebastien did to design bfMatlab… it’s a lot.
when there is opportunity I’ll try to investigate it further, as it really looks practical.
but, to get it at the same level of convenience, like “bfJulia”, - someone will need to allocate an FTE, possibly in sort of, joint project with Bioformats team? not joking, they may be interested.
may I say Julia community way exceeded my expectations in every topic I pasted.
wow.
I used bfMatlab in many places and it is always pleasure.
opens every murky proprietary microscope format.
I think Melissa Linkert who is in charge of Bioformats, deserves a Damehood for this work.
not joking again.
already quite Kantian, but still not a meritocracy.
…