2

ImageJ HyperStacks have a data type (8-32 bit), a width, a height, a number of channels, a number of slices and a number of frames. They represent 5D (XYCZT) data sets. ImageJ stores them as multipage tiff files where number of channels times number of slices times number of frames 2D (XY) images are stored. The first image seems to have two custom tags with IDs 50838 and 50839.

I want to create tif files containing 5D data from Matlab that can be read by ImageJ as a valid 5D HyperStack.

I can store a number of 2D images in a multipage tiff file in Matlab using imwrite(matrix, file, 'WriteMode','append') but ImageJ will read that as 3D (XYZ) image stack only. The information about the channels, slices and frames is not contained.

I guess I could look at the ImageJ sources to find out where they store this missing information, then use Matlab's wrapper of LibTIFF to recreate the meta information of ImageJ. If you, however, already know what to do or if there is an alternative, I would like to hear it.

NoDataDumpNoContribution
  • 10,591
  • 9
  • 64
  • 104

3 Answers3

3

I also thought that Bio-Fomats was the only way. But then I realized that Fiji's ImageJ-MATLAB allows you to pass MATLAB data to ImageJ. Then, you can save the image by ImageJ, so ImageJ can open it for sure.

The problem was that people (or just one guy?) created ImageJ-MATLAB did a great job in creating a route from MATLAB to ImageJ, but they didn't seem to bother optmizing the behaviour. ImageJ-MATLAB's IJM.show('name') had a lot of hidden or undocumented limitations (I massively changed the documentation, so it should be clearer now). Eventually, I enede up wriring a wrapper function

ijmshow

https://github.com/kouichi-c-nakamura/ijmshow

Example MATLAB code

You can do it with 4 lines.

addpath '/Applications/Fiji.app/scripts' % depends your Fiji installation
ImageJ

imp = ijmshow(I,'YXCZT') % I is 5D array of uint8 or uint16
% the second argument determines which dimension represents what
% imp is a 5D hyperstack

ij.IJ.saveAsTiff(imp, 'image1.tif');

You may want to set Display Range of each channel before saving.

Added on 5/7/2018

copytoImagePlus provides better solution than ijmshow above (you can use the same syntax), because copytoImagePlus does not rely on the IJM variable in the base workspace anymore.

https://github.com/kouichi-c-nakamura/copytoImagePlus

addpath '/Applications/Fiji.app/scripts' % depends your Fiji installation
ImageJ

imp = copytoImagePlus(I,'YXCZT') % I is 5D array of uint8 or uint16
% the second argument determines which dimension represents what
% imp is a 5D hyperstack

ij.IJ.saveAsTiff(imp, 'image1.tif');

Also see copytoImgPlus which create ImageJ2 ImgPlus object instead.

https://github.com/fiji/fiji/blob/master/scripts/copytoImgPlus.m

Kouichi C. Nakamura
  • 850
  • 3
  • 10
  • 25
  • I just wrote this function yesterday, so I'll appreciate your feedback, positive or negative! – Kouichi C. Nakamura May 04 '18 at 01:30
  • I tested it. I was surprised to see that Fiji already has a Matlab bridge. However, it's not a well trodden path. Warnings, errors, non-closable stack windows and unreliably also Java exceptions (Fiji 1.52d with Matlab 2017b on Windows)). I would not use it for production yet. – NoDataDumpNoContribution Jul 05 '18 at 13:26
  • Most reliable way so far for me is the Bioformats Matlab plugin. – NoDataDumpNoContribution Jul 05 '18 at 13:27
  • 2
    I had that impression as well, so I ended up adding lots of text to [the documentation of ImageJ-MATLAB](https://imagej.net/MATLAB_Scripting) and wrote essential functions above to link ImageJ and MATLAB. If you know you're not going to use more than 5D, `copytoImagePlus` is what you need. In my memory, bio-formats did not handle 5D stack images very well either. To start with, `bfopen` does not support hyperstack. I was quite surprised. – Kouichi C. Nakamura Jul 05 '18 at 17:19
  • Thanks for adding the stuff. Currently I just need a quick, reliable solution while exporting tons of data. Maybe later I could help, for example with writing some tests/demos from the Matlab site. – NoDataDumpNoContribution Jul 06 '18 at 08:26
2

ImageJ uses the ImageDescription tag of the TIFF's first IFD to store its meta-information. Here is an example from the Mitosis sample dataset (File > Open Samples > Mitosis):

ImageJ=1.51d
images=510
channels=2
slices=5
frames=51
hyperstack=true
mode=composite
unit=\u00B5m
finterval=0.14285714285714285
loop=false
min=1582.0
max=6440.0

MATLAB's Tiff class might give you fine-grained enough control to write a custom ImageDescription to the first IFD; I am not sure.

Probably easier would be to use the Bio-Formats library's bfsave.m function to write OME-TIFF, which can be 5-dimensional; ImageJ can read this format via the Bio-Formats plugin. I recommend using the Fiji distribution of ImageJ, which comes with Bio-Formats pre-installed.

There was also this same question posted on MATLAB Central.

ctrueden
  • 6,751
  • 3
  • 37
  • 69
1

Using Matlab's Tiff class.

I can assemble an ImageDescription tag that I think looks fine and ImageJ reads it (File>Open) as a 5D Hyperstack but the data is partly corrupted. There seem to be offset problems (I can read the data just fine in again with Matlab).

However, if reading the tiff file with File>Import>Bio-Formats it becomes 5D (XYCZT) stack in ImageJ if view stack with Hyperstack is marked in the Bio-Formats import dialog. Thanks to ctrueden for his helpful comment.

d = ones(100, 200, 10, 2, 3, 'single') * 3.765;
hyperstack_write('test.tif', d);

function hyperstack_write(file, hyperstack)
% Writes an (up to) 5D stack into a (XYCZT) HyperStack Tiff file
% readable by ImageJ
%
% hyperstack must have class single

% simple checks
assert(nargin == 2, 'Not enough arguments');
assert(isa(hyperstack, 'single'), 'hyperstack must be single');

% get all five dimensions
d = zeros(5, 1);
for i = 1 : 5
    d(i) = size(hyperstack, i);
end

% assemble image description
s = sprintf('ImageJ=1.51\nnimages=%d\nchannels=%d\nslices=%d\nframes=%d\nhyperstack=true\nmode=color\nloop=false\nmin=%.1f\nmax=%.1f\n', prod(d(3:5)), d(3), d(4), d(5), floor(min(hyperstack(:))*10)/10, ceil(max(hyperstack(:))*10)/10);

% open tif file for writing and set file tags
t = Tiff(file, 'w');

ts.ImageLength = d(1);
ts.ImageWidth = d(2);
ts.Photometric = Tiff.Photometric.MinIsBlack;
ts.Compression = Tiff.Compression.None;
ts.BitsPerSample = 32;
ts.SamplesPerPixel = 1;
ts.SampleFormat = Tiff.SampleFormat.IEEEFP;
ts.RowsPerStrip = 5;
ts.PlanarConfiguration = Tiff.PlanarConfiguration.Chunky;
ts.Software = 'MATLAB';
ts.ImageDescription = s;

% loop over dimensions 3, 4, and 5
for k = 1 : d(5)
    for j = 1 : d(4)
        for i = 1 : d(3)
            frame = hyperstack(:, :, i, j, k);
            t.setTag(ts)            
            t.write(frame);
            t.writeDirectory();
        end
    end
end

% close tif file
t.close();

end

It seems Bio-Formats is the only fully paved and available way to export >2D data from Matlab to ImageJ, although this solution here could be a lightweight alternative in cases where not much metadata is available and needs to be transferred.

NoDataDumpNoContribution
  • 10,591
  • 9
  • 64
  • 104
  • 1
    Did you try reading your TIFF in ImageJ using SCIFIO (_File > Import > Image..._) or Bio-Formats (_File > Import > Bio-Formats_)? ImageJ 1.x's built-in TIFF reader, which is preferentially used by _File > Open..._, cannot handle the full baseline TIFF specification. See this page for details: https://imagej.net/TIFF – ctrueden Dec 01 '17 at 15:29
  • 1
    @ctrueden Using Fiji I used *File>Open* which gave me the broken HyperStack, *File>Import>SCIFIO" flattens the 5D structure into a 3D structure but shows no other artifacts and *File>Import>Bio-Formats* actually did the right thing. Thanks alot. – NoDataDumpNoContribution Dec 07 '17 at 15:48