- Copyright: (C) 2019-2026 Qianqian Fang <q.fang at neu.edu>, 2020 Edward Xu <xu.ed at northeastern.edu>
- License: Apache License, Version 2.0
- Version: V1 (Draft-3)
- URL: https://neurojson.org/jnifti
- Status: Stable
- Development: https://github.com/NeuroJSON/jnifti
- Abstract:
This specification defines the JNIfTI standard format. The JNIfTI format allows one to store and extend the widely used NIfTI format (.nii) using JavaScript Object Notation (JSON) [RFC4627] and binary JSON serialization methods. It loss-lessly maps all NIfTI-1 and NIfTI-2 headers and data structures to a human-readable JSON-based wrapper. Use of JSON and JNIfTI formats to store NIfTI data makes it possible to rapidly index, exchange, and query large amount of NIfTI datasets and metadata using modern database engines where JSON is used as the underlying data exchange format. With the extension of JData annotations, JNIfTI also permits optional hierarchical data storage, image data grouping, various data compression codecs, filters, streaming and encryption.
- Introduction
- Grammar
- JNIfTI Keywords
- NIFTIHeader
- DataType (NIFTI-1 header: datatype)
- Dim (NIFTI-1 header: dim)
- DimInfo (NIFTI-1 header: dim_info)
- Orientation (NIFTI-1 header: pixdim[0])
- Unit (NIFTI-1 header: xyzt_units)
- Intent (NIFTI-1 header: intent_code)
- SliceType (NIFTI-1 header: slice_code)
- QForm/SForm (NIFTI-1 header: qform_code/sform_code)
- NIIFormat (NIFTI-1 header: magic)
- NIIHeaderSize (NIFTI-1 header: sizeof_hdr)
- NIIByteOffset (NIFTI-1 header: vox_offset)
- Other deprecated subfields
- NIFTIData
- NIFTIExtension
- NIFTIHeader
- Data Organization and Grouping
- Recommended File Specifiers
- Summary
JNIfTI is a JSON- and binary-JSON-based wrapper for the widely used NIfTI neuroimaging format. Because JNIfTI data files are self-documenting and human-readable, they can serve as a universal exchange format for NIfTI-based datasets, including N-dimensional (ND) arrays and time series data. Representing imaging data in JSON allows the format to be naturally extended with new metadata fields and data types without breaking backward compatibility — directly addressing the long-standing rigidity of the binary NIfTI format, whose fixed-size header caused breaking changes when transitioning from Analyze 7.5 to NIfTI-1, and again from NIfTI-1 to NIfTI-2. Beyond interoperability, the human- and machine-readable nature of JNIfTI promotes long-term data reusability and makes neuroimaging datasets readily accessible to emerging AI-powered workflows for data augmentation, transformation, aggregation, and automation.
To avoid the storage overhead of text-based JSON when handling large binary imaging datasets, JNIfTI leverages two complementary specifications. The first is the JData specification, which defines ND-array containers with support for strongly typed arrays and built-in data compression. The second is the Binary JData (BJData) specification — a compact binary JSON format with native ND-array support — enabling efficient storage of complex binary data while retaining full structural compatibility with the JSON-based JNIfTI format.
JNIfTI is an extensible framework for storing neuroimaging and time series data using the JData representation, with a syntax fully compatible with JSON and Binary JData (BJData) file formats. By leveraging these open standards, JNIfTI directly addresses the key limitations of the NIfTI formats: it provides flexible and rich metadata support, efficient storage of strongly typed numerical array data, accommodation of both array- and non-array-valued auxiliary or multi-modal data, flexible hierarchical data grouping, and built-in data compression. Together, these capabilities establish a solid foundation for robust data sharing, long-term reusability, and seamless integration with modern data processing and automation pipelines.
The purpose of this document is to
- define a 1-to-1 mapping from NIFTI-1 and NIFTI-2 headers to a JSON/BJData-based flexible metadata structure, ensuring all NIfTI header fields can be losslessly stored using JNIfTI
- define dedicated data containers to losslessly store all NIfTI-formatted neuroimaging data arrays, with examples demonstrating JData-enabled features for data compression, enhanced readability, and improved organization
- define a set of human-readable, standardized string values as alternatives to NIFTI-1/2 integer-coded fields
- define flexible extension mechanisms to accommodate additional physiological, anatomical, and multi-modal data
The following sections define the JNIfTI grammar, header, and data containers, and discuss and illustrate the available extension mechanisms.
All JNIfTI files are JData specification compliant. As with JData, JNIfTI provides both a text-based format using JSON serialization and a binary format based upon the BJData serialization scheme. The two forms can be converted from one to another.
Briefly, the text-based JNIfTI is a valid JSON file with an extension to support concatenated JSON objects; the binary-format JNIfTI is a valid BJData file with extended syntax to support N-D arrays. Please refer to the JData specification for these definitions.
Each NIFTI-1/2 file carries a numerical N-dimensional (N-D, N=1-7) array as the
primary data payload. According to the JData specification, N-D arrays have
two equivalent and interchangeable storage forms - the direct storage format
and the annotated storage format.
For example, one can store a 1-D or 2-D array using the direct storage format as
"jnifti_keyword": [v1,v2,...,vn]
or
"jnifti_keyword": [
[v11,v12,...,v1n],
[v21,v22,...,v2n],
...
[vm1,vm2,...,vmn]
]
or using the "annotated storage" format as
"jnifti_keyword": {
"_ArrayType_": "typename",
"_ArraySize_": [N1,N2,N3,...],
"_ArrayData_": [v1,v2,v3,...]
}
The direct storage format and the annotated storage format are functionally equivalent. While we primarily describe data storage in the context of the direct format below, it is applicable to the annotated format as well. We also note that any valid JSON formatted data structure can be converted into a binary form using the rules defined in the Binary JData specification, which was extended from UBJSON specification (Draft 12).
JNIfTI uses three dedicated data containers to store NIFTI-1/2 compatible data:
NIFTIHeader: a named structure to store all defined NIFTI-1/2 header metadata and to allow for additional user-defined metadata or headers,NIFTIData: an array or structure object to store the primary neuroimaging data. When using the array-form, it can support an arbitrary number of dimensions, with the length of each dimension stored as an integer of up to 64bit.NIFTIExtension: (optional) an array of JData"_ByteStream_"objects to store the NIFTI-1 extension buffers (for compatibility purposes)
These three data containers can appear at any level in a JData tree. NIFTIData is the
only required data object if a JNIfTI file contains a neuroimaging dataset.
When a NIFTIHeader field is stored under the same parent node as a NIFTIData object,
the NIFTIHeader record serves as the metadata for the NIFTIData object.
The optional NIFTIExtension is used for compatibility purposes only,
and is grouped with the NIFTIHeader and NIFTIData records if they appear under the same node.
When multiple NIFTIHeader/NIFTIData/NIFTIExtension objects need to be stored under
the same parent node in a JData tree, they must be differentiated by attaching a
name, such as NIFTIHeader(name), NIFTIData(name) and NIFTIExtension(name). Objects
of the same name shall be grouped and processed together. JNIfTI keywords
should not be repeated more than once (with the same name or without a name) under the same
parent node, as this creates an invalid JSON construct.
The JNIfTI format uses a structure named "NIFTIHeader" to store NIFTI-compatible
header information.
In the below table, we define a 1-to-1 mapping from NIFTI-1/2 headers to the
corresponding JNIfTI NIFTIHeader self-explanatory subfields
Table 1. A mapping table for NIFTI-1/2 headers and JNIfTI NIFTIHeader structure
| NIFTI-1 | NIFTI-2 | Headers | Meanings | JNIfTI NIFTIHeader container |
|---|---|---|---|---|
struct |
struct |
nifti_1_header{ |
"NIFTIHeader": { |
|
int |
int |
sizeof_hdr; |
NIFTI-1/2: 348/540 | "NIIHeaderSize": <i>, |
char |
- | data_type[10]; |
++UNUSED++ | "A75DataTypeName": "s", |
char |
- | db_name[18]; |
++UNUSED++ | "A75DBName": "s", |
int |
- | extents; |
++UNUSED++ | "A75Extends": <i>, |
short |
- | session_error; |
++UNUSED++ | "A75SessionError": <i>, |
char |
- | regular; |
++UNUSED++ | "A75Regular": <i>, |
char |
char |
dim_info; |
MRI slice ordering | "DimInfo" : { |
"Freq": <i>, |
||||
"Phase": <i>, |
||||
"Slice": <i> |
||||
}, |
||||
short |
int64 |
dim[8]; |
Data array dimensions | "Dim": [dim[1],dim[2],...], |
float |
double |
intent_p1 ; |
1st intent parameter | "Param1": <f>, |
float |
double |
intent_p2 ; |
2nd intent parameter | "Param2": <f>, |
float |
double |
intent_p3 ; |
3rd intent parameter | "Param3": <f>, |
short |
int |
intent_code ; |
NIFTI_INTENT_* code | "Intent": <i>|"s", |
short |
short |
datatype; |
Defines data type | "DataType": <i>|"s", |
short |
short |
bitpix; |
Number bits/voxel | "BitDepth": <i>, |
short |
int |
slice_start; |
First slice index | "FirstSliceID": <i>, |
float |
double |
pixdim[8]; |
Grid spacings | "VoxelSize":[pixdim[1],pixdim[2],...], |
| +x direction meaning | "Orientation": { "x": "s", |
|||
| +y direction meaning | "y": "s", |
|||
| +z direction meaning | "z": "s" |
|||
| RAS or LAS based on pixdim[0] | }, |
|||
float |
double |
vox_offset; |
Offset into .nii file | "NIIByteOffset": <f>, |
float |
double |
scl_slope ; |
Data scaling: slope | "ScaleSlope": <f>, |
float |
double |
scl_inter ; |
Data scaling: offset | "ScaleOffset": <f>, |
short |
int |
slice_end; |
Last slice index | "LastSliceID": <i>, |
char |
int |
slice_code ; |
Slice timing order | "SliceType": <i>|"s", |
char |
int |
xyzt_units ; |
Units of pixdim[1..4] | "Unit":{"L":<i>|"s","T":<i>|"s"}, |
float |
float |
cal_max; |
Max display intensity | "MaxIntensity": <f>, |
float |
float |
cal_min; |
Min display intensity | "MinIntensity": <f>, |
float |
float |
slice_duration; |
Time for 1 slice | "SliceTime": <f>, |
float |
float |
toffset; |
Time axis shift | "TimeOffset": <f>, |
int |
- | glmax; |
++UNUSED++ | "A75GlobalMax": <i>, |
int |
- | glmin; |
++UNUSED++ | "A75GlobalMin": <i>, |
char |
char |
descrip[80]; |
Data description | "Description": "s", |
char |
char |
aux_file[24]; |
Auxiliary filename | "AuxFile": "s", |
short |
int |
qform_code ; |
NIFTI_XFORM_* code | "QForm": <i>|"s", |
short |
int |
sform_code ; |
NIFTI_XFORM_* code | "SForm": <i>|"s", |
float |
double |
quatern_b ; |
Quaternion b param | "Quatern": { "b": <f>, |
float |
double |
quatern_c ; |
Quaternion c param | "c": <f>, |
float |
double |
quatern_d ; |
Quaternion d param | "d": <f> |
}, |
||||
float |
double |
qoffset_x ; |
Quaternion x shift | "QuaternOffset":{ "x": <f>, |
float |
double |
qoffset_y ; |
Quaternion y shift | "y": <f>, |
float |
double |
qoffset_z ; |
Quaternion z shift | "z": <f> |
}, |
||||
float |
double |
srow_x[4] ; |
1st row affine transform | "Affine": [ [<f>,<f>,<f>,<f>], |
float |
double |
srow_y[4] ; |
2nd row affine transform | [<f>,<f>,<f>,<f>], |
float |
double |
srow_z[4] ; |
3rd row affine transform | [<f>,<f>,<f>,<f>] |
], |
||||
char |
char |
intent_name[16]; |
'name' or meaning of data | "Name" : "s", |
char*4 |
char*8 |
magic[] ; |
NIFTI-1:"ni1\0" or "n+1\0" | "NIIFormat": "s", |
}; |
||||
struct |
struct |
nifti_extender |
{char extension[4];}; |
"NIFTIExtension": [<i>,<i>,<i>,<i>], |
<...> |
||||
} |
Notations from the above table are explained below
<i>represents an integer value (signed integer of 8, 16, 32 or 64bit)<f>represents an numerical value (including integers, 32bit and 64bit floating point numbers)"s"represents a UTF-8 encoded string of arbitrary length[...]represents a vector of variable length<...>represents (optional) additional subfields for user-defined header or future extensions<i>|"s"represents alternative forms, in this example, the field can be either an integer or a string
To convert a NIFTI-1/2 header to the JNIfTI NIFTIHeader structure without
sacrificing accuracy, the storage type byte length of the NIFTIHeader subfields
must be of equal or greater value than their original NIfTI header counterpart; in
the case of a string value, the new string must be of the same
or longer length to store the entire original string value.
If the NIFTI header field contains an array, the converted NIFTIHeader subfield shall also
contain an array object sorted in the same order.
Not all "NIFTIHeader" subfields need to be present. However, if any of the subfields in
the NIFTI-1/2 header carry meaningful data, the corresponding subfield in the NIFTIHeader
must be present. The order of the NIFTIHeader subfields is not required.
Mapping in the reverse direction, i.e. from JNIfTI to NIFTI-1/2, is not guaranteed to be lossless.
To enhance the readability of the header, we allow the use of a string to
represent data type (i.e. the DataType subfield in NIFTIHeader) instead
of an integer code. The below
table maps the NIFTI data type codes to the acceptable data type strings.
Table 2. A mapping table from NIFTI-1 data types to string-valued JNIfTI data types and storage types in BJData
| NIFTI-1/2 Data Types | NIFTI Code | JNIfTI DataType | BJData Type |
|---|---|---|---|
| unsigned char | |||
NIFTI_TYPE_UINT8 |
2 |
"uint8" |
U |
| signed short | |||
NIFTI_TYPE_INT16 |
4 |
"int16" |
I |
| signed int | |||
NIFTI_TYPE_INT32 |
8 |
"int32" |
l |
| 32 bit float | |||
NIFTI_TYPE_FLOAT32 |
16 |
"single" |
d |
| 64 bit complex = 2 x 32 bit floats | |||
NIFTI_TYPE_COMPLEX64 |
32 |
"complex64"* |
d (x2) |
| 64 bit float = double | |||
NIFTI_TYPE_FLOAT64 |
64 |
"double" |
D |
| 3x 8 bit bytes | |||
NIFTI_TYPE_RGB24 |
128 |
"rgb24" * |
U (x3) |
| signed char | |||
NIFTI_TYPE_INT8 |
256 |
"int8" |
i |
| unsigned short | |||
NIFTI_TYPE_UINT16 |
512 |
"uint16" |
u |
| unsigned int | |||
NIFTI_TYPE_UINT32 |
768 |
"uint32" |
m |
| signed long long | |||
NIFTI_TYPE_INT64 |
1024 |
"int64" |
L |
| unsigned long long | |||
NIFTI_TYPE_UINT64 |
1280 |
"uint64" |
M |
| 128 bit float = long double | |||
NIFTI_TYPE_FLOAT128 |
1536 |
"double128"* |
U (x16) |
| 2x 64 bit floats = 128 bit complex | |||
NIFTI_TYPE_COMPLEX128 |
1792 |
"complex128"* |
D (x2) |
| 2x 128 bit floats = 256 bit complex | |||
NIFTI_TYPE_COMPLEX256 |
2048 |
"complex256"* |
U (x32) |
| 4x 8 bit bytes | |||
NIFTI_TYPE_RGBA32 |
2304 |
"rgba32" * |
U (x4) |
A "*" sign in the JNIfTI DataType column indicates that the data is a composite type, and must be stored using the "annotated" JData format.
In the NIFTI-1/2 formats, dim[0] stores the number of dimensions of the data, and dim[1]
to dim[7] store the respective dimension of data. In NIFTIHeader, we use an array object Dim to
store the effective dimension sizes starting from dim[1]. The length of Dim array
should equal to that of dim[0].
In the NIFTI-1/2 formats, the dim_info field combines 3 parameters, freq_dim, phase_dim
and slice_dim, using bit-masks. To enhance readability, we represent each of
these parameters as explicit subfields in JNIfTI, specifically "Freq",
"Phase" and "Slice" inside the "DimInfo"
structure. A fixed order of the 3 subfields is not required.
The first element in the pixdim[] array, i.e. pixdim[0] in the NIFTI-1/2 header,
indicates the handedness of the coordinate system. pixdim[0] is assigned a value
of either 0, indicating a "right-anterior-superior" (RAS) coordinate (+x-axis =
right, +y-axis = anterior, +z-axis = superior), or 1, representing a
"left-anterior-superior" (LAS) system.
To enhance readability of JNIfTI, NIFTIHeader uses much more intuitive and extended
labels to indicate the orientations of axes. In the "Orientation" field, one
can define 3 string-valued subfields, "x", "y" and "z", to indicate the direction of
the positive axis. The allowed values (case-insensitive) are
"l"or"left""r"or"right""a"or"anterior""p"or"posterior""s"or"superior""i"or"inferior"
For example, an RAS orientation can be indicated by
"Orientation" : {"x":"r", "y":"a", "z":"s"}
If this subfield is missing, we assume the same "RAS" default orientation as NIFTI-1/2.
The NIFTI-1/2 xyzt_units is a combined mask of both space and time.
In JNIfTI, we map it to a structure with at least two subfields:
"L" to store spatial units, and "T" to store time units.
Similar to DataType, both L and T allow the use of an integer value, matching
that of the NIFTI-1/2 unit definitions, or a more descriptive string value
to specify the units. The mapping between NIFTI-1/2 units to the string forms
is listed below
Table 3. A mapping table for NIFTI-1 unit types and string-valued JNIfTI NIFTIHeader Unit field
| NIFTI-1/2 Unit Types | JNIfTI Unit |
|---|---|
| Unknown Units | |
NIFTI_UNITS_UNKNOWN 0 |
"" |
| Length Units | |
| NIFTI code for meters | |
NIFTI_UNITS_METER 1 |
"m" |
| NIFTI code for millimeters | |
NIFTI_UNITS_MM 2 |
"mm" |
| NIFTI code for micrometers | |
NIFTI_UNITS_MICRON 3 |
"um" |
| Time Units | |
| NIFTI code for seconds | |
NIFTI_UNITS_SEC 8 |
"s" |
| NIFTI code for milliseconds | |
NIFTI_UNITS_MSEC 16 |
"ms" |
| NIFTI code for microseconds | |
NIFTI_UNITS_USEC 24 |
"us" |
| Other Units | |
| NIFTI code for Hertz | |
NIFTI_UNITS_HZ 32 |
"hz" |
| NIFTI code for ppm | |
NIFTI_UNITS_PPM 40 |
"ppm" |
| NIFTI code for radians per second | |
NIFTI_UNITS_RADS 48 |
"rad/s" |
Similar to DataType, data intent (i.e. the Intent subfield in NIFTIHeader) can be represented by a string instead of an integer code.
The below table maps the NIFTI data intent codes to the acceptable intent strings.
| NIFTI-1/2 Data Intent Type | Code | JNIfTI Intent String |
|---|---|---|
| Unknown data intent | ||
NIFTI_INTENT_NONE |
0 |
"" |
| Correlation coefficient R (1 param) | ||
NIFTI_INTENT_CORREL |
2 |
"corr" |
| Student t statistic (1 param): p1 = DOF | ||
NIFTI_INTENT_TTEST |
3 |
"ttest" |
| Fisher F statistic (2 params) | ||
NIFTI_INTENT_FTEST |
4 |
"ftest" |
| Standard normal (0 params): Density = N(0,1) | ||
NIFTI_INTENT_ZSCORE |
5 |
"zscore" |
| Chi-squared (1 param): p1 = DOF | ||
NIFTI_INTENT_CHISQ |
6 |
"chi2" |
| Beta distribution (2 params): p1=a, p2=b | ||
NIFTI_INTENT_BETA |
7 |
"beta" |
| Binomial distribution (2 params) | ||
NIFTI_INTENT_BINOM |
8 |
"binomial" |
| Gamma distribution (2 params) | ||
NIFTI_INTENT_GAMMA |
9 |
"gamma" |
| Poisson distribution (1 param): p1 = mean | ||
NIFTI_INTENT_POISSON |
10 |
"poisson" |
| Normal distribution (2 params) | ||
NIFTI_INTENT_NORMAL |
11 |
"normal" |
| Noncentral F statistic (3 params) | ||
NIFTI_INTENT_FTEST_NONC |
12 |
"ncftest" |
| Noncentral chi-squared statistic (2 params) | ||
NIFTI_INTENT_CHISQ_NONC |
13 |
"ncchi2" |
| Logistic distribution (2 params) | ||
NIFTI_INTENT_LOGISTIC |
14 |
"logistic" |
| Laplace distribution (2 params) | ||
NIFTI_INTENT_LAPLACE |
15 |
"laplace" |
| Uniform distribution: p1=lower end,p2=upper end | ||
NIFTI_INTENT_UNIFORM |
16 |
"uniform" |
| Noncentral t statistic (2 params) | ||
NIFTI_INTENT_TTEST_NONC |
17 |
"ncttest" |
| Weibull distribution (3 params) | ||
NIFTI_INTENT_WEIBULL |
18 |
"weibull" |
| Chi distribution (1 param): p1 = DOF | ||
NIFTI_INTENT_CHI |
19 |
"chi" |
| Inverse Gaussian (2 params) | ||
NIFTI_INTENT_INVGAUSS |
20 |
"invgauss" |
| Extreme value type I (2 params) | ||
NIFTI_INTENT_EXTVAL |
21 |
"extval" |
| Data is a 'p-value' (no params) | ||
NIFTI_INTENT_PVAL |
22 |
"pvalue" |
| Data is ln(p-value) (no params) | ||
NIFTI_INTENT_LOGPVAL |
23 |
"logpvalue" |
| Data is log10(p-value) (no params) | ||
NIFTI_INTENT_LOG10PVAL |
24 |
"log10pvalue" |
| Data is an estimate of some parameter | ||
NIFTI_INTENT_ESTIMATE |
1001 |
"estimate" |
| Data is an index into a set of labels | ||
NIFTI_INTENT_LABEL |
1002 |
"label" |
| Data is an index into the NeuroNames labels | ||
NIFTI_INTENT_NEURONAME |
1003 |
"neuronames" |
| To store an M x N matrix at each voxel | ||
NIFTI_INTENT_GENMATRIX |
1004 |
"matrix" |
| To store an NxN symmetric matrix at each voxel | ||
NIFTI_INTENT_SYMMATRIX |
1005 |
"symmatrix" |
| Each voxel is a displacement vector | ||
NIFTI_INTENT_DISPVECT |
1006 |
"dispvec" |
| Specifically for displacements | ||
NIFTI_INTENT_VECTOR |
1007 |
"vector" |
| Any other type of vector | ||
NIFTI_INTENT_POINTSET |
1008 |
"point" |
| Each voxel is really a triple | ||
NIFTI_INTENT_TRIANGLE |
1009 |
"triangle" |
| Each voxel is a quaternion | ||
NIFTI_INTENT_QUATERNION |
1010 |
"quaternion" |
| Dimensionless value - no params | ||
NIFTI_INTENT_DIMLESS |
1011 |
"unitless" |
| Each data point is a time series | ||
NIFTI_INTENT_TIME_SERIES |
2001 |
"tseries" |
| Each data point is a node index | ||
NIFTI_INTENT_NODE_INDEX |
2002 |
"elem" |
| Each data point is an RGB triplet | ||
NIFTI_INTENT_RGB_VECTOR |
2003 |
"rgb" |
| Each data point is a 4 valued RGBA | ||
NIFTI_INTENT_RGBA_VECTOR |
2004 |
"rgba" |
| Each data point is a shape value | ||
NIFTI_INTENT_SHAPE |
2005 |
"shape" |
| Used by FSL FNIRT | ||
NIFTI_INTENT_FSL_FNIRT_DISPLACEMENT_FIELD |
2006 |
"fsl_fnirt_displacement_field" |
NIFTI_INTENT_FSL_CUBIC_SPLINE_COEFFICIENTS |
2007 |
"fsl_cubic_spline_coefficients" |
NIFTI_INTENT_FSL_DCT_COEFFICIENTS |
2008 |
"fsl_dct_coefficients" |
NIFTI_INTENT_FSL_QUADRATIC_SPLINE_COEFFICIENTS |
2009 |
"fsl_quadratic_spline_coefficients" |
| Used by FSL TOPUP | ||
NIFTI_INTENT_FSL_TOPUP_CUBIC_SPLINE_COEFFICIENTS |
2016 |
"fsl_topup_cubic_spline_coefficients" |
NIFTI_INTENT_FSL_TOPUP_QUADRATIC_SPLINE_COEFFICIENTS |
2017 |
"fsl_topup_quadratic_spline_coefficients" |
NIFTI_INTENT_FSL_TOPUP_FIELD |
2018 |
"fsl_topup_field" |
| Used by NIRS/fNIRS/DOT | ||
NIFTI_INTENT_NIRS_DELTA_OD |
4050 |
"nirs_delta_od" |
NIFTI_INTENT_NIRS_DELTA_MEAN_TOF |
4051 |
"nirs_delta_mean_tof" |
NIFTI_INTENT_NIRS_DELTA_VARIANCE_TOF |
4052 |
"nirs_delta_variance_tof" |
NIFTI_INTENT_NIRS_DELTA_SKEWNESS_TOF |
4053 |
"nirs_delta_skewness_tof" |
NIFTI_INTENT_NIRS_MUA |
4054 |
"nirs_mua" |
NIFTI_INTENT_NIRS_MUSP |
4055 |
"nirs_musp" |
NIFTI_INTENT_NIRS_HBO |
4056 |
"nirs_hbo" |
NIFTI_INTENT_NIRS_HBR |
4057 |
"nirs_hbr" |
NIFTI_INTENT_NIRS_HBT |
4058 |
"nirs_hbt" |
NIFTI_INTENT_NIRS_H2O |
4059 |
"nirs_h2o" |
NIFTI_INTENT_NIRS_LIPID |
4060 |
"nirs_lipid" |
NIFTI_INTENT_NIRS_STO2 |
4061 |
"nirs_sto2" |
NIFTI_INTENT_NIRS_BFI |
4062 |
"nirs_bfi" |
NIFTI_INTENT_NIRS_HRF_DELTA_OD |
4063 |
"nirs_hrf_delta_od" |
NIFTI_INTENT_NIRS_HRF_DELTA_MEAN_TOF |
4064 |
"nirs_hrf_delta_mean_tof" |
NIFTI_INTENT_NIRS_HRF_DELTA_VARIANCE_TOF |
4065 |
"nirs_hrf_delta_variance_tof" |
NIFTI_INTENT_NIRS_HRF_DELTA_SKEWNESS_TOF |
4066 |
"nirs_hrf_delta_skewness_tof" |
NIFTI_INTENT_NIRS_HRF_HBO |
4067 |
"nirs_hrf_hbo" |
NIFTI_INTENT_NIRS_HRF_HBR |
4068 |
"nirs_hrf_hbr" |
NIFTI_INTENT_NIRS_HRF_HBT |
4069 |
"nirs_hrf_hbt" |
NIFTI_INTENT_NIRS_HRF_BFI |
4070 |
"nirs_hrf_bfi" |
Similar to DataType, the slice type (i.e. the SliceType subfield in
NIFTIHeader) can be represented as a string instead of an integer code.
The below table maps the NIFTI data slice codes to the acceptable slice strings.
| NIFTI-1/2 Slice Code Name | Code | JNIfTI SliceType Key |
|---|---|---|
| Unknown slice type | ||
NIFTI_SLICE_UNKNOWN |
0 |
"" |
| Slice sequential increasing | ||
NIFTI_SLICE_SEQ_INC |
1 |
"seq+" |
| Slice sequential decreasing | ||
NIFTI_SLICE_SEQ_DEC |
2 |
"seq-" |
| Slice alternating increasing | ||
NIFTI_SLICE_ALT_INC |
3 |
"alt+" |
| Slice alternating decreasing | ||
NIFTI_SLICE_ALT_DEC |
4 |
"alt-" |
| Slice alternating increasing type 2 | ||
NIFTI_SLICE_ALT_INC2 |
5 |
"alt2+" |
| Slice alternating decreasing type 2 | ||
NIFTI_SLICE_ALT_DEC2 |
6 |
"alt2-" |
| NIFTI-1/2 XForm Code Name | Code | JNIfTI QForm/SForm Key |
|---|---|---|
| Arbitrary coordinates | ||
NIFTI_XFORM_UNKNOWN |
0 |
"" |
| Scanner-based anatomical coordinates | ||
NIFTI_XFORM_SCANNER_ANAT |
1 |
"scanner_anat" |
| Coordinates aligned to another file's, or to anatomical "truth" | ||
NIFTI_XFORM_ALIGNED_ANAT |
2 |
"aligned_anat" |
| Coordinates aligned to Talairach-Tournoux Atlas | ||
NIFTI_XFORM_TALAIRACH |
3 |
"talairach" |
| MNI 152 normalized coordinates | ||
NIFTI_XFORM_MNI_152 |
4 |
"mni_152" |
| Normalized coordinates (for any general standard template space) | ||
NIFTI_XFORM_TEMPLATE_OTHER |
5 |
"template_other" |
The "NIIFormat" field stores the original NIFTI-1 format identifier, and is designed for
compatibility purposes only. The use of this field is deprecated.
The "NIIHeaderSize" field stores the original NIFTI-1 header size, and is designed for
compatibility purposes only. The use of this field is deprecated.
The "NIIByteOffset" field stores the original NIFTI-1 voxel data starting position offset,
and is designed for compatibility purposes only. The use of this field is deprecated.
All Analyze 7.5 header fields that have been deprecated in NIFTI-1/2 formats remain deprecated in JNIfTI files. These subfields include
data_type->A75DataTypeNamedb_name->A75DBNameextents->A75Extendssession_error->A75SessionErrorregular->A75Regularglmax->A75GlobalMaxglmin->A75GlobalMin
The use of these subfields is strictly for compatibility purposes and we highly recommend not including them in JNIfTI files.
The primary data carried within a NIFTI-1/2 file is a numerical array of dimensions and types
specified by the dim and datatype records in the NIFTI-1 header, respectively. In
JNIfTI, we use the "NIFTIData" record to store such information. It can
additionally be expanded upon to store supplemental auxiliary data or metadata.
The NIFTIData record can be either an array object or a structure.
If stored as an array, the NIFTIData shall contain the same data as the NIFTI-1/2 primary data serialized using the JData specification.
For example, a 3-D array of dimension Nx-by-Ny-by-Nz (v_ijk where i=1,2,...,Nx,
j=1,2,...,Ny, k=1,2,...,Nz) can be stored in the direct array format as
"NIFTIData": [
[ [v_111,v_112,v_113,...,v_11Nz], [v_121,v_122,v_123,...,v_12Nz],...,[v_1Ny1,v_1Ny2,v_1Ny3,...,v_1NyNz] ],
[ [v_211,v_212,v_113,...,v_21Nz], [v_221,v_222,v_223,...,v_22Nz],...,[v_2Ny1,v_2Ny2,v_2Ny3,...,v_2NyNz] ],
...
[ [v_Nx11,v_Nx12,v_Nx13,...,v_Nx1Nz],[v_Nx21,v_Nx22,v_Nx23,...,v_Nx2Nz],...,[v_NxNy1,v_NxNy2,...,v_NxNyNz] ]
]
or as the "annotated array format" as
"NIFTIData": {
"_ArrayType_": "datatype",
"_ArraySize_": [Nx,Ny,Nz],
"_ArrayData_": [v_111,v_112,...,v_11Nz,v_121,v_122,...,v_NxNyNz]
}
One can also apply data compression to reduce file sizes. In this case
"NIFTIData": {
"_ArrayType_": "datatype",
"_ArraySize_": [Nx,Ny,Nz],
"_ArrayZipType_": "zlib",
"_ArrayZipSize_": [Nx,Ny,Nz],
"_ArrayZipData_": "<base64-encoded zlib-compressed byte stream>"
}
Please note that all composite data types (marked by "*" in Table 2) can not be stored in the direct form and therefore must be stored using the annotated array format.
NIfTI-1/2 stores raw data values in the column-major element order (meaning
that the left-most index (dim[1]) is the fastest index while the right-most index
is the slowest) while JData _ArrayData_ construct by default stores data elements
in the row-major order (i.e. the right-most index is the fastest index). As a result,
if one has to directly copy the NIfTI data buffer to the _ArrayData_ element,
one must add "_ArrayOrder_" : "c" or "_ArrayOrder_" : "col" before _ArrayData_
or _ArrayZipData_ entries in the above annotated NIFTIData forms.
Alternatively, if _ArrayOrder_ is not specified (which suggests "row-major" order),
one must perform an N-D transpose operation to the NIfTI image data buffer before
serializing those to _ArrayData_.
All three of the above forms are valid JSON formats, and thus can be converted to the corresponding BJData formats when a binary JNIfTI file is desired. Using the optimized N-D array header defined in the JData specification, the binary storage of the direct-form array can be efficiently written as
[U][10][NIFTIData] [[] [$][datatype][#] [[] [$][l][#][U][3][Nx][Ny][Nz] [v_111,v_112,...,v_121,v_122,...,v_NxNyNz]
|----------------| |--------------------------------------------------| |----------------------------------------|
name optimized array container header for N-D array row-major-order serialized N-D array data
Data compression can also be applied to the binary JNIfTI NIFTIData by
converting the above corresponding annotated array into BJData form.
For example, for a uint8 formatted 256x256x256 3D volume, one can use
[U][10][NIFTIData]
[[]
[U][11][_ArrayType_][S][U][5][uint8]
[U][11][_ArraySize_]
[[]
[U][256][U][256][U][256]
[]]
[U][14][_ArrayZipType_][S][U][4][zlib]
[U][14][_ArrayZipSize_]
[[]
[U][256][U][256][U][256]
[]]
[U][14][_ArrayZipData_][H][L][length][... zlib-compressed byte stream ...]
[]]
Using the structure form of NIFTIData allows for the storage of additional
imaging-data-related metadata or auxiliary data, if desired. The structure shall have
the below format
"NIFTIData": {
"_DataInfo_":{
...
},
"Data":[
...
],
"Properties": {
...
},
<...>
}
The three subfields are
Data: this is the only required subfield and its value must be the same as the array data format described in the above subsection;Properties: this optional subfield can store additional auxiliary data using either an array or structure;_DataInfo_: this optional subfield is the JData-compatible metadata record which, if present, must be located as the 1st element ofNIFTIData.
The NIFTIData structure can accommodate additional user-defined subfields which
will be treated as auxiliary data.
From Table 2, six of the data types are composite data types and must be stored using the annotated array format (for both text and binary forms).
Note that double128 and complex256 are stored by first type-casting to uint8
buffers of the same length. The parsing of these data structures is application
dependent.
"NIFTIData": {
"_ArrayType_": "single",
"_ArraySize_": [Nx,Ny,Nz],
"_ArrayIsComplex_": true,
"_ArrayData_": [
[Nx*Ny*Nz singles for the real part],
[Nx*Ny*Nz singles for the imaginary part]
]
}
"NIFTIData": {
"_ArrayType_": "double",
"_ArraySize_": [Nx,Ny,Nz],
"_ArrayIsComplex_": true,
"_ArrayData_": [
[Nx*Ny*Nz doubles for the real part],
[Nx*Ny*Nz doubles for the imaginary part]
]
}
"NIFTIData": {
"_ArrayType_": "uint8",
"_ArraySize_": [Nx,Ny,Nz,3],
"_ArrayData_": [ Nx*Ny*Nz*3 integers ]
}
"NIFTIData": {
"_ArrayType_": "uint8",
"_ArraySize_": [Nx,Ny,Nz,4],
"_ArrayData_": [ Nx*Ny*Nz*4 integers ]
}
"NIFTIData": {
"_ArrayType_": "uint8",
"_ArraySize_": [Nx,Ny,Nz,16],
"_ArrayData_": [ Nx*Ny*Nz*16 uint8 numbers ]
}
"NIFTIData": {
"_ArrayType_": "uint8",
"_ArraySize_": [Nx,Ny,Nz,32],
"_ArrayData_": [ Nx*Ny*Nz*32 uint8 numbers ]
}
In the NIFTI-1/2 format, if extensions[0] in the nifti1_extender structure is
non-zero, NIFTI-1 stores one or more raw data buffers as the extension data.
If these extension data buffers are present, one may use the NIFTIExtension
container to store these data buffers for compatibility purposes only.
The NIFTIExtension must be an array object, with each element containing a
NIFTI-1 extension buffer in the order it is presented.
"NIFTIExtension":[
{
"Size": <i>,
"Type": <i>|"s",
"_ByteStream_":"base64-encoded byte stream for the 1st extension buffer"
},
{
"Size": <i>,
"Type": <i>|"s",
"_ByteStream_":"base64-encoded byte stream for the 2nd extension buffer"
},
...
]
The "Type" field must be one of the 3 values according to the NIFTI-1 specification:
- 0 or
""- for unknown or private format - 1 or
"dicom"- for DICOM formatted data buffer - 2 or
"afni"- for AFNI group formatted data buffer
"_ByteStream_" is a JData keyword to store raw byte-stream buffers. For text-based JNIfTI/JData
files, its value must be a base64-encoded string; no base64 encoding is needed when storing in the
binary format. For details, please see the JData specification "Generic byte-stream data" section.
Again, because the extension data buffer has very little semantic information, the use of such a buffer is not recommended. Please consider converting the data to meaningful JData structures and storing it in the JNIfTI document as auxiliary data.
To facilitate the organization of multiple neuroimaging datasets, JNIfTI supports optional data grouping mechanisms similar to those defined in the JData specification.
In a JNIfTI document, one can use "NIFTIGroup" and "NIFTIObject" to organize
datasets in a hierarchical form. They are equivalent to the "_DataGroup_" and "_DataSet_"
constructs, respectively, as defined in the JData specification, but are specifically
applicable to neuroimaging data. The format of "NIFTIGroup" and "NIFTIObject" is identical
to the JData data grouping tags, i.e., they can be either an array or structure with an
optional unique name (within the current document) via "NIFTIGroup(unique name)"
and "NIFTIObject(unique name)".
For example, the below JNIfTI snippet defines two data groups, each containing
multiple NIFTI datasets. Here we also show examples on how to store multiple NIFTIHeader
and NIFTIData records under a common parent, as well as on the use of "_DataLink_" as defined
in the JData specification for flexible data referencing.
{
"NIFTIGroup(studyname1)": {
"NIFTIObject(subj1)": {
"NIFTIHeader":{ ... },
"NIFTIData":[ ... ]
},
"NIFTIObject(subj2)": {
"NIFTIHeader":{ ... },
"NIFTIData":[ ... ]
},
"NIFTIObject(subj3)": {
"NIFTIHeader(visit1)":{ ... },
"NIFTIData(visit1)":[ ... ],
"NIFTIHeader(visit2)":{ ... },
"NIFTIData(visit2)":[ ... ]
}
},
"NIFTIGroup(studyname2)": {
"NIFTIObject(subj1)": {
"NIFTIHeader":{ ... },
"NIFTIData":[ ... ]
},
"NIFTIObject(subj2)": {
"NIFTIData":[ ... ]
},
"NIFTIObject(subj3)": {
"_DataLink_": "file:///space/test/jnifti/study2subj3.jnii"
}
}
}
For the text-based JNIfTI file, the recommended file suffix is ".jnii"; for
the binary JNIfTI file, the recommended file suffix is ".bnii".
The MIME type for the text-based JNIfTI document is
"application/jnifti-text"; that for the binary JNIfTI document is
"application/jnifti-binary"
In summary, this specification defines a pair of new file formats - the text and binary JNIfTI formats - to efficiently store and exchange neuroimaging scans, along with associated metadata and auxiliary measurements. Any previously generated NIFTI-1/2 file can be fully mapped to a JNIfTI document without losing any information. However, JNIfTI greatly expands upon the flexibility of the NIFTI-1/2 formats by removing a few key, inherent limitations, thereby allowing storage of multiple datasets, data compression, flexible data grouping, and user-defined metadata fields.
By using JSON-/BJData-compatible JData constructs, JNIfTI provides a highly portable, versatile, and extensible framework to store a large variety of neuroanatomical and functional imaging data. These constructs also confer user-readability in both text and binary formats through self-explanatory keywords. The widespread availability of JSON and BJData parsers provides the groundwork for easily sharing, processing, and analyzing JNIfTI data files without imposing an extensive programming overhead. The underlying JData specification offers greater flexibility in data organization and referencing mechanisms, which, in conjunction with a simple and highly readable human syntax, enables JNIfTI to record and share large-scale, complex neuroimaging datasets among researchers, clinicians, and data scientists alike.