The purpose of this page is just to serve as todo or scratch pad for the development project and to list and share some ideas.

After making changes to the code and/or documentation, this page should remain on the wiki as a reminder of what was done and how it was done. However, there is no guarantee that this page is updated in the end to reflect the final state of the project

So chances are that this page is considerably outdated and irrelevant. The notes here might not reflect the current state of the code, and you should not use this as serious documentation.


Analysis of NIRS data is not particularly different from analysing any other signal. A few nuts and bolts need to be twisted differently, and some more transformations are possible (changes in optical densities to concentration changes, i.e. changes in oxygenated and deoxygenated blood). The specific NIRS part should become a toolbox similar to the spike toolbox (see fieldtrip/contrib/spike). As Jörn Horschig started working at Artinis and got several requests of using FieldTrip to analyze multimodal EEG/NIRS data, he will take the lead in implementing this.

Points of action:

  • define a standardized way to represent data and their peculiarities
  • extend getting started section on NIRS. Information on different devices need to come from the manufacturers
  • if analysis steps specific to NIRS should be implemented, these need to be written by experienced NIRS researchers
  • a tutorial for analysing NIRS and/or combined NIRS/EEG needs to be written

Additional notes: Mark van Wanrooij (DCN/biophysics) and his group might substantially contribute to this project.

The FieldTrip header contains meta information about the recording. More information be found in the respective reading file ft_read_header. For MEG data, the header also contains a .grad field, which contains information about the gradiometers. The respective counterpart for EEG data is .elec, but is commonly not stored together with the recorded data and thus not represented in the header.

NIRS data has another kind of sensor called “optode”. An optode can either emit light, laser light or LED light, called a “transmitter”, or receive light, e.g. by avalanching photodiodes, called “receiver”. A channel is defined by the amount of transmitted light from the “transmitter” that is received by the “receiver” (hence the nomenclature). I propose the header of NIRS data to contain a .opto field, that includes optode specific information. These types need to be incorporated in ft_senstype and ft_chantype.

In a similar vein as for MEG data, the .opto field should contain a .tra matrix, that contains information on how the channels are defined in terms of transmitters and receivers. Note that, in contrast to electrophysiological measurements, this is a 1-1-1 mapping, i.e. exactly one transmitter and exactly one receiver make up one channel (technically this is commonly achieved by multiplexing).

Optode specifications:

hdr.opto            - contains information about the optodes.
hdr.opto.tra        - NxC matrix, boolean, contains information about how receiver and transmitter form channels.
hdr.opto.optopos    - contains information about the position of the optodes.
hdr.opto.optotype   - contains information about the type of optode (receiver or transmitter).
hdr.opto.chanpos    - contains information about the position of the channels (i.e. average of optopos)
hdr.opto.chantype   - contains information about the channel type (NIRS)
hdr.opto.wavelength - 1xM vector of all wavelengths that were used
hdr.opto.transmits  - NxM matrix, boolean, where N is the number of optodes and M the number of wavelengths per transmitter. Specifies what optode is transmitting at what wavelength (or nothing at all, which indicates that it is a receiver)
hdr.opto.laserstrength - 1xM vector of the strength of the emitted light of the lasers.


There are different datatypes in FieldTrip. The basic starting point is a raw data, see ft_datatype_raw for more information. There will be no changes requires for NIRS data structures. Labels will be represented as 'RxY - TxZ [type]', where Y and Z are integer numbers indexing the receiver number and type can be the type of chromophore or the wavelength at which the measurement was taken.


New channels for ft_chantype should be 'nirs', 'receiver' and 'transmitter'.


ft_filetype need to be able to identify NIRS data files correctly. Die to copyright issues, these files should be best put into fieldtrip\external\manufacturer. The following table shows manufacturers and systems and the respective extension of the data files. Note that I do not know all these different types, and below is just an example table:

Manufacturer System(s) File format Proprietary file format
Artinis Medical Systems Oxymon, Octamon, Portamon, Portalite .oxy3 yes
Hitachi Medical Systems ETG-4000 .csv no


NIRS data requires transformations from (changes in) optical densities to (changes in) concentrations (oxygenated hemoglobin and changes in deoxygenated hemoglobin). These changes can be expressed in log-ratios or ln-ratios. Different labs have different preferences. In either case, we need a respective lookup table for the absorption coefficient (or extinction coefficient, which is proportional. The absorption coefficient is measured in natural logarithm, whereas the extinction coefficient uses the base 10 logarithm) for different wavelengths. ft_chanunit needs to be adjusted to incorporate the respective units (molar for concentrations, Watt for transmitter). The transformation is dependent on the wavelengths of the transmitter, the change in optical density (fraction of received light), the distance between transmitter and receiver and the differential path length factor (DPF), which is mostly estimated by the age of the participant and a lookup table.

Robert and me settled on creating a forward- and an inverse-function for this purpose.

  function [transform] = ft_convertODs(cfg, opto)

with = cell-array of strings or 1xN vector, defines on which channels the transformation matrix should be computed = string, can be 'HbO' (oxygenated hemoglobin) or 'HbR' (deoxygenated hemoglobin')
  cfg.age = scalar, age of the participant
  cfg.dpf = scalar, differential path length factor

additional fields can contain the lookup table for the absorption coefficient or dpf.

The resulting transform matrix can be multiplied with the data to obtain the concentrations. A respective ft_convertToODs function can be made to undo the conversion.

I think we actually *do* need a high-level function dealing directly with the data. Otherwise the channel labels will not be updated respectively. The ft_convertODs function can, however, serve as the low-level implementation.

Update: We might overcome this problem by having the function return a montage, which contains the new channel labels and the mixing coefficient of the channels


Preprocessing of NIRS data mostly consists of filtering and artifact rejection or correction. Filtering is most often performed by simple bandpass filtering, which are already implemented in FieldTrip. Some labs prefer to apply a gaussian moving average filter. Artifact correction is most often done using bandpass-filtering (filtering out physiological artifacts such as heartbeat and respiration) or using “wavelet-based detrending”, i.e. a more fancy form of band-pass filtering. This could also be performed using standard FieldTrip functions, but more information on this would be required.

The most crucial step in preprocessing is to transform the optical densities to concentrations, which has to be an ft_nirs_XXX function.


Layouts should be created on-the-fly by ft_prepare_layout. NeuroMag layouts can be taken as an example, where within the same data, different sensortypes are present at the same/nearby locations. The function should create an outline where optode positions are indicated (i.e. by a circle), and space for the different numbers of measures (concentrations) is computed and reserved, e.g. for multiplotting. The space depends on the cfg, i.e. desired channels/concentrations to be plotted (reminder: concentrations will be read out by the data labels).

Code structure

Overall structure: In case a high-level FieldTrip function calls a NIRS function, ft_hastoolbox will check whether the respective subfolder is already added and adds it, and a splash screen is shown, indicating a change in copyright (probably not GPL, definitely not for medical use, etc.).

Other Matlab NIRS toolboxes

The original NIRS-SPM was developed by Korea Advanced Institute of Science & Technology. The general NIRS-SPM approach is to solve a GLM based on different approaches of nongaussian random field theory. One of the developers, Sungho Tak, is now working at UCL in Will Penny's group. He reworked NIRS-SPM, which can now be found as on NIRTC as SPM for fNIRS toolbox. SPM-fNIRS includes DCM as well.

Homer2, developed by the Martinos Centre in Harvard, and primarily maintained by Ted Huppert from University in Pittsburgh. Is the most commonly used toolbox for NIRS analysis. Includes some forward modelling in the AtlasViewer.

Other available toolboxes such as EasyTopo (for visualization) or the NIRS Analysis package (NAP) are not widely used.