- Status of this document: release candidate
- Editor: Yael Balbastre <y.balbastre at ucl.ac.uk>
- Version: 1.0.rc1
This document specifies the nifti-zarr format for storing neuroimaging data in the cloud.
- References
- Introduction
- Format Specification
- Main differences with NIfTI and/or OME-NGFF
- Conversion tables
- Reference implementations
- Zarr is a format for the storage of chunked, compressed, N-dimensional arrays inspired by HDF5, h5py and bcolz.
- OME-NGFF (Next Generation File Format) is a format based on zarr for the storage of biomedical imaging data.
- NIfTI (Neuroimaging Informatics Technology Initiative) is a single-file/single-resolution storage format for 3D+ neuroimaging data.
- JNIfTI is a pure JSON implementation of the NIfTI format.
- BIDS (Brain Imaging Data Structure) is a simple and intuitive way to organize and describe data.
As biomedical imaging scales up, it is increasingly making use of remote storage, remote computing and remote visualization. Classical file formatsβwhich store array data contiguously in a single fileβare limited at large scales as
- They often do not store data at multiple resolutions;
- They do not offer efficient parallel access to data chunks;
- They do not efficiently compress 3D raster data.
These limits are very clear when it comes to visualizing very large data volumes, which cannot be loaded in memory in full. In this context, it is preferable to only load the data required to display a given scene (either a large field-of-view at low-resolution, or a small field-of-view at high resolution).
The Zarr format was developed to bypass the limitations of single-file formats such as HDF5. The microscopy community is currently developping its own standard for cloud-friendly biomedical imaging data (OME-NGFF)βwith a Zarr-based implementationβ and adds rules for storing multi-resolutions images and medical-specific metadata such as axis names and voxel sizes. However, this community has needs in terms of metadata and coordinate-space description that are relatively complex, as they need to conform to different organs, a wide range of acquisition systems, and different tissue processing pipelines. This has drastically slowed down the adoption of a coordinate transform standard, which hampers the use of OME-NGFF with neuroimaging data in two ways:
- at the time of this writing, the current version of the format (0.5) only handles canonical scales and offsets;
- the coordinate transform standard being drafted is more flexible than required for pure neuroimaging applications, which may prevent its widespread adoption by the neuroimaging community.
In contrast, the neuroimaging community has adopted and used a standard "world" coordinate frame for decades, where
+x = left -> right
+y = posterior -> anterior
+z = inferior -> superior
An affine transform is used to map from the F-ordered voxel space
Let us further add that OME-NGFF is mostly oriented towards microscopy, whereas neuroimaging formats focus on magnetic resonance imaging (MRI), computed tomography (CT), and/or positon emission tomography (PET).
The NIfTI-Zarr (nii.zarr) specification attempts to merge the best of
both worlds, in the simplest possible way. Like NIfTI, it aims to make the
implementation of I/O libraries as simple as possible, to maximize chances
that it gets adopted by the community. Its guiding principles are
- OME-Zarr compliant: any
nii.zarrfile should be a validome.zarrfile; - OME-Zarr minimal: only implements the minimum set of metadata necessary to describe [multi-resolution] neuroimaging data;
- NIfTI-compliant: the binary nifti header should be stored in its raw
form in an additional
niftizarr array; - NIfTI-priority: if metadata conflict across the nifti header and OME attributes, the nifti metadata should take precedence.
Note
- Being OME-NGFF compliant does not mean (for now) that the OME-NGFF transform and the NIfTI transform match. Currently, OME-NGFF only handles scales (for voxel sizes) and translations (for origin shifts caused by pyramid methods). It is therefore impossible to encode an affine tranform - or even swap axes - using the current OME-NGFF specification. What we mean by OME-NGFF compliant is that any OME-NGFF viewer will correctly display the content of the file in scaled voxel space.
- OME-NGFF does not currently offer the possibility to store an intensity
transform. This means that OME-NGFF viewers will not use the intensity
affine transform encoded by
scl_slopeandscl_interin the nifti header. - That said, the nifti layer added on top of OME-NGFF is light enough that
viewer developers may easily extend their software to handle
- an affine geometric tranform, and
- an affine intensity transform.
- In modern languages such as Python and Julia, a virtual array
that points to the raw data can easily be encapsulated in a high-level
class that applies the intensity transform on the fly. This is
examplified in our Python and Julia reference implementations, which
respectively leverage
nibabel'sNifti1ImageandNIfTI.jl'sNIVolume.
The simplicity of these guiding principles should make the adoption of
nii.zarr in cloud environments (almost) as straightforward as the adoption
of compressed-NIfTI (.nii.gz).
A NIfTI-Zarr file MUST be a valid OME-Zarr multi-resolution image (and therefore also a valid Zarr dataset), whose directory structure and metadata are described in sections 2.1, 2.2 and 2.3.
In addition, it MUST store the nifti header corresponding to the finest
level of the pyramid as a Zarr array with the "nifti" key, as described
in section 2.4.
Note
At the time of this writing, Zarr is at version 3 and OME-NGFF is at version 0.5. NIfTI-Zarr being a simple layer within an OME-Zarr object, it does not impose a specific Zarr or OME-NGFF version. However, note that OME-NGFF v0.4 specifies that it should be used with Zarr v2, while OME-NGFF v0.5 specifies that it should be used with Zarr v3.
Similarly, the NIfTI header may follow the NIfTI v1 or NIfTI v2 specifications.
All examples below use the OME-NGFF v0.4 + Zarr v2 specification, but they could equivalently have used OME-NGFF v0.5 + Zarr v3.
REF:
- OME-NGFF latest: https://ngff.openmicroscopy.org/latest/#image-layout
- OME-NGFF v0.5: https://ngff.openmicroscopy.org/0.5/#image-layout
- OME-NGFF v0.4: https://ngff.openmicroscopy.org/0.4/#image-layout
βββ mri.nii.zarr # A NIfTI volume converted to Zarr.
β
βββ .zgroup # Each volume is a Zarr group, of arrays.
βββ .zattrs # Group level attributes are stored in the .zattrs
| # file include the OME "multiscales" key.
| # In addition, the group level attributes
β # may also contain "_ARRAY_DIMENSIONS" for
| # compatibility with xarray if this group directly
| # contains multi-scale arrays.
|
βββ nifti # The NIfTI header is stored as a raw array
β βββ .zarray # of bytes, with an optional JSON form stored in
β βββ .zattrs # the associated .zattrs file.
β βββ 0
β
βββ 0 # Each multiscale level is stored as a separate
| # Zarr array, which is a folder containing chunk
β ... # files which compose the array.
|
βββ n # The name of the array is arbitrary with the
| # ordering defined by the "multiscales" metadata,
β # but is often a sequence starting at 0.
β
βββ .zarray # All image arrays must be up to 5-dimensional
β # with the axis of type time before type channel,
| # before spatial axes.
β
ββ t # Chunks are stored with the nested directory
ββ c # layout. All but the last chunk element are stored
ββ z # as directories. The terminal chunk is a file.
ββ y # Together the directory and file names provide the
ββ x # "chunk coordinate" (t, c, z, y, x), where the
# maximum coordinate will be dimension_size / chunk_size.
REF:
- Zarr v3: https://zarr-specs.readthedocs.io/en/latest/v3/core/v3.0.html#array-metadata
- Zarr v2: https://zarr-specs.readthedocs.io/en/latest/v2/v2.0.html#arrays
# {filename}.nii.zarr/{0..n}/.zarray
{
"chunks": [
1, # Number of time chunks
3, # Number of channel chunks
1000, # Number of z chunks
1000, # Number of y chunks
1000, # Number of x chunks
],
"compressor": { # Codec used to compress chunks
"id": "blosc", # MUST be "blosc" or "zlib"
"cname": "lz4",
"clevel": 5,
"shuffle": 1
},
"dtype": "<f4", # SHOULD be the compatible with zattrs["nifti"]["DataType"]
"fill_value": "NaN", # Value to use for missing chunks
"order": "F", # MUST be "F"
"shape": [ # SHOULD be the same as zattrs["nifti"]["Dim"][[3, 4, 2, 1, 0]]
1, # T shape
3, # C shape
10000, # Z shape
10000, # Y shape
10000 # X shape
],
"zarr_format": 2 # MUST be 2
}REF:
- OME-NGFF latest: https://ngff.openmicroscopy.org/latest/#image-layout
- OME-NGFF v0.5: https://ngff.openmicroscopy.org/0.5/#image-layout
- OME-NGFF v0.4: https://ngff.openmicroscopy.org/0.4/#image-layout
# {filename}.nii.zarr/.zattrs
{
"multiscales": [
{
"version": "0.4",
"axes": [
{"name": "t", "type": "time", "unit": "second"},
{"name": "c", "type": "channel"},
{"name": "z", "type": "space", "unit": "millimeter"},
{"name": "y", "type": "space", "unit": "millimeter"},
{"name": "x", "type": "space", "unit": "millimeter"}
],
"datasets": [
{
"path": "0",
"coordinateTransformations": [{
# the voxel size for the first scale level (0.5 millimeter)
"type": "scale",
"scale": [1.0, 1.0, 0.5, 0.5, 0.5]
}]
},
{
"path": "1",
"coordinateTransformations": [{
# the voxel size for the second scale level
# (downscaled by a factor of 2 -> 1 millimeter)
"type": "scale",
"scale": [1.0, 1.0, 1.0, 1.0, 1.0]
}]
},
{
"path": "2",
"coordinateTransformations": [{
# the voxel size for the third scale level
# (downscaled by a factor of 4 -> 2 millimeter)
"type": "scale",
"scale": [1.0, 1.0, 2.0, 2.0, 2.0]
}]
}
],
"coordinateTransformations": [{
# the time unit (0.1 seconds),
# which is the same for each scale level
"type": "scale",
"scale": [0.1, 1.0, 1.0, 1.0, 1.0]
}],
}
]
}FUTURE CHANGES: as soon as affine coordinate transforms are integrated into the OME-NGFF standard, it will be used to encode both the NIfTI qform and sform as valid OME-NGFF metadata. However, only these two transforms will be accepted in a valid NIfTI-Zarr file. None of the more advanced combinations of affine and nonlinear transforms will be accepted. Similarly, only a very specific set of coordinate spaces will be accepted.
REF:
- NIfTI v1: https://nifti.nimh.nih.gov/pub/dist/src/niftilib/nifti1.h
- NIfTI v2: https://nifti.nimh.nih.gov/pub/dist/doc/nifti2.h
- JNIfTI v1: https://github.com/NeuroJSON/jnifti/blob/master/JNIfTI_specification.md#niftiheader
- Zarr v3: https://zarr-specs.readthedocs.io/en/latest/v3/core/v3.0.html#array-metadata
- Zarr v2: https://zarr-specs.readthedocs.io/en/latest/v2/v2.0.html#arrays
- NIfTI-Zarr v1.0.rc1: nifti-zarr-schema-1.0.rc1.json
The nifti header (v1
or v2) MUST be encoded
as a single-chunk zarr array if bytes under the nifti key:
βββ mri.nii.zarr
β
βββ nifti # The NIfTI header is stored as a raw array
βββ .zarray # of bytes, with an optional JSON form stored in
βββ .zattrs # the associated .zattrs file.
βββ 0
# {filename}.nii.zarr/nifti/.zarray
{
"zarr_format": 2, # MUST be 2
"shape": [348], # MUST be header length if `dtype="u1"` else 1
"compressor": {
"id": "zlib", # MUST be `{"id": "zlib", "level": 0..9}` or `null`
"level": 9 # MUST be in 0..9, if "zlib"
},
"dtype": "u1", # MUST be "u1" or "S{length:d}"
"order": "C", # UNUSED ("F" or "C")
"chunks": [1], # MUST be 1
"fill_value": null, # UNUSED
}A JSON variant of the nifti header MAY be encoded in the attributes file
(.zattrs or attrs.json). The JSON variant is only provided for
human-readability. Its values SHOULD be compatible with those of the
binary header. If values conflict between the binary and JSON headers,
the binary form MUST take precedence. The JSON variant MUST be
compatible with the JNIfTI/NIFTIHeader
specification. The JSON variant MUST be compatible with the
NIfTI-Zarr schema specification.
# filename.nii.zarr/nifti/.zattrs
{
# ------------------------------------------------------------------
# All other tags **MAY** contain JSON representations of the nifti
# header. Not all fields are included. This JSON representation is
# OPTIONAL and has a lower priority than the binary header.
# ------------------------------------------------------------------
"NIIFormat": b"ni1\0", # MUST be one of "ni1\0", "n+1\0", "ni2\0", "n+2\0"
"Dim": [128, 128, 128, 1, 3], # SHOULD match filename.nii.zarr/0/.zarray["shape"][[4, 3, 2, 0, 1]]
"VoxelSize": [ # xtztc unit size, SHOULD be compatible with:
1.5, 1.5, 1.5, # filename.nii.zarr/.zattrs["multiscales"][0]["datasets"][0]["coordinateTransformations"][0]["scale"][2:5][::-1]
0.1, # filename.nii.zarr/.zattrs["multiscales"][0]["coordinateTransformations"][0]["scale"][0]
1.0, # filename.nii.zarr/.zattrs["multiscales"][0]["coordinateTransformations"][0]["scale"][1]
],
"Unit": { # xyzt unit, SHOULD be compatible with:
"L": "mm", # filename.nii.zarr/.zattrs["multiscales"][0]["axes"][2:]["unit"]
"T": "s", # filename.nii.zarr/.zattrs["multiscales"][0]["axes"][0]["unit"]
},
"DataType": "single", # SHOULD be compatible with filename.nii.zarr/0/.zarray["dtype"]
"DimInfo": {
"Freq": 1, # MUST be one of {0, 1, 2, 3}
"Phase": 2, # MUST be one of {0, 1, 2, 3}
"Slice": 3 # MUST be one of {0, 1, 2, 3}
},
"Intent": "dispvec", # MUST be a valid intent code (see table 4.2)
"Param1": None,
"Param2": None,
"Param3": None,
"Name": "",
"ScaleSlope": 1.0, # Data scaling: slope
"ScaleOffset": 0.0, # Data scaling: intercept
"SliceType": "seq+", # MUST be a valid slice timing code (see table 4.6)
"FirstSliceID": 0 , # First slice index
"LastSliceID": 127, # Last slice index
"SliceTime": 1.0, # Time for 1 slice.
"MinIntensity": 0.0, # Min display intensity
"MaxIntensity": 1.0, # Max display intensity
"TimeOffset": 0.0, # Time axis shift
"Description": "An MRI", # Any text you like
"AuxFile": "/path/to/aux", # Auxiliary filename
"QForm": 0, # MUST be a valid xform code (see table 4.5)
"Quatern": { # Quaternion
"b": b,
"c": c,
"d": d
},
"QuaternOffset": { # Translation
"x": tx,
"y": ty,
"z": tz
},
"SForm": 0, # MUST be a valid xform code (see table 4.5)
"Affine": [
[axx, axy, axz, tx], # 1st row affine transform
[ayx, ayy, ayz, ty], # 2nd row affine transform
[azx, azy, azz, tz], # 3rd row affine transform
]
}Some fields SHOULD be equivalent to their OME-Zarr counterparts:
nifti.zattrs["Dim"] == 0.zarray["shape"][[4, 3, 2, 0, 1]] # Level 0 zarray
nifti.zattrs["DataType"] == *.zarray["dtype"] # All zarrays
nifti.zattrs["VoxelSize"][:3] == zattrs["multiscales"][0]["datasets"][0]["coordinateTransformations"][0]["scale"][2:5][::-1]
nifti.zattrs["VoxelSize"][3] == zattrs["multiscales"][0]["coordinateTransformations"][0]["scale"][0]
nifti.zattrs["VoxelSize"][4] == zattrs["multiscales"][0]["coordinateTransformations"][0]["scale"][1]- Following the OME-NGFF specifcation, dimensions are ordered as [T, C, Z, Y, X] (in C order) as opposed to [C, T, Z, Y, X].
- To conform with the NIfTI expectation, on load data should be returned as a [C, T, Z, Y, X] array (in C order; [X, Y, Z, T, C] in F order).
- Any file with more than 5 dimensions
- Image collections
- Image with labels
- High-content screening data
- OMERO metadata
As a reminder, the nifti1 header has the following structure:
| Type | Name | NIfTI-1 usage | JNIfTI | JSON type |
|---|---|---|---|---|
int |
sizeof_hdr |
MUST be 348 | "NIIHeaderSize" |
integer |
char |
data_type |
"A75DataTypeName" |
string |
|
char |
db_name |
"A75DBName" |
string |
|
int |
extents |
"A75Extends" |
integer |
|
short |
session_error |
"A75SessionError" |
integer |
|
char |
regular |
"A75Regular" |
integer |
|
char |
dim_info |
MRI slice ordering. | "DimInfo" |
property |
"DimInfo"/"Freq" |
integer |
|||
"DimInfo"/"Phase" |
integer |
|||
"DimInfo"/"Slice" |
integer |
|||
short[8] |
dim |
Data array dimensions. | "Dim" |
array[integer] |
float |
intent_p1 |
1st intent parameter. | "Param1" |
number |
float |
intent_p2 |
2nd intent parameter. | "Param2" |
number |
float |
intent_p3 |
3rd intent parameter. | "Param3" |
number |
short |
intent_code |
NIFTI_INTENT_* code. |
"Intent" |
[integer, string] |
short |
datatype |
Defines data type! | "DataType" |
[integer, string] |
short |
bitpix |
Number bits/voxel. | "BitDepth" |
integer |
short |
slice_start |
First slice index. | "FirstSliceID" |
integer |
float[8] |
pixdim |
Grid spacings. | "VoxelSize" |
array[number] |
"Orientation" |
property |
|||
"Orientation"/"x" |
enum: ["l", "r", "a", "p", "i", "s"] |
|||
"Orientation"/"y" |
enum: ["l", "r", "a", "p", "i", "s"] |
|||
"Orientation"/"z" |
enum: ["l", "r", "a", "p", "i", "s"] |
|||
float |
vox_offset |
Offset into .nii file | "NIIByteOffset" |
number |
float |
scl_slope |
Data scaling: slope. | "ScaleSlope" |
number |
float |
scl_inter |
Data scaling: offset. | "ScaleOffset" |
number |
short |
slice_end |
Last slice index. | "LastSliceID" |
integer |
char |
slice_code |
Slice timing order. | "SliceType" |
[integer, string] |
char |
xyzt_units |
Units of pixdim[1..4] |
"Unit" |
property |
"Unit"/"L" |
[integer, string] |
|||
"Unit"/"T" |
[integer, string] |
|||
float |
cal_max |
Max display intensity | "MaxIntensity" |
number |
float |
cal_min |
Min display intensity | "MinIntensity" |
number |
float |
slice_duration |
Time for 1 slice. | "SliceTime" |
number |
float |
toffset |
Time axis shift. | "TimeOffset" |
number |
int |
glmax |
"A75GlobalMax" |
integer |
|
int |
glmin |
"A75GlobalMin" |
integer |
|
char[80] |
descrip |
any text you like. | "Description" |
string |
char[24] |
aux_file |
auxiliary filename. | "AuxFile" |
string |
short |
qform_code |
NIFTI_XFORM_* code. |
"QForm" |
integer |
short |
sform_code |
NIFTI_XFORM_* code. |
"SForm" |
integer |
float |
quatern_b |
Quaternion b param. | "Quatern"/"b" |
number |
float |
quatern_c |
Quaternion c param. | "Quatern"/"c" |
number |
float |
quatern_d |
Quaternion d param. | "Quatern"/"d" |
number |
float |
qoffset_x |
Quaternion x shift. | "QuaternOffset"/"x" |
number |
float |
qoffset_y |
Quaternion y shift. | "QuaternOffset"/"y" |
number |
float |
qoffset_z |
Quaternion z shift. | "QuaternOffset"/"z" |
number |
float[4] |
srow_x |
1st row affine transform. | "Affine"/[0] |
array[number] |
float[4] |
srow_y |
2nd row affine transform. | "Affine"/[1] |
array[number] |
float[4] |
srow_z |
3rd row affine transform. | "Affine"/[2] |
array[number] |
char[16] |
intent_name |
'name' or meaning of data. | "Name" |
string |
char[4] |
magic |
MUST be "ni1\0" or "n+1\0". |
"NIIFormat" |
string |
In Zarr, the byte order MUST be specified by prepending one of
{"|", "<", ">"} to the data type string.
| Data type | NIfTI | Zarr | JNIfTI |
|---|---|---|---|
uint8 |
2 |
"|u1" |
"uint8" |
int16 |
4 |
"i2" |
"int16" |
int32 |
8 |
"i4" |
"int32" |
float32 |
16 |
"f4" |
"single" |
complex64 |
32 |
"c8" |
"complex64" |
float64 |
64 |
"f8" |
"double" |
rgb24 |
128 |
[["r", "|u1"], ["g", "|u1"], ["b", "|u1"]] |
"rgb24" |
int8 |
256 |
"|i1" |
"int8" |
uint16 |
512 |
"u2" |
"uint16" |
uint32 |
768 |
"u4" |
"uint32" |
int64 |
1024 |
"i8" |
"int64" |
uint64 |
1280 |
"u8" |
"uint64" |
float128 |
1536 |
"f16" |
"double128" |
complex128 |
1792 |
"c16" |
"complex128" |
complex256 |
2048 |
"c32" |
"complex256" |
rgba32 |
2304 |
[["r", "|u1"], ["g", "|u1"], ["b", "|u1"], ["a", "|u1"]] |
"rgba32" |
bool |
π unsupported! | "|b1" |
|
timedelta |
π unsupported! | "m8[{unit}]" |
|
time |
π unsupported! | "M8[{unit}]" |
In OME-NGFF, units must be names from the UDUNITS-2 database.
| Unit | NIfTI | UDUNITS-2 | OME-NGFF axis | JNIfTI |
|---|---|---|---|---|
| unknown | 0 |
"" |
"" |
|
| meter | 1 |
"meter" |
"space" |
"m" |
| millimeter | 2 |
"millimeter" |
"space" |
"mm" |
| micron | 3 |
"micrometer" |
"space" |
"um" |
| second | 8 |
"second" |
"time" |
"s" |
| millisecond | 16 |
"millisecond" |
"time" |
"ms" |
| microsecond | 24 |
"microsecond" |
"time" |
"us" |
| hertz | 32 |
"hertz" |
"channel" |
"hz" |
| ppm | 40 |
"micro" |
"channel" |
"ppm" |
| rad | 48 |
"radian" |
"channel" |
"rad/s" |
| Intent | NIfTI | JNIfTI | len(intent_p) |
Intent parameters |
|---|---|---|---|---|
| None | 0 |
"none" |
0 |
[] |
| Correlation coefficient R | 2 |
"corr" |
1 |
[dof] |
| Student t statistic | 3 |
"ttest" |
1 |
[dof] |
| Fisher F statistic | 4 |
"ftest" |
2 |
[num dof, den dof] |
| Standard normal | 5 |
"zscore" |
0 |
[] |
| Chi-squared | 6 |
"chi2" |
1 |
[dof] |
| Beta distribution | 7 |
"beta" |
2 |
[a, b] |
| Binomial distribution | 8 |
"binomial" |
2 |
[nb trials, prob per trial] |
| Gamma distribution | 9 |
"gamma" |
2 |
[shape, scale] |
| Poisson distribution | 10 |
"poisson" |
1 |
[mean] |
| Normal distribution | 11 |
"normal" |
2 |
[mean, standard deviation] |
| Noncentral F statistic | 12 |
"ncftest" |
3 |
[num dof, den dof, num noncentrality] |
| Noncentral chi-squared statistic | 13 |
"ncchi2" |
2 |
[dof, noncentrality] |
| Logistic distribution | 14 |
"logistic" |
2 |
[location, scale] |
| Laplace distribution | 15 |
"laplace" |
2 |
[location, scale] |
| Uniform distribution | 16 |
"uniform" |
2 |
[lower end, upper end] |
| Noncentral t statistic | 17 |
"ncttest" |
2 |
[dof, noncentrality] |
| Weibull distribution | 18 |
"weibull" |
3 |
[location, scale, power] |
| Chi distribution | 19 |
"chi" |
1 |
[dof] |
| Inverse Gaussian | 20 |
"invgauss" |
2 |
[mu, lambda] |
| Extreme value type I | 21 |
"extval" |
2 |
[location, scale] |
| Data is a 'p-value' | 22 |
"pvalue" |
0 |
[] |
| Data is ln(p-value) | 23 |
"logpvalue" |
0 |
[] |
| Data is log10(p-value) | 24 |
"log10pvalue" |
0 |
[] |
| Parameter estimate | 1001 |
"estimate" |
0 |
[] |
| Index into set of labels | 1002 |
"label" |
0 |
[] |
| Index into NeuroNames set | 1003 |
"neuronames" |
0 |
[] |
| MxN matrix at each voxel | 1004 |
"matrix" |
2 |
[M, N] |
| NxN matrix at each voxel | 1005 |
"symmatrix" |
1 |
[N] |
| Displacement field | 1006 |
"dispvec" |
0 |
[] |
| Vector field | 1007 |
"vector" |
0 |
[] |
| Spatial coordinate | 1008 |
"point" |
0 |
[] |
| Triangle (3 indices) | 1009 |
"triangle" |
0 |
[] |
| Quaternion (4 values) | 1010 |
"quaternion" |
0 |
[] |
| Dimensionless value | 1011 |
"unitless" |
0 |
[] |
| Gifti time series | 2001 |
"tseries" |
0 |
[] |
| Gifti node index | 2002 |
"elem" |
0 |
[] |
| Gifti RGB (3 values) | 2003 |
"rgb" |
0 |
[] |
| Gifti RGBA (4 values) | 2004 |
"rgba" |
0 |
[] |
| Gifti shape | 2005 |
"shape" |
0 |
[] |
Additional FSL codes:
| Intent | NIfTI | JNIfTI |
|---|---|---|
| FSL displacement field | 2006 |
"FSL_FNIRT_DISPLACEMENT_FIELD" |
| FSL cubic spline | 2007 |
"FSL_CUBIC_SPLINE_COEFFICIENTS" |
| FSL DCT coefficients | 2008 |
"FSL_DCT_COEFFICIENTS" |
| FSL quad spline | 2009 |
"FSL_QUADRATIC_SPLINE_COEFFICIENTS" |
| FSL-TOPUP cubic spline | 2016 |
"FSL_TOPUP_CUBIC_SPLINE_COEFFICIENTS" |
| FSL-TOPUP quad spline | 2017 |
"FSL_TOPUP_QUADRATIC_SPLINE_COEFFICIENTS" |
| FSL-TOPUP field | 2018 |
"FSL_TOPUP_FIELD" |
| Transform | NIfTI | JNIfTI |
|---|---|---|
| Unknown | 0 |
"unknown" |
| Scanner | 1 |
"scanner" |
| Aligned | 2 |
"aligned" |
| Talairach | 3 |
"talairach" |
| MNI | 4 |
"mni" |
| Template | 5 |
"template" |
| Order | NIfTI | JNIfTI |
|---|---|---|
| Unknown | 0 |
"" |
| Sequential increasing | 1 |
"seq+" |
| Sequential decreasing | 2 |
"seq-" |
| alternating increasing | 3 |
"alt+" |
| alternating decreasing | 4 |
"alt-" |
| alternating increasing #2 | 5 |
"alt2+" |
| alternating decreasing #2 | 6 |
"alt2-" |
Reference software to convert data between .nii[.gz] and .nii.zarr
is provided.
5.1. Python
from niizarr import nii2zarr, zarr2nii
# convert from nii.gz to nii.zarr
nii2zarr('/path/to/mri.nii.gz', '/path/to/mri.nii.zarr')
# convert from nii.zarr to nii.gz
# The pyramid level can be selected with `level=L`, where 0 is the
# base/finest level.
zarr2nii('/path/to/mri.nii.zarr', '/path/to/mri.nii.gz')
zarr2nii('/path/to/mri.nii.zarr', '/path/to/mri_2x.nii.gz', level=1)
# Encapsulate a nifti-zarr into a nibabel.Nifti1Image object, whose
# dataobj is a dask array
img = zarr2nii('/path/to/mri.nii.zarr')5.2. Julia
import NIfTIZarr: nii2zarr, zarr2nii
# convert from nii.gz to nii.zarr
nii2zarr("path/to/nifti.nii.gz", "s3://path/to/bucket")
# convert from nii.zarr to nii.gz
# The pyramid level can be selected with `level=L`, where 0 is the
# base/finest level.
zarr2nii("/path/to/mri.nii.zarr", "/path/to/mri.nii.gz")
zarr2nii("/path/to/mri.nii.zarr", "/path/to/mri_2x.nii.gz"; level=1)
# Encapsulate a nifti-zarr into a NIVolume object, whose
# raw data is a DiskArray
img = zarr2nii("s3://path/to/bucket")5.3. NGtools
The ngtools package allows
NIfTI-Zarr files to be properly oriented and displayed in
neuroglancer.