matlabtiffimagejimagej-hyperstack

How to generate valid HyperStack ImageJ data files from Matlab?


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.


Solution

  • 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.