Part of the Oxford Instruments Group
Expand

Imaris File Format Description (IMS)

The Imaris File Format is designed to allow fast visualization of very large images. For this purpose it stores not only the original image data but also lower resolution versions of the original data. This allows the visualization software to load only low resolution data when those are sufficient. Also for the purpose of fast visualization the Imaris File Format stores the image data in contiguous 3D chunks (hdf-terminology for 3D blocks) which allows the visualization software to load only those data that are in the field of view. The multiresolution structure and the chunk-wise storage layout are the cornerstones of this high performance file format.

Summary

The file format is based on the standard HDF5 (Hierarchical Data Format 5) developed by The National Center for Supercomputing Applications, University of Illinois at Urbana-Champaign. This allows the use of widely available HDF5 libraries and tools.

An Imaris 5.5 file consists of three main types of groups (or folders) for the image:

An additional group may contain the Imaris Scene:

In this document, the terms group, attribute and dataset refer to the concepts given in the HDF5 documentation. Whenever a path is given (/DataSet/ResolutionLevel 12) one should open the corresponding groups and subgroups.

The prior “Imaris Classic” and “Imaris3” file formats are not based on the HDF5 specifications and will not be described in this document.

Tools and Resources

Bitplane uses the HDF5 library from the HDF Group as a backend for reading and writing HDF5 files. A good starting point for reading about the HDF5 file format is the website of the HDF5 Group, http://www.hdfgroup.org/HDF5/. The HDF Group provides its library as open source and free of charge. It is recommended to make use of the library rather than creating your own HDF5 reader/writer.

The HDF Group also provides helpful tools along with the library. Noteworthy is HDFView, a java-based HDF file inspector. It can be downloaded free of charge here.

It is highly recommended to use HDFView to look at some example IMS files in order to gain an understanding of the file format.

Structure

The Imaris 5.5 file structure is composed of a root “folder” and three main groups, DataSet, DataSetInfo, and Thumbnail.

The screenshot on the right of an IMS file in HDFView shows the HDF file structure. The example image has two channels and 3 resolution levels.

The DataSet folder contains the actual image data. The DataSetInfo folder contains descriptive parameters. The Thumbnail folder contains a 2D thumbnail of the image.

Path Attribute Value Description
/ ImarisDataSet ImarisDataSet Specific to format
FormatVersion 5.5.0 Format version
/DataSetInfo Contains DataSet information
/Thumbnail Contains the Thumbnail dataz

DataSet

An Imaris 5.5 DataSet has the following structure. A Dataset consists of one or more 3D images (for 2D images the size of one dimension is equal to 1). When a dataset has multiple channels or multiple time points it stores 3D images for each channel and each time point. Datasets are saved in the file using chunks (see HDF5 documentation) and can optionally be compressed using GNU GZIP. For good reading performance, chunks must be stored in the size that the Imaris Software requests for visualization (see chapter Imaris Datablocks below).

The HDF5 chunks mechanism implies that the effective size of the Dataset can be bigger than the size of the original 3D image. Thus, the attributes ImageSizeZ, ImageSizeY and ImageSizeX are also saved with each Dataset.

The type of the Dataset needs to resemble the type of data to be stored. Valid types are listed in the following table.

HDF5 Data type Imaris Image Data type
H5T_NATIVE_UCHAR 8 bit unsigned integer (char)
H5T_NATIVE_USHORT 16 bit unsigned integer (short)
H5T_NATIVE_UINT32 32 bit unsigned integer
H5T_NATIVE_FLOAT 32 bit floating point

The creation attributes for the Dataset should be chunked, storage allocation time incremental, fill value none, compression none or GZIP. If GZIP compression is activated, any valid GZIP parameter may be used (i.e. compression 0 to 9 is acceptable, 3 is preferred).

Along with each 3D image, the corresponding histogram is saved as well (see table below). The histogram is a HDF5 1D Dataset of type 64bit unsigned integer. Its length can be read out using the HDF5 library. The first value corresponds to the count of value HistogramMin in the image. The last value is the count of HistogramMax in the image.

Path Attribute Description
/DataSet/ResolutionLevel 0/TimePoint 0/Channel 0 Informations concerning resolution 0, time point 0 and channel 0
ImageSizeX = 285 The size in X in pixel for Resolution Level 0
ImageSizeY = 218 The size in Y in pixel
ImageSizeZ = 64 The size in Z in pixel
ImageBlockSizeX = 64 The size of a image block in X in pixel for resolution level 0 (alpha version only) - deprecated
ImageBlockSizeY = 256 The size of a image block in Y in pixel(alpha version only) - deprecated
ImageBlockSizeZ = 64 The size of a image block in Z in pixel(alpha version only) - deprecated
HistogramMin = 0 The minimal value of the histogram corresponding to this image
HistogramMax = 255 The maximal value of the histogram
/DataSet/Resolution Level 0/TimePoint 0/Channel 0/Data THE image, with size ImageSizeX*ImageSizeY*ImageSizeZ
/DataSet/Resolution Level 0/TimePoint 0/Channel 0/Histogram The histogram of the image. The first bin corresponds to HistogramMin and the last bin to HistogramMax
/DataSet/ResolutionLevel 0/TimePoint 0/Channel 1 Informations concerning resolution 0, time point 0 and channel 1
/DataSet/ResolutionLevel 0/TimePoint 0/Channel 0/Data Image data for resolution 0, time point 0 and channel 0
/DataSet/ResolutionLevel 0/TimePoint 0/Channel 0/Histogram Image histogram for resolution 0, time point 0 and channel 0

Example:

mFileId = H5Fopen(mFileName.c_str(), H5F_ACC_RDONLY, H5P_DEFAULT);
hid_t vDataSetId = H5Gopen(mFileId, “DataSet”);
hid_t vLevelId = H5Gopen(vDataSetId, “Resolution Level 0”);
hid_t vTimePointId = H5Gopen(vLevelId, "TimePoint 0");
hid_t vChannelId = H5Gopen(vTimePointId, "Channel 0");
hid_t vDataId = H5Dopen(vChannelId, “Data”);
// read the attributes ImageSizeX,Y,Z hsize_t vFileDim[3] = {ImageSizeZ, ImageSizeY, ImagesizeX};
hid_t vFileSpaceId = H5Screate_simple(3, vFileDim, NULL); char* vBuffer = new vBuffer[ImageSizeZ*ImageSizeY*ImageSizeX];
H5Dread(vDataId, H5T_NATIVE_CHAR, H5S_ALL, vFileSpaceId, H5P_DEFAULT, vBuffer);

In the above example, the whole 3D image corresponding to resolution 0, time point 0 and channel 0 is read. Using the HDF5 library it also possible to read only part of the image, for memory or other requirements

DataSetInfo

The DataSetInfo group contains all the image parameters from Imaris. The sections are stored as HDF5 groups, parameters are stored as HDF5 attributes. Hdf5 attributes can be opened using H5Aopen_name and read using H5Aread. All attributes are stores as type string, i.e. numbers have to be converted to string. The HDF5 type for attributes is an array of H5T_C_S1 (C String).

In the following, the term “LSM" is used as an abbreviation of “Laser Scanning Microscope”.

Group / Section Name Attribute / Parameter Name Description
ImarisDataSet This section holds information about the data organization in the file. (always present)
Creator = Imaris
NumberOfImages = 1 At the moment there is only one multi-channel-time image per file
Version = 5.5 The version of Imaris which created this file
Imaris Information about the thumbnail and Imaris. (always present)
Filename = retina.ims The name of the original file
ManufactorString = Generic Imaris 3.x Manufactor information
ManufactorType = LSM Manufactor type information
ThumbnailMode = thumbnailMIP The type of data representation of the thumbnail. Valid values are "thumbnailNone", "thumbnailMiddleSection", "thumbnailMIP" or "thumbnailNone".
Version = 5.5 The version of Imaris which created this file
Image Information about the DataSet. (always present)
Description = nucleus Detailed description of the image in plain text (can be multiple lines)
ExtMax0 = 46.7464 Data max. extension X (in given units: um, nm, …)
ExtMax1 = 35.7182 Data max. extension Y
ExtMax2 = 12.6 Data max. extension Z
ExtMin0 = -10.3 Data origin X
ExtMin1 = -1.5 Data origin Y
ExtMin2 = 3.4 Data origin Z
LensPower = 63x Deconvolution parameter
Name = m1193.pic Short description of the image (some characters)
Noc = 2 Number of channels
RecordingDate = 1991-10-01 16:45:45 “YYYY-MM-DD HH:MM:SS”
Unit = um "m“, "mm“, "um“ or "nm“
X = 285 Image Size X (in voxels)
Y = 218 Image Size Y (in voxels)
Z = 64 Image Size Z (in voxels)
Channel X Information about channel X (there is one section per channel) (always present)
Color = 1 0 0 The base color (r,g,b float values from 0.0 to 1.0)
ColorMode = BaseColor “BaseColor”, “TableColor” see example below for the color table mode.
ColorOpacity = 0.168 The opacity with which the volume rendering displays the channel (float value from 0.0 to 1.0)
ColorRange = 0 194.921 The display “contrast”
Description = Cy5 Detailed description of the channel
Gain = 0 Deconvolution parameter
LSMEmissionWavelength = Emission Wavelength
LSMExcitationWavelength = Excitation Wavelength
LSMPhotons = Deconvolution parameter
LSMPinhole = Pinhole diameter
Max = 255 The data maximum value of the channel image
MicroscopeMode = Deconvolution parameter
Min = 0 The data minimum value of the channel image
Name = CollagenIV (TxRed) Short description of the channel (some chars)
NumericalAperture = Numerical Aperture
Offset = 0 Deconvolution parameter
Pinhole = 0 Deconvolution parameter
RefractionIndexEmbedding = Deconvolution parameter
RefractionIndexImmersion = Deconvolution parameter
TimeInfo Information about time for all channels. (always present)
DataSetTimePoints = 1 The number of time points in the DataSet
FileTimePoints = 1 The number of time points in the file (currently the same as DataSetTimePoints)
TimePoint1 = 1991-10-01 16:45:45.000 Time for time point 1. Time must be strictly increasing between time points.
Log Any information about the history of the image (especially the data manipulation).
Entries = 3 Number of entries (number of image data modifications). Can be zero.
Entry0 = First modification
Entry1 = Second modification
Entry2 = Third modification

Note that any other group/section can be available depending on the original file format (Olympus, Zeiss etc)

Example to read LSMEmissionWavelength of Channel 3

mFileId = H5Fopen(mFileName.c_str(), H5F_ACC_RDONLY, H5P_DEFAULT);
// open DataSetInfo group
hid_t vDataSetInfoId = H5Gopen(mFileId, “DataSetInfo”);
// open channel 3 group
hid_t vChannel3Id = H5Gopen(vDataSetInfoId, “Channel 3”);
// open attribute LSMEmissionWavelength
hid_t vAttributeId = H5Aopen_name(vChannelId, “LSMEmissionWavelength”);
// get data space
hid_t vAttributeSpaceId = H5Aget_space(vAttributeId);
// get attribute value size
hsize_t vAttributeSize = 0;
H5Sget_simple_extent_dims(vAttributeSpaceId, &vAttributeSize, NULL);
// create buffer
char* vBuffer = new char[(bpSize)vAttributeSize+1];
vBuffer[vAttributeSize] = '\0';
// read attribute value
H5Aread(vAttributeId, H5T_C_S1, vBuffer); 

Thumbnail

The thumbnail directory contains a 2D, square RGBA image, of arbitrary size (typical values being 128x128 or 256x256). The image data for a thumbnail of size W should be read using a buffer of unsigned char with a size of W x W x 4 (with H5Dread). The HDF5 dataset size is W rows and W x 4 columns. Each image pixel is stored as 4 HDF5 values, in the order Red, Green, Blue and Alpha component.

Example

// open the group where the thumbnail stuff is
H5Gopen(mFileId, “Thumbnail”);
// get the dataset
hid_t vThumbnailDataId = H5Dopen(vThumbnailId, "Data");
// get the dataspace
 hid_t vThumbnailSpaceId = H5Dget_space(vThumbnailDataId);
// get the size of data
hsize_t vThumbnailDims[2];
 H5Sget_simple_extent_dims(vThumbnailSpaceId, vThumbnailDims, NULL);
char* vBuffer = new char[(bpSize)(vThumbnailDims[0] * vThumbnailDims[1])];
// read the thumbnail data
H5Dread(vThumbnailDataId, H5T_NATIVE_UCHAR, H5S_ALL, H5S_ALL, H5P_DEFAULT, vBuffer);
// create image
vThumbnail = new image(vThumbnailDim[1]/4, vThumbnailDim[0]);
for all thumbnail pixel {
 vThumbnail[vPixel].Red = vBuffer[vIndex];
vThumbnail[vPixel].Green = vBuffer[vIndex+1];
vThumbnail[vPixel].Blue = vBuffer[vIndex+2];
 vThumbnail[vPixel].Alpha = vBuffer[vIndex+3];

Data

The multiresolution structure and the chunk-wise storage layout are the cornerstones of this high performance file format.

Chunk Size

For efficient data access for visualization the Imaris 5.5 file format stores image data in 3D chunks. Typical chunk sizes are 128x128x64 or 256x256x16. The optimal chunk size is determined by the geometry of the image and it is not easy to specify rules for reproducing exactly the chunk sizes that Imaris will write into the hdf-file. It is also not necessary because the hdf library is very efficient at reading data as long as the layout is not entirely different. If you want to write image files for Imaris to read, try to create 3D chunks that are of roughly 1 Megabyte size. This will produce good results for rendering in Imaris. If you need to tweak performance, please contact the Bitplane engineering team to get more detailed information.

Resolution Levels

For efficient visualization the Imaris 5.5 file format stores not only the original data but also low resolution versions of the original data. The number of resolution levels in the file is determined by the following pseudocode:

void getMultiResolutionPyramidalSizes( const size_t[3] aDataSize,
std::vector& aResolutionSizes)
{
const float mMinVolumeSizeMB = 1.f;
aResolutionSizes.clear();
size_t[3] vNewResolution = aDataSize;

float vVolumeMB;
do {
 vResolutionSizes.push_back(vNewResolution);
size_t[3] vLastResolution = vNewResolution;
size_t vLastVolume = vLastResolution[0] * vLastResolution[1] * vLastResolution[2];
for (int d = 0; d < N; ++d) {
if ((10*vLastResolution[d]) * (10*vLastResolution[d]) > vLastVolume / vLastResolution[d])
vNewResolution[d] = vLastResolution[d] / 2;
else
 vNewResolution[d] = vLastResolution[d];
// make sure we don't have zero-size dimension
vNewResolution[d] = std::max((size_t)1, vNewResolution[d]);
 }
vVolumeMB = vNewResolution[0] * vNewResolution[1] * vNewResolution[2]) / (1024.f * 1024.f);
} while (vVolumeMB > mMinVolumeSizeMB);
}