jsnirfy

MATLAB/Octave Toolbox for SNIRF and JSNIRF Files

A complete parser and converter for functional near-infrared spectroscopy (fNIRS) data. Read/write SNIRF (HDF5) and JSNIRF (JSON/BJData) formats with ease.

📄 Dual Format

Support both HDF5-based SNIRF and text/binary JSNIRF formats

🔄 Format Converter

Seamlessly convert between SNIRF and JSNIRF with 1-to-1 mapping

✅ Fully Compatible

Compliant with SNIRF v1.0+ and JSNIRF specifications

âš¡ Fast & Complete

High-performance HDF5 I/O via EasyH5 toolbox

Scroll to explore

Why JSNIRF?

Advantages Over Pure HDF5

JSNIRF provides text-based and binary interfaces as alternatives to HDF5, offering better portability and ease of use.

Text Format Benefits

  • Human Readable: View and edit data with any text editor
  • Simple Format: JSON is much simpler than HDF5 specification
  • Lightweight: Minimal overhead for small datasets
  • Wide Support: Countless free JSON parsers available
  • Easy to Parse: Writing custom parsers is straightforward

Binary Format Benefits

  • Quasi-Readable: Binary format with human-readable markers
  • Compact Storage: Efficient binary encoding
  • Multiple Parsers: Available for MATLAB, Python, C++, and C
  • Simple Specification: Easy to implement custom parsers

Get Started

Installation

Quick setup in MATLAB or GNU Octave with minimal dependencies.

% Add to MATLAB/Octave path
addpath('/path/to/jsnirfy');

Required Dependencies

  • EasyH5: For reading/writing SNIRF/HDF5 files
    % https://github.com/NeuroJSON/easyh5
  • JSONLab: For JSNIRF (JSON/BJData) file support
    % https://github.com/NeuroJSON/jsonlab

Optional Dependencies

  • oct-hdf5: For HDF5 support in GNU Octave
    pkg install https://github.com/fangq/oct-hdf5/archive/refs/heads/main.zip
  • ZMat: For compressed JSNIRF files (https://github.com/NeuroJSON/zmat)

Data Format

SNIRF ↔ JSNIRF Compatibility

JSNIRF maintains high compatibility with SNIRF. Convert between formats losslessly with automatic data reorganization.

Key Differences

  1. Root Object Naming: SNIRF's /nirs becomes SNIRFData in JSNIRF
  2. Array Grouping: Indexed groups like /nirs1, /nirs2 merge into JSON arrays
  3. Format Version Location: Moved from root to subfield of SNIRFData

Example Conversion

% SNIRF/HDF5 structure:
/formatVersion
/nirs1/metaDataTags
/nirs1/data1
/nirs1/data2

% Converts to JSNIRF:
{
  "SNIRFData": [{
    "formatVersion": "1.0",
    "metaDataTags": {...},
    "data": [{...}, {...}]
  }]
}

Read Data

Load SNIRF & JSNIRF Files

Simple functions to load fNIRS data from multiple formats into MATLAB structures.

% Load SNIRF (HDF5) file
data = loadsnirf('mydata.snirf');

% Load text JSNIRF file
jdata = loadjsnirf('mydata.jnirs');

% Load binary JSNIRF file
bdata = loadjsnirf('mydata.bnirs');

% Access the loaded data
timeSeries = data.SNIRFData.data.dataTimeSeries;
metadata = data.SNIRFData.metaDataTags;

% Convert and save to different format
loadsnirf('input.snirf', 'FileName', 'output.jnirs');

Write Data

Save to SNIRF & JSNIRF

Export your fNIRS data structures to any supported format with optional compression.

% Create or modify data
data = snirfcreate;
data.nirs.data.dataTimeSeries = rand(100, 5);
data.nirs.metaDataTags.SubjectID = 'subj001';
data.nirs.metaDataTags.MeasurementDate = date;

% Save as SNIRF (HDF5)
savesnirf(data, 'output.snirf');

% Save as text JSNIRF
savejsnirf(data, 'output.jnirs');

% Save as binary JSNIRF
savejsnirf(data, 'output.bnirs');

% Save with compression
savejsnirf(data, 'output.bnirs', 'compression', 'zlib');

Data Creation

Create SNIRF/JSNIRF Structures

Generate compliant data structures with all required fields automatically initialized.

% Create empty SNIRF structure
data = snirfcreate;

% Create with initial data
data = jsnirfcreate('data', mydata, 'aux', myaux);

% Specify format explicitly
jsn = jsnirfcreate('format', 'jsnirf');

% Decode raw HDF5 to JSNIRF structure
raw = loadh5('data.snirf', 'stringarray', 1);
jsn = snirfdecode(raw);

% Fill in your data
data.nirs.probe.wavelengths = [690, 830];
data.nirs.probe.sourcePos2D = [0, 0; 1, 0];
data.nirs.probe.detectorPos2D = [0.5, 1];
data.nirs.data.time = (0:99) / 10;  % 10 Hz sampling

Learn More

Documentation & Support

Access specifications, examples, and community support for JSNIRFY.

Main Functions

  • snirfcreate/jsnirfcreate - Create empty data structure
  • loadsnirf/loadjsnirf - Load from file
  • savesnirf/savejsnirf - Save to file
  • snirfdecode - Convert raw HDF5 to JSNIRF structure
  • aos2soa/soa2aos - Convert array/struct organizations

Compatibility

  • MATLAB R2010b or newer (R2016b+ for SNIRF 1.1 compliance)
  • GNU Octave 5.0 or newer
  • SNIRF v1.0+ specification
  • JSNIRF specification (JData-based)

Copyright © 2019-2025 Qianqian Fang • Part of the NeuroJSON Project
Licensed under GPLv3 or Apache 2.0 • Supported by NIH Grant U24-NS124027

Powered by Habitat